agent-voice 0.2.0 → 0.2.1
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.
|
@@ -43,6 +43,9 @@ function createRealtimeSession(options) {
|
|
|
43
43
|
const pcm16 = Buffer.from(event.delta, "base64");
|
|
44
44
|
options.onAudioDelta(pcm16);
|
|
45
45
|
});
|
|
46
|
+
rt.on("response.audio.done", () => {
|
|
47
|
+
options.onAudioDone?.();
|
|
48
|
+
});
|
|
46
49
|
rt.on("conversation.item.input_audio_transcription.completed", (event) => {
|
|
47
50
|
options.onTranscript(event.transcript);
|
|
48
51
|
});
|
package/dist/cli.js
CHANGED
|
@@ -22,8 +22,8 @@ async function withSuppressedNativeOutput() {
|
|
|
22
22
|
openSync("/dev/null", "w");
|
|
23
23
|
closeSync(2);
|
|
24
24
|
openSync("/dev/null", "w");
|
|
25
|
-
const { ask } = await import("./ask-
|
|
26
|
-
const { say } = await import("./say-
|
|
25
|
+
const { ask } = await import("./ask-A32EH5QX.js");
|
|
26
|
+
const { say } = await import("./say-ELJAIWUM.js");
|
|
27
27
|
function writeResult(text) {
|
|
28
28
|
writeSync(savedStdout, `${text}
|
|
29
29
|
`);
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,9 @@ function createRealtimeSession(options) {
|
|
|
44
44
|
const pcm16 = Buffer.from(event.delta, "base64");
|
|
45
45
|
options.onAudioDelta(pcm16);
|
|
46
46
|
});
|
|
47
|
+
rt.on("response.audio.done", () => {
|
|
48
|
+
options.onAudioDone?.();
|
|
49
|
+
});
|
|
47
50
|
rt.on("conversation.item.input_audio_transcription.completed", (event) => {
|
|
48
51
|
options.onTranscript(event.transcript);
|
|
49
52
|
});
|
|
@@ -367,9 +370,14 @@ async function say(message, options = {}) {
|
|
|
367
370
|
engine.start();
|
|
368
371
|
return new Promise((resolve, reject) => {
|
|
369
372
|
let cleaned = false;
|
|
373
|
+
let settled = false;
|
|
374
|
+
let responseDoneFallbackTimer = null;
|
|
375
|
+
let completionTailTimer = null;
|
|
370
376
|
function cleanup() {
|
|
371
377
|
if (cleaned) return;
|
|
372
378
|
cleaned = true;
|
|
379
|
+
if (responseDoneFallbackTimer) clearTimeout(responseDoneFallbackTimer);
|
|
380
|
+
if (completionTailTimer) clearTimeout(completionTailTimer);
|
|
373
381
|
try {
|
|
374
382
|
engine.stop();
|
|
375
383
|
engine.close();
|
|
@@ -377,6 +385,25 @@ async function say(message, options = {}) {
|
|
|
377
385
|
}
|
|
378
386
|
session.close();
|
|
379
387
|
}
|
|
388
|
+
function resolveOnce() {
|
|
389
|
+
if (settled) return;
|
|
390
|
+
settled = true;
|
|
391
|
+
cleanup();
|
|
392
|
+
resolve();
|
|
393
|
+
}
|
|
394
|
+
function rejectOnce(error) {
|
|
395
|
+
if (settled) return;
|
|
396
|
+
settled = true;
|
|
397
|
+
cleanup();
|
|
398
|
+
reject(error);
|
|
399
|
+
}
|
|
400
|
+
function scheduleTailResolve(delayMs) {
|
|
401
|
+
if (settled) return;
|
|
402
|
+
if (completionTailTimer) clearTimeout(completionTailTimer);
|
|
403
|
+
completionTailTimer = setTimeout(() => {
|
|
404
|
+
resolveOnce();
|
|
405
|
+
}, delayMs);
|
|
406
|
+
}
|
|
380
407
|
const session = createRealtimeSession({
|
|
381
408
|
voice,
|
|
382
409
|
mode: "say",
|
|
@@ -385,19 +412,23 @@ async function say(message, options = {}) {
|
|
|
385
412
|
onAudioDelta(pcm16) {
|
|
386
413
|
engine.play(pcm16);
|
|
387
414
|
},
|
|
415
|
+
onAudioDone() {
|
|
416
|
+
scheduleTailResolve(140);
|
|
417
|
+
},
|
|
388
418
|
onTranscript() {
|
|
389
419
|
},
|
|
390
420
|
onSpeechStarted() {
|
|
391
421
|
},
|
|
392
422
|
onInitialResponseDone() {
|
|
393
|
-
|
|
394
|
-
|
|
423
|
+
if (responseDoneFallbackTimer) clearTimeout(responseDoneFallbackTimer);
|
|
424
|
+
responseDoneFallbackTimer = setTimeout(() => {
|
|
425
|
+
scheduleTailResolve(220);
|
|
426
|
+
}, 700);
|
|
395
427
|
},
|
|
396
428
|
onDone() {
|
|
397
429
|
},
|
|
398
430
|
onError(error) {
|
|
399
|
-
|
|
400
|
-
reject(new Error(error));
|
|
431
|
+
rejectOnce(new Error(error));
|
|
401
432
|
}
|
|
402
433
|
});
|
|
403
434
|
session.connect().then(() => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
createRealtimeSession
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UYBFONQE.js";
|
|
5
5
|
import {
|
|
6
6
|
DEFAULT_VOICE,
|
|
7
7
|
SAMPLE_RATE
|
|
@@ -21,9 +21,14 @@ async function say(message, options = {}) {
|
|
|
21
21
|
engine.start();
|
|
22
22
|
return new Promise((resolve, reject) => {
|
|
23
23
|
let cleaned = false;
|
|
24
|
+
let settled = false;
|
|
25
|
+
let responseDoneFallbackTimer = null;
|
|
26
|
+
let completionTailTimer = null;
|
|
24
27
|
function cleanup() {
|
|
25
28
|
if (cleaned) return;
|
|
26
29
|
cleaned = true;
|
|
30
|
+
if (responseDoneFallbackTimer) clearTimeout(responseDoneFallbackTimer);
|
|
31
|
+
if (completionTailTimer) clearTimeout(completionTailTimer);
|
|
27
32
|
try {
|
|
28
33
|
engine.stop();
|
|
29
34
|
engine.close();
|
|
@@ -31,6 +36,25 @@ async function say(message, options = {}) {
|
|
|
31
36
|
}
|
|
32
37
|
session.close();
|
|
33
38
|
}
|
|
39
|
+
function resolveOnce() {
|
|
40
|
+
if (settled) return;
|
|
41
|
+
settled = true;
|
|
42
|
+
cleanup();
|
|
43
|
+
resolve();
|
|
44
|
+
}
|
|
45
|
+
function rejectOnce(error) {
|
|
46
|
+
if (settled) return;
|
|
47
|
+
settled = true;
|
|
48
|
+
cleanup();
|
|
49
|
+
reject(error);
|
|
50
|
+
}
|
|
51
|
+
function scheduleTailResolve(delayMs) {
|
|
52
|
+
if (settled) return;
|
|
53
|
+
if (completionTailTimer) clearTimeout(completionTailTimer);
|
|
54
|
+
completionTailTimer = setTimeout(() => {
|
|
55
|
+
resolveOnce();
|
|
56
|
+
}, delayMs);
|
|
57
|
+
}
|
|
34
58
|
const session = createRealtimeSession({
|
|
35
59
|
voice,
|
|
36
60
|
mode: "say",
|
|
@@ -39,19 +63,23 @@ async function say(message, options = {}) {
|
|
|
39
63
|
onAudioDelta(pcm16) {
|
|
40
64
|
engine.play(pcm16);
|
|
41
65
|
},
|
|
66
|
+
onAudioDone() {
|
|
67
|
+
scheduleTailResolve(140);
|
|
68
|
+
},
|
|
42
69
|
onTranscript() {
|
|
43
70
|
},
|
|
44
71
|
onSpeechStarted() {
|
|
45
72
|
},
|
|
46
73
|
onInitialResponseDone() {
|
|
47
|
-
|
|
48
|
-
|
|
74
|
+
if (responseDoneFallbackTimer) clearTimeout(responseDoneFallbackTimer);
|
|
75
|
+
responseDoneFallbackTimer = setTimeout(() => {
|
|
76
|
+
scheduleTailResolve(220);
|
|
77
|
+
}, 700);
|
|
49
78
|
},
|
|
50
79
|
onDone() {
|
|
51
80
|
},
|
|
52
81
|
onError(error) {
|
|
53
|
-
|
|
54
|
-
reject(new Error(error));
|
|
82
|
+
rejectOnce(new Error(error));
|
|
55
83
|
}
|
|
56
84
|
});
|
|
57
85
|
session.connect().then(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-voice",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "CLI for AI agents to interact with humans via voice",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"dist"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"agent-voice-audio": "^0.2.
|
|
21
|
+
"agent-voice-audio": "^0.2.1",
|
|
22
22
|
"@inquirer/prompts": "^8.2.0",
|
|
23
23
|
"commander": "^13.1.0",
|
|
24
24
|
"openai": "^4.96.0",
|