@absolutejs/voice 0.0.22-beta.168 → 0.0.22-beta.169

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.
@@ -4031,6 +4031,11 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
4031
4031
  ...row,
4032
4032
  detail: contractDetail(row),
4033
4033
  label: `${formatProvider3(row.provider)} ${row.kind.toUpperCase()}`,
4034
+ remediations: row.checks.filter((check) => check.status !== "pass" && check.remediation).map((check) => ({
4035
+ detail: check.remediation?.detail ?? "",
4036
+ href: check.remediation?.href,
4037
+ label: check.remediation?.label ?? check.label
4038
+ })),
4034
4039
  rows: [
4035
4040
  { label: "Status", value: formatStatus3(row.status) },
4036
4041
  { label: "Selected", value: row.selected ? "Yes" : "No" },
@@ -4061,6 +4066,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
4061
4066
  <span>${escapeHtml9(formatStatus3(row.status))}</span>
4062
4067
  </header>
4063
4068
  <p>${escapeHtml9(row.detail)}</p>
4069
+ ${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>` : ""}
4064
4070
  <dl>${row.rows.map((item) => `<div>
4065
4071
  <dt>${escapeHtml9(item.label)}</dt>
4066
4072
  <dd>${escapeHtml9(item.value)}</dd>
@@ -4076,7 +4082,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
4076
4082
  ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml9(model.error)}</p>` : ""}
4077
4083
  </section>`;
4078
4084
  };
