@absolutejs/voice 0.0.22-beta.459 → 0.0.22-beta.460
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/index.d.ts +1 -0
- package/dist/angular/index.js +328 -204
- package/dist/angular/voice-session-observability.service.d.ts +12 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +528 -362
- package/dist/client/sessionObservability.d.ts +19 -0
- package/dist/client/sessionObservabilityWidget.d.ts +31 -0
- package/dist/react/VoiceSessionObservability.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +716 -460
- package/dist/react/useVoiceSessionObservability.d.ts +8 -0
- package/dist/svelte/createVoiceSessionObservability.d.ts +10 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +313 -142
- package/dist/vue/VoiceSessionObservability.d.ts +23 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +589 -339
- package/dist/vue/useVoiceSessionObservability.d.ts +9 -0
- package/package.json +1 -1
package/dist/svelte/index.js
CHANGED
|
@@ -3235,6 +3235,176 @@ var createVoiceSessionSnapshot = (path, options = {}) => {
|
|
|
3235
3235
|
getViewModel: () => createVoiceSessionSnapshotViewModel(store.getSnapshot(), options)
|
|
3236
3236
|
};
|
|
3237
3237
|
};
|
|
3238
|
+
// src/client/sessionObservability.ts
|
|
3239
|
+
var fetchVoiceSessionObservability = async (path, options = {}) => {
|
|
3240
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3241
|
+
const response = await fetchImpl(path);
|
|
3242
|
+
if (!response.ok) {
|
|
3243
|
+
throw new Error(`Voice session observability failed: HTTP ${response.status}`);
|
|
3244
|
+
}
|
|
3245
|
+
return await response.json();
|
|
3246
|
+
};
|
|
3247
|
+
var createVoiceSessionObservabilityStore = (path, options = {}) => {
|
|
3248
|
+
const listeners = new Set;
|
|
3249
|
+
let closed = false;
|
|
3250
|
+
let timer;
|
|
3251
|
+
let snapshot = {
|
|
3252
|
+
error: null,
|
|
3253
|
+
isLoading: false,
|
|
3254
|
+
report: null
|
|
3255
|
+
};
|
|
3256
|
+
const emit = () => {
|
|
3257
|
+
for (const listener of listeners) {
|
|
3258
|
+
listener();
|
|
3259
|
+
}
|
|
3260
|
+
};
|
|
3261
|
+
const refresh = async () => {
|
|
3262
|
+
if (closed) {
|
|
3263
|
+
return snapshot.report;
|
|
3264
|
+
}
|
|
3265
|
+
snapshot = {
|
|
3266
|
+
...snapshot,
|
|
3267
|
+
error: null,
|
|
3268
|
+
isLoading: true
|
|
3269
|
+
};
|
|
3270
|
+
emit();
|
|
3271
|
+
try {
|
|
3272
|
+
const report = await fetchVoiceSessionObservability(path, options);
|
|
3273
|
+
snapshot = {
|
|
3274
|
+
error: null,
|
|
3275
|
+
isLoading: false,
|
|
3276
|
+
report,
|
|
3277
|
+
updatedAt: Date.now()
|
|
3278
|
+
};
|
|
3279
|
+
emit();
|
|
3280
|
+
return report;
|
|
3281
|
+
} catch (error) {
|
|
3282
|
+
snapshot = {
|
|
3283
|
+
...snapshot,
|
|
3284
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3285
|
+
isLoading: false
|
|
3286
|
+
};
|
|
3287
|
+
emit();
|
|
3288
|
+
throw error;
|
|
3289
|
+
}
|
|
3290
|
+
};
|
|
3291
|
+
const close = () => {
|
|
3292
|
+
closed = true;
|
|
3293
|
+
if (timer) {
|
|
3294
|
+
clearInterval(timer);
|
|
3295
|
+
timer = undefined;
|
|
3296
|
+
}
|
|
3297
|
+
listeners.clear();
|
|
3298
|
+
};
|
|
3299
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
3300
|
+
timer = setInterval(() => {
|
|
3301
|
+
refresh().catch(() => {});
|
|
3302
|
+
}, options.intervalMs);
|
|
3303
|
+
}
|
|
3304
|
+
return {
|
|
3305
|
+
close,
|
|
3306
|
+
getServerSnapshot: () => snapshot,
|
|
3307
|
+
getSnapshot: () => snapshot,
|
|
3308
|
+
refresh,
|
|
3309
|
+
subscribe: (listener) => {
|
|
3310
|
+
listeners.add(listener);
|
|
3311
|
+
return () => {
|
|
3312
|
+
listeners.delete(listener);
|
|
3313
|
+
};
|
|
3314
|
+
}
|
|
3315
|
+
};
|
|
3316
|
+
};
|
|
3317
|
+
|
|
3318
|
+
// src/client/sessionObservabilityWidget.ts
|
|
3319
|
+
var DEFAULT_TITLE6 = "Session Observability";
|
|
3320
|
+
var DEFAULT_DESCRIPTION6 = "One support/debug report for a voice call across traces, provider recovery, tools, handoffs, guardrails, turn waterfalls, and incident handoff.";
|
|
3321
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3322
|
+
var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
3323
|
+
var createVoiceSessionObservabilityViewModel = (snapshot, options = {}) => {
|
|
3324
|
+
const report = snapshot.report;
|
|
3325
|
+
const turns = (report?.turns ?? []).slice(0, options.maxTurns ?? 3).map((turn) => ({
|
|
3326
|
+
...turn,
|
|
3327
|
+
durationLabel: formatMs(turn.durationMs),
|
|
3328
|
+
label: `${turn.transcripts} transcripts / ${turn.toolCalls} tools / ${turn.providerDecisions} provider decisions`
|
|
3329
|
+
}));
|
|
3330
|
+
return {
|
|
3331
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
3332
|
+
error: snapshot.error,
|
|
3333
|
+
isLoading: snapshot.isLoading,
|
|
3334
|
+
label: snapshot.error ? "Unavailable" : report ? `${report.summary.turns} turns / ${report.summary.fallbacks} fallbacks / ${report.summary.errors} errors` : snapshot.isLoading ? "Checking" : "No session loaded",
|
|
3335
|
+
links: report?.links ?? [],
|
|
3336
|
+
sessionId: report?.sessionId,
|
|
3337
|
+
status: snapshot.error ? "error" : report?.status === "failed" ? "failed" : report?.status === "warning" ? "warning" : report ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3338
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
3339
|
+
turns,
|
|
3340
|
+
updatedAt: snapshot.updatedAt
|
|
3341
|
+
};
|
|
3342
|
+
};
|
|
3343
|
+
var renderLinks = (links) => links.length ? `<p class="absolute-voice-session-observability__actions">${links.map((link) => `<a href="${escapeHtml8(link.href)}">${escapeHtml8(link.label)}</a>`).join("")}</p>` : "";
|
|
3344
|
+
var renderVoiceSessionObservabilityHTML = (snapshot, options = {}) => {
|
|
3345
|
+
const model = createVoiceSessionObservabilityViewModel(snapshot, options);
|
|
3346
|
+
const turns = model.turns.length ? `<div class="absolute-voice-session-observability__turns">${model.turns.map((turn) => `<article class="absolute-voice-session-observability__turn"><header><strong>${escapeHtml8(turn.turnId)}</strong><span>${escapeHtml8(turn.durationLabel)}</span></header><p>${escapeHtml8(turn.label)}</p></article>`).join("")}</div>` : '<p class="absolute-voice-session-observability__empty">Open a voice session to see turn waterfalls.</p>';
|
|
3347
|
+
return `<section class="absolute-voice-session-observability absolute-voice-session-observability--${escapeHtml8(model.status)}">
|
|
3348
|
+
<header class="absolute-voice-session-observability__header">
|
|
3349
|
+
<span class="absolute-voice-session-observability__eyebrow">${escapeHtml8(model.title)}</span>
|
|
3350
|
+
<strong class="absolute-voice-session-observability__label">${escapeHtml8(model.label)}</strong>
|
|
3351
|
+
</header>
|
|
3352
|
+
<p class="absolute-voice-session-observability__description">${escapeHtml8(model.description)}</p>
|
|
3353
|
+
${model.sessionId ? `<p class="absolute-voice-session-observability__session">${escapeHtml8(model.sessionId)}</p>` : ""}
|
|
3354
|
+
${renderLinks(model.links)}
|
|
3355
|
+
${turns}
|
|
3356
|
+
${model.error ? `<p class="absolute-voice-session-observability__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
3357
|
+
</section>`;
|
|
3358
|
+
};
|
|
3359
|
+
var getVoiceSessionObservabilityCSS = () => `.absolute-voice-session-observability{border:1px solid #c8d9bf;border-radius:20px;background:#fbfff3;color:#18220d;padding:18px;box-shadow:0 18px 40px rgba(24,34,13,.12);font-family:inherit}.absolute-voice-session-observability--error,.absolute-voice-session-observability--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-session-observability--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-session-observability__header,.absolute-voice-session-observability__turn header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-session-observability__eyebrow{color:#4d7c0f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-session-observability__label{font-size:24px;line-height:1}.absolute-voice-session-observability__description,.absolute-voice-session-observability__turn p,.absolute-voice-session-observability__empty,.absolute-voice-session-observability__session{color:#4b5f3e}.absolute-voice-session-observability__actions{display:flex;flex-wrap:wrap;gap:10px;margin:14px 0}.absolute-voice-session-observability__actions a{color:#3f6212;font-weight:800}.absolute-voice-session-observability__turns{display:grid;gap:12px;margin-top:14px}.absolute-voice-session-observability__turn{background:#fff;border:1px solid #dcebcf;border-radius:16px;padding:14px}.absolute-voice-session-observability__turn p{margin:10px 0 0}.absolute-voice-session-observability__empty{margin:14px 0 0}.absolute-voice-session-observability__error{color:#9f1239;font-weight:700}`;
|
|
3360
|
+
var mountVoiceSessionObservability = (element, path, options = {}) => {
|
|
3361
|
+
const store = createVoiceSessionObservabilityStore(path, options);
|
|
3362
|
+
const render = () => {
|
|
3363
|
+
element.innerHTML = renderVoiceSessionObservabilityHTML(store.getSnapshot(), options);
|
|
3364
|
+
};
|
|
3365
|
+
const unsubscribe = store.subscribe(render);
|
|
3366
|
+
render();
|
|
3367
|
+
store.refresh().catch(() => {});
|
|
3368
|
+
return {
|
|
3369
|
+
close: () => {
|
|
3370
|
+
unsubscribe();
|
|
3371
|
+
store.close();
|
|
3372
|
+
},
|
|
3373
|
+
refresh: store.refresh
|
|
3374
|
+
};
|
|
3375
|
+
};
|
|
3376
|
+
var defineVoiceSessionObservabilityElement = (tagName = "absolute-voice-session-observability") => {
|
|
3377
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
3378
|
+
return;
|
|
3379
|
+
}
|
|
3380
|
+
customElements.define(tagName, class AbsoluteVoiceSessionObservabilityElement extends HTMLElement {
|
|
3381
|
+
mounted;
|
|
3382
|
+
connectedCallback() {
|
|
3383
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
3384
|
+
const maxTurns = Number(this.getAttribute("max-turns") ?? 3);
|
|
3385
|
+
this.mounted = mountVoiceSessionObservability(this, this.getAttribute("path") ?? "/api/voice/session-observability/latest", {
|
|
3386
|
+
description: this.getAttribute("description") ?? undefined,
|
|
3387
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
3388
|
+
maxTurns: Number.isFinite(maxTurns) ? maxTurns : 3,
|
|
3389
|
+
title: this.getAttribute("title") ?? undefined
|
|
3390
|
+
});
|
|
3391
|
+
}
|
|
3392
|
+
disconnectedCallback() {
|
|
3393
|
+
this.mounted?.close();
|
|
3394
|
+
this.mounted = undefined;
|
|
3395
|
+
}
|
|
3396
|
+
});
|
|
3397
|
+
};
|
|
3398
|
+
|
|
3399
|
+
// src/svelte/createVoiceSessionObservability.ts
|
|
3400
|
+
var createVoiceSessionObservability = (path = "/api/voice/session-observability/latest", options = {}) => {
|
|
3401
|
+
const store = createVoiceSessionObservabilityStore(path, options);
|
|
3402
|
+
return {
|
|
3403
|
+
...store,
|
|
3404
|
+
getHTML: () => renderVoiceSessionObservabilityHTML(store.getSnapshot(), options),
|
|
3405
|
+
getViewModel: () => createVoiceSessionObservabilityViewModel(store.getSnapshot(), options)
|
|
3406
|
+
};
|
|
3407
|
+
};
|
|
3238
3408
|
// src/client/profileComparison.ts
|
|
3239
3409
|
var fetchVoiceProfileComparison = async (path = "/api/voice/real-call-profile-history", options = {}) => {
|
|
3240
3410
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -3485,7 +3655,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
3485
3655
|
};
|
|
3486
3656
|
|
|
3487
3657
|
// src/client/providerSimulationControlsWidget.ts
|
|
3488
|
-
var
|
|
3658
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3489
3659
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
3490
3660
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
3491
3661
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -3505,18 +3675,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
3505
3675
|
};
|
|
3506
3676
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
3507
3677
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
3508
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
3509
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
3678
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml9(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml9(provider.provider)} ${escapeHtml9(formatKind(options.kind))} failure</button>`).join("");
|
|
3679
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml9(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml9(provider.provider)} recovered</button>`).join("");
|
|
3510
3680
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
3511
3681
|
<header class="absolute-voice-provider-simulation__header">
|
|
3512
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
3513
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
3682
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml9(model.title)}</span>
|
|
3683
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml9(model.label)}</strong>
|
|
3514
3684
|
</header>
|
|
3515
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
3516
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
3685
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml9(model.description)}</p>
|
|
3686
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml9(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
3517
3687
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
3518
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
3519
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
3688
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml9(snapshot.error)}</p>` : ""}
|
|
3689
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml9(model.resultText)}</pre>` : ""}
|
|
3520
3690
|
</section>`;
|
|
3521
3691
|
};
|
|
3522
3692
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -3671,9 +3841,9 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
|
|
|
3671
3841
|
};
|
|
3672
3842
|
|
|
3673
3843
|
// src/client/providerCapabilitiesWidget.ts
|
|
3674
|
-
var
|
|
3675
|
-
var
|
|
3676
|
-
var
|
|
3844
|
+
var DEFAULT_TITLE7 = "Provider Capabilities";
|
|
3845
|
+
var DEFAULT_DESCRIPTION7 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
3846
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3677
3847
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3678
3848
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
3679
3849
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -3717,36 +3887,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
3717
3887
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
3718
3888
|
return {
|
|
3719
3889
|
capabilities,
|
|
3720
|
-
description: options.description ??
|
|
3890
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
3721
3891
|
error: snapshot.error,
|
|
3722
3892
|
isLoading: snapshot.isLoading,
|
|
3723
3893
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
3724
3894
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3725
|
-
title: options.title ??
|
|
3895
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
3726
3896
|
updatedAt: snapshot.updatedAt
|
|
3727
3897
|
};
|
|
3728
3898
|
};
|
|
3729
3899
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
3730
3900
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
3731
|
-
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--${
|
|
3901
|
+
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--${escapeHtml10(capability.status)}">
|
|
3732
3902
|
<header>
|
|
3733
|
-
<strong>${
|
|
3734
|
-
<span>${
|
|
3903
|
+
<strong>${escapeHtml10(capability.label)}</strong>
|
|
3904
|
+
<span>${escapeHtml10(formatStatus2(capability.status))}</span>
|
|
3735
3905
|
</header>
|
|
3736
|
-
<p>${
|
|
3906
|
+
<p>${escapeHtml10(capability.detail)}</p>
|
|
3737
3907
|
<dl>${capability.rows.map((row) => `<div>
|
|
3738
|
-
<dt>${
|
|
3739
|
-
<dd>${
|
|
3908
|
+
<dt>${escapeHtml10(row.label)}</dt>
|
|
3909
|
+
<dd>${escapeHtml10(row.value)}</dd>
|
|
3740
3910
|
</div>`).join("")}</dl>
|
|
3741
3911
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
3742
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
3912
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml10(model.status)}">
|
|
3743
3913
|
<header class="absolute-voice-provider-capabilities__header">
|
|
3744
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
3745
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
3914
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml10(model.title)}</span>
|
|
3915
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml10(model.label)}</strong>
|
|
3746
3916
|
</header>
|
|
3747
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
3917
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml10(model.description)}</p>
|
|
3748
3918
|
${capabilities}
|
|
3749
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
3919
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
3750
3920
|
</section>`;
|
|
3751
3921
|
};
|
|
3752
3922
|
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}`;
|
|
@@ -3872,9 +4042,9 @@ var createVoiceProviderContractsStore = (path = "/api/provider-contracts", optio
|
|
|
3872
4042
|
};
|
|
3873
4043
|
|
|
3874
4044
|
// src/client/providerContractsWidget.ts
|
|
3875
|
-
var
|
|
3876
|
-
var
|
|
3877
|
-
var
|
|
4045
|
+
var DEFAULT_TITLE8 = "Provider Contracts";
|
|
4046
|
+
var DEFAULT_DESCRIPTION8 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
4047
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3878
4048
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3879
4049
|
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
3880
4050
|
var contractDetail = (row) => {
|
|
@@ -3906,38 +4076,38 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
|
3906
4076
|
}));
|
|
3907
4077
|
const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
|
|
3908
4078
|
return {
|
|
3909
|
-
description: options.description ??
|
|
4079
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
3910
4080
|
error: snapshot.error,
|
|
3911
4081
|
isLoading: snapshot.isLoading,
|
|
3912
4082
|
label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
|
|
3913
4083
|
rows,
|
|
3914
4084
|
status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3915
|
-
title: options.title ??
|
|
4085
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
3916
4086
|
updatedAt: snapshot.updatedAt
|
|
3917
4087
|
};
|
|
3918
4088
|
};
|
|
3919
4089
|
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
3920
4090
|
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
3921
|
-
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--${
|
|
4091
|
+
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--${escapeHtml11(row.status)}">
|
|
3922
4092
|
<header>
|
|
3923
|
-
<strong>${
|
|
3924
|
-
<span>${
|
|
4093
|
+
<strong>${escapeHtml11(row.label)}</strong>
|
|
4094
|
+
<span>${escapeHtml11(formatStatus3(row.status))}</span>
|
|
3925
4095
|
</header>
|
|
3926
|
-
<p>${
|
|
3927
|
-
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${
|
|
4096
|
+
<p>${escapeHtml11(row.detail)}</p>
|
|
4097
|
+
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml11(remediation.href)}">${escapeHtml11(remediation.label)}</a>` : `<strong>${escapeHtml11(remediation.label)}</strong>`}<span>${escapeHtml11(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
|
|
3928
4098
|
<dl>${row.rows.map((item) => `<div>
|
|
3929
|
-
<dt>${
|
|
3930
|
-
<dd>${
|
|
4099
|
+
<dt>${escapeHtml11(item.label)}</dt>
|
|
4100
|
+
<dd>${escapeHtml11(item.value)}</dd>
|
|
3931
4101
|
</div>`).join("")}</dl>
|
|
3932
4102
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
3933
|
-
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${
|
|
4103
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml11(model.status)}">
|
|
3934
4104
|
<header class="absolute-voice-provider-contracts__header">
|
|
3935
|
-
<span class="absolute-voice-provider-contracts__eyebrow">${
|
|
3936
|
-
<strong class="absolute-voice-provider-contracts__label">${
|
|
4105
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml11(model.title)}</span>
|
|
4106
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml11(model.label)}</strong>
|
|
3937
4107
|
</header>
|
|
3938
|
-
<p class="absolute-voice-provider-contracts__description">${
|
|
4108
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml11(model.description)}</p>
|
|
3939
4109
|
${rows}
|
|
3940
|
-
${model.error ? `<p class="absolute-voice-provider-contracts__error">${
|
|
4110
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
3941
4111
|
</section>`;
|
|
3942
4112
|
};
|
|
3943
4113
|
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}`;
|
|
@@ -5470,9 +5640,9 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
5470
5640
|
};
|
|
5471
5641
|
|
|
5472
5642
|
// src/client/providerStatusWidget.ts
|
|
5473
|
-
var
|
|
5474
|
-
var
|
|
5475
|
-
var
|
|
5643
|
+
var DEFAULT_TITLE9 = "Voice Providers";
|
|
5644
|
+
var DEFAULT_DESCRIPTION9 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
5645
|
+
var escapeHtml12 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5476
5646
|
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
5477
5647
|
var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
5478
5648
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -5516,37 +5686,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
5516
5686
|
const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
|
|
5517
5687
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
5518
5688
|
return {
|
|
5519
|
-
description: options.description ??
|
|
5689
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
5520
5690
|
error: snapshot.error,
|
|
5521
5691
|
isLoading: snapshot.isLoading,
|
|
5522
5692
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
5523
5693
|
providers,
|
|
5524
5694
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
5525
|
-
title: options.title ??
|
|
5695
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
5526
5696
|
updatedAt: snapshot.updatedAt
|
|
5527
5697
|
};
|
|
5528
5698
|
};
|
|
5529
5699
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
5530
5700
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
5531
|
-
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--${
|
|
5701
|
+
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--${escapeHtml12(provider.status)}">
|
|
5532
5702
|
<header>
|
|
5533
|
-
<strong>${
|
|
5534
|
-
<span>${
|
|
5703
|
+
<strong>${escapeHtml12(provider.label)}</strong>
|
|
5704
|
+
<span>${escapeHtml12(formatStatus4(provider.status))}</span>
|
|
5535
5705
|
</header>
|
|
5536
|
-
<p>${
|
|
5706
|
+
<p>${escapeHtml12(provider.detail)}</p>
|
|
5537
5707
|
<dl>${provider.rows.map((row) => `<div>
|
|
5538
|
-
<dt>${
|
|
5539
|
-
<dd>${
|
|
5708
|
+
<dt>${escapeHtml12(row.label)}</dt>
|
|
5709
|
+
<dd>${escapeHtml12(row.value)}</dd>
|
|
5540
5710
|
</div>`).join("")}</dl>
|
|
5541
5711
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
5542
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
5712
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml12(model.status)}">
|
|
5543
5713
|
<header class="absolute-voice-provider-status__header">
|
|
5544
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
5545
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
5714
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml12(model.title)}</span>
|
|
5715
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml12(model.label)}</strong>
|
|
5546
5716
|
</header>
|
|
5547
|
-
<p class="absolute-voice-provider-status__description">${
|
|
5717
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml12(model.description)}</p>
|
|
5548
5718
|
${providers}
|
|
5549
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
5719
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml12(model.error)}</p>` : ""}
|
|
5550
5720
|
</section>`;
|
|
5551
5721
|
};
|
|
5552
5722
|
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}`;
|
|
@@ -5677,9 +5847,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
5677
5847
|
};
|
|
5678
5848
|
|
|
5679
5849
|
// src/client/routingStatusWidget.ts
|
|
5680
|
-
var
|
|
5681
|
-
var
|
|
5682
|
-
var
|
|
5850
|
+
var DEFAULT_TITLE10 = "Voice Routing";
|
|
5851
|
+
var DEFAULT_DESCRIPTION10 = "Latest provider routing decision from the self-hosted trace store.";
|
|
5852
|
+
var escapeHtml13 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5683
5853
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
5684
5854
|
var formatProviderRoutes = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
|
|
5685
5855
|
var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
|
|
@@ -5748,35 +5918,35 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
5748
5918
|
return {
|
|
5749
5919
|
activeStack,
|
|
5750
5920
|
decision,
|
|
5751
|
-
description: options.description ??
|
|
5921
|
+
description: options.description ?? DEFAULT_DESCRIPTION10,
|
|
5752
5922
|
error: snapshot.error,
|
|
5753
5923
|
isLoading: snapshot.isLoading,
|
|
5754
5924
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
5755
5925
|
rows,
|
|
5756
5926
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
5757
|
-
title: options.title ??
|
|
5927
|
+
title: options.title ?? DEFAULT_TITLE10,
|
|
5758
5928
|
updatedAt: snapshot.updatedAt
|
|
5759
5929
|
};
|
|
5760
5930
|
};
|
|
5761
5931
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
5762
5932
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
5763
5933
|
const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
|
|
5764
|
-
<span>${
|
|
5765
|
-
<strong>${
|
|
5934
|
+
<span>${escapeHtml13(item.label)}</span>
|
|
5935
|
+
<strong>${escapeHtml13(item.value)}</strong>
|
|
5766
5936
|
</div>`).join("")}</div>` : "";
|
|
5767
5937
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
5768
|
-
<span>${
|
|
5769
|
-
<strong>${
|
|
5938
|
+
<span>${escapeHtml13(row.label)}</span>
|
|
5939
|
+
<strong>${escapeHtml13(row.value)}</strong>
|
|
5770
5940
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
5771
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
5941
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml13(model.status)}">
|
|
5772
5942
|
<header class="absolute-voice-routing-status__header">
|
|
5773
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
5774
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
5943
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml13(model.title)}</span>
|
|
5944
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml13(model.label)}</strong>
|
|
5775
5945
|
</header>
|
|
5776
|
-
<p class="absolute-voice-routing-status__description">${
|
|
5946
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml13(model.description)}</p>
|
|
5777
5947
|
${activeStack}
|
|
5778
5948
|
${rows}
|
|
5779
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
5949
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml13(model.error)}</p>` : ""}
|
|
5780
5950
|
</section>`;
|
|
5781
5951
|
};
|
|
5782
5952
|
var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__stack{background:linear-gradient(135deg,#16130d,#49391f);border-radius:18px;color:#fff;display:grid;gap:8px;grid-template-columns:repeat(5,minmax(0,1fr));margin-top:14px;padding:12px}.absolute-voice-routing-status__stack div{border-left:1px solid rgba(255,255,255,.18);padding-left:10px}.absolute-voice-routing-status__stack div:first-child{border-left:0;padding-left:0}.absolute-voice-routing-status__stack span{color:#e9d9b8;display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:5px;text-transform:uppercase}.absolute-voice-routing-status__stack strong{display:block;font-size:13px;line-height:1.25;overflow-wrap:anywhere}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}@media (max-width:760px){.absolute-voice-routing-status__stack{grid-template-columns:repeat(2,minmax(0,1fr))}.absolute-voice-routing-status__stack div{border-left:0;border-top:1px solid rgba(255,255,255,.18);padding-left:0;padding-top:8px}.absolute-voice-routing-status__stack div:first-child{border-top:0;padding-top:0}}`;
|
|
@@ -5907,16 +6077,16 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
|
|
|
5907
6077
|
};
|
|
5908
6078
|
|
|
5909
6079
|
// src/client/traceTimelineWidget.ts
|
|
5910
|
-
var
|
|
5911
|
-
var
|
|
5912
|
-
var
|
|
5913
|
-
var
|
|
6080
|
+
var DEFAULT_TITLE11 = "Voice Traces";
|
|
6081
|
+
var DEFAULT_DESCRIPTION11 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
6082
|
+
var escapeHtml14 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6083
|
+
var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
5914
6084
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
5915
6085
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
5916
6086
|
const sessions = (snapshot.report?.sessions ?? []).slice(0, options.limit ?? 3).map((session) => ({
|
|
5917
6087
|
...session,
|
|
5918
6088
|
detailHref: `${options.detailBasePath ?? "/traces"}/${encodeURIComponent(session.sessionId)}`,
|
|
5919
|
-
durationLabel:
|
|
6089
|
+
durationLabel: formatMs2(session.summary.callDurationMs),
|
|
5920
6090
|
incidentBundleHref: options.incidentBundleBasePath === false ? undefined : `${options.incidentBundleBasePath ?? "/voice-incidents"}/${encodeURIComponent(session.sessionId)}/markdown`,
|
|
5921
6091
|
label: `${session.summary.eventCount} events / ${session.summary.turnCount} turns`,
|
|
5922
6092
|
operationsRecordHref: options.operationsRecordBasePath === false ? undefined : `${options.operationsRecordBasePath ?? "/voice-operations"}/${encodeURIComponent(session.sessionId)}`,
|
|
@@ -5925,13 +6095,13 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
5925
6095
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
5926
6096
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
5927
6097
|
return {
|
|
5928
|
-
description: options.description ??
|
|
6098
|
+
description: options.description ?? DEFAULT_DESCRIPTION11,
|
|
5929
6099
|
error: snapshot.error,
|
|
5930
6100
|
isLoading: snapshot.isLoading,
|
|
5931
6101
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
5932
6102
|
sessions,
|
|
5933
6103
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
5934
|
-
title: options.title ??
|
|
6104
|
+
title: options.title ?? DEFAULT_TITLE11,
|
|
5935
6105
|
updatedAt: snapshot.updatedAt
|
|
5936
6106
|
};
|
|
5937
6107
|
};
|
|
@@ -5939,27 +6109,27 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
|
5939
6109
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
5940
6110
|
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
|
|
5941
6111
|
const supportLinks = [
|
|
5942
|
-
`<a href="${
|
|
5943
|
-
session.operationsRecordHref ? `<a href="${
|
|
5944
|
-
session.incidentBundleHref ? `<a href="${
|
|
6112
|
+
`<a href="${escapeHtml14(session.detailHref)}">Open timeline</a>`,
|
|
6113
|
+
session.operationsRecordHref ? `<a href="${escapeHtml14(session.operationsRecordHref)}">Open operations record</a>` : undefined,
|
|
6114
|
+
session.incidentBundleHref ? `<a href="${escapeHtml14(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
|
|
5945
6115
|
].filter(Boolean).join("");
|
|
5946
|
-
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${
|
|
6116
|
+
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml14(session.status)}">
|
|
5947
6117
|
<header>
|
|
5948
|
-
<strong>${
|
|
5949
|
-
<span>${
|
|
6118
|
+
<strong>${escapeHtml14(session.sessionId)}</strong>
|
|
6119
|
+
<span>${escapeHtml14(session.status)}</span>
|
|
5950
6120
|
</header>
|
|
5951
|
-
<p>${
|
|
6121
|
+
<p>${escapeHtml14(session.label)} \xB7 ${escapeHtml14(session.durationLabel)} \xB7 ${escapeHtml14(session.providerLabel)}</p>
|
|
5952
6122
|
<p class="absolute-voice-trace-timeline__actions">${supportLinks}</p>
|
|
5953
6123
|
</article>`;
|
|
5954
6124
|
}).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
5955
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
6125
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml14(model.status)}">
|
|
5956
6126
|
<header class="absolute-voice-trace-timeline__header">
|
|
5957
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
5958
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
6127
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml14(model.title)}</span>
|
|
6128
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml14(model.label)}</strong>
|
|
5959
6129
|
</header>
|
|
5960
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
6130
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml14(model.description)}</p>
|
|
5961
6131
|
${sessions}
|
|
5962
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
6132
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml14(model.error)}</p>` : ""}
|
|
5963
6133
|
</section>`;
|
|
5964
6134
|
};
|
|
5965
6135
|
var getVoiceTraceTimelineCSS = () => `.absolute-voice-trace-timeline{border:1px solid #bad7d3;border-radius:20px;background:#f3fffb;color:#09201c;padding:18px;box-shadow:0 18px 40px rgba(9,32,28,.12);font-family:inherit}.absolute-voice-trace-timeline--error,.absolute-voice-trace-timeline--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-trace-timeline--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-trace-timeline__header,.absolute-voice-trace-timeline__session header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-trace-timeline__eyebrow{color:#17665b;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-trace-timeline__label{font-size:24px;line-height:1}.absolute-voice-trace-timeline__description,.absolute-voice-trace-timeline__session p,.absolute-voice-trace-timeline__empty{color:#35544f}.absolute-voice-trace-timeline__sessions{display:grid;gap:12px;margin-top:14px}.absolute-voice-trace-timeline__session{background:#fff;border:1px solid #cfe7e2;border-radius:16px;padding:14px}.absolute-voice-trace-timeline__session--failed{border-color:#f2a7a7}.absolute-voice-trace-timeline__session--warning{border-color:#fbbf24}.absolute-voice-trace-timeline__session p{margin:10px 0}.absolute-voice-trace-timeline__actions{display:flex;flex-wrap:wrap;gap:10px}.absolute-voice-trace-timeline__session a{color:#0f766e;font-weight:800}.absolute-voice-trace-timeline__empty{margin:14px 0 0}.absolute-voice-trace-timeline__error{color:#9f1239;font-weight:700}`;
|
|
@@ -6089,9 +6259,9 @@ var createVoiceAgentSquadStatusStore = (path = "/api/voice-traces", options = {}
|
|
|
6089
6259
|
};
|
|
6090
6260
|
|
|
6091
6261
|
// src/client/agentSquadStatusWidget.ts
|
|
6092
|
-
var
|
|
6093
|
-
var
|
|
6094
|
-
var
|
|
6262
|
+
var DEFAULT_TITLE12 = "Voice Agent Squad";
|
|
6263
|
+
var DEFAULT_DESCRIPTION12 = "Current specialist and recent handoffs from your self-hosted voice traces.";
|
|
6264
|
+
var escapeHtml15 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6095
6265
|
var labelFor = (current) => {
|
|
6096
6266
|
if (!current)
|
|
6097
6267
|
return "Waiting for specialist activity";
|
|
@@ -6105,37 +6275,37 @@ var labelFor = (current) => {
|
|
|
6105
6275
|
};
|
|
6106
6276
|
var createVoiceAgentSquadStatusViewModel = (snapshot, options = {}) => ({
|
|
6107
6277
|
current: snapshot.report.current,
|
|
6108
|
-
description: options.description ??
|
|
6278
|
+
description: options.description ?? DEFAULT_DESCRIPTION12,
|
|
6109
6279
|
error: snapshot.error,
|
|
6110
6280
|
isLoading: snapshot.isLoading,
|
|
6111
6281
|
label: snapshot.error ? "Unavailable" : labelFor(snapshot.report.current),
|
|
6112
6282
|
sessionCount: snapshot.report.sessionCount,
|
|
6113
6283
|
sessions: snapshot.report.sessions,
|
|
6114
|
-
title: options.title ??
|
|
6284
|
+
title: options.title ?? DEFAULT_TITLE12,
|
|
6115
6285
|
updatedAt: snapshot.updatedAt
|
|
6116
6286
|
});
|
|
6117
6287
|
var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
|
|
6118
6288
|
const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
|
|
6119
6289
|
const current = model.current;
|
|
6120
6290
|
const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
|
|
6121
|
-
<span>${
|
|
6122
|
-
<strong>${
|
|
6123
|
-
<em>${
|
|
6124
|
-
${session.summary || session.reason ? `<p>${
|
|
6291
|
+
<span>${escapeHtml15(session.sessionId)}</span>
|
|
6292
|
+
<strong>${escapeHtml15(session.targetAgentId ?? "none")}</strong>
|
|
6293
|
+
<em>${escapeHtml15(session.status)}</em>
|
|
6294
|
+
${session.summary || session.reason ? `<p>${escapeHtml15(session.summary ?? session.reason ?? "")}</p>` : ""}
|
|
6125
6295
|
</li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
|
|
6126
6296
|
return `<section class="absolute-voice-agent-squad-status">
|
|
6127
6297
|
<header>
|
|
6128
|
-
<span>${
|
|
6129
|
-
<strong>${
|
|
6298
|
+
<span>${escapeHtml15(model.title)}</span>
|
|
6299
|
+
<strong>${escapeHtml15(model.label)}</strong>
|
|
6130
6300
|
</header>
|
|
6131
|
-
<p>${
|
|
6301
|
+
<p>${escapeHtml15(model.description)}</p>
|
|
6132
6302
|
<div>
|
|
6133
|
-
<span>Session</span><strong>${
|
|
6134
|
-
<span>From</span><strong>${
|
|
6135
|
-
<span>Status</span><strong>${
|
|
6303
|
+
<span>Session</span><strong>${escapeHtml15(current?.sessionId ?? "n/a")}</strong>
|
|
6304
|
+
<span>From</span><strong>${escapeHtml15(current?.fromAgentId ?? "n/a")}</strong>
|
|
6305
|
+
<span>Status</span><strong>${escapeHtml15(current?.status ?? "idle")}</strong>
|
|
6136
6306
|
</div>
|
|
6137
6307
|
<ul>${rows}</ul>
|
|
6138
|
-
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${
|
|
6308
|
+
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml15(model.error)}</p>` : ""}
|
|
6139
6309
|
</section>`;
|
|
6140
6310
|
};
|
|
6141
6311
|
var getVoiceAgentSquadStatusCSS = () => `.absolute-voice-agent-squad-status{border:1px solid #38bdf866;border-radius:20px;background:#0f172a;color:#f8fafc;padding:18px;font-family:inherit}.absolute-voice-agent-squad-status header{display:grid;gap:4px}.absolute-voice-agent-squad-status header span{color:#7dd3fc;font-size:12px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-agent-squad-status header strong{font-size:20px}.absolute-voice-agent-squad-status p{color:#cbd5e1}.absolute-voice-agent-squad-status div{display:grid;gap:6px;grid-template-columns:max-content 1fr;margin:14px 0}.absolute-voice-agent-squad-status div span{color:#94a3b8}.absolute-voice-agent-squad-status ul{display:grid;gap:8px;list-style:none;margin:0;padding:0}.absolute-voice-agent-squad-status li{background:#020617;border:1px solid #1e293b;border-radius:14px;padding:10px}.absolute-voice-agent-squad-status li span{color:#94a3b8;display:block;font-size:12px}.absolute-voice-agent-squad-status li strong{display:block}.absolute-voice-agent-squad-status li em{color:#7dd3fc;font-style:normal}.absolute-voice-agent-squad-status__error{color:#fecaca;font-weight:800}`;
|
|
@@ -6295,56 +6465,56 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
|
|
|
6295
6465
|
};
|
|
6296
6466
|
|
|
6297
6467
|
// src/client/turnLatencyWidget.ts
|
|
6298
|
-
var
|
|
6299
|
-
var
|
|
6468
|
+
var DEFAULT_TITLE13 = "Turn Latency";
|
|
6469
|
+
var DEFAULT_DESCRIPTION13 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
6300
6470
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
6301
|
-
var
|
|
6302
|
-
var
|
|
6471
|
+
var escapeHtml16 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6472
|
+
var formatMs3 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
6303
6473
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
6304
6474
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
6305
6475
|
...turn,
|
|
6306
6476
|
label: turn.text || "Empty turn",
|
|
6307
6477
|
rows: turn.stages.map((stage) => ({
|
|
6308
6478
|
label: stage.label,
|
|
6309
|
-
value:
|
|
6479
|
+
value: formatMs3(stage.valueMs)
|
|
6310
6480
|
}))
|
|
6311
6481
|
}));
|
|
6312
6482
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
6313
6483
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
6314
6484
|
return {
|
|
6315
|
-
description: options.description ??
|
|
6485
|
+
description: options.description ?? DEFAULT_DESCRIPTION13,
|
|
6316
6486
|
error: snapshot.error,
|
|
6317
6487
|
isLoading: snapshot.isLoading,
|
|
6318
|
-
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${
|
|
6488
|
+
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs3(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
6319
6489
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
6320
6490
|
showProofAction: Boolean(options.proofPath),
|
|
6321
6491
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
6322
|
-
title: options.title ??
|
|
6492
|
+
title: options.title ?? DEFAULT_TITLE13,
|
|
6323
6493
|
turns,
|
|
6324
6494
|
updatedAt: snapshot.updatedAt
|
|
6325
6495
|
};
|
|
6326
6496
|
};
|
|
6327
6497
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
6328
6498
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
6329
|
-
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--${
|
|
6499
|
+
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--${escapeHtml16(turn.status)}">
|
|
6330
6500
|
<header>
|
|
6331
|
-
<strong>${
|
|
6332
|
-
<span>${
|
|
6501
|
+
<strong>${escapeHtml16(turn.label)}</strong>
|
|
6502
|
+
<span>${escapeHtml16(turn.status)}</span>
|
|
6333
6503
|
</header>
|
|
6334
6504
|
<dl>${turn.rows.map((row) => `<div>
|
|
6335
|
-
<dt>${
|
|
6336
|
-
<dd>${
|
|
6505
|
+
<dt>${escapeHtml16(row.label)}</dt>
|
|
6506
|
+
<dd>${escapeHtml16(row.value)}</dd>
|
|
6337
6507
|
</div>`).join("")}</dl>
|
|
6338
6508
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
6339
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
6509
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml16(model.status)}">
|
|
6340
6510
|
<header class="absolute-voice-turn-latency__header">
|
|
6341
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
6342
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
6511
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml16(model.title)}</span>
|
|
6512
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml16(model.label)}</strong>
|
|
6343
6513
|
</header>
|
|
6344
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
6345
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
6514
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml16(model.description)}</p>
|
|
6515
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml16(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
6346
6516
|
${turns}
|
|
6347
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
6517
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml16(model.error)}</p>` : ""}
|
|
6348
6518
|
</section>`;
|
|
6349
6519
|
};
|
|
6350
6520
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -6483,9 +6653,9 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
6483
6653
|
};
|
|
6484
6654
|
|
|
6485
6655
|
// src/client/turnQualityWidget.ts
|
|
6486
|
-
var
|
|
6487
|
-
var
|
|
6488
|
-
var
|
|
6656
|
+
var DEFAULT_TITLE14 = "Turn Quality";
|
|
6657
|
+
var DEFAULT_DESCRIPTION14 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
6658
|
+
var escapeHtml17 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6489
6659
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
6490
6660
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
6491
6661
|
var getTurnDetail = (turn) => {
|
|
@@ -6529,37 +6699,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
6529
6699
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
6530
6700
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
6531
6701
|
return {
|
|
6532
|
-
description: options.description ??
|
|
6702
|
+
description: options.description ?? DEFAULT_DESCRIPTION14,
|
|
6533
6703
|
error: snapshot.error,
|
|
6534
6704
|
isLoading: snapshot.isLoading,
|
|
6535
6705
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
6536
6706
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
6537
|
-
title: options.title ??
|
|
6707
|
+
title: options.title ?? DEFAULT_TITLE14,
|
|
6538
6708
|
turns,
|
|
6539
6709
|
updatedAt: snapshot.updatedAt
|
|
6540
6710
|
};
|
|
6541
6711
|
};
|
|
6542
6712
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
6543
6713
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
6544
|
-
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--${
|
|
6714
|
+
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--${escapeHtml17(turn.status)}">
|
|
6545
6715
|
<header>
|
|
6546
|
-
<strong>${
|
|
6547
|
-
<span>${
|
|
6716
|
+
<strong>${escapeHtml17(turn.label)}</strong>
|
|
6717
|
+
<span>${escapeHtml17(turn.status)}</span>
|
|
6548
6718
|
</header>
|
|
6549
|
-
<p>${
|
|
6719
|
+
<p>${escapeHtml17(turn.detail)}</p>
|
|
6550
6720
|
<dl>${turn.rows.map((row) => `<div>
|
|
6551
|
-
<dt>${
|
|
6552
|
-
<dd>${
|
|
6721
|
+
<dt>${escapeHtml17(row.label)}</dt>
|
|
6722
|
+
<dd>${escapeHtml17(row.value)}</dd>
|
|
6553
6723
|
</div>`).join("")}</dl>
|
|
6554
6724
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
6555
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
6725
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml17(model.status)}">
|
|
6556
6726
|
<header class="absolute-voice-turn-quality__header">
|
|
6557
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
6558
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
6727
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml17(model.title)}</span>
|
|
6728
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml17(model.label)}</strong>
|
|
6559
6729
|
</header>
|
|
6560
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
6730
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml17(model.description)}</p>
|
|
6561
6731
|
${turns}
|
|
6562
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
6732
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml17(model.error)}</p>` : ""}
|
|
6563
6733
|
</section>`;
|
|
6564
6734
|
};
|
|
6565
6735
|
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}`;
|
|
@@ -7343,6 +7513,7 @@ export {
|
|
|
7343
7513
|
createVoiceTraceTimeline,
|
|
7344
7514
|
createVoiceStream2 as createVoiceStream,
|
|
7345
7515
|
createVoiceSessionSnapshot,
|
|
7516
|
+
createVoiceSessionObservability,
|
|
7346
7517
|
createVoiceRoutingStatus,
|
|
7347
7518
|
createVoiceReconnectProfileEvidence,
|
|
7348
7519
|
createVoiceReadinessFailures,
|