@absolutejs/voice 0.0.22-beta.3 → 0.0.22-beta.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/index.d.ts +1 -0
- package/dist/angular/index.js +172 -2
- package/dist/angular/voice-provider-status.service.d.ts +12 -0
- package/dist/angular/voice-stream.service.d.ts +2 -0
- package/dist/assistant.d.ts +20 -0
- package/dist/assistantHealth.d.ts +81 -0
- package/dist/assistantMemory.d.ts +63 -0
- package/dist/client/actions.d.ts +22 -0
- package/dist/client/connection.d.ts +3 -0
- package/dist/client/htmxBootstrap.js +44 -2
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +125 -2
- package/dist/client/providerStatus.d.ts +19 -0
- package/dist/fileStore.d.ts +5 -2
- package/dist/handoff.d.ts +40 -0
- package/dist/handoffHealth.d.ts +94 -0
- package/dist/index.d.ts +18 -2
- package/dist/index.js +2379 -138
- package/dist/modelAdapters.d.ts +93 -0
- package/dist/opsWebhook.d.ts +126 -0
- package/dist/providerHealth.d.ts +78 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +148 -2
- package/dist/react/useVoiceController.d.ts +2 -0
- package/dist/react/useVoiceProviderStatus.d.ts +8 -0
- package/dist/react/useVoiceStream.d.ts +2 -0
- package/dist/sessionReplay.d.ts +175 -0
- package/dist/svelte/createVoiceProviderStatus.d.ts +8 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +127 -2
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +1216 -7
- package/dist/testing/providerSimulator.d.ts +44 -0
- package/dist/trace.d.ts +1 -1
- package/dist/types.d.ts +54 -2
- package/dist/vue/index.d.ts +1 -0
- package/dist/vue/index.js +161 -2
- package/dist/vue/useVoiceProviderStatus.d.ts +9 -0
- package/dist/vue/useVoiceStream.d.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { VoiceAgentModelInput, VoiceAgentModelOutput } from '../agent';
|
|
2
|
+
import type { VoiceSessionRecord } from '../types';
|
|
3
|
+
import type { VoiceProviderRouterEvent, VoiceProviderRouterHealthOptions } from '../modelAdapters';
|
|
4
|
+
export type VoiceProviderFailureSimulationMode = 'failure' | 'recovery';
|
|
5
|
+
export type VoiceProviderFailureSimulationContext<TProvider extends string = string> = {
|
|
6
|
+
query: {
|
|
7
|
+
provider: TProvider;
|
|
8
|
+
recoverProvider?: TProvider;
|
|
9
|
+
simulateFailureProvider?: TProvider;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export type VoiceProviderFailureSimulationResult<TProvider extends string = string, TResult = unknown> = {
|
|
13
|
+
mode: VoiceProviderFailureSimulationMode;
|
|
14
|
+
provider: TProvider;
|
|
15
|
+
replayHref?: string;
|
|
16
|
+
result: VoiceAgentModelOutput<TResult>;
|
|
17
|
+
sessionId: string;
|
|
18
|
+
status: 'simulated';
|
|
19
|
+
turnId: string;
|
|
20
|
+
};
|
|
21
|
+
type ProviderListResolver<TContext, TSession extends VoiceSessionRecord, TProvider extends string> = readonly TProvider[] | ((input: VoiceAgentModelInput<TContext, TSession>) => readonly TProvider[] | Promise<readonly TProvider[]>);
|
|
22
|
+
export type VoiceProviderFailureSimulatorOptions<TContext extends VoiceProviderFailureSimulationContext<TProvider>, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown, TProvider extends string = string> = {
|
|
23
|
+
allowProviders?: ProviderListResolver<TContext, TSession, TProvider>;
|
|
24
|
+
fallback?: readonly TProvider[] | ((provider: TProvider, input: VoiceAgentModelInput<TContext, TSession>) => readonly TProvider[] | Promise<readonly TProvider[]>);
|
|
25
|
+
isProviderError?: (error: unknown, provider: TProvider) => boolean;
|
|
26
|
+
isRateLimitError?: (error: unknown, provider: TProvider) => boolean;
|
|
27
|
+
onProviderEvent?: (event: VoiceProviderRouterEvent<TProvider>, input: VoiceAgentModelInput<TContext, TSession>) => Promise<void> | void;
|
|
28
|
+
providerHealth?: boolean | VoiceProviderRouterHealthOptions;
|
|
29
|
+
providerLabel?: (provider: TProvider) => string;
|
|
30
|
+
providers: readonly TProvider[];
|
|
31
|
+
replayHref?: false | string | ((input: {
|
|
32
|
+
provider: TProvider;
|
|
33
|
+
sessionId: string;
|
|
34
|
+
turnId: string;
|
|
35
|
+
}) => string);
|
|
36
|
+
response?: (input: {
|
|
37
|
+
mode: VoiceProviderFailureSimulationMode;
|
|
38
|
+
provider: TProvider;
|
|
39
|
+
} & VoiceAgentModelInput<TContext, TSession>) => VoiceAgentModelOutput<TResult> | Promise<VoiceAgentModelOutput<TResult>>;
|
|
40
|
+
};
|
|
41
|
+
export declare const createVoiceProviderFailureSimulator: <TProvider extends string, TResult = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TContext extends VoiceProviderFailureSimulationContext<TProvider> = VoiceProviderFailureSimulationContext<TProvider>>(options: VoiceProviderFailureSimulatorOptions<TContext, TSession, TResult, TProvider>) => {
|
|
42
|
+
run: (provider: TProvider, mode: VoiceProviderFailureSimulationMode) => Promise<VoiceProviderFailureSimulationResult<TProvider, TResult>>;
|
|
43
|
+
};
|
|
44
|
+
export {};
|
package/dist/trace.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type VoiceTraceEventType = 'assistant.guardrail' | 'assistant.run' | 'agent.handoff' | 'agent.model' | 'agent.result' | 'agent.tool' | 'call.lifecycle' | 'session.error' | 'turn.assistant' | 'turn.committed' | 'turn.cost' | 'turn.transcript';
|
|
1
|
+
export type VoiceTraceEventType = 'assistant.guardrail' | 'assistant.memory' | 'assistant.run' | 'agent.handoff' | 'agent.model' | 'agent.result' | 'agent.tool' | 'call.handoff' | 'call.lifecycle' | 'session.error' | 'turn.assistant' | 'turn.committed' | 'turn.cost' | 'turn.transcript';
|
|
2
2
|
export type VoiceTraceEvent<TPayload extends Record<string, unknown> = Record<string, unknown>> = {
|
|
3
3
|
at: number;
|
|
4
4
|
id?: string;
|
package/dist/types.d.ts
CHANGED
|
@@ -269,6 +269,35 @@ export type VoiceCallLifecycleState = {
|
|
|
269
269
|
lastEventAt: number;
|
|
270
270
|
startedAt: number;
|
|
271
271
|
};
|
|
272
|
+
export type VoiceHandoffAction = 'escalate' | 'no-answer' | 'transfer' | 'voicemail';
|
|
273
|
+
export type VoiceHandoffStatus = 'delivered' | 'failed' | 'skipped';
|
|
274
|
+
export type VoiceHandoffResult = {
|
|
275
|
+
deliveredAt?: number;
|
|
276
|
+
deliveredTo?: string;
|
|
277
|
+
error?: string;
|
|
278
|
+
metadata?: Record<string, unknown>;
|
|
279
|
+
status: VoiceHandoffStatus;
|
|
280
|
+
};
|
|
281
|
+
export type VoiceHandoffInput<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = {
|
|
282
|
+
action: VoiceHandoffAction;
|
|
283
|
+
api: VoiceSessionHandle<TContext, TSession, TResult>;
|
|
284
|
+
context: TContext;
|
|
285
|
+
metadata?: Record<string, unknown>;
|
|
286
|
+
reason?: string;
|
|
287
|
+
result?: TResult;
|
|
288
|
+
session: TSession;
|
|
289
|
+
target?: string;
|
|
290
|
+
};
|
|
291
|
+
export type VoiceHandoffAdapter<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = {
|
|
292
|
+
actions?: VoiceHandoffAction[];
|
|
293
|
+
handoff: (input: VoiceHandoffInput<TContext, TSession, TResult>) => Promise<VoiceHandoffResult> | VoiceHandoffResult;
|
|
294
|
+
id: string;
|
|
295
|
+
kind?: string;
|
|
296
|
+
};
|
|
297
|
+
export type VoiceHandoffConfig<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = {
|
|
298
|
+
adapters: VoiceHandoffAdapter<TContext, TSession, TResult>[];
|
|
299
|
+
failMode?: 'record' | 'throw';
|
|
300
|
+
};
|
|
272
301
|
export type VoiceSessionStore<TSession extends VoiceSessionRecord = VoiceSessionRecord> = SessionStore<TSession, VoiceSessionSummary>;
|
|
273
302
|
export type VoiceLogger = {
|
|
274
303
|
debug?: (message: string, meta?: Record<string, unknown>) => void;
|
|
@@ -567,6 +596,7 @@ export type VoicePluginConfig<TContext = unknown, TSession extends VoiceSessionR
|
|
|
567
596
|
audioConditioning?: VoiceAudioConditioningConfig;
|
|
568
597
|
logger?: VoiceLogger;
|
|
569
598
|
htmx?: boolean | VoiceHTMXConfig<TSession, NoInfer<TResult>>;
|
|
599
|
+
handoff?: VoiceHandoffConfig<TContext, TSession, TResult>;
|
|
570
600
|
ops?: VoiceRuntimeOpsConfig<TContext, TSession, TResult>;
|
|
571
601
|
trace?: VoiceTraceEventStore;
|
|
572
602
|
} & VoiceRouteConfig<TContext, TSession, TResult>;
|
|
@@ -588,6 +618,7 @@ export type CreateVoiceSessionOptions<TContext = unknown, TSession extends Voice
|
|
|
588
618
|
sttLifecycle: VoiceSTTLifecycle;
|
|
589
619
|
turnDetection: VoiceResolvedTurnDetectionConfig;
|
|
590
620
|
audioConditioning?: VoiceResolvedAudioConditioningConfig;
|
|
621
|
+
handoff?: VoiceHandoffConfig<TContext, TSession, TResult>;
|
|
591
622
|
route: VoiceNormalizedRouteConfig<TContext, TSession, TResult>;
|
|
592
623
|
logger?: VoiceLogger;
|
|
593
624
|
};
|
|
@@ -604,10 +635,17 @@ export type VoiceClientCloseMessage = {
|
|
|
604
635
|
type: 'close';
|
|
605
636
|
reason?: string;
|
|
606
637
|
};
|
|
638
|
+
export type VoiceClientCallControlMessage = {
|
|
639
|
+
type: 'call_control';
|
|
640
|
+
action: 'complete' | 'escalate' | 'no-answer' | 'transfer' | 'voicemail';
|
|
641
|
+
metadata?: Record<string, unknown>;
|
|
642
|
+
reason?: string;
|
|
643
|
+
target?: string;
|
|
644
|
+
};
|
|
607
645
|
export type VoiceClientPingMessage = {
|
|
608
646
|
type: 'ping';
|
|
609
647
|
};
|
|
610
|
-
export type VoiceClientMessage = VoiceClientStartMessage | VoiceClientEndTurnMessage | VoiceClientCloseMessage | VoiceClientPingMessage;
|
|
648
|
+
export type VoiceClientMessage = VoiceClientStartMessage | VoiceClientEndTurnMessage | VoiceClientCloseMessage | VoiceClientCallControlMessage | VoiceClientPingMessage;
|
|
611
649
|
export type VoiceServerSessionMessage = {
|
|
612
650
|
type: 'session';
|
|
613
651
|
sessionId: string;
|
|
@@ -642,6 +680,11 @@ export type VoiceServerCompleteMessage = {
|
|
|
642
680
|
type: 'complete';
|
|
643
681
|
sessionId: string;
|
|
644
682
|
};
|
|
683
|
+
export type VoiceServerCallLifecycleMessage = {
|
|
684
|
+
type: 'call_lifecycle';
|
|
685
|
+
event: VoiceCallLifecycleEvent;
|
|
686
|
+
sessionId: string;
|
|
687
|
+
};
|
|
645
688
|
export type VoiceServerErrorMessage = {
|
|
646
689
|
type: 'error';
|
|
647
690
|
message: string;
|
|
@@ -650,7 +693,7 @@ export type VoiceServerErrorMessage = {
|
|
|
650
693
|
export type VoiceServerPongMessage = {
|
|
651
694
|
type: 'pong';
|
|
652
695
|
};
|
|
653
|
-
export type VoiceServerMessage<TResult = unknown> = VoiceServerSessionMessage | VoiceServerPartialMessage | VoiceServerFinalMessage | VoiceServerTurnMessage<TResult> | VoiceServerAssistantMessage | VoiceServerAudioMessage | VoiceServerCompleteMessage | VoiceServerErrorMessage | VoiceServerPongMessage;
|
|
696
|
+
export type VoiceServerMessage<TResult = unknown> = VoiceServerSessionMessage | VoiceServerPartialMessage | VoiceServerFinalMessage | VoiceServerTurnMessage<TResult> | VoiceServerAssistantMessage | VoiceServerAudioMessage | VoiceServerCallLifecycleMessage | VoiceServerCompleteMessage | VoiceServerErrorMessage | VoiceServerPongMessage;
|
|
654
697
|
export type VoiceConnectionOptions = {
|
|
655
698
|
protocols?: string[];
|
|
656
699
|
scenarioId?: string;
|
|
@@ -728,6 +771,7 @@ export type VoiceHTMXOptions<TSession extends VoiceSessionRecord = VoiceSessionR
|
|
|
728
771
|
};
|
|
729
772
|
export type VoiceHTMXConfig<TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = VoiceHTMXRenderer<TSession, TResult> | VoiceHTMXOptions<TSession, TResult>;
|
|
730
773
|
export type VoiceStreamState<TResult = unknown> = {
|
|
774
|
+
call: VoiceCallLifecycleState | null;
|
|
731
775
|
sessionId: string | null;
|
|
732
776
|
scenarioId: string | null;
|
|
733
777
|
status: VoiceSessionStatus | 'idle';
|
|
@@ -744,6 +788,8 @@ export type VoiceStreamState<TResult = unknown> = {
|
|
|
744
788
|
isConnected: boolean;
|
|
745
789
|
};
|
|
746
790
|
export type VoiceStream<TResult = unknown> = {
|
|
791
|
+
call: VoiceCallLifecycleState | null;
|
|
792
|
+
callControl: (message: Omit<VoiceClientCallControlMessage, 'type'>) => void;
|
|
747
793
|
close: () => void;
|
|
748
794
|
start: (input?: {
|
|
749
795
|
scenarioId?: string;
|
|
@@ -810,6 +856,8 @@ export type VoiceBargeInBinding = {
|
|
|
810
856
|
};
|
|
811
857
|
export type VoiceController<TResult = unknown> = {
|
|
812
858
|
bindHTMX: (options: VoiceHTMXBindingOptions) => () => void;
|
|
859
|
+
call: VoiceCallLifecycleState | null;
|
|
860
|
+
callControl: (message: Omit<VoiceClientCallControlMessage, 'type'>) => void;
|
|
813
861
|
close: () => void;
|
|
814
862
|
endTurn: () => void;
|
|
815
863
|
start: (input?: {
|
|
@@ -855,6 +903,10 @@ export type VoiceStoreAction<TResult = unknown> = {
|
|
|
855
903
|
sessionId: string;
|
|
856
904
|
scenarioId?: string;
|
|
857
905
|
status: VoiceSessionStatus;
|
|
906
|
+
} | {
|
|
907
|
+
type: 'call_lifecycle';
|
|
908
|
+
event: VoiceCallLifecycleEvent;
|
|
909
|
+
sessionId: string;
|
|
858
910
|
} | {
|
|
859
911
|
type: 'partial';
|
|
860
912
|
transcript: Transcript;
|
package/dist/vue/index.d.ts
CHANGED
package/dist/vue/index.js
CHANGED
|
@@ -120,6 +120,12 @@ var serverMessageToAction = (message) => {
|
|
|
120
120
|
sessionId: message.sessionId,
|
|
121
121
|
type: "complete"
|
|
122
122
|
};
|
|
123
|
+
case "call_lifecycle":
|
|
124
|
+
return {
|
|
125
|
+
event: message.event,
|
|
126
|
+
sessionId: message.sessionId,
|
|
127
|
+
type: "call_lifecycle"
|
|
128
|
+
};
|
|
123
129
|
case "error":
|
|
124
130
|
return {
|
|
125
131
|
message: normalizeErrorMessage(message.message),
|
|
@@ -163,7 +169,7 @@ var DEFAULT_SCENARIO_QUERY_PARAM = "scenarioId";
|
|
|
163
169
|
var noop = () => {};
|
|
164
170
|
var noopUnsubscribe = () => noop;
|
|
165
171
|
var NOOP_CONNECTION = {
|
|
166
|
-
|
|
172
|
+
callControl: noop,
|
|
167
173
|
close: noop,
|
|
168
174
|
endTurn: noop,
|
|
169
175
|
getReadyState: () => WS_CLOSED,
|
|
@@ -171,6 +177,7 @@ var NOOP_CONNECTION = {
|
|
|
171
177
|
getSessionId: () => "",
|
|
172
178
|
send: noop,
|
|
173
179
|
sendAudio: noop,
|
|
180
|
+
start: () => {},
|
|
174
181
|
subscribe: noopUnsubscribe
|
|
175
182
|
};
|
|
176
183
|
var createSessionId = () => crypto.randomUUID();
|
|
@@ -192,6 +199,7 @@ var isVoiceServerMessage = (value) => {
|
|
|
192
199
|
switch (value.type) {
|
|
193
200
|
case "audio":
|
|
194
201
|
case "assistant":
|
|
202
|
+
case "call_lifecycle":
|
|
195
203
|
case "complete":
|
|
196
204
|
case "error":
|
|
197
205
|
case "final":
|
|
@@ -332,6 +340,12 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
332
340
|
const endTurn = () => {
|
|
333
341
|
send({ type: "end_turn" });
|
|
334
342
|
};
|
|
343
|
+
const callControl = (message) => {
|
|
344
|
+
send({
|
|
345
|
+
...message,
|
|
346
|
+
type: "call_control"
|
|
347
|
+
});
|
|
348
|
+
};
|
|
335
349
|
const close = () => {
|
|
336
350
|
clearTimers();
|
|
337
351
|
if (state.ws) {
|
|
@@ -349,7 +363,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
349
363
|
};
|
|
350
364
|
connect();
|
|
351
365
|
return {
|
|
352
|
-
|
|
366
|
+
callControl,
|
|
353
367
|
close,
|
|
354
368
|
endTurn,
|
|
355
369
|
getReadyState: () => state.ws?.readyState ?? WS_CLOSED,
|
|
@@ -357,6 +371,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
357
371
|
getSessionId: () => state.sessionId,
|
|
358
372
|
send,
|
|
359
373
|
sendAudio,
|
|
374
|
+
start,
|
|
360
375
|
subscribe
|
|
361
376
|
};
|
|
362
377
|
};
|
|
@@ -365,6 +380,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
365
380
|
var createInitialState = () => ({
|
|
366
381
|
assistantAudio: [],
|
|
367
382
|
assistantTexts: [],
|
|
383
|
+
call: null,
|
|
368
384
|
error: null,
|
|
369
385
|
isConnected: false,
|
|
370
386
|
scenarioId: null,
|
|
@@ -408,6 +424,20 @@ var createVoiceStreamStore = () => {
|
|
|
408
424
|
status: "completed"
|
|
409
425
|
};
|
|
410
426
|
break;
|
|
427
|
+
case "call_lifecycle":
|
|
428
|
+
state = {
|
|
429
|
+
...state,
|
|
430
|
+
call: {
|
|
431
|
+
...state.call,
|
|
432
|
+
disposition: action.event.type === "end" ? action.event.disposition : state.call?.disposition,
|
|
433
|
+
endedAt: action.event.type === "end" ? action.event.at : state.call?.endedAt,
|
|
434
|
+
events: [...state.call?.events ?? [], action.event],
|
|
435
|
+
lastEventAt: action.event.at,
|
|
436
|
+
startedAt: state.call?.startedAt ?? action.event.at
|
|
437
|
+
},
|
|
438
|
+
sessionId: action.sessionId
|
|
439
|
+
};
|
|
440
|
+
break;
|
|
411
441
|
case "connected":
|
|
412
442
|
state = {
|
|
413
443
|
...state,
|
|
@@ -494,6 +524,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
494
524
|
}
|
|
495
525
|
});
|
|
496
526
|
return {
|
|
527
|
+
callControl(message) {
|
|
528
|
+
connection.callControl(message);
|
|
529
|
+
},
|
|
497
530
|
close() {
|
|
498
531
|
unsubscribeConnection();
|
|
499
532
|
connection.close();
|
|
@@ -537,6 +570,9 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
537
570
|
get assistantAudio() {
|
|
538
571
|
return store.getSnapshot().assistantAudio;
|
|
539
572
|
},
|
|
573
|
+
get call() {
|
|
574
|
+
return store.getSnapshot().call;
|
|
575
|
+
},
|
|
540
576
|
sendAudio(audio) {
|
|
541
577
|
connection.sendAudio(audio);
|
|
542
578
|
},
|
|
@@ -554,6 +590,7 @@ var useVoiceStream = (path, options = {}) => {
|
|
|
554
590
|
const stream = createVoiceStream(path, options);
|
|
555
591
|
const assistantAudio = shallowRef([]);
|
|
556
592
|
const assistantTexts = shallowRef([]);
|
|
593
|
+
const call = shallowRef(null);
|
|
557
594
|
const error = ref(null);
|
|
558
595
|
const isConnected = ref(false);
|
|
559
596
|
const partial = ref("");
|
|
@@ -563,6 +600,7 @@ var useVoiceStream = (path, options = {}) => {
|
|
|
563
600
|
const sync = () => {
|
|
564
601
|
assistantAudio.value = [...stream.assistantAudio];
|
|
565
602
|
assistantTexts.value = [...stream.assistantTexts];
|
|
603
|
+
call.value = stream.call;
|
|
566
604
|
error.value = stream.error;
|
|
567
605
|
isConnected.value = stream.isConnected;
|
|
568
606
|
partial.value = stream.partial;
|
|
@@ -580,6 +618,8 @@ var useVoiceStream = (path, options = {}) => {
|
|
|
580
618
|
return {
|
|
581
619
|
assistantAudio,
|
|
582
620
|
assistantTexts,
|
|
621
|
+
call,
|
|
622
|
+
callControl: (message) => stream.callControl(message),
|
|
583
623
|
close: () => destroy(),
|
|
584
624
|
endTurn: () => stream.endTurn(),
|
|
585
625
|
error,
|
|
@@ -1056,6 +1096,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
1056
1096
|
var createInitialState2 = (stream) => ({
|
|
1057
1097
|
assistantAudio: [...stream.assistantAudio],
|
|
1058
1098
|
assistantTexts: [...stream.assistantTexts],
|
|
1099
|
+
call: stream.call,
|
|
1059
1100
|
error: stream.error,
|
|
1060
1101
|
isConnected: stream.isConnected,
|
|
1061
1102
|
isRecording: false,
|
|
@@ -1085,6 +1126,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1085
1126
|
...state,
|
|
1086
1127
|
assistantAudio: [...stream.assistantAudio],
|
|
1087
1128
|
assistantTexts: [...stream.assistantTexts],
|
|
1129
|
+
call: stream.call,
|
|
1088
1130
|
error: stream.error,
|
|
1089
1131
|
isConnected: stream.isConnected,
|
|
1090
1132
|
partial: stream.partial,
|
|
@@ -1162,6 +1204,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1162
1204
|
bindHTMX(bindingOptions) {
|
|
1163
1205
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
1164
1206
|
},
|
|
1207
|
+
callControl: (message) => stream.callControl(message),
|
|
1165
1208
|
close,
|
|
1166
1209
|
endTurn: () => stream.endTurn(),
|
|
1167
1210
|
get error() {
|
|
@@ -1214,6 +1257,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1214
1257
|
},
|
|
1215
1258
|
get assistantAudio() {
|
|
1216
1259
|
return state.assistantAudio;
|
|
1260
|
+
},
|
|
1261
|
+
get call() {
|
|
1262
|
+
return state.call;
|
|
1217
1263
|
}
|
|
1218
1264
|
};
|
|
1219
1265
|
};
|
|
@@ -1270,7 +1316,120 @@ var useVoiceController = (path, options = {}) => {
|
|
|
1270
1316
|
turns
|
|
1271
1317
|
};
|
|
1272
1318
|
};
|
|
1319
|
+
// src/vue/useVoiceProviderStatus.ts
|
|
1320
|
+
import { onUnmounted as onUnmounted3, ref as ref3, shallowRef as shallowRef3 } from "vue";
|
|
1321
|
+
|
|
1322
|
+
// src/client/providerStatus.ts
|
|
1323
|
+
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
1324
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1325
|
+
const response = await fetchImpl(path);
|
|
1326
|
+
if (!response.ok) {
|
|
1327
|
+
throw new Error(`Voice provider status failed: HTTP ${response.status}`);
|
|
1328
|
+
}
|
|
1329
|
+
return await response.json();
|
|
1330
|
+
};
|
|
1331
|
+
var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {}) => {
|
|
1332
|
+
const listeners = new Set;
|
|
1333
|
+
let closed = false;
|
|
1334
|
+
let timer;
|
|
1335
|
+
let snapshot = {
|
|
1336
|
+
error: null,
|
|
1337
|
+
isLoading: false,
|
|
1338
|
+
providers: []
|
|
1339
|
+
};
|
|
1340
|
+
const emit = () => {
|
|
1341
|
+
for (const listener of listeners) {
|
|
1342
|
+
listener();
|
|
1343
|
+
}
|
|
1344
|
+
};
|
|
1345
|
+
const refresh = async () => {
|
|
1346
|
+
if (closed) {
|
|
1347
|
+
return snapshot.providers;
|
|
1348
|
+
}
|
|
1349
|
+
snapshot = {
|
|
1350
|
+
...snapshot,
|
|
1351
|
+
error: null,
|
|
1352
|
+
isLoading: true
|
|
1353
|
+
};
|
|
1354
|
+
emit();
|
|
1355
|
+
try {
|
|
1356
|
+
const providers = await fetchVoiceProviderStatus(path, options);
|
|
1357
|
+
snapshot = {
|
|
1358
|
+
error: null,
|
|
1359
|
+
isLoading: false,
|
|
1360
|
+
providers,
|
|
1361
|
+
updatedAt: Date.now()
|
|
1362
|
+
};
|
|
1363
|
+
emit();
|
|
1364
|
+
return providers;
|
|
1365
|
+
} catch (error) {
|
|
1366
|
+
snapshot = {
|
|
1367
|
+
...snapshot,
|
|
1368
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1369
|
+
isLoading: false
|
|
1370
|
+
};
|
|
1371
|
+
emit();
|
|
1372
|
+
throw error;
|
|
1373
|
+
}
|
|
1374
|
+
};
|
|
1375
|
+
const close = () => {
|
|
1376
|
+
closed = true;
|
|
1377
|
+
if (timer) {
|
|
1378
|
+
clearInterval(timer);
|
|
1379
|
+
timer = undefined;
|
|
1380
|
+
}
|
|
1381
|
+
listeners.clear();
|
|
1382
|
+
};
|
|
1383
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
1384
|
+
timer = setInterval(() => {
|
|
1385
|
+
refresh().catch(() => {});
|
|
1386
|
+
}, options.intervalMs);
|
|
1387
|
+
}
|
|
1388
|
+
return {
|
|
1389
|
+
close,
|
|
1390
|
+
getServerSnapshot: () => snapshot,
|
|
1391
|
+
getSnapshot: () => snapshot,
|
|
1392
|
+
refresh,
|
|
1393
|
+
subscribe: (listener) => {
|
|
1394
|
+
listeners.add(listener);
|
|
1395
|
+
return () => {
|
|
1396
|
+
listeners.delete(listener);
|
|
1397
|
+
};
|
|
1398
|
+
}
|
|
1399
|
+
};
|
|
1400
|
+
};
|
|
1401
|
+
|
|
1402
|
+
// src/vue/useVoiceProviderStatus.ts
|
|
1403
|
+
var useVoiceProviderStatus = (path = "/api/provider-status", options = {}) => {
|
|
1404
|
+
const store = createVoiceProviderStatusStore(path, options);
|
|
1405
|
+
const error = ref3(null);
|
|
1406
|
+
const isLoading = ref3(false);
|
|
1407
|
+
const providers = shallowRef3([]);
|
|
1408
|
+
const updatedAt = ref3(undefined);
|
|
1409
|
+
const sync = () => {
|
|
1410
|
+
const snapshot = store.getSnapshot();
|
|
1411
|
+
error.value = snapshot.error;
|
|
1412
|
+
isLoading.value = snapshot.isLoading;
|
|
1413
|
+
providers.value = [...snapshot.providers];
|
|
1414
|
+
updatedAt.value = snapshot.updatedAt;
|
|
1415
|
+
};
|
|
1416
|
+
const unsubscribe = store.subscribe(sync);
|
|
1417
|
+
sync();
|
|
1418
|
+
store.refresh().catch(() => {});
|
|
1419
|
+
onUnmounted3(() => {
|
|
1420
|
+
unsubscribe();
|
|
1421
|
+
store.close();
|
|
1422
|
+
});
|
|
1423
|
+
return {
|
|
1424
|
+
error,
|
|
1425
|
+
isLoading,
|
|
1426
|
+
providers,
|
|
1427
|
+
refresh: store.refresh,
|
|
1428
|
+
updatedAt
|
|
1429
|
+
};
|
|
1430
|
+
};
|
|
1273
1431
|
export {
|
|
1274
1432
|
useVoiceStream,
|
|
1433
|
+
useVoiceProviderStatus,
|
|
1275
1434
|
useVoiceController
|
|
1276
1435
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type VoiceProviderStatusClientOptions } from '../client/providerStatus';
|
|
2
|
+
import type { VoiceProviderHealthSummary } from '../providerHealth';
|
|
3
|
+
export declare const useVoiceProviderStatus: <TProvider extends string = string>(path?: string, options?: VoiceProviderStatusClientOptions) => {
|
|
4
|
+
error: import("vue").Ref<string | null, string | null>;
|
|
5
|
+
isLoading: import("vue").Ref<boolean, boolean>;
|
|
6
|
+
providers: import("vue").ShallowRef<VoiceProviderHealthSummary<TProvider>[], VoiceProviderHealthSummary<TProvider>[]>;
|
|
7
|
+
refresh: () => Promise<VoiceProviderHealthSummary<TProvider>[]>;
|
|
8
|
+
updatedAt: import("vue").Ref<number | undefined, number | undefined>;
|
|
9
|
+
};
|
|
@@ -12,6 +12,8 @@ export declare const useVoiceStream: <TResult = unknown>(path: string, options?:
|
|
|
12
12
|
turnId?: string;
|
|
13
13
|
}[]>;
|
|
14
14
|
assistantTexts: import("vue").ShallowRef<string[], string[]>;
|
|
15
|
+
call: import("vue").ShallowRef<import("..").VoiceCallLifecycleState | null, import("..").VoiceCallLifecycleState | null>;
|
|
16
|
+
callControl: (message: Parameters<(message: Omit<import("..").VoiceClientCallControlMessage, "type">) => void>[0]) => void;
|
|
15
17
|
close: () => void;
|
|
16
18
|
endTurn: () => void;
|
|
17
19
|
error: import("vue").Ref<string | null, string | null>;
|