@livekit/agents 1.0.0-next.0 → 1.0.0-next.2

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 (65) hide show
  1. package/dist/llm/llm.cjs +1 -2
  2. package/dist/llm/llm.cjs.map +1 -1
  3. package/dist/llm/llm.d.ts.map +1 -1
  4. package/dist/llm/llm.js +1 -2
  5. package/dist/llm/llm.js.map +1 -1
  6. package/dist/llm/utils.cjs +5 -4
  7. package/dist/llm/utils.cjs.map +1 -1
  8. package/dist/llm/utils.d.cts +2 -2
  9. package/dist/llm/utils.d.ts +2 -2
  10. package/dist/llm/utils.d.ts.map +1 -1
  11. package/dist/llm/utils.js +5 -4
  12. package/dist/llm/utils.js.map +1 -1
  13. package/dist/stream/deferred_stream.test.cjs +10 -10
  14. package/dist/stream/deferred_stream.test.cjs.map +1 -1
  15. package/dist/stream/deferred_stream.test.js +1 -1
  16. package/dist/stream/deferred_stream.test.js.map +1 -1
  17. package/dist/stt/stt.cjs +1 -2
  18. package/dist/stt/stt.cjs.map +1 -1
  19. package/dist/stt/stt.d.ts.map +1 -1
  20. package/dist/stt/stt.js +1 -2
  21. package/dist/stt/stt.js.map +1 -1
  22. package/dist/tts/tts.cjs +2 -3
  23. package/dist/tts/tts.cjs.map +1 -1
  24. package/dist/tts/tts.d.ts.map +1 -1
  25. package/dist/tts/tts.js +1 -2
  26. package/dist/tts/tts.js.map +1 -1
  27. package/dist/utils.cjs +19 -2
  28. package/dist/utils.cjs.map +1 -1
  29. package/dist/utils.d.cts +11 -0
  30. package/dist/utils.d.ts +11 -0
  31. package/dist/utils.d.ts.map +1 -1
  32. package/dist/utils.js +17 -1
  33. package/dist/utils.js.map +1 -1
  34. package/dist/utils.test.cjs +30 -31
  35. package/dist/utils.test.cjs.map +1 -1
  36. package/dist/utils.test.js +1 -1
  37. package/dist/utils.test.js.map +1 -1
  38. package/dist/voice/agent_session.cjs +3 -0
  39. package/dist/voice/agent_session.cjs.map +1 -1
  40. package/dist/voice/agent_session.d.cts +1 -0
  41. package/dist/voice/agent_session.d.ts +1 -0
  42. package/dist/voice/agent_session.d.ts.map +1 -1
  43. package/dist/voice/agent_session.js +3 -0
  44. package/dist/voice/agent_session.js.map +1 -1
  45. package/dist/voice/audio_recognition.cjs +2 -3
  46. package/dist/voice/audio_recognition.cjs.map +1 -1
  47. package/dist/voice/audio_recognition.d.ts.map +1 -1
  48. package/dist/voice/audio_recognition.js +1 -2
  49. package/dist/voice/audio_recognition.js.map +1 -1
  50. package/dist/voice/transcription/synchronizer.cjs +1 -2
  51. package/dist/voice/transcription/synchronizer.cjs.map +1 -1
  52. package/dist/voice/transcription/synchronizer.d.ts.map +1 -1
  53. package/dist/voice/transcription/synchronizer.js +1 -2
  54. package/dist/voice/transcription/synchronizer.js.map +1 -1
  55. package/package.json +1 -2
  56. package/src/llm/llm.ts +1 -2
  57. package/src/llm/utils.ts +9 -5
  58. package/src/stream/deferred_stream.test.ts +1 -1
  59. package/src/stt/stt.ts +1 -2
  60. package/src/tts/tts.ts +1 -2
  61. package/src/utils.test.ts +1 -1
  62. package/src/utils.ts +28 -1
  63. package/src/voice/agent_session.ts +4 -0
  64. package/src/voice/audio_recognition.ts +1 -2
  65. package/src/voice/transcription/synchronizer.ts +1 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/stream/deferred_stream.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { delay } from '@std/async/delay';\nimport { ReadableStream } from 'node:stream/web';\nimport { describe, expect, it } from 'vitest';\nimport { DeferredReadableStream } from './deferred_stream.js';\n\ndescribe('DeferredReadableStream', () => {\n it('should create a readable stream that can be read after setting source', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Create a source stream with test data\n const testData = ['chunk1', 'chunk2', 'chunk3'];\n const source = new ReadableStream<string>({\n start(controller) {\n for (const chunk of testData) {\n controller.enqueue(chunk);\n }\n controller.close();\n },\n });\n\n // Set the source\n deferred.setSource(source);\n\n // Read all data\n const results: string[] = [];\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n\n expect(results).toEqual(testData);\n });\n\n it('should allow reading from stream before source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading before source is set (this should not resolve immediately)\n const readPromise = reader.read();\n\n // Wait a bit to ensure the read is pending\n await delay(10);\n\n // Now set the source\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test-value');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // The read should now resolve\n const result = await readPromise;\n expect(result.done).toBe(false);\n expect(result.value).toBe('test-value');\n\n // Next read should indicate stream completion\n const nextResult = await reader.read();\n expect(nextResult.done).toBe(true);\n });\n\n it('should throw error when trying to set source on locked stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Get a reader to lock the stream\n const reader = deferred.stream.getReader();\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream({\n start(controller) {\n controller.enqueue('test2');\n controller.close();\n },\n });\n\n expect(() => deferred.setSource(source)).not.toThrow();\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n\n // Clean up\n reader.releaseLock();\n });\n\n it('should handle multiple concurrent readers before source is set', async () => {\n const deferred = new DeferredReadableStream<number>();\n\n // Create multiple readers by using tee()\n const [stream1, stream2] = deferred.stream.tee();\n const reader1 = stream1.getReader();\n const reader2 = stream2.getReader();\n\n // Start reading from both streams concurrently\n const read1Promise = reader1.read();\n const read2Promise = reader2.read();\n\n // Wait to ensure reads are pending\n await delay(10);\n\n // Set source with test data\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue(42);\n controller.enqueue(84);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Both readers should receive the data\n const [result1, result2] = await Promise.all([read1Promise, read2Promise]);\n\n expect(result1.done).toBe(false);\n expect(result1.value).toBe(42);\n expect(result2.done).toBe(false);\n expect(result2.value).toBe(42);\n\n // Read second values\n const [second1, second2] = await Promise.all([reader1.read(), reader2.read()]);\n expect(second1.value).toBe(84);\n expect(second2.value).toBe(84);\n });\n\n it('should handle concurrent reads and writes', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Create a source that writes data over time\n const chunks = ['a', 'b', 'c', 'd', 'e'];\n let chunkIndex = 0;\n\n const source = new ReadableStream({\n start(controller) {\n const writeNext = () => {\n if (chunkIndex < chunks.length) {\n controller.enqueue(chunks[chunkIndex++]);\n setTimeout(writeNext, 5); // Write next chunk after small delay\n } else {\n controller.close();\n }\n };\n writeNext();\n },\n });\n\n // Set source and immediately start reading concurrently\n deferred.setSource(source);\n\n const results: string[] = [];\n const readConcurrently = async () => {\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n };\n\n await readConcurrently();\n expect(results).toEqual(chunks);\n });\n\n it('should handle race condition between setSource and getReader', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('race-test');\n controller.close();\n },\n });\n\n // Race between setting source and getting reader\n const [, reader] = await Promise.all([\n // Set source\n Promise.resolve().then(() => deferred.setSource(source)),\n // Get reader\n Promise.resolve().then(() => deferred.stream.getReader()),\n ]);\n\n const result = await reader.read();\n expect(result.value).toBe('race-test');\n });\n\n it('should handle empty source stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n const emptySource = new ReadableStream({\n start(controller) {\n controller.close();\n },\n });\n\n deferred.setSource(emptySource);\n\n const result = await reader.read();\n expect(result.done).toBe(true);\n });\n\n it('should handle source stream with errors', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n const errorSource = new ReadableStream({\n async start(controller) {\n controller.enqueue('before-error');\n // Use async/await to keep the error within the test scope\n await new Promise((resolve) => setTimeout(resolve, 100));\n controller.error(new Error('Source stream error'));\n },\n });\n\n deferred.setSource(errorSource);\n\n // Should read the value before error\n const result1 = await reader.read();\n expect(result1.value).toBe('before-error');\n\n // Next read should throw the error\n await expect(() => reader.read()).rejects.toThrow('Source stream error');\n });\n\n it('should handle multiple concurrent read operations', async () => {\n const deferred = new DeferredReadableStream<number>();\n const reader = deferred.stream.getReader();\n\n // Start multiple read operations before setting source\n const readPromises = Array.from({ length: 3 }, () => reader.read());\n\n await delay(10);\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue(1);\n controller.enqueue(2);\n controller.enqueue(3);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // All reads should resolve with the sequential values\n const results = await Promise.all(readPromises);\n\n expect(results[0]?.value).toBe(1);\n expect(results[1]?.value).toBe(2);\n expect(results[2]?.value).toBe(3);\n expect(results.every((r) => !r.done)).toBe(true);\n\n // Final read should indicate completion\n const finalResult = await reader.read();\n expect(finalResult.done).toBe(true);\n });\n\n it('should handle backpressure correctly', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Create a source with large chunks to test backpressure\n const largeChunks = Array.from({ length: 1000 }, (_, i) => `chunk-${i}`);\n\n const source = new ReadableStream({\n start(controller) {\n for (const chunk of largeChunks) {\n controller.enqueue(chunk);\n }\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const reader = deferred.stream.getReader();\n const results: string[] = [];\n\n // Read all chunks\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n\n expect(results).toEqual(largeChunks);\n });\n\n it('should handle concurrent setSource calls (second should fail)', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source1 = new ReadableStream({\n start(controller) {\n controller.enqueue('first');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream({\n start(controller) {\n controller.enqueue('second');\n controller.close();\n },\n });\n\n // First setSource should succeed\n deferred.setSource(source1);\n\n // Second setSource should fail because stream is now locked\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n\n // Verify we get data from the first source\n const reader = deferred.stream.getReader();\n const result = await reader.read();\n expect(result.value).toBe('first');\n });\n\n it('should handle reader release and re-acquire before source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Get reader and immediately release it\n const reader1 = deferred.stream.getReader();\n reader1.releaseLock();\n\n // Get a new reader\n const reader2 = deferred.stream.getReader();\n\n // Now set the source\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test-after-release');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const result = await reader2.read();\n expect(result.value).toBe('test-after-release');\n });\n\n it('should handle type safety with different data types', async () => {\n interface TestData {\n id: number;\n name: string;\n }\n\n const deferred = new DeferredReadableStream<TestData>();\n const reader = deferred.stream.getReader();\n\n const testObject: TestData = { id: 1, name: 'test' };\n\n const source = new ReadableStream<TestData>({\n start(controller) {\n controller.enqueue(testObject);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const result = await reader.read();\n expect(result.value).toEqual(testObject);\n expect(result.value).toBeDefined();\n expect(typeof result.value!.id).toBe('number');\n expect(typeof result.value!.name).toBe('string');\n });\n\n it('should create a readable stream', () => {\n const deferred = new DeferredReadableStream<string>();\n expect(deferred.stream).toBeInstanceOf(ReadableStream);\n });\n\n it('should keep reader awaiting before source is set, then read after source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Track if read operation is still pending\n let readCompleted = false;\n\n // Start reading - this should hang until source is set\n const readPromise = reader.read().then((result) => {\n readCompleted = true;\n return result;\n });\n\n // Give some time to ensure read doesn't complete immediately\n await delay(50);\n expect(readCompleted).toBe(false);\n\n // Create and set the source\n const sourceData = ['hello', 'world'];\n const source = new ReadableStream<string>({\n start(controller) {\n sourceData.forEach((chunk) => controller.enqueue(chunk));\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Now the read should complete\n const result = await readPromise;\n expect(readCompleted).toBe(true);\n expect(result.done).toBe(false);\n expect(result.value).toBe('hello');\n\n // Read the second chunk\n const result2 = await reader.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('world');\n\n // Stream should be closed\n const result3 = await reader.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('should handle multiple chunks from source', async () => {\n const deferred = new DeferredReadableStream<number>();\n const chunks: number[] = [];\n\n // Set up a reader that collects all chunks\n const collectPromise = (async () => {\n const reader = deferred.stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n })();\n\n // Create a source that emits multiple chunks over time\n const source = new ReadableStream<number>({\n async start(controller) {\n for (let i = 0; i < 5; i++) {\n controller.enqueue(i);\n await delay(10);\n }\n controller.close();\n },\n });\n\n // Set the source\n deferred.setSource(source);\n\n // Wait for all chunks to be collected\n await collectPromise;\n\n expect(chunks).toEqual([0, 1, 2, 3, 4]);\n });\n\n it('should propagate errors from source to reader', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading\n const readPromise = reader.read();\n\n // Create a source that errors\n const errorMessage = 'Source error';\n const source = new ReadableStream<string>({\n async start(controller) {\n controller.error(new Error(errorMessage));\n },\n cancel(reason) {\n console.log('cancel', reason);\n },\n });\n\n deferred.setSource(source);\n\n // The read should reject with the error\n try {\n await readPromise;\n expect.fail('readPromise should have rejected');\n } catch (e: unknown) {\n const error = e as Error;\n expect(error).toBeInstanceOf(Error);\n expect(error.message).toBe('Source error');\n }\n\n reader.releaseLock();\n });\n\n it('should throw error when trying to set source twice', () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source1 = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('first');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('second');\n controller.close();\n },\n });\n\n // First setSource should work\n deferred.setSource(source1);\n\n // Second setSource should throw\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n });\n\n it('should throw error when trying to detach source before setting it', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Attempting to detach source before setting it should throw\n await expect(deferred.detachSource()).rejects.toThrow('Source not set');\n });\n\n it('read returns undefined as soon as reader is cancelled', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('data');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n await reader.cancel();\n\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('reads after detaching source should return undefined', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('first');\n controller.enqueue('second');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Detach the source\n await deferred.detachSource();\n\n const result = await readPromise;\n expect(result.done).toBe(false);\n expect(result.value).toBe('first');\n\n const result2 = await reader.read();\n expect(result2.done).toBe(true);\n expect(result2.value).toBeUndefined();\n reader.releaseLock();\n\n const reader2 = source.getReader();\n const result3 = await reader2.read();\n expect(result3.done).toBe(false);\n expect(result3.value).toBe('second');\n\n const result4 = await reader2.read();\n expect(result4.done).toBe(true);\n expect(result4.value).toBeUndefined();\n reader.releaseLock();\n });\n\n it('should handle empty source stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading\n const readPromise = reader.read();\n\n // Set an empty source\n const source = new ReadableStream<string>({\n start(controller) {\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Read should indicate end of stream\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('source can be set by another deferred stream after calling detach', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Create a new source stream\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('before-cancel');\n controller.enqueue('after-cancel');\n controller.close();\n },\n });\n\n // read first chunk\n deferred.setSource(source);\n const reader = deferred.stream.getReader();\n const result = await reader.read();\n expect(result.done).toBe(false);\n expect(result.value).toBe('before-cancel');\n\n const result2Promise = reader.read();\n\n // detach the source\n await deferred.detachSource();\n\n // read second chunk\n const result2 = await result2Promise;\n expect(result2.done).toBe(true);\n expect(result2.value).toBeUndefined();\n\n // we manually release the lock\n reader.releaseLock();\n\n // create a new deferred stream and set the source\n const deferred2 = new DeferredReadableStream<string>();\n deferred2.setSource(source);\n const reader2 = deferred2.stream.getReader();\n\n // read the second chunk\n const result3 = await reader2.read();\n expect(result3.done).toBe(false);\n expect(result3.value).toBe('after-cancel');\n\n // read the third chunk\n const result4 = await reader2.read();\n expect(result4.done).toBe(true);\n expect(result4.value).toBeUndefined();\n reader2.releaseLock();\n });\n\n it('a non-terminating source reader releases lock after detaching', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n let resumeSource = false;\n\n const source = new ReadableStream<string>({\n async start(controller) {\n while (!resumeSource) await delay(10);\n\n controller.enqueue('data');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n await deferred.detachSource();\n await delay(100);\n\n // read before detach should return undefined since source never resumed\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n const reader2 = source.getReader();\n resumeSource = true;\n\n // read after detach should return correct order of data since source resumed\n const result2 = await reader2.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('data');\n\n const result3 = await reader2.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n reader2.releaseLock();\n });\n\n it('should transfer source between deferred streams while reading is ongoing', async () => {\n const deferred1 = new DeferredReadableStream<string>();\n const deferred2 = new DeferredReadableStream<string>();\n\n // Create a source that slowly emits data\n const source = new ReadableStream<string>({\n async start(controller) {\n // Emit 5 chunks with delays\n for (let i = 0; i < 4; i++) {\n controller.enqueue(`chunk-${i}`);\n await delay(20); // Small delay between chunks\n }\n controller.close();\n },\n });\n\n deferred1.setSource(source);\n const reader1 = deferred1.stream.getReader();\n const result1 = await reader1.read();\n expect(result1.done).toBe(false);\n expect(result1.value).toBe('chunk-0');\n\n const result2 = await reader1.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('chunk-1');\n await delay(10);\n await deferred1.detachSource();\n\n // reader1 now done\n const result3 = await reader1.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n deferred2.setSource(source);\n const reader2 = deferred2.stream.getReader();\n const result4 = await reader2.read();\n expect(result4.done).toBe(false);\n expect(result4.value).toBe('chunk-2');\n\n const result5 = await reader2.read();\n expect(result5.done).toBe(false);\n expect(result5.value).toBe('chunk-3');\n\n const result6 = await reader2.read();\n expect(result6.done).toBe(true);\n expect(result6.value).toBeUndefined();\n\n reader1.releaseLock();\n reader2.releaseLock();\n });\n});\n"],"mappings":"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","names":["result"]}
1
+ {"version":3,"sources":["../../src/stream/deferred_stream.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { ReadableStream } from 'node:stream/web';\nimport { describe, expect, it } from 'vitest';\nimport { delay } from '../utils.js';\nimport { DeferredReadableStream } from './deferred_stream.js';\n\ndescribe('DeferredReadableStream', () => {\n it('should create a readable stream that can be read after setting source', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Create a source stream with test data\n const testData = ['chunk1', 'chunk2', 'chunk3'];\n const source = new ReadableStream<string>({\n start(controller) {\n for (const chunk of testData) {\n controller.enqueue(chunk);\n }\n controller.close();\n },\n });\n\n // Set the source\n deferred.setSource(source);\n\n // Read all data\n const results: string[] = [];\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n\n expect(results).toEqual(testData);\n });\n\n it('should allow reading from stream before source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading before source is set (this should not resolve immediately)\n const readPromise = reader.read();\n\n // Wait a bit to ensure the read is pending\n await delay(10);\n\n // Now set the source\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test-value');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // The read should now resolve\n const result = await readPromise;\n expect(result.done).toBe(false);\n expect(result.value).toBe('test-value');\n\n // Next read should indicate stream completion\n const nextResult = await reader.read();\n expect(nextResult.done).toBe(true);\n });\n\n it('should throw error when trying to set source on locked stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Get a reader to lock the stream\n const reader = deferred.stream.getReader();\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream({\n start(controller) {\n controller.enqueue('test2');\n controller.close();\n },\n });\n\n expect(() => deferred.setSource(source)).not.toThrow();\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n\n // Clean up\n reader.releaseLock();\n });\n\n it('should handle multiple concurrent readers before source is set', async () => {\n const deferred = new DeferredReadableStream<number>();\n\n // Create multiple readers by using tee()\n const [stream1, stream2] = deferred.stream.tee();\n const reader1 = stream1.getReader();\n const reader2 = stream2.getReader();\n\n // Start reading from both streams concurrently\n const read1Promise = reader1.read();\n const read2Promise = reader2.read();\n\n // Wait to ensure reads are pending\n await delay(10);\n\n // Set source with test data\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue(42);\n controller.enqueue(84);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Both readers should receive the data\n const [result1, result2] = await Promise.all([read1Promise, read2Promise]);\n\n expect(result1.done).toBe(false);\n expect(result1.value).toBe(42);\n expect(result2.done).toBe(false);\n expect(result2.value).toBe(42);\n\n // Read second values\n const [second1, second2] = await Promise.all([reader1.read(), reader2.read()]);\n expect(second1.value).toBe(84);\n expect(second2.value).toBe(84);\n });\n\n it('should handle concurrent reads and writes', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Create a source that writes data over time\n const chunks = ['a', 'b', 'c', 'd', 'e'];\n let chunkIndex = 0;\n\n const source = new ReadableStream({\n start(controller) {\n const writeNext = () => {\n if (chunkIndex < chunks.length) {\n controller.enqueue(chunks[chunkIndex++]);\n setTimeout(writeNext, 5); // Write next chunk after small delay\n } else {\n controller.close();\n }\n };\n writeNext();\n },\n });\n\n // Set source and immediately start reading concurrently\n deferred.setSource(source);\n\n const results: string[] = [];\n const readConcurrently = async () => {\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n };\n\n await readConcurrently();\n expect(results).toEqual(chunks);\n });\n\n it('should handle race condition between setSource and getReader', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('race-test');\n controller.close();\n },\n });\n\n // Race between setting source and getting reader\n const [, reader] = await Promise.all([\n // Set source\n Promise.resolve().then(() => deferred.setSource(source)),\n // Get reader\n Promise.resolve().then(() => deferred.stream.getReader()),\n ]);\n\n const result = await reader.read();\n expect(result.value).toBe('race-test');\n });\n\n it('should handle empty source stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n const emptySource = new ReadableStream({\n start(controller) {\n controller.close();\n },\n });\n\n deferred.setSource(emptySource);\n\n const result = await reader.read();\n expect(result.done).toBe(true);\n });\n\n it('should handle source stream with errors', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n const errorSource = new ReadableStream({\n async start(controller) {\n controller.enqueue('before-error');\n // Use async/await to keep the error within the test scope\n await new Promise((resolve) => setTimeout(resolve, 100));\n controller.error(new Error('Source stream error'));\n },\n });\n\n deferred.setSource(errorSource);\n\n // Should read the value before error\n const result1 = await reader.read();\n expect(result1.value).toBe('before-error');\n\n // Next read should throw the error\n await expect(() => reader.read()).rejects.toThrow('Source stream error');\n });\n\n it('should handle multiple concurrent read operations', async () => {\n const deferred = new DeferredReadableStream<number>();\n const reader = deferred.stream.getReader();\n\n // Start multiple read operations before setting source\n const readPromises = Array.from({ length: 3 }, () => reader.read());\n\n await delay(10);\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue(1);\n controller.enqueue(2);\n controller.enqueue(3);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // All reads should resolve with the sequential values\n const results = await Promise.all(readPromises);\n\n expect(results[0]?.value).toBe(1);\n expect(results[1]?.value).toBe(2);\n expect(results[2]?.value).toBe(3);\n expect(results.every((r) => !r.done)).toBe(true);\n\n // Final read should indicate completion\n const finalResult = await reader.read();\n expect(finalResult.done).toBe(true);\n });\n\n it('should handle backpressure correctly', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Create a source with large chunks to test backpressure\n const largeChunks = Array.from({ length: 1000 }, (_, i) => `chunk-${i}`);\n\n const source = new ReadableStream({\n start(controller) {\n for (const chunk of largeChunks) {\n controller.enqueue(chunk);\n }\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const reader = deferred.stream.getReader();\n const results: string[] = [];\n\n // Read all chunks\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n\n expect(results).toEqual(largeChunks);\n });\n\n it('should handle concurrent setSource calls (second should fail)', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source1 = new ReadableStream({\n start(controller) {\n controller.enqueue('first');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream({\n start(controller) {\n controller.enqueue('second');\n controller.close();\n },\n });\n\n // First setSource should succeed\n deferred.setSource(source1);\n\n // Second setSource should fail because stream is now locked\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n\n // Verify we get data from the first source\n const reader = deferred.stream.getReader();\n const result = await reader.read();\n expect(result.value).toBe('first');\n });\n\n it('should handle reader release and re-acquire before source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Get reader and immediately release it\n const reader1 = deferred.stream.getReader();\n reader1.releaseLock();\n\n // Get a new reader\n const reader2 = deferred.stream.getReader();\n\n // Now set the source\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test-after-release');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const result = await reader2.read();\n expect(result.value).toBe('test-after-release');\n });\n\n it('should handle type safety with different data types', async () => {\n interface TestData {\n id: number;\n name: string;\n }\n\n const deferred = new DeferredReadableStream<TestData>();\n const reader = deferred.stream.getReader();\n\n const testObject: TestData = { id: 1, name: 'test' };\n\n const source = new ReadableStream<TestData>({\n start(controller) {\n controller.enqueue(testObject);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const result = await reader.read();\n expect(result.value).toEqual(testObject);\n expect(result.value).toBeDefined();\n expect(typeof result.value!.id).toBe('number');\n expect(typeof result.value!.name).toBe('string');\n });\n\n it('should create a readable stream', () => {\n const deferred = new DeferredReadableStream<string>();\n expect(deferred.stream).toBeInstanceOf(ReadableStream);\n });\n\n it('should keep reader awaiting before source is set, then read after source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Track if read operation is still pending\n let readCompleted = false;\n\n // Start reading - this should hang until source is set\n const readPromise = reader.read().then((result) => {\n readCompleted = true;\n return result;\n });\n\n // Give some time to ensure read doesn't complete immediately\n await delay(50);\n expect(readCompleted).toBe(false);\n\n // Create and set the source\n const sourceData = ['hello', 'world'];\n const source = new ReadableStream<string>({\n start(controller) {\n sourceData.forEach((chunk) => controller.enqueue(chunk));\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Now the read should complete\n const result = await readPromise;\n expect(readCompleted).toBe(true);\n expect(result.done).toBe(false);\n expect(result.value).toBe('hello');\n\n // Read the second chunk\n const result2 = await reader.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('world');\n\n // Stream should be closed\n const result3 = await reader.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('should handle multiple chunks from source', async () => {\n const deferred = new DeferredReadableStream<number>();\n const chunks: number[] = [];\n\n // Set up a reader that collects all chunks\n const collectPromise = (async () => {\n const reader = deferred.stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n })();\n\n // Create a source that emits multiple chunks over time\n const source = new ReadableStream<number>({\n async start(controller) {\n for (let i = 0; i < 5; i++) {\n controller.enqueue(i);\n await delay(10);\n }\n controller.close();\n },\n });\n\n // Set the source\n deferred.setSource(source);\n\n // Wait for all chunks to be collected\n await collectPromise;\n\n expect(chunks).toEqual([0, 1, 2, 3, 4]);\n });\n\n it('should propagate errors from source to reader', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading\n const readPromise = reader.read();\n\n // Create a source that errors\n const errorMessage = 'Source error';\n const source = new ReadableStream<string>({\n async start(controller) {\n controller.error(new Error(errorMessage));\n },\n cancel(reason) {\n console.log('cancel', reason);\n },\n });\n\n deferred.setSource(source);\n\n // The read should reject with the error\n try {\n await readPromise;\n expect.fail('readPromise should have rejected');\n } catch (e: unknown) {\n const error = e as Error;\n expect(error).toBeInstanceOf(Error);\n expect(error.message).toBe('Source error');\n }\n\n reader.releaseLock();\n });\n\n it('should throw error when trying to set source twice', () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source1 = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('first');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('second');\n controller.close();\n },\n });\n\n // First setSource should work\n deferred.setSource(source1);\n\n // Second setSource should throw\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n });\n\n it('should throw error when trying to detach source before setting it', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Attempting to detach source before setting it should throw\n await expect(deferred.detachSource()).rejects.toThrow('Source not set');\n });\n\n it('read returns undefined as soon as reader is cancelled', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('data');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n await reader.cancel();\n\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('reads after detaching source should return undefined', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('first');\n controller.enqueue('second');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Detach the source\n await deferred.detachSource();\n\n const result = await readPromise;\n expect(result.done).toBe(false);\n expect(result.value).toBe('first');\n\n const result2 = await reader.read();\n expect(result2.done).toBe(true);\n expect(result2.value).toBeUndefined();\n reader.releaseLock();\n\n const reader2 = source.getReader();\n const result3 = await reader2.read();\n expect(result3.done).toBe(false);\n expect(result3.value).toBe('second');\n\n const result4 = await reader2.read();\n expect(result4.done).toBe(true);\n expect(result4.value).toBeUndefined();\n reader.releaseLock();\n });\n\n it('should handle empty source stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading\n const readPromise = reader.read();\n\n // Set an empty source\n const source = new ReadableStream<string>({\n start(controller) {\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Read should indicate end of stream\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('source can be set by another deferred stream after calling detach', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Create a new source stream\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('before-cancel');\n controller.enqueue('after-cancel');\n controller.close();\n },\n });\n\n // read first chunk\n deferred.setSource(source);\n const reader = deferred.stream.getReader();\n const result = await reader.read();\n expect(result.done).toBe(false);\n expect(result.value).toBe('before-cancel');\n\n const result2Promise = reader.read();\n\n // detach the source\n await deferred.detachSource();\n\n // read second chunk\n const result2 = await result2Promise;\n expect(result2.done).toBe(true);\n expect(result2.value).toBeUndefined();\n\n // we manually release the lock\n reader.releaseLock();\n\n // create a new deferred stream and set the source\n const deferred2 = new DeferredReadableStream<string>();\n deferred2.setSource(source);\n const reader2 = deferred2.stream.getReader();\n\n // read the second chunk\n const result3 = await reader2.read();\n expect(result3.done).toBe(false);\n expect(result3.value).toBe('after-cancel');\n\n // read the third chunk\n const result4 = await reader2.read();\n expect(result4.done).toBe(true);\n expect(result4.value).toBeUndefined();\n reader2.releaseLock();\n });\n\n it('a non-terminating source reader releases lock after detaching', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n let resumeSource = false;\n\n const source = new ReadableStream<string>({\n async start(controller) {\n while (!resumeSource) await delay(10);\n\n controller.enqueue('data');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n await deferred.detachSource();\n await delay(100);\n\n // read before detach should return undefined since source never resumed\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n const reader2 = source.getReader();\n resumeSource = true;\n\n // read after detach should return correct order of data since source resumed\n const result2 = await reader2.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('data');\n\n const result3 = await reader2.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n reader2.releaseLock();\n });\n\n it('should transfer source between deferred streams while reading is ongoing', async () => {\n const deferred1 = new DeferredReadableStream<string>();\n const deferred2 = new DeferredReadableStream<string>();\n\n // Create a source that slowly emits data\n const source = new ReadableStream<string>({\n async start(controller) {\n // Emit 5 chunks with delays\n for (let i = 0; i < 4; i++) {\n controller.enqueue(`chunk-${i}`);\n await delay(20); // Small delay between chunks\n }\n controller.close();\n },\n });\n\n deferred1.setSource(source);\n const reader1 = deferred1.stream.getReader();\n const result1 = await reader1.read();\n expect(result1.done).toBe(false);\n expect(result1.value).toBe('chunk-0');\n\n const result2 = await reader1.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('chunk-1');\n await delay(10);\n await deferred1.detachSource();\n\n // reader1 now done\n const result3 = await reader1.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n deferred2.setSource(source);\n const reader2 = deferred2.stream.getReader();\n const result4 = await reader2.read();\n expect(result4.done).toBe(false);\n expect(result4.value).toBe('chunk-2');\n\n const result5 = await reader2.read();\n expect(result5.done).toBe(false);\n expect(result5.value).toBe('chunk-3');\n\n const result6 = await reader2.read();\n expect(result6.done).toBe(true);\n expect(result6.value).toBeUndefined();\n\n reader1.releaseLock();\n reader2.releaseLock();\n });\n});\n"],"mappings":"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","names":["result"]}
@@ -1,6 +1,6 @@
1
- import { delay } from "@std/async/delay";
2
1
  import { ReadableStream } from "node:stream/web";
3
2
  import { describe, expect, it } from "vitest";
3
+ import { delay } from "../utils.js";
4
4
  import { DeferredReadableStream } from "./deferred_stream.js";
5
5
  describe("DeferredReadableStream", () => {
6
6
  it("should create a readable stream that can be read after setting source", async () => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/stream/deferred_stream.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { delay } from '@std/async/delay';\nimport { ReadableStream } from 'node:stream/web';\nimport { describe, expect, it } from 'vitest';\nimport { DeferredReadableStream } from './deferred_stream.js';\n\ndescribe('DeferredReadableStream', () => {\n it('should create a readable stream that can be read after setting source', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Create a source stream with test data\n const testData = ['chunk1', 'chunk2', 'chunk3'];\n const source = new ReadableStream<string>({\n start(controller) {\n for (const chunk of testData) {\n controller.enqueue(chunk);\n }\n controller.close();\n },\n });\n\n // Set the source\n deferred.setSource(source);\n\n // Read all data\n const results: string[] = [];\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n\n expect(results).toEqual(testData);\n });\n\n it('should allow reading from stream before source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading before source is set (this should not resolve immediately)\n const readPromise = reader.read();\n\n // Wait a bit to ensure the read is pending\n await delay(10);\n\n // Now set the source\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test-value');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // The read should now resolve\n const result = await readPromise;\n expect(result.done).toBe(false);\n expect(result.value).toBe('test-value');\n\n // Next read should indicate stream completion\n const nextResult = await reader.read();\n expect(nextResult.done).toBe(true);\n });\n\n it('should throw error when trying to set source on locked stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Get a reader to lock the stream\n const reader = deferred.stream.getReader();\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream({\n start(controller) {\n controller.enqueue('test2');\n controller.close();\n },\n });\n\n expect(() => deferred.setSource(source)).not.toThrow();\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n\n // Clean up\n reader.releaseLock();\n });\n\n it('should handle multiple concurrent readers before source is set', async () => {\n const deferred = new DeferredReadableStream<number>();\n\n // Create multiple readers by using tee()\n const [stream1, stream2] = deferred.stream.tee();\n const reader1 = stream1.getReader();\n const reader2 = stream2.getReader();\n\n // Start reading from both streams concurrently\n const read1Promise = reader1.read();\n const read2Promise = reader2.read();\n\n // Wait to ensure reads are pending\n await delay(10);\n\n // Set source with test data\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue(42);\n controller.enqueue(84);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Both readers should receive the data\n const [result1, result2] = await Promise.all([read1Promise, read2Promise]);\n\n expect(result1.done).toBe(false);\n expect(result1.value).toBe(42);\n expect(result2.done).toBe(false);\n expect(result2.value).toBe(42);\n\n // Read second values\n const [second1, second2] = await Promise.all([reader1.read(), reader2.read()]);\n expect(second1.value).toBe(84);\n expect(second2.value).toBe(84);\n });\n\n it('should handle concurrent reads and writes', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Create a source that writes data over time\n const chunks = ['a', 'b', 'c', 'd', 'e'];\n let chunkIndex = 0;\n\n const source = new ReadableStream({\n start(controller) {\n const writeNext = () => {\n if (chunkIndex < chunks.length) {\n controller.enqueue(chunks[chunkIndex++]);\n setTimeout(writeNext, 5); // Write next chunk after small delay\n } else {\n controller.close();\n }\n };\n writeNext();\n },\n });\n\n // Set source and immediately start reading concurrently\n deferred.setSource(source);\n\n const results: string[] = [];\n const readConcurrently = async () => {\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n };\n\n await readConcurrently();\n expect(results).toEqual(chunks);\n });\n\n it('should handle race condition between setSource and getReader', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('race-test');\n controller.close();\n },\n });\n\n // Race between setting source and getting reader\n const [, reader] = await Promise.all([\n // Set source\n Promise.resolve().then(() => deferred.setSource(source)),\n // Get reader\n Promise.resolve().then(() => deferred.stream.getReader()),\n ]);\n\n const result = await reader.read();\n expect(result.value).toBe('race-test');\n });\n\n it('should handle empty source stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n const emptySource = new ReadableStream({\n start(controller) {\n controller.close();\n },\n });\n\n deferred.setSource(emptySource);\n\n const result = await reader.read();\n expect(result.done).toBe(true);\n });\n\n it('should handle source stream with errors', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n const errorSource = new ReadableStream({\n async start(controller) {\n controller.enqueue('before-error');\n // Use async/await to keep the error within the test scope\n await new Promise((resolve) => setTimeout(resolve, 100));\n controller.error(new Error('Source stream error'));\n },\n });\n\n deferred.setSource(errorSource);\n\n // Should read the value before error\n const result1 = await reader.read();\n expect(result1.value).toBe('before-error');\n\n // Next read should throw the error\n await expect(() => reader.read()).rejects.toThrow('Source stream error');\n });\n\n it('should handle multiple concurrent read operations', async () => {\n const deferred = new DeferredReadableStream<number>();\n const reader = deferred.stream.getReader();\n\n // Start multiple read operations before setting source\n const readPromises = Array.from({ length: 3 }, () => reader.read());\n\n await delay(10);\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue(1);\n controller.enqueue(2);\n controller.enqueue(3);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // All reads should resolve with the sequential values\n const results = await Promise.all(readPromises);\n\n expect(results[0]?.value).toBe(1);\n expect(results[1]?.value).toBe(2);\n expect(results[2]?.value).toBe(3);\n expect(results.every((r) => !r.done)).toBe(true);\n\n // Final read should indicate completion\n const finalResult = await reader.read();\n expect(finalResult.done).toBe(true);\n });\n\n it('should handle backpressure correctly', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Create a source with large chunks to test backpressure\n const largeChunks = Array.from({ length: 1000 }, (_, i) => `chunk-${i}`);\n\n const source = new ReadableStream({\n start(controller) {\n for (const chunk of largeChunks) {\n controller.enqueue(chunk);\n }\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const reader = deferred.stream.getReader();\n const results: string[] = [];\n\n // Read all chunks\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n\n expect(results).toEqual(largeChunks);\n });\n\n it('should handle concurrent setSource calls (second should fail)', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source1 = new ReadableStream({\n start(controller) {\n controller.enqueue('first');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream({\n start(controller) {\n controller.enqueue('second');\n controller.close();\n },\n });\n\n // First setSource should succeed\n deferred.setSource(source1);\n\n // Second setSource should fail because stream is now locked\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n\n // Verify we get data from the first source\n const reader = deferred.stream.getReader();\n const result = await reader.read();\n expect(result.value).toBe('first');\n });\n\n it('should handle reader release and re-acquire before source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Get reader and immediately release it\n const reader1 = deferred.stream.getReader();\n reader1.releaseLock();\n\n // Get a new reader\n const reader2 = deferred.stream.getReader();\n\n // Now set the source\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test-after-release');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const result = await reader2.read();\n expect(result.value).toBe('test-after-release');\n });\n\n it('should handle type safety with different data types', async () => {\n interface TestData {\n id: number;\n name: string;\n }\n\n const deferred = new DeferredReadableStream<TestData>();\n const reader = deferred.stream.getReader();\n\n const testObject: TestData = { id: 1, name: 'test' };\n\n const source = new ReadableStream<TestData>({\n start(controller) {\n controller.enqueue(testObject);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const result = await reader.read();\n expect(result.value).toEqual(testObject);\n expect(result.value).toBeDefined();\n expect(typeof result.value!.id).toBe('number');\n expect(typeof result.value!.name).toBe('string');\n });\n\n it('should create a readable stream', () => {\n const deferred = new DeferredReadableStream<string>();\n expect(deferred.stream).toBeInstanceOf(ReadableStream);\n });\n\n it('should keep reader awaiting before source is set, then read after source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Track if read operation is still pending\n let readCompleted = false;\n\n // Start reading - this should hang until source is set\n const readPromise = reader.read().then((result) => {\n readCompleted = true;\n return result;\n });\n\n // Give some time to ensure read doesn't complete immediately\n await delay(50);\n expect(readCompleted).toBe(false);\n\n // Create and set the source\n const sourceData = ['hello', 'world'];\n const source = new ReadableStream<string>({\n start(controller) {\n sourceData.forEach((chunk) => controller.enqueue(chunk));\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Now the read should complete\n const result = await readPromise;\n expect(readCompleted).toBe(true);\n expect(result.done).toBe(false);\n expect(result.value).toBe('hello');\n\n // Read the second chunk\n const result2 = await reader.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('world');\n\n // Stream should be closed\n const result3 = await reader.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('should handle multiple chunks from source', async () => {\n const deferred = new DeferredReadableStream<number>();\n const chunks: number[] = [];\n\n // Set up a reader that collects all chunks\n const collectPromise = (async () => {\n const reader = deferred.stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n })();\n\n // Create a source that emits multiple chunks over time\n const source = new ReadableStream<number>({\n async start(controller) {\n for (let i = 0; i < 5; i++) {\n controller.enqueue(i);\n await delay(10);\n }\n controller.close();\n },\n });\n\n // Set the source\n deferred.setSource(source);\n\n // Wait for all chunks to be collected\n await collectPromise;\n\n expect(chunks).toEqual([0, 1, 2, 3, 4]);\n });\n\n it('should propagate errors from source to reader', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading\n const readPromise = reader.read();\n\n // Create a source that errors\n const errorMessage = 'Source error';\n const source = new ReadableStream<string>({\n async start(controller) {\n controller.error(new Error(errorMessage));\n },\n cancel(reason) {\n console.log('cancel', reason);\n },\n });\n\n deferred.setSource(source);\n\n // The read should reject with the error\n try {\n await readPromise;\n expect.fail('readPromise should have rejected');\n } catch (e: unknown) {\n const error = e as Error;\n expect(error).toBeInstanceOf(Error);\n expect(error.message).toBe('Source error');\n }\n\n reader.releaseLock();\n });\n\n it('should throw error when trying to set source twice', () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source1 = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('first');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('second');\n controller.close();\n },\n });\n\n // First setSource should work\n deferred.setSource(source1);\n\n // Second setSource should throw\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n });\n\n it('should throw error when trying to detach source before setting it', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Attempting to detach source before setting it should throw\n await expect(deferred.detachSource()).rejects.toThrow('Source not set');\n });\n\n it('read returns undefined as soon as reader is cancelled', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('data');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n await reader.cancel();\n\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('reads after detaching source should return undefined', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('first');\n controller.enqueue('second');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Detach the source\n await deferred.detachSource();\n\n const result = await readPromise;\n expect(result.done).toBe(false);\n expect(result.value).toBe('first');\n\n const result2 = await reader.read();\n expect(result2.done).toBe(true);\n expect(result2.value).toBeUndefined();\n reader.releaseLock();\n\n const reader2 = source.getReader();\n const result3 = await reader2.read();\n expect(result3.done).toBe(false);\n expect(result3.value).toBe('second');\n\n const result4 = await reader2.read();\n expect(result4.done).toBe(true);\n expect(result4.value).toBeUndefined();\n reader.releaseLock();\n });\n\n it('should handle empty source stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading\n const readPromise = reader.read();\n\n // Set an empty source\n const source = new ReadableStream<string>({\n start(controller) {\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Read should indicate end of stream\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('source can be set by another deferred stream after calling detach', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Create a new source stream\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('before-cancel');\n controller.enqueue('after-cancel');\n controller.close();\n },\n });\n\n // read first chunk\n deferred.setSource(source);\n const reader = deferred.stream.getReader();\n const result = await reader.read();\n expect(result.done).toBe(false);\n expect(result.value).toBe('before-cancel');\n\n const result2Promise = reader.read();\n\n // detach the source\n await deferred.detachSource();\n\n // read second chunk\n const result2 = await result2Promise;\n expect(result2.done).toBe(true);\n expect(result2.value).toBeUndefined();\n\n // we manually release the lock\n reader.releaseLock();\n\n // create a new deferred stream and set the source\n const deferred2 = new DeferredReadableStream<string>();\n deferred2.setSource(source);\n const reader2 = deferred2.stream.getReader();\n\n // read the second chunk\n const result3 = await reader2.read();\n expect(result3.done).toBe(false);\n expect(result3.value).toBe('after-cancel');\n\n // read the third chunk\n const result4 = await reader2.read();\n expect(result4.done).toBe(true);\n expect(result4.value).toBeUndefined();\n reader2.releaseLock();\n });\n\n it('a non-terminating source reader releases lock after detaching', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n let resumeSource = false;\n\n const source = new ReadableStream<string>({\n async start(controller) {\n while (!resumeSource) await delay(10);\n\n controller.enqueue('data');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n await deferred.detachSource();\n await delay(100);\n\n // read before detach should return undefined since source never resumed\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n const reader2 = source.getReader();\n resumeSource = true;\n\n // read after detach should return correct order of data since source resumed\n const result2 = await reader2.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('data');\n\n const result3 = await reader2.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n reader2.releaseLock();\n });\n\n it('should transfer source between deferred streams while reading is ongoing', async () => {\n const deferred1 = new DeferredReadableStream<string>();\n const deferred2 = new DeferredReadableStream<string>();\n\n // Create a source that slowly emits data\n const source = new ReadableStream<string>({\n async start(controller) {\n // Emit 5 chunks with delays\n for (let i = 0; i < 4; i++) {\n controller.enqueue(`chunk-${i}`);\n await delay(20); // Small delay between chunks\n }\n controller.close();\n },\n });\n\n deferred1.setSource(source);\n const reader1 = deferred1.stream.getReader();\n const result1 = await reader1.read();\n expect(result1.done).toBe(false);\n expect(result1.value).toBe('chunk-0');\n\n const result2 = await reader1.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('chunk-1');\n await delay(10);\n await deferred1.detachSource();\n\n // reader1 now done\n const result3 = await reader1.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n deferred2.setSource(source);\n const reader2 = deferred2.stream.getReader();\n const result4 = await reader2.read();\n expect(result4.done).toBe(false);\n expect(result4.value).toBe('chunk-2');\n\n const result5 = await reader2.read();\n expect(result5.done).toBe(false);\n expect(result5.value).toBe('chunk-3');\n\n const result6 = await reader2.read();\n expect(result6.done).toBe(true);\n expect(result6.value).toBeUndefined();\n\n reader1.releaseLock();\n reader2.releaseLock();\n });\n});\n"],"mappings":"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","names":["result"]}
1
+ {"version":3,"sources":["../../src/stream/deferred_stream.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { ReadableStream } from 'node:stream/web';\nimport { describe, expect, it } from 'vitest';\nimport { delay } from '../utils.js';\nimport { DeferredReadableStream } from './deferred_stream.js';\n\ndescribe('DeferredReadableStream', () => {\n it('should create a readable stream that can be read after setting source', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Create a source stream with test data\n const testData = ['chunk1', 'chunk2', 'chunk3'];\n const source = new ReadableStream<string>({\n start(controller) {\n for (const chunk of testData) {\n controller.enqueue(chunk);\n }\n controller.close();\n },\n });\n\n // Set the source\n deferred.setSource(source);\n\n // Read all data\n const results: string[] = [];\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n\n expect(results).toEqual(testData);\n });\n\n it('should allow reading from stream before source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading before source is set (this should not resolve immediately)\n const readPromise = reader.read();\n\n // Wait a bit to ensure the read is pending\n await delay(10);\n\n // Now set the source\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test-value');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // The read should now resolve\n const result = await readPromise;\n expect(result.done).toBe(false);\n expect(result.value).toBe('test-value');\n\n // Next read should indicate stream completion\n const nextResult = await reader.read();\n expect(nextResult.done).toBe(true);\n });\n\n it('should throw error when trying to set source on locked stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Get a reader to lock the stream\n const reader = deferred.stream.getReader();\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream({\n start(controller) {\n controller.enqueue('test2');\n controller.close();\n },\n });\n\n expect(() => deferred.setSource(source)).not.toThrow();\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n\n // Clean up\n reader.releaseLock();\n });\n\n it('should handle multiple concurrent readers before source is set', async () => {\n const deferred = new DeferredReadableStream<number>();\n\n // Create multiple readers by using tee()\n const [stream1, stream2] = deferred.stream.tee();\n const reader1 = stream1.getReader();\n const reader2 = stream2.getReader();\n\n // Start reading from both streams concurrently\n const read1Promise = reader1.read();\n const read2Promise = reader2.read();\n\n // Wait to ensure reads are pending\n await delay(10);\n\n // Set source with test data\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue(42);\n controller.enqueue(84);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Both readers should receive the data\n const [result1, result2] = await Promise.all([read1Promise, read2Promise]);\n\n expect(result1.done).toBe(false);\n expect(result1.value).toBe(42);\n expect(result2.done).toBe(false);\n expect(result2.value).toBe(42);\n\n // Read second values\n const [second1, second2] = await Promise.all([reader1.read(), reader2.read()]);\n expect(second1.value).toBe(84);\n expect(second2.value).toBe(84);\n });\n\n it('should handle concurrent reads and writes', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Create a source that writes data over time\n const chunks = ['a', 'b', 'c', 'd', 'e'];\n let chunkIndex = 0;\n\n const source = new ReadableStream({\n start(controller) {\n const writeNext = () => {\n if (chunkIndex < chunks.length) {\n controller.enqueue(chunks[chunkIndex++]);\n setTimeout(writeNext, 5); // Write next chunk after small delay\n } else {\n controller.close();\n }\n };\n writeNext();\n },\n });\n\n // Set source and immediately start reading concurrently\n deferred.setSource(source);\n\n const results: string[] = [];\n const readConcurrently = async () => {\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n };\n\n await readConcurrently();\n expect(results).toEqual(chunks);\n });\n\n it('should handle race condition between setSource and getReader', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('race-test');\n controller.close();\n },\n });\n\n // Race between setting source and getting reader\n const [, reader] = await Promise.all([\n // Set source\n Promise.resolve().then(() => deferred.setSource(source)),\n // Get reader\n Promise.resolve().then(() => deferred.stream.getReader()),\n ]);\n\n const result = await reader.read();\n expect(result.value).toBe('race-test');\n });\n\n it('should handle empty source stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n const emptySource = new ReadableStream({\n start(controller) {\n controller.close();\n },\n });\n\n deferred.setSource(emptySource);\n\n const result = await reader.read();\n expect(result.done).toBe(true);\n });\n\n it('should handle source stream with errors', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n const errorSource = new ReadableStream({\n async start(controller) {\n controller.enqueue('before-error');\n // Use async/await to keep the error within the test scope\n await new Promise((resolve) => setTimeout(resolve, 100));\n controller.error(new Error('Source stream error'));\n },\n });\n\n deferred.setSource(errorSource);\n\n // Should read the value before error\n const result1 = await reader.read();\n expect(result1.value).toBe('before-error');\n\n // Next read should throw the error\n await expect(() => reader.read()).rejects.toThrow('Source stream error');\n });\n\n it('should handle multiple concurrent read operations', async () => {\n const deferred = new DeferredReadableStream<number>();\n const reader = deferred.stream.getReader();\n\n // Start multiple read operations before setting source\n const readPromises = Array.from({ length: 3 }, () => reader.read());\n\n await delay(10);\n\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue(1);\n controller.enqueue(2);\n controller.enqueue(3);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // All reads should resolve with the sequential values\n const results = await Promise.all(readPromises);\n\n expect(results[0]?.value).toBe(1);\n expect(results[1]?.value).toBe(2);\n expect(results[2]?.value).toBe(3);\n expect(results.every((r) => !r.done)).toBe(true);\n\n // Final read should indicate completion\n const finalResult = await reader.read();\n expect(finalResult.done).toBe(true);\n });\n\n it('should handle backpressure correctly', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Create a source with large chunks to test backpressure\n const largeChunks = Array.from({ length: 1000 }, (_, i) => `chunk-${i}`);\n\n const source = new ReadableStream({\n start(controller) {\n for (const chunk of largeChunks) {\n controller.enqueue(chunk);\n }\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const reader = deferred.stream.getReader();\n const results: string[] = [];\n\n // Read all chunks\n let result = await reader.read();\n while (!result.done) {\n results.push(result.value);\n result = await reader.read();\n }\n\n expect(results).toEqual(largeChunks);\n });\n\n it('should handle concurrent setSource calls (second should fail)', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source1 = new ReadableStream({\n start(controller) {\n controller.enqueue('first');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream({\n start(controller) {\n controller.enqueue('second');\n controller.close();\n },\n });\n\n // First setSource should succeed\n deferred.setSource(source1);\n\n // Second setSource should fail because stream is now locked\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n\n // Verify we get data from the first source\n const reader = deferred.stream.getReader();\n const result = await reader.read();\n expect(result.value).toBe('first');\n });\n\n it('should handle reader release and re-acquire before source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Get reader and immediately release it\n const reader1 = deferred.stream.getReader();\n reader1.releaseLock();\n\n // Get a new reader\n const reader2 = deferred.stream.getReader();\n\n // Now set the source\n const source = new ReadableStream({\n start(controller) {\n controller.enqueue('test-after-release');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const result = await reader2.read();\n expect(result.value).toBe('test-after-release');\n });\n\n it('should handle type safety with different data types', async () => {\n interface TestData {\n id: number;\n name: string;\n }\n\n const deferred = new DeferredReadableStream<TestData>();\n const reader = deferred.stream.getReader();\n\n const testObject: TestData = { id: 1, name: 'test' };\n\n const source = new ReadableStream<TestData>({\n start(controller) {\n controller.enqueue(testObject);\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n const result = await reader.read();\n expect(result.value).toEqual(testObject);\n expect(result.value).toBeDefined();\n expect(typeof result.value!.id).toBe('number');\n expect(typeof result.value!.name).toBe('string');\n });\n\n it('should create a readable stream', () => {\n const deferred = new DeferredReadableStream<string>();\n expect(deferred.stream).toBeInstanceOf(ReadableStream);\n });\n\n it('should keep reader awaiting before source is set, then read after source is set', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Track if read operation is still pending\n let readCompleted = false;\n\n // Start reading - this should hang until source is set\n const readPromise = reader.read().then((result) => {\n readCompleted = true;\n return result;\n });\n\n // Give some time to ensure read doesn't complete immediately\n await delay(50);\n expect(readCompleted).toBe(false);\n\n // Create and set the source\n const sourceData = ['hello', 'world'];\n const source = new ReadableStream<string>({\n start(controller) {\n sourceData.forEach((chunk) => controller.enqueue(chunk));\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Now the read should complete\n const result = await readPromise;\n expect(readCompleted).toBe(true);\n expect(result.done).toBe(false);\n expect(result.value).toBe('hello');\n\n // Read the second chunk\n const result2 = await reader.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('world');\n\n // Stream should be closed\n const result3 = await reader.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('should handle multiple chunks from source', async () => {\n const deferred = new DeferredReadableStream<number>();\n const chunks: number[] = [];\n\n // Set up a reader that collects all chunks\n const collectPromise = (async () => {\n const reader = deferred.stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n })();\n\n // Create a source that emits multiple chunks over time\n const source = new ReadableStream<number>({\n async start(controller) {\n for (let i = 0; i < 5; i++) {\n controller.enqueue(i);\n await delay(10);\n }\n controller.close();\n },\n });\n\n // Set the source\n deferred.setSource(source);\n\n // Wait for all chunks to be collected\n await collectPromise;\n\n expect(chunks).toEqual([0, 1, 2, 3, 4]);\n });\n\n it('should propagate errors from source to reader', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading\n const readPromise = reader.read();\n\n // Create a source that errors\n const errorMessage = 'Source error';\n const source = new ReadableStream<string>({\n async start(controller) {\n controller.error(new Error(errorMessage));\n },\n cancel(reason) {\n console.log('cancel', reason);\n },\n });\n\n deferred.setSource(source);\n\n // The read should reject with the error\n try {\n await readPromise;\n expect.fail('readPromise should have rejected');\n } catch (e: unknown) {\n const error = e as Error;\n expect(error).toBeInstanceOf(Error);\n expect(error.message).toBe('Source error');\n }\n\n reader.releaseLock();\n });\n\n it('should throw error when trying to set source twice', () => {\n const deferred = new DeferredReadableStream<string>();\n\n const source1 = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('first');\n controller.close();\n },\n });\n\n const source2 = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('second');\n controller.close();\n },\n });\n\n // First setSource should work\n deferred.setSource(source1);\n\n // Second setSource should throw\n expect(() => deferred.setSource(source2)).toThrow('Stream source already set');\n });\n\n it('should throw error when trying to detach source before setting it', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Attempting to detach source before setting it should throw\n await expect(deferred.detachSource()).rejects.toThrow('Source not set');\n });\n\n it('read returns undefined as soon as reader is cancelled', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('data');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n await reader.cancel();\n\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('reads after detaching source should return undefined', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('first');\n controller.enqueue('second');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Detach the source\n await deferred.detachSource();\n\n const result = await readPromise;\n expect(result.done).toBe(false);\n expect(result.value).toBe('first');\n\n const result2 = await reader.read();\n expect(result2.done).toBe(true);\n expect(result2.value).toBeUndefined();\n reader.releaseLock();\n\n const reader2 = source.getReader();\n const result3 = await reader2.read();\n expect(result3.done).toBe(false);\n expect(result3.value).toBe('second');\n\n const result4 = await reader2.read();\n expect(result4.done).toBe(true);\n expect(result4.value).toBeUndefined();\n reader.releaseLock();\n });\n\n it('should handle empty source stream', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n\n // Start reading\n const readPromise = reader.read();\n\n // Set an empty source\n const source = new ReadableStream<string>({\n start(controller) {\n controller.close();\n },\n });\n\n deferred.setSource(source);\n\n // Read should indicate end of stream\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n reader.releaseLock();\n });\n\n it('source can be set by another deferred stream after calling detach', async () => {\n const deferred = new DeferredReadableStream<string>();\n\n // Create a new source stream\n const source = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('before-cancel');\n controller.enqueue('after-cancel');\n controller.close();\n },\n });\n\n // read first chunk\n deferred.setSource(source);\n const reader = deferred.stream.getReader();\n const result = await reader.read();\n expect(result.done).toBe(false);\n expect(result.value).toBe('before-cancel');\n\n const result2Promise = reader.read();\n\n // detach the source\n await deferred.detachSource();\n\n // read second chunk\n const result2 = await result2Promise;\n expect(result2.done).toBe(true);\n expect(result2.value).toBeUndefined();\n\n // we manually release the lock\n reader.releaseLock();\n\n // create a new deferred stream and set the source\n const deferred2 = new DeferredReadableStream<string>();\n deferred2.setSource(source);\n const reader2 = deferred2.stream.getReader();\n\n // read the second chunk\n const result3 = await reader2.read();\n expect(result3.done).toBe(false);\n expect(result3.value).toBe('after-cancel');\n\n // read the third chunk\n const result4 = await reader2.read();\n expect(result4.done).toBe(true);\n expect(result4.value).toBeUndefined();\n reader2.releaseLock();\n });\n\n it('a non-terminating source reader releases lock after detaching', async () => {\n const deferred = new DeferredReadableStream<string>();\n const reader = deferred.stream.getReader();\n const readPromise = reader.read();\n let resumeSource = false;\n\n const source = new ReadableStream<string>({\n async start(controller) {\n while (!resumeSource) await delay(10);\n\n controller.enqueue('data');\n controller.close();\n },\n });\n\n deferred.setSource(source);\n await deferred.detachSource();\n await delay(100);\n\n // read before detach should return undefined since source never resumed\n const result = await readPromise;\n expect(result.done).toBe(true);\n expect(result.value).toBeUndefined();\n\n const reader2 = source.getReader();\n resumeSource = true;\n\n // read after detach should return correct order of data since source resumed\n const result2 = await reader2.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('data');\n\n const result3 = await reader2.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n reader2.releaseLock();\n });\n\n it('should transfer source between deferred streams while reading is ongoing', async () => {\n const deferred1 = new DeferredReadableStream<string>();\n const deferred2 = new DeferredReadableStream<string>();\n\n // Create a source that slowly emits data\n const source = new ReadableStream<string>({\n async start(controller) {\n // Emit 5 chunks with delays\n for (let i = 0; i < 4; i++) {\n controller.enqueue(`chunk-${i}`);\n await delay(20); // Small delay between chunks\n }\n controller.close();\n },\n });\n\n deferred1.setSource(source);\n const reader1 = deferred1.stream.getReader();\n const result1 = await reader1.read();\n expect(result1.done).toBe(false);\n expect(result1.value).toBe('chunk-0');\n\n const result2 = await reader1.read();\n expect(result2.done).toBe(false);\n expect(result2.value).toBe('chunk-1');\n await delay(10);\n await deferred1.detachSource();\n\n // reader1 now done\n const result3 = await reader1.read();\n expect(result3.done).toBe(true);\n expect(result3.value).toBeUndefined();\n\n deferred2.setSource(source);\n const reader2 = deferred2.stream.getReader();\n const result4 = await reader2.read();\n expect(result4.done).toBe(false);\n expect(result4.value).toBe('chunk-2');\n\n const result5 = await reader2.read();\n expect(result5.done).toBe(false);\n expect(result5.value).toBe('chunk-3');\n\n const result6 = await reader2.read();\n expect(result6.done).toBe(true);\n expect(result6.value).toBeUndefined();\n\n reader1.releaseLock();\n reader2.releaseLock();\n });\n});\n"],"mappings":"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","names":["result"]}
package/dist/stt/stt.cjs CHANGED
@@ -24,7 +24,6 @@ __export(stt_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(stt_exports);
26
26
  var import_rtc_node = require("@livekit/rtc-node");
27
- var import_delay = require("@std/async/delay");
28
27
  var import_node_events = require("node:events");
29
28
  var import_exceptions = require("../_exceptions.cjs");
30
29
  var import_audio = require("../audio.cjs");
@@ -112,7 +111,7 @@ class SpeechStream {
112
111
  );
113
112
  }
114
113
  if (retryInterval > 0) {
115
- await (0, import_delay.delay)(retryInterval);
114
+ await (0, import_utils.delay)(retryInterval);
116
115
  }
117
116
  } else {
118
117
  this.emitError({ error: (0, import_utils.toError)(error), recoverable: false });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/stt/stt.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type AudioFrame, AudioResampler } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { delay } from '@std/async/delay';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport { APIConnectionError, APIError } from '../_exceptions.js';\nimport { calculateAudioDuration } from '../audio.js';\nimport { log } from '../log.js';\nimport type { STTMetrics } from '../metrics/base.js';\nimport { DeferredReadableStream } from '../stream/deferred_stream.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../types.js';\nimport type { AudioBuffer } from '../utils.js';\nimport { AsyncIterableQueue, startSoon, toError } from '../utils.js';\n\n/** Indicates start/middle/end of speech */\nexport enum SpeechEventType {\n /**\n * Indicate the start of speech.\n * If the STT doesn't support this event, this will be emitted at the same time\n * as the first INTERIM_TRANSCRIPT.\n */\n START_OF_SPEECH = 0,\n /**\n * Interim transcript, useful for real-time transcription.\n */\n INTERIM_TRANSCRIPT = 1,\n /**\n * Final transcript, emitted when the STT is confident enough that a certain\n * portion of the speech will not change.\n */\n FINAL_TRANSCRIPT = 2,\n /**\n * Indicate the end of speech, emitted when the user stops speaking.\n * The first alternative is a combination of all the previous FINAL_TRANSCRIPT events.\n */\n END_OF_SPEECH = 3,\n /** Usage event, emitted periodically to indicate usage metrics. */\n RECOGNITION_USAGE = 4,\n}\n\n/** SpeechData contains metadata about this {@link SpeechEvent}. */\nexport interface SpeechData {\n language: string;\n text: string;\n startTime: number;\n endTime: number;\n confidence: number;\n}\n\nexport interface RecognitionUsage {\n audioDuration: number;\n}\n\n/** SpeechEvent is a packet of speech-to-text data. */\nexport interface SpeechEvent {\n type: SpeechEventType;\n alternatives?: [SpeechData, ...SpeechData[]];\n requestId?: string;\n recognitionUsage?: RecognitionUsage;\n}\n\n/**\n * Describes the capabilities of the STT provider.\n *\n * @remarks\n * At present, the framework only supports providers that have a streaming endpoint.\n */\nexport interface STTCapabilities {\n streaming: boolean;\n interimResults: boolean;\n}\n\nexport interface STTError {\n type: 'stt_error';\n timestamp: number;\n label: string;\n error: Error;\n recoverable: boolean;\n}\n\nexport type STTCallbacks = {\n ['metrics_collected']: (metrics: STTMetrics) => void;\n ['error']: (error: STTError) => void;\n};\n\n/**\n * An instance of a speech-to-text adapter.\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child STT class, which inherits this class's methods.\n */\nexport abstract class STT extends (EventEmitter as new () => TypedEmitter<STTCallbacks>) {\n abstract label: string;\n #capabilities: STTCapabilities;\n\n constructor(capabilities: STTCapabilities) {\n super();\n this.#capabilities = capabilities;\n }\n\n /** Returns this STT's capabilities */\n get capabilities(): STTCapabilities {\n return this.#capabilities;\n }\n\n /** Receives an audio buffer and returns transcription in the form of a {@link SpeechEvent} */\n async recognize(frame: AudioBuffer): Promise<SpeechEvent> {\n const startTime = process.hrtime.bigint();\n const event = await this._recognize(frame);\n const duration = Number((process.hrtime.bigint() - startTime) / BigInt(1000000));\n this.emit('metrics_collected', {\n type: 'stt_metrics',\n requestId: event.requestId ?? '',\n timestamp: Date.now(),\n duration,\n label: this.label,\n audioDuration: calculateAudioDuration(frame),\n streamed: false,\n });\n return event;\n }\n protected abstract _recognize(frame: AudioBuffer): Promise<SpeechEvent>;\n\n /**\n * Returns a {@link SpeechStream} that can be used to push audio frames and receive\n * transcriptions\n */\n abstract stream(): SpeechStream;\n}\n\n/**\n * An instance of a speech-to-text stream, as an asynchronous iterable iterator.\n *\n * @example Looping through frames\n * ```ts\n * for await (const event of stream) {\n * if (event.type === SpeechEventType.FINAL_TRANSCRIPT) {\n * console.log(event.alternatives[0].text)\n * }\n * }\n * ```\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child SpeechStream class, which inherits this class's methods.\n */\nexport abstract class SpeechStream implements AsyncIterableIterator<SpeechEvent> {\n protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');\n protected input = new AsyncIterableQueue<AudioFrame | typeof SpeechStream.FLUSH_SENTINEL>();\n protected output = new AsyncIterableQueue<SpeechEvent>();\n protected queue = new AsyncIterableQueue<SpeechEvent>();\n protected neededSampleRate?: number;\n protected resampler?: AudioResampler;\n abstract label: string;\n protected closed = false;\n #stt: STT;\n private deferredInputStream: DeferredReadableStream<AudioFrame>;\n private logger = log();\n private _connOptions: APIConnectOptions;\n\n constructor(\n stt: STT,\n sampleRate?: number,\n connectionOptions: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,\n ) {\n this.#stt = stt;\n this._connOptions = connectionOptions;\n this.deferredInputStream = new DeferredReadableStream<AudioFrame>();\n this.neededSampleRate = sampleRate;\n this.monitorMetrics();\n this.pumpInput();\n\n // this is a hack to immitate asyncio.create_task so that mainTask\n // is run **after** the constructor has finished. Otherwise we get\n // runtime error when trying to access class variables in the\n // `run` method.\n startSoon(() => this.mainTask().then(() => this.queue.close()));\n }\n\n private async mainTask() {\n for (let i = 0; i < this._connOptions.maxRetry + 1; i++) {\n try {\n return await this.run();\n } catch (error) {\n if (error instanceof APIError) {\n const retryInterval = this._connOptions._intervalForRetry(i);\n\n if (this._connOptions.maxRetry === 0 || !error.retryable) {\n this.emitError({ error, recoverable: false });\n throw error;\n } else if (i === this._connOptions.maxRetry) {\n this.emitError({ error, recoverable: false });\n throw new APIConnectionError({\n message: `failed to recognize speech after ${this._connOptions.maxRetry + 1} attempts`,\n options: { retryable: false },\n });\n } else {\n this.emitError({ error, recoverable: true });\n this.logger.warn(\n { tts: this.#stt.label, attempt: i + 1, error },\n `failed to recognize speech, retrying in ${retryInterval}s`,\n );\n }\n\n if (retryInterval > 0) {\n await delay(retryInterval);\n }\n } else {\n this.emitError({ error: toError(error), recoverable: false });\n throw error;\n }\n }\n }\n }\n\n private emitError({ error, recoverable }: { error: Error; recoverable: boolean }) {\n this.#stt.emit('error', {\n type: 'stt_error',\n timestamp: Date.now(),\n label: this.#stt.label,\n error,\n recoverable,\n });\n }\n\n protected async pumpInput() {\n // TODO(AJS-35): Implement STT with webstreams API\n const inputStream = this.deferredInputStream.stream;\n const reader = inputStream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n this.pushFrame(value);\n }\n } catch (error) {\n this.logger.error('Error in STTStream mainTask:', error);\n } finally {\n reader.releaseLock();\n }\n }\n\n protected async monitorMetrics() {\n for await (const event of this.queue) {\n this.output.put(event);\n if (event.type !== SpeechEventType.RECOGNITION_USAGE) continue;\n const metrics: STTMetrics = {\n type: 'stt_metrics',\n timestamp: Date.now(),\n requestId: event.requestId!,\n duration: 0,\n label: this.#stt.label,\n audioDuration: event.recognitionUsage!.audioDuration,\n streamed: true,\n };\n this.#stt.emit('metrics_collected', metrics);\n }\n this.output.close();\n }\n\n protected abstract run(): Promise<void>;\n\n updateInputStream(audioStream: ReadableStream<AudioFrame>) {\n this.deferredInputStream.setSource(audioStream);\n }\n\n detachInputStream() {\n this.deferredInputStream.detachSource();\n }\n\n /** Push an audio frame to the STT */\n pushFrame(frame: AudioFrame) {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n\n if (this.neededSampleRate && frame.sampleRate !== this.neededSampleRate) {\n if (!this.resampler) {\n this.resampler = new AudioResampler(frame.sampleRate, this.neededSampleRate);\n }\n }\n\n if (this.resampler) {\n const frames = this.resampler.push(frame);\n for (const frame of frames) {\n this.input.put(frame);\n }\n } else {\n this.input.put(frame);\n }\n }\n\n /** Flush the STT, causing it to process all pending text */\n flush() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.put(SpeechStream.FLUSH_SENTINEL);\n }\n\n /** Mark the input as ended and forbid additional pushes */\n endInput() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.close();\n }\n\n next(): Promise<IteratorResult<SpeechEvent>> {\n return this.output.next();\n }\n\n /** Close both the input and output of the STT stream */\n close() {\n this.input.close();\n this.queue.close();\n this.output.close();\n this.closed = true;\n }\n\n [Symbol.asyncIterator](): SpeechStream {\n return this;\n }\n}\n"],"mappings":"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","names":["SpeechEventType","frame"]}
1
+ {"version":3,"sources":["../../src/stt/stt.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type AudioFrame, AudioResampler } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport { APIConnectionError, APIError } from '../_exceptions.js';\nimport { calculateAudioDuration } from '../audio.js';\nimport { log } from '../log.js';\nimport type { STTMetrics } from '../metrics/base.js';\nimport { DeferredReadableStream } from '../stream/deferred_stream.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../types.js';\nimport type { AudioBuffer } from '../utils.js';\nimport { AsyncIterableQueue, delay, startSoon, toError } from '../utils.js';\n\n/** Indicates start/middle/end of speech */\nexport enum SpeechEventType {\n /**\n * Indicate the start of speech.\n * If the STT doesn't support this event, this will be emitted at the same time\n * as the first INTERIM_TRANSCRIPT.\n */\n START_OF_SPEECH = 0,\n /**\n * Interim transcript, useful for real-time transcription.\n */\n INTERIM_TRANSCRIPT = 1,\n /**\n * Final transcript, emitted when the STT is confident enough that a certain\n * portion of the speech will not change.\n */\n FINAL_TRANSCRIPT = 2,\n /**\n * Indicate the end of speech, emitted when the user stops speaking.\n * The first alternative is a combination of all the previous FINAL_TRANSCRIPT events.\n */\n END_OF_SPEECH = 3,\n /** Usage event, emitted periodically to indicate usage metrics. */\n RECOGNITION_USAGE = 4,\n}\n\n/** SpeechData contains metadata about this {@link SpeechEvent}. */\nexport interface SpeechData {\n language: string;\n text: string;\n startTime: number;\n endTime: number;\n confidence: number;\n}\n\nexport interface RecognitionUsage {\n audioDuration: number;\n}\n\n/** SpeechEvent is a packet of speech-to-text data. */\nexport interface SpeechEvent {\n type: SpeechEventType;\n alternatives?: [SpeechData, ...SpeechData[]];\n requestId?: string;\n recognitionUsage?: RecognitionUsage;\n}\n\n/**\n * Describes the capabilities of the STT provider.\n *\n * @remarks\n * At present, the framework only supports providers that have a streaming endpoint.\n */\nexport interface STTCapabilities {\n streaming: boolean;\n interimResults: boolean;\n}\n\nexport interface STTError {\n type: 'stt_error';\n timestamp: number;\n label: string;\n error: Error;\n recoverable: boolean;\n}\n\nexport type STTCallbacks = {\n ['metrics_collected']: (metrics: STTMetrics) => void;\n ['error']: (error: STTError) => void;\n};\n\n/**\n * An instance of a speech-to-text adapter.\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child STT class, which inherits this class's methods.\n */\nexport abstract class STT extends (EventEmitter as new () => TypedEmitter<STTCallbacks>) {\n abstract label: string;\n #capabilities: STTCapabilities;\n\n constructor(capabilities: STTCapabilities) {\n super();\n this.#capabilities = capabilities;\n }\n\n /** Returns this STT's capabilities */\n get capabilities(): STTCapabilities {\n return this.#capabilities;\n }\n\n /** Receives an audio buffer and returns transcription in the form of a {@link SpeechEvent} */\n async recognize(frame: AudioBuffer): Promise<SpeechEvent> {\n const startTime = process.hrtime.bigint();\n const event = await this._recognize(frame);\n const duration = Number((process.hrtime.bigint() - startTime) / BigInt(1000000));\n this.emit('metrics_collected', {\n type: 'stt_metrics',\n requestId: event.requestId ?? '',\n timestamp: Date.now(),\n duration,\n label: this.label,\n audioDuration: calculateAudioDuration(frame),\n streamed: false,\n });\n return event;\n }\n protected abstract _recognize(frame: AudioBuffer): Promise<SpeechEvent>;\n\n /**\n * Returns a {@link SpeechStream} that can be used to push audio frames and receive\n * transcriptions\n */\n abstract stream(): SpeechStream;\n}\n\n/**\n * An instance of a speech-to-text stream, as an asynchronous iterable iterator.\n *\n * @example Looping through frames\n * ```ts\n * for await (const event of stream) {\n * if (event.type === SpeechEventType.FINAL_TRANSCRIPT) {\n * console.log(event.alternatives[0].text)\n * }\n * }\n * ```\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child SpeechStream class, which inherits this class's methods.\n */\nexport abstract class SpeechStream implements AsyncIterableIterator<SpeechEvent> {\n protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');\n protected input = new AsyncIterableQueue<AudioFrame | typeof SpeechStream.FLUSH_SENTINEL>();\n protected output = new AsyncIterableQueue<SpeechEvent>();\n protected queue = new AsyncIterableQueue<SpeechEvent>();\n protected neededSampleRate?: number;\n protected resampler?: AudioResampler;\n abstract label: string;\n protected closed = false;\n #stt: STT;\n private deferredInputStream: DeferredReadableStream<AudioFrame>;\n private logger = log();\n private _connOptions: APIConnectOptions;\n\n constructor(\n stt: STT,\n sampleRate?: number,\n connectionOptions: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,\n ) {\n this.#stt = stt;\n this._connOptions = connectionOptions;\n this.deferredInputStream = new DeferredReadableStream<AudioFrame>();\n this.neededSampleRate = sampleRate;\n this.monitorMetrics();\n this.pumpInput();\n\n // this is a hack to immitate asyncio.create_task so that mainTask\n // is run **after** the constructor has finished. Otherwise we get\n // runtime error when trying to access class variables in the\n // `run` method.\n startSoon(() => this.mainTask().then(() => this.queue.close()));\n }\n\n private async mainTask() {\n for (let i = 0; i < this._connOptions.maxRetry + 1; i++) {\n try {\n return await this.run();\n } catch (error) {\n if (error instanceof APIError) {\n const retryInterval = this._connOptions._intervalForRetry(i);\n\n if (this._connOptions.maxRetry === 0 || !error.retryable) {\n this.emitError({ error, recoverable: false });\n throw error;\n } else if (i === this._connOptions.maxRetry) {\n this.emitError({ error, recoverable: false });\n throw new APIConnectionError({\n message: `failed to recognize speech after ${this._connOptions.maxRetry + 1} attempts`,\n options: { retryable: false },\n });\n } else {\n this.emitError({ error, recoverable: true });\n this.logger.warn(\n { tts: this.#stt.label, attempt: i + 1, error },\n `failed to recognize speech, retrying in ${retryInterval}s`,\n );\n }\n\n if (retryInterval > 0) {\n await delay(retryInterval);\n }\n } else {\n this.emitError({ error: toError(error), recoverable: false });\n throw error;\n }\n }\n }\n }\n\n private emitError({ error, recoverable }: { error: Error; recoverable: boolean }) {\n this.#stt.emit('error', {\n type: 'stt_error',\n timestamp: Date.now(),\n label: this.#stt.label,\n error,\n recoverable,\n });\n }\n\n protected async pumpInput() {\n // TODO(AJS-35): Implement STT with webstreams API\n const inputStream = this.deferredInputStream.stream;\n const reader = inputStream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n this.pushFrame(value);\n }\n } catch (error) {\n this.logger.error('Error in STTStream mainTask:', error);\n } finally {\n reader.releaseLock();\n }\n }\n\n protected async monitorMetrics() {\n for await (const event of this.queue) {\n this.output.put(event);\n if (event.type !== SpeechEventType.RECOGNITION_USAGE) continue;\n const metrics: STTMetrics = {\n type: 'stt_metrics',\n timestamp: Date.now(),\n requestId: event.requestId!,\n duration: 0,\n label: this.#stt.label,\n audioDuration: event.recognitionUsage!.audioDuration,\n streamed: true,\n };\n this.#stt.emit('metrics_collected', metrics);\n }\n this.output.close();\n }\n\n protected abstract run(): Promise<void>;\n\n updateInputStream(audioStream: ReadableStream<AudioFrame>) {\n this.deferredInputStream.setSource(audioStream);\n }\n\n detachInputStream() {\n this.deferredInputStream.detachSource();\n }\n\n /** Push an audio frame to the STT */\n pushFrame(frame: AudioFrame) {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n\n if (this.neededSampleRate && frame.sampleRate !== this.neededSampleRate) {\n if (!this.resampler) {\n this.resampler = new AudioResampler(frame.sampleRate, this.neededSampleRate);\n }\n }\n\n if (this.resampler) {\n const frames = this.resampler.push(frame);\n for (const frame of frames) {\n this.input.put(frame);\n }\n } else {\n this.input.put(frame);\n }\n }\n\n /** Flush the STT, causing it to process all pending text */\n flush() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.put(SpeechStream.FLUSH_SENTINEL);\n }\n\n /** Mark the input as ended and forbid additional pushes */\n endInput() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.close();\n }\n\n next(): Promise<IteratorResult<SpeechEvent>> {\n return this.output.next();\n }\n\n /** Close both the input and output of the STT stream */\n close() {\n this.input.close();\n this.queue.close();\n this.output.close();\n this.closed = true;\n }\n\n [Symbol.asyncIterator](): SpeechStream {\n return this;\n }\n}\n"],"mappings":"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","names":["SpeechEventType","frame"]}
@@ -1 +1 @@
1
- {"version":3,"file":"stt.d.ts","sourceRoot":"","sources":["../../src/stt/stt.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stt.d.ts","sourceRoot":"","sources":["../../src/stt/stt.ts"],"names":[],"mappings":"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"}
package/dist/stt/stt.js CHANGED
@@ -1,12 +1,11 @@
1
1
  import { AudioResampler } from "@livekit/rtc-node";
2
- import { delay } from "@std/async/delay";
3
2
  import { EventEmitter } from "node:events";
4
3
  import { APIConnectionError, APIError } from "../_exceptions.js";
5
4
  import { calculateAudioDuration } from "../audio.js";
6
5
  import { log } from "../log.js";
7
6
  import { DeferredReadableStream } from "../stream/deferred_stream.js";
8
7
  import { DEFAULT_API_CONNECT_OPTIONS } from "../types.js";
9
- import { AsyncIterableQueue, startSoon, toError } from "../utils.js";
8
+ import { AsyncIterableQueue, delay, startSoon, toError } from "../utils.js";
10
9
  var SpeechEventType = /* @__PURE__ */ ((SpeechEventType2) => {
11
10
  SpeechEventType2[SpeechEventType2["START_OF_SPEECH"] = 0] = "START_OF_SPEECH";
12
11
  SpeechEventType2[SpeechEventType2["INTERIM_TRANSCRIPT"] = 1] = "INTERIM_TRANSCRIPT";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/stt/stt.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type AudioFrame, AudioResampler } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { delay } from '@std/async/delay';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport { APIConnectionError, APIError } from '../_exceptions.js';\nimport { calculateAudioDuration } from '../audio.js';\nimport { log } from '../log.js';\nimport type { STTMetrics } from '../metrics/base.js';\nimport { DeferredReadableStream } from '../stream/deferred_stream.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../types.js';\nimport type { AudioBuffer } from '../utils.js';\nimport { AsyncIterableQueue, startSoon, toError } from '../utils.js';\n\n/** Indicates start/middle/end of speech */\nexport enum SpeechEventType {\n /**\n * Indicate the start of speech.\n * If the STT doesn't support this event, this will be emitted at the same time\n * as the first INTERIM_TRANSCRIPT.\n */\n START_OF_SPEECH = 0,\n /**\n * Interim transcript, useful for real-time transcription.\n */\n INTERIM_TRANSCRIPT = 1,\n /**\n * Final transcript, emitted when the STT is confident enough that a certain\n * portion of the speech will not change.\n */\n FINAL_TRANSCRIPT = 2,\n /**\n * Indicate the end of speech, emitted when the user stops speaking.\n * The first alternative is a combination of all the previous FINAL_TRANSCRIPT events.\n */\n END_OF_SPEECH = 3,\n /** Usage event, emitted periodically to indicate usage metrics. */\n RECOGNITION_USAGE = 4,\n}\n\n/** SpeechData contains metadata about this {@link SpeechEvent}. */\nexport interface SpeechData {\n language: string;\n text: string;\n startTime: number;\n endTime: number;\n confidence: number;\n}\n\nexport interface RecognitionUsage {\n audioDuration: number;\n}\n\n/** SpeechEvent is a packet of speech-to-text data. */\nexport interface SpeechEvent {\n type: SpeechEventType;\n alternatives?: [SpeechData, ...SpeechData[]];\n requestId?: string;\n recognitionUsage?: RecognitionUsage;\n}\n\n/**\n * Describes the capabilities of the STT provider.\n *\n * @remarks\n * At present, the framework only supports providers that have a streaming endpoint.\n */\nexport interface STTCapabilities {\n streaming: boolean;\n interimResults: boolean;\n}\n\nexport interface STTError {\n type: 'stt_error';\n timestamp: number;\n label: string;\n error: Error;\n recoverable: boolean;\n}\n\nexport type STTCallbacks = {\n ['metrics_collected']: (metrics: STTMetrics) => void;\n ['error']: (error: STTError) => void;\n};\n\n/**\n * An instance of a speech-to-text adapter.\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child STT class, which inherits this class's methods.\n */\nexport abstract class STT extends (EventEmitter as new () => TypedEmitter<STTCallbacks>) {\n abstract label: string;\n #capabilities: STTCapabilities;\n\n constructor(capabilities: STTCapabilities) {\n super();\n this.#capabilities = capabilities;\n }\n\n /** Returns this STT's capabilities */\n get capabilities(): STTCapabilities {\n return this.#capabilities;\n }\n\n /** Receives an audio buffer and returns transcription in the form of a {@link SpeechEvent} */\n async recognize(frame: AudioBuffer): Promise<SpeechEvent> {\n const startTime = process.hrtime.bigint();\n const event = await this._recognize(frame);\n const duration = Number((process.hrtime.bigint() - startTime) / BigInt(1000000));\n this.emit('metrics_collected', {\n type: 'stt_metrics',\n requestId: event.requestId ?? '',\n timestamp: Date.now(),\n duration,\n label: this.label,\n audioDuration: calculateAudioDuration(frame),\n streamed: false,\n });\n return event;\n }\n protected abstract _recognize(frame: AudioBuffer): Promise<SpeechEvent>;\n\n /**\n * Returns a {@link SpeechStream} that can be used to push audio frames and receive\n * transcriptions\n */\n abstract stream(): SpeechStream;\n}\n\n/**\n * An instance of a speech-to-text stream, as an asynchronous iterable iterator.\n *\n * @example Looping through frames\n * ```ts\n * for await (const event of stream) {\n * if (event.type === SpeechEventType.FINAL_TRANSCRIPT) {\n * console.log(event.alternatives[0].text)\n * }\n * }\n * ```\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child SpeechStream class, which inherits this class's methods.\n */\nexport abstract class SpeechStream implements AsyncIterableIterator<SpeechEvent> {\n protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');\n protected input = new AsyncIterableQueue<AudioFrame | typeof SpeechStream.FLUSH_SENTINEL>();\n protected output = new AsyncIterableQueue<SpeechEvent>();\n protected queue = new AsyncIterableQueue<SpeechEvent>();\n protected neededSampleRate?: number;\n protected resampler?: AudioResampler;\n abstract label: string;\n protected closed = false;\n #stt: STT;\n private deferredInputStream: DeferredReadableStream<AudioFrame>;\n private logger = log();\n private _connOptions: APIConnectOptions;\n\n constructor(\n stt: STT,\n sampleRate?: number,\n connectionOptions: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,\n ) {\n this.#stt = stt;\n this._connOptions = connectionOptions;\n this.deferredInputStream = new DeferredReadableStream<AudioFrame>();\n this.neededSampleRate = sampleRate;\n this.monitorMetrics();\n this.pumpInput();\n\n // this is a hack to immitate asyncio.create_task so that mainTask\n // is run **after** the constructor has finished. Otherwise we get\n // runtime error when trying to access class variables in the\n // `run` method.\n startSoon(() => this.mainTask().then(() => this.queue.close()));\n }\n\n private async mainTask() {\n for (let i = 0; i < this._connOptions.maxRetry + 1; i++) {\n try {\n return await this.run();\n } catch (error) {\n if (error instanceof APIError) {\n const retryInterval = this._connOptions._intervalForRetry(i);\n\n if (this._connOptions.maxRetry === 0 || !error.retryable) {\n this.emitError({ error, recoverable: false });\n throw error;\n } else if (i === this._connOptions.maxRetry) {\n this.emitError({ error, recoverable: false });\n throw new APIConnectionError({\n message: `failed to recognize speech after ${this._connOptions.maxRetry + 1} attempts`,\n options: { retryable: false },\n });\n } else {\n this.emitError({ error, recoverable: true });\n this.logger.warn(\n { tts: this.#stt.label, attempt: i + 1, error },\n `failed to recognize speech, retrying in ${retryInterval}s`,\n );\n }\n\n if (retryInterval > 0) {\n await delay(retryInterval);\n }\n } else {\n this.emitError({ error: toError(error), recoverable: false });\n throw error;\n }\n }\n }\n }\n\n private emitError({ error, recoverable }: { error: Error; recoverable: boolean }) {\n this.#stt.emit('error', {\n type: 'stt_error',\n timestamp: Date.now(),\n label: this.#stt.label,\n error,\n recoverable,\n });\n }\n\n protected async pumpInput() {\n // TODO(AJS-35): Implement STT with webstreams API\n const inputStream = this.deferredInputStream.stream;\n const reader = inputStream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n this.pushFrame(value);\n }\n } catch (error) {\n this.logger.error('Error in STTStream mainTask:', error);\n } finally {\n reader.releaseLock();\n }\n }\n\n protected async monitorMetrics() {\n for await (const event of this.queue) {\n this.output.put(event);\n if (event.type !== SpeechEventType.RECOGNITION_USAGE) continue;\n const metrics: STTMetrics = {\n type: 'stt_metrics',\n timestamp: Date.now(),\n requestId: event.requestId!,\n duration: 0,\n label: this.#stt.label,\n audioDuration: event.recognitionUsage!.audioDuration,\n streamed: true,\n };\n this.#stt.emit('metrics_collected', metrics);\n }\n this.output.close();\n }\n\n protected abstract run(): Promise<void>;\n\n updateInputStream(audioStream: ReadableStream<AudioFrame>) {\n this.deferredInputStream.setSource(audioStream);\n }\n\n detachInputStream() {\n this.deferredInputStream.detachSource();\n }\n\n /** Push an audio frame to the STT */\n pushFrame(frame: AudioFrame) {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n\n if (this.neededSampleRate && frame.sampleRate !== this.neededSampleRate) {\n if (!this.resampler) {\n this.resampler = new AudioResampler(frame.sampleRate, this.neededSampleRate);\n }\n }\n\n if (this.resampler) {\n const frames = this.resampler.push(frame);\n for (const frame of frames) {\n this.input.put(frame);\n }\n } else {\n this.input.put(frame);\n }\n }\n\n /** Flush the STT, causing it to process all pending text */\n flush() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.put(SpeechStream.FLUSH_SENTINEL);\n }\n\n /** Mark the input as ended and forbid additional pushes */\n endInput() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.close();\n }\n\n next(): Promise<IteratorResult<SpeechEvent>> {\n return this.output.next();\n }\n\n /** Close both the input and output of the STT stream */\n close() {\n this.input.close();\n this.queue.close();\n this.output.close();\n this.closed = true;\n }\n\n [Symbol.asyncIterator](): SpeechStream {\n return this;\n }\n}\n"],"mappings":"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","names":["SpeechEventType","frame"]}
1
+ {"version":3,"sources":["../../src/stt/stt.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type AudioFrame, AudioResampler } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport { APIConnectionError, APIError } from '../_exceptions.js';\nimport { calculateAudioDuration } from '../audio.js';\nimport { log } from '../log.js';\nimport type { STTMetrics } from '../metrics/base.js';\nimport { DeferredReadableStream } from '../stream/deferred_stream.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../types.js';\nimport type { AudioBuffer } from '../utils.js';\nimport { AsyncIterableQueue, delay, startSoon, toError } from '../utils.js';\n\n/** Indicates start/middle/end of speech */\nexport enum SpeechEventType {\n /**\n * Indicate the start of speech.\n * If the STT doesn't support this event, this will be emitted at the same time\n * as the first INTERIM_TRANSCRIPT.\n */\n START_OF_SPEECH = 0,\n /**\n * Interim transcript, useful for real-time transcription.\n */\n INTERIM_TRANSCRIPT = 1,\n /**\n * Final transcript, emitted when the STT is confident enough that a certain\n * portion of the speech will not change.\n */\n FINAL_TRANSCRIPT = 2,\n /**\n * Indicate the end of speech, emitted when the user stops speaking.\n * The first alternative is a combination of all the previous FINAL_TRANSCRIPT events.\n */\n END_OF_SPEECH = 3,\n /** Usage event, emitted periodically to indicate usage metrics. */\n RECOGNITION_USAGE = 4,\n}\n\n/** SpeechData contains metadata about this {@link SpeechEvent}. */\nexport interface SpeechData {\n language: string;\n text: string;\n startTime: number;\n endTime: number;\n confidence: number;\n}\n\nexport interface RecognitionUsage {\n audioDuration: number;\n}\n\n/** SpeechEvent is a packet of speech-to-text data. */\nexport interface SpeechEvent {\n type: SpeechEventType;\n alternatives?: [SpeechData, ...SpeechData[]];\n requestId?: string;\n recognitionUsage?: RecognitionUsage;\n}\n\n/**\n * Describes the capabilities of the STT provider.\n *\n * @remarks\n * At present, the framework only supports providers that have a streaming endpoint.\n */\nexport interface STTCapabilities {\n streaming: boolean;\n interimResults: boolean;\n}\n\nexport interface STTError {\n type: 'stt_error';\n timestamp: number;\n label: string;\n error: Error;\n recoverable: boolean;\n}\n\nexport type STTCallbacks = {\n ['metrics_collected']: (metrics: STTMetrics) => void;\n ['error']: (error: STTError) => void;\n};\n\n/**\n * An instance of a speech-to-text adapter.\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child STT class, which inherits this class's methods.\n */\nexport abstract class STT extends (EventEmitter as new () => TypedEmitter<STTCallbacks>) {\n abstract label: string;\n #capabilities: STTCapabilities;\n\n constructor(capabilities: STTCapabilities) {\n super();\n this.#capabilities = capabilities;\n }\n\n /** Returns this STT's capabilities */\n get capabilities(): STTCapabilities {\n return this.#capabilities;\n }\n\n /** Receives an audio buffer and returns transcription in the form of a {@link SpeechEvent} */\n async recognize(frame: AudioBuffer): Promise<SpeechEvent> {\n const startTime = process.hrtime.bigint();\n const event = await this._recognize(frame);\n const duration = Number((process.hrtime.bigint() - startTime) / BigInt(1000000));\n this.emit('metrics_collected', {\n type: 'stt_metrics',\n requestId: event.requestId ?? '',\n timestamp: Date.now(),\n duration,\n label: this.label,\n audioDuration: calculateAudioDuration(frame),\n streamed: false,\n });\n return event;\n }\n protected abstract _recognize(frame: AudioBuffer): Promise<SpeechEvent>;\n\n /**\n * Returns a {@link SpeechStream} that can be used to push audio frames and receive\n * transcriptions\n */\n abstract stream(): SpeechStream;\n}\n\n/**\n * An instance of a speech-to-text stream, as an asynchronous iterable iterator.\n *\n * @example Looping through frames\n * ```ts\n * for await (const event of stream) {\n * if (event.type === SpeechEventType.FINAL_TRANSCRIPT) {\n * console.log(event.alternatives[0].text)\n * }\n * }\n * ```\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child SpeechStream class, which inherits this class's methods.\n */\nexport abstract class SpeechStream implements AsyncIterableIterator<SpeechEvent> {\n protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');\n protected input = new AsyncIterableQueue<AudioFrame | typeof SpeechStream.FLUSH_SENTINEL>();\n protected output = new AsyncIterableQueue<SpeechEvent>();\n protected queue = new AsyncIterableQueue<SpeechEvent>();\n protected neededSampleRate?: number;\n protected resampler?: AudioResampler;\n abstract label: string;\n protected closed = false;\n #stt: STT;\n private deferredInputStream: DeferredReadableStream<AudioFrame>;\n private logger = log();\n private _connOptions: APIConnectOptions;\n\n constructor(\n stt: STT,\n sampleRate?: number,\n connectionOptions: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,\n ) {\n this.#stt = stt;\n this._connOptions = connectionOptions;\n this.deferredInputStream = new DeferredReadableStream<AudioFrame>();\n this.neededSampleRate = sampleRate;\n this.monitorMetrics();\n this.pumpInput();\n\n // this is a hack to immitate asyncio.create_task so that mainTask\n // is run **after** the constructor has finished. Otherwise we get\n // runtime error when trying to access class variables in the\n // `run` method.\n startSoon(() => this.mainTask().then(() => this.queue.close()));\n }\n\n private async mainTask() {\n for (let i = 0; i < this._connOptions.maxRetry + 1; i++) {\n try {\n return await this.run();\n } catch (error) {\n if (error instanceof APIError) {\n const retryInterval = this._connOptions._intervalForRetry(i);\n\n if (this._connOptions.maxRetry === 0 || !error.retryable) {\n this.emitError({ error, recoverable: false });\n throw error;\n } else if (i === this._connOptions.maxRetry) {\n this.emitError({ error, recoverable: false });\n throw new APIConnectionError({\n message: `failed to recognize speech after ${this._connOptions.maxRetry + 1} attempts`,\n options: { retryable: false },\n });\n } else {\n this.emitError({ error, recoverable: true });\n this.logger.warn(\n { tts: this.#stt.label, attempt: i + 1, error },\n `failed to recognize speech, retrying in ${retryInterval}s`,\n );\n }\n\n if (retryInterval > 0) {\n await delay(retryInterval);\n }\n } else {\n this.emitError({ error: toError(error), recoverable: false });\n throw error;\n }\n }\n }\n }\n\n private emitError({ error, recoverable }: { error: Error; recoverable: boolean }) {\n this.#stt.emit('error', {\n type: 'stt_error',\n timestamp: Date.now(),\n label: this.#stt.label,\n error,\n recoverable,\n });\n }\n\n protected async pumpInput() {\n // TODO(AJS-35): Implement STT with webstreams API\n const inputStream = this.deferredInputStream.stream;\n const reader = inputStream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n this.pushFrame(value);\n }\n } catch (error) {\n this.logger.error('Error in STTStream mainTask:', error);\n } finally {\n reader.releaseLock();\n }\n }\n\n protected async monitorMetrics() {\n for await (const event of this.queue) {\n this.output.put(event);\n if (event.type !== SpeechEventType.RECOGNITION_USAGE) continue;\n const metrics: STTMetrics = {\n type: 'stt_metrics',\n timestamp: Date.now(),\n requestId: event.requestId!,\n duration: 0,\n label: this.#stt.label,\n audioDuration: event.recognitionUsage!.audioDuration,\n streamed: true,\n };\n this.#stt.emit('metrics_collected', metrics);\n }\n this.output.close();\n }\n\n protected abstract run(): Promise<void>;\n\n updateInputStream(audioStream: ReadableStream<AudioFrame>) {\n this.deferredInputStream.setSource(audioStream);\n }\n\n detachInputStream() {\n this.deferredInputStream.detachSource();\n }\n\n /** Push an audio frame to the STT */\n pushFrame(frame: AudioFrame) {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n\n if (this.neededSampleRate && frame.sampleRate !== this.neededSampleRate) {\n if (!this.resampler) {\n this.resampler = new AudioResampler(frame.sampleRate, this.neededSampleRate);\n }\n }\n\n if (this.resampler) {\n const frames = this.resampler.push(frame);\n for (const frame of frames) {\n this.input.put(frame);\n }\n } else {\n this.input.put(frame);\n }\n }\n\n /** Flush the STT, causing it to process all pending text */\n flush() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.put(SpeechStream.FLUSH_SENTINEL);\n }\n\n /** Mark the input as ended and forbid additional pushes */\n endInput() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.close();\n }\n\n next(): Promise<IteratorResult<SpeechEvent>> {\n return this.output.next();\n }\n\n /** Close both the input and output of the STT stream */\n close() {\n this.input.close();\n this.queue.close();\n this.output.close();\n this.closed = true;\n }\n\n [Symbol.asyncIterator](): SpeechStream {\n return this;\n }\n}\n"],"mappings":"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","names":["SpeechEventType","frame"]}
package/dist/tts/tts.cjs CHANGED
@@ -23,7 +23,6 @@ __export(tts_exports, {
23
23
  TTS: () => TTS
24
24
  });
25
25
  module.exports = __toCommonJS(tts_exports);
26
- var import_async = require("@std/async");
27
26
  var import_node_events = require("node:events");
28
27
  var import_exceptions = require("../_exceptions.cjs");
29
28
  var import_log = require("../log.cjs");
@@ -105,7 +104,7 @@ class SynthesizeStream {
105
104
  );
106
105
  }
107
106
  if (retryInterval > 0) {
108
- await (0, import_async.delay)(retryInterval);
107
+ await (0, import_utils.delay)(retryInterval);
109
108
  }
110
109
  } else {
111
110
  this.emitError({ error: (0, import_utils.toError)(error), recoverable: false });
@@ -281,7 +280,7 @@ class ChunkedStream {
281
280
  );
282
281
  }
283
282
  if (retryInterval > 0) {
284
- await (0, import_async.delay)(retryInterval);
283
+ await (0, import_utils.delay)(retryInterval);
285
284
  }
286
285
  } else {
287
286
  this.emitError({ error: (0, import_utils.toError)(error), recoverable: false });