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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createRealtimeSession
4
- } from "./chunk-VV2VNOC4.js";
4
+ } from "./chunk-UYBFONQE.js";
5
5
  import {
6
6
  DEFAULT_VOICE,
7
7
  SAMPLE_RATE
@@ -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-GUSXGYSY.js");
26
- const { say } = await import("./say-W56HCNK4.js");
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
- cleanup();
394
- resolve();
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
- cleanup();
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-VV2VNOC4.js";
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
- cleanup();
48
- resolve();
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
- cleanup();
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.0",
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.0",
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",