@absolutejs/voice 0.0.22-beta.49 → 0.0.22-beta.50

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
@@ -9191,6 +9191,86 @@ var toOpsLinks = (links) => links.map((link) => ({
9191
9191
  statusHref: link.statusHref
9192
9192
  }));
9193
9193
  var toResilienceLinks = (links) => links.map(({ href, label }) => ({ href, label }));
9194
+ var countStatus = (statuses) => ({
9195
+ failed: statuses.filter((status) => status === "fail").length,
9196
+ passed: statuses.filter((status) => status === "pass").length,
9197
+ total: statuses.length
9198
+ });
9199
+ var summarizeVoiceAppKitStatus = async (options) => {
9200
+ const links = resolveLinks(options.links);
9201
+ const events = filterVoiceTraceEvents(await options.store.list());
9202
+ const [quality, workflows, providers, sessions, handoffs] = await Promise.all([
9203
+ options.quality === false ? undefined : evaluateVoiceQuality({
9204
+ events,
9205
+ thresholds: options.quality?.thresholds
9206
+ }),
9207
+ options.evals === false ? undefined : runVoiceScenarioEvals({
9208
+ events,
9209
+ scenarios: options.evals?.scenarios
9210
+ }),
9211
+ options.providerHealth === false ? undefined : summarizeVoiceProviderHealth({
9212
+ events,
9213
+ providers: options.llmProviders
9214
+ }),
9215
+ options.sessions === false ? undefined : summarizeVoiceSessions({
9216
+ events
9217
+ }),
9218
+ options.handoffs === false ? undefined : summarizeVoiceHandoffHealth({
9219
+ events
9220
+ })
9221
+ ]);
9222
+ const surfaces = {};
9223
+ const statuses = [];
9224
+ if (quality) {
9225
+ surfaces.quality = { status: quality.status };
9226
+ statuses.push(quality.status);
9227
+ }
9228
+ if (workflows) {
9229
+ const status = workflows.status;
9230
+ surfaces.workflows = {
9231
+ failed: workflows.failed,
9232
+ status,
9233
+ total: workflows.total
9234
+ };
9235
+ statuses.push(status);
9236
+ }
9237
+ if (providers) {
9238
+ const degraded = providers.filter((provider) => provider.status === "degraded" || provider.status === "rate-limited" || provider.status === "suppressed").length;
9239
+ const status = degraded > 0 ? "fail" : "pass";
9240
+ surfaces.providers = {
9241
+ degraded,
9242
+ status,
9243
+ total: providers.length
9244
+ };
9245
+ statuses.push(status);
9246
+ }
9247
+ if (sessions) {
9248
+ const failed = sessions.filter((session) => session.status === "failed").length;
9249
+ const status = failed > 0 ? "fail" : "pass";
9250
+ surfaces.sessions = {
9251
+ failed,
9252
+ status,
9253
+ total: sessions.length
9254
+ };
9255
+ statuses.push(status);
9256
+ }
9257
+ if (handoffs) {
9258
+ const status = handoffs.failed > 0 ? "fail" : "pass";
9259
+ surfaces.handoffs = {
9260
+ failed: handoffs.failed,
9261
+ status,
9262
+ total: handoffs.total
9263
+ };
9264
+ statuses.push(status);
9265
+ }
9266
+ return {
9267
+ checkedAt: Date.now(),
9268
+ links,
9269
+ status: statuses.includes("fail") ? "fail" : "pass",
9270
+ surfaces,
9271
+ ...countStatus(statuses)
9272
+ };
9273
+ };
9194
9274
  var createVoiceAppKitRoutes = (options) => {
9195
9275
  const routes = new Elysia11({
9196
9276
  name: options.name ?? "absolutejs-voice-app-kit"
@@ -9201,6 +9281,9 @@ var createVoiceAppKitRoutes = (options) => {
9201
9281
  store: options.store
9202
9282
  };
9203
9283
  const surfaces = [];
9284
+ if (options.appStatus !== false) {
9285
+ routes.get(options.appStatus?.path ?? "/app-kit/status", () => summarizeVoiceAppKitStatus(options));
9286
+ }
9204
9287
  if (options.providerHealth !== false) {
9205
9288
  surfaces.push("providerHealth");
9206
9289
  routes.use(createVoiceProviderHealthRoutes({
@@ -13859,6 +13942,7 @@ export {
13859
13942
  summarizeVoiceHandoffDeliveries,
13860
13943
  summarizeVoiceAssistantRuns,
13861
13944
  summarizeVoiceAssistantHealth,
13945
+ summarizeVoiceAppKitStatus,
13862
13946
  startVoiceOpsTask,
13863
13947
  shapeTelephonyAssistantText,
13864
13948
  selectVoiceTraceEventsForPrune,
@@ -1,3 +1,4 @@
1
+ export { useVoiceAppKitStatus } from './useVoiceAppKitStatus';
1
2
  export { useVoiceStream } from './useVoiceStream';
2
3
  export { useVoiceController } from './useVoiceController';
3
4
  export { useVoiceProviderStatus } from './useVoiceProviderStatus';
@@ -69,9 +69,107 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
71
 
72
- // src/react/useVoiceStream.tsx
72
+ // src/react/useVoiceAppKitStatus.tsx
73
73
  import { useEffect, useRef, useSyncExternalStore } from "react";
74
74
 
75
+ // src/client/appKitStatus.ts
76
+ var fetchVoiceAppKitStatus = async (path = "/app-kit/status", options = {}) => {
77
+ const fetchImpl = options.fetch ?? globalThis.fetch;
78
+ const response = await fetchImpl(path);
79
+ if (!response.ok) {
80
+ throw new Error(`Voice app kit status failed: HTTP ${response.status}`);
81
+ }
82
+ return await response.json();
83
+ };
84
+ var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
85
+ const listeners = new Set;
86
+ let closed = false;
87
+ let timer;
88
+ let snapshot = {
89
+ error: null,
90
+ isLoading: false
91
+ };
92
+ const emit = () => {
93
+ for (const listener of listeners) {
94
+ listener();
95
+ }
96
+ };
97
+ const refresh = async () => {
98
+ if (closed) {
99
+ return snapshot.report;
100
+ }
101
+ snapshot = {
102
+ ...snapshot,
103
+ error: null,
104
+ isLoading: true
105
+ };
106
+ emit();
107
+ try {
108
+ const report = await fetchVoiceAppKitStatus(path, options);
109
+ snapshot = {
110
+ error: null,
111
+ isLoading: false,
112
+ report,
113
+ updatedAt: Date.now()
114
+ };
115
+ emit();
116
+ return report;
117
+ } catch (error) {
118
+ snapshot = {
119
+ ...snapshot,
120
+ error: error instanceof Error ? error.message : String(error),
121
+ isLoading: false
122
+ };
123
+ emit();
124
+ throw error;
125
+ }
126
+ };
127
+ const close = () => {
128
+ closed = true;
129
+ if (timer) {
130
+ clearInterval(timer);
131
+ timer = undefined;
132
+ }
133
+ listeners.clear();
134
+ };
135
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
136
+ timer = setInterval(() => {
137
+ refresh().catch(() => {});
138
+ }, options.intervalMs);
139
+ }
140
+ return {
141
+ close,
142
+ getServerSnapshot: () => snapshot,
143
+ getSnapshot: () => snapshot,
144
+ refresh,
145
+ subscribe: (listener) => {
146
+ listeners.add(listener);
147
+ return () => {
148
+ listeners.delete(listener);
149
+ };
150
+ }
151
+ };
152
+ };
153
+
154
+ // src/react/useVoiceAppKitStatus.tsx
155
+ var useVoiceAppKitStatus = (path = "/app-kit/status", options = {}) => {
156
+ const storeRef = useRef(null);
157
+ if (!storeRef.current) {
158
+ storeRef.current = createVoiceAppKitStatusStore(path, options);
159
+ }
160
+ const store = storeRef.current;
161
+ useEffect(() => {
162
+ store.refresh().catch(() => {});
163
+ return () => store.close();
164
+ }, [store]);
165
+ return {
166
+ ...useSyncExternalStore(store.subscribe, store.getSnapshot, store.getServerSnapshot),
167
+ refresh: store.refresh
168
+ };
169
+ };
170
+ // src/react/useVoiceStream.tsx
171
+ import { useEffect as useEffect2, useRef as useRef2, useSyncExternalStore as useSyncExternalStore2 } from "react";
172
+
75
173
  // src/client/actions.ts
76
174
  var normalizeErrorMessage = (value) => {
77
175
  if (typeof value === "string" && value.trim()) {
@@ -598,13 +696,13 @@ var EMPTY_SNAPSHOT = {
598
696
  turns: []
599
697
  };
600
698
  var useVoiceStream = (path, options = {}) => {
601
- const streamRef = useRef(null);
699
+ const streamRef = useRef2(null);
602
700
  if (!streamRef.current) {
603
701
  streamRef.current = createVoiceStream(path, options);
604
702
  }
605
703
  const stream = streamRef.current;
606
- useEffect(() => () => stream.close(), [stream]);
607
- const snapshot = useSyncExternalStore(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
704
+ useEffect2(() => () => stream.close(), [stream]);
705
+ const snapshot = useSyncExternalStore2(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
608
706
  return {
609
707
  ...snapshot,
610
708
  callControl: (message) => stream.callControl(message),
@@ -614,7 +712,7 @@ var useVoiceStream = (path, options = {}) => {
614
712
  };
615
713
  };
616
714
  // src/react/useVoiceController.tsx
617
- import { useEffect as useEffect2, useRef as useRef2, useSyncExternalStore as useSyncExternalStore2 } from "react";
715
+ import { useEffect as useEffect3, useRef as useRef3, useSyncExternalStore as useSyncExternalStore3 } from "react";
618
716
 
619
717
  // src/client/htmx.ts
620
718
  var DEFAULT_EVENT_NAME = "voice-refresh";
@@ -1261,13 +1359,13 @@ var EMPTY_SNAPSHOT2 = {
1261
1359
  turns: []
1262
1360
  };
1263
1361
  var useVoiceController = (path, options = {}) => {
1264
- const controllerRef = useRef2(null);
1362
+ const controllerRef = useRef3(null);
1265
1363
  if (!controllerRef.current) {
1266
1364
  controllerRef.current = createVoiceController(path, options);
1267
1365
  }
1268
1366
  const controller = controllerRef.current;
1269
- useEffect2(() => () => controller.close(), [controller]);
1270
- const snapshot = useSyncExternalStore2(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
1367
+ useEffect3(() => () => controller.close(), [controller]);
1368
+ const snapshot = useSyncExternalStore3(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
1271
1369
  return {
1272
1370
  ...snapshot,
1273
1371
  bindHTMX: controller.bindHTMX,
@@ -1281,7 +1379,7 @@ var useVoiceController = (path, options = {}) => {
1281
1379
  };
1282
1380
  };
1283
1381
  // src/react/useVoiceProviderStatus.tsx
1284
- import { useEffect as useEffect3, useRef as useRef3, useSyncExternalStore as useSyncExternalStore3 } from "react";
1382
+ import { useEffect as useEffect4, useRef as useRef4, useSyncExternalStore as useSyncExternalStore4 } from "react";
1285
1383
 
1286
1384
  // src/client/providerStatus.ts
1287
1385
  var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
@@ -1365,22 +1463,22 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
1365
1463
 
1366
1464
  // src/react/useVoiceProviderStatus.tsx
1367
1465
  var useVoiceProviderStatus = (path = "/api/provider-status", options = {}) => {
1368
- const storeRef = useRef3(null);
1466
+ const storeRef = useRef4(null);
1369
1467
  if (!storeRef.current) {
1370
1468
  storeRef.current = createVoiceProviderStatusStore(path, options);
1371
1469
  }
1372
1470
  const store = storeRef.current;
1373
- useEffect3(() => {
1471
+ useEffect4(() => {
1374
1472
  store.refresh().catch(() => {});
1375
1473
  return () => store.close();
1376
1474
  }, [store]);
1377
1475
  return {
1378
- ...useSyncExternalStore3(store.subscribe, store.getSnapshot, store.getServerSnapshot),
1476
+ ...useSyncExternalStore4(store.subscribe, store.getSnapshot, store.getServerSnapshot),
1379
1477
  refresh: store.refresh
1380
1478
  };
1381
1479
  };
1382
1480
  // src/react/useVoiceWorkflowStatus.tsx
1383
- import { useEffect as useEffect4, useRef as useRef4, useSyncExternalStore as useSyncExternalStore4 } from "react";
1481
+ import { useEffect as useEffect5, useRef as useRef5, useSyncExternalStore as useSyncExternalStore5 } from "react";
1384
1482
 
1385
1483
  // src/client/workflowStatus.ts
1386
1484
  var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
@@ -1463,17 +1561,17 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
1463
1561
 
1464
1562
  // src/react/useVoiceWorkflowStatus.tsx
1465
1563
  var useVoiceWorkflowStatus = (path = "/evals/scenarios/json", options = {}) => {
1466
- const storeRef = useRef4(null);
1564
+ const storeRef = useRef5(null);
1467
1565
  if (!storeRef.current) {
1468
1566
  storeRef.current = createVoiceWorkflowStatusStore(path, options);
1469
1567
  }
1470
1568
  const store = storeRef.current;
1471
- useEffect4(() => {
1569
+ useEffect5(() => {
1472
1570
  store.refresh().catch(() => {});
1473
1571
  return () => store.close();
1474
1572
  }, [store]);
1475
1573
  return {
1476
- ...useSyncExternalStore4(store.subscribe, store.getSnapshot, store.getServerSnapshot),
1574
+ ...useSyncExternalStore5(store.subscribe, store.getSnapshot, store.getServerSnapshot),
1477
1575
  refresh: store.refresh
1478
1576
  };
1479
1577
  };
@@ -1481,5 +1579,6 @@ export {
1481
1579
  useVoiceWorkflowStatus,
1482
1580
  useVoiceStream,
1483
1581
  useVoiceProviderStatus,
1484
- useVoiceController
1582
+ useVoiceController,
1583
+ useVoiceAppKitStatus
1485
1584
  };
@@ -0,0 +1,8 @@
1
+ import { type VoiceAppKitStatusClientOptions } from '../client/appKitStatus';
2
+ export declare const useVoiceAppKitStatus: (path?: string, options?: VoiceAppKitStatusClientOptions) => {
3
+ refresh: () => Promise<import("..").VoiceAppKitStatusReport | undefined>;
4
+ error: string | null;
5
+ isLoading: boolean;
6
+ report?: import("..").VoiceAppKitStatusReport;
7
+ updatedAt?: number;
8
+ };
@@ -0,0 +1,8 @@
1
+ import type { VoiceAppKitStatusClientOptions } from '../client/appKitStatus';
2
+ export declare const createVoiceAppKitStatus: (path?: string, options?: VoiceAppKitStatusClientOptions) => {
3
+ close: () => void;
4
+ getServerSnapshot: () => import("../client").VoiceAppKitStatusSnapshot;
5
+ getSnapshot: () => import("../client").VoiceAppKitStatusSnapshot;
6
+ refresh: () => Promise<import("..").VoiceAppKitStatusReport | undefined>;
7
+ subscribe: (listener: () => void) => () => void;
8
+ };
@@ -1,3 +1,4 @@
1
+ export { createVoiceAppKitStatus } from './createVoiceAppKitStatus';
1
2
  export { createVoiceStream } from './createVoiceStream';
2
3
  export { createVoiceProviderStatus } from './createVoiceProviderStatus';
3
4
  export { createVoiceWorkflowStatus } from './createVoiceWorkflowStatus';
@@ -69,6 +69,87 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
69
69
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
70
  };
71
71
 
72
+ // src/client/appKitStatus.ts
73
+ var fetchVoiceAppKitStatus = async (path = "/app-kit/status", options = {}) => {
74
+ const fetchImpl = options.fetch ?? globalThis.fetch;
75
+ const response = await fetchImpl(path);
76
+ if (!response.ok) {
77
+ throw new Error(`Voice app kit status failed: HTTP ${response.status}`);
78
+ }
79
+ return await response.json();
80
+ };
81
+ var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
82
+ const listeners = new Set;
83
+ let closed = false;
84
+ let timer;
85
+ let snapshot = {
86
+ error: null,
87
+ isLoading: false
88
+ };
89
+ const emit = () => {
90
+ for (const listener of listeners) {
91
+ listener();
92
+ }
93
+ };
94
+ const refresh = async () => {
95
+ if (closed) {
96
+ return snapshot.report;
97
+ }
98
+ snapshot = {
99
+ ...snapshot,
100
+ error: null,
101
+ isLoading: true
102
+ };
103
+ emit();
104
+ try {
105
+ const report = await fetchVoiceAppKitStatus(path, options);
106
+ snapshot = {
107
+ error: null,
108
+ isLoading: false,
109
+ report,
110
+ updatedAt: Date.now()
111
+ };
112
+ emit();
113
+ return report;
114
+ } catch (error) {
115
+ snapshot = {
116
+ ...snapshot,
117
+ error: error instanceof Error ? error.message : String(error),
118
+ isLoading: false
119
+ };
120
+ emit();
121
+ throw error;
122
+ }
123
+ };
124
+ const close = () => {
125
+ closed = true;
126
+ if (timer) {
127
+ clearInterval(timer);
128
+ timer = undefined;
129
+ }
130
+ listeners.clear();
131
+ };
132
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
133
+ timer = setInterval(() => {
134
+ refresh().catch(() => {});
135
+ }, options.intervalMs);
136
+ }
137
+ return {
138
+ close,
139
+ getServerSnapshot: () => snapshot,
140
+ getSnapshot: () => snapshot,
141
+ refresh,
142
+ subscribe: (listener) => {
143
+ listeners.add(listener);
144
+ return () => {
145
+ listeners.delete(listener);
146
+ };
147
+ }
148
+ };
149
+ };
150
+
151
+ // src/svelte/createVoiceAppKitStatus.ts
152
+ var createVoiceAppKitStatus = (path = "/app-kit/status", options = {}) => createVoiceAppKitStatusStore(path, options);
72
153
  // src/client/actions.ts
73
154
  var normalizeErrorMessage = (value) => {
74
155
  if (typeof value === "string" && value.trim()) {
@@ -1380,5 +1461,6 @@ export {
1380
1461
  createVoiceWorkflowStatus,
1381
1462
  createVoiceStream2 as createVoiceStream,
1382
1463
  createVoiceProviderStatus,
1383
- createVoiceController
1464
+ createVoiceController,
1465
+ createVoiceAppKitStatus
1384
1466
  };
@@ -1,3 +1,4 @@
1
+ export { useVoiceAppKitStatus } from './useVoiceAppKitStatus';
1
2
  export { useVoiceStream } from './useVoiceStream';
2
3
  export { useVoiceController } from './useVoiceController';
3
4
  export { useVoiceProviderStatus } from './useVoiceProviderStatus';