@absolutejs/voice 0.0.22-beta.85 → 0.0.22-beta.87

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.d.ts CHANGED
@@ -20,7 +20,7 @@ export { createVoiceProviderHealthHTMLHandler, createVoiceProviderHealthJSONHand
20
20
  export { createVoiceProviderCapabilityHTMLHandler, createVoiceProviderCapabilityJSONHandler, createVoiceProviderCapabilityRoutes, renderVoiceProviderCapabilityHTML, summarizeVoiceProviderCapabilities } from './providerCapabilities';
21
21
  export { buildVoiceOpsConsoleReport, createVoiceOpsConsoleRoutes, renderVoiceOpsConsoleHTML } from './opsConsoleRoutes';
22
22
  export { createVoiceQualityRoutes, evaluateVoiceQuality, renderVoiceQualityHTML } from './qualityRoutes';
23
- export { createVoiceResilienceRoutes, createVoiceRoutingDecisionSummary, listVoiceRoutingEvents, renderVoiceResilienceHTML, summarizeVoiceRoutingDecision } from './resilienceRoutes';
23
+ export { createVoiceResilienceRoutes, createVoiceRoutingDecisionSummary, listVoiceRoutingEvents, renderVoiceResilienceHTML, summarizeVoiceRoutingDecision, summarizeVoiceRoutingSessions } from './resilienceRoutes';
24
24
  export { createVoiceSTTProviderRouter, createVoiceTTSProviderRouter } from './providerAdapters';
25
25
  export { buildVoiceTraceReplay, createVoiceMemoryTraceSinkDeliveryStore, createVoiceTraceHTTPSink, createVoiceMemoryTraceEventStore, createVoiceTraceSinkDeliveryId, createVoiceTraceSinkDeliveryRecord, createVoiceTraceSinkStore, createVoiceTraceEvent, createVoiceTraceEventId, deliverVoiceTraceEventsToSinks, evaluateVoiceTrace, exportVoiceTrace, filterVoiceTraceEvents, pruneVoiceTraceEvents, redactVoiceTraceEvent, redactVoiceTraceEvents, redactVoiceTraceText, renderVoiceTraceHTML, renderVoiceTraceMarkdown, resolveVoiceTraceRedactionOptions, selectVoiceTraceEventsForPrune, summarizeVoiceTrace } from './trace';
26
26
  export { createVoiceSQLiteExternalObjectMapStore, createVoiceSQLiteIntegrationEventStore, createVoiceSQLiteReviewStore, createVoiceSQLiteRuntimeStorage, createVoiceSQLiteSessionStore, createVoiceSQLiteTaskStore, createVoiceSQLiteTelephonyWebhookIdempotencyStore, createVoiceSQLiteTraceSinkDeliveryStore, createVoiceSQLiteTraceEventStore } from './sqliteStore';
@@ -62,7 +62,7 @@ export type { VoiceOutcomeContractDefinition, VoiceOutcomeContractHTMLHandlerOpt
62
62
  export type { VoiceTelephonyOutcomeAction, VoiceTelephonyOutcomeDecision, VoiceTelephonyOutcomePolicy, VoiceTelephonyOutcomeProviderEvent, VoiceTelephonyOutcomeRouteResult, VoiceTelephonyOutcomeStatusDecision, VoiceTelephonyWebhookDecision, VoiceTelephonyWebhookHandlerOptions, VoiceTelephonyWebhookIdempotencyStore, VoiceTelephonyWebhookParseInput, VoiceTelephonyWebhookProvider, VoiceTelephonyWebhookRoutesOptions, VoiceTelephonyWebhookVerificationResult, StoredVoiceTelephonyWebhookDecision } from './telephonyOutcome';
63
63
  export type { VoiceOpsConsoleLink, VoiceOpsConsoleReport, VoiceOpsConsoleRoutesOptions } from './opsConsoleRoutes';
64
64
  export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
65
- export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind } from './resilienceRoutes';
65
+ export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingKindSummary, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind, VoiceRoutingSessionSummary, VoiceRoutingSessionSummaryOptions } from './resilienceRoutes';
66
66
  export type { VoiceIOProviderRouterEvent, VoiceIOProviderRouterOptions, VoiceIOProviderRouterPolicy, VoiceIOProviderRouterPolicyConfig, VoiceSTTProviderRouterOptions, VoiceTTSProviderRouterOptions } from './providerAdapters';
