@absolutejs/voice 0.0.22-beta.400 → 0.0.22-beta.401

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.
@@ -3071,6 +3071,7 @@ var DEFAULT_TITLE = "Session Snapshot";
3071
3071
  var DEFAULT_DESCRIPTION = "Portable call artifact with media graph, provider routing, proof, quality, and telephony evidence.";
3072
3072
  var DEFAULT_DOWNLOAD_LABEL = "Download snapshot";
3073
3073
  var escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3074
+ var formatStatus = (status) => status ?? "n/a";
3074
3075
  var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
3075
3076
  const snapshot = state.snapshot;
3076
3077
  const failedProofs = snapshot?.proofSummary.failed ?? 0;
@@ -3078,7 +3079,13 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
3078
3079
  const timingWarnings = snapshot?.media.reduce((total, media) => total + media.report.timing.overBudgetFrames, 0) ?? 0;
3079
3080
  const backpressureDrops = snapshot?.media.reduce((total, media) => total + media.report.backpressure.droppedFrames, 0) ?? 0;
3080
3081
  const qualityWarnings = snapshot?.quality.filter((quality) => quality.status !== "pass").length ?? 0;
3082
+ const artifactWarnings = snapshot?.artifacts.filter((artifact) => artifact.status !== undefined && artifact.status !== "pass").length ?? 0;
3081
3083
  return {
3084
+ artifacts: snapshot?.artifacts.map((artifact) => ({
3085
+ href: artifact.href,
3086
+ label: artifact.label,
3087
+ status: formatStatus(artifact.status)
3088
+ })) ?? [],
3082
3089
  description: options.description ?? DEFAULT_DESCRIPTION,
3083
3090
  error: state.error,
3084
3091
  isLoading: state.isLoading,
@@ -3090,6 +3097,8 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
3090
3097
  { label: "Backpressure drops", value: String(backpressureDrops) },
3091
3098
  { label: "Proof failures", value: String(failedProofs) },
3092
3099
  { label: "Quality warnings", value: String(qualityWarnings) },
3100
+ { label: "Debug artifacts", value: String(snapshot.artifacts.length) },
3101
+ { label: "Artifact warnings", value: String(artifactWarnings) },
3093
3102
  {
3094
3103
  label: "Provider routing",
3095
3104
  value: String(snapshot.providerRoutingEvents.length)
@@ -3111,6 +3120,10 @@ var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
3111
3120
  <dt>${escapeHtml(row.label)}</dt>
3112
3121
  <dd>${escapeHtml(row.value)}</dd>
3113
3122
  </div>`).join("")}</dl>` : '<p class="absolute-voice-session-snapshot__empty">Load a session snapshot to see support diagnostics.</p>';
3123
+ const artifacts = model.artifacts.length ? `<div class="absolute-voice-session-snapshot__artifacts">${model.artifacts.map((artifact) => {
3124
+ const body = `<strong>${escapeHtml(artifact.label)}</strong><span>${escapeHtml(artifact.status)}</span>`;
3125
+ return artifact.href ? `<a href="${escapeHtml(artifact.href)}">${body}</a>` : `<div>${body}</div>`;
3126
+ }).join("")}</div>` : "";
3114
3127
  return `<section class="absolute-voice-session-snapshot absolute-voice-session-snapshot--${escapeHtml(model.status)}">
3115
3128
  <header class="absolute-voice-session-snapshot__header">
3116
3129
  <span class="absolute-voice-session-snapshot__eyebrow">${escapeHtml(model.title)}</span>
@@ -3119,6 +3132,7 @@ var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
3119
3132
  <p class="absolute-voice-session-snapshot__description">${escapeHtml(model.description)}</p>
3120
3133
  ${model.showDownload ? `<button class="absolute-voice-session-snapshot__download" data-absolute-voice-session-snapshot-download type="button">${escapeHtml(options.downloadLabel ?? DEFAULT_DOWNLOAD_LABEL)}</button>` : ""}
3121
3134
  ${rows}
3135
+ ${artifacts}
3122
3136
  ${model.error ? `<p class="absolute-voice-session-snapshot__error">${escapeHtml(model.error)}</p>` : ""}
3123
3137
  </section>`;
3124
3138
  };
@@ -4020,7 +4034,7 @@ var DEFAULT_LINKS = [
4020
4034
  { href: "/api/voice/vapi-coverage", label: "Coverage JSON" }
4021
4035
  ];
4022
4036
  var escapeHtml3 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4023
- var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
4037
+ var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
4024
4038
  var surfaceDetail2 = (surface) => {
4025
4039
  if (surface.status === "pass") {
4026
4040
  return surface.replacement;
@@ -4059,7 +4073,7 @@ var renderVoicePlatformCoverageHTML = (snapshot, options = {}) => {
4059
4073
  const surfaces = model.surfaces.length ? `<div class="absolute-voice-platform-coverage__surfaces">${model.surfaces.map((surface) => `<article class="absolute-voice-platform-coverage__surface absolute-voice-platform-coverage__surface--${escapeHtml3(surface.status)}">
4060
4074
  <header>
4061
4075
  <strong>${escapeHtml3(surface.label)}</strong>
4062
- <span>${escapeHtml3(formatStatus(surface.status))}</span>
4076
+ <span>${escapeHtml3(formatStatus2(surface.status))}</span>
4063
4077
  </header>
4064
4078
  <p>${escapeHtml3(surface.detail)}</p>
4065
4079
  <small>${surface.evidence.filter((item) => item.ok).length}/${surface.evidence.length} evidence checks passing</small>
@@ -10303,7 +10317,7 @@ var DEFAULT_TITLE11 = "Voice Providers";
10303
10317
  var DEFAULT_DESCRIPTION11 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
10304
10318
  var escapeHtml19 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10305
10319
  var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
10306
- var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
10320
+ var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
10307
10321
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
10308
10322
  var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
10309
10323
  var getProviderDetail = (provider) => {
@@ -10360,7 +10374,7 @@ var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
10360
10374
  const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml19(provider.status)}">
10361
10375
  <header>
10362
10376
  <strong>${escapeHtml19(provider.label)}</strong>
10363
- <span>${escapeHtml19(formatStatus2(provider.status))}</span>
10377
+ <span>${escapeHtml19(formatStatus3(provider.status))}</span>
10364
10378
  </header>
10365
10379
  <p>${escapeHtml19(provider.detail)}</p>
10366
10380
  <dl>${provider.rows.map((row) => `<div>
@@ -10421,7 +10435,7 @@ var DEFAULT_DESCRIPTION12 = "Configured, selected, and healthy voice providers f
10421
10435
  var escapeHtml20 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10422
10436
  var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
10423
10437
  var formatKind2 = (kind) => kind.toUpperCase();
10424
- var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
10438
+ var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
10425
10439
  var getCapabilityDetail = (capability) => {
10426
10440
  if (!capability.configured) {
10427
10441
  return "Not configured in this deployment.";
@@ -10447,7 +10461,7 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
10447
10461
  detail: getCapabilityDetail(capability),
10448
10462
  label: `${formatProvider2(capability.provider)} ${formatKind2(capability.kind)}`,
10449
10463
  rows: [
10450
- { label: "Status", value: formatStatus3(capability.status) },
10464
+ { label: "Status", value: formatStatus4(capability.status) },
10451
10465
  { label: "Selected", value: capability.selected ? "Yes" : "No" },
10452
10466
  { label: "Model", value: capability.model ?? "Default" },
10453
10467
  {
@@ -10476,7 +10490,7 @@ var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
10476
10490
  const capabilities = model.capabilities.length ? `<div class="absolute-voice-provider-capabilities__providers">${model.capabilities.map((capability) => `<article class="absolute-voice-provider-capabilities__provider absolute-voice-provider-capabilities__provider--${escapeHtml20(capability.status)}">
10477
10491
  <header>
10478
10492
  <strong>${escapeHtml20(capability.label)}</strong>
10479
- <span>${escapeHtml20(formatStatus3(capability.status))}</span>
10493
+ <span>${escapeHtml20(formatStatus4(capability.status))}</span>
10480
10494
  </header>
10481
10495
  <p>${escapeHtml20(capability.detail)}</p>
10482
10496
  <dl>${capability.rows.map((row) => `<div>
@@ -10536,7 +10550,7 @@ var DEFAULT_TITLE13 = "Provider Contracts";
10536
10550
  var DEFAULT_DESCRIPTION13 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
10537
10551
  var escapeHtml21 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10538
10552
  var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
10539
- var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
10553
+ var formatStatus5 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
10540
10554
  var contractDetail = (row) => {
10541
10555
  const failing = row.checks.filter((check) => check.status !== "pass");
10542
10556
  if (failing.length === 0) {
@@ -10555,12 +10569,12 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
10555
10569
  label: check.remediation?.label ?? check.label
10556
10570
  })),
10557
10571
  rows: [
10558
- { label: "Status", value: formatStatus4(row.status) },
10572
+ { label: "Status", value: formatStatus5(row.status) },
10559
10573
  { label: "Selected", value: row.selected ? "Yes" : "No" },
10560
10574
  { label: "Configured", value: row.configured ? "Yes" : "No" },
10561
10575
  {
10562
10576
  label: "Checks",
10563
- value: row.checks.map((check) => `${check.label}: ${formatStatus4(check.status)}`).join(", ")
10577
+ value: row.checks.map((check) => `${check.label}: ${formatStatus5(check.status)}`).join(", ")
10564
10578
  }
10565
10579
  ]
10566
10580
  }));
@@ -10581,7 +10595,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
10581
10595
  const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml21(row.status)}">
10582
10596
  <header>
10583
10597
  <strong>${escapeHtml21(row.label)}</strong>
10584
- <span>${escapeHtml21(formatStatus4(row.status))}</span>
10598
+ <span>${escapeHtml21(formatStatus5(row.status))}</span>
10585
10599
  </header>
10586
10600
  <p>${escapeHtml21(row.detail)}</p>
10587
10601
  ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml21(remediation.href)}">${escapeHtml21(remediation.label)}</a>` : `<strong>${escapeHtml21(remediation.label)}</strong>`}<span>${escapeHtml21(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
@@ -1,5 +1,10 @@
1
1
  import { type VoiceSessionSnapshotClientOptions, type VoiceSessionSnapshotClientState } from './sessionSnapshot';
2
2
  export type VoiceSessionSnapshotViewModel = {
3
+ artifacts: Array<{
4
+ href?: string;
5
+ label: string;
6
+ status: string;
7
+ }>;
3
8
  description: string;
4
9
  error: string | null;
5
10
  isLoading: boolean;
package/dist/index.d.ts CHANGED
@@ -34,7 +34,7 @@ export { assertVoiceProofTrendEvidence, appendVoiceRealCallProfileRecoveryEviden
34
34
  export { createVoiceEvidenceAssertion, createVoiceProofAssertion, summarizeVoiceProofAssertions } from './proofAssertions';
35
35
  export { buildVoiceSessionSnapshot, buildVoiceSessionSnapshotStatus, createVoiceSessionSnapshotRoutes, parseVoiceSessionSnapshot } from './sessionSnapshot';
36
36
  export type { VoiceEvidenceAssertionInput, VoiceProofAssertionInput, VoiceProofAssertionResult, VoiceProofAssertionSummary } from './proofAssertions';
37
- export type { VoiceSessionSnapshot, VoiceSessionSnapshotInput, VoiceSessionSnapshotQualityEvidence, VoiceSessionSnapshotRoutesOptions, VoiceSessionSnapshotRouteSource, VoiceSessionSnapshotRouteSourceInput, VoiceSessionSnapshotStatus } from './sessionSnapshot';
37
+ export type { VoiceSessionSnapshot, VoiceSessionSnapshotArtifact, VoiceSessionSnapshotArtifactKind, VoiceSessionSnapshotInput, VoiceSessionSnapshotQualityEvidence, VoiceSessionSnapshotRoutesOptions, VoiceSessionSnapshotRouteSource, VoiceSessionSnapshotRouteSourceInput, VoiceSessionSnapshotStatus } from './sessionSnapshot';
38
38
  export { fetchVoiceProofTarget, getVoiceProofTargetLogicalFailure, mapVoiceProofTargetsWithConcurrency, runVoiceCommandProofTarget, runVoiceCommandProofTargets, runVoiceProofTargets } from './proofRunner';
39
39
  export type { VoiceCommandProofExecutionResult, VoiceCommandProofTarget, VoiceCommandProofTargetResult, VoiceCommandProofTargetRunnerOptions, VoiceCommandProofTargetRunOptions, VoiceProofTarget, VoiceProofTargetMethod, VoiceProofTargetResult, VoiceProofTargetRunnerOptions, VoiceProofTargetRunOptions } from './proofRunner';
40
40
  export { applyVoiceProfileSwitchGuard, buildVoiceProfileSwitchReadinessReport, buildVoiceProfileSwitchLiveDecisionReport, createVoiceProfileSwitchLiveDecisionRoutes, createVoiceProfileSwitchPolicyProofRoutes, createVoiceProfileSwitchReadinessRoutes, recommendVoiceProfileSwitch, renderVoiceProfileSwitchLiveDecisionHTML, renderVoiceProfileSwitchPolicyProofHTML, renderVoiceProfileSwitchReadinessHTML, runVoiceProfileSwitchPolicyProof } from './profileSwitchRecommendation';
package/dist/index.js CHANGED
@@ -18399,6 +18399,11 @@ var statusRank4 = (status) => {
18399
18399
  var maxStatus = (statuses) => statuses.reduce((current, status) => statusRank4(status) > statusRank4(current) ? status : current, "pass");
18400
18400
  var buildVoiceSessionSnapshotStatus = (input) => {
18401
18401
  const statuses = [];
18402
+ for (const artifact of input.artifacts ?? []) {
18403
+ if (artifact.status !== undefined) {
18404
+ statuses.push(artifact.status);
18405
+ }
18406
+ }
18402
18407
  for (const media of input.media ?? []) {
18403
18408
  statuses.push(media.report.status);
18404
18409
  }
@@ -18420,6 +18425,7 @@ var buildVoiceSessionSnapshotStatus = (input) => {
18420
18425
  return maxStatus(statuses);
18421
18426
  };
18422
18427
  var buildVoiceSessionSnapshot = (input) => {
18428
+ const artifacts = [...input.artifacts ?? []];
18423
18429
  const proofAssertions = [...input.proofAssertions ?? []];
18424
18430
  const proofSummary = summarizeVoiceProofAssertions(proofAssertions);
18425
18431
  const media = [...input.media ?? []];
@@ -18427,6 +18433,7 @@ var buildVoiceSessionSnapshot = (input) => {
18427
18433
  const quality = [...input.quality ?? []];
18428
18434
  const telephonyOutcomes = [...input.telephonyOutcomes ?? []];
18429
18435
  return {
18436
+ artifacts,
18430
18437
  capturedAt: Date.now(),
18431
18438
  media,
18432
18439
  name: input.name,
@@ -18438,6 +18445,7 @@ var buildVoiceSessionSnapshot = (input) => {
18438
18445
  schema: "absolute.voice.session.snapshot.v1",
18439
18446
  sessionId: input.sessionId,
18440
18447
  status: buildVoiceSessionSnapshotStatus({
18448
+ artifacts,
18441
18449
  media,
18442
18450
  proofSummary,
18443
18451
  quality,
@@ -18466,6 +18474,7 @@ var sessionSnapshotJsonResponse = (snapshot, headers = {}, downloadFilename) =>
18466
18474
  var resolveVoiceSessionSnapshot = async (options, input) => {
18467
18475
  const source = typeof options.source === "function" ? await options.source(input) : options.source ?? {
18468
18476
  media: options.media,
18477
+ artifacts: options.artifacts,
18469
18478
  name: options.name,
18470
18479
  proofAssertions: options.proofAssertions,
18471
18480
  providerRoutingEvents: options.providerRoutingEvents,
@@ -5643,6 +5643,7 @@ var DEFAULT_TITLE6 = "Session Snapshot";
5643
5643
  var DEFAULT_DESCRIPTION6 = "Portable call artifact with media graph, provider routing, proof, quality, and telephony evidence.";
5644
5644
  var DEFAULT_DOWNLOAD_LABEL = "Download snapshot";
5645
5645
  var escapeHtml11 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
5646
+ var formatStatus2 = (status) => status ?? "n/a";
5646
5647
  var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
5647
5648
  const snapshot = state.snapshot;
5648
5649
  const failedProofs = snapshot?.proofSummary.failed ?? 0;
@@ -5650,7 +5651,13 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
5650
5651
  const timingWarnings = snapshot?.media.reduce((total, media) => total + media.report.timing.overBudgetFrames, 0) ?? 0;
5651
5652
  const backpressureDrops = snapshot?.media.reduce((total, media) => total + media.report.backpressure.droppedFrames, 0) ?? 0;
5652
5653
  const qualityWarnings = snapshot?.quality.filter((quality) => quality.status !== "pass").length ?? 0;
5654
+ const artifactWarnings = snapshot?.artifacts.filter((artifact) => artifact.status !== undefined && artifact.status !== "pass").length ?? 0;
5653
5655
  return {
5656
+ artifacts: snapshot?.artifacts.map((artifact) => ({
5657
+ href: artifact.href,
5658
+ label: artifact.label,
5659
+ status: formatStatus2(artifact.status)
5660
+ })) ?? [],
5654
5661
  description: options.description ?? DEFAULT_DESCRIPTION6,
5655
5662
  error: state.error,
5656
5663
  isLoading: state.isLoading,
@@ -5662,6 +5669,8 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
5662
5669
  { label: "Backpressure drops", value: String(backpressureDrops) },
5663
5670
  { label: "Proof failures", value: String(failedProofs) },
5664
5671
  { label: "Quality warnings", value: String(qualityWarnings) },
5672
+ { label: "Debug artifacts", value: String(snapshot.artifacts.length) },
5673
+ { label: "Artifact warnings", value: String(artifactWarnings) },
5665
5674
  {
5666
5675
  label: "Provider routing",
5667
5676
  value: String(snapshot.providerRoutingEvents.length)
@@ -5683,6 +5692,10 @@ var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
5683
5692
  <dt>${escapeHtml11(row.label)}</dt>
5684
5693
  <dd>${escapeHtml11(row.value)}</dd>
5685
5694
  </div>`).join("")}</dl>` : '<p class="absolute-voice-session-snapshot__empty">Load a session snapshot to see support diagnostics.</p>';
5695
+ const artifacts = model.artifacts.length ? `<div class="absolute-voice-session-snapshot__artifacts">${model.artifacts.map((artifact) => {
5696
+ const body = `<strong>${escapeHtml11(artifact.label)}</strong><span>${escapeHtml11(artifact.status)}</span>`;
5697
+ return artifact.href ? `<a href="${escapeHtml11(artifact.href)}">${body}</a>` : `<div>${body}</div>`;
5698
+ }).join("")}</div>` : "";
5686
5699
  return `<section class="absolute-voice-session-snapshot absolute-voice-session-snapshot--${escapeHtml11(model.status)}">
5687
5700
  <header class="absolute-voice-session-snapshot__header">
5688
5701
  <span class="absolute-voice-session-snapshot__eyebrow">${escapeHtml11(model.title)}</span>
@@ -5691,6 +5704,7 @@ var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
5691
5704
  <p class="absolute-voice-session-snapshot__description">${escapeHtml11(model.description)}</p>
5692
5705
  ${model.showDownload ? `<button class="absolute-voice-session-snapshot__download" data-absolute-voice-session-snapshot-download type="button">${escapeHtml11(options.downloadLabel ?? DEFAULT_DOWNLOAD_LABEL)}</button>` : ""}
5693
5706
  ${rows}
5707
+ ${artifacts}
5694
5708
  ${model.error ? `<p class="absolute-voice-session-snapshot__error">${escapeHtml11(model.error)}</p>` : ""}
5695
5709
  </section>`;
5696
5710
  };
@@ -6943,7 +6957,7 @@ var DEFAULT_DESCRIPTION10 = "Configured, selected, and healthy voice providers f
6943
6957
  var escapeHtml16 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6944
6958
  var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
6945
6959
  var formatKind2 = (kind) => kind.toUpperCase();
6946
- var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
6960
+ var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
6947
6961
  var getCapabilityDetail = (capability) => {
6948
6962
  if (!capability.configured) {
6949
6963
  return "Not configured in this deployment.";
@@ -6969,7 +6983,7 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
6969
6983
  detail: getCapabilityDetail(capability),
6970
6984
  label: `${formatProvider(capability.provider)} ${formatKind2(capability.kind)}`,
6971
6985
  rows: [
6972
- { label: "Status", value: formatStatus2(capability.status) },
6986
+ { label: "Status", value: formatStatus3(capability.status) },
6973
6987
  { label: "Selected", value: capability.selected ? "Yes" : "No" },
6974
6988
  { label: "Model", value: capability.model ?? "Default" },
6975
6989
  {
@@ -6998,7 +7012,7 @@ var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
6998
7012
  const capabilities = model.capabilities.length ? `<div class="absolute-voice-provider-capabilities__providers">${model.capabilities.map((capability) => `<article class="absolute-voice-provider-capabilities__provider absolute-voice-provider-capabilities__provider--${escapeHtml16(capability.status)}">
6999
7013
  <header>
7000
7014
  <strong>${escapeHtml16(capability.label)}</strong>
7001
- <span>${escapeHtml16(formatStatus2(capability.status))}</span>
7015
+ <span>${escapeHtml16(formatStatus3(capability.status))}</span>
7002
7016
  </header>
7003
7017
  <p>${escapeHtml16(capability.detail)}</p>
7004
7018
  <dl>${capability.rows.map((row) => `<div>
@@ -7233,7 +7247,7 @@ var DEFAULT_TITLE11 = "Provider Contracts";
7233
7247
  var DEFAULT_DESCRIPTION11 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
7234
7248
  var escapeHtml17 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7235
7249
  var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
7236
- var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
7250
+ var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
7237
7251
  var contractDetail = (row) => {
7238
7252
  const failing = row.checks.filter((check) => check.status !== "pass");
7239
7253
  if (failing.length === 0) {
@@ -7252,12 +7266,12 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
7252
7266
  label: check.remediation?.label ?? check.label
7253
7267
  })),
7254
7268
  rows: [
7255
- { label: "Status", value: formatStatus3(row.status) },
7269
+ { label: "Status", value: formatStatus4(row.status) },
7256
7270
  { label: "Selected", value: row.selected ? "Yes" : "No" },
7257
7271
  { label: "Configured", value: row.configured ? "Yes" : "No" },
7258
7272
  {
7259
7273
  label: "Checks",
7260
- value: row.checks.map((check) => `${check.label}: ${formatStatus3(check.status)}`).join(", ")
7274
+ value: row.checks.map((check) => `${check.label}: ${formatStatus4(check.status)}`).join(", ")
7261
7275
  }
7262
7276
  ]
7263
7277
  }));
@@ -7278,7 +7292,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
7278
7292
  const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml17(row.status)}">
7279
7293
  <header>
7280
7294
  <strong>${escapeHtml17(row.label)}</strong>
7281
- <span>${escapeHtml17(formatStatus3(row.status))}</span>
7295
+ <span>${escapeHtml17(formatStatus4(row.status))}</span>
7282
7296
  </header>
7283
7297
  <p>${escapeHtml17(row.detail)}</p>
7284
7298
  ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml17(remediation.href)}">${escapeHtml17(remediation.label)}</a>` : `<strong>${escapeHtml17(remediation.label)}</strong>`}<span>${escapeHtml17(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
@@ -7535,7 +7549,7 @@ var DEFAULT_TITLE12 = "Voice Providers";
7535
7549
  var DEFAULT_DESCRIPTION12 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
7536
7550
  var escapeHtml18 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7537
7551
  var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
7538
- var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
7552
+ var formatStatus5 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
7539
7553
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
7540
7554
  var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
7541
7555
  var getProviderDetail = (provider) => {
@@ -7592,7 +7606,7 @@ var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
7592
7606
  const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml18(provider.status)}">
7593
7607
  <header>
7594
7608
  <strong>${escapeHtml18(provider.label)}</strong>
7595
- <span>${escapeHtml18(formatStatus4(provider.status))}</span>
7609
+ <span>${escapeHtml18(formatStatus5(provider.status))}</span>
7596
7610
  </header>
7597
7611
  <p>${escapeHtml18(provider.detail)}</p>
7598
7612
  <dl>${provider.rows.map((row) => `<div>
@@ -9,7 +9,16 @@ export type VoiceSessionSnapshotQualityEvidence = {
9
9
  report: unknown;
10
10
  status?: VoiceSessionSnapshotStatus;
11
11
  };
12
+ export type VoiceSessionSnapshotArtifactKind = 'failure-replay' | 'incident-bundle' | 'operations-record' | 'provider-fallback' | 'trace' | 'custom';
13
+ export type VoiceSessionSnapshotArtifact = {
14
+ href?: string;
15
+ kind: VoiceSessionSnapshotArtifactKind;
16
+ label: string;
17
+ report?: unknown;
18
+ status?: VoiceSessionSnapshotStatus;
19
+ };
12
20
  export type VoiceSessionSnapshot = {
21
+ artifacts: readonly VoiceSessionSnapshotArtifact[];
13
22
  capturedAt: number;
14
23
  media: readonly MediaProcessorGraphSnapshot[];
15
24
  name?: string;
@@ -25,6 +34,7 @@ export type VoiceSessionSnapshot = {
25
34
  turnId?: string;
26
35
  };
27
36
  export type VoiceSessionSnapshotInput = {
37
+ artifacts?: readonly VoiceSessionSnapshotArtifact[];
28
38
  media?: readonly MediaProcessorGraphSnapshot[];
29
39
  name?: string;
30
40
  proofAssertions?: readonly VoiceProofAssertionResult[];
@@ -49,6 +59,7 @@ export type VoiceSessionSnapshotRoutesOptions = Partial<VoiceSessionSnapshotInpu
49
59
  source?: VoiceSessionSnapshotRouteSource;
50
60
  };
51
61
  export declare const buildVoiceSessionSnapshotStatus: (input: {
62
+ artifacts?: readonly Pick<VoiceSessionSnapshotArtifact, "status">[];
52
63
  media?: readonly Pick<MediaProcessorGraphSnapshot, "report">[];
53
64
  proofSummary?: Pick<VoiceProofAssertionSummary, "ok">;
54
65
  quality?: readonly Pick<VoiceSessionSnapshotQualityEvidence, "status">[];
@@ -2727,6 +2727,7 @@ var DEFAULT_TITLE4 = "Session Snapshot";
2727
2727
  var DEFAULT_DESCRIPTION4 = "Portable call artifact with media graph, provider routing, proof, quality, and telephony evidence.";
2728
2728
  var DEFAULT_DOWNLOAD_LABEL = "Download snapshot";
2729
2729
  var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2730
+ var formatStatus = (status) => status ?? "n/a";
2730
2731
  var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
2731
2732
  const snapshot = state.snapshot;
2732
2733
  const failedProofs = snapshot?.proofSummary.failed ?? 0;
@@ -2734,7 +2735,13 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
2734
2735
  const timingWarnings = snapshot?.media.reduce((total, media) => total + media.report.timing.overBudgetFrames, 0) ?? 0;
2735
2736
  const backpressureDrops = snapshot?.media.reduce((total, media) => total + media.report.backpressure.droppedFrames, 0) ?? 0;
2736
2737
  const qualityWarnings = snapshot?.quality.filter((quality) => quality.status !== "pass").length ?? 0;
2738
+ const artifactWarnings = snapshot?.artifacts.filter((artifact) => artifact.status !== undefined && artifact.status !== "pass").length ?? 0;
2737
2739
  return {
2740
+ artifacts: snapshot?.artifacts.map((artifact) => ({
2741
+ href: artifact.href,
2742
+ label: artifact.label,
2743
+ status: formatStatus(artifact.status)
2744
+ })) ?? [],
2738
2745
  description: options.description ?? DEFAULT_DESCRIPTION4,
2739
2746
  error: state.error,
2740
2747
  isLoading: state.isLoading,
@@ -2746,6 +2753,8 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
2746
2753
  { label: "Backpressure drops", value: String(backpressureDrops) },
2747
2754
  { label: "Proof failures", value: String(failedProofs) },
2748
2755
  { label: "Quality warnings", value: String(qualityWarnings) },
2756
+ { label: "Debug artifacts", value: String(snapshot.artifacts.length) },
2757
+ { label: "Artifact warnings", value: String(artifactWarnings) },
2749
2758
  {
2750
2759
  label: "Provider routing",
2751
2760
  value: String(snapshot.providerRoutingEvents.length)
@@ -2767,6 +2776,10 @@ var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
2767
2776
  <dt>${escapeHtml6(row.label)}</dt>
2768
2777
  <dd>${escapeHtml6(row.value)}</dd>
2769
2778
  </div>`).join("")}</dl>` : '<p class="absolute-voice-session-snapshot__empty">Load a session snapshot to see support diagnostics.</p>';
2779
+ const artifacts = model.artifacts.length ? `<div class="absolute-voice-session-snapshot__artifacts">${model.artifacts.map((artifact) => {
2780
+ const body = `<strong>${escapeHtml6(artifact.label)}</strong><span>${escapeHtml6(artifact.status)}</span>`;
2781
+ return artifact.href ? `<a href="${escapeHtml6(artifact.href)}">${body}</a>` : `<div>${body}</div>`;
2782
+ }).join("")}</div>` : "";
2770
2783
  return `<section class="absolute-voice-session-snapshot absolute-voice-session-snapshot--${escapeHtml6(model.status)}">
2771
2784
  <header class="absolute-voice-session-snapshot__header">
2772
2785
  <span class="absolute-voice-session-snapshot__eyebrow">${escapeHtml6(model.title)}</span>
@@ -2775,6 +2788,7 @@ var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
2775
2788
  <p class="absolute-voice-session-snapshot__description">${escapeHtml6(model.description)}</p>
2776
2789
  ${model.showDownload ? `<button class="absolute-voice-session-snapshot__download" data-absolute-voice-session-snapshot-download type="button">${escapeHtml6(options.downloadLabel ?? DEFAULT_DOWNLOAD_LABEL)}</button>` : ""}
2777
2790
  ${rows}
2791
+ ${artifacts}
2778
2792
  ${model.error ? `<p class="absolute-voice-session-snapshot__error">${escapeHtml6(model.error)}</p>` : ""}
2779
2793
  </section>`;
2780
2794
  };
@@ -3288,7 +3302,7 @@ var DEFAULT_DESCRIPTION5 = "Configured, selected, and healthy voice providers fo
3288
3302
  var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3289
3303
  var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
3290
3304
  var formatKind2 = (kind) => kind.toUpperCase();
3291
- var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
3305
+ var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
3292
3306
  var getCapabilityDetail = (capability) => {
3293
3307
  if (!capability.configured) {
3294
3308
  return "Not configured in this deployment.";
@@ -3314,7 +3328,7 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
3314
3328
  detail: getCapabilityDetail(capability),
3315
3329
  label: `${formatProvider(capability.provider)} ${formatKind2(capability.kind)}`,
3316
3330
  rows: [
3317
- { label: "Status", value: formatStatus(capability.status) },
3331
+ { label: "Status", value: formatStatus2(capability.status) },
3318
3332
  { label: "Selected", value: capability.selected ? "Yes" : "No" },
3319
3333
  { label: "Model", value: capability.model ?? "Default" },
3320
3334
  {
@@ -3343,7 +3357,7 @@ var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
3343
3357
  const capabilities = model.capabilities.length ? `<div class="absolute-voice-provider-capabilities__providers">${model.capabilities.map((capability) => `<article class="absolute-voice-provider-capabilities__provider absolute-voice-provider-capabilities__provider--${escapeHtml8(capability.status)}">
3344
3358
  <header>
3345
3359
  <strong>${escapeHtml8(capability.label)}</strong>
3346
- <span>${escapeHtml8(formatStatus(capability.status))}</span>
3360
+ <span>${escapeHtml8(formatStatus2(capability.status))}</span>
3347
3361
  </header>
3348
3362
  <p>${escapeHtml8(capability.detail)}</p>
3349
3363
  <dl>${capability.rows.map((row) => `<div>
@@ -3488,7 +3502,7 @@ var DEFAULT_TITLE6 = "Provider Contracts";
3488
3502
  var DEFAULT_DESCRIPTION6 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
3489
3503
  var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3490
3504
  var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
3491
- var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
3505
+ var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
3492
3506
  var contractDetail = (row) => {
3493
3507
  const failing = row.checks.filter((check) => check.status !== "pass");
3494
3508
  if (failing.length === 0) {
@@ -3507,12 +3521,12 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
3507
3521
  label: check.remediation?.label ?? check.label
3508
3522
  })),
3509
3523
  rows: [
3510
- { label: "Status", value: formatStatus2(row.status) },
3524
+ { label: "Status", value: formatStatus3(row.status) },
3511
3525
  { label: "Selected", value: row.selected ? "Yes" : "No" },
3512
3526
  { label: "Configured", value: row.configured ? "Yes" : "No" },
3513
3527
  {
3514
3528
  label: "Checks",
3515
- value: row.checks.map((check) => `${check.label}: ${formatStatus2(check.status)}`).join(", ")
3529
+ value: row.checks.map((check) => `${check.label}: ${formatStatus3(check.status)}`).join(", ")
3516
3530
  }
3517
3531
  ]
3518
3532
  }));
@@ -3533,7 +3547,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
3533
3547
  const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml9(row.status)}">
3534
3548
  <header>
3535
3549
  <strong>${escapeHtml9(row.label)}</strong>
3536
- <span>${escapeHtml9(formatStatus2(row.status))}</span>
3550
+ <span>${escapeHtml9(formatStatus3(row.status))}</span>
3537
3551
  </header>
3538
3552
  <p>${escapeHtml9(row.detail)}</p>
3539
3553
  ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml9(remediation.href)}">${escapeHtml9(remediation.label)}</a>` : `<strong>${escapeHtml9(remediation.label)}</strong>`}<span>${escapeHtml9(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
@@ -5076,7 +5090,7 @@ var DEFAULT_TITLE7 = "Voice Providers";
5076
5090
  var DEFAULT_DESCRIPTION7 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
5077
5091
  var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
5078
5092
  var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
5079
- var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
5093
+ var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
5080
5094
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
5081
5095
  var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
5082
5096
  var getProviderDetail = (provider) => {
@@ -5133,7 +5147,7 @@ var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
5133
5147
  const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml10(provider.status)}">
5134
5148
  <header>
5135
5149
  <strong>${escapeHtml10(provider.label)}</strong>
5136
- <span>${escapeHtml10(formatStatus3(provider.status))}</span>
5150
+ <span>${escapeHtml10(formatStatus4(provider.status))}</span>
5137
5151
  </header>
5138
5152
  <p>${escapeHtml10(provider.detail)}</p>
5139
5153
  <dl>${provider.rows.map((row) => `<div>
package/dist/vue/index.js CHANGED
@@ -5666,6 +5666,7 @@ var DEFAULT_TITLE6 = "Session Snapshot";
5666
5666
  var DEFAULT_DESCRIPTION6 = "Portable call artifact with media graph, provider routing, proof, quality, and telephony evidence.";
5667
5667
  var DEFAULT_DOWNLOAD_LABEL = "Download snapshot";
5668
5668
  var escapeHtml11 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
5669
+ var formatStatus2 = (status) => status ?? "n/a";
5669
5670
  var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
5670
5671
  const snapshot = state.snapshot;
5671
5672
  const failedProofs = snapshot?.proofSummary.failed ?? 0;
@@ -5673,7 +5674,13 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
5673
5674
  const timingWarnings = snapshot?.media.reduce((total, media) => total + media.report.timing.overBudgetFrames, 0) ?? 0;
5674
5675
  const backpressureDrops = snapshot?.media.reduce((total, media) => total + media.report.backpressure.droppedFrames, 0) ?? 0;
5675
5676
  const qualityWarnings = snapshot?.quality.filter((quality) => quality.status !== "pass").length ?? 0;
5677
+ const artifactWarnings = snapshot?.artifacts.filter((artifact) => artifact.status !== undefined && artifact.status !== "pass").length ?? 0;
5676
5678
  return {
5679
+ artifacts: snapshot?.artifacts.map((artifact) => ({
5680
+ href: artifact.href,
5681
+ label: artifact.label,
5682
+ status: formatStatus2(artifact.status)
5683
+ })) ?? [],
5677
5684
  description: options.description ?? DEFAULT_DESCRIPTION6,
5678
5685
  error: state.error,
5679
5686
  isLoading: state.isLoading,
@@ -5685,6 +5692,8 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
5685
5692
  { label: "Backpressure drops", value: String(backpressureDrops) },
5686
5693
  { label: "Proof failures", value: String(failedProofs) },
5687
5694
  { label: "Quality warnings", value: String(qualityWarnings) },
5695
+ { label: "Debug artifacts", value: String(snapshot.artifacts.length) },
5696
+ { label: "Artifact warnings", value: String(artifactWarnings) },
5688
5697
  {
5689
5698
  label: "Provider routing",
5690
5699
  value: String(snapshot.providerRoutingEvents.length)
@@ -5706,6 +5715,10 @@ var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
5706
5715
  <dt>${escapeHtml11(row.label)}</dt>
5707
5716
  <dd>${escapeHtml11(row.value)}</dd>
5708
5717
  </div>`).join("")}</dl>` : '<p class="absolute-voice-session-snapshot__empty">Load a session snapshot to see support diagnostics.</p>';
5718
+ const artifacts = model.artifacts.length ? `<div class="absolute-voice-session-snapshot__artifacts">${model.artifacts.map((artifact) => {
5719
+ const body = `<strong>${escapeHtml11(artifact.label)}</strong><span>${escapeHtml11(artifact.status)}</span>`;
5720
+ return artifact.href ? `<a href="${escapeHtml11(artifact.href)}">${body}</a>` : `<div>${body}</div>`;
5721
+ }).join("")}</div>` : "";
5709
5722
  return `<section class="absolute-voice-session-snapshot absolute-voice-session-snapshot--${escapeHtml11(model.status)}">
5710
5723
  <header class="absolute-voice-session-snapshot__header">
5711
5724
  <span class="absolute-voice-session-snapshot__eyebrow">${escapeHtml11(model.title)}</span>
@@ -5714,6 +5727,7 @@ var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
5714
5727
  <p class="absolute-voice-session-snapshot__description">${escapeHtml11(model.description)}</p>
5715
5728
  ${model.showDownload ? `<button class="absolute-voice-session-snapshot__download" data-absolute-voice-session-snapshot-download type="button">${escapeHtml11(options.downloadLabel ?? DEFAULT_DOWNLOAD_LABEL)}</button>` : ""}
5716
5729
  ${rows}
5730
+ ${artifacts}
5717
5731
  ${model.error ? `<p class="absolute-voice-session-snapshot__error">${escapeHtml11(model.error)}</p>` : ""}
5718
5732
  </section>`;
5719
5733
  };
@@ -6515,7 +6529,7 @@ var DEFAULT_DESCRIPTION8 = "Configured, selected, and healthy voice providers fo
6515
6529
  var escapeHtml14 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6516
6530
  var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
6517
6531
  var formatKind2 = (kind) => kind.toUpperCase();
6518
- var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
6532
+ var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
6519
6533
  var getCapabilityDetail = (capability) => {
6520
6534
  if (!capability.configured) {
6521
6535
  return "Not configured in this deployment.";
@@ -6541,7 +6555,7 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
6541
6555
  detail: getCapabilityDetail(capability),
6542
6556
  label: `${formatProvider(capability.provider)} ${formatKind2(capability.kind)}`,
6543
6557
  rows: [
6544
- { label: "Status", value: formatStatus2(capability.status) },
6558
+ { label: "Status", value: formatStatus3(capability.status) },
6545
6559
  { label: "Selected", value: capability.selected ? "Yes" : "No" },
6546
6560
  { label: "Model", value: capability.model ?? "Default" },
6547
6561
  {
@@ -6570,7 +6584,7 @@ var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
6570
6584
  const capabilities = model.capabilities.length ? `<div class="absolute-voice-provider-capabilities__providers">${model.capabilities.map((capability) => `<article class="absolute-voice-provider-capabilities__provider absolute-voice-provider-capabilities__provider--${escapeHtml14(capability.status)}">
6571
6585
  <header>
6572
6586
  <strong>${escapeHtml14(capability.label)}</strong>
6573
- <span>${escapeHtml14(formatStatus2(capability.status))}</span>
6587
+ <span>${escapeHtml14(formatStatus3(capability.status))}</span>
6574
6588
  </header>
6575
6589
  <p>${escapeHtml14(capability.detail)}</p>
6576
6590
  <dl>${capability.rows.map((row) => `<div>
@@ -6844,7 +6858,7 @@ var DEFAULT_TITLE9 = "Provider Contracts";
6844
6858
  var DEFAULT_DESCRIPTION9 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
6845
6859
  var escapeHtml15 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6846
6860
  var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
6847
- var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
6861
+ var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
6848
6862
  var contractDetail = (row) => {
6849
6863
  const failing = row.checks.filter((check) => check.status !== "pass");
6850
6864
  if (failing.length === 0) {
@@ -6863,12 +6877,12 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
6863
6877
  label: check.remediation?.label ?? check.label
6864
6878
  })),
6865
6879
  rows: [
6866
- { label: "Status", value: formatStatus3(row.status) },
6880
+ { label: "Status", value: formatStatus4(row.status) },
6867
6881
  { label: "Selected", value: row.selected ? "Yes" : "No" },
6868
6882
  { label: "Configured", value: row.configured ? "Yes" : "No" },
6869
6883
  {
6870
6884
  label: "Checks",
6871
- value: row.checks.map((check) => `${check.label}: ${formatStatus3(check.status)}`).join(", ")
6885
+ value: row.checks.map((check) => `${check.label}: ${formatStatus4(check.status)}`).join(", ")
6872
6886
  }
6873
6887
  ]
6874
6888
  }));
@@ -6889,7 +6903,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
6889
6903
  const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml15(row.status)}">
6890
6904
  <header>
6891
6905
  <strong>${escapeHtml15(row.label)}</strong>
6892
- <span>${escapeHtml15(formatStatus3(row.status))}</span>
6906
+ <span>${escapeHtml15(formatStatus4(row.status))}</span>
6893
6907
  </header>
6894
6908
  <p>${escapeHtml15(row.detail)}</p>
6895
6909
  ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml15(remediation.href)}">${escapeHtml15(remediation.label)}</a>` : `<strong>${escapeHtml15(remediation.label)}</strong>`}<span>${escapeHtml15(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
@@ -7104,7 +7118,7 @@ var DEFAULT_TITLE10 = "Voice Providers";
7104
7118
  var DEFAULT_DESCRIPTION10 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
7105
7119
  var escapeHtml16 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7106
7120
  var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
7107
- var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
7121
+ var formatStatus5 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
7108
7122
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
7109
7123
  var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
7110
7124
  var getProviderDetail = (provider) => {
@@ -7161,7 +7175,7 @@ var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
7161
7175
  const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml16(provider.status)}">
7162
7176
  <header>
7163
7177
  <strong>${escapeHtml16(provider.label)}</strong>
7164
- <span>${escapeHtml16(formatStatus4(provider.status))}</span>
7178
+ <span>${escapeHtml16(formatStatus5(provider.status))}</span>
7165
7179
  </header>
7166
7180
  <p>${escapeHtml16(provider.detail)}</p>
7167
7181
  <dl>${provider.rows.map((row) => `<div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.400",
3
+ "version": "0.0.22-beta.401",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",