@absolutejs/voice 0.0.22-beta.403 → 0.0.22-beta.405
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 +333 -214
- package/dist/angular/voice-call-debugger.service.d.ts +12 -0
- package/dist/client/callDebugger.d.ts +19 -0
- package/dist/client/callDebuggerWidget.d.ts +30 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +525 -345
- package/dist/react/VoiceCallDebuggerLaunch.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +739 -483
- package/dist/react/useVoiceCallDebugger.d.ts +8 -0
- package/dist/svelte/createVoiceCallDebugger.d.ts +12 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +338 -152
- package/dist/vue/VoiceCallDebuggerLaunch.d.ts +68 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +628 -364
- package/dist/vue/useVoiceCallDebugger.d.ts +10 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -3066,11 +3066,185 @@ var createVoiceSessionSnapshotStore = (path, options = {}) => {
|
|
|
3066
3066
|
}
|
|
3067
3067
|
};
|
|
3068
3068
|
};
|
|
3069
|
+
// src/client/callDebugger.ts
|
|
3070
|
+
var fetchVoiceCallDebugger = async (path, options = {}) => {
|
|
3071
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3072
|
+
const response = await fetchImpl(path);
|
|
3073
|
+
if (!response.ok) {
|
|
3074
|
+
throw new Error(`Voice call debugger failed: HTTP ${response.status}`);
|
|
3075
|
+
}
|
|
3076
|
+
return await response.json();
|
|
3077
|
+
};
|
|
3078
|
+
var createVoiceCallDebuggerStore = (path, options = {}) => {
|
|
3079
|
+
const listeners = new Set;
|
|
3080
|
+
let closed = false;
|
|
3081
|
+
let timer;
|
|
3082
|
+
let snapshot = {
|
|
3083
|
+
error: null,
|
|
3084
|
+
isLoading: false
|
|
3085
|
+
};
|
|
3086
|
+
const emit = () => {
|
|
3087
|
+
for (const listener of listeners) {
|
|
3088
|
+
listener();
|
|
3089
|
+
}
|
|
3090
|
+
};
|
|
3091
|
+
const refresh = async () => {
|
|
3092
|
+
if (closed) {
|
|
3093
|
+
return snapshot.report;
|
|
3094
|
+
}
|
|
3095
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
3096
|
+
emit();
|
|
3097
|
+
try {
|
|
3098
|
+
const report = await fetchVoiceCallDebugger(path, options);
|
|
3099
|
+
snapshot = {
|
|
3100
|
+
error: null,
|
|
3101
|
+
isLoading: false,
|
|
3102
|
+
report,
|
|
3103
|
+
updatedAt: Date.now()
|
|
3104
|
+
};
|
|
3105
|
+
emit();
|
|
3106
|
+
return report;
|
|
3107
|
+
} catch (error) {
|
|
3108
|
+
snapshot = {
|
|
3109
|
+
...snapshot,
|
|
3110
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3111
|
+
isLoading: false
|
|
3112
|
+
};
|
|
3113
|
+
emit();
|
|
3114
|
+
throw error;
|
|
3115
|
+
}
|
|
3116
|
+
};
|
|
3117
|
+
const close = () => {
|
|
3118
|
+
closed = true;
|
|
3119
|
+
if (timer) {
|
|
3120
|
+
clearInterval(timer);
|
|
3121
|
+
timer = undefined;
|
|
3122
|
+
}
|
|
3123
|
+
listeners.clear();
|
|
3124
|
+
};
|
|
3125
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
3126
|
+
timer = setInterval(() => {
|
|
3127
|
+
refresh().catch(() => {});
|
|
3128
|
+
}, options.intervalMs);
|
|
3129
|
+
}
|
|
3130
|
+
return {
|
|
3131
|
+
close,
|
|
3132
|
+
getServerSnapshot: () => snapshot,
|
|
3133
|
+
getSnapshot: () => snapshot,
|
|
3134
|
+
refresh,
|
|
3135
|
+
subscribe: (listener) => {
|
|
3136
|
+
listeners.add(listener);
|
|
3137
|
+
return () => {
|
|
3138
|
+
listeners.delete(listener);
|
|
3139
|
+
};
|
|
3140
|
+
}
|
|
3141
|
+
};
|
|
3142
|
+
};
|
|
3143
|
+
// src/client/callDebuggerWidget.ts
|
|
3144
|
+
var DEFAULT_TITLE = "Call Debugger";
|
|
3145
|
+
var DEFAULT_DESCRIPTION = "Open the latest call artifact with snapshot, operations record, failure replay, provider path, transcript, and incident markdown.";
|
|
3146
|
+
var DEFAULT_LINK_LABEL = "Open debugger";
|
|
3147
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3148
|
+
var defaultHref = (path, report) => {
|
|
3149
|
+
if (path.startsWith("/api/voice-call-debugger/")) {
|
|
3150
|
+
return path.replace("/api/voice-call-debugger/", "/voice-call-debugger/");
|
|
3151
|
+
}
|
|
3152
|
+
return report ? `/voice-call-debugger/${encodeURIComponent(report.sessionId)}` : path;
|
|
3153
|
+
};
|
|
3154
|
+
var resolveHref = (path, state, options) => {
|
|
3155
|
+
if (typeof options.href === "function") {
|
|
3156
|
+
return options.href({ report: state.report });
|
|
3157
|
+
}
|
|
3158
|
+
return options.href ?? defaultHref(path, state.report);
|
|
3159
|
+
};
|
|
3160
|
+
var createVoiceCallDebuggerLaunchViewModel = (path, state, options = {}) => {
|
|
3161
|
+
const report = state.report;
|
|
3162
|
+
const href = resolveHref(path, state, options);
|
|
3163
|
+
return {
|
|
3164
|
+
description: options.description ?? DEFAULT_DESCRIPTION,
|
|
3165
|
+
error: state.error,
|
|
3166
|
+
href,
|
|
3167
|
+
isLoading: state.isLoading,
|
|
3168
|
+
label: state.error ? "Unavailable" : report ? `${report.status} \xB7 ${report.sessionId}` : state.isLoading ? "Loading" : "No call loaded",
|
|
3169
|
+
rows: report ? [
|
|
3170
|
+
{ label: "Events", value: String(report.operationsRecord.summary.eventCount) },
|
|
3171
|
+
{ label: "Turns", value: String(report.operationsRecord.summary.turnCount) },
|
|
3172
|
+
{ label: "Errors", value: String(report.operationsRecord.summary.errorCount) },
|
|
3173
|
+
{
|
|
3174
|
+
label: "Provider recovery",
|
|
3175
|
+
value: report.operationsRecord.providerDecisionSummary.recoveryStatus
|
|
3176
|
+
},
|
|
3177
|
+
{
|
|
3178
|
+
label: "Fallbacks",
|
|
3179
|
+
value: String(report.operationsRecord.providerDecisionSummary.fallbacks)
|
|
3180
|
+
},
|
|
3181
|
+
{ label: "Snapshot", value: report.snapshot.status }
|
|
3182
|
+
] : [],
|
|
3183
|
+
status: state.error ? "error" : report ? report.status === "healthy" ? "ready" : "warning" : state.isLoading ? "loading" : "empty",
|
|
3184
|
+
title: options.title ?? DEFAULT_TITLE,
|
|
3185
|
+
updatedAt: state.updatedAt
|
|
3186
|
+
};
|
|
3187
|
+
};
|
|
3188
|
+
var renderVoiceCallDebuggerLaunchHTML = (path, state, options = {}) => {
|
|
3189
|
+
const model = createVoiceCallDebuggerLaunchViewModel(path, state, options);
|
|
3190
|
+
const rows = model.rows.length ? `<dl>${model.rows.map((row) => `<div>
|
|
3191
|
+
<dt>${escapeHtml(row.label)}</dt>
|
|
3192
|
+
<dd>${escapeHtml(row.value)}</dd>
|
|
3193
|
+
</div>`).join("")}</dl>` : '<p class="absolute-voice-call-debugger-launch__empty">Load a call debugger report to see the latest support artifact.</p>';
|
|
3194
|
+
return `<section class="absolute-voice-call-debugger-launch absolute-voice-call-debugger-launch--${escapeHtml(model.status)}">
|
|
3195
|
+
<header class="absolute-voice-call-debugger-launch__header">
|
|
3196
|
+
<span class="absolute-voice-call-debugger-launch__eyebrow">${escapeHtml(model.title)}</span>
|
|
3197
|
+
<strong class="absolute-voice-call-debugger-launch__label">${escapeHtml(model.label)}</strong>
|
|
3198
|
+
</header>
|
|
3199
|
+
<p class="absolute-voice-call-debugger-launch__description">${escapeHtml(model.description)}</p>
|
|
3200
|
+
<a class="absolute-voice-call-debugger-launch__link" href="${escapeHtml(model.href)}">${escapeHtml(options.linkLabel ?? DEFAULT_LINK_LABEL)}</a>
|
|
3201
|
+
${rows}
|
|
3202
|
+
${model.error ? `<p class="absolute-voice-call-debugger-launch__error">${escapeHtml(model.error)}</p>` : ""}
|
|
3203
|
+
</section>`;
|
|
3204
|
+
};
|
|
3205
|
+
var mountVoiceCallDebuggerLaunch = (element, path, options = {}) => {
|
|
3206
|
+
const store = createVoiceCallDebuggerStore(path, options);
|
|
3207
|
+
const render = () => {
|
|
3208
|
+
element.innerHTML = renderVoiceCallDebuggerLaunchHTML(path, store.getSnapshot(), options);
|
|
3209
|
+
};
|
|
3210
|
+
const unsubscribe = store.subscribe(render);
|
|
3211
|
+
render();
|
|
3212
|
+
store.refresh().catch(() => {});
|
|
3213
|
+
return {
|
|
3214
|
+
close: () => {
|
|
3215
|
+
unsubscribe();
|
|
3216
|
+
store.close();
|
|
3217
|
+
},
|
|
3218
|
+
refresh: store.refresh
|
|
3219
|
+
};
|
|
3220
|
+
};
|
|
3221
|
+
var defineVoiceCallDebuggerLaunchElement = (tagName = "absolute-voice-call-debugger-launch") => {
|
|
3222
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
3223
|
+
return;
|
|
3224
|
+
}
|
|
3225
|
+
customElements.define(tagName, class AbsoluteVoiceCallDebuggerLaunchElement extends HTMLElement {
|
|
3226
|
+
mounted;
|
|
3227
|
+
connectedCallback() {
|
|
3228
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 0);
|
|
3229
|
+
this.mounted = mountVoiceCallDebuggerLaunch(this, this.getAttribute("path") ?? "/api/voice-call-debugger/latest", {
|
|
3230
|
+
description: this.getAttribute("description") ?? undefined,
|
|
3231
|
+
href: this.getAttribute("href") ?? undefined,
|
|
3232
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 0,
|
|
3233
|
+
linkLabel: this.getAttribute("link-label") ?? undefined,
|
|
3234
|
+
title: this.getAttribute("title") ?? undefined
|
|
3235
|
+
});
|
|
3236
|
+
}
|
|
3237
|
+
disconnectedCallback() {
|
|
3238
|
+
this.mounted?.close();
|
|
3239
|
+
this.mounted = undefined;
|
|
3240
|
+
}
|
|
3241
|
+
});
|
|
3242
|
+
};
|
|
3069
3243
|
// src/client/sessionSnapshotWidget.ts
|
|
3070
|
-
var
|
|
3071
|
-
var
|
|
3244
|
+
var DEFAULT_TITLE2 = "Session Snapshot";
|
|
3245
|
+
var DEFAULT_DESCRIPTION2 = "Portable call artifact with media graph, provider routing, proof, quality, and telephony evidence.";
|
|
3072
3246
|
var DEFAULT_DOWNLOAD_LABEL = "Download snapshot";
|
|
3073
|
-
var
|
|
3247
|
+
var escapeHtml2 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3074
3248
|
var formatStatus = (status) => status ?? "n/a";
|
|
3075
3249
|
var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
|
|
3076
3250
|
const snapshot = state.snapshot;
|
|
@@ -3086,7 +3260,7 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
|
|
|
3086
3260
|
label: artifact.label,
|
|
3087
3261
|
status: formatStatus(artifact.status)
|
|
3088
3262
|
})) ?? [],
|
|
3089
|
-
description: options.description ??
|
|
3263
|
+
description: options.description ?? DEFAULT_DESCRIPTION2,
|
|
3090
3264
|
error: state.error,
|
|
3091
3265
|
isLoading: state.isLoading,
|
|
3092
3266
|
label: state.error ? "Unavailable" : snapshot ? `${snapshot.status} \xB7 ${snapshot.sessionId}` : state.isLoading ? "Loading" : "No snapshot",
|
|
@@ -3110,30 +3284,30 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
|
|
|
3110
3284
|
] : [],
|
|
3111
3285
|
showDownload: snapshot !== undefined,
|
|
3112
3286
|
status: state.error ? "error" : snapshot ? snapshot.status === "pass" ? "ready" : "warning" : state.isLoading ? "loading" : "empty",
|
|
3113
|
-
title: options.title ??
|
|
3287
|
+
title: options.title ?? DEFAULT_TITLE2,
|
|
3114
3288
|
updatedAt: state.updatedAt
|
|
3115
3289
|
};
|
|
3116
3290
|
};
|
|
3117
3291
|
var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
|
|
3118
3292
|
const model = createVoiceSessionSnapshotViewModel(state, options);
|
|
3119
3293
|
const rows = model.rows.length ? `<dl>${model.rows.map((row) => `<div>
|
|
3120
|
-
<dt>${
|
|
3121
|
-
<dd>${
|
|
3294
|
+
<dt>${escapeHtml2(row.label)}</dt>
|
|
3295
|
+
<dd>${escapeHtml2(row.value)}</dd>
|
|
3122
3296
|
</div>`).join("")}</dl>` : '<p class="absolute-voice-session-snapshot__empty">Load a session snapshot to see support diagnostics.</p>';
|
|
3123
3297
|
const artifacts = model.artifacts.length ? `<div class="absolute-voice-session-snapshot__artifacts">${model.artifacts.map((artifact) => {
|
|
3124
|
-
const body = `<strong>${
|
|
3125
|
-
return artifact.href ? `<a href="${
|
|
3298
|
+
const body = `<strong>${escapeHtml2(artifact.label)}</strong><span>${escapeHtml2(artifact.status)}</span>`;
|
|
3299
|
+
return artifact.href ? `<a href="${escapeHtml2(artifact.href)}">${body}</a>` : `<div>${body}</div>`;
|
|
3126
3300
|
}).join("")}</div>` : "";
|
|
3127
|
-
return `<section class="absolute-voice-session-snapshot absolute-voice-session-snapshot--${
|
|
3301
|
+
return `<section class="absolute-voice-session-snapshot absolute-voice-session-snapshot--${escapeHtml2(model.status)}">
|
|
3128
3302
|
<header class="absolute-voice-session-snapshot__header">
|
|
3129
|
-
<span class="absolute-voice-session-snapshot__eyebrow">${
|
|
3130
|
-
<strong class="absolute-voice-session-snapshot__label">${
|
|
3303
|
+
<span class="absolute-voice-session-snapshot__eyebrow">${escapeHtml2(model.title)}</span>
|
|
3304
|
+
<strong class="absolute-voice-session-snapshot__label">${escapeHtml2(model.label)}</strong>
|
|
3131
3305
|
</header>
|
|
3132
|
-
<p class="absolute-voice-session-snapshot__description">${
|
|
3133
|
-
${model.showDownload ? `<button class="absolute-voice-session-snapshot__download" data-absolute-voice-session-snapshot-download type="button">${
|
|
3306
|
+
<p class="absolute-voice-session-snapshot__description">${escapeHtml2(model.description)}</p>
|
|
3307
|
+
${model.showDownload ? `<button class="absolute-voice-session-snapshot__download" data-absolute-voice-session-snapshot-download type="button">${escapeHtml2(options.downloadLabel ?? DEFAULT_DOWNLOAD_LABEL)}</button>` : ""}
|
|
3134
3308
|
${rows}
|
|
3135
3309
|
${artifacts}
|
|
3136
|
-
${model.error ? `<p class="absolute-voice-session-snapshot__error">${
|
|
3310
|
+
${model.error ? `<p class="absolute-voice-session-snapshot__error">${escapeHtml2(model.error)}</p>` : ""}
|
|
3137
3311
|
</section>`;
|
|
3138
3312
|
};
|
|
3139
3313
|
var downloadBlob = (blob, filename) => {
|
|
@@ -3903,8 +4077,8 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
|
|
|
3903
4077
|
};
|
|
3904
4078
|
};
|
|
3905
4079
|
// src/client/opsStatusWidget.ts
|
|
3906
|
-
var
|
|
3907
|
-
var
|
|
4080
|
+
var DEFAULT_TITLE3 = "Voice Ops Status";
|
|
4081
|
+
var DEFAULT_DESCRIPTION3 = "Certified workflow, provider, and handoff readiness from your AbsoluteJS voice app.";
|
|
3908
4082
|
var SURFACE_LABELS = {
|
|
3909
4083
|
handoffs: "Handoffs",
|
|
3910
4084
|
providers: "Providers",
|
|
@@ -3912,7 +4086,7 @@ var SURFACE_LABELS = {
|
|
|
3912
4086
|
sessions: "Sessions",
|
|
3913
4087
|
workflows: "Workflows"
|
|
3914
4088
|
};
|
|
3915
|
-
var
|
|
4089
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3916
4090
|
var readNumber = (value, key) => value && typeof value === "object" && (key in value) ? Number(value[key] ?? 0) : 0;
|
|
3917
4091
|
var surfaceDetail = (surface) => {
|
|
3918
4092
|
const total = readNumber(surface, "total");
|
|
@@ -3952,7 +4126,7 @@ var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
|
|
|
3952
4126
|
};
|
|
3953
4127
|
});
|
|
3954
4128
|
return {
|
|
3955
|
-
description: options.description ??
|
|
4129
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
3956
4130
|
error: snapshot.error,
|
|
3957
4131
|
isLoading: snapshot.isLoading,
|
|
3958
4132
|
label: getVoiceOpsStatusLabel(report, snapshot.error),
|
|
@@ -3960,31 +4134,31 @@ var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
|
|
|
3960
4134
|
passed: report?.passed ?? 0,
|
|
3961
4135
|
status: snapshot.error ? "error" : report ? report.status : snapshot.isLoading ? "loading" : "loading",
|
|
3962
4136
|
surfaces,
|
|
3963
|
-
title: options.title ??
|
|
4137
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
3964
4138
|
total: report?.total ?? 0,
|
|
3965
4139
|
updatedAt: snapshot.updatedAt
|
|
3966
4140
|
};
|
|
3967
4141
|
};
|
|
3968
4142
|
var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
|
|
3969
4143
|
const model = createVoiceOpsStatusViewModel(snapshot, options);
|
|
3970
|
-
const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${
|
|
3971
|
-
<span>${
|
|
3972
|
-
<strong>${
|
|
4144
|
+
const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml3(surface.status)}">
|
|
4145
|
+
<span>${escapeHtml3(surface.label)}</span>
|
|
4146
|
+
<strong>${escapeHtml3(surface.detail)}</strong>
|
|
3973
4147
|
</li>`).join("") : '<li class="absolute-voice-ops-status__surface"><span>Status</span><strong>Waiting for first check</strong></li>';
|
|
3974
|
-
const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${
|
|
3975
|
-
return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${
|
|
4148
|
+
const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${escapeHtml3(link.href)}">${escapeHtml3(link.label)}</a>`).join("")}</nav>` : "";
|
|
4149
|
+
return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml3(model.status)}">
|
|
3976
4150
|
<header class="absolute-voice-ops-status__header">
|
|
3977
|
-
<span class="absolute-voice-ops-status__eyebrow">${
|
|
3978
|
-
<strong class="absolute-voice-ops-status__label">${
|
|
4151
|
+
<span class="absolute-voice-ops-status__eyebrow">${escapeHtml3(model.title)}</span>
|
|
4152
|
+
<strong class="absolute-voice-ops-status__label">${escapeHtml3(model.label)}</strong>
|
|
3979
4153
|
</header>
|
|
3980
|
-
<p class="absolute-voice-ops-status__description">${
|
|
4154
|
+
<p class="absolute-voice-ops-status__description">${escapeHtml3(model.description)}</p>
|
|
3981
4155
|
<div class="absolute-voice-ops-status__summary">
|
|
3982
4156
|
<span>${model.passed} passing</span>
|
|
3983
4157
|
<span>${Math.max(model.total - model.passed, 0)} failing</span>
|
|
3984
4158
|
<span>${model.total} checks</span>
|
|
3985
4159
|
</div>
|
|
3986
4160
|
<ul class="absolute-voice-ops-status__surfaces">${surfaces}</ul>
|
|
3987
|
-
${model.error ? `<p class="absolute-voice-ops-status__error">${
|
|
4161
|
+
${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
3988
4162
|
${links}
|
|
3989
4163
|
</section>`;
|
|
3990
4164
|
};
|
|
@@ -4027,13 +4201,13 @@ var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
|
|
|
4027
4201
|
});
|
|
4028
4202
|
};
|
|
4029
4203
|
// src/client/platformCoverageWidget.ts
|
|
4030
|
-
var
|
|
4031
|
-
var
|
|
4204
|
+
var DEFAULT_TITLE4 = "Platform Replacement Coverage";
|
|
4205
|
+
var DEFAULT_DESCRIPTION4 = "Code-owned coverage for hosted voice-platform surfaces, backed by the same proof routes used by release evidence.";
|
|
4032
4206
|
var DEFAULT_LINKS = [
|
|
4033
4207
|
{ href: "/switching-from-vapi", label: "Switching guide" },
|
|
4034
4208
|
{ href: "/api/voice/vapi-coverage", label: "Coverage JSON" }
|
|
4035
4209
|
];
|
|
4036
|
-
var
|
|
4210
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4037
4211
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
4038
4212
|
var surfaceDetail2 = (surface) => {
|
|
4039
4213
|
if (surface.status === "pass") {
|
|
@@ -4057,37 +4231,37 @@ var createVoicePlatformCoverageViewModel = (snapshot, options = {}) => {
|
|
|
4057
4231
|
label: surface.surface
|
|
4058
4232
|
}));
|
|
4059
4233
|
return {
|
|
4060
|
-
description: options.description ??
|
|
4234
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
4061
4235
|
error: snapshot.error,
|
|
4062
4236
|
isLoading: snapshot.isLoading,
|
|
4063
4237
|
label: snapshot.error ? "Unavailable" : snapshot.report ? failing.length ? `${failing.length} gaps` : `${snapshot.report.total} surfaces passing` : snapshot.isLoading ? "Checking" : "No coverage report",
|
|
4064
4238
|
links: options.links ?? DEFAULT_LINKS,
|
|
4065
4239
|
status: snapshot.error ? "error" : snapshot.report ? failing.length ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
4066
4240
|
surfaces,
|
|
4067
|
-
title: options.title ??
|
|
4241
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
4068
4242
|
updatedAt: snapshot.updatedAt
|
|
4069
4243
|
};
|
|
4070
4244
|
};
|
|
4071
4245
|
var renderVoicePlatformCoverageHTML = (snapshot, options = {}) => {
|
|
4072
4246
|
const model = createVoicePlatformCoverageViewModel(snapshot, options);
|
|
4073
|
-
const surfaces = model.surfaces.length ? `<div class="absolute-voice-platform-coverage__surfaces">${model.surfaces.map((surface) => `<article class="absolute-voice-platform-coverage__surface absolute-voice-platform-coverage__surface--${
|
|
4247
|
+
const surfaces = model.surfaces.length ? `<div class="absolute-voice-platform-coverage__surfaces">${model.surfaces.map((surface) => `<article class="absolute-voice-platform-coverage__surface absolute-voice-platform-coverage__surface--${escapeHtml4(surface.status)}">
|
|
4074
4248
|
<header>
|
|
4075
|
-
<strong>${
|
|
4076
|
-
<span>${
|
|
4249
|
+
<strong>${escapeHtml4(surface.label)}</strong>
|
|
4250
|
+
<span>${escapeHtml4(formatStatus2(surface.status))}</span>
|
|
4077
4251
|
</header>
|
|
4078
|
-
<p>${
|
|
4252
|
+
<p>${escapeHtml4(surface.detail)}</p>
|
|
4079
4253
|
<small>${surface.evidence.filter((item) => item.ok).length}/${surface.evidence.length} evidence checks passing</small>
|
|
4080
|
-
</article>`).join("")}</div>` : `<p class="absolute-voice-platform-coverage__empty">${model.error ?
|
|
4081
|
-
const links = model.links.length ? `<p class="absolute-voice-platform-coverage__links">${model.links.map((link) => `<a href="${
|
|
4082
|
-
return `<section class="absolute-voice-platform-coverage absolute-voice-platform-coverage--${
|
|
4254
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-platform-coverage__empty">${model.error ? escapeHtml4(model.error) : "Run the proof pack to populate platform coverage evidence."}</p>`;
|
|
4255
|
+
const links = model.links.length ? `<p class="absolute-voice-platform-coverage__links">${model.links.map((link) => `<a href="${escapeHtml4(link.href)}">${escapeHtml4(link.label)}</a>`).join("")}</p>` : "";
|
|
4256
|
+
return `<section class="absolute-voice-platform-coverage absolute-voice-platform-coverage--${escapeHtml4(model.status)}">
|
|
4083
4257
|
<header class="absolute-voice-platform-coverage__header">
|
|
4084
|
-
<span class="absolute-voice-platform-coverage__eyebrow">${
|
|
4085
|
-
<strong class="absolute-voice-platform-coverage__label">${
|
|
4258
|
+
<span class="absolute-voice-platform-coverage__eyebrow">${escapeHtml4(model.title)}</span>
|
|
4259
|
+
<strong class="absolute-voice-platform-coverage__label">${escapeHtml4(model.label)}</strong>
|
|
4086
4260
|
</header>
|
|
4087
|
-
<p class="absolute-voice-platform-coverage__description">${
|
|
4261
|
+
<p class="absolute-voice-platform-coverage__description">${escapeHtml4(model.description)}</p>
|
|
4088
4262
|
${surfaces}
|
|
4089
4263
|
${links}
|
|
4090
|
-
${model.error ? `<p class="absolute-voice-platform-coverage__error">${
|
|
4264
|
+
${model.error ? `<p class="absolute-voice-platform-coverage__error">${escapeHtml4(model.error)}</p>` : ""}
|
|
4091
4265
|
</section>`;
|
|
4092
4266
|
};
|
|
4093
4267
|
var getVoicePlatformCoverageCSS = () => `.absolute-voice-platform-coverage{border:1px solid #c7d2fe;border-radius:20px;background:#f8fbff;color:#111827;padding:18px;box-shadow:0 18px 40px rgba(30,64,175,.12);font-family:inherit}.absolute-voice-platform-coverage--warning,.absolute-voice-platform-coverage--error{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-platform-coverage__header,.absolute-voice-platform-coverage__surface header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-platform-coverage__eyebrow{color:#1d4ed8;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-platform-coverage__label{font-size:24px;line-height:1}.absolute-voice-platform-coverage__description,.absolute-voice-platform-coverage__surface p,.absolute-voice-platform-coverage__surface small,.absolute-voice-platform-coverage__empty{color:#475569}.absolute-voice-platform-coverage__surfaces{display:grid;gap:10px;margin-top:14px}.absolute-voice-platform-coverage__surface{background:#fff;border:1px solid #dbeafe;border-radius:16px;padding:12px}.absolute-voice-platform-coverage__surface--pass{border-color:#86efac}.absolute-voice-platform-coverage__surface--fail,.absolute-voice-platform-coverage__surface--missing,.absolute-voice-platform-coverage__surface--stale{border-color:#f2a7a7}.absolute-voice-platform-coverage__surface p{margin:8px 0}.absolute-voice-platform-coverage__surface span{text-transform:capitalize}.absolute-voice-platform-coverage__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-platform-coverage__links a{border:1px solid #bfdbfe;border-radius:999px;color:#1d4ed8;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-platform-coverage__error{color:#9f1239;font-weight:700}`;
|
|
@@ -4278,16 +4452,16 @@ var summarizeVoiceProviderHealth = async (input) => {
|
|
|
4278
4452
|
}
|
|
4279
4453
|
return summaries;
|
|
4280
4454
|
};
|
|
4281
|
-
var
|
|
4455
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4282
4456
|
var renderVoiceProviderHealthHTML = (providers) => providers.length === 0 ? '<p class="voice-provider-empty">No provider status yet.</p>' : [
|
|
4283
4457
|
'<div class="voice-provider-health">',
|
|
4284
4458
|
...providers.map((provider) => {
|
|
4285
4459
|
const suppressionSeconds = typeof provider.suppressionRemainingMs === "number" ? Math.ceil(provider.suppressionRemainingMs / 1000) : undefined;
|
|
4286
4460
|
return [
|
|
4287
|
-
`<article class="voice-provider-card ${
|
|
4461
|
+
`<article class="voice-provider-card ${escapeHtml5(provider.status)}">`,
|
|
4288
4462
|
'<div class="voice-provider-card-header">',
|
|
4289
|
-
`<strong>${
|
|
4290
|
-
`<span>${
|
|
4463
|
+
`<strong>${escapeHtml5(provider.provider)}</strong>`,
|
|
4464
|
+
`<span>${escapeHtml5(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>`,
|
|
4291
4465
|
"</div>",
|
|
4292
4466
|
"<dl>",
|
|
4293
4467
|
`<div><dt>Runs</dt><dd>${String(provider.runCount)}</dd></div>`,
|
|
@@ -4297,7 +4471,7 @@ var renderVoiceProviderHealthHTML = (providers) => providers.length === 0 ? '<p
|
|
|
4297
4471
|
`<div><dt>Fallbacks</dt><dd>${String(provider.fallbackCount)}</dd></div>`,
|
|
4298
4472
|
"</dl>",
|
|
4299
4473
|
suppressionSeconds ? `<p>Temporarily suppressed for ${String(suppressionSeconds)}s.</p>` : "",
|
|
4300
|
-
provider.lastError ? `<p>${
|
|
4474
|
+
provider.lastError ? `<p>${escapeHtml5(provider.lastError)}</p>` : "",
|
|
4301
4475
|
"</article>"
|
|
4302
4476
|
].join("");
|
|
4303
4477
|
}),
|
|
@@ -4328,7 +4502,7 @@ var createVoiceProviderHealthRoutes = (options) => {
|
|
|
4328
4502
|
};
|
|
4329
4503
|
|
|
4330
4504
|
// src/resilienceRoutes.ts
|
|
4331
|
-
var
|
|
4505
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4332
4506
|
var getString2 = (value) => typeof value === "string" ? value : undefined;
|
|
4333
4507
|
var getNumber2 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
4334
4508
|
var getBoolean = (value) => value === true;
|
|
@@ -4476,13 +4650,13 @@ var summarizeRoutingEvents = (events) => {
|
|
|
4476
4650
|
};
|
|
4477
4651
|
var renderProviderCards = (title, providers) => {
|
|
4478
4652
|
if (providers.length === 0) {
|
|
4479
|
-
return `<p class="muted">No ${
|
|
4653
|
+
return `<p class="muted">No ${escapeHtml6(title)} provider health yet.</p>`;
|
|
4480
4654
|
}
|
|
4481
4655
|
return `<div class="provider-grid">${providers.map((provider) => `
|
|
4482
|
-
<article class="card provider ${
|
|
4656
|
+
<article class="card provider ${escapeHtml6(provider.status)}">
|
|
4483
4657
|
<div class="card-header">
|
|
4484
|
-
<strong>${
|
|
4485
|
-
<span>${
|
|
4658
|
+
<strong>${escapeHtml6(provider.provider)}</strong>
|
|
4659
|
+
<span>${escapeHtml6(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
|
|
4486
4660
|
</div>
|
|
4487
4661
|
<dl>
|
|
4488
4662
|
<div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
|
|
@@ -4491,7 +4665,7 @@ var renderProviderCards = (title, providers) => {
|
|
|
4491
4665
|
<div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
|
|
4492
4666
|
<div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
|
|
4493
4667
|
</dl>
|
|
4494
|
-
${provider.lastError ? `<p class="muted">${
|
|
4668
|
+
${provider.lastError ? `<p class="muted">${escapeHtml6(provider.lastError)}</p>` : ""}
|
|
4495
4669
|
</article>
|
|
4496
4670
|
`).join("")}</div>`;
|
|
4497
4671
|
};
|
|
@@ -4500,24 +4674,24 @@ var renderTimeline = (events) => {
|
|
|
4500
4674
|
return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
|
|
4501
4675
|
}
|
|
4502
4676
|
return `<div class="timeline">${events.slice(0, 40).map((event) => `
|
|
4503
|
-
<article class="card event ${
|
|
4677
|
+
<article class="card event ${escapeHtml6(event.status ?? "unknown")}">
|
|
4504
4678
|
<div class="card-header">
|
|
4505
|
-
<strong>${
|
|
4679
|
+
<strong>${escapeHtml6(event.kind.toUpperCase())} ${escapeHtml6(event.operation ?? "generate")}</strong>
|
|
4506
4680
|
<span>${new Date(event.at).toLocaleString()}</span>
|
|
4507
4681
|
</div>
|
|
4508
4682
|
<p>
|
|
4509
|
-
<span class="pill">${
|
|
4510
|
-
<span class="pill">provider: ${
|
|
4511
|
-
${event.fallbackProvider ? `<span class="pill">fallback: ${
|
|
4683
|
+
<span class="pill">${escapeHtml6(event.status ?? "unknown")}</span>
|
|
4684
|
+
<span class="pill">provider: ${escapeHtml6(event.provider ?? "unknown")}</span>
|
|
4685
|
+
${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml6(event.fallbackProvider)}</span>` : ""}
|
|
4512
4686
|
${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
|
|
4513
4687
|
</p>
|
|
4514
4688
|
<dl>
|
|
4515
4689
|
<div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
|
|
4516
4690
|
<div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
|
|
4517
4691
|
<div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
|
|
4518
|
-
<div><dt>Session</dt><dd>${
|
|
4692
|
+
<div><dt>Session</dt><dd>${escapeHtml6(event.sessionId)}</dd></div>
|
|
4519
4693
|
</dl>
|
|
4520
|
-
${event.error ? `<p class="muted">${
|
|
4694
|
+
${event.error ? `<p class="muted">${escapeHtml6(event.error)}</p>` : ""}
|
|
4521
4695
|
</article>
|
|
4522
4696
|
`).join("")}</div>`;
|
|
4523
4697
|
};
|
|
@@ -4527,9 +4701,9 @@ var renderSessionKind = (kind, summary) => {
|
|
|
4527
4701
|
const status = latest?.status ?? "idle";
|
|
4528
4702
|
const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
|
|
4529
4703
|
return `<div>
|
|
4530
|
-
<dt>${
|
|
4531
|
-
<dd>${
|
|
4532
|
-
<small>${
|
|
4704
|
+
<dt>${escapeHtml6(kind.toUpperCase())}</dt>
|
|
4705
|
+
<dd>${escapeHtml6(provider)}${escapeHtml6(fallback)}</dd>
|
|
4706
|
+
<small>${escapeHtml6(status)} \xB7 ${summary.runCount} event${summary.runCount === 1 ? "" : "s"} \xB7 ${summary.errorCount} error${summary.errorCount === 1 ? "" : "s"} \xB7 ${summary.fallbackCount} fallback${summary.fallbackCount === 1 ? "" : "s"}</small>
|
|
4533
4707
|
</div>`;
|
|
4534
4708
|
};
|
|
4535
4709
|
var renderSessionSummaries = (sessions) => {
|
|
@@ -4537,10 +4711,10 @@ var renderSessionSummaries = (sessions) => {
|
|
|
4537
4711
|
return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
|
|
4538
4712
|
}
|
|
4539
4713
|
return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
|
|
4540
|
-
<article class="card session ${
|
|
4714
|
+
<article class="card session ${escapeHtml6(session.status)}">
|
|
4541
4715
|
<div class="card-header">
|
|
4542
|
-
<strong>${
|
|
4543
|
-
<span>${
|
|
4716
|
+
<strong>${escapeHtml6(session.sessionId)}</strong>
|
|
4717
|
+
<span>${escapeHtml6(session.status)}</span>
|
|
4544
4718
|
</div>
|
|
4545
4719
|
<p>
|
|
4546
4720
|
<span class="pill">${session.eventCount} routing events</span>
|
|
@@ -4567,21 +4741,21 @@ var renderSimulationControls = (kind, simulation) => {
|
|
|
4567
4741
|
const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
|
|
4568
4742
|
const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
|
|
4569
4743
|
const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
|
|
4570
|
-
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${
|
|
4571
|
-
<p class="muted">${
|
|
4744
|
+
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml6(pathPrefix)}">
|
|
4745
|
+
<p class="muted">${escapeHtml6(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
|
|
4572
4746
|
<div class="simulate-actions">
|
|
4573
|
-
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${
|
|
4574
|
-
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${
|
|
4747
|
+
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml6(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml6(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
|
|
4748
|
+
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml6(provider.provider)}">Mark ${escapeHtml6(provider.provider)} recovered</button>`).join("")}
|
|
4575
4749
|
</div>
|
|
4576
|
-
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${
|
|
4750
|
+
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml6(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
|
|
4577
4751
|
<pre class="simulate-output" hidden></pre>
|
|
4578
4752
|
</div>`;
|
|
4579
4753
|
};
|
|
4580
4754
|
var renderVoiceResilienceHTML = (input) => {
|
|
4581
4755
|
const summary = summarizeRoutingEvents(input.routingEvents);
|
|
4582
|
-
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${
|
|
4583
|
-
const links = input.links?.length ? input.links.map((link) => `<a href="${
|
|
4584
|
-
const snippet =
|
|
4756
|
+
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml6(kind)}: ${String(count)}</span>`).join("");
|
|
4757
|
+
const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml6(link.href)}">${escapeHtml6(link.label)}</a>`).join(" \xB7 ") : "";
|
|
4758
|
+
const snippet = escapeHtml6(`const sttSimulator = createVoiceIOProviderFailureSimulator({
|
|
4585
4759
|
kind: 'stt',
|
|
4586
4760
|
providers: ['deepgram', 'assemblyai'],
|
|
4587
4761
|
fallback: ['deepgram', 'assemblyai'],
|
|
@@ -4619,7 +4793,7 @@ app.use(
|
|
|
4619
4793
|
<head>
|
|
4620
4794
|
<meta charset="utf-8" />
|
|
4621
4795
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
4622
|
-
<title>${
|
|
4796
|
+
<title>${escapeHtml6(input.title ?? "AbsoluteJS Voice Resilience")}</title>
|
|
4623
4797
|
<style>
|
|
4624
4798
|
:root { color-scheme: dark; }
|
|
4625
4799
|
body { background: radial-gradient(circle at top left, #172554, #09090b 36%, #050505); color: #f4f4f5; font-family: ui-sans-serif, system-ui, sans-serif; margin: 0; padding: 24px; }
|
|
@@ -4812,7 +4986,7 @@ var createVoiceResilienceRoutes = (options) => {
|
|
|
4812
4986
|
};
|
|
4813
4987
|
|
|
4814
4988
|
// src/providerDecisionTraces.ts
|
|
4815
|
-
var
|
|
4989
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4816
4990
|
var getString3 = (value) => typeof value === "string" ? value : undefined;
|
|
4817
4991
|
var getNumber3 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
4818
4992
|
var isDecisionTrace = (event) => Boolean(event && typeof event === "object" && "provider" in event && "reason" in event && "sessionId" in event && "status" in event && "surface" in event);
|
|
@@ -5053,7 +5227,7 @@ var renderVoiceProviderDecisionTraceHTML = (report, title = "Provider Decision T
|
|
|
5053
5227
|
<head>
|
|
5054
5228
|
<meta charset="utf-8" />
|
|
5055
5229
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
5056
|
-
<title>${
|
|
5230
|
+
<title>${escapeHtml7(title)}</title>
|
|
5057
5231
|
<style>
|
|
5058
5232
|
body{font-family:ui-sans-serif,system-ui,sans-serif;margin:0;background:#f8fafc;color:#0f172a}
|
|
5059
5233
|
main{max-width:1100px;margin:0 auto;padding:32px}
|
|
@@ -5067,8 +5241,8 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
5067
5241
|
</head>
|
|
5068
5242
|
<body>
|
|
5069
5243
|
<main>
|
|
5070
|
-
<p class="status ${report.status}">${
|
|
5071
|
-
<h1>${
|
|
5244
|
+
<p class="status ${report.status}">${escapeHtml7(report.status)}</p>
|
|
5245
|
+
<h1>${escapeHtml7(title)}</h1>
|
|
5072
5246
|
<p class="muted">Runtime proof for why providers were selected, skipped, failed, or recovered by fallback.</p>
|
|
5073
5247
|
<section class="grid">
|
|
5074
5248
|
<article class="card"><strong>${String(report.summary.decisions)}</strong><p>decisions</p></article>
|
|
@@ -5079,10 +5253,10 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
5079
5253
|
</section>
|
|
5080
5254
|
<section class="surfaces">
|
|
5081
5255
|
${report.surfaces.map((surface) => `<article class="surface">
|
|
5082
|
-
<header><strong>${
|
|
5256
|
+
<header><strong>${escapeHtml7(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml7(surface.status)}</span></header>
|
|
5083
5257
|
<p>${String(surface.decisions)} decision(s), ${String(surface.fallbacks)} fallback(s), ${String(surface.degraded)} degraded decision(s), ${String(surface.errors)} error(s).</p>
|
|
5084
|
-
<p class="muted">Providers: ${
|
|
5085
|
-
<p>${surface.reasons.map((reason) => `<code>${
|
|
5258
|
+
<p class="muted">Providers: ${escapeHtml7(surface.providers.join(", ") || "none")}</p>
|
|
5259
|
+
<p>${surface.reasons.map((reason) => `<code>${escapeHtml7(reason)}</code>`).join(" ")}</p>
|
|
5086
5260
|
</article>`).join(`
|
|
5087
5261
|
`)}
|
|
5088
5262
|
</section>
|
|
@@ -5547,7 +5721,7 @@ var exportVoiceTrace = async (input) => {
|
|
|
5547
5721
|
};
|
|
5548
5722
|
};
|
|
5549
5723
|
var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
5550
|
-
var
|
|
5724
|
+
var escapeHtml8 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
5551
5725
|
var formatTraceValue = (value) => {
|
|
5552
5726
|
if (value === undefined || value === null) {
|
|
5553
5727
|
return "";
|
|
@@ -5827,10 +6001,10 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
5827
6001
|
const offset = summary.startedAt === undefined ? event.at : Math.max(0, event.at - summary.startedAt);
|
|
5828
6002
|
return [
|
|
5829
6003
|
"<tr>",
|
|
5830
|
-
`<td>${
|
|
5831
|
-
`<td>${
|
|
5832
|
-
`<td>${
|
|
5833
|
-
`<td><code>${
|
|
6004
|
+
`<td>${escapeHtml8(String(offset))}</td>`,
|
|
6005
|
+
`<td>${escapeHtml8(event.type)}</td>`,
|
|
6006
|
+
`<td>${escapeHtml8(event.turnId ?? "")}</td>`,
|
|
6007
|
+
`<td><code>${escapeHtml8(JSON.stringify(event.payload))}</code></td>`,
|
|
5834
6008
|
"</tr>"
|
|
5835
6009
|
].join("");
|
|
5836
6010
|
}).join(`
|
|
@@ -5841,7 +6015,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
5841
6015
|
"<head>",
|
|
5842
6016
|
'<meta charset="utf-8" />',
|
|
5843
6017
|
'<meta name="viewport" content="width=device-width, initial-scale=1" />',
|
|
5844
|
-
`<title>${
|
|
6018
|
+
`<title>${escapeHtml8(options.title ?? "Voice Trace")}</title>`,
|
|
5845
6019
|
"<style>",
|
|
5846
6020
|
"body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;line-height:1.45;background:#f8f7f2;color:#181713}",
|
|
5847
6021
|
"main{max-width:1100px;margin:auto}",
|
|
@@ -5855,7 +6029,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
5855
6029
|
"</style>",
|
|
5856
6030
|
"</head>",
|
|
5857
6031
|
"<body><main>",
|
|
5858
|
-
`<h1>${
|
|
6032
|
+
`<h1>${escapeHtml8(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</h1>`,
|
|
5859
6033
|
`<p class="${evaluation.pass ? "pass" : "fail"}">QA: ${evaluation.pass ? "pass" : "fail"}</p>`,
|
|
5860
6034
|
'<section class="summary">',
|
|
5861
6035
|
`<div class="card"><strong>Events</strong><br>${summary.eventCount}</div>`,
|
|
@@ -5869,7 +6043,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
5869
6043
|
eventRows,
|
|
5870
6044
|
"</tbody></table>",
|
|
5871
6045
|
"<h2>Markdown Export</h2>",
|
|
5872
|
-
`<pre>${
|
|
6046
|
+
`<pre>${escapeHtml8(markdown)}</pre>`,
|
|
5873
6047
|
"</main></body></html>"
|
|
5874
6048
|
].join(`
|
|
5875
6049
|
`);
|
|
@@ -7623,7 +7797,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
7623
7797
|
}
|
|
7624
7798
|
};
|
|
7625
7799
|
};
|
|
7626
|
-
var
|
|
7800
|
+
var escapeHtml9 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7627
7801
|
var escapeMarkdown = (value) => value.replaceAll("|", "\\|");
|
|
7628
7802
|
var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provider Runtime Recommendations") => [
|
|
7629
7803
|
`# ${title}`,
|
|
@@ -7656,11 +7830,11 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
7656
7830
|
].join(`
|
|
7657
7831
|
`);
|
|
7658
7832
|
var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider Runtime Recommendations") => {
|
|
7659
|
-
const cards = report.recommendations.map((recommendation) => `<article class="${
|
|
7660
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
7661
|
-
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${
|
|
7662
|
-
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${
|
|
7663
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
7833
|
+
const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml9(recommendation.status)}"><p class="eyebrow">${escapeHtml9(recommendation.surface)} \xB7 ${escapeHtml9(recommendation.status)}</p><h2>${escapeHtml9(recommendation.recommendation)}</h2><p>${escapeHtml9(recommendation.nextMove)}</p><pre>${escapeHtml9(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
|
|
7834
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml9(issue)}</li>`).join("");
|
|
7835
|
+
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml9(provider.label ?? provider.id)}</strong><span>${escapeHtml9(provider.role ?? "provider")} \xB7 ${escapeHtml9(provider.status)} \xB7 p95 ${escapeHtml9(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml9(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml9(provider.nextMove)}</small></li>`).join("");
|
|
7836
|
+
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml9(profile.label ?? profile.id)}</strong><span>${escapeHtml9(profile.status)} \xB7 ${escapeHtml9(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml9(profile.nextMove)}</small></li>`).join("");
|
|
7837
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml9(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml9(title)}</h1><p>Generated ${escapeHtml9(report.generatedAt)} from ${escapeHtml9(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml9(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml9(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
|
|
7664
7838
|
};
|
|
7665
7839
|
var renderVoiceRealCallProfileHistoryMarkdown = (report, title = "Voice Real-Call Profile History") => [
|
|
7666
7840
|
`# ${title}`,
|
|
@@ -7694,11 +7868,11 @@ var renderVoiceRealCallProfileHistoryMarkdown = (report, title = "Voice Real-Cal
|
|
|
7694
7868
|
].join(`
|
|
7695
7869
|
`);
|
|
7696
7870
|
var renderVoiceRealCallProfileHistoryHTML = (report, title = "Voice Real-Call Profile History") => {
|
|
7697
|
-
const profileRows = report.summary.profiles?.length ? report.summary.profiles.map((profile) => `<tr><td>${
|
|
7698
|
-
const defaultRows = report.defaults.profiles.length > 0 ? report.defaults.profiles.map((profile) => `<tr><td>${
|
|
7699
|
-
const recommendations = report.recommendations.recommendations.map((recommendation) => `<article class="${
|
|
7700
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
7701
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
7871
|
+
const profileRows = report.summary.profiles?.length ? report.summary.profiles.map((profile) => `<tr><td>${escapeHtml9(profile.label ?? profile.id)}</td><td>${escapeHtml9(profile.status ?? "unknown")}</td><td>${escapeHtml9(profile.maxLiveP95Ms ?? "n/a")}</td><td>${escapeHtml9(profile.maxProviderP95Ms ?? "n/a")}</td><td>${escapeHtml9(profile.maxTurnP95Ms ?? "n/a")}</td><td>${escapeHtml9(formatProviderMix(profile.providers ?? []))}</td></tr>`).join("") : '<tr><td colspan="6">No profiles present.</td></tr>';
|
|
7872
|
+
const defaultRows = report.defaults.profiles.length > 0 ? report.defaults.profiles.map((profile) => `<tr><td>${escapeHtml9(profile.label ?? profile.profileId)}</td><td>${escapeHtml9(profile.status)}</td><td>${escapeHtml9(Object.entries(profile.providerRoutes).map(([role, provider]) => `${role}: ${provider}`).join(", ") || "n/a")}</td><td>${escapeHtml9(profile.latencyBudgets.maxLiveP95Ms ?? "n/a")}</td><td>${escapeHtml9(profile.latencyBudgets.maxProviderP95Ms ?? "n/a")}</td><td>${escapeHtml9(profile.latencyBudgets.maxTurnP95Ms ?? "n/a")}</td></tr>`).join("") : '<tr><td colspan="6">No actionable defaults present.</td></tr>';
|
|
7873
|
+
const recommendations = report.recommendations.recommendations.map((recommendation) => `<article class="${escapeHtml9(recommendation.status)}"><p class="eyebrow">${escapeHtml9(recommendation.surface)} \xB7 ${escapeHtml9(recommendation.status)}</p><h2>${escapeHtml9(recommendation.recommendation)}</h2><p>${escapeHtml9(recommendation.nextMove)}</p></article>`).join("");
|
|
7874
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml9(issue)}</li>`).join("");
|
|
7875
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml9(title)}</title><style>body{background:#111510;color:#f6f0dd;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article,.card{background:#182117;border:1px solid #32412d;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(132,204,22,.16),rgba(20,184,166,.12))}.eyebrow{color:#bef264;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #52624b;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #32412d;padding:10px;text-align:left}</style></head><body><main><section class="hero"><p class="eyebrow">Real-call benchmark history</p><h1>${escapeHtml9(title)}</h1><p>Generated ${escapeHtml9(report.generatedAt)} from ${escapeHtml9(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml9(report.status)}</span><span class="pill">Reports ${String(report.reports)}</span><span class="pill">Profiles ${String(report.summary.profileCount)}</span><span class="pill">Defaults ${String(report.defaults.summary.actionableProfiles)}/${String(report.defaults.summary.profileCount)}</span><span class="pill">Cycles ${String(report.summary.cycles ?? 0)}</span><span class="pill">Best mix ${escapeHtml9(formatProviderMix(report.recommendations.bestProviders))}</span></div></section><section class="card"><h2>Profiles</h2><table><thead><tr><th>Profile</th><th>Status</th><th>Live p95</th><th>Provider p95</th><th>Turn p95</th><th>Provider mix</th></tr></thead><tbody>${profileRows}</tbody></table></section><section class="card"><h2>Actionable Defaults</h2><table><thead><tr><th>Profile</th><th>Status</th><th>Provider routes</th><th>Live budget</th><th>Provider budget</th><th>Turn budget</th></tr></thead><tbody>${defaultRows}</tbody></table></section>${recommendations}<section class="card"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
|
|
7702
7876
|
};
|
|
7703
7877
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
7704
7878
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
|
@@ -8008,13 +8182,13 @@ var formatVoiceProofTrendAge = (ageMs) => {
|
|
|
8008
8182
|
};
|
|
8009
8183
|
|
|
8010
8184
|
// src/client/proofTrendsWidget.ts
|
|
8011
|
-
var
|
|
8012
|
-
var
|
|
8185
|
+
var DEFAULT_TITLE5 = "Sustained Proof Trends";
|
|
8186
|
+
var DEFAULT_DESCRIPTION5 = "Repeated-cycle provider, latency, recovery, and readiness evidence with freshness gating.";
|
|
8013
8187
|
var DEFAULT_LINKS2 = [
|
|
8014
8188
|
{ href: "/voice/proof-trends", label: "Trend page" },
|
|
8015
8189
|
{ href: "/api/voice/proof-trends", label: "Trend JSON" }
|
|
8016
8190
|
];
|
|
8017
|
-
var
|
|
8191
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8018
8192
|
var formatMs = (value) => typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}ms` : "n/a";
|
|
8019
8193
|
var statusLabel = (report) => {
|
|
8020
8194
|
if (!report) {
|
|
@@ -8049,7 +8223,7 @@ var createVoiceProofTrendsViewModel = (snapshot, options = {}) => {
|
|
|
8049
8223
|
}
|
|
8050
8224
|
] : [];
|
|
8051
8225
|
return {
|
|
8052
|
-
description: options.description ??
|
|
8226
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
8053
8227
|
error: snapshot.error,
|
|
8054
8228
|
isLoading: snapshot.isLoading,
|
|
8055
8229
|
label: snapshot.error ? "Unavailable" : report ? statusLabel(report) : snapshot.isLoading ? "Checking" : "No trend report",
|
|
@@ -8057,26 +8231,26 @@ var createVoiceProofTrendsViewModel = (snapshot, options = {}) => {
|
|
|
8057
8231
|
metrics,
|
|
8058
8232
|
report,
|
|
8059
8233
|
status: snapshot.error ? "error" : report ? report.status === "pass" ? "ready" : "warning" : snapshot.isLoading ? "loading" : "empty",
|
|
8060
|
-
title: options.title ??
|
|
8234
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
8061
8235
|
updatedAt: snapshot.updatedAt
|
|
8062
8236
|
};
|
|
8063
8237
|
};
|
|
8064
8238
|
var renderVoiceProofTrendsHTML = (snapshot, options = {}) => {
|
|
8065
8239
|
const model = createVoiceProofTrendsViewModel(snapshot, options);
|
|
8066
8240
|
const metrics = model.metrics.length ? `<div class="absolute-voice-proof-trends__metrics">${model.metrics.map((metric) => `<article>
|
|
8067
|
-
<span>${
|
|
8068
|
-
<strong>${
|
|
8069
|
-
</article>`).join("")}</div>` : `<p class="absolute-voice-proof-trends__empty">${model.error ?
|
|
8070
|
-
const links = model.links.length ? `<p class="absolute-voice-proof-trends__links">${model.links.map((link) => `<a href="${
|
|
8071
|
-
return `<section class="absolute-voice-proof-trends absolute-voice-proof-trends--${
|
|
8241
|
+
<span>${escapeHtml10(metric.label)}</span>
|
|
8242
|
+
<strong>${escapeHtml10(metric.value)}</strong>
|
|
8243
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-proof-trends__empty">${model.error ? escapeHtml10(model.error) : "Run the sustained proof trends script to populate evidence."}</p>`;
|
|
8244
|
+
const links = model.links.length ? `<p class="absolute-voice-proof-trends__links">${model.links.map((link) => `<a href="${escapeHtml10(link.href)}">${escapeHtml10(link.label)}</a>`).join("")}</p>` : "";
|
|
8245
|
+
return `<section class="absolute-voice-proof-trends absolute-voice-proof-trends--${escapeHtml10(model.status)}">
|
|
8072
8246
|
<header class="absolute-voice-proof-trends__header">
|
|
8073
|
-
<span class="absolute-voice-proof-trends__eyebrow">${
|
|
8074
|
-
<strong class="absolute-voice-proof-trends__label">${
|
|
8247
|
+
<span class="absolute-voice-proof-trends__eyebrow">${escapeHtml10(model.title)}</span>
|
|
8248
|
+
<strong class="absolute-voice-proof-trends__label">${escapeHtml10(model.label)}</strong>
|
|
8075
8249
|
</header>
|
|
8076
|
-
<p class="absolute-voice-proof-trends__description">${
|
|
8250
|
+
<p class="absolute-voice-proof-trends__description">${escapeHtml10(model.description)}</p>
|
|
8077
8251
|
${metrics}
|
|
8078
8252
|
${links}
|
|
8079
|
-
${model.error ? `<p class="absolute-voice-proof-trends__error">${
|
|
8253
|
+
${model.error ? `<p class="absolute-voice-proof-trends__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
8080
8254
|
</section>`;
|
|
8081
8255
|
};
|
|
8082
8256
|
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}`;
|
|
@@ -8116,13 +8290,13 @@ var defineVoiceProofTrendsElement = (tagName = "absolute-voice-proof-trends") =>
|
|
|
8116
8290
|
});
|
|
8117
8291
|
};
|
|
8118
8292
|
// src/client/profileComparisonWidget.ts
|
|
8119
|
-
var
|
|
8120
|
-
var
|
|
8293
|
+
var DEFAULT_TITLE6 = "Profile Stack Comparison";
|
|
8294
|
+
var DEFAULT_DESCRIPTION6 = "Measured real-call evidence behind each profile default: provider routes, latency, and the next move.";
|
|
8121
8295
|
var DEFAULT_LINKS3 = [
|
|
8122
8296
|
{ href: "/voice/real-call-profile-history", label: "Profile history" },
|
|
8123
8297
|
{ href: "/api/voice/real-call-profile-history", label: "JSON" }
|
|
8124
8298
|
];
|
|
8125
|
-
var
|
|
8299
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8126
8300
|
var formatMs2 = (value) => typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}ms` : "n/a";
|
|
8127
8301
|
var formatProviderRoutes = (profile) => Object.entries(profile.providerRoutes).map(([role, provider]) => `${role}: ${provider}`).join(", ") || "No complete route yet";
|
|
8128
8302
|
var createProfileView = (profile) => ({
|
|
@@ -8141,37 +8315,37 @@ var createVoiceProfileComparisonViewModel = (snapshot, options = {}) => {
|
|
|
8141
8315
|
const report = snapshot.report;
|
|
8142
8316
|
const profiles = report?.defaults.profiles.map(createProfileView) ?? [];
|
|
8143
8317
|
return {
|
|
8144
|
-
description: options.description ??
|
|
8318
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
8145
8319
|
error: snapshot.error,
|
|
8146
8320
|
isLoading: snapshot.isLoading,
|
|
8147
8321
|
label: snapshot.error ? "Unavailable" : report ? `${report.defaults.summary.actionableProfiles}/${report.defaults.summary.profileCount} profiles ready` : snapshot.isLoading ? "Checking" : "No profile evidence",
|
|
8148
8322
|
links: options.links ?? DEFAULT_LINKS3,
|
|
8149
8323
|
profiles,
|
|
8150
8324
|
status: snapshot.error ? "error" : report ? report.status === "pass" ? "ready" : "warning" : snapshot.isLoading ? "loading" : "empty",
|
|
8151
|
-
title: options.title ??
|
|
8325
|
+
title: options.title ?? DEFAULT_TITLE6
|
|
8152
8326
|
};
|
|
8153
8327
|
};
|
|
8154
8328
|
var renderVoiceProfileComparisonHTML = (snapshot, options = {}) => {
|
|
8155
8329
|
const model = createVoiceProfileComparisonViewModel(snapshot, options);
|
|
8156
|
-
const profiles = model.profiles.length ? `<div class="absolute-voice-profile-comparison__profiles">${model.profiles.map((profile) => `<article class="absolute-voice-profile-comparison__profile absolute-voice-profile-comparison__profile--${
|
|
8330
|
+
const profiles = model.profiles.length ? `<div class="absolute-voice-profile-comparison__profiles">${model.profiles.map((profile) => `<article class="absolute-voice-profile-comparison__profile absolute-voice-profile-comparison__profile--${escapeHtml11(profile.status)}">
|
|
8157
8331
|
<header>
|
|
8158
|
-
<span>${
|
|
8159
|
-
<strong>${
|
|
8332
|
+
<span>${escapeHtml11(profile.status)}</span>
|
|
8333
|
+
<strong>${escapeHtml11(profile.label)}</strong>
|
|
8160
8334
|
</header>
|
|
8161
|
-
<p>${
|
|
8162
|
-
<div>${profile.evidence.map((metric) => `<span><small>${
|
|
8163
|
-
<em>${
|
|
8164
|
-
</article>`).join("")}</div>` : `<p class="absolute-voice-profile-comparison__empty">${model.error ?
|
|
8165
|
-
const links = model.links.length ? `<p class="absolute-voice-profile-comparison__links">${model.links.map((link) => `<a href="${
|
|
8166
|
-
return `<section class="absolute-voice-profile-comparison absolute-voice-profile-comparison--${
|
|
8335
|
+
<p>${escapeHtml11(profile.providerRoutes)}</p>
|
|
8336
|
+
<div>${profile.evidence.map((metric) => `<span><small>${escapeHtml11(metric.label)}</small><b>${escapeHtml11(metric.value)}</b></span>`).join("")}</div>
|
|
8337
|
+
<em>${escapeHtml11(profile.nextMove)}</em>
|
|
8338
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-profile-comparison__empty">${model.error ? escapeHtml11(model.error) : "Run real-call profile collection to populate profile comparisons."}</p>`;
|
|
8339
|
+
const links = model.links.length ? `<p class="absolute-voice-profile-comparison__links">${model.links.map((link) => `<a href="${escapeHtml11(link.href)}">${escapeHtml11(link.label)}</a>`).join("")}</p>` : "";
|
|
8340
|
+
return `<section class="absolute-voice-profile-comparison absolute-voice-profile-comparison--${escapeHtml11(model.status)}">
|
|
8167
8341
|
<header class="absolute-voice-profile-comparison__header">
|
|
8168
|
-
<span class="absolute-voice-profile-comparison__eyebrow">${
|
|
8169
|
-
<strong class="absolute-voice-profile-comparison__label">${
|
|
8342
|
+
<span class="absolute-voice-profile-comparison__eyebrow">${escapeHtml11(model.title)}</span>
|
|
8343
|
+
<strong class="absolute-voice-profile-comparison__label">${escapeHtml11(model.label)}</strong>
|
|
8170
8344
|
</header>
|
|
8171
|
-
<p class="absolute-voice-profile-comparison__description">${
|
|
8345
|
+
<p class="absolute-voice-profile-comparison__description">${escapeHtml11(model.description)}</p>
|
|
8172
8346
|
${profiles}
|
|
8173
8347
|
${links}
|
|
8174
|
-
${model.error ? `<p class="absolute-voice-profile-comparison__error">${
|
|
8348
|
+
${model.error ? `<p class="absolute-voice-profile-comparison__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
8175
8349
|
</section>`;
|
|
8176
8350
|
};
|
|
8177
8351
|
var getVoiceProfileComparisonCSS = () => `.absolute-voice-profile-comparison{border:1px solid #c7d2fe;border-radius:20px;background:#eef2ff;color:#111827;padding:18px;box-shadow:0 18px 40px rgba(79,70,229,.12);font-family:inherit}.absolute-voice-profile-comparison--warning,.absolute-voice-profile-comparison--error{border-color:#fbbf24;background:#fffbeb}.absolute-voice-profile-comparison__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-profile-comparison__eyebrow{color:#4338ca;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-profile-comparison__label{font-size:24px;line-height:1}.absolute-voice-profile-comparison__description,.absolute-voice-profile-comparison__empty{color:#4b5563}.absolute-voice-profile-comparison__profiles{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin-top:14px}.absolute-voice-profile-comparison__profile{background:#fff;border:1px solid #c7d2fe;border-radius:16px;padding:14px}.absolute-voice-profile-comparison__profile--warn{border-color:#fbbf24}.absolute-voice-profile-comparison__profile--fail{border-color:#f87171}.absolute-voice-profile-comparison__profile header{align-items:center;display:flex;gap:8px;justify-content:space-between}.absolute-voice-profile-comparison__profile header span{border:1px solid currentColor;border-radius:999px;color:#4338ca;font-size:11px;font-weight:900;padding:3px 7px;text-transform:uppercase}.absolute-voice-profile-comparison__profile p{color:#1f2937;font-weight:800;overflow-wrap:anywhere}.absolute-voice-profile-comparison__profile div{display:grid;gap:8px;grid-template-columns:repeat(3,minmax(0,1fr))}.absolute-voice-profile-comparison__profile small{color:#6b7280;display:block;font-size:11px}.absolute-voice-profile-comparison__profile b{display:block}.absolute-voice-profile-comparison__profile em{color:#4b5563;display:block;font-size:13px;margin-top:12px}.absolute-voice-profile-comparison__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-profile-comparison__links a{border:1px solid #a5b4fc;border-radius:999px;color:#4338ca;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-profile-comparison__error{color:#9f1239;font-weight:700}`;
|
|
@@ -8212,29 +8386,29 @@ var defineVoiceProfileComparisonElement = (tagName = "absolute-voice-profile-com
|
|
|
8212
8386
|
});
|
|
8213
8387
|
};
|
|
8214
8388
|
// src/client/profileSwitchRecommendationWidget.ts
|
|
8215
|
-
var
|
|
8216
|
-
var
|
|
8217
|
-
var
|
|
8389
|
+
var DEFAULT_TITLE7 = "Profile Switch Recommendation";
|
|
8390
|
+
var DEFAULT_DESCRIPTION7 = "Compares the current session against measured profile evidence and recommends whether to switch stacks.";
|
|
8391
|
+
var escapeHtml12 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8218
8392
|
var formatRoute = (routes) => routes ? Object.entries(routes).map(([role, provider]) => `${role}: ${provider}`).join(", ") : "No route";
|
|
8219
8393
|
var renderVoiceProfileSwitchRecommendationHTML = (snapshot, options = {}) => {
|
|
8220
8394
|
const recommendation = snapshot.recommendation;
|
|
8221
8395
|
const status = snapshot.error ? "error" : recommendation ? recommendation.status : snapshot.isLoading ? "loading" : "empty";
|
|
8222
8396
|
const label = snapshot.error ? "Unavailable" : recommendation ? recommendation.status === "switch" ? `Switch to ${recommendation.recommendedProfile?.label ?? recommendation.recommendedProfile?.profileId ?? "recommended profile"}` : recommendation.status === "stay" ? "Keep current profile" : "Needs evidence" : snapshot.isLoading ? "Checking" : "No recommendation";
|
|
8223
8397
|
const body = recommendation ? `<div class="absolute-voice-profile-switch__body">
|
|
8224
|
-
<p><strong>Current:</strong> ${
|
|
8225
|
-
<p><strong>Recommended:</strong> ${
|
|
8226
|
-
<p><strong>Routes:</strong> ${
|
|
8227
|
-
<ul>${recommendation.reasons.map((reason) => `<li>${
|
|
8228
|
-
<em>${
|
|
8229
|
-
</div>` : `<p class="absolute-voice-profile-switch__empty">${
|
|
8230
|
-
return `<section class="absolute-voice-profile-switch absolute-voice-profile-switch--${
|
|
8398
|
+
<p><strong>Current:</strong> ${escapeHtml12(recommendation.currentProfile?.label ?? recommendation.currentProfile?.profileId ?? "Unknown")}</p>
|
|
8399
|
+
<p><strong>Recommended:</strong> ${escapeHtml12(recommendation.recommendedProfile?.label ?? recommendation.recommendedProfile?.profileId ?? "None")}</p>
|
|
8400
|
+
<p><strong>Routes:</strong> ${escapeHtml12(formatRoute(recommendation.recommendedProfile?.providerRoutes))}</p>
|
|
8401
|
+
<ul>${recommendation.reasons.map((reason) => `<li>${escapeHtml12(reason)}</li>`).join("")}</ul>
|
|
8402
|
+
<em>${escapeHtml12(recommendation.nextMove)}</em>
|
|
8403
|
+
</div>` : `<p class="absolute-voice-profile-switch__empty">${escapeHtml12(snapshot.error ?? "Run session traffic to populate a recommendation.")}</p>`;
|
|
8404
|
+
return `<section class="absolute-voice-profile-switch absolute-voice-profile-switch--${escapeHtml12(status)}">
|
|
8231
8405
|
<header class="absolute-voice-profile-switch__header">
|
|
8232
|
-
<span class="absolute-voice-profile-switch__eyebrow">${
|
|
8233
|
-
<strong class="absolute-voice-profile-switch__label">${
|
|
8406
|
+
<span class="absolute-voice-profile-switch__eyebrow">${escapeHtml12(options.title ?? DEFAULT_TITLE7)}</span>
|
|
8407
|
+
<strong class="absolute-voice-profile-switch__label">${escapeHtml12(label)}</strong>
|
|
8234
8408
|
</header>
|
|
8235
|
-
<p class="absolute-voice-profile-switch__description">${
|
|
8409
|
+
<p class="absolute-voice-profile-switch__description">${escapeHtml12(options.description ?? DEFAULT_DESCRIPTION7)}</p>
|
|
8236
8410
|
${body}
|
|
8237
|
-
${snapshot.error ? `<p class="absolute-voice-profile-switch__error">${
|
|
8411
|
+
${snapshot.error ? `<p class="absolute-voice-profile-switch__error">${escapeHtml12(snapshot.error)}</p>` : ""}
|
|
8238
8412
|
</section>`;
|
|
8239
8413
|
};
|
|
8240
8414
|
var getVoiceProfileSwitchRecommendationCSS = () => `.absolute-voice-profile-switch{border:1px solid #fed7aa;border-radius:20px;background:#fff7ed;color:#1c1917;padding:18px;box-shadow:0 18px 40px rgba(234,88,12,.12);font-family:inherit}.absolute-voice-profile-switch--switch{border-color:#fdba74}.absolute-voice-profile-switch--stay{border-color:#86efac;background:#f0fdf4}.absolute-voice-profile-switch--warn,.absolute-voice-profile-switch--error{border-color:#fca5a5;background:#fff1f2}.absolute-voice-profile-switch__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-profile-switch__eyebrow{color:#c2410c;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-profile-switch__label{font-size:24px;line-height:1}.absolute-voice-profile-switch__description,.absolute-voice-profile-switch__body em,.absolute-voice-profile-switch__empty{color:#57534e}.absolute-voice-profile-switch__body{background:#fff;border:1px solid #fed7aa;border-radius:16px;margin-top:14px;padding:14px}.absolute-voice-profile-switch__body p{margin:.35rem 0}.absolute-voice-profile-switch__body ul{margin:.75rem 0;padding-left:1.2rem}.absolute-voice-profile-switch__body em{display:block}.absolute-voice-profile-switch__error{color:#9f1239;font-weight:700}`;
|
|
@@ -8275,13 +8449,13 @@ var defineVoiceProfileSwitchRecommendationElement = (tagName = "absolute-voice-p
|
|
|
8275
8449
|
});
|
|
8276
8450
|
};
|
|
8277
8451
|
// src/client/readinessFailuresWidget.ts
|
|
8278
|
-
var
|
|
8279
|
-
var
|
|
8452
|
+
var DEFAULT_TITLE8 = "Readiness Gate Explanations";
|
|
8453
|
+
var DEFAULT_DESCRIPTION8 = "Structured reasons for calibrated production-readiness warnings and failures.";
|
|
8280
8454
|
var DEFAULT_LINKS4 = [
|
|
8281
8455
|
{ href: "/production-readiness", label: "Readiness page" },
|
|
8282
8456
|
{ href: "/voice/slo-readiness-thresholds", label: "Gate thresholds" }
|
|
8283
8457
|
];
|
|
8284
|
-
var
|
|
8458
|
+
var escapeHtml13 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8285
8459
|
var formatExplanationValue = (value, unit) => {
|
|
8286
8460
|
if (value === undefined || value === null) {
|
|
8287
8461
|
return "n/a";
|
|
@@ -8309,36 +8483,36 @@ var createVoiceReadinessFailuresViewModel = (snapshot, options = {}) => {
|
|
|
8309
8483
|
const failures = snapshot.report?.checks.map(toFailureView).filter((value) => !!value) ?? [];
|
|
8310
8484
|
const hasOpenIssues = failures.length > 0;
|
|
8311
8485
|
return {
|
|
8312
|
-
description: options.description ??
|
|
8486
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
8313
8487
|
error: snapshot.error,
|
|
8314
8488
|
failures,
|
|
8315
8489
|
isLoading: snapshot.isLoading,
|
|
8316
8490
|
label: snapshot.error ? "Unavailable" : snapshot.report ? hasOpenIssues ? `${failures.length} calibrated gate issue(s)` : "No calibrated gate issues" : snapshot.isLoading ? "Checking" : "No readiness report",
|
|
8317
8491
|
links: options.links ?? DEFAULT_LINKS4,
|
|
8318
8492
|
status: snapshot.error ? "error" : snapshot.report ? hasOpenIssues ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
8319
|
-
title: options.title ??
|
|
8493
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
8320
8494
|
updatedAt: snapshot.updatedAt
|
|
8321
8495
|
};
|
|
8322
8496
|
};
|
|
8323
8497
|
var renderVoiceReadinessFailuresHTML = (snapshot, options = {}) => {
|
|
8324
8498
|
const model = createVoiceReadinessFailuresViewModel(snapshot, options);
|
|
8325
|
-
const failures = model.failures.length ? `<div class="absolute-voice-readiness-failures__items">${model.failures.map((failure) => `<article class="absolute-voice-readiness-failures__item absolute-voice-readiness-failures__item--${
|
|
8326
|
-
<span>${
|
|
8327
|
-
<strong>${
|
|
8328
|
-
<p>Observed ${
|
|
8329
|
-
<p>${
|
|
8330
|
-
<p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${
|
|
8331
|
-
</article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ?
|
|
8332
|
-
const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${
|
|
8333
|
-
return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${
|
|
8499
|
+
const failures = model.failures.length ? `<div class="absolute-voice-readiness-failures__items">${model.failures.map((failure) => `<article class="absolute-voice-readiness-failures__item absolute-voice-readiness-failures__item--${escapeHtml13(failure.status)}">
|
|
8500
|
+
<span>${escapeHtml13(failure.status.toUpperCase())}</span>
|
|
8501
|
+
<strong>${escapeHtml13(failure.label)}</strong>
|
|
8502
|
+
<p>Observed ${escapeHtml13(failure.observed)} against ${escapeHtml13(failure.thresholdLabel)} ${escapeHtml13(failure.threshold)}.</p>
|
|
8503
|
+
<p>${escapeHtml13(failure.remediation)}</p>
|
|
8504
|
+
<p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${escapeHtml13(failure.evidenceHref)}">Evidence</a>` : ""}${failure.sourceHref ? `<a href="${escapeHtml13(failure.sourceHref)}">Threshold source</a>` : ""}</p>
|
|
8505
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ? escapeHtml13(model.error) : "No calibrated readiness gate explanations are open."}</p>`;
|
|
8506
|
+
const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${escapeHtml13(link.href)}">${escapeHtml13(link.label)}</a>`).join("")}</p>` : "";
|
|
8507
|
+
return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${escapeHtml13(model.status)}">
|
|
8334
8508
|
<header class="absolute-voice-readiness-failures__header">
|
|
8335
|
-
<span class="absolute-voice-readiness-failures__eyebrow">${
|
|
8336
|
-
<strong class="absolute-voice-readiness-failures__label">${
|
|
8509
|
+
<span class="absolute-voice-readiness-failures__eyebrow">${escapeHtml13(model.title)}</span>
|
|
8510
|
+
<strong class="absolute-voice-readiness-failures__label">${escapeHtml13(model.label)}</strong>
|
|
8337
8511
|
</header>
|
|
8338
|
-
<p class="absolute-voice-readiness-failures__description">${
|
|
8512
|
+
<p class="absolute-voice-readiness-failures__description">${escapeHtml13(model.description)}</p>
|
|
8339
8513
|
${failures}
|
|
8340
8514
|
${links}
|
|
8341
|
-
${model.error ? `<p class="absolute-voice-readiness-failures__error">${
|
|
8515
|
+
${model.error ? `<p class="absolute-voice-readiness-failures__error">${escapeHtml13(model.error)}</p>` : ""}
|
|
8342
8516
|
</section>`;
|
|
8343
8517
|
};
|
|
8344
8518
|
var getVoiceReadinessFailuresCSS = () => `.absolute-voice-readiness-failures{border:1px solid #fed7aa;border-radius:20px;background:#fff7ed;color:#1c1917;padding:18px;box-shadow:0 18px 40px rgba(234,88,12,.12);font-family:inherit}.absolute-voice-readiness-failures--ready{border-color:#86efac;background:#f0fdf4}.absolute-voice-readiness-failures--error{border-color:#fda4af;background:#fff1f2}.absolute-voice-readiness-failures__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-readiness-failures__eyebrow{color:#9a3412;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-readiness-failures__label{font-size:24px;line-height:1}.absolute-voice-readiness-failures__description,.absolute-voice-readiness-failures__empty{color:#57534e}.absolute-voice-readiness-failures__items{display:grid;gap:10px;margin-top:14px}.absolute-voice-readiness-failures__item{background:white;border:1px solid #fed7aa;border-radius:16px;padding:12px}.absolute-voice-readiness-failures__item--fail{border-color:#fb7185}.absolute-voice-readiness-failures__item span{color:#9a3412;display:block;font-size:12px;font-weight:900;text-transform:uppercase}.absolute-voice-readiness-failures__item strong{display:block;font-size:18px;margin-top:4px}.absolute-voice-readiness-failures__item p{margin:.45rem 0 0}.absolute-voice-readiness-failures__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-readiness-failures__links a{border:1px solid #fdba74;border-radius:999px;color:#9a3412;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-readiness-failures__error{color:#9f1239;font-weight:700}`;
|
|
@@ -8378,9 +8552,9 @@ var defineVoiceReadinessFailuresElement = (tagName = "absolute-voice-readiness-f
|
|
|
8378
8552
|
});
|
|
8379
8553
|
};
|
|
8380
8554
|
// src/client/opsActionCenterWidget.ts
|
|
8381
|
-
var
|
|
8382
|
-
var
|
|
8383
|
-
var
|
|
8555
|
+
var DEFAULT_TITLE9 = "Voice Ops Action Center";
|
|
8556
|
+
var DEFAULT_DESCRIPTION9 = "Run production voice proofs and operator actions from one primitive panel.";
|
|
8557
|
+
var escapeHtml14 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8384
8558
|
var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
8385
8559
|
const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
|
|
8386
8560
|
return {
|
|
@@ -8391,29 +8565,29 @@ var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
|
8391
8565
|
isRunning: snapshot.runningActionId === action.id,
|
|
8392
8566
|
label: action.label
|
|
8393
8567
|
})),
|
|
8394
|
-
description: options.description ??
|
|
8568
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
8395
8569
|
error: snapshot.error,
|
|
8396
8570
|
isRunning: snapshot.isRunning,
|
|
8397
8571
|
label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
|
|
8398
8572
|
lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
|
|
8399
8573
|
status,
|
|
8400
|
-
title: options.title ??
|
|
8574
|
+
title: options.title ?? DEFAULT_TITLE9
|
|
8401
8575
|
};
|
|
8402
8576
|
};
|
|
8403
8577
|
var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
|
|
8404
8578
|
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
8405
|
-
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${
|
|
8406
|
-
${
|
|
8579
|
+
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml14(action.id)}"${action.disabled ? " disabled" : ""}>
|
|
8580
|
+
${escapeHtml14(action.isRunning ? "Working..." : action.label)}
|
|
8407
8581
|
</button>`).join("");
|
|
8408
|
-
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${
|
|
8582
|
+
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml14(model.status)}">
|
|
8409
8583
|
<header class="absolute-voice-ops-action-center__header">
|
|
8410
|
-
<span class="absolute-voice-ops-action-center__eyebrow">${
|
|
8411
|
-
<strong class="absolute-voice-ops-action-center__label">${
|
|
8584
|
+
<span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml14(model.title)}</span>
|
|
8585
|
+
<strong class="absolute-voice-ops-action-center__label">${escapeHtml14(model.label)}</strong>
|
|
8412
8586
|
</header>
|
|
8413
|
-
<p class="absolute-voice-ops-action-center__description">${
|
|
8587
|
+
<p class="absolute-voice-ops-action-center__description">${escapeHtml14(model.description)}</p>
|
|
8414
8588
|
<div class="absolute-voice-ops-action-center__actions">${actions}</div>
|
|
8415
|
-
<p class="absolute-voice-ops-action-center__result">${
|
|
8416
|
-
${model.error ? `<p class="absolute-voice-ops-action-center__error">${
|
|
8589
|
+
<p class="absolute-voice-ops-action-center__result">${escapeHtml14(model.lastResultLabel)}</p>
|
|
8590
|
+
${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml14(model.error)}</p>` : ""}
|
|
8417
8591
|
</section>`;
|
|
8418
8592
|
};
|
|
8419
8593
|
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}`;
|
|
@@ -8975,7 +9149,7 @@ var ACTION_LABELS = {
|
|
|
8975
9149
|
"resume-assistant": "Resume assistant",
|
|
8976
9150
|
tag: "Tag"
|
|
8977
9151
|
};
|
|
8978
|
-
var
|
|
9152
|
+
var escapeHtml15 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8979
9153
|
var createVoiceLiveOpsInput = (action, input) => ({
|
|
8980
9154
|
action,
|
|
8981
9155
|
assignee: input.assignee,
|
|
@@ -8986,17 +9160,17 @@ var createVoiceLiveOpsInput = (action, input) => ({
|
|
|
8986
9160
|
var renderVoiceLiveOpsHTML = (snapshot, options = {}) => {
|
|
8987
9161
|
const sessionId = options.getSessionId?.() ?? "";
|
|
8988
9162
|
const disabled = snapshot.isRunning || !sessionId;
|
|
8989
|
-
const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${
|
|
8990
|
-
const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${
|
|
9163
|
+
const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml15(action)}"${disabled ? " disabled" : ""}>${escapeHtml15(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
|
|
9164
|
+
const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml15(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml15(snapshot.lastResult.action)}. Control: ${escapeHtml15(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
|
|
8991
9165
|
return `<section class="absolute-voice-live-ops">
|
|
8992
9166
|
<header class="absolute-voice-live-ops__header">
|
|
8993
|
-
<span>${
|
|
8994
|
-
<strong>${
|
|
9167
|
+
<span>${escapeHtml15(options.title ?? "Live Ops")}</span>
|
|
9168
|
+
<strong>${escapeHtml15(sessionId || "No active session")}</strong>
|
|
8995
9169
|
</header>
|
|
8996
|
-
<p class="absolute-voice-live-ops__description">${
|
|
8997
|
-
<label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${
|
|
8998
|
-
<label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${
|
|
8999
|
-
<label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${
|
|
9170
|
+
<p class="absolute-voice-live-ops__description">${escapeHtml15(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
|
|
9171
|
+
<label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml15(options.defaultAssignee ?? "operator")}" /></label>
|
|
9172
|
+
<label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml15(options.defaultTag ?? "live-ops")}" /></label>
|
|
9173
|
+
<label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml15(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
|
|
9000
9174
|
<div class="absolute-voice-live-ops__actions">${actions}</div>
|
|
9001
9175
|
${result}
|
|
9002
9176
|
</section>`;
|
|
@@ -9083,16 +9257,16 @@ var defineVoiceLiveOpsElement = (tagName = "absolute-voice-live-ops", options =
|
|
|
9083
9257
|
});
|
|
9084
9258
|
};
|
|
9085
9259
|
// src/client/opsActionHistoryWidget.ts
|
|
9086
|
-
var
|
|
9260
|
+
var escapeHtml16 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9087
9261
|
var renderVoiceOpsActionHistoryWidgetHTML = (snapshot, options = {}) => {
|
|
9088
9262
|
const report = snapshot.report;
|
|
9089
9263
|
const entries = (report?.entries ?? []).slice(0, options.limit ?? 5);
|
|
9090
|
-
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${
|
|
9264
|
+
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${escapeHtml16(entry.actionId)}</span><strong>${escapeHtml16(entry.ok ? "Success" : "Failed")}</strong><small>${escapeHtml16(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</small></li>`).join("");
|
|
9091
9265
|
return `<section class="absolute-voice-ops-action-history">
|
|
9092
|
-
<header><span>Operator proof</span><strong>${
|
|
9266
|
+
<header><span>Operator proof</span><strong>${escapeHtml16(options.title ?? "Action History")}</strong></header>
|
|
9093
9267
|
<p>${String(report?.total ?? 0)} action(s), ${String(report?.failed ?? 0)} failed.</p>
|
|
9094
9268
|
<ul>${rows || "<li>No operator actions recorded yet.</li>"}</ul>
|
|
9095
|
-
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${
|
|
9269
|
+
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${escapeHtml16(snapshot.error)}</p>` : ""}
|
|
9096
9270
|
</section>`;
|
|
9097
9271
|
};
|
|
9098
9272
|
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}`;
|
|
@@ -9113,9 +9287,9 @@ var mountVoiceOpsActionHistory = (element, path = "/api/voice/ops-actions/histor
|
|
|
9113
9287
|
};
|
|
9114
9288
|
};
|
|
9115
9289
|
// src/client/deliveryRuntimeWidget.ts
|
|
9116
|
-
var
|
|
9117
|
-
var
|
|
9118
|
-
var
|
|
9290
|
+
var DEFAULT_TITLE10 = "Voice Delivery Runtime";
|
|
9291
|
+
var DEFAULT_DESCRIPTION10 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
9292
|
+
var escapeHtml17 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9119
9293
|
var createSurface = (id, summary) => {
|
|
9120
9294
|
if (!summary) {
|
|
9121
9295
|
return {
|
|
@@ -9149,7 +9323,7 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
9149
9323
|
];
|
|
9150
9324
|
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
9151
9325
|
return {
|
|
9152
|
-
description: options.description ??
|
|
9326
|
+
description: options.description ?? DEFAULT_DESCRIPTION10,
|
|
9153
9327
|
error: snapshot.error,
|
|
9154
9328
|
actionError: snapshot.actionError,
|
|
9155
9329
|
actionStatus: snapshot.actionStatus,
|
|
@@ -9158,32 +9332,32 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
9158
9332
|
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
9159
9333
|
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
9160
9334
|
surfaces,
|
|
9161
|
-
title: options.title ??
|
|
9335
|
+
title: options.title ?? DEFAULT_TITLE10,
|
|
9162
9336
|
updatedAt: snapshot.updatedAt
|
|
9163
9337
|
};
|
|
9164
9338
|
};
|
|
9165
9339
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
9166
9340
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
9167
|
-
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${
|
|
9168
|
-
<span>${
|
|
9169
|
-
<strong>${
|
|
9341
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml17(surface.status)}">
|
|
9342
|
+
<span>${escapeHtml17(surface.label)}</span>
|
|
9343
|
+
<strong>${escapeHtml17(surface.detail)}</strong>
|
|
9170
9344
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
9171
9345
|
</li>`).join("");
|
|
9172
9346
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
9173
9347
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
9174
9348
|
<button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
|
|
9175
9349
|
</div>`;
|
|
9176
|
-
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
9177
|
-
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${
|
|
9350
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml17(model.actionError)}</p>` : "";
|
|
9351
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml17(model.status)}">
|
|
9178
9352
|
<header class="absolute-voice-delivery-runtime__header">
|
|
9179
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
9180
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
9353
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml17(model.title)}</span>
|
|
9354
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml17(model.label)}</strong>
|
|
9181
9355
|
</header>
|
|
9182
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
9356
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml17(model.description)}</p>
|
|
9183
9357
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
9184
9358
|
${actions}
|
|
9185
9359
|
${actionError}
|
|
9186
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
9360
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml17(model.error)}</p>` : ""}
|
|
9187
9361
|
</section>`;
|
|
9188
9362
|
};
|
|
9189
9363
|
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}`;
|
|
@@ -9319,9 +9493,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
9319
9493
|
};
|
|
9320
9494
|
};
|
|
9321
9495
|
// src/client/routingStatusWidget.ts
|
|
9322
|
-
var
|
|
9323
|
-
var
|
|
9324
|
-
var
|
|
9496
|
+
var DEFAULT_TITLE11 = "Voice Routing";
|
|
9497
|
+
var DEFAULT_DESCRIPTION11 = "Latest provider routing decision from the self-hosted trace store.";
|
|
9498
|
+
var escapeHtml18 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9325
9499
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
9326
9500
|
var formatProviderRoutes2 = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
|
|
9327
9501
|
var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
|
|
@@ -9390,35 +9564,35 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
9390
9564
|
return {
|
|
9391
9565
|
activeStack,
|
|
9392
9566
|
decision,
|
|
9393
|
-
description: options.description ??
|
|
9567
|
+
description: options.description ?? DEFAULT_DESCRIPTION11,
|
|
9394
9568
|
error: snapshot.error,
|
|
9395
9569
|
isLoading: snapshot.isLoading,
|
|
9396
9570
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
9397
9571
|
rows,
|
|
9398
9572
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
9399
|
-
title: options.title ??
|
|
9573
|
+
title: options.title ?? DEFAULT_TITLE11,
|
|
9400
9574
|
updatedAt: snapshot.updatedAt
|
|
9401
9575
|
};
|
|
9402
9576
|
};
|
|
9403
9577
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
9404
9578
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
9405
9579
|
const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
|
|
9406
|
-
<span>${
|
|
9407
|
-
<strong>${
|
|
9580
|
+
<span>${escapeHtml18(item.label)}</span>
|
|
9581
|
+
<strong>${escapeHtml18(item.value)}</strong>
|
|
9408
9582
|
</div>`).join("")}</div>` : "";
|
|
9409
9583
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
9410
|
-
<span>${
|
|
9411
|
-
<strong>${
|
|
9584
|
+
<span>${escapeHtml18(row.label)}</span>
|
|
9585
|
+
<strong>${escapeHtml18(row.value)}</strong>
|
|
9412
9586
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
9413
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
9587
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml18(model.status)}">
|
|
9414
9588
|
<header class="absolute-voice-routing-status__header">
|
|
9415
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
9416
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
9589
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml18(model.title)}</span>
|
|
9590
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml18(model.label)}</strong>
|
|
9417
9591
|
</header>
|
|
9418
|
-
<p class="absolute-voice-routing-status__description">${
|
|
9592
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml18(model.description)}</p>
|
|
9419
9593
|
${activeStack}
|
|
9420
9594
|
${rows}
|
|
9421
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
9595
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml18(model.error)}</p>` : ""}
|
|
9422
9596
|
</section>`;
|
|
9423
9597
|
};
|
|
9424
9598
|
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__stack{background:linear-gradient(135deg,#16130d,#49391f);border-radius:18px;color:#fff;display:grid;gap:8px;grid-template-columns:repeat(5,minmax(0,1fr));margin-top:14px;padding:12px}.absolute-voice-routing-status__stack div{border-left:1px solid rgba(255,255,255,.18);padding-left:10px}.absolute-voice-routing-status__stack div:first-child{border-left:0;padding-left:0}.absolute-voice-routing-status__stack span{color:#e9d9b8;display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:5px;text-transform:uppercase}.absolute-voice-routing-status__stack strong{display:block;font-size:13px;line-height:1.25;overflow-wrap:anywhere}.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}@media (max-width:760px){.absolute-voice-routing-status__stack{grid-template-columns:repeat(2,minmax(0,1fr))}.absolute-voice-routing-status__stack div{border-left:0;border-top:1px solid rgba(255,255,255,.18);padding-left:0;padding-top:8px}.absolute-voice-routing-status__stack div:first-child{border-top:0;padding-top:0}}`;
|
|
@@ -10217,7 +10391,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
10217
10391
|
};
|
|
10218
10392
|
};
|
|
10219
10393
|
// src/client/providerSimulationControlsWidget.ts
|
|
10220
|
-
var
|
|
10394
|
+
var escapeHtml19 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10221
10395
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
10222
10396
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
10223
10397
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -10237,18 +10411,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
10237
10411
|
};
|
|
10238
10412
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
10239
10413
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
10240
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
10241
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
10414
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml19(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml19(provider.provider)} ${escapeHtml19(formatKind(options.kind))} failure</button>`).join("");
|
|
10415
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml19(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml19(provider.provider)} recovered</button>`).join("");
|
|
10242
10416
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
10243
10417
|
<header class="absolute-voice-provider-simulation__header">
|
|
10244
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
10245
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
10418
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml19(model.title)}</span>
|
|
10419
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml19(model.label)}</strong>
|
|
10246
10420
|
</header>
|
|
10247
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
10248
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
10421
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml19(model.description)}</p>
|
|
10422
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml19(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
10249
10423
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
10250
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
10251
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
10424
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml19(snapshot.error)}</p>` : ""}
|
|
10425
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml19(model.resultText)}</pre>` : ""}
|
|
10252
10426
|
</section>`;
|
|
10253
10427
|
};
|
|
10254
10428
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -10313,9 +10487,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
10313
10487
|
});
|
|
10314
10488
|
};
|
|
10315
10489
|
// src/client/providerStatusWidget.ts
|
|
10316
|
-
var
|
|
10317
|
-
var
|
|
10318
|
-
var
|
|
10490
|
+
var DEFAULT_TITLE12 = "Voice Providers";
|
|
10491
|
+
var DEFAULT_DESCRIPTION12 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
10492
|
+
var escapeHtml20 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10319
10493
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
10320
10494
|
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
10321
10495
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -10359,37 +10533,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
10359
10533
|
const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
|
|
10360
10534
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
10361
10535
|
return {
|
|
10362
|
-
description: options.description ??
|
|
10536
|
+
description: options.description ?? DEFAULT_DESCRIPTION12,
|
|
10363
10537
|
error: snapshot.error,
|
|
10364
10538
|
isLoading: snapshot.isLoading,
|
|
10365
10539
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
10366
10540
|
providers,
|
|
10367
10541
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
10368
|
-
title: options.title ??
|
|
10542
|
+
title: options.title ?? DEFAULT_TITLE12,
|
|
10369
10543
|
updatedAt: snapshot.updatedAt
|
|
10370
10544
|
};
|
|
10371
10545
|
};
|
|
10372
10546
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
10373
10547
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
10374
|
-
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--${
|
|
10548
|
+
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--${escapeHtml20(provider.status)}">
|
|
10375
10549
|
<header>
|
|
10376
|
-
<strong>${
|
|
10377
|
-
<span>${
|
|
10550
|
+
<strong>${escapeHtml20(provider.label)}</strong>
|
|
10551
|
+
<span>${escapeHtml20(formatStatus3(provider.status))}</span>
|
|
10378
10552
|
</header>
|
|
10379
|
-
<p>${
|
|
10553
|
+
<p>${escapeHtml20(provider.detail)}</p>
|
|
10380
10554
|
<dl>${provider.rows.map((row) => `<div>
|
|
10381
|
-
<dt>${
|
|
10382
|
-
<dd>${
|
|
10555
|
+
<dt>${escapeHtml20(row.label)}</dt>
|
|
10556
|
+
<dd>${escapeHtml20(row.value)}</dd>
|
|
10383
10557
|
</div>`).join("")}</dl>
|
|
10384
10558
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
10385
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
10559
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml20(model.status)}">
|
|
10386
10560
|
<header class="absolute-voice-provider-status__header">
|
|
10387
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
10388
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
10561
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml20(model.title)}</span>
|
|
10562
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml20(model.label)}</strong>
|
|
10389
10563
|
</header>
|
|
10390
|
-
<p class="absolute-voice-provider-status__description">${
|
|
10564
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml20(model.description)}</p>
|
|
10391
10565
|
${providers}
|
|
10392
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
10566
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml20(model.error)}</p>` : ""}
|
|
10393
10567
|
</section>`;
|
|
10394
10568
|
};
|
|
10395
10569
|
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}`;
|
|
@@ -10430,9 +10604,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
10430
10604
|
});
|
|
10431
10605
|
};
|
|
10432
10606
|
// src/client/providerCapabilitiesWidget.ts
|
|
10433
|
-
var
|
|
10434
|
-
var
|
|
10435
|
-
var
|
|
10607
|
+
var DEFAULT_TITLE13 = "Provider Capabilities";
|
|
10608
|
+
var DEFAULT_DESCRIPTION13 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
10609
|
+
var escapeHtml21 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10436
10610
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
10437
10611
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
10438
10612
|
var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -10476,36 +10650,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
10476
10650
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
10477
10651
|
return {
|
|
10478
10652
|
capabilities,
|
|
10479
|
-
description: options.description ??
|
|
10653
|
+
description: options.description ?? DEFAULT_DESCRIPTION13,
|
|
10480
10654
|
error: snapshot.error,
|
|
10481
10655
|
isLoading: snapshot.isLoading,
|
|
10482
10656
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
10483
10657
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
10484
|
-
title: options.title ??
|
|
10658
|
+
title: options.title ?? DEFAULT_TITLE13,
|
|
10485
10659
|
updatedAt: snapshot.updatedAt
|
|
10486
10660
|
};
|
|
10487
10661
|
};
|
|
10488
10662
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
10489
10663
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
10490
|
-
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--${
|
|
10664
|
+
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--${escapeHtml21(capability.status)}">
|
|
10491
10665
|
<header>
|
|
10492
|
-
<strong>${
|
|
10493
|
-
<span>${
|
|
10666
|
+
<strong>${escapeHtml21(capability.label)}</strong>
|
|
10667
|
+
<span>${escapeHtml21(formatStatus4(capability.status))}</span>
|
|
10494
10668
|
</header>
|
|
10495
|
-
<p>${
|
|
10669
|
+
<p>${escapeHtml21(capability.detail)}</p>
|
|
10496
10670
|
<dl>${capability.rows.map((row) => `<div>
|
|
10497
|
-
<dt>${
|
|
10498
|
-
<dd>${
|
|
10671
|
+
<dt>${escapeHtml21(row.label)}</dt>
|
|
10672
|
+
<dd>${escapeHtml21(row.value)}</dd>
|
|
10499
10673
|
</div>`).join("")}</dl>
|
|
10500
10674
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
10501
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
10675
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml21(model.status)}">
|
|
10502
10676
|
<header class="absolute-voice-provider-capabilities__header">
|
|
10503
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
10504
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
10677
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml21(model.title)}</span>
|
|
10678
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml21(model.label)}</strong>
|
|
10505
10679
|
</header>
|
|
10506
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
10680
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml21(model.description)}</p>
|
|
10507
10681
|
${capabilities}
|
|
10508
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
10682
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml21(model.error)}</p>` : ""}
|
|
10509
10683
|
</section>`;
|
|
10510
10684
|
};
|
|
10511
10685
|
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}`;
|
|
@@ -10546,9 +10720,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
10546
10720
|
});
|
|
10547
10721
|
};
|
|
10548
10722
|
// src/client/providerContractsWidget.ts
|
|
10549
|
-
var
|
|
10550
|
-
var
|
|
10551
|
-
var
|
|
10723
|
+
var DEFAULT_TITLE14 = "Provider Contracts";
|
|
10724
|
+
var DEFAULT_DESCRIPTION14 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
10725
|
+
var escapeHtml22 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10552
10726
|
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
10553
10727
|
var formatStatus5 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
10554
10728
|
var contractDetail = (row) => {
|
|
@@ -10580,38 +10754,38 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
|
10580
10754
|
}));
|
|
10581
10755
|
const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
|
|
10582
10756
|
return {
|
|
10583
|
-
description: options.description ??
|
|
10757
|
+
description: options.description ?? DEFAULT_DESCRIPTION14,
|
|
10584
10758
|
error: snapshot.error,
|
|
10585
10759
|
isLoading: snapshot.isLoading,
|
|
10586
10760
|
label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
|
|
10587
10761
|
rows,
|
|
10588
10762
|
status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
10589
|
-
title: options.title ??
|
|
10763
|
+
title: options.title ?? DEFAULT_TITLE14,
|
|
10590
10764
|
updatedAt: snapshot.updatedAt
|
|
10591
10765
|
};
|
|
10592
10766
|
};
|
|
10593
10767
|
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
10594
10768
|
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
10595
|
-
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--${
|
|
10769
|
+
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--${escapeHtml22(row.status)}">
|
|
10596
10770
|
<header>
|
|
10597
|
-
<strong>${
|
|
10598
|
-
<span>${
|
|
10771
|
+
<strong>${escapeHtml22(row.label)}</strong>
|
|
10772
|
+
<span>${escapeHtml22(formatStatus5(row.status))}</span>
|
|
10599
10773
|
</header>
|
|
10600
|
-
<p>${
|
|
10601
|
-
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${
|
|
10774
|
+
<p>${escapeHtml22(row.detail)}</p>
|
|
10775
|
+
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml22(remediation.href)}">${escapeHtml22(remediation.label)}</a>` : `<strong>${escapeHtml22(remediation.label)}</strong>`}<span>${escapeHtml22(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
|
|
10602
10776
|
<dl>${row.rows.map((item) => `<div>
|
|
10603
|
-
<dt>${
|
|
10604
|
-
<dd>${
|
|
10777
|
+
<dt>${escapeHtml22(item.label)}</dt>
|
|
10778
|
+
<dd>${escapeHtml22(item.value)}</dd>
|
|
10605
10779
|
</div>`).join("")}</dl>
|
|
10606
10780
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
10607
|
-
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${
|
|
10781
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml22(model.status)}">
|
|
10608
10782
|
<header class="absolute-voice-provider-contracts__header">
|
|
10609
|
-
<span class="absolute-voice-provider-contracts__eyebrow">${
|
|
10610
|
-
<strong class="absolute-voice-provider-contracts__label">${
|
|
10783
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml22(model.title)}</span>
|
|
10784
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml22(model.label)}</strong>
|
|
10611
10785
|
</header>
|
|
10612
|
-
<p class="absolute-voice-provider-contracts__description">${
|
|
10786
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml22(model.description)}</p>
|
|
10613
10787
|
${rows}
|
|
10614
|
-
${model.error ? `<p class="absolute-voice-provider-contracts__error">${
|
|
10788
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml22(model.error)}</p>` : ""}
|
|
10615
10789
|
</section>`;
|
|
10616
10790
|
};
|
|
10617
10791
|
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}`;
|
|
@@ -10652,9 +10826,9 @@ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-co
|
|
|
10652
10826
|
});
|
|
10653
10827
|
};
|
|
10654
10828
|
// src/client/turnQualityWidget.ts
|
|
10655
|
-
var
|
|
10656
|
-
var
|
|
10657
|
-
var
|
|
10829
|
+
var DEFAULT_TITLE15 = "Turn Quality";
|
|
10830
|
+
var DEFAULT_DESCRIPTION15 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
10831
|
+
var escapeHtml23 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10658
10832
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
10659
10833
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
10660
10834
|
var getTurnDetail = (turn) => {
|
|
@@ -10692,37 +10866,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
10692
10866
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
10693
10867
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
10694
10868
|
return {
|
|
10695
|
-
description: options.description ??
|
|
10869
|
+
description: options.description ?? DEFAULT_DESCRIPTION15,
|
|
10696
10870
|
error: snapshot.error,
|
|
10697
10871
|
isLoading: snapshot.isLoading,
|
|
10698
10872
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
10699
10873
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
10700
|
-
title: options.title ??
|
|
10874
|
+
title: options.title ?? DEFAULT_TITLE15,
|
|
10701
10875
|
turns,
|
|
10702
10876
|
updatedAt: snapshot.updatedAt
|
|
10703
10877
|
};
|
|
10704
10878
|
};
|
|
10705
10879
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
10706
10880
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
10707
|
-
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--${
|
|
10881
|
+
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--${escapeHtml23(turn.status)}">
|
|
10708
10882
|
<header>
|
|
10709
|
-
<strong>${
|
|
10710
|
-
<span>${
|
|
10883
|
+
<strong>${escapeHtml23(turn.label)}</strong>
|
|
10884
|
+
<span>${escapeHtml23(turn.status)}</span>
|
|
10711
10885
|
</header>
|
|
10712
|
-
<p>${
|
|
10886
|
+
<p>${escapeHtml23(turn.detail)}</p>
|
|
10713
10887
|
<dl>${turn.rows.map((row) => `<div>
|
|
10714
|
-
<dt>${
|
|
10715
|
-
<dd>${
|
|
10888
|
+
<dt>${escapeHtml23(row.label)}</dt>
|
|
10889
|
+
<dd>${escapeHtml23(row.value)}</dd>
|
|
10716
10890
|
</div>`).join("")}</dl>
|
|
10717
10891
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
10718
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
10892
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml23(model.status)}">
|
|
10719
10893
|
<header class="absolute-voice-turn-quality__header">
|
|
10720
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
10721
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
10894
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml23(model.title)}</span>
|
|
10895
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml23(model.label)}</strong>
|
|
10722
10896
|
</header>
|
|
10723
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
10897
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml23(model.description)}</p>
|
|
10724
10898
|
${turns}
|
|
10725
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
10899
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml23(model.error)}</p>` : ""}
|
|
10726
10900
|
</section>`;
|
|
10727
10901
|
};
|
|
10728
10902
|
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}`;
|
|
@@ -10763,10 +10937,10 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
10763
10937
|
});
|
|
10764
10938
|
};
|
|
10765
10939
|
// src/client/turnLatencyWidget.ts
|
|
10766
|
-
var
|
|
10767
|
-
var
|
|
10940
|
+
var DEFAULT_TITLE16 = "Turn Latency";
|
|
10941
|
+
var DEFAULT_DESCRIPTION16 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
10768
10942
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
10769
|
-
var
|
|
10943
|
+
var escapeHtml24 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10770
10944
|
var formatMs3 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
10771
10945
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
10772
10946
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -10780,39 +10954,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
10780
10954
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
10781
10955
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
10782
10956
|
return {
|
|
10783
|
-
description: options.description ??
|
|
10957
|
+
description: options.description ?? DEFAULT_DESCRIPTION16,
|
|
10784
10958
|
error: snapshot.error,
|
|
10785
10959
|
isLoading: snapshot.isLoading,
|
|
10786
10960
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs3(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
10787
10961
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
10788
10962
|
showProofAction: Boolean(options.proofPath),
|
|
10789
10963
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
10790
|
-
title: options.title ??
|
|
10964
|
+
title: options.title ?? DEFAULT_TITLE16,
|
|
10791
10965
|
turns,
|
|
10792
10966
|
updatedAt: snapshot.updatedAt
|
|
10793
10967
|
};
|
|
10794
10968
|
};
|
|
10795
10969
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
10796
10970
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
10797
|
-
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--${
|
|
10971
|
+
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--${escapeHtml24(turn.status)}">
|
|
10798
10972
|
<header>
|
|
10799
|
-
<strong>${
|
|
10800
|
-
<span>${
|
|
10973
|
+
<strong>${escapeHtml24(turn.label)}</strong>
|
|
10974
|
+
<span>${escapeHtml24(turn.status)}</span>
|
|
10801
10975
|
</header>
|
|
10802
10976
|
<dl>${turn.rows.map((row) => `<div>
|
|
10803
|
-
<dt>${
|
|
10804
|
-
<dd>${
|
|
10977
|
+
<dt>${escapeHtml24(row.label)}</dt>
|
|
10978
|
+
<dd>${escapeHtml24(row.value)}</dd>
|
|
10805
10979
|
</div>`).join("")}</dl>
|
|
10806
10980
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
10807
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
10981
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml24(model.status)}">
|
|
10808
10982
|
<header class="absolute-voice-turn-latency__header">
|
|
10809
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
10810
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
10983
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml24(model.title)}</span>
|
|
10984
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml24(model.label)}</strong>
|
|
10811
10985
|
</header>
|
|
10812
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
10813
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
10986
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml24(model.description)}</p>
|
|
10987
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml24(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
10814
10988
|
${turns}
|
|
10815
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
10989
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml24(model.error)}</p>` : ""}
|
|
10816
10990
|
</section>`;
|
|
10817
10991
|
};
|
|
10818
10992
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -10862,9 +11036,9 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
10862
11036
|
});
|
|
10863
11037
|
};
|
|
10864
11038
|
// src/client/traceTimelineWidget.ts
|
|
10865
|
-
var
|
|
10866
|
-
var
|
|
10867
|
-
var
|
|
11039
|
+
var DEFAULT_TITLE17 = "Voice Traces";
|
|
11040
|
+
var DEFAULT_DESCRIPTION17 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
11041
|
+
var escapeHtml25 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10868
11042
|
var formatMs4 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
10869
11043
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
10870
11044
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -10880,13 +11054,13 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
10880
11054
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
10881
11055
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
10882
11056
|
return {
|
|
10883
|
-
description: options.description ??
|
|
11057
|
+
description: options.description ?? DEFAULT_DESCRIPTION17,
|
|
10884
11058
|
error: snapshot.error,
|
|
10885
11059
|
isLoading: snapshot.isLoading,
|
|
10886
11060
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
10887
11061
|
sessions,
|
|
10888
11062
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
10889
|
-
title: options.title ??
|
|
11063
|
+
title: options.title ?? DEFAULT_TITLE17,
|
|
10890
11064
|
updatedAt: snapshot.updatedAt
|
|
10891
11065
|
};
|
|
10892
11066
|
};
|
|
@@ -10894,27 +11068,27 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
|
10894
11068
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
10895
11069
|
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
|
|
10896
11070
|
const supportLinks = [
|
|
10897
|
-
`<a href="${
|
|
10898
|
-
session.operationsRecordHref ? `<a href="${
|
|
10899
|
-
session.incidentBundleHref ? `<a href="${
|
|
11071
|
+
`<a href="${escapeHtml25(session.detailHref)}">Open timeline</a>`,
|
|
11072
|
+
session.operationsRecordHref ? `<a href="${escapeHtml25(session.operationsRecordHref)}">Open operations record</a>` : undefined,
|
|
11073
|
+
session.incidentBundleHref ? `<a href="${escapeHtml25(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
|
|
10900
11074
|
].filter(Boolean).join("");
|
|
10901
|
-
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${
|
|
11075
|
+
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml25(session.status)}">
|
|
10902
11076
|
<header>
|
|
10903
|
-
<strong>${
|
|
10904
|
-
<span>${
|
|
11077
|
+
<strong>${escapeHtml25(session.sessionId)}</strong>
|
|
11078
|
+
<span>${escapeHtml25(session.status)}</span>
|
|
10905
11079
|
</header>
|
|
10906
|
-
<p>${
|
|
11080
|
+
<p>${escapeHtml25(session.label)} \xB7 ${escapeHtml25(session.durationLabel)} \xB7 ${escapeHtml25(session.providerLabel)}</p>
|
|
10907
11081
|
<p class="absolute-voice-trace-timeline__actions">${supportLinks}</p>
|
|
10908
11082
|
</article>`;
|
|
10909
11083
|
}).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
10910
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
11084
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml25(model.status)}">
|
|
10911
11085
|
<header class="absolute-voice-trace-timeline__header">
|
|
10912
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
10913
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
11086
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml25(model.title)}</span>
|
|
11087
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml25(model.label)}</strong>
|
|
10914
11088
|
</header>
|
|
10915
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
11089
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml25(model.description)}</p>
|
|
10916
11090
|
${sessions}
|
|
10917
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
11091
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml25(model.error)}</p>` : ""}
|
|
10918
11092
|
</section>`;
|
|
10919
11093
|
};
|
|
10920
11094
|
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}`;
|
|
@@ -10960,9 +11134,9 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
|
|
|
10960
11134
|
});
|
|
10961
11135
|
};
|
|
10962
11136
|
// src/client/agentSquadStatusWidget.ts
|
|
10963
|
-
var
|
|
10964
|
-
var
|
|
10965
|
-
var
|
|
11137
|
+
var DEFAULT_TITLE18 = "Voice Agent Squad";
|
|
11138
|
+
var DEFAULT_DESCRIPTION18 = "Current specialist and recent handoffs from your self-hosted voice traces.";
|
|
11139
|
+
var escapeHtml26 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10966
11140
|
var labelFor = (current) => {
|
|
10967
11141
|
if (!current)
|
|
10968
11142
|
return "Waiting for specialist activity";
|
|
@@ -10976,37 +11150,37 @@ var labelFor = (current) => {
|
|
|
10976
11150
|
};
|
|
10977
11151
|
var createVoiceAgentSquadStatusViewModel = (snapshot, options = {}) => ({
|
|
10978
11152
|
current: snapshot.report.current,
|
|
10979
|
-
description: options.description ??
|
|
11153
|
+
description: options.description ?? DEFAULT_DESCRIPTION18,
|
|
10980
11154
|
error: snapshot.error,
|
|
10981
11155
|
isLoading: snapshot.isLoading,
|
|
10982
11156
|
label: snapshot.error ? "Unavailable" : labelFor(snapshot.report.current),
|
|
10983
11157
|
sessionCount: snapshot.report.sessionCount,
|
|
10984
11158
|
sessions: snapshot.report.sessions,
|
|
10985
|
-
title: options.title ??
|
|
11159
|
+
title: options.title ?? DEFAULT_TITLE18,
|
|
10986
11160
|
updatedAt: snapshot.updatedAt
|
|
10987
11161
|
});
|
|
10988
11162
|
var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
|
|
10989
11163
|
const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
|
|
10990
11164
|
const current = model.current;
|
|
10991
11165
|
const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
|
|
10992
|
-
<span>${
|
|
10993
|
-
<strong>${
|
|
10994
|
-
<em>${
|
|
10995
|
-
${session.summary || session.reason ? `<p>${
|
|
11166
|
+
<span>${escapeHtml26(session.sessionId)}</span>
|
|
11167
|
+
<strong>${escapeHtml26(session.targetAgentId ?? "none")}</strong>
|
|
11168
|
+
<em>${escapeHtml26(session.status)}</em>
|
|
11169
|
+
${session.summary || session.reason ? `<p>${escapeHtml26(session.summary ?? session.reason ?? "")}</p>` : ""}
|
|
10996
11170
|
</li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
|
|
10997
11171
|
return `<section class="absolute-voice-agent-squad-status">
|
|
10998
11172
|
<header>
|
|
10999
|
-
<span>${
|
|
11000
|
-
<strong>${
|
|
11173
|
+
<span>${escapeHtml26(model.title)}</span>
|
|
11174
|
+
<strong>${escapeHtml26(model.label)}</strong>
|
|
11001
11175
|
</header>
|
|
11002
|
-
<p>${
|
|
11176
|
+
<p>${escapeHtml26(model.description)}</p>
|
|
11003
11177
|
<div>
|
|
11004
|
-
<span>Session</span><strong>${
|
|
11005
|
-
<span>From</span><strong>${
|
|
11006
|
-
<span>Status</span><strong>${
|
|
11178
|
+
<span>Session</span><strong>${escapeHtml26(current?.sessionId ?? "n/a")}</strong>
|
|
11179
|
+
<span>From</span><strong>${escapeHtml26(current?.fromAgentId ?? "n/a")}</strong>
|
|
11180
|
+
<span>Status</span><strong>${escapeHtml26(current?.status ?? "idle")}</strong>
|
|
11007
11181
|
</div>
|
|
11008
11182
|
<ul>${rows}</ul>
|
|
11009
|
-
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${
|
|
11183
|
+
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml26(model.error)}</p>` : ""}
|
|
11010
11184
|
</section>`;
|
|
11011
11185
|
};
|
|
11012
11186
|
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}`;
|
|
@@ -11151,6 +11325,7 @@ export {
|
|
|
11151
11325
|
renderVoiceOpsActionCenterHTML,
|
|
11152
11326
|
renderVoiceLiveOpsHTML,
|
|
11153
11327
|
renderVoiceDeliveryRuntimeHTML,
|
|
11328
|
+
renderVoiceCallDebuggerLaunchHTML,
|
|
11154
11329
|
renderVoiceAgentSquadStatusHTML,
|
|
11155
11330
|
recordVoiceOpsActionResult,
|
|
11156
11331
|
postVoiceLiveOpsAction,
|
|
@@ -11173,6 +11348,7 @@ export {
|
|
|
11173
11348
|
mountVoiceOpsActionCenter,
|
|
11174
11349
|
mountVoiceLiveOps,
|
|
11175
11350
|
mountVoiceDeliveryRuntime,
|
|
11351
|
+
mountVoiceCallDebuggerLaunch,
|
|
11176
11352
|
mountVoiceAgentSquadStatus,
|
|
11177
11353
|
getVoiceTurnQualityCSS,
|
|
11178
11354
|
getVoiceTraceTimelineCSS,
|
|
@@ -11210,6 +11386,7 @@ export {
|
|
|
11210
11386
|
fetchVoiceOpsActionHistory,
|
|
11211
11387
|
fetchVoiceDeliveryRuntime,
|
|
11212
11388
|
fetchVoiceCampaignDialerProofStatus,
|
|
11389
|
+
fetchVoiceCallDebugger,
|
|
11213
11390
|
defineVoiceTurnQualityElement,
|
|
11214
11391
|
defineVoiceTurnLatencyElement,
|
|
11215
11392
|
defineVoiceTraceTimelineElement,
|
|
@@ -11228,6 +11405,7 @@ export {
|
|
|
11228
11405
|
defineVoiceOpsActionCenterElement,
|
|
11229
11406
|
defineVoiceLiveOpsElement,
|
|
11230
11407
|
defineVoiceDeliveryRuntimeElement,
|
|
11408
|
+
defineVoiceCallDebuggerLaunchElement,
|
|
11231
11409
|
defineVoiceAgentSquadStatusElement,
|
|
11232
11410
|
decodeVoiceAudioChunk,
|
|
11233
11411
|
createVoiceWorkflowStatusStore,
|
|
@@ -11274,6 +11452,8 @@ export {
|
|
|
11274
11452
|
createVoiceController,
|
|
11275
11453
|
createVoiceConnection,
|
|
11276
11454
|
createVoiceCampaignDialerProofStore,
|
|
11455
|
+
createVoiceCallDebuggerStore,
|
|
11456
|
+
createVoiceCallDebuggerLaunchViewModel,
|
|
11277
11457
|
createVoiceBrowserMediaReporter,
|
|
11278
11458
|
createVoiceBargeInMonitor,
|
|
11279
11459
|
createVoiceAudioPlayer,
|