@absolutejs/voice 0.0.22-beta.452 → 0.0.22-beta.454
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 +345 -224
- package/dist/angular/voice-reconnect-profile-evidence.service.d.ts +12 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +543 -240
- package/dist/client/reconnectProfileEvidence.d.ts +19 -0
- package/dist/client/reconnectProfileEvidenceWidget.d.ts +39 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +107 -0
- package/dist/proofTrends.d.ts +53 -0
- package/dist/react/VoiceReconnectProfileEvidence.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +919 -526
- package/dist/react/useVoiceReconnectProfileEvidence.d.ts +8 -0
- package/dist/svelte/createVoiceReconnectProfileEvidence.d.ts +7 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +86 -0
- package/dist/vue/VoiceReconnectProfileEvidence.d.ts +21 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +825 -438
- package/dist/vue/useVoiceReconnectProfileEvidence.d.ts +9 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -2985,6 +2985,80 @@ var createVoiceProofTrendsStore = (path = "/api/voice/proof-trends", options = {
|
|
|
2985
2985
|
}
|
|
2986
2986
|
};
|
|
2987
2987
|
};
|
|
2988
|
+
// src/client/reconnectProfileEvidence.ts
|
|
2989
|
+
var fetchVoiceReconnectProfileEvidence = async (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
|
|
2990
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2991
|
+
const response = await fetchImpl(path);
|
|
2992
|
+
if (!response.ok) {
|
|
2993
|
+
throw new Error(`Voice reconnect profile evidence failed: HTTP ${response.status}`);
|
|
2994
|
+
}
|
|
2995
|
+
return await response.json();
|
|
2996
|
+
};
|
|
2997
|
+
var createVoiceReconnectProfileEvidenceStore = (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
|
|
2998
|
+
const listeners = new Set;
|
|
2999
|
+
let closed = false;
|
|
3000
|
+
let timer;
|
|
3001
|
+
let snapshot = {
|
|
3002
|
+
error: null,
|
|
3003
|
+
isLoading: false
|
|
3004
|
+
};
|
|
3005
|
+
const emit = () => {
|
|
3006
|
+
for (const listener of listeners) {
|
|
3007
|
+
listener();
|
|
3008
|
+
}
|
|
3009
|
+
};
|
|
3010
|
+
const refresh = async () => {
|
|
3011
|
+
if (closed) {
|
|
3012
|
+
return snapshot.report;
|
|
3013
|
+
}
|
|
3014
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
3015
|
+
emit();
|
|
3016
|
+
try {
|
|
3017
|
+
const report = await fetchVoiceReconnectProfileEvidence(path, options);
|
|
3018
|
+
snapshot = {
|
|
3019
|
+
error: null,
|
|
3020
|
+
isLoading: false,
|
|
3021
|
+
report,
|
|
3022
|
+
updatedAt: Date.now()
|
|
3023
|
+
};
|
|
3024
|
+
emit();
|
|
3025
|
+
return report;
|
|
3026
|
+
} catch (error) {
|
|
3027
|
+
snapshot = {
|
|
3028
|
+
...snapshot,
|
|
3029
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3030
|
+
isLoading: false
|
|
3031
|
+
};
|
|
3032
|
+
emit();
|
|
3033
|
+
throw error;
|
|
3034
|
+
}
|
|
3035
|
+
};
|
|
3036
|
+
const close = () => {
|
|
3037
|
+
closed = true;
|
|
3038
|
+
if (timer) {
|
|
3039
|
+
clearInterval(timer);
|
|
3040
|
+
timer = undefined;
|
|
3041
|
+
}
|
|
3042
|
+
listeners.clear();
|
|
3043
|
+
};
|
|
3044
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
3045
|
+
timer = setInterval(() => {
|
|
3046
|
+
refresh().catch(() => {});
|
|
3047
|
+
}, options.intervalMs);
|
|
3048
|
+
}
|
|
3049
|
+
return {
|
|
3050
|
+
close,
|
|
3051
|
+
getServerSnapshot: () => snapshot,
|
|
3052
|
+
getSnapshot: () => snapshot,
|
|
3053
|
+
refresh,
|
|
3054
|
+
subscribe: (listener) => {
|
|
3055
|
+
listeners.add(listener);
|
|
3056
|
+
return () => {
|
|
3057
|
+
listeners.delete(listener);
|
|
3058
|
+
};
|
|
3059
|
+
}
|
|
3060
|
+
};
|
|
3061
|
+
};
|
|
2988
3062
|
// src/client/sessionSnapshot.ts
|
|
2989
3063
|
var withTurnId = (path, turnId) => {
|
|
2990
3064
|
if (!turnId) {
|
|
@@ -6245,6 +6319,33 @@ var maxNumber = (values) => {
|
|
|
6245
6319
|
const finite = values.filter((value) => typeof value === "number" && Number.isFinite(value));
|
|
6246
6320
|
return finite.length > 0 ? Math.max(...finite) : undefined;
|
|
6247
6321
|
};
|
|
6322
|
+
var buildVoiceReconnectProfileEvidenceSummary = (evidence, options = {}) => {
|
|
6323
|
+
const profileId = options.profileId ?? "reconnect-resume";
|
|
6324
|
+
const filtered = evidence.filter((record) => record.profileId === profileId).sort((left, right) => {
|
|
6325
|
+
const leftAt = Date.parse(left.generatedAt ?? left.createdAt);
|
|
6326
|
+
const rightAt = Date.parse(right.generatedAt ?? right.createdAt);
|
|
6327
|
+
return (Number.isFinite(rightAt) ? rightAt : 0) - (Number.isFinite(leftAt) ? leftAt : 0);
|
|
6328
|
+
});
|
|
6329
|
+
const latest = filtered[0];
|
|
6330
|
+
const sampleCount = filtered.reduce((total, record) => total + (record.reconnect?.samples ?? 1), 0);
|
|
6331
|
+
const snapshotCount = filtered.reduce((total, record) => total + (record.reconnect?.snapshotCount ?? 0), 0);
|
|
6332
|
+
const resumeLatencyP95Ms = maxNumber(filtered.map((record) => record.reconnect?.resumeLatencyP95Ms));
|
|
6333
|
+
const failed = filtered.some((record) => record.ok === false || record.reconnect?.status === "fail");
|
|
6334
|
+
const passed = filtered.some((record) => record.ok === true && record.reconnect?.resumed === true && record.reconnect?.reconnected === true);
|
|
6335
|
+
const status = filtered.length === 0 ? "empty" : failed ? "fail" : passed ? "pass" : "warn";
|
|
6336
|
+
return {
|
|
6337
|
+
evidence: filtered,
|
|
6338
|
+
generatedAt: options.generatedAt ?? new Date().toISOString(),
|
|
6339
|
+
latest,
|
|
6340
|
+
ok: status === "pass",
|
|
6341
|
+
profileId,
|
|
6342
|
+
resumeLatencyP95Ms,
|
|
6343
|
+
sampleCount,
|
|
6344
|
+
snapshotCount,
|
|
6345
|
+
sourceHref: options.sourceHref,
|
|
6346
|
+
status
|
|
6347
|
+
};
|
|
6348
|
+
};
|
|
6248
6349
|
var percentile = (values, rank) => {
|
|
6249
6350
|
const finite = values.filter((value) => Number.isFinite(value)).sort((left, right) => left - right);
|
|
6250
6351
|
if (finite.length === 0) {
|
|
@@ -6564,6 +6665,7 @@ var buildVoiceRealCallProfileEvidenceFromReconnectProofReports = (input, options
|
|
|
6564
6665
|
});
|
|
6565
6666
|
};
|
|
6566
6667
|
var loadVoiceRealCallProfileEvidenceFromTraceStore = async (options) => buildVoiceRealCallProfileEvidenceFromTraceEvents(await options.store.list({ limit: options.limit ?? 5000 }), options);
|
|
6668
|
+
var loadVoiceRealCallProfileEvidenceFromStore = async (options) => options.store.list(options);
|
|
6567
6669
|
var realCallProfileTraceSignalTypes = new Set([
|
|
6568
6670
|
"client.barge_in",
|
|
6569
6671
|
"client.browser_media",
|
|
@@ -7406,6 +7508,74 @@ var createVoiceInMemoryRealCallProfileRecoveryJobStore = (options = {}) => {
|
|
|
7406
7508
|
}
|
|
7407
7509
|
};
|
|
7408
7510
|
};
|
|
7511
|
+
var normalizeRealCallProfileEvidenceTableName = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_real_call_profile_evidence";
|
|
7512
|
+
var parseRealCallProfileEvidenceBoundary = (value) => value === undefined ? undefined : value instanceof Date ? value.getTime() : typeof value === "number" ? value : Date.parse(value);
|
|
7513
|
+
var readRealCallProfileEvidenceSortTime = (evidence, fallback) => Date.parse(evidence.generatedAt ?? fallback) || Date.parse(fallback);
|
|
7514
|
+
var createVoiceSQLiteRealCallProfileEvidenceStore = (options = {}) => {
|
|
7515
|
+
const { Database: SQLiteDatabase } = __require("bun:sqlite");
|
|
7516
|
+
const database = options.database ?? new SQLiteDatabase(options.path ?? ":memory:", {
|
|
7517
|
+
create: true
|
|
7518
|
+
});
|
|
7519
|
+
const tableName = normalizeRealCallProfileEvidenceTableName(options.tableName ?? "voice_real_call_profile_evidence");
|
|
7520
|
+
const now = () => (options.now ?? (() => new Date))().toISOString();
|
|
7521
|
+
const createId = () => `${options.idPrefix ?? "voice-profile-evidence"}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
7522
|
+
database.exec("PRAGMA journal_mode = WAL;");
|
|
7523
|
+
database.exec("PRAGMA synchronous = NORMAL;");
|
|
7524
|
+
database.exec("PRAGMA busy_timeout = 5000;");
|
|
7525
|
+
database.exec(`CREATE TABLE IF NOT EXISTS "${tableName}" (
|
|
7526
|
+
id TEXT PRIMARY KEY,
|
|
7527
|
+
sort_at INTEGER NOT NULL,
|
|
7528
|
+
profile_id TEXT NOT NULL,
|
|
7529
|
+
session_id TEXT NOT NULL,
|
|
7530
|
+
created_at TEXT NOT NULL,
|
|
7531
|
+
payload TEXT NOT NULL
|
|
7532
|
+
)`);
|
|
7533
|
+
const selectStatement = database.query(`SELECT payload FROM "${tableName}" WHERE id = ?1 LIMIT 1`);
|
|
7534
|
+
const listStatement = database.query(`SELECT payload FROM "${tableName}" ORDER BY sort_at DESC, id DESC`);
|
|
7535
|
+
const upsertStatement = database.query(`INSERT INTO "${tableName}" (id, sort_at, profile_id, session_id, created_at, payload)
|
|
7536
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6)
|
|
7537
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
7538
|
+
sort_at = excluded.sort_at,
|
|
7539
|
+
profile_id = excluded.profile_id,
|
|
7540
|
+
session_id = excluded.session_id,
|
|
7541
|
+
created_at = excluded.created_at,
|
|
7542
|
+
payload = excluded.payload`);
|
|
7543
|
+
const deleteStatement = database.query(`DELETE FROM "${tableName}" WHERE id = ?1`);
|
|
7544
|
+
const writeEvidence = (record) => {
|
|
7545
|
+
upsertStatement.run(record.id, readRealCallProfileEvidenceSortTime(record, record.createdAt), record.profileId, record.sessionId, record.createdAt, JSON.stringify(record));
|
|
7546
|
+
return record;
|
|
7547
|
+
};
|
|
7548
|
+
const readEvidence = (id) => {
|
|
7549
|
+
const row = selectStatement.get(id);
|
|
7550
|
+
return row ? JSON.parse(row.payload) : undefined;
|
|
7551
|
+
};
|
|
7552
|
+
const matchesListOptions = (record, input) => {
|
|
7553
|
+
const evidenceTime = readRealCallProfileEvidenceSortTime(record, record.createdAt);
|
|
7554
|
+
const since = parseRealCallProfileEvidenceBoundary(input.since);
|
|
7555
|
+
const until = parseRealCallProfileEvidenceBoundary(input.until);
|
|
7556
|
+
return (!input.profileId || record.profileId === input.profileId) && (!input.sessionId || record.sessionId === input.sessionId) && (since === undefined || Number.isNaN(since) || evidenceTime >= since) && (until === undefined || Number.isNaN(until) || evidenceTime <= until);
|
|
7557
|
+
};
|
|
7558
|
+
return {
|
|
7559
|
+
append(input) {
|
|
7560
|
+
const createdAt = input.createdAt ?? now();
|
|
7561
|
+
return writeEvidence({
|
|
7562
|
+
...input,
|
|
7563
|
+
createdAt,
|
|
7564
|
+
id: input.id ?? createId()
|
|
7565
|
+
});
|
|
7566
|
+
},
|
|
7567
|
+
get(id) {
|
|
7568
|
+
return readEvidence(id);
|
|
7569
|
+
},
|
|
7570
|
+
list(input = {}) {
|
|
7571
|
+
const limit = Number.isFinite(input.limit) && input.limit !== undefined && input.limit > 0 ? Math.floor(input.limit) : 500;
|
|
7572
|
+
return listStatement.all().map((row) => JSON.parse(row.payload)).filter((record) => matchesListOptions(record, input)).slice(0, limit);
|
|
7573
|
+
},
|
|
7574
|
+
remove(id) {
|
|
7575
|
+
deleteStatement.run(id);
|
|
7576
|
+
}
|
|
7577
|
+
};
|
|
7578
|
+
};
|
|
7409
7579
|
var normalizeRealCallRecoveryJobTableName = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_real_call_profile_recovery_jobs";
|
|
7410
7580
|
var createVoiceSQLiteRealCallProfileRecoveryJobStore = (options = {}) => {
|
|
7411
7581
|
const { Database: SQLiteDatabase } = __require("bun:sqlite");
|
|
@@ -7659,6 +7829,13 @@ var buildVoiceRealCallProfileHistoryReport = (options = {}) => {
|
|
|
7659
7829
|
trend
|
|
7660
7830
|
};
|
|
7661
7831
|
};
|
|
7832
|
+
var buildVoiceRealCallProfileHistoryReportFromStore = async (options) => {
|
|
7833
|
+
const evidence = await options.store.list(options);
|
|
7834
|
+
return buildVoiceRealCallProfileHistoryReport({
|
|
7835
|
+
...options,
|
|
7836
|
+
evidence
|
|
7837
|
+
});
|
|
7838
|
+
};
|
|
7662
7839
|
var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
|
|
7663
7840
|
var providerSortScore = (provider) => [
|
|
7664
7841
|
recommendationStatusRank[provider.status],
|
|
@@ -8492,21 +8669,140 @@ var defineVoiceProofTrendsElement = (tagName = "absolute-voice-proof-trends") =>
|
|
|
8492
8669
|
}
|
|
8493
8670
|
});
|
|
8494
8671
|
};
|
|
8495
|
-
// src/client/
|
|
8496
|
-
var DEFAULT_TITLE6 = "
|
|
8497
|
-
var DEFAULT_DESCRIPTION6 = "
|
|
8672
|
+
// src/client/reconnectProfileEvidenceWidget.ts
|
|
8673
|
+
var DEFAULT_TITLE6 = "Persisted Reconnect Evidence";
|
|
8674
|
+
var DEFAULT_DESCRIPTION6 = "Real browser reconnect/resume evidence persisted into profile history so recovery claims are backed by durable traces.";
|
|
8498
8675
|
var DEFAULT_LINKS3 = [
|
|
8499
|
-
{ href: "/voice/
|
|
8500
|
-
{
|
|
8676
|
+
{ href: "/voice/reconnect-contract", label: "Reconnect contract" },
|
|
8677
|
+
{
|
|
8678
|
+
href: "/api/voice/real-call-profile-history",
|
|
8679
|
+
label: "Profile history JSON"
|
|
8680
|
+
}
|
|
8501
8681
|
];
|
|
8502
8682
|
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8503
8683
|
var formatMs2 = (value) => typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}ms` : "n/a";
|
|
8684
|
+
var formatCount = (value) => new Intl.NumberFormat("en-US").format(value);
|
|
8685
|
+
var formatAge = (value) => {
|
|
8686
|
+
if (!value) {
|
|
8687
|
+
return "No evidence";
|
|
8688
|
+
}
|
|
8689
|
+
const elapsedMs = Date.now() - Date.parse(value);
|
|
8690
|
+
if (!Number.isFinite(elapsedMs) || elapsedMs < 0) {
|
|
8691
|
+
return "Just now";
|
|
8692
|
+
}
|
|
8693
|
+
const minutes = Math.floor(elapsedMs / 60000);
|
|
8694
|
+
if (minutes < 1) {
|
|
8695
|
+
return "Just now";
|
|
8696
|
+
}
|
|
8697
|
+
if (minutes < 60) {
|
|
8698
|
+
return `${minutes}m ago`;
|
|
8699
|
+
}
|
|
8700
|
+
const hours = Math.floor(minutes / 60);
|
|
8701
|
+
if (hours < 24) {
|
|
8702
|
+
return `${hours}h ago`;
|
|
8703
|
+
}
|
|
8704
|
+
return `${Math.floor(hours / 24)}d ago`;
|
|
8705
|
+
};
|
|
8706
|
+
var createVoiceReconnectProfileEvidenceViewModel = (snapshot, options = {}) => {
|
|
8707
|
+
const report = snapshot.report;
|
|
8708
|
+
const latest = report?.latest;
|
|
8709
|
+
const latestAt = latest?.generatedAt ?? latest?.createdAt;
|
|
8710
|
+
return {
|
|
8711
|
+
description: options.description ?? latest?.profileDescription ?? DEFAULT_DESCRIPTION6,
|
|
8712
|
+
error: snapshot.error,
|
|
8713
|
+
isLoading: snapshot.isLoading,
|
|
8714
|
+
label: snapshot.error ? "Unavailable" : report ? report.status === "pass" ? "Reconnect evidence passing" : report.status === "warn" ? "Reconnect evidence incomplete" : report.status === "fail" ? "Reconnect evidence failing" : "Waiting for reconnect evidence" : snapshot.isLoading ? "Checking" : "No reconnect evidence",
|
|
8715
|
+
latest: latest ? {
|
|
8716
|
+
profileLabel: latest.profileLabel ?? latest.profileId,
|
|
8717
|
+
sessionId: latest.sessionId,
|
|
8718
|
+
surfaces: (latest.surfaces ?? []).join(", ") || "browser"
|
|
8719
|
+
} : undefined,
|
|
8720
|
+
links: options.links ?? DEFAULT_LINKS3,
|
|
8721
|
+
metrics: [
|
|
8722
|
+
{ label: "Samples", value: formatCount(report?.sampleCount ?? 0) },
|
|
8723
|
+
{ label: "Snapshots", value: formatCount(report?.snapshotCount ?? 0) },
|
|
8724
|
+
{
|
|
8725
|
+
label: "Resume p95",
|
|
8726
|
+
value: formatMs2(report?.resumeLatencyP95Ms ?? latest?.reconnect?.resumeLatencyP95Ms)
|
|
8727
|
+
},
|
|
8728
|
+
{ label: "Last proof", value: formatAge(latestAt) }
|
|
8729
|
+
],
|
|
8730
|
+
status: snapshot.error ? "error" : report ? report.status === "pass" ? "ready" : report.status === "empty" ? "empty" : "warning" : snapshot.isLoading ? "loading" : "empty",
|
|
8731
|
+
title: options.title ?? DEFAULT_TITLE6
|
|
8732
|
+
};
|
|
8733
|
+
};
|
|
8734
|
+
var renderVoiceReconnectProfileEvidenceHTML = (snapshot, options = {}) => {
|
|
8735
|
+
const model = createVoiceReconnectProfileEvidenceViewModel(snapshot, options);
|
|
8736
|
+
const metrics = `<div class="absolute-voice-reconnect-evidence__metrics">${model.metrics.map((metric) => `<article>
|
|
8737
|
+
<span>${escapeHtml11(metric.label)}</span>
|
|
8738
|
+
<strong>${escapeHtml11(metric.value)}</strong>
|
|
8739
|
+
</article>`).join("")}</div>`;
|
|
8740
|
+
const latest = model.latest ? `<p class="absolute-voice-reconnect-evidence__latest">Latest ${escapeHtml11(model.latest.profileLabel)} \xB7 ${escapeHtml11(model.latest.sessionId)} \xB7 ${escapeHtml11(model.latest.surfaces)}</p>` : `<p class="absolute-voice-reconnect-evidence__empty">No persisted reconnect profile evidence yet.</p>`;
|
|
8741
|
+
const links = model.links.length ? `<p class="absolute-voice-reconnect-evidence__links">${model.links.map((link) => `<a href="${escapeHtml11(link.href)}">${escapeHtml11(link.label)}</a>`).join("")}</p>` : "";
|
|
8742
|
+
return `<section class="absolute-voice-reconnect-evidence absolute-voice-reconnect-evidence--${escapeHtml11(model.status)}">
|
|
8743
|
+
<header class="absolute-voice-reconnect-evidence__header">
|
|
8744
|
+
<span class="absolute-voice-reconnect-evidence__eyebrow">${escapeHtml11(model.title)}</span>
|
|
8745
|
+
<strong class="absolute-voice-reconnect-evidence__label">${escapeHtml11(model.label)}</strong>
|
|
8746
|
+
</header>
|
|
8747
|
+
<p class="absolute-voice-reconnect-evidence__description">${escapeHtml11(model.description)}</p>
|
|
8748
|
+
${metrics}
|
|
8749
|
+
${latest}
|
|
8750
|
+
${links}
|
|
8751
|
+
${model.error ? `<p class="absolute-voice-reconnect-evidence__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
8752
|
+
</section>`;
|
|
8753
|
+
};
|
|
8754
|
+
var getVoiceReconnectProfileEvidenceCSS = () => `.absolute-voice-reconnect-evidence{border:1px solid #bae6fd;border-radius:20px;background:#f0f9ff;color:#0f172a;padding:18px;box-shadow:0 18px 40px rgba(14,165,233,.12);font-family:inherit}.absolute-voice-reconnect-evidence--warning,.absolute-voice-reconnect-evidence--error{border-color:#fbbf24;background:#fffbeb}.absolute-voice-reconnect-evidence__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-reconnect-evidence__eyebrow{color:#0369a1;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-reconnect-evidence__label{font-size:24px;line-height:1}.absolute-voice-reconnect-evidence__description,.absolute-voice-reconnect-evidence__empty,.absolute-voice-reconnect-evidence__latest{color:#475569}.absolute-voice-reconnect-evidence__metrics{display:grid;gap:10px;grid-template-columns:repeat(4,minmax(0,1fr));margin-top:14px}.absolute-voice-reconnect-evidence__metrics article{background:#fff;border:1px solid #bae6fd;border-radius:16px;padding:12px}.absolute-voice-reconnect-evidence__metrics span{color:#64748b;display:block;font-size:11px;font-weight:800;text-transform:uppercase}.absolute-voice-reconnect-evidence__metrics strong{display:block;font-size:20px;margin-top:4px}.absolute-voice-reconnect-evidence__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-reconnect-evidence__links a{border:1px solid #7dd3fc;border-radius:999px;color:#0369a1;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-reconnect-evidence__error{color:#9f1239;font-weight:700}@media (max-width:720px){.absolute-voice-reconnect-evidence__metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}`;
|
|
8755
|
+
var mountVoiceReconnectProfileEvidence = (element, path = "/api/voice/reconnect-profile-evidence", options = {}) => {
|
|
8756
|
+
const store = createVoiceReconnectProfileEvidenceStore(path, options);
|
|
8757
|
+
const render = () => {
|
|
8758
|
+
element.innerHTML = renderVoiceReconnectProfileEvidenceHTML(store.getSnapshot(), options);
|
|
8759
|
+
};
|
|
8760
|
+
const unsubscribe = store.subscribe(render);
|
|
8761
|
+
render();
|
|
8762
|
+
store.refresh().catch(() => {});
|
|
8763
|
+
return {
|
|
8764
|
+
close: () => {
|
|
8765
|
+
unsubscribe();
|
|
8766
|
+
store.close();
|
|
8767
|
+
},
|
|
8768
|
+
refresh: store.refresh
|
|
8769
|
+
};
|
|
8770
|
+
};
|
|
8771
|
+
var defineVoiceReconnectProfileEvidenceElement = (tagName = "absolute-voice-reconnect-profile-evidence") => {
|
|
8772
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
8773
|
+
return;
|
|
8774
|
+
}
|
|
8775
|
+
customElements.define(tagName, class AbsoluteVoiceReconnectProfileEvidenceElement extends HTMLElement {
|
|
8776
|
+
mounted;
|
|
8777
|
+
connectedCallback() {
|
|
8778
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
8779
|
+
this.mounted = mountVoiceReconnectProfileEvidence(this, this.getAttribute("path") ?? "/api/voice/reconnect-profile-evidence", {
|
|
8780
|
+
description: this.getAttribute("description") ?? undefined,
|
|
8781
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
8782
|
+
title: this.getAttribute("title") ?? undefined
|
|
8783
|
+
});
|
|
8784
|
+
}
|
|
8785
|
+
disconnectedCallback() {
|
|
8786
|
+
this.mounted?.close();
|
|
8787
|
+
this.mounted = undefined;
|
|
8788
|
+
}
|
|
8789
|
+
});
|
|
8790
|
+
};
|
|
8791
|
+
// src/client/profileComparisonWidget.ts
|
|
8792
|
+
var DEFAULT_TITLE7 = "Profile Stack Comparison";
|
|
8793
|
+
var DEFAULT_DESCRIPTION7 = "Measured real-call evidence behind each profile default: provider routes, latency, and the next move.";
|
|
8794
|
+
var DEFAULT_LINKS4 = [
|
|
8795
|
+
{ href: "/voice/real-call-profile-history", label: "Profile history" },
|
|
8796
|
+
{ href: "/api/voice/real-call-profile-history", label: "JSON" }
|
|
8797
|
+
];
|
|
8798
|
+
var escapeHtml12 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8799
|
+
var formatMs3 = (value) => typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}ms` : "n/a";
|
|
8504
8800
|
var formatProviderRoutes = (profile) => Object.entries(profile.providerRoutes).map(([role, provider]) => `${role}: ${provider}`).join(", ") || "No complete route yet";
|
|
8505
8801
|
var createProfileView = (profile) => ({
|
|
8506
8802
|
evidence: [
|
|
8507
|
-
{ label: "Live p95", value:
|
|
8508
|
-
{ label: "Provider p95", value:
|
|
8509
|
-
{ label: "Turn p95", value:
|
|
8803
|
+
{ label: "Live p95", value: formatMs3(profile.evidence.liveP95Ms) },
|
|
8804
|
+
{ label: "Provider p95", value: formatMs3(profile.evidence.providerP95Ms) },
|
|
8805
|
+
{ label: "Turn p95", value: formatMs3(profile.evidence.turnP95Ms) }
|
|
8510
8806
|
],
|
|
8511
8807
|
label: profile.label ?? profile.profileId,
|
|
8512
8808
|
nextMove: profile.nextMove,
|
|
@@ -8518,37 +8814,37 @@ var createVoiceProfileComparisonViewModel = (snapshot, options = {}) => {
|
|
|
8518
8814
|
const report = snapshot.report;
|
|
8519
8815
|
const profiles = report?.defaults.profiles.map(createProfileView) ?? [];
|
|
8520
8816
|
return {
|
|
8521
|
-
description: options.description ??
|
|
8817
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
8522
8818
|
error: snapshot.error,
|
|
8523
8819
|
isLoading: snapshot.isLoading,
|
|
8524
8820
|
label: snapshot.error ? "Unavailable" : report ? `${report.defaults.summary.actionableProfiles}/${report.defaults.summary.profileCount} profiles ready` : snapshot.isLoading ? "Checking" : "No profile evidence",
|
|
8525
|
-
links: options.links ??
|
|
8821
|
+
links: options.links ?? DEFAULT_LINKS4,
|
|
8526
8822
|
profiles,
|
|
8527
8823
|
status: snapshot.error ? "error" : report ? report.status === "pass" ? "ready" : "warning" : snapshot.isLoading ? "loading" : "empty",
|
|
8528
|
-
title: options.title ??
|
|
8824
|
+
title: options.title ?? DEFAULT_TITLE7
|
|
8529
8825
|
};
|
|
8530
8826
|
};
|
|
8531
8827
|
var renderVoiceProfileComparisonHTML = (snapshot, options = {}) => {
|
|
8532
8828
|
const model = createVoiceProfileComparisonViewModel(snapshot, options);
|
|
8533
|
-
const profiles = model.profiles.length ? `<div class="absolute-voice-profile-comparison__profiles">${model.profiles.map((profile) => `<article class="absolute-voice-profile-comparison__profile absolute-voice-profile-comparison__profile--${
|
|
8829
|
+
const profiles = model.profiles.length ? `<div class="absolute-voice-profile-comparison__profiles">${model.profiles.map((profile) => `<article class="absolute-voice-profile-comparison__profile absolute-voice-profile-comparison__profile--${escapeHtml12(profile.status)}">
|
|
8534
8830
|
<header>
|
|
8535
|
-
<span>${
|
|
8536
|
-
<strong>${
|
|
8831
|
+
<span>${escapeHtml12(profile.status)}</span>
|
|
8832
|
+
<strong>${escapeHtml12(profile.label)}</strong>
|
|
8537
8833
|
</header>
|
|
8538
|
-
<p>${
|
|
8539
|
-
<div>${profile.evidence.map((metric) => `<span><small>${
|
|
8540
|
-
<em>${
|
|
8541
|
-
</article>`).join("")}</div>` : `<p class="absolute-voice-profile-comparison__empty">${model.error ?
|
|
8542
|
-
const links = model.links.length ? `<p class="absolute-voice-profile-comparison__links">${model.links.map((link) => `<a href="${
|
|
8543
|
-
return `<section class="absolute-voice-profile-comparison absolute-voice-profile-comparison--${
|
|
8834
|
+
<p>${escapeHtml12(profile.providerRoutes)}</p>
|
|
8835
|
+
<div>${profile.evidence.map((metric) => `<span><small>${escapeHtml12(metric.label)}</small><b>${escapeHtml12(metric.value)}</b></span>`).join("")}</div>
|
|
8836
|
+
<em>${escapeHtml12(profile.nextMove)}</em>
|
|
8837
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-profile-comparison__empty">${model.error ? escapeHtml12(model.error) : "Run real-call profile collection to populate profile comparisons."}</p>`;
|
|
8838
|
+
const links = model.links.length ? `<p class="absolute-voice-profile-comparison__links">${model.links.map((link) => `<a href="${escapeHtml12(link.href)}">${escapeHtml12(link.label)}</a>`).join("")}</p>` : "";
|
|
8839
|
+
return `<section class="absolute-voice-profile-comparison absolute-voice-profile-comparison--${escapeHtml12(model.status)}">
|
|
8544
8840
|
<header class="absolute-voice-profile-comparison__header">
|
|
8545
|
-
<span class="absolute-voice-profile-comparison__eyebrow">${
|
|
8546
|
-
<strong class="absolute-voice-profile-comparison__label">${
|
|
8841
|
+
<span class="absolute-voice-profile-comparison__eyebrow">${escapeHtml12(model.title)}</span>
|
|
8842
|
+
<strong class="absolute-voice-profile-comparison__label">${escapeHtml12(model.label)}</strong>
|
|
8547
8843
|
</header>
|
|
8548
|
-
<p class="absolute-voice-profile-comparison__description">${
|
|
8844
|
+
<p class="absolute-voice-profile-comparison__description">${escapeHtml12(model.description)}</p>
|
|
8549
8845
|
${profiles}
|
|
8550
8846
|
${links}
|
|
8551
|
-
${model.error ? `<p class="absolute-voice-profile-comparison__error">${
|
|
8847
|
+
${model.error ? `<p class="absolute-voice-profile-comparison__error">${escapeHtml12(model.error)}</p>` : ""}
|
|
8552
8848
|
</section>`;
|
|
8553
8849
|
};
|
|
8554
8850
|
var getVoiceProfileComparisonCSS = () => `.absolute-voice-profile-comparison{border:1px solid #c7d2fe;border-radius:20px;background:#eef2ff;color:#111827;padding:18px;box-shadow:0 18px 40px rgba(79,70,229,.12);font-family:inherit}.absolute-voice-profile-comparison--warning,.absolute-voice-profile-comparison--error{border-color:#fbbf24;background:#fffbeb}.absolute-voice-profile-comparison__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-profile-comparison__eyebrow{color:#4338ca;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-profile-comparison__label{font-size:24px;line-height:1}.absolute-voice-profile-comparison__description,.absolute-voice-profile-comparison__empty{color:#4b5563}.absolute-voice-profile-comparison__profiles{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin-top:14px}.absolute-voice-profile-comparison__profile{background:#fff;border:1px solid #c7d2fe;border-radius:16px;padding:14px}.absolute-voice-profile-comparison__profile--warn{border-color:#fbbf24}.absolute-voice-profile-comparison__profile--fail{border-color:#f87171}.absolute-voice-profile-comparison__profile header{align-items:center;display:flex;gap:8px;justify-content:space-between}.absolute-voice-profile-comparison__profile header span{border:1px solid currentColor;border-radius:999px;color:#4338ca;font-size:11px;font-weight:900;padding:3px 7px;text-transform:uppercase}.absolute-voice-profile-comparison__profile p{color:#1f2937;font-weight:800;overflow-wrap:anywhere}.absolute-voice-profile-comparison__profile div{display:grid;gap:8px;grid-template-columns:repeat(3,minmax(0,1fr))}.absolute-voice-profile-comparison__profile small{color:#6b7280;display:block;font-size:11px}.absolute-voice-profile-comparison__profile b{display:block}.absolute-voice-profile-comparison__profile em{color:#4b5563;display:block;font-size:13px;margin-top:12px}.absolute-voice-profile-comparison__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-profile-comparison__links a{border:1px solid #a5b4fc;border-radius:999px;color:#4338ca;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-profile-comparison__error{color:#9f1239;font-weight:700}`;
|
|
@@ -8589,29 +8885,29 @@ var defineVoiceProfileComparisonElement = (tagName = "absolute-voice-profile-com
|
|
|
8589
8885
|
});
|
|
8590
8886
|
};
|
|
8591
8887
|
// src/client/profileSwitchRecommendationWidget.ts
|
|
8592
|
-
var
|
|
8593
|
-
var
|
|
8594
|
-
var
|
|
8888
|
+
var DEFAULT_TITLE8 = "Profile Switch Recommendation";
|
|
8889
|
+
var DEFAULT_DESCRIPTION8 = "Compares the current session against measured profile evidence and recommends whether to switch stacks.";
|
|
8890
|
+
var escapeHtml13 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8595
8891
|
var formatRoute = (routes) => routes ? Object.entries(routes).map(([role, provider]) => `${role}: ${provider}`).join(", ") : "No route";
|
|
8596
8892
|
var renderVoiceProfileSwitchRecommendationHTML = (snapshot, options = {}) => {
|
|
8597
8893
|
const recommendation = snapshot.recommendation;
|
|
8598
8894
|
const status = snapshot.error ? "error" : recommendation ? recommendation.status : snapshot.isLoading ? "loading" : "empty";
|
|
8599
8895
|
const label = snapshot.error ? "Unavailable" : recommendation ? recommendation.status === "switch" ? `Switch to ${recommendation.recommendedProfile?.label ?? recommendation.recommendedProfile?.profileId ?? "recommended profile"}` : recommendation.status === "stay" ? "Keep current profile" : "Needs evidence" : snapshot.isLoading ? "Checking" : "No recommendation";
|
|
8600
8896
|
const body = recommendation ? `<div class="absolute-voice-profile-switch__body">
|
|
8601
|
-
<p><strong>Current:</strong> ${
|
|
8602
|
-
<p><strong>Recommended:</strong> ${
|
|
8603
|
-
<p><strong>Routes:</strong> ${
|
|
8604
|
-
<ul>${recommendation.reasons.map((reason) => `<li>${
|
|
8605
|
-
<em>${
|
|
8606
|
-
</div>` : `<p class="absolute-voice-profile-switch__empty">${
|
|
8607
|
-
return `<section class="absolute-voice-profile-switch absolute-voice-profile-switch--${
|
|
8897
|
+
<p><strong>Current:</strong> ${escapeHtml13(recommendation.currentProfile?.label ?? recommendation.currentProfile?.profileId ?? "Unknown")}</p>
|
|
8898
|
+
<p><strong>Recommended:</strong> ${escapeHtml13(recommendation.recommendedProfile?.label ?? recommendation.recommendedProfile?.profileId ?? "None")}</p>
|
|
8899
|
+
<p><strong>Routes:</strong> ${escapeHtml13(formatRoute(recommendation.recommendedProfile?.providerRoutes))}</p>
|
|
8900
|
+
<ul>${recommendation.reasons.map((reason) => `<li>${escapeHtml13(reason)}</li>`).join("")}</ul>
|
|
8901
|
+
<em>${escapeHtml13(recommendation.nextMove)}</em>
|
|
8902
|
+
</div>` : `<p class="absolute-voice-profile-switch__empty">${escapeHtml13(snapshot.error ?? "Run session traffic to populate a recommendation.")}</p>`;
|
|
8903
|
+
return `<section class="absolute-voice-profile-switch absolute-voice-profile-switch--${escapeHtml13(status)}">
|
|
8608
8904
|
<header class="absolute-voice-profile-switch__header">
|
|
8609
|
-
<span class="absolute-voice-profile-switch__eyebrow">${
|
|
8610
|
-
<strong class="absolute-voice-profile-switch__label">${
|
|
8905
|
+
<span class="absolute-voice-profile-switch__eyebrow">${escapeHtml13(options.title ?? DEFAULT_TITLE8)}</span>
|
|
8906
|
+
<strong class="absolute-voice-profile-switch__label">${escapeHtml13(label)}</strong>
|
|
8611
8907
|
</header>
|
|
8612
|
-
<p class="absolute-voice-profile-switch__description">${
|
|
8908
|
+
<p class="absolute-voice-profile-switch__description">${escapeHtml13(options.description ?? DEFAULT_DESCRIPTION8)}</p>
|
|
8613
8909
|
${body}
|
|
8614
|
-
${snapshot.error ? `<p class="absolute-voice-profile-switch__error">${
|
|
8910
|
+
${snapshot.error ? `<p class="absolute-voice-profile-switch__error">${escapeHtml13(snapshot.error)}</p>` : ""}
|
|
8615
8911
|
</section>`;
|
|
8616
8912
|
};
|
|
8617
8913
|
var getVoiceProfileSwitchRecommendationCSS = () => `.absolute-voice-profile-switch{border:1px solid #fed7aa;border-radius:20px;background:#fff7ed;color:#1c1917;padding:18px;box-shadow:0 18px 40px rgba(234,88,12,.12);font-family:inherit}.absolute-voice-profile-switch--switch{border-color:#fdba74}.absolute-voice-profile-switch--stay{border-color:#86efac;background:#f0fdf4}.absolute-voice-profile-switch--warn,.absolute-voice-profile-switch--error{border-color:#fca5a5;background:#fff1f2}.absolute-voice-profile-switch__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-profile-switch__eyebrow{color:#c2410c;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-profile-switch__label{font-size:24px;line-height:1}.absolute-voice-profile-switch__description,.absolute-voice-profile-switch__body em,.absolute-voice-profile-switch__empty{color:#57534e}.absolute-voice-profile-switch__body{background:#fff;border:1px solid #fed7aa;border-radius:16px;margin-top:14px;padding:14px}.absolute-voice-profile-switch__body p{margin:.35rem 0}.absolute-voice-profile-switch__body ul{margin:.75rem 0;padding-left:1.2rem}.absolute-voice-profile-switch__body em{display:block}.absolute-voice-profile-switch__error{color:#9f1239;font-weight:700}`;
|
|
@@ -8652,13 +8948,13 @@ var defineVoiceProfileSwitchRecommendationElement = (tagName = "absolute-voice-p
|
|
|
8652
8948
|
});
|
|
8653
8949
|
};
|
|
8654
8950
|
// src/client/readinessFailuresWidget.ts
|
|
8655
|
-
var
|
|
8656
|
-
var
|
|
8657
|
-
var
|
|
8951
|
+
var DEFAULT_TITLE9 = "Readiness Gate Explanations";
|
|
8952
|
+
var DEFAULT_DESCRIPTION9 = "Structured reasons for calibrated production-readiness warnings and failures.";
|
|
8953
|
+
var DEFAULT_LINKS5 = [
|
|
8658
8954
|
{ href: "/production-readiness", label: "Readiness page" },
|
|
8659
8955
|
{ href: "/voice/slo-readiness-thresholds", label: "Gate thresholds" }
|
|
8660
8956
|
];
|
|
8661
|
-
var
|
|
8957
|
+
var escapeHtml14 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8662
8958
|
var formatExplanationValue = (value, unit) => {
|
|
8663
8959
|
if (value === undefined || value === null) {
|
|
8664
8960
|
return "n/a";
|
|
@@ -8686,36 +8982,36 @@ var createVoiceReadinessFailuresViewModel = (snapshot, options = {}) => {
|
|
|
8686
8982
|
const failures = snapshot.report?.checks.map(toFailureView).filter((value) => !!value) ?? [];
|
|
8687
8983
|
const hasOpenIssues = failures.length > 0;
|
|
8688
8984
|
return {
|
|
8689
|
-
description: options.description ??
|
|
8985
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
8690
8986
|
error: snapshot.error,
|
|
8691
8987
|
failures,
|
|
8692
8988
|
isLoading: snapshot.isLoading,
|
|
8693
8989
|
label: snapshot.error ? "Unavailable" : snapshot.report ? hasOpenIssues ? `${failures.length} calibrated gate issue(s)` : "No calibrated gate issues" : snapshot.isLoading ? "Checking" : "No readiness report",
|
|
8694
|
-
links: options.links ??
|
|
8990
|
+
links: options.links ?? DEFAULT_LINKS5,
|
|
8695
8991
|
status: snapshot.error ? "error" : snapshot.report ? hasOpenIssues ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
8696
|
-
title: options.title ??
|
|
8992
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
8697
8993
|
updatedAt: snapshot.updatedAt
|
|
8698
8994
|
};
|
|
8699
8995
|
};
|
|
8700
8996
|
var renderVoiceReadinessFailuresHTML = (snapshot, options = {}) => {
|
|
8701
8997
|
const model = createVoiceReadinessFailuresViewModel(snapshot, options);
|
|
8702
|
-
const failures = model.failures.length ? `<div class="absolute-voice-readiness-failures__items">${model.failures.map((failure) => `<article class="absolute-voice-readiness-failures__item absolute-voice-readiness-failures__item--${
|
|
8703
|
-
<span>${
|
|
8704
|
-
<strong>${
|
|
8705
|
-
<p>Observed ${
|
|
8706
|
-
<p>${
|
|
8707
|
-
<p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${
|
|
8708
|
-
</article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ?
|
|
8709
|
-
const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${
|
|
8710
|
-
return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${
|
|
8998
|
+
const failures = model.failures.length ? `<div class="absolute-voice-readiness-failures__items">${model.failures.map((failure) => `<article class="absolute-voice-readiness-failures__item absolute-voice-readiness-failures__item--${escapeHtml14(failure.status)}">
|
|
8999
|
+
<span>${escapeHtml14(failure.status.toUpperCase())}</span>
|
|
9000
|
+
<strong>${escapeHtml14(failure.label)}</strong>
|
|
9001
|
+
<p>Observed ${escapeHtml14(failure.observed)} against ${escapeHtml14(failure.thresholdLabel)} ${escapeHtml14(failure.threshold)}.</p>
|
|
9002
|
+
<p>${escapeHtml14(failure.remediation)}</p>
|
|
9003
|
+
<p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${escapeHtml14(failure.evidenceHref)}">Evidence</a>` : ""}${failure.sourceHref ? `<a href="${escapeHtml14(failure.sourceHref)}">Threshold source</a>` : ""}</p>
|
|
9004
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ? escapeHtml14(model.error) : "No calibrated readiness gate explanations are open."}</p>`;
|
|
9005
|
+
const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${escapeHtml14(link.href)}">${escapeHtml14(link.label)}</a>`).join("")}</p>` : "";
|
|
9006
|
+
return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${escapeHtml14(model.status)}">
|
|
8711
9007
|
<header class="absolute-voice-readiness-failures__header">
|
|
8712
|
-
<span class="absolute-voice-readiness-failures__eyebrow">${
|
|
8713
|
-
<strong class="absolute-voice-readiness-failures__label">${
|
|
9008
|
+
<span class="absolute-voice-readiness-failures__eyebrow">${escapeHtml14(model.title)}</span>
|
|
9009
|
+
<strong class="absolute-voice-readiness-failures__label">${escapeHtml14(model.label)}</strong>
|
|
8714
9010
|
</header>
|
|
8715
|
-
<p class="absolute-voice-readiness-failures__description">${
|
|
9011
|
+
<p class="absolute-voice-readiness-failures__description">${escapeHtml14(model.description)}</p>
|
|
8716
9012
|
${failures}
|
|
8717
9013
|
${links}
|
|
8718
|
-
${model.error ? `<p class="absolute-voice-readiness-failures__error">${
|
|
9014
|
+
${model.error ? `<p class="absolute-voice-readiness-failures__error">${escapeHtml14(model.error)}</p>` : ""}
|
|
8719
9015
|
</section>`;
|
|
8720
9016
|
};
|
|
8721
9017
|
var getVoiceReadinessFailuresCSS = () => `.absolute-voice-readiness-failures{border:1px solid #fed7aa;border-radius:20px;background:#fff7ed;color:#1c1917;padding:18px;box-shadow:0 18px 40px rgba(234,88,12,.12);font-family:inherit}.absolute-voice-readiness-failures--ready{border-color:#86efac;background:#f0fdf4}.absolute-voice-readiness-failures--error{border-color:#fda4af;background:#fff1f2}.absolute-voice-readiness-failures__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-readiness-failures__eyebrow{color:#9a3412;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-readiness-failures__label{font-size:24px;line-height:1}.absolute-voice-readiness-failures__description,.absolute-voice-readiness-failures__empty{color:#57534e}.absolute-voice-readiness-failures__items{display:grid;gap:10px;margin-top:14px}.absolute-voice-readiness-failures__item{background:white;border:1px solid #fed7aa;border-radius:16px;padding:12px}.absolute-voice-readiness-failures__item--fail{border-color:#fb7185}.absolute-voice-readiness-failures__item span{color:#9a3412;display:block;font-size:12px;font-weight:900;text-transform:uppercase}.absolute-voice-readiness-failures__item strong{display:block;font-size:18px;margin-top:4px}.absolute-voice-readiness-failures__item p{margin:.45rem 0 0}.absolute-voice-readiness-failures__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-readiness-failures__links a{border:1px solid #fdba74;border-radius:999px;color:#9a3412;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-readiness-failures__error{color:#9f1239;font-weight:700}`;
|
|
@@ -8755,9 +9051,9 @@ var defineVoiceReadinessFailuresElement = (tagName = "absolute-voice-readiness-f
|
|
|
8755
9051
|
});
|
|
8756
9052
|
};
|
|
8757
9053
|
// src/client/opsActionCenterWidget.ts
|
|
8758
|
-
var
|
|
8759
|
-
var
|
|
8760
|
-
var
|
|
9054
|
+
var DEFAULT_TITLE10 = "Voice Ops Action Center";
|
|
9055
|
+
var DEFAULT_DESCRIPTION10 = "Run production voice proofs and operator actions from one primitive panel.";
|
|
9056
|
+
var escapeHtml15 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8761
9057
|
var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
8762
9058
|
const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
|
|
8763
9059
|
return {
|
|
@@ -8768,29 +9064,29 @@ var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
|
8768
9064
|
isRunning: snapshot.runningActionId === action.id,
|
|
8769
9065
|
label: action.label
|
|
8770
9066
|
})),
|
|
8771
|
-
description: options.description ??
|
|
9067
|
+
description: options.description ?? DEFAULT_DESCRIPTION10,
|
|
8772
9068
|
error: snapshot.error,
|
|
8773
9069
|
isRunning: snapshot.isRunning,
|
|
8774
9070
|
label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
|
|
8775
9071
|
lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
|
|
8776
9072
|
status,
|
|
8777
|
-
title: options.title ??
|
|
9073
|
+
title: options.title ?? DEFAULT_TITLE10
|
|
8778
9074
|
};
|
|
8779
9075
|
};
|
|
8780
9076
|
var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
|
|
8781
9077
|
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
8782
|
-
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${
|
|
8783
|
-
${
|
|
9078
|
+
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml15(action.id)}"${action.disabled ? " disabled" : ""}>
|
|
9079
|
+
${escapeHtml15(action.isRunning ? "Working..." : action.label)}
|
|
8784
9080
|
</button>`).join("");
|
|
8785
|
-
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${
|
|
9081
|
+
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml15(model.status)}">
|
|
8786
9082
|
<header class="absolute-voice-ops-action-center__header">
|
|
8787
|
-
<span class="absolute-voice-ops-action-center__eyebrow">${
|
|
8788
|
-
<strong class="absolute-voice-ops-action-center__label">${
|
|
9083
|
+
<span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml15(model.title)}</span>
|
|
9084
|
+
<strong class="absolute-voice-ops-action-center__label">${escapeHtml15(model.label)}</strong>
|
|
8789
9085
|
</header>
|
|
8790
|
-
<p class="absolute-voice-ops-action-center__description">${
|
|
9086
|
+
<p class="absolute-voice-ops-action-center__description">${escapeHtml15(model.description)}</p>
|
|
8791
9087
|
<div class="absolute-voice-ops-action-center__actions">${actions}</div>
|
|
8792
|
-
<p class="absolute-voice-ops-action-center__result">${
|
|
8793
|
-
${model.error ? `<p class="absolute-voice-ops-action-center__error">${
|
|
9088
|
+
<p class="absolute-voice-ops-action-center__result">${escapeHtml15(model.lastResultLabel)}</p>
|
|
9089
|
+
${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml15(model.error)}</p>` : ""}
|
|
8794
9090
|
</section>`;
|
|
8795
9091
|
};
|
|
8796
9092
|
var getVoiceOpsActionCenterCSS = () => `.absolute-voice-ops-action-center{border:1px solid #d5cbb8;border-radius:20px;background:#fffaf1;color:#17130b;padding:18px;box-shadow:0 18px 40px rgba(58,42,16,.12);font-family:inherit}.absolute-voice-ops-action-center--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-action-center__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-action-center__eyebrow{color:#725d37;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-action-center__label{font-size:28px;line-height:1}.absolute-voice-ops-action-center__description,.absolute-voice-ops-action-center__result{color:#5b4b2f;margin:12px 0 0}.absolute-voice-ops-action-center__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-action-center__actions button{background:#7c4a03;border:0;border-radius:999px;color:#fff8e8;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-ops-action-center__actions button:disabled{cursor:not-allowed;opacity:.5}.absolute-voice-ops-action-center__error{color:#9f1239;font-weight:700}`;
|
|
@@ -9389,7 +9685,7 @@ var ACTION_LABELS = {
|
|
|
9389
9685
|
"resume-assistant": "Resume assistant",
|
|
9390
9686
|
tag: "Tag"
|
|
9391
9687
|
};
|
|
9392
|
-
var
|
|
9688
|
+
var escapeHtml16 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9393
9689
|
var createVoiceLiveOpsInput = (action, input) => ({
|
|
9394
9690
|
action,
|
|
9395
9691
|
assignee: input.assignee,
|
|
@@ -9400,17 +9696,17 @@ var createVoiceLiveOpsInput = (action, input) => ({
|
|
|
9400
9696
|
var renderVoiceLiveOpsHTML = (snapshot, options = {}) => {
|
|
9401
9697
|
const sessionId = options.getSessionId?.() ?? "";
|
|
9402
9698
|
const disabled = snapshot.isRunning || !sessionId;
|
|
9403
|
-
const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${
|
|
9404
|
-
const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${
|
|
9699
|
+
const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml16(action)}"${disabled ? " disabled" : ""}>${escapeHtml16(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
|
|
9700
|
+
const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml16(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml16(snapshot.lastResult.action)}. Control: ${escapeHtml16(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
|
|
9405
9701
|
return `<section class="absolute-voice-live-ops">
|
|
9406
9702
|
<header class="absolute-voice-live-ops__header">
|
|
9407
|
-
<span>${
|
|
9408
|
-
<strong>${
|
|
9703
|
+
<span>${escapeHtml16(options.title ?? "Live Ops")}</span>
|
|
9704
|
+
<strong>${escapeHtml16(sessionId || "No active session")}</strong>
|
|
9409
9705
|
</header>
|
|
9410
|
-
<p class="absolute-voice-live-ops__description">${
|
|
9411
|
-
<label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${
|
|
9412
|
-
<label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${
|
|
9413
|
-
<label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${
|
|
9706
|
+
<p class="absolute-voice-live-ops__description">${escapeHtml16(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
|
|
9707
|
+
<label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml16(options.defaultAssignee ?? "operator")}" /></label>
|
|
9708
|
+
<label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml16(options.defaultTag ?? "live-ops")}" /></label>
|
|
9709
|
+
<label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml16(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
|
|
9414
9710
|
<div class="absolute-voice-live-ops__actions">${actions}</div>
|
|
9415
9711
|
${result}
|
|
9416
9712
|
</section>`;
|
|
@@ -9497,16 +9793,16 @@ var defineVoiceLiveOpsElement = (tagName = "absolute-voice-live-ops", options =
|
|
|
9497
9793
|
});
|
|
9498
9794
|
};
|
|
9499
9795
|
// src/client/opsActionHistoryWidget.ts
|
|
9500
|
-
var
|
|
9796
|
+
var escapeHtml17 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9501
9797
|
var renderVoiceOpsActionHistoryWidgetHTML = (snapshot, options = {}) => {
|
|
9502
9798
|
const report = snapshot.report;
|
|
9503
9799
|
const entries = (report?.entries ?? []).slice(0, options.limit ?? 5);
|
|
9504
|
-
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${
|
|
9800
|
+
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${escapeHtml17(entry.actionId)}</span><strong>${escapeHtml17(entry.ok ? "Success" : "Failed")}</strong><small>${escapeHtml17(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</small></li>`).join("");
|
|
9505
9801
|
return `<section class="absolute-voice-ops-action-history">
|
|
9506
|
-
<header><span>Operator proof</span><strong>${
|
|
9802
|
+
<header><span>Operator proof</span><strong>${escapeHtml17(options.title ?? "Action History")}</strong></header>
|
|
9507
9803
|
<p>${String(report?.total ?? 0)} action(s), ${String(report?.failed ?? 0)} failed.</p>
|
|
9508
9804
|
<ul>${rows || "<li>No operator actions recorded yet.</li>"}</ul>
|
|
9509
|
-
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${
|
|
9805
|
+
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${escapeHtml17(snapshot.error)}</p>` : ""}
|
|
9510
9806
|
</section>`;
|
|
9511
9807
|
};
|
|
9512
9808
|
var getVoiceOpsActionHistoryCSS = () => `.absolute-voice-ops-action-history{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;font-family:inherit}.absolute-voice-ops-action-history header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-action-history header span{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-action-history header strong{font-size:24px}.absolute-voice-ops-action-history p{color:#514733}.absolute-voice-ops-action-history ul{display:grid;gap:8px;list-style:none;margin:12px 0 0;padding:0}.absolute-voice-ops-action-history__entry{background:#fff;border:1px solid #eee4d2;border-radius:14px;display:grid;gap:3px;padding:10px 12px}.absolute-voice-ops-action-history__entry--error{border-color:#f2a7a7}.absolute-voice-ops-action-history__entry span{font-weight:800}.absolute-voice-ops-action-history__entry small{color:#655944}.absolute-voice-ops-action-history__error{color:#9f1239;font-weight:700}`;
|
|
@@ -9527,9 +9823,9 @@ var mountVoiceOpsActionHistory = (element, path = "/api/voice/ops-actions/histor
|
|
|
9527
9823
|
};
|
|
9528
9824
|
};
|
|
9529
9825
|
// src/client/deliveryRuntimeWidget.ts
|
|
9530
|
-
var
|
|
9531
|
-
var
|
|
9532
|
-
var
|
|
9826
|
+
var DEFAULT_TITLE11 = "Voice Delivery Runtime";
|
|
9827
|
+
var DEFAULT_DESCRIPTION11 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
9828
|
+
var escapeHtml18 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9533
9829
|
var createSurface = (id, summary) => {
|
|
9534
9830
|
if (!summary) {
|
|
9535
9831
|
return {
|
|
@@ -9563,7 +9859,7 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
9563
9859
|
];
|
|
9564
9860
|
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
9565
9861
|
return {
|
|
9566
|
-
description: options.description ??
|
|
9862
|
+
description: options.description ?? DEFAULT_DESCRIPTION11,
|
|
9567
9863
|
error: snapshot.error,
|
|
9568
9864
|
actionError: snapshot.actionError,
|
|
9569
9865
|
actionStatus: snapshot.actionStatus,
|
|
@@ -9572,32 +9868,32 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
9572
9868
|
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
9573
9869
|
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
9574
9870
|
surfaces,
|
|
9575
|
-
title: options.title ??
|
|
9871
|
+
title: options.title ?? DEFAULT_TITLE11,
|
|
9576
9872
|
updatedAt: snapshot.updatedAt
|
|
9577
9873
|
};
|
|
9578
9874
|
};
|
|
9579
9875
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
9580
9876
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
9581
|
-
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${
|
|
9582
|
-
<span>${
|
|
9583
|
-
<strong>${
|
|
9877
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml18(surface.status)}">
|
|
9878
|
+
<span>${escapeHtml18(surface.label)}</span>
|
|
9879
|
+
<strong>${escapeHtml18(surface.detail)}</strong>
|
|
9584
9880
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
9585
9881
|
</li>`).join("");
|
|
9586
9882
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
9587
9883
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
9588
9884
|
<button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
|
|
9589
9885
|
</div>`;
|
|
9590
|
-
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
9591
|
-
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${
|
|
9886
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml18(model.actionError)}</p>` : "";
|
|
9887
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml18(model.status)}">
|
|
9592
9888
|
<header class="absolute-voice-delivery-runtime__header">
|
|
9593
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
9594
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
9889
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml18(model.title)}</span>
|
|
9890
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml18(model.label)}</strong>
|
|
9595
9891
|
</header>
|
|
9596
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
9892
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml18(model.description)}</p>
|
|
9597
9893
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
9598
9894
|
${actions}
|
|
9599
9895
|
${actionError}
|
|
9600
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
9896
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml18(model.error)}</p>` : ""}
|
|
9601
9897
|
</section>`;
|
|
9602
9898
|
};
|
|
9603
9899
|
var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-delivery-runtime__actions button{background:#134e2d;border:0;border-radius:999px;color:#f6fff9;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-delivery-runtime__actions button:disabled{cursor:not-allowed;opacity:.48}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
|
|
@@ -9733,9 +10029,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
9733
10029
|
};
|
|
9734
10030
|
};
|
|
9735
10031
|
// src/client/routingStatusWidget.ts
|
|
9736
|
-
var
|
|
9737
|
-
var
|
|
9738
|
-
var
|
|
10032
|
+
var DEFAULT_TITLE12 = "Voice Routing";
|
|
10033
|
+
var DEFAULT_DESCRIPTION12 = "Latest provider routing decision from the self-hosted trace store.";
|
|
10034
|
+
var escapeHtml19 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9739
10035
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
9740
10036
|
var formatProviderRoutes2 = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
|
|
9741
10037
|
var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
|
|
@@ -9804,35 +10100,35 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
9804
10100
|
return {
|
|
9805
10101
|
activeStack,
|
|
9806
10102
|
decision,
|
|
9807
|
-
description: options.description ??
|
|
10103
|
+
description: options.description ?? DEFAULT_DESCRIPTION12,
|
|
9808
10104
|
error: snapshot.error,
|
|
9809
10105
|
isLoading: snapshot.isLoading,
|
|
9810
10106
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
9811
10107
|
rows,
|
|
9812
10108
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
9813
|
-
title: options.title ??
|
|
10109
|
+
title: options.title ?? DEFAULT_TITLE12,
|
|
9814
10110
|
updatedAt: snapshot.updatedAt
|
|
9815
10111
|
};
|
|
9816
10112
|
};
|
|
9817
10113
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
9818
10114
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
9819
10115
|
const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
|
|
9820
|
-
<span>${
|
|
9821
|
-
<strong>${
|
|
10116
|
+
<span>${escapeHtml19(item.label)}</span>
|
|
10117
|
+
<strong>${escapeHtml19(item.value)}</strong>
|
|
9822
10118
|
</div>`).join("")}</div>` : "";
|
|
9823
10119
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
9824
|
-
<span>${
|
|
9825
|
-
<strong>${
|
|
10120
|
+
<span>${escapeHtml19(row.label)}</span>
|
|
10121
|
+
<strong>${escapeHtml19(row.value)}</strong>
|
|
9826
10122
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
9827
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
10123
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml19(model.status)}">
|
|
9828
10124
|
<header class="absolute-voice-routing-status__header">
|
|
9829
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
9830
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
10125
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml19(model.title)}</span>
|
|
10126
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml19(model.label)}</strong>
|
|
9831
10127
|
</header>
|
|
9832
|
-
<p class="absolute-voice-routing-status__description">${
|
|
10128
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml19(model.description)}</p>
|
|
9833
10129
|
${activeStack}
|
|
9834
10130
|
${rows}
|
|
9835
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
10131
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml19(model.error)}</p>` : ""}
|
|
9836
10132
|
</section>`;
|
|
9837
10133
|
};
|
|
9838
10134
|
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}}`;
|
|
@@ -10631,7 +10927,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
10631
10927
|
};
|
|
10632
10928
|
};
|
|
10633
10929
|
// src/client/providerSimulationControlsWidget.ts
|
|
10634
|
-
var
|
|
10930
|
+
var escapeHtml20 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10635
10931
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
10636
10932
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
10637
10933
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -10651,18 +10947,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
10651
10947
|
};
|
|
10652
10948
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
10653
10949
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
10654
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
10655
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
10950
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml20(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml20(provider.provider)} ${escapeHtml20(formatKind(options.kind))} failure</button>`).join("");
|
|
10951
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml20(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml20(provider.provider)} recovered</button>`).join("");
|
|
10656
10952
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
10657
10953
|
<header class="absolute-voice-provider-simulation__header">
|
|
10658
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
10659
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
10954
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml20(model.title)}</span>
|
|
10955
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml20(model.label)}</strong>
|
|
10660
10956
|
</header>
|
|
10661
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
10662
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
10957
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml20(model.description)}</p>
|
|
10958
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml20(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
10663
10959
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
10664
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
10665
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
10960
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml20(snapshot.error)}</p>` : ""}
|
|
10961
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml20(model.resultText)}</pre>` : ""}
|
|
10666
10962
|
</section>`;
|
|
10667
10963
|
};
|
|
10668
10964
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -10727,9 +11023,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
10727
11023
|
});
|
|
10728
11024
|
};
|
|
10729
11025
|
// src/client/providerStatusWidget.ts
|
|
10730
|
-
var
|
|
10731
|
-
var
|
|
10732
|
-
var
|
|
11026
|
+
var DEFAULT_TITLE13 = "Voice Providers";
|
|
11027
|
+
var DEFAULT_DESCRIPTION13 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
11028
|
+
var escapeHtml21 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10733
11029
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
10734
11030
|
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
10735
11031
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -10773,37 +11069,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
10773
11069
|
const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
|
|
10774
11070
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
10775
11071
|
return {
|
|
10776
|
-
description: options.description ??
|
|
11072
|
+
description: options.description ?? DEFAULT_DESCRIPTION13,
|
|
10777
11073
|
error: snapshot.error,
|
|
10778
11074
|
isLoading: snapshot.isLoading,
|
|
10779
11075
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
10780
11076
|
providers,
|
|
10781
11077
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
10782
|
-
title: options.title ??
|
|
11078
|
+
title: options.title ?? DEFAULT_TITLE13,
|
|
10783
11079
|
updatedAt: snapshot.updatedAt
|
|
10784
11080
|
};
|
|
10785
11081
|
};
|
|
10786
11082
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
10787
11083
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
10788
|
-
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--${
|
|
11084
|
+
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--${escapeHtml21(provider.status)}">
|
|
10789
11085
|
<header>
|
|
10790
|
-
<strong>${
|
|
10791
|
-
<span>${
|
|
11086
|
+
<strong>${escapeHtml21(provider.label)}</strong>
|
|
11087
|
+
<span>${escapeHtml21(formatStatus3(provider.status))}</span>
|
|
10792
11088
|
</header>
|
|
10793
|
-
<p>${
|
|
11089
|
+
<p>${escapeHtml21(provider.detail)}</p>
|
|
10794
11090
|
<dl>${provider.rows.map((row) => `<div>
|
|
10795
|
-
<dt>${
|
|
10796
|
-
<dd>${
|
|
11091
|
+
<dt>${escapeHtml21(row.label)}</dt>
|
|
11092
|
+
<dd>${escapeHtml21(row.value)}</dd>
|
|
10797
11093
|
</div>`).join("")}</dl>
|
|
10798
11094
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
10799
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
11095
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml21(model.status)}">
|
|
10800
11096
|
<header class="absolute-voice-provider-status__header">
|
|
10801
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
10802
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
11097
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml21(model.title)}</span>
|
|
11098
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml21(model.label)}</strong>
|
|
10803
11099
|
</header>
|
|
10804
|
-
<p class="absolute-voice-provider-status__description">${
|
|
11100
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml21(model.description)}</p>
|
|
10805
11101
|
${providers}
|
|
10806
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
11102
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml21(model.error)}</p>` : ""}
|
|
10807
11103
|
</section>`;
|
|
10808
11104
|
};
|
|
10809
11105
|
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}`;
|
|
@@ -10844,9 +11140,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
10844
11140
|
});
|
|
10845
11141
|
};
|
|
10846
11142
|
// src/client/providerCapabilitiesWidget.ts
|
|
10847
|
-
var
|
|
10848
|
-
var
|
|
10849
|
-
var
|
|
11143
|
+
var DEFAULT_TITLE14 = "Provider Capabilities";
|
|
11144
|
+
var DEFAULT_DESCRIPTION14 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
11145
|
+
var escapeHtml22 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10850
11146
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
10851
11147
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
10852
11148
|
var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -10890,36 +11186,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
10890
11186
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
10891
11187
|
return {
|
|
10892
11188
|
capabilities,
|
|
10893
|
-
description: options.description ??
|
|
11189
|
+
description: options.description ?? DEFAULT_DESCRIPTION14,
|
|
10894
11190
|
error: snapshot.error,
|
|
10895
11191
|
isLoading: snapshot.isLoading,
|
|
10896
11192
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
10897
11193
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
10898
|
-
title: options.title ??
|
|
11194
|
+
title: options.title ?? DEFAULT_TITLE14,
|
|
10899
11195
|
updatedAt: snapshot.updatedAt
|
|
10900
11196
|
};
|
|
10901
11197
|
};
|
|
10902
11198
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
10903
11199
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
10904
|
-
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--${
|
|
11200
|
+
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--${escapeHtml22(capability.status)}">
|
|
10905
11201
|
<header>
|
|
10906
|
-
<strong>${
|
|
10907
|
-
<span>${
|
|
11202
|
+
<strong>${escapeHtml22(capability.label)}</strong>
|
|
11203
|
+
<span>${escapeHtml22(formatStatus4(capability.status))}</span>
|
|
10908
11204
|
</header>
|
|
10909
|
-
<p>${
|
|
11205
|
+
<p>${escapeHtml22(capability.detail)}</p>
|
|
10910
11206
|
<dl>${capability.rows.map((row) => `<div>
|
|
10911
|
-
<dt>${
|
|
10912
|
-
<dd>${
|
|
11207
|
+
<dt>${escapeHtml22(row.label)}</dt>
|
|
11208
|
+
<dd>${escapeHtml22(row.value)}</dd>
|
|
10913
11209
|
</div>`).join("")}</dl>
|
|
10914
11210
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
10915
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
11211
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml22(model.status)}">
|
|
10916
11212
|
<header class="absolute-voice-provider-capabilities__header">
|
|
10917
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
10918
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
11213
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml22(model.title)}</span>
|
|
11214
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml22(model.label)}</strong>
|
|
10919
11215
|
</header>
|
|
10920
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
11216
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml22(model.description)}</p>
|
|
10921
11217
|
${capabilities}
|
|
10922
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
11218
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml22(model.error)}</p>` : ""}
|
|
10923
11219
|
</section>`;
|
|
10924
11220
|
};
|
|
10925
11221
|
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}`;
|
|
@@ -10960,9 +11256,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
10960
11256
|
});
|
|
10961
11257
|
};
|
|
10962
11258
|
// src/client/providerContractsWidget.ts
|
|
10963
|
-
var
|
|
10964
|
-
var
|
|
10965
|
-
var
|
|
11259
|
+
var DEFAULT_TITLE15 = "Provider Contracts";
|
|
11260
|
+
var DEFAULT_DESCRIPTION15 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
11261
|
+
var escapeHtml23 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10966
11262
|
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
10967
11263
|
var formatStatus5 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
10968
11264
|
var contractDetail = (row) => {
|
|
@@ -10994,38 +11290,38 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
|
10994
11290
|
}));
|
|
10995
11291
|
const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
|
|
10996
11292
|
return {
|
|
10997
|
-
description: options.description ??
|
|
11293
|
+
description: options.description ?? DEFAULT_DESCRIPTION15,
|
|
10998
11294
|
error: snapshot.error,
|
|
10999
11295
|
isLoading: snapshot.isLoading,
|
|
11000
11296
|
label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
|
|
11001
11297
|
rows,
|
|
11002
11298
|
status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
11003
|
-
title: options.title ??
|
|
11299
|
+
title: options.title ?? DEFAULT_TITLE15,
|
|
11004
11300
|
updatedAt: snapshot.updatedAt
|
|
11005
11301
|
};
|
|
11006
11302
|
};
|
|
11007
11303
|
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
11008
11304
|
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
11009
|
-
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--${
|
|
11305
|
+
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--${escapeHtml23(row.status)}">
|
|
11010
11306
|
<header>
|
|
11011
|
-
<strong>${
|
|
11012
|
-
<span>${
|
|
11307
|
+
<strong>${escapeHtml23(row.label)}</strong>
|
|
11308
|
+
<span>${escapeHtml23(formatStatus5(row.status))}</span>
|
|
11013
11309
|
</header>
|
|
11014
|
-
<p>${
|
|
11015
|
-
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${
|
|
11310
|
+
<p>${escapeHtml23(row.detail)}</p>
|
|
11311
|
+
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml23(remediation.href)}">${escapeHtml23(remediation.label)}</a>` : `<strong>${escapeHtml23(remediation.label)}</strong>`}<span>${escapeHtml23(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
|
|
11016
11312
|
<dl>${row.rows.map((item) => `<div>
|
|
11017
|
-
<dt>${
|
|
11018
|
-
<dd>${
|
|
11313
|
+
<dt>${escapeHtml23(item.label)}</dt>
|
|
11314
|
+
<dd>${escapeHtml23(item.value)}</dd>
|
|
11019
11315
|
</div>`).join("")}</dl>
|
|
11020
11316
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
11021
|
-
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${
|
|
11317
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml23(model.status)}">
|
|
11022
11318
|
<header class="absolute-voice-provider-contracts__header">
|
|
11023
|
-
<span class="absolute-voice-provider-contracts__eyebrow">${
|
|
11024
|
-
<strong class="absolute-voice-provider-contracts__label">${
|
|
11319
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml23(model.title)}</span>
|
|
11320
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml23(model.label)}</strong>
|
|
11025
11321
|
</header>
|
|
11026
|
-
<p class="absolute-voice-provider-contracts__description">${
|
|
11322
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml23(model.description)}</p>
|
|
11027
11323
|
${rows}
|
|
11028
|
-
${model.error ? `<p class="absolute-voice-provider-contracts__error">${
|
|
11324
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml23(model.error)}</p>` : ""}
|
|
11029
11325
|
</section>`;
|
|
11030
11326
|
};
|
|
11031
11327
|
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}`;
|
|
@@ -11066,9 +11362,9 @@ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-co
|
|
|
11066
11362
|
});
|
|
11067
11363
|
};
|
|
11068
11364
|
// src/client/turnQualityWidget.ts
|
|
11069
|
-
var
|
|
11070
|
-
var
|
|
11071
|
-
var
|
|
11365
|
+
var DEFAULT_TITLE16 = "Turn Quality";
|
|
11366
|
+
var DEFAULT_DESCRIPTION16 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
11367
|
+
var escapeHtml24 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11072
11368
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
11073
11369
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
11074
11370
|
var getTurnDetail = (turn) => {
|
|
@@ -11112,37 +11408,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
11112
11408
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
11113
11409
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
11114
11410
|
return {
|
|
11115
|
-
description: options.description ??
|
|
11411
|
+
description: options.description ?? DEFAULT_DESCRIPTION16,
|
|
11116
11412
|
error: snapshot.error,
|
|
11117
11413
|
isLoading: snapshot.isLoading,
|
|
11118
11414
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
11119
11415
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
11120
|
-
title: options.title ??
|
|
11416
|
+
title: options.title ?? DEFAULT_TITLE16,
|
|
11121
11417
|
turns,
|
|
11122
11418
|
updatedAt: snapshot.updatedAt
|
|
11123
11419
|
};
|
|
11124
11420
|
};
|
|
11125
11421
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
11126
11422
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
11127
|
-
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--${
|
|
11423
|
+
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--${escapeHtml24(turn.status)}">
|
|
11128
11424
|
<header>
|
|
11129
|
-
<strong>${
|
|
11130
|
-
<span>${
|
|
11425
|
+
<strong>${escapeHtml24(turn.label)}</strong>
|
|
11426
|
+
<span>${escapeHtml24(turn.status)}</span>
|
|
11131
11427
|
</header>
|
|
11132
|
-
<p>${
|
|
11428
|
+
<p>${escapeHtml24(turn.detail)}</p>
|
|
11133
11429
|
<dl>${turn.rows.map((row) => `<div>
|
|
11134
|
-
<dt>${
|
|
11135
|
-
<dd>${
|
|
11430
|
+
<dt>${escapeHtml24(row.label)}</dt>
|
|
11431
|
+
<dd>${escapeHtml24(row.value)}</dd>
|
|
11136
11432
|
</div>`).join("")}</dl>
|
|
11137
11433
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
11138
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
11434
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml24(model.status)}">
|
|
11139
11435
|
<header class="absolute-voice-turn-quality__header">
|
|
11140
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
11141
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
11436
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml24(model.title)}</span>
|
|
11437
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml24(model.label)}</strong>
|
|
11142
11438
|
</header>
|
|
11143
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
11439
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml24(model.description)}</p>
|
|
11144
11440
|
${turns}
|
|
11145
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
11441
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml24(model.error)}</p>` : ""}
|
|
11146
11442
|
</section>`;
|
|
11147
11443
|
};
|
|
11148
11444
|
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}`;
|
|
@@ -11183,56 +11479,56 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
11183
11479
|
});
|
|
11184
11480
|
};
|
|
11185
11481
|
// src/client/turnLatencyWidget.ts
|
|
11186
|
-
var
|
|
11187
|
-
var
|
|
11482
|
+
var DEFAULT_TITLE17 = "Turn Latency";
|
|
11483
|
+
var DEFAULT_DESCRIPTION17 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
11188
11484
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
11189
|
-
var
|
|
11190
|
-
var
|
|
11485
|
+
var escapeHtml25 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11486
|
+
var formatMs4 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
11191
11487
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
11192
11488
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
11193
11489
|
...turn,
|
|
11194
11490
|
label: turn.text || "Empty turn",
|
|
11195
11491
|
rows: turn.stages.map((stage) => ({
|
|
11196
11492
|
label: stage.label,
|
|
11197
|
-
value:
|
|
11493
|
+
value: formatMs4(stage.valueMs)
|
|
11198
11494
|
}))
|
|
11199
11495
|
}));
|
|
11200
11496
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
11201
11497
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
11202
11498
|
return {
|
|
11203
|
-
description: options.description ??
|
|
11499
|
+
description: options.description ?? DEFAULT_DESCRIPTION17,
|
|
11204
11500
|
error: snapshot.error,
|
|
11205
11501
|
isLoading: snapshot.isLoading,
|
|
11206
|
-
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${
|
|
11502
|
+
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs4(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
11207
11503
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
11208
11504
|
showProofAction: Boolean(options.proofPath),
|
|
11209
11505
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
11210
|
-
title: options.title ??
|
|
11506
|
+
title: options.title ?? DEFAULT_TITLE17,
|
|
11211
11507
|
turns,
|
|
11212
11508
|
updatedAt: snapshot.updatedAt
|
|
11213
11509
|
};
|
|
11214
11510
|
};
|
|
11215
11511
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
11216
11512
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
11217
|
-
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--${
|
|
11513
|
+
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--${escapeHtml25(turn.status)}">
|
|
11218
11514
|
<header>
|
|
11219
|
-
<strong>${
|
|
11220
|
-
<span>${
|
|
11515
|
+
<strong>${escapeHtml25(turn.label)}</strong>
|
|
11516
|
+
<span>${escapeHtml25(turn.status)}</span>
|
|
11221
11517
|
</header>
|
|
11222
11518
|
<dl>${turn.rows.map((row) => `<div>
|
|
11223
|
-
<dt>${
|
|
11224
|
-
<dd>${
|
|
11519
|
+
<dt>${escapeHtml25(row.label)}</dt>
|
|
11520
|
+
<dd>${escapeHtml25(row.value)}</dd>
|
|
11225
11521
|
</div>`).join("")}</dl>
|
|
11226
11522
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
11227
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
11523
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml25(model.status)}">
|
|
11228
11524
|
<header class="absolute-voice-turn-latency__header">
|
|
11229
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
11230
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
11525
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml25(model.title)}</span>
|
|
11526
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml25(model.label)}</strong>
|
|
11231
11527
|
</header>
|
|
11232
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
11233
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
11528
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml25(model.description)}</p>
|
|
11529
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml25(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
11234
11530
|
${turns}
|
|
11235
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
11531
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml25(model.error)}</p>` : ""}
|
|
11236
11532
|
</section>`;
|
|
11237
11533
|
};
|
|
11238
11534
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -11282,16 +11578,16 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
11282
11578
|
});
|
|
11283
11579
|
};
|
|
11284
11580
|
// src/client/traceTimelineWidget.ts
|
|
11285
|
-
var
|
|
11286
|
-
var
|
|
11287
|
-
var
|
|
11288
|
-
var
|
|
11581
|
+
var DEFAULT_TITLE18 = "Voice Traces";
|
|
11582
|
+
var DEFAULT_DESCRIPTION18 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
11583
|
+
var escapeHtml26 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11584
|
+
var formatMs5 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
11289
11585
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
11290
11586
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
11291
11587
|
const sessions = (snapshot.report?.sessions ?? []).slice(0, options.limit ?? 3).map((session) => ({
|
|
11292
11588
|
...session,
|
|
11293
11589
|
detailHref: `${options.detailBasePath ?? "/traces"}/${encodeURIComponent(session.sessionId)}`,
|
|
11294
|
-
durationLabel:
|
|
11590
|
+
durationLabel: formatMs5(session.summary.callDurationMs),
|
|
11295
11591
|
incidentBundleHref: options.incidentBundleBasePath === false ? undefined : `${options.incidentBundleBasePath ?? "/voice-incidents"}/${encodeURIComponent(session.sessionId)}/markdown`,
|
|
11296
11592
|
label: `${session.summary.eventCount} events / ${session.summary.turnCount} turns`,
|
|
11297
11593
|
operationsRecordHref: options.operationsRecordBasePath === false ? undefined : `${options.operationsRecordBasePath ?? "/voice-operations"}/${encodeURIComponent(session.sessionId)}`,
|
|
@@ -11300,13 +11596,13 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
11300
11596
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
11301
11597
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
11302
11598
|
return {
|
|
11303
|
-
description: options.description ??
|
|
11599
|
+
description: options.description ?? DEFAULT_DESCRIPTION18,
|
|
11304
11600
|
error: snapshot.error,
|
|
11305
11601
|
isLoading: snapshot.isLoading,
|
|
11306
11602
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
11307
11603
|
sessions,
|
|
11308
11604
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
11309
|
-
title: options.title ??
|
|
11605
|
+
title: options.title ?? DEFAULT_TITLE18,
|
|
11310
11606
|
updatedAt: snapshot.updatedAt
|
|
11311
11607
|
};
|
|
11312
11608
|
};
|
|
@@ -11314,27 +11610,27 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
|
11314
11610
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
11315
11611
|
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
|
|
11316
11612
|
const supportLinks = [
|
|
11317
|
-
`<a href="${
|
|
11318
|
-
session.operationsRecordHref ? `<a href="${
|
|
11319
|
-
session.incidentBundleHref ? `<a href="${
|
|
11613
|
+
`<a href="${escapeHtml26(session.detailHref)}">Open timeline</a>`,
|
|
11614
|
+
session.operationsRecordHref ? `<a href="${escapeHtml26(session.operationsRecordHref)}">Open operations record</a>` : undefined,
|
|
11615
|
+
session.incidentBundleHref ? `<a href="${escapeHtml26(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
|
|
11320
11616
|
].filter(Boolean).join("");
|
|
11321
|
-
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${
|
|
11617
|
+
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml26(session.status)}">
|
|
11322
11618
|
<header>
|
|
11323
|
-
<strong>${
|
|
11324
|
-
<span>${
|
|
11619
|
+
<strong>${escapeHtml26(session.sessionId)}</strong>
|
|
11620
|
+
<span>${escapeHtml26(session.status)}</span>
|
|
11325
11621
|
</header>
|
|
11326
|
-
<p>${
|
|
11622
|
+
<p>${escapeHtml26(session.label)} \xB7 ${escapeHtml26(session.durationLabel)} \xB7 ${escapeHtml26(session.providerLabel)}</p>
|
|
11327
11623
|
<p class="absolute-voice-trace-timeline__actions">${supportLinks}</p>
|
|
11328
11624
|
</article>`;
|
|
11329
11625
|
}).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
11330
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
11626
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml26(model.status)}">
|
|
11331
11627
|
<header class="absolute-voice-trace-timeline__header">
|
|
11332
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
11333
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
11628
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml26(model.title)}</span>
|
|
11629
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml26(model.label)}</strong>
|
|
11334
11630
|
</header>
|
|
11335
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
11631
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml26(model.description)}</p>
|
|
11336
11632
|
${sessions}
|
|
11337
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
11633
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml26(model.error)}</p>` : ""}
|
|
11338
11634
|
</section>`;
|
|
11339
11635
|
};
|
|
11340
11636
|
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}`;
|
|
@@ -11380,9 +11676,9 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
|
|
|
11380
11676
|
});
|
|
11381
11677
|
};
|
|
11382
11678
|
// src/client/agentSquadStatusWidget.ts
|
|
11383
|
-
var
|
|
11384
|
-
var
|
|
11385
|
-
var
|
|
11679
|
+
var DEFAULT_TITLE19 = "Voice Agent Squad";
|
|
11680
|
+
var DEFAULT_DESCRIPTION19 = "Current specialist and recent handoffs from your self-hosted voice traces.";
|
|
11681
|
+
var escapeHtml27 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11386
11682
|
var labelFor = (current) => {
|
|
11387
11683
|
if (!current)
|
|
11388
11684
|
return "Waiting for specialist activity";
|
|
@@ -11396,37 +11692,37 @@ var labelFor = (current) => {
|
|
|
11396
11692
|
};
|
|
11397
11693
|
var createVoiceAgentSquadStatusViewModel = (snapshot, options = {}) => ({
|
|
11398
11694
|
current: snapshot.report.current,
|
|
11399
|
-
description: options.description ??
|
|
11695
|
+
description: options.description ?? DEFAULT_DESCRIPTION19,
|
|
11400
11696
|
error: snapshot.error,
|
|
11401
11697
|
isLoading: snapshot.isLoading,
|
|
11402
11698
|
label: snapshot.error ? "Unavailable" : labelFor(snapshot.report.current),
|
|
11403
11699
|
sessionCount: snapshot.report.sessionCount,
|
|
11404
11700
|
sessions: snapshot.report.sessions,
|
|
11405
|
-
title: options.title ??
|
|
11701
|
+
title: options.title ?? DEFAULT_TITLE19,
|
|
11406
11702
|
updatedAt: snapshot.updatedAt
|
|
11407
11703
|
});
|
|
11408
11704
|
var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
|
|
11409
11705
|
const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
|
|
11410
11706
|
const current = model.current;
|
|
11411
11707
|
const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
|
|
11412
|
-
<span>${
|
|
11413
|
-
<strong>${
|
|
11414
|
-
<em>${
|
|
11415
|
-
${session.summary || session.reason ? `<p>${
|
|
11708
|
+
<span>${escapeHtml27(session.sessionId)}</span>
|
|
11709
|
+
<strong>${escapeHtml27(session.targetAgentId ?? "none")}</strong>
|
|
11710
|
+
<em>${escapeHtml27(session.status)}</em>
|
|
11711
|
+
${session.summary || session.reason ? `<p>${escapeHtml27(session.summary ?? session.reason ?? "")}</p>` : ""}
|
|
11416
11712
|
</li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
|
|
11417
11713
|
return `<section class="absolute-voice-agent-squad-status">
|
|
11418
11714
|
<header>
|
|
11419
|
-
<span>${
|
|
11420
|
-
<strong>${
|
|
11715
|
+
<span>${escapeHtml27(model.title)}</span>
|
|
11716
|
+
<strong>${escapeHtml27(model.label)}</strong>
|
|
11421
11717
|
</header>
|
|
11422
|
-
<p>${
|
|
11718
|
+
<p>${escapeHtml27(model.description)}</p>
|
|
11423
11719
|
<div>
|
|
11424
|
-
<span>Session</span><strong>${
|
|
11425
|
-
<span>From</span><strong>${
|
|
11426
|
-
<span>Status</span><strong>${
|
|
11720
|
+
<span>Session</span><strong>${escapeHtml27(current?.sessionId ?? "n/a")}</strong>
|
|
11721
|
+
<span>From</span><strong>${escapeHtml27(current?.fromAgentId ?? "n/a")}</strong>
|
|
11722
|
+
<span>Status</span><strong>${escapeHtml27(current?.status ?? "idle")}</strong>
|
|
11427
11723
|
</div>
|
|
11428
11724
|
<ul>${rows}</ul>
|
|
11429
|
-
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${
|
|
11725
|
+
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml27(model.error)}</p>` : ""}
|
|
11430
11726
|
</section>`;
|
|
11431
11727
|
};
|
|
11432
11728
|
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}`;
|
|
@@ -11557,6 +11853,7 @@ export {
|
|
|
11557
11853
|
renderVoiceTraceTimelineWidgetHTML,
|
|
11558
11854
|
renderVoiceSessionSnapshotHTML,
|
|
11559
11855
|
renderVoiceRoutingStatusHTML,
|
|
11856
|
+
renderVoiceReconnectProfileEvidenceHTML,
|
|
11560
11857
|
renderVoiceReadinessFailuresHTML,
|
|
11561
11858
|
renderVoiceProviderStatusHTML,
|
|
11562
11859
|
renderVoiceProviderSimulationControlsHTML,
|
|
@@ -11580,6 +11877,7 @@ export {
|
|
|
11580
11877
|
mountVoiceTraceTimeline,
|
|
11581
11878
|
mountVoiceSessionSnapshot,
|
|
11582
11879
|
mountVoiceRoutingStatus,
|
|
11880
|
+
mountVoiceReconnectProfileEvidence,
|
|
11583
11881
|
mountVoiceReadinessFailures,
|
|
11584
11882
|
mountVoiceProviderStatus,
|
|
11585
11883
|
mountVoiceProviderSimulationControls,
|
|
@@ -11599,6 +11897,7 @@ export {
|
|
|
11599
11897
|
getVoiceTurnQualityCSS,
|
|
11600
11898
|
getVoiceTraceTimelineCSS,
|
|
11601
11899
|
getVoiceRoutingStatusCSS,
|
|
11900
|
+
getVoiceReconnectProfileEvidenceCSS,
|
|
11602
11901
|
getVoiceReadinessFailuresCSS,
|
|
11603
11902
|
getVoiceProviderStatusCSS,
|
|
11604
11903
|
getVoiceProviderContractsCSS,
|
|
@@ -11620,6 +11919,7 @@ export {
|
|
|
11620
11919
|
fetchVoiceTraceTimeline,
|
|
11621
11920
|
fetchVoiceSessionSnapshot,
|
|
11622
11921
|
fetchVoiceRoutingStatus,
|
|
11922
|
+
fetchVoiceReconnectProfileEvidence,
|
|
11623
11923
|
fetchVoiceReadinessFailures,
|
|
11624
11924
|
fetchVoiceProviderStatus,
|
|
11625
11925
|
fetchVoiceProviderContracts,
|
|
@@ -11638,6 +11938,7 @@ export {
|
|
|
11638
11938
|
defineVoiceTraceTimelineElement,
|
|
11639
11939
|
defineVoiceSessionSnapshotElement,
|
|
11640
11940
|
defineVoiceRoutingStatusElement,
|
|
11941
|
+
defineVoiceReconnectProfileEvidenceElement,
|
|
11641
11942
|
defineVoiceReadinessFailuresElement,
|
|
11642
11943
|
defineVoiceProviderStatusElement,
|
|
11643
11944
|
defineVoiceProviderSimulationControlsElement,
|
|
@@ -11666,6 +11967,8 @@ export {
|
|
|
11666
11967
|
createVoiceSessionSnapshotStore,
|
|
11667
11968
|
createVoiceRoutingStatusViewModel,
|
|
11668
11969
|
createVoiceRoutingStatusStore,
|
|
11970
|
+
createVoiceReconnectProfileEvidenceViewModel,
|
|
11971
|
+
createVoiceReconnectProfileEvidenceStore,
|
|
11669
11972
|
createVoiceReadinessFailuresViewModel,
|
|
11670
11973
|
createVoiceReadinessFailuresStore,
|
|
11671
11974
|
createVoiceProviderStatusViewModel,
|