@absolutejs/voice 0.0.22-beta.351 → 0.0.22-beta.352

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.
@@ -6668,8 +6668,43 @@ var DEFAULT_DESCRIPTION7 = "Latest provider routing decision from the self-hoste
6668
6668
  var escapeHtml11 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6669
6669
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
6670
6670
  var formatProviderRoutes = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
6671
+ var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
6672
+ var formatFallbackPath = (decision) => {
6673
+ const provider = formatValue(decision.provider, "Unknown");
6674
+ const selectedProvider = formatValue(decision.selectedProvider, provider);
6675
+ const fallbackProvider = formatValue(decision.fallbackProvider, "");
6676
+ if (fallbackProvider !== "None" && fallbackProvider.trim()) {
6677
+ return `${provider} -> ${fallbackProvider}`;
6678
+ }
6679
+ if (selectedProvider !== provider) {
6680
+ return `${provider} -> ${selectedProvider}`;
6681
+ }
6682
+ return `${provider} primary`;
6683
+ };
6671
6684
  var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
6672
6685
  const decision = snapshot.decision;
6686
+ const activeStack = decision ? [
6687
+ {
6688
+ label: "Profile",
6689
+ value: formatValue(decision.profileLabel ?? decision.profileId)
6690
+ },
6691
+ {
6692
+ label: "LLM",
6693
+ value: getProviderRoute(decision.providerRoutes, "llm")
6694
+ },
6695
+ {
6696
+ label: "STT",
6697
+ value: getProviderRoute(decision.providerRoutes, "stt")
6698
+ },
6699
+ {
6700
+ label: "TTS",
6701
+ value: getProviderRoute(decision.providerRoutes, "tts")
6702
+ },
6703
+ {
6704
+ label: "Fallback path",
6705
+ value: formatFallbackPath(decision)
6706
+ }
6707
+ ] : [];
6673
6708
  const rows = decision ? [
6674
6709
  { label: "Kind", value: decision.kind.toUpperCase() },
6675
6710
  { label: "Policy", value: formatValue(decision.routing, "Unknown") },
@@ -6697,6 +6732,7 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
6697
6732
  }
6698
6733
  ] : [];
6699
6734
  return {
6735
+ activeStack,
6700
6736
  decision,
6701
6737
  description: options.description ?? DEFAULT_DESCRIPTION7,
6702
6738
  error: snapshot.error,
@@ -6710,6 +6746,10 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
6710
6746
  };
6711
6747
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
6712
6748
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
6749
+ const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
6750
+ <span>${escapeHtml11(item.label)}</span>
6751
+ <strong>${escapeHtml11(item.value)}</strong>
6752
+ </div>`).join("")}</div>` : "";
6713
6753
  const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
6714
6754
  <span>${escapeHtml11(row.label)}</span>
6715
6755
  <strong>${escapeHtml11(row.value)}</strong>
@@ -6720,11 +6760,12 @@ var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
6720
6760
  <strong class="absolute-voice-routing-status__label">${escapeHtml11(model.label)}</strong>
6721
6761
  </header>
6722
6762
  <p class="absolute-voice-routing-status__description">${escapeHtml11(model.description)}</p>
6763
+ ${activeStack}
6723
6764
  ${rows}
6724
6765
  ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml11(model.error)}</p>` : ""}
6725
6766
  </section>`;
6726
6767
  };
