@absolutejs/voice 0.0.22-beta.564 → 0.0.22-beta.566
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.js +30 -0
- package/dist/angular/voice-controller.service.d.ts +1 -0
- package/dist/angular/voice-stream.service.d.ts +1 -0
- package/dist/client/actions.d.ts +33 -1
- package/dist/client/htmxBootstrap.js +24 -0
- package/dist/client/index.js +24 -0
- package/dist/core/types.d.ts +26 -1
- package/dist/embed/index.js +24 -0
- package/dist/embed/voice-widget.js +7 -7
- package/dist/index.js +9 -0
- package/dist/react/index.js +24 -0
- package/dist/react/useVoiceController.d.ts +1 -0
- package/dist/react/useVoiceStream.d.ts +1 -0
- package/dist/svelte/index.js +24 -0
- package/dist/testing/index.js +25 -0
- package/dist/vue/index.js +30 -0
- package/dist/vue/useVoiceController.d.ts +1 -0
- package/dist/vue/useVoiceStream.d.ts +1 -0
- package/package.json +1 -1
package/dist/angular/index.js
CHANGED
|
@@ -416,8 +416,15 @@ var serverMessageToAction = (message) => {
|
|
|
416
416
|
case "assistant":
|
|
417
417
|
return {
|
|
418
418
|
text: message.text,
|
|
419
|
+
turnId: message.turnId,
|
|
419
420
|
type: "assistant"
|
|
420
421
|
};
|
|
422
|
+
case "assistant_delta":
|
|
423
|
+
return {
|
|
424
|
+
delta: message.delta,
|
|
425
|
+
turnId: message.turnId,
|
|
426
|
+
type: "assistant_delta"
|
|
427
|
+
};
|
|
421
428
|
case "complete":
|
|
422
429
|
return {
|
|
423
430
|
sessionId: message.sessionId,
|
|
@@ -836,6 +843,7 @@ var createInitialReconnectState = () => ({
|
|
|
836
843
|
});
|
|
837
844
|
var createInitialState = () => ({
|
|
838
845
|
assistantAudio: [],
|
|
846
|
+
assistantStreamingText: "",
|
|
839
847
|
assistantTexts: [],
|
|
840
848
|
call: null,
|
|
841
849
|
error: null,
|
|
@@ -873,9 +881,16 @@ var createVoiceStreamStore = () => {
|
|
|
873
881
|
case "assistant":
|
|
874
882
|
state = {
|
|
875
883
|
...state,
|
|
884
|
+
assistantStreamingText: "",
|
|
876
885
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
877
886
|
};
|
|
878
887
|
break;
|
|
888
|
+
case "assistant_delta":
|
|
889
|
+
state = {
|
|
890
|
+
...state,
|
|
891
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
892
|
+
};
|
|
893
|
+
break;
|
|
879
894
|
case "complete":
|
|
880
895
|
state = {
|
|
881
896
|
...state,
|
|
@@ -943,6 +958,7 @@ var createVoiceStreamStore = () => {
|
|
|
943
958
|
case "replay":
|
|
944
959
|
state = {
|
|
945
960
|
...state,
|
|
961
|
+
assistantStreamingText: "",
|
|
946
962
|
assistantTexts: [...action.assistantTexts],
|
|
947
963
|
call: action.call ?? null,
|
|
948
964
|
error: null,
|
|
@@ -1054,6 +1070,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
1054
1070
|
get assistantTexts() {
|
|
1055
1071
|
return store.getSnapshot().assistantTexts;
|
|
1056
1072
|
},
|
|
1073
|
+
get assistantStreamingText() {
|
|
1074
|
+
return store.getSnapshot().assistantStreamingText;
|
|
1075
|
+
},
|
|
1057
1076
|
get call() {
|
|
1058
1077
|
return store.getSnapshot().call;
|
|
1059
1078
|
},
|
|
@@ -1437,6 +1456,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
1437
1456
|
// src/client/controller.ts
|
|
1438
1457
|
var createInitialState2 = (stream) => ({
|
|
1439
1458
|
assistantAudio: [...stream.assistantAudio],
|
|
1459
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1440
1460
|
assistantTexts: [...stream.assistantTexts],
|
|
1441
1461
|
call: stream.call,
|
|
1442
1462
|
error: stream.error,
|
|
@@ -1469,6 +1489,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1469
1489
|
state = {
|
|
1470
1490
|
...state,
|
|
1471
1491
|
assistantAudio: [...stream.assistantAudio],
|
|
1492
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1472
1493
|
assistantTexts: [...stream.assistantTexts],
|
|
1473
1494
|
call: stream.call,
|
|
1474
1495
|
error: stream.error,
|
|
@@ -1562,6 +1583,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1562
1583
|
get assistantTexts() {
|
|
1563
1584
|
return state.assistantTexts;
|
|
1564
1585
|
},
|
|
1586
|
+
get assistantStreamingText() {
|
|
1587
|
+
return state.assistantStreamingText;
|
|
1588
|
+
},
|
|
1565
1589
|
bindHTMX(bindingOptions) {
|
|
1566
1590
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
1567
1591
|
},
|
|
@@ -4201,6 +4225,7 @@ class VoiceStreamService {
|
|
|
4201
4225
|
connect(path, options = {}) {
|
|
4202
4226
|
const stream = createVoiceStream(path, options);
|
|
4203
4227
|
const assistantAudioSignal = signal20([]);
|
|
4228
|
+
const assistantStreamingTextSignal = signal20("");
|
|
4204
4229
|
const assistantTextsSignal = signal20([]);
|
|
4205
4230
|
const callSignal = signal20(null);
|
|
4206
4231
|
const errorSignal = signal20(null);
|
|
@@ -4213,6 +4238,7 @@ class VoiceStreamService {
|
|
|
4213
4238
|
const turnsSignal = signal20([]);
|
|
4214
4239
|
const sync = () => {
|
|
4215
4240
|
assistantAudioSignal.set([...stream.assistantAudio]);
|
|
4241
|
+
assistantStreamingTextSignal.set(stream.assistantStreamingText);
|
|
4216
4242
|
assistantTextsSignal.set([...stream.assistantTexts]);
|
|
4217
4243
|
callSignal.set(stream.call);
|
|
4218
4244
|
errorSignal.set(stream.error);
|
|
@@ -4228,6 +4254,7 @@ class VoiceStreamService {
|
|
|
4228
4254
|
sync();
|
|
4229
4255
|
return {
|
|
4230
4256
|
assistantAudio: computed20(() => assistantAudioSignal()),
|
|
4257
|
+
assistantStreamingText: computed20(() => assistantStreamingTextSignal()),
|
|
4231
4258
|
assistantTexts: computed20(() => assistantTextsSignal()),
|
|
4232
4259
|
call: computed20(() => callSignal()),
|
|
4233
4260
|
callControl: (message) => stream.callControl(message),
|
|
@@ -4264,6 +4291,7 @@ class VoiceControllerService {
|
|
|
4264
4291
|
connect(path, options = {}) {
|
|
4265
4292
|
const controller = createVoiceController(path, options);
|
|
4266
4293
|
const assistantAudioSignal = signal21([]);
|
|
4294
|
+
const assistantStreamingTextSignal = signal21("");
|
|
4267
4295
|
const assistantTextsSignal = signal21([]);
|
|
4268
4296
|
const errorSignal = signal21(null);
|
|
4269
4297
|
const isConnectedSignal = signal21(false);
|
|
@@ -4276,6 +4304,7 @@ class VoiceControllerService {
|
|
|
4276
4304
|
const turnsSignal = signal21([]);
|
|
4277
4305
|
const sync = () => {
|
|
4278
4306
|
assistantAudioSignal.set([...controller.assistantAudio]);
|
|
4307
|
+
assistantStreamingTextSignal.set(controller.assistantStreamingText);
|
|
4279
4308
|
assistantTextsSignal.set([...controller.assistantTexts]);
|
|
4280
4309
|
errorSignal.set(controller.error);
|
|
4281
4310
|
isConnectedSignal.set(controller.isConnected);
|
|
@@ -4291,6 +4320,7 @@ class VoiceControllerService {
|
|
|
4291
4320
|
sync();
|
|
4292
4321
|
return {
|
|
4293
4322
|
assistantAudio: computed21(() => assistantAudioSignal()),
|
|
4323
|
+
assistantStreamingText: computed21(() => assistantStreamingTextSignal()),
|
|
4294
4324
|
assistantTexts: computed21(() => assistantTextsSignal()),
|
|
4295
4325
|
bindHTMX: controller.bindHTMX,
|
|
4296
4326
|
close: () => {
|
|
@@ -7,6 +7,7 @@ export declare class VoiceControllerService {
|
|
|
7
7
|
receivedAt: number;
|
|
8
8
|
turnId?: string;
|
|
9
9
|
}[]>;
|
|
10
|
+
assistantStreamingText: import("@angular/core").Signal<string>;
|
|
10
11
|
assistantTexts: import("@angular/core").Signal<string[]>;
|
|
11
12
|
bindHTMX: (options: import("..").VoiceHTMXBindingOptions) => () => void;
|
|
12
13
|
close: () => void;
|
|
@@ -7,6 +7,7 @@ export declare class VoiceStreamService {
|
|
|
7
7
|
receivedAt: number;
|
|
8
8
|
turnId?: string;
|
|
9
9
|
}[]>;
|
|
10
|
+
assistantStreamingText: import("@angular/core").Signal<string>;
|
|
10
11
|
assistantTexts: import("@angular/core").Signal<string[]>;
|
|
11
12
|
call: import("@angular/core").Signal<import("..").VoiceCallLifecycleState | null>;
|
|
12
13
|
callControl: (message: Parameters<(message: Omit<import("..").VoiceClientCallControlMessage, "type">) => void>[0]) => void;
|
package/dist/client/actions.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
6
6
|
turnId: string | undefined;
|
|
7
7
|
type: "audio";
|
|
8
8
|
text?: undefined;
|
|
9
|
+
delta?: undefined;
|
|
9
10
|
sessionId?: undefined;
|
|
10
11
|
reconnect?: undefined;
|
|
11
12
|
event?: undefined;
|
|
@@ -21,11 +22,33 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
21
22
|
turn?: undefined;
|
|
22
23
|
} | {
|
|
23
24
|
text: string;
|
|
25
|
+
turnId: string | undefined;
|
|
24
26
|
type: "assistant";
|
|
25
27
|
chunk?: undefined;
|
|
26
28
|
format?: undefined;
|
|
27
29
|
receivedAt?: undefined;
|
|
28
|
-
|
|
30
|
+
delta?: undefined;
|
|
31
|
+
sessionId?: undefined;
|
|
32
|
+
reconnect?: undefined;
|
|
33
|
+
event?: undefined;
|
|
34
|
+
message?: undefined;
|
|
35
|
+
transcript?: undefined;
|
|
36
|
+
assistantTexts?: undefined;
|
|
37
|
+
call?: undefined;
|
|
38
|
+
partial?: undefined;
|
|
39
|
+
scenarioId?: undefined;
|
|
40
|
+
sessionMetadata?: undefined;
|
|
41
|
+
status?: undefined;
|
|
42
|
+
turns?: undefined;
|
|
43
|
+
turn?: undefined;
|
|
44
|
+
} | {
|
|
45
|
+
delta: string;
|
|
46
|
+
turnId: string | undefined;
|
|
47
|
+
type: "assistant_delta";
|
|
48
|
+
chunk?: undefined;
|
|
49
|
+
format?: undefined;
|
|
50
|
+
receivedAt?: undefined;
|
|
51
|
+
text?: undefined;
|
|
29
52
|
sessionId?: undefined;
|
|
30
53
|
reconnect?: undefined;
|
|
31
54
|
event?: undefined;
|
|
@@ -47,6 +70,7 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
47
70
|
receivedAt?: undefined;
|
|
48
71
|
turnId?: undefined;
|
|
49
72
|
text?: undefined;
|
|
73
|
+
delta?: undefined;
|
|
50
74
|
reconnect?: undefined;
|
|
51
75
|
event?: undefined;
|
|
52
76
|
message?: undefined;
|
|
@@ -67,6 +91,7 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
67
91
|
receivedAt?: undefined;
|
|
68
92
|
turnId?: undefined;
|
|
69
93
|
text?: undefined;
|
|
94
|
+
delta?: undefined;
|
|
70
95
|
sessionId?: undefined;
|
|
71
96
|
event?: undefined;
|
|
72
97
|
message?: undefined;
|
|
@@ -88,6 +113,7 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
88
113
|
receivedAt?: undefined;
|
|
89
114
|
turnId?: undefined;
|
|
90
115
|
text?: undefined;
|
|
116
|
+
delta?: undefined;
|
|
91
117
|
reconnect?: undefined;
|
|
92
118
|
message?: undefined;
|
|
93
119
|
transcript?: undefined;
|
|
@@ -107,6 +133,7 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
107
133
|
receivedAt?: undefined;
|
|
108
134
|
turnId?: undefined;
|
|
109
135
|
text?: undefined;
|
|
136
|
+
delta?: undefined;
|
|
110
137
|
sessionId?: undefined;
|
|
111
138
|
reconnect?: undefined;
|
|
112
139
|
event?: undefined;
|
|
@@ -127,6 +154,7 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
127
154
|
receivedAt?: undefined;
|
|
128
155
|
turnId?: undefined;
|
|
129
156
|
text?: undefined;
|
|
157
|
+
delta?: undefined;
|
|
130
158
|
sessionId?: undefined;
|
|
131
159
|
reconnect?: undefined;
|
|
132
160
|
event?: undefined;
|
|
@@ -147,6 +175,7 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
147
175
|
receivedAt?: undefined;
|
|
148
176
|
turnId?: undefined;
|
|
149
177
|
text?: undefined;
|
|
178
|
+
delta?: undefined;
|
|
150
179
|
sessionId?: undefined;
|
|
151
180
|
reconnect?: undefined;
|
|
152
181
|
event?: undefined;
|
|
@@ -174,6 +203,7 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
174
203
|
receivedAt?: undefined;
|
|
175
204
|
turnId?: undefined;
|
|
176
205
|
text?: undefined;
|
|
206
|
+
delta?: undefined;
|
|
177
207
|
reconnect?: undefined;
|
|
178
208
|
event?: undefined;
|
|
179
209
|
message?: undefined;
|
|
@@ -190,6 +220,7 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
190
220
|
receivedAt?: undefined;
|
|
191
221
|
turnId?: undefined;
|
|
192
222
|
text?: undefined;
|
|
223
|
+
delta?: undefined;
|
|
193
224
|
reconnect?: undefined;
|
|
194
225
|
event?: undefined;
|
|
195
226
|
message?: undefined;
|
|
@@ -207,6 +238,7 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
|
|
|
207
238
|
receivedAt?: undefined;
|
|
208
239
|
turnId?: undefined;
|
|
209
240
|
text?: undefined;
|
|
241
|
+
delta?: undefined;
|
|
210
242
|
sessionId?: undefined;
|
|
211
243
|
reconnect?: undefined;
|
|
212
244
|
event?: undefined;
|
|
@@ -184,8 +184,15 @@ var serverMessageToAction = (message) => {
|
|
|
184
184
|
case "assistant":
|
|
185
185
|
return {
|
|
186
186
|
text: message.text,
|
|
187
|
+
turnId: message.turnId,
|
|
187
188
|
type: "assistant"
|
|
188
189
|
};
|
|
190
|
+
case "assistant_delta":
|
|
191
|
+
return {
|
|
192
|
+
delta: message.delta,
|
|
193
|
+
turnId: message.turnId,
|
|
194
|
+
type: "assistant_delta"
|
|
195
|
+
};
|
|
189
196
|
case "complete":
|
|
190
197
|
return {
|
|
191
198
|
sessionId: message.sessionId,
|
|
@@ -753,6 +760,7 @@ var createInitialReconnectState = () => ({
|
|
|
753
760
|
});
|
|
754
761
|
var createInitialState = () => ({
|
|
755
762
|
assistantAudio: [],
|
|
763
|
+
assistantStreamingText: "",
|
|
756
764
|
assistantTexts: [],
|
|
757
765
|
call: null,
|
|
758
766
|
error: null,
|
|
@@ -790,9 +798,16 @@ var createVoiceStreamStore = () => {
|
|
|
790
798
|
case "assistant":
|
|
791
799
|
state = {
|
|
792
800
|
...state,
|
|
801
|
+
assistantStreamingText: "",
|
|
793
802
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
794
803
|
};
|
|
795
804
|
break;
|
|
805
|
+
case "assistant_delta":
|
|
806
|
+
state = {
|
|
807
|
+
...state,
|
|
808
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
809
|
+
};
|
|
810
|
+
break;
|
|
796
811
|
case "complete":
|
|
797
812
|
state = {
|
|
798
813
|
...state,
|
|
@@ -860,6 +875,7 @@ var createVoiceStreamStore = () => {
|
|
|
860
875
|
case "replay":
|
|
861
876
|
state = {
|
|
862
877
|
...state,
|
|
878
|
+
assistantStreamingText: "",
|
|
863
879
|
assistantTexts: [...action.assistantTexts],
|
|
864
880
|
call: action.call ?? null,
|
|
865
881
|
error: null,
|
|
@@ -971,6 +987,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
971
987
|
get assistantTexts() {
|
|
972
988
|
return store.getSnapshot().assistantTexts;
|
|
973
989
|
},
|
|
990
|
+
get assistantStreamingText() {
|
|
991
|
+
return store.getSnapshot().assistantStreamingText;
|
|
992
|
+
},
|
|
974
993
|
get call() {
|
|
975
994
|
return store.getSnapshot().call;
|
|
976
995
|
},
|
|
@@ -1317,6 +1336,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
1317
1336
|
// src/client/controller.ts
|
|
1318
1337
|
var createInitialState2 = (stream) => ({
|
|
1319
1338
|
assistantAudio: [...stream.assistantAudio],
|
|
1339
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1320
1340
|
assistantTexts: [...stream.assistantTexts],
|
|
1321
1341
|
call: stream.call,
|
|
1322
1342
|
error: stream.error,
|
|
@@ -1349,6 +1369,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1349
1369
|
state = {
|
|
1350
1370
|
...state,
|
|
1351
1371
|
assistantAudio: [...stream.assistantAudio],
|
|
1372
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1352
1373
|
assistantTexts: [...stream.assistantTexts],
|
|
1353
1374
|
call: stream.call,
|
|
1354
1375
|
error: stream.error,
|
|
@@ -1442,6 +1463,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1442
1463
|
get assistantTexts() {
|
|
1443
1464
|
return state.assistantTexts;
|
|
1444
1465
|
},
|
|
1466
|
+
get assistantStreamingText() {
|
|
1467
|
+
return state.assistantStreamingText;
|
|
1468
|
+
},
|
|
1445
1469
|
bindHTMX(bindingOptions) {
|
|
1446
1470
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
1447
1471
|
},
|
package/dist/client/index.js
CHANGED
|
@@ -757,8 +757,15 @@ var serverMessageToAction = (message) => {
|
|
|
757
757
|
case "assistant":
|
|
758
758
|
return {
|
|
759
759
|
text: message.text,
|
|
760
|
+
turnId: message.turnId,
|
|
760
761
|
type: "assistant"
|
|
761
762
|
};
|
|
763
|
+
case "assistant_delta":
|
|
764
|
+
return {
|
|
765
|
+
delta: message.delta,
|
|
766
|
+
turnId: message.turnId,
|
|
767
|
+
type: "assistant_delta"
|
|
768
|
+
};
|
|
762
769
|
case "complete":
|
|
763
770
|
return {
|
|
764
771
|
sessionId: message.sessionId,
|
|
@@ -906,6 +913,7 @@ var createInitialReconnectState = () => ({
|
|
|
906
913
|
});
|
|
907
914
|
var createInitialState2 = () => ({
|
|
908
915
|
assistantAudio: [],
|
|
916
|
+
assistantStreamingText: "",
|
|
909
917
|
assistantTexts: [],
|
|
910
918
|
call: null,
|
|
911
919
|
error: null,
|
|
@@ -943,9 +951,16 @@ var createVoiceStreamStore = () => {
|
|
|
943
951
|
case "assistant":
|
|
944
952
|
state = {
|
|
945
953
|
...state,
|
|
954
|
+
assistantStreamingText: "",
|
|
946
955
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
947
956
|
};
|
|
948
957
|
break;
|
|
958
|
+
case "assistant_delta":
|
|
959
|
+
state = {
|
|
960
|
+
...state,
|
|
961
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
962
|
+
};
|
|
963
|
+
break;
|
|
949
964
|
case "complete":
|
|
950
965
|
state = {
|
|
951
966
|
...state,
|
|
@@ -1013,6 +1028,7 @@ var createVoiceStreamStore = () => {
|
|
|
1013
1028
|
case "replay":
|
|
1014
1029
|
state = {
|
|
1015
1030
|
...state,
|
|
1031
|
+
assistantStreamingText: "",
|
|
1016
1032
|
assistantTexts: [...action.assistantTexts],
|
|
1017
1033
|
call: action.call ?? null,
|
|
1018
1034
|
error: null,
|
|
@@ -1124,6 +1140,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
1124
1140
|
get assistantTexts() {
|
|
1125
1141
|
return store.getSnapshot().assistantTexts;
|
|
1126
1142
|
},
|
|
1143
|
+
get assistantStreamingText() {
|
|
1144
|
+
return store.getSnapshot().assistantStreamingText;
|
|
1145
|
+
},
|
|
1127
1146
|
get call() {
|
|
1128
1147
|
return store.getSnapshot().call;
|
|
1129
1148
|
},
|
|
@@ -1648,6 +1667,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
1648
1667
|
// src/client/controller.ts
|
|
1649
1668
|
var createInitialState3 = (stream) => ({
|
|
1650
1669
|
assistantAudio: [...stream.assistantAudio],
|
|
1670
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1651
1671
|
assistantTexts: [...stream.assistantTexts],
|
|
1652
1672
|
call: stream.call,
|
|
1653
1673
|
error: stream.error,
|
|
@@ -1680,6 +1700,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1680
1700
|
state = {
|
|
1681
1701
|
...state,
|
|
1682
1702
|
assistantAudio: [...stream.assistantAudio],
|
|
1703
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1683
1704
|
assistantTexts: [...stream.assistantTexts],
|
|
1684
1705
|
call: stream.call,
|
|
1685
1706
|
error: stream.error,
|
|
@@ -1773,6 +1794,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1773
1794
|
get assistantTexts() {
|
|
1774
1795
|
return state.assistantTexts;
|
|
1775
1796
|
},
|
|
1797
|
+
get assistantStreamingText() {
|
|
1798
|
+
return state.assistantStreamingText;
|
|
1799
|
+
},
|
|
1776
1800
|
bindHTMX(bindingOptions) {
|
|
1777
1801
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
1778
1802
|
},
|
package/dist/core/types.d.ts
CHANGED
|
@@ -773,6 +773,18 @@ export type VoicePluginConfig<TContext = unknown, TSession extends VoiceSessionR
|
|
|
773
773
|
session: VoiceSessionStore<NoInfer<TSession>>;
|
|
774
774
|
reconnect?: VoiceReconnectConfig;
|
|
775
775
|
turnDetection?: VoiceTurnDetectionConfig;
|
|
776
|
+
semanticTurnDetector?: import("./semanticTurn").VoiceSemanticTurnDetector;
|
|
777
|
+
bargeInMinPartialWords?: number;
|
|
778
|
+
fillerPhrases?: ReadonlyArray<string>;
|
|
779
|
+
fillerDelayMs?: number;
|
|
780
|
+
fillerFor?: (input: {
|
|
781
|
+
sessionId: string;
|
|
782
|
+
turnId: string;
|
|
783
|
+
userText: string;
|
|
784
|
+
}) => Promise<string | null>;
|
|
785
|
+
fillerForTimeoutMs?: number;
|
|
786
|
+
defaultSilentTurnAck?: string;
|
|
787
|
+
routeOnTurnTimeoutMs?: number;
|
|
776
788
|
audioConditioning?: VoiceAudioConditioningConfig;
|
|
777
789
|
noiseSuppressor?: VoiceNoiseSuppressor;
|
|
778
790
|
noiseSuppressorFormat?: AudioFormat;
|
|
@@ -1047,6 +1059,11 @@ export type VoiceServerAssistantMessage = {
|
|
|
1047
1059
|
text: string;
|
|
1048
1060
|
turnId?: string;
|
|
1049
1061
|
};
|
|
1062
|
+
export type VoiceServerAssistantDeltaMessage = {
|
|
1063
|
+
type: "assistant_delta";
|
|
1064
|
+
delta: string;
|
|
1065
|
+
turnId?: string;
|
|
1066
|
+
};
|
|
1050
1067
|
export type VoiceServerAudioMessage = {
|
|
1051
1068
|
type: "audio";
|
|
1052
1069
|
chunkBase64: string;
|
|
@@ -1075,7 +1092,7 @@ export type VoiceServerConnectionMessage = {
|
|
|
1075
1092
|
type: "connection";
|
|
1076
1093
|
reconnect: VoiceReconnectClientState;
|
|
1077
1094
|
};
|
|
1078
|
-
export type VoiceServerMessage<TResult = unknown> = VoiceServerSessionMessage | VoiceServerReplayMessage<TResult> | VoiceServerPartialMessage | VoiceServerFinalMessage | VoiceServerTurnMessage<TResult> | VoiceServerAssistantMessage | VoiceServerAudioMessage | VoiceServerCallLifecycleMessage | VoiceServerCompleteMessage | VoiceServerErrorMessage | VoiceServerPongMessage | VoiceServerConnectionMessage;
|
|
1095
|
+
export type VoiceServerMessage<TResult = unknown> = VoiceServerSessionMessage | VoiceServerReplayMessage<TResult> | VoiceServerPartialMessage | VoiceServerFinalMessage | VoiceServerTurnMessage<TResult> | VoiceServerAssistantMessage | VoiceServerAssistantDeltaMessage | VoiceServerAudioMessage | VoiceServerCallLifecycleMessage | VoiceServerCompleteMessage | VoiceServerErrorMessage | VoiceServerPongMessage | VoiceServerConnectionMessage;
|
|
1079
1096
|
export type VoiceConnectionOptions = {
|
|
1080
1097
|
browserMedia?: false | VoiceBrowserMediaReporterOptions;
|
|
1081
1098
|
protocols?: string[];
|
|
@@ -1224,6 +1241,7 @@ export type VoiceStreamState<TResult = unknown> = {
|
|
|
1224
1241
|
partial: string;
|
|
1225
1242
|
turns: VoiceTurnRecord<TResult>[];
|
|
1226
1243
|
assistantTexts: string[];
|
|
1244
|
+
assistantStreamingText: string;
|
|
1227
1245
|
assistantAudio: Array<{
|
|
1228
1246
|
chunk: Uint8Array;
|
|
1229
1247
|
format: AudioFormat;
|
|
@@ -1257,6 +1275,7 @@ export type VoiceStream<TResult = unknown> = {
|
|
|
1257
1275
|
subscribe: (subscriber: () => void) => () => void;
|
|
1258
1276
|
turns: VoiceTurnRecord<TResult>[];
|
|
1259
1277
|
assistantTexts: string[];
|
|
1278
|
+
assistantStreamingText: string;
|
|
1260
1279
|
assistantAudio: Array<{
|
|
1261
1280
|
chunk: Uint8Array;
|
|
1262
1281
|
format: AudioFormat;
|
|
@@ -1333,6 +1352,7 @@ export type VoiceController<TResult = unknown> = {
|
|
|
1333
1352
|
toggleRecording: () => Promise<void>;
|
|
1334
1353
|
turns: VoiceTurnRecord<TResult>[];
|
|
1335
1354
|
assistantTexts: string[];
|
|
1355
|
+
assistantStreamingText: string;
|
|
1336
1356
|
assistantAudio: Array<{
|
|
1337
1357
|
chunk: Uint8Array;
|
|
1338
1358
|
format: AudioFormat;
|
|
@@ -1382,6 +1402,11 @@ export type VoiceStoreAction<TResult = unknown> = {
|
|
|
1382
1402
|
} | {
|
|
1383
1403
|
type: "assistant";
|
|
1384
1404
|
text: string;
|
|
1405
|
+
turnId?: string;
|
|
1406
|
+
} | {
|
|
1407
|
+
type: "assistant_delta";
|
|
1408
|
+
delta: string;
|
|
1409
|
+
turnId?: string;
|
|
1385
1410
|
} | {
|
|
1386
1411
|
type: "audio";
|
|
1387
1412
|
chunk: Uint8Array;
|
package/dist/embed/index.js
CHANGED
|
@@ -181,8 +181,15 @@ var serverMessageToAction = (message) => {
|
|
|
181
181
|
case "assistant":
|
|
182
182
|
return {
|
|
183
183
|
text: message.text,
|
|
184
|
+
turnId: message.turnId,
|
|
184
185
|
type: "assistant"
|
|
185
186
|
};
|
|
187
|
+
case "assistant_delta":
|
|
188
|
+
return {
|
|
189
|
+
delta: message.delta,
|
|
190
|
+
turnId: message.turnId,
|
|
191
|
+
type: "assistant_delta"
|
|
192
|
+
};
|
|
186
193
|
case "complete":
|
|
187
194
|
return {
|
|
188
195
|
sessionId: message.sessionId,
|
|
@@ -750,6 +757,7 @@ var createInitialReconnectState = () => ({
|
|
|
750
757
|
});
|
|
751
758
|
var createInitialState = () => ({
|
|
752
759
|
assistantAudio: [],
|
|
760
|
+
assistantStreamingText: "",
|
|
753
761
|
assistantTexts: [],
|
|
754
762
|
call: null,
|
|
755
763
|
error: null,
|
|
@@ -787,9 +795,16 @@ var createVoiceStreamStore = () => {
|
|
|
787
795
|
case "assistant":
|
|
788
796
|
state = {
|
|
789
797
|
...state,
|
|
798
|
+
assistantStreamingText: "",
|
|
790
799
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
791
800
|
};
|
|
792
801
|
break;
|
|
802
|
+
case "assistant_delta":
|
|
803
|
+
state = {
|
|
804
|
+
...state,
|
|
805
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
806
|
+
};
|
|
807
|
+
break;
|
|
793
808
|
case "complete":
|
|
794
809
|
state = {
|
|
795
810
|
...state,
|
|
@@ -857,6 +872,7 @@ var createVoiceStreamStore = () => {
|
|
|
857
872
|
case "replay":
|
|
858
873
|
state = {
|
|
859
874
|
...state,
|
|
875
|
+
assistantStreamingText: "",
|
|
860
876
|
assistantTexts: [...action.assistantTexts],
|
|
861
877
|
call: action.call ?? null,
|
|
862
878
|
error: null,
|
|
@@ -968,6 +984,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
968
984
|
get assistantTexts() {
|
|
969
985
|
return store.getSnapshot().assistantTexts;
|
|
970
986
|
},
|
|
987
|
+
get assistantStreamingText() {
|
|
988
|
+
return store.getSnapshot().assistantStreamingText;
|
|
989
|
+
},
|
|
971
990
|
get call() {
|
|
972
991
|
return store.getSnapshot().call;
|
|
973
992
|
},
|
|
@@ -1314,6 +1333,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
1314
1333
|
// src/client/controller.ts
|
|
1315
1334
|
var createInitialState2 = (stream) => ({
|
|
1316
1335
|
assistantAudio: [...stream.assistantAudio],
|
|
1336
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1317
1337
|
assistantTexts: [...stream.assistantTexts],
|
|
1318
1338
|
call: stream.call,
|
|
1319
1339
|
error: stream.error,
|
|
@@ -1346,6 +1366,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1346
1366
|
state = {
|
|
1347
1367
|
...state,
|
|
1348
1368
|
assistantAudio: [...stream.assistantAudio],
|
|
1369
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1349
1370
|
assistantTexts: [...stream.assistantTexts],
|
|
1350
1371
|
call: stream.call,
|
|
1351
1372
|
error: stream.error,
|
|
@@ -1439,6 +1460,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1439
1460
|
get assistantTexts() {
|
|
1440
1461
|
return state.assistantTexts;
|
|
1441
1462
|
},
|
|
1463
|
+
get assistantStreamingText() {
|
|
1464
|
+
return state.assistantStreamingText;
|
|
1465
|
+
},
|
|
1442
1466
|
bindHTMX(bindingOptions) {
|
|
1443
1467
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
1444
1468
|
},
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
(()=>{var{defineProperty:H,getOwnPropertyNames:oc,getOwnPropertyDescriptor:lc}=Object,Ac=Object.prototype.hasOwnProperty;function Cc(c){return this[c]}var ic=(c)=>{var n=(Y??=new WeakMap).get(c),o;if(n)return n;if(n=H({},"__esModule",{value:!0}),c&&typeof c==="object"||typeof c==="function"){for(var g of oc(c))if(!Ac.call(n,g))H(n,g,{get:Cc.bind(c,g),enumerable:!(o=lc(c,g))||o.enumerable})}return Y.set(c,n),n},Y;var yc=(c)=>c;function Tc(c,n){this[c]=yc.bind(null,n)}var Vc=(c,n)=>{for(var o in n)H(c,o,{get:n[o],enumerable:!0,configurable:!0,set:Tc.bind(n,o)})};var Bc={};Vc(Bc,{mount:()=>p,default:()=>Kc,VOICE_EMBED_VERSION:()=>cc});var Ic=(c)=>{if(typeof c!=="string")return c;return document.querySelector(c)},Rc=(c,n,o,g)=>{let l=n??c.getAttribute("hx-get")??"";if(!l)return"";let i=new URL(l,window.location.origin);if(g)i.searchParams.set(o,g);else i.searchParams.delete(o);return`${i.pathname}${i.search}${i.hash}`},Q=(c,n)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let o=Ic(n.element);if(!o)return()=>{};let g=n.eventName??"voice-refresh",l=n.sessionQueryParam??"sessionId",i=()=>{let V=window,I=Rc(o,n.route,l,c.sessionId);if(I)o.setAttribute("hx-get",I);V.htmx?.process?.(o),V.htmx?.trigger?.(o,g)},C=c.subscribe(i);return i(),()=>{C()}};var hc=(c)=>Math.max(-1,Math.min(1,c)),Sc=(c)=>{let n=new Int16Array(c.length);for(let o=0;o<c.length;o+=1){let g=hc(c[o]??0);n[o]=g<0?g*32768:g*32767}return new Uint8Array(n.buffer)},dc=(c)=>{let n=c instanceof Uint8Array?c:new Uint8Array(c);if(n.byteLength<2)return 0;let o=new Int16Array(n.buffer,n.byteOffset,Math.floor(n.byteLength/2));if(o.length===0)return 0;let g=0;for(let l of o){let i=l/32768;g+=i*i}return Math.min(1,Math.max(0,Math.sqrt(g/o.length)*5.5))},_c=(c,n,o)=>{if(n===o)return c;let g=n/o,l=Math.round(c.length/g),i=new Float32Array(l),C=0,V=0;while(C<i.length){let I=Math.round((C+1)*g),S=0,T=0;for(let h=V;h<I&&h<c.length;h+=1)S+=c[h]??0,T+=1;i[C]=T>0?S/T:0,C+=1,V=I}return i},J=(c)=>{let n=null,o=null,g=null,l=null;return{start:async()=>{if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let V=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!V)throw Error("Browser microphone capture requires AudioContext support.");l=await navigator.mediaDevices.getUserMedia({audio:{channelCount:c.channelCount??1}}),n=new V,o=n.createMediaStreamSource(l),g=n.createScriptProcessor(4096,1,1),g.onaudioprocess=(I)=>{let S=I.inputBuffer.getChannelData(0),T=_c(S,n?.sampleRate??48000,c.sampleRateHz??16000),h=Sc(T);c.onLevel?.(dc(h)),c.onAudio(h)},o.connect(g),g.connect(n.destination)},stop:()=>{g?.disconnect(),o?.disconnect(),l?.getTracks().forEach((V)=>V.stop()),n?.close(),c.onLevel?.(0),n=null,l=null,g=null,o=null}}};var G=(c)=>{if(typeof c==="string"&&c.trim())return c;if(c instanceof Error&&c.message.trim())return c.message;if(c&&typeof c==="object"){let n=c;for(let o of["message","reason","description"]){let g=n[o];if(typeof g==="string"&&g.trim())return g}if("error"in n)return G(n.error);if("cause"in n)return G(n.cause);try{return JSON.stringify(c)}catch{}}return"Unexpected error"},q=(c)=>{switch(c.type){case"audio":return{chunk:Uint8Array.from(atob(c.chunkBase64),(n)=>n.charCodeAt(0)),format:c.format,receivedAt:c.receivedAt,turnId:c.turnId,type:"audio"};case"assistant":return{text:c.text,type:"assistant"};case"complete":return{sessionId:c.sessionId,type:"complete"};case"connection":return{reconnect:c.reconnect,type:"connection"};case"call_lifecycle":return{event:c.event,sessionId:c.sessionId,type:"call_lifecycle"};case"error":return{message:G(c.message),type:"error"};case"final":return{transcript:c.transcript,type:"final"};case"partial":return{transcript:c.transcript,type:"partial"};case"replay":return{assistantTexts:c.assistantTexts,call:c.call,partial:c.partial,scenarioId:c.scenarioId,sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,status:c.status,turns:c.turns,type:"replay"};case"session":return{sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,scenarioId:c.scenarioId,status:c.status,type:"session"};case"turn":return{turn:c.turn,type:"turn"};default:return null}};var tc=Math.PI*2;var D=(c,n,o,g)=>{c.push({code:o,message:g,severity:n})};var wc=(c)=>c.length===0?void 0:c.reduce((n,o)=>n+o,0)/c.length,$=(c)=>c.length===0?void 0:Math.max(...c);var _=(c,n)=>{let o=c[n];return typeof o==="number"&&Number.isFinite(o)?o:void 0},N=(c,n)=>{let o=c[n];return typeof o==="boolean"?o:void 0},w=(c,n)=>{let o=c[n];return typeof o==="string"?o:void 0},X=(c)=>String(c.id??w(c,"ssrc")??_(c,"ssrc")??w(c,"trackIdentifier")??w(c,"mid")??"unknown"),Z=(c)=>c===void 0?void 0:c*1000;var Lc=(c)=>{let n={};for(let[o,g]of Object.entries(c))if(g===null||typeof g==="boolean"||typeof g==="number"||typeof g==="string")n[o]=g;return n};var z=(c={})=>{let n=c.stats??[],o=[],g=n.filter((A)=>A.type==="inbound-rtp"&&w(A,"kind")!=="video"),l=n.filter((A)=>A.type==="outbound-rtp"&&w(A,"kind")!=="video"),i=n.filter((A)=>A.type==="candidate-pair"),C=n.filter((A)=>(A.type==="track"||A.type==="media-source")&&w(A,"kind")==="audio"),V=i.filter((A)=>N(A,"selected")===!0||N(A,"nominated")===!0||w(A,"state")==="succeeded").length,I=C.filter((A)=>w(A,"readyState")!=="ended"&&w(A,"trackState")!=="ended"&&N(A,"ended")!==!0).length,S=C.filter((A)=>w(A,"readyState")==="ended"||w(A,"trackState")==="ended"||N(A,"ended")===!0).length,T=g.reduce((A,d)=>A+(_(d,"packetsReceived")??0),0),h=l.reduce((A,d)=>A+(_(d,"packetsSent")??0),0),y=[...g,...l].reduce((A,d)=>A+Math.max(0,_(d,"packetsLost")??0),0),L=T+y,R=L===0?0:y/L,x=g.reduce((A,d)=>A+(_(d,"bytesReceived")??0),0),U=l.reduce((A,d)=>A+(_(d,"bytesSent")??0),0),M=$(i.map((A)=>Z(_(A,"currentRoundTripTime")??_(A,"roundTripTime"))).filter((A)=>A!==void 0)),O=$([...g,...l].map((A)=>Z(_(A,"jitter"))).filter((A)=>A!==void 0)),W=$(g.map((A)=>{let d=_(A,"jitterBufferDelay"),b=_(A,"jitterBufferEmittedCount");return d!==void 0&&b!==void 0&&b>0?d/b*1000:void 0}).filter((A)=>A!==void 0)),P=C.map((A)=>_(A,"audioLevel")).filter((A)=>A!==void 0);if(c.requireConnectedCandidatePair&&i.length>0&&V===0)D(o,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(c.requireLiveAudioTrack&&I===0)D(o,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(c.maxPacketLossRatio!==void 0&&R>c.maxPacketLossRatio)D(o,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(R)} above ${String(c.maxPacketLossRatio)}.`);if(c.maxRoundTripTimeMs!==void 0&&M!==void 0&&M>c.maxRoundTripTimeMs)D(o,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(M)}ms above ${String(c.maxRoundTripTimeMs)}ms.`);if(c.maxJitterMs!==void 0&&O!==void 0&&O>c.maxJitterMs)D(o,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(O)}ms above ${String(c.maxJitterMs)}ms.`);return{activeCandidatePairs:V,audioLevelAverage:wc(P),bytesReceived:x,bytesSent:U,checkedAt:Date.now(),endedAudioTracks:S,inboundPackets:T,issues:o,jitterBufferDelayMs:W,jitterMs:O,liveAudioTracks:I,outboundPackets:h,packetLossRatio:R,packetsLost:y,roundTripTimeMs:M,status:o.some((A)=>A.severity==="error")?"fail":o.length>0?"warn":"pass",totalStats:n.length}},B=async(c)=>{return[...(await c.peerConnection.getStats(c.selector??null)).values()].map(Lc)};var K=(c={})=>{let n=c.stats??[],o=c.previousStats??[],g=[],l=new Map(o.map((y)=>[X(y),y])),C=n.filter((y)=>(y.type==="inbound-rtp"||y.type==="outbound-rtp")&&w(y,"kind")!=="video"&&w(y,"mediaType")!=="video").map((y)=>{let L=y.type==="outbound-rtp"?"outbound":"inbound",R=L==="outbound"?"packetsSent":"packetsReceived",x=L==="outbound"?"bytesSent":"bytesReceived",U=l.get(X(y)),M=_(y,R),O=U?_(U,R):void 0,W=_(y,x),P=U?_(U,x):void 0,A=y.timestamp!==void 0&&U?.timestamp!==void 0?y.timestamp-U.timestamp:void 0;return{bytesDelta:W!==void 0&&P!==void 0?W-P:void 0,currentPackets:M,direction:L,id:X(y),packetDelta:M!==void 0&&O!==void 0?M-O:void 0,previousPackets:O,timeDeltaMs:A}}),V=C.filter((y)=>y.direction==="inbound"),I=C.filter((y)=>y.direction==="outbound"),S=$(C.map((y)=>y.timeDeltaMs).filter((y)=>y!==void 0)),T=V.filter((y)=>c.maxInboundPacketStallMs!==void 0&&y.timeDeltaMs!==void 0&&y.timeDeltaMs>=c.maxInboundPacketStallMs&&y.packetDelta!==void 0&&y.packetDelta<=0).length,h=I.filter((y)=>c.maxOutboundPacketStallMs!==void 0&&y.timeDeltaMs!==void 0&&y.timeDeltaMs>=c.maxOutboundPacketStallMs&&y.packetDelta!==void 0&&y.packetDelta<=0).length;if(c.requireInboundAudio&&V.length===0)D(g,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(c.requireOutboundAudio&&I.length===0)D(g,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(c.maxGapMs!==void 0&&S!==void 0&&S>c.maxGapMs)D(g,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String(S)}ms above ${String(c.maxGapMs)}ms.`);if(T>0)D(g,"error","media.webrtc_inbound_stalled",`${String(T)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(h>0)D(g,"error","media.webrtc_outbound_stalled",`${String(h)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:V.length,issues:g,maxObservedGapMs:S,outboundAudioStreams:I.length,stalledInboundStreams:T,stalledOutboundStreams:h,status:g.some((y)=>y.severity==="error")?"fail":g.length>0?"warn":"pass",streams:C,totalStats:n.length}};var bc="/api/voice/browser-media",Uc=5000,Mc=async(c)=>c.peerConnection??await c.getPeerConnection?.()??null,Oc=async(c,n)=>{let o=n.fetch??globalThis.fetch;if(!o)return;await o(n.path??bc,{body:JSON.stringify(c),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},j=(c)=>{let n=null,o=[],g=async()=>{let C=await Mc(c);if(!C)return;let V=await B({peerConnection:C}),I=z({...c,stats:V}),S=c.continuity===!1?void 0:K({...c.continuity,previousStats:o,stats:V}),T={at:Date.now(),continuity:S,report:I,scenarioId:c.getScenarioId?.()??null,sessionId:c.getSessionId?.()??null};return o=V,c.onReport?.(T),await Oc(T,c),T},l=()=>{g().catch((C)=>{c.onError?.(C)})},i=()=>{if(n)clearInterval(n),n=null};return{close:i,reportOnce:g,stop:i,start:()=>{if(n)return;l(),n=setInterval(l,c.intervalMs??Uc)}}};var E=()=>{},Dc=()=>E,sc={callControl:E,close:E,endTurn:E,send:E,sendAudio:E,simulateDisconnect:E,subscribe:Dc,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",start:()=>{}},Ec=()=>crypto.randomUUID(),xc=(c,n,o)=>{let{hostname:g,port:l,protocol:i}=window.location,C=i==="https:"?"wss:":"ws:",V=l?`:${l}`:"",I=new URL(`${C}//${g}${V}${c}`);if(I.searchParams.set("sessionId",n),o)I.searchParams.set("scenarioId",o);return I.toString()},Wc=(c)=>{if(!c||typeof c!=="object"||!("type"in c))return!1;switch(c.type){case"audio":case"assistant":case"call_lifecycle":case"complete":case"connection":case"error":case"final":case"partial":case"pong":case"replay":case"session":case"turn":return!0;default:return!1}},Pc=(c)=>{if(typeof c.data!=="string")return null;try{let n=JSON.parse(c.data);return Wc(n)?n:null}catch{return null}},f=(c,n={})=>{if(typeof window>"u")return sc;let o=new Set,g=n.reconnect!==!1,l=n.maxReconnectAttempts??10,i=n.pingInterval??30000,C={isConnected:!1,pendingMessages:[],scenarioId:n.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:n.sessionId??Ec(),ws:null},V=(A)=>{o.forEach((d)=>d(A))},I=()=>{if(C.pingInterval)clearInterval(C.pingInterval),C.pingInterval=null;if(C.reconnectTimeout)clearTimeout(C.reconnectTimeout),C.reconnectTimeout=null},S=()=>{if(C.ws?.readyState!==1)return;while(C.pendingMessages.length>0){let A=C.pendingMessages.shift();if(A!==void 0)C.ws.send(A)}},T=()=>{let A=Date.now()+500;C.reconnectAttempts+=1,V({reconnect:{attempts:C.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:l,nextAttemptAt:A,status:"reconnecting"},type:"connection"}),C.reconnectTimeout=setTimeout(()=>{if(C.reconnectAttempts>l){V({reconnect:{attempts:C.reconnectAttempts,maxAttempts:l,status:"exhausted"},type:"connection"});return}h()},500)},h=()=>{let A=new WebSocket(xc(c,C.sessionId,C.scenarioId));A.binaryType="arraybuffer",A.onopen=()=>{let d=C.reconnectAttempts>0;if(C.isConnected=!0,S(),d)V({reconnect:{attempts:C.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:l,status:"resumed"},type:"connection"}),C.reconnectAttempts=0;o.forEach((b)=>b({scenarioId:C.scenarioId??void 0,sessionId:C.sessionId,status:"active",type:"session"})),C.pingInterval=setInterval(()=>{if(A.readyState===1)A.send(JSON.stringify({type:"ping"}))},i)},A.onmessage=(d)=>{let b=Pc(d);if(!b)return;if(b.type==="session")C.sessionId=b.sessionId,C.scenarioId=b.scenarioId??C.scenarioId;o.forEach((gc)=>gc(b))},A.onclose=(d)=>{if(C.isConnected=!1,I(),g&&d.code!==1000&&C.reconnectAttempts<l)T();else if(g&&d.code!==1000)V({reconnect:{attempts:C.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:l,status:"exhausted"},type:"connection"})},C.ws=A},y=(A)=>{if(C.ws?.readyState===1){C.ws.send(A);return}C.pendingMessages.push(A)},L=(A)=>{y(JSON.stringify(A))},R=(A={})=>{if(A.sessionId)C.sessionId=A.sessionId;if(A.scenarioId)C.scenarioId=A.scenarioId;L({scenarioId:C.scenarioId??void 0,sessionId:C.sessionId,type:"start"})},x=(A)=>{y(A)},U=()=>{L({type:"end_turn"})},M=(A)=>{L({...A,type:"call_control"})},O=()=>{if(I(),C.ws)C.ws.close(1000),C.ws=null;C.isConnected=!1,o.clear()},W=()=>{if(C.ws?.readyState===1)C.ws.close(4000,"absolutejs-voice-reconnect-proof")},P=(A)=>{return o.add(A),()=>{o.delete(A)}};return h(),{callControl:M,close:O,endTurn:U,send:L,sendAudio:x,simulateDisconnect:W,start:R,subscribe:P,getReadyState:()=>C.ws?.readyState??3,getScenarioId:()=>C.scenarioId??"",getSessionId:()=>C.sessionId}};var Nc=()=>({attempts:0,maxAttempts:0,status:"idle"}),$c=()=>({assistantAudio:[],assistantTexts:[],call:null,error:null,isConnected:!1,partial:"",reconnect:Nc(),scenarioId:null,sessionId:null,sessionMetadata:null,status:"idle",turns:[]}),e=()=>{let c=$c(),n=new Set,o=()=>{n.forEach((l)=>l())};return{dispatch:(l)=>{switch(l.type){case"audio":c={...c,assistantAudio:[...c.assistantAudio,{chunk:l.chunk,format:l.format,receivedAt:l.receivedAt,turnId:l.turnId}]};break;case"assistant":c={...c,assistantTexts:[...c.assistantTexts,l.text]};break;case"complete":c={...c,sessionId:l.sessionId,status:"completed"};break;case"call_lifecycle":c={...c,call:{...c.call,disposition:l.event.type==="end"?l.event.disposition:c.call?.disposition,endedAt:l.event.type==="end"?l.event.at:c.call?.endedAt,events:[...c.call?.events??[],l.event],lastEventAt:l.event.at,startedAt:c.call?.startedAt??l.event.at},sessionId:l.sessionId};break;case"connected":c={...c,isConnected:!0,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect};break;case"connection":c={...c,reconnect:l.reconnect};break;case"disconnected":c={...c,isConnected:!1};break;case"error":c={...c,error:l.message};break;case"final":c={...c,partial:l.transcript.text,turns:c.turns.map((i)=>i)};break;case"partial":c={...c,partial:l.transcript.text};break;case"replay":c={...c,assistantTexts:[...l.assistantTexts],call:l.call??null,error:null,isConnected:l.status==="active",partial:l.partial,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect,scenarioId:l.scenarioId??c.scenarioId,sessionId:l.sessionId,sessionMetadata:l.sessionMetadata??c.sessionMetadata,status:l.status,turns:[...l.turns]};break;case"session":c={...c,error:null,scenarioId:l.scenarioId??c.scenarioId,isConnected:l.status==="active",sessionId:l.sessionId,sessionMetadata:l.sessionMetadata??c.sessionMetadata,status:l.status};break;case"turn":c={...c,partial:"",turns:[...c.turns,l.turn]};break}o()},getServerSnapshot:()=>c,getSnapshot:()=>c,subscribe:(l)=>{return n.add(l),()=>{n.delete(l)}}}};var k=(c,n={})=>{let o=f(c,n),g=e(),l=n.browserMedia&&typeof window<"u"?j({...n.browserMedia,getScenarioId:()=>n.browserMedia?n.browserMedia.getScenarioId?.()??o.getScenarioId():o.getScenarioId(),getSessionId:()=>n.browserMedia?n.browserMedia.getSessionId?.()??o.getSessionId():o.getSessionId()}):null,i=new Set,C=(T)=>Promise.resolve().then(()=>{if(!T?.sessionId&&!T?.scenarioId)return;o.start(T),l?.start()}),V=()=>{i.forEach((T)=>T())},I=()=>{if(!n.reconnectReportPath||typeof fetch>"u")return;let T=g.getSnapshot(),h=JSON.stringify({at:Date.now(),reconnect:T.reconnect,scenarioId:T.scenarioId,sessionId:o.getSessionId(),turnIds:T.turns.map((y)=>y.id)});fetch(n.reconnectReportPath,{body:h,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},S=o.subscribe((T)=>{let h=q(T);if(h){if(g.dispatch(h),T.type==="connection")I();V()}});return{start:C,get assistantAudio(){return g.getSnapshot().assistantAudio},get assistantTexts(){return g.getSnapshot().assistantTexts},get call(){return g.getSnapshot().call},callControl(T){o.callControl(T)},close(){S(),l?.close(),o.close(),g.dispatch({type:"disconnected"}),V()},endTurn(){o.endTurn()},get error(){return g.getSnapshot().error},getServerSnapshot(){return g.getServerSnapshot()},getSnapshot(){return g.getSnapshot()},get isConnected(){return g.getSnapshot().isConnected},get partial(){return g.getSnapshot().partial},get reconnect(){return g.getSnapshot().reconnect},get scenarioId(){return g.getSnapshot().scenarioId},sendAudio(T){o.sendAudio(T)},get sessionId(){return o.getSessionId()},get sessionMetadata(){return g.getSnapshot().sessionMetadata},simulateDisconnect(){o.simulateDisconnect()},get status(){return g.getSnapshot().status},subscribe(T){return i.add(T),()=>{i.delete(T)}},get turns(){return g.getSnapshot().turns}}};var t=(c)=>{if(!c||c.enabled===!1)return;return{enabled:!0,maxGain:c.maxGain??3,noiseGateAttenuation:c.noiseGateAttenuation??0.15,noiseGateThreshold:c.noiseGateThreshold??0.006,targetLevel:c.targetLevel??0.08}};var Hc={balanced:{qualityProfile:"general",silenceMs:1400,speechThreshold:0.012,transcriptStabilityMs:1000},fast:{qualityProfile:"general",silenceMs:700,speechThreshold:0.015,transcriptStabilityMs:450},"long-form":{qualityProfile:"general",silenceMs:2200,speechThreshold:0.01,transcriptStabilityMs:1500}},Gc={"accent-heavy":{silenceMs:1200,speechThreshold:0.01,transcriptStabilityMs:1200},general:{},"noisy-room":{silenceMs:2000,speechThreshold:0.02,transcriptStabilityMs:1600},"short-command":{silenceMs:500,speechThreshold:0.016,transcriptStabilityMs:420}};var F=(c)=>{let n=c?.profile??"fast",o=c?.qualityProfile??"general",g=Hc[n],l=Gc[o];return{profile:n,qualityProfile:o,silenceMs:c?.silenceMs??l.silenceMs??g.silenceMs,speechThreshold:c?.speechThreshold??l.speechThreshold??g.speechThreshold,transcriptStabilityMs:c?.transcriptStabilityMs??l.transcriptStabilityMs??g.transcriptStabilityMs}};var Xc={chat:{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"balanced",qualityProfile:"short-command"}},default:{capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"fast",qualityProfile:"general"}},dictation:{audioConditioning:{enabled:!0,maxGain:2.25,noiseGateAttenuation:0.05,noiseGateThreshold:0.003,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"guided-intake":{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"turn-scoped",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"noisy-room":{audioConditioning:{enabled:!0,maxGain:3,noiseGateAttenuation:0.12,noiseGateThreshold:0.006,targetLevel:0.085},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:2100,speechThreshold:0.02,transcriptStabilityMs:1650}},"pstn-balanced":{audioConditioning:{enabled:!0,maxGain:2.8,noiseGateAttenuation:0.07,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:660,speechThreshold:0.012,transcriptStabilityMs:300}},"pstn-fast":{audioConditioning:{enabled:!0,maxGain:2.75,noiseGateAttenuation:0.06,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:620,speechThreshold:0.012,transcriptStabilityMs:280}},reliability:{audioConditioning:{enabled:!0,maxGain:2.9,noiseGateAttenuation:0.08,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room"}}},r=(c="default")=>{let n=Xc[c];return{audioConditioning:t(n.audioConditioning),capture:{channelCount:n.capture?.channelCount??1,sampleRateHz:n.capture?.sampleRateHz??16000},connection:{...n.connection},name:c,sttLifecycle:n.sttLifecycle??"continuous",turnDetection:F(n.turnDetection)}};var Yc=(c)=>({assistantAudio:[...c.assistantAudio],assistantTexts:[...c.assistantTexts],call:c.call,error:c.error,isConnected:c.isConnected,isRecording:!1,partial:c.partial,reconnect:c.reconnect,recordingError:null,sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,scenarioId:c.scenarioId,status:c.status,turns:[...c.turns]}),a=(c,n={})=>{let o=r(n.preset),g=k(c,{...o.connection,...n.connection}),l=null,i=Yc(g),C=new Set,V=()=>{for(let R of C)R()},I=()=>{if(i={...i,assistantAudio:[...g.assistantAudio],assistantTexts:[...g.assistantTexts],call:g.call,error:g.error,isConnected:g.isConnected,partial:g.partial,reconnect:g.reconnect,sessionId:g.sessionId,sessionMetadata:g.sessionMetadata,scenarioId:g.scenarioId,status:g.status,turns:[...g.turns]},n.autoStopOnComplete!==!1&&i.status==="completed"&&i.isRecording)l?.stop(),l=null,i={...i,isRecording:!1};V()},S=g.subscribe(I);I();let T=()=>{if(l)return l;return l=J({channelCount:n.capture?.channelCount??o.capture.channelCount,onLevel:n.capture?.onLevel,onAudio:(R)=>{if(n.capture?.onAudio){n.capture.onAudio(R,g.sendAudio);return}g.sendAudio(R)},sampleRateHz:n.capture?.sampleRateHz??o.capture.sampleRateHz}),l},h=()=>{l?.stop(),l=null,i={...i,isRecording:!1},V()},y=async()=>{if(i.isRecording)return;try{i={...i,recordingError:null},V(),await T().start(),i={...i,isRecording:!0},V()}catch(R){throw l=null,i={...i,isRecording:!1,recordingError:R instanceof Error?R.message:String(R)},V(),R}};return{close:()=>{S(),h(),g.close()},startRecording:y,stopRecording:h,get assistantAudio(){return i.assistantAudio},get assistantTexts(){return i.assistantTexts},bindHTMX(R){return Q(g,R)},get call(){return i.call},callControl:(R)=>g.callControl(R),endTurn:()=>g.endTurn(),get error(){return i.error},getServerSnapshot:()=>i,getSnapshot:()=>i,get isConnected(){return i.isConnected},get isRecording(){return i.isRecording},get partial(){return i.partial},get reconnect(){return i.reconnect},get recordingError(){return i.recordingError},get scenarioId(){return i.scenarioId},sendAudio:(R)=>g.sendAudio(R),get sessionId(){return i.sessionId},get sessionMetadata(){return i.sessionMetadata},simulateDisconnect:()=>g.simulateDisconnect(),get status(){return i.status},subscribe:(R)=>{return C.add(R),()=>{C.delete(R)}},toggleRecording:async()=>{if(i.isRecording){h();return}await y()},get turns(){return i.turns}}};var s=(c)=>String(c).replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'");var v=(c)=>{if(!c.isConnected)return"idle";if(c.isPlaying)return"speaking";if(c.isRecording&&c.hasActivePartial)return"listening";if(c.isRecording)return"listening";if(c.lastTranscriptAt&&!c.lastAssistantAt)return"thinking";if(c.lastTranscriptAt&&c.lastAssistantAt&&c.lastTranscriptAt>c.lastAssistantAt)return"thinking";return"idle"};var Qc={accent:"#3b82f6",background:"#0f172a",errorAccent:"#ef4444",fontFamily:'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',foreground:"#f8fafc",radius:16},Jc={callEnded:"Call ended",connecting:"Connecting…",endCall:"End call",idle:"Idle",listening:"Listening",mute:"Mute",speaking:"Speaking",startCall:"Start call",thinking:"Thinking",unmute:"Unmute"},qc=(c,n)=>{switch(c){case"listening":return n.listening;case"speaking":return n.speaking;case"thinking":return n.thinking;case"idle":return n.idle}},u=(c)=>{let n={...Qc,...c.theme},o={...Jc,...c.labels},g=c.state.assistantAudio.at(-1)?.receivedAt,l=c.state.turns.at(-1)?.committedAt,i=v({hasActivePartial:c.state.partial.length>0,isConnected:c.state.isConnected,isPlaying:!1,isRecording:c.state.isRecording,lastAssistantAt:g,lastTranscriptAt:l}),C=!c.state.isConnected&&c.state.status!=="idle"&&!c.state.error,V=c.state.error?"Error":C?o.connecting:c.state.status==="completed"?o.callEnded:qc(i,o);return{agentState:i,classes:{container:`absolute-voice-widget absolute-voice-widget--${i}`,dot:`absolute-voice-widget__dot${c.state.error?" absolute-voice-widget__dot--error":""}`},controls:{canEnd:c.state.isConnected,canMute:c.state.isRecording,canStart:!c.state.isRecording&&c.state.status!=="completed"},errorMessage:c.state.error??void 0,labels:o,partial:c.state.partial||void 0,statusLabel:V,theme:n,title:c.title??"Voice"}},Zc=(c)=>typeof c==="number"?`${c}px`:c,m=(c)=>{let n=c.theme,o=`background:${n.background};border-radius:${Zc(n.radius)};color:${n.foreground};font-family:${n.fontFamily};min-width:240px;padding:20px 22px;`,g=`background:${c.errorMessage?n.errorAccent:c.agentState==="idle"?"rgba(148,163,184,0.6)":n.accent};border-radius:50%;height:10px;width:10px;`,l=[];if(c.controls.canStart)l.push(`<button type="button" data-action="start" style="background:${n.accent};border:none;border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${s(c.labels.startCall)}</button>`);if(c.controls.canMute)l.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${s(c.labels.mute)}</button>`);if(c.controls.canEnd)l.push(`<button type="button" data-action="end" style="background:${n.errorAccent};border:none;border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${s(c.labels.endCall)}</button>`);return`<div role="region" aria-live="polite" data-agent-state="${c.agentState}" class="${s(c.classes.container)}" style="${o}">
|
|
1
|
+
(()=>{var{defineProperty:H,getOwnPropertyNames:oc,getOwnPropertyDescriptor:lc}=Object,Ac=Object.prototype.hasOwnProperty;function ic(c){return this[c]}var Cc=(c)=>{var n=(Y??=new WeakMap).get(c),o;if(n)return n;if(n=H({},"__esModule",{value:!0}),c&&typeof c==="object"||typeof c==="function"){for(var g of oc(c))if(!Ac.call(n,g))H(n,g,{get:ic.bind(c,g),enumerable:!(o=lc(c,g))||o.enumerable})}return Y.set(c,n),n},Y;var Tc=(c)=>c;function yc(c,n){this[c]=Tc.bind(null,n)}var Vc=(c,n)=>{for(var o in n)H(c,o,{get:n[o],enumerable:!0,configurable:!0,set:yc.bind(n,o)})};var ec={};Vc(ec,{mount:()=>p,default:()=>Bc,VOICE_EMBED_VERSION:()=>cc});var Ic=(c)=>{if(typeof c!=="string")return c;return document.querySelector(c)},Sc=(c,n,o,g)=>{let l=n??c.getAttribute("hx-get")??"";if(!l)return"";let C=new URL(l,window.location.origin);if(g)C.searchParams.set(o,g);else C.searchParams.delete(o);return`${C.pathname}${C.search}${C.hash}`},Q=(c,n)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let o=Ic(n.element);if(!o)return()=>{};let g=n.eventName??"voice-refresh",l=n.sessionQueryParam??"sessionId",C=()=>{let V=window,I=Sc(o,n.route,l,c.sessionId);if(I)o.setAttribute("hx-get",I);V.htmx?.process?.(o),V.htmx?.trigger?.(o,g)},i=c.subscribe(C);return C(),()=>{i()}};var dc=(c)=>Math.max(-1,Math.min(1,c)),Rc=(c)=>{let n=new Int16Array(c.length);for(let o=0;o<c.length;o+=1){let g=dc(c[o]??0);n[o]=g<0?g*32768:g*32767}return new Uint8Array(n.buffer)},hc=(c)=>{let n=c instanceof Uint8Array?c:new Uint8Array(c);if(n.byteLength<2)return 0;let o=new Int16Array(n.buffer,n.byteOffset,Math.floor(n.byteLength/2));if(o.length===0)return 0;let g=0;for(let l of o){let C=l/32768;g+=C*C}return Math.min(1,Math.max(0,Math.sqrt(g/o.length)*5.5))},_c=(c,n,o)=>{if(n===o)return c;let g=n/o,l=Math.round(c.length/g),C=new Float32Array(l),i=0,V=0;while(i<C.length){let I=Math.round((i+1)*g),R=0,y=0;for(let d=V;d<I&&d<c.length;d+=1)R+=c[d]??0,y+=1;C[i]=y>0?R/y:0,i+=1,V=I}return C},J=(c)=>{let n=null,o=null,g=null,l=null;return{start:async()=>{if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let V=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!V)throw Error("Browser microphone capture requires AudioContext support.");l=await navigator.mediaDevices.getUserMedia({audio:{channelCount:c.channelCount??1}}),n=new V,o=n.createMediaStreamSource(l),g=n.createScriptProcessor(4096,1,1),g.onaudioprocess=(I)=>{let R=I.inputBuffer.getChannelData(0),y=_c(R,n?.sampleRate??48000,c.sampleRateHz??16000),d=Rc(y);c.onLevel?.(hc(d)),c.onAudio(d)},o.connect(g),g.connect(n.destination)},stop:()=>{g?.disconnect(),o?.disconnect(),l?.getTracks().forEach((V)=>V.stop()),n?.close(),c.onLevel?.(0),n=null,l=null,g=null,o=null}}};var G=(c)=>{if(typeof c==="string"&&c.trim())return c;if(c instanceof Error&&c.message.trim())return c.message;if(c&&typeof c==="object"){let n=c;for(let o of["message","reason","description"]){let g=n[o];if(typeof g==="string"&&g.trim())return g}if("error"in n)return G(n.error);if("cause"in n)return G(n.cause);try{return JSON.stringify(c)}catch{}}return"Unexpected error"},q=(c)=>{switch(c.type){case"audio":return{chunk:Uint8Array.from(atob(c.chunkBase64),(n)=>n.charCodeAt(0)),format:c.format,receivedAt:c.receivedAt,turnId:c.turnId,type:"audio"};case"assistant":return{text:c.text,turnId:c.turnId,type:"assistant"};case"assistant_delta":return{delta:c.delta,turnId:c.turnId,type:"assistant_delta"};case"complete":return{sessionId:c.sessionId,type:"complete"};case"connection":return{reconnect:c.reconnect,type:"connection"};case"call_lifecycle":return{event:c.event,sessionId:c.sessionId,type:"call_lifecycle"};case"error":return{message:G(c.message),type:"error"};case"final":return{transcript:c.transcript,type:"final"};case"partial":return{transcript:c.transcript,type:"partial"};case"replay":return{assistantTexts:c.assistantTexts,call:c.call,partial:c.partial,scenarioId:c.scenarioId,sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,status:c.status,turns:c.turns,type:"replay"};case"session":return{sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,scenarioId:c.scenarioId,status:c.status,type:"session"};case"turn":return{turn:c.turn,type:"turn"};default:return null}};var kc=Math.PI*2;var x=(c,n,o,g)=>{c.push({code:o,message:g,severity:n})};var sc=(c)=>c.length===0?void 0:c.reduce((n,o)=>n+o,0)/c.length,N=(c)=>c.length===0?void 0:Math.max(...c);var _=(c,n)=>{let o=c[n];return typeof o==="number"&&Number.isFinite(o)?o:void 0},$=(c,n)=>{let o=c[n];return typeof o==="boolean"?o:void 0},s=(c,n)=>{let o=c[n];return typeof o==="string"?o:void 0},X=(c)=>String(c.id??s(c,"ssrc")??_(c,"ssrc")??s(c,"trackIdentifier")??s(c,"mid")??"unknown"),Z=(c)=>c===void 0?void 0:c*1000;var wc=(c)=>{let n={};for(let[o,g]of Object.entries(c))if(g===null||typeof g==="boolean"||typeof g==="number"||typeof g==="string")n[o]=g;return n};var z=(c={})=>{let n=c.stats??[],o=[],g=n.filter((A)=>A.type==="inbound-rtp"&&s(A,"kind")!=="video"),l=n.filter((A)=>A.type==="outbound-rtp"&&s(A,"kind")!=="video"),C=n.filter((A)=>A.type==="candidate-pair"),i=n.filter((A)=>(A.type==="track"||A.type==="media-source")&&s(A,"kind")==="audio"),V=C.filter((A)=>$(A,"selected")===!0||$(A,"nominated")===!0||s(A,"state")==="succeeded").length,I=i.filter((A)=>s(A,"readyState")!=="ended"&&s(A,"trackState")!=="ended"&&$(A,"ended")!==!0).length,R=i.filter((A)=>s(A,"readyState")==="ended"||s(A,"trackState")==="ended"||$(A,"ended")===!0).length,y=g.reduce((A,h)=>A+(_(h,"packetsReceived")??0),0),d=l.reduce((A,h)=>A+(_(h,"packetsSent")??0),0),T=[...g,...l].reduce((A,h)=>A+Math.max(0,_(h,"packetsLost")??0),0),w=y+T,S=w===0?0:T/w,E=g.reduce((A,h)=>A+(_(h,"bytesReceived")??0),0),b=l.reduce((A,h)=>A+(_(h,"bytesSent")??0),0),U=N(C.map((A)=>Z(_(A,"currentRoundTripTime")??_(A,"roundTripTime"))).filter((A)=>A!==void 0)),M=N([...g,...l].map((A)=>Z(_(A,"jitter"))).filter((A)=>A!==void 0)),W=N(g.map((A)=>{let h=_(A,"jitterBufferDelay"),L=_(A,"jitterBufferEmittedCount");return h!==void 0&&L!==void 0&&L>0?h/L*1000:void 0}).filter((A)=>A!==void 0)),P=i.map((A)=>_(A,"audioLevel")).filter((A)=>A!==void 0);if(c.requireConnectedCandidatePair&&C.length>0&&V===0)x(o,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(c.requireLiveAudioTrack&&I===0)x(o,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(c.maxPacketLossRatio!==void 0&&S>c.maxPacketLossRatio)x(o,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(S)} above ${String(c.maxPacketLossRatio)}.`);if(c.maxRoundTripTimeMs!==void 0&&U!==void 0&&U>c.maxRoundTripTimeMs)x(o,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(U)}ms above ${String(c.maxRoundTripTimeMs)}ms.`);if(c.maxJitterMs!==void 0&&M!==void 0&&M>c.maxJitterMs)x(o,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(M)}ms above ${String(c.maxJitterMs)}ms.`);return{activeCandidatePairs:V,audioLevelAverage:sc(P),bytesReceived:E,bytesSent:b,checkedAt:Date.now(),endedAudioTracks:R,inboundPackets:y,issues:o,jitterBufferDelayMs:W,jitterMs:M,liveAudioTracks:I,outboundPackets:d,packetLossRatio:S,packetsLost:T,roundTripTimeMs:U,status:o.some((A)=>A.severity==="error")?"fail":o.length>0?"warn":"pass",totalStats:n.length}},e=async(c)=>{return[...(await c.peerConnection.getStats(c.selector??null)).values()].map(wc)};var B=(c={})=>{let n=c.stats??[],o=c.previousStats??[],g=[],l=new Map(o.map((T)=>[X(T),T])),i=n.filter((T)=>(T.type==="inbound-rtp"||T.type==="outbound-rtp")&&s(T,"kind")!=="video"&&s(T,"mediaType")!=="video").map((T)=>{let w=T.type==="outbound-rtp"?"outbound":"inbound",S=w==="outbound"?"packetsSent":"packetsReceived",E=w==="outbound"?"bytesSent":"bytesReceived",b=l.get(X(T)),U=_(T,S),M=b?_(b,S):void 0,W=_(T,E),P=b?_(b,E):void 0,A=T.timestamp!==void 0&&b?.timestamp!==void 0?T.timestamp-b.timestamp:void 0;return{bytesDelta:W!==void 0&&P!==void 0?W-P:void 0,currentPackets:U,direction:w,id:X(T),packetDelta:U!==void 0&&M!==void 0?U-M:void 0,previousPackets:M,timeDeltaMs:A}}),V=i.filter((T)=>T.direction==="inbound"),I=i.filter((T)=>T.direction==="outbound"),R=N(i.map((T)=>T.timeDeltaMs).filter((T)=>T!==void 0)),y=V.filter((T)=>c.maxInboundPacketStallMs!==void 0&&T.timeDeltaMs!==void 0&&T.timeDeltaMs>=c.maxInboundPacketStallMs&&T.packetDelta!==void 0&&T.packetDelta<=0).length,d=I.filter((T)=>c.maxOutboundPacketStallMs!==void 0&&T.timeDeltaMs!==void 0&&T.timeDeltaMs>=c.maxOutboundPacketStallMs&&T.packetDelta!==void 0&&T.packetDelta<=0).length;if(c.requireInboundAudio&&V.length===0)x(g,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(c.requireOutboundAudio&&I.length===0)x(g,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(c.maxGapMs!==void 0&&R!==void 0&&R>c.maxGapMs)x(g,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String(R)}ms above ${String(c.maxGapMs)}ms.`);if(y>0)x(g,"error","media.webrtc_inbound_stalled",`${String(y)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(d>0)x(g,"error","media.webrtc_outbound_stalled",`${String(d)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:V.length,issues:g,maxObservedGapMs:R,outboundAudioStreams:I.length,stalledInboundStreams:y,stalledOutboundStreams:d,status:g.some((T)=>T.severity==="error")?"fail":g.length>0?"warn":"pass",streams:i,totalStats:n.length}};var Lc="/api/voice/browser-media",bc=5000,Uc=async(c)=>c.peerConnection??await c.getPeerConnection?.()??null,Mc=async(c,n)=>{let o=n.fetch??globalThis.fetch;if(!o)return;await o(n.path??Lc,{body:JSON.stringify(c),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},K=(c)=>{let n=null,o=[],g=async()=>{let i=await Uc(c);if(!i)return;let V=await e({peerConnection:i}),I=z({...c,stats:V}),R=c.continuity===!1?void 0:B({...c.continuity,previousStats:o,stats:V}),y={at:Date.now(),continuity:R,report:I,scenarioId:c.getScenarioId?.()??null,sessionId:c.getSessionId?.()??null};return o=V,c.onReport?.(y),await Mc(y,c),y},l=()=>{g().catch((i)=>{c.onError?.(i)})},C=()=>{if(n)clearInterval(n),n=null};return{close:C,reportOnce:g,stop:C,start:()=>{if(n)return;l(),n=setInterval(l,c.intervalMs??bc)}}};var D=()=>{},xc=()=>D,Oc={callControl:D,close:D,endTurn:D,send:D,sendAudio:D,simulateDisconnect:D,subscribe:xc,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",start:()=>{}},Dc=()=>crypto.randomUUID(),Ec=(c,n,o)=>{let{hostname:g,port:l,protocol:C}=window.location,i=C==="https:"?"wss:":"ws:",V=l?`:${l}`:"",I=new URL(`${i}//${g}${V}${c}`);if(I.searchParams.set("sessionId",n),o)I.searchParams.set("scenarioId",o);return I.toString()},Wc=(c)=>{if(!c||typeof c!=="object"||!("type"in c))return!1;switch(c.type){case"audio":case"assistant":case"call_lifecycle":case"complete":case"connection":case"error":case"final":case"partial":case"pong":case"replay":case"session":case"turn":return!0;default:return!1}},Pc=(c)=>{if(typeof c.data!=="string")return null;try{let n=JSON.parse(c.data);return Wc(n)?n:null}catch{return null}},j=(c,n={})=>{if(typeof window>"u")return Oc;let o=new Set,g=n.reconnect!==!1,l=n.maxReconnectAttempts??10,C=n.pingInterval??30000,i={isConnected:!1,pendingMessages:[],scenarioId:n.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:n.sessionId??Dc(),ws:null},V=(A)=>{o.forEach((h)=>h(A))},I=()=>{if(i.pingInterval)clearInterval(i.pingInterval),i.pingInterval=null;if(i.reconnectTimeout)clearTimeout(i.reconnectTimeout),i.reconnectTimeout=null},R=()=>{if(i.ws?.readyState!==1)return;while(i.pendingMessages.length>0){let A=i.pendingMessages.shift();if(A!==void 0)i.ws.send(A)}},y=()=>{let A=Date.now()+500;i.reconnectAttempts+=1,V({reconnect:{attempts:i.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:l,nextAttemptAt:A,status:"reconnecting"},type:"connection"}),i.reconnectTimeout=setTimeout(()=>{if(i.reconnectAttempts>l){V({reconnect:{attempts:i.reconnectAttempts,maxAttempts:l,status:"exhausted"},type:"connection"});return}d()},500)},d=()=>{let A=new WebSocket(Ec(c,i.sessionId,i.scenarioId));A.binaryType="arraybuffer",A.onopen=()=>{let h=i.reconnectAttempts>0;if(i.isConnected=!0,R(),h)V({reconnect:{attempts:i.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:l,status:"resumed"},type:"connection"}),i.reconnectAttempts=0;o.forEach((L)=>L({scenarioId:i.scenarioId??void 0,sessionId:i.sessionId,status:"active",type:"session"})),i.pingInterval=setInterval(()=>{if(A.readyState===1)A.send(JSON.stringify({type:"ping"}))},C)},A.onmessage=(h)=>{let L=Pc(h);if(!L)return;if(L.type==="session")i.sessionId=L.sessionId,i.scenarioId=L.scenarioId??i.scenarioId;o.forEach((gc)=>gc(L))},A.onclose=(h)=>{if(i.isConnected=!1,I(),g&&h.code!==1000&&i.reconnectAttempts<l)y();else if(g&&h.code!==1000)V({reconnect:{attempts:i.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:l,status:"exhausted"},type:"connection"})},i.ws=A},T=(A)=>{if(i.ws?.readyState===1){i.ws.send(A);return}i.pendingMessages.push(A)},w=(A)=>{T(JSON.stringify(A))},S=(A={})=>{if(A.sessionId)i.sessionId=A.sessionId;if(A.scenarioId)i.scenarioId=A.scenarioId;w({scenarioId:i.scenarioId??void 0,sessionId:i.sessionId,type:"start"})},E=(A)=>{T(A)},b=()=>{w({type:"end_turn"})},U=(A)=>{w({...A,type:"call_control"})},M=()=>{if(I(),i.ws)i.ws.close(1000),i.ws=null;i.isConnected=!1,o.clear()},W=()=>{if(i.ws?.readyState===1)i.ws.close(4000,"absolutejs-voice-reconnect-proof")},P=(A)=>{return o.add(A),()=>{o.delete(A)}};return d(),{callControl:U,close:M,endTurn:b,send:w,sendAudio:E,simulateDisconnect:W,start:S,subscribe:P,getReadyState:()=>i.ws?.readyState??3,getScenarioId:()=>i.scenarioId??"",getSessionId:()=>i.sessionId}};var $c=()=>({attempts:0,maxAttempts:0,status:"idle"}),Nc=()=>({assistantAudio:[],assistantStreamingText:"",assistantTexts:[],call:null,error:null,isConnected:!1,partial:"",reconnect:$c(),scenarioId:null,sessionId:null,sessionMetadata:null,status:"idle",turns:[]}),t=()=>{let c=Nc(),n=new Set,o=()=>{n.forEach((l)=>l())};return{dispatch:(l)=>{switch(l.type){case"audio":c={...c,assistantAudio:[...c.assistantAudio,{chunk:l.chunk,format:l.format,receivedAt:l.receivedAt,turnId:l.turnId}]};break;case"assistant":c={...c,assistantStreamingText:"",assistantTexts:[...c.assistantTexts,l.text]};break;case"assistant_delta":c={...c,assistantStreamingText:`${c.assistantStreamingText}${l.delta}`};break;case"complete":c={...c,sessionId:l.sessionId,status:"completed"};break;case"call_lifecycle":c={...c,call:{...c.call,disposition:l.event.type==="end"?l.event.disposition:c.call?.disposition,endedAt:l.event.type==="end"?l.event.at:c.call?.endedAt,events:[...c.call?.events??[],l.event],lastEventAt:l.event.at,startedAt:c.call?.startedAt??l.event.at},sessionId:l.sessionId};break;case"connected":c={...c,isConnected:!0,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect};break;case"connection":c={...c,reconnect:l.reconnect};break;case"disconnected":c={...c,isConnected:!1};break;case"error":c={...c,error:l.message};break;case"final":c={...c,partial:l.transcript.text,turns:c.turns.map((C)=>C)};break;case"partial":c={...c,partial:l.transcript.text};break;case"replay":c={...c,assistantStreamingText:"",assistantTexts:[...l.assistantTexts],call:l.call??null,error:null,isConnected:l.status==="active",partial:l.partial,reconnect:c.reconnect.status==="reconnecting"?{...c.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:c.reconnect,scenarioId:l.scenarioId??c.scenarioId,sessionId:l.sessionId,sessionMetadata:l.sessionMetadata??c.sessionMetadata,status:l.status,turns:[...l.turns]};break;case"session":c={...c,error:null,scenarioId:l.scenarioId??c.scenarioId,isConnected:l.status==="active",sessionId:l.sessionId,sessionMetadata:l.sessionMetadata??c.sessionMetadata,status:l.status};break;case"turn":c={...c,partial:"",turns:[...c.turns,l.turn]};break}o()},getServerSnapshot:()=>c,getSnapshot:()=>c,subscribe:(l)=>{return n.add(l),()=>{n.delete(l)}}}};var f=(c,n={})=>{let o=j(c,n),g=t(),l=n.browserMedia&&typeof window<"u"?K({...n.browserMedia,getScenarioId:()=>n.browserMedia?n.browserMedia.getScenarioId?.()??o.getScenarioId():o.getScenarioId(),getSessionId:()=>n.browserMedia?n.browserMedia.getSessionId?.()??o.getSessionId():o.getSessionId()}):null,C=new Set,i=(y)=>Promise.resolve().then(()=>{if(!y?.sessionId&&!y?.scenarioId)return;o.start(y),l?.start()}),V=()=>{C.forEach((y)=>y())},I=()=>{if(!n.reconnectReportPath||typeof fetch>"u")return;let y=g.getSnapshot(),d=JSON.stringify({at:Date.now(),reconnect:y.reconnect,scenarioId:y.scenarioId,sessionId:o.getSessionId(),turnIds:y.turns.map((T)=>T.id)});fetch(n.reconnectReportPath,{body:d,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},R=o.subscribe((y)=>{let d=q(y);if(d){if(g.dispatch(d),y.type==="connection")I();V()}});return{start:i,get assistantAudio(){return g.getSnapshot().assistantAudio},get assistantTexts(){return g.getSnapshot().assistantTexts},get assistantStreamingText(){return g.getSnapshot().assistantStreamingText},get call(){return g.getSnapshot().call},callControl(y){o.callControl(y)},close(){R(),l?.close(),o.close(),g.dispatch({type:"disconnected"}),V()},endTurn(){o.endTurn()},get error(){return g.getSnapshot().error},getServerSnapshot(){return g.getServerSnapshot()},getSnapshot(){return g.getSnapshot()},get isConnected(){return g.getSnapshot().isConnected},get partial(){return g.getSnapshot().partial},get reconnect(){return g.getSnapshot().reconnect},get scenarioId(){return g.getSnapshot().scenarioId},sendAudio(y){o.sendAudio(y)},get sessionId(){return o.getSessionId()},get sessionMetadata(){return g.getSnapshot().sessionMetadata},simulateDisconnect(){o.simulateDisconnect()},get status(){return g.getSnapshot().status},subscribe(y){return C.add(y),()=>{C.delete(y)}},get turns(){return g.getSnapshot().turns}}};var k=(c)=>{if(!c||c.enabled===!1)return;return{enabled:!0,maxGain:c.maxGain??3,noiseGateAttenuation:c.noiseGateAttenuation??0.15,noiseGateThreshold:c.noiseGateThreshold??0.006,targetLevel:c.targetLevel??0.08}};var Hc={balanced:{qualityProfile:"general",silenceMs:1400,speechThreshold:0.012,transcriptStabilityMs:1000},fast:{qualityProfile:"general",silenceMs:700,speechThreshold:0.015,transcriptStabilityMs:450},"long-form":{qualityProfile:"general",silenceMs:2200,speechThreshold:0.01,transcriptStabilityMs:1500}},Gc={"accent-heavy":{silenceMs:1200,speechThreshold:0.01,transcriptStabilityMs:1200},general:{},"noisy-room":{silenceMs:2000,speechThreshold:0.02,transcriptStabilityMs:1600},"short-command":{silenceMs:500,speechThreshold:0.016,transcriptStabilityMs:420}};var F=(c)=>{let n=c?.profile??"fast",o=c?.qualityProfile??"general",g=Hc[n],l=Gc[o];return{profile:n,qualityProfile:o,silenceMs:c?.silenceMs??l.silenceMs??g.silenceMs,speechThreshold:c?.speechThreshold??l.speechThreshold??g.speechThreshold,transcriptStabilityMs:c?.transcriptStabilityMs??l.transcriptStabilityMs??g.transcriptStabilityMs}};var Xc={chat:{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"balanced",qualityProfile:"short-command"}},default:{capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"fast",qualityProfile:"general"}},dictation:{audioConditioning:{enabled:!0,maxGain:2.25,noiseGateAttenuation:0.05,noiseGateThreshold:0.003,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"guided-intake":{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"turn-scoped",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"noisy-room":{audioConditioning:{enabled:!0,maxGain:3,noiseGateAttenuation:0.12,noiseGateThreshold:0.006,targetLevel:0.085},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:2100,speechThreshold:0.02,transcriptStabilityMs:1650}},"pstn-balanced":{audioConditioning:{enabled:!0,maxGain:2.8,noiseGateAttenuation:0.07,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:660,speechThreshold:0.012,transcriptStabilityMs:300}},"pstn-fast":{audioConditioning:{enabled:!0,maxGain:2.75,noiseGateAttenuation:0.06,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:620,speechThreshold:0.012,transcriptStabilityMs:280}},reliability:{audioConditioning:{enabled:!0,maxGain:2.9,noiseGateAttenuation:0.08,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room"}}},r=(c="default")=>{let n=Xc[c];return{audioConditioning:k(n.audioConditioning),capture:{channelCount:n.capture?.channelCount??1,sampleRateHz:n.capture?.sampleRateHz??16000},connection:{...n.connection},name:c,sttLifecycle:n.sttLifecycle??"continuous",turnDetection:F(n.turnDetection)}};var Yc=(c)=>({assistantAudio:[...c.assistantAudio],assistantStreamingText:c.assistantStreamingText,assistantTexts:[...c.assistantTexts],call:c.call,error:c.error,isConnected:c.isConnected,isRecording:!1,partial:c.partial,reconnect:c.reconnect,recordingError:null,sessionId:c.sessionId,sessionMetadata:c.sessionMetadata,scenarioId:c.scenarioId,status:c.status,turns:[...c.turns]}),a=(c,n={})=>{let o=r(n.preset),g=f(c,{...o.connection,...n.connection}),l=null,C=Yc(g),i=new Set,V=()=>{for(let S of i)S()},I=()=>{if(C={...C,assistantAudio:[...g.assistantAudio],assistantStreamingText:g.assistantStreamingText,assistantTexts:[...g.assistantTexts],call:g.call,error:g.error,isConnected:g.isConnected,partial:g.partial,reconnect:g.reconnect,sessionId:g.sessionId,sessionMetadata:g.sessionMetadata,scenarioId:g.scenarioId,status:g.status,turns:[...g.turns]},n.autoStopOnComplete!==!1&&C.status==="completed"&&C.isRecording)l?.stop(),l=null,C={...C,isRecording:!1};V()},R=g.subscribe(I);I();let y=()=>{if(l)return l;return l=J({channelCount:n.capture?.channelCount??o.capture.channelCount,onLevel:n.capture?.onLevel,onAudio:(S)=>{if(n.capture?.onAudio){n.capture.onAudio(S,g.sendAudio);return}g.sendAudio(S)},sampleRateHz:n.capture?.sampleRateHz??o.capture.sampleRateHz}),l},d=()=>{l?.stop(),l=null,C={...C,isRecording:!1},V()},T=async()=>{if(C.isRecording)return;try{C={...C,recordingError:null},V(),await y().start(),C={...C,isRecording:!0},V()}catch(S){throw l=null,C={...C,isRecording:!1,recordingError:S instanceof Error?S.message:String(S)},V(),S}};return{close:()=>{R(),d(),g.close()},startRecording:T,stopRecording:d,get assistantAudio(){return C.assistantAudio},get assistantTexts(){return C.assistantTexts},get assistantStreamingText(){return C.assistantStreamingText},bindHTMX(S){return Q(g,S)},get call(){return C.call},callControl:(S)=>g.callControl(S),endTurn:()=>g.endTurn(),get error(){return C.error},getServerSnapshot:()=>C,getSnapshot:()=>C,get isConnected(){return C.isConnected},get isRecording(){return C.isRecording},get partial(){return C.partial},get reconnect(){return C.reconnect},get recordingError(){return C.recordingError},get scenarioId(){return C.scenarioId},sendAudio:(S)=>g.sendAudio(S),get sessionId(){return C.sessionId},get sessionMetadata(){return C.sessionMetadata},simulateDisconnect:()=>g.simulateDisconnect(),get status(){return C.status},subscribe:(S)=>{return i.add(S),()=>{i.delete(S)}},toggleRecording:async()=>{if(C.isRecording){d();return}await T()},get turns(){return C.turns}}};var O=(c)=>String(c).replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'");var v=(c)=>{if(!c.isConnected)return"idle";if(c.isPlaying)return"speaking";if(c.isRecording&&c.hasActivePartial)return"listening";if(c.isRecording)return"listening";if(c.lastTranscriptAt&&!c.lastAssistantAt)return"thinking";if(c.lastTranscriptAt&&c.lastAssistantAt&&c.lastTranscriptAt>c.lastAssistantAt)return"thinking";return"idle"};var Qc={accent:"#3b82f6",background:"#0f172a",errorAccent:"#ef4444",fontFamily:'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',foreground:"#f8fafc",radius:16},Jc={callEnded:"Call ended",connecting:"Connecting…",endCall:"End call",idle:"Idle",listening:"Listening",mute:"Mute",speaking:"Speaking",startCall:"Start call",thinking:"Thinking",unmute:"Unmute"},qc=(c,n)=>{switch(c){case"listening":return n.listening;case"speaking":return n.speaking;case"thinking":return n.thinking;case"idle":return n.idle}},u=(c)=>{let n={...Qc,...c.theme},o={...Jc,...c.labels},g=c.state.assistantAudio.at(-1)?.receivedAt,l=c.state.turns.at(-1)?.committedAt,C=v({hasActivePartial:c.state.partial.length>0,isConnected:c.state.isConnected,isPlaying:!1,isRecording:c.state.isRecording,lastAssistantAt:g,lastTranscriptAt:l}),i=!c.state.isConnected&&c.state.status!=="idle"&&!c.state.error,V=c.state.error?"Error":i?o.connecting:c.state.status==="completed"?o.callEnded:qc(C,o);return{agentState:C,classes:{container:`absolute-voice-widget absolute-voice-widget--${C}`,dot:`absolute-voice-widget__dot${c.state.error?" absolute-voice-widget__dot--error":""}`},controls:{canEnd:c.state.isConnected,canMute:c.state.isRecording,canStart:!c.state.isRecording&&c.state.status!=="completed"},errorMessage:c.state.error??void 0,labels:o,partial:c.state.partial||void 0,statusLabel:V,theme:n,title:c.title??"Voice"}},Zc=(c)=>typeof c==="number"?`${c}px`:c,m=(c)=>{let n=c.theme,o=`background:${n.background};border-radius:${Zc(n.radius)};color:${n.foreground};font-family:${n.fontFamily};min-width:240px;padding:20px 22px;`,g=`background:${c.errorMessage?n.errorAccent:c.agentState==="idle"?"rgba(148,163,184,0.6)":n.accent};border-radius:50%;height:10px;width:10px;`,l=[];if(c.controls.canStart)l.push(`<button type="button" data-action="start" style="background:${n.accent};border:none;border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${O(c.labels.startCall)}</button>`);if(c.controls.canMute)l.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${O(c.labels.mute)}</button>`);if(c.controls.canEnd)l.push(`<button type="button" data-action="end" style="background:${n.errorAccent};border:none;border-radius:12px;color:${n.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${O(c.labels.endCall)}</button>`);return`<div role="region" aria-live="polite" data-agent-state="${c.agentState}" class="${O(c.classes.container)}" style="${o}">
|
|
2
2
|
<div style="align-items:center;display:flex;gap:10px;margin-bottom:12px;">
|
|
3
|
-
<span aria-hidden="true" class="${
|
|
4
|
-
<strong style="font-size:15px;">${
|
|
5
|
-
<span style="font-size:13px;margin-left:auto;opacity:0.7;">${
|
|
3
|
+
<span aria-hidden="true" class="${O(c.classes.dot)}" style="${g}"></span>
|
|
4
|
+
<strong style="font-size:15px;">${O(c.title)}</strong>
|
|
5
|
+
<span style="font-size:13px;margin-left:auto;opacity:0.7;">${O(c.statusLabel)}</span>
|
|
6
6
|
</div>
|
|
7
|
-
${c.partial?`<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">“${
|
|
7
|
+
${c.partial?`<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">“${O(c.partial)}”</p>`:""}
|
|
8
8
|
<div style="display:flex;gap:10px;">${l.join("")}</div>
|
|
9
|
-
${c.errorMessage?`<p style="color:${n.errorAccent};font-size:12px;margin-top:12px;">${
|
|
10
|
-
</div>`};var zc=(c)=>{if(typeof c!=="string")return c;let n=document.querySelector(c);if(!n)throw Error(`AbsoluteVoice.mount: no element matches "${c}"`);return n},p=(c,n={})=>{let o=zc(c),g=a(n.path??"/voice",n.controllerOptions),l=null,
|
|
9
|
+
${c.errorMessage?`<p style="color:${n.errorAccent};font-size:12px;margin-top:12px;">${O(c.errorMessage)}</p>`:""}
|
|
10
|
+
</div>`};var zc=(c)=>{if(typeof c!=="string")return c;let n=document.querySelector(c);if(!n)throw Error(`AbsoluteVoice.mount: no element matches "${c}"`);return n},p=(c,n={})=>{let o=zc(c),g=a(n.path??"/voice",n.controllerOptions),l=null,C=null,i=()=>{let I=u({...n.labels!==void 0?{labels:n.labels}:{},state:{assistantAudio:g.assistantAudio,error:g.error,isConnected:g.isConnected,isRecording:g.isRecording,partial:g.partial,status:g.status,turns:g.turns},...n.theme!==void 0?{theme:n.theme}:{},...n.title!==void 0?{title:n.title}:{}});o.innerHTML=m(I);for(let R of o.querySelectorAll("button[data-action]")){let{action:y}=R.dataset;R.addEventListener("click",()=>{if(y==="start")g.startRecording();else if(y==="mute")g.stopRecording();else if(y==="end")g.close()})}if(g.error&&g.error!==l)l=g.error,n.onError?.(g.error);if(g.status!==C)C=g.status,n.onStatusChange?.(g.status)},V=g.subscribe(i);if(i(),n.autoStart)g.startRecording();return{controller:g,async end(){await g.close()},mute(){g.stopRecording()},async start(){await g.startRecording()},unmount(){V(),g.close(),o.innerHTML=""}}},cc="0.0.22-beta.516",nc={mount:p,version:cc};if(typeof globalThis<"u")globalThis.AbsoluteVoice=nc;var Bc=nc;})();
|
package/dist/index.js
CHANGED
|
@@ -5290,6 +5290,7 @@ var createVoiceSession = (options) => {
|
|
|
5290
5290
|
return;
|
|
5291
5291
|
streamed = true;
|
|
5292
5292
|
full += delta;
|
|
5293
|
+
send({ delta, turnId: turn.id, type: "assistant_delta" });
|
|
5293
5294
|
buffer += delta;
|
|
5294
5295
|
let boundary = nextSpeakableBoundary(buffer);
|
|
5295
5296
|
while (boundary !== -1) {
|
|
@@ -39142,6 +39143,14 @@ var voice = (config) => {
|
|
|
39142
39143
|
stt: config.stt,
|
|
39143
39144
|
sttFallback: sessionOptions.sttFallback,
|
|
39144
39145
|
sttLifecycle: sessionOptions.sttLifecycle,
|
|
39146
|
+
...config.semanticTurnDetector ? { semanticTurnDetector: config.semanticTurnDetector } : {},
|
|
39147
|
+
...config.bargeInMinPartialWords !== undefined ? { bargeInMinPartialWords: config.bargeInMinPartialWords } : {},
|
|
39148
|
+
...config.fillerPhrases ? { fillerPhrases: config.fillerPhrases } : {},
|
|
39149
|
+
...config.fillerDelayMs !== undefined ? { fillerDelayMs: config.fillerDelayMs } : {},
|
|
39150
|
+
...config.fillerFor ? { fillerFor: config.fillerFor } : {},
|
|
39151
|
+
...config.fillerForTimeoutMs !== undefined ? { fillerForTimeoutMs: config.fillerForTimeoutMs } : {},
|
|
39152
|
+
...config.defaultSilentTurnAck !== undefined ? { defaultSilentTurnAck: config.defaultSilentTurnAck } : {},
|
|
39153
|
+
...config.routeOnTurnTimeoutMs !== undefined ? { routeOnTurnTimeoutMs: config.routeOnTurnTimeoutMs } : {},
|
|
39145
39154
|
tts: config.tts,
|
|
39146
39155
|
turnDetection: sessionOptions.turnDetection
|
|
39147
39156
|
});
|
package/dist/react/index.js
CHANGED
|
@@ -11281,8 +11281,15 @@ var serverMessageToAction = (message) => {
|
|
|
11281
11281
|
case "assistant":
|
|
11282
11282
|
return {
|
|
11283
11283
|
text: message.text,
|
|
11284
|
+
turnId: message.turnId,
|
|
11284
11285
|
type: "assistant"
|
|
11285
11286
|
};
|
|
11287
|
+
case "assistant_delta":
|
|
11288
|
+
return {
|
|
11289
|
+
delta: message.delta,
|
|
11290
|
+
turnId: message.turnId,
|
|
11291
|
+
type: "assistant_delta"
|
|
11292
|
+
};
|
|
11286
11293
|
case "complete":
|
|
11287
11294
|
return {
|
|
11288
11295
|
sessionId: message.sessionId,
|
|
@@ -11701,6 +11708,7 @@ var createInitialReconnectState = () => ({
|
|
|
11701
11708
|
});
|
|
11702
11709
|
var createInitialState = () => ({
|
|
11703
11710
|
assistantAudio: [],
|
|
11711
|
+
assistantStreamingText: "",
|
|
11704
11712
|
assistantTexts: [],
|
|
11705
11713
|
call: null,
|
|
11706
11714
|
error: null,
|
|
@@ -11738,9 +11746,16 @@ var createVoiceStreamStore = () => {
|
|
|
11738
11746
|
case "assistant":
|
|
11739
11747
|
state = {
|
|
11740
11748
|
...state,
|
|
11749
|
+
assistantStreamingText: "",
|
|
11741
11750
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
11742
11751
|
};
|
|
11743
11752
|
break;
|
|
11753
|
+
case "assistant_delta":
|
|
11754
|
+
state = {
|
|
11755
|
+
...state,
|
|
11756
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
11757
|
+
};
|
|
11758
|
+
break;
|
|
11744
11759
|
case "complete":
|
|
11745
11760
|
state = {
|
|
11746
11761
|
...state,
|
|
@@ -11808,6 +11823,7 @@ var createVoiceStreamStore = () => {
|
|
|
11808
11823
|
case "replay":
|
|
11809
11824
|
state = {
|
|
11810
11825
|
...state,
|
|
11826
|
+
assistantStreamingText: "",
|
|
11811
11827
|
assistantTexts: [...action.assistantTexts],
|
|
11812
11828
|
call: action.call ?? null,
|
|
11813
11829
|
error: null,
|
|
@@ -11919,6 +11935,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
11919
11935
|
get assistantTexts() {
|
|
11920
11936
|
return store.getSnapshot().assistantTexts;
|
|
11921
11937
|
},
|
|
11938
|
+
get assistantStreamingText() {
|
|
11939
|
+
return store.getSnapshot().assistantStreamingText;
|
|
11940
|
+
},
|
|
11922
11941
|
get call() {
|
|
11923
11942
|
return store.getSnapshot().call;
|
|
11924
11943
|
},
|
|
@@ -12482,6 +12501,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
12482
12501
|
// src/client/controller.ts
|
|
12483
12502
|
var createInitialState2 = (stream) => ({
|
|
12484
12503
|
assistantAudio: [...stream.assistantAudio],
|
|
12504
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
12485
12505
|
assistantTexts: [...stream.assistantTexts],
|
|
12486
12506
|
call: stream.call,
|
|
12487
12507
|
error: stream.error,
|
|
@@ -12514,6 +12534,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
12514
12534
|
state = {
|
|
12515
12535
|
...state,
|
|
12516
12536
|
assistantAudio: [...stream.assistantAudio],
|
|
12537
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
12517
12538
|
assistantTexts: [...stream.assistantTexts],
|
|
12518
12539
|
call: stream.call,
|
|
12519
12540
|
error: stream.error,
|
|
@@ -12607,6 +12628,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
12607
12628
|
get assistantTexts() {
|
|
12608
12629
|
return state.assistantTexts;
|
|
12609
12630
|
},
|
|
12631
|
+
get assistantStreamingText() {
|
|
12632
|
+
return state.assistantStreamingText;
|
|
12633
|
+
},
|
|
12610
12634
|
bindHTMX(bindingOptions) {
|
|
12611
12635
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
12612
12636
|
},
|
|
@@ -18,6 +18,7 @@ export declare const useVoiceController: <TResult = unknown>(path: string, optio
|
|
|
18
18
|
partial: string;
|
|
19
19
|
turns: import("..").VoiceTurnRecord<TResult>[];
|
|
20
20
|
assistantTexts: string[];
|
|
21
|
+
assistantStreamingText: string;
|
|
21
22
|
assistantAudio: Array<{
|
|
22
23
|
chunk: Uint8Array;
|
|
23
24
|
format: import("..").AudioFormat;
|
|
@@ -14,6 +14,7 @@ export declare const useVoiceStream: <TResult = unknown>(path: string, options?:
|
|
|
14
14
|
partial: string;
|
|
15
15
|
turns: import("..").VoiceTurnRecord<TResult>[];
|
|
16
16
|
assistantTexts: string[];
|
|
17
|
+
assistantStreamingText: string;
|
|
17
18
|
assistantAudio: Array<{
|
|
18
19
|
chunk: Uint8Array;
|
|
19
20
|
format: import("..").AudioFormat;
|
package/dist/svelte/index.js
CHANGED
|
@@ -598,8 +598,15 @@ var serverMessageToAction = (message) => {
|
|
|
598
598
|
case "assistant":
|
|
599
599
|
return {
|
|
600
600
|
text: message.text,
|
|
601
|
+
turnId: message.turnId,
|
|
601
602
|
type: "assistant"
|
|
602
603
|
};
|
|
604
|
+
case "assistant_delta":
|
|
605
|
+
return {
|
|
606
|
+
delta: message.delta,
|
|
607
|
+
turnId: message.turnId,
|
|
608
|
+
type: "assistant_delta"
|
|
609
|
+
};
|
|
603
610
|
case "complete":
|
|
604
611
|
return {
|
|
605
612
|
sessionId: message.sessionId,
|
|
@@ -1018,6 +1025,7 @@ var createInitialReconnectState = () => ({
|
|
|
1018
1025
|
});
|
|
1019
1026
|
var createInitialState = () => ({
|
|
1020
1027
|
assistantAudio: [],
|
|
1028
|
+
assistantStreamingText: "",
|
|
1021
1029
|
assistantTexts: [],
|
|
1022
1030
|
call: null,
|
|
1023
1031
|
error: null,
|
|
@@ -1055,9 +1063,16 @@ var createVoiceStreamStore = () => {
|
|
|
1055
1063
|
case "assistant":
|
|
1056
1064
|
state = {
|
|
1057
1065
|
...state,
|
|
1066
|
+
assistantStreamingText: "",
|
|
1058
1067
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
1059
1068
|
};
|
|
1060
1069
|
break;
|
|
1070
|
+
case "assistant_delta":
|
|
1071
|
+
state = {
|
|
1072
|
+
...state,
|
|
1073
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
1074
|
+
};
|
|
1075
|
+
break;
|
|
1061
1076
|
case "complete":
|
|
1062
1077
|
state = {
|
|
1063
1078
|
...state,
|
|
@@ -1125,6 +1140,7 @@ var createVoiceStreamStore = () => {
|
|
|
1125
1140
|
case "replay":
|
|
1126
1141
|
state = {
|
|
1127
1142
|
...state,
|
|
1143
|
+
assistantStreamingText: "",
|
|
1128
1144
|
assistantTexts: [...action.assistantTexts],
|
|
1129
1145
|
call: action.call ?? null,
|
|
1130
1146
|
error: null,
|
|
@@ -1236,6 +1252,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
1236
1252
|
get assistantTexts() {
|
|
1237
1253
|
return store.getSnapshot().assistantTexts;
|
|
1238
1254
|
},
|
|
1255
|
+
get assistantStreamingText() {
|
|
1256
|
+
return store.getSnapshot().assistantStreamingText;
|
|
1257
|
+
},
|
|
1239
1258
|
get call() {
|
|
1240
1259
|
return store.getSnapshot().call;
|
|
1241
1260
|
},
|
|
@@ -1619,6 +1638,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
1619
1638
|
// src/client/controller.ts
|
|
1620
1639
|
var createInitialState2 = (stream) => ({
|
|
1621
1640
|
assistantAudio: [...stream.assistantAudio],
|
|
1641
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1622
1642
|
assistantTexts: [...stream.assistantTexts],
|
|
1623
1643
|
call: stream.call,
|
|
1624
1644
|
error: stream.error,
|
|
@@ -1651,6 +1671,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1651
1671
|
state = {
|
|
1652
1672
|
...state,
|
|
1653
1673
|
assistantAudio: [...stream.assistantAudio],
|
|
1674
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
1654
1675
|
assistantTexts: [...stream.assistantTexts],
|
|
1655
1676
|
call: stream.call,
|
|
1656
1677
|
error: stream.error,
|
|
@@ -1744,6 +1765,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1744
1765
|
get assistantTexts() {
|
|
1745
1766
|
return state.assistantTexts;
|
|
1746
1767
|
},
|
|
1768
|
+
get assistantStreamingText() {
|
|
1769
|
+
return state.assistantStreamingText;
|
|
1770
|
+
},
|
|
1747
1771
|
bindHTMX(bindingOptions) {
|
|
1748
1772
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
1749
1773
|
},
|
package/dist/testing/index.js
CHANGED
|
@@ -2107,8 +2107,15 @@ var serverMessageToAction = (message) => {
|
|
|
2107
2107
|
case "assistant":
|
|
2108
2108
|
return {
|
|
2109
2109
|
text: message.text,
|
|
2110
|
+
turnId: message.turnId,
|
|
2110
2111
|
type: "assistant"
|
|
2111
2112
|
};
|
|
2113
|
+
case "assistant_delta":
|
|
2114
|
+
return {
|
|
2115
|
+
delta: message.delta,
|
|
2116
|
+
turnId: message.turnId,
|
|
2117
|
+
type: "assistant_delta"
|
|
2118
|
+
};
|
|
2112
2119
|
case "complete":
|
|
2113
2120
|
return {
|
|
2114
2121
|
sessionId: message.sessionId,
|
|
@@ -2527,6 +2534,7 @@ var createInitialReconnectState = () => ({
|
|
|
2527
2534
|
});
|
|
2528
2535
|
var createInitialState2 = () => ({
|
|
2529
2536
|
assistantAudio: [],
|
|
2537
|
+
assistantStreamingText: "",
|
|
2530
2538
|
assistantTexts: [],
|
|
2531
2539
|
call: null,
|
|
2532
2540
|
error: null,
|
|
@@ -2564,9 +2572,16 @@ var createVoiceStreamStore = () => {
|
|
|
2564
2572
|
case "assistant":
|
|
2565
2573
|
state = {
|
|
2566
2574
|
...state,
|
|
2575
|
+
assistantStreamingText: "",
|
|
2567
2576
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
2568
2577
|
};
|
|
2569
2578
|
break;
|
|
2579
|
+
case "assistant_delta":
|
|
2580
|
+
state = {
|
|
2581
|
+
...state,
|
|
2582
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
2583
|
+
};
|
|
2584
|
+
break;
|
|
2570
2585
|
case "complete":
|
|
2571
2586
|
state = {
|
|
2572
2587
|
...state,
|
|
@@ -2634,6 +2649,7 @@ var createVoiceStreamStore = () => {
|
|
|
2634
2649
|
case "replay":
|
|
2635
2650
|
state = {
|
|
2636
2651
|
...state,
|
|
2652
|
+
assistantStreamingText: "",
|
|
2637
2653
|
assistantTexts: [...action.assistantTexts],
|
|
2638
2654
|
call: action.call ?? null,
|
|
2639
2655
|
error: null,
|
|
@@ -2745,6 +2761,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
2745
2761
|
get assistantTexts() {
|
|
2746
2762
|
return store.getSnapshot().assistantTexts;
|
|
2747
2763
|
},
|
|
2764
|
+
get assistantStreamingText() {
|
|
2765
|
+
return store.getSnapshot().assistantStreamingText;
|
|
2766
|
+
},
|
|
2748
2767
|
get call() {
|
|
2749
2768
|
return store.getSnapshot().call;
|
|
2750
2769
|
},
|
|
@@ -3128,6 +3147,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
3128
3147
|
// src/client/controller.ts
|
|
3129
3148
|
var createInitialState3 = (stream) => ({
|
|
3130
3149
|
assistantAudio: [...stream.assistantAudio],
|
|
3150
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
3131
3151
|
assistantTexts: [...stream.assistantTexts],
|
|
3132
3152
|
call: stream.call,
|
|
3133
3153
|
error: stream.error,
|
|
@@ -3160,6 +3180,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
3160
3180
|
state = {
|
|
3161
3181
|
...state,
|
|
3162
3182
|
assistantAudio: [...stream.assistantAudio],
|
|
3183
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
3163
3184
|
assistantTexts: [...stream.assistantTexts],
|
|
3164
3185
|
call: stream.call,
|
|
3165
3186
|
error: stream.error,
|
|
@@ -3253,6 +3274,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
3253
3274
|
get assistantTexts() {
|
|
3254
3275
|
return state.assistantTexts;
|
|
3255
3276
|
},
|
|
3277
|
+
get assistantStreamingText() {
|
|
3278
|
+
return state.assistantStreamingText;
|
|
3279
|
+
},
|
|
3256
3280
|
bindHTMX(bindingOptions) {
|
|
3257
3281
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
3258
3282
|
},
|
|
@@ -7161,6 +7185,7 @@ var createVoiceSession = (options) => {
|
|
|
7161
7185
|
return;
|
|
7162
7186
|
streamed = true;
|
|
7163
7187
|
full += delta;
|
|
7188
|
+
send({ delta, turnId: turn.id, type: "assistant_delta" });
|
|
7164
7189
|
buffer += delta;
|
|
7165
7190
|
let boundary = nextSpeakableBoundary(buffer);
|
|
7166
7191
|
while (boundary !== -1) {
|
package/dist/vue/index.js
CHANGED
|
@@ -10677,8 +10677,15 @@ var serverMessageToAction = (message) => {
|
|
|
10677
10677
|
case "assistant":
|
|
10678
10678
|
return {
|
|
10679
10679
|
text: message.text,
|
|
10680
|
+
turnId: message.turnId,
|
|
10680
10681
|
type: "assistant"
|
|
10681
10682
|
};
|
|
10683
|
+
case "assistant_delta":
|
|
10684
|
+
return {
|
|
10685
|
+
delta: message.delta,
|
|
10686
|
+
turnId: message.turnId,
|
|
10687
|
+
type: "assistant_delta"
|
|
10688
|
+
};
|
|
10682
10689
|
case "complete":
|
|
10683
10690
|
return {
|
|
10684
10691
|
sessionId: message.sessionId,
|
|
@@ -11097,6 +11104,7 @@ var createInitialReconnectState = () => ({
|
|
|
11097
11104
|
});
|
|
11098
11105
|
var createInitialState = () => ({
|
|
11099
11106
|
assistantAudio: [],
|
|
11107
|
+
assistantStreamingText: "",
|
|
11100
11108
|
assistantTexts: [],
|
|
11101
11109
|
call: null,
|
|
11102
11110
|
error: null,
|
|
@@ -11134,9 +11142,16 @@ var createVoiceStreamStore = () => {
|
|
|
11134
11142
|
case "assistant":
|
|
11135
11143
|
state = {
|
|
11136
11144
|
...state,
|
|
11145
|
+
assistantStreamingText: "",
|
|
11137
11146
|
assistantTexts: [...state.assistantTexts, action.text]
|
|
11138
11147
|
};
|
|
11139
11148
|
break;
|
|
11149
|
+
case "assistant_delta":
|
|
11150
|
+
state = {
|
|
11151
|
+
...state,
|
|
11152
|
+
assistantStreamingText: `${state.assistantStreamingText}${action.delta}`
|
|
11153
|
+
};
|
|
11154
|
+
break;
|
|
11140
11155
|
case "complete":
|
|
11141
11156
|
state = {
|
|
11142
11157
|
...state,
|
|
@@ -11204,6 +11219,7 @@ var createVoiceStreamStore = () => {
|
|
|
11204
11219
|
case "replay":
|
|
11205
11220
|
state = {
|
|
11206
11221
|
...state,
|
|
11222
|
+
assistantStreamingText: "",
|
|
11207
11223
|
assistantTexts: [...action.assistantTexts],
|
|
11208
11224
|
call: action.call ?? null,
|
|
11209
11225
|
error: null,
|
|
@@ -11315,6 +11331,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
11315
11331
|
get assistantTexts() {
|
|
11316
11332
|
return store.getSnapshot().assistantTexts;
|
|
11317
11333
|
},
|
|
11334
|
+
get assistantStreamingText() {
|
|
11335
|
+
return store.getSnapshot().assistantStreamingText;
|
|
11336
|
+
},
|
|
11318
11337
|
get call() {
|
|
11319
11338
|
return store.getSnapshot().call;
|
|
11320
11339
|
},
|
|
@@ -11383,6 +11402,7 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
11383
11402
|
function useVoiceStream(path, options = {}) {
|
|
11384
11403
|
const stream = createVoiceStream(path, options);
|
|
11385
11404
|
const assistantAudio = shallowRef20([]);
|
|
11405
|
+
const assistantStreamingText = ref16("");
|
|
11386
11406
|
const assistantTexts = shallowRef20([]);
|
|
11387
11407
|
const call = shallowRef20(null);
|
|
11388
11408
|
const error = ref16(null);
|
|
@@ -11395,6 +11415,7 @@ function useVoiceStream(path, options = {}) {
|
|
|
11395
11415
|
const turns = shallowRef20([]);
|
|
11396
11416
|
const sync = () => {
|
|
11397
11417
|
assistantAudio.value = [...stream.assistantAudio];
|
|
11418
|
+
assistantStreamingText.value = stream.assistantStreamingText;
|
|
11398
11419
|
assistantTexts.value = [...stream.assistantTexts];
|
|
11399
11420
|
call.value = stream.call;
|
|
11400
11421
|
error.value = stream.error;
|
|
@@ -11415,6 +11436,7 @@ function useVoiceStream(path, options = {}) {
|
|
|
11415
11436
|
onUnmounted21(destroy);
|
|
11416
11437
|
return {
|
|
11417
11438
|
assistantAudio,
|
|
11439
|
+
assistantStreamingText,
|
|
11418
11440
|
assistantTexts,
|
|
11419
11441
|
call,
|
|
11420
11442
|
error,
|
|
@@ -11896,6 +11918,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
11896
11918
|
// src/client/controller.ts
|
|
11897
11919
|
var createInitialState2 = (stream) => ({
|
|
11898
11920
|
assistantAudio: [...stream.assistantAudio],
|
|
11921
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
11899
11922
|
assistantTexts: [...stream.assistantTexts],
|
|
11900
11923
|
call: stream.call,
|
|
11901
11924
|
error: stream.error,
|
|
@@ -11928,6 +11951,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
11928
11951
|
state = {
|
|
11929
11952
|
...state,
|
|
11930
11953
|
assistantAudio: [...stream.assistantAudio],
|
|
11954
|
+
assistantStreamingText: stream.assistantStreamingText,
|
|
11931
11955
|
assistantTexts: [...stream.assistantTexts],
|
|
11932
11956
|
call: stream.call,
|
|
11933
11957
|
error: stream.error,
|
|
@@ -12021,6 +12045,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
12021
12045
|
get assistantTexts() {
|
|
12022
12046
|
return state.assistantTexts;
|
|
12023
12047
|
},
|
|
12048
|
+
get assistantStreamingText() {
|
|
12049
|
+
return state.assistantStreamingText;
|
|
12050
|
+
},
|
|
12024
12051
|
bindHTMX(bindingOptions) {
|
|
12025
12052
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
12026
12053
|
},
|
|
@@ -12086,6 +12113,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
12086
12113
|
function useVoiceController(path, options = {}) {
|
|
12087
12114
|
const controller = createVoiceController(path, options);
|
|
12088
12115
|
const assistantAudio = shallowRef21([]);
|
|
12116
|
+
const assistantStreamingText = ref17("");
|
|
12089
12117
|
const assistantTexts = shallowRef21([]);
|
|
12090
12118
|
const error = ref17(null);
|
|
12091
12119
|
const isConnected = ref17(false);
|
|
@@ -12098,6 +12126,7 @@ function useVoiceController(path, options = {}) {
|
|
|
12098
12126
|
const turns = shallowRef21([]);
|
|
12099
12127
|
const sync = () => {
|
|
12100
12128
|
assistantAudio.value = [...controller.assistantAudio];
|
|
12129
|
+
assistantStreamingText.value = controller.assistantStreamingText;
|
|
12101
12130
|
assistantTexts.value = [...controller.assistantTexts];
|
|
12102
12131
|
error.value = controller.error;
|
|
12103
12132
|
isConnected.value = controller.isConnected;
|
|
@@ -12118,6 +12147,7 @@ function useVoiceController(path, options = {}) {
|
|
|
12118
12147
|
onUnmounted22(destroy);
|
|
12119
12148
|
return {
|
|
12120
12149
|
assistantAudio,
|
|
12150
|
+
assistantStreamingText,
|
|
12121
12151
|
assistantTexts,
|
|
12122
12152
|
bindHTMX: controller.bindHTMX,
|
|
12123
12153
|
error,
|
|
@@ -11,6 +11,7 @@ export declare function useVoiceController<TResult = unknown>(path: string, opti
|
|
|
11
11
|
receivedAt: number;
|
|
12
12
|
turnId?: string;
|
|
13
13
|
}[]>;
|
|
14
|
+
assistantStreamingText: import("vue").Ref<string, string>;
|
|
14
15
|
assistantTexts: import("vue").ShallowRef<string[], string[]>;
|
|
15
16
|
bindHTMX: (options: import("..").VoiceHTMXBindingOptions) => () => void;
|
|
16
17
|
error: import("vue").Ref<string | null, string | null>;
|
|
@@ -11,6 +11,7 @@ export declare function useVoiceStream<TResult = unknown>(path: string, options?
|
|
|
11
11
|
receivedAt: number;
|
|
12
12
|
turnId?: string;
|
|
13
13
|
}[]>;
|
|
14
|
+
assistantStreamingText: import("vue").Ref<string, string>;
|
|
14
15
|
assistantTexts: import("vue").ShallowRef<string[], string[]>;
|
|
15
16
|
call: import("vue").ShallowRef<import("..").VoiceCallLifecycleState | null, import("..").VoiceCallLifecycleState | null>;
|
|
16
17
|
error: import("vue").Ref<string | null, string | null>;
|