@absolutejs/voice 0.0.22-beta.461 → 0.0.22-beta.463

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
@@ -16864,7 +16864,38 @@ var resolveRealCallEvidenceRuntimeReconnectReports = async (reports, options) =>
16864
16864
  }
16865
16865
  return Array.isArray(resolved) ? resolved : [resolved];
16866
16866
  };
16867
+ var resolveRealCallEvidenceRuntimeSurfaceEvidence = async (source, options) => {
16868
+ const resolved = typeof source === "function" ? await source(options) : source;
16869
+ if (!resolved) {
16870
+ return [];
16871
+ }
16872
+ return Array.isArray(resolved) ? [...resolved] : [resolved];
16873
+ };
16874
+ var createRealCallEvidenceRuntimeSessionId = (prefix, generatedAt) => `${prefix}-${Date.parse(generatedAt) || Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
16875
+ var buildVoiceRealCallProfileEvidenceFromRuntimeSurface = (input, options) => {
16876
+ const evidence = Array.isArray(input) ? input : [input];
16877
+ return evidence.map((item) => {
16878
+ const generatedAt = item.generatedAt ?? (options.now ?? (() => new Date))().toISOString();
16879
+ return {
16880
+ ...item,
16881
+ generatedAt,
16882
+ profileId: item.profileId ?? options.defaultProfileId,
16883
+ providers: item.providers ? [...item.providers] : undefined,
16884
+ sessionId: item.sessionId ?? createRealCallEvidenceRuntimeSessionId(options.defaultSessionPrefix, generatedAt),
16885
+ surfaces: [
16886
+ ...new Set([...item.surfaces ?? [], ...options.defaultSurfaces])
16887
+ ].sort()
16888
+ };
16889
+ });
16890
+ };
16891
+ var buildVoiceRealCallProfileEvidenceFromRuntimeProviderRoles = (input, options = {}) => buildVoiceRealCallProfileEvidenceFromRuntimeSurface(input, {
16892
+ defaultProfileId: options.defaultProfileId ?? "provider-role-evidence",
16893
+ defaultSessionPrefix: options.defaultSessionPrefix ?? "provider-role-evidence",
16894
+ defaultSurfaces: ["provider-path"],
16895
+ now: options.now
16896
+ });
16867
16897
  var mergeRealCallEvidenceRuntimeOptions = (base, override = {}) => ({
16898
+ browserEvidence: override.browserEvidence ?? base.browserEvidence,
16868
16899
  dedupe: override.dedupe ?? base.dedupe,
16869
16900
  evidenceStore: override.evidenceStore ?? base.evidenceStore,
16870
16901
  existingEvidenceLimit: override.existingEvidenceLimit ?? base.existingEvidenceLimit,
@@ -16873,6 +16904,8 @@ var mergeRealCallEvidenceRuntimeOptions = (base, override = {}) => ({
16873
16904
  ...override.history ?? {}
16874
16905
  },
16875
16906
  now: override.now ?? base.now,
16907
+ phoneEvidence: override.phoneEvidence ?? base.phoneEvidence,
16908
+ providerRoleEvidence: override.providerRoleEvidence ?? base.providerRoleEvidence,
16876
16909
  reconnectEvidence: {
16877
16910
  ...base.reconnectEvidence ?? {},
16878
16911
  ...override.reconnectEvidence ?? {}
@@ -16921,6 +16954,30 @@ var buildRealCallEvidenceRuntimeReport = async (options, input = {}) => {
16921
16954
  };
16922
16955
  var collectVoiceRealCallEvidenceRuntimeEvidence = async (options) => {
16923
16956
  const evidence = [];
16957
+ const browserEvidence = await resolveRealCallEvidenceRuntimeSurfaceEvidence(options.browserEvidence, options);
16958
+ if (browserEvidence.length > 0) {
16959
+ evidence.push(...buildVoiceRealCallProfileEvidenceFromRuntimeSurface(browserEvidence, {
16960
+ defaultProfileId: "browser-call",
16961
+ defaultSessionPrefix: "browser-call",
16962
+ defaultSurfaces: ["browser"],
16963
+ now: options.now
16964
+ }));
16965
+ }
16966
+ const phoneEvidence = await resolveRealCallEvidenceRuntimeSurfaceEvidence(options.phoneEvidence, options);
16967
+ if (phoneEvidence.length > 0) {
16968
+ evidence.push(...buildVoiceRealCallProfileEvidenceFromRuntimeSurface(phoneEvidence, {
16969
+ defaultProfileId: "phone-agent",
16970
+ defaultSessionPrefix: "phone-agent",
16971
+ defaultSurfaces: ["phone", "telephony"],
16972
+ now: options.now
16973
+ }));
16974
+ }
16975
+ const providerRoleEvidence = await resolveRealCallEvidenceRuntimeSurfaceEvidence(options.providerRoleEvidence, options);
16976
+ if (providerRoleEvidence.length > 0) {
16977
+ evidence.push(...buildVoiceRealCallProfileEvidenceFromRuntimeProviderRoles(providerRoleEvidence, {
16978
+ now: options.now
16979
+ }));
16980
+ }
16924
16981
  if (options.traceStore) {
16925
16982
  evidence.push(...buildVoiceRealCallProfileEvidenceFromTraceEvents(await options.traceStore.list({
16926
16983
  limit: options.traceEvidence?.limit ?? 5000
@@ -22045,10 +22102,10 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
22045
22102
  return routes;
22046
22103
  };
22047
22104
  // src/operationalStatus.ts
22048
- import { Elysia as Elysia46 } from "elysia";
22105
+ import { Elysia as Elysia47 } from "elysia";
22049
22106
 
22050
22107
  // src/productionReadiness.ts
22051
- import { Elysia as Elysia45 } from "elysia";
22108
+ import { Elysia as Elysia46 } from "elysia";
22052
22109
 
22053
22110
  // src/handoffHealth.ts
22054
22111
  import { Elysia as Elysia33 } from "elysia";
@@ -26620,188 +26677,516 @@ var createVoiceProviderSloRoutes = (options) => {
26620
26677
  return app;
26621
26678
  };
26622
26679
 
26623
- // src/opsRecovery.ts
26680
+ // src/sessionObservability.ts
26624
26681
  import { Elysia as Elysia42 } from "elysia";
26625
-
26626
- // src/latencySlo.ts
26627
- var DEFAULT_WARN_AFTER_MS = 1800;
26628
- var DEFAULT_FAIL_AFTER_MS = 3200;
26629
- var STAGE_LABELS = {
26630
- assistant_text_to_tts_send: "Assistant text to TTS send",
26631
- barge_in_stop: "Barge-in stop latency",
26632
- commit_to_assistant_text: "Commit to assistant text",
26633
- final_to_commit: "Final transcript to commit",
26634
- live_latency: "Browser live latency",
26635
- provider_llm: "LLM provider latency",
26636
- provider_stt: "STT provider latency",
26637
- provider_tts: "TTS provider latency",
26638
- speech_to_commit: "Speech detected to commit",
26639
- tts_send_duration: "TTS send duration",
26640
- tts_to_first_audio: "TTS to first audio"
26641
- };
26642
- var TRACE_TYPES = [
26643
- "assistant.run",
26644
- "client.barge_in",
26645
- "client.live_latency",
26646
- "turn.transcript",
26647
- "turn_latency.stage"
26648
- ];
26649
- var getNumber10 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
26650
- var getString14 = (value) => typeof value === "string" && value.trim() ? value : undefined;
26651
- var percentile5 = (values, percentileValue) => {
26652
- if (values.length === 0) {
26653
- return;
26654
- }
26655
- const sorted = [...values].sort((left, right) => left - right);
26656
- const index = Math.min(sorted.length - 1, Math.max(0, Math.ceil(percentileValue / 100 * sorted.length) - 1));
26657
- return Math.round(sorted[index] ?? 0);
26658
- };
26659
- var average2 = (values) => values.length === 0 ? undefined : Math.round(values.reduce((total, value) => total + value, 0) / values.length);
26660
- var resolveBudget = (stage, options) => ({
26661
- failAfterMs: options.budgets?.[stage]?.failAfterMs ?? options.failAfterMs ?? DEFAULT_FAIL_AFTER_MS,
26662
- warnAfterMs: options.budgets?.[stage]?.warnAfterMs ?? options.warnAfterMs ?? DEFAULT_WARN_AFTER_MS
26663
- });
26664
- var statusForLatency = (latencyMs, budget) => latencyMs > budget.failAfterMs ? "fail" : budget.warnAfterMs !== undefined && latencyMs > budget.warnAfterMs ? "warn" : "pass";
26665
- var stageMeasurement = (input) => {
26666
- if (input.latencyMs === undefined) {
26682
+ var escapeHtml40 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
26683
+ var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
26684
+ var resolveHref = (href, sessionId) => {
26685
+ if (href === false) {
26667
26686
  return;
26668
26687
  }
26669
- return {
26670
- at: input.at,
26671
- latencyMs: Math.max(0, Math.round(input.latencyMs)),
26672
- label: STAGE_LABELS[input.stage],
26673
- provider: input.provider,
26674
- sessionId: input.sessionId,
26675
- stage: input.stage,
26676
- status: statusForLatency(Math.max(0, input.latencyMs), input.budget),
26677
- turnId: input.turnId
26678
- };
26679
- };
26680
- var providerStageForEvent = (event) => {
26681
- if (event.type === "assistant.run") {
26682
- return "provider_llm";
26683
- }
26684
- if (event.type === "turn.transcript") {
26685
- return "provider_stt";
26686
- }
26687
- const kind = getString14(event.payload.providerKind) ?? getString14(event.payload.kind) ?? getString14(event.payload.lane);
26688
- if (kind === "llm" || kind === "model") {
26689
- return "provider_llm";
26690
- }
26691
- if (kind === "stt" || kind === "transcription") {
26692
- return "provider_stt";
26688
+ if (typeof href === "function") {
26689
+ return href(sessionId);
26693
26690
  }
26694
- if (kind === "tts" || kind === "speech") {
26695
- return "provider_tts";
26691
+ if (typeof href === "string") {
26692
+ return href.includes(":sessionId") ? href.replaceAll(":sessionId", encodeURIComponent(sessionId)) : `${href.replace(/\/$/, "")}/${encodeURIComponent(sessionId)}`;
26696
26693
  }
26697
26694
  return;
26698
26695
  };
26699
- var eventElapsedMs2 = (event) => getNumber10(event.payload.elapsedMs) ?? getNumber10(event.payload.latencyMs) ?? getNumber10(event.payload.durationMs);
26700
- var collectTraceStageMeasurements = (events, options) => {
26701
- const grouped = new Map;
26702
- for (const event of events) {
26703
- if (event.type !== "turn_latency.stage" || !event.turnId) {
26704
- continue;
26696
+ var buildLinks = (options) => {
26697
+ const links = [];
26698
+ const add = (rel, label, href) => {
26699
+ if (href) {
26700
+ links.push({ href, label, rel });
26705
26701
  }
26706
- const stage = getString14(event.payload.stage);
26707
- if (!stage) {
26702
+ };
26703
+ add("operations-record", "Open operations record", resolveHref(options.operationsRecordHref, options.sessionId));
26704
+ add("trace-timeline", "Open trace timeline", resolveHref(options.traceTimelineHref, options.sessionId));
26705
+ add("call-debugger", "Open call debugger", resolveHref(options.callDebuggerHref, options.sessionId));
26706
+ add("incident-markdown", "Download incident Markdown", resolveHref(options.incidentMarkdownHref, options.sessionId));
26707
+ return [...links, ...options.customLinks ?? []];
26708
+ };
26709
+ var buildTurnWaterfalls = (record) => {
26710
+ const byTurn = new Map;
26711
+ const getTurn = (turnId) => {
26712
+ const existing = byTurn.get(turnId);
26713
+ if (existing) {
26714
+ return existing;
26715
+ }
26716
+ const turn = {
26717
+ assistantReplies: 0,
26718
+ errors: 0,
26719
+ providerDecisions: 0,
26720
+ stages: [],
26721
+ toolCalls: 0,
26722
+ transcripts: 0
26723
+ };
26724
+ byTurn.set(turnId, turn);
26725
+ return turn;
26726
+ };
26727
+ for (const event of record.timeline) {
26728
+ if (!event.turnId) {
26708
26729
  continue;
26709
26730
  }
26710
- const key = `${event.sessionId}:${event.turnId}`;
26711
- const stages = grouped.get(key) ?? new Map;
26712
- const previous = stages.get(stage);
26713
- if (!previous || event.at < previous.at) {
26714
- stages.set(stage, event);
26731
+ const turn = getTurn(event.turnId);
26732
+ turn.stages.push({
26733
+ at: event.at,
26734
+ elapsedMs: event.elapsedMs,
26735
+ label: event.label,
26736
+ offsetMs: event.offsetMs,
26737
+ provider: event.provider,
26738
+ status: event.status,
26739
+ type: event.type
26740
+ });
26741
+ if (event.type === "turn.transcript") {
26742
+ turn.transcripts += 1;
26715
26743
  }
26716
- grouped.set(key, stages);
26717
- }
26718
- const measurements = [];
26719
- for (const [key, stages] of grouped) {
26720
- const [sessionId, turnId] = key.split(":");
26721
- if (!sessionId || !turnId) {
26722
- continue;
26744
+ if (event.type === "turn.assistant") {
26745
+ turn.assistantReplies += 1;
26723
26746
  }
26724
- const speechDetected = stages.get("speech_detected")?.at;
26725
- const finalTranscript = stages.get("final_transcript")?.at;
26726
- const turnCommitted = stages.get("turn_committed")?.at;
26727
- const assistantTextStarted = stages.get("assistant_text_started")?.at;
26728
- const ttsSendStarted = stages.get("tts_send_started")?.at;
26729
- const ttsSendCompleted = stages.get("tts_send_completed")?.at;
26730
- const assistantAudioReceived = stages.get("assistant_audio_received")?.at;
26731
- const candidates = [
26732
- {
26733
- at: turnCommitted ?? 0,
26734
- budget: resolveBudget("speech_to_commit", options),
26735
- latencyMs: speechDetected === undefined || turnCommitted === undefined ? undefined : turnCommitted - speechDetected,
26736
- required: true,
26737
- sessionId,
26738
- stage: "speech_to_commit",
26739
- turnId
26740
- },
26741
- {
26742
- at: turnCommitted ?? 0,
26743
- budget: resolveBudget("final_to_commit", options),
26744
- latencyMs: finalTranscript === undefined || turnCommitted === undefined ? undefined : turnCommitted - finalTranscript,
26745
- required: true,
26746
- sessionId,
26747
- stage: "final_to_commit",
26748
- turnId
26749
- },
26750
- {
26751
- at: assistantTextStarted ?? 0,
26752
- budget: resolveBudget("commit_to_assistant_text", options),
26753
- latencyMs: turnCommitted === undefined || assistantTextStarted === undefined ? undefined : assistantTextStarted - turnCommitted,
26754
- required: true,
26755
- sessionId,
26756
- stage: "commit_to_assistant_text",
26757
- turnId
26758
- },
26759
- {
26760
- at: ttsSendStarted ?? 0,
26761
- budget: resolveBudget("assistant_text_to_tts_send", options),
26762
- latencyMs: assistantTextStarted === undefined || ttsSendStarted === undefined ? undefined : ttsSendStarted - assistantTextStarted,
26763
- required: true,
26764
- sessionId,
26765
- stage: "assistant_text_to_tts_send",
26766
- turnId
26767
- },
26768
- {
26769
- at: ttsSendCompleted ?? 0,
26770
- budget: resolveBudget("tts_send_duration", options),
26771
- latencyMs: ttsSendStarted === undefined || ttsSendCompleted === undefined ? undefined : ttsSendCompleted - ttsSendStarted,
26772
- required: true,
26773
- sessionId,
26774
- stage: "tts_send_duration",
26775
- turnId
26776
- },
26777
- {
26778
- at: assistantAudioReceived ?? 0,
26779
- budget: resolveBudget("tts_to_first_audio", options),
26780
- latencyMs: ttsSendCompleted === undefined || assistantAudioReceived === undefined ? undefined : assistantAudioReceived - ttsSendCompleted,
26781
- required: true,
26782
- sessionId,
26783
- stage: "tts_to_first_audio",
26784
- turnId
26785
- }
26786
- ];
26787
- for (const candidate of candidates) {
26788
- const measurement = stageMeasurement(candidate);
26789
- if (measurement) {
26790
- measurements.push(measurement);
26791
- }
26747
+ if (event.type === "agent.tool") {
26748
+ turn.toolCalls += 1;
26749
+ }
26750
+ if (event.type === "provider.decision") {
26751
+ turn.providerDecisions += 1;
26752
+ }
26753
+ if (event.type === "session.error" || event.status === "error") {
26754
+ turn.errors += 1;
26792
26755
  }
26793
26756
  }
26794
- return measurements;
26795
- };
26796
- var collectDirectMeasurements = (events, options) => {
26797
- const measurements = [];
26798
- for (const event of events) {
26799
- if (event.type === "client.live_latency") {
26800
- const stage = "live_latency";
26801
- const measurement = stageMeasurement({
26802
- at: event.at,
26803
- budget: resolveBudget(stage, options),
26804
- latencyMs: eventElapsedMs2(event),
26757
+ for (const transcript of record.transcript) {
26758
+ const turn = getTurn(transcript.id);
26759
+ turn.assistantReplies = Math.max(turn.assistantReplies, transcript.assistantReplies.length);
26760
+ turn.errors += transcript.errors.length;
26761
+ turn.transcripts = Math.max(turn.transcripts, transcript.transcripts.length);
26762
+ }
26763
+ return [...byTurn.entries()].map(([turnId, turn]) => {
26764
+ const startedAt = turn.stages[0]?.at;
26765
+ const endedAt = turn.stages.at(-1)?.at;
26766
+ return {
26767
+ assistantReplies: turn.assistantReplies,
26768
+ durationMs: startedAt !== undefined && endedAt !== undefined ? Math.max(0, endedAt - startedAt) : undefined,
26769
+ endedAt,
26770
+ errors: turn.errors,
26771
+ providerDecisions: turn.providerDecisions,
26772
+ stages: turn.stages,
26773
+ startedAt,
26774
+ toolCalls: turn.toolCalls,
26775
+ transcripts: turn.transcripts,
26776
+ turnId
26777
+ };
26778
+ }).sort((left, right) => (left.startedAt ?? 0) - (right.startedAt ?? 0));
26779
+ };
26780
+ var buildVoiceSessionObservabilityReport = async (options) => {
26781
+ const record = await buildVoiceOperationsRecord({
26782
+ audit: options.audit,
26783
+ evaluation: options.evaluation,
26784
+ events: options.events,
26785
+ integrationEvents: options.integrationEvents,
26786
+ redact: options.redact,
26787
+ reviews: options.reviews,
26788
+ sessionId: options.sessionId,
26789
+ store: options.store,
26790
+ tasks: options.tasks
26791
+ });
26792
+ const failureReplay = buildVoiceFailureReplay(record, {
26793
+ operationsRecordHref: resolveHref(options.operationsRecordHref, options.sessionId)
26794
+ });
26795
+ const incidentMarkdown = renderVoiceOperationsRecordIncidentMarkdown(record);
26796
+ const statuses = [
26797
+ record.status,
26798
+ failureReplay.status === "failed" ? "failed" : failureReplay.status === "degraded" ? "warning" : "healthy"
26799
+ ];
26800
+ const status = statuses.includes("failed") ? "failed" : statuses.includes("warning") ? "warning" : "healthy";
26801
+ return {
26802
+ checkedAt: Date.now(),
26803
+ failureReplay,
26804
+ incidentMarkdown,
26805
+ links: buildLinks(options),
26806
+ record,
26807
+ sessionId: options.sessionId,
26808
+ status,
26809
+ summary: {
26810
+ durationMs: record.summary.callDurationMs,
26811
+ errors: record.summary.errorCount,
26812
+ events: record.summary.eventCount,
26813
+ fallbacks: record.providerDecisionSummary.fallbacks,
26814
+ guardrailBlocks: record.guardrails.blocked,
26815
+ handoffs: record.handoffs.length,
26816
+ providerRecoveryStatus: record.providerDecisionSummary.recoveryStatus,
26817
+ providers: record.providerDecisionSummary.providers,
26818
+ telephonyMediaEvents: record.telephonyMedia.total,
26819
+ toolCalls: record.tools.length,
26820
+ turns: record.summary.turnCount
26821
+ },
26822
+ turns: buildTurnWaterfalls(record)
26823
+ };
26824
+ };
26825
+ var renderLinks = (links) => links.length === 0 ? "" : `<div class="actions">${links.map((link) => `<a href="${escapeHtml40(link.href)}">${escapeHtml40(link.label)}</a>`).join("")}</div>`;
26826
+ var renderTurns = (turns) => turns.length === 0 ? '<p class="muted">No turn-level events recorded yet.</p>' : turns.map((turn) => `<article class="turn"><header><strong>${escapeHtml40(turn.turnId)}</strong><span>${formatMs4(turn.durationMs)}</span></header><dl><div><dt>Transcripts</dt><dd>${String(turn.transcripts)}</dd></div><div><dt>Assistant</dt><dd>${String(turn.assistantReplies)}</dd></div><div><dt>Tools</dt><dd>${String(turn.toolCalls)}</dd></div><div><dt>Providers</dt><dd>${String(turn.providerDecisions)}</dd></div><div><dt>Errors</dt><dd>${String(turn.errors)}</dd></div></dl><table><thead><tr><th>Offset</th><th>Type</th><th>Stage</th><th>Provider</th><th>Status</th><th>Latency</th></tr></thead><tbody>${turn.stages.map((stage) => `<tr><td>+${String(stage.offsetMs)}ms</td><td>${escapeHtml40(stage.type)}</td><td>${escapeHtml40(stage.label)}</td><td>${escapeHtml40(stage.provider ?? "")}</td><td>${escapeHtml40(stage.status ?? "")}</td><td>${formatMs4(stage.elapsedMs)}</td></tr>`).join("")}</tbody></table></article>`).join("");
26827
+ var renderVoiceSessionObservabilityMarkdown = (report) => `# Voice session observability: ${report.sessionId}
26828
+
26829
+ Status: ${report.status}
26830
+
26831
+ - Events: ${report.summary.events}
26832
+ - Turns: ${report.summary.turns}
26833
+ - Errors: ${report.summary.errors}
26834
+ - Duration: ${formatMs4(report.summary.durationMs)}
26835
+ - Providers: ${report.summary.providers.join(", ") || "none"}
26836
+ - Provider recovery: ${report.summary.providerRecoveryStatus}
26837
+ - Fallbacks: ${report.summary.fallbacks}
26838
+ - Tool calls: ${report.summary.toolCalls}
26839
+ - Handoffs: ${report.summary.handoffs}
26840
+ - Guardrail blocks: ${report.summary.guardrailBlocks}
26841
+ - Telephony media events: ${report.summary.telephonyMediaEvents}
26842
+
26843
+ ## Links
26844
+
26845
+ ${report.links.length ? report.links.map((link) => `- [${link.label}](${link.href})`).join(`
26846
+ `) : "- none"}
26847
+
26848
+ ## Turn Waterfalls
26849
+
26850
+ ${report.turns.length ? report.turns.map((turn) => `### ${turn.turnId}
26851
+
26852
+ - Duration: ${formatMs4(turn.durationMs)}
26853
+ - Transcripts: ${turn.transcripts}
26854
+ - Assistant replies: ${turn.assistantReplies}
26855
+ - Tool calls: ${turn.toolCalls}
26856
+ - Provider decisions: ${turn.providerDecisions}
26857
+ - Errors: ${turn.errors}
26858
+
26859
+ ${turn.stages.map((stage) => `- +${stage.offsetMs}ms ${stage.type}: ${stage.label}${stage.provider ? ` (${stage.provider})` : ""}${stage.status ? ` [${stage.status}]` : ""}`).join(`
26860
+ `)}`).join(`
26861
+
26862
+ `) : "No turn-level events recorded."}
26863
+
26864
+ ## Incident Handoff
26865
+
26866
+ ${report.incidentMarkdown}`;
26867
+ var renderVoiceSessionObservabilityHTML = (report, options = {}) => `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(options.title ?? "Voice Session Observability")}</title><style>body{background:#0d1412;color:#f7f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.eyebrow{color:#fbbf24;font-size:.78rem;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 #425046;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.actions{display:flex;flex-wrap:wrap;gap:10px;margin:18px 0}.actions a{background:#fbbf24;border-radius:999px;color:#111827;font-weight:900;padding:10px 14px;text-decoration:none}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:22px 0}.card,.turn,.incident{background:#17201c;border:1px solid #2e3c35;border-radius:20px;padding:16px}.card span,.muted,dt{color:#a8b4ad}.card strong{display:block;font-size:2rem}section{margin-top:30px}.turn{margin:16px 0}.turn header{align-items:center;display:flex;justify-content:space-between;gap:14px}dl{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));margin:14px 0}dd{font-weight:900;margin:3px 0 0}table{border-collapse:collapse;margin-top:14px;width:100%}td,th{border-top:1px solid #2e3c35;padding:10px;text-align:left}pre{background:#08100d;border:1px solid #2e3c35;border-radius:16px;color:#d9f99d;overflow:auto;padding:14px}@media(max-width:760px){main{padding:20px}table{font-size:.9rem}}</style></head><body><main><header><p class="eyebrow">Session observability</p><h1>${escapeHtml40(report.sessionId)}</h1><p class="status ${escapeHtml40(report.status)}">${escapeHtml40(report.status)}</p>${renderLinks(report.links)}<p class="muted">One support/debug report across trace timeline, operations record, provider recovery, turn waterfalls, guardrails, tools, handoffs, failure replay, and incident handoff.</p></header><section class="grid"><article class="card"><span>Events</span><strong>${String(report.summary.events)}</strong></article><article class="card"><span>Turns</span><strong>${String(report.summary.turns)}</strong></article><article class="card"><span>Errors</span><strong>${String(report.summary.errors)}</strong></article><article class="card"><span>Duration</span><strong>${formatMs4(report.summary.durationMs)}</strong></article><article class="card"><span>Fallbacks</span><strong>${String(report.summary.fallbacks)}</strong></article><article class="card"><span>Tools</span><strong>${String(report.summary.toolCalls)}</strong></article><article class="card"><span>Handoffs</span><strong>${String(report.summary.handoffs)}</strong></article><article class="card"><span>Guardrails blocked</span><strong>${String(report.summary.guardrailBlocks)}</strong></article><article class="card"><span>Telephony media</span><strong>${String(report.summary.telephonyMediaEvents)}</strong></article></section><section><h2>Turn Waterfalls</h2>${renderTurns(report.turns)}</section><section class="incident"><h2>Incident Handoff</h2><pre><code>${escapeHtml40(report.incidentMarkdown)}</code></pre></section></main></body></html>`;
26868
+ var routeSessionId = (params) => typeof params.sessionId === "string" ? params.sessionId : "";
26869
+ var linkByRel = (links) => {
26870
+ const map = new Map;
26871
+ for (const link of links) {
26872
+ map.set(link.rel, true);
26873
+ }
26874
+ return (rel) => map.get(rel) ?? false;
26875
+ };
26876
+ var evaluateVoiceSessionObservabilityEvidence = (report, input = {}) => {
26877
+ const issues = [];
26878
+ const has = linkByRel(report.links);
26879
+ const status = report.status === "healthy" ? "pass" : report.status === "warning" ? "warn" : "fail";
26880
+ const turnsWithWaterfalls = report.turns.filter((turn) => turn.stages.length > 0).length;
26881
+ const stages = report.turns.reduce((total, turn) => total + turn.stages.length, 0);
26882
+ const providerDecisions = report.turns.reduce((total, turn) => total + turn.providerDecisions, 0);
26883
+ const toolCalls = report.turns.reduce((total, turn) => total + turn.toolCalls, 0);
26884
+ if (input.requireHealthy && report.status !== "healthy") {
26885
+ issues.push("Expected a healthy session observability report.");
26886
+ }
26887
+ if (input.minTurns !== undefined && report.summary.turns < input.minTurns) {
26888
+ issues.push(`Expected at least ${String(input.minTurns)} turn(s), found ${String(report.summary.turns)}.`);
26889
+ }
26890
+ if (input.minTurnWaterfalls !== undefined && turnsWithWaterfalls < input.minTurnWaterfalls) {
26891
+ issues.push(`Expected at least ${String(input.minTurnWaterfalls)} turn(s) with stage data, found ${String(turnsWithWaterfalls)}.`);
26892
+ }
26893
+ if (input.minStageCount !== undefined && stages < input.minStageCount) {
26894
+ issues.push(`Expected at least ${String(input.minStageCount)} turn stages, found ${String(stages)}.`);
26895
+ }
26896
+ if (input.minProviderDecisions !== undefined && providerDecisions < input.minProviderDecisions) {
26897
+ issues.push(`Expected at least ${String(input.minProviderDecisions)} provider decision stage(s), found ${String(providerDecisions)}.`);
26898
+ }
26899
+ if (input.minToolCalls !== undefined && toolCalls < input.minToolCalls) {
26900
+ issues.push(`Expected at least ${String(input.minToolCalls)} tool call stage(s), found ${String(toolCalls)}.`);
26901
+ }
26902
+ if (input.maxErrors !== undefined && report.summary.errors > input.maxErrors) {
26903
+ issues.push(`Expected at most ${String(input.maxErrors)} error(s), found ${String(report.summary.errors)}.`);
26904
+ }
26905
+ if (input.maxFallbacks !== undefined && report.summary.fallbacks > input.maxFallbacks) {
26906
+ issues.push(`Expected at most ${String(input.maxFallbacks)} fallback(s), found ${String(report.summary.fallbacks)}.`);
26907
+ }
26908
+ if (input.requireOperationsRecordLink && !has("operations-record")) {
26909
+ issues.push("Expected operations-record link in session observability evidence.");
26910
+ }
26911
+ if (input.requireTraceTimelineLink && !has("trace-timeline")) {
26912
+ issues.push("Expected trace-timeline link in session observability evidence.");
26913
+ }
26914
+ if (input.requireCallDebuggerLink && !has("call-debugger")) {
26915
+ issues.push("Expected call-debugger link in session observability evidence.");
26916
+ }
26917
+ if (input.requireIncidentMarkdownLink && !has("incident-markdown")) {
26918
+ issues.push("Expected incident-markdown link in session observability evidence.");
26919
+ }
26920
+ if (input.requireIncidentMarkdown && (!report.incidentMarkdown || report.incidentMarkdown.trim().length < 24 || !report.incidentMarkdown.toLowerCase().includes("incident handoff"))) {
26921
+ issues.push("Expected readable incident markdown payload.");
26922
+ }
26923
+ if (input.requireProviderRecoveryStatus !== undefined && (Array.isArray(input.requireProviderRecoveryStatus) ? input.requireProviderRecoveryStatus : [input.requireProviderRecoveryStatus]).indexOf(report.summary.providerRecoveryStatus) === -1) {
26924
+ issues.push(`Expected provider recovery status ${String(input.requireProviderRecoveryStatus)}, found ${report.summary.providerRecoveryStatus}.`);
26925
+ }
26926
+ return {
26927
+ checkedAt: Date.now(),
26928
+ issues,
26929
+ ok: issues.length === 0,
26930
+ status: issues.length > 0 ? status === "fail" ? "fail" : "warn" : status,
26931
+ summary: {
26932
+ incidentMarkdownLength: report.incidentMarkdown.length,
26933
+ providerDecisions,
26934
+ providerRecoveryStatus: report.summary.providerRecoveryStatus,
26935
+ reportStatus: report.status,
26936
+ stages,
26937
+ turns: report.turns.length,
26938
+ turnsWithWaterfalls,
26939
+ toolCalls,
26940
+ links: {
26941
+ callDebugger: has("call-debugger"),
26942
+ incidentMarkdown: has("incident-markdown"),
26943
+ operationsRecord: has("operations-record"),
26944
+ traceTimeline: has("trace-timeline")
26945
+ }
26946
+ }
26947
+ };
26948
+ };
26949
+ var assertVoiceSessionObservabilityEvidence = (report, input = {}) => {
26950
+ const assertion = evaluateVoiceSessionObservabilityEvidence(report, input);
26951
+ if (!assertion.ok) {
26952
+ throw new Error(`Voice session observability evidence assertion failed: ${assertion.issues.join(" ")}`);
26953
+ }
26954
+ return assertion;
26955
+ };
26956
+ var createVoiceSessionObservabilityRoutes = (options) => {
26957
+ const path = options.path ?? "/api/voice/session-observability/:sessionId";
26958
+ const htmlPath = options.htmlPath ?? "/voice/session-observability/:sessionId";
26959
+ const incidentPath = options.incidentPath ?? "/api/voice/session-observability/:sessionId/incident.md";
26960
+ const title = options.title ?? "AbsoluteJS Voice Session Observability";
26961
+ const routes = new Elysia42({
26962
+ name: options.name ?? "absolutejs-voice-session-observability"
26963
+ });
26964
+ const build = (sessionId) => buildVoiceSessionObservabilityReport({
26965
+ audit: options.audit,
26966
+ callDebuggerHref: options.callDebuggerHref,
26967
+ customLinks: options.customLinks,
26968
+ evaluation: options.evaluation,
26969
+ events: options.events,
26970
+ incidentMarkdownHref: options.incidentMarkdownHref ?? (incidentPath === false ? false : incidentPath),
26971
+ integrationEvents: options.integrationEvents,
26972
+ operationsRecordHref: options.operationsRecordHref,
26973
+ redact: options.redact,
26974
+ reviews: options.reviews,
26975
+ sessionId,
26976
+ store: options.store,
26977
+ tasks: options.tasks,
26978
+ traceTimelineHref: options.traceTimelineHref
26979
+ });
26980
+ routes.get(path, async ({ params }) => Response.json(await build(routeSessionId(params))));
26981
+ if (htmlPath !== false) {
26982
+ routes.get(htmlPath, async ({ params }) => {
26983
+ const report = await build(routeSessionId(params));
26984
+ const body = await (options.render ?? ((input) => renderVoiceSessionObservabilityHTML(input, { title })))(report);
26985
+ return new Response(body, {
26986
+ headers: {
26987
+ "content-type": "text/html; charset=utf-8",
26988
+ ...options.headers
26989
+ }
26990
+ });
26991
+ });
26992
+ }
26993
+ if (incidentPath !== false) {
26994
+ routes.get(incidentPath, async ({ params }) => {
26995
+ const report = await build(routeSessionId(params));
26996
+ const body = await (options.renderIncidentMarkdown ?? renderVoiceSessionObservabilityMarkdown)(report);
26997
+ return new Response(body, {
26998
+ headers: {
26999
+ "content-type": "text/markdown; charset=utf-8",
27000
+ ...options.headers
27001
+ }
27002
+ });
27003
+ });
27004
+ }
27005
+ return routes;
27006
+ };
27007
+
27008
+ // src/opsRecovery.ts
27009
+ import { Elysia as Elysia43 } from "elysia";
27010
+
27011
+ // src/latencySlo.ts
27012
+ var DEFAULT_WARN_AFTER_MS = 1800;
27013
+ var DEFAULT_FAIL_AFTER_MS = 3200;
27014
+ var STAGE_LABELS = {
27015
+ assistant_text_to_tts_send: "Assistant text to TTS send",
27016
+ barge_in_stop: "Barge-in stop latency",
27017
+ commit_to_assistant_text: "Commit to assistant text",
27018
+ final_to_commit: "Final transcript to commit",
27019
+ live_latency: "Browser live latency",
27020
+ provider_llm: "LLM provider latency",
27021
+ provider_stt: "STT provider latency",
27022
+ provider_tts: "TTS provider latency",
27023
+ speech_to_commit: "Speech detected to commit",
27024
+ tts_send_duration: "TTS send duration",
27025
+ tts_to_first_audio: "TTS to first audio"
27026
+ };
27027
+ var TRACE_TYPES = [
27028
+ "assistant.run",
27029
+ "client.barge_in",
27030
+ "client.live_latency",
27031
+ "turn.transcript",
27032
+ "turn_latency.stage"
27033
+ ];
27034
+ var getNumber10 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
27035
+ var getString14 = (value) => typeof value === "string" && value.trim() ? value : undefined;
27036
+ var percentile5 = (values, percentileValue) => {
27037
+ if (values.length === 0) {
27038
+ return;
27039
+ }
27040
+ const sorted = [...values].sort((left, right) => left - right);
27041
+ const index = Math.min(sorted.length - 1, Math.max(0, Math.ceil(percentileValue / 100 * sorted.length) - 1));
27042
+ return Math.round(sorted[index] ?? 0);
27043
+ };
27044
+ var average2 = (values) => values.length === 0 ? undefined : Math.round(values.reduce((total, value) => total + value, 0) / values.length);
27045
+ var resolveBudget = (stage, options) => ({
27046
+ failAfterMs: options.budgets?.[stage]?.failAfterMs ?? options.failAfterMs ?? DEFAULT_FAIL_AFTER_MS,
27047
+ warnAfterMs: options.budgets?.[stage]?.warnAfterMs ?? options.warnAfterMs ?? DEFAULT_WARN_AFTER_MS
27048
+ });
27049
+ var statusForLatency = (latencyMs, budget) => latencyMs > budget.failAfterMs ? "fail" : budget.warnAfterMs !== undefined && latencyMs > budget.warnAfterMs ? "warn" : "pass";
27050
+ var stageMeasurement = (input) => {
27051
+ if (input.latencyMs === undefined) {
27052
+ return;
27053
+ }
27054
+ return {
27055
+ at: input.at,
27056
+ latencyMs: Math.max(0, Math.round(input.latencyMs)),
27057
+ label: STAGE_LABELS[input.stage],
27058
+ provider: input.provider,
27059
+ sessionId: input.sessionId,
27060
+ stage: input.stage,
27061
+ status: statusForLatency(Math.max(0, input.latencyMs), input.budget),
27062
+ turnId: input.turnId
27063
+ };
27064
+ };
27065
+ var providerStageForEvent = (event) => {
27066
+ if (event.type === "assistant.run") {
27067
+ return "provider_llm";
27068
+ }
27069
+ if (event.type === "turn.transcript") {
27070
+ return "provider_stt";
27071
+ }
27072
+ const kind = getString14(event.payload.providerKind) ?? getString14(event.payload.kind) ?? getString14(event.payload.lane);
27073
+ if (kind === "llm" || kind === "model") {
27074
+ return "provider_llm";
27075
+ }
27076
+ if (kind === "stt" || kind === "transcription") {
27077
+ return "provider_stt";
27078
+ }
27079
+ if (kind === "tts" || kind === "speech") {
27080
+ return "provider_tts";
27081
+ }
27082
+ return;
27083
+ };
27084
+ var eventElapsedMs2 = (event) => getNumber10(event.payload.elapsedMs) ?? getNumber10(event.payload.latencyMs) ?? getNumber10(event.payload.durationMs);
27085
+ var collectTraceStageMeasurements = (events, options) => {
27086
+ const grouped = new Map;
27087
+ for (const event of events) {
27088
+ if (event.type !== "turn_latency.stage" || !event.turnId) {
27089
+ continue;
27090
+ }
27091
+ const stage = getString14(event.payload.stage);
27092
+ if (!stage) {
27093
+ continue;
27094
+ }
27095
+ const key = `${event.sessionId}:${event.turnId}`;
27096
+ const stages = grouped.get(key) ?? new Map;
27097
+ const previous = stages.get(stage);
27098
+ if (!previous || event.at < previous.at) {
27099
+ stages.set(stage, event);
27100
+ }
27101
+ grouped.set(key, stages);
27102
+ }
27103
+ const measurements = [];
27104
+ for (const [key, stages] of grouped) {
27105
+ const [sessionId, turnId] = key.split(":");
27106
+ if (!sessionId || !turnId) {
27107
+ continue;
27108
+ }
27109
+ const speechDetected = stages.get("speech_detected")?.at;
27110
+ const finalTranscript = stages.get("final_transcript")?.at;
27111
+ const turnCommitted = stages.get("turn_committed")?.at;
27112
+ const assistantTextStarted = stages.get("assistant_text_started")?.at;
27113
+ const ttsSendStarted = stages.get("tts_send_started")?.at;
27114
+ const ttsSendCompleted = stages.get("tts_send_completed")?.at;
27115
+ const assistantAudioReceived = stages.get("assistant_audio_received")?.at;
27116
+ const candidates = [
27117
+ {
27118
+ at: turnCommitted ?? 0,
27119
+ budget: resolveBudget("speech_to_commit", options),
27120
+ latencyMs: speechDetected === undefined || turnCommitted === undefined ? undefined : turnCommitted - speechDetected,
27121
+ required: true,
27122
+ sessionId,
27123
+ stage: "speech_to_commit",
27124
+ turnId
27125
+ },
27126
+ {
27127
+ at: turnCommitted ?? 0,
27128
+ budget: resolveBudget("final_to_commit", options),
27129
+ latencyMs: finalTranscript === undefined || turnCommitted === undefined ? undefined : turnCommitted - finalTranscript,
27130
+ required: true,
27131
+ sessionId,
27132
+ stage: "final_to_commit",
27133
+ turnId
27134
+ },
27135
+ {
27136
+ at: assistantTextStarted ?? 0,
27137
+ budget: resolveBudget("commit_to_assistant_text", options),
27138
+ latencyMs: turnCommitted === undefined || assistantTextStarted === undefined ? undefined : assistantTextStarted - turnCommitted,
27139
+ required: true,
27140
+ sessionId,
27141
+ stage: "commit_to_assistant_text",
27142
+ turnId
27143
+ },
27144
+ {
27145
+ at: ttsSendStarted ?? 0,
27146
+ budget: resolveBudget("assistant_text_to_tts_send", options),
27147
+ latencyMs: assistantTextStarted === undefined || ttsSendStarted === undefined ? undefined : ttsSendStarted - assistantTextStarted,
27148
+ required: true,
27149
+ sessionId,
27150
+ stage: "assistant_text_to_tts_send",
27151
+ turnId
27152
+ },
27153
+ {
27154
+ at: ttsSendCompleted ?? 0,
27155
+ budget: resolveBudget("tts_send_duration", options),
27156
+ latencyMs: ttsSendStarted === undefined || ttsSendCompleted === undefined ? undefined : ttsSendCompleted - ttsSendStarted,
27157
+ required: true,
27158
+ sessionId,
27159
+ stage: "tts_send_duration",
27160
+ turnId
27161
+ },
27162
+ {
27163
+ at: assistantAudioReceived ?? 0,
27164
+ budget: resolveBudget("tts_to_first_audio", options),
27165
+ latencyMs: ttsSendCompleted === undefined || assistantAudioReceived === undefined ? undefined : assistantAudioReceived - ttsSendCompleted,
27166
+ required: true,
27167
+ sessionId,
27168
+ stage: "tts_to_first_audio",
27169
+ turnId
27170
+ }
27171
+ ];
27172
+ for (const candidate of candidates) {
27173
+ const measurement = stageMeasurement(candidate);
27174
+ if (measurement) {
27175
+ measurements.push(measurement);
27176
+ }
27177
+ }
27178
+ }
27179
+ return measurements;
27180
+ };
27181
+ var collectDirectMeasurements = (events, options) => {
27182
+ const measurements = [];
27183
+ for (const event of events) {
27184
+ if (event.type === "client.live_latency") {
27185
+ const stage = "live_latency";
27186
+ const measurement = stageMeasurement({
27187
+ at: event.at,
27188
+ budget: resolveBudget(stage, options),
27189
+ latencyMs: eventElapsedMs2(event),
26805
27190
  sessionId: event.sessionId,
26806
27191
  stage,
26807
27192
  turnId: event.turnId
@@ -26927,7 +27312,7 @@ None.
26927
27312
  };
26928
27313
 
26929
27314
  // src/opsRecovery.ts
26930
- var escapeHtml40 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
27315
+ var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
26931
27316
  var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
26932
27317
  var hrefForSession = (value, sessionId) => {
26933
27318
  if (typeof value === "function") {
@@ -27141,19 +27526,19 @@ ${failedSessions || "None."}
27141
27526
  ${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
27142
27527
  `;
27143
27528
  };
27144
- var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml40(label)}</span><strong>${String(summary.failed + summary.deadLettered)} failed</strong><small>${String(summary.pending)} pending \xB7 ${String(summary.retryEligible)} retry eligible \xB7 ${String(summary.total)} total</small></article>` : `<article><span>${escapeHtml40(label)}</span><strong>not configured</strong></article>`;
27529
+ var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml41(label)}</span><strong>${String(summary.failed + summary.deadLettered)} failed</strong><small>${String(summary.pending)} pending \xB7 ${String(summary.retryEligible)} retry eligible \xB7 ${String(summary.total)} total</small></article>` : `<article><span>${escapeHtml41(label)}</span><strong>not configured</strong></article>`;
27145
27530
  var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
27146
27531
  const title = options.title ?? "Voice Ops Recovery";
27147
- const issues = report.issues.map((issue) => `<tr><td>${escapeHtml40(issue.severity)}</td><td><code>${escapeHtml40(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml40(issue.href)}">${escapeHtml40(issue.label)}</a>` : escapeHtml40(issue.label)}</td><td>${escapeHtml40(String(issue.value ?? ""))}</td><td>${escapeHtml40(issue.detail ?? "")}</td></tr>`).join("");
27148
- const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml40(provider.provider)}</td><td>${escapeHtml40(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml40(provider.lastError ?? "")}</td></tr>`).join("");
27149
- const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml40(session.operationsRecordHref)}">${escapeHtml40(session.sessionId)}</a>` : escapeHtml40(session.sessionId)}${session.provider ? ` via ${escapeHtml40(session.provider)}` : ""}${session.error ? `: ${escapeHtml40(session.error)}` : ""}</li>`).join("");
27150
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#f8fafc;color:#172033;margin:2rem;line-height:1.45}main{max-width:1180px;margin:auto}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:.75rem;margin:1rem 0}article{background:white;border:1px solid #dbe3ef;border-radius:14px;padding:1rem;box-shadow:0 10px 28px rgba(15,23,42,.05)}article span{display:block;color:#64748b;font-size:.85rem}article strong{display:block;font-size:1.5rem;margin:.2rem 0}article small{color:#64748b}table{border-collapse:collapse;width:100%;background:white;border:1px solid #dbe3ef;border-radius:14px;overflow:hidden}th,td{border-bottom:1px solid #e2e8f0;padding:.7rem;text-align:left;vertical-align:top}code{font-size:.85em}.status{display:inline-flex;border-radius:999px;padding:.35rem .7rem;background:${report.status === "fail" ? "#fee2e2" : report.status === "warn" ? "#fef3c7" : "#dcfce7"};color:${report.status === "fail" ? "#991b1b" : report.status === "warn" ? "#92400e" : "#166534"};font-weight:700}</style></head><body><main><h1>${escapeHtml40(title)}</h1><p><span class="status">${escapeHtml40(report.status)}</span> Checked ${escapeHtml40(new Date(report.checkedAt).toLocaleString())}</p><section class="grid"><article><span>Recovered fallbacks</span><strong>${String(report.providers.recoveredFallbacks)}</strong></article><article><span>Unresolved providers</span><strong>${String(report.providers.unresolvedFailures)}</strong></article><article><span>Operator interventions</span><strong>${String(report.interventions.total)}</strong></article><article><span>Latency status</span><strong>${escapeHtml40(report.latency?.status ?? "disabled")}</strong></article>${renderDeliverySummary("Audit delivery", report.auditDeliveries)}${renderDeliverySummary("Trace delivery", report.traceDeliveries)}${renderDeliverySummary("Handoff delivery", report.handoffDeliveries)}</section><h2>Issues</h2><table><thead><tr><th>Severity</th><th>Code</th><th>Label</th><th>Value</th><th>Detail</th></tr></thead><tbody>${issues || '<tr><td colspan="5">No recovery issues.</td></tr>'}</tbody></table><h2>Providers</h2><table><thead><tr><th>Provider</th><th>Status</th><th>Runs</th><th>Errors</th><th>Fallbacks</th><th>Last error</th></tr></thead><tbody>${providers || '<tr><td colspan="6">No provider activity.</td></tr>'}</tbody></table><h2>Failed Sessions</h2><ul>${failedSessions || "<li>None.</li>"}</ul></main></body></html>`;
27532
+ const issues = report.issues.map((issue) => `<tr><td>${escapeHtml41(issue.severity)}</td><td><code>${escapeHtml41(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml41(issue.href)}">${escapeHtml41(issue.label)}</a>` : escapeHtml41(issue.label)}</td><td>${escapeHtml41(String(issue.value ?? ""))}</td><td>${escapeHtml41(issue.detail ?? "")}</td></tr>`).join("");
27533
+ const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml41(provider.provider)}</td><td>${escapeHtml41(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml41(provider.lastError ?? "")}</td></tr>`).join("");
27534
+ const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml41(session.operationsRecordHref)}">${escapeHtml41(session.sessionId)}</a>` : escapeHtml41(session.sessionId)}${session.provider ? ` via ${escapeHtml41(session.provider)}` : ""}${session.error ? `: ${escapeHtml41(session.error)}` : ""}</li>`).join("");
27535
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#f8fafc;color:#172033;margin:2rem;line-height:1.45}main{max-width:1180px;margin:auto}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:.75rem;margin:1rem 0}article{background:white;border:1px solid #dbe3ef;border-radius:14px;padding:1rem;box-shadow:0 10px 28px rgba(15,23,42,.05)}article span{display:block;color:#64748b;font-size:.85rem}article strong{display:block;font-size:1.5rem;margin:.2rem 0}article small{color:#64748b}table{border-collapse:collapse;width:100%;background:white;border:1px solid #dbe3ef;border-radius:14px;overflow:hidden}th,td{border-bottom:1px solid #e2e8f0;padding:.7rem;text-align:left;vertical-align:top}code{font-size:.85em}.status{display:inline-flex;border-radius:999px;padding:.35rem .7rem;background:${report.status === "fail" ? "#fee2e2" : report.status === "warn" ? "#fef3c7" : "#dcfce7"};color:${report.status === "fail" ? "#991b1b" : report.status === "warn" ? "#92400e" : "#166534"};font-weight:700}</style></head><body><main><h1>${escapeHtml41(title)}</h1><p><span class="status">${escapeHtml41(report.status)}</span> Checked ${escapeHtml41(new Date(report.checkedAt).toLocaleString())}</p><section class="grid"><article><span>Recovered fallbacks</span><strong>${String(report.providers.recoveredFallbacks)}</strong></article><article><span>Unresolved providers</span><strong>${String(report.providers.unresolvedFailures)}</strong></article><article><span>Operator interventions</span><strong>${String(report.interventions.total)}</strong></article><article><span>Latency status</span><strong>${escapeHtml41(report.latency?.status ?? "disabled")}</strong></article>${renderDeliverySummary("Audit delivery", report.auditDeliveries)}${renderDeliverySummary("Trace delivery", report.traceDeliveries)}${renderDeliverySummary("Handoff delivery", report.handoffDeliveries)}</section><h2>Issues</h2><table><thead><tr><th>Severity</th><th>Code</th><th>Label</th><th>Value</th><th>Detail</th></tr></thead><tbody>${issues || '<tr><td colspan="5">No recovery issues.</td></tr>'}</tbody></table><h2>Providers</h2><table><thead><tr><th>Provider</th><th>Status</th><th>Runs</th><th>Errors</th><th>Fallbacks</th><th>Last error</th></tr></thead><tbody>${providers || '<tr><td colspan="6">No provider activity.</td></tr>'}</tbody></table><h2>Failed Sessions</h2><ul>${failedSessions || "<li>None.</li>"}</ul></main></body></html>`;
27151
27536
  };
27152
27537
  var createVoiceOpsRecoveryRoutes = (options = {}) => {
27153
27538
  const path = options.path ?? "/api/voice/ops-recovery";
27154
27539
  const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
27155
27540
  const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
27156
- const routes = new Elysia42({
27541
+ const routes = new Elysia43({
27157
27542
  name: options.name ?? "absolutejs-voice-ops-recovery"
27158
27543
  }).get(path, async () => buildVoiceOpsRecoveryReport(options));
27159
27544
  if (htmlPath) {
@@ -27183,8 +27568,8 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
27183
27568
  };
27184
27569
 
27185
27570
  // src/incidentTimeline.ts
27186
- import { Elysia as Elysia43 } from "elysia";
27187
- var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
27571
+ import { Elysia as Elysia44 } from "elysia";
27572
+ var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
27188
27573
  var resolveValue = async (value) => typeof value === "function" ? await value() : value;
27189
27574
  var linkForSession = (link, sessionId) => {
27190
27575
  if (!link || !sessionId) {
@@ -27305,8 +27690,8 @@ var buildVoiceIncidentRecoveryOutcomeReport = async (options) => {
27305
27690
  };
27306
27691
  var renderVoiceIncidentRecoveryOutcomeHTML = (report, options = {}) => {
27307
27692
  const title = options.title ?? "AbsoluteJS Voice Incident Recovery Outcomes";
27308
- const rows = report.entries.map((entry) => `<article class="${escapeHtml41(entry.outcome)}"><span>${escapeHtml41(entry.outcome.toUpperCase())}</span><h2>${escapeHtml41(entry.actionId)}</h2><p>${escapeHtml41(new Date(entry.at).toLocaleString())}</p><strong>${escapeHtml41(entry.beforeStatus ?? "unknown")} -> ${escapeHtml41(entry.afterStatus ?? "unknown")}</strong>${entry.detail ? `<p>${escapeHtml41(entry.detail)}</p>` : ""}</article>`).join("");
27309
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{background:#10120d;color:#fbf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero,article{background:#181711;border:1px solid #39301d;border-radius:24px;padding:20px}.hero{margin-bottom:16px}h1{font-size:clamp(2rem,6vw,4.5rem);line-height:.95}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{border:1px solid #4a3f23;border-radius:999px;padding:8px 12px}section{display:grid;gap:12px}article.improved{border-color:rgba(34,197,94,.65)}article.failed,article.regressed{border-color:rgba(239,68,68,.8)}article.unchanged{border-color:rgba(245,158,11,.7)}article span{color:#fcd34d;font-weight:900;letter-spacing:.08em}article strong{display:block;font-size:1.4rem;margin:.5rem 0}p{color:#cfc5a8}</style></head><body><main><section class="hero"><span>Recovery proof</span><h1>${escapeHtml41(title)}</h1><div class="summary"><span>${String(report.improved)} improved</span><span>${String(report.unchanged)} unchanged</span><span>${String(report.regressed)} regressed</span><span>${String(report.failed)} failed</span><span>${String(report.total)} total</span></div></section><section>${rows || "<p>No incident recovery actions have been recorded.</p>"}</section></main></body></html>`;
27693
+ const rows = report.entries.map((entry) => `<article class="${escapeHtml42(entry.outcome)}"><span>${escapeHtml42(entry.outcome.toUpperCase())}</span><h2>${escapeHtml42(entry.actionId)}</h2><p>${escapeHtml42(new Date(entry.at).toLocaleString())}</p><strong>${escapeHtml42(entry.beforeStatus ?? "unknown")} -> ${escapeHtml42(entry.afterStatus ?? "unknown")}</strong>${entry.detail ? `<p>${escapeHtml42(entry.detail)}</p>` : ""}</article>`).join("");
27694
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#10120d;color:#fbf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero,article{background:#181711;border:1px solid #39301d;border-radius:24px;padding:20px}.hero{margin-bottom:16px}h1{font-size:clamp(2rem,6vw,4.5rem);line-height:.95}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{border:1px solid #4a3f23;border-radius:999px;padding:8px 12px}section{display:grid;gap:12px}article.improved{border-color:rgba(34,197,94,.65)}article.failed,article.regressed{border-color:rgba(239,68,68,.8)}article.unchanged{border-color:rgba(245,158,11,.7)}article span{color:#fcd34d;font-weight:900;letter-spacing:.08em}article strong{display:block;font-size:1.4rem;margin:.5rem 0}p{color:#cfc5a8}</style></head><body><main><section class="hero"><span>Recovery proof</span><h1>${escapeHtml42(title)}</h1><div class="summary"><span>${String(report.improved)} improved</span><span>${String(report.unchanged)} unchanged</span><span>${String(report.regressed)} regressed</span><span>${String(report.failed)} failed</span><span>${String(report.total)} total</span></div></section><section>${rows || "<p>No incident recovery actions have been recorded.</p>"}</section></main></body></html>`;
27310
27695
  };
27311
27696
  var buildVoiceIncidentRecoveryOutcomeReadinessCheck = (report, options = {}) => {
27312
27697
  const failOnFailed = options.failOnFailed ?? true;
@@ -27503,8 +27888,8 @@ ${rows || "| n/a | 0 | 0 | 0 | 0 | 0 | n/a | n/a |"}
27503
27888
  };
27504
27889
  var renderVoiceIncidentRecoveryTrendHTML = (report, options = {}) => {
27505
27890
  const title = options.title ?? "AbsoluteJS Voice Incident Recovery Trend";
27506
- const rows = report.cycles.map((cycle) => `<tr><td>${escapeHtml41(new Date(cycle.checkedAt).toLocaleString())}</td><td>${String(cycle.total)}</td><td>${String(cycle.improved)}</td><td>${String(cycle.unchanged)}</td><td>${String(cycle.regressed)}</td><td>${String(cycle.failed)}</td><td>${escapeHtml41(percent(cycle.improvementRate))}</td><td>${escapeHtml41(percent(cycle.regressionRate))}</td></tr>`).join("");
27507
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{background:#10120d;color:#fbf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,table{background:#181711;border:1px solid #39301d;border-radius:24px}.hero{margin-bottom:16px;padding:24px}h1{font-size:clamp(2rem,6vw,4.5rem);line-height:.95}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{border:1px solid #4a3f23;border-radius:999px;padding:8px 12px}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #39301d;padding:12px;text-align:left}.pass{color:#86efac}.warn,.empty{color:#fcd34d}.fail{color:#fca5a5}p{color:#cfc5a8}</style></head><body><main><section class="hero"><span>Recovery trend</span><h1>${escapeHtml41(title)}</h1><p class="${escapeHtml41(report.status)}">Status: ${escapeHtml41(report.status)}</p><div class="summary"><span>${String(report.summary.cycles)} cycles</span><span>${String(report.summary.total)} actions</span><span>${escapeHtml41(percent(report.summary.improvementRate))} improved</span><span>${escapeHtml41(percent(report.summary.regressionRate))} regressed</span><span>${escapeHtml41(percent(report.trend.improvementRateDelta))} improvement delta</span></div></section><table><thead><tr><th>Checked at</th><th>Total</th><th>Improved</th><th>Unchanged</th><th>Regressed</th><th>Failed</th><th>Improve %</th><th>Regress %</th></tr></thead><tbody>${rows || '<tr><td colspan="8">No recovery outcome history has been recorded.</td></tr>'}</tbody></table></main></body></html>`;
27891
+ const rows = report.cycles.map((cycle) => `<tr><td>${escapeHtml42(new Date(cycle.checkedAt).toLocaleString())}</td><td>${String(cycle.total)}</td><td>${String(cycle.improved)}</td><td>${String(cycle.unchanged)}</td><td>${String(cycle.regressed)}</td><td>${String(cycle.failed)}</td><td>${escapeHtml42(percent(cycle.improvementRate))}</td><td>${escapeHtml42(percent(cycle.regressionRate))}</td></tr>`).join("");
27892
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#10120d;color:#fbf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,table{background:#181711;border:1px solid #39301d;border-radius:24px}.hero{margin-bottom:16px;padding:24px}h1{font-size:clamp(2rem,6vw,4.5rem);line-height:.95}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{border:1px solid #4a3f23;border-radius:999px;padding:8px 12px}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #39301d;padding:12px;text-align:left}.pass{color:#86efac}.warn,.empty{color:#fcd34d}.fail{color:#fca5a5}p{color:#cfc5a8}</style></head><body><main><section class="hero"><span>Recovery trend</span><h1>${escapeHtml42(title)}</h1><p class="${escapeHtml42(report.status)}">Status: ${escapeHtml42(report.status)}</p><div class="summary"><span>${String(report.summary.cycles)} cycles</span><span>${String(report.summary.total)} actions</span><span>${escapeHtml42(percent(report.summary.improvementRate))} improved</span><span>${escapeHtml42(percent(report.summary.regressionRate))} regressed</span><span>${escapeHtml42(percent(report.trend.improvementRateDelta))} improvement delta</span></div></section><table><thead><tr><th>Checked at</th><th>Total</th><th>Improved</th><th>Unchanged</th><th>Regressed</th><th>Failed</th><th>Improve %</th><th>Regress %</th></tr></thead><tbody>${rows || '<tr><td colspan="8">No recovery outcome history has been recorded.</td></tr>'}</tbody></table></main></body></html>`;
27508
27893
  };
27509
27894
  var pushOperationalStatusEvents = (events, report, links) => {
27510
27895
  if (!report) {
@@ -27730,22 +28115,22 @@ ${report.actions.map((action) => `- ${action.method ?? "GET"} ${action.id}: ${ac
27730
28115
  var renderVoiceIncidentTimelineHTML = (report, options = {}) => {
27731
28116
  const title = options.title ?? "AbsoluteJS Voice Incident Timeline";
27732
28117
  const actionPath = options.actionPath ?? "/api/voice/incident-timeline/actions";
27733
- const events = report.events.map((event) => `<article class="${escapeHtml41(event.severity)}">
27734
- <span>${escapeHtml41(event.severity.toUpperCase())} / ${escapeHtml41(event.category)}</span>
27735
- <h2>${escapeHtml41(event.label)}</h2>
27736
- <p>${escapeHtml41(new Date(event.at).toLocaleString())}${event.sessionId ? ` \xB7 session ${escapeHtml41(event.sessionId)}` : ""}</p>
27737
- ${event.value === undefined ? "" : `<strong>${escapeHtml41(String(event.value))}</strong>`}
27738
- ${event.detail ? `<p>${escapeHtml41(event.detail)}</p>` : ""}
27739
- <div>${event.href ? `<a href="${escapeHtml41(event.href)}">Open source</a>` : ""}${event.action?.href ? `<a href="${escapeHtml41(event.action.href)}">${escapeHtml41(event.action.label)}</a>` : ""}</div>
28118
+ const events = report.events.map((event) => `<article class="${escapeHtml42(event.severity)}">
28119
+ <span>${escapeHtml42(event.severity.toUpperCase())} / ${escapeHtml42(event.category)}</span>
28120
+ <h2>${escapeHtml42(event.label)}</h2>
28121
+ <p>${escapeHtml42(new Date(event.at).toLocaleString())}${event.sessionId ? ` \xB7 session ${escapeHtml42(event.sessionId)}` : ""}</p>
28122
+ ${event.value === undefined ? "" : `<strong>${escapeHtml42(String(event.value))}</strong>`}
28123
+ ${event.detail ? `<p>${escapeHtml42(event.detail)}</p>` : ""}
28124
+ <div>${event.href ? `<a href="${escapeHtml42(event.href)}">Open source</a>` : ""}${event.action?.href ? `<a href="${escapeHtml42(event.action.href)}">${escapeHtml42(event.action.label)}</a>` : ""}</div>
27740
28125
  </article>`).join("");
27741
28126
  const actions = report.actions.map((action) => {
27742
- const label = escapeHtml41(action.label);
27743
- const detail = action.detail ? `<p>${escapeHtml41(action.detail)}</p>` : "";
27744
- const href = action.href ? `<a href="${escapeHtml41(action.href)}">Open target</a>` : "";
27745
- const control = action.method === "POST" ? `<button type="button" data-voice-incident-action="${escapeHtml41(action.id)}" ${action.disabled ? "disabled" : ""}>${label}</button>` : href;
27746
- return `<article class="action"><span>${escapeHtml41(action.method ?? "GET")}</span><h2>${label}</h2>${detail}<div>${control}${href && action.method === "POST" ? href : ""}</div></article>`;
28127
+ const label = escapeHtml42(action.label);
28128
+ const detail = action.detail ? `<p>${escapeHtml42(action.detail)}</p>` : "";
28129
+ const href = action.href ? `<a href="${escapeHtml42(action.href)}">Open target</a>` : "";
28130
+ const control = action.method === "POST" ? `<button type="button" data-voice-incident-action="${escapeHtml42(action.id)}" ${action.disabled ? "disabled" : ""}>${label}</button>` : href;
28131
+ return `<article class="action"><span>${escapeHtml42(action.method ?? "GET")}</span><h2>${label}</h2>${detail}<div>${control}${href && action.method === "POST" ? href : ""}</div></article>`;
27747
28132
  }).join("");
27748
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(title)}</title><style>body{background:#11110d;color:#faf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero{background:linear-gradient(135deg,rgba(248,113,113,.2),rgba(245,158,11,.13),rgba(34,197,94,.12));border:1px solid #39301d;border-radius:30px;margin-bottom:18px;padding:28px}.eyebrow{color:#fcd34d;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #575030;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.status.pass{border-color:rgba(34,197,94,.65)}.status.warn{border-color:rgba(245,158,11,.75)}.status.fail{border-color:rgba(239,68,68,.85)}.grid{display:grid;gap:14px}.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:0 0 18px}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{background:#181711;border:1px solid #39301d;border-radius:999px;padding:8px 12px}article{background:#181711;border:1px solid #39301d;border-radius:22px;padding:18px}article.critical{border-color:rgba(239,68,68,.85)}article.warn{border-color:rgba(245,158,11,.75)}article.info{border-color:rgba(34,197,94,.55)}article.action{border-color:#5b4a22}article span{color:#fcd34d;font-size:.78rem;font-weight:900;letter-spacing:.08em}article h2{margin:.35rem 0}.muted,article p{color:#cfc5a8}article strong{display:block;font-size:1.3rem;margin:.5rem 0}a{color:#fde68a;margin-right:12px}button{background:#fcd34d;border:0;border-radius:999px;color:#171307;cursor:pointer;font-weight:900;padding:10px 14px}button:disabled{cursor:not-allowed;opacity:.55}</style></head><body><main><section class="hero"><p class="eyebrow">Operational triage</p><h1>${escapeHtml41(title)}</h1><p class="status ${escapeHtml41(report.status)}">Overall: ${escapeHtml41(report.status.toUpperCase())}</p><p class="muted">Generated ${escapeHtml41(new Date(report.generatedAt).toLocaleString())}</p><div class="summary"><span>${String(report.summary.critical)} critical</span><span>${String(report.summary.warn)} warn</span><span>${String(report.summary.info)} info</span><span>${String(report.summary.total)} total</span></div></section><h2>Recovery actions</h2><section class="actions">${actions || '<article class="action"><span>NONE</span><h2>No recovery actions</h2><p>No executable actions are available for this report.</p></article>'}</section><h2>Timeline</h2><section class="grid">${events || '<article class="info"><span>INFO</span><h2>No incident events</h2><p>No non-pass operational events were found in this window.</p></article>'}</section></main><script>const voiceIncidentActionPath=${JSON.stringify(actionPath)};document.querySelectorAll("[data-voice-incident-action]").forEach((button)=>{button.addEventListener("click",async()=>{const id=button.getAttribute("data-voice-incident-action");if(!id)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(voiceIncidentActionPath+"/"+encodeURIComponent(id),{method:"POST"});button.textContent=response.ok?"Done":"Failed";if(response.ok)setTimeout(()=>location.reload(),700)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1600)}})});</script></body></html>`;
28133
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#11110d;color:#faf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero{background:linear-gradient(135deg,rgba(248,113,113,.2),rgba(245,158,11,.13),rgba(34,197,94,.12));border:1px solid #39301d;border-radius:30px;margin-bottom:18px;padding:28px}.eyebrow{color:#fcd34d;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #575030;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.status.pass{border-color:rgba(34,197,94,.65)}.status.warn{border-color:rgba(245,158,11,.75)}.status.fail{border-color:rgba(239,68,68,.85)}.grid{display:grid;gap:14px}.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:0 0 18px}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{background:#181711;border:1px solid #39301d;border-radius:999px;padding:8px 12px}article{background:#181711;border:1px solid #39301d;border-radius:22px;padding:18px}article.critical{border-color:rgba(239,68,68,.85)}article.warn{border-color:rgba(245,158,11,.75)}article.info{border-color:rgba(34,197,94,.55)}article.action{border-color:#5b4a22}article span{color:#fcd34d;font-size:.78rem;font-weight:900;letter-spacing:.08em}article h2{margin:.35rem 0}.muted,article p{color:#cfc5a8}article strong{display:block;font-size:1.3rem;margin:.5rem 0}a{color:#fde68a;margin-right:12px}button{background:#fcd34d;border:0;border-radius:999px;color:#171307;cursor:pointer;font-weight:900;padding:10px 14px}button:disabled{cursor:not-allowed;opacity:.55}</style></head><body><main><section class="hero"><p class="eyebrow">Operational triage</p><h1>${escapeHtml42(title)}</h1><p class="status ${escapeHtml42(report.status)}">Overall: ${escapeHtml42(report.status.toUpperCase())}</p><p class="muted">Generated ${escapeHtml42(new Date(report.generatedAt).toLocaleString())}</p><div class="summary"><span>${String(report.summary.critical)} critical</span><span>${String(report.summary.warn)} warn</span><span>${String(report.summary.info)} info</span><span>${String(report.summary.total)} total</span></div></section><h2>Recovery actions</h2><section class="actions">${actions || '<article class="action"><span>NONE</span><h2>No recovery actions</h2><p>No executable actions are available for this report.</p></article>'}</section><h2>Timeline</h2><section class="grid">${events || '<article class="info"><span>INFO</span><h2>No incident events</h2><p>No non-pass operational events were found in this window.</p></article>'}</section></main><script>const voiceIncidentActionPath=${JSON.stringify(actionPath)};document.querySelectorAll("[data-voice-incident-action]").forEach((button)=>{button.addEventListener("click",async()=>{const id=button.getAttribute("data-voice-incident-action");if(!id)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(voiceIncidentActionPath+"/"+encodeURIComponent(id),{method:"POST"});button.textContent=response.ok?"Done":"Failed";if(response.ok)setTimeout(()=>location.reload(),700)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1600)}})});</script></body></html>`;
27749
28134
  };
27750
28135
  var createVoiceIncidentTimelineRoutes = (options) => {
27751
28136
  const path = options.path ?? "/api/voice/incident-timeline";
@@ -27765,7 +28150,7 @@ var createVoiceIncidentTimelineRoutes = (options) => {
27765
28150
  })
27766
28151
  ]);
27767
28152
  };
27768
- const routes = new Elysia43({
28153
+ const routes = new Elysia44({
27769
28154
  name: options.name ?? "absolutejs-voice-incident-timeline"
27770
28155
  }).get(path, async () => {
27771
28156
  const report = await buildVoiceIncidentTimelineReport(options);
@@ -27957,7 +28342,7 @@ var createVoiceIncidentTimelineRoutes = (options) => {
27957
28342
  };
27958
28343
 
27959
28344
  // src/observabilityExport.ts
27960
- import { Elysia as Elysia44 } from "elysia";
28345
+ import { Elysia as Elysia45 } from "elysia";
27961
28346
  import { Database as Database4 } from "bun:sqlite";
27962
28347
  import { createHash } from "crypto";
27963
28348
  import { mkdir as mkdir2, readFile, stat, unlink } from "fs/promises";
@@ -28622,7 +29007,7 @@ var createVoiceObservabilityExportReplayRoutes = (options) => {
28622
29007
  ...options.headers ?? {}
28623
29008
  };
28624
29009
  const buildReport = () => resolveVoiceObservabilityExportReplayReport(options.source);
28625
- const app = new Elysia44({
29010
+ const app = new Elysia45({
28626
29011
  name: options.name ?? "absolute-voice-observability-export-replay"
28627
29012
  });
28628
29013
  app.get(path, async () => Response.json(await buildReport(), { headers }));
@@ -29488,7 +29873,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
29488
29873
  artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
29489
29874
  }
29490
29875
  });
29491
- const app = new Elysia44({
29876
+ const app = new Elysia45({
29492
29877
  name: options.name ?? "absolute-voice-observability-export"
29493
29878
  });
29494
29879
  app.get(path, async () => Response.json(await buildReport(), { headers }));
@@ -29595,7 +29980,7 @@ var buildVoiceReadinessRecoveryActions = (input, options = {}) => {
29595
29980
  sourceChecks: sourceChecks.length
29596
29981
  };
29597
29982
  };
29598
- var escapeHtml42 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29983
+ var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
29599
29984
  var formatVoiceProofFreshnessDuration = (valueMs) => {
29600
29985
  if (valueMs < 1000) {
29601
29986
  return `${Math.max(0, Math.round(valueMs))}ms`;
@@ -29795,6 +30180,7 @@ var readinessGateCodes = {
29795
30180
  "Reconnect recovery contracts": "voice.readiness.reconnect_contracts",
29796
30181
  "Routing evidence": "voice.readiness.routing_evidence",
29797
30182
  "Session health": "voice.readiness.session_health",
30183
+ "Session observability evidence": "voice.readiness.session_observability_evidence",
29798
30184
  "Trace sink delivery": "voice.readiness.trace_sink_delivery"
29799
30185
  };
29800
30186
  var readinessGateCodeForCheck = (check) => readinessGateCodes[check.label] ?? `voice.readiness.${check.label.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "")}`;
@@ -29960,6 +30346,18 @@ var resolveMonitoringNotifierDelivery = async (options, input) => {
29960
30346
  }
29961
30347
  return typeof options.monitoringNotifierDelivery === "function" ? await options.monitoringNotifierDelivery(input) : options.monitoringNotifierDelivery;
29962
30348
  };
30349
+ var resolveSessionObservability = async (options, input) => {
30350
+ if (options.sessionObservability === false || options.sessionObservability === undefined) {
30351
+ return;
30352
+ }
30353
+ return typeof options.sessionObservability === "function" ? await options.sessionObservability(input) : options.sessionObservability;
30354
+ };
30355
+ var resolveSessionObservabilityEvidence = async (options, input) => {
30356
+ if (options.sessionObservabilityEvidence === false || options.sessionObservabilityEvidence === undefined) {
30357
+ return;
30358
+ }
30359
+ return typeof options.sessionObservabilityEvidence === "function" ? await options.sessionObservabilityEvidence(input) : options.sessionObservabilityEvidence;
30360
+ };
29963
30361
  var resolveMediaPipeline = async (options, input) => {
29964
30362
  if (options.mediaPipeline === false || options.mediaPipeline === undefined) {
29965
30363
  return;
@@ -30481,6 +30879,8 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30481
30879
  mediaPipeline,
30482
30880
  browserMedia,
30483
30881
  telephonyMedia,
30882
+ sessionObservability,
30883
+ sessionObservabilityEvidence,
30484
30884
  telephonyWebhookSecurity,
30485
30885
  reconnectContracts,
30486
30886
  bargeInReports,
@@ -30530,6 +30930,8 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30530
30930
  time("mediaPipeline", () => resolveMediaPipeline(options, { query, request })),
30531
30931
  time("browserMedia", () => resolveBrowserMedia(options, { query, request })),
30532
30932
  time("telephonyMedia", () => resolveTelephonyMedia(options, { query, request })),
30933
+ time("sessionObservability", () => resolveSessionObservability(options, { query, request })),
30934
+ time("sessionObservabilityEvidence", () => resolveSessionObservabilityEvidence(options, { query, request })),
30533
30935
  time("telephonyWebhookSecurity", () => resolveTelephonyWebhookSecurity(options, { query, request })),
30534
30936
  time("reconnectContracts", () => resolveReconnectContracts(options, { query, request })),
30535
30937
  time("bargeInReports", () => resolveBargeInReports(options, { query, request })),
@@ -30573,6 +30975,15 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30573
30975
  warnWhenEmpty: options.incidentRecoveryTrendSLO?.warnWhenEmpty,
30574
30976
  mode: options.incidentRecoveryTrendSLO?.mode
30575
30977
  }) : undefined;
30978
+ const sessionObservabilityEvidenceSummary = sessionObservability ? evaluateVoiceSessionObservabilityEvidence(sessionObservability, sessionObservabilityEvidence ?? {}) : undefined;
30979
+ const sessionObservabilitySummary = sessionObservability && sessionObservabilityEvidenceSummary ? {
30980
+ failed: sessionObservabilityEvidenceSummary.status === "fail" ? 1 : 0,
30981
+ passed: sessionObservabilityEvidenceSummary.status === "pass" ? 1 : 0,
30982
+ status: sessionObservabilityEvidenceSummary.status,
30983
+ total: 1,
30984
+ warnings: sessionObservabilityEvidenceSummary.status === "warn" ? 1 : 0
30985
+ } : undefined;
30986
+ const proofSource = (...keys) => keys.map((key) => proofSources?.[key]).find((source) => source !== undefined);
30576
30987
  const checks = [
30577
30988
  {
30578
30989
  detail: quality.status === "pass" ? "Quality gates are passing." : "Quality gates need attention.",
@@ -30693,6 +31104,23 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30693
31104
  }
30694
31105
  ] : []
30695
31106
  },
31107
+ ...sessionObservability && sessionObservabilitySummary ? [
31108
+ {
31109
+ detail: sessionObservabilitySummary.status === "pass" ? `Session observability is healthy with ${sessionObservabilityEvidenceSummary?.summary.turnsWithWaterfalls ?? 0} turn(s) containing waterfall stages and ${sessionObservabilityEvidenceSummary?.summary.providerDecisions ?? 0} provider decision stage(s).` : `${sessionObservabilityEvidenceSummary?.issues.join("; ") ?? "Session observability has unresolved issues."}`,
31110
+ href: options.links?.sessionObservability ?? "/voice/session-observability",
31111
+ label: "Session observability evidence",
31112
+ proofSource: proofSource("sessionObservability", "sessionObservability"),
31113
+ status: sessionObservabilitySummary.status,
31114
+ value: `${sessionObservabilitySummary.passed}/${sessionObservabilitySummary.total}`,
31115
+ actions: sessionObservabilitySummary.status === "pass" ? [] : [
31116
+ {
31117
+ description: "Open session observability report and address missing turns, provider decisions, tool calls, links, and incident markdown coverage.",
31118
+ href: options.links?.sessionObservability ?? "/voice/session-observability",
31119
+ label: "Open session observability"
31120
+ }
31121
+ ]
31122
+ }
31123
+ ] : [],
30696
31124
  {
30697
31125
  detail: routingEvents.length > 0 ? `${routingSessions.length} session(s) have provider routing evidence.` : "No provider routing traces are recorded yet.",
30698
31126
  href: options.links?.resilience ?? "/resilience",
@@ -30709,7 +31137,6 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30709
31137
  }
30710
31138
  ];
30711
31139
  checks.push(...additionalChecks);
30712
- const proofSource = (...keys) => keys.map((key) => proofSources?.[key]).find((source) => source !== undefined);
30713
31140
  const calibratedThresholdActions = () => options.links?.sloReadinessThresholds ? [
30714
31141
  {
30715
31142
  description: "Open the calibrated thresholds currently driving this readiness gate.",
@@ -31556,6 +31983,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
31556
31983
  profileSwitchLiveDecisions: "/voice/profile-switch-live-decisions",
31557
31984
  profileSwitchPolicy: "/voice/profile-switch-policy",
31558
31985
  profileSwitchReadiness: "/voice/profile-switch-readiness",
31986
+ sessionObservability: "/voice/session-observability",
31559
31987
  telephonyMedia: "/voice/telephony-media",
31560
31988
  telephonyWebhookSecurity: "/api/voice/telephony/webhook-security",
31561
31989
  providerContracts: "/provider-contracts",
@@ -31626,6 +32054,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
31626
32054
  providerRoutingContracts: providerRoutingContractSummary,
31627
32055
  providerSlo: providerSloSummary,
31628
32056
  reconnectContracts: reconnectContractSummary,
32057
+ sessionObservability: sessionObservabilitySummary,
31629
32058
  quality: {
31630
32059
  status: quality.status
31631
32060
  },
@@ -31644,25 +32073,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
31644
32073
  var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
31645
32074
  var renderVoiceProductionReadinessHTML = (report, options = {}) => {
31646
32075
  const title = options.title ?? "AbsoluteJS Voice Production Readiness";
31647
- const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml42(report.links.sloReadinessThresholds)}">Open Calibration -&gt; Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
31648
- const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml42(report.profile.name)}</h2><p>${escapeHtml42(report.profile.description)}</p><p>${escapeHtml42(report.profile.purpose)}</p><div class="profile-surfaces">${report.profile.surfaces.map((surface) => `<article class="${surface.configured ? "pass" : "warn"}"><span>${surface.configured ? "CONFIGURED" : "EXPECTED"}</span><strong>${surface.href ? `<a href="${escapeHtml42(surface.href)}">${escapeHtml42(surface.label)}</a>` : escapeHtml42(surface.label)}</strong></article>`).join("")}</div></section>` : "";
32076
+ const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml43(report.links.sloReadinessThresholds)}">Open Calibration -&gt; Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
32077
+ const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml43(report.profile.name)}</h2><p>${escapeHtml43(report.profile.description)}</p><p>${escapeHtml43(report.profile.purpose)}</p><div class="profile-surfaces">${report.profile.surfaces.map((surface) => `<article class="${surface.configured ? "pass" : "warn"}"><span>${surface.configured ? "CONFIGURED" : "EXPECTED"}</span><strong>${surface.href ? `<a href="${escapeHtml43(surface.href)}">${escapeHtml43(surface.label)}</a>` : escapeHtml43(surface.label)}</strong></article>`).join("")}</div></section>` : "";
31649
32078
  const checks = report.checks.map((check, index) => {
31650
- const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml42(action.href)}">${escapeHtml42(action.label)}</button>` : `<a href="${escapeHtml42(action.href)}">${escapeHtml42(action.label)}</a>`).join("");
31651
- const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml42(check.status)}: observed ${escapeHtml42(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml42(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml42(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml42(check.gateExplanation.unit)}` : ""}. ${escapeHtml42(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml42(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
31652
- return `<article class="check ${escapeHtml42(check.status)}">
32079
+ const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml43(action.href)}">${escapeHtml43(action.label)}</button>` : `<a href="${escapeHtml43(action.href)}">${escapeHtml43(action.label)}</a>`).join("");
32080
+ const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml43(check.status)}: observed ${escapeHtml43(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml43(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml43(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml43(check.gateExplanation.unit)}` : ""}. ${escapeHtml43(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml43(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
32081
+ return `<article class="check ${escapeHtml43(check.status)}">
31653
32082
  <div>
31654
- <span>${escapeHtml42(check.status.toUpperCase())}</span>
31655
- <h2>${escapeHtml42(check.label)}</h2>
31656
- ${check.detail ? `<p>${escapeHtml42(check.detail)}</p>` : ""}
32083
+ <span>${escapeHtml43(check.status.toUpperCase())}</span>
32084
+ <h2>${escapeHtml43(check.label)}</h2>
32085
+ ${check.detail ? `<p>${escapeHtml43(check.detail)}</p>` : ""}
31657
32086
  ${explanation}
31658
- ${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml42(check.proofSource.href)}">${escapeHtml42(check.proofSource.sourceLabel)}</a>` : escapeHtml42(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml42(check.proofSource.detail)}` : ""}</p>` : ""}
32087
+ ${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml43(check.proofSource.href)}">${escapeHtml43(check.proofSource.sourceLabel)}</a>` : escapeHtml43(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml43(check.proofSource.detail)}` : ""}</p>` : ""}
31659
32088
  ${actions ? `<p class="actions">${actions}</p>` : ""}
31660
32089
  </div>
31661
- <strong>${escapeHtml42(String(check.value ?? check.status))}</strong>
31662
- ${check.href ? `<a href="${escapeHtml42(check.href)}">Open surface</a>` : ""}
32090
+ <strong>${escapeHtml43(String(check.value ?? check.status))}</strong>
32091
+ ${check.href ? `<a href="${escapeHtml43(check.href)}">Open surface</a>` : ""}
31663
32092
  </article>`;
31664
32093
  }).join("");
31665
- const snippet = escapeHtml42(`createVoiceProductionReadinessRoutes({
32094
+ const snippet = escapeHtml43(`createVoiceProductionReadinessRoutes({
31666
32095
  htmlPath: '/production-readiness',
31667
32096
  path: '/api/production-readiness',
31668
32097
  gatePath: '/api/production-readiness/gate',
@@ -31678,13 +32107,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
31678
32107
  providerRoutingContracts: loadProviderRoutingContracts,
31679
32108
  store: traceStore
31680
32109
  });`);
31681
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero,.primitive,.profile{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.primitive,.profile{background:#111722}.primitive{border-color:#3a3f2d}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{display:inline-flex;border:1px solid #3f3f46;border-radius:999px;padding:8px 12px}.primitive code{color:#fde68a}.primitive p{color:#c8ccd3;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#0b0f16;border:1px solid #2c3440;border-radius:18px;color:#fef3c7;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.check.pass,.profile-surfaces .pass{border-color:rgba(34,197,94,.55)}.status.warn,.check.warn,.profile-surfaces .warn{border-color:rgba(245,158,11,.65)}.status.fail,.check.fail{border-color:rgba(239,68,68,.75)}.checks{display:grid;gap:14px}.check{align-items:center;background:#141922;border:1px solid #26313d;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto auto;padding:18px}.check span,.profile-surfaces span{color:#a8b0b8;font-size:.78rem;font-weight:900;letter-spacing:.08em}.check h2{margin:.2rem 0}.check p,.profile p{color:#b9c0c8;margin:.2rem 0 0}.check .proof-source{color:#f9d77e;font-weight:800}.check .gate-explanation{background:#0b0f16;border:1px solid #2c3440;border-radius:14px;color:#fef3c7;margin-top:10px;padding:10px}.check strong{font-size:1.5rem}.profile-surfaces{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin-top:16px}.profile-surfaces article{background:#141922;border:1px solid #26313d;border-radius:16px;padding:14px}.profile-surfaces strong{display:block;margin-top:6px}.actions{display:flex;flex-wrap:wrap;gap:10px}.check a,a{color:#fbbf24}button{background:#fbbf24;border:0;border-radius:999px;color:#111827;cursor:pointer;font-weight:800;padding:9px 12px}button:disabled{cursor:wait;opacity:.65}@media(max-width:760px){main{padding:20px}.check{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted readiness</p><h1>${escapeHtml42(title)}</h1><p>One deployable pass/fail report for quality gates, provider failover, session health, handoffs, routing evidence, and optional carrier readiness.</p><p class="status ${escapeHtml42(report.status)}">Overall: ${escapeHtml42(report.status.toUpperCase())}</p><p>Checked ${escapeHtml42(new Date(report.checkedAt).toLocaleString())}</p>${thresholdLink}</section>${profile}<section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProductionReadinessRoutes(...)</code> builds this deploy gate</h2><p>Mount one package primitive to expose JSON readiness, HTML readiness, and a machine-readable gate route. Feed it the proof stores and contract reports your app already owns.</p><pre><code>${snippet}</code></pre></section><section class="checks">${checks}</section></main><script>document.querySelectorAll("[data-readiness-action]").forEach((button)=>{button.addEventListener("click",async()=>{const url=button.getAttribute("data-action-url");if(!url)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(url,{method:"POST"});button.textContent=response.ok?"Done. Reloading...":"Failed";if(response.ok)setTimeout(()=>location.reload(),500)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1500)}})});</script></body></html>`;
32110
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero,.primitive,.profile{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.primitive,.profile{background:#111722}.primitive{border-color:#3a3f2d}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{display:inline-flex;border:1px solid #3f3f46;border-radius:999px;padding:8px 12px}.primitive code{color:#fde68a}.primitive p{color:#c8ccd3;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#0b0f16;border:1px solid #2c3440;border-radius:18px;color:#fef3c7;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.check.pass,.profile-surfaces .pass{border-color:rgba(34,197,94,.55)}.status.warn,.check.warn,.profile-surfaces .warn{border-color:rgba(245,158,11,.65)}.status.fail,.check.fail{border-color:rgba(239,68,68,.75)}.checks{display:grid;gap:14px}.check{align-items:center;background:#141922;border:1px solid #26313d;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto auto;padding:18px}.check span,.profile-surfaces span{color:#a8b0b8;font-size:.78rem;font-weight:900;letter-spacing:.08em}.check h2{margin:.2rem 0}.check p,.profile p{color:#b9c0c8;margin:.2rem 0 0}.check .proof-source{color:#f9d77e;font-weight:800}.check .gate-explanation{background:#0b0f16;border:1px solid #2c3440;border-radius:14px;color:#fef3c7;margin-top:10px;padding:10px}.check strong{font-size:1.5rem}.profile-surfaces{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin-top:16px}.profile-surfaces article{background:#141922;border:1px solid #26313d;border-radius:16px;padding:14px}.profile-surfaces strong{display:block;margin-top:6px}.actions{display:flex;flex-wrap:wrap;gap:10px}.check a,a{color:#fbbf24}button{background:#fbbf24;border:0;border-radius:999px;color:#111827;cursor:pointer;font-weight:800;padding:9px 12px}button:disabled{cursor:wait;opacity:.65}@media(max-width:760px){main{padding:20px}.check{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted readiness</p><h1>${escapeHtml43(title)}</h1><p>One deployable pass/fail report for quality gates, provider failover, session health, handoffs, routing evidence, and optional carrier readiness.</p><p class="status ${escapeHtml43(report.status)}">Overall: ${escapeHtml43(report.status.toUpperCase())}</p><p>Checked ${escapeHtml43(new Date(report.checkedAt).toLocaleString())}</p>${thresholdLink}</section>${profile}<section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProductionReadinessRoutes(...)</code> builds this deploy gate</h2><p>Mount one package primitive to expose JSON readiness, HTML readiness, and a machine-readable gate route. Feed it the proof stores and contract reports your app already owns.</p><pre><code>${snippet}</code></pre></section><section class="checks">${checks}</section></main><script>document.querySelectorAll("[data-readiness-action]").forEach((button)=>{button.addEventListener("click",async()=>{const url=button.getAttribute("data-action-url");if(!url)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(url,{method:"POST"});button.textContent=response.ok?"Done. Reloading...":"Failed";if(response.ok)setTimeout(()=>location.reload(),500)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1500)}})});</script></body></html>`;
31682
32111
  };
31683
32112
  var createVoiceProductionReadinessRoutes = (options) => {
31684
32113
  const path = options.path ?? "/api/production-readiness";
31685
32114
  const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
31686
32115
  const htmlPath = options.htmlPath ?? "/production-readiness";
31687
- const routes = new Elysia45({
32116
+ const routes = new Elysia46({
31688
32117
  name: options.name ?? "absolutejs-voice-production-readiness"
31689
32118
  });
31690
32119
  let cachedReport;
@@ -31756,7 +32185,7 @@ var createVoiceProductionReadinessRoutes = (options) => {
31756
32185
  };
31757
32186
 
31758
32187
  // src/operationalStatus.ts
31759
- var escapeHtml43 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
32188
+ var escapeHtml44 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
31760
32189
  var resolveValue2 = async (value) => typeof value === "function" ? await value() : value;
31761
32190
  var isDeliveryRuntime = (value) => Boolean(value && typeof value === "object" && "isRunning" in value && "summarize" in value);
31762
32191
  var worstStatus3 = (statuses) => statuses.includes("fail") ? "fail" : statuses.includes("warn") ? "warn" : "pass";
@@ -31826,19 +32255,19 @@ var buildVoiceOperationalStatusReport = async (options) => {
31826
32255
  };
31827
32256
  var renderVoiceOperationalStatusHTML = (report, options = {}) => {
31828
32257
  const title = options.title ?? "AbsoluteJS Voice Operational Status";
31829
- const checks = report.checks.map((check) => `<article class="${escapeHtml43(check.status)}">
31830
- <span>${escapeHtml43(check.status.toUpperCase())}</span>
31831
- <h2>${escapeHtml43(check.label)}</h2>
31832
- <strong>${escapeHtml43(String(check.value ?? check.status))}</strong>
31833
- ${check.detail ? `<p>${escapeHtml43(check.detail)}</p>` : ""}
31834
- ${check.href ? `<a href="${escapeHtml43(check.href)}">Open surface</a>` : ""}
32258
+ const checks = report.checks.map((check) => `<article class="${escapeHtml44(check.status)}">
32259
+ <span>${escapeHtml44(check.status.toUpperCase())}</span>
32260
+ <h2>${escapeHtml44(check.label)}</h2>
32261
+ <strong>${escapeHtml44(String(check.value ?? check.status))}</strong>
32262
+ ${check.detail ? `<p>${escapeHtml44(check.detail)}</p>` : ""}
32263
+ ${check.href ? `<a href="${escapeHtml44(check.href)}">Open surface</a>` : ""}
31835
32264
  </article>`).join("");
31836
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(title)}</title><style>body{background:#10130f;color:#f8f3df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1040px;padding:32px}.hero{background:linear-gradient(135deg,rgba(132,204,22,.18),rgba(14,165,233,.13));border:1px solid #2c3a28;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#bef264;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}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}article{background:#171d15;border:1px solid #2c3a28;border-radius:22px;padding:18px}article.pass{border-color:rgba(34,197,94,.65)}article.warn{border-color:rgba(245,158,11,.75)}article.fail{border-color:rgba(239,68,68,.85)}article span{color:#bef264;font-size:.78rem;font-weight:900;letter-spacing:.08em}article.warn span{color:#fbbf24}article.fail span{color:#fca5a5}article strong{display:block;font-size:1.6rem;margin:.4rem 0}article p{color:#c5ceb9}a{color:#bef264}</style></head><body><main><section class="hero"><p class="eyebrow">Operational status</p><h1>${escapeHtml43(title)}</h1><p class="status ${escapeHtml43(report.status)}">Overall: ${escapeHtml43(report.status.toUpperCase())}</p><p>${String(report.summary.pass)}/${String(report.summary.total)} checks passing. Checked ${escapeHtml43(new Date(report.checkedAt).toLocaleString())}.</p></section><section class="grid">${checks || '<article class="pass"><span>PASS</span><h2>No operational checks configured</h2><strong>0/0</strong></article>'}</section></main></body></html>`;
32265
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml44(title)}</title><style>body{background:#10130f;color:#f8f3df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1040px;padding:32px}.hero{background:linear-gradient(135deg,rgba(132,204,22,.18),rgba(14,165,233,.13));border:1px solid #2c3a28;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#bef264;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}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}article{background:#171d15;border:1px solid #2c3a28;border-radius:22px;padding:18px}article.pass{border-color:rgba(34,197,94,.65)}article.warn{border-color:rgba(245,158,11,.75)}article.fail{border-color:rgba(239,68,68,.85)}article span{color:#bef264;font-size:.78rem;font-weight:900;letter-spacing:.08em}article.warn span{color:#fbbf24}article.fail span{color:#fca5a5}article strong{display:block;font-size:1.6rem;margin:.4rem 0}article p{color:#c5ceb9}a{color:#bef264}</style></head><body><main><section class="hero"><p class="eyebrow">Operational status</p><h1>${escapeHtml44(title)}</h1><p class="status ${escapeHtml44(report.status)}">Overall: ${escapeHtml44(report.status.toUpperCase())}</p><p>${String(report.summary.pass)}/${String(report.summary.total)} checks passing. Checked ${escapeHtml44(new Date(report.checkedAt).toLocaleString())}.</p></section><section class="grid">${checks || '<article class="pass"><span>PASS</span><h2>No operational checks configured</h2><strong>0/0</strong></article>'}</section></main></body></html>`;
31837
32266
  };
31838
32267
  var createVoiceOperationalStatusRoutes = (options) => {
31839
32268
  const path = options.path ?? "/api/voice/operational-status";
31840
32269
  const htmlPath = options.htmlPath === undefined ? "/voice/operational-status" : options.htmlPath;
31841
- const routes = new Elysia46({
32270
+ const routes = new Elysia47({
31842
32271
  name: options.name ?? "absolutejs-voice-operational-status"
31843
32272
  }).get(path, async () => {
31844
32273
  const report = await buildVoiceOperationalStatusReport(options);
@@ -31865,7 +32294,7 @@ var createVoiceOperationalStatusRoutes = (options) => {
31865
32294
  return routes;
31866
32295
  };
31867
32296
  // src/dataControl.ts
31868
- import { Elysia as Elysia47 } from "elysia";
32297
+ import { Elysia as Elysia48 } from "elysia";
31869
32298
  var voiceComplianceRedactionDefaults = {
31870
32299
  keys: [
31871
32300
  "apiKey",
@@ -32104,7 +32533,7 @@ var parseRetentionScopes = (value) => {
32104
32533
  const allowed = new Set(allRetentionScopes);
32105
32534
  return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
32106
32535
  };
32107
- var escapeHtml44 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
32536
+ var escapeHtml45 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
32108
32537
  var buildStorageSurfaces = (options) => [
32109
32538
  {
32110
32539
  configured: Boolean(options.session ?? options.sessions),
@@ -32341,12 +32770,12 @@ var buildVoiceDataControlReport = async (options) => {
32341
32770
  zeroRetentionAvailable: true
32342
32771
  };
32343
32772
  };
32344
- var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml44(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml44(scope.skippedReason ?? "")}</td><td><code>${escapeHtml44(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
32773
+ var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml45(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml45(scope.skippedReason ?? "")}</td><td><code>${escapeHtml45(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
32345
32774
  var renderVoiceDataControlHTML = (report, options = {}) => {
32346
32775
  const title = options.title ?? "Voice Data Control";
32347
- const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml44(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml44(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
32348
- const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml44(key.name)}</td><td><code>${escapeHtml44(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml44(key.recommendation)}</td></tr>`).join("");
32349
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml44(title)}</title><style>body{background:#f8f7f2;color:#181713;font-family:ui-sans-serif,system-ui,sans-serif;line-height:1.45;margin:2rem}main{max-width:1120px;margin:auto}.summary{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card,table{background:white;border:1px solid #ddd6c8;border-radius:14px}.card{padding:1rem}table{border-collapse:collapse;width:100%;overflow:hidden}td,th{border-bottom:1px solid #eee8dc;padding:.7rem;text-align:left;vertical-align:top}code{white-space:pre-wrap;word-break:break-word}a{color:#9a3412}</style></head><body><main><h1>${escapeHtml44(title)}</h1><p>Self-hosted data-control proof for retention, redaction, audit export, deletion planning, customer-owned storage, and provider key handling.</p><section class="summary"><div class="card"><strong>Redaction</strong><br>${report.redaction.enabled ? "enabled" : "disabled"}</div><div class="card"><strong>Retention dry-run deletes</strong><br>${report.retentionPlan.deletedCount}</div><div class="card"><strong>Audit export events</strong><br>${report.auditExport?.events.length ?? 0}</div><div class="card"><strong>Zero retention recipe</strong><br>${report.zeroRetentionAvailable ? "available" : "missing"}</div></section><h2>Customer-Owned Storage</h2><table><thead><tr><th>Surface</th><th>Status</th><th>Control</th><th>Self-hosted</th></tr></thead><tbody>${storageRows}</tbody></table><h2>Retention Plan</h2><table><thead><tr><th>Scope</th><th>Scanned</th><th>Would delete</th><th>Skipped</th><th>Ids</th></tr></thead><tbody>${renderDataRetentionReportRows(report.retentionPlan)}</tbody></table><h2>Provider Keys</h2><table><thead><tr><th>Provider</th><th>Env</th><th>Required</th><th>Recommendation</th></tr></thead><tbody>${keyRows}</tbody></table><p><a href="./data-control/audit.md">Redacted audit Markdown</a> \xB7 <a href="./data-control/audit.html">Redacted audit HTML</a></p></main></body></html>`;
32776
+ const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml45(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml45(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
32777
+ const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml45(key.name)}</td><td><code>${escapeHtml45(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml45(key.recommendation)}</td></tr>`).join("");
32778
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{background:#f8f7f2;color:#181713;font-family:ui-sans-serif,system-ui,sans-serif;line-height:1.45;margin:2rem}main{max-width:1120px;margin:auto}.summary{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card,table{background:white;border:1px solid #ddd6c8;border-radius:14px}.card{padding:1rem}table{border-collapse:collapse;width:100%;overflow:hidden}td,th{border-bottom:1px solid #eee8dc;padding:.7rem;text-align:left;vertical-align:top}code{white-space:pre-wrap;word-break:break-word}a{color:#9a3412}</style></head><body><main><h1>${escapeHtml45(title)}</h1><p>Self-hosted data-control proof for retention, redaction, audit export, deletion planning, customer-owned storage, and provider key handling.</p><section class="summary"><div class="card"><strong>Redaction</strong><br>${report.redaction.enabled ? "enabled" : "disabled"}</div><div class="card"><strong>Retention dry-run deletes</strong><br>${report.retentionPlan.deletedCount}</div><div class="card"><strong>Audit export events</strong><br>${report.auditExport?.events.length ?? 0}</div><div class="card"><strong>Zero retention recipe</strong><br>${report.zeroRetentionAvailable ? "available" : "missing"}</div></section><h2>Customer-Owned Storage</h2><table><thead><tr><th>Surface</th><th>Status</th><th>Control</th><th>Self-hosted</th></tr></thead><tbody>${storageRows}</tbody></table><h2>Retention Plan</h2><table><thead><tr><th>Scope</th><th>Scanned</th><th>Would delete</th><th>Skipped</th><th>Ids</th></tr></thead><tbody>${renderDataRetentionReportRows(report.retentionPlan)}</tbody></table><h2>Provider Keys</h2><table><thead><tr><th>Provider</th><th>Env</th><th>Required</th><th>Recommendation</th></tr></thead><tbody>${keyRows}</tbody></table><p><a href="./data-control/audit.md">Redacted audit Markdown</a> \xB7 <a href="./data-control/audit.html">Redacted audit HTML</a></p></main></body></html>`;
32350
32779
  };
32351
32780
  var renderVoiceDataControlMarkdown = (report, options = {}) => [
32352
32781
  `# ${options.title ?? "Voice Data Control"}`,
@@ -32404,7 +32833,7 @@ var parseRetentionPolicyBody = (body, options, dryRun) => {
32404
32833
  var createVoiceDataControlRoutes = (options) => {
32405
32834
  const path = options.path ?? "/data-control";
32406
32835
  const title = options.title ?? "AbsoluteJS Voice Data Control";
32407
- const routes = new Elysia47({
32836
+ const routes = new Elysia48({
32408
32837
  name: options.name ?? "absolutejs-voice-data-control"
32409
32838
  });
32410
32839
  routes.get(path, async ({ query }) => {
@@ -32480,10 +32909,10 @@ var createVoiceDataControlRoutes = (options) => {
32480
32909
  return routes;
32481
32910
  };
32482
32911
  // src/evalRoutes.ts
32483
- import { Elysia as Elysia48 } from "elysia";
32912
+ import { Elysia as Elysia49 } from "elysia";
32484
32913
  import { mkdir as mkdir3 } from "fs/promises";
32485
32914
  import { dirname as dirname2 } from "path";
32486
- var escapeHtml45 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
32915
+ var escapeHtml46 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
32487
32916
  var rate4 = (count, total) => count / Math.max(1, total);
32488
32917
  var normalizeSearchText = (value) => value.trim().toLowerCase();
32489
32918
  var getString18 = (value) => typeof value === "string" ? value : undefined;
@@ -32814,7 +33243,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
32814
33243
  var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
32815
33244
  var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
32816
33245
  var renderVoiceEvalPrimitiveCopy = () => {
32817
- const snippet = escapeHtml45(`app.use(
33246
+ const snippet = escapeHtml46(`app.use(
32818
33247
  createVoiceEvalRoutes({
32819
33248
  path: '/evals',
32820
33249
  store: traceStore,
@@ -32835,48 +33264,48 @@ var renderVoiceEvalPrimitiveCopy = () => {
32835
33264
  };
32836
33265
  var renderVoiceEvalHTML = (report, options = {}) => {
32837
33266
  const title = options.title ?? "AbsoluteJS Voice Evals";
32838
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
32839
- const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml45(bucket.key)}</td><td>${bucket.total}</td><td>${bucket.passed}</td><td>${bucket.failed}</td></tr>`).join("") : '<tr><td colspan="4">No eval buckets yet.</td></tr>';
33267
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml46(link.href)}">${escapeHtml46(link.label)}</a>`).join("")}</nav>` : "";
33268
+ const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml46(bucket.key)}</td><td>${bucket.total}</td><td>${bucket.passed}</td><td>${bucket.failed}</td></tr>`).join("") : '<tr><td colspan="4">No eval buckets yet.</td></tr>';
32840
33269
  const sessions = report.sessions.length ? report.sessions.map((session) => {
32841
33270
  const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
32842
- const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml45(session.operationsRecordHref)}">${escapeHtml45(session.sessionId)}</a>` : escapeHtml45(session.sessionId);
32843
- return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml45(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml45(formatTime(session.endedAt))}</td><td>${escapeHtml45(failedMetrics || "none")}</td></tr>`;
33271
+ const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml46(session.operationsRecordHref)}">${escapeHtml46(session.sessionId)}</a>` : escapeHtml46(session.sessionId);
33272
+ return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml46(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml46(formatTime(session.endedAt))}</td><td>${escapeHtml46(failedMetrics || "none")}</td></tr>`;
32844
33273
  }).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
32845
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{color:#166534}.fail{color:#991b1b}.status.pass{background:#dcfce7}.status.fail{background:#fee2e2}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,.primitive{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3;margin:1rem 0}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}table{border-collapse:collapse;background:white;width:100%;margin:1rem 0 2rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml45(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}<h2>Trend</h2><table><thead><tr><th>Day</th><th>Total</th><th>Passed</th><th>Failed</th></tr></thead><tbody>${trend}</tbody></table><h2>Session Eval Results</h2><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Last event</th><th>Failed metrics</th></tr></thead><tbody>${sessions}</tbody></table></main></body></html>`;
33274
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{color:#166534}.fail{color:#991b1b}.status.pass{background:#dcfce7}.status.fail{background:#fee2e2}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,.primitive{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3;margin:1rem 0}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}table{border-collapse:collapse;background:white;width:100%;margin:1rem 0 2rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml46(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}<h2>Trend</h2><table><thead><tr><th>Day</th><th>Total</th><th>Passed</th><th>Failed</th></tr></thead><tbody>${trend}</tbody></table><h2>Session Eval Results</h2><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Last event</th><th>Failed metrics</th></tr></thead><tbody>${sessions}</tbody></table></main></body></html>`;
32846
33275
  };
32847
33276
  var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
32848
33277
  const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
32849
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
32850
- const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml45(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
32851
- const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml45(id)}</li>`).join("") : "<li>none</li>";
32852
- const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml45(id)}</li>`).join("") : "<li>none</li>";
32853
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1000px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{background:#dcfce7;color:#166534}.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.card strong{display:block;font-size:2rem}section{background:white;border:1px solid #e7e5e4;border-radius:1rem;margin:1rem 0;padding:1rem}</style></head><body><main>${links}<h1>${escapeHtml45(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml45(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml45(formatPercent(comparison.current.passRate))}</strong></article><article class="card"><span>Failed delta</span><strong>${comparison.deltas.failed}</strong></article><article class="card"><span>Pass rate delta</span><strong>${escapeHtml45(formatPercent(comparison.deltas.passRate))}</strong></article></div><section><h2>Regression Reasons</h2><ul>${reasons}</ul></section><section><h2>New Failed Sessions</h2><ul>${newFailures}</ul></section><section><h2>Recovered Sessions</h2><ul>${recovered}</ul></section></main></body></html>`;
33278
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml46(link.href)}">${escapeHtml46(link.label)}</a>`).join("")}</nav>` : "";
33279
+ const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml46(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
33280
+ const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml46(id)}</li>`).join("") : "<li>none</li>";
33281
+ const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml46(id)}</li>`).join("") : "<li>none</li>";
33282
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1000px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{background:#dcfce7;color:#166534}.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.card strong{display:block;font-size:2rem}section{background:white;border:1px solid #e7e5e4;border-radius:1rem;margin:1rem 0;padding:1rem}</style></head><body><main>${links}<h1>${escapeHtml46(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml46(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml46(formatPercent(comparison.current.passRate))}</strong></article><article class="card"><span>Failed delta</span><strong>${comparison.deltas.failed}</strong></article><article class="card"><span>Pass rate delta</span><strong>${escapeHtml46(formatPercent(comparison.deltas.passRate))}</strong></article></div><section><h2>Regression Reasons</h2><ul>${reasons}</ul></section><section><h2>New Failed Sessions</h2><ul>${newFailures}</ul></section><section><h2>Recovered Sessions</h2><ul>${recovered}</ul></section></main></body></html>`;
32854
33283
  };
32855
33284
  var renderVoiceScenarioEvalHTML = (report, options = {}) => {
32856
33285
  const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
32857
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
33286
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml46(link.href)}">${escapeHtml46(link.label)}</a>`).join("")}</nav>` : "";
32858
33287
  const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
32859
- const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml45(issue)}</li>`).join("")}</ul>` : "";
33288
+ const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml46(issue)}</li>`).join("")}</ul>` : "";
32860
33289
  const sessions = scenario.sessions.length ? scenario.sessions.map((session) => {
32861
- const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml45(session.operationsRecordHref)}">${escapeHtml45(session.sessionId)}</a>` : escapeHtml45(session.sessionId);
32862
- return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml45(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml45(session.issues.join(", ") || "none")}</td></tr>`;
33290
+ const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml46(session.operationsRecordHref)}">${escapeHtml46(session.sessionId)}</a>` : escapeHtml46(session.sessionId);
33291
+ return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml46(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml46(session.issues.join(", ") || "none")}</td></tr>`;
32863
33292
  }).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
32864
- return `<section class="scenario ${scenario.status}"><h2>${escapeHtml45(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml45(scenario.description)}</p>` : ""}<p class="status ${scenario.status}">${scenario.status}</p><p>${scenario.passed} passed, ${scenario.failed} failed, ${scenario.matchedSessions} matched.</p>${scenarioIssues}<table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Issues</th></tr></thead><tbody>${sessions}</tbody></table></section>`;
33293
+ return `<section class="scenario ${scenario.status}"><h2>${escapeHtml46(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml46(scenario.description)}</p>` : ""}<p class="status ${scenario.status}">${scenario.status}</p><p>${scenario.passed} passed, ${scenario.failed} failed, ${scenario.matchedSessions} matched.</p>${scenarioIssues}<table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Issues</th></tr></thead><tbody>${sessions}</tbody></table></section>`;
32865
33294
  }).join("") : "<section><p>No scenarios configured.</p></section>";
32866
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml45(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${scenarios}</main></body></html>`;
33295
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml46(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${scenarios}</main></body></html>`;
32867
33296
  };
32868
33297
  var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
32869
33298
  const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
32870
- const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
33299
+ const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml46(link.href)}">${escapeHtml46(link.label)}</a>`).join("")}</nav>` : "";
32871
33300
  const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
32872
- const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml45(scenario.label)}</td><td>${escapeHtml45(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml45([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
32873
- return `<section class="${fixture.status}"><h2>${escapeHtml45(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml45(fixture.description)}</p>` : ""}<p class="status ${fixture.status}">${fixture.status}</p><table><thead><tr><th>Scenario</th><th>Status</th><th>Sessions</th><th>Issues</th></tr></thead><tbody>${scenarios}</tbody></table></section>`;
33301
+ const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml46(scenario.label)}</td><td>${escapeHtml46(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml46([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
33302
+ return `<section class="${fixture.status}"><h2>${escapeHtml46(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml46(fixture.description)}</p>` : ""}<p class="status ${fixture.status}">${fixture.status}</p><table><thead><tr><th>Scenario</th><th>Status</th><th>Sessions</th><th>Issues</th></tr></thead><tbody>${scenarios}</tbody></table></section>`;
32874
33303
  }).join("") : "<section><p>No scenario fixtures configured.</p></section>";
32875
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml45(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${fixtures}</main></body></html>`;
33304
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml46(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${fixtures}</main></body></html>`;
32876
33305
  };
32877
33306
  var createVoiceEvalRoutes = (options) => {
32878
33307
  const path = options.path ?? "/evals";
32879
- const routes = new Elysia48({
33308
+ const routes = new Elysia49({
32880
33309
  name: options.name ?? "absolutejs-voice-evals"
32881
33310
  });
32882
33311
  const getReport = () => runVoiceSessionEvals({
@@ -33013,11 +33442,11 @@ var createVoiceEvalRoutes = (options) => {
33013
33442
  return routes;
33014
33443
  };
33015
33444
  // src/simulationSuite.ts
33016
- import { Elysia as Elysia51 } from "elysia";
33445
+ import { Elysia as Elysia52 } from "elysia";
33017
33446
 
33018
33447
  // src/outcomeContract.ts
33019
- import { Elysia as Elysia49 } from "elysia";
33020
- var escapeHtml46 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33448
+ import { Elysia as Elysia50 } from "elysia";
33449
+ var escapeHtml47 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33021
33450
  var resolveSessionHref4 = (value, sessionId) => {
33022
33451
  if (value === false) {
33023
33452
  return;
@@ -33228,13 +33657,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
33228
33657
  var renderVoiceOutcomeContractHTML = (report, options = {}) => {
33229
33658
  const title = options.title ?? "Voice Outcome Contracts";
33230
33659
  const contracts = report.contracts.map((contract) => {
33231
- const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml46(href)}">${escapeHtml46(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
33660
+ const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml47(href)}">${escapeHtml47(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
33232
33661
  return `<section class="contract ${contract.pass ? "pass" : "fail"}">
33233
33662
  <div class="contract-header">
33234
33663
  <div>
33235
- <p class="eyebrow">${escapeHtml46(contract.contractId)}</p>
33236
- <h2>${escapeHtml46(contract.label ?? contract.contractId)}</h2>
33237
- ${contract.description ? `<p>${escapeHtml46(contract.description)}</p>` : ""}
33664
+ <p class="eyebrow">${escapeHtml47(contract.contractId)}</p>
33665
+ <h2>${escapeHtml47(contract.label ?? contract.contractId)}</h2>
33666
+ ${contract.description ? `<p>${escapeHtml47(contract.description)}</p>` : ""}
33238
33667
  ${sessionLinks}
33239
33668
  </div>
33240
33669
  <strong>${contract.pass ? "pass" : "fail"}</strong>
@@ -33246,10 +33675,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
33246
33675
  <span>handoffs ${String(contract.matched.handoffs)}</span>
33247
33676
  <span>events ${String(contract.matched.integrationEvents)}</span>
33248
33677
  </div>
33249
- ${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml46(issue.message)}</li>`).join("")}</ul>` : ""}
33678
+ ${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml47(issue.message)}</li>`).join("")}</ul>` : ""}
33250
33679
  </section>`;
33251
33680
  }).join("");
33252
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(14,165,233,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary,.grid{display:flex;flex-wrap:wrap;gap:10px}.pill,.grid span{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}li{margin:8px 0}@media(max-width:800px){main{padding:18px}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Business Outcome Verification</p><h1>${escapeHtml46(title)}</h1><div class="summary"><span class="pill ${report.status}">${report.status}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section>${contracts || '<section class="contract"><p>No outcome contracts configured.</p></section>'}</main></body></html>`;
33681
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml47(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(14,165,233,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary,.grid{display:flex;flex-wrap:wrap;gap:10px}.pill,.grid span{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}li{margin:8px 0}@media(max-width:800px){main{padding:18px}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Business Outcome Verification</p><h1>${escapeHtml47(title)}</h1><div class="summary"><span class="pill ${report.status}">${report.status}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section>${contracts || '<section class="contract"><p>No outcome contracts configured.</p></section>'}</main></body></html>`;
33253
33682
  };
33254
33683
  var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
33255
33684
  var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
@@ -33265,7 +33694,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
33265
33694
  var createVoiceOutcomeContractRoutes = (options) => {
33266
33695
  const path = options.path ?? "/api/outcome-contracts";
33267
33696
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
33268
- const routes = new Elysia49({
33697
+ const routes = new Elysia50({
33269
33698
  name: options.name ?? "absolutejs-voice-outcome-contracts"
33270
33699
  }).get(path, createVoiceOutcomeContractJSONHandler(options));
33271
33700
  if (htmlPath) {
@@ -33275,7 +33704,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
33275
33704
  };
33276
33705
 
33277
33706
  // src/toolContract.ts
33278
- import { Elysia as Elysia50 } from "elysia";
33707
+ import { Elysia as Elysia51 } from "elysia";
33279
33708
 
33280
33709
  // src/toolRuntime.ts
33281
33710
  var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
@@ -33484,7 +33913,7 @@ var createDefaultTurn = (caseId) => ({
33484
33913
  });
33485
33914
  var defaultApi = {};
33486
33915
  var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
33487
- var escapeHtml47 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33916
+ var escapeHtml48 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33488
33917
  var resolveSessionHref5 = (value, sessionId) => {
33489
33918
  if (value === false) {
33490
33919
  return;
@@ -33735,7 +34164,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
33735
34164
  };
33736
34165
  var renderVoiceToolContractHTML = (report, options = {}) => {
33737
34166
  const title = options.title ?? "Voice Tool Contracts";
33738
- const snippet = escapeHtml47(`app.use(
34167
+ const snippet = escapeHtml48(`app.use(
33739
34168
  createVoiceToolContractRoutes({
33740
34169
  htmlPath: '/tool-contracts',
33741
34170
  path: '/api/tool-contracts',
@@ -33761,20 +34190,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
33761
34190
  );`);
33762
34191
  const contracts = report.contracts.map((contract) => {
33763
34192
  const cases = contract.cases.map((testCase) => `<tr>
33764
- <td>${testCase.operationsRecordHref ? `<a href="${escapeHtml47(testCase.operationsRecordHref)}">${escapeHtml47(testCase.label ?? testCase.caseId)}</a>` : escapeHtml47(testCase.label ?? testCase.caseId)}</td>
34193
+ <td>${testCase.operationsRecordHref ? `<a href="${escapeHtml48(testCase.operationsRecordHref)}">${escapeHtml48(testCase.label ?? testCase.caseId)}</a>` : escapeHtml48(testCase.label ?? testCase.caseId)}</td>
33765
34194
  <td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
33766
- <td>${escapeHtml47(testCase.status)}</td>
33767
- <td>${escapeHtml47(testCase.sessionId)}</td>
34195
+ <td>${escapeHtml48(testCase.status)}</td>
34196
+ <td>${escapeHtml48(testCase.sessionId)}</td>
33768
34197
  <td>${String(testCase.attempts)}</td>
33769
34198
  <td>${String(testCase.elapsedMs)}ms</td>
33770
34199
  <td>${testCase.timedOut ? "yes" : "no"}</td>
33771
- <td>${escapeHtml47(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
34200
+ <td>${escapeHtml48(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
33772
34201
  </tr>`).join("");
33773
34202
  return `<section class="contract ${contract.pass ? "pass" : "fail"}">
33774
34203
  <div class="contract-header">
33775
34204
  <div>
33776
- <p class="eyebrow">${escapeHtml47(contract.toolName)}</p>
33777
- <h2>${escapeHtml47(contract.label ?? contract.contractId)}</h2>
34205
+ <p class="eyebrow">${escapeHtml48(contract.toolName)}</p>
34206
+ <h2>${escapeHtml48(contract.label ?? contract.contractId)}</h2>
33778
34207
  </div>
33779
34208
  <strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
33780
34209
  </div>
@@ -33784,7 +34213,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
33784
34213
  </table>
33785
34214
  </section>`;
33786
34215
  }).join("");
33787
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml47(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(245,158,11,.12))}.primitive{background:#151b20;border-color:#5a4421}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}h2{margin:.2rem 0 1rem}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}.primitive p{color:#d8dee6;line-height:1.55}.primitive pre{background:#0f1217;border:1px solid #2a323a;border-radius:16px;color:#fef3c7;overflow:auto;padding:14px}.primitive code{color:#fef3c7}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left;vertical-align:top}th{color:#a8b0b8;font-size:.82rem}@media(max-width:800px){main{padding:18px}table{display:block;overflow:auto}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Tool Reliability</p><h1>${escapeHtml47(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml47(report.status)}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceToolContractRoutes(...)</code> certifies tool behavior</h2><p>Define deterministic tool cases for retries, idempotency, timeouts, result shape, and error handling so assistant tools fail in pre-production instead of live calls.</p><pre><code>${snippet}</code></pre></section>${contracts || '<section class="contract"><p>No tool contracts configured.</p></section>'}</main></body></html>`;
34216
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml48(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(245,158,11,.12))}.primitive{background:#151b20;border-color:#5a4421}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}h2{margin:.2rem 0 1rem}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}.primitive p{color:#d8dee6;line-height:1.55}.primitive pre{background:#0f1217;border:1px solid #2a323a;border-radius:16px;color:#fef3c7;overflow:auto;padding:14px}.primitive code{color:#fef3c7}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left;vertical-align:top}th{color:#a8b0b8;font-size:.82rem}@media(max-width:800px){main{padding:18px}table{display:block;overflow:auto}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Tool Reliability</p><h1>${escapeHtml48(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml48(report.status)}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceToolContractRoutes(...)</code> certifies tool behavior</h2><p>Define deterministic tool cases for retries, idempotency, timeouts, result shape, and error handling so assistant tools fail in pre-production instead of live calls.</p><pre><code>${snippet}</code></pre></section>${contracts || '<section class="contract"><p>No tool contracts configured.</p></section>'}</main></body></html>`;
33788
34217
  };
33789
34218
  var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
33790
34219
  var createVoiceToolContractHTMLHandler = (options) => async () => {
@@ -33801,7 +34230,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
33801
34230
  var createVoiceToolContractRoutes = (options) => {
33802
34231
  const path = options.path ?? "/api/tool-contracts";
33803
34232
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
33804
- const routes = new Elysia50({
34233
+ const routes = new Elysia51({
33805
34234
  name: options.name ?? "absolutejs-voice-tool-contracts"
33806
34235
  }).get(path, createVoiceToolContractJSONHandler(options));
33807
34236
  if (htmlPath) {
@@ -33811,7 +34240,7 @@ var createVoiceToolContractRoutes = (options) => {
33811
34240
  };
33812
34241
 
33813
34242
  // src/simulationSuite.ts
33814
- var escapeHtml48 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
34243
+ var escapeHtml49 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
33815
34244
  var summarizeSection = (report) => ({
33816
34245
  failed: report.failed,
33817
34246
  passed: report.passed,
@@ -34007,15 +34436,15 @@ var renderSection = (label, summary) => {
34007
34436
  if (!summary) {
34008
34437
  return "";
34009
34438
  }
34010
- return `<article class="${escapeHtml48(summary.status)}"><span>${escapeHtml48(label)}</span><strong>${escapeHtml48(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
34439
+ return `<article class="${escapeHtml49(summary.status)}"><span>${escapeHtml49(label)}</span><strong>${escapeHtml49(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
34011
34440
  };
34012
34441
  var renderAction = (action) => {
34013
- const content = `<strong>${escapeHtml48(action.label)}</strong><p>${escapeHtml48(action.description)}</p><span>${escapeHtml48(action.section)} / ${escapeHtml48(action.severity)}</span>`;
34014
- return action.href ? `<a class="action" href="${escapeHtml48(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
34442
+ const content = `<strong>${escapeHtml49(action.label)}</strong><p>${escapeHtml49(action.description)}</p><span>${escapeHtml49(action.section)} / ${escapeHtml49(action.severity)}</span>`;
34443
+ return action.href ? `<a class="action" href="${escapeHtml49(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
34015
34444
  };
34016
34445
  var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
34017
34446
  const title = options.title ?? "Voice Simulation Suite";
34018
- const snippet = escapeHtml48(`app.use(
34447
+ const snippet = escapeHtml49(`app.use(
34019
34448
  createVoiceSimulationSuiteRoutes({
34020
34449
  htmlPath: '/voice/simulations',
34021
34450
  path: '/api/voice/simulations',
@@ -34048,12 +34477,12 @@ app.use(
34048
34477
  store: traceStore
34049
34478
  })
34050
34479
  );`);
34051
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml48(title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(34,197,94,.18),rgba(59,130,246,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#355078}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid,.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin:18px 0}.grid article,.action{background:#151d27;border:1px solid #283544;border-radius:18px;color:inherit;padding:16px;text-decoration:none}.grid span,.action span{color:#aab5c0}.grid strong{display:block;font-size:2rem;margin:.25rem 0;text-transform:uppercase}.action strong{display:block;color:#f8f3e7;margin-bottom:.35rem}.action p,.primitive p{color:#d8dee6;line-height:1.55;margin:.3rem 0 .6rem}pre{background:#151d27;border:1px solid #283544;border-radius:18px;overflow:auto;padding:16px}.primitive pre{background:#0b1118;color:#dbeafe}.primitive code{color:#bfdbfe}</style></head><body><main><section class="hero"><p class="eyebrow">Pre-production proof</p><h1>${escapeHtml48(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml48(report.status)}">Status: ${escapeHtml48(report.status)}</p><section class="grid">${renderSection("Sessions", report.summary.sessions)}${renderSection("Scenarios", report.summary.scenarios)}${renderSection("Fixtures", report.summary.fixtures)}${renderSection("Tools", report.summary.tools)}${renderSection("Outcomes", report.summary.outcomes)}</section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceSimulationSuiteRoutes(...)</code> builds this pre-production proof surface</h2><p>Run session quality checks, scenario evals, fixture-backed simulations, tool contracts, and outcome contracts from one route group before live traffic sees a regression.</p><pre><code>${snippet}</code></pre></section><h2>Actions</h2><section class="actions">${report.actions.length > 0 ? report.actions.map(renderAction).join("") : '<article class="action"><strong>No action required</strong><p>All enabled simulation sections are passing.</p></article>'}</section><pre>${escapeHtml48(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
34480
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml49(title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(34,197,94,.18),rgba(59,130,246,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#355078}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid,.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin:18px 0}.grid article,.action{background:#151d27;border:1px solid #283544;border-radius:18px;color:inherit;padding:16px;text-decoration:none}.grid span,.action span{color:#aab5c0}.grid strong{display:block;font-size:2rem;margin:.25rem 0;text-transform:uppercase}.action strong{display:block;color:#f8f3e7;margin-bottom:.35rem}.action p,.primitive p{color:#d8dee6;line-height:1.55;margin:.3rem 0 .6rem}pre{background:#151d27;border:1px solid #283544;border-radius:18px;overflow:auto;padding:16px}.primitive pre{background:#0b1118;color:#dbeafe}.primitive code{color:#bfdbfe}</style></head><body><main><section class="hero"><p class="eyebrow">Pre-production proof</p><h1>${escapeHtml49(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml49(report.status)}">Status: ${escapeHtml49(report.status)}</p><section class="grid">${renderSection("Sessions", report.summary.sessions)}${renderSection("Scenarios", report.summary.scenarios)}${renderSection("Fixtures", report.summary.fixtures)}${renderSection("Tools", report.summary.tools)}${renderSection("Outcomes", report.summary.outcomes)}</section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceSimulationSuiteRoutes(...)</code> builds this pre-production proof surface</h2><p>Run session quality checks, scenario evals, fixture-backed simulations, tool contracts, and outcome contracts from one route group before live traffic sees a regression.</p><pre><code>${snippet}</code></pre></section><h2>Actions</h2><section class="actions">${report.actions.length > 0 ? report.actions.map(renderAction).join("") : '<article class="action"><strong>No action required</strong><p>All enabled simulation sections are passing.</p></article>'}</section><pre>${escapeHtml49(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
34052
34481
  };
34053
34482
  var createVoiceSimulationSuiteRoutes = (options) => {
34054
34483
  const path = options.path ?? "/api/voice/simulations";
34055
34484
  const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
34056
- const app = new Elysia51({
34485
+ const app = new Elysia52({
34057
34486
  name: options.name ?? "absolutejs-voice-simulation-suite"
34058
34487
  }).get(path, () => runVoiceSimulationSuite(options));
34059
34488
  if (htmlPath) {
@@ -34680,10 +35109,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
34680
35109
  return report;
34681
35110
  };
34682
35111
  // src/turnLatency.ts
34683
- import { Elysia as Elysia52 } from "elysia";
35112
+ import { Elysia as Elysia53 } from "elysia";
34684
35113
  var DEFAULT_WARN_AFTER_MS2 = 1800;
34685
35114
  var DEFAULT_FAIL_AFTER_MS2 = 3200;
34686
- var escapeHtml49 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
35115
+ var escapeHtml50 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
34687
35116
  var firstNumber4 = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
34688
35117
  var getString19 = (value) => typeof value === "string" && value.trim() ? value : undefined;
34689
35118
  var createTraceStageIndex = (events) => {
@@ -34798,7 +35227,7 @@ var summarizeVoiceTurnLatency = async (options) => {
34798
35227
  warnings
34799
35228
  };
34800
35229
  };
34801
- var formatMs4 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
35230
+ var formatMs5 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
34802
35231
  var renderVoiceTurnLatencyHTML = (report, options = {}) => {
34803
35232
  const title = options.title ?? "Voice Turn Latency";
34804
35233
  const snippet = `app.use(
@@ -34819,11 +35248,11 @@ await traceStore.append({
34819
35248
  turnId,
34820
35249
  type: 'turn_latency.stage'
34821
35250
  });`;
34822
- const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml49(turn.status)}">
34823
- <header><div><p class="eyebrow">${escapeHtml49(turn.sessionId)} \xB7 ${escapeHtml49(turn.turnId)}</p><h2>${escapeHtml49(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml49(turn.status)}</strong></header>
34824
- <dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml49(stage.label)}</dt><dd>${escapeHtml49(formatMs4(stage.valueMs))}</dd></div>`).join("")}</dl>
35251
+ const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml50(turn.status)}">
35252
+ <header><div><p class="eyebrow">${escapeHtml50(turn.sessionId)} \xB7 ${escapeHtml50(turn.turnId)}</p><h2>${escapeHtml50(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml50(turn.status)}</strong></header>
35253
+ <dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml50(stage.label)}</dt><dd>${escapeHtml50(formatMs5(stage.valueMs))}</dd></div>`).join("")}</dl>
34825
35254
  </article>`).join("");
34826
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml49(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn,.primitive{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(251,191,36,.1))}.eyebrow{color:#5eead4;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.primitive p{color:#cbd5e1}.primitive pre{background:#0a0d10;border:1px solid #2a323a;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}.turn header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.empty{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{font-weight:900;margin:0}@media(max-width:800px){main{padding:18px}.turn header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">End-to-end responsiveness</p><h1>${escapeHtml49(title)}</h1><div class="summary"><span class="pill ${escapeHtml49(report.status)}">${escapeHtml49(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml49(formatMs4(report.averageTotalMs))}</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTurnLatencyRoutes(...)</code> exposes the full turn waterfall</h2><p>Attach stage traces for speech detection, commit, model response, TTS send, and first audio so teams can prove where latency actually comes from.</p><pre><code>${escapeHtml49(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
35255
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn,.primitive{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(251,191,36,.1))}.eyebrow{color:#5eead4;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.primitive p{color:#cbd5e1}.primitive pre{background:#0a0d10;border:1px solid #2a323a;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}.turn header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.empty{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{font-weight:900;margin:0}@media(max-width:800px){main{padding:18px}.turn header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">End-to-end responsiveness</p><h1>${escapeHtml50(title)}</h1><div class="summary"><span class="pill ${escapeHtml50(report.status)}">${escapeHtml50(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml50(formatMs5(report.averageTotalMs))}</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTurnLatencyRoutes(...)</code> exposes the full turn waterfall</h2><p>Attach stage traces for speech detection, commit, model response, TTS send, and first audio so teams can prove where latency actually comes from.</p><pre><code>${escapeHtml50(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
34827
35256
  };
34828
35257
  var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
34829
35258
  var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
@@ -34840,7 +35269,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
34840
35269
  var createVoiceTurnLatencyRoutes = (options) => {
34841
35270
  const path = options.path ?? "/api/turn-latency";
34842
35271
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
34843
- const routes = new Elysia52({
35272
+ const routes = new Elysia53({
34844
35273
  name: options.name ?? "absolutejs-voice-turn-latency"
34845
35274
  }).get(path, createVoiceTurnLatencyJSONHandler(options));
34846
35275
  if (htmlPath) {
@@ -34849,8 +35278,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
34849
35278
  return routes;
34850
35279
  };
34851
35280
  // src/liveLatency.ts
34852
- import { Elysia as Elysia53 } from "elysia";
34853
- var escapeHtml50 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
35281
+ import { Elysia as Elysia54 } from "elysia";
35282
+ var escapeHtml51 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
34854
35283
  var percentile6 = (values, percentileValue) => {
34855
35284
  if (values.length === 0) {
34856
35285
  return;
@@ -34895,7 +35324,7 @@ var summarizeVoiceLiveLatency = async (options) => {
34895
35324
  warnings
34896
35325
  };
34897
35326
  };
34898
- var formatMs5 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
35327
+ var formatMs6 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
34899
35328
  var renderVoiceLiveLatencyHTML = (report, options = {}) => {
34900
35329
  const title = options.title ?? "Voice Live Latency";
34901
35330
  const snippet = `app.use(
@@ -34917,13 +35346,13 @@ await traceStore.append({
34917
35346
  sessionId,
34918
35347
  type: 'client.live_latency'
34919
35348
  });`;
34920
- const rows = report.recent.map((sample) => `<tr><td>${escapeHtml50(sample.sessionId)}</td><td>${escapeHtml50(formatMs5(sample.latencyMs))}</td><td>${escapeHtml50(sample.status ?? "unknown")}</td><td>${escapeHtml50(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
34921
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(245,158,11,.1));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.warn,.empty{color:#fbbf24}.fail{color:#fca5a5}.metrics{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:18px 0}.metrics article,table,.primitive{background:#141922;border:1px solid #26313d;border-radius:18px}.metrics article,.primitive{padding:16px}.metrics span{color:#a8b0b8}.metrics strong{display:block;font-size:2rem;margin-top:.25rem}.primitive{margin:0 0 18px}.primitive h2{margin:.2rem 0 .5rem}.primitive p{color:#cbd5e1}.primitive pre{background:#080b10;border:1px solid #26313d;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #26313d;padding:12px;text-align:left}@media(max-width:760px){main{padding:20px}}</style></head><body><main><section class="hero"><p class="eyebrow">Browser proof</p><h1>${escapeHtml50(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml50(report.status)}">Status: ${escapeHtml50(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml50(formatMs5(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml50(formatMs5(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml50(formatMs5(report.averageLatencyMs))}</strong></article><article><span>Samples</span><strong>${String(report.total)}</strong></article></section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceLiveLatencyRoutes(...)</code> turns real browser timing into a release gate</h2><p>Persist live timing samples into the trace store so readiness, simulations, and trace timelines all point at the same self-hosted proof.</p><pre><code>${escapeHtml50(snippet)}</code></pre></section><table><thead><tr><th>Session</th><th>Latency</th><th>Status</th><th>Measured</th></tr></thead><tbody>${rows || '<tr><td colspan="4">No live latency samples yet.</td></tr>'}</tbody></table></main></body></html>`;
35349
+ const rows = report.recent.map((sample) => `<tr><td>${escapeHtml51(sample.sessionId)}</td><td>${escapeHtml51(formatMs6(sample.latencyMs))}</td><td>${escapeHtml51(sample.status ?? "unknown")}</td><td>${escapeHtml51(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
35350
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml51(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(245,158,11,.1));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.warn,.empty{color:#fbbf24}.fail{color:#fca5a5}.metrics{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:18px 0}.metrics article,table,.primitive{background:#141922;border:1px solid #26313d;border-radius:18px}.metrics article,.primitive{padding:16px}.metrics span{color:#a8b0b8}.metrics strong{display:block;font-size:2rem;margin-top:.25rem}.primitive{margin:0 0 18px}.primitive h2{margin:.2rem 0 .5rem}.primitive p{color:#cbd5e1}.primitive pre{background:#080b10;border:1px solid #26313d;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #26313d;padding:12px;text-align:left}@media(max-width:760px){main{padding:20px}}</style></head><body><main><section class="hero"><p class="eyebrow">Browser proof</p><h1>${escapeHtml51(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml51(report.status)}">Status: ${escapeHtml51(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml51(formatMs6(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml51(formatMs6(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml51(formatMs6(report.averageLatencyMs))}</strong></article><article><span>Samples</span><strong>${String(report.total)}</strong></article></section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceLiveLatencyRoutes(...)</code> turns real browser timing into a release gate</h2><p>Persist live timing samples into the trace store so readiness, simulations, and trace timelines all point at the same self-hosted proof.</p><pre><code>${escapeHtml51(snippet)}</code></pre></section><table><thead><tr><th>Session</th><th>Latency</th><th>Status</th><th>Measured</th></tr></thead><tbody>${rows || '<tr><td colspan="4">No live latency samples yet.</td></tr>'}</tbody></table></main></body></html>`;
34922
35351
  };
34923
35352
  var createVoiceLiveLatencyRoutes = (options) => {
34924
35353
  const path = options.path ?? "/api/live-latency";
34925
35354
  const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
34926
- const routes = new Elysia53({
35355
+ const routes = new Elysia54({
34927
35356
  name: options.name ?? "absolutejs-voice-live-latency"
34928
35357
  }).get(path, () => summarizeVoiceLiveLatency(options));
34929
35358
  if (htmlPath) {
@@ -34940,9 +35369,9 @@ var createVoiceLiveLatencyRoutes = (options) => {
34940
35369
  return routes;
34941
35370
  };
34942
35371
  // src/turnQuality.ts
34943
- import { Elysia as Elysia54 } from "elysia";
35372
+ import { Elysia as Elysia55 } from "elysia";
34944
35373
  var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
34945
- var escapeHtml51 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
35374
+ var escapeHtml52 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
34946
35375
  var getTurnLatencyMs = (turn) => {
34947
35376
  const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
34948
35377
  if (firstTranscriptAt === undefined) {
@@ -35012,24 +35441,24 @@ var summarizeVoiceTurnQuality = async (options) => {
35012
35441
  };
35013
35442
  var renderVoiceTurnQualityHTML = (report, options = {}) => {
35014
35443
  const title = options.title ?? "Voice Turn Quality";
35015
- const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml51(turn.status)}">
35444
+ const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml52(turn.status)}">
35016
35445
  <div class="turn-header">
35017
35446
  <div>
35018
- <p class="eyebrow">${escapeHtml51(turn.sessionId)} \xB7 ${escapeHtml51(turn.turnId)}</p>
35019
- <h2>${escapeHtml51(turn.text || "Empty turn")}</h2>
35447
+ <p class="eyebrow">${escapeHtml52(turn.sessionId)} \xB7 ${escapeHtml52(turn.turnId)}</p>
35448
+ <h2>${escapeHtml52(turn.text || "Empty turn")}</h2>
35020
35449
  </div>
35021
- <strong>${escapeHtml51(turn.status)}</strong>
35450
+ <strong>${escapeHtml52(turn.status)}</strong>
35022
35451
  </div>
35023
35452
  <dl>
35024
- <div><dt>Source</dt><dd>${escapeHtml51(turn.source ?? "unknown")}</dd></div>
35453
+ <div><dt>Source</dt><dd>${escapeHtml52(turn.source ?? "unknown")}</dd></div>
35025
35454
  <div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
35026
- <div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml51(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
35027
- <div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml51(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
35455
+ <div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml52(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
35456
+ <div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml52(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
35028
35457
  <div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
35029
35458
  <div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
35030
35459
  </dl>
35031
35460
  </article>`).join("");
35032
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml51(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(251,191,36,.16),rgba(34,197,94,.1))}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.turn-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.unknown{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.turn-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Realtime STT Debugging</p><h1>${escapeHtml51(title)}</h1><div class="summary"><span class="pill ${escapeHtml51(report.status)}">${escapeHtml51(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span><span class="pill">${String(report.sessions)} sessions</span></div></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
35461
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml52(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(251,191,36,.16),rgba(34,197,94,.1))}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.turn-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.unknown{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.turn-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Realtime STT Debugging</p><h1>${escapeHtml52(title)}</h1><div class="summary"><span class="pill ${escapeHtml52(report.status)}">${escapeHtml52(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span><span class="pill">${String(report.sessions)} sessions</span></div></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
35033
35462
  };
35034
35463
  var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
35035
35464
  var createVoiceTurnQualityHTMLHandler = (options) => async () => {
@@ -35046,7 +35475,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
35046
35475
  var createVoiceTurnQualityRoutes = (options) => {
35047
35476
  const path = options.path ?? "/api/turn-quality";
35048
35477
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
35049
- const routes = new Elysia54({
35478
+ const routes = new Elysia55({
35050
35479
  name: options.name ?? "absolutejs-voice-turn-quality"
35051
35480
  }).get(path, createVoiceTurnQualityJSONHandler(options));
35052
35481
  if (htmlPath) {
@@ -35055,10 +35484,10 @@ var createVoiceTurnQualityRoutes = (options) => {
35055
35484
  return routes;
35056
35485
  };
35057
35486
  // src/phoneAgent.ts
35058
- import { Elysia as Elysia56 } from "elysia";
35487
+ import { Elysia as Elysia57 } from "elysia";
35059
35488
 
35060
35489
  // src/phoneAgentProductionSmoke.ts
35061
- import { Elysia as Elysia55 } from "elysia";
35490
+ import { Elysia as Elysia56 } from "elysia";
35062
35491
  var defaultRequirements = [
35063
35492
  "media-started",
35064
35493
  "transcript",
@@ -35066,7 +35495,7 @@ var defaultRequirements = [
35066
35495
  "lifecycle-outcome",
35067
35496
  "no-session-error"
35068
35497
  ];
35069
- var escapeHtml52 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
35498
+ var escapeHtml53 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
35070
35499
  var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
35071
35500
  var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
35072
35501
  const value = event.payload[key];
@@ -35175,10 +35604,10 @@ var resolveHandlerOptions = async (options, input) => ({
35175
35604
  });
35176
35605
  var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
35177
35606
  const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
35178
- const issues = report.issues.map((issue) => `<li><strong>${escapeHtml52(issue.requirement)}</strong>: ${escapeHtml52(issue.message)}</li>`).join("");
35179
- const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml52(outcome)}</span>`).join("");
35180
- const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml52(requirement)}</span>`).join("");
35181
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml52(title)}</title><style>body{background:#0e141b;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1050px;padding:32px}.hero,.panel{background:#151d26;border:1px solid #283544;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.metric{background:#0f151d;border:1px solid #283544;border-radius:16px;padding:14px}.metric strong{display:block;font-size:1.8rem}.pill{background:#0f151d;border:1px solid #3f3f46;border-radius:999px;display:inline-flex;margin:4px;padding:7px 10px}.issues{color:#fca5a5}code{color:#fde68a}@media(max-width:720px){main{padding:18px}}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent production smoke</p><h1>${escapeHtml52(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml52(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml52(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml52(report.sessionId)}</code>` : ""}.</p></section><section class="panel"><h2>Observed Trace Evidence</h2><div class="grid"><div class="metric"><span>Media starts</span><strong>${String(report.observed.mediaStarts)}</strong></div><div class="metric"><span>Transcripts</span><strong>${String(report.observed.transcripts)}</strong></div><div class="metric"><span>Assistant responses</span><strong>${String(report.observed.assistantResponses)}</strong></div><div class="metric"><span>Session errors</span><strong>${String(report.observed.sessionErrors)}</strong></div></div><p>${outcomes || '<span class="pill">No lifecycle outcome</span>'}</p></section><section class="panel"><h2>Requirements</h2><p>${requirements}</p>${issues ? `<ul class="issues">${issues}</ul>` : '<p class="pass">All required phone-agent smoke evidence is present.</p>'}</section></main></body></html>`;
35607
+ const issues = report.issues.map((issue) => `<li><strong>${escapeHtml53(issue.requirement)}</strong>: ${escapeHtml53(issue.message)}</li>`).join("");
35608
+ const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml53(outcome)}</span>`).join("");
35609
+ const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml53(requirement)}</span>`).join("");
35610
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml53(title)}</title><style>body{background:#0e141b;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1050px;padding:32px}.hero,.panel{background:#151d26;border:1px solid #283544;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.metric{background:#0f151d;border:1px solid #283544;border-radius:16px;padding:14px}.metric strong{display:block;font-size:1.8rem}.pill{background:#0f151d;border:1px solid #3f3f46;border-radius:999px;display:inline-flex;margin:4px;padding:7px 10px}.issues{color:#fca5a5}code{color:#fde68a}@media(max-width:720px){main{padding:18px}}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent production smoke</p><h1>${escapeHtml53(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml53(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml53(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml53(report.sessionId)}</code>` : ""}.</p></section><section class="panel"><h2>Observed Trace Evidence</h2><div class="grid"><div class="metric"><span>Media starts</span><strong>${String(report.observed.mediaStarts)}</strong></div><div class="metric"><span>Transcripts</span><strong>${String(report.observed.transcripts)}</strong></div><div class="metric"><span>Assistant responses</span><strong>${String(report.observed.assistantResponses)}</strong></div><div class="metric"><span>Session errors</span><strong>${String(report.observed.sessionErrors)}</strong></div></div><p>${outcomes || '<span class="pill">No lifecycle outcome</span>'}</p></section><section class="panel"><h2>Requirements</h2><p>${requirements}</p>${issues ? `<ul class="issues">${issues}</ul>` : '<p class="pass">All required phone-agent smoke evidence is present.</p>'}</section></main></body></html>`;
35182
35611
  };
35183
35612
  var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
35184
35613
  query,
@@ -35201,7 +35630,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
35201
35630
  var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
35202
35631
  const path = options.path ?? "/api/voice/phone/smoke-contract";
35203
35632
  const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
35204
- const routes = new Elysia55({
35633
+ const routes = new Elysia56({
35205
35634
  name: options.name ?? "absolutejs-voice-phone-smoke-contract"
35206
35635
  }).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
35207
35636
  if (htmlPath) {
@@ -35244,7 +35673,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
35244
35673
  "completed",
35245
35674
  "failed"
35246
35675
  ];
35247
- var escapeHtml53 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
35676
+ var escapeHtml54 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
35248
35677
  var loadRouteJson = async (input) => {
35249
35678
  const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
35250
35679
  headers: {
@@ -35482,10 +35911,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
35482
35911
  const entry = findCarrierMatrixEntry(report.matrix, carrier);
35483
35912
  const urls = entry?.setup.urls;
35484
35913
  const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
35485
- return `<tr><td>${escapeHtml53(carrier.name ?? carrier.provider)}</td><td>${escapeHtml53(carrier.provider)}</td><td><code>${escapeHtml53(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml53(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml53(entry.status)}">${escapeHtml53(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml53(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml53(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml53(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
35914
+ return `<tr><td>${escapeHtml54(carrier.name ?? carrier.provider)}</td><td>${escapeHtml54(carrier.provider)}</td><td><code>${escapeHtml54(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml54(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml54(entry.status)}">${escapeHtml54(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml54(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml54(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml54(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
35486
35915
  }).join("");
35487
- const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml53(stage)}</code></li>`).join("");
35488
- const snippet = escapeHtml53(`const phoneAgent = createVoicePhoneAgent({
35916
+ const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml54(stage)}</code></li>`).join("");
35917
+ const snippet = escapeHtml54(`const phoneAgent = createVoicePhoneAgent({
35489
35918
  carriers: [
35490
35919
  {
35491
35920
  provider: 'twilio',
@@ -35519,11 +35948,11 @@ app.use(
35519
35948
  );`);
35520
35949
  const checklist = report.carriers.map((carrier) => {
35521
35950
  const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
35522
- const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml53(issue)}</li>`).join("") ?? "";
35523
- const steps = instruction?.steps.map((step) => `<li>${escapeHtml53(step)}</li>`).join("") ?? "";
35524
- return `<article><h3>${escapeHtml53(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
35951
+ const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml54(issue)}</li>`).join("") ?? "";
35952
+ const steps = instruction?.steps.map((step) => `<li>${escapeHtml54(step)}</li>`).join("") ?? "";
35953
+ return `<article><h3>${escapeHtml54(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
35525
35954
  }).join("");
35526
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml53(report.title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(20,184,166,.2),rgba(245,158,11,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#365a60}.eyebrow{color:#5eead4;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}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.warn{color:#fde68a}.muted{color:#aab5c0}table{background:#151d27;border:1px solid #283544;border-collapse:collapse;border-radius:18px;display:block;overflow:auto;width:100%}td,th{border-bottom:1px solid #283544;padding:12px;text-align:left;vertical-align:top}code{color:#fde68a;overflow-wrap:anywhere}.primitive p{color:#cbd5de;line-height:1.55}.primitive pre{background:#0b1118;border:1px solid #283544;border-radius:18px;color:#fef3c7;overflow:auto;padding:16px}.checklist{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));margin:18px 0}.checklist article{background:#151d27;border:1px solid #283544;border-radius:18px;padding:18px}.checklist ol{padding-left:20px}.issues{color:#fca5a5}.stages{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));padding-left:18px}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent setup</p><h1>${escapeHtml53(report.title)}</h1><p>One self-hosted entrypoint for carrier routes, setup reports, smoke checks, and normalized call lifecycle stages.</p><p class="badge ${report.ready ? "pass" : "fail"}">Ready: ${String(report.ready)}</p>${report.matrixPath ? `<p><a href="${escapeHtml53(report.matrixPath)}?format=html">Open carrier matrix</a></p>` : ""}</section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoicePhoneAgent(...)</code> builds this carrier control plane</h2><p>Mount carrier routes once, expose setup and smoke proof, then feed the same carrier matrix and phone-agent smoke reports into production readiness so carrier regressions block deploys.</p><pre><code>${snippet}</code></pre></section><h2>Carrier Setup Checklist</h2><section class="checklist">${checklist}</section><h2>Carrier URLs</h2><table><thead><tr><th>Name</th><th>Provider</th><th>Setup</th><th>Smoke</th><th>Status</th><th>Answer/TwiML/TeXML</th><th>Webhook</th><th>Stream</th></tr></thead><tbody>${carrierRows}</tbody></table><h2>Lifecycle Schema</h2><ul class="stages">${stageList}</ul></main></body></html>`;
35955
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml54(report.title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(20,184,166,.2),rgba(245,158,11,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#365a60}.eyebrow{color:#5eead4;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}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.warn{color:#fde68a}.muted{color:#aab5c0}table{background:#151d27;border:1px solid #283544;border-collapse:collapse;border-radius:18px;display:block;overflow:auto;width:100%}td,th{border-bottom:1px solid #283544;padding:12px;text-align:left;vertical-align:top}code{color:#fde68a;overflow-wrap:anywhere}.primitive p{color:#cbd5de;line-height:1.55}.primitive pre{background:#0b1118;border:1px solid #283544;border-radius:18px;color:#fef3c7;overflow:auto;padding:16px}.checklist{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));margin:18px 0}.checklist article{background:#151d27;border:1px solid #283544;border-radius:18px;padding:18px}.checklist ol{padding-left:20px}.issues{color:#fca5a5}.stages{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));padding-left:18px}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent setup</p><h1>${escapeHtml54(report.title)}</h1><p>One self-hosted entrypoint for carrier routes, setup reports, smoke checks, and normalized call lifecycle stages.</p><p class="badge ${report.ready ? "pass" : "fail"}">Ready: ${String(report.ready)}</p>${report.matrixPath ? `<p><a href="${escapeHtml54(report.matrixPath)}?format=html">Open carrier matrix</a></p>` : ""}</section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoicePhoneAgent(...)</code> builds this carrier control plane</h2><p>Mount carrier routes once, expose setup and smoke proof, then feed the same carrier matrix and phone-agent smoke reports into production readiness so carrier regressions block deploys.</p><pre><code>${snippet}</code></pre></section><h2>Carrier Setup Checklist</h2><section class="checklist">${checklist}</section><h2>Carrier URLs</h2><table><thead><tr><th>Name</th><th>Provider</th><th>Setup</th><th>Smoke</th><th>Status</th><th>Answer/TwiML/TeXML</th><th>Webhook</th><th>Stream</th></tr></thead><tbody>${carrierRows}</tbody></table><h2>Lifecycle Schema</h2><ul class="stages">${stageList}</ul></main></body></html>`;
35527
35956
  };
35528
35957
  var createVoicePhoneAgent = (options) => {
35529
35958
  const carrierSummaries = options.carriers.map((carrier) => ({
@@ -35532,7 +35961,7 @@ var createVoicePhoneAgent = (options) => {
35532
35961
  setupPath: resolveSetupPath(carrier),
35533
35962
  smokePath: resolveSmokePath(carrier)
35534
35963
  }));
35535
- const app = new Elysia56({
35964
+ const app = new Elysia57({
35536
35965
  name: options.name ?? "absolutejs-voice-phone-agent"
35537
35966
  });
35538
35967
  for (const carrier of options.carriers) {
@@ -37281,8 +37710,8 @@ var createOpenAIVoiceTTS = (options) => {
37281
37710
  };
37282
37711
  };
37283
37712
  // src/providerCapabilities.ts
37284
- import { Elysia as Elysia57 } from "elysia";
37285
- var escapeHtml54 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
37713
+ import { Elysia as Elysia58 } from "elysia";
37714
+ var escapeHtml55 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
37286
37715
  var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
37287
37716
  configured: true,
37288
37717
  features: options.features?.[provider],
@@ -37347,27 +37776,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
37347
37776
  var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
37348
37777
  const title = options.title ?? "Voice Provider Capabilities";
37349
37778
  const cards = report.capabilities.map((capability) => {
37350
- const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml54(feature)}</span>`).join("");
37351
- return `<article class="card ${escapeHtml54(capability.status)}">
37779
+ const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml55(feature)}</span>`).join("");
37780
+ return `<article class="card ${escapeHtml55(capability.status)}">
37352
37781
  <div class="card-header">
37353
37782
  <div>
37354
- <p class="eyebrow">${escapeHtml54(capability.kind)}</p>
37355
- <h2>${escapeHtml54(capability.label ?? capability.provider)}</h2>
37783
+ <p class="eyebrow">${escapeHtml55(capability.kind)}</p>
37784
+ <h2>${escapeHtml55(capability.label ?? capability.provider)}</h2>
37356
37785
  </div>
37357
- <strong>${escapeHtml54(capability.status)}</strong>
37786
+ <strong>${escapeHtml55(capability.status)}</strong>
37358
37787
  </div>
37359
- ${capability.description ? `<p>${escapeHtml54(capability.description)}</p>` : ""}
37788
+ ${capability.description ? `<p>${escapeHtml55(capability.description)}</p>` : ""}
37360
37789
  <dl>
37361
37790
  <div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
37362
37791
  <div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
37363
- <div><dt>Model</dt><dd>${escapeHtml54(capability.model ?? "default")}</dd></div>
37792
+ <div><dt>Model</dt><dd>${escapeHtml55(capability.model ?? "default")}</dd></div>
37364
37793
  <div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
37365
37794
  <div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
37366
37795
  </dl>
37367
37796
  ${features ? `<div class="features">${features}</div>` : ""}
37368
37797
  </article>`;
37369
37798
  }).join("");
37370
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml54(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(14,165,233,.16),rgba(34,197,94,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary,.features{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.selected,.healthy{color:#86efac}.unconfigured,.degraded,.rate-limited,.suppressed{color:#fca5a5}.idle,.recoverable{color:#fde68a}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Discovery</p><h1>${escapeHtml54(title)}</h1><div class="summary"><span class="pill">${String(report.configured)} configured</span><span class="pill">${String(report.selected)} selected</span><span class="pill">${String(report.unconfigured)} missing</span><span class="pill">${String(report.total)} total</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider capabilities configured.</p></article>'}</section></main></body></html>`;
37799
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml55(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(14,165,233,.16),rgba(34,197,94,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary,.features{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.selected,.healthy{color:#86efac}.unconfigured,.degraded,.rate-limited,.suppressed{color:#fca5a5}.idle,.recoverable{color:#fde68a}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Discovery</p><h1>${escapeHtml55(title)}</h1><div class="summary"><span class="pill">${String(report.configured)} configured</span><span class="pill">${String(report.selected)} selected</span><span class="pill">${String(report.unconfigured)} missing</span><span class="pill">${String(report.total)} total</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider capabilities configured.</p></article>'}</section></main></body></html>`;
37371
37800
  };
37372
37801
  var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
37373
37802
  var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
@@ -37384,7 +37813,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
37384
37813
  var createVoiceProviderCapabilityRoutes = (options) => {
37385
37814
  const path = options.path ?? "/api/provider-capabilities";
37386
37815
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
37387
- const routes = new Elysia57({
37816
+ const routes = new Elysia58({
37388
37817
  name: options.name ?? "absolutejs-voice-provider-capabilities"
37389
37818
  }).get(path, createVoiceProviderCapabilityJSONHandler(options));
37390
37819
  if (htmlPath) {
@@ -37393,7 +37822,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
37393
37822
  return routes;
37394
37823
  };
37395
37824
  // src/providerOrchestration.ts
37396
- import { Elysia as Elysia58 } from "elysia";
37825
+ import { Elysia as Elysia59 } from "elysia";
37397
37826
  var defaultRequirement = {
37398
37827
  minProviders: 1,
37399
37828
  requireBudgetPolicy: false,
@@ -37406,7 +37835,7 @@ var statusRank7 = {
37406
37835
  warn: 1,
37407
37836
  fail: 2
37408
37837
  };
37409
- var escapeHtml55 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
37838
+ var escapeHtml56 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
37410
37839
  var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
37411
37840
  var uniqueSorted8 = (values) => [
37412
37841
  ...new Set(values.filter((value) => typeof value === "string"))
@@ -37549,27 +37978,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
37549
37978
  };
37550
37979
  var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
37551
37980
  const title = options.title ?? "Voice Provider Orchestration";
37552
- const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml55(surface.status)}">
37553
- <div class="card-header"><div><p class="eyebrow">${escapeHtml55(surface.surface)}</p><h2>${escapeHtml55(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml55(surface.status)}</strong></div>
37981
+ const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml56(surface.status)}">
37982
+ <div class="card-header"><div><p class="eyebrow">${escapeHtml56(surface.surface)}</p><h2>${escapeHtml56(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml56(surface.status)}</strong></div>
37554
37983
  <dl>
37555
- <div><dt>Providers</dt><dd>${escapeHtml55(surface.providers.join(", ") || "none")}</dd></div>
37556
- <div><dt>Fallback</dt><dd>${escapeHtml55(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
37984
+ <div><dt>Providers</dt><dd>${escapeHtml56(surface.providers.join(", ") || "none")}</dd></div>
37985
+ <div><dt>Fallback</dt><dd>${escapeHtml56(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
37557
37986
  <div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
37558
37987
  <div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
37559
37988
  <div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
37560
37989
  <div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
37561
37990
  <div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
37562
- <div><dt>Fallback mode</dt><dd>${escapeHtml55(surface.fallbackMode || "default")}</dd></div>
37991
+ <div><dt>Fallback mode</dt><dd>${escapeHtml56(surface.fallbackMode || "default")}</dd></div>
37563
37992
  </dl>
37564
- ${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml55(issue.status)}</strong> ${escapeHtml55(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
37993
+ ${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml56(issue.status)}</strong> ${escapeHtml56(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
37565
37994
  </article>`).join("");
37566
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml55(title)}</title><style>body{background:#111827;color:#f9fafb;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#172033;border:1px solid #2d3b55;border-radius:22px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(59,130,246,.18),rgba(20,184,166,.12))}.eyebrow{color:#93c5fd;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f172a;border:1px solid #334155;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass strong{color:#86efac}.warn strong{color:#fde68a}.fail strong{color:#fca5a5}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0;overflow-wrap:anywhere}li{margin:.35rem 0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Policy Proof</p><h1>${escapeHtml55(title)}</h1><div class="summary"><span class="pill">${escapeHtml55(report.profileId)}</span><span class="pill">${escapeHtml55(report.status)}</span><span class="pill">${String(report.summary.surfaces)} surfaces</span><span class="pill">${String(report.summary.providers)} providers</span><span class="pill">${String(report.issues.length)} issues</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider orchestration surfaces configured.</p></article>'}</section></main></body></html>`;
37995
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml56(title)}</title><style>body{background:#111827;color:#f9fafb;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#172033;border:1px solid #2d3b55;border-radius:22px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(59,130,246,.18),rgba(20,184,166,.12))}.eyebrow{color:#93c5fd;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f172a;border:1px solid #334155;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass strong{color:#86efac}.warn strong{color:#fde68a}.fail strong{color:#fca5a5}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0;overflow-wrap:anywhere}li{margin:.35rem 0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Policy Proof</p><h1>${escapeHtml56(title)}</h1><div class="summary"><span class="pill">${escapeHtml56(report.profileId)}</span><span class="pill">${escapeHtml56(report.status)}</span><span class="pill">${String(report.summary.surfaces)} surfaces</span><span class="pill">${String(report.summary.providers)} providers</span><span class="pill">${String(report.issues.length)} issues</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider orchestration surfaces configured.</p></article>'}</section></main></body></html>`;
37567
37996
  };
37568
37997
  var createVoiceProviderOrchestrationRoutes = (options) => {
37569
37998
  const path = options.path ?? "/api/voice/provider-orchestration";
37570
37999
  const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
37571
38000
  const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
37572
- const routes = new Elysia58({
38001
+ const routes = new Elysia59({
37573
38002
  name: options.name ?? "absolutejs-voice-provider-orchestration"
37574
38003
  }).get(path, () => buildVoiceProviderOrchestrationReport(options));
37575
38004
  if (htmlPath) {
@@ -37742,8 +38171,8 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
37742
38171
  return report;
37743
38172
  };
37744
38173
  // src/voiceMonitoring.ts
37745
- import { Elysia as Elysia59 } from "elysia";
37746
- var escapeHtml56 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
38174
+ import { Elysia as Elysia60 } from "elysia";
38175
+ var escapeHtml57 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
37747
38176
  var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
37748
38177
  var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
37749
38178
  var createVoiceMemoryMonitorIssueStore = (initial = []) => {
@@ -37996,14 +38425,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
37996
38425
  };
37997
38426
  var renderVoiceMonitorHTML = (report, options = {}) => {
37998
38427
  const title = options.title ?? "Voice Monitors";
37999
- const runs = report.runs.map((run) => `<tr><td>${escapeHtml56(run.label)}</td><td class="${escapeHtml56(run.status)}">${escapeHtml56(run.status)}</td><td>${escapeHtml56(run.severity)}</td><td>${escapeHtml56(String(run.value ?? ""))}</td><td>${escapeHtml56(String(run.threshold ?? ""))}</td><td>${escapeHtml56(run.detail ?? "")}</td></tr>`).join("");
38000
- const issues = report.issues.map((issue) => `<li><strong>${escapeHtml56(issue.label)}</strong> <span class="${escapeHtml56(issue.status)}">${escapeHtml56(issue.status)}</span> ${escapeHtml56(issue.detail ?? "")}</li>`).join("");
38001
- const snippet = escapeHtml56(`app.use(createVoiceMonitorRoutes({
38428
+ const runs = report.runs.map((run) => `<tr><td>${escapeHtml57(run.label)}</td><td class="${escapeHtml57(run.status)}">${escapeHtml57(run.status)}</td><td>${escapeHtml57(run.severity)}</td><td>${escapeHtml57(String(run.value ?? ""))}</td><td>${escapeHtml57(String(run.threshold ?? ""))}</td><td>${escapeHtml57(run.detail ?? "")}</td></tr>`).join("");
38429
+ const issues = report.issues.map((issue) => `<li><strong>${escapeHtml57(issue.label)}</strong> <span class="${escapeHtml57(issue.status)}">${escapeHtml57(issue.status)}</span> ${escapeHtml57(issue.detail ?? "")}</li>`).join("");
38430
+ const snippet = escapeHtml57(`app.use(createVoiceMonitorRoutes({
38002
38431
  evidence,
38003
38432
  issueStore,
38004
38433
  monitors: [defineVoiceMonitor(...)]
38005
38434
  }));`);
38006
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml56(title)}</title><style>body{background:#10141b;color:#f8f2df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero,.card{background:#171f2b;border:1px solid #2e3a4b;border-radius:24px;margin-bottom:16px;padding:22px}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);line-height:.92;margin:.2rem 0 1rem}.pill{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;margin-right:8px;padding:8px 12px}.pass{color:#86efac}.warn,.acknowledged{color:#fde68a}.fail,.open{color:#fca5a5}.resolved,.muted{color:#cbd5e1}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3a4b;padding:12px;text-align:left;vertical-align:top}pre{background:#0c1118;border:1px solid #2e3a4b;border-radius:16px;color:#dbeafe;overflow:auto;padding:16px}</style></head><body><main><section class="hero"><p class="eyebrow">Code-owned monitoring</p><h1>${escapeHtml56(title)}</h1><p class="pill ${escapeHtml56(report.status)}">Status: ${escapeHtml56(report.status)}</p><p class="pill">Open issues: ${String(report.summary.open)}</p><p class="pill">Critical: ${String(report.summary.criticalOpen)}</p></section><section class="card"><h2>Monitor Runs</h2><table><thead><tr><th>Monitor</th><th>Status</th><th>Severity</th><th>Value</th><th>Threshold</th><th>Detail</th></tr></thead><tbody>${runs}</tbody></table></section><section class="card"><h2>Issues</h2>${issues ? `<ul>${issues}</ul>` : '<p class="pass">No monitor issues.</p>'}</section><section class="card"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceMonitorRoutes(...)</code></h2><pre><code>${snippet}</code></pre></section></main></body></html>`;
38435
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml57(title)}</title><style>body{background:#10141b;color:#f8f2df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero,.card{background:#171f2b;border:1px solid #2e3a4b;border-radius:24px;margin-bottom:16px;padding:22px}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);line-height:.92;margin:.2rem 0 1rem}.pill{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;margin-right:8px;padding:8px 12px}.pass{color:#86efac}.warn,.acknowledged{color:#fde68a}.fail,.open{color:#fca5a5}.resolved,.muted{color:#cbd5e1}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3a4b;padding:12px;text-align:left;vertical-align:top}pre{background:#0c1118;border:1px solid #2e3a4b;border-radius:16px;color:#dbeafe;overflow:auto;padding:16px}</style></head><body><main><section class="hero"><p class="eyebrow">Code-owned monitoring</p><h1>${escapeHtml57(title)}</h1><p class="pill ${escapeHtml57(report.status)}">Status: ${escapeHtml57(report.status)}</p><p class="pill">Open issues: ${String(report.summary.open)}</p><p class="pill">Critical: ${String(report.summary.criticalOpen)}</p></section><section class="card"><h2>Monitor Runs</h2><table><thead><tr><th>Monitor</th><th>Status</th><th>Severity</th><th>Value</th><th>Threshold</th><th>Detail</th></tr></thead><tbody>${runs}</tbody></table></section><section class="card"><h2>Issues</h2>${issues ? `<ul>${issues}</ul>` : '<p class="pass">No monitor issues.</p>'}</section><section class="card"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceMonitorRoutes(...)</code></h2><pre><code>${snippet}</code></pre></section></main></body></html>`;
38007
38436
  };
38008
38437
  var actorFromRequest = async (request) => {
38009
38438
  if (!request.headers.get("content-type")?.includes("application/json")) {
@@ -38027,7 +38456,7 @@ var createVoiceMonitorRoutes = (options) => {
38027
38456
  monitors: options.monitors,
38028
38457
  now: options.now
38029
38458
  });
38030
- const routes = new Elysia59({
38459
+ const routes = new Elysia60({
38031
38460
  name: options.name ?? "absolutejs-voice-monitoring"
38032
38461
  }).get(path, report).get(`${path}.md`, async () => {
38033
38462
  return new Response(renderVoiceMonitorMarkdown(await report()), {
@@ -38074,7 +38503,7 @@ var createVoiceMonitorRoutes = (options) => {
38074
38503
  };
38075
38504
  var createVoiceMonitorRunnerRoutes = (options) => {
38076
38505
  const path = options.path ?? "/api/voice/monitor-runner";
38077
- return new Elysia59({
38506
+ return new Elysia60({
38078
38507
  name: options.name ?? "absolutejs-voice-monitor-runner"
38079
38508
  }).get(path, () => ({
38080
38509
  isRunning: options.runner.isRunning()
@@ -38462,8 +38891,8 @@ var recommendVoiceReadinessProfile = (options) => {
38462
38891
  };
38463
38892
  };
38464
38893
  // src/providerStackRecommendations.ts
38465
- import { Elysia as Elysia60 } from "elysia";
38466
- var escapeHtml57 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
38894
+ import { Elysia as Elysia61 } from "elysia";
38895
+ var escapeHtml58 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
38467
38896
  var profileProviderPriorities = {
38468
38897
  "meeting-recorder": {
38469
38898
  llm: ["openai", "anthropic", "gemini"],
@@ -38778,17 +39207,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
38778
39207
  var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
38779
39208
  const title = options.title ?? "Voice Provider Contract Matrix";
38780
39209
  const rows = report.rows.map((row) => {
38781
- const checks = row.checks.map((check) => `<li class="${escapeHtml57(check.status)}"><strong>${escapeHtml57(check.label)}</strong><span>${escapeHtml57(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml57(check.remediation.href)}">${escapeHtml57(check.remediation.label)}</a>` : escapeHtml57(check.remediation.label)}: ${escapeHtml57(check.remediation.detail)}</em>` : ""}</li>`).join("");
38782
- return `<article class="row ${escapeHtml57(row.status)}">
39210
+ const checks = row.checks.map((check) => `<li class="${escapeHtml58(check.status)}"><strong>${escapeHtml58(check.label)}</strong><span>${escapeHtml58(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml58(check.remediation.href)}">${escapeHtml58(check.remediation.label)}</a>` : escapeHtml58(check.remediation.label)}: ${escapeHtml58(check.remediation.detail)}</em>` : ""}</li>`).join("");
39211
+ return `<article class="row ${escapeHtml58(row.status)}">
38783
39212
  <div>
38784
- <p class="eyebrow">${escapeHtml57(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
38785
- <h2>${escapeHtml57(row.provider)}</h2>
38786
- <p class="status ${escapeHtml57(row.status)}">${escapeHtml57(row.status.toUpperCase())}</p>
39213
+ <p class="eyebrow">${escapeHtml58(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
39214
+ <h2>${escapeHtml58(row.provider)}</h2>
39215
+ <p class="status ${escapeHtml58(row.status)}">${escapeHtml58(row.status.toUpperCase())}</p>
38787
39216
  </div>
38788
39217
  <ul>${checks}</ul>
38789
39218
  </article>`;
38790
39219
  }).join("");
38791
- const snippet = escapeHtml57(`const providerContracts = () =>
39220
+ const snippet = escapeHtml58(`const providerContracts = () =>
38792
39221
  createVoiceProviderContractMatrixPreset('phone-agent', {
38793
39222
  env: process.env,
38794
39223
  providers: {
@@ -38809,7 +39238,7 @@ createVoiceProductionReadinessRoutes({
38809
39238
  providerContractMatrix: () =>
38810
39239
  buildVoiceProviderContractMatrix(providerContracts())
38811
39240
  });`);
38812
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml57(title)}</title><style>body{background:#0f1412;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.row{background:#17201b;border:1px solid #2d3b32;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.16),rgba(125,211,252,.12))}.primitive{background:#111814;border-color:#41604a}.eyebrow{color:#86efac;font-size:.78rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill,.status{border:1px solid #3f4f45;border-radius:999px;display:inline-flex;padding:8px 12px}.primitive code{color:#bbf7d0}.primitive p{color:#c8d8ca;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#08110d;border:1px solid #294132;border-radius:18px;color:#d9f99d;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.row.pass,.pass{border-color:rgba(34,197,94,.65)}.status.warn,.row.warn,.warn{border-color:rgba(245,158,11,.7)}.status.fail,.row.fail,.fail{border-color:rgba(239,68,68,.75)}.row{display:grid;gap:20px;grid-template-columns:minmax(180px,.45fr) 1fr}.row ul{display:grid;gap:10px;list-style:none;margin:0;padding:0}.row li{background:#111814;border:1px solid #2d3b32;border-radius:16px;display:grid;gap:4px;padding:12px}.row li span{color:#b8c2ba}.row li em{color:#f9d77e;font-style:normal}.row li a{color:#86efac}@media(max-width:760px){main{padding:18px}.row{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider contracts</p><h1>${escapeHtml57(title)}</h1><p>Self-hosted provider proof for configured state, required env, latency budgets, fallback, streaming, and declared capabilities.</p><div class="summary"><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.warned)} warning</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} total</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProviderContractMatrixPreset(...)</code> builds this matrix</h2><p>Give AbsoluteJS your configured LLM, STT, and TTS providers once. It turns them into deploy-checkable proof for env, fallback, streaming, latency budgets, selected providers, and profile-required capabilities without a hosted dashboard.</p><pre><code>${snippet}</code></pre></section>${rows || '<article class="row"><p>No provider contracts configured.</p></article>'}</main></body></html>`;
39241
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml58(title)}</title><style>body{background:#0f1412;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.row{background:#17201b;border:1px solid #2d3b32;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.16),rgba(125,211,252,.12))}.primitive{background:#111814;border-color:#41604a}.eyebrow{color:#86efac;font-size:.78rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill,.status{border:1px solid #3f4f45;border-radius:999px;display:inline-flex;padding:8px 12px}.primitive code{color:#bbf7d0}.primitive p{color:#c8d8ca;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#08110d;border:1px solid #294132;border-radius:18px;color:#d9f99d;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.row.pass,.pass{border-color:rgba(34,197,94,.65)}.status.warn,.row.warn,.warn{border-color:rgba(245,158,11,.7)}.status.fail,.row.fail,.fail{border-color:rgba(239,68,68,.75)}.row{display:grid;gap:20px;grid-template-columns:minmax(180px,.45fr) 1fr}.row ul{display:grid;gap:10px;list-style:none;margin:0;padding:0}.row li{background:#111814;border:1px solid #2d3b32;border-radius:16px;display:grid;gap:4px;padding:12px}.row li span{color:#b8c2ba}.row li em{color:#f9d77e;font-style:normal}.row li a{color:#86efac}@media(max-width:760px){main{padding:18px}.row{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider contracts</p><h1>${escapeHtml58(title)}</h1><p>Self-hosted provider proof for configured state, required env, latency budgets, fallback, streaming, and declared capabilities.</p><div class="summary"><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.warned)} warning</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} total</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProviderContractMatrixPreset(...)</code> builds this matrix</h2><p>Give AbsoluteJS your configured LLM, STT, and TTS providers once. It turns them into deploy-checkable proof for env, fallback, streaming, latency budgets, selected providers, and profile-required capabilities without a hosted dashboard.</p><pre><code>${snippet}</code></pre></section>${rows || '<article class="row"><p>No provider contracts configured.</p></article>'}</main></body></html>`;
38813
39242
  };
38814
39243
  var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
38815
39244
  var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
@@ -38824,7 +39253,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
38824
39253
  var createVoiceProviderContractMatrixRoutes = (options) => {
38825
39254
  const path = options.path ?? "/api/provider-contracts";
38826
39255
  const htmlPath = options.htmlPath ?? "/provider-contracts";
38827
- const routes = new Elysia60({
39256
+ const routes = new Elysia61({
38828
39257
  name: options.name ?? "absolutejs-voice-provider-contract-matrix"
38829
39258
  });
38830
39259
  const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
@@ -38942,7 +39371,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
38942
39371
  return assertion;
38943
39372
  };
38944
39373
  // src/opsConsoleRoutes.ts
38945
- import { Elysia as Elysia61 } from "elysia";
39374
+ import { Elysia as Elysia62 } from "elysia";
38946
39375
  var DEFAULT_LINKS = [
38947
39376
  {
38948
39377
  description: "Quality gates for CI, deploy checks, and production readiness.",
@@ -38977,7 +39406,7 @@ var DEFAULT_LINKS = [
38977
39406
  label: "Handoffs"
38978
39407
  }
38979
39408
  ];
38980
- var escapeHtml58 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
39409
+ var escapeHtml59 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
38981
39410
  var countProviderStatuses = (providers) => {
38982
39411
  const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
38983
39412
  const healthy = providers.filter((provider) => provider.status === "healthy").length;
@@ -39046,20 +39475,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
39046
39475
  trace
39047
39476
  };
39048
39477
  };
39049
- var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml58(input.label)}</span><strong>${escapeHtml58(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml58(input.status)}">${escapeHtml58(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml58(input.href)}">Open</a>` : ""}</article>`;
39478
+ var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml59(input.label)}</span><strong>${escapeHtml59(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml59(input.status)}">${escapeHtml59(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml59(input.href)}">Open</a>` : ""}</article>`;
39050
39479
  var renderVoiceOpsConsoleHTML = (report, options = {}) => {
39051
39480
  const links = report.links.map((link) => `<article class="surface">
39052
- <div><h2>${escapeHtml58(link.label)}</h2>${link.description ? `<p>${escapeHtml58(link.description)}</p>` : ""}</div>
39053
- <p><a href="${escapeHtml58(link.href)}">Open ${escapeHtml58(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml58(link.statusHref)}">Status</a>` : ""}</p>
39481
+ <div><h2>${escapeHtml59(link.label)}</h2>${link.description ? `<p>${escapeHtml59(link.description)}</p>` : ""}</div>
39482
+ <p><a href="${escapeHtml59(link.href)}">Open ${escapeHtml59(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml59(link.statusHref)}">Status</a>` : ""}</p>
39054
39483
  </article>`).join("");
39055
- const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml58(session.sessionId)}</td><td>${escapeHtml58(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml58(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
39056
- const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml58(event.kind)}</td><td>${escapeHtml58(event.provider ?? "unknown")}</td><td>${escapeHtml58(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml58(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
39484
+ const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml59(session.sessionId)}</td><td>${escapeHtml59(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml59(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
39485
+ const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml59(event.kind)}</td><td>${escapeHtml59(event.provider ?? "unknown")}</td><td>${escapeHtml59(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml59(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
39057
39486
  const title = options.title ?? "AbsoluteJS Voice Ops Console";
39058
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml58(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#101316;color:#f6f2e8;margin:0}main{max-width:1180px;margin:auto;padding:32px}a{color:#fbbf24}header{display:flex;justify-content:space-between;gap:24px;align-items:flex-start;margin-bottom:24px}.eyebrow{color:#fbbf24;font-weight:800;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.2rem,5vw,4.5rem);line-height:.95;margin:.2rem 0 1rem}.muted{color:#a8b0b8}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px 0}.metric,.surface{background:#181d22;border:1px solid #2a323a;border-radius:20px;padding:18px}.metric strong{display:block;font-size:2.2rem;margin:.25rem 0}.pass,.healthy{color:#86efac}.fail,.failed,.degraded{color:#fca5a5}.surfaces{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:24px 0}table{width:100%;border-collapse:collapse;background:#181d22;border-radius:16px;overflow:hidden;margin:12px 0 28px}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left}section{margin-top:30px}@media(max-width:700px){main{padding:20px}header{display:block}}</style></head><body><main><header><div><p class="eyebrow">Self-hosted voice operations</p><h1>${escapeHtml58(title)}</h1><p class="muted">One deployable control plane for quality gates, failover, traces, sessions, handoffs, and provider health.</p></div><p class="muted">Checked ${escapeHtml58(new Date(report.checkedAt).toLocaleString())}</p></header><div class="grid">${renderMetricCard({ label: "Quality", value: report.quality.status, status: report.quality.status, href: "/quality" })}${renderMetricCard({ label: "Events", value: report.eventCount, href: "/diagnostics" })}${renderMetricCard({ label: "Sessions", value: report.sessions.total, status: report.sessions.failed > 0 ? "failed" : "healthy", href: "/sessions" })}${renderMetricCard({ label: "Handoffs failed", value: report.handoffs.failed, status: report.handoffs.failed > 0 ? "failed" : "healthy", href: "/handoffs" })}${renderMetricCard({ label: "Providers degraded", value: report.providers.degraded, status: report.providers.degraded > 0 ? "degraded" : "healthy", href: "/resilience" })}</div><section><h2>Operational Surfaces</h2><div class="surfaces">${links}</div></section><section><h2>Recent Sessions</h2><table><thead><tr><th>Session</th><th>Status</th><th>Turns</th><th>Errors</th><th>Replay</th></tr></thead><tbody>${sessions}</tbody></table></section><section><h2>Recent Provider Routing</h2><table><thead><tr><th>Kind</th><th>Provider</th><th>Status</th><th>Elapsed</th><th>Session</th></tr></thead><tbody>${routing}</tbody></table></section></main></body></html>`;
39487
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml59(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#101316;color:#f6f2e8;margin:0}main{max-width:1180px;margin:auto;padding:32px}a{color:#fbbf24}header{display:flex;justify-content:space-between;gap:24px;align-items:flex-start;margin-bottom:24px}.eyebrow{color:#fbbf24;font-weight:800;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.2rem,5vw,4.5rem);line-height:.95;margin:.2rem 0 1rem}.muted{color:#a8b0b8}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px 0}.metric,.surface{background:#181d22;border:1px solid #2a323a;border-radius:20px;padding:18px}.metric strong{display:block;font-size:2.2rem;margin:.25rem 0}.pass,.healthy{color:#86efac}.fail,.failed,.degraded{color:#fca5a5}.surfaces{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:24px 0}table{width:100%;border-collapse:collapse;background:#181d22;border-radius:16px;overflow:hidden;margin:12px 0 28px}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left}section{margin-top:30px}@media(max-width:700px){main{padding:20px}header{display:block}}</style></head><body><main><header><div><p class="eyebrow">Self-hosted voice operations</p><h1>${escapeHtml59(title)}</h1><p class="muted">One deployable control plane for quality gates, failover, traces, sessions, handoffs, and provider health.</p></div><p class="muted">Checked ${escapeHtml59(new Date(report.checkedAt).toLocaleString())}</p></header><div class="grid">${renderMetricCard({ label: "Quality", value: report.quality.status, status: report.quality.status, href: "/quality" })}${renderMetricCard({ label: "Events", value: report.eventCount, href: "/diagnostics" })}${renderMetricCard({ label: "Sessions", value: report.sessions.total, status: report.sessions.failed > 0 ? "failed" : "healthy", href: "/sessions" })}${renderMetricCard({ label: "Handoffs failed", value: report.handoffs.failed, status: report.handoffs.failed > 0 ? "failed" : "healthy", href: "/handoffs" })}${renderMetricCard({ label: "Providers degraded", value: report.providers.degraded, status: report.providers.degraded > 0 ? "degraded" : "healthy", href: "/resilience" })}</div><section><h2>Operational Surfaces</h2><div class="surfaces">${links}</div></section><section><h2>Recent Sessions</h2><table><thead><tr><th>Session</th><th>Status</th><th>Turns</th><th>Errors</th><th>Replay</th></tr></thead><tbody>${sessions}</tbody></table></section><section><h2>Recent Provider Routing</h2><table><thead><tr><th>Kind</th><th>Provider</th><th>Status</th><th>Elapsed</th><th>Session</th></tr></thead><tbody>${routing}</tbody></table></section></main></body></html>`;
39059
39488
  };
39060
39489
  var createVoiceOpsConsoleRoutes = (options) => {
39061
39490
  const path = options.path ?? "/ops-console";
39062
- const routes = new Elysia61({
39491
+ const routes = new Elysia62({
39063
39492
  name: options.name ?? "absolutejs-voice-ops-console"
39064
39493
  });
39065
39494
  const getReport = () => buildVoiceOpsConsoleReport(options);
@@ -39075,246 +39504,6 @@ var createVoiceOpsConsoleRoutes = (options) => {
39075
39504
  routes.get(`${path}/json`, async () => getReport());
39076
39505
  return routes;
39077
39506
  };
39078
- // src/sessionObservability.ts
39079
- import { Elysia as Elysia62 } from "elysia";
39080
- var escapeHtml59 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
39081
- var formatMs6 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
39082
- var resolveHref = (href, sessionId) => {
39083
- if (href === false) {
39084
- return;
39085
- }
39086
- if (typeof href === "function") {
39087
- return href(sessionId);
39088
- }
39089
- if (typeof href === "string") {
39090
- return href.includes(":sessionId") ? href.replaceAll(":sessionId", encodeURIComponent(sessionId)) : `${href.replace(/\/$/, "")}/${encodeURIComponent(sessionId)}`;
39091
- }
39092
- return;
39093
- };
39094
- var buildLinks = (options) => {
39095
- const links = [];
39096
- const add = (rel, label, href) => {
39097
- if (href) {
39098
- links.push({ href, label, rel });
39099
- }
39100
- };
39101
- add("operations-record", "Open operations record", resolveHref(options.operationsRecordHref, options.sessionId));
39102
- add("trace-timeline", "Open trace timeline", resolveHref(options.traceTimelineHref, options.sessionId));
39103
- add("call-debugger", "Open call debugger", resolveHref(options.callDebuggerHref, options.sessionId));
39104
- add("incident-markdown", "Download incident Markdown", resolveHref(options.incidentMarkdownHref, options.sessionId));
39105
- return [...links, ...options.customLinks ?? []];
39106
- };
39107
- var buildTurnWaterfalls = (record) => {
39108
- const byTurn = new Map;
39109
- const getTurn = (turnId) => {
39110
- const existing = byTurn.get(turnId);
39111
- if (existing) {
39112
- return existing;
39113
- }
39114
- const turn = {
39115
- assistantReplies: 0,
39116
- errors: 0,
39117
- providerDecisions: 0,
39118
- stages: [],
39119
- toolCalls: 0,
39120
- transcripts: 0
39121
- };
39122
- byTurn.set(turnId, turn);
39123
- return turn;
39124
- };
39125
- for (const event of record.timeline) {
39126
- if (!event.turnId) {
39127
- continue;
39128
- }
39129
- const turn = getTurn(event.turnId);
39130
- turn.stages.push({
39131
- at: event.at,
39132
- elapsedMs: event.elapsedMs,
39133
- label: event.label,
39134
- offsetMs: event.offsetMs,
39135
- provider: event.provider,
39136
- status: event.status,
39137
- type: event.type
39138
- });
39139
- if (event.type === "turn.transcript") {
39140
- turn.transcripts += 1;
39141
- }
39142
- if (event.type === "turn.assistant") {
39143
- turn.assistantReplies += 1;
39144
- }
39145
- if (event.type === "agent.tool") {
39146
- turn.toolCalls += 1;
39147
- }
39148
- if (event.type === "provider.decision") {
39149
- turn.providerDecisions += 1;
39150
- }
39151
- if (event.type === "session.error" || event.status === "error") {
39152
- turn.errors += 1;
39153
- }
39154
- }
39155
- for (const transcript of record.transcript) {
39156
- const turn = getTurn(transcript.id);
39157
- turn.assistantReplies = Math.max(turn.assistantReplies, transcript.assistantReplies.length);
39158
- turn.errors += transcript.errors.length;
39159
- turn.transcripts = Math.max(turn.transcripts, transcript.transcripts.length);
39160
- }
39161
- return [...byTurn.entries()].map(([turnId, turn]) => {
39162
- const startedAt = turn.stages[0]?.at;
39163
- const endedAt = turn.stages.at(-1)?.at;
39164
- return {
39165
- assistantReplies: turn.assistantReplies,
39166
- durationMs: startedAt !== undefined && endedAt !== undefined ? Math.max(0, endedAt - startedAt) : undefined,
39167
- endedAt,
39168
- errors: turn.errors,
39169
- providerDecisions: turn.providerDecisions,
39170
- stages: turn.stages,
39171
- startedAt,
39172
- toolCalls: turn.toolCalls,
39173
- transcripts: turn.transcripts,
39174
- turnId
39175
- };
39176
- }).sort((left, right) => (left.startedAt ?? 0) - (right.startedAt ?? 0));
39177
- };
39178
- var buildVoiceSessionObservabilityReport = async (options) => {
39179
- const record = await buildVoiceOperationsRecord({
39180
- audit: options.audit,
39181
- evaluation: options.evaluation,
39182
- events: options.events,
39183
- integrationEvents: options.integrationEvents,
39184
- redact: options.redact,
39185
- reviews: options.reviews,
39186
- sessionId: options.sessionId,
39187
- store: options.store,
39188
- tasks: options.tasks
39189
- });
39190
- const failureReplay = buildVoiceFailureReplay(record, {
39191
- operationsRecordHref: resolveHref(options.operationsRecordHref, options.sessionId)
39192
- });
39193
- const incidentMarkdown = renderVoiceOperationsRecordIncidentMarkdown(record);
39194
- const statuses = [
39195
- record.status,
39196
- failureReplay.status === "failed" ? "failed" : failureReplay.status === "degraded" ? "warning" : "healthy"
39197
- ];
39198
- const status = statuses.includes("failed") ? "failed" : statuses.includes("warning") ? "warning" : "healthy";
39199
- return {
39200
- checkedAt: Date.now(),
39201
- failureReplay,
39202
- incidentMarkdown,
39203
- links: buildLinks(options),
39204
- record,
39205
- sessionId: options.sessionId,
39206
- status,
39207
- summary: {
39208
- durationMs: record.summary.callDurationMs,
39209
- errors: record.summary.errorCount,
39210
- events: record.summary.eventCount,
39211
- fallbacks: record.providerDecisionSummary.fallbacks,
39212
- guardrailBlocks: record.guardrails.blocked,
39213
- handoffs: record.handoffs.length,
39214
- providerRecoveryStatus: record.providerDecisionSummary.recoveryStatus,
39215
- providers: record.providerDecisionSummary.providers,
39216
- telephonyMediaEvents: record.telephonyMedia.total,
39217
- toolCalls: record.tools.length,
39218
- turns: record.summary.turnCount
39219
- },
39220
- turns: buildTurnWaterfalls(record)
39221
- };
39222
- };
39223
- var renderLinks = (links) => links.length === 0 ? "" : `<div class="actions">${links.map((link) => `<a href="${escapeHtml59(link.href)}">${escapeHtml59(link.label)}</a>`).join("")}</div>`;
39224
- var renderTurns = (turns) => turns.length === 0 ? '<p class="muted">No turn-level events recorded yet.</p>' : turns.map((turn) => `<article class="turn"><header><strong>${escapeHtml59(turn.turnId)}</strong><span>${formatMs6(turn.durationMs)}</span></header><dl><div><dt>Transcripts</dt><dd>${String(turn.transcripts)}</dd></div><div><dt>Assistant</dt><dd>${String(turn.assistantReplies)}</dd></div><div><dt>Tools</dt><dd>${String(turn.toolCalls)}</dd></div><div><dt>Providers</dt><dd>${String(turn.providerDecisions)}</dd></div><div><dt>Errors</dt><dd>${String(turn.errors)}</dd></div></dl><table><thead><tr><th>Offset</th><th>Type</th><th>Stage</th><th>Provider</th><th>Status</th><th>Latency</th></tr></thead><tbody>${turn.stages.map((stage) => `<tr><td>+${String(stage.offsetMs)}ms</td><td>${escapeHtml59(stage.type)}</td><td>${escapeHtml59(stage.label)}</td><td>${escapeHtml59(stage.provider ?? "")}</td><td>${escapeHtml59(stage.status ?? "")}</td><td>${formatMs6(stage.elapsedMs)}</td></tr>`).join("")}</tbody></table></article>`).join("");
39225
- var renderVoiceSessionObservabilityMarkdown = (report) => `# Voice session observability: ${report.sessionId}
39226
-
39227
- Status: ${report.status}
39228
-
39229
- - Events: ${report.summary.events}
39230
- - Turns: ${report.summary.turns}
39231
- - Errors: ${report.summary.errors}
39232
- - Duration: ${formatMs6(report.summary.durationMs)}
39233
- - Providers: ${report.summary.providers.join(", ") || "none"}
39234
- - Provider recovery: ${report.summary.providerRecoveryStatus}
39235
- - Fallbacks: ${report.summary.fallbacks}
39236
- - Tool calls: ${report.summary.toolCalls}
39237
- - Handoffs: ${report.summary.handoffs}
39238
- - Guardrail blocks: ${report.summary.guardrailBlocks}
39239
- - Telephony media events: ${report.summary.telephonyMediaEvents}
39240
-
39241
- ## Links
39242
-
39243
- ${report.links.length ? report.links.map((link) => `- [${link.label}](${link.href})`).join(`
39244
- `) : "- none"}
39245
-
39246
- ## Turn Waterfalls
39247
-
39248
- ${report.turns.length ? report.turns.map((turn) => `### ${turn.turnId}
39249
-
39250
- - Duration: ${formatMs6(turn.durationMs)}
39251
- - Transcripts: ${turn.transcripts}
39252
- - Assistant replies: ${turn.assistantReplies}
39253
- - Tool calls: ${turn.toolCalls}
39254
- - Provider decisions: ${turn.providerDecisions}
39255
- - Errors: ${turn.errors}
39256
-
39257
- ${turn.stages.map((stage) => `- +${stage.offsetMs}ms ${stage.type}: ${stage.label}${stage.provider ? ` (${stage.provider})` : ""}${stage.status ? ` [${stage.status}]` : ""}`).join(`
39258
- `)}`).join(`
39259
-
39260
- `) : "No turn-level events recorded."}
39261
-
39262
- ## Incident Handoff
39263
-
39264
- ${report.incidentMarkdown}`;
39265
- var renderVoiceSessionObservabilityHTML = (report, options = {}) => `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml59(options.title ?? "Voice Session Observability")}</title><style>body{background:#0d1412;color:#f7f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.eyebrow{color:#fbbf24;font-size:.78rem;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 #425046;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.actions{display:flex;flex-wrap:wrap;gap:10px;margin:18px 0}.actions a{background:#fbbf24;border-radius:999px;color:#111827;font-weight:900;padding:10px 14px;text-decoration:none}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:22px 0}.card,.turn,.incident{background:#17201c;border:1px solid #2e3c35;border-radius:20px;padding:16px}.card span,.muted,dt{color:#a8b4ad}.card strong{display:block;font-size:2rem}section{margin-top:30px}.turn{margin:16px 0}.turn header{align-items:center;display:flex;justify-content:space-between;gap:14px}dl{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));margin:14px 0}dd{font-weight:900;margin:3px 0 0}table{border-collapse:collapse;margin-top:14px;width:100%}td,th{border-top:1px solid #2e3c35;padding:10px;text-align:left}pre{background:#08100d;border:1px solid #2e3c35;border-radius:16px;color:#d9f99d;overflow:auto;padding:14px}@media(max-width:760px){main{padding:20px}table{font-size:.9rem}}</style></head><body><main><header><p class="eyebrow">Session observability</p><h1>${escapeHtml59(report.sessionId)}</h1><p class="status ${escapeHtml59(report.status)}">${escapeHtml59(report.status)}</p>${renderLinks(report.links)}<p class="muted">One support/debug report across trace timeline, operations record, provider recovery, turn waterfalls, guardrails, tools, handoffs, failure replay, and incident handoff.</p></header><section class="grid"><article class="card"><span>Events</span><strong>${String(report.summary.events)}</strong></article><article class="card"><span>Turns</span><strong>${String(report.summary.turns)}</strong></article><article class="card"><span>Errors</span><strong>${String(report.summary.errors)}</strong></article><article class="card"><span>Duration</span><strong>${formatMs6(report.summary.durationMs)}</strong></article><article class="card"><span>Fallbacks</span><strong>${String(report.summary.fallbacks)}</strong></article><article class="card"><span>Tools</span><strong>${String(report.summary.toolCalls)}</strong></article><article class="card"><span>Handoffs</span><strong>${String(report.summary.handoffs)}</strong></article><article class="card"><span>Guardrails blocked</span><strong>${String(report.summary.guardrailBlocks)}</strong></article><article class="card"><span>Telephony media</span><strong>${String(report.summary.telephonyMediaEvents)}</strong></article></section><section><h2>Turn Waterfalls</h2>${renderTurns(report.turns)}</section><section class="incident"><h2>Incident Handoff</h2><pre><code>${escapeHtml59(report.incidentMarkdown)}</code></pre></section></main></body></html>`;
39266
- var routeSessionId = (params) => typeof params.sessionId === "string" ? params.sessionId : "";
39267
- var createVoiceSessionObservabilityRoutes = (options) => {
39268
- const path = options.path ?? "/api/voice/session-observability/:sessionId";
39269
- const htmlPath = options.htmlPath ?? "/voice/session-observability/:sessionId";
39270
- const incidentPath = options.incidentPath ?? "/api/voice/session-observability/:sessionId/incident.md";
39271
- const title = options.title ?? "AbsoluteJS Voice Session Observability";
39272
- const routes = new Elysia62({
39273
- name: options.name ?? "absolutejs-voice-session-observability"
39274
- });
39275
- const build = (sessionId) => buildVoiceSessionObservabilityReport({
39276
- audit: options.audit,
39277
- callDebuggerHref: options.callDebuggerHref,
39278
- customLinks: options.customLinks,
39279
- evaluation: options.evaluation,
39280
- events: options.events,
39281
- incidentMarkdownHref: options.incidentMarkdownHref ?? (incidentPath === false ? false : incidentPath),
39282
- integrationEvents: options.integrationEvents,
39283
- operationsRecordHref: options.operationsRecordHref,
39284
- redact: options.redact,
39285
- reviews: options.reviews,
39286
- sessionId,
39287
- store: options.store,
39288
- tasks: options.tasks,
39289
- traceTimelineHref: options.traceTimelineHref
39290
- });
39291
- routes.get(path, async ({ params }) => Response.json(await build(routeSessionId(params))));
39292
- if (htmlPath !== false) {
39293
- routes.get(htmlPath, async ({ params }) => {
39294
- const report = await build(routeSessionId(params));
39295
- const body = await (options.render ?? ((input) => renderVoiceSessionObservabilityHTML(input, { title })))(report);
39296
- return new Response(body, {
39297
- headers: {
39298
- "content-type": "text/html; charset=utf-8",
39299
- ...options.headers
39300
- }
39301
- });
39302
- });
39303
- }
39304
- if (incidentPath !== false) {
39305
- routes.get(incidentPath, async ({ params }) => {
39306
- const report = await build(routeSessionId(params));
39307
- const body = await (options.renderIncidentMarkdown ?? renderVoiceSessionObservabilityMarkdown)(report);
39308
- return new Response(body, {
39309
- headers: {
39310
- "content-type": "text/markdown; charset=utf-8",
39311
- ...options.headers
39312
- }
39313
- });
39314
- });
39315
- }
39316
- return routes;
39317
- };
39318
39507
  // src/incidentBundle.ts
39319
39508
  import { Elysia as Elysia63 } from "elysia";
39320
39509
  var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
@@ -43113,6 +43302,7 @@ export {
43113
43302
  evaluateVoiceTelephonyWebhookNormalizationEvidence,
43114
43303
  evaluateVoiceTelephonyContract,
43115
43304
  evaluateVoiceSimulationSuiteEvidence,
43305
+ evaluateVoiceSessionObservabilityEvidence,
43116
43306
  evaluateVoiceRealtimeProviderContractEvidence,
43117
43307
  evaluateVoiceRealtimeChannelEvidence,
43118
43308
  evaluateVoiceQuality,
@@ -43507,6 +43697,8 @@ export {
43507
43697
  buildVoiceRealCallProfileHistoryReportFromStore,
43508
43698
  buildVoiceRealCallProfileHistoryReport,
43509
43699
  buildVoiceRealCallProfileEvidenceFromTraceEvents,
43700
+ buildVoiceRealCallProfileEvidenceFromRuntimeSurface,
43701
+ buildVoiceRealCallProfileEvidenceFromRuntimeProviderRoles,
43510
43702
  buildVoiceRealCallProfileEvidenceFromReconnectProofReports,
43511
43703
  buildVoiceRealCallProfileDefaults,
43512
43704
  buildVoiceRealCallEvidenceRuntimeWorkerReadinessCheck,
@@ -43575,6 +43767,7 @@ export {
43575
43767
  assertVoiceTelephonyWebhookNormalizationEvidence,
43576
43768
  assertVoiceSloCalibration,
43577
43769
  assertVoiceSimulationSuiteEvidence,
43770
+ assertVoiceSessionObservabilityEvidence,
43578
43771
  assertVoiceRealtimeProviderContractEvidence,
43579
43772
  assertVoiceRealtimeChannelEvidence,
43580
43773
  assertVoiceProviderStackEvidence,