@absolutejs/voice 0.0.22-beta.242 → 0.0.22-beta.243
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/index.d.ts +1 -0
- package/dist/angular/index.js +306 -181
- package/dist/angular/voice-proof-trends.service.d.ts +12 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +490 -190
- package/dist/client/proofTrends.d.ts +19 -0
- package/dist/client/proofTrendsWidget.d.ts +37 -0
- package/dist/react/VoiceProofTrends.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +730 -350
- package/dist/react/useVoiceProofTrends.d.ts +8 -0
- package/dist/svelte/createVoiceProofTrends.d.ts +7 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +90 -0
- package/dist/vue/VoiceProofTrends.d.ts +21 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +704 -321
- package/dist/vue/useVoiceProofTrends.d.ts +9 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -2140,6 +2140,84 @@ var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", o
|
|
|
2140
2140
|
}
|
|
2141
2141
|
};
|
|
2142
2142
|
};
|
|
2143
|
+
// src/client/proofTrends.ts
|
|
2144
|
+
var fetchVoiceProofTrends = async (path = "/api/voice/proof-trends", options = {}) => {
|
|
2145
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2146
|
+
const response = await fetchImpl(path);
|
|
2147
|
+
if (!response.ok) {
|
|
2148
|
+
throw new Error(`Voice proof trends failed: HTTP ${response.status}`);
|
|
2149
|
+
}
|
|
2150
|
+
return await response.json();
|
|
2151
|
+
};
|
|
2152
|
+
var createVoiceProofTrendsStore = (path = "/api/voice/proof-trends", options = {}) => {
|
|
2153
|
+
const listeners = new Set;
|
|
2154
|
+
let closed = false;
|
|
2155
|
+
let timer;
|
|
2156
|
+
let snapshot = {
|
|
2157
|
+
error: null,
|
|
2158
|
+
isLoading: false
|
|
2159
|
+
};
|
|
2160
|
+
const emit = () => {
|
|
2161
|
+
for (const listener of listeners) {
|
|
2162
|
+
listener();
|
|
2163
|
+
}
|
|
2164
|
+
};
|
|
2165
|
+
const refresh = async () => {
|
|
2166
|
+
if (closed) {
|
|
2167
|
+
return snapshot.report;
|
|
2168
|
+
}
|
|
2169
|
+
snapshot = {
|
|
2170
|
+
...snapshot,
|
|
2171
|
+
error: null,
|
|
2172
|
+
isLoading: true
|
|
2173
|
+
};
|
|
2174
|
+
emit();
|
|
2175
|
+
try {
|
|
2176
|
+
const report = await fetchVoiceProofTrends(path, options);
|
|
2177
|
+
snapshot = {
|
|
2178
|
+
error: null,
|
|
2179
|
+
isLoading: false,
|
|
2180
|
+
report,
|
|
2181
|
+
updatedAt: Date.now()
|
|
2182
|
+
};
|
|
2183
|
+
emit();
|
|
2184
|
+
return report;
|
|
2185
|
+
} catch (error) {
|
|
2186
|
+
snapshot = {
|
|
2187
|
+
...snapshot,
|
|
2188
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2189
|
+
isLoading: false
|
|
2190
|
+
};
|
|
2191
|
+
emit();
|
|
2192
|
+
throw error;
|
|
2193
|
+
}
|
|
2194
|
+
};
|
|
2195
|
+
const close = () => {
|
|
2196
|
+
closed = true;
|
|
2197
|
+
if (timer) {
|
|
2198
|
+
clearInterval(timer);
|
|
2199
|
+
timer = undefined;
|
|
2200
|
+
}
|
|
2201
|
+
listeners.clear();
|
|
2202
|
+
};
|
|
2203
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
2204
|
+
timer = setInterval(() => {
|
|
2205
|
+
refresh().catch(() => {});
|
|
2206
|
+
}, options.intervalMs);
|
|
2207
|
+
}
|
|
2208
|
+
return {
|
|
2209
|
+
close,
|
|
2210
|
+
getServerSnapshot: () => snapshot,
|
|
2211
|
+
getSnapshot: () => snapshot,
|
|
2212
|
+
refresh,
|
|
2213
|
+
subscribe: (listener) => {
|
|
2214
|
+
listeners.add(listener);
|
|
2215
|
+
return () => {
|
|
2216
|
+
listeners.delete(listener);
|
|
2217
|
+
};
|
|
2218
|
+
}
|
|
2219
|
+
};
|
|
2220
|
+
};
|
|
2143
2221
|
// src/client/opsActionCenter.ts
|
|
2144
2222
|
var recordVoiceOpsActionResult = async (result, options = {}) => {
|
|
2145
2223
|
if (options.auditPath === false) {
|
|
@@ -2850,10 +2928,225 @@ var defineVoicePlatformCoverageElement = (tagName = "absolute-voice-platform-cov
|
|
|
2850
2928
|
}
|
|
2851
2929
|
});
|
|
2852
2930
|
};
|
|
2853
|
-
// src/
|
|
2854
|
-
|
|
2855
|
-
var
|
|
2931
|
+
// src/proofTrends.ts
|
|
2932
|
+
import { Elysia } from "elysia";
|
|
2933
|
+
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
2934
|
+
var normalizeMaxAgeMs = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS;
|
|
2935
|
+
var toTimeMs = (value) => {
|
|
2936
|
+
if (value instanceof Date) {
|
|
2937
|
+
return value.getTime();
|
|
2938
|
+
}
|
|
2939
|
+
if (typeof value === "number") {
|
|
2940
|
+
return value;
|
|
2941
|
+
}
|
|
2942
|
+
if (typeof value === "string") {
|
|
2943
|
+
return Date.parse(value);
|
|
2944
|
+
}
|
|
2945
|
+
return Date.now();
|
|
2946
|
+
};
|
|
2947
|
+
var buildVoiceProofTrendReport = (input = {}) => {
|
|
2948
|
+
const maxAgeMs = normalizeMaxAgeMs(input.maxAgeMs);
|
|
2949
|
+
const nowMs = toTimeMs(input.now);
|
|
2950
|
+
const generatedAtMs = typeof input.generatedAt === "string" ? Date.parse(input.generatedAt) : Number.NaN;
|
|
2951
|
+
const ageMs = Number.isFinite(generatedAtMs) && Number.isFinite(nowMs) ? Math.max(0, nowMs - generatedAtMs) : undefined;
|
|
2952
|
+
const freshUntil = Number.isFinite(generatedAtMs) && Number.isFinite(maxAgeMs) ? new Date(generatedAtMs + maxAgeMs).toISOString() : undefined;
|
|
2953
|
+
const isFresh = ageMs !== undefined && ageMs <= maxAgeMs;
|
|
2954
|
+
const status = input.status === "empty" ? "empty" : !isFresh ? "stale" : input.ok === true ? "pass" : "fail";
|
|
2955
|
+
return {
|
|
2956
|
+
ageMs,
|
|
2957
|
+
baseUrl: input.baseUrl,
|
|
2958
|
+
cycles: input.cycles ?? [],
|
|
2959
|
+
freshUntil,
|
|
2960
|
+
generatedAt: input.generatedAt,
|
|
2961
|
+
maxAgeMs,
|
|
2962
|
+
ok: input.ok === true && status === "pass",
|
|
2963
|
+
outputDir: input.outputDir,
|
|
2964
|
+
runId: input.runId,
|
|
2965
|
+
source: input.source ?? "",
|
|
2966
|
+
status,
|
|
2967
|
+
summary: input.summary ?? {}
|
|
2968
|
+
};
|
|
2969
|
+
};
|
|
2970
|
+
var buildEmptyVoiceProofTrendReport = (source = "", maxAgeMs) => buildVoiceProofTrendReport({
|
|
2971
|
+
maxAgeMs,
|
|
2972
|
+
source,
|
|
2973
|
+
status: "empty"
|
|
2974
|
+
});
|
|
2975
|
+
var normalizeVoiceProofTrendReport = (value, options = {}) => {
|
|
2976
|
+
if ("status" in value && value.status === "empty") {
|
|
2977
|
+
return buildEmptyVoiceProofTrendReport(value.source || options.source || "", options.maxAgeMs ?? value.maxAgeMs);
|
|
2978
|
+
}
|
|
2979
|
+
return buildVoiceProofTrendReport({
|
|
2980
|
+
...value,
|
|
2981
|
+
maxAgeMs: options.maxAgeMs ?? value.maxAgeMs,
|
|
2982
|
+
source: value.source ?? options.source
|
|
2983
|
+
});
|
|
2984
|
+
};
|
|
2985
|
+
var readVoiceProofTrendReportFile = async (path, options = {}) => {
|
|
2986
|
+
const file = Bun.file(path);
|
|
2987
|
+
if (!await file.exists()) {
|
|
2988
|
+
return buildEmptyVoiceProofTrendReport(path, options.maxAgeMs);
|
|
2989
|
+
}
|
|
2990
|
+
try {
|
|
2991
|
+
const parsed = await file.json();
|
|
2992
|
+
return normalizeVoiceProofTrendReport(parsed, {
|
|
2993
|
+
maxAgeMs: options.maxAgeMs,
|
|
2994
|
+
source: path
|
|
2995
|
+
});
|
|
2996
|
+
} catch {
|
|
2997
|
+
return buildVoiceProofTrendReport({
|
|
2998
|
+
maxAgeMs: options.maxAgeMs,
|
|
2999
|
+
source: path
|
|
3000
|
+
});
|
|
3001
|
+
}
|
|
3002
|
+
};
|
|
3003
|
+
var createVoiceProofTrendRoutes = (options) => {
|
|
3004
|
+
const path = options.path ?? "/api/voice/proof-trends";
|
|
3005
|
+
const routes = new Elysia({
|
|
3006
|
+
name: options.name ?? "absolutejs-voice-proof-trends"
|
|
3007
|
+
});
|
|
3008
|
+
routes.get(path, async () => {
|
|
3009
|
+
const value = options.source !== undefined ? typeof options.source === "function" ? await options.source() : options.source : options.jsonPath ? await readVoiceProofTrendReportFile(options.jsonPath, {
|
|
3010
|
+
maxAgeMs: options.maxAgeMs
|
|
3011
|
+
}) : buildEmptyVoiceProofTrendReport("", options.maxAgeMs);
|
|
3012
|
+
return Response.json(normalizeVoiceProofTrendReport(value, {
|
|
3013
|
+
maxAgeMs: options.maxAgeMs,
|
|
3014
|
+
source: options.jsonPath
|
|
3015
|
+
}), { headers: options.headers });
|
|
3016
|
+
});
|
|
3017
|
+
return routes;
|
|
3018
|
+
};
|
|
3019
|
+
var formatVoiceProofTrendAge = (ageMs) => {
|
|
3020
|
+
if (typeof ageMs !== "number" || !Number.isFinite(ageMs)) {
|
|
3021
|
+
return "unknown";
|
|
3022
|
+
}
|
|
3023
|
+
const minutes = Math.floor(ageMs / 60000);
|
|
3024
|
+
if (minutes < 1) {
|
|
3025
|
+
return "less than 1m";
|
|
3026
|
+
}
|
|
3027
|
+
if (minutes < 60) {
|
|
3028
|
+
return `${minutes}m`;
|
|
3029
|
+
}
|
|
3030
|
+
const hours = Math.floor(minutes / 60);
|
|
3031
|
+
if (hours < 48) {
|
|
3032
|
+
return `${hours}h ${minutes % 60}m`;
|
|
3033
|
+
}
|
|
3034
|
+
const days = Math.floor(hours / 24);
|
|
3035
|
+
return `${days}d ${hours % 24}h`;
|
|
3036
|
+
};
|
|
3037
|
+
|
|
3038
|
+
// src/client/proofTrendsWidget.ts
|
|
3039
|
+
var DEFAULT_TITLE3 = "Sustained Proof Trends";
|
|
3040
|
+
var DEFAULT_DESCRIPTION3 = "Repeated-cycle provider, latency, recovery, and readiness evidence with freshness gating.";
|
|
3041
|
+
var DEFAULT_LINKS2 = [
|
|
3042
|
+
{ href: "/voice/proof-trends", label: "Trend page" },
|
|
3043
|
+
{ href: "/api/voice/proof-trends", label: "Trend JSON" }
|
|
3044
|
+
];
|
|
2856
3045
|
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3046
|
+
var formatMs = (value) => typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}ms` : "n/a";
|
|
3047
|
+
var statusLabel = (report) => {
|
|
3048
|
+
if (!report) {
|
|
3049
|
+
return "No trend report";
|
|
3050
|
+
}
|
|
3051
|
+
if (report.status === "pass") {
|
|
3052
|
+
return `${report.summary.cycles ?? report.cycles.length} cycles passing`;
|
|
3053
|
+
}
|
|
3054
|
+
return report.status;
|
|
3055
|
+
};
|
|
3056
|
+
var createVoiceProofTrendsViewModel = (snapshot, options = {}) => {
|
|
3057
|
+
const report = snapshot.report;
|
|
3058
|
+
const metrics = report ? [
|
|
3059
|
+
{ label: "Status", value: report.status.toUpperCase() },
|
|
3060
|
+
{
|
|
3061
|
+
label: "Cycles",
|
|
3062
|
+
value: String(report.summary.cycles ?? report.cycles.length)
|
|
3063
|
+
},
|
|
3064
|
+
{
|
|
3065
|
+
label: "Provider p95",
|
|
3066
|
+
value: formatMs(report.summary.maxProviderP95Ms)
|
|
3067
|
+
},
|
|
3068
|
+
{ label: "Turn p95", value: formatMs(report.summary.maxTurnP95Ms) },
|
|
3069
|
+
{ label: "Live p95", value: formatMs(report.summary.maxLiveP95Ms) },
|
|
3070
|
+
{
|
|
3071
|
+
label: "Artifact age",
|
|
3072
|
+
value: formatVoiceProofTrendAge(report.ageMs)
|
|
3073
|
+
},
|
|
3074
|
+
{
|
|
3075
|
+
label: "Stale after",
|
|
3076
|
+
value: formatVoiceProofTrendAge(report.maxAgeMs)
|
|
3077
|
+
}
|
|
3078
|
+
] : [];
|
|
3079
|
+
return {
|
|
3080
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
3081
|
+
error: snapshot.error,
|
|
3082
|
+
isLoading: snapshot.isLoading,
|
|
3083
|
+
label: snapshot.error ? "Unavailable" : report ? statusLabel(report) : snapshot.isLoading ? "Checking" : "No trend report",
|
|
3084
|
+
links: options.links ?? DEFAULT_LINKS2,
|
|
3085
|
+
metrics,
|
|
3086
|
+
report,
|
|
3087
|
+
status: snapshot.error ? "error" : report ? report.status === "pass" ? "ready" : "warning" : snapshot.isLoading ? "loading" : "empty",
|
|
3088
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
3089
|
+
updatedAt: snapshot.updatedAt
|
|
3090
|
+
};
|
|
3091
|
+
};
|
|
3092
|
+
var renderVoiceProofTrendsHTML = (snapshot, options = {}) => {
|
|
3093
|
+
const model = createVoiceProofTrendsViewModel(snapshot, options);
|
|
3094
|
+
const metrics = model.metrics.length ? `<div class="absolute-voice-proof-trends__metrics">${model.metrics.map((metric) => `<article>
|
|
3095
|
+
<span>${escapeHtml3(metric.label)}</span>
|
|
3096
|
+
<strong>${escapeHtml3(metric.value)}</strong>
|
|
3097
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-proof-trends__empty">${model.error ? escapeHtml3(model.error) : "Run the sustained proof trends script to populate evidence."}</p>`;
|
|
3098
|
+
const links = model.links.length ? `<p class="absolute-voice-proof-trends__links">${model.links.map((link) => `<a href="${escapeHtml3(link.href)}">${escapeHtml3(link.label)}</a>`).join("")}</p>` : "";
|
|
3099
|
+
return `<section class="absolute-voice-proof-trends absolute-voice-proof-trends--${escapeHtml3(model.status)}">
|
|
3100
|
+
<header class="absolute-voice-proof-trends__header">
|
|
3101
|
+
<span class="absolute-voice-proof-trends__eyebrow">${escapeHtml3(model.title)}</span>
|
|
3102
|
+
<strong class="absolute-voice-proof-trends__label">${escapeHtml3(model.label)}</strong>
|
|
3103
|
+
</header>
|
|
3104
|
+
<p class="absolute-voice-proof-trends__description">${escapeHtml3(model.description)}</p>
|
|
3105
|
+
${metrics}
|
|
3106
|
+
${links}
|
|
3107
|
+
${model.error ? `<p class="absolute-voice-proof-trends__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
3108
|
+
</section>`;
|
|
3109
|
+
};
|
|
3110
|
+
var getVoiceProofTrendsCSS = () => `.absolute-voice-proof-trends{border:1px solid #99f6e4;border-radius:20px;background:#f0fdfa;color:#0f172a;padding:18px;box-shadow:0 18px 40px rgba(13,148,136,.12);font-family:inherit}.absolute-voice-proof-trends--warning,.absolute-voice-proof-trends--error{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-proof-trends__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-proof-trends__eyebrow{color:#0f766e;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-proof-trends__label{font-size:24px;line-height:1}.absolute-voice-proof-trends__description,.absolute-voice-proof-trends__empty{color:#475569}.absolute-voice-proof-trends__metrics{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));margin-top:14px}.absolute-voice-proof-trends__metrics article{background:#fff;border:1px solid #ccfbf1;border-radius:16px;padding:12px}.absolute-voice-proof-trends__metrics span{color:#64748b;display:block;font-size:12px;font-weight:800;text-transform:uppercase}.absolute-voice-proof-trends__metrics strong{display:block;font-size:20px;margin-top:4px}.absolute-voice-proof-trends__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-proof-trends__links a{border:1px solid #99f6e4;border-radius:999px;color:#0f766e;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-proof-trends__error{color:#9f1239;font-weight:700}`;
|
|
3111
|
+
var mountVoiceProofTrends = (element, path = "/api/voice/proof-trends", options = {}) => {
|
|
3112
|
+
const store = createVoiceProofTrendsStore(path, options);
|
|
3113
|
+
const render = () => {
|
|
3114
|
+
element.innerHTML = renderVoiceProofTrendsHTML(store.getSnapshot(), options);
|
|
3115
|
+
};
|
|
3116
|
+
const unsubscribe = store.subscribe(render);
|
|
3117
|
+
render();
|
|
3118
|
+
store.refresh().catch(() => {});
|
|
3119
|
+
return {
|
|
3120
|
+
close: () => {
|
|
3121
|
+
unsubscribe();
|
|
3122
|
+
store.close();
|
|
3123
|
+
},
|
|
3124
|
+
refresh: store.refresh
|
|
3125
|
+
};
|
|
3126
|
+
};
|
|
3127
|
+
var defineVoiceProofTrendsElement = (tagName = "absolute-voice-proof-trends") => {
|
|
3128
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
3129
|
+
return;
|
|
3130
|
+
}
|
|
3131
|
+
customElements.define(tagName, class AbsoluteVoiceProofTrendsElement extends HTMLElement {
|
|
3132
|
+
mounted;
|
|
3133
|
+
connectedCallback() {
|
|
3134
|
+
this.mounted = mountVoiceProofTrends(this, this.getAttribute("path") ?? "/api/voice/proof-trends", {
|
|
3135
|
+
description: this.getAttribute("description") ?? undefined,
|
|
3136
|
+
intervalMs: Number(this.getAttribute("interval-ms") ?? 0) || undefined,
|
|
3137
|
+
title: this.getAttribute("title") ?? undefined
|
|
3138
|
+
});
|
|
3139
|
+
}
|
|
3140
|
+
disconnectedCallback() {
|
|
3141
|
+
this.mounted?.close();
|
|
3142
|
+
this.mounted = undefined;
|
|
3143
|
+
}
|
|
3144
|
+
});
|
|
3145
|
+
};
|
|
3146
|
+
// src/client/opsActionCenterWidget.ts
|
|
3147
|
+
var DEFAULT_TITLE4 = "Voice Ops Action Center";
|
|
3148
|
+
var DEFAULT_DESCRIPTION4 = "Run production voice proofs and operator actions from one primitive panel.";
|
|
3149
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2857
3150
|
var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
2858
3151
|
const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
|
|
2859
3152
|
return {
|
|
@@ -2864,29 +3157,29 @@ var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
|
2864
3157
|
isRunning: snapshot.runningActionId === action.id,
|
|
2865
3158
|
label: action.label
|
|
2866
3159
|
})),
|
|
2867
|
-
description: options.description ??
|
|
3160
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
2868
3161
|
error: snapshot.error,
|
|
2869
3162
|
isRunning: snapshot.isRunning,
|
|
2870
3163
|
label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
|
|
2871
3164
|
lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
|
|
2872
3165
|
status,
|
|
2873
|
-
title: options.title ??
|
|
3166
|
+
title: options.title ?? DEFAULT_TITLE4
|
|
2874
3167
|
};
|
|
2875
3168
|
};
|
|
2876
3169
|
var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
|
|
2877
3170
|
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
2878
|
-
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${
|
|
2879
|
-
${
|
|
3171
|
+
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml4(action.id)}"${action.disabled ? " disabled" : ""}>
|
|
3172
|
+
${escapeHtml4(action.isRunning ? "Working..." : action.label)}
|
|
2880
3173
|
</button>`).join("");
|
|
2881
|
-
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${
|
|
3174
|
+
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml4(model.status)}">
|
|
2882
3175
|
<header class="absolute-voice-ops-action-center__header">
|
|
2883
|
-
<span class="absolute-voice-ops-action-center__eyebrow">${
|
|
2884
|
-
<strong class="absolute-voice-ops-action-center__label">${
|
|
3176
|
+
<span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml4(model.title)}</span>
|
|
3177
|
+
<strong class="absolute-voice-ops-action-center__label">${escapeHtml4(model.label)}</strong>
|
|
2885
3178
|
</header>
|
|
2886
|
-
<p class="absolute-voice-ops-action-center__description">${
|
|
3179
|
+
<p class="absolute-voice-ops-action-center__description">${escapeHtml4(model.description)}</p>
|
|
2887
3180
|
<div class="absolute-voice-ops-action-center__actions">${actions}</div>
|
|
2888
|
-
<p class="absolute-voice-ops-action-center__result">${
|
|
2889
|
-
${model.error ? `<p class="absolute-voice-ops-action-center__error">${
|
|
3181
|
+
<p class="absolute-voice-ops-action-center__result">${escapeHtml4(model.lastResultLabel)}</p>
|
|
3182
|
+
${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml4(model.error)}</p>` : ""}
|
|
2890
3183
|
</section>`;
|
|
2891
3184
|
};
|
|
2892
3185
|
var getVoiceOpsActionCenterCSS = () => `.absolute-voice-ops-action-center{border:1px solid #d5cbb8;border-radius:20px;background:#fffaf1;color:#17130b;padding:18px;box-shadow:0 18px 40px rgba(58,42,16,.12);font-family:inherit}.absolute-voice-ops-action-center--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-action-center__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-action-center__eyebrow{color:#725d37;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-action-center__label{font-size:28px;line-height:1}.absolute-voice-ops-action-center__description,.absolute-voice-ops-action-center__result{color:#5b4b2f;margin:12px 0 0}.absolute-voice-ops-action-center__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-action-center__actions button{background:#7c4a03;border:0;border-radius:999px;color:#fff8e8;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-ops-action-center__actions button:disabled{cursor:not-allowed;opacity:.5}.absolute-voice-ops-action-center__error{color:#9f1239;font-weight:700}`;
|
|
@@ -2938,7 +3231,7 @@ var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-ce
|
|
|
2938
3231
|
});
|
|
2939
3232
|
};
|
|
2940
3233
|
// src/liveOps.ts
|
|
2941
|
-
import { Elysia } from "elysia";
|
|
3234
|
+
import { Elysia as Elysia2 } from "elysia";
|
|
2942
3235
|
|
|
2943
3236
|
// src/audit.ts
|
|
2944
3237
|
var includes = (filter, value) => {
|
|
@@ -3487,7 +3780,7 @@ var exportVoiceTrace = async (input) => {
|
|
|
3487
3780
|
};
|
|
3488
3781
|
};
|
|
3489
3782
|
var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
3490
|
-
var
|
|
3783
|
+
var escapeHtml5 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
3491
3784
|
var formatTraceValue = (value) => {
|
|
3492
3785
|
if (value === undefined || value === null) {
|
|
3493
3786
|
return "";
|
|
@@ -3767,10 +4060,10 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
3767
4060
|
const offset = summary.startedAt === undefined ? event.at : Math.max(0, event.at - summary.startedAt);
|
|
3768
4061
|
return [
|
|
3769
4062
|
"<tr>",
|
|
3770
|
-
`<td>${
|
|
3771
|
-
`<td>${
|
|
3772
|
-
`<td>${
|
|
3773
|
-
`<td><code>${
|
|
4063
|
+
`<td>${escapeHtml5(String(offset))}</td>`,
|
|
4064
|
+
`<td>${escapeHtml5(event.type)}</td>`,
|
|
4065
|
+
`<td>${escapeHtml5(event.turnId ?? "")}</td>`,
|
|
4066
|
+
`<td><code>${escapeHtml5(JSON.stringify(event.payload))}</code></td>`,
|
|
3774
4067
|
"</tr>"
|
|
3775
4068
|
].join("");
|
|
3776
4069
|
}).join(`
|
|
@@ -3781,7 +4074,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
3781
4074
|
"<head>",
|
|
3782
4075
|
'<meta charset="utf-8" />',
|
|
3783
4076
|
'<meta name="viewport" content="width=device-width, initial-scale=1" />',
|
|
3784
|
-
`<title>${
|
|
4077
|
+
`<title>${escapeHtml5(options.title ?? "Voice Trace")}</title>`,
|
|
3785
4078
|
"<style>",
|
|
3786
4079
|
"body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;line-height:1.45;background:#f8f7f2;color:#181713}",
|
|
3787
4080
|
"main{max-width:1100px;margin:auto}",
|
|
@@ -3795,7 +4088,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
3795
4088
|
"</style>",
|
|
3796
4089
|
"</head>",
|
|
3797
4090
|
"<body><main>",
|
|
3798
|
-
`<h1>${
|
|
4091
|
+
`<h1>${escapeHtml5(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</h1>`,
|
|
3799
4092
|
`<p class="${evaluation.pass ? "pass" : "fail"}">QA: ${evaluation.pass ? "pass" : "fail"}</p>`,
|
|
3800
4093
|
'<section class="summary">',
|
|
3801
4094
|
`<div class="card"><strong>Events</strong><br>${summary.eventCount}</div>`,
|
|
@@ -3809,7 +4102,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
3809
4102
|
eventRows,
|
|
3810
4103
|
"</tbody></table>",
|
|
3811
4104
|
"<h2>Markdown Export</h2>",
|
|
3812
|
-
`<pre>${
|
|
4105
|
+
`<pre>${escapeHtml5(markdown)}</pre>`,
|
|
3813
4106
|
"</main></body></html>"
|
|
3814
4107
|
].join(`
|
|
3815
4108
|
`);
|
|
@@ -3986,7 +4279,7 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
3986
4279
|
const controller = createVoiceLiveOpsController(options);
|
|
3987
4280
|
const path = options.path ?? "/api/voice/live-ops/action";
|
|
3988
4281
|
const controlPath = options.controlPath ?? "/api/voice/live-ops/control/:sessionId";
|
|
3989
|
-
return new
|
|
4282
|
+
return new Elysia2({
|
|
3990
4283
|
name: options.name ?? "absolutejs-voice-live-ops"
|
|
3991
4284
|
}).post(path, async ({ request, set }) => {
|
|
3992
4285
|
try {
|
|
@@ -4020,7 +4313,7 @@ var ACTION_LABELS = {
|
|
|
4020
4313
|
"resume-assistant": "Resume assistant",
|
|
4021
4314
|
tag: "Tag"
|
|
4022
4315
|
};
|
|
4023
|
-
var
|
|
4316
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4024
4317
|
var createVoiceLiveOpsInput = (action, input) => ({
|
|
4025
4318
|
action,
|
|
4026
4319
|
assignee: input.assignee,
|
|
@@ -4031,17 +4324,17 @@ var createVoiceLiveOpsInput = (action, input) => ({
|
|
|
4031
4324
|
var renderVoiceLiveOpsHTML = (snapshot, options = {}) => {
|
|
4032
4325
|
const sessionId = options.getSessionId?.() ?? "";
|
|
4033
4326
|
const disabled = snapshot.isRunning || !sessionId;
|
|
4034
|
-
const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${
|
|
4035
|
-
const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${
|
|
4327
|
+
const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml6(action)}"${disabled ? " disabled" : ""}>${escapeHtml6(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
|
|
4328
|
+
const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml6(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml6(snapshot.lastResult.action)}. Control: ${escapeHtml6(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
|
|
4036
4329
|
return `<section class="absolute-voice-live-ops">
|
|
4037
4330
|
<header class="absolute-voice-live-ops__header">
|
|
4038
|
-
<span>${
|
|
4039
|
-
<strong>${
|
|
4331
|
+
<span>${escapeHtml6(options.title ?? "Live Ops")}</span>
|
|
4332
|
+
<strong>${escapeHtml6(sessionId || "No active session")}</strong>
|
|
4040
4333
|
</header>
|
|
4041
|
-
<p class="absolute-voice-live-ops__description">${
|
|
4042
|
-
<label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${
|
|
4043
|
-
<label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${
|
|
4044
|
-
<label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${
|
|
4334
|
+
<p class="absolute-voice-live-ops__description">${escapeHtml6(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
|
|
4335
|
+
<label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml6(options.defaultAssignee ?? "operator")}" /></label>
|
|
4336
|
+
<label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml6(options.defaultTag ?? "live-ops")}" /></label>
|
|
4337
|
+
<label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml6(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
|
|
4045
4338
|
<div class="absolute-voice-live-ops__actions">${actions}</div>
|
|
4046
4339
|
${result}
|
|
4047
4340
|
</section>`;
|
|
@@ -4128,16 +4421,16 @@ var defineVoiceLiveOpsElement = (tagName = "absolute-voice-live-ops", options =
|
|
|
4128
4421
|
});
|
|
4129
4422
|
};
|
|
4130
4423
|
// src/client/opsActionHistoryWidget.ts
|
|
4131
|
-
var
|
|
4424
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4132
4425
|
var renderVoiceOpsActionHistoryWidgetHTML = (snapshot, options = {}) => {
|
|
4133
4426
|
const report = snapshot.report;
|
|
4134
4427
|
const entries = (report?.entries ?? []).slice(0, options.limit ?? 5);
|
|
4135
|
-
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${
|
|
4428
|
+
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${escapeHtml7(entry.actionId)}</span><strong>${escapeHtml7(entry.ok ? "Success" : "Failed")}</strong><small>${escapeHtml7(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</small></li>`).join("");
|
|
4136
4429
|
return `<section class="absolute-voice-ops-action-history">
|
|
4137
|
-
<header><span>Operator proof</span><strong>${
|
|
4430
|
+
<header><span>Operator proof</span><strong>${escapeHtml7(options.title ?? "Action History")}</strong></header>
|
|
4138
4431
|
<p>${String(report?.total ?? 0)} action(s), ${String(report?.failed ?? 0)} failed.</p>
|
|
4139
4432
|
<ul>${rows || "<li>No operator actions recorded yet.</li>"}</ul>
|
|
4140
|
-
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${
|
|
4433
|
+
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${escapeHtml7(snapshot.error)}</p>` : ""}
|
|
4141
4434
|
</section>`;
|
|
4142
4435
|
};
|
|
4143
4436
|
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}`;
|
|
@@ -4158,9 +4451,9 @@ var mountVoiceOpsActionHistory = (element, path = "/api/voice/ops-actions/histor
|
|
|
4158
4451
|
};
|
|
4159
4452
|
};
|
|
4160
4453
|
// src/client/deliveryRuntimeWidget.ts
|
|
4161
|
-
var
|
|
4162
|
-
var
|
|
4163
|
-
var
|
|
4454
|
+
var DEFAULT_TITLE5 = "Voice Delivery Runtime";
|
|
4455
|
+
var DEFAULT_DESCRIPTION5 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
4456
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4164
4457
|
var createSurface = (id, summary) => {
|
|
4165
4458
|
if (!summary) {
|
|
4166
4459
|
return {
|
|
@@ -4194,7 +4487,7 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
4194
4487
|
];
|
|
4195
4488
|
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
4196
4489
|
return {
|
|
4197
|
-
description: options.description ??
|
|
4490
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
4198
4491
|
error: snapshot.error,
|
|
4199
4492
|
actionError: snapshot.actionError,
|
|
4200
4493
|
actionStatus: snapshot.actionStatus,
|
|
@@ -4203,32 +4496,32 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
4203
4496
|
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
4204
4497
|
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
4205
4498
|
surfaces,
|
|
4206
|
-
title: options.title ??
|
|
4499
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
4207
4500
|
updatedAt: snapshot.updatedAt
|
|
4208
4501
|
};
|
|
4209
4502
|
};
|
|
4210
4503
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
4211
4504
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
4212
|
-
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${
|
|
4213
|
-
<span>${
|
|
4214
|
-
<strong>${
|
|
4505
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml8(surface.status)}">
|
|
4506
|
+
<span>${escapeHtml8(surface.label)}</span>
|
|
4507
|
+
<strong>${escapeHtml8(surface.detail)}</strong>
|
|
4215
4508
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
4216
4509
|
</li>`).join("");
|
|
4217
4510
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
4218
4511
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
4219
4512
|
<button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
|
|
4220
4513
|
</div>`;
|
|
4221
|
-
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
4222
|
-
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${
|
|
4514
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml8(model.actionError)}</p>` : "";
|
|
4515
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml8(model.status)}">
|
|
4223
4516
|
<header class="absolute-voice-delivery-runtime__header">
|
|
4224
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
4225
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
4517
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml8(model.title)}</span>
|
|
4518
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml8(model.label)}</strong>
|
|
4226
4519
|
</header>
|
|
4227
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
4520
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml8(model.description)}</p>
|
|
4228
4521
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
4229
4522
|
${actions}
|
|
4230
4523
|
${actionError}
|
|
4231
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
4524
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
4232
4525
|
</section>`;
|
|
4233
4526
|
};
|
|
4234
4527
|
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}`;
|
|
@@ -4364,9 +4657,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
4364
4657
|
};
|
|
4365
4658
|
};
|
|
4366
4659
|
// src/client/routingStatusWidget.ts
|
|
4367
|
-
var
|
|
4368
|
-
var
|
|
4369
|
-
var
|
|
4660
|
+
var DEFAULT_TITLE6 = "Voice Routing";
|
|
4661
|
+
var DEFAULT_DESCRIPTION6 = "Latest provider routing decision from the self-hosted trace store.";
|
|
4662
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4370
4663
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
4371
4664
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
4372
4665
|
const decision = snapshot.decision;
|
|
@@ -4390,30 +4683,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
4390
4683
|
] : [];
|
|
4391
4684
|
return {
|
|
4392
4685
|
decision,
|
|
4393
|
-
description: options.description ??
|
|
4686
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
4394
4687
|
error: snapshot.error,
|
|
4395
4688
|
isLoading: snapshot.isLoading,
|
|
4396
4689
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
4397
4690
|
rows,
|
|
4398
4691
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
4399
|
-
title: options.title ??
|
|
4692
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
4400
4693
|
updatedAt: snapshot.updatedAt
|
|
4401
4694
|
};
|
|
4402
4695
|
};
|
|
4403
4696
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
4404
4697
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
4405
4698
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
4406
|
-
<span>${
|
|
4407
|
-
<strong>${
|
|
4699
|
+
<span>${escapeHtml9(row.label)}</span>
|
|
4700
|
+
<strong>${escapeHtml9(row.value)}</strong>
|
|
4408
4701
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
4409
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
4702
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml9(model.status)}">
|
|
4410
4703
|
<header class="absolute-voice-routing-status__header">
|
|
4411
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
4412
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
4704
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml9(model.title)}</span>
|
|
4705
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml9(model.label)}</strong>
|
|
4413
4706
|
</header>
|
|
4414
|
-
<p class="absolute-voice-routing-status__description">${
|
|
4707
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml9(model.description)}</p>
|
|
4415
4708
|
${rows}
|
|
4416
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
4709
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
4417
4710
|
</section>`;
|
|
4418
4711
|
};
|
|
4419
4712
|
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}`;
|
|
@@ -5212,7 +5505,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
5212
5505
|
};
|
|
5213
5506
|
};
|
|
5214
5507
|
// src/client/providerSimulationControlsWidget.ts
|
|
5215
|
-
var
|
|
5508
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5216
5509
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
5217
5510
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
5218
5511
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -5232,18 +5525,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
5232
5525
|
};
|
|
5233
5526
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
5234
5527
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
5235
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
5236
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
5528
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml10(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml10(provider.provider)} ${escapeHtml10(formatKind(options.kind))} failure</button>`).join("");
|
|
5529
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml10(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml10(provider.provider)} recovered</button>`).join("");
|
|
5237
5530
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
5238
5531
|
<header class="absolute-voice-provider-simulation__header">
|
|
5239
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
5240
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
5532
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml10(model.title)}</span>
|
|
5533
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml10(model.label)}</strong>
|
|
5241
5534
|
</header>
|
|
5242
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
5243
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
5535
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml10(model.description)}</p>
|
|
5536
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml10(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
5244
5537
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
5245
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
5246
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
5538
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml10(snapshot.error)}</p>` : ""}
|
|
5539
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml10(model.resultText)}</pre>` : ""}
|
|
5247
5540
|
</section>`;
|
|
5248
5541
|
};
|
|
5249
5542
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -5308,9 +5601,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
5308
5601
|
});
|
|
5309
5602
|
};
|
|
5310
5603
|
// src/client/providerStatusWidget.ts
|
|
5311
|
-
var
|
|
5312
|
-
var
|
|
5313
|
-
var
|
|
5604
|
+
var DEFAULT_TITLE7 = "Voice Providers";
|
|
5605
|
+
var DEFAULT_DESCRIPTION7 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
5606
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5314
5607
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
5315
5608
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
5316
5609
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -5354,37 +5647,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
5354
5647
|
const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
|
|
5355
5648
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
5356
5649
|
return {
|
|
5357
|
-
description: options.description ??
|
|
5650
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
5358
5651
|
error: snapshot.error,
|
|
5359
5652
|
isLoading: snapshot.isLoading,
|
|
5360
5653
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
5361
5654
|
providers,
|
|
5362
5655
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
5363
|
-
title: options.title ??
|
|
5656
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
5364
5657
|
updatedAt: snapshot.updatedAt
|
|
5365
5658
|
};
|
|
5366
5659
|
};
|
|
5367
5660
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
5368
5661
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
5369
|
-
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--${
|
|
5662
|
+
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--${escapeHtml11(provider.status)}">
|
|
5370
5663
|
<header>
|
|
5371
|
-
<strong>${
|
|
5372
|
-
<span>${
|
|
5664
|
+
<strong>${escapeHtml11(provider.label)}</strong>
|
|
5665
|
+
<span>${escapeHtml11(formatStatus2(provider.status))}</span>
|
|
5373
5666
|
</header>
|
|
5374
|
-
<p>${
|
|
5667
|
+
<p>${escapeHtml11(provider.detail)}</p>
|
|
5375
5668
|
<dl>${provider.rows.map((row) => `<div>
|
|
5376
|
-
<dt>${
|
|
5377
|
-
<dd>${
|
|
5669
|
+
<dt>${escapeHtml11(row.label)}</dt>
|
|
5670
|
+
<dd>${escapeHtml11(row.value)}</dd>
|
|
5378
5671
|
</div>`).join("")}</dl>
|
|
5379
5672
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
5380
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
5673
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml11(model.status)}">
|
|
5381
5674
|
<header class="absolute-voice-provider-status__header">
|
|
5382
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
5383
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
5675
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml11(model.title)}</span>
|
|
5676
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml11(model.label)}</strong>
|
|
5384
5677
|
</header>
|
|
5385
|
-
<p class="absolute-voice-provider-status__description">${
|
|
5678
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml11(model.description)}</p>
|
|
5386
5679
|
${providers}
|
|
5387
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
5680
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
5388
5681
|
</section>`;
|
|
5389
5682
|
};
|
|
5390
5683
|
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}`;
|
|
@@ -5425,9 +5718,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
5425
5718
|
});
|
|
5426
5719
|
};
|
|
5427
5720
|
// src/client/providerCapabilitiesWidget.ts
|
|
5428
|
-
var
|
|
5429
|
-
var
|
|
5430
|
-
var
|
|
5721
|
+
var DEFAULT_TITLE8 = "Provider Capabilities";
|
|
5722
|
+
var DEFAULT_DESCRIPTION8 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
5723
|
+
var escapeHtml12 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5431
5724
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
5432
5725
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
5433
5726
|
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -5471,36 +5764,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
5471
5764
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
5472
5765
|
return {
|
|
5473
5766
|
capabilities,
|
|
5474
|
-
description: options.description ??
|
|
5767
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
5475
5768
|
error: snapshot.error,
|
|
5476
5769
|
isLoading: snapshot.isLoading,
|
|
5477
5770
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
5478
5771
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
5479
|
-
title: options.title ??
|
|
5772
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
5480
5773
|
updatedAt: snapshot.updatedAt
|
|
5481
5774
|
};
|
|
5482
5775
|
};
|
|
5483
5776
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
5484
5777
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
5485
|
-
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--${
|
|
5778
|
+
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--${escapeHtml12(capability.status)}">
|
|
5486
5779
|
<header>
|
|
5487
|
-
<strong>${
|
|
5488
|
-
<span>${
|
|
5780
|
+
<strong>${escapeHtml12(capability.label)}</strong>
|
|
5781
|
+
<span>${escapeHtml12(formatStatus3(capability.status))}</span>
|
|
5489
5782
|
</header>
|
|
5490
|
-
<p>${
|
|
5783
|
+
<p>${escapeHtml12(capability.detail)}</p>
|
|
5491
5784
|
<dl>${capability.rows.map((row) => `<div>
|
|
5492
|
-
<dt>${
|
|
5493
|
-
<dd>${
|
|
5785
|
+
<dt>${escapeHtml12(row.label)}</dt>
|
|
5786
|
+
<dd>${escapeHtml12(row.value)}</dd>
|
|
5494
5787
|
</div>`).join("")}</dl>
|
|
5495
5788
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
5496
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
5789
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml12(model.status)}">
|
|
5497
5790
|
<header class="absolute-voice-provider-capabilities__header">
|
|
5498
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
5499
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
5791
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml12(model.title)}</span>
|
|
5792
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml12(model.label)}</strong>
|
|
5500
5793
|
</header>
|
|
5501
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
5794
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml12(model.description)}</p>
|
|
5502
5795
|
${capabilities}
|
|
5503
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
5796
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml12(model.error)}</p>` : ""}
|
|
5504
5797
|
</section>`;
|
|
5505
5798
|
};
|
|
5506
5799
|
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}`;
|
|
@@ -5541,9 +5834,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
5541
5834
|
});
|
|
5542
5835
|
};
|
|
5543
5836
|
// src/client/providerContractsWidget.ts
|
|
5544
|
-
var
|
|
5545
|
-
var
|
|
5546
|
-
var
|
|
5837
|
+
var DEFAULT_TITLE9 = "Provider Contracts";
|
|
5838
|
+
var DEFAULT_DESCRIPTION9 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
5839
|
+
var escapeHtml13 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5547
5840
|
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
5548
5841
|
var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
5549
5842
|
var contractDetail = (row) => {
|
|
@@ -5575,38 +5868,38 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
|
5575
5868
|
}));
|
|
5576
5869
|
const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
|
|
5577
5870
|
return {
|
|
5578
|
-
description: options.description ??
|
|
5871
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
5579
5872
|
error: snapshot.error,
|
|
5580
5873
|
isLoading: snapshot.isLoading,
|
|
5581
5874
|
label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
|
|
5582
5875
|
rows,
|
|
5583
5876
|
status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
5584
|
-
title: options.title ??
|
|
5877
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
5585
5878
|
updatedAt: snapshot.updatedAt
|
|
5586
5879
|
};
|
|
5587
5880
|
};
|
|
5588
5881
|
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
5589
5882
|
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
5590
|
-
const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${
|
|
5883
|
+
const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml13(row.status)}">
|
|
5591
5884
|
<header>
|
|
5592
|
-
<strong>${
|
|
5593
|
-
<span>${
|
|
5885
|
+
<strong>${escapeHtml13(row.label)}</strong>
|
|
5886
|
+
<span>${escapeHtml13(formatStatus4(row.status))}</span>
|
|
5594
5887
|
</header>
|
|
5595
|
-
<p>${
|
|
5596
|
-
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${
|
|
5888
|
+
<p>${escapeHtml13(row.detail)}</p>
|
|
5889
|
+
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml13(remediation.href)}">${escapeHtml13(remediation.label)}</a>` : `<strong>${escapeHtml13(remediation.label)}</strong>`}<span>${escapeHtml13(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
|
|
5597
5890
|
<dl>${row.rows.map((item) => `<div>
|
|
5598
|
-
<dt>${
|
|
5599
|
-
<dd>${
|
|
5891
|
+
<dt>${escapeHtml13(item.label)}</dt>
|
|
5892
|
+
<dd>${escapeHtml13(item.value)}</dd>
|
|
5600
5893
|
</div>`).join("")}</dl>
|
|
5601
5894
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
5602
|
-
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${
|
|
5895
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml13(model.status)}">
|
|
5603
5896
|
<header class="absolute-voice-provider-contracts__header">
|
|
5604
|
-
<span class="absolute-voice-provider-contracts__eyebrow">${
|
|
5605
|
-
<strong class="absolute-voice-provider-contracts__label">${
|
|
5897
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml13(model.title)}</span>
|
|
5898
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml13(model.label)}</strong>
|
|
5606
5899
|
</header>
|
|
5607
|
-
<p class="absolute-voice-provider-contracts__description">${
|
|
5900
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml13(model.description)}</p>
|
|
5608
5901
|
${rows}
|
|
5609
|
-
${model.error ? `<p class="absolute-voice-provider-contracts__error">${
|
|
5902
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml13(model.error)}</p>` : ""}
|
|
5610
5903
|
</section>`;
|
|
5611
5904
|
};
|
|
5612
5905
|
var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
|
|
@@ -5647,9 +5940,9 @@ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-co
|
|
|
5647
5940
|
});
|
|
5648
5941
|
};
|
|
5649
5942
|
// src/client/turnQualityWidget.ts
|
|
5650
|
-
var
|
|
5651
|
-
var
|
|
5652
|
-
var
|
|
5943
|
+
var DEFAULT_TITLE10 = "Turn Quality";
|
|
5944
|
+
var DEFAULT_DESCRIPTION10 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
5945
|
+
var escapeHtml14 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5653
5946
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
5654
5947
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
5655
5948
|
var getTurnDetail = (turn) => {
|
|
@@ -5687,37 +5980,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
5687
5980
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
5688
5981
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
5689
5982
|
return {
|
|
5690
|
-
description: options.description ??
|
|
5983
|
+
description: options.description ?? DEFAULT_DESCRIPTION10,
|
|
5691
5984
|
error: snapshot.error,
|
|
5692
5985
|
isLoading: snapshot.isLoading,
|
|
5693
5986
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
5694
5987
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
5695
|
-
title: options.title ??
|
|
5988
|
+
title: options.title ?? DEFAULT_TITLE10,
|
|
5696
5989
|
turns,
|
|
5697
5990
|
updatedAt: snapshot.updatedAt
|
|
5698
5991
|
};
|
|
5699
5992
|
};
|
|
5700
5993
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
5701
5994
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
5702
|
-
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--${
|
|
5995
|
+
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--${escapeHtml14(turn.status)}">
|
|
5703
5996
|
<header>
|
|
5704
|
-
<strong>${
|
|
5705
|
-
<span>${
|
|
5997
|
+
<strong>${escapeHtml14(turn.label)}</strong>
|
|
5998
|
+
<span>${escapeHtml14(turn.status)}</span>
|
|
5706
5999
|
</header>
|
|
5707
|
-
<p>${
|
|
6000
|
+
<p>${escapeHtml14(turn.detail)}</p>
|
|
5708
6001
|
<dl>${turn.rows.map((row) => `<div>
|
|
5709
|
-
<dt>${
|
|
5710
|
-
<dd>${
|
|
6002
|
+
<dt>${escapeHtml14(row.label)}</dt>
|
|
6003
|
+
<dd>${escapeHtml14(row.value)}</dd>
|
|
5711
6004
|
</div>`).join("")}</dl>
|
|
5712
6005
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
5713
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
6006
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml14(model.status)}">
|
|
5714
6007
|
<header class="absolute-voice-turn-quality__header">
|
|
5715
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
5716
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
6008
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml14(model.title)}</span>
|
|
6009
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml14(model.label)}</strong>
|
|
5717
6010
|
</header>
|
|
5718
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
6011
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml14(model.description)}</p>
|
|
5719
6012
|
${turns}
|
|
5720
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
6013
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml14(model.error)}</p>` : ""}
|
|
5721
6014
|
</section>`;
|
|
5722
6015
|
};
|
|
5723
6016
|
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}`;
|
|
@@ -5758,56 +6051,56 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
5758
6051
|
});
|
|
5759
6052
|
};
|
|
5760
6053
|
// src/client/turnLatencyWidget.ts
|
|
5761
|
-
var
|
|
5762
|
-
var
|
|
6054
|
+
var DEFAULT_TITLE11 = "Turn Latency";
|
|
6055
|
+
var DEFAULT_DESCRIPTION11 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
5763
6056
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
5764
|
-
var
|
|
5765
|
-
var
|
|
6057
|
+
var escapeHtml15 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6058
|
+
var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
5766
6059
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
5767
6060
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
5768
6061
|
...turn,
|
|
5769
6062
|
label: turn.text || "Empty turn",
|
|
5770
6063
|
rows: turn.stages.map((stage) => ({
|
|
5771
6064
|
label: stage.label,
|
|
5772
|
-
value:
|
|
6065
|
+
value: formatMs2(stage.valueMs)
|
|
5773
6066
|
}))
|
|
5774
6067
|
}));
|
|
5775
6068
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
5776
6069
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
5777
6070
|
return {
|
|
5778
|
-
description: options.description ??
|
|
6071
|
+
description: options.description ?? DEFAULT_DESCRIPTION11,
|
|
5779
6072
|
error: snapshot.error,
|
|
5780
6073
|
isLoading: snapshot.isLoading,
|
|
5781
|
-
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${
|
|
6074
|
+
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs2(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
5782
6075
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
5783
6076
|
showProofAction: Boolean(options.proofPath),
|
|
5784
6077
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
5785
|
-
title: options.title ??
|
|
6078
|
+
title: options.title ?? DEFAULT_TITLE11,
|
|
5786
6079
|
turns,
|
|
5787
6080
|
updatedAt: snapshot.updatedAt
|
|
5788
6081
|
};
|
|
5789
6082
|
};
|
|
5790
6083
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
5791
6084
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
5792
|
-
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--${
|
|
6085
|
+
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--${escapeHtml15(turn.status)}">
|
|
5793
6086
|
<header>
|
|
5794
|
-
<strong>${
|
|
5795
|
-
<span>${
|
|
6087
|
+
<strong>${escapeHtml15(turn.label)}</strong>
|
|
6088
|
+
<span>${escapeHtml15(turn.status)}</span>
|
|
5796
6089
|
</header>
|
|
5797
6090
|
<dl>${turn.rows.map((row) => `<div>
|
|
5798
|
-
<dt>${
|
|
5799
|
-
<dd>${
|
|
6091
|
+
<dt>${escapeHtml15(row.label)}</dt>
|
|
6092
|
+
<dd>${escapeHtml15(row.value)}</dd>
|
|
5800
6093
|
</div>`).join("")}</dl>
|
|
5801
6094
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
5802
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
6095
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml15(model.status)}">
|
|
5803
6096
|
<header class="absolute-voice-turn-latency__header">
|
|
5804
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
5805
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
6097
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml15(model.title)}</span>
|
|
6098
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml15(model.label)}</strong>
|
|
5806
6099
|
</header>
|
|
5807
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
5808
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
6100
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml15(model.description)}</p>
|
|
6101
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml15(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
5809
6102
|
${turns}
|
|
5810
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
6103
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml15(model.error)}</p>` : ""}
|
|
5811
6104
|
</section>`;
|
|
5812
6105
|
};
|
|
5813
6106
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -5857,16 +6150,16 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
5857
6150
|
});
|
|
5858
6151
|
};
|
|
5859
6152
|
// src/client/traceTimelineWidget.ts
|
|
5860
|
-
var
|
|
5861
|
-
var
|
|
5862
|
-
var
|
|
5863
|
-
var
|
|
6153
|
+
var DEFAULT_TITLE12 = "Voice Traces";
|
|
6154
|
+
var DEFAULT_DESCRIPTION12 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
6155
|
+
var escapeHtml16 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6156
|
+
var formatMs3 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
5864
6157
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
5865
6158
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
5866
6159
|
const sessions = (snapshot.report?.sessions ?? []).slice(0, options.limit ?? 3).map((session) => ({
|
|
5867
6160
|
...session,
|
|
5868
6161
|
detailHref: `${options.detailBasePath ?? "/traces"}/${encodeURIComponent(session.sessionId)}`,
|
|
5869
|
-
durationLabel:
|
|
6162
|
+
durationLabel: formatMs3(session.summary.callDurationMs),
|
|
5870
6163
|
incidentBundleHref: options.incidentBundleBasePath === false ? undefined : `${options.incidentBundleBasePath ?? "/voice-incidents"}/${encodeURIComponent(session.sessionId)}/markdown`,
|
|
5871
6164
|
label: `${session.summary.eventCount} events / ${session.summary.turnCount} turns`,
|
|
5872
6165
|
operationsRecordHref: options.operationsRecordBasePath === false ? undefined : `${options.operationsRecordBasePath ?? "/voice-operations"}/${encodeURIComponent(session.sessionId)}`,
|
|
@@ -5875,13 +6168,13 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
5875
6168
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
5876
6169
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
5877
6170
|
return {
|
|
5878
|
-
description: options.description ??
|
|
6171
|
+
description: options.description ?? DEFAULT_DESCRIPTION12,
|
|
5879
6172
|
error: snapshot.error,
|
|
5880
6173
|
isLoading: snapshot.isLoading,
|
|
5881
6174
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
5882
6175
|
sessions,
|
|
5883
6176
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
5884
|
-
title: options.title ??
|
|
6177
|
+
title: options.title ?? DEFAULT_TITLE12,
|
|
5885
6178
|
updatedAt: snapshot.updatedAt
|
|
5886
6179
|
};
|
|
5887
6180
|
};
|
|
@@ -5889,27 +6182,27 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
|
5889
6182
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
5890
6183
|
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
|
|
5891
6184
|
const supportLinks = [
|
|
5892
|
-
`<a href="${
|
|
5893
|
-
session.operationsRecordHref ? `<a href="${
|
|
5894
|
-
session.incidentBundleHref ? `<a href="${
|
|
6185
|
+
`<a href="${escapeHtml16(session.detailHref)}">Open timeline</a>`,
|
|
6186
|
+
session.operationsRecordHref ? `<a href="${escapeHtml16(session.operationsRecordHref)}">Open operations record</a>` : undefined,
|
|
6187
|
+
session.incidentBundleHref ? `<a href="${escapeHtml16(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
|
|
5895
6188
|
].filter(Boolean).join("");
|
|
5896
|
-
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${
|
|
6189
|
+
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml16(session.status)}">
|
|
5897
6190
|
<header>
|
|
5898
|
-
<strong>${
|
|
5899
|
-
<span>${
|
|
6191
|
+
<strong>${escapeHtml16(session.sessionId)}</strong>
|
|
6192
|
+
<span>${escapeHtml16(session.status)}</span>
|
|
5900
6193
|
</header>
|
|
5901
|
-
<p>${
|
|
6194
|
+
<p>${escapeHtml16(session.label)} \xB7 ${escapeHtml16(session.durationLabel)} \xB7 ${escapeHtml16(session.providerLabel)}</p>
|
|
5902
6195
|
<p class="absolute-voice-trace-timeline__actions">${supportLinks}</p>
|
|
5903
6196
|
</article>`;
|
|
5904
6197
|
}).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
5905
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
6198
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml16(model.status)}">
|
|
5906
6199
|
<header class="absolute-voice-trace-timeline__header">
|
|
5907
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
5908
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
6200
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml16(model.title)}</span>
|
|
6201
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml16(model.label)}</strong>
|
|
5909
6202
|
</header>
|
|
5910
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
6203
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml16(model.description)}</p>
|
|
5911
6204
|
${sessions}
|
|
5912
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
6205
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml16(model.error)}</p>` : ""}
|
|
5913
6206
|
</section>`;
|
|
5914
6207
|
};
|
|
5915
6208
|
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__actions{display:flex;flex-wrap:wrap;gap:10px}.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}`;
|
|
@@ -5955,9 +6248,9 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
|
|
|
5955
6248
|
});
|
|
5956
6249
|
};
|
|
5957
6250
|
// src/client/agentSquadStatusWidget.ts
|
|
5958
|
-
var
|
|
5959
|
-
var
|
|
5960
|
-
var
|
|
6251
|
+
var DEFAULT_TITLE13 = "Voice Agent Squad";
|
|
6252
|
+
var DEFAULT_DESCRIPTION13 = "Current specialist and recent handoffs from your self-hosted voice traces.";
|
|
6253
|
+
var escapeHtml17 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5961
6254
|
var labelFor = (current) => {
|
|
5962
6255
|
if (!current)
|
|
5963
6256
|
return "Waiting for specialist activity";
|
|
@@ -5971,37 +6264,37 @@ var labelFor = (current) => {
|
|
|
5971
6264
|
};
|
|
5972
6265
|
var createVoiceAgentSquadStatusViewModel = (snapshot, options = {}) => ({
|
|
5973
6266
|
current: snapshot.report.current,
|
|
5974
|
-
description: options.description ??
|
|
6267
|
+
description: options.description ?? DEFAULT_DESCRIPTION13,
|
|
5975
6268
|
error: snapshot.error,
|
|
5976
6269
|
isLoading: snapshot.isLoading,
|
|
5977
6270
|
label: snapshot.error ? "Unavailable" : labelFor(snapshot.report.current),
|
|
5978
6271
|
sessionCount: snapshot.report.sessionCount,
|
|
5979
6272
|
sessions: snapshot.report.sessions,
|
|
5980
|
-
title: options.title ??
|
|
6273
|
+
title: options.title ?? DEFAULT_TITLE13,
|
|
5981
6274
|
updatedAt: snapshot.updatedAt
|
|
5982
6275
|
});
|
|
5983
6276
|
var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
|
|
5984
6277
|
const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
|
|
5985
6278
|
const current = model.current;
|
|
5986
6279
|
const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
|
|
5987
|
-
<span>${
|
|
5988
|
-
<strong>${
|
|
5989
|
-
<em>${
|
|
5990
|
-
${session.summary || session.reason ? `<p>${
|
|
6280
|
+
<span>${escapeHtml17(session.sessionId)}</span>
|
|
6281
|
+
<strong>${escapeHtml17(session.targetAgentId ?? "none")}</strong>
|
|
6282
|
+
<em>${escapeHtml17(session.status)}</em>
|
|
6283
|
+
${session.summary || session.reason ? `<p>${escapeHtml17(session.summary ?? session.reason ?? "")}</p>` : ""}
|
|
5991
6284
|
</li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
|
|
5992
6285
|
return `<section class="absolute-voice-agent-squad-status">
|
|
5993
6286
|
<header>
|
|
5994
|
-
<span>${
|
|
5995
|
-
<strong>${
|
|
6287
|
+
<span>${escapeHtml17(model.title)}</span>
|
|
6288
|
+
<strong>${escapeHtml17(model.label)}</strong>
|
|
5996
6289
|
</header>
|
|
5997
|
-
<p>${
|
|
6290
|
+
<p>${escapeHtml17(model.description)}</p>
|
|
5998
6291
|
<div>
|
|
5999
|
-
<span>Session</span><strong>${
|
|
6000
|
-
<span>From</span><strong>${
|
|
6001
|
-
<span>Status</span><strong>${
|
|
6292
|
+
<span>Session</span><strong>${escapeHtml17(current?.sessionId ?? "n/a")}</strong>
|
|
6293
|
+
<span>From</span><strong>${escapeHtml17(current?.fromAgentId ?? "n/a")}</strong>
|
|
6294
|
+
<span>Status</span><strong>${escapeHtml17(current?.status ?? "idle")}</strong>
|
|
6002
6295
|
</div>
|
|
6003
6296
|
<ul>${rows}</ul>
|
|
6004
|
-
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${
|
|
6297
|
+
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml17(model.error)}</p>` : ""}
|
|
6005
6298
|
</section>`;
|
|
6006
6299
|
};
|
|
6007
6300
|
var getVoiceAgentSquadStatusCSS = () => `.absolute-voice-agent-squad-status{border:1px solid #38bdf866;border-radius:20px;background:#0f172a;color:#f8fafc;padding:18px;font-family:inherit}.absolute-voice-agent-squad-status header{display:grid;gap:4px}.absolute-voice-agent-squad-status header span{color:#7dd3fc;font-size:12px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-agent-squad-status header strong{font-size:20px}.absolute-voice-agent-squad-status p{color:#cbd5e1}.absolute-voice-agent-squad-status div{display:grid;gap:6px;grid-template-columns:max-content 1fr;margin:14px 0}.absolute-voice-agent-squad-status div span{color:#94a3b8}.absolute-voice-agent-squad-status ul{display:grid;gap:8px;list-style:none;margin:0;padding:0}.absolute-voice-agent-squad-status li{background:#020617;border:1px solid #1e293b;border-radius:14px;padding:10px}.absolute-voice-agent-squad-status li span{color:#94a3b8;display:block;font-size:12px}.absolute-voice-agent-squad-status li strong{display:block}.absolute-voice-agent-squad-status li em{color:#7dd3fc;font-style:normal}.absolute-voice-agent-squad-status__error{color:#fecaca;font-weight:800}`;
|
|
@@ -6135,6 +6428,7 @@ export {
|
|
|
6135
6428
|
renderVoiceProviderSimulationControlsHTML,
|
|
6136
6429
|
renderVoiceProviderContractsHTML,
|
|
6137
6430
|
renderVoiceProviderCapabilitiesHTML,
|
|
6431
|
+
renderVoiceProofTrendsHTML,
|
|
6138
6432
|
renderVoicePlatformCoverageHTML,
|
|
6139
6433
|
renderVoiceOpsStatusHTML,
|
|
6140
6434
|
renderVoiceOpsActionHistoryWidgetHTML,
|
|
@@ -6152,6 +6446,7 @@ export {
|
|
|
6152
6446
|
mountVoiceProviderSimulationControls,
|
|
6153
6447
|
mountVoiceProviderContracts,
|
|
6154
6448
|
mountVoiceProviderCapabilities,
|
|
6449
|
+
mountVoiceProofTrends,
|
|
6155
6450
|
mountVoicePlatformCoverage,
|
|
6156
6451
|
mountVoiceOpsStatus,
|
|
6157
6452
|
mountVoiceOpsActionHistory,
|
|
@@ -6165,6 +6460,7 @@ export {
|
|
|
6165
6460
|
getVoiceProviderStatusCSS,
|
|
6166
6461
|
getVoiceProviderContractsCSS,
|
|
6167
6462
|
getVoiceProviderCapabilitiesCSS,
|
|
6463
|
+
getVoiceProofTrendsCSS,
|
|
6168
6464
|
getVoicePlatformCoverageCSS,
|
|
6169
6465
|
getVoiceOpsStatusLabel,
|
|
6170
6466
|
getVoiceOpsStatusCSS,
|
|
@@ -6181,6 +6477,7 @@ export {
|
|
|
6181
6477
|
fetchVoiceProviderStatus,
|
|
6182
6478
|
fetchVoiceProviderContracts,
|
|
6183
6479
|
fetchVoiceProviderCapabilities,
|
|
6480
|
+
fetchVoiceProofTrends,
|
|
6184
6481
|
fetchVoicePlatformCoverage,
|
|
6185
6482
|
fetchVoiceOpsStatus,
|
|
6186
6483
|
fetchVoiceOpsActionHistory,
|
|
@@ -6194,6 +6491,7 @@ export {
|
|
|
6194
6491
|
defineVoiceProviderSimulationControlsElement,
|
|
6195
6492
|
defineVoiceProviderContractsElement,
|
|
6196
6493
|
defineVoiceProviderCapabilitiesElement,
|
|
6494
|
+
defineVoiceProofTrendsElement,
|
|
6197
6495
|
defineVoicePlatformCoverageElement,
|
|
6198
6496
|
defineVoiceOpsStatusElement,
|
|
6199
6497
|
defineVoiceOpsActionCenterElement,
|
|
@@ -6219,6 +6517,8 @@ export {
|
|
|
6219
6517
|
createVoiceProviderContractsStore,
|
|
6220
6518
|
createVoiceProviderCapabilitiesViewModel,
|
|
6221
6519
|
createVoiceProviderCapabilitiesStore,
|
|
6520
|
+
createVoiceProofTrendsViewModel,
|
|
6521
|
+
createVoiceProofTrendsStore,
|
|
6222
6522
|
createVoicePlatformCoverageViewModel,
|
|
6223
6523
|
createVoicePlatformCoverageStore,
|
|
6224
6524
|
createVoiceOpsStatusViewModel,
|