@absolutejs/voice 0.0.22-beta.154 → 0.0.22-beta.156
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 +15 -0
- package/dist/angular/index.js +29 -0
- package/dist/client/index.d.ts +5 -1
- package/dist/client/index.js +225 -86
- package/dist/client/opsActionCenter.d.ts +4 -0
- package/dist/client/opsActionHistory.d.ts +19 -0
- package/dist/client/opsActionHistoryWidget.d.ts +11 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +389 -254
- package/dist/opsActionAuditRoutes.d.ts +99 -0
- package/dist/react/index.js +29 -0
- package/dist/svelte/index.js +29 -0
- package/dist/trace.d.ts +1 -1
- package/dist/vue/index.js +29 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -2063,6 +2063,23 @@ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) =
|
|
|
2063
2063
|
};
|
|
2064
2064
|
};
|
|
2065
2065
|
// src/client/opsActionCenter.ts
|
|
2066
|
+
var recordVoiceOpsActionResult = async (result, options = {}) => {
|
|
2067
|
+
if (options.auditPath === false) {
|
|
2068
|
+
return;
|
|
2069
|
+
}
|
|
2070
|
+
const path = options.auditPath ?? "/api/voice/ops-actions/audit";
|
|
2071
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2072
|
+
const response = await fetchImpl(path, {
|
|
2073
|
+
body: JSON.stringify(result),
|
|
2074
|
+
headers: {
|
|
2075
|
+
"Content-Type": "application/json"
|
|
2076
|
+
},
|
|
2077
|
+
method: "POST"
|
|
2078
|
+
});
|
|
2079
|
+
if (!response.ok) {
|
|
2080
|
+
throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
|
|
2081
|
+
}
|
|
2082
|
+
};
|
|
2066
2083
|
var createVoiceOpsActionCenterActions = (options = {}) => {
|
|
2067
2084
|
const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
|
|
2068
2085
|
const actions = [];
|
|
@@ -2175,6 +2192,8 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
|
|
|
2175
2192
|
emit();
|
|
2176
2193
|
try {
|
|
2177
2194
|
const result = await runVoiceOpsAction(action, options);
|
|
2195
|
+
await options.onActionResult?.(result);
|
|
2196
|
+
await recordVoiceOpsActionResult(result, options);
|
|
2178
2197
|
snapshot = {
|
|
2179
2198
|
...snapshot,
|
|
2180
2199
|
error: null,
|
|
@@ -2186,6 +2205,16 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
|
|
|
2186
2205
|
emit();
|
|
2187
2206
|
return result;
|
|
2188
2207
|
} catch (error) {
|
|
2208
|
+
const result = {
|
|
2209
|
+
actionId: action.id,
|
|
2210
|
+
body: null,
|
|
2211
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2212
|
+
ok: false,
|
|
2213
|
+
ranAt: Date.now(),
|
|
2214
|
+
status: 0
|
|
2215
|
+
};
|
|
2216
|
+
await options.onActionResult?.(result);
|
|
2217
|
+
await recordVoiceOpsActionResult(result, options).catch(() => {});
|
|
2189
2218
|
snapshot = {
|
|
2190
2219
|
...snapshot,
|
|
2191
2220
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -2223,6 +2252,80 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
|
|
|
2223
2252
|
}
|
|
2224
2253
|
};
|
|
2225
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
|
+
};
|
|
2226
2329
|
// src/client/deliveryRuntime.ts
|
|
2227
2330
|
var getDefaultActionPath = (path, action, options) => {
|
|
2228
2331
|
if (action === "tick") {
|
|
@@ -2570,10 +2673,40 @@ var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-ce
|
|
|
2570
2673
|
}
|
|
2571
2674
|
});
|
|
2572
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
|
+
};
|
|
2573
2706
|
// src/client/deliveryRuntimeWidget.ts
|
|
2574
2707
|
var DEFAULT_TITLE3 = "Voice Delivery Runtime";
|
|
2575
2708
|
var DEFAULT_DESCRIPTION3 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
2576
|
-
var
|
|
2709
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2577
2710
|
var createSurface = (id, summary) => {
|
|
2578
2711
|
if (!summary) {
|
|
2579
2712
|
return {
|
|
@@ -2622,26 +2755,26 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
2622
2755
|
};
|
|
2623
2756
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
2624
2757
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
2625
|
-
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${
|
|
2626
|
-
<span>${
|
|
2627
|
-
<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>
|
|
2628
2761
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
2629
2762
|
</li>`).join("");
|
|
2630
2763
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
2631
2764
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
2632
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>
|
|
2633
2766
|
</div>`;
|
|
2634
|
-
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
2635
|
-
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)}">
|
|
2636
2769
|
<header class="absolute-voice-delivery-runtime__header">
|
|
2637
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
2638
|
-
<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>
|
|
2639
2772
|
</header>
|
|
2640
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
2773
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml4(model.description)}</p>
|
|
2641
2774
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
2642
2775
|
${actions}
|
|
2643
2776
|
${actionError}
|
|
2644
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
2777
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml4(model.error)}</p>` : ""}
|
|
2645
2778
|
</section>`;
|
|
2646
2779
|
};
|
|
2647
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}`;
|
|
@@ -2779,7 +2912,7 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
2779
2912
|
// src/client/routingStatusWidget.ts
|
|
2780
2913
|
var DEFAULT_TITLE4 = "Voice Routing";
|
|
2781
2914
|
var DEFAULT_DESCRIPTION4 = "Latest provider routing decision from the self-hosted trace store.";
|
|
2782
|
-
var
|
|
2915
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2783
2916
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
2784
2917
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
2785
2918
|
const decision = snapshot.decision;
|
|
@@ -2816,17 +2949,17 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
2816
2949
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
2817
2950
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
2818
2951
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
2819
|
-
<span>${
|
|
2820
|
-
<strong>${
|
|
2952
|
+
<span>${escapeHtml5(row.label)}</span>
|
|
2953
|
+
<strong>${escapeHtml5(row.value)}</strong>
|
|
2821
2954
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
2822
|
-
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)}">
|
|
2823
2956
|
<header class="absolute-voice-routing-status__header">
|
|
2824
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
2825
|
-
<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>
|
|
2826
2959
|
</header>
|
|
2827
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2960
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml5(model.description)}</p>
|
|
2828
2961
|
${rows}
|
|
2829
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2962
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
2830
2963
|
</section>`;
|
|
2831
2964
|
};
|
|
2832
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}`;
|
|
@@ -3478,7 +3611,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
3478
3611
|
};
|
|
3479
3612
|
};
|
|
3480
3613
|
// src/client/providerSimulationControlsWidget.ts
|
|
3481
|
-
var
|
|
3614
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3482
3615
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
3483
3616
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
3484
3617
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -3498,18 +3631,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
3498
3631
|
};
|
|
3499
3632
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
3500
3633
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
3501
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
3502
|
-
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("");
|
|
3503
3636
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
3504
3637
|
<header class="absolute-voice-provider-simulation__header">
|
|
3505
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
3506
|
-
<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>
|
|
3507
3640
|
</header>
|
|
3508
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
3509
|
-
${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>`}
|
|
3510
3643
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
3511
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
3512
|
-
${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>` : ""}
|
|
3513
3646
|
</section>`;
|
|
3514
3647
|
};
|
|
3515
3648
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -3576,7 +3709,7 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
3576
3709
|
// src/client/providerStatusWidget.ts
|
|
3577
3710
|
var DEFAULT_TITLE5 = "Voice Providers";
|
|
3578
3711
|
var DEFAULT_DESCRIPTION5 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
3579
|
-
var
|
|
3712
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3580
3713
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3581
3714
|
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
3582
3715
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -3632,25 +3765,25 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
3632
3765
|
};
|
|
3633
3766
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
3634
3767
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
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--${
|
|
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)}">
|
|
3636
3769
|
<header>
|
|
3637
|
-
<strong>${
|
|
3638
|
-
<span>${
|
|
3770
|
+
<strong>${escapeHtml7(provider.label)}</strong>
|
|
3771
|
+
<span>${escapeHtml7(formatStatus(provider.status))}</span>
|
|
3639
3772
|
</header>
|
|
3640
|
-
<p>${
|
|
3773
|
+
<p>${escapeHtml7(provider.detail)}</p>
|
|
3641
3774
|
<dl>${provider.rows.map((row) => `<div>
|
|
3642
|
-
<dt>${
|
|
3643
|
-
<dd>${
|
|
3775
|
+
<dt>${escapeHtml7(row.label)}</dt>
|
|
3776
|
+
<dd>${escapeHtml7(row.value)}</dd>
|
|
3644
3777
|
</div>`).join("")}</dl>
|
|
3645
3778
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
3646
|
-
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)}">
|
|
3647
3780
|
<header class="absolute-voice-provider-status__header">
|
|
3648
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
3649
|
-
<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>
|
|
3650
3783
|
</header>
|
|
3651
|
-
<p class="absolute-voice-provider-status__description">${
|
|
3784
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml7(model.description)}</p>
|
|
3652
3785
|
${providers}
|
|
3653
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
3786
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
3654
3787
|
</section>`;
|
|
3655
3788
|
};
|
|
3656
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}`;
|
|
@@ -3693,7 +3826,7 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
3693
3826
|
// src/client/providerCapabilitiesWidget.ts
|
|
3694
3827
|
var DEFAULT_TITLE6 = "Provider Capabilities";
|
|
3695
3828
|
var DEFAULT_DESCRIPTION6 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
3696
|
-
var
|
|
3829
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3697
3830
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3698
3831
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
3699
3832
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -3748,25 +3881,25 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
3748
3881
|
};
|
|
3749
3882
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
3750
3883
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
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--${
|
|
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)}">
|
|
3752
3885
|
<header>
|
|
3753
|
-
<strong>${
|
|
3754
|
-
<span>${
|
|
3886
|
+
<strong>${escapeHtml8(capability.label)}</strong>
|
|
3887
|
+
<span>${escapeHtml8(formatStatus2(capability.status))}</span>
|
|
3755
3888
|
</header>
|
|
3756
|
-
<p>${
|
|
3889
|
+
<p>${escapeHtml8(capability.detail)}</p>
|
|
3757
3890
|
<dl>${capability.rows.map((row) => `<div>
|
|
3758
|
-
<dt>${
|
|
3759
|
-
<dd>${
|
|
3891
|
+
<dt>${escapeHtml8(row.label)}</dt>
|
|
3892
|
+
<dd>${escapeHtml8(row.value)}</dd>
|
|
3760
3893
|
</div>`).join("")}</dl>
|
|
3761
3894
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
3762
|
-
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)}">
|
|
3763
3896
|
<header class="absolute-voice-provider-capabilities__header">
|
|
3764
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
3765
|
-
<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>
|
|
3766
3899
|
</header>
|
|
3767
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
3900
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml8(model.description)}</p>
|
|
3768
3901
|
${capabilities}
|
|
3769
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
3902
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
3770
3903
|
</section>`;
|
|
3771
3904
|
};
|
|
3772
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}`;
|
|
@@ -3809,7 +3942,7 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
3809
3942
|
// src/client/turnQualityWidget.ts
|
|
3810
3943
|
var DEFAULT_TITLE7 = "Turn Quality";
|
|
3811
3944
|
var DEFAULT_DESCRIPTION7 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
3812
|
-
var
|
|
3945
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3813
3946
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
3814
3947
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
3815
3948
|
var getTurnDetail = (turn) => {
|
|
@@ -3859,25 +3992,25 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
3859
3992
|
};
|
|
3860
3993
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
3861
3994
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
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--${
|
|
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)}">
|
|
3863
3996
|
<header>
|
|
3864
|
-
<strong>${
|
|
3865
|
-
<span>${
|
|
3997
|
+
<strong>${escapeHtml9(turn.label)}</strong>
|
|
3998
|
+
<span>${escapeHtml9(turn.status)}</span>
|
|
3866
3999
|
</header>
|
|
3867
|
-
<p>${
|
|
4000
|
+
<p>${escapeHtml9(turn.detail)}</p>
|
|
3868
4001
|
<dl>${turn.rows.map((row) => `<div>
|
|
3869
|
-
<dt>${
|
|
3870
|
-
<dd>${
|
|
4002
|
+
<dt>${escapeHtml9(row.label)}</dt>
|
|
4003
|
+
<dd>${escapeHtml9(row.value)}</dd>
|
|
3871
4004
|
</div>`).join("")}</dl>
|
|
3872
4005
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
3873
|
-
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)}">
|
|
3874
4007
|
<header class="absolute-voice-turn-quality__header">
|
|
3875
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
3876
|
-
<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>
|
|
3877
4010
|
</header>
|
|
3878
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
4011
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml9(model.description)}</p>
|
|
3879
4012
|
${turns}
|
|
3880
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
4013
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
3881
4014
|
</section>`;
|
|
3882
4015
|
};
|
|
3883
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}`;
|
|
@@ -3921,7 +4054,7 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
3921
4054
|
var DEFAULT_TITLE8 = "Turn Latency";
|
|
3922
4055
|
var DEFAULT_DESCRIPTION8 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
3923
4056
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
3924
|
-
var
|
|
4057
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3925
4058
|
var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
3926
4059
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
3927
4060
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -3949,25 +4082,25 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
3949
4082
|
};
|
|
3950
4083
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
3951
4084
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
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--${
|
|
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)}">
|
|
3953
4086
|
<header>
|
|
3954
|
-
<strong>${
|
|
3955
|
-
<span>${
|
|
4087
|
+
<strong>${escapeHtml10(turn.label)}</strong>
|
|
4088
|
+
<span>${escapeHtml10(turn.status)}</span>
|
|
3956
4089
|
</header>
|
|
3957
4090
|
<dl>${turn.rows.map((row) => `<div>
|
|
3958
|
-
<dt>${
|
|
3959
|
-
<dd>${
|
|
4091
|
+
<dt>${escapeHtml10(row.label)}</dt>
|
|
4092
|
+
<dd>${escapeHtml10(row.value)}</dd>
|
|
3960
4093
|
</div>`).join("")}</dl>
|
|
3961
4094
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
3962
|
-
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)}">
|
|
3963
4096
|
<header class="absolute-voice-turn-latency__header">
|
|
3964
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
3965
|
-
<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>
|
|
3966
4099
|
</header>
|
|
3967
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
3968
|
-
${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>` : ""}
|
|
3969
4102
|
${turns}
|
|
3970
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
4103
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
3971
4104
|
</section>`;
|
|
3972
4105
|
};
|
|
3973
4106
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -4019,7 +4152,7 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
4019
4152
|
// src/client/traceTimelineWidget.ts
|
|
4020
4153
|
var DEFAULT_TITLE9 = "Voice Traces";
|
|
4021
4154
|
var DEFAULT_DESCRIPTION9 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
4022
|
-
var
|
|
4155
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4023
4156
|
var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
4024
4157
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
4025
4158
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -4045,22 +4178,22 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
4045
4178
|
};
|
|
4046
4179
|
var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
4047
4180
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
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--${
|
|
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)}">
|
|
4049
4182
|
<header>
|
|
4050
|
-
<strong>${
|
|
4051
|
-
<span>${
|
|
4183
|
+
<strong>${escapeHtml11(session.sessionId)}</strong>
|
|
4184
|
+
<span>${escapeHtml11(session.status)}</span>
|
|
4052
4185
|
</header>
|
|
4053
|
-
<p>${
|
|
4054
|
-
<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>
|
|
4055
4188
|
</article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
4056
|
-
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)}">
|
|
4057
4190
|
<header class="absolute-voice-trace-timeline__header">
|
|
4058
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
4059
|
-
<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>
|
|
4060
4193
|
</header>
|
|
4061
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
4194
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml11(model.description)}</p>
|
|
4062
4195
|
${sessions}
|
|
4063
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
4196
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
4064
4197
|
</section>`;
|
|
4065
4198
|
};
|
|
4066
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}`;
|
|
@@ -4194,8 +4327,10 @@ export {
|
|
|
4194
4327
|
renderVoiceProviderSimulationControlsHTML,
|
|
4195
4328
|
renderVoiceProviderCapabilitiesHTML,
|
|
4196
4329
|
renderVoiceOpsStatusHTML,
|
|
4330
|
+
renderVoiceOpsActionHistoryWidgetHTML,
|
|
4197
4331
|
renderVoiceOpsActionCenterHTML,
|
|
4198
4332
|
renderVoiceDeliveryRuntimeHTML,
|
|
4333
|
+
recordVoiceOpsActionResult,
|
|
4199
4334
|
mountVoiceTurnQuality,
|
|
4200
4335
|
mountVoiceTurnLatency,
|
|
4201
4336
|
mountVoiceTraceTimeline,
|
|
@@ -4204,6 +4339,7 @@ export {
|
|
|
4204
4339
|
mountVoiceProviderSimulationControls,
|
|
4205
4340
|
mountVoiceProviderCapabilities,
|
|
4206
4341
|
mountVoiceOpsStatus,
|
|
4342
|
+
mountVoiceOpsActionHistory,
|
|
4207
4343
|
mountVoiceOpsActionCenter,
|
|
4208
4344
|
mountVoiceDeliveryRuntime,
|
|
4209
4345
|
getVoiceTurnQualityCSS,
|
|
@@ -4213,6 +4349,7 @@ export {
|
|
|
4213
4349
|
getVoiceProviderCapabilitiesCSS,
|
|
4214
4350
|
getVoiceOpsStatusLabel,
|
|
4215
4351
|
getVoiceOpsStatusCSS,
|
|
4352
|
+
getVoiceOpsActionHistoryCSS,
|
|
4216
4353
|
getVoiceOpsActionCenterCSS,
|
|
4217
4354
|
getVoiceDeliveryRuntimeCSS,
|
|
4218
4355
|
fetchVoiceWorkflowStatus,
|
|
@@ -4223,6 +4360,7 @@ export {
|
|
|
4223
4360
|
fetchVoiceProviderStatus,
|
|
4224
4361
|
fetchVoiceProviderCapabilities,
|
|
4225
4362
|
fetchVoiceOpsStatus,
|
|
4363
|
+
fetchVoiceOpsActionHistory,
|
|
4226
4364
|
fetchVoiceDeliveryRuntime,
|
|
4227
4365
|
fetchVoiceCampaignDialerProofStatus,
|
|
4228
4366
|
defineVoiceTurnQualityElement,
|
|
@@ -4254,6 +4392,7 @@ export {
|
|
|
4254
4392
|
createVoiceProviderCapabilitiesStore,
|
|
4255
4393
|
createVoiceOpsStatusViewModel,
|
|
4256
4394
|
createVoiceOpsStatusStore,
|
|
4395
|
+
createVoiceOpsActionHistoryStore,
|
|
4257
4396
|
createVoiceOpsActionCenterViewModel,
|
|
4258
4397
|
createVoiceOpsActionCenterStore,
|
|
4259
4398
|
createVoiceOpsActionCenterActions,
|
|
@@ -9,16 +9,20 @@ export type VoiceOpsActionDescriptor = {
|
|
|
9
9
|
};
|
|
10
10
|
export type VoiceOpsActionCenterClientOptions = {
|
|
11
11
|
actions?: VoiceOpsActionDescriptor[];
|
|
12
|
+
auditPath?: false | string;
|
|
12
13
|
fetch?: typeof fetch;
|
|
13
14
|
intervalMs?: number;
|
|
15
|
+
onActionResult?: (result: VoiceOpsActionRunResult) => Promise<void> | void;
|
|
14
16
|
};
|
|
15
17
|
export type VoiceOpsActionRunResult = {
|
|
16
18
|
actionId: string;
|
|
17
19
|
body: unknown;
|
|
20
|
+
error?: string;
|
|
18
21
|
ok: boolean;
|
|
19
22
|
ranAt: number;
|
|
20
23
|
status: number;
|
|
21
24
|
};
|
|
25
|
+
export declare const recordVoiceOpsActionResult: (result: VoiceOpsActionRunResult, options?: VoiceOpsActionCenterClientOptions) => Promise<void>;
|
|
22
26
|
export type VoiceOpsActionCenterSnapshot = {
|
|
23
27
|
actions: VoiceOpsActionDescriptor[];
|
|
24
28
|
error: string | null;
|
|
@@ -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
|
+
};
|