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

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.
@@ -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.402",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",