@livekit/agents 1.0.36-dev.0 → 1.0.37

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 (176) hide show
  1. package/dist/index.cjs +1 -3
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +0 -1
  4. package/dist/index.d.ts +0 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +0 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/inference/utils.cjs +2 -15
  9. package/dist/inference/utils.cjs.map +1 -1
  10. package/dist/inference/utils.d.cts +0 -1
  11. package/dist/inference/utils.d.ts +0 -1
  12. package/dist/inference/utils.d.ts.map +1 -1
  13. package/dist/inference/utils.js +1 -13
  14. package/dist/inference/utils.js.map +1 -1
  15. package/dist/stream/stream_channel.cjs +0 -3
  16. package/dist/stream/stream_channel.cjs.map +1 -1
  17. package/dist/stream/stream_channel.d.cts +2 -3
  18. package/dist/stream/stream_channel.d.ts +2 -3
  19. package/dist/stream/stream_channel.d.ts.map +1 -1
  20. package/dist/stream/stream_channel.js +0 -3
  21. package/dist/stream/stream_channel.js.map +1 -1
  22. package/dist/telemetry/trace_types.cjs +0 -15
  23. package/dist/telemetry/trace_types.cjs.map +1 -1
  24. package/dist/telemetry/trace_types.d.cts +0 -5
  25. package/dist/telemetry/trace_types.d.ts +0 -5
  26. package/dist/telemetry/trace_types.d.ts.map +1 -1
  27. package/dist/telemetry/trace_types.js +0 -10
  28. package/dist/telemetry/trace_types.js.map +1 -1
  29. package/dist/voice/agent_activity.cjs +19 -68
  30. package/dist/voice/agent_activity.cjs.map +1 -1
  31. package/dist/voice/agent_activity.d.cts +0 -14
  32. package/dist/voice/agent_activity.d.ts +0 -14
  33. package/dist/voice/agent_activity.d.ts.map +1 -1
  34. package/dist/voice/agent_activity.js +19 -68
  35. package/dist/voice/agent_activity.js.map +1 -1
  36. package/dist/voice/agent_session.cjs +65 -37
  37. package/dist/voice/agent_session.cjs.map +1 -1
  38. package/dist/voice/agent_session.d.cts +25 -4
  39. package/dist/voice/agent_session.d.ts +25 -4
  40. package/dist/voice/agent_session.d.ts.map +1 -1
  41. package/dist/voice/agent_session.js +65 -37
  42. package/dist/voice/agent_session.js.map +1 -1
  43. package/dist/voice/audio_recognition.cjs +2 -124
  44. package/dist/voice/audio_recognition.cjs.map +1 -1
  45. package/dist/voice/audio_recognition.d.cts +1 -32
  46. package/dist/voice/audio_recognition.d.ts +1 -32
  47. package/dist/voice/audio_recognition.d.ts.map +1 -1
  48. package/dist/voice/audio_recognition.js +2 -127
  49. package/dist/voice/audio_recognition.js.map +1 -1
  50. package/dist/voice/index.cjs +14 -1
  51. package/dist/voice/index.cjs.map +1 -1
  52. package/dist/voice/index.d.cts +1 -0
  53. package/dist/voice/index.d.ts +1 -0
  54. package/dist/voice/index.d.ts.map +1 -1
  55. package/dist/voice/index.js +3 -1
  56. package/dist/voice/index.js.map +1 -1
  57. package/dist/voice/room_io/room_io.cjs +1 -0
  58. package/dist/voice/room_io/room_io.cjs.map +1 -1
  59. package/dist/voice/room_io/room_io.d.ts.map +1 -1
  60. package/dist/voice/room_io/room_io.js +1 -0
  61. package/dist/voice/room_io/room_io.js.map +1 -1
  62. package/dist/voice/speech_handle.cjs +12 -3
  63. package/dist/voice/speech_handle.cjs.map +1 -1
  64. package/dist/voice/speech_handle.d.cts +12 -2
  65. package/dist/voice/speech_handle.d.ts +12 -2
  66. package/dist/voice/speech_handle.d.ts.map +1 -1
  67. package/dist/voice/speech_handle.js +10 -2
  68. package/dist/voice/speech_handle.js.map +1 -1
  69. package/dist/voice/testing/index.cjs +54 -0
  70. package/dist/voice/testing/index.cjs.map +1 -0
  71. package/dist/voice/testing/index.d.cts +20 -0
  72. package/dist/voice/testing/index.d.ts +20 -0
  73. package/dist/voice/testing/index.d.ts.map +1 -0
  74. package/dist/voice/testing/index.js +33 -0
  75. package/dist/voice/testing/index.js.map +1 -0
  76. package/dist/voice/testing/run_result.cjs +766 -0
  77. package/dist/voice/testing/run_result.cjs.map +1 -0
  78. package/dist/voice/testing/run_result.d.cts +374 -0
  79. package/dist/voice/testing/run_result.d.ts +374 -0
  80. package/dist/voice/testing/run_result.d.ts.map +1 -0
  81. package/dist/voice/testing/run_result.js +739 -0
  82. package/dist/voice/testing/run_result.js.map +1 -0
  83. package/dist/{inference/interruption/index.cjs → voice/testing/types.cjs} +24 -12
  84. package/dist/voice/testing/types.cjs.map +1 -0
  85. package/dist/voice/testing/types.d.cts +83 -0
  86. package/dist/voice/testing/types.d.ts +83 -0
  87. package/dist/voice/testing/types.d.ts.map +1 -0
  88. package/dist/voice/testing/types.js +19 -0
  89. package/dist/voice/testing/types.js.map +1 -0
  90. package/package.json +3 -4
  91. package/src/index.ts +0 -2
  92. package/src/inference/utils.ts +0 -15
  93. package/src/stream/stream_channel.ts +2 -6
  94. package/src/telemetry/trace_types.ts +0 -7
  95. package/src/voice/agent_activity.ts +24 -83
  96. package/src/voice/agent_session.ts +74 -49
  97. package/src/voice/audio_recognition.ts +1 -161
  98. package/src/voice/index.ts +1 -0
  99. package/src/voice/room_io/room_io.ts +1 -0
  100. package/src/voice/speech_handle.ts +24 -4
  101. package/src/voice/testing/index.ts +50 -0
  102. package/src/voice/testing/run_result.ts +937 -0
  103. package/src/voice/testing/types.ts +118 -0
  104. package/dist/inference/interruption/AdaptiveInterruptionDetector.cjs +0 -152
  105. package/dist/inference/interruption/AdaptiveInterruptionDetector.cjs.map +0 -1
  106. package/dist/inference/interruption/AdaptiveInterruptionDetector.d.cts +0 -50
  107. package/dist/inference/interruption/AdaptiveInterruptionDetector.d.ts +0 -50
  108. package/dist/inference/interruption/AdaptiveInterruptionDetector.d.ts.map +0 -1
  109. package/dist/inference/interruption/AdaptiveInterruptionDetector.js +0 -125
  110. package/dist/inference/interruption/AdaptiveInterruptionDetector.js.map +0 -1
  111. package/dist/inference/interruption/InterruptionStream.cjs +0 -310
  112. package/dist/inference/interruption/InterruptionStream.cjs.map +0 -1
  113. package/dist/inference/interruption/InterruptionStream.d.cts +0 -57
  114. package/dist/inference/interruption/InterruptionStream.d.ts +0 -57
  115. package/dist/inference/interruption/InterruptionStream.d.ts.map +0 -1
  116. package/dist/inference/interruption/InterruptionStream.js +0 -288
  117. package/dist/inference/interruption/InterruptionStream.js.map +0 -1
  118. package/dist/inference/interruption/defaults.cjs +0 -76
  119. package/dist/inference/interruption/defaults.cjs.map +0 -1
  120. package/dist/inference/interruption/defaults.d.cts +0 -14
  121. package/dist/inference/interruption/defaults.d.ts +0 -14
  122. package/dist/inference/interruption/defaults.d.ts.map +0 -1
  123. package/dist/inference/interruption/defaults.js +0 -42
  124. package/dist/inference/interruption/defaults.js.map +0 -1
  125. package/dist/inference/interruption/errors.cjs +0 -2
  126. package/dist/inference/interruption/errors.cjs.map +0 -1
  127. package/dist/inference/interruption/errors.d.cts +0 -2
  128. package/dist/inference/interruption/errors.d.ts +0 -2
  129. package/dist/inference/interruption/errors.d.ts.map +0 -1
  130. package/dist/inference/interruption/errors.js +0 -1
  131. package/dist/inference/interruption/errors.js.map +0 -1
  132. package/dist/inference/interruption/http_transport.cjs +0 -57
  133. package/dist/inference/interruption/http_transport.cjs.map +0 -1
  134. package/dist/inference/interruption/http_transport.d.cts +0 -23
  135. package/dist/inference/interruption/http_transport.d.ts +0 -23
  136. package/dist/inference/interruption/http_transport.d.ts.map +0 -1
  137. package/dist/inference/interruption/http_transport.js +0 -33
  138. package/dist/inference/interruption/http_transport.js.map +0 -1
  139. package/dist/inference/interruption/index.cjs.map +0 -1
  140. package/dist/inference/interruption/index.d.cts +0 -5
  141. package/dist/inference/interruption/index.d.ts +0 -5
  142. package/dist/inference/interruption/index.d.ts.map +0 -1
  143. package/dist/inference/interruption/index.js +0 -7
  144. package/dist/inference/interruption/index.js.map +0 -1
  145. package/dist/inference/interruption/interruption.cjs +0 -85
  146. package/dist/inference/interruption/interruption.cjs.map +0 -1
  147. package/dist/inference/interruption/interruption.d.cts +0 -48
  148. package/dist/inference/interruption/interruption.d.ts +0 -48
  149. package/dist/inference/interruption/interruption.d.ts.map +0 -1
  150. package/dist/inference/interruption/interruption.js +0 -59
  151. package/dist/inference/interruption/interruption.js.map +0 -1
  152. package/dist/inference/utils.test.cjs +0 -20
  153. package/dist/inference/utils.test.cjs.map +0 -1
  154. package/dist/inference/utils.test.js +0 -19
  155. package/dist/inference/utils.test.js.map +0 -1
  156. package/dist/utils/ws_transport.cjs +0 -51
  157. package/dist/utils/ws_transport.cjs.map +0 -1
  158. package/dist/utils/ws_transport.d.cts +0 -9
  159. package/dist/utils/ws_transport.d.ts +0 -9
  160. package/dist/utils/ws_transport.d.ts.map +0 -1
  161. package/dist/utils/ws_transport.js +0 -17
  162. package/dist/utils/ws_transport.js.map +0 -1
  163. package/dist/utils/ws_transport.test.cjs +0 -212
  164. package/dist/utils/ws_transport.test.cjs.map +0 -1
  165. package/dist/utils/ws_transport.test.js +0 -211
  166. package/dist/utils/ws_transport.test.js.map +0 -1
  167. package/src/inference/interruption/AdaptiveInterruptionDetector.ts +0 -166
  168. package/src/inference/interruption/InterruptionStream.ts +0 -397
  169. package/src/inference/interruption/defaults.ts +0 -33
  170. package/src/inference/interruption/errors.ts +0 -0
  171. package/src/inference/interruption/http_transport.ts +0 -61
  172. package/src/inference/interruption/index.ts +0 -4
  173. package/src/inference/interruption/interruption.ts +0 -88
  174. package/src/inference/utils.test.ts +0 -31
  175. package/src/utils/ws_transport.test.ts +0 -282
  176. package/src/utils/ws_transport.ts +0 -22
