@absolutejs/voice 0.0.22-beta.155 → 0.0.22-beta.157
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 +2 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +195 -86
- package/dist/client/opsActionHistory.d.ts +19 -0
- package/dist/client/opsActionHistoryWidget.d.ts +11 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +292 -202
- package/dist/opsActionAuditRoutes.d.ts +23 -3
- package/dist/productionReadiness.d.ts +15 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -703,6 +703,8 @@ app.use(
|
|
|
703
703
|
);
|
|
704
704
|
```
|
|
705
705
|
|
|
706
|
+
The same route exposes `GET /api/voice/ops-actions/history` and `/voice/ops-actions` so apps can show recent operator actions beside the action center. For HTML or HTMX pages, use `mountVoiceOpsActionHistory(...)` from `@absolutejs/voice/client`.
|
|
707
|
+
|
|
706
708
|
For HTML or HTMX pages:
|
|
707
709
|
|
|
708
710
|
```html
|
package/dist/client/index.d.ts
CHANGED
|
@@ -9,9 +9,11 @@ export { createVoiceBargeInMonitor } from './bargeInMonitor';
|
|
|
9
9
|
export { createVoiceLiveTurnLatencyMonitor } from './liveTurnLatency';
|
|
10
10
|
export { createVoiceOpsStatusStore, fetchVoiceOpsStatus } from './opsStatus';
|
|
11
11
|
export { createVoiceOpsActionCenterActions, createVoiceOpsActionCenterStore, recordVoiceOpsActionResult, runVoiceOpsAction } from './opsActionCenter';
|
|
12
|
+
export { createVoiceOpsActionHistoryStore, fetchVoiceOpsActionHistory } from './opsActionHistory';
|
|
12
13
|
export { createVoiceDeliveryRuntimeStore, fetchVoiceDeliveryRuntime, runVoiceDeliveryRuntimeAction } from './deliveryRuntime';
|
|
13
14
|
export { createVoiceOpsStatusViewModel, defineVoiceOpsStatusElement, getVoiceOpsStatusCSS, getVoiceOpsStatusLabel, mountVoiceOpsStatus, renderVoiceOpsStatusHTML } from './opsStatusWidget';
|
|
14
15
|
export { createVoiceOpsActionCenterViewModel, defineVoiceOpsActionCenterElement, getVoiceOpsActionCenterCSS, mountVoiceOpsActionCenter, renderVoiceOpsActionCenterHTML } from './opsActionCenterWidget';
|
|
16
|
+
export { getVoiceOpsActionHistoryCSS, mountVoiceOpsActionHistory, renderVoiceOpsActionHistoryWidgetHTML } from './opsActionHistoryWidget';
|
|
15
17
|
export { createVoiceDeliveryRuntimeViewModel, defineVoiceDeliveryRuntimeElement, getVoiceDeliveryRuntimeCSS, mountVoiceDeliveryRuntime, renderVoiceDeliveryRuntimeHTML } from './deliveryRuntimeWidget';
|
|
16
18
|
export { createVoiceRoutingStatusStore, fetchVoiceRoutingStatus } from './routingStatus';
|
|
17
19
|
export { createVoiceRoutingStatusViewModel, defineVoiceRoutingStatusElement, getVoiceRoutingStatusCSS, mountVoiceRoutingStatus, renderVoiceRoutingStatusHTML } from './routingStatusWidget';
|
|
@@ -31,11 +33,13 @@ export { createVoiceTraceTimelineViewModel, defineVoiceTraceTimelineElement, get
|
|
|
31
33
|
export { createVoiceWorkflowStatusStore, fetchVoiceWorkflowStatus } from './workflowStatus';
|
|
32
34
|
export type { VoiceOpsStatusClientOptions, VoiceOpsStatusSnapshot } from './opsStatus';
|
|
33
35
|
export type { VoiceOpsActionCenterClientOptions, VoiceOpsActionCenterPresetOptions, VoiceOpsActionCenterSnapshot, VoiceOpsActionDescriptor, VoiceOpsActionMethod, VoiceOpsActionRunResult } from './opsActionCenter';
|
|
36
|
+
export type { VoiceOpsActionHistoryClientOptions, VoiceOpsActionHistorySnapshot } from './opsActionHistory';
|
|
34
37
|
export type { VoiceDeliveryRuntimeClientOptions, VoiceDeliveryRuntimeAction, VoiceDeliveryRuntimeActionResult, VoiceDeliveryRuntimeSnapshot } from './deliveryRuntime';
|
|
35
38
|
export type { VoiceBargeInMonitorOptions } from './bargeInMonitor';
|
|
36
39
|
export type { VoiceLiveTurnLatencyEvent, VoiceLiveTurnLatencyMonitorOptions, VoiceLiveTurnLatencySnapshot, VoiceLiveTurnLatencyStatus } from './liveTurnLatency';
|
|
37
40
|
export type { VoiceOpsStatusSurfaceView, VoiceOpsStatusViewModel, VoiceOpsStatusWidgetOptions } from './opsStatusWidget';
|
|
38
41
|
export type { VoiceOpsActionCenterViewModel, VoiceOpsActionCenterWidgetOptions } from './opsActionCenterWidget';
|
|
42
|
+
export type { VoiceOpsActionHistoryWidgetOptions } from './opsActionHistoryWidget';
|
|
39
43
|
export type { VoiceDeliveryRuntimeSurfaceView, VoiceDeliveryRuntimeViewModel, VoiceDeliveryRuntimeWidgetOptions } from './deliveryRuntimeWidget';
|
|
40
44
|
export type { VoiceRoutingStatusClientOptions, VoiceRoutingStatusSnapshot } from './routingStatus';
|
|
41
45
|
export type { VoiceRoutingStatusViewModel, VoiceRoutingStatusWidgetOptions } from './routingStatusWidget';
|
package/dist/client/index.js
CHANGED
|
@@ -2252,6 +2252,80 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
|
|
|
2252
2252
|
}
|
|
2253
2253
|
};
|
|
2254
2254
|
};
|
|
2255
|
+
// src/client/opsActionHistory.ts
|
|
2256
|
+
var fetchVoiceOpsActionHistory = async (path = "/api/voice/ops-actions/history", options = {}) => {
|
|
2257
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2258
|
+
const response = await fetchImpl(path);
|
|
2259
|
+
if (!response.ok) {
|
|
2260
|
+
throw new Error(`Voice ops action history failed: HTTP ${response.status}`);
|
|
2261
|
+
}
|
|
2262
|
+
return await response.json();
|
|
2263
|
+
};
|
|
2264
|
+
var createVoiceOpsActionHistoryStore = (path = "/api/voice/ops-actions/history", options = {}) => {
|
|
2265
|
+
const listeners = new Set;
|
|
2266
|
+
let closed = false;
|
|
2267
|
+
let timer;
|
|
2268
|
+
let snapshot = {
|
|
2269
|
+
error: null,
|
|
2270
|
+
isLoading: false
|
|
2271
|
+
};
|
|
2272
|
+
const emit = () => {
|
|
2273
|
+
for (const listener of listeners) {
|
|
2274
|
+
listener();
|
|
2275
|
+
}
|
|
2276
|
+
};
|
|
2277
|
+
const refresh = async () => {
|
|
2278
|
+
if (closed) {
|
|
2279
|
+
return snapshot.report;
|
|
2280
|
+
}
|
|
2281
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
2282
|
+
emit();
|
|
2283
|
+
try {
|
|
2284
|
+
const report = await fetchVoiceOpsActionHistory(path, options);
|
|
2285
|
+
snapshot = {
|
|
2286
|
+
error: null,
|
|
2287
|
+
isLoading: false,
|
|
2288
|
+
report,
|
|
2289
|
+
updatedAt: Date.now()
|
|
2290
|
+
};
|
|
2291
|
+
emit();
|
|
2292
|
+
return report;
|
|
2293
|
+
} catch (error) {
|
|
2294
|
+
snapshot = {
|
|
2295
|
+
...snapshot,
|
|
2296
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2297
|
+
isLoading: false
|
|
2298
|
+
};
|
|
2299
|
+
emit();
|
|
2300
|
+
throw error;
|
|
2301
|
+
}
|
|
2302
|
+
};
|
|
2303
|
+
const close = () => {
|
|
2304
|
+
closed = true;
|
|
2305
|
+
if (timer) {
|
|
2306
|
+
clearInterval(timer);
|
|
2307
|
+
timer = undefined;
|
|
2308
|
+
}
|
|
2309
|
+
listeners.clear();
|
|
2310
|
+
};
|
|
2311
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
2312
|
+
timer = setInterval(() => {
|
|
2313
|
+
refresh().catch(() => {});
|
|
2314
|
+
}, options.intervalMs);
|
|
2315
|
+
}
|
|
2316
|
+
return {
|
|
2317
|
+
close,
|
|
2318
|
+
getServerSnapshot: () => snapshot,
|
|
2319
|
+
getSnapshot: () => snapshot,
|
|
2320
|
+
refresh,
|
|
2321
|
+
subscribe: (listener) => {
|
|
2322
|
+
listeners.add(listener);
|
|
2323
|
+
return () => {
|
|
2324
|
+
listeners.delete(listener);
|
|
2325
|
+
};
|
|
2326
|
+
}
|
|
2327
|
+
};
|
|
2328
|
+
};
|
|
2255
2329
|
// src/client/deliveryRuntime.ts
|
|
2256
2330
|
var getDefaultActionPath = (path, action, options) => {
|
|
2257
2331
|
if (action === "tick") {
|
|
@@ -2599,10 +2673,40 @@ var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-ce
|
|
|
2599
2673
|
}
|
|
2600
2674
|
});
|
|
2601
2675
|
};
|
|
2676
|
+
// src/client/opsActionHistoryWidget.ts
|
|
2677
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2678
|
+
var renderVoiceOpsActionHistoryWidgetHTML = (snapshot, options = {}) => {
|
|
2679
|
+
const report = snapshot.report;
|
|
2680
|
+
const entries = (report?.entries ?? []).slice(0, options.limit ?? 5);
|
|
2681
|
+
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${escapeHtml3(entry.actionId)}</span><strong>${escapeHtml3(entry.ok ? "Success" : "Failed")}</strong><small>${escapeHtml3(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</small></li>`).join("");
|
|
2682
|
+
return `<section class="absolute-voice-ops-action-history">
|
|
2683
|
+
<header><span>Operator proof</span><strong>${escapeHtml3(options.title ?? "Action History")}</strong></header>
|
|
2684
|
+
<p>${String(report?.total ?? 0)} action(s), ${String(report?.failed ?? 0)} failed.</p>
|
|
2685
|
+
<ul>${rows || "<li>No operator actions recorded yet.</li>"}</ul>
|
|
2686
|
+
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${escapeHtml3(snapshot.error)}</p>` : ""}
|
|
2687
|
+
</section>`;
|
|
2688
|
+
};
|
|
2689
|
+
var getVoiceOpsActionHistoryCSS = () => `.absolute-voice-ops-action-history{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;font-family:inherit}.absolute-voice-ops-action-history header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-action-history header span{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-action-history header strong{font-size:24px}.absolute-voice-ops-action-history p{color:#514733}.absolute-voice-ops-action-history ul{display:grid;gap:8px;list-style:none;margin:12px 0 0;padding:0}.absolute-voice-ops-action-history__entry{background:#fff;border:1px solid #eee4d2;border-radius:14px;display:grid;gap:3px;padding:10px 12px}.absolute-voice-ops-action-history__entry--error{border-color:#f2a7a7}.absolute-voice-ops-action-history__entry span{font-weight:800}.absolute-voice-ops-action-history__entry small{color:#655944}.absolute-voice-ops-action-history__error{color:#9f1239;font-weight:700}`;
|
|
2690
|
+
var mountVoiceOpsActionHistory = (element, path = "/api/voice/ops-actions/history", options = {}) => {
|
|
2691
|
+
const store = createVoiceOpsActionHistoryStore(path, options);
|
|
2692
|
+
const render = () => {
|
|
2693
|
+
element.innerHTML = renderVoiceOpsActionHistoryWidgetHTML(store.getSnapshot(), options);
|
|
2694
|
+
};
|
|
2695
|
+
const unsubscribe = store.subscribe(render);
|
|
2696
|
+
render();
|
|
2697
|
+
store.refresh().catch(() => {});
|
|
2698
|
+
return {
|
|
2699
|
+
close: () => {
|
|
2700
|
+
unsubscribe();
|
|
2701
|
+
store.close();
|
|
2702
|
+
},
|
|
2703
|
+
refresh: store.refresh
|
|
2704
|
+
};
|
|
2705
|
+
};
|
|
2602
2706
|
// src/client/deliveryRuntimeWidget.ts
|
|
2603
2707
|
var DEFAULT_TITLE3 = "Voice Delivery Runtime";
|
|
2604
2708
|
var DEFAULT_DESCRIPTION3 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
2605
|
-
var
|
|
2709
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2606
2710
|
var createSurface = (id, summary) => {
|
|
2607
2711
|
if (!summary) {
|
|
2608
2712
|
return {
|
|
@@ -2651,26 +2755,26 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
2651
2755
|
};
|
|
2652
2756
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
2653
2757
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
2654
|
-
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${
|
|
2655
|
-
<span>${
|
|
2656
|
-
<strong>${
|
|
2758
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml4(surface.status)}">
|
|
2759
|
+
<span>${escapeHtml4(surface.label)}</span>
|
|
2760
|
+
<strong>${escapeHtml4(surface.detail)}</strong>
|
|
2657
2761
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
2658
2762
|
</li>`).join("");
|
|
2659
2763
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
2660
2764
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
2661
2765
|
<button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
|
|
2662
2766
|
</div>`;
|
|
2663
|
-
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
2664
|
-
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${
|
|
2767
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml4(model.actionError)}</p>` : "";
|
|
2768
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml4(model.status)}">
|
|
2665
2769
|
<header class="absolute-voice-delivery-runtime__header">
|
|
2666
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
2667
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
2770
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml4(model.title)}</span>
|
|
2771
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml4(model.label)}</strong>
|
|
2668
2772
|
</header>
|
|
2669
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
2773
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml4(model.description)}</p>
|
|
2670
2774
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
2671
2775
|
${actions}
|
|
2672
2776
|
${actionError}
|
|
2673
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
2777
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml4(model.error)}</p>` : ""}
|
|
2674
2778
|
</section>`;
|
|
2675
2779
|
};
|
|
2676
2780
|
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}`;
|
|
@@ -2808,7 +2912,7 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
2808
2912
|
// src/client/routingStatusWidget.ts
|
|
2809
2913
|
var DEFAULT_TITLE4 = "Voice Routing";
|
|
2810
2914
|
var DEFAULT_DESCRIPTION4 = "Latest provider routing decision from the self-hosted trace store.";
|
|
2811
|
-
var
|
|
2915
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2812
2916
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
2813
2917
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
2814
2918
|
const decision = snapshot.decision;
|
|
@@ -2845,17 +2949,17 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
2845
2949
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
2846
2950
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
2847
2951
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
2848
|
-
<span>${
|
|
2849
|
-
<strong>${
|
|
2952
|
+
<span>${escapeHtml5(row.label)}</span>
|
|
2953
|
+
<strong>${escapeHtml5(row.value)}</strong>
|
|
2850
2954
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
2851
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
2955
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml5(model.status)}">
|
|
2852
2956
|
<header class="absolute-voice-routing-status__header">
|
|
2853
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
2854
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
2957
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml5(model.title)}</span>
|
|
2958
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml5(model.label)}</strong>
|
|
2855
2959
|
</header>
|
|
2856
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2960
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml5(model.description)}</p>
|
|
2857
2961
|
${rows}
|
|
2858
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2962
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
2859
2963
|
</section>`;
|
|
2860
2964
|
};
|
|
2861
2965
|
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}`;
|
|
@@ -3507,7 +3611,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
3507
3611
|
};
|
|
3508
3612
|
};
|
|
3509
3613
|
// src/client/providerSimulationControlsWidget.ts
|
|
3510
|
-
var
|
|
3614
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3511
3615
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
3512
3616
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
3513
3617
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -3527,18 +3631,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
3527
3631
|
};
|
|
3528
3632
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
3529
3633
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
3530
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
3531
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
3634
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml6(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml6(provider.provider)} ${escapeHtml6(formatKind(options.kind))} failure</button>`).join("");
|
|
3635
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml6(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml6(provider.provider)} recovered</button>`).join("");
|
|
3532
3636
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
3533
3637
|
<header class="absolute-voice-provider-simulation__header">
|
|
3534
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
3535
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
3638
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml6(model.title)}</span>
|
|
3639
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml6(model.label)}</strong>
|
|
3536
3640
|
</header>
|
|
3537
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
3538
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
3641
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml6(model.description)}</p>
|
|
3642
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml6(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
3539
3643
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
3540
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
3541
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
3644
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml6(snapshot.error)}</p>` : ""}
|
|
3645
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml6(model.resultText)}</pre>` : ""}
|
|
3542
3646
|
</section>`;
|
|
3543
3647
|
};
|
|
3544
3648
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -3605,7 +3709,7 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
3605
3709
|
// src/client/providerStatusWidget.ts
|
|
3606
3710
|
var DEFAULT_TITLE5 = "Voice Providers";
|
|
3607
3711
|
var DEFAULT_DESCRIPTION5 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
3608
|
-
var
|
|
3712
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3609
3713
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3610
3714
|
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
3611
3715
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -3661,25 +3765,25 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
3661
3765
|
};
|
|
3662
3766
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
3663
3767
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
3664
|
-
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--${
|
|
3768
|
+
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--${escapeHtml7(provider.status)}">
|
|
3665
3769
|
<header>
|
|
3666
|
-
<strong>${
|
|
3667
|
-
<span>${
|
|
3770
|
+
<strong>${escapeHtml7(provider.label)}</strong>
|
|
3771
|
+
<span>${escapeHtml7(formatStatus(provider.status))}</span>
|
|
3668
3772
|
</header>
|
|
3669
|
-
<p>${
|
|
3773
|
+
<p>${escapeHtml7(provider.detail)}</p>
|
|
3670
3774
|
<dl>${provider.rows.map((row) => `<div>
|
|
3671
|
-
<dt>${
|
|
3672
|
-
<dd>${
|
|
3775
|
+
<dt>${escapeHtml7(row.label)}</dt>
|
|
3776
|
+
<dd>${escapeHtml7(row.value)}</dd>
|
|
3673
3777
|
</div>`).join("")}</dl>
|
|
3674
3778
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
3675
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
3779
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml7(model.status)}">
|
|
3676
3780
|
<header class="absolute-voice-provider-status__header">
|
|
3677
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
3678
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
3781
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml7(model.title)}</span>
|
|
3782
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml7(model.label)}</strong>
|
|
3679
3783
|
</header>
|
|
3680
|
-
<p class="absolute-voice-provider-status__description">${
|
|
3784
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml7(model.description)}</p>
|
|
3681
3785
|
${providers}
|
|
3682
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
3786
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
3683
3787
|
</section>`;
|
|
3684
3788
|
};
|
|
3685
3789
|
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}`;
|
|
@@ -3722,7 +3826,7 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
3722
3826
|
// src/client/providerCapabilitiesWidget.ts
|
|
3723
3827
|
var DEFAULT_TITLE6 = "Provider Capabilities";
|
|
3724
3828
|
var DEFAULT_DESCRIPTION6 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
3725
|
-
var
|
|
3829
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3726
3830
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3727
3831
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
3728
3832
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -3777,25 +3881,25 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
3777
3881
|
};
|
|
3778
3882
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
3779
3883
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
3780
|
-
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--${
|
|
3884
|
+
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--${escapeHtml8(capability.status)}">
|
|
3781
3885
|
<header>
|
|
3782
|
-
<strong>${
|
|
3783
|
-
<span>${
|
|
3886
|
+
<strong>${escapeHtml8(capability.label)}</strong>
|
|
3887
|
+
<span>${escapeHtml8(formatStatus2(capability.status))}</span>
|
|
3784
3888
|
</header>
|
|
3785
|
-
<p>${
|
|
3889
|
+
<p>${escapeHtml8(capability.detail)}</p>
|
|
3786
3890
|
<dl>${capability.rows.map((row) => `<div>
|
|
3787
|
-
<dt>${
|
|
3788
|
-
<dd>${
|
|
3891
|
+
<dt>${escapeHtml8(row.label)}</dt>
|
|
3892
|
+
<dd>${escapeHtml8(row.value)}</dd>
|
|
3789
3893
|
</div>`).join("")}</dl>
|
|
3790
3894
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
3791
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
3895
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml8(model.status)}">
|
|
3792
3896
|
<header class="absolute-voice-provider-capabilities__header">
|
|
3793
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
3794
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
3897
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml8(model.title)}</span>
|
|
3898
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml8(model.label)}</strong>
|
|
3795
3899
|
</header>
|
|
3796
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
3900
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml8(model.description)}</p>
|
|
3797
3901
|
${capabilities}
|
|
3798
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
3902
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
3799
3903
|
</section>`;
|
|
3800
3904
|
};
|
|
3801
3905
|
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}`;
|
|
@@ -3838,7 +3942,7 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
3838
3942
|
// src/client/turnQualityWidget.ts
|
|
3839
3943
|
var DEFAULT_TITLE7 = "Turn Quality";
|
|
3840
3944
|
var DEFAULT_DESCRIPTION7 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
3841
|
-
var
|
|
3945
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3842
3946
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
3843
3947
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
3844
3948
|
var getTurnDetail = (turn) => {
|
|
@@ -3888,25 +3992,25 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
3888
3992
|
};
|
|
3889
3993
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
3890
3994
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
3891
|
-
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--${
|
|
3995
|
+
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--${escapeHtml9(turn.status)}">
|
|
3892
3996
|
<header>
|
|
3893
|
-
<strong>${
|
|
3894
|
-
<span>${
|
|
3997
|
+
<strong>${escapeHtml9(turn.label)}</strong>
|
|
3998
|
+
<span>${escapeHtml9(turn.status)}</span>
|
|
3895
3999
|
</header>
|
|
3896
|
-
<p>${
|
|
4000
|
+
<p>${escapeHtml9(turn.detail)}</p>
|
|
3897
4001
|
<dl>${turn.rows.map((row) => `<div>
|
|
3898
|
-
<dt>${
|
|
3899
|
-
<dd>${
|
|
4002
|
+
<dt>${escapeHtml9(row.label)}</dt>
|
|
4003
|
+
<dd>${escapeHtml9(row.value)}</dd>
|
|
3900
4004
|
</div>`).join("")}</dl>
|
|
3901
4005
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
3902
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
4006
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml9(model.status)}">
|
|
3903
4007
|
<header class="absolute-voice-turn-quality__header">
|
|
3904
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
3905
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
4008
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml9(model.title)}</span>
|
|
4009
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml9(model.label)}</strong>
|
|
3906
4010
|
</header>
|
|
3907
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
4011
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml9(model.description)}</p>
|
|
3908
4012
|
${turns}
|
|
3909
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
4013
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
3910
4014
|
</section>`;
|
|
3911
4015
|
};
|
|
3912
4016
|
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}`;
|
|
@@ -3950,7 +4054,7 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
3950
4054
|
var DEFAULT_TITLE8 = "Turn Latency";
|
|
3951
4055
|
var DEFAULT_DESCRIPTION8 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
3952
4056
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
3953
|
-
var
|
|
4057
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3954
4058
|
var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
3955
4059
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
3956
4060
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -3978,25 +4082,25 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
3978
4082
|
};
|
|
3979
4083
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
3980
4084
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
3981
|
-
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--${
|
|
4085
|
+
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--${escapeHtml10(turn.status)}">
|
|
3982
4086
|
<header>
|
|
3983
|
-
<strong>${
|
|
3984
|
-
<span>${
|
|
4087
|
+
<strong>${escapeHtml10(turn.label)}</strong>
|
|
4088
|
+
<span>${escapeHtml10(turn.status)}</span>
|
|
3985
4089
|
</header>
|
|
3986
4090
|
<dl>${turn.rows.map((row) => `<div>
|
|
3987
|
-
<dt>${
|
|
3988
|
-
<dd>${
|
|
4091
|
+
<dt>${escapeHtml10(row.label)}</dt>
|
|
4092
|
+
<dd>${escapeHtml10(row.value)}</dd>
|
|
3989
4093
|
</div>`).join("")}</dl>
|
|
3990
4094
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
3991
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
4095
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml10(model.status)}">
|
|
3992
4096
|
<header class="absolute-voice-turn-latency__header">
|
|
3993
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
3994
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
4097
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml10(model.title)}</span>
|
|
4098
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml10(model.label)}</strong>
|
|
3995
4099
|
</header>
|
|
3996
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
3997
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
4100
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml10(model.description)}</p>
|
|
4101
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml10(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
3998
4102
|
${turns}
|
|
3999
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
4103
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
4000
4104
|
</section>`;
|
|
4001
4105
|
};
|
|
4002
4106
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -4048,7 +4152,7 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
4048
4152
|
// src/client/traceTimelineWidget.ts
|
|
4049
4153
|
var DEFAULT_TITLE9 = "Voice Traces";
|
|
4050
4154
|
var DEFAULT_DESCRIPTION9 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
4051
|
-
var
|
|
4155
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4052
4156
|
var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
4053
4157
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
4054
4158
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -4074,22 +4178,22 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
4074
4178
|
};
|
|
4075
4179
|
var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
4076
4180
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
4077
|
-
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--${
|
|
4181
|
+
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--${escapeHtml11(session.status)}">
|
|
4078
4182
|
<header>
|
|
4079
|
-
<strong>${
|
|
4080
|
-
<span>${
|
|
4183
|
+
<strong>${escapeHtml11(session.sessionId)}</strong>
|
|
4184
|
+
<span>${escapeHtml11(session.status)}</span>
|
|
4081
4185
|
</header>
|
|
4082
|
-
<p>${
|
|
4083
|
-
<a href="${
|
|
4186
|
+
<p>${escapeHtml11(session.label)} \xB7 ${escapeHtml11(session.durationLabel)} \xB7 ${escapeHtml11(session.providerLabel)}</p>
|
|
4187
|
+
<a href="${escapeHtml11(session.detailHref)}">Open timeline</a>
|
|
4084
4188
|
</article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
4085
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
4189
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml11(model.status)}">
|
|
4086
4190
|
<header class="absolute-voice-trace-timeline__header">
|
|
4087
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
4088
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
4191
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml11(model.title)}</span>
|
|
4192
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml11(model.label)}</strong>
|
|
4089
4193
|
</header>
|
|
4090
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
4194
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml11(model.description)}</p>
|
|
4091
4195
|
${sessions}
|
|
4092
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
4196
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
4093
4197
|
</section>`;
|
|
4094
4198
|
};
|
|
4095
4199
|
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}`;
|
|
@@ -4223,6 +4327,7 @@ export {
|
|
|
4223
4327
|
renderVoiceProviderSimulationControlsHTML,
|
|
4224
4328
|
renderVoiceProviderCapabilitiesHTML,
|
|
4225
4329
|
renderVoiceOpsStatusHTML,
|
|
4330
|
+
renderVoiceOpsActionHistoryWidgetHTML,
|
|
4226
4331
|
renderVoiceOpsActionCenterHTML,
|
|
4227
4332
|
renderVoiceDeliveryRuntimeHTML,
|
|
4228
4333
|
recordVoiceOpsActionResult,
|
|
@@ -4234,6 +4339,7 @@ export {
|
|
|
4234
4339
|
mountVoiceProviderSimulationControls,
|
|
4235
4340
|
mountVoiceProviderCapabilities,
|
|
4236
4341
|
mountVoiceOpsStatus,
|
|
4342
|
+
mountVoiceOpsActionHistory,
|
|
4237
4343
|
mountVoiceOpsActionCenter,
|
|
4238
4344
|
mountVoiceDeliveryRuntime,
|
|
4239
4345
|
getVoiceTurnQualityCSS,
|
|
@@ -4243,6 +4349,7 @@ export {
|
|
|
4243
4349
|
getVoiceProviderCapabilitiesCSS,
|
|
4244
4350
|
getVoiceOpsStatusLabel,
|
|
4245
4351
|
getVoiceOpsStatusCSS,
|
|
4352
|
+
getVoiceOpsActionHistoryCSS,
|
|
4246
4353
|
getVoiceOpsActionCenterCSS,
|
|
4247
4354
|
getVoiceDeliveryRuntimeCSS,
|
|
4248
4355
|
fetchVoiceWorkflowStatus,
|
|
@@ -4253,6 +4360,7 @@ export {
|
|
|
4253
4360
|
fetchVoiceProviderStatus,
|
|
4254
4361
|
fetchVoiceProviderCapabilities,
|
|
4255
4362
|
fetchVoiceOpsStatus,
|
|
4363
|
+
fetchVoiceOpsActionHistory,
|
|
4256
4364
|
fetchVoiceDeliveryRuntime,
|
|
4257
4365
|
fetchVoiceCampaignDialerProofStatus,
|
|
4258
4366
|
defineVoiceTurnQualityElement,
|
|
@@ -4284,6 +4392,7 @@ export {
|
|
|
4284
4392
|
createVoiceProviderCapabilitiesStore,
|
|
4285
4393
|
createVoiceOpsStatusViewModel,
|
|
4286
4394
|
createVoiceOpsStatusStore,
|
|
4395
|
+
createVoiceOpsActionHistoryStore,
|
|
4287
4396
|
createVoiceOpsActionCenterViewModel,
|
|
4288
4397
|
createVoiceOpsActionCenterStore,
|
|
4289
4398
|
createVoiceOpsActionCenterActions,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { VoiceOpsActionHistoryReport } from '../opsActionAuditRoutes';
|
|
2
|
+
export type VoiceOpsActionHistoryClientOptions = {
|
|
3
|
+
fetch?: typeof fetch;
|
|
4
|
+
intervalMs?: number;
|
|
5
|
+
};
|
|
6
|
+
export type VoiceOpsActionHistorySnapshot = {
|
|
7
|
+
error: string | null;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
report?: VoiceOpsActionHistoryReport;
|
|
10
|
+
updatedAt?: number;
|
|
11
|
+
};
|
|
12
|
+
export declare const fetchVoiceOpsActionHistory: (path?: string, options?: Pick<VoiceOpsActionHistoryClientOptions, "fetch">) => Promise<VoiceOpsActionHistoryReport>;
|
|
13
|
+
export declare const createVoiceOpsActionHistoryStore: (path?: string, options?: VoiceOpsActionHistoryClientOptions) => {
|
|
14
|
+
close: () => void;
|
|
15
|
+
getServerSnapshot: () => VoiceOpsActionHistorySnapshot;
|
|
16
|
+
getSnapshot: () => VoiceOpsActionHistorySnapshot;
|
|
17
|
+
refresh: () => Promise<VoiceOpsActionHistoryReport | undefined>;
|
|
18
|
+
subscribe: (listener: () => void) => () => void;
|
|
19
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type VoiceOpsActionHistoryClientOptions, type VoiceOpsActionHistorySnapshot } from './opsActionHistory';
|
|
2
|
+
export type VoiceOpsActionHistoryWidgetOptions = VoiceOpsActionHistoryClientOptions & {
|
|
3
|
+
limit?: number;
|
|
4
|
+
title?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const renderVoiceOpsActionHistoryWidgetHTML: (snapshot: VoiceOpsActionHistorySnapshot, options?: VoiceOpsActionHistoryWidgetOptions) => string;
|
|
7
|
+
export declare const getVoiceOpsActionHistoryCSS: () => string;
|
|
8
|
+
export declare const mountVoiceOpsActionHistory: (element: Element, path?: string, options?: VoiceOpsActionHistoryWidgetOptions) => {
|
|
9
|
+
close: () => void;
|
|
10
|
+
refresh: () => Promise<import("..").VoiceOpsActionHistoryReport | undefined>;
|
|
11
|
+
};
|