@absolutejs/voice 0.0.22-beta.528 → 0.0.22-beta.529
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.js +3 -1
- package/dist/client/htmxBootstrap.js +3 -1
- package/dist/client/index.js +290 -304
- package/dist/embed/index.js +3 -1
- package/dist/embed/voice-widget.js +7 -7
- package/dist/index.d.ts +4 -6
- package/dist/index.js +513 -892
- package/dist/internal/html.d.ts +6 -0
- package/dist/internal/status.d.ts +9 -0
- package/dist/react/index.js +287 -300
- package/dist/svelte/index.js +181 -198
- package/dist/testing/index.js +57 -62
- package/dist/vue/index.d.ts +1 -1
- package/dist/vue/index.js +231 -239
- package/package.json +1 -1
package/dist/testing/index.js
CHANGED
|
@@ -7867,6 +7867,9 @@ var runVoiceResilienceBenchmark = async () => {
|
|
|
7867
7867
|
}
|
|
7868
7868
|
};
|
|
7869
7869
|
};
|
|
7870
|
+
// src/internal/html.ts
|
|
7871
|
+
var escapeHtml = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7872
|
+
|
|
7870
7873
|
// src/testing/review.ts
|
|
7871
7874
|
var roundMetric4 = (value) => typeof value === "number" ? Math.round(value * 100) / 100 : undefined;
|
|
7872
7875
|
var formatMetric = (label, value, unit = "ms") => typeof value === "number" ? `${label}: ${roundMetric4(value)}${unit}` : undefined;
|
|
@@ -8312,7 +8315,6 @@ var renderVoiceCallReviewMarkdown = (artifact) => {
|
|
|
8312
8315
|
].filter((value) => typeof value === "string").join(`
|
|
8313
8316
|
`);
|
|
8314
8317
|
};
|
|
8315
|
-
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8316
8318
|
var renderVoiceCallReviewHTML = (artifact) => {
|
|
8317
8319
|
const notes = artifact.notes.map((note) => `<li>${escapeHtml(note)}</li>`).join("");
|
|
8318
8320
|
const latency = artifact.latencyBreakdown.map((entry) => `<li><strong>${escapeHtml(entry.label)}:</strong> ${roundMetric4(entry.valueMs)}ms</li>`).join("");
|
|
@@ -9516,7 +9518,6 @@ var exportVoiceTrace = async (input) => {
|
|
|
9516
9518
|
};
|
|
9517
9519
|
};
|
|
9518
9520
|
var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
9519
|
-
var escapeHtml2 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
9520
9521
|
var formatTraceValue = (value) => {
|
|
9521
9522
|
if (value === undefined || value === null) {
|
|
9522
9523
|
return "";
|
|
@@ -9800,10 +9801,10 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
9800
9801
|
const offset = summary.startedAt === undefined ? event.at : Math.max(0, event.at - summary.startedAt);
|
|
9801
9802
|
return [
|
|
9802
9803
|
"<tr>",
|
|
9803
|
-
`<td>${
|
|
9804
|
-
`<td>${
|
|
9805
|
-
`<td>${
|
|
9806
|
-
`<td><code>${
|
|
9804
|
+
`<td>${escapeHtml(String(offset))}</td>`,
|
|
9805
|
+
`<td>${escapeHtml(event.type)}</td>`,
|
|
9806
|
+
`<td>${escapeHtml(event.turnId ?? "")}</td>`,
|
|
9807
|
+
`<td><code>${escapeHtml(JSON.stringify(event.payload))}</code></td>`,
|
|
9807
9808
|
"</tr>"
|
|
9808
9809
|
].join("");
|
|
9809
9810
|
}).join(`
|
|
@@ -9814,7 +9815,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
9814
9815
|
"<head>",
|
|
9815
9816
|
'<meta charset="utf-8" />',
|
|
9816
9817
|
'<meta name="viewport" content="width=device-width, initial-scale=1" />',
|
|
9817
|
-
`<title>${
|
|
9818
|
+
`<title>${escapeHtml(options.title ?? "Voice Trace")}</title>`,
|
|
9818
9819
|
"<style>",
|
|
9819
9820
|
"body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;line-height:1.45;background:#f8f7f2;color:#181713}",
|
|
9820
9821
|
"main{max-width:1100px;margin:auto}",
|
|
@@ -9828,7 +9829,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
9828
9829
|
"</style>",
|
|
9829
9830
|
"</head>",
|
|
9830
9831
|
"<body><main>",
|
|
9831
|
-
`<h1>${
|
|
9832
|
+
`<h1>${escapeHtml(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</h1>`,
|
|
9832
9833
|
`<p class="${evaluation.pass ? "pass" : "fail"}">QA: ${evaluation.pass ? "pass" : "fail"}</p>`,
|
|
9833
9834
|
'<section class="summary">',
|
|
9834
9835
|
`<div class="card"><strong>Events</strong><br>${summary.eventCount}</div>`,
|
|
@@ -9842,7 +9843,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
9842
9843
|
eventRows,
|
|
9843
9844
|
"</tbody></table>",
|
|
9844
9845
|
"<h2>Markdown Export</h2>",
|
|
9845
|
-
`<pre>${
|
|
9846
|
+
`<pre>${escapeHtml(markdown)}</pre>`,
|
|
9846
9847
|
"</main></body></html>"
|
|
9847
9848
|
].join(`
|
|
9848
9849
|
`);
|
|
@@ -9856,7 +9857,6 @@ var buildVoiceTraceReplay = (events, options = {}) => ({
|
|
|
9856
9857
|
|
|
9857
9858
|
// src/auditRoutes.ts
|
|
9858
9859
|
import { Elysia } from "elysia";
|
|
9859
|
-
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9860
9860
|
var getString = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
9861
9861
|
var getNumber = (value) => {
|
|
9862
9862
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -9954,14 +9954,14 @@ var buildVoiceAuditTrailReport = async (options) => {
|
|
|
9954
9954
|
};
|
|
9955
9955
|
var renderVoiceAuditTrailHTML = (report, options = {}) => {
|
|
9956
9956
|
const title = options.title ?? "AbsoluteJS Voice Audit Trail";
|
|
9957
|
-
const chips = report.summary.byType.map(([type, count]) => `<span>${
|
|
9957
|
+
const chips = report.summary.byType.map(([type, count]) => `<span>${escapeHtml(type)} <strong>${count}</strong></span>`).join("");
|
|
9958
9958
|
const rows = report.events.map((event) => {
|
|
9959
9959
|
const actor = event.actor ? `${event.actor.kind}:${event.actor.id}` : "unknown";
|
|
9960
9960
|
const resource = event.resource ? `${event.resource.type}${event.resource.id ? `:${event.resource.id}` : ""}` : "";
|
|
9961
9961
|
const payload = event.payload ? JSON.stringify(event.payload, null, 2) : "";
|
|
9962
|
-
return `<article class="event ${
|
|
9962
|
+
return `<article class="event ${escapeHtml(event.outcome ?? "unknown")}"><div><span>${escapeHtml(event.type)}</span><h2>${escapeHtml(event.action)}</h2><p>${escapeHtml(new Date(event.at).toLocaleString())}</p><p>Actor: ${escapeHtml(actor)}${resource ? ` \xB7 Resource: ${escapeHtml(resource)}` : ""}</p>${event.sessionId ? `<p>Session: ${escapeHtml(event.sessionId)}</p>` : ""}</div><strong>${escapeHtml(event.outcome ?? "recorded")}</strong>${payload ? `<pre>${escapeHtml(payload)}</pre>` : ""}</article>`;
|
|
9963
9963
|
}).join("");
|
|
9964
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
9964
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml(title)}</title><style>body{background:#11140f;color:#f7f1df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.18),rgba(245,158,11,.12));border:1px solid #2c3327;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#facc15;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.chips{display:flex;flex-wrap:wrap;gap:10px}.chips span{border:1px solid #46513b;border-radius:999px;padding:8px 12px}.events{display:grid;gap:14px}.event{background:#181d15;border:1px solid #2c3327;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto;padding:18px}.event.error{border-color:rgba(239,68,68,.75)}.event.skipped{border-color:rgba(245,158,11,.7)}.event.success{border-color:rgba(34,197,94,.55)}.event span{color:#facc15;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.event h2{margin:.2rem 0}.event p{color:#c8ccb8;margin:.2rem 0}.event strong{text-transform:uppercase}pre{background:#0c0f0a;border-radius:14px;grid-column:1/-1;overflow:auto;padding:14px;white-space:pre-wrap}@media(max-width:760px){main{padding:20px}.event{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted evidence</p><h1>${escapeHtml(title)}</h1><p>${report.summary.total} event(s), ${report.summary.errors} error(s). Latest ${report.summary.latestAt ? escapeHtml(new Date(report.summary.latestAt).toLocaleString()) : "never"}.</p><div class="chips">${chips}</div></section><section class="events">${rows || "<p>No audit events match this filter.</p>"}</section></main></body></html>`;
|
|
9965
9965
|
};
|
|
9966
9966
|
var createVoiceAuditTrailRoutes = (options) => {
|
|
9967
9967
|
const path = options.path ?? "/api/voice-audit";
|
|
@@ -10053,7 +10053,6 @@ var createVoiceAuditTrailRoutes = (options) => {
|
|
|
10053
10053
|
};
|
|
10054
10054
|
|
|
10055
10055
|
// src/auditExport.ts
|
|
10056
|
-
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10057
10056
|
var normalizeRedactionKey2 = (key) => key.trim().toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
10058
10057
|
var resolveReplacement2 = (input) => typeof input.options.replacement === "function" ? input.options.replacement({
|
|
10059
10058
|
key: input.key,
|
|
@@ -10171,8 +10170,8 @@ var renderVoiceAuditHTML = (events, options = {}) => {
|
|
|
10171
10170
|
const markdown = renderVoiceAuditMarkdown(events, options);
|
|
10172
10171
|
const renderEvents = options.redact ? redactVoiceAuditEvents(events, options.redact) : events;
|
|
10173
10172
|
const summary = summarizeVoiceAuditTrail(renderEvents);
|
|
10174
|
-
const rows = renderEvents.map((event) => `<tr><td>${
|
|
10175
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
10173
|
+
const rows = renderEvents.map((event) => `<tr><td>${escapeHtml(new Date(event.at).toISOString())}</td><td>${escapeHtml(event.type)}</td><td>${escapeHtml(event.action)}</td><td>${escapeHtml(event.outcome ?? "")}</td><td><code>${escapeHtml(JSON.stringify(event.payload ?? {}))}</code></td></tr>`).join("");
|
|
10174
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;line-height:1.45;background:#f8f7f2;color:#181713}main{max-width:1100px;margin:auto}.summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:.75rem;margin:1rem 0}.card{background:white;border:1px solid #ded9cc;border-radius:12px;padding:1rem}table{border-collapse:collapse;width:100%;background:white;border:1px solid #ded9cc}th,td{border-bottom:1px solid #eee8dc;padding:.65rem;text-align:left;vertical-align:top}code{white-space:pre-wrap;word-break:break-word}pre{background:#181713;color:#f8f7f2;padding:1rem;border-radius:12px;overflow:auto}</style></head><body><main><h1>${escapeHtml(title)}</h1><section class="summary"><div class="card"><strong>Events</strong><br>${summary.total}</div><div class="card"><strong>Errors</strong><br>${summary.errors}</div><div class="card"><strong>Latest</strong><br>${summary.latestAt ? escapeHtml(new Date(summary.latestAt).toLocaleString()) : "never"}</div></section><table><thead><tr><th>At</th><th>Type</th><th>Action</th><th>Outcome</th><th>Payload</th></tr></thead><tbody>${rows}</tbody></table><h2>Markdown Export</h2><pre>${escapeHtml(markdown)}</pre></main></body></html>`;
|
|
10176
10175
|
};
|
|
10177
10176
|
var buildVoiceAuditExport = (events, options = {}) => {
|
|
10178
10177
|
const exportEvents = options.redact ? redactVoiceAuditEvents(events, options.redact) : events;
|
|
@@ -10187,7 +10186,6 @@ var buildVoiceAuditExport = (events, options = {}) => {
|
|
|
10187
10186
|
// src/sessionReplay.ts
|
|
10188
10187
|
import { Elysia as Elysia2 } from "elysia";
|
|
10189
10188
|
var getString2 = (value) => typeof value === "string" ? value : undefined;
|
|
10190
|
-
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10191
10189
|
var increment2 = (record, key) => {
|
|
10192
10190
|
record[key] = (record[key] ?? 0) + 1;
|
|
10193
10191
|
};
|
|
@@ -10384,10 +10382,10 @@ var summarizeVoiceSessions = async (options = {}) => {
|
|
|
10384
10382
|
var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="voice-sessions-empty">No voice sessions found.</p>' : [
|
|
10385
10383
|
'<div class="voice-sessions-list">',
|
|
10386
10384
|
...sessions.map((session) => [
|
|
10387
|
-
`<article class="voice-session-card ${
|
|
10385
|
+
`<article class="voice-session-card ${escapeHtml(session.status)}">`,
|
|
10388
10386
|
'<div class="voice-session-card-header">',
|
|
10389
|
-
`<strong>${
|
|
10390
|
-
`<span>${
|
|
10387
|
+
`<strong>${escapeHtml(session.sessionId)}</strong>`,
|
|
10388
|
+
`<span>${escapeHtml(session.status)}</span>`,
|
|
10391
10389
|
"</div>",
|
|
10392
10390
|
"<dl>",
|
|
10393
10391
|
`<div><dt>Events</dt><dd>${String(session.eventCount)}</dd></div>`,
|
|
@@ -10395,9 +10393,9 @@ var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="v
|
|
|
10395
10393
|
`<div><dt>Transcripts</dt><dd>${String(session.transcriptCount)}</dd></div>`,
|
|
10396
10394
|
`<div><dt>Errors</dt><dd>${String(session.errorCount)}</dd></div>`,
|
|
10397
10395
|
"</dl>",
|
|
10398
|
-
session.latestOutcome ? `<p>Outcome: ${
|
|
10399
|
-
session.providers.length ? `<p>Providers: ${session.providers.map(
|
|
10400
|
-
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${
|
|
10396
|
+
session.latestOutcome ? `<p>Outcome: ${escapeHtml(session.latestOutcome)}</p>` : "",
|
|
10397
|
+
session.providers.length ? `<p>Providers: ${session.providers.map(escapeHtml).join(", ")}</p>` : "",
|
|
10398
|
+
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${escapeHtml(session.operationsRecordHref)}">Open operations record</a> \xB7 ` : ""}<a href="${escapeHtml(session.replayHref)}">Open replay</a></p>` : "",
|
|
10401
10399
|
"</article>"
|
|
10402
10400
|
].join("")),
|
|
10403
10401
|
"</div>"
|
|
@@ -10467,7 +10465,6 @@ var createVoiceSessionReplayRoutes = (options) => {
|
|
|
10467
10465
|
|
|
10468
10466
|
// src/traceTimeline.ts
|
|
10469
10467
|
import { Elysia as Elysia3 } from "elysia";
|
|
10470
|
-
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10471
10468
|
var getString3 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
10472
10469
|
var getNumber2 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
10473
10470
|
var firstString = (payload, keys) => {
|
|
@@ -10653,17 +10650,17 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
10653
10650
|
};
|
|
10654
10651
|
};
|
|
10655
10652
|
var formatMs = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
10656
|
-
var renderProviderCards = (session) => session.providers.length === 0 ? '<p class="muted">No provider events recorded for this session.</p>' : `<div class="providers">${session.providers.map((provider) => `<article><strong>${
|
|
10653
|
+
var renderProviderCards = (session) => session.providers.length === 0 ? '<p class="muted">No provider events recorded for this session.</p>' : `<div class="providers">${session.providers.map((provider) => `<article><strong>${escapeHtml(provider.provider)}</strong><dl><div><dt>Events</dt><dd>${String(provider.eventCount)}</dd></div><div><dt>Avg</dt><dd>${formatMs(provider.averageElapsedMs)}</dd></div><div><dt>Max</dt><dd>${formatMs(provider.maxElapsedMs)}</dd></div><div><dt>Errors</dt><dd>${String(provider.errorCount)}</dd></div><div><dt>Fallbacks</dt><dd>${String(provider.fallbackCount)}</dd></div><div><dt>Timeouts</dt><dd>${String(provider.timeoutCount)}</dd></div></dl></article>`).join("")}</div>`;
|
|
10657
10654
|
var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
|
|
10658
|
-
const events = session.events.map((event) => `<tr class="${
|
|
10659
|
-
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${
|
|
10660
|
-
const supportLinks = session.operationsRecordHref ? `<p><a href="${
|
|
10661
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
10655
|
+
const events = session.events.map((event) => `<tr class="${escapeHtml(event.status ?? "")}"><td>+${String(event.offsetMs)}ms</td><td>${escapeHtml(event.type)}</td><td>${escapeHtml(event.label)}</td><td>${escapeHtml(event.provider ?? "")}</td><td>${escapeHtml(event.status ?? "")}</td><td>${formatMs(event.elapsedMs)}</td></tr>`).join("");
|
|
10656
|
+
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${escapeHtml(issue.severity)}">${escapeHtml(issue.code)}: ${escapeHtml(issue.message)}</li>`).join("") : "<li>none</li>";
|
|
10657
|
+
const supportLinks = session.operationsRecordHref ? `<p><a href="${escapeHtml(session.operationsRecordHref)}">Open operations record</a></p>` : "";
|
|
10658
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml(options.title ?? "Voice Trace Timeline")}</title><style>${timelineCSS}</style></head><body><main><a href="/traces">Back to traces</a><header><p class="eyebrow">Call timeline</p><h1>${escapeHtml(session.sessionId)}</h1><p class="status ${escapeHtml(session.status)}">${escapeHtml(session.status)}</p>${supportLinks}</header><section class="metrics"><article><span>Events</span><strong>${String(session.summary.eventCount)}</strong></article><article><span>Turns</span><strong>${String(session.summary.turnCount)}</strong></article><article><span>Errors</span><strong>${String(session.summary.errorCount)}</strong></article><article><span>Duration</span><strong>${formatMs(session.summary.callDurationMs)}</strong></article></section><section><h2>Providers</h2>${renderProviderCards(session)}</section><section><h2>Issues</h2><ul>${issues}</ul></section><section><h2>Timeline</h2><table><thead><tr><th>Offset</th><th>Type</th><th>Event</th><th>Provider</th><th>Status</th><th>Latency</th></tr></thead><tbody>${events}</tbody></table></section></main></body></html>`;
|
|
10662
10659
|
};
|
|
10663
|
-
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${
|
|
10660
|
+
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${escapeHtml(session.status)}"><td>${session.operationsRecordHref ? `<a href="${escapeHtml(session.operationsRecordHref)}">${escapeHtml(session.sessionId)}</a>` : `<a href="/traces/${encodeURIComponent(session.sessionId)}">${escapeHtml(session.sessionId)}</a>`}</td><td>${escapeHtml(session.status)}</td><td>${String(session.summary.eventCount)}</td><td>${String(session.summary.turnCount)}</td><td>${String(session.summary.errorCount)}</td><td>${formatMs(session.summary.callDurationMs)}</td><td>${session.providers.map((provider) => escapeHtml(provider.provider)).join(", ")}</td></tr>`).join("");
|
|
10664
10661
|
var timelineCSS = "body{background:#0f1318;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}a{color:#fbbf24}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.5rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #475569;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.metrics,.providers{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:20px 0}.metrics article,.providers article{background:#181f27;border:1px solid #2b3642;border-radius:20px;padding:16px}.metrics span,dt,.muted{color:#a8b0b8}.metrics strong{display:block;font-size:2rem}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:12px 0 0}dd{font-weight:800;margin:4px 0 0}table{background:#181f27;border-collapse:collapse;border-radius:18px;overflow:hidden;width:100%}td,th{border-bottom:1px solid #2b3642;padding:12px;text-align:left}section{margin-top:28px}@media(max-width:760px){main{padding:20px}table{font-size:.9rem}}";
|
|
10665
10662
|
var renderVoiceTraceTimelineHTML = (report, options = {}) => {
|
|
10666
|
-
const snippet =
|
|
10663
|
+
const snippet = escapeHtml(`const traceStore = createVoiceTraceSinkStore({
|
|
10667
10664
|
store: runtimeStorage.traces,
|
|
10668
10665
|
sinks: [
|
|
10669
10666
|
createVoiceTraceHTTPSink({
|
|
@@ -10689,7 +10686,7 @@ app.use(
|
|
|
10689
10686
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
10690
10687
|
})
|
|
10691
10688
|
);`);
|
|
10692
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
10689
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml(options.title ?? "Voice Trace Timelines")}</title><style>${timelineCSS}.primitive{background:#181f27;border:1px solid #334155;border-radius:20px;margin:20px 0;padding:18px}.primitive p{line-height:1.55}.primitive pre{background:#0b1118;border:1px solid #2b3642;border-radius:16px;color:#dbeafe;overflow:auto;padding:14px}.primitive code{color:#bfdbfe}</style></head><body><main><header><p class="eyebrow">Self-hosted voice debugging</p><h1>${escapeHtml(options.title ?? "Voice Trace Timelines")}</h1><p class="muted">Per-call event timelines with provider latency, fallback, timeout, handoff, and error context.</p></header><section class="metrics"><article><span>Sessions</span><strong>${String(report.total)}</strong></article><article><span>Failed</span><strong>${String(report.failed)}</strong></article><article><span>Warnings</span><strong>${String(report.warnings)}</strong></article></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTraceTimelineRoutes(...)</code> makes traces the proof backbone</h2><p class="muted">Mount trace timelines from the same trace store used by readiness, simulations, provider recovery, delivery sinks, and phone-agent smoke proof.</p><pre><code>${snippet}</code></pre></section><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Duration</th><th>Providers</th></tr></thead><tbody>${renderSessionRows(report)}</tbody></table></main></body></html>`;
|
|
10693
10690
|
};
|
|
10694
10691
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
10695
10692
|
const path = options.path ?? "/api/voice-traces";
|
|
@@ -11359,7 +11356,6 @@ var renderVoiceFailureReplayMarkdown = (report) => {
|
|
|
11359
11356
|
].join(`
|
|
11360
11357
|
`);
|
|
11361
11358
|
};
|
|
11362
|
-
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11363
11359
|
var formatMs2 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
11364
11360
|
var outcomeLabels = (outcome) => [
|
|
11365
11361
|
outcome.complete ? "complete" : undefined,
|
|
@@ -11485,18 +11481,18 @@ var renderVoiceOperationsRecordGuardrailMarkdown = (record) => {
|
|
|
11485
11481
|
`);
|
|
11486
11482
|
};
|
|
11487
11483
|
var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
11488
|
-
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${
|
|
11489
|
-
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${
|
|
11490
|
-
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${
|
|
11484
|
+
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${escapeHtml(provider.provider)}</strong><span>${String(provider.eventCount)} events</span><span>${formatMs2(provider.averageElapsedMs)} avg</span><span>${String(provider.errorCount)} errors</span></article>`).join("") : '<p class="muted">No provider events recorded.</p>';
|
|
11485
|
+
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${escapeHtml(turn.id)}</strong>${turn.committedText ? `<p><span class="label">Caller</span>${escapeHtml(turn.committedText)}</p>` : ""}${turn.assistantReplies.map((reply) => `<p><span class="label">Assistant</span>${escapeHtml(reply)}</p>`).join("")}${turn.errors.map((error) => `<p class="error"><span class="label">Error</span>${escapeHtml(error)}</p>`).join("")}</li>`).join("") : "<li>No transcript turns recorded.</li>";
|
|
11486
|
+
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${escapeHtml(decision.provider ?? decision.selectedProvider ?? decision.fallbackProvider ?? "provider")}</strong> <span>${escapeHtml(decision.status ?? decision.type)}</span> ${formatMs2(decision.elapsedMs)}${decision.surface ? `<p><span class="label">Surface</span>${escapeHtml(decision.surface)}</p>` : ""}${decision.kind ? `<p><span class="label">Kind</span>${escapeHtml(decision.kind)}</p>` : ""}${decision.selectedProvider ? `<p>Selected: ${escapeHtml(decision.selectedProvider)}</p>` : ""}${decision.fallbackProvider ? `<p>Fallback: ${escapeHtml(decision.fallbackProvider)}</p>` : ""}${decision.error ? `<p class="error">${escapeHtml(decision.error)}</p>` : ""}${decision.reason ? `<p>${escapeHtml(decision.reason)}</p>` : ""}</li>`).join("") : "<li>No provider decisions recorded.</li>";
|
|
11491
11487
|
const providerDecisionSummary = record.providerDecisionSummary;
|
|
11492
|
-
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${
|
|
11493
|
-
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${
|
|
11494
|
-
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${
|
|
11495
|
-
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${
|
|
11496
|
-
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${
|
|
11488
|
+
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${escapeHtml(handoff.fromAgentId ?? "unknown")}</strong> to <strong>${escapeHtml(handoff.targetAgentId ?? "unknown")}</strong> <span>${escapeHtml(handoff.status ?? "")}</span><p>${escapeHtml(handoff.summary ?? handoff.reason ?? "")}</p></li>`).join("") : "<li>No agent handoffs recorded.</li>";
|
|
11489
|
+
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${escapeHtml(tool.toolName ?? "tool")}</strong> <span>${escapeHtml(tool.status ?? "")}</span> ${formatMs2(tool.elapsedMs)} ${tool.error ? `<p>${escapeHtml(tool.error)}</p>` : ""}</li>`).join("") : "<li>No tool calls recorded.</li>";
|
|
11490
|
+
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${escapeHtml(review.title)}</strong> <span>${escapeHtml(review.summary.outcome ?? "")}</span><p>${escapeHtml(review.postCall?.summary ?? review.transcript.actual)}</p></li>`).join("") : "<li>No call reviews recorded.</li>";
|
|
11491
|
+
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${escapeHtml(task.title)}</strong> <span>${escapeHtml(task.status)}</span><p>${escapeHtml(task.recommendedAction)}</p></li>`).join("") : "<li>No ops tasks recorded.</li>";
|
|
11492
|
+
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${escapeHtml(event.type)}</strong> <span>${escapeHtml(event.deliveryStatus ?? "local")}</span><p>${escapeHtml(event.deliveryError ?? event.deliveredTo ?? "")}</p></li>`).join("") : "<li>No integration events recorded.</li>";
|
|
11497
11493
|
const guardrails = record.guardrails.total ? record.guardrails.decisions.map((decision) => {
|
|
11498
11494
|
const findings = decision.findings.map((finding) => finding.label ?? finding.ruleId ?? finding.action).filter((value) => typeof value === "string").join(", ") || "none";
|
|
11499
|
-
return `<li><strong>assistant.guardrail ${
|
|
11495
|
+
return `<li><strong>assistant.guardrail ${escapeHtml(decision.stage ?? "unknown")}</strong> <span>${escapeHtml(decision.status ?? "")}</span><p>Allowed: ${escapeHtml(String(decision.allowed ?? "unknown"))} \xB7 Proof: ${escapeHtml(decision.proof ?? "runtime")}${decision.turnId ? ` \xB7 Turn: ${escapeHtml(decision.turnId)}` : ""}</p><p>${escapeHtml(findings)}</p></li>`;
|
|
11500
11496
|
}).join("") : "<li>No assistant.guardrail events recorded.</li>";
|
|
11501
11497
|
const telephonyMedia = record.telephonyMedia.events.length ? record.telephonyMedia.events.slice(0, 50).map((event) => {
|
|
11502
11498
|
const details = [
|
|
@@ -11507,12 +11503,12 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
11507
11503
|
event.sequenceNumber ? `Seq: ${event.sequenceNumber}` : undefined,
|
|
11508
11504
|
`Audio bytes: ${String(event.audioBytes)}`
|
|
11509
11505
|
].filter((detail) => typeof detail === "string");
|
|
11510
|
-
return `<li><strong>${
|
|
11506
|
+
return `<li><strong>${escapeHtml(event.event)}</strong> <span>${escapeHtml(new Date(event.at).toLocaleString())}</span><p>${escapeHtml(details.join(" \xB7 "))}</p></li>`;
|
|
11511
11507
|
}).join("") : "<li>No telephony media trace events recorded.</li>";
|
|
11512
|
-
const mediaPipelineSection = record.mediaPipeline ? `<section id="media-pipeline"><h2>Media Pipeline</h2><p class="muted">Surface: ${
|
|
11513
|
-
const mediaPipelineCard = record.mediaPipeline ? `<div class="card"><span>Media pipeline</span><strong>${
|
|
11508
|
+
const mediaPipelineSection = record.mediaPipeline ? `<section id="media-pipeline"><h2>Media Pipeline</h2><p class="muted">Surface: ${escapeHtml(record.mediaPipeline.surface)} \xB7 Status: ${escapeHtml(record.mediaPipeline.status)} \xB7 Quality: ${escapeHtml(record.mediaPipeline.qualityStatus)} \xB7 Transport: ${escapeHtml(record.mediaPipeline.transportStatus ?? "n/a")} \xB7 Graph: ${escapeHtml(record.mediaPipeline.processorGraphStatus ?? "n/a")} \xB7 Frames: ${String(record.mediaPipeline.frames)} \xB7 Jitter: ${record.mediaPipeline.jitterMs === undefined ? "n/a" : `${String(record.mediaPipeline.jitterMs)}ms`}</p><ul>${record.mediaPipeline.issueCodes.length ? record.mediaPipeline.issueCodes.map((code) => `<li><strong>${escapeHtml(code)}</strong></li>`).join("") : "<li>No media pipeline issue codes.</li>"}</ul></section>` : "";
|
|
11509
|
+
const mediaPipelineCard = record.mediaPipeline ? `<div class="card"><span>Media pipeline</span><strong>${escapeHtml(record.mediaPipeline.status)}</strong><span>${String(record.mediaPipeline.issueCodes.length)} issue code(s)</span></div>` : "";
|
|
11514
11510
|
const mediaPipelineNavLink = record.mediaPipeline ? '<a href="#media-pipeline">Media pipeline</a>' : "";
|
|
11515
|
-
const snippet =
|
|
11511
|
+
const snippet = escapeHtml(`app.use(
|
|
11516
11512
|
createVoiceOperationsRecordRoutes({
|
|
11517
11513
|
audit: auditStore,
|
|
11518
11514
|
integrationEvents: opsEvents,
|
|
@@ -11526,9 +11522,9 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
11526
11522
|
tasks: opsTasks
|
|
11527
11523
|
})
|
|
11528
11524
|
);`);
|
|
11529
|
-
const incidentMarkdown =
|
|
11530
|
-
const incidentLink = options.incidentHref ? `<a href="${
|
|
11531
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
11525
|
+
const incidentMarkdown = escapeHtml(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
11526
|
+
const incidentLink = options.incidentHref ? `<a href="${escapeHtml(options.incidentHref)}">Download incident.md</a>` : "";
|
|
11527
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml(options.title ?? "Voice Operations Record")}</title><style>body{background:#101417;color:#f9f4e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.eyebrow{color:#fbbf24;font-size:.8rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.8rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #475569;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px 0}.card,.primitive{background:#182025;border:1px solid #2d3a43;border-radius:20px;padding:16px}.card span,.muted,.label{color:#a9b4bd}.label{display:block;font-size:.72rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.card strong{display:block;font-size:2rem}section{margin-top:28px}article{display:grid;gap:8px}ul{display:grid;gap:10px;list-style:none;padding:0}li{background:#182025;border:1px solid #2d3a43;border-radius:16px;padding:14px}pre{background:#080d10;border:1px solid #2d3a43;border-radius:16px;color:#dbeafe;overflow:auto;padding:14px}.hero-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:16px}.hero-actions a{background:#fbbf24;border-radius:999px;color:#111827;font-weight:900;padding:10px 14px;text-decoration:none}.two-column{display:grid;gap:18px;grid-template-columns:minmax(0,1.15fr) minmax(280px,.85fr)}@media(max-width:860px){main{padding:20px}.two-column{grid-template-columns:1fr}}</style></head><body><main><p class="eyebrow">Call log replacement</p><h1>${escapeHtml(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml(record.status)}">${escapeHtml(record.status)}</p><div class="hero-actions"><a href="#transcript">Transcript</a><a href="#provider-decisions">Provider decisions</a><a href="#telephony-media">Telephony media</a>${mediaPipelineNavLink}<a href="#guardrails">Guardrails</a><a href="#incident-handoff">Incident handoff</a>${incidentLink}</div><section class="grid"><div class="card"><span>Events</span><strong>${String(record.summary.eventCount)}</strong></div><div class="card"><span>Turns</span><strong>${String(record.summary.turnCount)}</strong></div><div class="card"><span>Errors</span><strong>${String(record.summary.errorCount)}</strong></div><div class="card"><span>Duration</span><strong>${formatMs2(record.summary.callDurationMs)}</strong></div><div class="card"><span>Provider recovery</span><strong>${escapeHtml(providerDecisionSummary.recoveryStatus)}</strong><span>${String(providerDecisionSummary.fallbacks)} fallback / ${String(providerDecisionSummary.degraded)} degraded / ${String(providerDecisionSummary.errors)} errors</span></div><div class="card"><span>Telephony media</span><strong>${String(record.telephonyMedia.media)}</strong><span>${String(record.telephonyMedia.inbound)} inbound / ${String(record.telephonyMedia.outbound)} outbound / ${String(record.telephonyMedia.clears)} clears</span></div><div class="card"><span>Guardrails</span><strong>${String(record.guardrails.blocked)}</strong></div><div class="card"><span>Audit</span><strong>${String(record.audit?.total ?? 0)}</strong></div><div class="card"><span>Reviews</span><strong>${String(record.reviews?.total ?? 0)}</strong></div><div class="card"><span>Tasks</span><strong>${String(record.tasks?.total ?? 0)}</strong></div><div class="card"><span>Integrations</span><strong>${String(record.integrationEvents?.total ?? 0)}</strong></div>${mediaPipelineCard}</section><section class="two-column"><div><h2 id="transcript">Transcript</h2><ul>${transcript}</ul></div><div><h2 id="provider-decisions">Provider Decisions</h2><ul>${providerDecisions}</ul></div></section><section id="telephony-media"><h2>Telephony Media</h2><p class="muted">Live <code>client.telephony_media</code> stream lifecycle evidence attached to this session. Carriers: ${escapeHtml(record.telephonyMedia.carriers.join(", ") || "none")}. Streams: ${escapeHtml(record.telephonyMedia.streamIds.join(", ") || "none")}. Inbound: ${String(record.telephonyMedia.inbound)}. Outbound: ${String(record.telephonyMedia.outbound)}. Marks: ${String(record.telephonyMedia.marks)}. Clears: ${String(record.telephonyMedia.clears)}.</p><ul>${telephonyMedia}</ul></section>${mediaPipelineSection}<section id="guardrails"><h2>Guardrail Evidence</h2><p class="muted">Live <code>assistant.guardrail</code> decisions attached to this session.</p><ul>${guardrails}</ul></section><section id="incident-handoff"><h2>Copyable Incident Handoff</h2><p class="muted">Paste this into Slack, Linear, Zendesk, or an incident review. ${incidentLink}</p><pre><code>${incidentMarkdown}</code></pre></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceOperationsRecordRoutes(...)</code> gives every call one debuggable object</h2><p class="muted">Use this as the support/debug payload across traces, provider routing, tools, handoffs, guardrails, audit, latency, replay, reviews, tasks, media streams, and webhook delivery.</p><pre><code>${snippet}</code></pre></section><section><h2>Provider Summary</h2><div class="grid">${providers}</div></section><section><h2>Handoffs</h2><ul>${handoffs}</ul></section><section><h2>Tools</h2><ul>${tools}</ul></section><section><h2>Reviews</h2><ul>${reviews}</ul></section><section><h2>Tasks</h2><ul>${tasks}</ul></section><section><h2>Integration Events</h2><ul>${integrationEvents}</ul></section></main></body></html>`;
|
|
11532
11528
|
};
|
|
11533
11529
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
11534
11530
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
|
@@ -12419,7 +12415,6 @@ var resolveTwilioStreamParameters = async (parameters, input) => {
|
|
|
12419
12415
|
return parameters;
|
|
12420
12416
|
};
|
|
12421
12417
|
var joinUrlPath = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
12422
|
-
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
12423
12418
|
var getWebhookVerificationUrl = (webhook, input) => {
|
|
12424
12419
|
if (!webhook?.verificationUrl) {
|
|
12425
12420
|
return;
|
|
@@ -12464,23 +12459,23 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
|
|
|
12464
12459
|
};
|
|
12465
12460
|
var renderTwilioVoiceSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
12466
12461
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio setup</p>
|
|
12467
|
-
<h1>${
|
|
12462
|
+
<h1>${escapeHtml(title)}</h1>
|
|
12468
12463
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
12469
12464
|
<section>
|
|
12470
12465
|
<h2>URLs</h2>
|
|
12471
12466
|
<ul>
|
|
12472
|
-
<li><strong>TwiML:</strong> <code>${
|
|
12473
|
-
<li><strong>Media stream:</strong> <code>${
|
|
12474
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
12467
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml(status.urls.twiml)}</code></li>
|
|
12468
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml(status.urls.stream)}</code></li>
|
|
12469
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml(status.urls.webhook)}</code></li>
|
|
12475
12470
|
</ul>
|
|
12476
12471
|
</section>
|
|
12477
12472
|
<section>
|
|
12478
12473
|
<h2>Signing</h2>
|
|
12479
12474
|
<p>Mode: <code>${status.signing.mode}</code></p>
|
|
12480
|
-
${status.signing.verificationUrl ? `<p>Verification URL: <code>${
|
|
12475
|
+
${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml(status.signing.verificationUrl)}</code></p>` : ""}
|
|
12481
12476
|
</section>
|
|
12482
|
-
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
12483
|
-
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
12477
|
+
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml(name)}</code></li>`).join("")}</ul></section>` : ""}
|
|
12478
|
+
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml(warning)}</li>`).join("")}</ul></section>` : ""}
|
|
12484
12479
|
</main>`;
|
|
12485
12480
|
var extractTwilioStreamUrl = (twiml) => twiml.match(/<Stream\b[^>]*\surl="([^"]+)"/i)?.[1]?.replaceAll("&", "&");
|
|
12486
12481
|
var createSmokeCheck = (name, status, message, details) => ({
|
|
@@ -12491,20 +12486,20 @@ var createSmokeCheck = (name, status, message, details) => ({
|
|
|
12491
12486
|
});
|
|
12492
12487
|
var renderTwilioVoiceSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
12493
12488
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio smoke test</p>
|
|
12494
|
-
<h1>${
|
|
12489
|
+
<h1>${escapeHtml(title)}</h1>
|
|
12495
12490
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
12496
12491
|
<section>
|
|
12497
12492
|
<h2>Checks</h2>
|
|
12498
12493
|
<ul>
|
|
12499
|
-
${report.checks.map((check) => `<li><strong>${
|
|
12494
|
+
${report.checks.map((check) => `<li><strong>${escapeHtml(check.name)}</strong>: ${escapeHtml(check.status)}${check.message ? ` - ${escapeHtml(check.message)}` : ""}</li>`).join("")}
|
|
12500
12495
|
</ul>
|
|
12501
12496
|
</section>
|
|
12502
12497
|
<section>
|
|
12503
12498
|
<h2>Observed URLs</h2>
|
|
12504
12499
|
<ul>
|
|
12505
|
-
<li><strong>TwiML:</strong> <code>${
|
|
12506
|
-
<li><strong>Stream:</strong> <code>${
|
|
12507
|
-
<li><strong>Webhook:</strong> <code>${
|
|
12500
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml(report.setup.urls.twiml)}</code></li>
|
|
12501
|
+
<li><strong>Stream:</strong> <code>${escapeHtml(report.twiml?.streamUrl ?? report.setup.urls.stream)}</code></li>
|
|
12502
|
+
<li><strong>Webhook:</strong> <code>${escapeHtml(report.setup.urls.webhook)}</code></li>
|
|
12508
12503
|
</ul>
|
|
12509
12504
|
</section>
|
|
12510
12505
|
</main>`;
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export { VoiceCostDashboard } from "./VoiceCostDashboard";
|
|
|
37
37
|
export { VoiceLiveAgentConsole } from "./VoiceLiveAgentConsole";
|
|
38
38
|
export { VoiceLiveCallViewer } from "./VoiceLiveCallViewer";
|
|
39
39
|
export { VoiceReplayTimeline } from "./VoiceReplayTimeline";
|
|
40
|
-
export type { VoiceWidgetLabels, VoiceWidgetTheme
|
|
40
|
+
export type { VoiceWidgetLabels, VoiceWidgetTheme } from "./VoiceWidget";
|
|
41
41
|
export { useVoiceProviderStatus } from "./useVoiceProviderStatus";
|
|
42
42
|
export { useVoiceProviderCapabilities } from "./useVoiceProviderCapabilities";
|
|
43
43
|
export { useVoiceProviderContracts } from "./useVoiceProviderContracts";
|