@livekit/agents 1.0.46 → 1.0.47

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 (151) hide show
  1. package/dist/cli.cjs +14 -20
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +14 -20
  5. package/dist/cli.js.map +1 -1
  6. package/dist/ipc/job_proc_lazy_main.cjs +14 -5
  7. package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
  8. package/dist/ipc/job_proc_lazy_main.js +14 -5
  9. package/dist/ipc/job_proc_lazy_main.js.map +1 -1
  10. package/dist/llm/chat_context.cjs +19 -0
  11. package/dist/llm/chat_context.cjs.map +1 -1
  12. package/dist/llm/chat_context.d.cts +4 -0
  13. package/dist/llm/chat_context.d.ts +4 -0
  14. package/dist/llm/chat_context.d.ts.map +1 -1
  15. package/dist/llm/chat_context.js +19 -0
  16. package/dist/llm/chat_context.js.map +1 -1
  17. package/dist/llm/provider_format/index.cjs +2 -0
  18. package/dist/llm/provider_format/index.cjs.map +1 -1
  19. package/dist/llm/provider_format/index.d.cts +1 -1
  20. package/dist/llm/provider_format/index.d.ts +1 -1
  21. package/dist/llm/provider_format/index.d.ts.map +1 -1
  22. package/dist/llm/provider_format/index.js +6 -1
  23. package/dist/llm/provider_format/index.js.map +1 -1
  24. package/dist/llm/provider_format/openai.cjs +82 -2
  25. package/dist/llm/provider_format/openai.cjs.map +1 -1
  26. package/dist/llm/provider_format/openai.d.cts +1 -0
  27. package/dist/llm/provider_format/openai.d.ts +1 -0
  28. package/dist/llm/provider_format/openai.d.ts.map +1 -1
  29. package/dist/llm/provider_format/openai.js +80 -1
  30. package/dist/llm/provider_format/openai.js.map +1 -1
  31. package/dist/llm/provider_format/openai.test.cjs +326 -0
  32. package/dist/llm/provider_format/openai.test.cjs.map +1 -1
  33. package/dist/llm/provider_format/openai.test.js +327 -1
  34. package/dist/llm/provider_format/openai.test.js.map +1 -1
  35. package/dist/llm/provider_format/utils.cjs +4 -3
  36. package/dist/llm/provider_format/utils.cjs.map +1 -1
  37. package/dist/llm/provider_format/utils.d.ts.map +1 -1
  38. package/dist/llm/provider_format/utils.js +4 -3
  39. package/dist/llm/provider_format/utils.js.map +1 -1
  40. package/dist/llm/realtime.cjs.map +1 -1
  41. package/dist/llm/realtime.d.cts +1 -0
  42. package/dist/llm/realtime.d.ts +1 -0
  43. package/dist/llm/realtime.d.ts.map +1 -1
  44. package/dist/llm/realtime.js.map +1 -1
  45. package/dist/log.cjs +5 -2
  46. package/dist/log.cjs.map +1 -1
  47. package/dist/log.d.ts.map +1 -1
  48. package/dist/log.js +5 -2
  49. package/dist/log.js.map +1 -1
  50. package/dist/stream/deferred_stream.cjs +15 -6
  51. package/dist/stream/deferred_stream.cjs.map +1 -1
  52. package/dist/stream/deferred_stream.d.ts.map +1 -1
  53. package/dist/stream/deferred_stream.js +15 -6
  54. package/dist/stream/deferred_stream.js.map +1 -1
  55. package/dist/utils.cjs +31 -2
  56. package/dist/utils.cjs.map +1 -1
  57. package/dist/utils.d.cts +7 -0
  58. package/dist/utils.d.ts +7 -0
  59. package/dist/utils.d.ts.map +1 -1
  60. package/dist/utils.js +31 -2
  61. package/dist/utils.js.map +1 -1
  62. package/dist/utils.test.cjs +71 -0
  63. package/dist/utils.test.cjs.map +1 -1
  64. package/dist/utils.test.js +71 -0
  65. package/dist/utils.test.js.map +1 -1
  66. package/dist/version.cjs +1 -1
  67. package/dist/version.cjs.map +1 -1
  68. package/dist/version.d.cts +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/dist/version.d.ts.map +1 -1
  71. package/dist/version.js +1 -1
  72. package/dist/version.js.map +1 -1
  73. package/dist/voice/agent.cjs +144 -12
  74. package/dist/voice/agent.cjs.map +1 -1
  75. package/dist/voice/agent.d.cts +29 -4
  76. package/dist/voice/agent.d.ts +29 -4
  77. package/dist/voice/agent.d.ts.map +1 -1
  78. package/dist/voice/agent.js +140 -11
  79. package/dist/voice/agent.js.map +1 -1
  80. package/dist/voice/agent.test.cjs +120 -0
  81. package/dist/voice/agent.test.cjs.map +1 -1
  82. package/dist/voice/agent.test.js +122 -2
  83. package/dist/voice/agent.test.js.map +1 -1
  84. package/dist/voice/agent_activity.cjs +383 -298
  85. package/dist/voice/agent_activity.cjs.map +1 -1
  86. package/dist/voice/agent_activity.d.cts +34 -7
  87. package/dist/voice/agent_activity.d.ts +34 -7
  88. package/dist/voice/agent_activity.d.ts.map +1 -1
  89. package/dist/voice/agent_activity.js +383 -293
  90. package/dist/voice/agent_activity.js.map +1 -1
  91. package/dist/voice/agent_session.cjs +140 -40
  92. package/dist/voice/agent_session.cjs.map +1 -1
  93. package/dist/voice/agent_session.d.cts +19 -7
  94. package/dist/voice/agent_session.d.ts +19 -7
  95. package/dist/voice/agent_session.d.ts.map +1 -1
  96. package/dist/voice/agent_session.js +137 -37
  97. package/dist/voice/agent_session.js.map +1 -1
  98. package/dist/voice/audio_recognition.cjs +4 -0
  99. package/dist/voice/audio_recognition.cjs.map +1 -1
  100. package/dist/voice/audio_recognition.d.ts.map +1 -1
  101. package/dist/voice/audio_recognition.js +4 -0
  102. package/dist/voice/audio_recognition.js.map +1 -1
  103. package/dist/voice/generation.cjs +39 -19
  104. package/dist/voice/generation.cjs.map +1 -1
  105. package/dist/voice/generation.d.ts.map +1 -1
  106. package/dist/voice/generation.js +44 -20
  107. package/dist/voice/generation.js.map +1 -1
  108. package/dist/voice/index.cjs +2 -0
  109. package/dist/voice/index.cjs.map +1 -1
  110. package/dist/voice/index.d.cts +1 -1
  111. package/dist/voice/index.d.ts +1 -1
  112. package/dist/voice/index.d.ts.map +1 -1
  113. package/dist/voice/index.js +2 -1
  114. package/dist/voice/index.js.map +1 -1
  115. package/dist/voice/speech_handle.cjs +7 -1
  116. package/dist/voice/speech_handle.cjs.map +1 -1
  117. package/dist/voice/speech_handle.d.cts +2 -0
  118. package/dist/voice/speech_handle.d.ts +2 -0
  119. package/dist/voice/speech_handle.d.ts.map +1 -1
  120. package/dist/voice/speech_handle.js +8 -2
  121. package/dist/voice/speech_handle.js.map +1 -1
  122. package/dist/voice/testing/run_result.cjs +66 -15
  123. package/dist/voice/testing/run_result.cjs.map +1 -1
  124. package/dist/voice/testing/run_result.d.cts +14 -3
  125. package/dist/voice/testing/run_result.d.ts +14 -3
  126. package/dist/voice/testing/run_result.d.ts.map +1 -1
  127. package/dist/voice/testing/run_result.js +66 -15
  128. package/dist/voice/testing/run_result.js.map +1 -1
  129. package/package.json +1 -1
  130. package/src/cli.ts +20 -33
  131. package/src/ipc/job_proc_lazy_main.ts +16 -5
  132. package/src/llm/chat_context.ts +35 -0
  133. package/src/llm/provider_format/index.ts +7 -2
  134. package/src/llm/provider_format/openai.test.ts +385 -1
  135. package/src/llm/provider_format/openai.ts +103 -0
  136. package/src/llm/provider_format/utils.ts +6 -4
  137. package/src/llm/realtime.ts +1 -0
  138. package/src/log.ts +5 -2
  139. package/src/stream/deferred_stream.ts +17 -6
  140. package/src/utils.test.ts +87 -0
  141. package/src/utils.ts +36 -2
  142. package/src/version.ts +1 -1
  143. package/src/voice/agent.test.ts +140 -2
  144. package/src/voice/agent.ts +189 -10
  145. package/src/voice/agent_activity.ts +427 -289
  146. package/src/voice/agent_session.ts +178 -40
  147. package/src/voice/audio_recognition.ts +4 -0
  148. package/src/voice/generation.ts +52 -23
  149. package/src/voice/index.ts +1 -1
  150. package/src/voice/speech_handle.ts +9 -2
  151. package/src/voice/testing/run_result.ts +81 -23
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { AudioFrame } from '@livekit/rtc-node';\nimport { ReadableStream } from 'node:stream/web';\nimport { describe, expect, it } from 'vitest';\nimport { initializeLogger } from '../src/log.js';\nimport { Event, Task, TaskResult, delay, isPending, resampleStream } from '../src/utils.js';\n\ndescribe('utils', () => {\n // initialize logger\n initializeLogger({ pretty: true, level: 'debug' });\n\n describe('Task', () => {\n it('should execute task successfully and return result', async () => {\n const expectedResult = 'task completed';\n const task = Task.from(async () => {\n await delay(10);\n return expectedResult;\n });\n\n expect(task.done).toBe(false);\n const result = await task.result;\n expect(result).toBe(expectedResult);\n expect(task.done).toBe(true);\n });\n\n it('should handle task errors properly', async () => {\n const expectedError = new Error('Task failed');\n const task = Task.from(async () => {\n await delay(10);\n throw expectedError;\n });\n\n expect(task.done).toBe(false);\n await expect(task.result).rejects.toThrow(expectedError);\n expect(task.done).toBe(true);\n });\n\n it('should cancel task when cancel is called', async () => {\n let taskStarted = false;\n let taskCompleted = false;\n\n const task = Task.from(async (controller) => {\n taskStarted = true;\n await delay(100, { signal: controller.signal });\n taskCompleted = true;\n return 'should not complete';\n });\n\n // Wait a bit to ensure task starts\n await delay(10);\n expect(taskStarted).toBe(true);\n expect(task.done).toBe(false);\n\n // Cancel the task\n task.cancel();\n\n // The task should reject with AbortError\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(taskCompleted).toBe(false);\n expect(task.done).toBe(true);\n });\n\n it('should use provided AbortController', async () => {\n const controller = new AbortController();\n const task = Task.from(async (ctrl) => {\n expect(ctrl).toBe(controller);\n await delay(100, { signal: ctrl.signal });\n return 'completed';\n }, controller);\n\n await delay(10);\n controller.abort();\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle immediate resolution', async () => {\n const task = Task.from(async () => {\n return 'immediate';\n });\n\n const result = await task.result;\n expect(result).toBe('immediate');\n expect(task.done).toBe(true);\n });\n\n it('should handle immediate rejection', async () => {\n const expectedError = new Error('Immediate error');\n const task = Task.from(async () => {\n throw expectedError;\n });\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect(error).toBe(expectedError);\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle multiple calls to cancel', async () => {\n const task = Task.from(async (controller) => {\n await delay(100, { signal: controller.signal });\n return 'should not complete';\n });\n\n await delay(10);\n\n // Multiple cancellations should not cause issues\n task.cancel();\n task.cancel();\n task.cancel();\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle task that checks abort signal manually', async () => {\n const arr: number[] = [];\n const task = Task.from(async (controller) => {\n for (let i = 0; i < 10; i++) {\n if (controller.signal.aborted) {\n throw new Error('Task was aborted');\n }\n await delay(10);\n arr.push(i);\n }\n return 'completed';\n });\n\n await delay(39);\n task.cancel();\n\n expect(arr).toEqual([0, 1, 2]);\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).message).toBe('Task was aborted');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle cleanup in finally block', async () => {\n let cleanupExecuted = false;\n\n const task = Task.from(async (controller) => {\n try {\n await delay(100, { signal: controller.signal });\n return 'completed';\n } finally {\n cleanupExecuted = true;\n }\n });\n\n await delay(10);\n task.cancel();\n\n try {\n await task.result;\n } catch {\n // Ignore the abort error\n }\n\n // Cleanup should still execute even when cancelled\n expect(cleanupExecuted).toBe(true);\n });\n\n it('should handle accessing result multiple times', async () => {\n const task = Task.from(async () => {\n await delay(10);\n return 'result';\n });\n\n const result1 = await task.result;\n const result2 = await task.result;\n const result3 = await task.result;\n\n expect(result1).toBe('result');\n expect(result2).toBe('result');\n expect(result3).toBe('result');\n expect(task.done).toBe(true);\n });\n\n it('should handle accessing result promise before completion', async () => {\n const task = Task.from(async () => {\n await delay(50);\n return 'delayed result';\n });\n\n // Get references to result promise before completion\n const resultPromise1 = task.result;\n const resultPromise2 = task.result;\n\n expect(task.done).toBe(false);\n\n // Both promises should resolve to the same value\n const [result1, result2] = await Promise.all([resultPromise1, resultPromise2]);\n\n expect(result1).toBe('delayed result');\n expect(result2).toBe('delayed result');\n expect(task.done).toBe(true);\n });\n\n it('should cancel child tasks when parent task is canceled', async () => {\n let parentStarted = false;\n let child1Started = false;\n let child2Started = false;\n let parentCompleted = false;\n let child1Completed = false;\n let child2Completed = false;\n\n let child1Task: Task<string> | undefined = undefined;\n let child2Task: Task<string> | undefined = undefined;\n\n const parentTask = Task.from(async (controller) => {\n parentStarted = true;\n\n // Create two child tasks using the parent's controller\n child1Task = Task.from(async (childController) => {\n child1Started = true;\n await delay(100, { signal: childController.signal });\n child1Completed = true;\n return 'child1';\n }, controller);\n\n child2Task = Task.from(async (childController) => {\n child2Started = true;\n await delay(100, { signal: childController.signal });\n child2Completed = true;\n return 'child2';\n }, controller);\n\n // Wait for both child tasks\n const results = await Promise.all([child1Task.result, child2Task.result]);\n parentCompleted = true;\n return results;\n });\n\n // Let tasks start\n await delay(20);\n\n // Verify tasks have started\n expect(parentStarted).toBe(true);\n expect(child1Started).toBe(true);\n expect(child2Started).toBe(true);\n\n // Cancel parent task\n parentTask.cancel();\n\n // Use Promise.allSettled to handle all promise settlements\n const [parentResult, child1Result, child2Result] = await Promise.allSettled([\n parentTask.result,\n child1Task!.result,\n child2Task!.result,\n ]);\n\n // Verify all tasks were rejected with AbortError\n expect(parentResult.status).toBe('rejected');\n expect((parentResult as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n expect(child1Result.status).toBe('rejected');\n expect((child1Result as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n expect(child2Result.status).toBe('rejected');\n expect((child2Result as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n // Verify none of the tasks completed\n expect(parentCompleted).toBe(false);\n expect(child1Completed).toBe(false);\n expect(child2Completed).toBe(false);\n expect(parentTask.done).toBe(true);\n expect(child1Task!.done).toBe(true);\n expect(child2Task!.done).toBe(true);\n });\n\n it('should handle nested tasks that complete successfully', async () => {\n const results: string[] = [];\n\n const parentTask = Task.from(async (controller) => {\n results.push('parent-start');\n\n // Create first child task\n const child1Task = Task.from(async () => {\n results.push('child1-start');\n await delay(25);\n results.push('child1-end');\n return 'child1-result';\n }, controller);\n\n // Create second child task that depends on first\n const child2Task = Task.from(async (childController) => {\n results.push('child2-start');\n\n // Create a grandchild task\n const grandchildTask = Task.from(async () => {\n results.push('grandchild-start');\n await delay(10);\n results.push('grandchild-end');\n return 'grandchild-result';\n }, childController);\n\n const grandchildResult = await grandchildTask.result;\n await delay(10);\n results.push('child2-end');\n return `child2-result-with-${grandchildResult}`;\n }, controller);\n\n // Wait for all tasks\n const [child1Result, child2Result] = await Promise.all([\n child1Task.result,\n child2Task.result,\n ]);\n\n results.push('parent-end');\n return {\n parent: 'parent-result',\n child1: child1Result,\n child2: child2Result,\n };\n });\n\n // Wait for everything to complete\n const finalResult = await parentTask.result;\n\n // Verify results\n expect(finalResult).toEqual({\n parent: 'parent-result',\n child1: 'child1-result',\n child2: 'child2-result-with-grandchild-result',\n });\n\n // Verify execution order\n // Check important ordering constraints without being strict about parallel task ordering\n expect(results).toEqual([\n 'parent-start',\n 'child1-start',\n 'child2-start',\n 'grandchild-start',\n 'grandchild-end',\n 'child2-end',\n 'child1-end',\n 'parent-end',\n ]);\n\n // All tasks should be done\n expect(parentTask.done).toBe(true);\n });\n\n it('should propagate errors from nested tasks', async () => {\n let parentError: Error | null = null;\n let child1Completed = false;\n let child2Started = false;\n\n const parentTask = Task.from(async (controller) => {\n const child1Task = Task.from(async () => {\n await delay(20);\n throw new Error('child1 error');\n }, controller);\n\n const child2Task = Task.from(async () => {\n child2Started = true;\n await delay(30);\n child1Completed = true;\n return 'child2-result';\n }, controller);\n\n // This will throw when child1 fails\n const results = await Promise.all([child1Task.result, child2Task.result]);\n return results;\n });\n\n // Wait for the parent task to fail\n try {\n await parentTask.result;\n expect.fail('Parent task should have thrown');\n } catch (error: unknown) {\n parentError = error as Error;\n }\n\n // Verify the error propagated correctly\n expect(parentError?.message).toBe('child1 error');\n expect(child1Completed).toBe(false);\n expect(child2Started).toBe(true);\n expect(parentTask.done).toBe(true);\n });\n\n it('should cancel and wait for task completion', async () => {\n let taskCompleted = false;\n\n const task = Task.from(async (controller) => {\n await delay(5000, { signal: controller.signal });\n taskCompleted = true;\n return 'should not complete';\n });\n\n // Cancel and wait should complete quickly when task is aborted\n const start = Date.now();\n const result = await task.cancelAndWait(1000);\n const duration = Date.now() - start;\n\n expect(result).toBe(TaskResult.Aborted);\n expect(duration).toBeLessThan(100); // Should not wait for full timeout\n expect(taskCompleted).toBe(false);\n expect(task.done).toBe(true);\n });\n\n it('should timeout if task does not respond to cancellation', async () => {\n const task = Task.from(async () => {\n await delay(1000);\n });\n\n // This should timeout because the task ignores cancellation\n try {\n await task.cancelAndWait(200);\n expect.fail('Task should have timed out');\n } catch (error: unknown) {\n expect(error).instanceof(Error);\n expect((error as Error).message).toBe('Task cancellation timed out');\n }\n });\n\n it('should handle task that completes before timeout', async () => {\n const task = Task.from(async () => {\n await delay(50);\n });\n\n // Start the task\n await delay(10);\n\n // Cancel and wait - but task will complete normally before being canceled\n const result = await task.cancelAndWait(1000);\n\n // Task should have completed normally\n expect(result).toBe(TaskResult.Completed);\n expect(task.done).toBe(true);\n });\n\n it('should propagate non-abort errors from cancelAndWait', async () => {\n const task = Task.from(async () => {\n await delay(10);\n throw new TypeError('Custom error');\n });\n\n try {\n await task.cancelAndWait(1000);\n expect.fail('Task should have thrown');\n } catch (error: unknown) {\n expect((error as Error).message).toBe('Custom error');\n expect((error as Error).name).toBe('TypeError');\n }\n });\n });\n\n describe('Event', () => {\n it('wait resolves immediately when the event is already set', async () => {\n const event = new Event();\n event.set();\n\n const result = await event.wait();\n expect(result).toBe(true);\n });\n\n it('wait resolves after set is called', async () => {\n // check promise is pending\n const event = new Event();\n const waiterPromise = event.wait();\n\n await delay(10);\n expect(await isPending(waiterPromise)).toBe(true);\n\n // check promise is resolved after set is called\n event.set();\n const result = await waiterPromise;\n expect(result).toBe(true);\n });\n\n it('all waiters resolve once set is called', async () => {\n const event = new Event();\n const waiters = [event.wait(), event.wait(), event.wait()];\n\n await delay(10);\n const pendings = await Promise.all(waiters.map((w) => isPending(w)));\n expect(pendings).toEqual([true, true, true]);\n\n event.set();\n const results = await Promise.all(waiters);\n expect(results).toEqual([true, true, true]);\n });\n\n it('wait after 2 seconds is still pending before set', async () => {\n const event = new Event();\n const waiter = event.wait();\n\n await delay(2000);\n expect(await isPending(waiter)).toBe(true);\n\n event.set();\n const result = await waiter;\n expect(result).toBe(true);\n });\n\n it('wait after set and clear should be pending', async () => {\n const event = new Event();\n const waiterBeforeSet = event.wait();\n event.set();\n event.clear();\n\n const waiterAfterSet = event.wait();\n\n const result = await Promise.race([\n waiterBeforeSet.then(() => 'before'),\n waiterAfterSet.then(() => 'after'),\n ]);\n\n expect(result).toBe('before');\n expect(await isPending(waiterBeforeSet)).toBe(false);\n expect(await isPending(waiterAfterSet)).toBe(true);\n\n event.set();\n expect(await waiterAfterSet).toBe(true);\n });\n });\n\n describe('resampleStream', () => {\n const createAudioFrame = (sampleRate: number, samples: number, channels = 1): AudioFrame => {\n const data = new Int16Array(samples * channels);\n for (let i = 0; i < data.length; i++) {\n data[i] = Math.sin((i / samples) * Math.PI * 2) * 16000;\n }\n return new AudioFrame(data, sampleRate, channels, samples);\n };\n\n const streamToArray = async (stream: ReadableStream<AudioFrame>): Promise<AudioFrame[]> => {\n const reader = stream.getReader();\n const chunks: AudioFrame[] = [];\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 return chunks;\n };\n\n it('should resample audio frames to target sample rate', async () => {\n const inputRate = 48000;\n const outputRate = 16000;\n const inputFrame = createAudioFrame(inputRate, 960); // 20ms at 48kHz\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(inputFrame);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(outputRate);\n expect(frame.channels).toBe(inputFrame.channels);\n }\n });\n\n it('should handle same input and output rate', async () => {\n const sampleRate = 44100;\n const inputFrame = createAudioFrame(sampleRate, 1024);\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(inputFrame);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate: sampleRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(sampleRate);\n expect(frame.channels).toBe(inputFrame.channels);\n }\n });\n\n it('should handle multiple input frames', async () => {\n const inputRate = 32000;\n const outputRate = 48000;\n const frame1 = createAudioFrame(inputRate, 640);\n const frame2 = createAudioFrame(inputRate, 640);\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(frame1);\n controller.enqueue(frame2);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(outputRate);\n expect(frame.channels).toBe(frame1.channels);\n }\n });\n\n it('should handle empty stream', async () => {\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate: 44100 });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames).toEqual([]);\n });\n });\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/utils.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { AudioFrame } from '@livekit/rtc-node';\nimport { ReadableStream } from 'node:stream/web';\nimport { describe, expect, it } from 'vitest';\nimport { initializeLogger } from '../src/log.js';\nimport { Event, Task, TaskResult, delay, isPending, resampleStream } from '../src/utils.js';\n\ndescribe('utils', () => {\n // initialize logger\n initializeLogger({ pretty: true, level: 'debug' });\n\n describe('Task', () => {\n it('should execute task successfully and return result', async () => {\n const expectedResult = 'task completed';\n const task = Task.from(async () => {\n await delay(10);\n return expectedResult;\n });\n\n expect(task.done).toBe(false);\n const result = await task.result;\n expect(result).toBe(expectedResult);\n expect(task.done).toBe(true);\n });\n\n it('should handle task errors properly', async () => {\n const expectedError = new Error('Task failed');\n const task = Task.from(async () => {\n await delay(10);\n throw expectedError;\n });\n\n expect(task.done).toBe(false);\n await expect(task.result).rejects.toThrow(expectedError);\n expect(task.done).toBe(true);\n });\n\n it('should cancel task when cancel is called', async () => {\n let taskStarted = false;\n let taskCompleted = false;\n\n const task = Task.from(async (controller) => {\n taskStarted = true;\n await delay(100, { signal: controller.signal });\n taskCompleted = true;\n return 'should not complete';\n });\n\n // Wait a bit to ensure task starts\n await delay(10);\n expect(taskStarted).toBe(true);\n expect(task.done).toBe(false);\n\n // Cancel the task\n task.cancel();\n\n // The task should reject with AbortError\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(taskCompleted).toBe(false);\n expect(task.done).toBe(true);\n });\n\n it('should use provided AbortController', async () => {\n const controller = new AbortController();\n const task = Task.from(async (ctrl) => {\n expect(ctrl).toBe(controller);\n await delay(100, { signal: ctrl.signal });\n return 'completed';\n }, controller);\n\n await delay(10);\n controller.abort();\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle immediate resolution', async () => {\n const task = Task.from(async () => {\n return 'immediate';\n });\n\n const result = await task.result;\n expect(result).toBe('immediate');\n expect(task.done).toBe(true);\n });\n\n it('should handle immediate rejection', async () => {\n const expectedError = new Error('Immediate error');\n const task = Task.from(async () => {\n throw expectedError;\n });\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect(error).toBe(expectedError);\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle multiple calls to cancel', async () => {\n const task = Task.from(async (controller) => {\n await delay(100, { signal: controller.signal });\n return 'should not complete';\n });\n\n await delay(10);\n\n // Multiple cancellations should not cause issues\n task.cancel();\n task.cancel();\n task.cancel();\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle task that checks abort signal manually', async () => {\n const arr: number[] = [];\n const task = Task.from(async (controller) => {\n for (let i = 0; i < 10; i++) {\n if (controller.signal.aborted) {\n throw new Error('Task was aborted');\n }\n await delay(10);\n arr.push(i);\n }\n return 'completed';\n });\n\n await delay(39);\n task.cancel();\n\n expect(arr).toEqual([0, 1, 2]);\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).message).toBe('Task was aborted');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle cleanup in finally block', async () => {\n let cleanupExecuted = false;\n\n const task = Task.from(async (controller) => {\n try {\n await delay(100, { signal: controller.signal });\n return 'completed';\n } finally {\n cleanupExecuted = true;\n }\n });\n\n await delay(10);\n task.cancel();\n\n try {\n await task.result;\n } catch {\n // Ignore the abort error\n }\n\n // Cleanup should still execute even when cancelled\n expect(cleanupExecuted).toBe(true);\n });\n\n it('should handle accessing result multiple times', async () => {\n const task = Task.from(async () => {\n await delay(10);\n return 'result';\n });\n\n const result1 = await task.result;\n const result2 = await task.result;\n const result3 = await task.result;\n\n expect(result1).toBe('result');\n expect(result2).toBe('result');\n expect(result3).toBe('result');\n expect(task.done).toBe(true);\n });\n\n it('should handle accessing result promise before completion', async () => {\n const task = Task.from(async () => {\n await delay(50);\n return 'delayed result';\n });\n\n // Get references to result promise before completion\n const resultPromise1 = task.result;\n const resultPromise2 = task.result;\n\n expect(task.done).toBe(false);\n\n // Both promises should resolve to the same value\n const [result1, result2] = await Promise.all([resultPromise1, resultPromise2]);\n\n expect(result1).toBe('delayed result');\n expect(result2).toBe('delayed result');\n expect(task.done).toBe(true);\n });\n\n it('should cancel child tasks when parent task is canceled', async () => {\n let parentStarted = false;\n let child1Started = false;\n let child2Started = false;\n let parentCompleted = false;\n let child1Completed = false;\n let child2Completed = false;\n\n let child1Task: Task<string> | undefined = undefined;\n let child2Task: Task<string> | undefined = undefined;\n\n const parentTask = Task.from(async (controller) => {\n parentStarted = true;\n\n // Create two child tasks using the parent's controller\n child1Task = Task.from(async (childController) => {\n child1Started = true;\n await delay(100, { signal: childController.signal });\n child1Completed = true;\n return 'child1';\n }, controller);\n\n child2Task = Task.from(async (childController) => {\n child2Started = true;\n await delay(100, { signal: childController.signal });\n child2Completed = true;\n return 'child2';\n }, controller);\n\n // Wait for both child tasks\n const results = await Promise.all([child1Task.result, child2Task.result]);\n parentCompleted = true;\n return results;\n });\n\n // Let tasks start\n await delay(20);\n\n // Verify tasks have started\n expect(parentStarted).toBe(true);\n expect(child1Started).toBe(true);\n expect(child2Started).toBe(true);\n\n // Cancel parent task\n parentTask.cancel();\n\n // Use Promise.allSettled to handle all promise settlements\n const [parentResult, child1Result, child2Result] = await Promise.allSettled([\n parentTask.result,\n child1Task!.result,\n child2Task!.result,\n ]);\n\n // Verify all tasks were rejected with AbortError\n expect(parentResult.status).toBe('rejected');\n expect((parentResult as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n expect(child1Result.status).toBe('rejected');\n expect((child1Result as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n expect(child2Result.status).toBe('rejected');\n expect((child2Result as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n // Verify none of the tasks completed\n expect(parentCompleted).toBe(false);\n expect(child1Completed).toBe(false);\n expect(child2Completed).toBe(false);\n expect(parentTask.done).toBe(true);\n expect(child1Task!.done).toBe(true);\n expect(child2Task!.done).toBe(true);\n });\n\n it('should handle nested tasks that complete successfully', async () => {\n const results: string[] = [];\n\n const parentTask = Task.from(async (controller) => {\n results.push('parent-start');\n\n // Create first child task\n const child1Task = Task.from(async () => {\n results.push('child1-start');\n await delay(25);\n results.push('child1-end');\n return 'child1-result';\n }, controller);\n\n // Create second child task that depends on first\n const child2Task = Task.from(async (childController) => {\n results.push('child2-start');\n\n // Create a grandchild task\n const grandchildTask = Task.from(async () => {\n results.push('grandchild-start');\n await delay(10);\n results.push('grandchild-end');\n return 'grandchild-result';\n }, childController);\n\n const grandchildResult = await grandchildTask.result;\n await delay(10);\n results.push('child2-end');\n return `child2-result-with-${grandchildResult}`;\n }, controller);\n\n // Wait for all tasks\n const [child1Result, child2Result] = await Promise.all([\n child1Task.result,\n child2Task.result,\n ]);\n\n results.push('parent-end');\n return {\n parent: 'parent-result',\n child1: child1Result,\n child2: child2Result,\n };\n });\n\n // Wait for everything to complete\n const finalResult = await parentTask.result;\n\n // Verify results\n expect(finalResult).toEqual({\n parent: 'parent-result',\n child1: 'child1-result',\n child2: 'child2-result-with-grandchild-result',\n });\n\n // Verify execution order\n // Check important ordering constraints without being strict about parallel task ordering\n expect(results).toEqual([\n 'parent-start',\n 'child1-start',\n 'child2-start',\n 'grandchild-start',\n 'grandchild-end',\n 'child2-end',\n 'child1-end',\n 'parent-end',\n ]);\n\n // All tasks should be done\n expect(parentTask.done).toBe(true);\n });\n\n it('should propagate errors from nested tasks', async () => {\n let parentError: Error | null = null;\n let child1Completed = false;\n let child2Started = false;\n\n const parentTask = Task.from(async (controller) => {\n const child1Task = Task.from(async () => {\n await delay(20);\n throw new Error('child1 error');\n }, controller);\n\n const child2Task = Task.from(async () => {\n child2Started = true;\n await delay(30);\n child1Completed = true;\n return 'child2-result';\n }, controller);\n\n // This will throw when child1 fails\n const results = await Promise.all([child1Task.result, child2Task.result]);\n return results;\n });\n\n // Wait for the parent task to fail\n try {\n await parentTask.result;\n expect.fail('Parent task should have thrown');\n } catch (error: unknown) {\n parentError = error as Error;\n }\n\n // Verify the error propagated correctly\n expect(parentError?.message).toBe('child1 error');\n expect(child1Completed).toBe(false);\n expect(child2Started).toBe(true);\n expect(parentTask.done).toBe(true);\n });\n\n it('should cancel and wait for task completion', async () => {\n let taskCompleted = false;\n\n const task = Task.from(async (controller) => {\n await delay(5000, { signal: controller.signal });\n taskCompleted = true;\n return 'should not complete';\n });\n\n // Cancel and wait should complete quickly when task is aborted\n const start = Date.now();\n const result = await task.cancelAndWait(1000);\n const duration = Date.now() - start;\n\n expect(result).toBe(TaskResult.Aborted);\n expect(duration).toBeLessThan(100); // Should not wait for full timeout\n expect(taskCompleted).toBe(false);\n expect(task.done).toBe(true);\n });\n\n it('should timeout if task does not respond to cancellation', async () => {\n const task = Task.from(async () => {\n await delay(1000);\n });\n\n // This should timeout because the task ignores cancellation\n try {\n await task.cancelAndWait(200);\n expect.fail('Task should have timed out');\n } catch (error: unknown) {\n expect(error).instanceof(Error);\n expect((error as Error).message).toBe('Task cancellation timed out');\n }\n });\n\n it('should handle task that completes before timeout', async () => {\n const task = Task.from(async () => {\n await delay(50);\n });\n\n // Start the task\n await delay(10);\n\n // Cancel and wait - but task will complete normally before being canceled\n const result = await task.cancelAndWait(1000);\n\n // Task should have completed normally\n expect(result).toBe(TaskResult.Completed);\n expect(task.done).toBe(true);\n });\n\n it('should propagate non-abort errors from cancelAndWait', async () => {\n const task = Task.from(async () => {\n await delay(10);\n throw new TypeError('Custom error');\n });\n\n try {\n await task.cancelAndWait(1000);\n expect.fail('Task should have thrown');\n } catch (error: unknown) {\n expect((error as Error).message).toBe('Custom error');\n expect((error as Error).name).toBe('TypeError');\n }\n });\n\n it('should return undefined for Task.current outside task context', () => {\n expect(Task.current()).toBeUndefined();\n });\n\n it('should preserve Task.current inside a task across awaits', async () => {\n const task = Task.from(\n async () => {\n const currentAtStart = Task.current();\n await delay(5);\n const currentAfterAwait = Task.current();\n\n expect(currentAtStart).toBeDefined();\n expect(currentAfterAwait).toBe(currentAtStart);\n\n return currentAtStart;\n },\n undefined,\n 'current-context-test',\n );\n\n const currentFromResult = await task.result;\n expect(currentFromResult).toBe(task);\n });\n\n it('should isolate nested Task.current context and restore parent context', async () => {\n const parentTask = Task.from(\n async (controller) => {\n const parentCurrent = Task.current();\n expect(parentCurrent).toBeDefined();\n\n const childTask = Task.from(\n async () => {\n const childCurrentStart = Task.current();\n await delay(5);\n const childCurrentAfterAwait = Task.current();\n\n expect(childCurrentStart).toBeDefined();\n expect(childCurrentAfterAwait).toBe(childCurrentStart);\n expect(childCurrentStart).not.toBe(parentCurrent);\n\n return childCurrentStart;\n },\n controller,\n 'child-current-context-test',\n );\n\n const childCurrent = await childTask.result;\n const parentCurrentAfterChild = Task.current();\n\n expect(parentCurrentAfterChild).toBe(parentCurrent);\n\n return { parentCurrent, childCurrent };\n },\n undefined,\n 'parent-current-context-test',\n );\n\n const { parentCurrent, childCurrent } = await parentTask.result;\n expect(parentCurrent).toBe(parentTask);\n expect(childCurrent).not.toBe(parentCurrent);\n expect(Task.current()).toBeUndefined();\n });\n\n it('should always expose Task.current for concurrent task callbacks', async () => {\n const tasks = Array.from({ length: 25 }, (_, idx) =>\n Task.from(\n async () => {\n const currentAtStart = Task.current();\n await delay(1);\n const currentAfterAwait = Task.current();\n\n expect(currentAtStart).toBeDefined();\n expect(currentAfterAwait).toBe(currentAtStart);\n\n return currentAtStart;\n },\n undefined,\n `current-context-stress-${idx}`,\n ),\n );\n\n const currentTasks = await Promise.all(tasks.map((task) => task.result));\n currentTasks.forEach((currentTask, idx) => {\n expect(currentTask).toBe(tasks[idx]);\n });\n });\n });\n\n describe('Event', () => {\n it('wait resolves immediately when the event is already set', async () => {\n const event = new Event();\n event.set();\n\n const result = await event.wait();\n expect(result).toBe(true);\n });\n\n it('wait resolves after set is called', async () => {\n // check promise is pending\n const event = new Event();\n const waiterPromise = event.wait();\n\n await delay(10);\n expect(await isPending(waiterPromise)).toBe(true);\n\n // check promise is resolved after set is called\n event.set();\n const result = await waiterPromise;\n expect(result).toBe(true);\n });\n\n it('all waiters resolve once set is called', async () => {\n const event = new Event();\n const waiters = [event.wait(), event.wait(), event.wait()];\n\n await delay(10);\n const pendings = await Promise.all(waiters.map((w) => isPending(w)));\n expect(pendings).toEqual([true, true, true]);\n\n event.set();\n const results = await Promise.all(waiters);\n expect(results).toEqual([true, true, true]);\n });\n\n it('wait after 2 seconds is still pending before set', async () => {\n const event = new Event();\n const waiter = event.wait();\n\n await delay(2000);\n expect(await isPending(waiter)).toBe(true);\n\n event.set();\n const result = await waiter;\n expect(result).toBe(true);\n });\n\n it('wait after set and clear should be pending', async () => {\n const event = new Event();\n const waiterBeforeSet = event.wait();\n event.set();\n event.clear();\n\n const waiterAfterSet = event.wait();\n\n const result = await Promise.race([\n waiterBeforeSet.then(() => 'before'),\n waiterAfterSet.then(() => 'after'),\n ]);\n\n expect(result).toBe('before');\n expect(await isPending(waiterBeforeSet)).toBe(false);\n expect(await isPending(waiterAfterSet)).toBe(true);\n\n event.set();\n expect(await waiterAfterSet).toBe(true);\n });\n });\n\n describe('resampleStream', () => {\n const createAudioFrame = (sampleRate: number, samples: number, channels = 1): AudioFrame => {\n const data = new Int16Array(samples * channels);\n for (let i = 0; i < data.length; i++) {\n data[i] = Math.sin((i / samples) * Math.PI * 2) * 16000;\n }\n return new AudioFrame(data, sampleRate, channels, samples);\n };\n\n const streamToArray = async (stream: ReadableStream<AudioFrame>): Promise<AudioFrame[]> => {\n const reader = stream.getReader();\n const chunks: AudioFrame[] = [];\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 return chunks;\n };\n\n it('should resample audio frames to target sample rate', async () => {\n const inputRate = 48000;\n const outputRate = 16000;\n const inputFrame = createAudioFrame(inputRate, 960); // 20ms at 48kHz\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(inputFrame);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(outputRate);\n expect(frame.channels).toBe(inputFrame.channels);\n }\n });\n\n it('should handle same input and output rate', async () => {\n const sampleRate = 44100;\n const inputFrame = createAudioFrame(sampleRate, 1024);\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(inputFrame);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate: sampleRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(sampleRate);\n expect(frame.channels).toBe(inputFrame.channels);\n }\n });\n\n it('should handle multiple input frames', async () => {\n const inputRate = 32000;\n const outputRate = 48000;\n const frame1 = createAudioFrame(inputRate, 640);\n const frame2 = createAudioFrame(inputRate, 640);\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(frame1);\n controller.enqueue(frame2);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(outputRate);\n expect(frame.channels).toBe(frame1.channels);\n }\n });\n\n it('should handle empty stream', async () => {\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate: 44100 });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames).toEqual([]);\n });\n });\n});\n"],"mappings":"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","names":["parentCurrent","childCurrent"]}
package/dist/version.cjs CHANGED
@@ -21,7 +21,7 @@ __export(version_exports, {
21
21
  version: () => version
22
22
  });
23
23
  module.exports = __toCommonJS(version_exports);
24
- const version = "0.1.0";
24
+ const version = "1.0.47";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  version
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nexport const version = '0.1.0';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,MAAM,UAAU;","names":[]}
1
+ {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nexport const version = __PACKAGE_VERSION__;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,MAAM,UAAU;","names":[]}
@@ -1,2 +1,2 @@
1
- export declare const version = "0.1.0";
1
+ export declare const version: string;
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const version = "0.1.0";
1
+ export declare const version: string;
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,UAAU,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,QAAsB,CAAC"}
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "0.1.0";
1
+ const version = "1.0.47";
2
2
  export {
3
3
  version
4
4
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nexport const version = '0.1.0';\n"],"mappings":"AAIO,MAAM,UAAU;","names":[]}
1
+ {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nexport const version = __PACKAGE_VERSION__;\n"],"mappings":"AAIO,MAAM,UAAU;","names":[]}
@@ -19,10 +19,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var agent_exports = {};
20
20
  __export(agent_exports, {
21
21
  Agent: () => Agent,
22
+ AgentTask: () => AgentTask,
22
23
  STOP_RESPONSE_SYMBOL: () => STOP_RESPONSE_SYMBOL,
23
24
  StopResponse: () => StopResponse,
24
- asyncLocalStorage: () => asyncLocalStorage,
25
- isStopResponse: () => isStopResponse
25
+ _getActivityTaskInfo: () => _getActivityTaskInfo,
26
+ _setActivityTaskInfo: () => _setActivityTaskInfo,
27
+ functionCallStorage: () => functionCallStorage,
28
+ isStopResponse: () => isStopResponse,
29
+ speechHandleStorage: () => speechHandleStorage
26
30
  });
27
31
  module.exports = __toCommonJS(agent_exports);
28
32
  var import_node_async_hooks = require("node:async_hooks");
@@ -30,11 +34,36 @@ var import_web = require("node:stream/web");
30
34
  var import_inference = require("../inference/index.cjs");
31
35
  var import_chat_context = require("../llm/chat_context.cjs");
32
36
  var import_llm = require("../llm/index.cjs");
37
+ var import_log = require("../log.cjs");
33
38
  var import_stt = require("../stt/index.cjs");
34
39
  var import_basic = require("../tokenize/basic/index.cjs");
35
40
  var import_tts = require("../tts/index.cjs");
36
41
  var import_types = require("../types.cjs");
37
- const asyncLocalStorage = new import_node_async_hooks.AsyncLocalStorage();
42
+ var import_utils = require("../utils.cjs");
43
+ var import_agent_activity = require("./agent_activity.cjs");
44
+ const functionCallStorage = new import_node_async_hooks.AsyncLocalStorage();
45
+ const speechHandleStorage = new import_node_async_hooks.AsyncLocalStorage();
46
+ const activityTaskInfoStorage = /* @__PURE__ */ new WeakMap();
47
+ function _setActivityTaskInfo(task, options) {
48
+ const info = activityTaskInfoStorage.get(task) ?? {
49
+ functionCall: null,
50
+ speechHandle: null,
51
+ inlineTask: false
52
+ };
53
+ if (Object.hasOwn(options, "functionCall")) {
54
+ info.functionCall = options.functionCall ?? null;
55
+ }
56
+ if (Object.hasOwn(options, "speechHandle")) {
57
+ info.speechHandle = options.speechHandle ?? null;
58
+ }
59
+ if (Object.hasOwn(options, "inlineTask")) {
60
+ info.inlineTask = options.inlineTask ?? false;
61
+ }
62
+ activityTaskInfoStorage.set(task, info);
63
+ }
64
+ function _getActivityTaskInfo(task) {
65
+ return activityTaskInfoStorage.get(task);
66
+ }
38
67
  const STOP_RESPONSE_SYMBOL = Symbol("StopResponse");
39
68
  class StopResponse extends Error {
40
69
  constructor() {
@@ -183,18 +212,18 @@ class Agent {
183
212
  if (!activity.stt) {
184
213
  throw new Error("sttNode called but no STT node is available");
185
214
  }
186
- let wrapped_stt = activity.stt;
187
- if (!wrapped_stt.capabilities.streaming) {
215
+ let wrappedStt = activity.stt;
216
+ if (!wrappedStt.capabilities.streaming) {
188
217
  const vad = agent.vad || activity.vad;
189
218
  if (!vad) {
190
219
  throw new Error(
191
220
  "STT does not support streaming, add a VAD to the AgentTask/VoiceAgent to enable streaming"
192
221
  );
193
222
  }
194
- wrapped_stt = new import_stt.StreamAdapter(wrapped_stt, vad);
223
+ wrappedStt = new import_stt.StreamAdapter(wrappedStt, vad);
195
224
  }
196
225
  const connOptions = activity.agentSession.connOptions.sttConnOptions;
197
- const stream = wrapped_stt.stream({ connOptions });
226
+ const stream = wrappedStt.stream({ connOptions });
198
227
  const audioInputStartedAt = ((_a = activity.agentSession._recorderIO) == null ? void 0 : _a.recordingStartedAt) ?? // Use recording start time if available
199
228
  activity.agentSession._startedAt ?? // Fallback to session start time
200
229
  Date.now();
@@ -268,12 +297,12 @@ class Agent {
268
297
  if (!activity.tts) {
269
298
  throw new Error("ttsNode called but no TTS node is available");
270
299
  }
271
- let wrapped_tts = activity.tts;
300
+ let wrappedTts = activity.tts;
272
301
  if (!activity.tts.capabilities.streaming) {
273
- wrapped_tts = new import_tts.StreamAdapter(wrapped_tts, new import_basic.SentenceTokenizer());
302
+ wrappedTts = new import_tts.StreamAdapter(wrappedTts, new import_basic.SentenceTokenizer());
274
303
  }
275
304
  const connOptions = activity.agentSession.connOptions.ttsConnOptions;
276
- const stream = wrapped_tts.stream({ connOptions });
305
+ const stream = wrappedTts.stream({ connOptions });
277
306
  stream.updateInputStream(text);
278
307
  let cleaned = false;
279
308
  const cleanup = () => {
@@ -311,12 +340,115 @@ class Agent {
311
340
  }
312
341
  };
313
342
  }
343
+ class AgentTask extends Agent {
344
+ started = false;
345
+ future = new import_utils.Future();
346
+ #logger = (0, import_log.log)();
347
+ get done() {
348
+ return this.future.done;
349
+ }
350
+ complete(result) {
351
+ if (this.future.done) {
352
+ throw new Error(`${this.constructor.name} is already done`);
353
+ }
354
+ if (result instanceof Error) {
355
+ this.future.reject(result);
356
+ } else {
357
+ this.future.resolve(result);
358
+ }
359
+ const speechHandle = speechHandleStorage.getStore();
360
+ if (speechHandle) {
361
+ speechHandle._maybeRunFinalOutput = result;
362
+ }
363
+ }
364
+ async run() {
365
+ if (this.started) {
366
+ throw new Error(
367
+ `Task ${this.constructor.name} has already started and cannot be awaited multiple times`
368
+ );
369
+ }
370
+ this.started = true;
371
+ const currentTask = import_utils.Task.current();
372
+ if (!currentTask) {
373
+ throw new Error(`${this.constructor.name} must be executed inside a Task context`);
374
+ }
375
+ const taskInfo = _getActivityTaskInfo(currentTask);
376
+ if (!taskInfo || !taskInfo.inlineTask) {
377
+ throw new Error(
378
+ `${this.constructor.name} should only be awaited inside function tools or the onEnter/onExit methods of an Agent`
379
+ );
380
+ }
381
+ const speechHandle = speechHandleStorage.getStore();
382
+ const oldActivity = import_agent_activity.agentActivityStorage.getStore();
383
+ if (!oldActivity) {
384
+ throw new Error(`${this.constructor.name} must be executed inside an AgentActivity context`);
385
+ }
386
+ currentTask.addDoneCallback(() => {
387
+ if (this.future.done) return;
388
+ this.#logger.error(`The Task finished before ${this.constructor.name} was completed.`);
389
+ this.complete(new Error(`The Task finished before ${this.constructor.name} was completed.`));
390
+ });
391
+ const oldAgent = oldActivity.agent;
392
+ const session = oldActivity.agentSession;
393
+ const blockedTasks = [currentTask];
394
+ const onEnterTask = oldActivity._onEnterTask;
395
+ if (onEnterTask && !onEnterTask.done && onEnterTask !== currentTask) {
396
+ blockedTasks.push(onEnterTask);
397
+ }
398
+ if (taskInfo.functionCall && oldActivity.llm instanceof import_llm.RealtimeModel && !oldActivity.llm.capabilities.manualFunctionCalls) {
399
+ this.#logger.error(
400
+ `Realtime model does not support resuming function calls from chat context, using AgentTask inside a function tool may have unexpected behavior.`
401
+ );
402
+ }
403
+ await session._updateActivity(this, {
404
+ previousActivity: "pause",
405
+ newActivity: "start",
406
+ blockedTasks
407
+ });
408
+ let runState = session._globalRunState;
409
+ if (speechHandle && runState && !runState.done()) {
410
+ if (runState._watchedHandleCount() > 1) {
411
+ runState._unwatchHandle(speechHandle);
412
+ }
413
+ runState._markDoneIfNeeded();
414
+ }
415
+ try {
416
+ return await this.future.await;
417
+ } finally {
418
+ runState = session._globalRunState;
419
+ if (session.currentAgent !== this) {
420
+ this.#logger.warn(
421
+ `${this.constructor.name} completed, but the agent has changed in the meantime. Ignoring handoff to the previous agent, likely due to AgentSession.updateAgent being invoked.`
422
+ );
423
+ await oldActivity.close();
424
+ } else {
425
+ if (speechHandle && runState && !runState.done()) {
426
+ runState._watchHandle(speechHandle);
427
+ }
428
+ const mergedChatCtx = oldAgent._chatCtx.merge(this._chatCtx, {
429
+ excludeFunctionCall: true,
430
+ excludeInstructions: true
431
+ });
432
+ oldAgent._chatCtx.items = mergedChatCtx.items;
433
+ await session._updateActivity(oldAgent, {
434
+ previousActivity: "close",
435
+ newActivity: "resume",
436
+ waitOnEnter: false
437
+ });
438
+ }
439
+ }
440
+ }
441
+ }
314
442
  // Annotate the CommonJS export names for ESM import in node:
315
443
  0 && (module.exports = {
316
444
  Agent,
445
+ AgentTask,
317
446
  STOP_RESPONSE_SYMBOL,
318
447
  StopResponse,
319
- asyncLocalStorage,
320
- isStopResponse
448
+ _getActivityTaskInfo,
449
+ _setActivityTaskInfo,
450
+ functionCallStorage,
451
+ isStopResponse,
452
+ speechHandleStorage
321
453
  });
322
454
  //# sourceMappingURL=agent.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/voice/agent.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { ReadableStream } from 'node:stream/web';\nimport {\n LLM as InferenceLLM,\n STT as InferenceSTT,\n TTS as InferenceTTS,\n type LLMModels,\n type STTModelString,\n type TTSModelString,\n} from '../inference/index.js';\nimport { ReadonlyChatContext } from '../llm/chat_context.js';\nimport type { ChatMessage, FunctionCall, RealtimeModel } from '../llm/index.js';\nimport {\n type ChatChunk,\n ChatContext,\n LLM,\n type ToolChoice,\n type ToolContext,\n} from '../llm/index.js';\nimport type { STT, SpeechEvent } from '../stt/index.js';\nimport { StreamAdapter as STTStreamAdapter } from '../stt/index.js';\nimport { SentenceTokenizer as BasicSentenceTokenizer } from '../tokenize/basic/index.js';\nimport type { TTS } from '../tts/index.js';\nimport { SynthesizeStream, StreamAdapter as TTSStreamAdapter } from '../tts/index.js';\nimport { USERDATA_TIMED_TRANSCRIPT } from '../types.js';\nimport type { VAD } from '../vad.js';\nimport type { AgentActivity } from './agent_activity.js';\nimport type { AgentSession, TurnDetectionMode } from './agent_session.js';\nimport type { TimedString } from './io.js';\n\nexport const asyncLocalStorage = new AsyncLocalStorage<{ functionCall?: FunctionCall }>();\nexport const STOP_RESPONSE_SYMBOL = Symbol('StopResponse');\n\nexport class StopResponse extends Error {\n constructor() {\n super();\n this.name = 'StopResponse';\n\n Object.defineProperty(this, STOP_RESPONSE_SYMBOL, {\n value: true,\n });\n }\n}\n\nexport function isStopResponse(value: unknown): value is StopResponse {\n return (\n value !== undefined &&\n value !== null &&\n typeof value === 'object' &&\n STOP_RESPONSE_SYMBOL in value\n );\n}\n\nexport interface ModelSettings {\n /** The tool choice to use when calling the LLM. */\n toolChoice?: ToolChoice;\n}\n\nexport interface AgentOptions<UserData> {\n id?: string;\n instructions: string;\n chatCtx?: ChatContext;\n tools?: ToolContext<UserData>;\n turnDetection?: TurnDetectionMode;\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n allowInterruptions?: boolean;\n minConsecutiveSpeechDelay?: number;\n useTtsAlignedTranscript?: boolean;\n}\n\nexport class Agent<UserData = any> {\n private _id: string;\n private turnDetection?: TurnDetectionMode;\n private _stt?: STT;\n private _vad?: VAD;\n private _llm?: LLM | RealtimeModel;\n private _tts?: TTS;\n private _useTtsAlignedTranscript?: boolean;\n\n /** @internal */\n _agentActivity?: AgentActivity;\n\n /** @internal */\n _chatCtx: ChatContext;\n\n /** @internal */\n _instructions: string;\n\n /** @internal */\n _tools?: ToolContext<UserData>;\n\n constructor({\n id,\n instructions,\n chatCtx,\n tools,\n turnDetection,\n stt,\n vad,\n llm,\n tts,\n useTtsAlignedTranscript,\n }: AgentOptions<UserData>) {\n if (id) {\n this._id = id;\n } else {\n // Convert class name to snake_case\n const className = this.constructor.name;\n if (className === 'Agent') {\n this._id = 'default_agent';\n } else {\n this._id = className\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '');\n }\n }\n\n this._instructions = instructions;\n this._tools = { ...tools };\n this._chatCtx = chatCtx\n ? chatCtx.copy({\n toolCtx: this._tools,\n })\n : ChatContext.empty();\n\n this.turnDetection = turnDetection;\n this._vad = vad;\n\n if (typeof stt === 'string') {\n this._stt = InferenceSTT.fromModelString(stt);\n } else {\n this._stt = stt;\n }\n\n if (typeof llm === 'string') {\n this._llm = InferenceLLM.fromModelString(llm);\n } else {\n this._llm = llm;\n }\n\n if (typeof tts === 'string') {\n this._tts = InferenceTTS.fromModelString(tts);\n } else {\n this._tts = tts;\n }\n\n this._useTtsAlignedTranscript = useTtsAlignedTranscript;\n\n this._agentActivity = undefined;\n }\n\n get vad(): VAD | undefined {\n return this._vad;\n }\n\n get stt(): STT | undefined {\n return this._stt;\n }\n\n get llm(): LLM | RealtimeModel | undefined {\n return this._llm;\n }\n\n get tts(): TTS | undefined {\n return this._tts;\n }\n\n get useTtsAlignedTranscript(): boolean | undefined {\n return this._useTtsAlignedTranscript;\n }\n\n get chatCtx(): ReadonlyChatContext {\n return new ReadonlyChatContext(this._chatCtx.items);\n }\n\n get id(): string {\n return this._id;\n }\n\n get instructions(): string {\n return this._instructions;\n }\n\n get toolCtx(): ToolContext<UserData> {\n return { ...this._tools };\n }\n\n get session(): AgentSession<UserData> {\n return this.getActivityOrThrow().agentSession as AgentSession<UserData>;\n }\n\n async onEnter(): Promise<void> {}\n\n async onExit(): Promise<void> {}\n\n async transcriptionNode(\n text: ReadableStream<string | TimedString>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return Agent.default.transcriptionNode(this, text, modelSettings);\n }\n\n async onUserTurnCompleted(_chatCtx: ChatContext, _newMessage: ChatMessage): Promise<void> {}\n\n async sttNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n return Agent.default.sttNode(this, audio, modelSettings);\n }\n\n async llmNode(\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n return Agent.default.llmNode(this, chatCtx, toolCtx, modelSettings);\n }\n\n async ttsNode(\n text: ReadableStream<string>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.ttsNode(this, text, modelSettings);\n }\n\n async realtimeAudioOutputNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.realtimeAudioOutputNode(this, audio, modelSettings);\n }\n\n // realtime_audio_output_node\n\n getActivityOrThrow(): AgentActivity {\n if (!this._agentActivity) {\n throw new Error('Agent activity not found');\n }\n return this._agentActivity;\n }\n\n async updateChatCtx(chatCtx: ChatContext): Promise<void> {\n if (!this._agentActivity) {\n this._chatCtx = chatCtx.copy({ toolCtx: this.toolCtx });\n return;\n }\n\n this._agentActivity.updateChatCtx(chatCtx);\n }\n\n static default = {\n async sttNode(\n agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.stt) {\n throw new Error('sttNode called but no STT node is available');\n }\n\n let wrapped_stt = activity.stt;\n\n if (!wrapped_stt.capabilities.streaming) {\n const vad = agent.vad || activity.vad;\n if (!vad) {\n throw new Error(\n 'STT does not support streaming, add a VAD to the AgentTask/VoiceAgent to enable streaming',\n );\n }\n wrapped_stt = new STTStreamAdapter(wrapped_stt, vad);\n }\n\n const connOptions = activity.agentSession.connOptions.sttConnOptions;\n const stream = wrapped_stt.stream({ connOptions });\n\n // Set startTimeOffset to provide linear timestamps across reconnections\n const audioInputStartedAt =\n activity.agentSession._recorderIO?.recordingStartedAt ?? // Use recording start time if available\n activity.agentSession._startedAt ?? // Fallback to session start time\n Date.now(); // Fallback to current time\n\n stream.startTimeOffset = (Date.now() - audioInputStartedAt) / 1000;\n\n stream.updateInputStream(audio);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.detachInputStream();\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const event of stream) {\n controller.enqueue(event);\n }\n controller.close();\n } finally {\n // Always clean up the STT stream, whether it ends naturally or is cancelled\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async llmNode(\n agent: Agent,\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.llm) {\n throw new Error('llmNode called but no LLM node is available');\n }\n\n if (!(activity.llm instanceof LLM)) {\n throw new Error(\n 'llmNode should only be used with LLM (non-multimodal/realtime APIs) nodes',\n );\n }\n\n const { toolChoice } = modelSettings;\n const connOptions = activity.agentSession.connOptions.llmConnOptions;\n\n // parallelToolCalls is not passed here - it will use the value from LLM's modelOptions\n // This allows users to configure it via: new inference.LLM({ modelOptions: { parallel_tool_calls: false } })\n const stream = activity.llm.chat({\n chatCtx,\n toolCtx,\n toolChoice,\n connOptions,\n });\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n controller.enqueue(chunk);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async ttsNode(\n agent: Agent,\n text: ReadableStream<string>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.tts) {\n throw new Error('ttsNode called but no TTS node is available');\n }\n\n let wrapped_tts = activity.tts;\n\n if (!activity.tts.capabilities.streaming) {\n wrapped_tts = new TTSStreamAdapter(wrapped_tts, new BasicSentenceTokenizer());\n }\n\n const connOptions = activity.agentSession.connOptions.ttsConnOptions;\n const stream = wrapped_tts.stream({ connOptions });\n stream.updateInputStream(text);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n if (chunk === SynthesizeStream.END_OF_STREAM) {\n break;\n }\n // Attach timed transcripts to frame.userdata\n if (chunk.timedTranscripts && chunk.timedTranscripts.length > 0) {\n chunk.frame.userdata[USERDATA_TIMED_TRANSCRIPT] = chunk.timedTranscripts;\n }\n controller.enqueue(chunk.frame);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async transcriptionNode(\n agent: Agent,\n text: ReadableStream<string | TimedString>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return text;\n },\n\n async realtimeAudioOutputNode(\n _agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return audio;\n },\n };\n}\n"],"mappings":"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","names":["InferenceSTT","InferenceLLM","InferenceTTS","STTStreamAdapter","TTSStreamAdapter","BasicSentenceTokenizer"]}
1
+ {"version":3,"sources":["../../src/voice/agent.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { ReadableStream } from 'node:stream/web';\nimport {\n LLM as InferenceLLM,\n STT as InferenceSTT,\n TTS as InferenceTTS,\n type LLMModels,\n type STTModelString,\n type TTSModelString,\n} from '../inference/index.js';\nimport { ReadonlyChatContext } from '../llm/chat_context.js';\nimport type { ChatMessage, FunctionCall } from '../llm/index.js';\nimport {\n type ChatChunk,\n ChatContext,\n LLM,\n RealtimeModel,\n type ToolChoice,\n type ToolContext,\n} from '../llm/index.js';\nimport { log } from '../log.js';\nimport type { STT, SpeechEvent } from '../stt/index.js';\nimport { StreamAdapter as STTStreamAdapter } from '../stt/index.js';\nimport { SentenceTokenizer as BasicSentenceTokenizer } from '../tokenize/basic/index.js';\nimport type { TTS } from '../tts/index.js';\nimport { SynthesizeStream, StreamAdapter as TTSStreamAdapter } from '../tts/index.js';\nimport { USERDATA_TIMED_TRANSCRIPT } from '../types.js';\nimport { Future, Task } from '../utils.js';\nimport type { VAD } from '../vad.js';\nimport { type AgentActivity, agentActivityStorage } from './agent_activity.js';\nimport type { AgentSession, TurnDetectionMode } from './agent_session.js';\nimport type { TimedString } from './io.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport const functionCallStorage = new AsyncLocalStorage<{ functionCall?: FunctionCall }>();\nexport const speechHandleStorage = new AsyncLocalStorage<SpeechHandle>();\nconst activityTaskInfoStorage = new WeakMap<Task<any>, _ActivityTaskInfo>();\n\ntype _ActivityTaskInfo = {\n functionCall: FunctionCall | null;\n speechHandle: SpeechHandle | null;\n inlineTask: boolean;\n};\n\n/** @internal */\nexport function _setActivityTaskInfo<T>(\n task: Task<T>,\n options: {\n functionCall?: FunctionCall | null;\n speechHandle?: SpeechHandle | null;\n inlineTask?: boolean;\n },\n): void {\n const info = activityTaskInfoStorage.get(task) ?? {\n functionCall: null,\n speechHandle: null,\n inlineTask: false,\n };\n\n if (Object.hasOwn(options, 'functionCall')) {\n info.functionCall = options.functionCall ?? null;\n }\n if (Object.hasOwn(options, 'speechHandle')) {\n info.speechHandle = options.speechHandle ?? null;\n }\n if (Object.hasOwn(options, 'inlineTask')) {\n info.inlineTask = options.inlineTask ?? false;\n }\n\n activityTaskInfoStorage.set(task, info);\n}\n\n/** @internal */\nexport function _getActivityTaskInfo<T>(task: Task<T>): _ActivityTaskInfo | undefined {\n return activityTaskInfoStorage.get(task);\n}\nexport const STOP_RESPONSE_SYMBOL = Symbol('StopResponse');\n\nexport class StopResponse extends Error {\n constructor() {\n super();\n this.name = 'StopResponse';\n\n Object.defineProperty(this, STOP_RESPONSE_SYMBOL, {\n value: true,\n });\n }\n}\n\nexport function isStopResponse(value: unknown): value is StopResponse {\n return (\n value !== undefined &&\n value !== null &&\n typeof value === 'object' &&\n STOP_RESPONSE_SYMBOL in value\n );\n}\n\nexport interface ModelSettings {\n /** The tool choice to use when calling the LLM. */\n toolChoice?: ToolChoice;\n}\n\nexport interface AgentOptions<UserData> {\n id?: string;\n instructions: string;\n chatCtx?: ChatContext;\n tools?: ToolContext<UserData>;\n turnDetection?: TurnDetectionMode;\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n allowInterruptions?: boolean;\n minConsecutiveSpeechDelay?: number;\n useTtsAlignedTranscript?: boolean;\n}\n\nexport class Agent<UserData = any> {\n private _id: string;\n private turnDetection?: TurnDetectionMode;\n private _stt?: STT;\n private _vad?: VAD;\n private _llm?: LLM | RealtimeModel;\n private _tts?: TTS;\n private _useTtsAlignedTranscript?: boolean;\n\n /** @internal */\n _agentActivity?: AgentActivity;\n\n /** @internal */\n _chatCtx: ChatContext;\n\n /** @internal */\n _instructions: string;\n\n /** @internal */\n _tools?: ToolContext<UserData>;\n\n constructor({\n id,\n instructions,\n chatCtx,\n tools,\n turnDetection,\n stt,\n vad,\n llm,\n tts,\n useTtsAlignedTranscript,\n }: AgentOptions<UserData>) {\n if (id) {\n this._id = id;\n } else {\n // Convert class name to snake_case\n const className = this.constructor.name;\n if (className === 'Agent') {\n this._id = 'default_agent';\n } else {\n this._id = className\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '');\n }\n }\n\n this._instructions = instructions;\n this._tools = { ...tools };\n this._chatCtx = chatCtx\n ? chatCtx.copy({\n toolCtx: this._tools,\n })\n : ChatContext.empty();\n\n this.turnDetection = turnDetection;\n this._vad = vad;\n\n if (typeof stt === 'string') {\n this._stt = InferenceSTT.fromModelString(stt);\n } else {\n this._stt = stt;\n }\n\n if (typeof llm === 'string') {\n this._llm = InferenceLLM.fromModelString(llm);\n } else {\n this._llm = llm;\n }\n\n if (typeof tts === 'string') {\n this._tts = InferenceTTS.fromModelString(tts);\n } else {\n this._tts = tts;\n }\n\n this._useTtsAlignedTranscript = useTtsAlignedTranscript;\n\n this._agentActivity = undefined;\n }\n\n get vad(): VAD | undefined {\n return this._vad;\n }\n\n get stt(): STT | undefined {\n return this._stt;\n }\n\n get llm(): LLM | RealtimeModel | undefined {\n return this._llm;\n }\n\n get tts(): TTS | undefined {\n return this._tts;\n }\n\n get useTtsAlignedTranscript(): boolean | undefined {\n return this._useTtsAlignedTranscript;\n }\n\n get chatCtx(): ReadonlyChatContext {\n return new ReadonlyChatContext(this._chatCtx.items);\n }\n\n get id(): string {\n return this._id;\n }\n\n get instructions(): string {\n return this._instructions;\n }\n\n get toolCtx(): ToolContext<UserData> {\n return { ...this._tools };\n }\n\n get session(): AgentSession<UserData> {\n return this.getActivityOrThrow().agentSession as AgentSession<UserData>;\n }\n\n async onEnter(): Promise<void> {}\n\n async onExit(): Promise<void> {}\n\n async transcriptionNode(\n text: ReadableStream<string | TimedString>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return Agent.default.transcriptionNode(this, text, modelSettings);\n }\n\n async onUserTurnCompleted(_chatCtx: ChatContext, _newMessage: ChatMessage): Promise<void> {}\n\n async sttNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n return Agent.default.sttNode(this, audio, modelSettings);\n }\n\n async llmNode(\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n return Agent.default.llmNode(this, chatCtx, toolCtx, modelSettings);\n }\n\n async ttsNode(\n text: ReadableStream<string>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.ttsNode(this, text, modelSettings);\n }\n\n async realtimeAudioOutputNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.realtimeAudioOutputNode(this, audio, modelSettings);\n }\n\n // realtime_audio_output_node\n\n getActivityOrThrow(): AgentActivity {\n if (!this._agentActivity) {\n throw new Error('Agent activity not found');\n }\n return this._agentActivity;\n }\n\n async updateChatCtx(chatCtx: ChatContext): Promise<void> {\n if (!this._agentActivity) {\n this._chatCtx = chatCtx.copy({ toolCtx: this.toolCtx });\n return;\n }\n\n this._agentActivity.updateChatCtx(chatCtx);\n }\n\n static default = {\n async sttNode(\n agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.stt) {\n throw new Error('sttNode called but no STT node is available');\n }\n\n let wrappedStt = activity.stt;\n\n if (!wrappedStt.capabilities.streaming) {\n const vad = agent.vad || activity.vad;\n if (!vad) {\n throw new Error(\n 'STT does not support streaming, add a VAD to the AgentTask/VoiceAgent to enable streaming',\n );\n }\n wrappedStt = new STTStreamAdapter(wrappedStt, vad);\n }\n\n const connOptions = activity.agentSession.connOptions.sttConnOptions;\n const stream = wrappedStt.stream({ connOptions });\n\n // Set startTimeOffset to provide linear timestamps across reconnections\n const audioInputStartedAt =\n activity.agentSession._recorderIO?.recordingStartedAt ?? // Use recording start time if available\n activity.agentSession._startedAt ?? // Fallback to session start time\n Date.now(); // Fallback to current time\n\n stream.startTimeOffset = (Date.now() - audioInputStartedAt) / 1000;\n\n stream.updateInputStream(audio);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.detachInputStream();\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const event of stream) {\n controller.enqueue(event);\n }\n controller.close();\n } finally {\n // Always clean up the STT stream, whether it ends naturally or is cancelled\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async llmNode(\n agent: Agent,\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.llm) {\n throw new Error('llmNode called but no LLM node is available');\n }\n\n if (!(activity.llm instanceof LLM)) {\n throw new Error(\n 'llmNode should only be used with LLM (non-multimodal/realtime APIs) nodes',\n );\n }\n\n const { toolChoice } = modelSettings;\n const connOptions = activity.agentSession.connOptions.llmConnOptions;\n\n // parallelToolCalls is not passed here - it will use the value from LLM's modelOptions\n // This allows users to configure it via: new inference.LLM({ modelOptions: { parallel_tool_calls: false } })\n const stream = activity.llm.chat({\n chatCtx,\n toolCtx,\n toolChoice,\n connOptions,\n });\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n controller.enqueue(chunk);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async ttsNode(\n agent: Agent,\n text: ReadableStream<string>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.tts) {\n throw new Error('ttsNode called but no TTS node is available');\n }\n\n let wrappedTts = activity.tts;\n\n if (!activity.tts.capabilities.streaming) {\n wrappedTts = new TTSStreamAdapter(wrappedTts, new BasicSentenceTokenizer());\n }\n\n const connOptions = activity.agentSession.connOptions.ttsConnOptions;\n const stream = wrappedTts.stream({ connOptions });\n stream.updateInputStream(text);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n if (chunk === SynthesizeStream.END_OF_STREAM) {\n break;\n }\n // Attach timed transcripts to frame.userdata\n if (chunk.timedTranscripts && chunk.timedTranscripts.length > 0) {\n chunk.frame.userdata[USERDATA_TIMED_TRANSCRIPT] = chunk.timedTranscripts;\n }\n controller.enqueue(chunk.frame);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async transcriptionNode(\n agent: Agent,\n text: ReadableStream<string | TimedString>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return text;\n },\n\n async realtimeAudioOutputNode(\n _agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return audio;\n },\n };\n}\n\nexport class AgentTask<ResultT = unknown, UserData = any> extends Agent<UserData> {\n private started = false;\n private future = new Future<ResultT>();\n\n #logger = log();\n\n get done(): boolean {\n return this.future.done;\n }\n\n complete(result: ResultT | Error): void {\n if (this.future.done) {\n throw new Error(`${this.constructor.name} is already done`);\n }\n\n if (result instanceof Error) {\n this.future.reject(result);\n } else {\n this.future.resolve(result);\n }\n\n const speechHandle = speechHandleStorage.getStore();\n if (speechHandle) {\n speechHandle._maybeRunFinalOutput = result;\n }\n }\n\n async run(): Promise<ResultT> {\n if (this.started) {\n throw new Error(\n `Task ${this.constructor.name} has already started and cannot be awaited multiple times`,\n );\n }\n this.started = true;\n\n const currentTask = Task.current();\n if (!currentTask) {\n throw new Error(`${this.constructor.name} must be executed inside a Task context`);\n }\n\n const taskInfo = _getActivityTaskInfo(currentTask);\n if (!taskInfo || !taskInfo.inlineTask) {\n throw new Error(\n `${this.constructor.name} should only be awaited inside function tools or the onEnter/onExit methods of an Agent`,\n );\n }\n\n const speechHandle = speechHandleStorage.getStore();\n const oldActivity = agentActivityStorage.getStore();\n if (!oldActivity) {\n throw new Error(`${this.constructor.name} must be executed inside an AgentActivity context`);\n }\n\n currentTask.addDoneCallback(() => {\n if (this.future.done) return;\n\n // If the Task finished before the AgentTask was completed, complete the AgentTask with an error.\n this.#logger.error(`The Task finished before ${this.constructor.name} was completed.`);\n this.complete(new Error(`The Task finished before ${this.constructor.name} was completed.`));\n });\n\n const oldAgent = oldActivity.agent;\n const session = oldActivity.agentSession;\n\n const blockedTasks: Task<any>[] = [currentTask];\n const onEnterTask = oldActivity._onEnterTask;\n\n if (onEnterTask && !onEnterTask.done && onEnterTask !== currentTask) {\n blockedTasks.push(onEnterTask);\n }\n\n if (\n taskInfo.functionCall &&\n oldActivity.llm instanceof RealtimeModel &&\n !oldActivity.llm.capabilities.manualFunctionCalls\n ) {\n this.#logger.error(\n `Realtime model does not support resuming function calls from chat context, ` +\n `using AgentTask inside a function tool may have unexpected behavior.`,\n );\n }\n\n await session._updateActivity(this, {\n previousActivity: 'pause',\n newActivity: 'start',\n blockedTasks,\n });\n\n let runState = session._globalRunState;\n if (speechHandle && runState && !runState.done()) {\n // Only unwatch the parent speech handle if there are other handles keeping the run alive.\n // When watchedHandleCount is 1 (only the parent), unwatching would drop it to 0 and\n // mark the run done prematurely — before function_call_output and assistant message arrive.\n if (runState._watchedHandleCount() > 1) {\n runState._unwatchHandle(speechHandle);\n }\n // it is OK to call _markDoneIfNeeded here, the above _updateActivity will call onEnter\n // and newly added handles keep the run alive.\n runState._markDoneIfNeeded();\n }\n\n try {\n return await this.future.await;\n } finally {\n // runState could have changed after future resolved\n runState = session._globalRunState;\n\n if (session.currentAgent !== this) {\n this.#logger.warn(\n `${this.constructor.name} completed, but the agent has changed in the meantime. ` +\n `Ignoring handoff to the previous agent, likely due to AgentSession.updateAgent being invoked.`,\n );\n await oldActivity.close();\n } else {\n if (speechHandle && runState && !runState.done()) {\n runState._watchHandle(speechHandle);\n }\n\n const mergedChatCtx = oldAgent._chatCtx.merge(this._chatCtx, {\n excludeFunctionCall: true,\n excludeInstructions: true,\n });\n oldAgent._chatCtx.items = mergedChatCtx.items;\n\n await session._updateActivity(oldAgent, {\n previousActivity: 'close',\n newActivity: 'resume',\n waitOnEnter: false,\n });\n }\n }\n }\n}\n"],"mappings":"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","names":["InferenceSTT","InferenceLLM","InferenceTTS","STTStreamAdapter","TTSStreamAdapter","BasicSentenceTokenizer"]}
@@ -5,17 +5,33 @@ import { AsyncLocalStorage } from 'node:async_hooks';
5
5
  import { ReadableStream } from 'node:stream/web';
6
6
  import { type LLMModels, type STTModelString, type TTSModelString } from '../inference/index.js';
7
7
  import { ReadonlyChatContext } from '../llm/chat_context.js';
8
- import type { ChatMessage, FunctionCall, RealtimeModel } from '../llm/index.js';
9
- import { type ChatChunk, ChatContext, LLM, type ToolChoice, type ToolContext } from '../llm/index.js';
8
+ import type { ChatMessage, FunctionCall } from '../llm/index.js';
9
+ import { type ChatChunk, ChatContext, LLM, RealtimeModel, type ToolChoice, type ToolContext } from '../llm/index.js';
10
10
  import type { STT, SpeechEvent } from '../stt/index.js';
11
11
  import type { TTS } from '../tts/index.js';
12
+ import { Task } from '../utils.js';
12
13
  import type { VAD } from '../vad.js';
13
- import type { AgentActivity } from './agent_activity.js';
14
+ import { type AgentActivity } from './agent_activity.js';
14
15
  import type { AgentSession, TurnDetectionMode } from './agent_session.js';
15
16
  import type { TimedString } from './io.js';
16
- export declare const asyncLocalStorage: AsyncLocalStorage<{
17
+ import type { SpeechHandle } from './speech_handle.js';
18
+ export declare const functionCallStorage: AsyncLocalStorage<{
17
19
  functionCall?: FunctionCall | undefined;
18
20
  }>;
21
+ export declare const speechHandleStorage: AsyncLocalStorage<SpeechHandle>;
22
+ type _ActivityTaskInfo = {
23
+ functionCall: FunctionCall | null;
24
+ speechHandle: SpeechHandle | null;
25
+ inlineTask: boolean;
26
+ };
27
+ /** @internal */
28
+ export declare function _setActivityTaskInfo<T>(task: Task<T>, options: {
29
+ functionCall?: FunctionCall | null;
30
+ speechHandle?: SpeechHandle | null;
31
+ inlineTask?: boolean;
32
+ }): void;
33
+ /** @internal */
34
+ export declare function _getActivityTaskInfo<T>(task: Task<T>): _ActivityTaskInfo | undefined;
19
35
  export declare const STOP_RESPONSE_SYMBOL: unique symbol;
20
36
  export declare class StopResponse extends Error {
21
37
  constructor();
@@ -84,4 +100,13 @@ export declare class Agent<UserData = any> {
84
100
  realtimeAudioOutputNode(_agent: Agent, audio: ReadableStream<AudioFrame>, _modelSettings: ModelSettings): Promise<ReadableStream<AudioFrame> | null>;
85
101
  };
86
102
  }
103
+ export declare class AgentTask<ResultT = unknown, UserData = any> extends Agent<UserData> {
104
+ #private;
105
+ private started;
106
+ private future;
107
+ get done(): boolean;
108
+ complete(result: ResultT | Error): void;
109
+ run(): Promise<ResultT>;
110
+ }
111
+ export {};
87
112
  //# sourceMappingURL=agent.d.ts.map