@absolutejs/voice 0.0.22-beta.652 → 0.0.22-beta.654
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 +79 -4
- package/dist/angular/voice-stream.service.d.ts +1 -1
- package/dist/client/actions.d.ts +12 -0
- package/dist/client/connection.d.ts +1 -1
- package/dist/client/htmxBootstrap.js +79 -4
- package/dist/client/index.js +79 -4
- package/dist/core/types.d.ts +21 -3
- package/dist/embed/index.js +79 -4
- package/dist/embed/voice-widget.js +8 -8
- package/dist/index.js +58 -40
- package/dist/react/index.js +79 -4
- package/dist/react/useVoiceController.d.ts +1 -1
- package/dist/react/useVoiceStream.d.ts +1 -1
- package/dist/svelte/index.js +79 -4
- package/dist/testing/index.js +79 -4
- package/dist/vue/index.js +79 -4
- package/dist/vue/useVoiceStream.d.ts +1 -1
- package/package.json +1 -1
package/dist/vue/index.js
CHANGED
|
@@ -10705,8 +10705,11 @@ var serverMessageToAction = (message) => {
|
|
|
10705
10705
|
case "error":
|
|
10706
10706
|
return {
|
|
10707
10707
|
message: normalizeErrorMessage(message.message),
|
|
10708
|
+
recoverable: message.recoverable,
|
|
10708
10709
|
type: "error"
|
|
10709
10710
|
};
|
|
10711
|
+
case "call_control_ack":
|
|
10712
|
+
return null;
|
|
10710
10713
|
case "final":
|
|
10711
10714
|
return {
|
|
10712
10715
|
transcript: message.transcript,
|
|
@@ -10834,14 +10837,17 @@ var WS_FORBIDDEN = 4403;
|
|
|
10834
10837
|
var DEFAULT_MAX_RECONNECT_ATTEMPTS = 15;
|
|
10835
10838
|
var DEFAULT_PING_INTERVAL = 30000;
|
|
10836
10839
|
var DEFAULT_RECONNECT_RESET_AFTER_MS = 30000;
|
|
10840
|
+
var DEFAULT_CALL_CONTROL_ACK_TIMEOUT_MS = 5000;
|
|
10841
|
+
var MAX_PENDING_CONTROL_MESSAGES = 100;
|
|
10837
10842
|
var RECONNECT_BASE_DELAY_MS = 500;
|
|
10838
10843
|
var DEFAULT_RECONNECT_MAX_DELAY_MS = 8000;
|
|
10839
10844
|
var computeVoiceReconnectDelayMs = (attempt, baseMs, maxDelayMs) => Math.min(maxDelayMs, baseMs * 2 ** (Math.max(1, attempt) - 1));
|
|
10840
10845
|
var DEFAULT_SCENARIO_QUERY_PARAM = "scenarioId";
|
|
10841
10846
|
var noop = () => {};
|
|
10847
|
+
var noopAsync = () => Promise.resolve();
|
|
10842
10848
|
var noopUnsubscribe = () => noop;
|
|
10843
10849
|
var NOOP_CONNECTION = {
|
|
10844
|
-
callControl:
|
|
10850
|
+
callControl: noopAsync,
|
|
10845
10851
|
close: noop,
|
|
10846
10852
|
disconnect: noop,
|
|
10847
10853
|
endTurn: noop,
|
|
@@ -10879,6 +10885,7 @@ var isVoiceServerMessage = (value) => {
|
|
|
10879
10885
|
case "audio":
|
|
10880
10886
|
case "assistant":
|
|
10881
10887
|
case "call_lifecycle":
|
|
10888
|
+
case "call_control_ack":
|
|
10882
10889
|
case "complete":
|
|
10883
10890
|
case "connection":
|
|
10884
10891
|
case "error":
|
|
@@ -10909,6 +10916,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
10909
10916
|
return NOOP_CONNECTION;
|
|
10910
10917
|
}
|
|
10911
10918
|
const listeners = new Set;
|
|
10919
|
+
const pendingCallControls = new Map;
|
|
10912
10920
|
const shouldReconnect = options.reconnect !== false;
|
|
10913
10921
|
const maxReconnectAttempts = options.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;
|
|
10914
10922
|
const reconnectMaxDelayMs = options.reconnectMaxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS;
|
|
@@ -10954,6 +10962,13 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
10954
10962
|
}
|
|
10955
10963
|
}
|
|
10956
10964
|
};
|
|
10965
|
+
const rejectPendingCallControls = (message) => {
|
|
10966
|
+
for (const pending of pendingCallControls.values()) {
|
|
10967
|
+
clearTimeout(pending.timeout);
|
|
10968
|
+
pending.reject(new Error(message));
|
|
10969
|
+
}
|
|
10970
|
+
pendingCallControls.clear();
|
|
10971
|
+
};
|
|
10957
10972
|
const scheduleReconnect = () => {
|
|
10958
10973
|
state.reconnectAttempts += 1;
|
|
10959
10974
|
const delayMs = computeReconnectDelayMs(state.reconnectAttempts);
|
|
@@ -10968,7 +10983,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
10968
10983
|
},
|
|
10969
10984
|
type: "connection"
|
|
10970
10985
|
});
|
|
10971
|
-
state.reconnectTimeout = setTimeout(() => {
|
|
10986
|
+
state.reconnectTimeout = setTimeout(async () => {
|
|
10972
10987
|
if (state.reconnectAttempts > maxReconnectAttempts) {
|
|
10973
10988
|
emitConnection({
|
|
10974
10989
|
reconnect: {
|
|
@@ -10980,6 +10995,28 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
10980
10995
|
});
|
|
10981
10996
|
return;
|
|
10982
10997
|
}
|
|
10998
|
+
try {
|
|
10999
|
+
await options.prepareReconnect?.({
|
|
11000
|
+
attempt: state.reconnectAttempts,
|
|
11001
|
+
path,
|
|
11002
|
+
scenarioId: state.scenarioId,
|
|
11003
|
+
sessionId: state.sessionId
|
|
11004
|
+
});
|
|
11005
|
+
} catch {
|
|
11006
|
+
if (state.reconnectAttempts < maxReconnectAttempts) {
|
|
11007
|
+
scheduleReconnect();
|
|
11008
|
+
} else {
|
|
11009
|
+
emitConnection({
|
|
11010
|
+
reconnect: {
|
|
11011
|
+
attempts: state.reconnectAttempts,
|
|
11012
|
+
maxAttempts: maxReconnectAttempts,
|
|
11013
|
+
status: "exhausted"
|
|
11014
|
+
},
|
|
11015
|
+
type: "connection"
|
|
11016
|
+
});
|
|
11017
|
+
}
|
|
11018
|
+
return;
|
|
11019
|
+
}
|
|
10983
11020
|
connect();
|
|
10984
11021
|
}, delayMs);
|
|
10985
11022
|
};
|
|
@@ -11034,6 +11071,18 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
11034
11071
|
state.sessionId = parsed.sessionId;
|
|
11035
11072
|
state.scenarioId = parsed.scenarioId ?? state.scenarioId;
|
|
11036
11073
|
}
|
|
11074
|
+
if (parsed.type === "call_control_ack") {
|
|
11075
|
+
const pending = pendingCallControls.get(parsed.requestId);
|
|
11076
|
+
if (pending) {
|
|
11077
|
+
clearTimeout(pending.timeout);
|
|
11078
|
+
pendingCallControls.delete(parsed.requestId);
|
|
11079
|
+
if (parsed.ok) {
|
|
11080
|
+
pending.resolve();
|
|
11081
|
+
} else {
|
|
11082
|
+
pending.reject(new Error(parsed.message ?? `${parsed.action} was not applied`));
|
|
11083
|
+
}
|
|
11084
|
+
}
|
|
11085
|
+
}
|
|
11037
11086
|
listeners.forEach((listener) => listener(parsed));
|
|
11038
11087
|
};
|
|
11039
11088
|
ws.onclose = (event) => {
|
|
@@ -11043,6 +11092,14 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
11043
11092
|
state.isConnected = false;
|
|
11044
11093
|
clearTimers();
|
|
11045
11094
|
const reconnectable = shouldReconnect && event.code !== WS_NORMAL_CLOSURE && event.code !== WS_UNAUTHORIZED && event.code !== WS_FORBIDDEN && state.reconnectAttempts < maxReconnectAttempts;
|
|
11095
|
+
const authorizationFailure = event.code === WS_UNAUTHORIZED || event.code === WS_FORBIDDEN;
|
|
11096
|
+
if (authorizationFailure) {
|
|
11097
|
+
listeners.forEach((listener) => listener({
|
|
11098
|
+
message: event.code === WS_UNAUTHORIZED ? "Voice authorization expired or was rejected." : "Voice authorization was forbidden.",
|
|
11099
|
+
recoverable: false,
|
|
11100
|
+
type: "error"
|
|
11101
|
+
}));
|
|
11102
|
+
}
|
|
11046
11103
|
if (reconnectable) {
|
|
11047
11104
|
scheduleReconnect();
|
|
11048
11105
|
} else if (shouldReconnect && event.code !== WS_NORMAL_CLOSURE) {
|
|
@@ -11064,6 +11121,12 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
11064
11121
|
state.ws.send(value);
|
|
11065
11122
|
return;
|
|
11066
11123
|
}
|
|
11124
|
+
if (typeof value !== "string") {
|
|
11125
|
+
return;
|
|
11126
|
+
}
|
|
11127
|
+
if (state.pendingMessages.length >= MAX_PENDING_CONTROL_MESSAGES) {
|
|
11128
|
+
state.pendingMessages.shift();
|
|
11129
|
+
}
|
|
11067
11130
|
state.pendingMessages.push(value);
|
|
11068
11131
|
};
|
|
11069
11132
|
const send = (message) => {
|
|
@@ -11089,13 +11152,23 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
11089
11152
|
send({ type: "end_turn" });
|
|
11090
11153
|
};
|
|
11091
11154
|
const callControl = (message) => {
|
|
11155
|
+
const requestId = crypto.randomUUID();
|
|
11156
|
+
const { promise, reject, resolve } = Promise.withResolvers();
|
|
11157
|
+
const timeout = setTimeout(() => {
|
|
11158
|
+
pendingCallControls.delete(requestId);
|
|
11159
|
+
reject(new Error(`${message.action} acknowledgement timed out`));
|
|
11160
|
+
}, DEFAULT_CALL_CONTROL_ACK_TIMEOUT_MS);
|
|
11161
|
+
pendingCallControls.set(requestId, { reject, resolve, timeout });
|
|
11092
11162
|
send({
|
|
11093
11163
|
...message,
|
|
11164
|
+
requestId,
|
|
11094
11165
|
type: "call_control"
|
|
11095
11166
|
});
|
|
11167
|
+
return promise;
|
|
11096
11168
|
};
|
|
11097
11169
|
const close = (reason = "client-close") => {
|
|
11098
11170
|
clearTimers();
|
|
11171
|
+
rejectPendingCallControls("Voice connection closed");
|
|
11099
11172
|
if (state.ws) {
|
|
11100
11173
|
const ws = state.ws;
|
|
11101
11174
|
state.ws = null;
|
|
@@ -11109,6 +11182,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
11109
11182
|
};
|
|
11110
11183
|
const disconnect = () => {
|
|
11111
11184
|
clearTimers();
|
|
11185
|
+
rejectPendingCallControls("Voice connection disconnected");
|
|
11112
11186
|
if (state.ws) {
|
|
11113
11187
|
const ws = state.ws;
|
|
11114
11188
|
state.ws = null;
|
|
@@ -11271,7 +11345,8 @@ var createVoiceStreamStore = () => {
|
|
|
11271
11345
|
case "error":
|
|
11272
11346
|
state = {
|
|
11273
11347
|
...state,
|
|
11274
|
-
error: action.message
|
|
11348
|
+
error: action.message,
|
|
11349
|
+
...action.recoverable === false ? { isConnected: false, status: "failed" } : {}
|
|
11275
11350
|
};
|
|
11276
11351
|
break;
|
|
11277
11352
|
case "final":
|
|
@@ -11411,7 +11486,7 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
11411
11486
|
return store.getSnapshot().call;
|
|
11412
11487
|
},
|
|
11413
11488
|
callControl(message) {
|
|
11414
|
-
connection.callControl(message);
|
|
11489
|
+
return connection.callControl(message);
|
|
11415
11490
|
},
|
|
11416
11491
|
close(reason) {
|
|
11417
11492
|
unsubscribeConnection();
|
|
@@ -22,7 +22,7 @@ export declare function useVoiceStream<TResult = unknown>(path: string, options?
|
|
|
22
22
|
sessionMetadata: import("vue").ShallowRef<Record<string, unknown> | null, Record<string, unknown> | null>;
|
|
23
23
|
status: import("vue").Ref<import("..").VoiceSessionStatus | "idle", import("..").VoiceSessionStatus | "idle">;
|
|
24
24
|
turns: import("vue").ShallowRef<VoiceTurnRecord<TResult>[], VoiceTurnRecord<TResult>[]>;
|
|
25
|
-
callControl: (message: Parameters<(message: Omit<import("..").VoiceClientCallControlMessage, "type">) => void
|
|
25
|
+
callControl: (message: Parameters<(message: Omit<import("..").VoiceClientCallControlMessage, "requestId" | "type">) => Promise<void>>[0]) => Promise<void>;
|
|
26
26
|
close: () => void;
|
|
27
27
|
endTurn: () => void;
|
|
28
28
|
sendAudio: (audio: Uint8Array | ArrayBuffer) => void;
|