67
67
  export type { VoiceAgent, VoiceAgentMessage, VoiceAgentMessageRole, VoiceAgentModel, VoiceAgentModelInput, VoiceAgentModelOutput, VoiceAgentOptions, VoiceAgentRunResult, VoiceAgentSquadOptions, VoiceAgentTool, VoiceAgentToolCall, VoiceAgentToolResult } from './agent';
68
68
  export type { VoiceToolRetryDelay, VoiceToolRuntime, VoiceToolRuntimeExecuteInput, VoiceToolRuntimeOptions, VoiceToolRuntimeResult } from './toolRuntime';
package/dist/index.js CHANGED
@@ -8539,6 +8539,68 @@ var summarizeVoiceRoutingDecision = (events, options = {}) => {
8539
8539
  const limited = typeof options.limit === "number" && options.limit >= 0 ? routingEvents.slice(0, options.limit) : routingEvents;
8540
8540
  return limited[0] ?? null;
8541
8541
  };
8542
+ var createEmptyKindSummary = () => ({
8543
+ errorCount: 0,
8544
+ fallbackCount: 0,
8545
+ providers: [],
8546
+ runCount: 0,
8547
+ timeoutCount: 0
8548
+ });
8549
+ var summarizeVoiceRoutingSessions = (events, options = {}) => {
8550
+ const routingEvents = (events.some((event) => ("payload" in event)) ? listVoiceRoutingEvents(events) : [...events]).filter((event) => !options.sessionId || event.sessionId === options.sessionId);
8551
+ const sessions = new Map;
8552
+ for (const event of routingEvents) {
8553
+ const existing = sessions.get(event.sessionId);
8554
+ const summary = existing ?? {
8555
+ errorCount: 0,
8556
+ eventCount: 0,
8557
+ fallbackCount: 0,
8558
+ kinds: {
8559
+ llm: createEmptyKindSummary(),
8560
+ stt: createEmptyKindSummary(),
8561
+ tts: createEmptyKindSummary()
8562
+ },
8563
+ lastEventAt: event.at,
8564
+ sessionId: event.sessionId,
8565
+ startedAt: event.at,
8566
+ status: "healthy",
8567
+ timeoutCount: 0
8568
+ };
8569
+ summary.eventCount += 1;
8570
+ summary.startedAt = Math.min(summary.startedAt, event.at);
8571
+ summary.lastEventAt = Math.max(summary.lastEventAt, event.at);
8572
+ if (event.status === "error") {
8573
+ summary.errorCount += 1;
8574
+ }
8575
+ if (event.status === "fallback") {
8576
+ summary.fallbackCount += 1;
8577
+ }
8578
+ if (event.timedOut) {
8579
+ summary.timeoutCount += 1;
8580
+ }
8581
+ const kind = summary.kinds[event.kind];
8582
+ kind.runCount += 1;
8583
+ if (event.status === "error") {
8584
+ kind.errorCount += 1;
8585
+ }
8586
+ if (event.status === "fallback") {
8587
+ kind.fallbackCount += 1;
8588
+ }
8589
+ if (event.timedOut) {
8590
+ kind.timeoutCount += 1;
8591
+ }
8592
+ if (event.provider && !kind.providers.includes(event.provider)) {
8593
+ kind.providers.push(event.provider);
8594
+ }
8595
+ if (!kind.latest || event.at > kind.latest.at) {
8596
+ kind.latest = event;
8597
+ }
8598
+ summary.status = summary.errorCount > 0 || summary.timeoutCount > 0 ? "degraded" : summary.fallbackCount > 0 ? "fallback" : "healthy";
8599
+ sessions.set(event.sessionId, summary);
8600
+ }
8601
+ const sorted = [...sessions.values()].sort((left, right) => right.lastEventAt - left.lastEventAt);
8602
+ return typeof options.limit === "number" && options.limit >= 0 ? sorted.slice(0, options.limit) : sorted;
8603
+ };
8542
8604
  var createVoiceRoutingDecisionSummary = async (options) => {
8543
8605
  const events = await options.store.list({
8544
8606
  sessionId: options.sessionId,
@@ -8618,6 +8680,41 @@ var renderTimeline2 = (events) => {
8618
8680
  </article>
8619
8681
  `).join("")}</div>`;
8620
8682
  };
8683
+ var renderSessionKind = (kind, summary) => {
8684
+ const latest = summary.latest;
8685
+ const provider = latest?.provider ?? summary.providers[0] ?? "none";
8686
+ const status = latest?.status ?? "idle";
8687
+ const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
8688
+ return `<div>
8689
+ <dt>${escapeHtml10(kind.toUpperCase())}</dt>
8690
+ <dd>${escapeHtml10(provider)}${escapeHtml10(fallback)}</dd>
8691
+ <small>${escapeHtml10(status)} \xB7 ${summary.runCount} event${summary.runCount === 1 ? "" : "s"} \xB7 ${summary.errorCount} error${summary.errorCount === 1 ? "" : "s"} \xB7 ${summary.fallbackCount} fallback${summary.fallbackCount === 1 ? "" : "s"}</small>
8692
+ </div>`;
8693
+ };
8694
+ var renderSessionSummaries = (sessions) => {
8695
+ if (sessions.length === 0) {
8696
+ return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
8697
+ }
8698
+ return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
8699
+ <article class="card session ${escapeHtml10(session.status)}">
8700
+ <div class="card-header">
8701
+ <strong>${escapeHtml10(session.sessionId)}</strong>
8702
+ <span>${escapeHtml10(session.status)}</span>
8703
+ </div>
8704
+ <p>
8705
+ <span class="pill">${session.eventCount} routing events</span>
8706
+ <span class="pill">${session.fallbackCount} fallbacks</span>
8707
+ <span class="pill">${session.errorCount} errors</span>
8708
+ <span class="pill">${session.timeoutCount} timeouts</span>
8709
+ </p>
8710
+ <dl>
8711
+ ${renderSessionKind("llm", session.kinds.llm)}
8712
+ ${renderSessionKind("stt", session.kinds.stt)}
8713
+ ${renderSessionKind("tts", session.kinds.tts)}
8714
+ </dl>
8715
+ </article>
8716
+ `).join("")}</div>`;
8717
+ };
8621
8718
  var renderSimulationControls = (kind, simulation) => {
8622
8719
  if (!simulation) {
8623
8720
  return "";
@@ -8656,6 +8753,7 @@ var renderVoiceResilienceHTML = (input) => {
8656
8753
  section, .card { background: rgba(19, 22, 27, 0.92); border: 1px solid #27272a; border-radius: 20px; padding: 20px; }
8657
8754
  .hero { background: linear-gradient(135deg, rgba(14, 165, 233, 0.18), rgba(245, 158, 11, 0.12)); }
8658
8755
  .grid, .provider-grid { display: grid; gap: 14px; grid-template-columns: repeat(4, minmax(0, 1fr)); }
8756
+ .session-grid { display: grid; gap: 14px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
8659
8757
  .timeline { display: grid; gap: 12px; }
8660
8758
  .card-header { align-items: center; display: flex; gap: 12px; justify-content: space-between; }
8661
8759
  .card-header strong { font-size: 1.05rem; }
@@ -8667,8 +8765,9 @@ var renderVoiceResilienceHTML = (input) => {
8667
8765
  .pill { background: #0f1217; border: 1px solid #3f3f46; border-radius: 999px; color: #d4d4d8; display: inline-flex; margin: 3px 4px 3px 0; padding: 5px 9px; }
8668
8766
  .danger { border-color: rgba(239, 68, 68, 0.75); color: #fecaca; }
8669
8767
  .event.error { border-color: rgba(239, 68, 68, 0.7); }
8670
- .event.fallback { border-color: rgba(245, 158, 11, 0.7); }
8671
- .event.success, .provider.healthy { border-color: rgba(34, 197, 94, 0.5); }
8768
+ .event.fallback, .session.fallback { border-color: rgba(245, 158, 11, 0.7); }
8769
+ .event.success, .provider.healthy, .session.healthy { border-color: rgba(34, 197, 94, 0.5); }
8770
+ .session.degraded { border-color: rgba(239, 68, 68, 0.7); }
8672
8771
  .provider.suppressed, .provider.degraded, .provider.rate-limited { border-color: rgba(239, 68, 68, 0.7); }
8673
8772
  .provider.recoverable { border-color: rgba(59, 130, 246, 0.7); }
8674
8773
  button { background: #f59e0b; border: 0; border-radius: 999px; color: #111827; cursor: pointer; font-weight: 800; padding: 10px 14px; }
@@ -8676,7 +8775,7 @@ var renderVoiceResilienceHTML = (input) => {
8676
8775
  .simulate-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
8677
8776
  .simulate-output { background: #050505; border: 1px solid #27272a; border-radius: 14px; color: #d4d4d8; overflow: auto; padding: 12px; white-space: pre-wrap; }
8678
8777
  a { color: #f59e0b; }
8679
- @media (max-width: 850px) { .grid, .provider-grid, dl { grid-template-columns: 1fr; } }
8778
+ @media (max-width: 850px) { .grid, .provider-grid, .session-grid, dl { grid-template-columns: 1fr; } }
8680
8779
  </style>
8681
8780
  </head>
8682
8781
  <body>
@@ -8693,6 +8792,11 @@ var renderVoiceResilienceHTML = (input) => {
8693
8792
  <article class="card metric"><span>Errors</span><strong>${summary.errors}</strong></article>
8694
8793
  <article class="card metric"><span>Timeouts</span><strong>${summary.timeouts}</strong></article>
8695
8794
  </section>
8795
+ <section>
8796
+ <h2>Call-level routing summaries</h2>
8797
+ <p class="muted">A compact per-call view of which LLM, STT, and TTS providers handled the session, including fallback and timeout counts.</p>
8798
+ ${renderSessionSummaries(input.routingSessions)}
8799
+ </section>
8696
8800
  <section>
8697
8801
  <h2>LLM provider health</h2>
8698
8802
  ${renderProviderCards("LLM", input.llmProviderHealth)}
@@ -8790,13 +8894,15 @@ var createVoiceResilienceRoutes = (options) => {
8790
8894
  const events = await options.store.list();
8791
8895
  const sttEvents = events.filter((event) => event.payload.kind === "stt");
8792
8896
  const ttsEvents = events.filter((event) => event.payload.kind === "tts");
8897
+ const routingEvents = listVoiceRoutingEvents(events);
8793
8898
  const data = {
8794
8899
  links: options.links,
8795
8900
  llmProviderHealth: await summarizeVoiceProviderHealth({
8796
8901
  events,
8797
8902
  providers: options.llmProviders ?? []
8798
8903
  }),
8799
- routingEvents: listVoiceRoutingEvents(events),
8904
+ routingEvents,
8905
+ routingSessions: summarizeVoiceRoutingSessions(routingEvents),
8800
8906
  sttProviderHealth: await summarizeVoiceProviderHealth({
8801
8907
  events: sttEvents,
8802
8908
  providers: options.sttProviders ?? []
@@ -12845,9 +12951,6 @@ var createVoiceTTSProviderRouter = (options) => {
12845
12951
  session.on("error", (event) => {
12846
12952
  emitter.emit("error", event);
12847
12953
  });
12848
- session.on("close", (event) => {
12849
- emitter.emit("close", event);
12850
- });
12851
12954
  };
12852
12955
  const openProvider = async (provider, attempt) => {
12853
12956
  const adapter = options.adapters[provider];
@@ -17190,6 +17293,7 @@ export {
17190
17293
  summarizeVoiceTrace,
17191
17294
  summarizeVoiceSessions,
17192
17295
  summarizeVoiceSessionReplay,
17296
+ summarizeVoiceRoutingSessions,
17193
17297
  summarizeVoiceRoutingDecision,
17194
17298
  summarizeVoiceProviderHealth,
17195
17299
  summarizeVoiceProviderCapabilities,
@@ -28,6 +28,29 @@ export type VoiceRoutingDecisionSummaryOptions = {
28
28
  sessionId?: string;
29
29
  store: VoiceTraceEventStore;
30
30
  };
31
+ export type VoiceRoutingKindSummary = {
32
+ errorCount: number;
33
+ fallbackCount: number;
34
+ latest?: VoiceRoutingEvent;
35
+ providers: string[];
36
+ runCount: number;
37
+ timeoutCount: number;
38
+ };
39
+ export type VoiceRoutingSessionSummary = {
40
+ errorCount: number;
41
+ eventCount: number;
42
+ fallbackCount: number;
43
+ kinds: Record<VoiceRoutingEventKind, VoiceRoutingKindSummary>;
44
+ lastEventAt: number;
45
+ sessionId: string;
46
+ startedAt: number;
47
+ status: 'healthy' | 'fallback' | 'degraded';
48
+ timeoutCount: number;
49
+ };
50
+ export type VoiceRoutingSessionSummaryOptions = {
51
+ limit?: number;
52
+ sessionId?: string;
53
+ };
31
54
  export type VoiceResilienceLink = {
32
55
  href: string;
33
56
  label: string;
@@ -51,6 +74,7 @@ export type VoiceResiliencePageData = {
51
74
  links?: readonly VoiceResilienceLink[];
52
75
  llmProviderHealth: VoiceProviderHealthSummary<string>[];
53
76
  routingEvents: VoiceRoutingEvent[];
77
+ routingSessions: VoiceRoutingSessionSummary[];
54
78
  sttProviderHealth: VoiceProviderHealthSummary<string>[];
55
79
  sttSimulation?: VoiceResilienceIOSimulator<string>;
56
80
  title?: string;
@@ -73,6 +97,7 @@ export type VoiceResilienceRoutesOptions = {
73
97
  };
74
98
  export declare const listVoiceRoutingEvents: (events: StoredVoiceTraceEvent[]) => VoiceRoutingEvent[];
75
99
  export declare const summarizeVoiceRoutingDecision: (events: StoredVoiceTraceEvent[], options?: Omit<VoiceRoutingDecisionSummaryOptions, "store">) => VoiceRoutingDecisionSummary | null;
100
+ export declare const summarizeVoiceRoutingSessions: (events: StoredVoiceTraceEvent[] | VoiceRoutingEvent[], options?: VoiceRoutingSessionSummaryOptions) => VoiceRoutingSessionSummary[];
76
101
  export declare const createVoiceRoutingDecisionSummary: (options: VoiceRoutingDecisionSummaryOptions) => Promise<VoiceRoutingDecisionSummary | null>;
77
102
  export declare const renderVoiceResilienceHTML: (input: VoiceResiliencePageData) => string;
78
103
  export declare const createVoiceResilienceRoutes: (options: VoiceResilienceRoutesOptions) => Elysia<"", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.85",
3
+ "version": "0.0.22-beta.87",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",