@absolutejs/voice 0.0.22-beta.26 → 0.0.22-beta.27

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.
@@ -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
- start: () => {},
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
- start,
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
  },
@@ -1040,6 +1076,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
1040
1076
  var createInitialState2 = (stream) => ({
1041
1077
  assistantAudio: [...stream.assistantAudio],
1042
1078
  assistantTexts: [...stream.assistantTexts],
1079
+ call: stream.call,
1043
1080
  error: stream.error,
1044
1081
  isConnected: stream.isConnected,
1045
1082
  isRecording: false,
@@ -1069,6 +1106,7 @@ var createVoiceController = (path, options = {}) => {
1069
1106
  ...state,
1070
1107
  assistantAudio: [...stream.assistantAudio],
1071
1108
  assistantTexts: [...stream.assistantTexts],
1109
+ call: stream.call,
1072
1110
  error: stream.error,
1073
1111
  isConnected: stream.isConnected,
1074
1112
  partial: stream.partial,
@@ -1146,6 +1184,7 @@ var createVoiceController = (path, options = {}) => {
1146
1184
  bindHTMX(bindingOptions) {
1147
1185
  return bindVoiceHTMX(stream, bindingOptions);
1148
1186
  },
1187
+ callControl: (message) => stream.callControl(message),
1149
1188
  close,
1150
1189
  endTurn: () => stream.endTurn(),
1151
1190
  get error() {
@@ -1198,6 +1237,9 @@ var createVoiceController = (path, options = {}) => {
1198
1237
  },
1199
1238
  get assistantAudio() {
1200
1239
  return state.assistantAudio;
1240
+ },
1241
+ get call() {
1242
+ return state.call;
1201
1243
  }
1202
1244
  };
1203
1245
  };
@@ -7,6 +7,7 @@ export declare const useVoiceController: <TResult = unknown>(path: string, optio
7
7
  startRecording: () => Promise<void>;
8
8
  stopRecording: () => void;
9
9
  toggleRecording: () => Promise<void>;
10
+ call: import("..").VoiceCallLifecycleState | null;
10
11
  sessionId: string | null;
11
12
  scenarioId: string | null;
12
13
  status: import("..").VoiceSessionStatus | "idle";
@@ -3,6 +3,7 @@ export declare const useVoiceStream: <TResult = unknown>(path: string, options?:
3
3
  close: () => void;
4
4
  endTurn: () => void;
5
5
  sendAudio: (audio: Uint8Array | ArrayBuffer) => void;
6
+ call: import("..").VoiceCallLifecycleState | null;
6
7
  sessionId: string | null;
7
8
  scenarioId: string | null;
8
9
  status: import("..").VoiceSessionStatus | "idle";
@@ -117,6 +117,12 @@ var serverMessageToAction = (message) => {
117
117
  sessionId: message.sessionId,
118
118
  type: "complete"
119
119
  };
120
+ case "call_lifecycle":
121
+ return {
122
+ event: message.event,
123
+ sessionId: message.sessionId,
124
+ type: "call_lifecycle"
125
+ };
120
126
  case "error":
121
127
  return {
122
128
  message: normalizeErrorMessage(message.message),
@@ -160,7 +166,7 @@ var DEFAULT_SCENARIO_QUERY_PARAM = "scenarioId";
160
166
  var noop = () => {};
161
167
  var noopUnsubscribe = () => noop;
162
168
  var NOOP_CONNECTION = {
163
- start: () => {},
169
+ callControl: noop,
164
170
  close: noop,
165
171
  endTurn: noop,
166
172
  getReadyState: () => WS_CLOSED,
@@ -168,6 +174,7 @@ var NOOP_CONNECTION = {
168
174
  getSessionId: () => "",
169
175
  send: noop,
170
176
  sendAudio: noop,
177
+ start: () => {},
171
178
  subscribe: noopUnsubscribe
172
179
  };
173
180
  var createSessionId = () => crypto.randomUUID();
@@ -189,6 +196,7 @@ var isVoiceServerMessage = (value) => {
189
196
  switch (value.type) {
190
197
  case "audio":
191
198
  case "assistant":
199
+ case "call_lifecycle":
192
200
  case "complete":
193
201
  case "error":
194
202
  case "final":
@@ -329,6 +337,12 @@ var createVoiceConnection = (path, options = {}) => {
329
337
  const endTurn = () => {
330
338
  send({ type: "end_turn" });
331
339
  };
340
+ const callControl = (message) => {
341
+ send({
342
+ ...message,
343
+ type: "call_control"
344
+ });
345
+ };
332
346
  const close = () => {
333
347
  clearTimers();
334
348
  if (state.ws) {
@@ -346,7 +360,7 @@ var createVoiceConnection = (path, options = {}) => {
346
360
  };
347
361
  connect();
348
362
  return {
349
- start,
363
+ callControl,
350
364
  close,
351
365
  endTurn,
352
366
  getReadyState: () => state.ws?.readyState ?? WS_CLOSED,
@@ -354,6 +368,7 @@ var createVoiceConnection = (path, options = {}) => {
354
368
  getSessionId: () => state.sessionId,
355
369
  send,
356
370
  sendAudio,
371
+ start,
357
372
  subscribe
358
373
  };
359
374
  };
@@ -362,6 +377,7 @@ var createVoiceConnection = (path, options = {}) => {
362
377
  var createInitialState = () => ({
363
378
  assistantAudio: [],
364
379
  assistantTexts: [],
380
+ call: null,
365
381
  error: null,
366
382
  isConnected: false,
367
383
  scenarioId: null,
@@ -405,6 +421,20 @@ var createVoiceStreamStore = () => {
405
421
  status: "completed"
406
422
  };
407
423
  break;
424
+ case "call_lifecycle":
425
+ state = {
426
+ ...state,
427
+ call: {
428
+ ...state.call,
429
+ disposition: action.event.type === "end" ? action.event.disposition : state.call?.disposition,
430
+ endedAt: action.event.type === "end" ? action.event.at : state.call?.endedAt,
431
+ events: [...state.call?.events ?? [], action.event],
432
+ lastEventAt: action.event.at,
433
+ startedAt: state.call?.startedAt ?? action.event.at
434
+ },
435
+ sessionId: action.sessionId
436
+ };
437
+ break;
408
438
  case "connected":
409
439
  state = {
410
440
  ...state,
@@ -491,6 +521,9 @@ var createVoiceStream = (path, options = {}) => {
491
521
  }
492
522
  });
493
523
  return {
524
+ callControl(message) {
525
+ connection.callControl(message);
526
+ },
494
527
  close() {
495
528
  unsubscribeConnection();
496
529
  connection.close();
@@ -534,6 +567,9 @@ var createVoiceStream = (path, options = {}) => {
534
567
  get assistantAudio() {
535
568
  return store.getSnapshot().assistantAudio;
536
569
  },
570
+ get call() {
571
+ return store.getSnapshot().call;
572
+ },
537
573
  sendAudio(audio) {
538
574
  connection.sendAudio(audio);
539
575
  },
@@ -1092,6 +1128,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
1092
1128
  var createInitialState2 = (stream) => ({
1093
1129
  assistantAudio: [...stream.assistantAudio],
1094
1130
  assistantTexts: [...stream.assistantTexts],
1131
+ call: stream.call,
1095
1132
  error: stream.error,
1096
1133
  isConnected: stream.isConnected,
1097
1134
  isRecording: false,
@@ -1121,6 +1158,7 @@ var createVoiceController = (path, options = {}) => {
1121
1158
  ...state,
1122
1159
  assistantAudio: [...stream.assistantAudio],
1123
1160
  assistantTexts: [...stream.assistantTexts],
1161
+ call: stream.call,
1124
1162
  error: stream.error,
1125
1163
  isConnected: stream.isConnected,
1126
1164
  partial: stream.partial,
@@ -1198,6 +1236,7 @@ var createVoiceController = (path, options = {}) => {
1198
1236
  bindHTMX(bindingOptions) {
1199
1237
  return bindVoiceHTMX(stream, bindingOptions);
1200
1238
  },
1239
+ callControl: (message) => stream.callControl(message),
1201
1240
  close,
1202
1241
  endTurn: () => stream.endTurn(),
1203
1242
  get error() {
@@ -1250,6 +1289,9 @@ var createVoiceController = (path, options = {}) => {
1250
1289
  },
1251
1290
  get assistantAudio() {
1252
1291
  return state.assistantAudio;
1292
+ },
1293
+ get call() {
1294
+ return state.call;
1253
1295
  }
1254
1296
  };
1255
1297
  };
@@ -2105,6 +2105,12 @@ var serverMessageToAction = (message) => {
2105
2105
  sessionId: message.sessionId,
2106
2106
  type: "complete"
2107
2107
  };
2108
+ case "call_lifecycle":
2109
+ return {
2110
+ event: message.event,
2111
+ sessionId: message.sessionId,
2112
+ type: "call_lifecycle"
2113
+ };
2108
2114
  case "error":
2109
2115
  return {
2110
2116
  message: normalizeErrorMessage(message.message),
@@ -2148,7 +2154,7 @@ var DEFAULT_SCENARIO_QUERY_PARAM = "scenarioId";
2148
2154
  var noop = () => {};
2149
2155
  var noopUnsubscribe = () => noop;
2150
2156
  var NOOP_CONNECTION = {
2151
- start: () => {},
2157
+ callControl: noop,
2152
2158
  close: noop,
2153
2159
  endTurn: noop,
2154
2160
  getReadyState: () => WS_CLOSED,
@@ -2156,6 +2162,7 @@ var NOOP_CONNECTION = {
2156
2162
  getSessionId: () => "",
2157
2163
  send: noop,
2158
2164
  sendAudio: noop,
2165
+ start: () => {},
2159
2166
  subscribe: noopUnsubscribe
2160
2167
  };
2161
2168
  var createSessionId = () => crypto.randomUUID();
@@ -2177,6 +2184,7 @@ var isVoiceServerMessage = (value) => {
2177
2184
  switch (value.type) {
2178
2185
  case "audio":
2179
2186
  case "assistant":
2187
+ case "call_lifecycle":
2180
2188
  case "complete":
2181
2189
  case "error":
2182
2190
  case "final":
@@ -2317,6 +2325,12 @@ var createVoiceConnection = (path, options = {}) => {
2317
2325
  const endTurn = () => {
2318
2326
  send({ type: "end_turn" });
2319
2327
  };
2328
+ const callControl = (message) => {
2329
+ send({
2330
+ ...message,
2331
+ type: "call_control"
2332
+ });
2333
+ };
2320
2334
  const close = () => {
2321
2335
  clearTimers();
2322
2336
  if (state.ws) {
@@ -2334,7 +2348,7 @@ var createVoiceConnection = (path, options = {}) => {
2334
2348
  };
2335
2349
  connect();
2336
2350
  return {
2337
- start,
2351
+ callControl,
2338
2352
  close,
2339
2353
  endTurn,
2340
2354
  getReadyState: () => state.ws?.readyState ?? WS_CLOSED,
@@ -2342,6 +2356,7 @@ var createVoiceConnection = (path, options = {}) => {
2342
2356
  getSessionId: () => state.sessionId,
2343
2357
  send,
2344
2358
  sendAudio,
2359
+ start,
2345
2360
  subscribe
2346
2361
  };
2347
2362
  };
@@ -2350,6 +2365,7 @@ var createVoiceConnection = (path, options = {}) => {
2350
2365
  var createInitialState2 = () => ({
2351
2366
  assistantAudio: [],
2352
2367
  assistantTexts: [],
2368
+ call: null,
2353
2369
  error: null,
2354
2370
  isConnected: false,
2355
2371
  scenarioId: null,
@@ -2393,6 +2409,20 @@ var createVoiceStreamStore = () => {
2393
2409
  status: "completed"
2394
2410
  };
2395
2411
  break;
2412
+ case "call_lifecycle":
2413
+ state = {
2414
+ ...state,
2415
+ call: {
2416
+ ...state.call,
2417
+ disposition: action.event.type === "end" ? action.event.disposition : state.call?.disposition,
2418
+ endedAt: action.event.type === "end" ? action.event.at : state.call?.endedAt,
2419
+ events: [...state.call?.events ?? [], action.event],
2420
+ lastEventAt: action.event.at,
2421
+ startedAt: state.call?.startedAt ?? action.event.at
2422
+ },
2423
+ sessionId: action.sessionId
2424
+ };
2425
+ break;
2396
2426
  case "connected":
2397
2427
  state = {
2398
2428
  ...state,
@@ -2479,6 +2509,9 @@ var createVoiceStream = (path, options = {}) => {
2479
2509
  }
2480
2510
  });
2481
2511
  return {
2512
+ callControl(message) {
2513
+ connection.callControl(message);
2514
+ },
2482
2515
  close() {
2483
2516
  unsubscribeConnection();
2484
2517
  connection.close();
@@ -2522,6 +2555,9 @@ var createVoiceStream = (path, options = {}) => {
2522
2555
  get assistantAudio() {
2523
2556
  return store.getSnapshot().assistantAudio;
2524
2557
  },
2558
+ get call() {
2559
+ return store.getSnapshot().call;
2560
+ },
2525
2561
  sendAudio(audio) {
2526
2562
  connection.sendAudio(audio);
2527
2563
  },
@@ -2854,6 +2890,7 @@ var resolveVoiceRuntimePreset = (name = "default") => {
2854
2890
  var createInitialState3 = (stream) => ({
2855
2891
  assistantAudio: [...stream.assistantAudio],
2856
2892
  assistantTexts: [...stream.assistantTexts],
2893
+ call: stream.call,
2857
2894
  error: stream.error,
2858
2895
  isConnected: stream.isConnected,
2859
2896
  isRecording: false,
@@ -2883,6 +2920,7 @@ var createVoiceController = (path, options = {}) => {
2883
2920
  ...state,
2884
2921
  assistantAudio: [...stream.assistantAudio],
2885
2922
  assistantTexts: [...stream.assistantTexts],
2923
+ call: stream.call,
2886
2924
  error: stream.error,
2887
2925
  isConnected: stream.isConnected,
2888
2926
  partial: stream.partial,
@@ -2960,6 +2998,7 @@ var createVoiceController = (path, options = {}) => {
2960
2998
  bindHTMX(bindingOptions) {
2961
2999
  return bindVoiceHTMX(stream, bindingOptions);
2962
3000
  },
3001
+ callControl: (message) => stream.callControl(message),
2963
3002
  close,
2964
3003
  endTurn: () => stream.endTurn(),
2965
3004
  get error() {
@@ -3012,6 +3051,9 @@ var createVoiceController = (path, options = {}) => {
3012
3051
  },
3013
3052
  get assistantAudio() {
3014
3053
  return state.assistantAudio;
3054
+ },
3055
+ get call() {
3056
+ return state.call;
3015
3057
  }
3016
3058
  };
3017
3059
  };
@@ -4609,6 +4651,7 @@ var pushCallLifecycleEvent = (session, input) => {
4609
4651
  }
4610
4652
  return lifecycle;
4611
4653
  };
4654
+ var getLatestCallLifecycleEvent = (session) => session.call?.events.at(-1);
4612
4655
  var createVoiceSession = (options) => {
4613
4656
  const logger = resolveLogger(options.logger);
4614
4657
  const reconnect = {
@@ -4709,6 +4752,17 @@ var createVoiceSession = (options) => {
4709
4752
  });
4710
4753
  }
4711
4754
  };
4755
+ const sendCallLifecycle = async (session) => {
4756
+ const event = getLatestCallLifecycleEvent(session);
4757
+ if (!event) {
4758
+ return;
4759
+ }
4760
+ await send({
4761
+ event,
4762
+ sessionId: options.id,
4763
+ type: "call_lifecycle"
4764
+ });
4765
+ };
4712
4766
  const readSession = async () => options.store.getOrCreate(options.id);
4713
4767
  const writeSession = async (mutate) => {
4714
4768
  const session = await options.store.getOrCreate(options.id);
@@ -4899,6 +4953,7 @@ var createVoiceSession = (options) => {
4899
4953
  await appendTrace({
4900
4954
  payload: {
4901
4955
  disposition,
4956
+ metadata: input.metadata,
4902
4957
  reason: input.reason,
4903
4958
  target: input.target,
4904
4959
  type: "end"
@@ -4906,6 +4961,7 @@ var createVoiceSession = (options) => {
4906
4961
  session,
4907
4962
  type: "call.lifecycle"
4908
4963
  });
4964
+ await sendCallLifecycle(session);
4909
4965
  await send({
4910
4966
  sessionId: options.id,
4911
4967
  type: "complete"
@@ -4985,6 +5041,7 @@ var createVoiceSession = (options) => {
4985
5041
  session,
4986
5042
  type: "call.lifecycle"
4987
5043
  });
5044
+ await sendCallLifecycle(session);
4988
5045
  await completeInternal(input.result, {
4989
5046
  disposition: "transferred",
4990
5047
  invokeOnComplete: false,
@@ -5010,6 +5067,7 @@ var createVoiceSession = (options) => {
5010
5067
  session,
5011
5068
  type: "call.lifecycle"
5012
5069
  });
5070
+ await sendCallLifecycle(session);
5013
5071
  await completeInternal(input.result, {
5014
5072
  disposition: "escalated",
5015
5073
  invokeOnComplete: false,
@@ -5032,6 +5090,7 @@ var createVoiceSession = (options) => {
5032
5090
  session,
5033
5091
  type: "call.lifecycle"
5034
5092
  });
5093
+ await sendCallLifecycle(session);
5035
5094
  await completeInternal(input?.result, {
5036
5095
  disposition: "no-answer",
5037
5096
  invokeOnComplete: false,
@@ -5053,6 +5112,7 @@ var createVoiceSession = (options) => {
5053
5112
  session,
5054
5113
  type: "call.lifecycle"
5055
5114
  });
5115
+ await sendCallLifecycle(session);
5056
5116
  await completeInternal(input?.result, {
5057
5117
  disposition: "voicemail",
5058
5118
  invokeOnComplete: false,
@@ -5839,6 +5899,7 @@ var createVoiceSession = (options) => {
5839
5899
  session,
5840
5900
  type: "call.lifecycle"
5841
5901
  });
5902
+ await sendCallLifecycle(session);
5842
5903
  }
5843
5904
  await send({
5844
5905
  sessionId: options.id,
package/dist/types.d.ts CHANGED
@@ -604,10 +604,17 @@ export type VoiceClientCloseMessage = {
604
604
  type: 'close';
605
605
  reason?: string;
606
606
  };
607
+ export type VoiceClientCallControlMessage = {
608
+ type: 'call_control';
609
+ action: 'complete' | 'escalate' | 'no-answer' | 'transfer' | 'voicemail';
610
+ metadata?: Record<string, unknown>;
611
+ reason?: string;
612
+ target?: string;
613
+ };
607
614
  export type VoiceClientPingMessage = {
608
615
  type: 'ping';
609
616
  };
610
- export type VoiceClientMessage = VoiceClientStartMessage | VoiceClientEndTurnMessage | VoiceClientCloseMessage | VoiceClientPingMessage;
617
+ export type VoiceClientMessage = VoiceClientStartMessage | VoiceClientEndTurnMessage | VoiceClientCloseMessage | VoiceClientCallControlMessage | VoiceClientPingMessage;
611
618
  export type VoiceServerSessionMessage = {
612
619
  type: 'session';
613
620
  sessionId: string;
@@ -642,6 +649,11 @@ export type VoiceServerCompleteMessage = {
642
649
  type: 'complete';
643
650
  sessionId: string;
644
651
  };
652
+ export type VoiceServerCallLifecycleMessage = {
653
+ type: 'call_lifecycle';
654
+ event: VoiceCallLifecycleEvent;
655
+ sessionId: string;
656
+ };
645
657
  export type VoiceServerErrorMessage = {
646
658
  type: 'error';
647
659
  message: string;
@@ -650,7 +662,7 @@ export type VoiceServerErrorMessage = {
650
662
  export type VoiceServerPongMessage = {
651
663
  type: 'pong';
652
664
  };
653
- export type VoiceServerMessage<TResult = unknown> = VoiceServerSessionMessage | VoiceServerPartialMessage | VoiceServerFinalMessage | VoiceServerTurnMessage<TResult> | VoiceServerAssistantMessage | VoiceServerAudioMessage | VoiceServerCompleteMessage | VoiceServerErrorMessage | VoiceServerPongMessage;
665
+ export type VoiceServerMessage<TResult = unknown> = VoiceServerSessionMessage | VoiceServerPartialMessage | VoiceServerFinalMessage | VoiceServerTurnMessage<TResult> | VoiceServerAssistantMessage | VoiceServerAudioMessage | VoiceServerCallLifecycleMessage | VoiceServerCompleteMessage | VoiceServerErrorMessage | VoiceServerPongMessage;
654
666
  export type VoiceConnectionOptions = {
655
667
  protocols?: string[];
656
668
  scenarioId?: string;
@@ -728,6 +740,7 @@ export type VoiceHTMXOptions<TSession extends VoiceSessionRecord = VoiceSessionR
728
740
  };
729
741
  export type VoiceHTMXConfig<TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = VoiceHTMXRenderer<TSession, TResult> | VoiceHTMXOptions<TSession, TResult>;
730
742
  export type VoiceStreamState<TResult = unknown> = {
743
+ call: VoiceCallLifecycleState | null;
731
744
  sessionId: string | null;
732
745
  scenarioId: string | null;
733
746
  status: VoiceSessionStatus | 'idle';
@@ -744,6 +757,8 @@ export type VoiceStreamState<TResult = unknown> = {
744
757
  isConnected: boolean;
745
758
  };
746
759
  export type VoiceStream<TResult = unknown> = {
760
+ call: VoiceCallLifecycleState | null;
761
+ callControl: (message: Omit<VoiceClientCallControlMessage, 'type'>) => void;
747
762
  close: () => void;
748
763
  start: (input?: {
749
764
  scenarioId?: string;
@@ -810,6 +825,8 @@ export type VoiceBargeInBinding = {
810
825
  };
811
826
  export type VoiceController<TResult = unknown> = {
812
827
  bindHTMX: (options: VoiceHTMXBindingOptions) => () => void;
828
+ call: VoiceCallLifecycleState | null;
829
+ callControl: (message: Omit<VoiceClientCallControlMessage, 'type'>) => void;
813
830
  close: () => void;
814
831
  endTurn: () => void;
815
832
  start: (input?: {
@@ -855,6 +872,10 @@ export type VoiceStoreAction<TResult = unknown> = {
855
872
  sessionId: string;
856
873
  scenarioId?: string;
857
874
  status: VoiceSessionStatus;
875
+ } | {
876
+ type: 'call_lifecycle';
877
+ event: VoiceCallLifecycleEvent;
878
+ sessionId: string;
858
879
  } | {
859
880
  type: 'partial';
860
881
  transcript: Transcript;