@livekit/agents 0.4.3 → 0.4.5

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.
Files changed (79) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +26 -0
  3. package/dist/ipc/job_main.js +1 -0
  4. package/dist/ipc/job_main.js.map +1 -1
  5. package/dist/ipc/proc_job_executor.js.map +1 -1
  6. package/dist/job.d.ts.map +1 -1
  7. package/dist/job.js +1 -2
  8. package/dist/job.js.map +1 -1
  9. package/dist/llm/function_context.d.ts +10 -1
  10. package/dist/llm/function_context.d.ts.map +1 -1
  11. package/dist/llm/function_context.js +3 -2
  12. package/dist/llm/function_context.js.map +1 -1
  13. package/dist/pipeline/agent_output.js +3 -9
  14. package/dist/pipeline/agent_output.js.map +1 -1
  15. package/dist/pipeline/agent_playout.d.ts.map +1 -1
  16. package/dist/pipeline/agent_playout.js +2 -1
  17. package/dist/pipeline/agent_playout.js.map +1 -1
  18. package/dist/pipeline/index.d.ts +1 -1
  19. package/dist/pipeline/index.d.ts.map +1 -1
  20. package/dist/pipeline/index.js +1 -1
  21. package/dist/pipeline/index.js.map +1 -1
  22. package/dist/pipeline/pipeline_agent.d.ts +1 -1
  23. package/dist/pipeline/pipeline_agent.d.ts.map +1 -1
  24. package/dist/pipeline/pipeline_agent.js +12 -3
  25. package/dist/pipeline/pipeline_agent.js.map +1 -1
  26. package/dist/stt/index.d.ts +1 -0
  27. package/dist/stt/index.d.ts.map +1 -1
  28. package/dist/stt/index.js +1 -0
  29. package/dist/stt/index.js.map +1 -1
  30. package/dist/stt/stream_adapter.d.ts +15 -0
  31. package/dist/stt/stream_adapter.d.ts.map +1 -0
  32. package/dist/stt/stream_adapter.js +59 -0
  33. package/dist/stt/stream_adapter.js.map +1 -0
  34. package/dist/stt/stt.d.ts +4 -1
  35. package/dist/stt/stt.d.ts.map +1 -1
  36. package/dist/stt/stt.js.map +1 -1
  37. package/dist/tokenize/basic/hyphenator.d.ts.map +1 -1
  38. package/dist/tokenize/basic/hyphenator.js +2 -5
  39. package/dist/tokenize/basic/hyphenator.js.map +1 -1
  40. package/dist/tokenize/token_stream.d.ts +3 -0
  41. package/dist/tokenize/token_stream.d.ts.map +1 -1
  42. package/dist/tokenize/token_stream.js +11 -3
  43. package/dist/tokenize/token_stream.js.map +1 -1
  44. package/dist/tts/index.d.ts +2 -1
  45. package/dist/tts/index.d.ts.map +1 -1
  46. package/dist/tts/index.js +2 -1
  47. package/dist/tts/index.js.map +1 -1
  48. package/dist/tts/stream_adapter.d.ts +14 -0
  49. package/dist/tts/stream_adapter.d.ts.map +1 -0
  50. package/dist/tts/stream_adapter.js +50 -0
  51. package/dist/tts/stream_adapter.js.map +1 -0
  52. package/dist/tts/tts.d.ts +28 -0
  53. package/dist/tts/tts.d.ts.map +1 -1
  54. package/dist/tts/tts.js +38 -1
  55. package/dist/tts/tts.js.map +1 -1
  56. package/dist/utils.js.map +1 -1
  57. package/dist/worker.d.ts.map +1 -1
  58. package/dist/worker.js +13 -8
  59. package/dist/worker.js.map +1 -1
  60. package/package.json +7 -4
  61. package/src/ipc/job_main.ts +2 -1
  62. package/src/ipc/proc_job_executor.ts +1 -1
  63. package/src/job.ts +1 -4
  64. package/src/llm/function_context.ts +12 -3
  65. package/src/pipeline/agent_output.ts +4 -8
  66. package/src/pipeline/agent_playout.ts +3 -1
  67. package/src/pipeline/index.ts +1 -1
  68. package/src/pipeline/pipeline_agent.ts +17 -7
  69. package/src/stt/index.ts +1 -0
  70. package/src/stt/stream_adapter.ts +75 -0
  71. package/src/stt/stt.ts +5 -1
  72. package/src/tokenize/basic/hyphenator.ts +4 -6
  73. package/src/tokenize/token_stream.ts +14 -3
  74. package/src/tts/index.ts +8 -1
  75. package/src/tts/stream_adapter.ts +63 -0
  76. package/src/tts/tts.ts +48 -1
  77. package/src/utils.ts +2 -2
  78. package/src/worker.ts +14 -10
  79. package/tsconfig.tsbuildinfo +1 -1
package/src/tts/tts.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  import type { AudioFrame } from '@livekit/rtc-node';
5
- import { AsyncIterableQueue } from '../utils.js';
5
+ import { AsyncIterableQueue, mergeFrames } from '../utils.js';
6
6
 
