@absolutejs/voice 0.0.22-beta.467 → 0.0.22-beta.468
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/index.js +20 -1
- package/dist/testing/index.js +20 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20264,6 +20264,17 @@ var renderVoiceOperationsRecordIncidentMarkdown = (record) => {
|
|
|
20264
20264
|
].filter((part) => typeof part === "string");
|
|
20265
20265
|
return `- ${event.event}: ${parts.join("; ")}`;
|
|
20266
20266
|
}) : ["- none recorded"];
|
|
20267
|
+
const mediaPipelineLine = record.mediaPipeline ? [
|
|
20268
|
+
`status=${record.mediaPipeline.status}`,
|
|
20269
|
+
`surface=${record.mediaPipeline.surface}`,
|
|
20270
|
+
`quality=${record.mediaPipeline.qualityStatus}`,
|
|
20271
|
+
`transport=${record.mediaPipeline.transportStatus ?? "n/a"}`,
|
|
20272
|
+
`graph=${record.mediaPipeline.processorGraphStatus ?? "n/a"}`,
|
|
20273
|
+
`frames=${String(record.mediaPipeline.frames)}`,
|
|
20274
|
+
`jitter=${record.mediaPipeline.jitterMs === undefined ? "n/a" : `${String(record.mediaPipeline.jitterMs)}ms`}`,
|
|
20275
|
+
`issueCodes=${record.mediaPipeline.issueCodes.join(", ") || "none"}`
|
|
20276
|
+
].join("; ") : "not provided";
|
|
20277
|
+
const mediaPipelineCodeLines = record.mediaPipeline ? record.mediaPipeline.issueCodes.length ? record.mediaPipeline.issueCodes.map((code) => `- ${code}`) : ["- none"] : ["- media pipeline report not attached to this record"];
|
|
20267
20278
|
return [
|
|
20268
20279
|
`# Voice incident handoff: ${record.sessionId}`,
|
|
20269
20280
|
"",
|
|
@@ -20278,6 +20289,7 @@ var renderVoiceOperationsRecordIncidentMarkdown = (record) => {
|
|
|
20278
20289
|
`- Guardrails: ${String(record.guardrails.blocked)} blocked / ${String(record.guardrails.warned)} warned / ${String(record.guardrails.total)} decisions`,
|
|
20279
20290
|
`- Provider recovery: ${providerRecoveryLine}`,
|
|
20280
20291
|
`- Telephony media: ${telephonyMediaLine}`,
|
|
20292
|
+
`- Media pipeline: ${mediaPipelineLine}`,
|
|
20281
20293
|
"",
|
|
20282
20294
|
"## Provider decisions",
|
|
20283
20295
|
"",
|
|
@@ -20287,6 +20299,10 @@ var renderVoiceOperationsRecordIncidentMarkdown = (record) => {
|
|
|
20287
20299
|
"",
|
|
20288
20300
|
...telephonyMediaLines,
|
|
20289
20301
|
"",
|
|
20302
|
+
"## Media pipeline issue codes",
|
|
20303
|
+
"",
|
|
20304
|
+
...mediaPipelineCodeLines,
|
|
20305
|
+
"",
|
|
20290
20306
|
renderVoiceOperationsRecordGuardrailMarkdown(record),
|
|
20291
20307
|
"",
|
|
20292
20308
|
"## Next checks",
|
|
@@ -20340,6 +20356,9 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
20340
20356
|
].filter((detail) => typeof detail === "string");
|
|
20341
20357
|
return `<li><strong>${escapeHtml29(event.event)}</strong> <span>${escapeHtml29(new Date(event.at).toLocaleString())}</span><p>${escapeHtml29(details.join(" \xB7 "))}</p></li>`;
|
|
20342
20358
|
}).join("") : "<li>No telephony media trace events recorded.</li>";
|
|
20359
|
+
const mediaPipelineSection = record.mediaPipeline ? `<section id="media-pipeline"><h2>Media Pipeline</h2><p class="muted">Surface: ${escapeHtml29(record.mediaPipeline.surface)} \xB7 Status: ${escapeHtml29(record.mediaPipeline.status)} \xB7 Quality: ${escapeHtml29(record.mediaPipeline.qualityStatus)} \xB7 Transport: ${escapeHtml29(record.mediaPipeline.transportStatus ?? "n/a")} \xB7 Graph: ${escapeHtml29(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>${escapeHtml29(code)}</strong></li>`).join("") : "<li>No media pipeline issue codes.</li>"}</ul></section>` : "";
|
|
20360
|
+
const mediaPipelineCard = record.mediaPipeline ? `<div class="card"><span>Media pipeline</span><strong>${escapeHtml29(record.mediaPipeline.status)}</strong><span>${String(record.mediaPipeline.issueCodes.length)} issue code(s)</span></div>` : "";
|
|
20361
|
+
const mediaPipelineNavLink = record.mediaPipeline ? '<a href="#media-pipeline">Media pipeline</a>' : "";
|
|
20343
20362
|
const snippet = escapeHtml29(`app.use(
|
|
20344
20363
|
createVoiceOperationsRecordRoutes({
|
|
20345
20364
|
audit: auditStore,
|
|
@@ -20356,7 +20375,7 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
20356
20375
|
);`);
|
|
20357
20376
|
const incidentMarkdown = escapeHtml29(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
20358
20377
|
const incidentLink = options.incidentHref ? `<a href="${escapeHtml29(options.incidentHref)}">Download incident.md</a>` : "";
|
|
20359
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml29(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>${escapeHtml29(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml29(record.status)}">${escapeHtml29(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
|
|
20378
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml29(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>${escapeHtml29(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml29(record.status)}">${escapeHtml29(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>${escapeHtml29(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: ${escapeHtml29(record.telephonyMedia.carriers.join(", ") || "none")}. Streams: ${escapeHtml29(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>`;
|
|
20360
20379
|
};
|
|
20361
20380
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
20362
20381
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
package/dist/testing/index.js
CHANGED
|
@@ -10958,6 +10958,17 @@ var renderVoiceOperationsRecordIncidentMarkdown = (record) => {
|
|
|
10958
10958
|
].filter((part) => typeof part === "string");
|
|
10959
10959
|
return `- ${event.event}: ${parts.join("; ")}`;
|
|
10960
10960
|
}) : ["- none recorded"];
|
|
10961
|
+
const mediaPipelineLine = record.mediaPipeline ? [
|
|
10962
|
+
`status=${record.mediaPipeline.status}`,
|
|
10963
|
+
`surface=${record.mediaPipeline.surface}`,
|
|
10964
|
+
`quality=${record.mediaPipeline.qualityStatus}`,
|
|
10965
|
+
`transport=${record.mediaPipeline.transportStatus ?? "n/a"}`,
|
|
10966
|
+
`graph=${record.mediaPipeline.processorGraphStatus ?? "n/a"}`,
|
|
10967
|
+
`frames=${String(record.mediaPipeline.frames)}`,
|
|
10968
|
+
`jitter=${record.mediaPipeline.jitterMs === undefined ? "n/a" : `${String(record.mediaPipeline.jitterMs)}ms`}`,
|
|
10969
|
+
`issueCodes=${record.mediaPipeline.issueCodes.join(", ") || "none"}`
|
|
10970
|
+
].join("; ") : "not provided";
|
|
10971
|
+
const mediaPipelineCodeLines = record.mediaPipeline ? record.mediaPipeline.issueCodes.length ? record.mediaPipeline.issueCodes.map((code) => `- ${code}`) : ["- none"] : ["- media pipeline report not attached to this record"];
|
|
10961
10972
|
return [
|
|
10962
10973
|
`# Voice incident handoff: ${record.sessionId}`,
|
|
10963
10974
|
"",
|
|
@@ -10972,6 +10983,7 @@ var renderVoiceOperationsRecordIncidentMarkdown = (record) => {
|
|
|
10972
10983
|
`- Guardrails: ${String(record.guardrails.blocked)} blocked / ${String(record.guardrails.warned)} warned / ${String(record.guardrails.total)} decisions`,
|
|
10973
10984
|
`- Provider recovery: ${providerRecoveryLine}`,
|
|
10974
10985
|
`- Telephony media: ${telephonyMediaLine}`,
|
|
10986
|
+
`- Media pipeline: ${mediaPipelineLine}`,
|
|
10975
10987
|
"",
|
|
10976
10988
|
"## Provider decisions",
|
|
10977
10989
|
"",
|
|
@@ -10981,6 +10993,10 @@ var renderVoiceOperationsRecordIncidentMarkdown = (record) => {
|
|
|
10981
10993
|
"",
|
|
10982
10994
|
...telephonyMediaLines,
|
|
10983
10995
|
"",
|
|
10996
|
+
"## Media pipeline issue codes",
|
|
10997
|
+
"",
|
|
10998
|
+
...mediaPipelineCodeLines,
|
|
10999
|
+
"",
|
|
10984
11000
|
renderVoiceOperationsRecordGuardrailMarkdown(record),
|
|
10985
11001
|
"",
|
|
10986
11002
|
"## Next checks",
|
|
@@ -11034,6 +11050,9 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
11034
11050
|
].filter((detail) => typeof detail === "string");
|
|
11035
11051
|
return `<li><strong>${escapeHtml7(event.event)}</strong> <span>${escapeHtml7(new Date(event.at).toLocaleString())}</span><p>${escapeHtml7(details.join(" \xB7 "))}</p></li>`;
|
|
11036
11052
|
}).join("") : "<li>No telephony media trace events recorded.</li>";
|
|
11053
|
+
const mediaPipelineSection = record.mediaPipeline ? `<section id="media-pipeline"><h2>Media Pipeline</h2><p class="muted">Surface: ${escapeHtml7(record.mediaPipeline.surface)} \xB7 Status: ${escapeHtml7(record.mediaPipeline.status)} \xB7 Quality: ${escapeHtml7(record.mediaPipeline.qualityStatus)} \xB7 Transport: ${escapeHtml7(record.mediaPipeline.transportStatus ?? "n/a")} \xB7 Graph: ${escapeHtml7(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>${escapeHtml7(code)}</strong></li>`).join("") : "<li>No media pipeline issue codes.</li>"}</ul></section>` : "";
|
|
11054
|
+
const mediaPipelineCard = record.mediaPipeline ? `<div class="card"><span>Media pipeline</span><strong>${escapeHtml7(record.mediaPipeline.status)}</strong><span>${String(record.mediaPipeline.issueCodes.length)} issue code(s)</span></div>` : "";
|
|
11055
|
+
const mediaPipelineNavLink = record.mediaPipeline ? '<a href="#media-pipeline">Media pipeline</a>' : "";
|
|
11037
11056
|
const snippet = escapeHtml7(`app.use(
|
|
11038
11057
|
createVoiceOperationsRecordRoutes({
|
|
11039
11058
|
audit: auditStore,
|
|
@@ -11050,7 +11069,7 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
11050
11069
|
);`);
|
|
11051
11070
|
const incidentMarkdown = escapeHtml7(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
11052
11071
|
const incidentLink = options.incidentHref ? `<a href="${escapeHtml7(options.incidentHref)}">Download incident.md</a>` : "";
|
|
11053
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml7(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>${escapeHtml7(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml7(record.status)}">${escapeHtml7(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
|
|
11072
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml7(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>${escapeHtml7(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml7(record.status)}">${escapeHtml7(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>${escapeHtml7(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: ${escapeHtml7(record.telephonyMedia.carriers.join(", ") || "none")}. Streams: ${escapeHtml7(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>`;
|
|
11054
11073
|
};
|
|
11055
11074
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
11056
11075
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|