@absolutejs/voice 0.0.22-beta.353 → 0.0.22-beta.354
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/client/index.d.ts +3 -0
- package/dist/client/index.js +346 -203
- package/dist/client/profileSwitchRecommendation.d.ts +19 -0
- package/dist/client/profileSwitchRecommendationWidget.d.ts +12 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +67 -0
- package/dist/profileSwitchRecommendation.d.ts +38 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -3034,6 +3034,80 @@ var createVoiceProfileComparisonStore = (path = "/api/voice/real-call-profile-hi
|
|
|
3034
3034
|
}
|
|
3035
3035
|
};
|
|
3036
3036
|
};
|
|
3037
|
+
// src/client/profileSwitchRecommendation.ts
|
|
3038
|
+
var fetchVoiceProfileSwitchRecommendation = async (path = "/api/voice/profile-switch-recommendation", options = {}) => {
|
|
3039
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3040
|
+
const response = await fetchImpl(path);
|
|
3041
|
+
if (!response.ok) {
|
|
3042
|
+
throw new Error(`Voice profile switch recommendation failed: HTTP ${response.status}`);
|
|
3043
|
+
}
|
|
3044
|
+
return await response.json();
|
|
3045
|
+
};
|
|
3046
|
+
var createVoiceProfileSwitchRecommendationStore = (path = "/api/voice/profile-switch-recommendation", options = {}) => {
|
|
3047
|
+
const listeners = new Set;
|
|
3048
|
+
let closed = false;
|
|
3049
|
+
let timer;
|
|
3050
|
+
let snapshot = {
|
|
3051
|
+
error: null,
|
|
3052
|
+
isLoading: false
|
|
3053
|
+
};
|
|
3054
|
+
const emit = () => {
|
|
3055
|
+
for (const listener of listeners) {
|
|
3056
|
+
listener();
|
|
3057
|
+
}
|
|
3058
|
+
};
|
|
3059
|
+
const refresh = async () => {
|
|
3060
|
+
if (closed) {
|
|
3061
|
+
return snapshot.recommendation;
|
|
3062
|
+
}
|
|
3063
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
3064
|
+
emit();
|
|
3065
|
+
try {
|
|
3066
|
+
const recommendation = await fetchVoiceProfileSwitchRecommendation(path, options);
|
|
3067
|
+
snapshot = {
|
|
3068
|
+
error: null,
|
|
3069
|
+
isLoading: false,
|
|
3070
|
+
recommendation,
|
|
3071
|
+
updatedAt: Date.now()
|
|
3072
|
+
};
|
|
3073
|
+
emit();
|
|
3074
|
+
return recommendation;
|
|
3075
|
+
} catch (error) {
|
|
3076
|
+
snapshot = {
|
|
3077
|
+
...snapshot,
|
|
3078
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3079
|
+
isLoading: false
|
|
3080
|
+
};
|
|
3081
|
+
emit();
|
|
3082
|
+
throw error;
|
|
3083
|
+
}
|
|
3084
|
+
};
|
|
3085
|
+
const close = () => {
|
|
3086
|
+
closed = true;
|
|
3087
|
+
if (timer) {
|
|
3088
|
+
clearInterval(timer);
|
|
3089
|
+
timer = undefined;
|
|
3090
|
+
}
|
|
3091
|
+
listeners.clear();
|
|
3092
|
+
};
|
|
3093
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
3094
|
+
timer = setInterval(() => {
|
|
3095
|
+
refresh().catch(() => {});
|
|
3096
|
+
}, options.intervalMs);
|
|
3097
|
+
}
|
|
3098
|
+
return {
|
|
3099
|
+
close,
|
|
3100
|
+
getServerSnapshot: () => snapshot,
|
|
3101
|
+
getSnapshot: () => snapshot,
|
|
3102
|
+
refresh,
|
|
3103
|
+
subscribe: (listener) => {
|
|
3104
|
+
listeners.add(listener);
|
|
3105
|
+
return () => {
|
|
3106
|
+
listeners.delete(listener);
|
|
3107
|
+
};
|
|
3108
|
+
}
|
|
3109
|
+
};
|
|
3110
|
+
};
|
|
3037
3111
|
// src/client/readinessFailures.ts
|
|
3038
3112
|
var fetchVoiceReadinessFailures = async (path = "/api/production-readiness", options = {}) => {
|
|
3039
3113
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -5071,14 +5145,77 @@ var defineVoiceProfileComparisonElement = (tagName = "absolute-voice-profile-com
|
|
|
5071
5145
|
}
|
|
5072
5146
|
});
|
|
5073
5147
|
};
|
|
5148
|
+
// src/client/profileSwitchRecommendationWidget.ts
|
|
5149
|
+
var DEFAULT_TITLE5 = "Profile Switch Recommendation";
|
|
5150
|
+
var DEFAULT_DESCRIPTION5 = "Compares the current session against measured profile evidence and recommends whether to switch stacks.";
|
|
5151
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5152
|
+
var formatRoute = (routes) => routes ? Object.entries(routes).map(([role, provider]) => `${role}: ${provider}`).join(", ") : "No route";
|
|
5153
|
+
var renderVoiceProfileSwitchRecommendationHTML = (snapshot, options = {}) => {
|
|
5154
|
+
const recommendation = snapshot.recommendation;
|
|
5155
|
+
const status = snapshot.error ? "error" : recommendation ? recommendation.status : snapshot.isLoading ? "loading" : "empty";
|
|
5156
|
+
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";
|
|
5157
|
+
const body = recommendation ? `<div class="absolute-voice-profile-switch__body">
|
|
5158
|
+
<p><strong>Current:</strong> ${escapeHtml6(recommendation.currentProfile?.label ?? recommendation.currentProfile?.profileId ?? "Unknown")}</p>
|
|
5159
|
+
<p><strong>Recommended:</strong> ${escapeHtml6(recommendation.recommendedProfile?.label ?? recommendation.recommendedProfile?.profileId ?? "None")}</p>
|
|
5160
|
+
<p><strong>Routes:</strong> ${escapeHtml6(formatRoute(recommendation.recommendedProfile?.providerRoutes))}</p>
|
|
5161
|
+
<ul>${recommendation.reasons.map((reason) => `<li>${escapeHtml6(reason)}</li>`).join("")}</ul>
|
|
5162
|
+
<em>${escapeHtml6(recommendation.nextMove)}</em>
|
|
5163
|
+
</div>` : `<p class="absolute-voice-profile-switch__empty">${escapeHtml6(snapshot.error ?? "Run session traffic to populate a recommendation.")}</p>`;
|
|
5164
|
+
return `<section class="absolute-voice-profile-switch absolute-voice-profile-switch--${escapeHtml6(status)}">
|
|
5165
|
+
<header class="absolute-voice-profile-switch__header">
|
|
5166
|
+
<span class="absolute-voice-profile-switch__eyebrow">${escapeHtml6(options.title ?? DEFAULT_TITLE5)}</span>
|
|
5167
|
+
<strong class="absolute-voice-profile-switch__label">${escapeHtml6(label)}</strong>
|
|
5168
|
+
</header>
|
|
5169
|
+
<p class="absolute-voice-profile-switch__description">${escapeHtml6(options.description ?? DEFAULT_DESCRIPTION5)}</p>
|
|
5170
|
+
${body}
|
|
5171
|
+
${snapshot.error ? `<p class="absolute-voice-profile-switch__error">${escapeHtml6(snapshot.error)}</p>` : ""}
|
|
5172
|
+
</section>`;
|
|
5173
|
+
};
|
|
5174
|
+
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}`;
|
|
5175
|
+
var mountVoiceProfileSwitchRecommendation = (element, path = "/api/voice/profile-switch-recommendation", options = {}) => {
|
|
5176
|
+
const store = createVoiceProfileSwitchRecommendationStore(path, options);
|
|
5177
|
+
const render = () => {
|
|
5178
|
+
element.innerHTML = renderVoiceProfileSwitchRecommendationHTML(store.getSnapshot(), options);
|
|
5179
|
+
};
|
|
5180
|
+
const unsubscribe = store.subscribe(render);
|
|
5181
|
+
render();
|
|
5182
|
+
store.refresh().catch(() => {});
|
|
5183
|
+
return {
|
|
5184
|
+
close: () => {
|
|
5185
|
+
unsubscribe();
|
|
5186
|
+
store.close();
|
|
5187
|
+
},
|
|
5188
|
+
refresh: store.refresh
|
|
5189
|
+
};
|
|
5190
|
+
};
|
|
5191
|
+
var defineVoiceProfileSwitchRecommendationElement = (tagName = "absolute-voice-profile-switch") => {
|
|
5192
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
5193
|
+
return;
|
|
5194
|
+
}
|
|
5195
|
+
customElements.define(tagName, class AbsoluteVoiceProfileSwitchElement extends HTMLElement {
|
|
5196
|
+
mounted;
|
|
5197
|
+
connectedCallback() {
|
|
5198
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
5199
|
+
this.mounted = mountVoiceProfileSwitchRecommendation(this, this.getAttribute("path") ?? "/api/voice/profile-switch-recommendation", {
|
|
5200
|
+
description: this.getAttribute("description") ?? undefined,
|
|
5201
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
5202
|
+
title: this.getAttribute("title") ?? undefined
|
|
5203
|
+
});
|
|
5204
|
+
}
|
|
5205
|
+
disconnectedCallback() {
|
|
5206
|
+
this.mounted?.close();
|
|
5207
|
+
this.mounted = undefined;
|
|
5208
|
+
}
|
|
5209
|
+
});
|
|
5210
|
+
};
|
|
5074
5211
|
// src/client/readinessFailuresWidget.ts
|
|
5075
|
-
var
|
|
5076
|
-
var
|
|
5212
|
+
var DEFAULT_TITLE6 = "Readiness Gate Explanations";
|
|
5213
|
+
var DEFAULT_DESCRIPTION6 = "Structured reasons for calibrated production-readiness warnings and failures.";
|
|
5077
5214
|
var DEFAULT_LINKS4 = [
|
|
5078
5215
|
{ href: "/production-readiness", label: "Readiness page" },
|
|
5079
5216
|
{ href: "/voice/slo-readiness-thresholds", label: "Gate thresholds" }
|
|
5080
5217
|
];
|
|
5081
|
-
var
|
|
5218
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5082
5219
|
var formatExplanationValue = (value, unit) => {
|
|
5083
5220
|
if (value === undefined || value === null) {
|
|
5084
5221
|
return "n/a";
|
|
@@ -5106,36 +5243,36 @@ var createVoiceReadinessFailuresViewModel = (snapshot, options = {}) => {
|
|
|
5106
5243
|
const failures = snapshot.report?.checks.map(toFailureView).filter((value) => !!value) ?? [];
|
|
5107
5244
|
const hasOpenIssues = failures.length > 0;
|
|
5108
5245
|
return {
|
|
5109
|
-
description: options.description ??
|
|
5246
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
5110
5247
|
error: snapshot.error,
|
|
5111
5248
|
failures,
|
|
5112
5249
|
isLoading: snapshot.isLoading,
|
|
5113
5250
|
label: snapshot.error ? "Unavailable" : snapshot.report ? hasOpenIssues ? `${failures.length} calibrated gate issue(s)` : "No calibrated gate issues" : snapshot.isLoading ? "Checking" : "No readiness report",
|
|
5114
5251
|
links: options.links ?? DEFAULT_LINKS4,
|
|
5115
5252
|
status: snapshot.error ? "error" : snapshot.report ? hasOpenIssues ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
5116
|
-
title: options.title ??
|
|
5253
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
5117
5254
|
updatedAt: snapshot.updatedAt
|
|
5118
5255
|
};
|
|
5119
5256
|
};
|
|
5120
5257
|
var renderVoiceReadinessFailuresHTML = (snapshot, options = {}) => {
|
|
5121
5258
|
const model = createVoiceReadinessFailuresViewModel(snapshot, options);
|
|
5122
|
-
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--${
|
|
5123
|
-
<span>${
|
|
5124
|
-
<strong>${
|
|
5125
|
-
<p>Observed ${
|
|
5126
|
-
<p>${
|
|
5127
|
-
<p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${
|
|
5128
|
-
</article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ?
|
|
5129
|
-
const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${
|
|
5130
|
-
return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${
|
|
5259
|
+
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--${escapeHtml7(failure.status)}">
|
|
5260
|
+
<span>${escapeHtml7(failure.status.toUpperCase())}</span>
|
|
5261
|
+
<strong>${escapeHtml7(failure.label)}</strong>
|
|
5262
|
+
<p>Observed ${escapeHtml7(failure.observed)} against ${escapeHtml7(failure.thresholdLabel)} ${escapeHtml7(failure.threshold)}.</p>
|
|
5263
|
+
<p>${escapeHtml7(failure.remediation)}</p>
|
|
5264
|
+
<p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${escapeHtml7(failure.evidenceHref)}">Evidence</a>` : ""}${failure.sourceHref ? `<a href="${escapeHtml7(failure.sourceHref)}">Threshold source</a>` : ""}</p>
|
|
5265
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ? escapeHtml7(model.error) : "No calibrated readiness gate explanations are open."}</p>`;
|
|
5266
|
+
const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${escapeHtml7(link.href)}">${escapeHtml7(link.label)}</a>`).join("")}</p>` : "";
|
|
5267
|
+
return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${escapeHtml7(model.status)}">
|
|
5131
5268
|
<header class="absolute-voice-readiness-failures__header">
|
|
5132
|
-
<span class="absolute-voice-readiness-failures__eyebrow">${
|
|
5133
|
-
<strong class="absolute-voice-readiness-failures__label">${
|
|
5269
|
+
<span class="absolute-voice-readiness-failures__eyebrow">${escapeHtml7(model.title)}</span>
|
|
5270
|
+
<strong class="absolute-voice-readiness-failures__label">${escapeHtml7(model.label)}</strong>
|
|
5134
5271
|
</header>
|
|
5135
|
-
<p class="absolute-voice-readiness-failures__description">${
|
|
5272
|
+
<p class="absolute-voice-readiness-failures__description">${escapeHtml7(model.description)}</p>
|
|
5136
5273
|
${failures}
|
|
5137
5274
|
${links}
|
|
5138
|
-
${model.error ? `<p class="absolute-voice-readiness-failures__error">${
|
|
5275
|
+
${model.error ? `<p class="absolute-voice-readiness-failures__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
5139
5276
|
</section>`;
|
|
5140
5277
|
};
|
|
5141
5278
|
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}`;
|
|
@@ -5175,9 +5312,9 @@ var defineVoiceReadinessFailuresElement = (tagName = "absolute-voice-readiness-f
|
|
|
5175
5312
|
});
|
|
5176
5313
|
};
|
|
5177
5314
|
// src/client/opsActionCenterWidget.ts
|
|
5178
|
-
var
|
|
5179
|
-
var
|
|
5180
|
-
var
|
|
5315
|
+
var DEFAULT_TITLE7 = "Voice Ops Action Center";
|
|
5316
|
+
var DEFAULT_DESCRIPTION7 = "Run production voice proofs and operator actions from one primitive panel.";
|
|
5317
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5181
5318
|
var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
5182
5319
|
const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
|
|
5183
5320
|
return {
|
|
@@ -5188,29 +5325,29 @@ var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
|
5188
5325
|
isRunning: snapshot.runningActionId === action.id,
|
|
5189
5326
|
label: action.label
|
|
5190
5327
|
})),
|
|
5191
|
-
description: options.description ??
|
|
5328
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
5192
5329
|
error: snapshot.error,
|
|
5193
5330
|
isRunning: snapshot.isRunning,
|
|
5194
5331
|
label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
|
|
5195
5332
|
lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
|
|
5196
5333
|
status,
|
|
5197
|
-
title: options.title ??
|
|
5334
|
+
title: options.title ?? DEFAULT_TITLE7
|
|
5198
5335
|
};
|
|
5199
5336
|
};
|
|
5200
5337
|
var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
|
|
5201
5338
|
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
5202
|
-
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${
|
|
5203
|
-
${
|
|
5339
|
+
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml8(action.id)}"${action.disabled ? " disabled" : ""}>
|
|
5340
|
+
${escapeHtml8(action.isRunning ? "Working..." : action.label)}
|
|
5204
5341
|
</button>`).join("");
|
|
5205
|
-
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${
|
|
5342
|
+
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml8(model.status)}">
|
|
5206
5343
|
<header class="absolute-voice-ops-action-center__header">
|
|
5207
|
-
<span class="absolute-voice-ops-action-center__eyebrow">${
|
|
5208
|
-
<strong class="absolute-voice-ops-action-center__label">${
|
|
5344
|
+
<span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml8(model.title)}</span>
|
|
5345
|
+
<strong class="absolute-voice-ops-action-center__label">${escapeHtml8(model.label)}</strong>
|
|
5209
5346
|
</header>
|
|
5210
|
-
<p class="absolute-voice-ops-action-center__description">${
|
|
5347
|
+
<p class="absolute-voice-ops-action-center__description">${escapeHtml8(model.description)}</p>
|
|
5211
5348
|
<div class="absolute-voice-ops-action-center__actions">${actions}</div>
|
|
5212
|
-
<p class="absolute-voice-ops-action-center__result">${
|
|
5213
|
-
${model.error ? `<p class="absolute-voice-ops-action-center__error">${
|
|
5349
|
+
<p class="absolute-voice-ops-action-center__result">${escapeHtml8(model.lastResultLabel)}</p>
|
|
5350
|
+
${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
5214
5351
|
</section>`;
|
|
5215
5352
|
};
|
|
5216
5353
|
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}`;
|
|
@@ -5811,7 +5948,7 @@ var exportVoiceTrace = async (input) => {
|
|
|
5811
5948
|
};
|
|
5812
5949
|
};
|
|
5813
5950
|
var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
5814
|
-
var
|
|
5951
|
+
var escapeHtml9 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
5815
5952
|
var formatTraceValue = (value) => {
|
|
5816
5953
|
if (value === undefined || value === null) {
|
|
5817
5954
|
return "";
|
|
@@ -6091,10 +6228,10 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
6091
6228
|
const offset = summary.startedAt === undefined ? event.at : Math.max(0, event.at - summary.startedAt);
|
|
6092
6229
|
return [
|
|
6093
6230
|
"<tr>",
|
|
6094
|
-
`<td>${
|
|
6095
|
-
`<td>${
|
|
6096
|
-
`<td>${
|
|
6097
|
-
`<td><code>${
|
|
6231
|
+
`<td>${escapeHtml9(String(offset))}</td>`,
|
|
6232
|
+
`<td>${escapeHtml9(event.type)}</td>`,
|
|
6233
|
+
`<td>${escapeHtml9(event.turnId ?? "")}</td>`,
|
|
6234
|
+
`<td><code>${escapeHtml9(JSON.stringify(event.payload))}</code></td>`,
|
|
6098
6235
|
"</tr>"
|
|
6099
6236
|
].join("");
|
|
6100
6237
|
}).join(`
|
|
@@ -6105,7 +6242,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
6105
6242
|
"<head>",
|
|
6106
6243
|
'<meta charset="utf-8" />',
|
|
6107
6244
|
'<meta name="viewport" content="width=device-width, initial-scale=1" />',
|
|
6108
|
-
`<title>${
|
|
6245
|
+
`<title>${escapeHtml9(options.title ?? "Voice Trace")}</title>`,
|
|
6109
6246
|
"<style>",
|
|
6110
6247
|
"body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;line-height:1.45;background:#f8f7f2;color:#181713}",
|
|
6111
6248
|
"main{max-width:1100px;margin:auto}",
|
|
@@ -6119,7 +6256,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
6119
6256
|
"</style>",
|
|
6120
6257
|
"</head>",
|
|
6121
6258
|
"<body><main>",
|
|
6122
|
-
`<h1>${
|
|
6259
|
+
`<h1>${escapeHtml9(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</h1>`,
|
|
6123
6260
|
`<p class="${evaluation.pass ? "pass" : "fail"}">QA: ${evaluation.pass ? "pass" : "fail"}</p>`,
|
|
6124
6261
|
'<section class="summary">',
|
|
6125
6262
|
`<div class="card"><strong>Events</strong><br>${summary.eventCount}</div>`,
|
|
@@ -6133,7 +6270,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
6133
6270
|
eventRows,
|
|
6134
6271
|
"</tbody></table>",
|
|
6135
6272
|
"<h2>Markdown Export</h2>",
|
|
6136
|
-
`<pre>${
|
|
6273
|
+
`<pre>${escapeHtml9(markdown)}</pre>`,
|
|
6137
6274
|
"</main></body></html>"
|
|
6138
6275
|
].join(`
|
|
6139
6276
|
`);
|
|
@@ -6489,7 +6626,7 @@ var ACTION_LABELS = {
|
|
|
6489
6626
|
"resume-assistant": "Resume assistant",
|
|
6490
6627
|
tag: "Tag"
|
|
6491
6628
|
};
|
|
6492
|
-
var
|
|
6629
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6493
6630
|
var createVoiceLiveOpsInput = (action, input) => ({
|
|
6494
6631
|
action,
|
|
6495
6632
|
assignee: input.assignee,
|
|
@@ -6500,17 +6637,17 @@ var createVoiceLiveOpsInput = (action, input) => ({
|
|
|
6500
6637
|
var renderVoiceLiveOpsHTML = (snapshot, options = {}) => {
|
|
6501
6638
|
const sessionId = options.getSessionId?.() ?? "";
|
|
6502
6639
|
const disabled = snapshot.isRunning || !sessionId;
|
|
6503
|
-
const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${
|
|
6504
|
-
const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${
|
|
6640
|
+
const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml10(action)}"${disabled ? " disabled" : ""}>${escapeHtml10(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
|
|
6641
|
+
const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml10(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml10(snapshot.lastResult.action)}. Control: ${escapeHtml10(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
|
|
6505
6642
|
return `<section class="absolute-voice-live-ops">
|
|
6506
6643
|
<header class="absolute-voice-live-ops__header">
|
|
6507
|
-
<span>${
|
|
6508
|
-
<strong>${
|
|
6644
|
+
<span>${escapeHtml10(options.title ?? "Live Ops")}</span>
|
|
6645
|
+
<strong>${escapeHtml10(sessionId || "No active session")}</strong>
|
|
6509
6646
|
</header>
|
|
6510
|
-
<p class="absolute-voice-live-ops__description">${
|
|
6511
|
-
<label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${
|
|
6512
|
-
<label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${
|
|
6513
|
-
<label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${
|
|
6647
|
+
<p class="absolute-voice-live-ops__description">${escapeHtml10(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
|
|
6648
|
+
<label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml10(options.defaultAssignee ?? "operator")}" /></label>
|
|
6649
|
+
<label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml10(options.defaultTag ?? "live-ops")}" /></label>
|
|
6650
|
+
<label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml10(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
|
|
6514
6651
|
<div class="absolute-voice-live-ops__actions">${actions}</div>
|
|
6515
6652
|
${result}
|
|
6516
6653
|
</section>`;
|
|
@@ -6597,16 +6734,16 @@ var defineVoiceLiveOpsElement = (tagName = "absolute-voice-live-ops", options =
|
|
|
6597
6734
|
});
|
|
6598
6735
|
};
|
|
6599
6736
|
// src/client/opsActionHistoryWidget.ts
|
|
6600
|
-
var
|
|
6737
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6601
6738
|
var renderVoiceOpsActionHistoryWidgetHTML = (snapshot, options = {}) => {
|
|
6602
6739
|
const report = snapshot.report;
|
|
6603
6740
|
const entries = (report?.entries ?? []).slice(0, options.limit ?? 5);
|
|
6604
|
-
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${
|
|
6741
|
+
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${escapeHtml11(entry.actionId)}</span><strong>${escapeHtml11(entry.ok ? "Success" : "Failed")}</strong><small>${escapeHtml11(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</small></li>`).join("");
|
|
6605
6742
|
return `<section class="absolute-voice-ops-action-history">
|
|
6606
|
-
<header><span>Operator proof</span><strong>${
|
|
6743
|
+
<header><span>Operator proof</span><strong>${escapeHtml11(options.title ?? "Action History")}</strong></header>
|
|
6607
6744
|
<p>${String(report?.total ?? 0)} action(s), ${String(report?.failed ?? 0)} failed.</p>
|
|
6608
6745
|
<ul>${rows || "<li>No operator actions recorded yet.</li>"}</ul>
|
|
6609
|
-
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${
|
|
6746
|
+
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${escapeHtml11(snapshot.error)}</p>` : ""}
|
|
6610
6747
|
</section>`;
|
|
6611
6748
|
};
|
|
6612
6749
|
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}`;
|
|
@@ -6627,9 +6764,9 @@ var mountVoiceOpsActionHistory = (element, path = "/api/voice/ops-actions/histor
|
|
|
6627
6764
|
};
|
|
6628
6765
|
};
|
|
6629
6766
|
// src/client/deliveryRuntimeWidget.ts
|
|
6630
|
-
var
|
|
6631
|
-
var
|
|
6632
|
-
var
|
|
6767
|
+
var DEFAULT_TITLE8 = "Voice Delivery Runtime";
|
|
6768
|
+
var DEFAULT_DESCRIPTION8 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
6769
|
+
var escapeHtml12 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6633
6770
|
var createSurface = (id, summary) => {
|
|
6634
6771
|
if (!summary) {
|
|
6635
6772
|
return {
|
|
@@ -6663,7 +6800,7 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
6663
6800
|
];
|
|
6664
6801
|
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
6665
6802
|
return {
|
|
6666
|
-
description: options.description ??
|
|
6803
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
6667
6804
|
error: snapshot.error,
|
|
6668
6805
|
actionError: snapshot.actionError,
|
|
6669
6806
|
actionStatus: snapshot.actionStatus,
|
|
@@ -6672,32 +6809,32 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
6672
6809
|
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
6673
6810
|
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
6674
6811
|
surfaces,
|
|
6675
|
-
title: options.title ??
|
|
6812
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
6676
6813
|
updatedAt: snapshot.updatedAt
|
|
6677
6814
|
};
|
|
6678
6815
|
};
|
|
6679
6816
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
6680
6817
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
6681
|
-
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${
|
|
6682
|
-
<span>${
|
|
6683
|
-
<strong>${
|
|
6818
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml12(surface.status)}">
|
|
6819
|
+
<span>${escapeHtml12(surface.label)}</span>
|
|
6820
|
+
<strong>${escapeHtml12(surface.detail)}</strong>
|
|
6684
6821
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
6685
6822
|
</li>`).join("");
|
|
6686
6823
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
6687
6824
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
6688
6825
|
<button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
|
|
6689
6826
|
</div>`;
|
|
6690
|
-
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
6691
|
-
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${
|
|
6827
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml12(model.actionError)}</p>` : "";
|
|
6828
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml12(model.status)}">
|
|
6692
6829
|
<header class="absolute-voice-delivery-runtime__header">
|
|
6693
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
6694
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
6830
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml12(model.title)}</span>
|
|
6831
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml12(model.label)}</strong>
|
|
6695
6832
|
</header>
|
|
6696
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
6833
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml12(model.description)}</p>
|
|
6697
6834
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
6698
6835
|
${actions}
|
|
6699
6836
|
${actionError}
|
|
6700
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
6837
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml12(model.error)}</p>` : ""}
|
|
6701
6838
|
</section>`;
|
|
6702
6839
|
};
|
|
6703
6840
|
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}`;
|
|
@@ -6833,9 +6970,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
6833
6970
|
};
|
|
6834
6971
|
};
|
|
6835
6972
|
// src/client/routingStatusWidget.ts
|
|
6836
|
-
var
|
|
6837
|
-
var
|
|
6838
|
-
var
|
|
6973
|
+
var DEFAULT_TITLE9 = "Voice Routing";
|
|
6974
|
+
var DEFAULT_DESCRIPTION9 = "Latest provider routing decision from the self-hosted trace store.";
|
|
6975
|
+
var escapeHtml13 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6839
6976
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
6840
6977
|
var formatProviderRoutes2 = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
|
|
6841
6978
|
var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
|
|
@@ -6904,35 +7041,35 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
6904
7041
|
return {
|
|
6905
7042
|
activeStack,
|
|
6906
7043
|
decision,
|
|
6907
|
-
description: options.description ??
|
|
7044
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
6908
7045
|
error: snapshot.error,
|
|
6909
7046
|
isLoading: snapshot.isLoading,
|
|
6910
7047
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
6911
7048
|
rows,
|
|
6912
7049
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
6913
|
-
title: options.title ??
|
|
7050
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
6914
7051
|
updatedAt: snapshot.updatedAt
|
|
6915
7052
|
};
|
|
6916
7053
|
};
|
|
6917
7054
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
6918
7055
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
6919
7056
|
const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
|
|
6920
|
-
<span>${
|
|
6921
|
-
<strong>${
|
|
7057
|
+
<span>${escapeHtml13(item.label)}</span>
|
|
7058
|
+
<strong>${escapeHtml13(item.value)}</strong>
|
|
6922
7059
|
</div>`).join("")}</div>` : "";
|
|
6923
7060
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
6924
|
-
<span>${
|
|
6925
|
-
<strong>${
|
|
7061
|
+
<span>${escapeHtml13(row.label)}</span>
|
|
7062
|
+
<strong>${escapeHtml13(row.value)}</strong>
|
|
6926
7063
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
6927
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
7064
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml13(model.status)}">
|
|
6928
7065
|
<header class="absolute-voice-routing-status__header">
|
|
6929
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
6930
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
7066
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml13(model.title)}</span>
|
|
7067
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml13(model.label)}</strong>
|
|
6931
7068
|
</header>
|
|
6932
|
-
<p class="absolute-voice-routing-status__description">${
|
|
7069
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml13(model.description)}</p>
|
|
6933
7070
|
${activeStack}
|
|
6934
7071
|
${rows}
|
|
6935
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
7072
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml13(model.error)}</p>` : ""}
|
|
6936
7073
|
</section>`;
|
|
6937
7074
|
};
|
|
6938
7075
|
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}}`;
|
|
@@ -7731,7 +7868,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
7731
7868
|
};
|
|
7732
7869
|
};
|
|
7733
7870
|
// src/client/providerSimulationControlsWidget.ts
|
|
7734
|
-
var
|
|
7871
|
+
var escapeHtml14 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7735
7872
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
7736
7873
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
7737
7874
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -7751,18 +7888,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
7751
7888
|
};
|
|
7752
7889
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
7753
7890
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
7754
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
7755
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
7891
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml14(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml14(provider.provider)} ${escapeHtml14(formatKind(options.kind))} failure</button>`).join("");
|
|
7892
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml14(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml14(provider.provider)} recovered</button>`).join("");
|
|
7756
7893
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
7757
7894
|
<header class="absolute-voice-provider-simulation__header">
|
|
7758
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
7759
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
7895
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml14(model.title)}</span>
|
|
7896
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml14(model.label)}</strong>
|
|
7760
7897
|
</header>
|
|
7761
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
7762
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
7898
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml14(model.description)}</p>
|
|
7899
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml14(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
7763
7900
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
7764
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
7765
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
7901
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml14(snapshot.error)}</p>` : ""}
|
|
7902
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml14(model.resultText)}</pre>` : ""}
|
|
7766
7903
|
</section>`;
|
|
7767
7904
|
};
|
|
7768
7905
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -7827,9 +7964,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
7827
7964
|
});
|
|
7828
7965
|
};
|
|
7829
7966
|
// src/client/providerStatusWidget.ts
|
|
7830
|
-
var
|
|
7831
|
-
var
|
|
7832
|
-
var
|
|
7967
|
+
var DEFAULT_TITLE10 = "Voice Providers";
|
|
7968
|
+
var DEFAULT_DESCRIPTION10 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
7969
|
+
var escapeHtml15 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7833
7970
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
7834
7971
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
7835
7972
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -7873,37 +8010,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
7873
8010
|
const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
|
|
7874
8011
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
7875
8012
|
return {
|
|
7876
|
-
description: options.description ??
|
|
8013
|
+
description: options.description ?? DEFAULT_DESCRIPTION10,
|
|
7877
8014
|
error: snapshot.error,
|
|
7878
8015
|
isLoading: snapshot.isLoading,
|
|
7879
8016
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
7880
8017
|
providers,
|
|
7881
8018
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
7882
|
-
title: options.title ??
|
|
8019
|
+
title: options.title ?? DEFAULT_TITLE10,
|
|
7883
8020
|
updatedAt: snapshot.updatedAt
|
|
7884
8021
|
};
|
|
7885
8022
|
};
|
|
7886
8023
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
7887
8024
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
7888
|
-
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--${
|
|
8025
|
+
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--${escapeHtml15(provider.status)}">
|
|
7889
8026
|
<header>
|
|
7890
|
-
<strong>${
|
|
7891
|
-
<span>${
|
|
8027
|
+
<strong>${escapeHtml15(provider.label)}</strong>
|
|
8028
|
+
<span>${escapeHtml15(formatStatus2(provider.status))}</span>
|
|
7892
8029
|
</header>
|
|
7893
|
-
<p>${
|
|
8030
|
+
<p>${escapeHtml15(provider.detail)}</p>
|
|
7894
8031
|
<dl>${provider.rows.map((row) => `<div>
|
|
7895
|
-
<dt>${
|
|
7896
|
-
<dd>${
|
|
8032
|
+
<dt>${escapeHtml15(row.label)}</dt>
|
|
8033
|
+
<dd>${escapeHtml15(row.value)}</dd>
|
|
7897
8034
|
</div>`).join("")}</dl>
|
|
7898
8035
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
7899
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
8036
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml15(model.status)}">
|
|
7900
8037
|
<header class="absolute-voice-provider-status__header">
|
|
7901
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
7902
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
8038
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml15(model.title)}</span>
|
|
8039
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml15(model.label)}</strong>
|
|
7903
8040
|
</header>
|
|
7904
|
-
<p class="absolute-voice-provider-status__description">${
|
|
8041
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml15(model.description)}</p>
|
|
7905
8042
|
${providers}
|
|
7906
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
8043
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml15(model.error)}</p>` : ""}
|
|
7907
8044
|
</section>`;
|
|
7908
8045
|
};
|
|
7909
8046
|
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}`;
|
|
@@ -7944,9 +8081,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
7944
8081
|
});
|
|
7945
8082
|
};
|
|
7946
8083
|
// src/client/providerCapabilitiesWidget.ts
|
|
7947
|
-
var
|
|
7948
|
-
var
|
|
7949
|
-
var
|
|
8084
|
+
var DEFAULT_TITLE11 = "Provider Capabilities";
|
|
8085
|
+
var DEFAULT_DESCRIPTION11 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
8086
|
+
var escapeHtml16 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7950
8087
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
7951
8088
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
7952
8089
|
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -7990,36 +8127,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
7990
8127
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
7991
8128
|
return {
|
|
7992
8129
|
capabilities,
|
|
7993
|
-
description: options.description ??
|
|
8130
|
+
description: options.description ?? DEFAULT_DESCRIPTION11,
|
|
7994
8131
|
error: snapshot.error,
|
|
7995
8132
|
isLoading: snapshot.isLoading,
|
|
7996
8133
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
7997
8134
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
7998
|
-
title: options.title ??
|
|
8135
|
+
title: options.title ?? DEFAULT_TITLE11,
|
|
7999
8136
|
updatedAt: snapshot.updatedAt
|
|
8000
8137
|
};
|
|
8001
8138
|
};
|
|
8002
8139
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
8003
8140
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
8004
|
-
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--${
|
|
8141
|
+
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--${escapeHtml16(capability.status)}">
|
|
8005
8142
|
<header>
|
|
8006
|
-
<strong>${
|
|
8007
|
-
<span>${
|
|
8143
|
+
<strong>${escapeHtml16(capability.label)}</strong>
|
|
8144
|
+
<span>${escapeHtml16(formatStatus3(capability.status))}</span>
|
|
8008
8145
|
</header>
|
|
8009
|
-
<p>${
|
|
8146
|
+
<p>${escapeHtml16(capability.detail)}</p>
|
|
8010
8147
|
<dl>${capability.rows.map((row) => `<div>
|
|
8011
|
-
<dt>${
|
|
8012
|
-
<dd>${
|
|
8148
|
+
<dt>${escapeHtml16(row.label)}</dt>
|
|
8149
|
+
<dd>${escapeHtml16(row.value)}</dd>
|
|
8013
8150
|
</div>`).join("")}</dl>
|
|
8014
8151
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
8015
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
8152
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml16(model.status)}">
|
|
8016
8153
|
<header class="absolute-voice-provider-capabilities__header">
|
|
8017
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
8018
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
8154
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml16(model.title)}</span>
|
|
8155
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml16(model.label)}</strong>
|
|
8019
8156
|
</header>
|
|
8020
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
8157
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml16(model.description)}</p>
|
|
8021
8158
|
${capabilities}
|
|
8022
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
8159
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml16(model.error)}</p>` : ""}
|
|
8023
8160
|
</section>`;
|
|
8024
8161
|
};
|
|
8025
8162
|
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}`;
|
|
@@ -8060,9 +8197,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
8060
8197
|
});
|
|
8061
8198
|
};
|
|
8062
8199
|
// src/client/providerContractsWidget.ts
|
|
8063
|
-
var
|
|
8064
|
-
var
|
|
8065
|
-
var
|
|
8200
|
+
var DEFAULT_TITLE12 = "Provider Contracts";
|
|
8201
|
+
var DEFAULT_DESCRIPTION12 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
8202
|
+
var escapeHtml17 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8066
8203
|
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
8067
8204
|
var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
8068
8205
|
var contractDetail = (row) => {
|
|
@@ -8094,38 +8231,38 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
|
8094
8231
|
}));
|
|
8095
8232
|
const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
|
|
8096
8233
|
return {
|
|
8097
|
-
description: options.description ??
|
|
8234
|
+
description: options.description ?? DEFAULT_DESCRIPTION12,
|
|
8098
8235
|
error: snapshot.error,
|
|
8099
8236
|
isLoading: snapshot.isLoading,
|
|
8100
8237
|
label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
|
|
8101
8238
|
rows,
|
|
8102
8239
|
status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
8103
|
-
title: options.title ??
|
|
8240
|
+
title: options.title ?? DEFAULT_TITLE12,
|
|
8104
8241
|
updatedAt: snapshot.updatedAt
|
|
8105
8242
|
};
|
|
8106
8243
|
};
|
|
8107
8244
|
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
8108
8245
|
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
8109
|
-
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--${
|
|
8246
|
+
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--${escapeHtml17(row.status)}">
|
|
8110
8247
|
<header>
|
|
8111
|
-
<strong>${
|
|
8112
|
-
<span>${
|
|
8248
|
+
<strong>${escapeHtml17(row.label)}</strong>
|
|
8249
|
+
<span>${escapeHtml17(formatStatus4(row.status))}</span>
|
|
8113
8250
|
</header>
|
|
8114
|
-
<p>${
|
|
8115
|
-
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${
|
|
8251
|
+
<p>${escapeHtml17(row.detail)}</p>
|
|
8252
|
+
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml17(remediation.href)}">${escapeHtml17(remediation.label)}</a>` : `<strong>${escapeHtml17(remediation.label)}</strong>`}<span>${escapeHtml17(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
|
|
8116
8253
|
<dl>${row.rows.map((item) => `<div>
|
|
8117
|
-
<dt>${
|
|
8118
|
-
<dd>${
|
|
8254
|
+
<dt>${escapeHtml17(item.label)}</dt>
|
|
8255
|
+
<dd>${escapeHtml17(item.value)}</dd>
|
|
8119
8256
|
</div>`).join("")}</dl>
|
|
8120
8257
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
8121
|
-
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${
|
|
8258
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml17(model.status)}">
|
|
8122
8259
|
<header class="absolute-voice-provider-contracts__header">
|
|
8123
|
-
<span class="absolute-voice-provider-contracts__eyebrow">${
|
|
8124
|
-
<strong class="absolute-voice-provider-contracts__label">${
|
|
8260
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml17(model.title)}</span>
|
|
8261
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml17(model.label)}</strong>
|
|
8125
8262
|
</header>
|
|
8126
|
-
<p class="absolute-voice-provider-contracts__description">${
|
|
8263
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml17(model.description)}</p>
|
|
8127
8264
|
${rows}
|
|
8128
|
-
${model.error ? `<p class="absolute-voice-provider-contracts__error">${
|
|
8265
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml17(model.error)}</p>` : ""}
|
|
8129
8266
|
</section>`;
|
|
8130
8267
|
};
|
|
8131
8268
|
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}`;
|
|
@@ -8166,9 +8303,9 @@ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-co
|
|
|
8166
8303
|
});
|
|
8167
8304
|
};
|
|
8168
8305
|
// src/client/turnQualityWidget.ts
|
|
8169
|
-
var
|
|
8170
|
-
var
|
|
8171
|
-
var
|
|
8306
|
+
var DEFAULT_TITLE13 = "Turn Quality";
|
|
8307
|
+
var DEFAULT_DESCRIPTION13 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
8308
|
+
var escapeHtml18 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8172
8309
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
8173
8310
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
8174
8311
|
var getTurnDetail = (turn) => {
|
|
@@ -8206,37 +8343,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
8206
8343
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
8207
8344
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
8208
8345
|
return {
|
|
8209
|
-
description: options.description ??
|
|
8346
|
+
description: options.description ?? DEFAULT_DESCRIPTION13,
|
|
8210
8347
|
error: snapshot.error,
|
|
8211
8348
|
isLoading: snapshot.isLoading,
|
|
8212
8349
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
8213
8350
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
8214
|
-
title: options.title ??
|
|
8351
|
+
title: options.title ?? DEFAULT_TITLE13,
|
|
8215
8352
|
turns,
|
|
8216
8353
|
updatedAt: snapshot.updatedAt
|
|
8217
8354
|
};
|
|
8218
8355
|
};
|
|
8219
8356
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
8220
8357
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
8221
|
-
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--${
|
|
8358
|
+
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--${escapeHtml18(turn.status)}">
|
|
8222
8359
|
<header>
|
|
8223
|
-
<strong>${
|
|
8224
|
-
<span>${
|
|
8360
|
+
<strong>${escapeHtml18(turn.label)}</strong>
|
|
8361
|
+
<span>${escapeHtml18(turn.status)}</span>
|
|
8225
8362
|
</header>
|
|
8226
|
-
<p>${
|
|
8363
|
+
<p>${escapeHtml18(turn.detail)}</p>
|
|
8227
8364
|
<dl>${turn.rows.map((row) => `<div>
|
|
8228
|
-
<dt>${
|
|
8229
|
-
<dd>${
|
|
8365
|
+
<dt>${escapeHtml18(row.label)}</dt>
|
|
8366
|
+
<dd>${escapeHtml18(row.value)}</dd>
|
|
8230
8367
|
</div>`).join("")}</dl>
|
|
8231
8368
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
8232
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
8369
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml18(model.status)}">
|
|
8233
8370
|
<header class="absolute-voice-turn-quality__header">
|
|
8234
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
8235
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
8371
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml18(model.title)}</span>
|
|
8372
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml18(model.label)}</strong>
|
|
8236
8373
|
</header>
|
|
8237
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
8374
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml18(model.description)}</p>
|
|
8238
8375
|
${turns}
|
|
8239
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
8376
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml18(model.error)}</p>` : ""}
|
|
8240
8377
|
</section>`;
|
|
8241
8378
|
};
|
|
8242
8379
|
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}`;
|
|
@@ -8277,10 +8414,10 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
8277
8414
|
});
|
|
8278
8415
|
};
|
|
8279
8416
|
// src/client/turnLatencyWidget.ts
|
|
8280
|
-
var
|
|
8281
|
-
var
|
|
8417
|
+
var DEFAULT_TITLE14 = "Turn Latency";
|
|
8418
|
+
var DEFAULT_DESCRIPTION14 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
8282
8419
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
8283
|
-
var
|
|
8420
|
+
var escapeHtml19 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8284
8421
|
var formatMs3 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
8285
8422
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
8286
8423
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -8294,39 +8431,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
8294
8431
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
8295
8432
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
8296
8433
|
return {
|
|
8297
|
-
description: options.description ??
|
|
8434
|
+
description: options.description ?? DEFAULT_DESCRIPTION14,
|
|
8298
8435
|
error: snapshot.error,
|
|
8299
8436
|
isLoading: snapshot.isLoading,
|
|
8300
8437
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs3(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
8301
8438
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
8302
8439
|
showProofAction: Boolean(options.proofPath),
|
|
8303
8440
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
8304
|
-
title: options.title ??
|
|
8441
|
+
title: options.title ?? DEFAULT_TITLE14,
|
|
8305
8442
|
turns,
|
|
8306
8443
|
updatedAt: snapshot.updatedAt
|
|
8307
8444
|
};
|
|
8308
8445
|
};
|
|
8309
8446
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
8310
8447
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
8311
|
-
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--${
|
|
8448
|
+
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--${escapeHtml19(turn.status)}">
|
|
8312
8449
|
<header>
|
|
8313
|
-
<strong>${
|
|
8314
|
-
<span>${
|
|
8450
|
+
<strong>${escapeHtml19(turn.label)}</strong>
|
|
8451
|
+
<span>${escapeHtml19(turn.status)}</span>
|
|
8315
8452
|
</header>
|
|
8316
8453
|
<dl>${turn.rows.map((row) => `<div>
|
|
8317
|
-
<dt>${
|
|
8318
|
-
<dd>${
|
|
8454
|
+
<dt>${escapeHtml19(row.label)}</dt>
|
|
8455
|
+
<dd>${escapeHtml19(row.value)}</dd>
|
|
8319
8456
|
</div>`).join("")}</dl>
|
|
8320
8457
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
8321
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
8458
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml19(model.status)}">
|
|
8322
8459
|
<header class="absolute-voice-turn-latency__header">
|
|
8323
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
8324
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
8460
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml19(model.title)}</span>
|
|
8461
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml19(model.label)}</strong>
|
|
8325
8462
|
</header>
|
|
8326
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
8327
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
8463
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml19(model.description)}</p>
|
|
8464
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml19(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
8328
8465
|
${turns}
|
|
8329
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
8466
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml19(model.error)}</p>` : ""}
|
|
8330
8467
|
</section>`;
|
|
8331
8468
|
};
|
|
8332
8469
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -8376,9 +8513,9 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
8376
8513
|
});
|
|
8377
8514
|
};
|
|
8378
8515
|
// src/client/traceTimelineWidget.ts
|
|
8379
|
-
var
|
|
8380
|
-
var
|
|
8381
|
-
var
|
|
8516
|
+
var DEFAULT_TITLE15 = "Voice Traces";
|
|
8517
|
+
var DEFAULT_DESCRIPTION15 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
8518
|
+
var escapeHtml20 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8382
8519
|
var formatMs4 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
8383
8520
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
8384
8521
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -8394,13 +8531,13 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
8394
8531
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
8395
8532
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
8396
8533
|
return {
|
|
8397
|
-
description: options.description ??
|
|
8534
|
+
description: options.description ?? DEFAULT_DESCRIPTION15,
|
|
8398
8535
|
error: snapshot.error,
|
|
8399
8536
|
isLoading: snapshot.isLoading,
|
|
8400
8537
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
8401
8538
|
sessions,
|
|
8402
8539
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
8403
|
-
title: options.title ??
|
|
8540
|
+
title: options.title ?? DEFAULT_TITLE15,
|
|
8404
8541
|
updatedAt: snapshot.updatedAt
|
|
8405
8542
|
};
|
|
8406
8543
|
};
|
|
@@ -8408,27 +8545,27 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
|
8408
8545
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
8409
8546
|
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
|
|
8410
8547
|
const supportLinks = [
|
|
8411
|
-
`<a href="${
|
|
8412
|
-
session.operationsRecordHref ? `<a href="${
|
|
8413
|
-
session.incidentBundleHref ? `<a href="${
|
|
8548
|
+
`<a href="${escapeHtml20(session.detailHref)}">Open timeline</a>`,
|
|
8549
|
+
session.operationsRecordHref ? `<a href="${escapeHtml20(session.operationsRecordHref)}">Open operations record</a>` : undefined,
|
|
8550
|
+
session.incidentBundleHref ? `<a href="${escapeHtml20(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
|
|
8414
8551
|
].filter(Boolean).join("");
|
|
8415
|
-
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${
|
|
8552
|
+
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml20(session.status)}">
|
|
8416
8553
|
<header>
|
|
8417
|
-
<strong>${
|
|
8418
|
-
<span>${
|
|
8554
|
+
<strong>${escapeHtml20(session.sessionId)}</strong>
|
|
8555
|
+
<span>${escapeHtml20(session.status)}</span>
|
|
8419
8556
|
</header>
|
|
8420
|
-
<p>${
|
|
8557
|
+
<p>${escapeHtml20(session.label)} \xB7 ${escapeHtml20(session.durationLabel)} \xB7 ${escapeHtml20(session.providerLabel)}</p>
|
|
8421
8558
|
<p class="absolute-voice-trace-timeline__actions">${supportLinks}</p>
|
|
8422
8559
|
</article>`;
|
|
8423
8560
|
}).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
8424
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
8561
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml20(model.status)}">
|
|
8425
8562
|
<header class="absolute-voice-trace-timeline__header">
|
|
8426
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
8427
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
8563
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml20(model.title)}</span>
|
|
8564
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml20(model.label)}</strong>
|
|
8428
8565
|
</header>
|
|
8429
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
8566
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml20(model.description)}</p>
|
|
8430
8567
|
${sessions}
|
|
8431
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
8568
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml20(model.error)}</p>` : ""}
|
|
8432
8569
|
</section>`;
|
|
8433
8570
|
};
|
|
8434
8571
|
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}`;
|
|
@@ -8474,9 +8611,9 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
|
|
|
8474
8611
|
});
|
|
8475
8612
|
};
|
|
8476
8613
|
// src/client/agentSquadStatusWidget.ts
|
|
8477
|
-
var
|
|
8478
|
-
var
|
|
8479
|
-
var
|
|
8614
|
+
var DEFAULT_TITLE16 = "Voice Agent Squad";
|
|
8615
|
+
var DEFAULT_DESCRIPTION16 = "Current specialist and recent handoffs from your self-hosted voice traces.";
|
|
8616
|
+
var escapeHtml21 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8480
8617
|
var labelFor = (current) => {
|
|
8481
8618
|
if (!current)
|
|
8482
8619
|
return "Waiting for specialist activity";
|
|
@@ -8490,37 +8627,37 @@ var labelFor = (current) => {
|
|
|
8490
8627
|
};
|
|
8491
8628
|
var createVoiceAgentSquadStatusViewModel = (snapshot, options = {}) => ({
|
|
8492
8629
|
current: snapshot.report.current,
|
|
8493
|
-
description: options.description ??
|
|
8630
|
+
description: options.description ?? DEFAULT_DESCRIPTION16,
|
|
8494
8631
|
error: snapshot.error,
|
|
8495
8632
|
isLoading: snapshot.isLoading,
|
|
8496
8633
|
label: snapshot.error ? "Unavailable" : labelFor(snapshot.report.current),
|
|
8497
8634
|
sessionCount: snapshot.report.sessionCount,
|
|
8498
8635
|
sessions: snapshot.report.sessions,
|
|
8499
|
-
title: options.title ??
|
|
8636
|
+
title: options.title ?? DEFAULT_TITLE16,
|
|
8500
8637
|
updatedAt: snapshot.updatedAt
|
|
8501
8638
|
});
|
|
8502
8639
|
var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
|
|
8503
8640
|
const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
|
|
8504
8641
|
const current = model.current;
|
|
8505
8642
|
const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
|
|
8506
|
-
<span>${
|
|
8507
|
-
<strong>${
|
|
8508
|
-
<em>${
|
|
8509
|
-
${session.summary || session.reason ? `<p>${
|
|
8643
|
+
<span>${escapeHtml21(session.sessionId)}</span>
|
|
8644
|
+
<strong>${escapeHtml21(session.targetAgentId ?? "none")}</strong>
|
|
8645
|
+
<em>${escapeHtml21(session.status)}</em>
|
|
8646
|
+
${session.summary || session.reason ? `<p>${escapeHtml21(session.summary ?? session.reason ?? "")}</p>` : ""}
|
|
8510
8647
|
</li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
|
|
8511
8648
|
return `<section class="absolute-voice-agent-squad-status">
|
|
8512
8649
|
<header>
|
|
8513
|
-
<span>${
|
|
8514
|
-
<strong>${
|
|
8650
|
+
<span>${escapeHtml21(model.title)}</span>
|
|
8651
|
+
<strong>${escapeHtml21(model.label)}</strong>
|
|
8515
8652
|
</header>
|
|
8516
|
-
<p>${
|
|
8653
|
+
<p>${escapeHtml21(model.description)}</p>
|
|
8517
8654
|
<div>
|
|
8518
|
-
<span>Session</span><strong>${
|
|
8519
|
-
<span>From</span><strong>${
|
|
8520
|
-
<span>Status</span><strong>${
|
|
8655
|
+
<span>Session</span><strong>${escapeHtml21(current?.sessionId ?? "n/a")}</strong>
|
|
8656
|
+
<span>From</span><strong>${escapeHtml21(current?.fromAgentId ?? "n/a")}</strong>
|
|
8657
|
+
<span>Status</span><strong>${escapeHtml21(current?.status ?? "idle")}</strong>
|
|
8521
8658
|
</div>
|
|
8522
8659
|
<ul>${rows}</ul>
|
|
8523
|
-
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${
|
|
8660
|
+
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml21(model.error)}</p>` : ""}
|
|
8524
8661
|
</section>`;
|
|
8525
8662
|
};
|
|
8526
8663
|
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}`;
|
|
@@ -8656,6 +8793,7 @@ export {
|
|
|
8656
8793
|
renderVoiceProviderContractsHTML,
|
|
8657
8794
|
renderVoiceProviderCapabilitiesHTML,
|
|
8658
8795
|
renderVoiceProofTrendsHTML,
|
|
8796
|
+
renderVoiceProfileSwitchRecommendationHTML,
|
|
8659
8797
|
renderVoiceProfileComparisonHTML,
|
|
8660
8798
|
renderVoicePlatformCoverageHTML,
|
|
8661
8799
|
renderVoiceOpsStatusHTML,
|
|
@@ -8676,6 +8814,7 @@ export {
|
|
|
8676
8814
|
mountVoiceProviderContracts,
|
|
8677
8815
|
mountVoiceProviderCapabilities,
|
|
8678
8816
|
mountVoiceProofTrends,
|
|
8817
|
+
mountVoiceProfileSwitchRecommendation,
|
|
8679
8818
|
mountVoiceProfileComparison,
|
|
8680
8819
|
mountVoicePlatformCoverage,
|
|
8681
8820
|
mountVoiceOpsStatus,
|
|
@@ -8692,6 +8831,7 @@ export {
|
|
|
8692
8831
|
getVoiceProviderContractsCSS,
|
|
8693
8832
|
getVoiceProviderCapabilitiesCSS,
|
|
8694
8833
|
getVoiceProofTrendsCSS,
|
|
8834
|
+
getVoiceProfileSwitchRecommendationCSS,
|
|
8695
8835
|
getVoiceProfileComparisonCSS,
|
|
8696
8836
|
getVoicePlatformCoverageCSS,
|
|
8697
8837
|
getVoiceOpsStatusLabel,
|
|
@@ -8711,6 +8851,7 @@ export {
|
|
|
8711
8851
|
fetchVoiceProviderContracts,
|
|
8712
8852
|
fetchVoiceProviderCapabilities,
|
|
8713
8853
|
fetchVoiceProofTrends,
|
|
8854
|
+
fetchVoiceProfileSwitchRecommendation,
|
|
8714
8855
|
fetchVoiceProfileComparison,
|
|
8715
8856
|
fetchVoicePlatformCoverage,
|
|
8716
8857
|
fetchVoiceOpsStatus,
|
|
@@ -8727,6 +8868,7 @@ export {
|
|
|
8727
8868
|
defineVoiceProviderContractsElement,
|
|
8728
8869
|
defineVoiceProviderCapabilitiesElement,
|
|
8729
8870
|
defineVoiceProofTrendsElement,
|
|
8871
|
+
defineVoiceProfileSwitchRecommendationElement,
|
|
8730
8872
|
defineVoiceProfileComparisonElement,
|
|
8731
8873
|
defineVoicePlatformCoverageElement,
|
|
8732
8874
|
defineVoiceOpsStatusElement,
|
|
@@ -8757,6 +8899,7 @@ export {
|
|
|
8757
8899
|
createVoiceProviderCapabilitiesStore,
|
|
8758
8900
|
createVoiceProofTrendsViewModel,
|
|
8759
8901
|
createVoiceProofTrendsStore,
|
|
8902
|
+
createVoiceProfileSwitchRecommendationStore,
|
|
8760
8903
|
createVoiceProfileComparisonViewModel,
|
|
8761
8904
|
createVoiceProfileComparisonStore,
|
|
8762
8905
|
createVoicePlatformCoverageViewModel,
|