6727
- var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}`;
6768
+ var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__stack{background:linear-gradient(135deg,#16130d,#49391f);border-radius:18px;color:#fff;display:grid;gap:8px;grid-template-columns:repeat(5,minmax(0,1fr));margin-top:14px;padding:12px}.absolute-voice-routing-status__stack div{border-left:1px solid rgba(255,255,255,.18);padding-left:10px}.absolute-voice-routing-status__stack div:first-child{border-left:0;padding-left:0}.absolute-voice-routing-status__stack span{color:#e9d9b8;display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:5px;text-transform:uppercase}.absolute-voice-routing-status__stack strong{display:block;font-size:13px;line-height:1.25;overflow-wrap:anywhere}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}@media (max-width:760px){.absolute-voice-routing-status__stack{grid-template-columns:repeat(2,minmax(0,1fr))}.absolute-voice-routing-status__stack div{border-left:0;border-top:1px solid rgba(255,255,255,.18);padding-left:0;padding-top:8px}.absolute-voice-routing-status__stack div:first-child{border-top:0;padding-top:0}}`;
6728
6769
  var mountVoiceRoutingStatus = (element, path = "/api/routing/latest", options = {}) => {
6729
6770
  const store = createVoiceRoutingStatusStore(path, options);
6730
6771
  const render = () => {
@@ -1,6 +1,10 @@
1
1
  import type { VoiceRoutingDecisionSummary } from '../resilienceRoutes';
2
2
  import { type VoiceRoutingStatusClientOptions, type VoiceRoutingStatusSnapshot } from './routingStatus';
3
3
  export type VoiceRoutingStatusViewModel = {
4
+ activeStack: Array<{
5
+ label: string;
6
+ value: string;
7
+ }>;
4
8
  decision: VoiceRoutingDecisionSummary | null;
5
9
  description: string;
6
10
  error: string | null;
@@ -4265,8 +4265,43 @@ var DEFAULT_DESCRIPTION10 = "Latest provider routing decision from the self-host
4265
4265
  var escapeHtml12 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4266
4266
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
4267
4267
  var formatProviderRoutes = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
4268
+ var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
4269
+ var formatFallbackPath = (decision) => {
4270
+ const provider = formatValue(decision.provider, "Unknown");
4271
+ const selectedProvider = formatValue(decision.selectedProvider, provider);
4272
+ const fallbackProvider = formatValue(decision.fallbackProvider, "");
4273
+ if (fallbackProvider !== "None" && fallbackProvider.trim()) {
4274
+ return `${provider} -> ${fallbackProvider}`;
4275
+ }
4276
+ if (selectedProvider !== provider) {
4277
+ return `${provider} -> ${selectedProvider}`;
4278
+ }
4279
+ return `${provider} primary`;
4280
+ };
4268
4281
  var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
4269
4282
  const decision = snapshot.decision;
4283
+ const activeStack = decision ? [
4284
+ {
4285
+ label: "Profile",
4286
+ value: formatValue(decision.profileLabel ?? decision.profileId)
4287
+ },
4288
+ {
4289
+ label: "LLM",
4290
+ value: getProviderRoute(decision.providerRoutes, "llm")
4291
+ },
4292
+ {
4293
+ label: "STT",
4294
+ value: getProviderRoute(decision.providerRoutes, "stt")
4295
+ },
4296
+ {
4297
+ label: "TTS",
4298
+ value: getProviderRoute(decision.providerRoutes, "tts")
4299
+ },
4300
+ {
4301
+ label: "Fallback path",
4302
+ value: formatFallbackPath(decision)
4303
+ }
4304
+ ] : [];
4270
4305
  const rows = decision ? [
4271
4306
  { label: "Kind", value: decision.kind.toUpperCase() },
4272
4307
  { label: "Policy", value: formatValue(decision.routing, "Unknown") },
@@ -4294,6 +4329,7 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
4294
4329
  }
4295
4330
  ] : [];
4296
4331
  return {
4332
+ activeStack,
4297
4333
  decision,
4298
4334
  description: options.description ?? DEFAULT_DESCRIPTION10,
4299
4335
  error: snapshot.error,
@@ -4307,6 +4343,10 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
4307
4343
  };
4308
4344
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
4309
4345
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
4346
+ const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
4347
+ <span>${escapeHtml12(item.label)}</span>
4348
+ <strong>${escapeHtml12(item.value)}</strong>
4349
+ </div>`).join("")}</div>` : "";
4310
4350
  const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
4311
4351
  <span>${escapeHtml12(row.label)}</span>
4312
4352
  <strong>${escapeHtml12(row.value)}</strong>
@@ -4317,11 +4357,12 @@ var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
4317
4357
  <strong class="absolute-voice-routing-status__label">${escapeHtml12(model.label)}</strong>
4318
4358
  </header>
4319
4359
  <p class="absolute-voice-routing-status__description">${escapeHtml12(model.description)}</p>
4360
+ ${activeStack}
4320
4361
  ${rows}
4321
4362
  ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml12(model.error)}</p>` : ""}
4322
4363
  </section>`;
4323
4364
  };
