@absolutejs/voice 0.0.22-beta.239 → 0.0.22-beta.240
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 +1 -0
- package/dist/client/index.js +295 -189
- package/dist/client/platformCoverageWidget.d.ts +37 -0
- package/dist/react/VoicePlatformCoverage.d.ts +6 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +615 -429
- package/dist/vue/VoicePlatformCoverage.d.ts +23 -0
- package/dist/vue/index.d.ts +1 -0
- package/dist/vue/index.js +556 -386
- package/package.json +1 -1
package/dist/vue/index.js
CHANGED
|
@@ -1128,8 +1128,290 @@ var VoiceDeliveryRuntime = defineComponent3({
|
|
|
1128
1128
|
};
|
|
1129
1129
|
}
|
|
1130
1130
|
});
|
|
1131
|
+
// src/vue/VoicePlatformCoverage.ts
|
|
1132
|
+
import { defineComponent as defineComponent4, h as h4 } from "vue";
|
|
1133
|
+
|
|
1134
|
+
// src/vue/useVoicePlatformCoverage.ts
|
|
1135
|
+
import { onUnmounted as onUnmounted4, ref as ref4, shallowRef as shallowRef4 } from "vue";
|
|
1136
|
+
|
|
1137
|
+
// src/client/platformCoverage.ts
|
|
1138
|
+
var fetchVoicePlatformCoverage = async (path = "/api/voice/platform-coverage", options = {}) => {
|
|
1139
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1140
|
+
const response = await fetchImpl(path);
|
|
1141
|
+
if (!response.ok) {
|
|
1142
|
+
throw new Error(`Voice platform coverage failed: HTTP ${response.status}`);
|
|
1143
|
+
}
|
|
1144
|
+
return await response.json();
|
|
1145
|
+
};
|
|
1146
|
+
var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", options = {}) => {
|
|
1147
|
+
const listeners = new Set;
|
|
1148
|
+
let closed = false;
|
|
1149
|
+
let timer;
|
|
1150
|
+
let snapshot = {
|
|
1151
|
+
error: null,
|
|
1152
|
+
isLoading: false
|
|
1153
|
+
};
|
|
1154
|
+
const emit = () => {
|
|
1155
|
+
for (const listener of listeners) {
|
|
1156
|
+
listener();
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
const refresh = async () => {
|
|
1160
|
+
if (closed) {
|
|
1161
|
+
return snapshot.report;
|
|
1162
|
+
}
|
|
1163
|
+
snapshot = {
|
|
1164
|
+
...snapshot,
|
|
1165
|
+
error: null,
|
|
1166
|
+
isLoading: true
|
|
1167
|
+
};
|
|
1168
|
+
emit();
|
|
1169
|
+
try {
|
|
1170
|
+
const report = await fetchVoicePlatformCoverage(path, options);
|
|
1171
|
+
snapshot = {
|
|
1172
|
+
error: null,
|
|
1173
|
+
isLoading: false,
|
|
1174
|
+
report,
|
|
1175
|
+
updatedAt: Date.now()
|
|
1176
|
+
};
|
|
1177
|
+
emit();
|
|
1178
|
+
return report;
|
|
1179
|
+
} catch (error) {
|
|
1180
|
+
snapshot = {
|
|
1181
|
+
...snapshot,
|
|
1182
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1183
|
+
isLoading: false
|
|
1184
|
+
};
|
|
1185
|
+
emit();
|
|
1186
|
+
throw error;
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
const close = () => {
|
|
1190
|
+
closed = true;
|
|
1191
|
+
if (timer) {
|
|
1192
|
+
clearInterval(timer);
|
|
1193
|
+
timer = undefined;
|
|
1194
|
+
}
|
|
1195
|
+
listeners.clear();
|
|
1196
|
+
};
|
|
1197
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
1198
|
+
timer = setInterval(() => {
|
|
1199
|
+
refresh().catch(() => {});
|
|
1200
|
+
}, options.intervalMs);
|
|
1201
|
+
}
|
|
1202
|
+
return {
|
|
1203
|
+
close,
|
|
1204
|
+
getServerSnapshot: () => snapshot,
|
|
1205
|
+
getSnapshot: () => snapshot,
|
|
1206
|
+
refresh,
|
|
1207
|
+
subscribe: (listener) => {
|
|
1208
|
+
listeners.add(listener);
|
|
1209
|
+
return () => {
|
|
1210
|
+
listeners.delete(listener);
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
};
|
|
1215
|
+
|
|
1216
|
+
// src/vue/useVoicePlatformCoverage.ts
|
|
1217
|
+
function useVoicePlatformCoverage(path = "/api/voice/platform-coverage", options = {}) {
|
|
1218
|
+
const store = createVoicePlatformCoverageStore(path, options);
|
|
1219
|
+
const error = ref4(null);
|
|
1220
|
+
const isLoading = ref4(false);
|
|
1221
|
+
const report = shallowRef4(undefined);
|
|
1222
|
+
const updatedAt = ref4(undefined);
|
|
1223
|
+
const sync = () => {
|
|
1224
|
+
const snapshot = store.getSnapshot();
|
|
1225
|
+
error.value = snapshot.error;
|
|
1226
|
+
isLoading.value = snapshot.isLoading;
|
|
1227
|
+
report.value = snapshot.report;
|
|
1228
|
+
updatedAt.value = snapshot.updatedAt;
|
|
1229
|
+
};
|
|
1230
|
+
const unsubscribe = store.subscribe(sync);
|
|
1231
|
+
sync();
|
|
1232
|
+
if (typeof window !== "undefined") {
|
|
1233
|
+
store.refresh().catch(() => {});
|
|
1234
|
+
}
|
|
1235
|
+
onUnmounted4(() => {
|
|
1236
|
+
unsubscribe();
|
|
1237
|
+
store.close();
|
|
1238
|
+
});
|
|
1239
|
+
return {
|
|
1240
|
+
error,
|
|
1241
|
+
isLoading,
|
|
1242
|
+
refresh: store.refresh,
|
|
1243
|
+
report,
|
|
1244
|
+
updatedAt
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
// src/client/platformCoverageWidget.ts
|
|
1249
|
+
var DEFAULT_TITLE4 = "Platform Replacement Coverage";
|
|
1250
|
+
var DEFAULT_DESCRIPTION4 = "Code-owned coverage for hosted voice-platform surfaces, backed by the same proof routes used by release evidence.";
|
|
1251
|
+
var DEFAULT_LINKS = [
|
|
1252
|
+
{ href: "/switching-from-vapi", label: "Switching guide" },
|
|
1253
|
+
{ href: "/api/voice/vapi-coverage", label: "Coverage JSON" }
|
|
1254
|
+
];
|
|
1255
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1256
|
+
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
1257
|
+
var surfaceDetail2 = (surface) => {
|
|
1258
|
+
if (surface.status === "pass") {
|
|
1259
|
+
return surface.replacement;
|
|
1260
|
+
}
|
|
1261
|
+
if (surface.gap) {
|
|
1262
|
+
return surface.gap;
|
|
1263
|
+
}
|
|
1264
|
+
if (surface.missingEvidence?.length) {
|
|
1265
|
+
return `Missing evidence: ${surface.missingEvidence.join(", ")}`;
|
|
1266
|
+
}
|
|
1267
|
+
return surface.replacement;
|
|
1268
|
+
};
|
|
1269
|
+
var createVoicePlatformCoverageViewModel = (snapshot, options = {}) => {
|
|
1270
|
+
const allSurfaces = snapshot.report?.coverage ?? [];
|
|
1271
|
+
const failing = allSurfaces.filter((surface) => surface.status !== "pass");
|
|
1272
|
+
const limit = options.limit ?? 6;
|
|
1273
|
+
const surfaces = allSurfaces.slice(0, limit).map((surface) => ({
|
|
1274
|
+
...surface,
|
|
1275
|
+
detail: surfaceDetail2(surface),
|
|
1276
|
+
label: surface.surface
|
|
1277
|
+
}));
|
|
1278
|
+
return {
|
|
1279
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
1280
|
+
error: snapshot.error,
|
|
1281
|
+
isLoading: snapshot.isLoading,
|
|
1282
|
+
label: snapshot.error ? "Unavailable" : snapshot.report ? failing.length ? `${failing.length} gaps` : `${snapshot.report.total} surfaces passing` : snapshot.isLoading ? "Checking" : "No coverage report",
|
|
1283
|
+
links: options.links ?? DEFAULT_LINKS,
|
|
1284
|
+
status: snapshot.error ? "error" : snapshot.report ? failing.length ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1285
|
+
surfaces,
|
|
1286
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
1287
|
+
updatedAt: snapshot.updatedAt
|
|
1288
|
+
};
|
|
1289
|
+
};
|
|
1290
|
+
var renderVoicePlatformCoverageHTML = (snapshot, options = {}) => {
|
|
1291
|
+
const model = createVoicePlatformCoverageViewModel(snapshot, options);
|
|
1292
|
+
const surfaces = model.surfaces.length ? `<div class="absolute-voice-platform-coverage__surfaces">${model.surfaces.map((surface) => `<article class="absolute-voice-platform-coverage__surface absolute-voice-platform-coverage__surface--${escapeHtml4(surface.status)}">
|
|
1293
|
+
<header>
|
|
1294
|
+
<strong>${escapeHtml4(surface.label)}</strong>
|
|
1295
|
+
<span>${escapeHtml4(formatStatus(surface.status))}</span>
|
|
1296
|
+
</header>
|
|
1297
|
+
<p>${escapeHtml4(surface.detail)}</p>
|
|
1298
|
+
<small>${surface.evidence.filter((item) => item.ok).length}/${surface.evidence.length} evidence checks passing</small>
|
|
1299
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-platform-coverage__empty">${model.error ? escapeHtml4(model.error) : "Run the proof pack to populate platform coverage evidence."}</p>`;
|
|
1300
|
+
const links = model.links.length ? `<p class="absolute-voice-platform-coverage__links">${model.links.map((link) => `<a href="${escapeHtml4(link.href)}">${escapeHtml4(link.label)}</a>`).join("")}</p>` : "";
|
|
1301
|
+
return `<section class="absolute-voice-platform-coverage absolute-voice-platform-coverage--${escapeHtml4(model.status)}">
|
|
1302
|
+
<header class="absolute-voice-platform-coverage__header">
|
|
1303
|
+
<span class="absolute-voice-platform-coverage__eyebrow">${escapeHtml4(model.title)}</span>
|
|
1304
|
+
<strong class="absolute-voice-platform-coverage__label">${escapeHtml4(model.label)}</strong>
|
|
1305
|
+
</header>
|
|
1306
|
+
<p class="absolute-voice-platform-coverage__description">${escapeHtml4(model.description)}</p>
|
|
1307
|
+
${surfaces}
|
|
1308
|
+
${links}
|
|
1309
|
+
${model.error ? `<p class="absolute-voice-platform-coverage__error">${escapeHtml4(model.error)}</p>` : ""}
|
|
1310
|
+
</section>`;
|
|
1311
|
+
};
|
|
1312
|
+
var getVoicePlatformCoverageCSS = () => `.absolute-voice-platform-coverage{border:1px solid #c7d2fe;border-radius:20px;background:#f8fbff;color:#111827;padding:18px;box-shadow:0 18px 40px rgba(30,64,175,.12);font-family:inherit}.absolute-voice-platform-coverage--warning,.absolute-voice-platform-coverage--error{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-platform-coverage__header,.absolute-voice-platform-coverage__surface header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-platform-coverage__eyebrow{color:#1d4ed8;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-platform-coverage__label{font-size:24px;line-height:1}.absolute-voice-platform-coverage__description,.absolute-voice-platform-coverage__surface p,.absolute-voice-platform-coverage__surface small,.absolute-voice-platform-coverage__empty{color:#475569}.absolute-voice-platform-coverage__surfaces{display:grid;gap:10px;margin-top:14px}.absolute-voice-platform-coverage__surface{background:#fff;border:1px solid #dbeafe;border-radius:16px;padding:12px}.absolute-voice-platform-coverage__surface--pass{border-color:#86efac}.absolute-voice-platform-coverage__surface--fail,.absolute-voice-platform-coverage__surface--missing,.absolute-voice-platform-coverage__surface--stale{border-color:#f2a7a7}.absolute-voice-platform-coverage__surface p{margin:8px 0}.absolute-voice-platform-coverage__surface span{text-transform:capitalize}.absolute-voice-platform-coverage__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-platform-coverage__links a{border:1px solid #bfdbfe;border-radius:999px;color:#1d4ed8;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-platform-coverage__error{color:#9f1239;font-weight:700}`;
|
|
1313
|
+
var mountVoicePlatformCoverage = (element, path = "/api/voice/platform-coverage", options = {}) => {
|
|
1314
|
+
const store = createVoicePlatformCoverageStore(path, options);
|
|
1315
|
+
const render = () => {
|
|
1316
|
+
element.innerHTML = renderVoicePlatformCoverageHTML(store.getSnapshot(), options);
|
|
1317
|
+
};
|
|
1318
|
+
const unsubscribe = store.subscribe(render);
|
|
1319
|
+
render();
|
|
1320
|
+
store.refresh().catch(() => {});
|
|
1321
|
+
return {
|
|
1322
|
+
close: () => {
|
|
1323
|
+
unsubscribe();
|
|
1324
|
+
store.close();
|
|
1325
|
+
},
|
|
1326
|
+
refresh: store.refresh
|
|
1327
|
+
};
|
|
1328
|
+
};
|
|
1329
|
+
var defineVoicePlatformCoverageElement = (tagName = "absolute-voice-platform-coverage") => {
|
|
1330
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
customElements.define(tagName, class AbsoluteVoicePlatformCoverageElement extends HTMLElement {
|
|
1334
|
+
mounted;
|
|
1335
|
+
connectedCallback() {
|
|
1336
|
+
this.mounted = mountVoicePlatformCoverage(this, this.getAttribute("path") ?? "/api/voice/platform-coverage", {
|
|
1337
|
+
description: this.getAttribute("description") ?? undefined,
|
|
1338
|
+
intervalMs: Number(this.getAttribute("interval-ms") ?? 0) || undefined,
|
|
1339
|
+
limit: Number(this.getAttribute("limit") ?? 0) || undefined,
|
|
1340
|
+
title: this.getAttribute("title") ?? undefined
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
disconnectedCallback() {
|
|
1344
|
+
this.mounted?.close();
|
|
1345
|
+
this.mounted = undefined;
|
|
1346
|
+
}
|
|
1347
|
+
});
|
|
1348
|
+
};
|
|
1349
|
+
|
|
1350
|
+
// src/vue/VoicePlatformCoverage.ts
|
|
1351
|
+
var VoicePlatformCoverage = defineComponent4({
|
|
1352
|
+
name: "VoicePlatformCoverage",
|
|
1353
|
+
props: {
|
|
1354
|
+
description: String,
|
|
1355
|
+
intervalMs: Number,
|
|
1356
|
+
limit: Number,
|
|
1357
|
+
path: {
|
|
1358
|
+
default: "/api/voice/platform-coverage",
|
|
1359
|
+
type: String
|
|
1360
|
+
},
|
|
1361
|
+
title: String
|
|
1362
|
+
},
|
|
1363
|
+
setup(props) {
|
|
1364
|
+
const state = useVoicePlatformCoverage(props.path, {
|
|
1365
|
+
description: props.description,
|
|
1366
|
+
intervalMs: props.intervalMs,
|
|
1367
|
+
limit: props.limit,
|
|
1368
|
+
title: props.title
|
|
1369
|
+
});
|
|
1370
|
+
return () => {
|
|
1371
|
+
const model = createVoicePlatformCoverageViewModel({
|
|
1372
|
+
error: state.error.value,
|
|
1373
|
+
isLoading: state.isLoading.value,
|
|
1374
|
+
report: state.report.value,
|
|
1375
|
+
updatedAt: state.updatedAt.value
|
|
1376
|
+
}, {
|
|
1377
|
+
description: props.description,
|
|
1378
|
+
intervalMs: props.intervalMs,
|
|
1379
|
+
limit: props.limit,
|
|
1380
|
+
title: props.title
|
|
1381
|
+
});
|
|
1382
|
+
return h4("section", {
|
|
1383
|
+
class: [
|
|
1384
|
+
"absolute-voice-platform-coverage",
|
|
1385
|
+
`absolute-voice-platform-coverage--${model.status}`
|
|
1386
|
+
]
|
|
1387
|
+
}, [
|
|
1388
|
+
h4("header", { class: "absolute-voice-platform-coverage__header" }, [
|
|
1389
|
+
h4("span", { class: "absolute-voice-platform-coverage__eyebrow" }, model.title),
|
|
1390
|
+
h4("strong", { class: "absolute-voice-platform-coverage__label" }, model.label)
|
|
1391
|
+
]),
|
|
1392
|
+
h4("p", { class: "absolute-voice-platform-coverage__description" }, model.description),
|
|
1393
|
+
model.surfaces.length ? h4("div", { class: "absolute-voice-platform-coverage__surfaces" }, model.surfaces.map((surface) => h4("article", {
|
|
1394
|
+
class: [
|
|
1395
|
+
"absolute-voice-platform-coverage__surface",
|
|
1396
|
+
`absolute-voice-platform-coverage__surface--${surface.status}`
|
|
1397
|
+
],
|
|
1398
|
+
key: surface.surface
|
|
1399
|
+
}, [
|
|
1400
|
+
h4("header", [
|
|
1401
|
+
h4("strong", surface.label),
|
|
1402
|
+
h4("span", surface.status)
|
|
1403
|
+
]),
|
|
1404
|
+
h4("p", surface.detail),
|
|
1405
|
+
h4("small", `${surface.evidence.filter((item) => item.ok).length}/${surface.evidence.length} evidence checks passing`)
|
|
1406
|
+
]))) : h4("p", { class: "absolute-voice-platform-coverage__empty" }, model.error ?? "Run the proof pack to populate platform coverage evidence."),
|
|
1407
|
+
model.links.length ? h4("p", { class: "absolute-voice-platform-coverage__links" }, model.links.map((link) => h4("a", { href: link.href, key: link.href }, link.label))) : null,
|
|
1408
|
+
model.error ? h4("p", { class: "absolute-voice-platform-coverage__error" }, model.error) : null
|
|
1409
|
+
]);
|
|
1410
|
+
};
|
|
1411
|
+
}
|
|
1412
|
+
});
|
|
1131
1413
|
// src/vue/VoiceProviderSimulationControls.ts
|
|
1132
|
-
import { computed, defineComponent as
|
|
1414
|
+
import { computed, defineComponent as defineComponent5, h as h5 } from "vue";
|
|
1133
1415
|
|
|
1134
1416
|
// src/client/providerSimulationControls.ts
|
|
1135
1417
|
var postSimulation = async (pathPrefix, mode, provider, fetchImpl) => {
|
|
@@ -1211,7 +1493,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
1211
1493
|
};
|
|
1212
1494
|
|
|
1213
1495
|
// src/client/providerSimulationControlsWidget.ts
|
|
1214
|
-
var
|
|
1496
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1215
1497
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
1216
1498
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
1217
1499
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -1231,18 +1513,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
1231
1513
|
};
|
|
1232
1514
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
1233
1515
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
1234
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
1235
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
1516
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml5(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml5(provider.provider)} ${escapeHtml5(formatKind(options.kind))} failure</button>`).join("");
|
|
1517
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml5(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml5(provider.provider)} recovered</button>`).join("");
|
|
1236
1518
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
1237
1519
|
<header class="absolute-voice-provider-simulation__header">
|
|
1238
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
1239
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
1520
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml5(model.title)}</span>
|
|
1521
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml5(model.label)}</strong>
|
|
1240
1522
|
</header>
|
|
1241
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
1242
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
1523
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml5(model.description)}</p>
|
|
1524
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml5(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
1243
1525
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
1244
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
1245
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
1526
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml5(snapshot.error)}</p>` : ""}
|
|
1527
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml5(model.resultText)}</pre>` : ""}
|
|
1246
1528
|
</section>`;
|
|
1247
1529
|
};
|
|
1248
1530
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -1308,15 +1590,15 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
1308
1590
|
};
|
|
1309
1591
|
|
|
1310
1592
|
// src/vue/useVoiceProviderSimulationControls.ts
|
|
1311
|
-
import { onUnmounted as
|
|
1593
|
+
import { onUnmounted as onUnmounted5, ref as ref5 } from "vue";
|
|
1312
1594
|
function useVoiceProviderSimulationControls(options) {
|
|
1313
1595
|
const store = createVoiceProviderSimulationControlsStore(options);
|
|
1314
|
-
const error =
|
|
1315
|
-
const isRunning =
|
|
1316
|
-
const lastResult =
|
|
1317
|
-
const mode =
|
|
1318
|
-
const provider =
|
|
1319
|
-
const updatedAt =
|
|
1596
|
+
const error = ref5(null);
|
|
1597
|
+
const isRunning = ref5(false);
|
|
1598
|
+
const lastResult = ref5(null);
|
|
1599
|
+
const mode = ref5(null);
|
|
1600
|
+
const provider = ref5(null);
|
|
1601
|
+
const updatedAt = ref5(undefined);
|
|
1320
1602
|
const sync = () => {
|
|
1321
1603
|
const snapshot = store.getSnapshot();
|
|
1322
1604
|
error.value = snapshot.error;
|
|
@@ -1328,7 +1610,7 @@ function useVoiceProviderSimulationControls(options) {
|
|
|
1328
1610
|
};
|
|
1329
1611
|
const unsubscribe = store.subscribe(sync);
|
|
1330
1612
|
sync();
|
|
1331
|
-
|
|
1613
|
+
onUnmounted5(() => {
|
|
1332
1614
|
unsubscribe();
|
|
1333
1615
|
store.close();
|
|
1334
1616
|
});
|
|
@@ -1344,7 +1626,7 @@ function useVoiceProviderSimulationControls(options) {
|
|
|
1344
1626
|
}
|
|
1345
1627
|
|
|
1346
1628
|
// src/vue/VoiceProviderSimulationControls.ts
|
|
1347
|
-
var VoiceProviderSimulationControls =
|
|
1629
|
+
var VoiceProviderSimulationControls = defineComponent5({
|
|
1348
1630
|
name: "VoiceProviderSimulationControls",
|
|
1349
1631
|
props: {
|
|
1350
1632
|
class: { default: "", type: String },
|
|
@@ -1386,40 +1668,40 @@ var VoiceProviderSimulationControls = defineComponent4({
|
|
|
1386
1668
|
const run = (provider, mode) => {
|
|
1387
1669
|
controls.run(provider, mode).catch(() => {});
|
|
1388
1670
|
};
|
|
1389
|
-
return () =>
|
|
1671
|
+
return () => h5("section", {
|
|
1390
1672
|
class: [
|
|
1391
1673
|
"absolute-voice-provider-simulation",
|
|
1392
1674
|
`absolute-voice-provider-simulation--${controls.error.value ? "error" : controls.isRunning.value ? "running" : "ready"}`,
|
|
1393
1675
|
props.class
|
|
1394
1676
|
]
|
|
1395
1677
|
}, [
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1678
|
+
h5("header", { class: "absolute-voice-provider-simulation__header" }, [
|
|
1679
|
+
h5("span", { class: "absolute-voice-provider-simulation__eyebrow" }, model.value.title),
|
|
1680
|
+
h5("strong", { class: "absolute-voice-provider-simulation__label" }, model.value.label)
|
|
1399
1681
|
]),
|
|
1400
|
-
|
|
1401
|
-
model.value.canSimulateFailure ? null :
|
|
1402
|
-
|
|
1403
|
-
...model.value.failureProviders.map((provider) =>
|
|
1682
|
+
h5("p", { class: "absolute-voice-provider-simulation__description" }, model.value.description),
|
|
1683
|
+
model.value.canSimulateFailure ? null : h5("p", { class: "absolute-voice-provider-simulation__empty" }, props.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure."),
|
|
1684
|
+
h5("div", { class: "absolute-voice-provider-simulation__actions" }, [
|
|
1685
|
+
...model.value.failureProviders.map((provider) => h5("button", {
|
|
1404
1686
|
disabled: !model.value.canSimulateFailure || controls.isRunning.value,
|
|
1405
1687
|
key: `fail-${provider.provider}`,
|
|
1406
1688
|
onClick: () => run(provider.provider, "failure"),
|
|
1407
1689
|
type: "button"
|
|
1408
1690
|
}, `Simulate ${provider.provider} ${props.kind.toUpperCase()} failure`)),
|
|
1409
|
-
...model.value.providers.map((provider) =>
|
|
1691
|
+
...model.value.providers.map((provider) => h5("button", {
|
|
1410
1692
|
disabled: controls.isRunning.value,
|
|
1411
1693
|
key: `recover-${provider.provider}`,
|
|
1412
1694
|
onClick: () => run(provider.provider, "recovery"),
|
|
1413
1695
|
type: "button"
|
|
1414
1696
|
}, `Mark ${provider.provider} recovered`))
|
|
1415
1697
|
]),
|
|
1416
|
-
controls.error.value ?
|
|
1417
|
-
model.value.resultText ?
|
|
1698
|
+
controls.error.value ? h5("p", { class: "absolute-voice-provider-simulation__error" }, controls.error.value) : null,
|
|
1699
|
+
model.value.resultText ? h5("pre", { class: "absolute-voice-provider-simulation__result" }, model.value.resultText) : null
|
|
1418
1700
|
]);
|
|
1419
1701
|
}
|
|
1420
1702
|
});
|
|
1421
1703
|
// src/vue/VoiceProviderCapabilities.ts
|
|
1422
|
-
import { computed as computed2, defineComponent as
|
|
1704
|
+
import { computed as computed2, defineComponent as defineComponent6, h as h6 } from "vue";
|
|
1423
1705
|
|
|
1424
1706
|
// src/client/providerCapabilities.ts
|
|
1425
1707
|
var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
|
|
@@ -1501,12 +1783,12 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
|
|
|
1501
1783
|
};
|
|
1502
1784
|
|
|
1503
1785
|
// src/client/providerCapabilitiesWidget.ts
|
|
1504
|
-
var
|
|
1505
|
-
var
|
|
1506
|
-
var
|
|
1786
|
+
var DEFAULT_TITLE5 = "Provider Capabilities";
|
|
1787
|
+
var DEFAULT_DESCRIPTION5 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
1788
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1507
1789
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1508
1790
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
1509
|
-
var
|
|
1791
|
+
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
1510
1792
|
var getCapabilityDetail = (capability) => {
|
|
1511
1793
|
if (!capability.configured) {
|
|
1512
1794
|
return "Not configured in this deployment.";
|
|
@@ -1532,7 +1814,7 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
1532
1814
|
detail: getCapabilityDetail(capability),
|
|
1533
1815
|
label: `${formatProvider(capability.provider)} ${formatKind2(capability.kind)}`,
|
|
1534
1816
|
rows: [
|
|
1535
|
-
{ label: "Status", value:
|
|
1817
|
+
{ label: "Status", value: formatStatus2(capability.status) },
|
|
1536
1818
|
{ label: "Selected", value: capability.selected ? "Yes" : "No" },
|
|
1537
1819
|
{ label: "Model", value: capability.model ?? "Default" },
|
|
1538
1820
|
{
|
|
@@ -1547,36 +1829,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
1547
1829
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
1548
1830
|
return {
|
|
1549
1831
|
capabilities,
|
|
1550
|
-
description: options.description ??
|
|
1832
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
1551
1833
|
error: snapshot.error,
|
|
1552
1834
|
isLoading: snapshot.isLoading,
|
|
1553
1835
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
1554
1836
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1555
|
-
title: options.title ??
|
|
1837
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
1556
1838
|
updatedAt: snapshot.updatedAt
|
|
1557
1839
|
};
|
|
1558
1840
|
};
|
|
1559
1841
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
1560
1842
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
1561
|
-
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--${
|
|
1843
|
+
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--${escapeHtml6(capability.status)}">
|
|
1562
1844
|
<header>
|
|
1563
|
-
<strong>${
|
|
1564
|
-
<span>${
|
|
1845
|
+
<strong>${escapeHtml6(capability.label)}</strong>
|
|
1846
|
+
<span>${escapeHtml6(formatStatus2(capability.status))}</span>
|
|
1565
1847
|
</header>
|
|
1566
|
-
<p>${
|
|
1848
|
+
<p>${escapeHtml6(capability.detail)}</p>
|
|
1567
1849
|
<dl>${capability.rows.map((row) => `<div>
|
|
1568
|
-
<dt>${
|
|
1569
|
-
<dd>${
|
|
1850
|
+
<dt>${escapeHtml6(row.label)}</dt>
|
|
1851
|
+
<dd>${escapeHtml6(row.value)}</dd>
|
|
1570
1852
|
</div>`).join("")}</dl>
|
|
1571
1853
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
1572
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
1854
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml6(model.status)}">
|
|
1573
1855
|
<header class="absolute-voice-provider-capabilities__header">
|
|
1574
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
1575
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
1856
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml6(model.title)}</span>
|
|
1857
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml6(model.label)}</strong>
|
|
1576
1858
|
</header>
|
|
1577
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
1859
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml6(model.description)}</p>
|
|
1578
1860
|
${capabilities}
|
|
1579
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
1861
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
1580
1862
|
</section>`;
|
|
1581
1863
|
};
|
|
1582
1864
|
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}`;
|
|
@@ -1618,13 +1900,13 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
1618
1900
|
};
|
|
1619
1901
|
|
|
1620
1902
|
// src/vue/useVoiceProviderCapabilities.ts
|
|
1621
|
-
import { onUnmounted as
|
|
1903
|
+
import { onUnmounted as onUnmounted6, shallowRef as shallowRef5 } from "vue";
|
|
1622
1904
|
function useVoiceProviderCapabilities(path = "/api/provider-capabilities", options = {}) {
|
|
1623
1905
|
const store = createVoiceProviderCapabilitiesStore(path, options);
|
|
1624
|
-
const error =
|
|
1625
|
-
const isLoading =
|
|
1626
|
-
const report =
|
|
1627
|
-
const updatedAt =
|
|
1906
|
+
const error = shallowRef5(null);
|
|
1907
|
+
const isLoading = shallowRef5(false);
|
|
1908
|
+
const report = shallowRef5();
|
|
1909
|
+
const updatedAt = shallowRef5(undefined);
|
|
1628
1910
|
const sync = () => {
|
|
1629
1911
|
const snapshot = store.getSnapshot();
|
|
1630
1912
|
error.value = snapshot.error;
|
|
@@ -1635,7 +1917,7 @@ function useVoiceProviderCapabilities(path = "/api/provider-capabilities", optio
|
|
|
1635
1917
|
const unsubscribe = store.subscribe(sync);
|
|
1636
1918
|
sync();
|
|
1637
1919
|
store.refresh().catch(() => {});
|
|
1638
|
-
|
|
1920
|
+
onUnmounted6(() => {
|
|
1639
1921
|
unsubscribe();
|
|
1640
1922
|
store.close();
|
|
1641
1923
|
});
|
|
@@ -1649,7 +1931,7 @@ function useVoiceProviderCapabilities(path = "/api/provider-capabilities", optio
|
|
|
1649
1931
|
}
|
|
1650
1932
|
|
|
1651
1933
|
// src/vue/VoiceProviderCapabilities.ts
|
|
1652
|
-
var VoiceProviderCapabilities =
|
|
1934
|
+
var VoiceProviderCapabilities = defineComponent6({
|
|
1653
1935
|
name: "VoiceProviderCapabilities",
|
|
1654
1936
|
props: {
|
|
1655
1937
|
class: {
|
|
@@ -1686,44 +1968,44 @@ var VoiceProviderCapabilities = defineComponent5({
|
|
|
1686
1968
|
report: capabilities.report.value,
|
|
1687
1969
|
updatedAt: capabilities.updatedAt.value
|
|
1688
1970
|
}, options));
|
|
1689
|
-
return () =>
|
|
1971
|
+
return () => h6("section", {
|
|
1690
1972
|
class: [
|
|
1691
1973
|
"absolute-voice-provider-capabilities",
|
|
1692
1974
|
`absolute-voice-provider-capabilities--${model.value.status}`,
|
|
1693
1975
|
props.class
|
|
1694
1976
|
]
|
|
1695
1977
|
}, [
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1978
|
+
h6("header", { class: "absolute-voice-provider-capabilities__header" }, [
|
|
1979
|
+
h6("span", { class: "absolute-voice-provider-capabilities__eyebrow" }, model.value.title),
|
|
1980
|
+
h6("strong", { class: "absolute-voice-provider-capabilities__label" }, model.value.label)
|
|
1699
1981
|
]),
|
|
1700
|
-
|
|
1701
|
-
model.value.capabilities.length ?
|
|
1982
|
+
h6("p", { class: "absolute-voice-provider-capabilities__description" }, model.value.description),
|
|
1983
|
+
model.value.capabilities.length ? h6("div", { class: "absolute-voice-provider-capabilities__providers" }, model.value.capabilities.map((capability) => h6("article", {
|
|
1702
1984
|
class: [
|
|
1703
1985
|
"absolute-voice-provider-capabilities__provider",
|
|
1704
1986
|
`absolute-voice-provider-capabilities__provider--${capability.status}`
|
|
1705
1987
|
],
|
|
1706
1988
|
key: `${capability.kind}:${capability.provider}`
|
|
1707
1989
|
}, [
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1990
|
+
h6("header", [
|
|
1991
|
+
h6("strong", capability.label),
|
|
1992
|
+
h6("span", capability.status)
|
|
1711
1993
|
]),
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1994
|
+
h6("p", capability.detail),
|
|
1995
|
+
h6("dl", capability.rows.map((row) => h6("div", { key: row.label }, [
|
|
1996
|
+
h6("dt", row.label),
|
|
1997
|
+
h6("dd", row.value)
|
|
1716
1998
|
])))
|
|
1717
|
-
]))) :
|
|
1718
|
-
model.value.error ?
|
|
1999
|
+
]))) : h6("p", { class: "absolute-voice-provider-capabilities__empty" }, "Configure provider capabilities to see deployment coverage."),
|
|
2000
|
+
model.value.error ? h6("p", { class: "absolute-voice-provider-capabilities__error" }, model.value.error) : null
|
|
1719
2001
|
]);
|
|
1720
2002
|
}
|
|
1721
2003
|
});
|
|
1722
2004
|
// src/vue/VoiceProviderContracts.ts
|
|
1723
|
-
import { defineComponent as
|
|
2005
|
+
import { defineComponent as defineComponent7, h as h7 } from "vue";
|
|
1724
2006
|
|
|
1725
2007
|
// src/vue/useVoiceProviderContracts.ts
|
|
1726
|
-
import { onUnmounted as
|
|
2008
|
+
import { onUnmounted as onUnmounted7, shallowRef as shallowRef6 } from "vue";
|
|
1727
2009
|
|
|
1728
2010
|
// src/client/providerContracts.ts
|
|
1729
2011
|
var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
|
|
@@ -1803,10 +2085,10 @@ var createVoiceProviderContractsStore = (path = "/api/provider-contracts", optio
|
|
|
1803
2085
|
// src/vue/useVoiceProviderContracts.ts
|
|
1804
2086
|
function useVoiceProviderContracts(path = "/api/provider-contracts", options = {}) {
|
|
1805
2087
|
const store = createVoiceProviderContractsStore(path, options);
|
|
1806
|
-
const error =
|
|
1807
|
-
const isLoading =
|
|
1808
|
-
const report =
|
|
1809
|
-
const updatedAt =
|
|
2088
|
+
const error = shallowRef6(null);
|
|
2089
|
+
const isLoading = shallowRef6(false);
|
|
2090
|
+
const report = shallowRef6();
|
|
2091
|
+
const updatedAt = shallowRef6(undefined);
|
|
1810
2092
|
const sync = () => {
|
|
1811
2093
|
const snapshot = store.getSnapshot();
|
|
1812
2094
|
error.value = snapshot.error;
|
|
@@ -1817,7 +2099,7 @@ function useVoiceProviderContracts(path = "/api/provider-contracts", options = {
|
|
|
1817
2099
|
const unsubscribe = store.subscribe(sync);
|
|
1818
2100
|
sync();
|
|
1819
2101
|
store.refresh().catch(() => {});
|
|
1820
|
-
|
|
2102
|
+
onUnmounted7(() => {
|
|
1821
2103
|
unsubscribe();
|
|
1822
2104
|
store.close();
|
|
1823
2105
|
});
|
|
@@ -1831,11 +2113,11 @@ function useVoiceProviderContracts(path = "/api/provider-contracts", options = {
|
|
|
1831
2113
|
}
|
|
1832
2114
|
|
|
1833
2115
|
// src/client/providerContractsWidget.ts
|
|
1834
|
-
var
|
|
1835
|
-
var
|
|
1836
|
-
var
|
|
2116
|
+
var DEFAULT_TITLE6 = "Provider Contracts";
|
|
2117
|
+
var DEFAULT_DESCRIPTION6 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
2118
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1837
2119
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1838
|
-
var
|
|
2120
|
+
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
1839
2121
|
var contractDetail = (row) => {
|
|
1840
2122
|
const failing = row.checks.filter((check) => check.status !== "pass");
|
|
1841
2123
|
if (failing.length === 0) {
|
|
@@ -1854,49 +2136,49 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
|
1854
2136
|
label: check.remediation?.label ?? check.label
|
|
1855
2137
|
})),
|
|
1856
2138
|
rows: [
|
|
1857
|
-
{ label: "Status", value:
|
|
2139
|
+
{ label: "Status", value: formatStatus3(row.status) },
|
|
1858
2140
|
{ label: "Selected", value: row.selected ? "Yes" : "No" },
|
|
1859
2141
|
{ label: "Configured", value: row.configured ? "Yes" : "No" },
|
|
1860
2142
|
{
|
|
1861
2143
|
label: "Checks",
|
|
1862
|
-
value: row.checks.map((check) => `${check.label}: ${
|
|
2144
|
+
value: row.checks.map((check) => `${check.label}: ${formatStatus3(check.status)}`).join(", ")
|
|
1863
2145
|
}
|
|
1864
2146
|
]
|
|
1865
2147
|
}));
|
|
1866
2148
|
const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
|
|
1867
2149
|
return {
|
|
1868
|
-
description: options.description ??
|
|
2150
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
1869
2151
|
error: snapshot.error,
|
|
1870
2152
|
isLoading: snapshot.isLoading,
|
|
1871
2153
|
label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
|
|
1872
2154
|
rows,
|
|
1873
2155
|
status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1874
|
-
title: options.title ??
|
|
2156
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
1875
2157
|
updatedAt: snapshot.updatedAt
|
|
1876
2158
|
};
|
|
1877
2159
|
};
|
|
1878
2160
|
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
1879
2161
|
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
1880
|
-
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--${
|
|
2162
|
+
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--${escapeHtml7(row.status)}">
|
|
1881
2163
|
<header>
|
|
1882
|
-
<strong>${
|
|
1883
|
-
<span>${
|
|
2164
|
+
<strong>${escapeHtml7(row.label)}</strong>
|
|
2165
|
+
<span>${escapeHtml7(formatStatus3(row.status))}</span>
|
|
1884
2166
|
</header>
|
|
1885
|
-
<p>${
|
|
1886
|
-
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${
|
|
2167
|
+
<p>${escapeHtml7(row.detail)}</p>
|
|
2168
|
+
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml7(remediation.href)}">${escapeHtml7(remediation.label)}</a>` : `<strong>${escapeHtml7(remediation.label)}</strong>`}<span>${escapeHtml7(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
|
|
1887
2169
|
<dl>${row.rows.map((item) => `<div>
|
|
1888
|
-
<dt>${
|
|
1889
|
-
<dd>${
|
|
2170
|
+
<dt>${escapeHtml7(item.label)}</dt>
|
|
2171
|
+
<dd>${escapeHtml7(item.value)}</dd>
|
|
1890
2172
|
</div>`).join("")}</dl>
|
|
1891
2173
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
1892
|
-
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${
|
|
2174
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml7(model.status)}">
|
|
1893
2175
|
<header class="absolute-voice-provider-contracts__header">
|
|
1894
|
-
<span class="absolute-voice-provider-contracts__eyebrow">${
|
|
1895
|
-
<strong class="absolute-voice-provider-contracts__label">${
|
|
2176
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml7(model.title)}</span>
|
|
2177
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml7(model.label)}</strong>
|
|
1896
2178
|
</header>
|
|
1897
|
-
<p class="absolute-voice-provider-contracts__description">${
|
|
2179
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml7(model.description)}</p>
|
|
1898
2180
|
${rows}
|
|
1899
|
-
${model.error ? `<p class="absolute-voice-provider-contracts__error">${
|
|
2181
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
1900
2182
|
</section>`;
|
|
1901
2183
|
};
|
|
1902
2184
|
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}`;
|
|
@@ -1938,7 +2220,7 @@ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-co
|
|
|
1938
2220
|
};
|
|
1939
2221
|
|
|
1940
2222
|
// src/vue/VoiceProviderContracts.ts
|
|
1941
|
-
var VoiceProviderContracts =
|
|
2223
|
+
var VoiceProviderContracts = defineComponent7({
|
|
1942
2224
|
name: "VoiceProviderContracts",
|
|
1943
2225
|
props: {
|
|
1944
2226
|
description: String,
|
|
@@ -1966,49 +2248,49 @@ var VoiceProviderContracts = defineComponent6({
|
|
|
1966
2248
|
intervalMs: props.intervalMs,
|
|
1967
2249
|
title: props.title
|
|
1968
2250
|
});
|
|
1969
|
-
return
|
|
2251
|
+
return h7("section", {
|
|
1970
2252
|
class: [
|
|
1971
2253
|
"absolute-voice-provider-contracts",
|
|
1972
2254
|
`absolute-voice-provider-contracts--${model.status}`
|
|
1973
2255
|
]
|
|
1974
2256
|
}, [
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
2257
|
+
h7("header", { class: "absolute-voice-provider-contracts__header" }, [
|
|
2258
|
+
h7("span", { class: "absolute-voice-provider-contracts__eyebrow" }, model.title),
|
|
2259
|
+
h7("strong", { class: "absolute-voice-provider-contracts__label" }, model.label)
|
|
1978
2260
|
]),
|
|
1979
|
-
|
|
1980
|
-
model.rows.length ?
|
|
2261
|
+
h7("p", { class: "absolute-voice-provider-contracts__description" }, model.description),
|
|
2262
|
+
model.rows.length ? h7("div", { class: "absolute-voice-provider-contracts__rows" }, model.rows.map((row) => h7("article", {
|
|
1981
2263
|
class: [
|
|
1982
2264
|
"absolute-voice-provider-contracts__row",
|
|
1983
2265
|
`absolute-voice-provider-contracts__row--${row.status}`
|
|
1984
2266
|
],
|
|
1985
2267
|
key: `${row.kind}:${row.provider}`
|
|
1986
2268
|
}, [
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
2269
|
+
h7("header", [
|
|
2270
|
+
h7("strong", row.label),
|
|
2271
|
+
h7("span", row.status)
|
|
1990
2272
|
]),
|
|
1991
|
-
|
|
1992
|
-
row.remediations.length ?
|
|
2273
|
+
h7("p", row.detail),
|
|
2274
|
+
row.remediations.length ? h7("ul", {
|
|
1993
2275
|
class: "absolute-voice-provider-contracts__remediations"
|
|
1994
|
-
}, row.remediations.map((remediation) =>
|
|
2276
|
+
}, row.remediations.map((remediation) => h7("li", {
|
|
1995
2277
|
key: `${row.kind}:${row.provider}:${remediation.label}`
|
|
1996
2278
|
}, [
|
|
1997
|
-
remediation.href ?
|
|
1998
|
-
|
|
2279
|
+
remediation.href ? h7("a", { href: remediation.href }, remediation.label) : h7("strong", remediation.label),
|
|
2280
|
+
h7("span", remediation.detail)
|
|
1999
2281
|
]))) : null,
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2282
|
+
h7("dl", row.rows.map((item) => h7("div", { key: item.label }, [
|
|
2283
|
+
h7("dt", item.label),
|
|
2284
|
+
h7("dd", item.value)
|
|
2003
2285
|
])))
|
|
2004
|
-
]))) :
|
|
2005
|
-
model.error ?
|
|
2286
|
+
]))) : h7("p", { class: "absolute-voice-provider-contracts__empty" }, "Configure provider contracts to see production coverage."),
|
|
2287
|
+
model.error ? h7("p", { class: "absolute-voice-provider-contracts__error" }, model.error) : null
|
|
2006
2288
|
]);
|
|
2007
2289
|
};
|
|
2008
2290
|
}
|
|
2009
2291
|
});
|
|
2010
2292
|
// src/vue/VoiceProviderStatus.ts
|
|
2011
|
-
import { computed as computed3, defineComponent as
|
|
2293
|
+
import { computed as computed3, defineComponent as defineComponent8, h as h8 } from "vue";
|
|
2012
2294
|
|
|
2013
2295
|
// src/client/providerStatus.ts
|
|
2014
2296
|
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
@@ -2091,11 +2373,11 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
2091
2373
|
};
|
|
2092
2374
|
|
|
2093
2375
|
// src/client/providerStatusWidget.ts
|
|
2094
|
-
var
|
|
2095
|
-
var
|
|
2096
|
-
var
|
|
2376
|
+
var DEFAULT_TITLE7 = "Voice Providers";
|
|
2377
|
+
var DEFAULT_DESCRIPTION7 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
2378
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2097
2379
|
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
2098
|
-
var
|
|
2380
|
+
var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
2099
2381
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
2100
2382
|
var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
|
|
2101
2383
|
var getProviderDetail = (provider) => {
|
|
@@ -2137,37 +2419,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
2137
2419
|
const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
|
|
2138
2420
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
2139
2421
|
return {
|
|
2140
|
-
description: options.description ??
|
|
2422
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
2141
2423
|
error: snapshot.error,
|
|
2142
2424
|
isLoading: snapshot.isLoading,
|
|
2143
2425
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
2144
2426
|
providers,
|
|
2145
2427
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2146
|
-
title: options.title ??
|
|
2428
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
2147
2429
|
updatedAt: snapshot.updatedAt
|
|
2148
2430
|
};
|
|
2149
2431
|
};
|
|
2150
2432
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
2151
2433
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
2152
|
-
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--${
|
|
2434
|
+
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--${escapeHtml8(provider.status)}">
|
|
2153
2435
|
<header>
|
|
2154
|
-
<strong>${
|
|
2155
|
-
<span>${
|
|
2436
|
+
<strong>${escapeHtml8(provider.label)}</strong>
|
|
2437
|
+
<span>${escapeHtml8(formatStatus4(provider.status))}</span>
|
|
2156
2438
|
</header>
|
|
2157
|
-
<p>${
|
|
2439
|
+
<p>${escapeHtml8(provider.detail)}</p>
|
|
2158
2440
|
<dl>${provider.rows.map((row) => `<div>
|
|
2159
|
-
<dt>${
|
|
2160
|
-
<dd>${
|
|
2441
|
+
<dt>${escapeHtml8(row.label)}</dt>
|
|
2442
|
+
<dd>${escapeHtml8(row.value)}</dd>
|
|
2161
2443
|
</div>`).join("")}</dl>
|
|
2162
2444
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
2163
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
2445
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml8(model.status)}">
|
|
2164
2446
|
<header class="absolute-voice-provider-status__header">
|
|
2165
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
2166
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
2447
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml8(model.title)}</span>
|
|
2448
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml8(model.label)}</strong>
|
|
2167
2449
|
</header>
|
|
2168
|
-
<p class="absolute-voice-provider-status__description">${
|
|
2450
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml8(model.description)}</p>
|
|
2169
2451
|
${providers}
|
|
2170
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
2452
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
2171
2453
|
</section>`;
|
|
2172
2454
|
};
|
|
2173
2455
|
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}`;
|
|
@@ -2209,13 +2491,13 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
2209
2491
|
};
|
|
2210
2492
|
|
|
2211
2493
|
// src/vue/useVoiceProviderStatus.ts
|
|
2212
|
-
import { onUnmounted as
|
|
2494
|
+
import { onUnmounted as onUnmounted8, ref as ref6, shallowRef as shallowRef7 } from "vue";
|
|
2213
2495
|
function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
|
|
2214
2496
|
const store = createVoiceProviderStatusStore(path, options);
|
|
2215
|
-
const error =
|
|
2216
|
-
const isLoading =
|
|
2217
|
-
const providers =
|
|
2218
|
-
const updatedAt =
|
|
2497
|
+
const error = ref6(null);
|
|
2498
|
+
const isLoading = ref6(false);
|
|
2499
|
+
const providers = shallowRef7([]);
|
|
2500
|
+
const updatedAt = ref6(undefined);
|
|
2219
2501
|
const sync = () => {
|
|
2220
2502
|
const snapshot = store.getSnapshot();
|
|
2221
2503
|
error.value = snapshot.error;
|
|
@@ -2226,7 +2508,7 @@ function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
|
|
|
2226
2508
|
const unsubscribe = store.subscribe(sync);
|
|
2227
2509
|
sync();
|
|
2228
2510
|
store.refresh().catch(() => {});
|
|
2229
|
-
|
|
2511
|
+
onUnmounted8(() => {
|
|
2230
2512
|
unsubscribe();
|
|
2231
2513
|
store.close();
|
|
2232
2514
|
});
|
|
@@ -2240,7 +2522,7 @@ function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
|
|
|
2240
2522
|
}
|
|
2241
2523
|
|
|
2242
2524
|
// src/vue/VoiceProviderStatus.ts
|
|
2243
|
-
var VoiceProviderStatus =
|
|
2525
|
+
var VoiceProviderStatus = defineComponent8({
|
|
2244
2526
|
name: "VoiceProviderStatus",
|
|
2245
2527
|
props: {
|
|
2246
2528
|
class: {
|
|
@@ -2277,41 +2559,41 @@ var VoiceProviderStatus = defineComponent7({
|
|
|
2277
2559
|
providers: status.providers.value,
|
|
2278
2560
|
updatedAt: status.updatedAt.value
|
|
2279
2561
|
}, options));
|
|
2280
|
-
return () =>
|
|
2562
|
+
return () => h8("section", {
|
|
2281
2563
|
class: [
|
|
2282
2564
|
"absolute-voice-provider-status",
|
|
2283
2565
|
`absolute-voice-provider-status--${model.value.status}`,
|
|
2284
2566
|
props.class
|
|
2285
2567
|
]
|
|
2286
2568
|
}, [
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2569
|
+
h8("header", { class: "absolute-voice-provider-status__header" }, [
|
|
2570
|
+
h8("span", { class: "absolute-voice-provider-status__eyebrow" }, model.value.title),
|
|
2571
|
+
h8("strong", { class: "absolute-voice-provider-status__label" }, model.value.label)
|
|
2290
2572
|
]),
|
|
2291
|
-
|
|
2292
|
-
model.value.providers.length ?
|
|
2573
|
+
h8("p", { class: "absolute-voice-provider-status__description" }, model.value.description),
|
|
2574
|
+
model.value.providers.length ? h8("div", { class: "absolute-voice-provider-status__providers" }, model.value.providers.map((provider) => h8("article", {
|
|
2293
2575
|
class: [
|
|
2294
2576
|
"absolute-voice-provider-status__provider",
|
|
2295
2577
|
`absolute-voice-provider-status__provider--${provider.status}`
|
|
2296
2578
|
],
|
|
2297
2579
|
key: provider.provider
|
|
2298
2580
|
}, [
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2581
|
+
h8("header", [
|
|
2582
|
+
h8("strong", provider.label),
|
|
2583
|
+
h8("span", provider.status)
|
|
2302
2584
|
]),
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2585
|
+
h8("p", provider.detail),
|
|
2586
|
+
h8("dl", provider.rows.map((row) => h8("div", { key: row.label }, [
|
|
2587
|
+
h8("dt", row.label),
|
|
2588
|
+
h8("dd", row.value)
|
|
2307
2589
|
])))
|
|
2308
|
-
]))) :
|
|
2309
|
-
model.value.error ?
|
|
2590
|
+
]))) : h8("p", { class: "absolute-voice-provider-status__empty" }, "Run voice traffic to see provider health."),
|
|
2591
|
+
model.value.error ? h8("p", { class: "absolute-voice-provider-status__error" }, model.value.error) : null
|
|
2310
2592
|
]);
|
|
2311
2593
|
}
|
|
2312
2594
|
});
|
|
2313
2595
|
// src/vue/VoiceRoutingStatus.ts
|
|
2314
|
-
import { computed as computed4, defineComponent as
|
|
2596
|
+
import { computed as computed4, defineComponent as defineComponent9, h as h9 } from "vue";
|
|
2315
2597
|
|
|
2316
2598
|
// src/client/routingStatus.ts
|
|
2317
2599
|
var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
|
|
@@ -2394,9 +2676,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
2394
2676
|
};
|
|
2395
2677
|
|
|
2396
2678
|
// src/client/routingStatusWidget.ts
|
|
2397
|
-
var
|
|
2398
|
-
var
|
|
2399
|
-
var
|
|
2679
|
+
var DEFAULT_TITLE8 = "Voice Routing";
|
|
2680
|
+
var DEFAULT_DESCRIPTION8 = "Latest provider routing decision from the self-hosted trace store.";
|
|
2681
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2400
2682
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
2401
2683
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
2402
2684
|
const decision = snapshot.decision;
|
|
@@ -2420,30 +2702,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
2420
2702
|
] : [];
|
|
2421
2703
|
return {
|
|
2422
2704
|
decision,
|
|
2423
|
-
description: options.description ??
|
|
2705
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
2424
2706
|
error: snapshot.error,
|
|
2425
2707
|
isLoading: snapshot.isLoading,
|
|
2426
2708
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
2427
2709
|
rows,
|
|
2428
2710
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2429
|
-
title: options.title ??
|
|
2711
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
2430
2712
|
updatedAt: snapshot.updatedAt
|
|
2431
2713
|
};
|
|
2432
2714
|
};
|
|
2433
2715
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
2434
2716
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
2435
2717
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
2436
|
-
<span>${
|
|
2437
|
-
<strong>${
|
|
2718
|
+
<span>${escapeHtml9(row.label)}</span>
|
|
2719
|
+
<strong>${escapeHtml9(row.value)}</strong>
|
|
2438
2720
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
2439
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
2721
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml9(model.status)}">
|
|
2440
2722
|
<header class="absolute-voice-routing-status__header">
|
|
2441
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
2442
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
2723
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml9(model.title)}</span>
|
|
2724
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml9(model.label)}</strong>
|
|
2443
2725
|
</header>
|
|
2444
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2726
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml9(model.description)}</p>
|
|
2445
2727
|
${rows}
|
|
2446
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2728
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
2447
2729
|
</section>`;
|
|
2448
2730
|
};
|
|
2449
2731
|
var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}`;
|
|
@@ -2485,13 +2767,13 @@ var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status"
|
|
|
2485
2767
|
};
|
|
2486
2768
|
|
|
2487
2769
|
// src/vue/useVoiceRoutingStatus.ts
|
|
2488
|
-
import { onUnmounted as
|
|
2770
|
+
import { onUnmounted as onUnmounted9, ref as ref7, shallowRef as shallowRef8 } from "vue";
|
|
2489
2771
|
function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
|
|
2490
2772
|
const store = createVoiceRoutingStatusStore(path, options);
|
|
2491
|
-
const decision =
|
|
2492
|
-
const error =
|
|
2493
|
-
const isLoading =
|
|
2494
|
-
const updatedAt =
|
|
2773
|
+
const decision = shallowRef8(null);
|
|
2774
|
+
const error = ref7(null);
|
|
2775
|
+
const isLoading = ref7(false);
|
|
2776
|
+
const updatedAt = ref7(undefined);
|
|
2495
2777
|
const sync = () => {
|
|
2496
2778
|
const snapshot = store.getSnapshot();
|
|
2497
2779
|
decision.value = snapshot.decision;
|
|
@@ -2502,7 +2784,7 @@ function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
|
|
|
2502
2784
|
const unsubscribe = store.subscribe(sync);
|
|
2503
2785
|
sync();
|
|
2504
2786
|
store.refresh().catch(() => {});
|
|
2505
|
-
|
|
2787
|
+
onUnmounted9(() => {
|
|
2506
2788
|
unsubscribe();
|
|
2507
2789
|
store.close();
|
|
2508
2790
|
});
|
|
@@ -2516,7 +2798,7 @@ function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
|
|
|
2516
2798
|
}
|
|
2517
2799
|
|
|
2518
2800
|
// src/vue/VoiceRoutingStatus.ts
|
|
2519
|
-
var VoiceRoutingStatus =
|
|
2801
|
+
var VoiceRoutingStatus = defineComponent9({
|
|
2520
2802
|
name: "VoiceRoutingStatus",
|
|
2521
2803
|
props: {
|
|
2522
2804
|
class: {
|
|
@@ -2553,28 +2835,28 @@ var VoiceRoutingStatus = defineComponent8({
|
|
|
2553
2835
|
isLoading: status.isLoading.value,
|
|
2554
2836
|
updatedAt: status.updatedAt.value
|
|
2555
2837
|
}, options));
|
|
2556
|
-
return () =>
|
|
2838
|
+
return () => h9("section", {
|
|
2557
2839
|
class: [
|
|
2558
2840
|
"absolute-voice-routing-status",
|
|
2559
2841
|
`absolute-voice-routing-status--${model.value.status}`,
|
|
2560
2842
|
props.class
|
|
2561
2843
|
]
|
|
2562
2844
|
}, [
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2845
|
+
h9("header", { class: "absolute-voice-routing-status__header" }, [
|
|
2846
|
+
h9("span", { class: "absolute-voice-routing-status__eyebrow" }, model.value.title),
|
|
2847
|
+
h9("strong", { class: "absolute-voice-routing-status__label" }, model.value.label)
|
|
2566
2848
|
]),
|
|
2567
|
-
|
|
2568
|
-
model.value.rows.length ?
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
]))) :
|
|
2572
|
-
model.value.error ?
|
|
2849
|
+
h9("p", { class: "absolute-voice-routing-status__description" }, model.value.description),
|
|
2850
|
+
model.value.rows.length ? h9("div", { class: "absolute-voice-routing-status__grid" }, model.value.rows.map((row) => h9("div", { key: row.label }, [
|
|
2851
|
+
h9("span", row.label),
|
|
2852
|
+
h9("strong", row.value)
|
|
2853
|
+
]))) : h9("p", { class: "absolute-voice-routing-status__empty" }, "Start a voice session to see the selected provider."),
|
|
2854
|
+
model.value.error ? h9("p", { class: "absolute-voice-routing-status__error" }, model.value.error) : null
|
|
2573
2855
|
]);
|
|
2574
2856
|
}
|
|
2575
2857
|
});
|
|
2576
2858
|
// src/vue/useVoiceAgentSquadStatus.ts
|
|
2577
|
-
import { onUnmounted as
|
|
2859
|
+
import { onUnmounted as onUnmounted10, ref as ref8, shallowRef as shallowRef9 } from "vue";
|
|
2578
2860
|
|
|
2579
2861
|
// src/client/traceTimeline.ts
|
|
2580
2862
|
var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
|
|
@@ -2733,11 +3015,11 @@ var createVoiceAgentSquadStatusStore = (path = "/api/voice-traces", options = {}
|
|
|
2733
3015
|
// src/vue/useVoiceAgentSquadStatus.ts
|
|
2734
3016
|
function useVoiceAgentSquadStatus(path = "/api/voice-traces", options = {}) {
|
|
2735
3017
|
const store = createVoiceAgentSquadStatusStore(path, options);
|
|
2736
|
-
const current =
|
|
2737
|
-
const error =
|
|
2738
|
-
const isLoading =
|
|
2739
|
-
const report =
|
|
2740
|
-
const updatedAt =
|
|
3018
|
+
const current = shallowRef9(undefined);
|
|
3019
|
+
const error = ref8(null);
|
|
3020
|
+
const isLoading = ref8(false);
|
|
3021
|
+
const report = shallowRef9(undefined);
|
|
3022
|
+
const updatedAt = ref8(undefined);
|
|
2741
3023
|
const sync = () => {
|
|
2742
3024
|
const snapshot = store.getSnapshot();
|
|
2743
3025
|
current.value = snapshot.report.current;
|
|
@@ -2751,7 +3033,7 @@ function useVoiceAgentSquadStatus(path = "/api/voice-traces", options = {}) {
|
|
|
2751
3033
|
if (typeof window !== "undefined") {
|
|
2752
3034
|
store.refresh().catch(() => {});
|
|
2753
3035
|
}
|
|
2754
|
-
|
|
3036
|
+
onUnmounted10(() => {
|
|
2755
3037
|
unsubscribe();
|
|
2756
3038
|
store.close();
|
|
2757
3039
|
});
|
|
@@ -2765,7 +3047,7 @@ function useVoiceAgentSquadStatus(path = "/api/voice-traces", options = {}) {
|
|
|
2765
3047
|
};
|
|
2766
3048
|
}
|
|
2767
3049
|
// src/vue/VoiceTurnLatency.ts
|
|
2768
|
-
import { computed as computed5, defineComponent as
|
|
3050
|
+
import { computed as computed5, defineComponent as defineComponent10, h as h10 } from "vue";
|
|
2769
3051
|
|
|
2770
3052
|
// src/client/turnLatency.ts
|
|
2771
3053
|
var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
|
|
@@ -2871,10 +3153,10 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
|
|
|
2871
3153
|
};
|
|
2872
3154
|
|
|
2873
3155
|
// src/client/turnLatencyWidget.ts
|
|
2874
|
-
var
|
|
2875
|
-
var
|
|
3156
|
+
var DEFAULT_TITLE9 = "Turn Latency";
|
|
3157
|
+
var DEFAULT_DESCRIPTION9 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
2876
3158
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
2877
|
-
var
|
|
3159
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2878
3160
|
var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
2879
3161
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
2880
3162
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -2888,39 +3170,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
2888
3170
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2889
3171
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2890
3172
|
return {
|
|
2891
|
-
description: options.description ??
|
|
3173
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
2892
3174
|
error: snapshot.error,
|
|
2893
3175
|
isLoading: snapshot.isLoading,
|
|
2894
3176
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2895
3177
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
2896
3178
|
showProofAction: Boolean(options.proofPath),
|
|
2897
3179
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2898
|
-
title: options.title ??
|
|
3180
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
2899
3181
|
turns,
|
|
2900
3182
|
updatedAt: snapshot.updatedAt
|
|
2901
3183
|
};
|
|
2902
3184
|
};
|
|
2903
3185
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
2904
3186
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
2905
|
-
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--${
|
|
3187
|
+
const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${escapeHtml10(turn.status)}">
|
|
2906
3188
|
<header>
|
|
2907
|
-
<strong>${
|
|
2908
|
-
<span>${
|
|
3189
|
+
<strong>${escapeHtml10(turn.label)}</strong>
|
|
3190
|
+
<span>${escapeHtml10(turn.status)}</span>
|
|
2909
3191
|
</header>
|
|
2910
3192
|
<dl>${turn.rows.map((row) => `<div>
|
|
2911
|
-
<dt>${
|
|
2912
|
-
<dd>${
|
|
3193
|
+
<dt>${escapeHtml10(row.label)}</dt>
|
|
3194
|
+
<dd>${escapeHtml10(row.value)}</dd>
|
|
2913
3195
|
</div>`).join("")}</dl>
|
|
2914
3196
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
2915
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
3197
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml10(model.status)}">
|
|
2916
3198
|
<header class="absolute-voice-turn-latency__header">
|
|
2917
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
2918
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
3199
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml10(model.title)}</span>
|
|
3200
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml10(model.label)}</strong>
|
|
2919
3201
|
</header>
|
|
2920
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
2921
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
3202
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml10(model.description)}</p>
|
|
3203
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml10(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
2922
3204
|
${turns}
|
|
2923
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
3205
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
2924
3206
|
</section>`;
|
|
2925
3207
|
};
|
|
2926
3208
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -2971,13 +3253,13 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
2971
3253
|
};
|
|
2972
3254
|
|
|
2973
3255
|
// src/vue/useVoiceTurnLatency.ts
|
|
2974
|
-
import { onUnmounted as
|
|
3256
|
+
import { onUnmounted as onUnmounted11, shallowRef as shallowRef10 } from "vue";
|
|
2975
3257
|
function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
|
|
2976
3258
|
const store = createVoiceTurnLatencyStore(path, options);
|
|
2977
|
-
const error =
|
|
2978
|
-
const isLoading =
|
|
2979
|
-
const report =
|
|
2980
|
-
const updatedAt =
|
|
3259
|
+
const error = shallowRef10(null);
|
|
3260
|
+
const isLoading = shallowRef10(false);
|
|
3261
|
+
const report = shallowRef10();
|
|
3262
|
+
const updatedAt = shallowRef10(undefined);
|
|
2981
3263
|
const sync = () => {
|
|
2982
3264
|
const snapshot = store.getSnapshot();
|
|
2983
3265
|
error.value = snapshot.error;
|
|
@@ -2988,7 +3270,7 @@ function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
|
|
|
2988
3270
|
const unsubscribe = store.subscribe(sync);
|
|
2989
3271
|
sync();
|
|
2990
3272
|
store.refresh().catch(() => {});
|
|
2991
|
-
|
|
3273
|
+
onUnmounted11(() => {
|
|
2992
3274
|
unsubscribe();
|
|
2993
3275
|
store.close();
|
|
2994
3276
|
});
|
|
@@ -3003,7 +3285,7 @@ function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
|
|
|
3003
3285
|
}
|
|
3004
3286
|
|
|
3005
3287
|
// src/vue/VoiceTurnLatency.ts
|
|
3006
|
-
var VoiceTurnLatency =
|
|
3288
|
+
var VoiceTurnLatency = defineComponent10({
|
|
3007
3289
|
name: "VoiceTurnLatency",
|
|
3008
3290
|
props: {
|
|
3009
3291
|
class: { default: "", type: String },
|
|
@@ -3029,47 +3311,47 @@ var VoiceTurnLatency = defineComponent9({
|
|
|
3029
3311
|
report: latency.report.value,
|
|
3030
3312
|
updatedAt: latency.updatedAt.value
|
|
3031
3313
|
}, options));
|
|
3032
|
-
return () =>
|
|
3314
|
+
return () => h10("section", {
|
|
3033
3315
|
class: [
|
|
3034
3316
|
"absolute-voice-turn-latency",
|
|
3035
3317
|
`absolute-voice-turn-latency--${model.value.status}`,
|
|
3036
3318
|
props.class
|
|
3037
3319
|
]
|
|
3038
3320
|
}, [
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3321
|
+
h10("header", { class: "absolute-voice-turn-latency__header" }, [
|
|
3322
|
+
h10("span", { class: "absolute-voice-turn-latency__eyebrow" }, model.value.title),
|
|
3323
|
+
h10("strong", { class: "absolute-voice-turn-latency__label" }, model.value.label)
|
|
3042
3324
|
]),
|
|
3043
|
-
|
|
3044
|
-
model.value.showProofAction ?
|
|
3325
|
+
h10("p", { class: "absolute-voice-turn-latency__description" }, model.value.description),
|
|
3326
|
+
model.value.showProofAction ? h10("button", {
|
|
3045
3327
|
class: "absolute-voice-turn-latency__proof",
|
|
3046
3328
|
onClick: () => {
|
|
3047
3329
|
latency.runProof().catch(() => {});
|
|
3048
3330
|
},
|
|
3049
3331
|
type: "button"
|
|
3050
3332
|
}, model.value.proofLabel) : null,
|
|
3051
|
-
model.value.turns.length ?
|
|
3333
|
+
model.value.turns.length ? h10("div", { class: "absolute-voice-turn-latency__turns" }, model.value.turns.map((turn) => h10("article", {
|
|
3052
3334
|
class: [
|
|
3053
3335
|
"absolute-voice-turn-latency__turn",
|
|
3054
3336
|
`absolute-voice-turn-latency__turn--${turn.status}`
|
|
3055
3337
|
],
|
|
3056
3338
|
key: `${turn.sessionId}:${turn.turnId}`
|
|
3057
3339
|
}, [
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3340
|
+
h10("header", [
|
|
3341
|
+
h10("strong", turn.label),
|
|
3342
|
+
h10("span", turn.status)
|
|
3061
3343
|
]),
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3344
|
+
h10("dl", turn.rows.map((row) => h10("div", { key: row.label }, [
|
|
3345
|
+
h10("dt", row.label),
|
|
3346
|
+
h10("dd", row.value)
|
|
3065
3347
|
])))
|
|
3066
|
-
]))) :
|
|
3067
|
-
model.value.error ?
|
|
3348
|
+
]))) : h10("p", { class: "absolute-voice-turn-latency__empty" }, "Complete a voice turn to see latency diagnostics."),
|
|
3349
|
+
model.value.error ? h10("p", { class: "absolute-voice-turn-latency__error" }, model.value.error) : null
|
|
3068
3350
|
]);
|
|
3069
3351
|
}
|
|
3070
3352
|
});
|
|
3071
3353
|
// src/vue/VoiceTurnQuality.ts
|
|
3072
|
-
import { computed as computed6, defineComponent as
|
|
3354
|
+
import { computed as computed6, defineComponent as defineComponent11, h as h11 } from "vue";
|
|
3073
3355
|
|
|
3074
3356
|
// src/client/turnQuality.ts
|
|
3075
3357
|
var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
|
|
@@ -3151,9 +3433,9 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
3151
3433
|
};
|
|
3152
3434
|
|
|
3153
3435
|
// src/client/turnQualityWidget.ts
|
|
3154
|
-
var
|
|
3155
|
-
var
|
|
3156
|
-
var
|
|
3436
|
+
var DEFAULT_TITLE10 = "Turn Quality";
|
|
3437
|
+
var DEFAULT_DESCRIPTION10 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
3438
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3157
3439
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
3158
3440
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
3159
3441
|
var getTurnDetail = (turn) => {
|
|
@@ -3191,37 +3473,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
3191
3473
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
3192
3474
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
3193
3475
|
return {
|
|
3194
|
-
description: options.description ??
|
|
3476
|
+
description: options.description ?? DEFAULT_DESCRIPTION10,
|
|
3195
3477
|
error: snapshot.error,
|
|
3196
3478
|
isLoading: snapshot.isLoading,
|
|
3197
3479
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
3198
3480
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3199
|
-
title: options.title ??
|
|
3481
|
+
title: options.title ?? DEFAULT_TITLE10,
|
|
3200
3482
|
turns,
|
|
3201
3483
|
updatedAt: snapshot.updatedAt
|
|
3202
3484
|
};
|
|
3203
3485
|
};
|
|
3204
3486
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
3205
3487
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
3206
|
-
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--${
|
|
3488
|
+
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--${escapeHtml11(turn.status)}">
|
|
3207
3489
|
<header>
|
|
3208
|
-
<strong>${
|
|
3209
|
-
<span>${
|
|
3490
|
+
<strong>${escapeHtml11(turn.label)}</strong>
|
|
3491
|
+
<span>${escapeHtml11(turn.status)}</span>
|
|
3210
3492
|
</header>
|
|
3211
|
-
<p>${
|
|
3493
|
+
<p>${escapeHtml11(turn.detail)}</p>
|
|
3212
3494
|
<dl>${turn.rows.map((row) => `<div>
|
|
3213
|
-
<dt>${
|
|
3214
|
-
<dd>${
|
|
3495
|
+
<dt>${escapeHtml11(row.label)}</dt>
|
|
3496
|
+
<dd>${escapeHtml11(row.value)}</dd>
|
|
3215
3497
|
</div>`).join("")}</dl>
|
|
3216
3498
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
3217
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
3499
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml11(model.status)}">
|
|
3218
3500
|
<header class="absolute-voice-turn-quality__header">
|
|
3219
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
3220
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
3501
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml11(model.title)}</span>
|
|
3502
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml11(model.label)}</strong>
|
|
3221
3503
|
</header>
|
|
3222
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
3504
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml11(model.description)}</p>
|
|
3223
3505
|
${turns}
|
|
3224
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
3506
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
3225
3507
|
</section>`;
|
|
3226
3508
|
};
|
|
3227
3509
|
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}`;
|
|
@@ -3263,13 +3545,13 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
3263
3545
|
};
|
|
3264
3546
|
|
|
3265
3547
|
// src/vue/useVoiceTurnQuality.ts
|
|
3266
|
-
import { onUnmounted as
|
|
3548
|
+
import { onUnmounted as onUnmounted12, shallowRef as shallowRef11 } from "vue";
|
|
3267
3549
|
function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
|
|
3268
3550
|
const store = createVoiceTurnQualityStore(path, options);
|
|
3269
|
-
const error =
|
|
3270
|
-
const isLoading =
|
|
3271
|
-
const report =
|
|
3272
|
-
const updatedAt =
|
|
3551
|
+
const error = shallowRef11(null);
|
|
3552
|
+
const isLoading = shallowRef11(false);
|
|
3553
|
+
const report = shallowRef11();
|
|
3554
|
+
const updatedAt = shallowRef11(undefined);
|
|
3273
3555
|
const sync = () => {
|
|
3274
3556
|
const snapshot = store.getSnapshot();
|
|
3275
3557
|
error.value = snapshot.error;
|
|
@@ -3280,7 +3562,7 @@ function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
|
|
|
3280
3562
|
const unsubscribe = store.subscribe(sync);
|
|
3281
3563
|
sync();
|
|
3282
3564
|
store.refresh().catch(() => {});
|
|
3283
|
-
|
|
3565
|
+
onUnmounted12(() => {
|
|
3284
3566
|
unsubscribe();
|
|
3285
3567
|
store.close();
|
|
3286
3568
|
});
|
|
@@ -3288,7 +3570,7 @@ function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
|
|
|
3288
3570
|
}
|
|
3289
3571
|
|
|
3290
3572
|
// src/vue/VoiceTurnQuality.ts
|
|
3291
|
-
var VoiceTurnQuality =
|
|
3573
|
+
var VoiceTurnQuality = defineComponent11({
|
|
3292
3574
|
name: "VoiceTurnQuality",
|
|
3293
3575
|
props: {
|
|
3294
3576
|
class: { default: "", type: String },
|
|
@@ -3310,152 +3592,39 @@ var VoiceTurnQuality = defineComponent10({
|
|
|
3310
3592
|
report: quality.report.value,
|
|
3311
3593
|
updatedAt: quality.updatedAt.value
|
|
3312
3594
|
}, options));
|
|
3313
|
-
return () =>
|
|
3595
|
+
return () => h11("section", {
|
|
3314
3596
|
class: [
|
|
3315
3597
|
"absolute-voice-turn-quality",
|
|
3316
3598
|
`absolute-voice-turn-quality--${model.value.status}`,
|
|
3317
3599
|
props.class
|
|
3318
3600
|
]
|
|
3319
3601
|
}, [
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3602
|
+
h11("header", { class: "absolute-voice-turn-quality__header" }, [
|
|
3603
|
+
h11("span", { class: "absolute-voice-turn-quality__eyebrow" }, model.value.title),
|
|
3604
|
+
h11("strong", { class: "absolute-voice-turn-quality__label" }, model.value.label)
|
|
3323
3605
|
]),
|
|
3324
|
-
|
|
3325
|
-
model.value.turns.length ?
|
|
3606
|
+
h11("p", { class: "absolute-voice-turn-quality__description" }, model.value.description),
|
|
3607
|
+
model.value.turns.length ? h11("div", { class: "absolute-voice-turn-quality__turns" }, model.value.turns.map((turn) => h11("article", {
|
|
3326
3608
|
class: [
|
|
3327
3609
|
"absolute-voice-turn-quality__turn",
|
|
3328
3610
|
`absolute-voice-turn-quality__turn--${turn.status}`
|
|
3329
3611
|
],
|
|
3330
3612
|
key: `${turn.sessionId}:${turn.turnId}`
|
|
3331
3613
|
}, [
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3614
|
+
h11("header", [
|
|
3615
|
+
h11("strong", turn.label),
|
|
3616
|
+
h11("span", turn.status)
|
|
3335
3617
|
]),
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3618
|
+
h11("p", turn.detail),
|
|
3619
|
+
h11("dl", turn.rows.map((row) => h11("div", { key: row.label }, [
|
|
3620
|
+
h11("dt", row.label),
|
|
3621
|
+
h11("dd", row.value)
|
|
3340
3622
|
])))
|
|
3341
|
-
]))) :
|
|
3342
|
-
model.value.error ?
|
|
3623
|
+
]))) : h11("p", { class: "absolute-voice-turn-quality__empty" }, "Complete a voice turn to see STT quality diagnostics."),
|
|
3624
|
+
model.value.error ? h11("p", { class: "absolute-voice-turn-quality__error" }, model.value.error) : null
|
|
3343
3625
|
]);
|
|
3344
3626
|
}
|
|
3345
3627
|
});
|
|
3346
|
-
// src/vue/useVoicePlatformCoverage.ts
|
|
3347
|
-
import { onUnmounted as onUnmounted12, ref as ref8, shallowRef as shallowRef11 } from "vue";
|
|
3348
|
-
|
|
3349
|
-
// src/client/platformCoverage.ts
|
|
3350
|
-
var fetchVoicePlatformCoverage = async (path = "/api/voice/platform-coverage", options = {}) => {
|
|
3351
|
-
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3352
|
-
const response = await fetchImpl(path);
|
|
3353
|
-
if (!response.ok) {
|
|
3354
|
-
throw new Error(`Voice platform coverage failed: HTTP ${response.status}`);
|
|
3355
|
-
}
|
|
3356
|
-
return await response.json();
|
|
3357
|
-
};
|
|
3358
|
-
var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", options = {}) => {
|
|
3359
|
-
const listeners = new Set;
|
|
3360
|
-
let closed = false;
|
|
3361
|
-
let timer;
|
|
3362
|
-
let snapshot = {
|
|
3363
|
-
error: null,
|
|
3364
|
-
isLoading: false
|
|
3365
|
-
};
|
|
3366
|
-
const emit = () => {
|
|
3367
|
-
for (const listener of listeners) {
|
|
3368
|
-
listener();
|
|
3369
|
-
}
|
|
3370
|
-
};
|
|
3371
|
-
const refresh = async () => {
|
|
3372
|
-
if (closed) {
|
|
3373
|
-
return snapshot.report;
|
|
3374
|
-
}
|
|
3375
|
-
snapshot = {
|
|
3376
|
-
...snapshot,
|
|
3377
|
-
error: null,
|
|
3378
|
-
isLoading: true
|
|
3379
|
-
};
|
|
3380
|
-
emit();
|
|
3381
|
-
try {
|
|
3382
|
-
const report = await fetchVoicePlatformCoverage(path, options);
|
|
3383
|
-
snapshot = {
|
|
3384
|
-
error: null,
|
|
3385
|
-
isLoading: false,
|
|
3386
|
-
report,
|
|
3387
|
-
updatedAt: Date.now()
|
|
3388
|
-
};
|
|
3389
|
-
emit();
|
|
3390
|
-
return report;
|
|
3391
|
-
} catch (error) {
|
|
3392
|
-
snapshot = {
|
|
3393
|
-
...snapshot,
|
|
3394
|
-
error: error instanceof Error ? error.message : String(error),
|
|
3395
|
-
isLoading: false
|
|
3396
|
-
};
|
|
3397
|
-
emit();
|
|
3398
|
-
throw error;
|
|
3399
|
-
}
|
|
3400
|
-
};
|
|
3401
|
-
const close = () => {
|
|
3402
|
-
closed = true;
|
|
3403
|
-
if (timer) {
|
|
3404
|
-
clearInterval(timer);
|
|
3405
|
-
timer = undefined;
|
|
3406
|
-
}
|
|
3407
|
-
listeners.clear();
|
|
3408
|
-
};
|
|
3409
|
-
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
3410
|
-
timer = setInterval(() => {
|
|
3411
|
-
refresh().catch(() => {});
|
|
3412
|
-
}, options.intervalMs);
|
|
3413
|
-
}
|
|
3414
|
-
return {
|
|
3415
|
-
close,
|
|
3416
|
-
getServerSnapshot: () => snapshot,
|
|
3417
|
-
getSnapshot: () => snapshot,
|
|
3418
|
-
refresh,
|
|
3419
|
-
subscribe: (listener) => {
|
|
3420
|
-
listeners.add(listener);
|
|
3421
|
-
return () => {
|
|
3422
|
-
listeners.delete(listener);
|
|
3423
|
-
};
|
|
3424
|
-
}
|
|
3425
|
-
};
|
|
3426
|
-
};
|
|
3427
|
-
|
|
3428
|
-
// src/vue/useVoicePlatformCoverage.ts
|
|
3429
|
-
function useVoicePlatformCoverage(path = "/api/voice/platform-coverage", options = {}) {
|
|
3430
|
-
const store = createVoicePlatformCoverageStore(path, options);
|
|
3431
|
-
const error = ref8(null);
|
|
3432
|
-
const isLoading = ref8(false);
|
|
3433
|
-
const report = shallowRef11(undefined);
|
|
3434
|
-
const updatedAt = ref8(undefined);
|
|
3435
|
-
const sync = () => {
|
|
3436
|
-
const snapshot = store.getSnapshot();
|
|
3437
|
-
error.value = snapshot.error;
|
|
3438
|
-
isLoading.value = snapshot.isLoading;
|
|
3439
|
-
report.value = snapshot.report;
|
|
3440
|
-
updatedAt.value = snapshot.updatedAt;
|
|
3441
|
-
};
|
|
3442
|
-
const unsubscribe = store.subscribe(sync);
|
|
3443
|
-
sync();
|
|
3444
|
-
if (typeof window !== "undefined") {
|
|
3445
|
-
store.refresh().catch(() => {});
|
|
3446
|
-
}
|
|
3447
|
-
onUnmounted12(() => {
|
|
3448
|
-
unsubscribe();
|
|
3449
|
-
store.close();
|
|
3450
|
-
});
|
|
3451
|
-
return {
|
|
3452
|
-
error,
|
|
3453
|
-
isLoading,
|
|
3454
|
-
refresh: store.refresh,
|
|
3455
|
-
report,
|
|
3456
|
-
updatedAt
|
|
3457
|
-
};
|
|
3458
|
-
}
|
|
3459
3628
|
// src/vue/useVoiceLiveOps.ts
|
|
3460
3629
|
import { onUnmounted as onUnmounted13, ref as ref9, shallowRef as shallowRef12 } from "vue";
|
|
3461
3630
|
|
|
@@ -5292,6 +5461,7 @@ export {
|
|
|
5292
5461
|
VoiceProviderSimulationControls,
|
|
5293
5462
|
VoiceProviderContracts,
|
|
5294
5463
|
VoiceProviderCapabilities,
|
|
5464
|
+
VoicePlatformCoverage,
|
|
5295
5465
|
VoiceOpsStatus,
|
|
5296
5466
|
VoiceOpsActionCenter,
|
|
5297
5467
|
VoiceDeliveryRuntime
|