@@ -0,0 +1,118 @@
1
+ // SPDX-FileCopyrightText: 2025 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import type {
5
+ AgentHandoffItem,
6
+ ChatMessage,
7
+ ChatRole,
8
+ FunctionCall,
9
+ FunctionCallOutput,
10
+ } from '../../llm/chat_context.js';
11
+ import type { Agent } from '../agent.js';
12
+
13
+ /**
14
+ * Event representing an assistant or user message in the conversation.
15
+ */
16
+ export interface ChatMessageEvent {
17
+ type: 'message';
18
+ item: ChatMessage;
19
+ }
20
+
21
+ /**
22
+ * Event representing a function/tool call initiated by the LLM.
23
+ */
24
+ export interface FunctionCallEvent {
25
+ type: 'function_call';
26
+ item: FunctionCall;
27
+ }
28
+
29
+ /**
30
+ * Event representing the output/result of a function call.
31
+ */
32
+ export interface FunctionCallOutputEvent {
33
+ type: 'function_call_output';
34
+ item: FunctionCallOutput;
35
+ }
36
+
37
+ /**
38
+ * Event representing an agent handoff (switching from one agent to another).
39
+ */
40
+ export interface AgentHandoffEvent {
41
+ type: 'agent_handoff';
42
+ item: AgentHandoffItem;
43
+ oldAgent?: Agent;
44
+ newAgent: Agent;
45
+ }
46
+
47
+ /**
48
+ * Union type of all possible run events that can occur during a test run.
49
+ */
50
+ export type RunEvent =
51
+ | ChatMessageEvent
52
+ | FunctionCallEvent
53
+ | FunctionCallOutputEvent
54
+ | AgentHandoffEvent;
55
+
56
+ /**
57
+ * Type guard to check if an event is a ChatMessageEvent.
58
+ */
59
+ export function isChatMessageEvent(event: RunEvent): event is ChatMessageEvent {
60
+ return event.type === 'message';
61
+ }
62
+
63
+ /**
64
+ * Type guard to check if an event is a FunctionCallEvent.
65
+ */
66
+ export function isFunctionCallEvent(event: RunEvent): event is FunctionCallEvent {
67
+ return event.type === 'function_call';
68
+ }
69
+
70
+ /**
71
+ * Type guard to check if an event is a FunctionCallOutputEvent.
72
+ */
73
+ export function isFunctionCallOutputEvent(event: RunEvent): event is FunctionCallOutputEvent {
74
+ return event.type === 'function_call_output';
75
+ }
76
+
77
+ /**
78
+ * Type guard to check if an event is an AgentHandoffEvent.
79
+ */
80
+ export function isAgentHandoffEvent(event: RunEvent): event is AgentHandoffEvent {
81
+ return event.type === 'agent_handoff';
82
+ }
83
+
84
+ /**
85
+ * Options for message assertion.
86
+ */
87
+ export interface MessageAssertOptions {
88
+ role?: ChatRole;
89
+ }
90
+
91
+ /**
92
+ * Options for function call assertion.
93
+ */
94
+ export interface FunctionCallAssertOptions {
95
+ name?: string;
96
+ args?: Record<string, unknown>;
97
+ }
98
+
99
+ /**
100
+ * Options for function call output assertion.
101
+ */
102
+ export interface FunctionCallOutputAssertOptions {
103
+ output?: string;
104
+ isError?: boolean;
105
+ }
106
+
107
+ /**
108
+ * Options for agent handoff assertion.
109
+ */
110
+ export interface AgentHandoffAssertOptions {
111
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
112
+ newAgentType?: new (...args: any[]) => Agent;
113
+ }
114
+
115
+ /**
116
+ * Event type literals for type-safe event filtering.
117
+ */
118
+ export type EventType = 'message' | 'function_call' | 'function_call_output' | 'agent_handoff';
@@ -1,152 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var AdaptiveInterruptionDetector_exports = {};
30
- __export(AdaptiveInterruptionDetector_exports, {
31
- AdaptiveInterruptionDetector: () => AdaptiveInterruptionDetector
32
- });
33
- module.exports = __toCommonJS(AdaptiveInterruptionDetector_exports);
34
- var import_events = __toESM(require("events"), 1);
35
- var import_web = require("stream/web");
36
- var import_InterruptionStream = require("./InterruptionStream.cjs");
37
- var import_defaults = require("./defaults.cjs");
38
- var import_interruption = require("./interruption.cjs");
39
- class AdaptiveInterruptionDetector extends import_events.default {
40
- options;
41
- label;
42
- streams;
43
- // TODO: Union of InterruptionHttpStream | InterruptionWebSocketStream
44
- constructor(options = {}) {
45
- super();
46
- const {
47
- maxAudioDuration,
48
- baseUrl,
49
- apiKey,
50
- apiSecret,
51
- useProxy: useProxyArg,
52
- audioPrefixDuration,
53
- threshold,
54
- detectionInterval,
55
- inferenceTimeout,
56
- minInterruptionDuration
57
- } = { ...import_defaults.interruptionOptionDefaults, ...options };
58
- if (maxAudioDuration > 3) {
59
- throw new Error("maxAudioDuration must be less than or equal to 3.0 seconds");
60
- }
61
- const lkBaseUrl = baseUrl ?? process.env.LIVEKIT_REMOTE_EOT_URL ?? import_defaults.DEFAULT_BASE_URL;
62
- let lkApiKey = apiKey ?? "";
63
- let lkApiSecret = apiSecret ?? "";
64
- let useProxy;
65
- if (lkBaseUrl === import_defaults.DEFAULT_BASE_URL) {
66
- lkApiKey = apiKey ?? process.env.LIVEKIT_INFERENCE_API_KEY ?? process.env.LIVEKIT_API_KEY ?? "";
67
- if (!lkApiKey) {
68
- throw new Error(
69
- "apiKey is required, either as argument or set LIVEKIT_API_KEY environmental variable"
70
- );
71
- }
72
- lkApiSecret = apiSecret ?? process.env.LIVEKIT_INFERENCE_API_SECRET ?? process.env.LIVEKIT_API_SECRET ?? "";
73
- if (!lkApiSecret) {
74
- throw new Error(
75
- "apiSecret is required, either as argument or set LIVEKIT_API_SECRET environmental variable"
76
- );
77
- }
78
- useProxy = true;
79
- } else {
80
- useProxy = useProxyArg ?? false;
81
- }
82
- this.options = {
83
- sampleRate: import_defaults.SAMPLE_RATE,
84
- threshold,
85
- minFrames: Math.ceil(minInterruptionDuration * import_defaults.FRAMES_PER_SECOND),
86
- maxAudioDuration,
87
- audioPrefixDuration,
88
- detectionInterval,
89
- inferenceTimeout,
90
- baseUrl: lkBaseUrl,
91
- apiKey: lkApiKey,
92
- apiSecret: lkApiSecret,
93
- useProxy,
94
- minInterruptionDuration
95
- };
96
- this.label = `${this.constructor.name}`;
97
- this.streams = /* @__PURE__ */ new WeakSet();
98
- console.info("adaptive interruption detector initialized", {
99
- baseUrl: this.options.baseUrl,
100
- detectionInterval: this.options.detectionInterval,
101
- audioPrefixDuration: this.options.audioPrefixDuration,
102
- maxAudioDuration: this.options.maxAudioDuration,
103
- minFrames: this.options.minFrames,
104
- threshold: this.options.threshold,
105
- inferenceTimeout: this.options.inferenceTimeout,
106
- useProxy: this.options.useProxy
107
- });
108
- }
109
- /**
110
- * Creates a new InterruptionStreamBase for internal use.
111
- * The stream can receive audio frames and sentinels via pushFrame().
112
- * Use this when you need direct access to the stream for pushing frames.
113
- */
114
- createStream() {
115
- const stream = new import_InterruptionStream.InterruptionStreamBase(this, {});
116
- this.streams.add(stream);
117
- return stream;
118
- }
119
- /**
120
- * Creates a new interruption stream and returns a ReadableStream of InterruptionEvents.
121
- * This is a convenience method for consuming interruption events without needing
122
- * to manage the underlying stream directly.
123
- */
124
- stream() {
125
- const httpStream = this.createStream();
126
- const transformer = new import_web.TransformStream({
127
- transform: (chunk, controller) => {
128
- if (chunk.type === import_interruption.InterruptionEventType.INTERRUPTION) {
129
- this.emit("interruptionDetected");
130
- } else if (chunk.type === import_interruption.InterruptionEventType.OVERLAP_SPEECH_ENDED) {
131
- this.emit("overlapSpeechDetected");
132
- }
133
- controller.enqueue(chunk);
134
- }
135
- });
136
- const stream = httpStream.stream.pipeThrough(transformer);
137
- return stream;
138
- }
139
- updateOptions(options) {
140
- if (options.threshold !== void 0) {
141
- this.options.threshold = options.threshold;
142
- }
143
- if (options.minInterruptionDuration !== void 0) {
144
- this.options.minFrames = Math.ceil(options.minInterruptionDuration * import_defaults.FRAMES_PER_SECOND);
145
- }
146
- }
147
- }
148
- // Annotate the CommonJS export names for ESM import in node:
149
- 0 && (module.exports = {
150
- AdaptiveInterruptionDetector
151
- });
152
- //# sourceMappingURL=AdaptiveInterruptionDetector.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/inference/interruption/AdaptiveInterruptionDetector.ts"],"sourcesContent":["import type { TypedEventEmitter } from '@livekit/typed-emitter';\nimport EventEmitter from 'events';\nimport { type ReadableStream, TransformStream } from 'stream/web';\nimport { InterruptionStreamBase } from './InterruptionStream.js';\nimport {\n DEFAULT_BASE_URL,\n FRAMES_PER_SECOND,\n SAMPLE_RATE,\n interruptionOptionDefaults,\n} from './defaults.js';\nimport {\n type InterruptionDetectionError,\n type InterruptionEvent,\n InterruptionEventType,\n} from './interruption.js';\n\ntype InterruptionCallbacks = {\n interruptionDetected: () => void;\n overlapSpeechDetected: () => void;\n error: (error: InterruptionDetectionError) => void;\n};\n\nexport interface InterruptionOptions {\n sampleRate: number;\n threshold: number;\n minFrames: number;\n maxAudioDuration: number;\n audioPrefixDuration: number;\n detectionInterval: number;\n inferenceTimeout: number;\n minInterruptionDuration: number;\n baseUrl: string;\n apiKey: string;\n apiSecret: string;\n useProxy: boolean;\n}\n\nexport type AdaptiveInterruptionDetectorOptions = Partial<InterruptionOptions>;\n\nexport class AdaptiveInterruptionDetector extends (EventEmitter as new () => TypedEventEmitter<InterruptionCallbacks>) {\n options: InterruptionOptions;\n private label: string;\n private streams: WeakSet<object>; // TODO: Union of InterruptionHttpStream | InterruptionWebSocketStream\n\n constructor(options: AdaptiveInterruptionDetectorOptions = {}) {\n super();\n\n const {\n maxAudioDuration,\n baseUrl,\n apiKey,\n apiSecret,\n useProxy: useProxyArg,\n audioPrefixDuration,\n threshold,\n detectionInterval,\n inferenceTimeout,\n minInterruptionDuration,\n } = { ...interruptionOptionDefaults, ...options };\n\n if (maxAudioDuration > 3.0) {\n throw new Error('maxAudioDuration must be less than or equal to 3.0 seconds');\n }\n\n const lkBaseUrl = baseUrl ?? process.env.LIVEKIT_REMOTE_EOT_URL ?? DEFAULT_BASE_URL;\n let lkApiKey = apiKey ?? '';\n let lkApiSecret = apiSecret ?? '';\n let useProxy: boolean;\n\n // use LiveKit credentials if using the default base URL (inference)\n if (lkBaseUrl === DEFAULT_BASE_URL) {\n lkApiKey =\n apiKey ?? process.env.LIVEKIT_INFERENCE_API_KEY ?? process.env.LIVEKIT_API_KEY ?? '';\n if (!lkApiKey) {\n throw new Error(\n 'apiKey is required, either as argument or set LIVEKIT_API_KEY environmental variable',\n );\n }\n\n lkApiSecret =\n apiSecret ??\n process.env.LIVEKIT_INFERENCE_API_SECRET ??\n process.env.LIVEKIT_API_SECRET ??\n '';\n if (!lkApiSecret) {\n throw new Error(\n 'apiSecret is required, either as argument or set LIVEKIT_API_SECRET environmental variable',\n );\n }\n\n useProxy = true;\n } else {\n useProxy = useProxyArg ?? false;\n }\n\n this.options = {\n sampleRate: SAMPLE_RATE,\n threshold,\n minFrames: Math.ceil(minInterruptionDuration * FRAMES_PER_SECOND),\n maxAudioDuration,\n audioPrefixDuration,\n detectionInterval,\n inferenceTimeout,\n baseUrl: lkBaseUrl,\n apiKey: lkApiKey,\n apiSecret: lkApiSecret,\n useProxy,\n minInterruptionDuration,\n };\n\n this.label = `${this.constructor.name}`;\n this.streams = new WeakSet();\n\n console.info('adaptive interruption detector initialized', {\n baseUrl: this.options.baseUrl,\n detectionInterval: this.options.detectionInterval,\n audioPrefixDuration: this.options.audioPrefixDuration,\n maxAudioDuration: this.options.maxAudioDuration,\n minFrames: this.options.minFrames,\n threshold: this.options.threshold,\n inferenceTimeout: this.options.inferenceTimeout,\n useProxy: this.options.useProxy,\n });\n }\n\n /**\n * Creates a new InterruptionStreamBase for internal use.\n * The stream can receive audio frames and sentinels via pushFrame().\n * Use this when you need direct access to the stream for pushing frames.\n */\n createStream(): InterruptionStreamBase {\n const stream = new InterruptionStreamBase(this, {});\n this.streams.add(stream);\n return stream;\n }\n\n /**\n * Creates a new interruption stream and returns a ReadableStream of InterruptionEvents.\n * This is a convenience method for consuming interruption events without needing\n * to manage the underlying stream directly.\n */\n stream(): ReadableStream<InterruptionEvent> {\n const httpStream = this.createStream();\n const transformer = new TransformStream<InterruptionEvent, InterruptionEvent>({\n transform: (chunk, controller) => {\n if (chunk.type === InterruptionEventType.INTERRUPTION) {\n this.emit('interruptionDetected'); // TODO payload\n } else if (chunk.type === InterruptionEventType.OVERLAP_SPEECH_ENDED) {\n this.emit('overlapSpeechDetected'); // TODO payload\n }\n controller.enqueue(chunk);\n },\n });\n const stream = httpStream.stream.pipeThrough(transformer);\n return stream;\n }\n\n updateOptions(options: { threshold?: number; minInterruptionDuration?: number }): void {\n if (options.threshold !== undefined) {\n this.options.threshold = options.threshold;\n }\n if (options.minInterruptionDuration !== undefined) {\n this.options.minFrames = Math.ceil(options.minInterruptionDuration * FRAMES_PER_SECOND);\n }\n }\n}\n"],"mappings":"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","names":["EventEmitter"]}
@@ -1,50 +0,0 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import type { TypedEventEmitter } from '@livekit/typed-emitter';
3
- import { type ReadableStream } from 'stream/web';
4
- import { InterruptionStreamBase } from './InterruptionStream.js';
5
- import { type InterruptionDetectionError, type InterruptionEvent } from './interruption.js';
6
- type InterruptionCallbacks = {
7
- interruptionDetected: () => void;
8
- overlapSpeechDetected: () => void;
9
- error: (error: InterruptionDetectionError) => void;
10
- };
11
- export interface InterruptionOptions {
12
- sampleRate: number;
13
- threshold: number;
14
- minFrames: number;
15
- maxAudioDuration: number;
16
- audioPrefixDuration: number;
17
- detectionInterval: number;
18
- inferenceTimeout: number;
19
- minInterruptionDuration: number;
20
- baseUrl: string;
21
- apiKey: string;
22
- apiSecret: string;
23
- useProxy: boolean;
24
- }
25
- export type AdaptiveInterruptionDetectorOptions = Partial<InterruptionOptions>;
26
- declare const AdaptiveInterruptionDetector_base: new () => TypedEventEmitter<InterruptionCallbacks>;
27
- export declare class AdaptiveInterruptionDetector extends AdaptiveInterruptionDetector_base {
28
- options: InterruptionOptions;
29
- private label;
30
- private streams;
31
- constructor(options?: AdaptiveInterruptionDetectorOptions);
32
- /**
33
- * Creates a new InterruptionStreamBase for internal use.
34
- * The stream can receive audio frames and sentinels via pushFrame().
35
- * Use this when you need direct access to the stream for pushing frames.
36
- */
37
- createStream(): InterruptionStreamBase;
38
- /**
39
- * Creates a new interruption stream and returns a ReadableStream of InterruptionEvents.
40
- * This is a convenience method for consuming interruption events without needing
41
- * to manage the underlying stream directly.
42
- */
43
- stream(): ReadableStream<InterruptionEvent>;
44
- updateOptions(options: {
45
- threshold?: number;
46
- minInterruptionDuration?: number;
47
- }): void;
48
- }
49
- export {};
50
- //# sourceMappingURL=AdaptiveInterruptionDetector.d.ts.map
@@ -1,50 +0,0 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import type { TypedEventEmitter } from '@livekit/typed-emitter';
3
- import { type ReadableStream } from 'stream/web';
4
- import { InterruptionStreamBase } from './InterruptionStream.js';
5
- import { type InterruptionDetectionError, type InterruptionEvent } from './interruption.js';
6
- type InterruptionCallbacks = {
7
- interruptionDetected: () => void;
8
- overlapSpeechDetected: () => void;
9
- error: (error: InterruptionDetectionError) => void;
10
- };
11
- export interface InterruptionOptions {
12
- sampleRate: number;
13
- threshold: number;
14
- minFrames: number;
15
- maxAudioDuration: number;
16
- audioPrefixDuration: number;
17
- detectionInterval: number;
18
- inferenceTimeout: number;
19
- minInterruptionDuration: number;
20
- baseUrl: string;
21
- apiKey: string;
22
- apiSecret: string;
23
- useProxy: boolean;
24
- }
25
- export type AdaptiveInterruptionDetectorOptions = Partial<InterruptionOptions>;
26
- declare const AdaptiveInterruptionDetector_base: new () => TypedEventEmitter<InterruptionCallbacks>;
27
- export declare class AdaptiveInterruptionDetector extends AdaptiveInterruptionDetector_base {
28
- options: InterruptionOptions;
29
- private label;
30
- private streams;
31
- constructor(options?: AdaptiveInterruptionDetectorOptions);
32
- /**
33
- * Creates a new InterruptionStreamBase for internal use.
34
- * The stream can receive audio frames and sentinels via pushFrame().
35
- * Use this when you need direct access to the stream for pushing frames.
36
- */
37
- createStream(): InterruptionStreamBase;
38
- /**
39
- * Creates a new interruption stream and returns a ReadableStream of InterruptionEvents.
40
- * This is a convenience method for consuming interruption events without needing
41
- * to manage the underlying stream directly.
42
- */
43
- stream(): ReadableStream<InterruptionEvent>;
44
- updateOptions(options: {
45
- threshold?: number;
46
- minInterruptionDuration?: number;
47
- }): void;
48
- }
49
- export {};
50
- //# sourceMappingURL=AdaptiveInterruptionDetector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdaptiveInterruptionDetector.d.ts","sourceRoot":"","sources":["../../../src/inference/interruption/AdaptiveInterruptionDetector.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,OAAO,EAAE,KAAK,cAAc,EAAmB,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAOjE,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,iBAAiB,EAEvB,MAAM,mBAAmB,CAAC;AAE3B,KAAK,qBAAqB,GAAG;IAC3B,oBAAoB,EAAE,MAAM,IAAI,CAAC;IACjC,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;CACpD,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,mCAAmC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;2DAEF,kBAAkB,qBAAqB,CAAC;AAArH,qBAAa,4BAA6B,SAAQ,iCAAoE;IACpH,OAAO,EAAE,mBAAmB,CAAC;IAC7B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAkB;gBAErB,OAAO,GAAE,mCAAwC;IAiF7D;;;;OAIG;IACH,YAAY,IAAI,sBAAsB;IAMtC;;;;OAIG;IACH,MAAM,IAAI,cAAc,CAAC,iBAAiB,CAAC;IAgB3C,aAAa,CAAC,OAAO,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,uBAAuB,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAQvF"}
@@ -1,125 +0,0 @@
1
- import EventEmitter from "events";
2
- import { TransformStream } from "stream/web";
3
- import { InterruptionStreamBase } from "./InterruptionStream.js";
4
- import {
5
- DEFAULT_BASE_URL,
6
- FRAMES_PER_SECOND,
7
- SAMPLE_RATE,
8
- interruptionOptionDefaults
9
- } from "./defaults.js";
10
- import {
11
- InterruptionEventType
12
- } from "./interruption.js";
13
- class AdaptiveInterruptionDetector extends EventEmitter {
14
- options;
15
- label;
16
- streams;
17
- // TODO: Union of InterruptionHttpStream | InterruptionWebSocketStream
18
- constructor(options = {}) {
19
- super();
20
- const {
21
- maxAudioDuration,
22
- baseUrl,
23
- apiKey,
24
- apiSecret,
25
- useProxy: useProxyArg,
26
- audioPrefixDuration,
27
- threshold,
28
- detectionInterval,
29
- inferenceTimeout,
30
- minInterruptionDuration
31
- } = { ...interruptionOptionDefaults, ...options };
32
- if (maxAudioDuration > 3) {
33
- throw new Error("maxAudioDuration must be less than or equal to 3.0 seconds");
34
- }
35
- const lkBaseUrl = baseUrl ?? process.env.LIVEKIT_REMOTE_EOT_URL ?? DEFAULT_BASE_URL;
36
- let lkApiKey = apiKey ?? "";
37
- let lkApiSecret = apiSecret ?? "";
38
- let useProxy;
39
- if (lkBaseUrl === DEFAULT_BASE_URL) {
40
- lkApiKey = apiKey ?? process.env.LIVEKIT_INFERENCE_API_KEY ?? process.env.LIVEKIT_API_KEY ?? "";
41
- if (!lkApiKey) {
42
- throw new Error(
43
- "apiKey is required, either as argument or set LIVEKIT_API_KEY environmental variable"
44
- );
45
- }
46
- lkApiSecret = apiSecret ?? process.env.LIVEKIT_INFERENCE_API_SECRET ?? process.env.LIVEKIT_API_SECRET ?? "";
47
- if (!lkApiSecret) {
48
- throw new Error(
49
- "apiSecret is required, either as argument or set LIVEKIT_API_SECRET environmental variable"
50
- );
51
- }
52
- useProxy = true;
53
- } else {
54
- useProxy = useProxyArg ?? false;
55
- }
56
- this.options = {
57
- sampleRate: SAMPLE_RATE,
58
- threshold,
59
- minFrames: Math.ceil(minInterruptionDuration * FRAMES_PER_SECOND),
60
- maxAudioDuration,
61
- audioPrefixDuration,
62
- detectionInterval,
63
- inferenceTimeout,
64
- baseUrl: lkBaseUrl,
65
- apiKey: lkApiKey,
66
- apiSecret: lkApiSecret,
67
- useProxy,
68
- minInterruptionDuration
69
- };
70
- this.label = `${this.constructor.name}`;
71
- this.streams = /* @__PURE__ */ new WeakSet();
72
- console.info("adaptive interruption detector initialized", {
73
- baseUrl: this.options.baseUrl,
74
- detectionInterval: this.options.detectionInterval,
75
- audioPrefixDuration: this.options.audioPrefixDuration,
76
- maxAudioDuration: this.options.maxAudioDuration,
77
- minFrames: this.options.minFrames,
78
- threshold: this.options.threshold,
79
- inferenceTimeout: this.options.inferenceTimeout,
80
- useProxy: this.options.useProxy
81
- });
82
- }
83
- /**
84
- * Creates a new InterruptionStreamBase for internal use.
85
- * The stream can receive audio frames and sentinels via pushFrame().
86
- * Use this when you need direct access to the stream for pushing frames.
87
- */
88
- createStream() {
89
- const stream = new InterruptionStreamBase(this, {});
90
- this.streams.add(stream);
91
- return stream;
92
- }
93
- /**
94
- * Creates a new interruption stream and returns a ReadableStream of InterruptionEvents.
95
- * This is a convenience method for consuming interruption events without needing
96
- * to manage the underlying stream directly.
97
- */
98
- stream() {
99
- const httpStream = this.createStream();
100
- const transformer = new TransformStream({
101
- transform: (chunk, controller) => {
102
- if (chunk.type === InterruptionEventType.INTERRUPTION) {
103
- this.emit("interruptionDetected");
104
- } else if (chunk.type === InterruptionEventType.OVERLAP_SPEECH_ENDED) {
105
- this.emit("overlapSpeechDetected");
106
- }
107
- controller.enqueue(chunk);
108
- }
109
- });
110
- const stream = httpStream.stream.pipeThrough(transformer);
111
- return stream;
112
- }
113
- updateOptions(options) {
114
- if (options.threshold !== void 0) {
115
- this.options.threshold = options.threshold;
116
- }
117
- if (options.minInterruptionDuration !== void 0) {
118
- this.options.minFrames = Math.ceil(options.minInterruptionDuration * FRAMES_PER_SECOND);
119
- }
120
- }
121
- }
122
- export {
123
- AdaptiveInterruptionDetector
124
- };
125
- //# sourceMappingURL=AdaptiveInterruptionDetector.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/inference/interruption/AdaptiveInterruptionDetector.ts"],"sourcesContent":["import type { TypedEventEmitter } from '@livekit/typed-emitter';\nimport EventEmitter from 'events';\nimport { type ReadableStream, TransformStream } from 'stream/web';\nimport { InterruptionStreamBase } from './InterruptionStream.js';\nimport {\n DEFAULT_BASE_URL,\n FRAMES_PER_SECOND,\n SAMPLE_RATE,\n interruptionOptionDefaults,\n} from './defaults.js';\nimport {\n type InterruptionDetectionError,\n type InterruptionEvent,\n InterruptionEventType,\n} from './interruption.js';\n\ntype InterruptionCallbacks = {\n interruptionDetected: () => void;\n overlapSpeechDetected: () => void;\n error: (error: InterruptionDetectionError) => void;\n};\n\nexport interface InterruptionOptions {\n sampleRate: number;\n threshold: number;\n minFrames: number;\n maxAudioDuration: number;\n audioPrefixDuration: number;\n detectionInterval: number;\n inferenceTimeout: number;\n minInterruptionDuration: number;\n baseUrl: string;\n apiKey: string;\n apiSecret: string;\n useProxy: boolean;\n}\n\nexport type AdaptiveInterruptionDetectorOptions = Partial<InterruptionOptions>;\n\nexport class AdaptiveInterruptionDetector extends (EventEmitter as new () => TypedEventEmitter<InterruptionCallbacks>) {\n options: InterruptionOptions;\n private label: string;\n private streams: WeakSet<object>; // TODO: Union of InterruptionHttpStream | InterruptionWebSocketStream\n\n constructor(options: AdaptiveInterruptionDetectorOptions = {}) {\n super();\n\n const {\n maxAudioDuration,\n baseUrl,\n apiKey,\n apiSecret,\n useProxy: useProxyArg,\n audioPrefixDuration,\n threshold,\n detectionInterval,\n inferenceTimeout,\n minInterruptionDuration,\n } = { ...interruptionOptionDefaults, ...options };\n\n if (maxAudioDuration > 3.0) {\n throw new Error('maxAudioDuration must be less than or equal to 3.0 seconds');\n }\n\n const lkBaseUrl = baseUrl ?? process.env.LIVEKIT_REMOTE_EOT_URL ?? DEFAULT_BASE_URL;\n let lkApiKey = apiKey ?? '';\n let lkApiSecret = apiSecret ?? '';\n let useProxy: boolean;\n\n // use LiveKit credentials if using the default base URL (inference)\n if (lkBaseUrl === DEFAULT_BASE_URL) {\n lkApiKey =\n apiKey ?? process.env.LIVEKIT_INFERENCE_API_KEY ?? process.env.LIVEKIT_API_KEY ?? '';\n if (!lkApiKey) {\n throw new Error(\n 'apiKey is required, either as argument or set LIVEKIT_API_KEY environmental variable',\n );\n }\n\n lkApiSecret =\n apiSecret ??\n process.env.LIVEKIT_INFERENCE_API_SECRET ??\n process.env.LIVEKIT_API_SECRET ??\n '';\n if (!lkApiSecret) {\n throw new Error(\n 'apiSecret is required, either as argument or set LIVEKIT_API_SECRET environmental variable',\n );\n }\n\n useProxy = true;\n } else {\n useProxy = useProxyArg ?? false;\n }\n\n this.options = {\n sampleRate: SAMPLE_RATE,\n threshold,\n minFrames: Math.ceil(minInterruptionDuration * FRAMES_PER_SECOND),\n maxAudioDuration,\n audioPrefixDuration,\n detectionInterval,\n inferenceTimeout,\n baseUrl: lkBaseUrl,\n apiKey: lkApiKey,\n apiSecret: lkApiSecret,\n useProxy,\n minInterruptionDuration,\n };\n\n this.label = `${this.constructor.name}`;\n this.streams = new WeakSet();\n\n console.info('adaptive interruption detector initialized', {\n baseUrl: this.options.baseUrl,\n detectionInterval: this.options.detectionInterval,\n audioPrefixDuration: this.options.audioPrefixDuration,\n maxAudioDuration: this.options.maxAudioDuration,\n minFrames: this.options.minFrames,\n threshold: this.options.threshold,\n inferenceTimeout: this.options.inferenceTimeout,\n useProxy: this.options.useProxy,\n });\n }\n\n /**\n * Creates a new InterruptionStreamBase for internal use.\n * The stream can receive audio frames and sentinels via pushFrame().\n * Use this when you need direct access to the stream for pushing frames.\n */\n createStream(): InterruptionStreamBase {\n const stream = new InterruptionStreamBase(this, {});\n this.streams.add(stream);\n return stream;\n }\n\n /**\n * Creates a new interruption stream and returns a ReadableStream of InterruptionEvents.\n * This is a convenience method for consuming interruption events without needing\n * to manage the underlying stream directly.\n */\n stream(): ReadableStream<InterruptionEvent> {\n const httpStream = this.createStream();\n const transformer = new TransformStream<InterruptionEvent, InterruptionEvent>({\n transform: (chunk, controller) => {\n if (chunk.type === InterruptionEventType.INTERRUPTION) {\n this.emit('interruptionDetected'); // TODO payload\n } else if (chunk.type === InterruptionEventType.OVERLAP_SPEECH_ENDED) {\n this.emit('overlapSpeechDetected'); // TODO payload\n }\n controller.enqueue(chunk);\n },\n });\n const stream = httpStream.stream.pipeThrough(transformer);\n return stream;\n }\n\n updateOptions(options: { threshold?: number; minInterruptionDuration?: number }): void {\n if (options.threshold !== undefined) {\n this.options.threshold = options.threshold;\n }\n if (options.minInterruptionDuration !== undefined) {\n this.options.minFrames = Math.ceil(options.minInterruptionDuration * FRAMES_PER_SECOND);\n }\n }\n}\n"],"mappings":"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","names":[]}