4079
- var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
4085
+ var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
4080
4086
  var mountVoiceProviderContracts = (element, path = "/api/provider-contracts", options = {}) => {
4081
4087
  const store = createVoiceProviderContractsStore(path, options);
4082
4088
  const render = () => {
@@ -3,6 +3,11 @@ import { type VoiceProviderContractsClientOptions, type VoiceProviderContractsSn
3
3
  export type VoiceProviderContractRowView<TProvider extends string = string> = VoiceProviderContractMatrixRow<TProvider> & {
4
4
  detail: string;
5
5
  label: string;
6
+ remediations: Array<{
7
+ detail: string;
8
+ href?: string;
9
+ label: string;
10
+ }>;
6
11
  rows: Array<{
7
12
  label: string;
8
13
  value: string;
package/dist/index.js CHANGED
@@ -21437,36 +21437,72 @@ var buildVoiceProviderContractMatrix = (input) => {
21437
21437
  detail: configured ? "Provider is configured for this deployment." : "Provider is declared but not configured.",
21438
21438
  key: "configured",
21439
21439
  label: "Configured",
21440
+ remediation: configured ? undefined : {
21441
+ code: "provider.configure",
21442
+ detail: "Enable this provider or remove it from the contract matrix for this deployment.",
21443
+ href: contract.remediationHref,
21444
+ label: "Configure provider"
21445
+ },
21440
21446
  status: configured ? "pass" : "fail"
21441
21447
  },
21442
21448
  {
21443
21449
  detail: missingEnv.length === 0 ? "Required environment is present." : `Missing env: ${missingEnv.join(", ")}.`,
21444
21450
  key: "env",
21445
21451
  label: "Required env",
21452
+ remediation: missingEnv.length === 0 ? undefined : {
21453
+ code: "provider.env",
21454
+ detail: `Set ${missingEnv.join(", ")} before deploying this provider.`,
21455
+ href: contract.remediationHref,
21456
+ label: "Add missing env"
21457
+ },
21446
21458
  status: missingEnv.length === 0 ? "pass" : "fail"
21447
21459
  },
21448
21460
  {
21449
21461
  detail: contract.latencyBudgetMs !== undefined ? `Latency budget is ${contract.latencyBudgetMs}ms.` : "No latency budget declared.",
21450
21462
  key: "latencyBudget",
21451
21463
  label: "Latency budget",
21464
+ remediation: contract.latencyBudgetMs !== undefined ? undefined : {
21465
+ code: "provider.latency_budget",
21466
+ detail: "Declare latencyBudgetMs so readiness can distinguish expected latency from regressions.",
21467
+ href: contract.remediationHref,
21468
+ label: "Declare latency budget"
21469
+ },
21452
21470
  status: contract.latencyBudgetMs !== undefined ? "pass" : "warn"
21453
21471
  },
21454
21472
  {
21455
21473
  detail: (contract.fallbackProviders ?? []).length > 0 ? `Fallback providers: ${contract.fallbackProviders?.join(", ")}.` : "No fallback provider declared.",
21456
21474
  key: "fallback",
21457
21475
  label: "Fallback",
21476
+ remediation: (contract.fallbackProviders ?? []).length > 0 ? undefined : {
21477
+ code: "provider.fallback",
21478
+ detail: "Declare at least one fallback provider for this lane or mark this provider as intentionally single-provider.",
21479
+ href: contract.remediationHref,
21480
+ label: "Add fallback provider"
21481
+ },
21458
21482
  status: (contract.fallbackProviders ?? []).length > 0 ? "pass" : "warn"
21459
21483
  },
21460
21484
  {
21461
21485
  detail: contract.streaming ? "Streaming is supported." : "Streaming support is not declared.",
21462
21486
  key: "streaming",
21463
21487
  label: "Streaming",
21488
+ remediation: contract.streaming ? undefined : {
21489
+ code: "provider.streaming",
21490
+ detail: "Use a streaming-capable adapter for realtime voice, or route this provider only to non-realtime workflows.",
21491
+ href: contract.remediationHref,
21492
+ label: "Add streaming support"
21493
+ },
21464
21494
  status: contract.streaming ? "pass" : "warn"
21465
21495
  },
21466
21496
  {
21467
21497
  detail: missingCapabilities.length === 0 ? "Required capabilities are declared." : `Missing capabilities: ${missingCapabilities.join(", ")}.`,
21468
21498
  key: "capabilities",
21469
21499
  label: "Capabilities",
21500
+ remediation: missingCapabilities.length === 0 ? undefined : {
21501
+ code: "provider.capabilities",
21502
+ detail: `Declare or implement capabilities: ${missingCapabilities.join(", ")}.`,
21503
+ href: contract.remediationHref,
21504
+ label: "Add capability coverage"
21505
+ },
21470
21506
  status: missingCapabilities.length === 0 ? "pass" : "warn"
21471
21507
  }
21472
21508
  ];
@@ -21495,7 +21531,7 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
21495
21531
  var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
21496
21532
  const title = options.title ?? "Voice Provider Contract Matrix";
21497
21533
  const rows = report.rows.map((row) => {
21498
- const checks = row.checks.map((check) => `<li class="${escapeHtml36(check.status)}"><strong>${escapeHtml36(check.label)}</strong><span>${escapeHtml36(check.detail ?? check.status)}</span></li>`).join("");
21534
+ const checks = row.checks.map((check) => `<li class="${escapeHtml36(check.status)}"><strong>${escapeHtml36(check.label)}</strong><span>${escapeHtml36(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml36(check.remediation.href)}">${escapeHtml36(check.remediation.label)}</a>` : escapeHtml36(check.remediation.label)}: ${escapeHtml36(check.remediation.detail)}</em>` : ""}</li>`).join("");
21499
21535
  return `<article class="row ${escapeHtml36(row.status)}">
21500
21536
  <div>
21501
21537
  <p class="eyebrow">${escapeHtml36(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
@@ -21505,7 +21541,7 @@ var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
21505
21541
  <ul>${checks}</ul>
21506
21542
  </article>`;
21507
21543
  }).join("");
21508
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml36(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,.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))}.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}.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}@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>${escapeHtml36(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>${rows || '<article class="row"><p>No provider contracts configured.</p></article>'}</main></body></html>`;
21544
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml36(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,.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))}.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}.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>${escapeHtml36(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>${rows || '<article class="row"><p>No provider contracts configured.</p></article>'}</main></body></html>`;
21509
21545
  };
21510
21546
  var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
21511
21547
  var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
@@ -37,10 +37,17 @@ export type VoiceProviderStackCapabilityGapInput<TProvider extends string = stri
37
37
  required?: Partial<Record<VoiceProviderStackKind, readonly string[]>>;
38
38
  };
39
39
  export type VoiceProviderContractCheckStatus = 'fail' | 'pass' | 'warn';
