@absolutejs/voice 0.0.22-beta.142 → 0.0.22-beta.143

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -20286,14 +20286,26 @@ var buildVoiceOpsConsoleReport = async (options) => {
20286
20286
  const quality = await evaluateVoiceQuality({ events });
20287
20287
  const routingEvents = listVoiceRoutingEvents(events).slice(0, 10);
20288
20288
  const trace = summarizeVoiceTrace(events);
20289
+ const deliverySinkOptions = options.deliverySinks || undefined;
20290
+ const deliverySinks = deliverySinkOptions ? await buildVoiceDeliverySinkReport(deliverySinkOptions) : undefined;
20291
+ const links = options.links ?? (deliverySinks ? [
20292
+ ...DEFAULT_LINKS,
20293
+ {
20294
+ description: "Configured audit and trace delivery sinks with queue health.",
20295
+ href: deliverySinkOptions?.htmlPath === false ? deliverySinkOptions.path ?? "/api/voice-delivery-sinks" : deliverySinkOptions?.htmlPath ?? "/delivery-sinks",
20296
+ label: "Delivery Sinks",
20297
+ statusHref: deliverySinkOptions?.path ?? "/api/voice-delivery-sinks"
20298
+ }
20299
+ ] : DEFAULT_LINKS);
20289
20300
  return {
20290
20301
  checkedAt: Date.now(),
20302
+ deliverySinks,
20291
20303
  eventCount: events.length,
20292
20304
  handoffs: {
20293
20305
  failed: handoffs.failed,
20294
20306
  total: handoffs.total
20295
20307
  },
20296
- links: options.links ?? DEFAULT_LINKS,
20308
+ links,
20297
20309
  providers: countProviderStatuses(providers),
20298
20310
  quality,
20299
20311
  recentRoutingEvents: routingEvents,
@@ -20382,7 +20394,7 @@ var summarizeVoiceOpsStatus = async (options) => {
20382
20394
  const shouldInclude = (surface) => include?.[surface] !== false;
20383
20395
  const evals = options.evals === false ? undefined : options.evals;
20384
20396
  const events = filterVoiceTraceEvents(await options.store.list());
20385
- const [quality, workflows, providers, sessions, handoffs] = await Promise.all([
20397
+ const [quality, workflows, providers, sessions, handoffs, deliverySinks] = await Promise.all([
20386
20398
  options.quality === false || !shouldInclude("quality") ? undefined : evaluateVoiceQuality({
20387
20399
  events,
20388
20400
  thresholds: options.quality?.thresholds
@@ -20431,7 +20443,8 @@ var summarizeVoiceOpsStatus = async (options) => {
20431
20443
  }),
20432
20444
  !shouldInclude("handoffs") ? undefined : summarizeVoiceHandoffHealth({
20433
20445
  events
20434
- })
20446
+ }),
20447
+ !options.deliverySinks || !shouldInclude("deliverySinks") ? undefined : buildVoiceDeliverySinkReport(options.deliverySinks)
20435
20448
  ]);
20436
20449
  const providerRecovery = shouldInclude("providerRecovery") ? summarizeVoiceProviderFallbackRecovery(events) : undefined;
20437
20450
  const surfaces = {};
@@ -20477,9 +20490,26 @@ var summarizeVoiceOpsStatus = async (options) => {
20477
20490
  };
20478
20491
  statuses.push(status);
20479
20492
  }
20493
+ if (deliverySinks) {
20494
+ const status = deliverySinks.status === "fail" ? "fail" : "pass";
20495
+ surfaces.deliverySinks = {
20496
+ auditTotal: deliverySinks.auditDeliveries?.summary.total ?? 0,
20497
+ status,
20498
+ traceTotal: deliverySinks.traceDeliveries?.summary.total ?? 0
20499
+ };
20500
+ statuses.push(status);
20501
+ }
20480
20502
  return {
20481
20503
  checkedAt: Date.now(),
20482
- links: options.links ?? DEFAULT_LINKS2,
20504
+ links: options.links ?? (options.deliverySinks ? [
20505
+ ...DEFAULT_LINKS2,
20506
+ {
20507
+ description: "Audit and trace delivery sink health.",
20508
+ href: options.deliverySinks.htmlPath === false ? options.deliverySinks.path ?? "/api/voice-delivery-sinks" : options.deliverySinks.htmlPath ?? "/delivery-sinks",
20509
+ label: "Delivery Sinks",
20510
+ statusHref: options.deliverySinks.path ?? "/api/voice-delivery-sinks"
20511
+ }
20512
+ ] : DEFAULT_LINKS2),
20483
20513
  status: statuses.includes("fail") ? "fail" : "pass",
20484
20514
  surfaces,
20485
20515
  ...countStatus(statuses)
@@ -20491,7 +20521,7 @@ var escapeHtml35 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&l
20491
20521
  var renderVoiceOpsStatusHTML = (report, options = {}) => {
20492
20522
  const title = options.title ?? "AbsoluteJS Voice Ops Status";
20493
20523
  const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
20494
- const value = "recovered" in surface ? surface.total === 0 ? "0 events" : `${surface.recovered}/${surface.total}` : ("total" in surface) ? `${Math.max(surface.total - ("failed" in surface ? surface.failed : ("degraded" in surface) ? surface.degraded : 0), 0)}/${surface.total}` : surface.status;
20524
+ const value = "recovered" in surface ? surface.total === 0 ? "0 events" : `${surface.recovered}/${surface.total}` : ("auditTotal" in surface) ? `${surface.auditTotal + surface.traceTotal} deliveries` : ("total" in surface) ? `${Math.max(surface.total - ("failed" in surface ? surface.failed : ("degraded" in surface) ? surface.degraded : 0), 0)}/${surface.total}` : surface.status;
20495
20525
  return `<article class="surface ${escapeHtml35(surface.status)}"><span>${escapeHtml35(surface.status.toUpperCase())}</span><h2>${escapeHtml35(key)}</h2><strong>${escapeHtml35(value)}</strong></article>`;
20496
20526
  }).join("");
20497
20527
  return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml35(title)}</title><style>body{background:#0d141b;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.2),rgba(245,158,11,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.surfaces{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.surface{background:#151d26;border:1px solid #283544;border-radius:20px;padding:18px}.surface span{color:#aab5c0;font-size:.78rem;font-weight:900;letter-spacing:.08em}.surface strong{font-size:1.5rem}.pass{border-color:rgba(34,197,94,.55)}.fail{border-color:rgba(239,68,68,.75)}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Ops status</p><h1>${escapeHtml35(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml35(report.status)}">Overall: ${escapeHtml35(report.status.toUpperCase())}</p><p>${report.passed}/${report.total} checks passing</p></section><section class="surfaces">${surfaces || '<article class="surface pass"><span>PASS</span><h2>No checks configured</h2><strong>0/0</strong></article>'}</section></main></body></html>`;
@@ -1,4 +1,5 @@
1
1
  import { Elysia } from 'elysia';
2
+ import { type VoiceDeliverySinkReport, type VoiceDeliverySinkRoutesOptions } from './deliverySinkRoutes';
2
3
  import { type VoiceQualityReport } from './qualityRoutes';
3
4
  import { type VoiceRoutingEvent } from './resilienceRoutes';
4
5
  import { type VoiceSessionListItem } from './sessionReplay';
@@ -17,6 +18,7 @@ export type VoiceOpsConsoleReport = {
17
18
  total: number;
18
19
  };
19
20
  links: VoiceOpsConsoleLink[];
21
+ deliverySinks?: VoiceDeliverySinkReport;
20
22
  providers: {
21
23
  degraded: number;
22
24
  healthy: number;
@@ -34,6 +36,7 @@ export type VoiceOpsConsoleReport = {
34
36
  };
35
37
  export type VoiceOpsConsoleRoutesOptions = {
36
38
  headers?: HeadersInit;
39
+ deliverySinks?: false | VoiceDeliverySinkRoutesOptions;
37
40
  links?: VoiceOpsConsoleLink[];
38
41
  llmProviders?: readonly string[];
39
42
  name?: string;
@@ -1,4 +1,5 @@
1
1
  import { type VoiceEvalLink, type VoiceEvalRoutesOptions } from './evalRoutes';
2
+ import { type VoiceDeliverySinkRoutesOptions } from './deliverySinkRoutes';
2
3
  import { type VoiceQualityRoutesOptions } from './qualityRoutes';
3
4
  import { type VoiceProviderFallbackRecoverySummary } from './sessionReplay';
4
5
  import { type VoiceTraceEventStore } from './trace';
@@ -8,8 +9,10 @@ export type VoiceOpsStatusLink = VoiceEvalLink & {
8
9
  statusHref?: string;
9
10
  };
10
11
  export type VoiceOpsStatusOptions<TProvider extends string = string> = {
12
+ deliverySinks?: false | VoiceDeliverySinkRoutesOptions;
11
13
  evals?: false | Partial<VoiceEvalRoutesOptions>;
12
14
  include?: {
15
+ deliverySinks?: boolean;
13
16
  handoffs?: boolean;
14
17
  providers?: boolean;
15
18
  providerRecovery?: boolean;
@@ -37,6 +40,11 @@ export type VoiceOpsStatusReport = {
37
40
  status: VoiceOpsStatus;
38
41
  total: number;
39
42
  };
43
+ deliverySinks?: {
44
+ auditTotal: number;
45
+ status: VoiceOpsStatus;
46
+ traceTotal: number;
47
+ };
40
48
  providers?: {
41
49
  degraded: number;
42
50
  status: VoiceOpsStatus;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.142",
3
+ "version": "0.0.22-beta.143",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",