4324
- var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}`;
4365
+ var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__stack{background:linear-gradient(135deg,#16130d,#49391f);border-radius:18px;color:#fff;display:grid;gap:8px;grid-template-columns:repeat(5,minmax(0,1fr));margin-top:14px;padding:12px}.absolute-voice-routing-status__stack div{border-left:1px solid rgba(255,255,255,.18);padding-left:10px}.absolute-voice-routing-status__stack div:first-child{border-left:0;padding-left:0}.absolute-voice-routing-status__stack span{color:#e9d9b8;display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:5px;text-transform:uppercase}.absolute-voice-routing-status__stack strong{display:block;font-size:13px;line-height:1.25;overflow-wrap:anywhere}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}@media (max-width:760px){.absolute-voice-routing-status__stack{grid-template-columns:repeat(2,minmax(0,1fr))}.absolute-voice-routing-status__stack div{border-left:0;border-top:1px solid rgba(255,255,255,.18);padding-left:0;padding-top:8px}.absolute-voice-routing-status__stack div:first-child{border-top:0;padding-top:0}}`;
4325
4366
  var mountVoiceRoutingStatus = (element, path = "/api/routing/latest", options = {}) => {
4326
4367
  const store = createVoiceRoutingStatusStore(path, options);
4327
4368
  const render = () => {
@@ -4932,8 +4932,43 @@ var DEFAULT_DESCRIPTION7 = "Latest provider routing decision from the self-hoste
4932
4932
  var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4933
4933
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
4934
4934
  var formatProviderRoutes = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
4935
+ var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
4936
+ var formatFallbackPath = (decision) => {
4937
+ const provider = formatValue(decision.provider, "Unknown");
4938
+ const selectedProvider = formatValue(decision.selectedProvider, provider);
4939
+ const fallbackProvider = formatValue(decision.fallbackProvider, "");
4940
+ if (fallbackProvider !== "None" && fallbackProvider.trim()) {
4941
+ return `${provider} -> ${fallbackProvider}`;
4942
+ }
4943
+ if (selectedProvider !== provider) {
4944
+ return `${provider} -> ${selectedProvider}`;
4945
+ }
4946
+ return `${provider} primary`;
4947
+ };
4935
4948
  var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
4936
4949
  const decision = snapshot.decision;
4950
+ const activeStack = decision ? [
4951
+ {
4952
+ label: "Profile",
4953
+ value: formatValue(decision.profileLabel ?? decision.profileId)
4954
+ },
4955
+ {
4956
+ label: "LLM",
4957
+ value: getProviderRoute(decision.providerRoutes, "llm")
4958
+ },
4959
+ {
4960
+ label: "STT",
4961
+ value: getProviderRoute(decision.providerRoutes, "stt")
4962
+ },
4963
+ {
4964
+ label: "TTS",
4965
+ value: getProviderRoute(decision.providerRoutes, "tts")
4966
+ },
4967
+ {
4968
+ label: "Fallback path",
4969
+ value: formatFallbackPath(decision)
4970
+ }
4971
+ ] : [];
4937
4972
  const rows = decision ? [
4938
4973
  { label: "Kind", value: decision.kind.toUpperCase() },
4939
4974
  { label: "Policy", value: formatValue(decision.routing, "Unknown") },
@@ -4961,6 +4996,7 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
4961
4996
  }
4962
4997
  ] : [];
4963
4998
  return {
4999
+ activeStack,
4964
5000
  decision,
4965
5001
  description: options.description ?? DEFAULT_DESCRIPTION7,
4966
5002
  error: snapshot.error,
@@ -4974,6 +5010,10 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
4974
5010
  };
4975
5011
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
4976
5012
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
5013
+ const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
5014
+ <span>${escapeHtml10(item.label)}</span>
5015
+ <strong>${escapeHtml10(item.value)}</strong>
5016
+ </div>`).join("")}</div>` : "";
4977
5017
  const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
4978
5018
  <span>${escapeHtml10(row.label)}</span>
4979
5019
  <strong>${escapeHtml10(row.value)}</strong>
@@ -4984,11 +5024,12 @@ var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
4984
5024
  <strong class="absolute-voice-routing-status__label">${escapeHtml10(model.label)}</strong>
4985
5025
  </header>
4986
5026
  <p class="absolute-voice-routing-status__description">${escapeHtml10(model.description)}</p>
5027
+ ${activeStack}
4987
5028
  ${rows}
4988
5029
  ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml10(model.error)}</p>` : ""}
4989
5030
  </section>`;
4990
5031
  };
