@absolutejs/voice 0.0.22-beta.5 → 0.0.22-beta.51
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/angular/index.d.ts +3 -0
- package/dist/angular/index.js +463 -43
- package/dist/angular/voice-app-kit-status.service.d.ts +12 -0
- package/dist/angular/voice-provider-status.service.d.ts +12 -0
- package/dist/angular/voice-stream.service.d.ts +2 -0
- package/dist/angular/voice-workflow-status.service.d.ts +12 -0
- package/dist/appKit.d.ts +92 -0
- package/dist/assistantHealth.d.ts +81 -0
- package/dist/client/actions.d.ts +22 -0
- package/dist/client/appKitStatus.d.ts +19 -0
- package/dist/client/connection.d.ts +3 -0
- package/dist/client/htmxBootstrap.js +44 -2
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +285 -2
- package/dist/client/providerStatus.d.ts +19 -0
- package/dist/client/workflowStatus.d.ts +19 -0
- package/dist/diagnosticsRoutes.d.ts +44 -0
- package/dist/evalRoutes.d.ts +213 -0
- package/dist/handoff.d.ts +54 -0
- package/dist/handoffHealth.d.ts +94 -0
- package/dist/index.d.ts +32 -4
- package/dist/index.js +4425 -166
- package/dist/modelAdapters.d.ts +81 -0
- package/dist/opsConsoleRoutes.d.ts +77 -0
- package/dist/opsWebhook.d.ts +126 -0
- package/dist/providerAdapters.d.ts +37 -0
- package/dist/providerHealth.d.ts +79 -0
- package/dist/qualityRoutes.d.ts +76 -0
- package/dist/queue.d.ts +52 -0
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.js +355 -11
- package/dist/react/useVoiceAppKitStatus.d.ts +8 -0
- package/dist/react/useVoiceController.d.ts +2 -0
- package/dist/react/useVoiceProviderStatus.d.ts +8 -0
- package/dist/react/useVoiceStream.d.ts +2 -0
- package/dist/react/useVoiceWorkflowStatus.d.ts +8 -0
- package/dist/resilienceRoutes.d.ts +106 -0
- package/dist/sessionReplay.d.ts +175 -0
- package/dist/svelte/createVoiceAppKitStatus.d.ts +8 -0
- package/dist/svelte/createVoiceProviderStatus.d.ts +8 -0
- package/dist/svelte/createVoiceWorkflowStatus.d.ts +8 -0
- package/dist/svelte/index.d.ts +3 -0
- package/dist/svelte/index.js +292 -3
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +1468 -7
- package/dist/testing/ioProviderSimulator.d.ts +41 -0
- package/dist/testing/providerSimulator.d.ts +44 -0
- package/dist/trace.d.ts +1 -1
- package/dist/types.d.ts +84 -2
- package/dist/vue/index.d.ts +3 -0
- package/dist/vue/index.js +412 -25
- package/dist/vue/useVoiceAppKitStatus.d.ts +9 -0
- package/dist/vue/useVoiceProviderStatus.d.ts +9 -0
- package/dist/vue/useVoiceStream.d.ts +2 -0
- package/dist/vue/useVoiceWorkflowStatus.d.ts +9 -0
- package/dist/workflowContract.d.ts +91 -0
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -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/
|
|
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()) {
|
|
@@ -120,6 +218,12 @@ var serverMessageToAction = (message) => {
|
|
|
120
218
|
sessionId: message.sessionId,
|
|
121
219
|
type: "complete"
|
|
122
220
|
};
|
|
221
|
+
case "call_lifecycle":
|
|
222
|
+
return {
|
|
223
|
+
event: message.event,
|
|
224
|
+
sessionId: message.sessionId,
|
|
225
|
+
type: "call_lifecycle"
|
|
226
|
+
};
|
|
123
227
|
case "error":
|
|
124
228
|
return {
|
|
125
229
|
message: normalizeErrorMessage(message.message),
|
|
@@ -163,7 +267,7 @@ var DEFAULT_SCENARIO_QUERY_PARAM = "scenarioId";
|
|
|
163
267
|
var noop = () => {};
|
|
164
268
|
var noopUnsubscribe = () => noop;
|
|
165
269
|
var NOOP_CONNECTION = {
|
|
166
|
-
|
|
270
|
+
callControl: noop,
|
|
167
271
|
close: noop,
|
|
168
272
|
endTurn: noop,
|
|
169
273
|
getReadyState: () => WS_CLOSED,
|
|
@@ -171,6 +275,7 @@ var NOOP_CONNECTION = {
|
|
|
171
275
|
getSessionId: () => "",
|
|
172
276
|
send: noop,
|
|
173
277
|
sendAudio: noop,
|
|
278
|
+
start: () => {},
|
|
174
279
|
subscribe: noopUnsubscribe
|
|
175
280
|
};
|
|
176
281
|
var createSessionId = () => crypto.randomUUID();
|
|
@@ -192,6 +297,7 @@ var isVoiceServerMessage = (value) => {
|
|
|
192
297
|
switch (value.type) {
|
|
193
298
|
case "audio":
|
|
194
299
|
case "assistant":
|
|
300
|
+
case "call_lifecycle":
|
|
195
301
|
case "complete":
|
|
196
302
|
case "error":
|
|
197
303
|
case "final":
|
|
@@ -332,6 +438,12 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
332
438
|
const endTurn = () => {
|
|
333
439
|
send({ type: "end_turn" });
|
|
334
440
|
};
|
|
441
|
+
const callControl = (message) => {
|
|
442
|
+
send({
|
|
443
|
+
...message,
|
|
444
|
+
type: "call_control"
|
|
445
|
+
});
|
|
446
|
+
};
|
|
335
447
|
const close = () => {
|
|
336
448
|
clearTimers();
|
|
337
449
|
if (state.ws) {
|
|
@@ -349,7 +461,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
349
461
|
};
|
|
350
462
|
connect();
|
|
351
463
|
return {
|
|
352
|
-
|
|
464
|
+
callControl,
|
|
353
465
|
close,
|
|
354
466
|
endTurn,
|
|
355
467
|
getReadyState: () => state.ws?.readyState ?? WS_CLOSED,
|
|
@@ -357,6 +469,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
357
469
|
getSessionId: () => state.sessionId,
|
|
358
470
|
send,
|
|
359
471
|
sendAudio,
|
|
472
|
+
start,
|
|
360
473
|
subscribe
|
|
361
474
|
};
|
|
362
475
|
};
|
|
@@ -365,6 +478,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
365
478
|
var createInitialState = () => ({
|
|
366
479
|
assistantAudio: [],
|
|
367
480
|
assistantTexts: [],
|
|
481
|
+
call: null,
|
|
368
482
|
error: null,
|
|
369
483
|
isConnected: false,
|
|
370
484
|
scenarioId: null,
|
|
@@ -408,6 +522,20 @@ var createVoiceStreamStore = () => {
|
|
|
408
522
|
status: "completed"
|
|
409
523
|
};
|
|
410
524
|
break;
|
|
525
|
+
case "call_lifecycle":
|
|
526
|
+
state = {
|
|
527
|
+
...state,
|
|
528
|
+
call: {
|
|
529
|
+
...state.call,
|
|
530
|
+
disposition: action.event.type === "end" ? action.event.disposition : state.call?.disposition,
|
|
531
|
+
endedAt: action.event.type === "end" ? action.event.at : state.call?.endedAt,
|
|
532
|
+
events: [...state.call?.events ?? [], action.event],
|
|
533
|
+
lastEventAt: action.event.at,
|
|
534
|
+
startedAt: state.call?.startedAt ?? action.event.at
|
|
535
|
+
},
|
|
536
|
+
sessionId: action.sessionId
|
|
537
|
+
};
|
|
538
|
+
break;
|
|
411
539
|
case "connected":
|
|
412
540
|
state = {
|
|
413
541
|
...state,
|
|
@@ -494,6 +622,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
494
622
|
}
|
|
495
623
|
});
|
|
496
624
|
return {
|
|
625
|
+
callControl(message) {
|
|
626
|
+
connection.callControl(message);
|
|
627
|
+
},
|
|
497
628
|
close() {
|
|
498
629
|
unsubscribeConnection();
|
|
499
630
|
connection.close();
|
|
@@ -537,6 +668,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
537
668
|
get assistantAudio() {
|
|
538
669
|
return store.getSnapshot().assistantAudio;
|
|
539
670
|
},
|
|
671
|
+
get call() {
|
|
672
|
+
return store.getSnapshot().call;
|
|
673
|
+
},
|
|
540
674
|
sendAudio(audio) {
|
|
541
675
|
connection.sendAudio(audio);
|
|
542
676
|
},
|
|
@@ -553,6 +687,7 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
553
687
|
var EMPTY_SNAPSHOT = {
|
|
554
688
|
assistantAudio: [],
|
|
555
689
|
assistantTexts: [],
|
|
690
|
+
call: null,
|
|
556
691
|
error: null,
|
|
557
692
|
isConnected: false,
|
|
558
693
|
partial: "",
|
|
@@ -561,22 +696,23 @@ var EMPTY_SNAPSHOT = {
|
|
|
561
696
|
turns: []
|
|
562
697
|
};
|
|
563
698
|
var useVoiceStream = (path, options = {}) => {
|
|
564
|
-
const streamRef =
|
|
699
|
+
const streamRef = useRef2(null);
|
|
565
700
|
if (!streamRef.current) {
|
|
566
701
|
streamRef.current = createVoiceStream(path, options);
|
|
567
702
|
}
|
|
568
703
|
const stream = streamRef.current;
|
|
569
|
-
|
|
570
|
-
const snapshot =
|
|
704
|
+
useEffect2(() => () => stream.close(), [stream]);
|
|
705
|
+
const snapshot = useSyncExternalStore2(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
|
|
571
706
|
return {
|
|
572
707
|
...snapshot,
|
|
708
|
+
callControl: (message) => stream.callControl(message),
|
|
573
709
|
close: () => stream.close(),
|
|
574
710
|
endTurn: () => stream.endTurn(),
|
|
575
711
|
sendAudio: (audio) => stream.sendAudio(audio)
|
|
576
712
|
};
|
|
577
713
|
};
|
|
578
714
|
// src/react/useVoiceController.tsx
|
|
579
|
-
import { useEffect as
|
|
715
|
+
import { useEffect as useEffect3, useRef as useRef3, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
580
716
|
|
|
581
717
|
// src/client/htmx.ts
|
|
582
718
|
var DEFAULT_EVENT_NAME = "voice-refresh";
|
|
@@ -1040,6 +1176,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
1040
1176
|
var createInitialState2 = (stream) => ({
|
|
1041
1177
|
assistantAudio: [...stream.assistantAudio],
|
|
1042
1178
|
assistantTexts: [...stream.assistantTexts],
|
|
1179
|
+
call: stream.call,
|
|
1043
1180
|
error: stream.error,
|
|
1044
1181
|
isConnected: stream.isConnected,
|
|
1045
1182
|
isRecording: false,
|
|
@@ -1069,6 +1206,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1069
1206
|
...state,
|
|
1070
1207
|
assistantAudio: [...stream.assistantAudio],
|
|
1071
1208
|
assistantTexts: [...stream.assistantTexts],
|
|
1209
|
+
call: stream.call,
|
|
1072
1210
|
error: stream.error,
|
|
1073
1211
|
isConnected: stream.isConnected,
|
|
1074
1212
|
partial: stream.partial,
|
|
@@ -1146,6 +1284,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1146
1284
|
bindHTMX(bindingOptions) {
|
|
1147
1285
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
1148
1286
|
},
|
|
1287
|
+
callControl: (message) => stream.callControl(message),
|
|
1149
1288
|
close,
|
|
1150
1289
|
endTurn: () => stream.endTurn(),
|
|
1151
1290
|
get error() {
|
|
@@ -1198,6 +1337,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1198
1337
|
},
|
|
1199
1338
|
get assistantAudio() {
|
|
1200
1339
|
return state.assistantAudio;
|
|
1340
|
+
},
|
|
1341
|
+
get call() {
|
|
1342
|
+
return state.call;
|
|
1201
1343
|
}
|
|
1202
1344
|
};
|
|
1203
1345
|
};
|
|
@@ -1206,6 +1348,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1206
1348
|
var EMPTY_SNAPSHOT2 = {
|
|
1207
1349
|
assistantAudio: [],
|
|
1208
1350
|
assistantTexts: [],
|
|
1351
|
+
call: null,
|
|
1209
1352
|
error: null,
|
|
1210
1353
|
isConnected: false,
|
|
1211
1354
|
isRecording: false,
|
|
@@ -1216,16 +1359,17 @@ var EMPTY_SNAPSHOT2 = {
|
|
|
1216
1359
|
turns: []
|
|
1217
1360
|
};
|
|
1218
1361
|
var useVoiceController = (path, options = {}) => {
|
|
1219
|
-
const controllerRef =
|
|
1362
|
+
const controllerRef = useRef3(null);
|
|
1220
1363
|
if (!controllerRef.current) {
|
|
1221
1364
|
controllerRef.current = createVoiceController(path, options);
|
|
1222
1365
|
}
|
|
1223
1366
|
const controller = controllerRef.current;
|
|
1224
|
-
|
|
1225
|
-
const snapshot =
|
|
1367
|
+
useEffect3(() => () => controller.close(), [controller]);
|
|
1368
|
+
const snapshot = useSyncExternalStore3(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
|
|
1226
1369
|
return {
|
|
1227
1370
|
...snapshot,
|
|
1228
1371
|
bindHTMX: controller.bindHTMX,
|
|
1372
|
+
callControl: (message) => controller.callControl(message),
|
|
1229
1373
|
close: () => controller.close(),
|
|
1230
1374
|
endTurn: () => controller.endTurn(),
|
|
1231
1375
|
sendAudio: (audio) => controller.sendAudio(audio),
|
|
@@ -1234,7 +1378,207 @@ var useVoiceController = (path, options = {}) => {
|
|
|
1234
1378
|
toggleRecording: () => controller.toggleRecording()
|
|
1235
1379
|
};
|
|
1236
1380
|
};
|
|
1381
|
+
// src/react/useVoiceProviderStatus.tsx
|
|
1382
|
+
import { useEffect as useEffect4, useRef as useRef4, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
1383
|
+
|
|
1384
|
+
// src/client/providerStatus.ts
|
|
1385
|
+
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
1386
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1387
|
+
const response = await fetchImpl(path);
|
|
1388
|
+
if (!response.ok) {
|
|
1389
|
+
throw new Error(`Voice provider status failed: HTTP ${response.status}`);
|
|
1390
|
+
}
|
|
1391
|
+
return await response.json();
|
|
1392
|
+
};
|
|
1393
|
+
var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {}) => {
|
|
1394
|
+
const listeners = new Set;
|
|
1395
|
+
let closed = false;
|
|
1396
|
+
let timer;
|
|
1397
|
+
let snapshot = {
|
|
1398
|
+
error: null,
|
|
1399
|
+
isLoading: false,
|
|
1400
|
+
providers: []
|
|
1401
|
+
};
|
|
1402
|
+
const emit = () => {
|
|
1403
|
+
for (const listener of listeners) {
|
|
1404
|
+
listener();
|
|
1405
|
+
}
|
|
1406
|
+
};
|
|
1407
|
+
const refresh = async () => {
|
|
1408
|
+
if (closed) {
|
|
1409
|
+
return snapshot.providers;
|
|
1410
|
+
}
|
|
1411
|
+
snapshot = {
|
|
1412
|
+
...snapshot,
|
|
1413
|
+
error: null,
|
|
1414
|
+
isLoading: true
|
|
1415
|
+
};
|
|
1416
|
+
emit();
|
|
1417
|
+
try {
|
|
1418
|
+
const providers = await fetchVoiceProviderStatus(path, options);
|
|
1419
|
+
snapshot = {
|
|
1420
|
+
error: null,
|
|
1421
|
+
isLoading: false,
|
|
1422
|
+
providers,
|
|
1423
|
+
updatedAt: Date.now()
|
|
1424
|
+
};
|
|
1425
|
+
emit();
|
|
1426
|
+
return providers;
|
|
1427
|
+
} catch (error) {
|
|
1428
|
+
snapshot = {
|
|
1429
|
+
...snapshot,
|
|
1430
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1431
|
+
isLoading: false
|
|
1432
|
+
};
|
|
1433
|
+
emit();
|
|
1434
|
+
throw error;
|
|
1435
|
+
}
|
|
1436
|
+
};
|
|
1437
|
+
const close = () => {
|
|
1438
|
+
closed = true;
|
|
1439
|
+
if (timer) {
|
|
1440
|
+
clearInterval(timer);
|
|
1441
|
+
timer = undefined;
|
|
1442
|
+
}
|
|
1443
|
+
listeners.clear();
|
|
1444
|
+
};
|
|
1445
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
1446
|
+
timer = setInterval(() => {
|
|
1447
|
+
refresh().catch(() => {});
|
|
1448
|
+
}, options.intervalMs);
|
|
1449
|
+
}
|
|
1450
|
+
return {
|
|
1451
|
+
close,
|
|
1452
|
+
getServerSnapshot: () => snapshot,
|
|
1453
|
+
getSnapshot: () => snapshot,
|
|
1454
|
+
refresh,
|
|
1455
|
+
subscribe: (listener) => {
|
|
1456
|
+
listeners.add(listener);
|
|
1457
|
+
return () => {
|
|
1458
|
+
listeners.delete(listener);
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
};
|
|
1462
|
+
};
|
|
1463
|
+
|
|
1464
|
+
// src/react/useVoiceProviderStatus.tsx
|
|
1465
|
+
var useVoiceProviderStatus = (path = "/api/provider-status", options = {}) => {
|
|
1466
|
+
const storeRef = useRef4(null);
|
|
1467
|
+
if (!storeRef.current) {
|
|
1468
|
+
storeRef.current = createVoiceProviderStatusStore(path, options);
|
|
1469
|
+
}
|
|
1470
|
+
const store = storeRef.current;
|
|
1471
|
+
useEffect4(() => {
|
|
1472
|
+
store.refresh().catch(() => {});
|
|
1473
|
+
return () => store.close();
|
|
1474
|
+
}, [store]);
|
|
1475
|
+
return {
|
|
1476
|
+
...useSyncExternalStore4(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1477
|
+
refresh: store.refresh
|
|
1478
|
+
};
|
|
1479
|
+
};
|
|
1480
|
+
// src/react/useVoiceWorkflowStatus.tsx
|
|
1481
|
+
import { useEffect as useEffect5, useRef as useRef5, useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
1482
|
+
|
|
1483
|
+
// src/client/workflowStatus.ts
|
|
1484
|
+
var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
|
|
1485
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1486
|
+
const response = await fetchImpl(path);
|
|
1487
|
+
if (!response.ok) {
|
|
1488
|
+
throw new Error(`Voice workflow status failed: HTTP ${response.status}`);
|
|
1489
|
+
}
|
|
1490
|
+
return await response.json();
|
|
1491
|
+
};
|
|
1492
|
+
var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options = {}) => {
|
|
1493
|
+
const listeners = new Set;
|
|
1494
|
+
let closed = false;
|
|
1495
|
+
let timer;
|
|
1496
|
+
let snapshot = {
|
|
1497
|
+
error: null,
|
|
1498
|
+
isLoading: false
|
|
1499
|
+
};
|
|
1500
|
+
const emit = () => {
|
|
1501
|
+
for (const listener of listeners) {
|
|
1502
|
+
listener();
|
|
1503
|
+
}
|
|
1504
|
+
};
|
|
1505
|
+
const refresh = async () => {
|
|
1506
|
+
if (closed) {
|
|
1507
|
+
return snapshot.report;
|
|
1508
|
+
}
|
|
1509
|
+
snapshot = {
|
|
1510
|
+
...snapshot,
|
|
1511
|
+
error: null,
|
|
1512
|
+
isLoading: true
|
|
1513
|
+
};
|
|
1514
|
+
emit();
|
|
1515
|
+
try {
|
|
1516
|
+
const report = await fetchVoiceWorkflowStatus(path, options);
|
|
1517
|
+
snapshot = {
|
|
1518
|
+
error: null,
|
|
1519
|
+
isLoading: false,
|
|
1520
|
+
report,
|
|
1521
|
+
updatedAt: Date.now()
|
|
1522
|
+
};
|
|
1523
|
+
emit();
|
|
1524
|
+
return report;
|
|
1525
|
+
} catch (error) {
|
|
1526
|
+
snapshot = {
|
|
1527
|
+
...snapshot,
|
|
1528
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1529
|
+
isLoading: false
|
|
1530
|
+
};
|
|
1531
|
+
emit();
|
|
1532
|
+
throw error;
|
|
1533
|
+
}
|
|
1534
|
+
};
|
|
1535
|
+
const close = () => {
|
|
1536
|
+
closed = true;
|
|
1537
|
+
if (timer) {
|
|
1538
|
+
clearInterval(timer);
|
|
1539
|
+
timer = undefined;
|
|
1540
|
+
}
|
|
1541
|
+
listeners.clear();
|
|
1542
|
+
};
|
|
1543
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
1544
|
+
timer = setInterval(() => {
|
|
1545
|
+
refresh().catch(() => {});
|
|
1546
|
+
}, options.intervalMs);
|
|
1547
|
+
}
|
|
1548
|
+
return {
|
|
1549
|
+
close,
|
|
1550
|
+
getServerSnapshot: () => snapshot,
|
|
1551
|
+
getSnapshot: () => snapshot,
|
|
1552
|
+
refresh,
|
|
1553
|
+
subscribe: (listener) => {
|
|
1554
|
+
listeners.add(listener);
|
|
1555
|
+
return () => {
|
|
1556
|
+
listeners.delete(listener);
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
};
|
|
1560
|
+
};
|
|
1561
|
+
|
|
1562
|
+
// src/react/useVoiceWorkflowStatus.tsx
|
|
1563
|
+
var useVoiceWorkflowStatus = (path = "/evals/scenarios/json", options = {}) => {
|
|
1564
|
+
const storeRef = useRef5(null);
|
|
1565
|
+
if (!storeRef.current) {
|
|
1566
|
+
storeRef.current = createVoiceWorkflowStatusStore(path, options);
|
|
1567
|
+
}
|
|
1568
|
+
const store = storeRef.current;
|
|
1569
|
+
useEffect5(() => {
|
|
1570
|
+
store.refresh().catch(() => {});
|
|
1571
|
+
return () => store.close();
|
|
1572
|
+
}, [store]);
|
|
1573
|
+
return {
|
|
1574
|
+
...useSyncExternalStore5(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1575
|
+
refresh: store.refresh
|
|
1576
|
+
};
|
|
1577
|
+
};
|
|
1237
1578
|
export {
|
|
1579
|
+
useVoiceWorkflowStatus,
|
|
1238
1580
|
useVoiceStream,
|
|
1239
|
-
|
|
1581
|
+
useVoiceProviderStatus,
|
|
1582
|
+
useVoiceController,
|
|
1583
|
+
useVoiceAppKitStatus
|
|
1240
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
|
+
};
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { VoiceControllerOptions } from '../types';
|
|
2
2
|
export declare const useVoiceController: <TResult = unknown>(path: string, options?: VoiceControllerOptions) => {
|
|
3
3
|
bindHTMX: (options: import("..").VoiceHTMXBindingOptions) => () => void;
|
|
4
|
+
callControl: (message: Parameters<(message: Omit<import("..").VoiceClientCallControlMessage, "type">) => void>[0]) => void;
|
|
4
5
|
close: () => void;
|
|
5
6
|
endTurn: () => void;
|
|
6
7
|
sendAudio: (audio: Uint8Array | ArrayBuffer) => void;
|
|
7
8
|
startRecording: () => Promise<void>;
|
|
8
9
|
stopRecording: () => void;
|
|
9
10
|
toggleRecording: () => Promise<void>;
|
|
11
|
+
call: import("..").VoiceCallLifecycleState | null;
|
|
10
12
|
sessionId: string | null;
|
|
11
13
|
scenarioId: string | null;
|
|
12
14
|
status: import("..").VoiceSessionStatus | "idle";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type VoiceProviderStatusClientOptions } from '../client/providerStatus';
|
|
2
|
+
export declare const useVoiceProviderStatus: <TProvider extends string = string>(path?: string, options?: VoiceProviderStatusClientOptions) => {
|
|
3
|
+
refresh: () => Promise<import("..").VoiceProviderHealthSummary<TProvider>[]>;
|
|
4
|
+
error: string | null;
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
providers: import("..").VoiceProviderHealthSummary<TProvider>[];
|
|
7
|
+
updatedAt?: number;
|
|
8
|
+
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { VoiceConnectionOptions } from '../types';
|
|
2
2
|
export declare const useVoiceStream: <TResult = unknown>(path: string, options?: VoiceConnectionOptions) => {
|
|
3
|
+
callControl: (message: Parameters<(message: Omit<import("..").VoiceClientCallControlMessage, "type">) => void>[0]) => void;
|
|
3
4
|
close: () => void;
|
|
4
5
|
endTurn: () => void;
|
|
5
6
|
sendAudio: (audio: Uint8Array | ArrayBuffer) => void;
|
|
7
|
+
call: import("..").VoiceCallLifecycleState | null;
|
|
6
8
|
sessionId: string | null;
|
|
7
9
|
scenarioId: string | null;
|
|
8
10
|
status: import("..").VoiceSessionStatus | "idle";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type VoiceWorkflowStatusClientOptions } from '../client/workflowStatus';
|
|
2
|
+
export declare const useVoiceWorkflowStatus: (path?: string, options?: VoiceWorkflowStatusClientOptions) => {
|
|
3
|
+
refresh: () => Promise<import("..").VoiceScenarioEvalReport | undefined>;
|
|
4
|
+
error: string | null;
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
report?: import("..").VoiceScenarioEvalReport;
|
|
7
|
+
updatedAt?: number;
|
|
8
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Elysia } from 'elysia';
|
|
2
|
+
import { type VoiceProviderHealthSummary } from './providerHealth';
|
|
3
|
+
import type { StoredVoiceTraceEvent, VoiceTraceEventStore } from './trace';
|
|
4
|
+
import type { VoiceIOProviderFailureSimulationMode, VoiceIOProviderFailureSimulationResult } from './testing/ioProviderSimulator';
|
|
5
|
+
export type VoiceRoutingEventKind = 'llm' | 'stt' | 'tts';
|
|
6
|
+
export type VoiceRoutingEvent = {
|
|
7
|
+
at: number;
|
|
8
|
+
attempt?: number;
|
|
9
|
+
elapsedMs?: number;
|
|
10
|
+
error?: string;
|
|
11
|
+
fallbackProvider?: string;
|
|
12
|
+
kind: VoiceRoutingEventKind;
|
|
13
|
+
latencyBudgetMs?: number;
|
|
14
|
+
operation?: string;
|
|
15
|
+
provider?: string;
|
|
16
|
+
selectedProvider?: string;
|
|
17
|
+
sessionId: string;
|
|
18
|
+
status?: string;
|
|
19
|
+
timedOut: boolean;
|
|
20
|
+
turnId?: string;
|
|
21
|
+
};
|
|
22
|
+
export type VoiceResilienceLink = {
|
|
23
|
+
href: string;
|
|
24
|
+
label: string;
|
|
25
|
+
};
|
|
26
|
+
export type VoiceResilienceSimulationProvider<TProvider extends string = string> = {
|
|
27
|
+
configured?: boolean;
|
|
28
|
+
provider: TProvider;
|
|
29
|
+
};
|
|
30
|
+
export type VoiceResilienceIOSimulator<TProvider extends string = string> = {
|
|
31
|
+
failureProviders?: readonly TProvider[];
|
|
32
|
+
fallbackRequiredProvider?: TProvider;
|
|
33
|
+
fallbackRequiredMessage?: string;
|
|
34
|
+
failureMessage?: string;
|
|
35
|
+
label?: string;
|
|
36
|
+
pathPrefix?: string;
|
|
37
|
+
providers: readonly VoiceResilienceSimulationProvider<TProvider>[];
|
|
38
|
+
recoveryMessage?: string;
|
|
39
|
+
run: (provider: TProvider, mode: VoiceIOProviderFailureSimulationMode) => Promise<VoiceIOProviderFailureSimulationResult<TProvider>>;
|
|
40
|
+
};
|
|
41
|
+
export type VoiceResiliencePageData = {
|
|
42
|
+
links?: readonly VoiceResilienceLink[];
|
|
43
|
+
llmProviderHealth: VoiceProviderHealthSummary<string>[];
|
|
44
|
+
routingEvents: VoiceRoutingEvent[];
|
|
45
|
+
sttProviderHealth: VoiceProviderHealthSummary<string>[];
|
|
46
|
+
sttSimulation?: VoiceResilienceIOSimulator<string>;
|
|
47
|
+
title?: string;
|
|
48
|
+
ttsProviderHealth: VoiceProviderHealthSummary<string>[];
|
|
49
|
+
ttsSimulation?: VoiceResilienceIOSimulator<string>;
|
|
50
|
+
};
|
|
51
|
+
export type VoiceResilienceRoutesOptions = {
|
|
52
|
+
headers?: HeadersInit;
|
|
53
|
+
links?: readonly VoiceResilienceLink[];
|
|
54
|
+
llmProviders?: readonly string[];
|
|
55
|
+
name?: string;
|
|
56
|
+
path?: string;
|
|
57
|
+
render?: (input: VoiceResiliencePageData) => string | Promise<string>;
|
|
58
|
+
sttProviders?: readonly string[];
|
|
59
|
+
sttSimulation?: VoiceResilienceIOSimulator<string>;
|
|
60
|
+
store: VoiceTraceEventStore;
|
|
61
|
+
title?: string;
|
|
62
|
+
ttsProviders?: readonly string[];
|
|
63
|
+
ttsSimulation?: VoiceResilienceIOSimulator<string>;
|
|
64
|
+
};
|
|
65
|
+
export declare const listVoiceRoutingEvents: (events: StoredVoiceTraceEvent[]) => VoiceRoutingEvent[];
|
|
66
|
+
export declare const renderVoiceResilienceHTML: (input: VoiceResiliencePageData) => string;
|
|
67
|
+
export declare const createVoiceResilienceRoutes: (options: VoiceResilienceRoutesOptions) => Elysia<"", {
|
|
68
|
+
decorator: {};
|
|
69
|
+
store: {};
|
|
70
|
+
derive: {};
|
|
71
|
+
resolve: {};
|
|
72
|
+
}, {
|
|
73
|
+
typebox: {};
|
|
74
|
+
error: {};
|
|
75
|
+
}, {
|
|
76
|
+
schema: {};
|
|
77
|
+
standaloneSchema: {};
|
|
78
|
+
macro: {};
|
|
79
|
+
macroFn: {};
|
|
80
|
+
parser: {};
|
|
81
|
+
response: {};
|
|
82
|
+
}, {
|
|
83
|
+
[x: string]: {
|
|
84
|
+
get: {
|
|
85
|
+
body: unknown;
|
|
86
|
+
params: {};
|
|
87
|
+
query: unknown;
|
|
88
|
+
headers: unknown;
|
|
89
|
+
response: {
|
|
90
|
+
200: Response;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
}, {
|
|
95
|
+
derive: {};
|
|
96
|
+
resolve: {};
|
|
97
|
+
schema: {};
|
|
98
|
+
standaloneSchema: {};
|
|
99
|
+
response: {};
|
|
100
|
+
}, {
|
|
101
|
+
derive: {};
|
|
102
|
+
resolve: {};
|
|
103
|
+
schema: {};
|
|
104
|
+
standaloneSchema: {};
|
|
105
|
+
response: {};
|
|
106
|
+
}>;
|