40
+ export type VoiceProviderContractRemediation = {
41
+ code: string;
42
+ detail: string;
43
+ href?: string;
44
+ label: string;
45
+ };
40
46
  export type VoiceProviderContractCheck = {
41
47
  detail?: string;
42
48
  key: string;
43
49
  label: string;
50
+ remediation?: VoiceProviderContractRemediation;
44
51
  status: VoiceProviderContractCheckStatus;
45
52
  };
46
53
  export type VoiceProviderContractDefinition<TProvider extends string = string> = {
@@ -53,6 +60,7 @@ export type VoiceProviderContractDefinition<TProvider extends string = string> =
53
60
  provider: TProvider;
54
61
  requiredCapabilities?: readonly string[];
55
62
  requiredEnv?: readonly string[];
63
+ remediationHref?: string;
56
64
  selected?: boolean;
57
65
  streaming?: boolean;
58
66
  };
@@ -1787,6 +1787,11 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
1787
1787
  ...row,
1788
1788
  detail: contractDetail(row),
1789
1789
  label: `${formatProvider2(row.provider)} ${row.kind.toUpperCase()}`,
1790
+ remediations: row.checks.filter((check) => check.status !== "pass" && check.remediation).map((check) => ({
1791
+ detail: check.remediation?.detail ?? "",
1792
+ href: check.remediation?.href,
1793
+ label: check.remediation?.label ?? check.label
1794
+ })),
1790
1795
  rows: [
1791
1796
  { label: "Status", value: formatStatus2(row.status) },
1792
1797
  { label: "Selected", value: row.selected ? "Yes" : "No" },
@@ -1817,6 +1822,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
1817
1822
  <span>${escapeHtml6(formatStatus2(row.status))}</span>
1818
1823
  </header>
1819
1824
  <p>${escapeHtml6(row.detail)}</p>
1825
+ ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml6(remediation.href)}">${escapeHtml6(remediation.label)}</a>` : `<strong>${escapeHtml6(remediation.label)}</strong>`}<span>${escapeHtml6(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
1820
1826
  <dl>${row.rows.map((item) => `<div>
1821
1827
  <dt>${escapeHtml6(item.label)}</dt>
1822
1828
  <dd>${escapeHtml6(item.value)}</dd>
@@ -1832,7 +1838,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
1832
1838
  ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml6(model.error)}</p>` : ""}
1833
1839
  </section>`;
1834
1840
  };
1835
- var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
1841
+ var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
1836
1842
  var mountVoiceProviderContracts = (element, path = "/api/provider-contracts", options = {}) => {
1837
1843
  const store = createVoiceProviderContractsStore(path, options);
1838
1844
  const render = () => {
@@ -1924,6 +1930,22 @@ var VoiceProviderContracts = ({
1924
1930
  /* @__PURE__ */ jsxDEV6("p", {
1925
1931
  children: row.detail
1926
1932
  }, undefined, false, undefined, this),
1933
+ row.remediations.length ? /* @__PURE__ */ jsxDEV6("ul", {
1934
+ className: "absolute-voice-provider-contracts__remediations",
1935
+ children: row.remediations.map((remediation) => /* @__PURE__ */ jsxDEV6("li", {
1936
+ children: [
1937
+ remediation.href ? /* @__PURE__ */ jsxDEV6("a", {
1938
+ href: remediation.href,
1939
+ children: remediation.label
1940
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV6("strong", {
1941
+ children: remediation.label
1942
+ }, undefined, false, undefined, this),
1943
+ /* @__PURE__ */ jsxDEV6("span", {
1944
+ children: remediation.detail
1945
+ }, undefined, false, undefined, this)
1946
+ ]
1947
+ }, `${row.kind}:${row.provider}:${remediation.label}`, true, undefined, this))
1948
+ }, undefined, false, undefined, this) : null,
1927
1949
  /* @__PURE__ */ jsxDEV6("dl", {
1928
1950
  children: row.rows.map((item) => /* @__PURE__ */ jsxDEV6("div", {
1929
1951
  children: [
@@ -1460,6 +1460,11 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
1460
1460
  ...row,
1461
1461
  detail: contractDetail(row),
1462
1462
  label: `${formatProvider2(row.provider)} ${row.kind.toUpperCase()}`,
1463
+ remediations: row.checks.filter((check) => check.status !== "pass" && check.remediation).map((check) => ({
1464
+ detail: check.remediation?.detail ?? "",
1465
+ href: check.remediation?.href,
1466
+ label: check.remediation?.label ?? check.label
1467
+ })),
1463
1468
  rows: [
1464
1469
  { label: "Status", value: formatStatus2(row.status) },
1465
1470
  { label: "Selected", value: row.selected ? "Yes" : "No" },
@@ -1490,6 +1495,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
1490
1495
  <span>${escapeHtml6(formatStatus2(row.status))}</span>
1491
1496
  </header>
1492
1497
  <p>${escapeHtml6(row.detail)}</p>
1498
+ ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml6(remediation.href)}">${escapeHtml6(remediation.label)}</a>` : `<strong>${escapeHtml6(remediation.label)}</strong>`}<span>${escapeHtml6(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
1493
1499
  <dl>${row.rows.map((item) => `<div>
1494
1500
  <dt>${escapeHtml6(item.label)}</dt>
1495
1501
  <dd>${escapeHtml6(item.value)}</dd>
@@ -1505,7 +1511,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
1505
1511
  ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml6(model.error)}</p>` : ""}
1506
1512
  </section>`;
1507
1513
  };
1508
- var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
1514
+ var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
1509
1515
  var mountVoiceProviderContracts = (element, path = "/api/provider-contracts", options = {}) => {
1510
1516
  const store = createVoiceProviderContractsStore(path, options);
1511
1517
  const render = () => {
package/dist/vue/index.js CHANGED
@@ -1848,6 +1848,11 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
1848
1848
  ...row,
1849
1849
  detail: contractDetail(row),
1850
1850
  label: `${formatProvider2(row.provider)} ${row.kind.toUpperCase()}`,
1851
+ remediations: row.checks.filter((check) => check.status !== "pass" && check.remediation).map((check) => ({
1852
+ detail: check.remediation?.detail ?? "",
1853
+ href: check.remediation?.href,
1854
+ label: check.remediation?.label ?? check.label
1855
+ })),
1851
1856
  rows: [
1852
1857
  { label: "Status", value: formatStatus2(row.status) },
1853
1858
  { label: "Selected", value: row.selected ? "Yes" : "No" },
@@ -1878,6 +1883,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
1878
1883
  <span>${escapeHtml6(formatStatus2(row.status))}</span>
1879
1884
  </header>
1880
1885
  <p>${escapeHtml6(row.detail)}</p>
1886
+ ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml6(remediation.href)}">${escapeHtml6(remediation.label)}</a>` : `<strong>${escapeHtml6(remediation.label)}</strong>`}<span>${escapeHtml6(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
1881
1887
  <dl>${row.rows.map((item) => `<div>
1882
1888
  <dt>${escapeHtml6(item.label)}</dt>
1883
1889
  <dd>${escapeHtml6(item.value)}</dd>
@@ -1893,7 +1899,7 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
1893
1899
  ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml6(model.error)}</p>` : ""}
1894
1900
  </section>`;
1895
1901
  };
1896
- var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
1902
+ var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
1897
1903
  var mountVoiceProviderContracts = (element, path = "/api/provider-contracts", options = {}) => {
1898
1904
  const store = createVoiceProviderContractsStore(path, options);
1899
1905
  const render = () => {
@@ -1983,6 +1989,14 @@ var VoiceProviderContracts = defineComponent6({
1983
1989
  h6("span", row.status)
1984
1990
  ]),
1985
1991
  h6("p", row.detail),
1992
+ row.remediations.length ? h6("ul", {
1993
+ class: "absolute-voice-provider-contracts__remediations"
1994
+ }, row.remediations.map((remediation) => h6("li", {
1995
+ key: `${row.kind}:${row.provider}:${remediation.label}`
1996
+ }, [
1997
+ remediation.href ? h6("a", { href: remediation.href }, remediation.label) : h6("strong", remediation.label),
1998
+ h6("span", remediation.detail)
1999
+ ]))) : null,
1986
2000
  h6("dl", row.rows.map((item) => h6("div", { key: item.label }, [
1987
2001
  h6("dt", item.label),
1988
2002
  h6("dd", item.value)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.168",
3
+ "version": "0.0.22-beta.169",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",