7
7
  /** SynthesizedAudio is a packet of speech synthesis as returned by the TTS. */
8
8
  export interface SynthesizedAudio {
@@ -60,6 +60,11 @@ export abstract class TTS {
60
60
  return this.#numChannels;
61
61
  }
62
62
 
63
+ /**
64
+ * Receives text and returns synthesis in the form of a {@link ChunkedStream}
65
+ */
66
+ abstract synthesize(text: string): ChunkedStream;
67
+
63
68
  /**
64
69
  * Returns a {@link SynthesizeStream} that can be used to push text and receive audio data
65
70
  */
@@ -139,3 +144,45 @@ export abstract class SynthesizeStream
139
144
  return this;
140
145
  }
141
146
  }
147
+
148
+ /**
149
+ * An instance of a text-to-speech response, as an asynchronous iterable iterator.
150
+ *
151
+ * @example Looping through frames
152
+ * ```ts
153
+ * for await (const event of stream) {
154
+ * await source.captureFrame(event.frame);
155
+ * }
156
+ * ```
157
+ *
158
+ * @remarks
159
+ * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that
160
+ * exports its own child ChunkedStream class, which inherits this class's methods.
161
+ */
162
+ export abstract class ChunkedStream implements AsyncIterableIterator<SynthesizedAudio> {
163
+ protected queue = new AsyncIterableQueue<SynthesizedAudio>();
164
+ protected closed = false;
165
+
166
+ /** Collect every frame into one in a single call */
167
+ async collect(): Promise<AudioFrame> {
168
+ const frames = [];
169
+ for await (const event of this) {
170
+ frames.push(event.frame);
171
+ }
172
+ return mergeFrames(frames);
173
+ }
174
+
175
+ next(): Promise<IteratorResult<SynthesizedAudio>> {
176
+ return this.queue.next();
177
+ }
178
+
179
+ /** Close both the input and output of the TTS stream */
180
+ close() {
181
+ this.queue.close();
182
+ this.closed = true;
183
+ }
184
+
185
+ [Symbol.asyncIterator](): ChunkedStream {
186
+ return this;
187
+ }
188
+ }
package/src/utils.ts CHANGED
@@ -28,8 +28,8 @@ export const mergeFrames = (buffer: AudioBuffer): AudioFrame => {
28
28
  throw new TypeError('buffer is empty');
29
29
  }
30
30
 
31
- const sampleRate = buffer[0].sampleRate;
32
- const channels = buffer[0].channels;
31
+ const sampleRate = buffer[0]!.sampleRate;
32
+ const channels = buffer[0]!.channels;
33
33
  let samplesPerChannel = 0;
34
34
  let data = new Int16Array();
35
35
 
package/src/worker.ts CHANGED
@@ -89,8 +89,8 @@ const defaultCpuLoad = async (): Promise<number> => {
89
89
  let total = 0;
90
90
 
91
91
  for (let i = 0; i < cpus1.length; i++) {
92
- const cpu1 = cpus1[i].times;
93
- const cpu2 = cpus2[i].times;
92
+ const cpu1 = cpus1[i]!.times;
93
+ const cpu2 = cpus2[i]!.times;
94
94
 
95
95
  idle += cpu2.idle - cpu1.idle;
96
96
 
@@ -495,7 +495,7 @@ export class Worker {
495
495
  if (job.id in this.#pending) {
496
496
  const task = this.#pending[job.id];
497
497
  delete this.#pending[job.id];
498
- task.resolve(msg.message.value);
498
+ task?.resolve(msg.message.value);
499
499
  } else {
500
500
  this.#logger.child({ job }).warn('received assignment for unknown job ' + job.id);
501
501
  }
@@ -610,17 +610,21 @@ export class Worker {
610
610
  this.#logger.child({ req }).warn(`assignment for job ${req.id} timed out`);
611
611
  return;
612
612
  }, ASSIGNMENT_TIMEOUT);
613
- const asgn = await this.#pending[req.id].promise.then(async (asgn) => {
613
+ const asgn = await this.#pending[req.id]?.promise.then(async (asgn) => {
614
614
  clearTimeout(timer);
615
615
  return asgn;
616
616
  });
617
617
 
618
- await this.#procPool.launchJob({
619
- acceptArguments: args,
620
- job: msg.job!,
621
- url: asgn.url || this.#opts.wsURL,
622
- token: asgn.token,
623
- });
618
+ if (asgn) {
619
+ await this.#procPool.launchJob({
620
+ acceptArguments: args,
621
+ job: msg.job!,
622
+ url: asgn.url || this.#opts.wsURL,
623
+ token: asgn.token,
624
+ });
625
+ } else {
626
+ this.#logger.child({ requestId: req.id }).warn('pending assignment not found');
627
+ }
624
628
  };
625
629
 
626
630
  const req = new JobRequest(msg.job!, onReject, onAccept);