@absolutejs/voice 0.0.22-beta.631 → 0.0.22-beta.633
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/core/types.d.ts +18 -1
- package/dist/index.js +94 -1
- package/dist/manifest.d.ts +2 -0
- package/dist/manifest.js +8865 -0
- package/dist/manifest.json +385 -0
- package/dist/testing/index.js +85 -0
- package/package.json +17 -4
package/dist/core/types.d.ts
CHANGED
|
@@ -522,6 +522,17 @@ export type VoiceSessionHandle<TContext = unknown, TSession extends VoiceSession
|
|
|
522
522
|
transferMode?: "cold" | "warm";
|
|
523
523
|
}) => Promise<void>;
|
|
524
524
|
close: (reason?: string) => Promise<void>;
|
|
525
|
+
/**
|
|
526
|
+
* Caller-driven in-call pause: the session stays LIVE (socket, state,
|
|
527
|
+
* transcript) but every idle/silence watchdog is suspended and turn
|
|
528
|
+
* processing is skipped, so a paused caller is never nudged or hung up on.
|
|
529
|
+
* Past `pause.maxMs` (default 10 min) the session closes gracefully with
|
|
530
|
+
* reason "pause-timeout" — completed turns stay durably persisted, so the
|
|
531
|
+
* host's normal draft/resume path takes over.
|
|
532
|
+
*/
|
|
533
|
+
pause: () => Promise<void>;
|
|
534
|
+
/** Lift a caller-driven pause: watchdogs re-arm and turns process again. */
|
|
535
|
+
resume: () => Promise<void>;
|
|
525
536
|
snapshot: () => Promise<TSession>;
|
|
526
537
|
/**
|
|
527
538
|
* Mutate the live turn-detection config for this session — useful when a
|
|
@@ -1016,6 +1027,12 @@ export type CreateVoiceSessionOptions<TContext = unknown, TSession extends Voice
|
|
|
1016
1027
|
}) => string | Promise<string>);
|
|
1017
1028
|
maxReprompts?: number;
|
|
1018
1029
|
};
|
|
1030
|
+
/** Caller-driven in-call pause (VoiceSessionHandle.pause/resume). `maxMs`
|
|
1031
|
+
* bounds how long a session may sit paused before it closes gracefully
|
|
1032
|
+
* with reason "pause-timeout" (default 10 minutes). */
|
|
1033
|
+
pause?: {
|
|
1034
|
+
maxMs?: number;
|
|
1035
|
+
};
|
|
1019
1036
|
stt?: STTAdapter;
|
|
1020
1037
|
realtime?: RealtimeAdapter;
|
|
1021
1038
|
realtimeInputFormat?: AudioFormat;
|
|
@@ -1161,7 +1178,7 @@ export type VoiceClientCloseMessage = {
|
|
|
1161
1178
|
};
|
|
1162
1179
|
export type VoiceClientCallControlMessage = {
|
|
1163
1180
|
type: "call_control";
|
|
1164
|
-
action: "complete" | "escalate" | "no-answer" | "transfer" | "voicemail";
|
|
1181
|
+
action: "complete" | "escalate" | "no-answer" | "pause" | "resume" | "transfer" | "voicemail";
|
|
1165
1182
|
metadata?: Record<string, unknown>;
|
|
1166
1183
|
reason?: string;
|
|
1167
1184
|
target?: string;
|
package/dist/index.js
CHANGED
|
@@ -4368,6 +4368,9 @@ var createVoiceSession = (options) => {
|
|
|
4368
4368
|
if (callSilenceTimeoutMs === undefined || callSilenceFired) {
|
|
4369
4369
|
return;
|
|
4370
4370
|
}
|
|
4371
|
+
if (callerPaused) {
|
|
4372
|
+
return;
|
|
4373
|
+
}
|
|
4371
4374
|
clearCallSilenceWatchdog();
|
|
4372
4375
|
callSilenceWatchdog = setTimeout(fireCallSilenceTimeout, callSilenceTimeoutMs);
|
|
4373
4376
|
};
|
|
@@ -4413,6 +4416,9 @@ var createVoiceSession = (options) => {
|
|
|
4413
4416
|
if (stuckCloseAfterMs === undefined || stuckCloseFired) {
|
|
4414
4417
|
return;
|
|
4415
4418
|
}
|
|
4419
|
+
if (callerPaused) {
|
|
4420
|
+
return;
|
|
4421
|
+
}
|
|
4416
4422
|
clearStuckCloseWatchdog();
|
|
4417
4423
|
stuckCloseWatchdog = setTimeout(fireStuckClose, stuckCloseAfterMs);
|
|
4418
4424
|
};
|
|
@@ -4435,6 +4441,9 @@ var createVoiceSession = (options) => {
|
|
|
4435
4441
|
idleRepromptsUsed = 0;
|
|
4436
4442
|
}
|
|
4437
4443
|
clearIdleRepromptWatchdog();
|
|
4444
|
+
if (callerPaused) {
|
|
4445
|
+
return;
|
|
4446
|
+
}
|
|
4438
4447
|
if (idleRepromptsUsed >= idleRepromptMax) {
|
|
4439
4448
|
return;
|
|
4440
4449
|
}
|
|
@@ -4455,6 +4464,60 @@ var createVoiceSession = (options) => {
|
|
|
4455
4464
|
});
|
|
4456
4465
|
}, idleRepromptAfterMs);
|
|
4457
4466
|
};
|
|
4467
|
+
const PAUSE_MAX_MS_DEFAULT = 600000;
|
|
4468
|
+
const pauseMaxMs = options.pause?.maxMs && options.pause.maxMs > 0 ? options.pause.maxMs : PAUSE_MAX_MS_DEFAULT;
|
|
4469
|
+
let callerPaused = false;
|
|
4470
|
+
let pauseTimeout = null;
|
|
4471
|
+
const clearPauseTimeout = () => {
|
|
4472
|
+
if (pauseTimeout) {
|
|
4473
|
+
clearTimeout(pauseTimeout);
|
|
4474
|
+
pauseTimeout = null;
|
|
4475
|
+
}
|
|
4476
|
+
};
|
|
4477
|
+
const pauseInternal = async () => {
|
|
4478
|
+
if (callerPaused) {
|
|
4479
|
+
return;
|
|
4480
|
+
}
|
|
4481
|
+
const snapshot = await readSession();
|
|
4482
|
+
if (snapshot.status === "completed" || snapshot.status === "failed" || snapshot.call?.endedAt) {
|
|
4483
|
+
return;
|
|
4484
|
+
}
|
|
4485
|
+
callerPaused = true;
|
|
4486
|
+
clearCallSilenceWatchdog();
|
|
4487
|
+
clearStuckCloseWatchdog();
|
|
4488
|
+
clearIdleRepromptWatchdog();
|
|
4489
|
+
clearPauseTimeout();
|
|
4490
|
+
pauseTimeout = setTimeout(() => {
|
|
4491
|
+
pauseTimeout = null;
|
|
4492
|
+
api.close("pause-timeout");
|
|
4493
|
+
}, pauseMaxMs);
|
|
4494
|
+
await appendTrace({
|
|
4495
|
+
payload: {
|
|
4496
|
+
action: "call.paused",
|
|
4497
|
+
maxMs: pauseMaxMs
|
|
4498
|
+
},
|
|
4499
|
+
session: snapshot,
|
|
4500
|
+
type: "call.lifecycle"
|
|
4501
|
+
});
|
|
4502
|
+
};
|
|
4503
|
+
const resumeInternal = async () => {
|
|
4504
|
+
if (!callerPaused) {
|
|
4505
|
+
return;
|
|
4506
|
+
}
|
|
4507
|
+
callerPaused = false;
|
|
4508
|
+
clearPauseTimeout();
|
|
4509
|
+
kickCallSilenceWatchdog();
|
|
4510
|
+
kickStuckCloseWatchdog();
|
|
4511
|
+
kickIdleRepromptWatchdog(true);
|
|
4512
|
+
const snapshot = await readSession();
|
|
4513
|
+
await appendTrace({
|
|
4514
|
+
payload: {
|
|
4515
|
+
action: "call.resumed"
|
|
4516
|
+
},
|
|
4517
|
+
session: snapshot,
|
|
4518
|
+
type: "call.lifecycle"
|
|
4519
|
+
});
|
|
4520
|
+
};
|
|
4458
4521
|
const recordingConfig = options.recording;
|
|
4459
4522
|
const recordingChannels = new Set(recordingConfig?.channels ?? ["assistant", "user"]);
|
|
4460
4523
|
const recordingMaxBytes = recordingConfig?.maxBytesPerChannel ?? 50 * 1024 * 1024;
|
|
@@ -4962,6 +5025,7 @@ var createVoiceSession = (options) => {
|
|
|
4962
5025
|
clearCallSilenceWatchdog();
|
|
4963
5026
|
clearStuckCloseWatchdog();
|
|
4964
5027
|
clearIdleRepromptWatchdog();
|
|
5028
|
+
clearPauseTimeout();
|
|
4965
5029
|
clearAmdEvaluationTimer();
|
|
4966
5030
|
await closeTTSSession("failed");
|
|
4967
5031
|
await closeAdapter("failed");
|
|
@@ -5073,6 +5137,7 @@ var createVoiceSession = (options) => {
|
|
|
5073
5137
|
clearCallSilenceWatchdog();
|
|
5074
5138
|
clearStuckCloseWatchdog();
|
|
5075
5139
|
clearIdleRepromptWatchdog();
|
|
5140
|
+
clearPauseTimeout();
|
|
5076
5141
|
clearAmdEvaluationTimer();
|
|
5077
5142
|
await closeTTSSession("complete");
|
|
5078
5143
|
await closeAdapter("complete");
|
|
@@ -6033,6 +6098,19 @@ var createVoiceSession = (options) => {
|
|
|
6033
6098
|
}
|
|
6034
6099
|
kickStuckCloseWatchdog();
|
|
6035
6100
|
kickIdleRepromptWatchdog(true);
|
|
6101
|
+
if (callerPaused) {
|
|
6102
|
+
await appendTrace({
|
|
6103
|
+
payload: {
|
|
6104
|
+
action: "turn.skipped",
|
|
6105
|
+
reason: "caller-paused",
|
|
6106
|
+
status: "skipped"
|
|
6107
|
+
},
|
|
6108
|
+
session,
|
|
6109
|
+
turnId: turn.id,
|
|
6110
|
+
type: "call.lifecycle"
|
|
6111
|
+
});
|
|
6112
|
+
return;
|
|
6113
|
+
}
|
|
6036
6114
|
const liveOpsControl = await options.liveOps?.getControl(options.id);
|
|
6037
6115
|
if (liveOpsControl?.assistantPaused || liveOpsControl?.operatorTakeover) {
|
|
6038
6116
|
await appendTrace({
|
|
@@ -6883,6 +6961,7 @@ var createVoiceSession = (options) => {
|
|
|
6883
6961
|
clearCallSilenceWatchdog();
|
|
6884
6962
|
clearStuckCloseWatchdog();
|
|
6885
6963
|
clearIdleRepromptWatchdog();
|
|
6964
|
+
clearPauseTimeout();
|
|
6886
6965
|
clearAmdEvaluationTimer();
|
|
6887
6966
|
if (options.noiseSuppressor?.close) {
|
|
6888
6967
|
try {
|
|
@@ -6948,9 +7027,15 @@ var createVoiceSession = (options) => {
|
|
|
6948
7027
|
markVoicemail: async (input) => runSerial("api.markVoicemail", async () => {
|
|
6949
7028
|
await markVoicemailInternal(input);
|
|
6950
7029
|
}),
|
|
7030
|
+
pause: async () => runSerial("api.pause", async () => {
|
|
7031
|
+
await pauseInternal();
|
|
7032
|
+
}),
|
|
6951
7033
|
receiveAudio: async (audio) => runSerial("api.receiveAudio", async () => {
|
|
6952
7034
|
await receiveAudioInternal(audio);
|
|
6953
7035
|
}),
|
|
7036
|
+
resume: async () => runSerial("api.resume", async () => {
|
|
7037
|
+
await resumeInternal();
|
|
7038
|
+
}),
|
|
6954
7039
|
snapshot: async () => runSerial("api.snapshot", async () => readSession()),
|
|
6955
7040
|
transfer: async (input) => runSerial("api.transfer", async () => {
|
|
6956
7041
|
await transferInternal(input);
|
|
@@ -39724,7 +39809,7 @@ var isVoiceClientMessage = (value) => {
|
|
|
39724
39809
|
if (!("action" in value)) {
|
|
39725
39810
|
return false;
|
|
39726
39811
|
}
|
|
39727
|
-
if (value.action !== "complete" && value.action !== "escalate" && value.action !== "no-answer" && value.action !== "transfer" && value.action !== "voicemail") {
|
|
39812
|
+
if (value.action !== "complete" && value.action !== "escalate" && value.action !== "no-answer" && value.action !== "pause" && value.action !== "resume" && value.action !== "transfer" && value.action !== "voicemail") {
|
|
39728
39813
|
return false;
|
|
39729
39814
|
}
|
|
39730
39815
|
return (!("metadata" in value) || value.metadata === undefined || value.metadata !== null && typeof value.metadata === "object") && (!("reason" in value) || value.reason === undefined || typeof value.reason === "string") && (!("target" in value) || value.target === undefined || typeof value.target === "string");
|
|
@@ -40313,6 +40398,12 @@ var voice = (config) => {
|
|
|
40313
40398
|
if (message.action === "complete") {
|
|
40314
40399
|
await current.complete();
|
|
40315
40400
|
}
|
|
40401
|
+
if (message.action === "pause") {
|
|
40402
|
+
await current.pause();
|
|
40403
|
+
}
|
|
40404
|
+
if (message.action === "resume") {
|
|
40405
|
+
await current.resume();
|
|
40406
|
+
}
|
|
40316
40407
|
}
|
|
40317
40408
|
if (message.type === "start" && message.sessionId && message.sessionId !== sessionState.sessionId) {
|
|
40318
40409
|
const currentSession = runtime.activeSessions.get(sessionState.sessionId);
|
|
@@ -44373,7 +44464,9 @@ var createContractApi = (session) => ({
|
|
|
44373
44464
|
fail: async () => {},
|
|
44374
44465
|
markNoAnswer: async () => {},
|
|
44375
44466
|
markVoicemail: async () => {},
|
|
44467
|
+
pause: async () => {},
|
|
44376
44468
|
receiveAudio: async () => {},
|
|
44469
|
+
resume: async () => {},
|
|
44377
44470
|
setTurnDetection: async () => ({
|
|
44378
44471
|
silenceMs: 0,
|
|
44379
44472
|
speechThreshold: 0,
|