@absolutejs/voice 0.0.22-beta.466 → 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 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><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></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><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>`;
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";
@@ -20366,11 +20385,17 @@ var createVoiceOperationsRecordRoutes = (options) => {
20366
20385
  const routes = new Elysia28({
20367
20386
  name: options.name ?? "absolutejs-voice-operations-record"
20368
20387
  });
20369
- const buildRecord = (sessionId) => buildVoiceOperationsRecord({
20388
+ const resolveMediaPipeline = async (sessionId) => {
20389
+ if (options.mediaPipeline === undefined)
20390
+ return;
20391
+ return typeof options.mediaPipeline === "function" ? await options.mediaPipeline({ sessionId }) : options.mediaPipeline;
20392
+ };
20393
+ const buildRecord = async (sessionId) => buildVoiceOperationsRecord({
20370
20394
  audit: options.audit,
20371
20395
  evaluation: options.evaluation,
20372
20396
  events: options.events,
20373
20397
  integrationEvents: options.integrationEvents,
20398
+ mediaPipeline: await resolveMediaPipeline(sessionId),
20374
20399
  redact: options.redact,
20375
20400
  reviews: options.reviews,
20376
20401
  sessionId,
@@ -313,11 +313,14 @@ export type VoiceOperationsRecordOptions = {
313
313
  store?: VoiceTraceEventStore;
314
314
  tasks?: VoiceOpsTaskStore;
315
315
  };
316
- export type VoiceOperationsRecordRoutesOptions = Omit<VoiceOperationsRecordOptions, "sessionId"> & {
316
+ export type VoiceOperationsRecordRoutesOptions = Omit<VoiceOperationsRecordOptions, "sessionId" | "mediaPipeline"> & {
317
317
  headers?: HeadersInit;
318
318
  htmlPath?: false | string;
319
319
  incidentHtmlPath?: false | string;
320
320
  incidentPath?: false | string;
321
+ mediaPipeline?: VoiceMediaPipelineReport | ((input: {
322
+ sessionId: string;
323
+ }) => Promise<VoiceMediaPipelineReport | undefined> | VoiceMediaPipelineReport | undefined);
321
324
  name?: string;
322
325
  path?: string;
323
326
  render?: (record: VoiceOperationsRecord) => string | Promise<string>;
@@ -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><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></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><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>`;
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";
@@ -11060,11 +11079,17 @@ var createVoiceOperationsRecordRoutes = (options) => {
11060
11079
  const routes = new Elysia4({
11061
11080
  name: options.name ?? "absolutejs-voice-operations-record"
11062
11081
  });
11063
- const buildRecord = (sessionId) => buildVoiceOperationsRecord({
11082
+ const resolveMediaPipeline = async (sessionId) => {
11083
+ if (options.mediaPipeline === undefined)
11084
+ return;
11085
+ return typeof options.mediaPipeline === "function" ? await options.mediaPipeline({ sessionId }) : options.mediaPipeline;
11086
+ };
11087
+ const buildRecord = async (sessionId) => buildVoiceOperationsRecord({
11064
11088
  audit: options.audit,
11065
11089
  evaluation: options.evaluation,
11066
11090
  events: options.events,
11067
11091
  integrationEvents: options.integrationEvents,
11092
+ mediaPipeline: await resolveMediaPipeline(sessionId),
11068
11093
  redact: options.redact,
11069
11094
  reviews: options.reviews,
11070
11095
  sessionId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.466",
3
+ "version": "0.0.22-beta.468",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",