4991
- var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}`;
5032
+ var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__stack{background:linear-gradient(135deg,#16130d,#49391f);border-radius:18px;color:#fff;display:grid;gap:8px;grid-template-columns:repeat(5,minmax(0,1fr));margin-top:14px;padding:12px}.absolute-voice-routing-status__stack div{border-left:1px solid rgba(255,255,255,.18);padding-left:10px}.absolute-voice-routing-status__stack div:first-child{border-left:0;padding-left:0}.absolute-voice-routing-status__stack span{color:#e9d9b8;display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:5px;text-transform:uppercase}.absolute-voice-routing-status__stack strong{display:block;font-size:13px;line-height:1.25;overflow-wrap:anywhere}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}@media (max-width:760px){.absolute-voice-routing-status__stack{grid-template-columns:repeat(2,minmax(0,1fr))}.absolute-voice-routing-status__stack div{border-left:0;border-top:1px solid rgba(255,255,255,.18);padding-left:0;padding-top:8px}.absolute-voice-routing-status__stack div:first-child{border-top:0;padding-top:0}}`;
4992
5033
  var mountVoiceRoutingStatus = (element, path = "/api/routing/latest", options = {}) => {
4993
5034
  const store = createVoiceRoutingStatusStore(path, options);
4994
5035
  const render = () => {
package/dist/vue/index.js CHANGED
@@ -4280,8 +4280,43 @@ var DEFAULT_DESCRIPTION10 = "Latest provider routing decision from the self-host
4280
4280
  var escapeHtml12 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4281
4281
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
4282
4282
  var formatProviderRoutes = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
4283
+ var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
4284
+ var formatFallbackPath = (decision) => {
4285
+ const provider = formatValue(decision.provider, "Unknown");
4286
+ const selectedProvider = formatValue(decision.selectedProvider, provider);
4287
+ const fallbackProvider = formatValue(decision.fallbackProvider, "");
4288
+ if (fallbackProvider !== "None" && fallbackProvider.trim()) {
4289
+ return `${provider} -> ${fallbackProvider}`;
4290
+ }
4291
+ if (selectedProvider !== provider) {
4292
+ return `${provider} -> ${selectedProvider}`;
4293
+ }
4294
+ return `${provider} primary`;
4295
+ };
4283
4296
  var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
4284
4297
  const decision = snapshot.decision;
4298
+ const activeStack = decision ? [
4299
+ {
4300
+ label: "Profile",
4301
+ value: formatValue(decision.profileLabel ?? decision.profileId)
4302
+ },
4303
+ {
4304
+ label: "LLM",
4305
+ value: getProviderRoute(decision.providerRoutes, "llm")
4306
+ },
4307
+ {
4308
+ label: "STT",
4309
+ value: getProviderRoute(decision.providerRoutes, "stt")
4310
+ },
4311
+ {
4312
+ label: "TTS",
4313
+ value: getProviderRoute(decision.providerRoutes, "tts")
4314
+ },
4315
+ {
4316
+ label: "Fallback path",
4317
+ value: formatFallbackPath(decision)
4318
+ }
4319
+ ] : [];
4285
4320
  const rows = decision ? [
4286
4321
  { label: "Kind", value: decision.kind.toUpperCase() },
4287
4322
  { label: "Policy", value: formatValue(decision.routing, "Unknown") },
@@ -4309,6 +4344,7 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
4309
4344
  }
4310
4345
  ] : [];
4311
4346
  return {
4347
+ activeStack,
4312
4348
  decision,
4313
4349
  description: options.description ?? DEFAULT_DESCRIPTION10,
4314
4350
  error: snapshot.error,
@@ -4322,6 +4358,10 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
4322
4358
  };
4323
4359
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
4324
4360
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
4361
+ const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
4362
+ <span>${escapeHtml12(item.label)}</span>
4363
+ <strong>${escapeHtml12(item.value)}</strong>
4364
+ </div>`).join("")}</div>` : "";
4325
4365
  const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
4326
4366
  <span>${escapeHtml12(row.label)}</span>
4327
4367
  <strong>${escapeHtml12(row.value)}</strong>
@@ -4332,11 +4372,12 @@ var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
4332
4372
  <strong class="absolute-voice-routing-status__label">${escapeHtml12(model.label)}</strong>
4333
4373
  </header>
4334
4374
  <p class="absolute-voice-routing-status__description">${escapeHtml12(model.description)}</p>
4375
+ ${activeStack}
4335
4376
  ${rows}
4336
4377
  ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml12(model.error)}</p>` : ""}
4337
4378
  </section>`;
4338
4379
  };
4339
- var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}`;
4380
+ var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__stack{background:linear-gradient(135deg,#16130d,#49391f);border-radius:18px;color:#fff;display:grid;gap:8px;grid-template-columns:repeat(5,minmax(0,1fr));margin-top:14px;padding:12px}.absolute-voice-routing-status__stack div{border-left:1px solid rgba(255,255,255,.18);padding-left:10px}.absolute-voice-routing-status__stack div:first-child{border-left:0;padding-left:0}.absolute-voice-routing-status__stack span{color:#e9d9b8;display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:5px;text-transform:uppercase}.absolute-voice-routing-status__stack strong{display:block;font-size:13px;line-height:1.25;overflow-wrap:anywhere}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}@media (max-width:760px){.absolute-voice-routing-status__stack{grid-template-columns:repeat(2,minmax(0,1fr))}.absolute-voice-routing-status__stack div{border-left:0;border-top:1px solid rgba(255,255,255,.18);padding-left:0;padding-top:8px}.absolute-voice-routing-status__stack div:first-child{border-top:0;padding-top:0}}`;
4340
4381
  var mountVoiceRoutingStatus = (element, path = "/api/routing/latest", options = {}) => {
4341
4382
  const store = createVoiceRoutingStatusStore(path, options);
4342
4383
  const render = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.351",
3
+ "version": "0.0.22-beta.352",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",