@livekit/agents 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_exceptions.cjs.map +1 -1
- package/dist/_exceptions.d.ts.map +1 -1
- package/dist/_exceptions.js.map +1 -1
- package/dist/audio.cjs +10 -0
- package/dist/audio.cjs.map +1 -1
- package/dist/audio.d.cts +1 -1
- package/dist/audio.d.ts +1 -1
- package/dist/audio.d.ts.map +1 -1
- package/dist/audio.js +10 -0
- package/dist/audio.js.map +1 -1
- package/dist/beta/workflows/task_group.cjs +7 -4
- package/dist/beta/workflows/task_group.cjs.map +1 -1
- package/dist/beta/workflows/task_group.d.ts.map +1 -1
- package/dist/beta/workflows/task_group.js +7 -4
- package/dist/beta/workflows/task_group.js.map +1 -1
- package/dist/inference/api_protos.d.cts +26 -26
- package/dist/inference/api_protos.d.ts +26 -26
- package/dist/inference/interruption/http_transport.cjs.map +1 -1
- package/dist/inference/interruption/http_transport.d.cts +3 -1
- package/dist/inference/interruption/http_transport.d.ts +3 -1
- package/dist/inference/interruption/http_transport.d.ts.map +1 -1
- package/dist/inference/interruption/http_transport.js.map +1 -1
- package/dist/inference/interruption/ws_transport.cjs +37 -32
- package/dist/inference/interruption/ws_transport.cjs.map +1 -1
- package/dist/inference/interruption/ws_transport.d.ts.map +1 -1
- package/dist/inference/interruption/ws_transport.js +37 -32
- package/dist/inference/interruption/ws_transport.js.map +1 -1
- package/dist/inference/tts.cjs +14 -1
- package/dist/inference/tts.cjs.map +1 -1
- package/dist/inference/tts.d.cts +42 -4
- package/dist/inference/tts.d.ts +42 -4
- package/dist/inference/tts.d.ts.map +1 -1
- package/dist/inference/tts.js +24 -3
- package/dist/inference/tts.js.map +1 -1
- package/dist/inference/tts.test.cjs +72 -0
- package/dist/inference/tts.test.cjs.map +1 -1
- package/dist/inference/tts.test.js +72 -0
- package/dist/inference/tts.test.js.map +1 -1
- package/dist/ipc/job_proc_lazy_main.cjs +7 -2
- package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
- package/dist/ipc/job_proc_lazy_main.js +7 -2
- package/dist/ipc/job_proc_lazy_main.js.map +1 -1
- package/dist/ipc/supervised_proc.cjs +4 -1
- package/dist/ipc/supervised_proc.cjs.map +1 -1
- package/dist/ipc/supervised_proc.d.ts.map +1 -1
- package/dist/ipc/supervised_proc.js +4 -1
- package/dist/ipc/supervised_proc.js.map +1 -1
- package/dist/ipc/supervised_proc.test.cjs +82 -0
- package/dist/ipc/supervised_proc.test.cjs.map +1 -1
- package/dist/ipc/supervised_proc.test.js +82 -0
- package/dist/ipc/supervised_proc.test.js.map +1 -1
- package/dist/job.cjs +2 -1
- package/dist/job.cjs.map +1 -1
- package/dist/job.d.ts.map +1 -1
- package/dist/job.js +2 -1
- package/dist/job.js.map +1 -1
- package/dist/llm/chat_context.cjs +102 -31
- package/dist/llm/chat_context.cjs.map +1 -1
- package/dist/llm/chat_context.d.ts.map +1 -1
- package/dist/llm/chat_context.js +102 -31
- package/dist/llm/chat_context.js.map +1 -1
- package/dist/llm/chat_context.test.cjs +123 -5
- package/dist/llm/chat_context.test.cjs.map +1 -1
- package/dist/llm/chat_context.test.js +123 -5
- package/dist/llm/chat_context.test.js.map +1 -1
- package/dist/llm/fallback_adapter.cjs +2 -0
- package/dist/llm/fallback_adapter.cjs.map +1 -1
- package/dist/llm/fallback_adapter.d.ts.map +1 -1
- package/dist/llm/fallback_adapter.js +2 -0
- package/dist/llm/fallback_adapter.js.map +1 -1
- package/dist/llm/index.cjs +2 -0
- package/dist/llm/index.cjs.map +1 -1
- package/dist/llm/index.d.cts +1 -1
- package/dist/llm/index.d.ts +1 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +2 -0
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/utils.cjs +89 -0
- package/dist/llm/utils.cjs.map +1 -1
- package/dist/llm/utils.d.cts +8 -0
- package/dist/llm/utils.d.ts +8 -0
- package/dist/llm/utils.d.ts.map +1 -1
- package/dist/llm/utils.js +88 -0
- package/dist/llm/utils.js.map +1 -1
- package/dist/llm/utils.test.cjs +90 -0
- package/dist/llm/utils.test.cjs.map +1 -1
- package/dist/llm/utils.test.js +98 -2
- package/dist/llm/utils.test.js.map +1 -1
- package/dist/stt/stt.cjs +8 -0
- package/dist/stt/stt.cjs.map +1 -1
- package/dist/stt/stt.d.cts +8 -0
- package/dist/stt/stt.d.ts +8 -0
- package/dist/stt/stt.d.ts.map +1 -1
- package/dist/stt/stt.js +8 -0
- package/dist/stt/stt.js.map +1 -1
- package/dist/tts/fallback_adapter.cjs +6 -0
- package/dist/tts/fallback_adapter.cjs.map +1 -1
- package/dist/tts/fallback_adapter.d.ts.map +1 -1
- package/dist/tts/fallback_adapter.js +6 -0
- package/dist/tts/fallback_adapter.js.map +1 -1
- package/dist/typed_promise.cjs +48 -0
- package/dist/typed_promise.cjs.map +1 -0
- package/dist/typed_promise.d.cts +24 -0
- package/dist/typed_promise.d.ts +24 -0
- package/dist/typed_promise.d.ts.map +1 -0
- package/dist/typed_promise.js +28 -0
- package/dist/typed_promise.js.map +1 -0
- package/dist/utils.cjs +30 -2
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +18 -0
- package/dist/utils.d.ts +18 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +27 -2
- package/dist/utils.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/dist/voice/agent_activity.cjs +10 -0
- package/dist/voice/agent_activity.cjs.map +1 -1
- package/dist/voice/agent_activity.d.ts.map +1 -1
- package/dist/voice/agent_activity.js +11 -0
- package/dist/voice/agent_activity.js.map +1 -1
- package/dist/voice/agent_session.cjs +1 -1
- package/dist/voice/agent_session.cjs.map +1 -1
- package/dist/voice/agent_session.d.cts +4 -2
- package/dist/voice/agent_session.d.ts +4 -2
- package/dist/voice/agent_session.d.ts.map +1 -1
- package/dist/voice/agent_session.js +1 -1
- package/dist/voice/agent_session.js.map +1 -1
- package/dist/voice/events.cjs +11 -0
- package/dist/voice/events.cjs.map +1 -1
- package/dist/voice/events.d.cts +12 -1
- package/dist/voice/events.d.ts +12 -1
- package/dist/voice/events.d.ts.map +1 -1
- package/dist/voice/events.js +10 -0
- package/dist/voice/events.js.map +1 -1
- package/dist/voice/generation.cjs +23 -4
- package/dist/voice/generation.cjs.map +1 -1
- package/dist/voice/generation.d.ts.map +1 -1
- package/dist/voice/generation.js +32 -5
- package/dist/voice/generation.js.map +1 -1
- package/dist/voice/generation_tts_timeout.test.cjs +85 -0
- package/dist/voice/generation_tts_timeout.test.cjs.map +1 -0
- package/dist/voice/generation_tts_timeout.test.js +84 -0
- package/dist/voice/generation_tts_timeout.test.js.map +1 -0
- package/dist/voice/index.cjs.map +1 -1
- package/dist/voice/index.d.cts +1 -1
- package/dist/voice/index.d.ts +1 -1
- package/dist/voice/index.d.ts.map +1 -1
- package/dist/voice/index.js +3 -1
- package/dist/voice/index.js.map +1 -1
- package/dist/voice/recorder_io/recorder_io.cjs +1 -2
- package/dist/voice/recorder_io/recorder_io.cjs.map +1 -1
- package/dist/voice/recorder_io/recorder_io.d.ts.map +1 -1
- package/dist/voice/recorder_io/recorder_io.js +2 -3
- package/dist/voice/recorder_io/recorder_io.js.map +1 -1
- package/dist/voice/report.cjs +1 -1
- package/dist/voice/report.cjs.map +1 -1
- package/dist/voice/report.js +1 -1
- package/dist/voice/report.js.map +1 -1
- package/dist/voice/report.test.cjs +70 -0
- package/dist/voice/report.test.cjs.map +1 -1
- package/dist/voice/report.test.js +70 -0
- package/dist/voice/report.test.js.map +1 -1
- package/dist/voice/room_io/room_io.cjs +5 -1
- package/dist/voice/room_io/room_io.cjs.map +1 -1
- package/dist/voice/room_io/room_io.d.ts.map +1 -1
- package/dist/voice/room_io/room_io.js +5 -1
- package/dist/voice/room_io/room_io.js.map +1 -1
- package/dist/voice/room_io/room_io.test.cjs +18 -0
- package/dist/voice/room_io/room_io.test.cjs.map +1 -0
- package/dist/voice/room_io/room_io.test.js +17 -0
- package/dist/voice/room_io/room_io.test.js.map +1 -0
- package/package.json +4 -2
- package/src/_exceptions.ts +5 -0
- package/src/audio.ts +12 -1
- package/src/beta/workflows/task_group.ts +14 -5
- package/src/inference/interruption/http_transport.ts +2 -1
- package/src/inference/interruption/ws_transport.ts +44 -34
- package/src/inference/tts.test.ts +87 -0
- package/src/inference/tts.ts +71 -9
- package/src/ipc/job_proc_lazy_main.ts +7 -2
- package/src/ipc/supervised_proc.test.ts +96 -0
- package/src/ipc/supervised_proc.ts +8 -1
- package/src/job.ts +1 -0
- package/src/llm/chat_context.test.ts +137 -5
- package/src/llm/chat_context.ts +119 -38
- package/src/llm/fallback_adapter.ts +5 -2
- package/src/llm/index.ts +2 -0
- package/src/llm/utils.test.ts +103 -2
- package/src/llm/utils.ts +128 -0
- package/src/stt/stt.ts +9 -1
- package/src/tts/fallback_adapter.ts +9 -2
- package/src/typed_promise.ts +67 -0
- package/src/utils.ts +45 -2
- package/src/voice/agent_activity.ts +11 -0
- package/src/voice/agent_session.ts +13 -7
- package/src/voice/events.ts +21 -0
- package/src/voice/generation.ts +35 -8
- package/src/voice/generation_tts_timeout.test.ts +112 -0
- package/src/voice/index.ts +6 -1
- package/src/voice/recorder_io/recorder_io.ts +2 -7
- package/src/voice/report.test.ts +78 -0
- package/src/voice/report.ts +1 -1
- package/src/voice/room_io/room_io.test.ts +38 -0
- package/src/voice/room_io/room_io.ts +7 -2
package/src/voice/index.ts
CHANGED
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
//
|
|
3
3
|
// SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
export { Agent, AgentTask, StopResponse, type AgentOptions, type ModelSettings } from './agent.js';
|
|
5
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
AgentSession,
|
|
7
|
+
type AgentSessionOptions,
|
|
8
|
+
type AgentSessionUsage,
|
|
9
|
+
type VoiceOptions,
|
|
10
|
+
} from './agent_session.js';
|
|
6
11
|
export * from './avatar/index.js';
|
|
7
12
|
export * from './background_audio.js';
|
|
8
13
|
export {
|
|
@@ -13,7 +13,7 @@ import { TransformStream } from 'node:stream/web';
|
|
|
13
13
|
import { log } from '../../log.js';
|
|
14
14
|
import { isStreamReaderReleaseError } from '../../stream/deferred_stream.js';
|
|
15
15
|
import { type StreamChannel, createStreamChannel } from '../../stream/stream_channel.js';
|
|
16
|
-
import { Future, Task, cancelAndWait, delay } from '../../utils.js';
|
|
16
|
+
import { Future, Task, cancelAndWait, delay, isFfmpegTeardownError } from '../../utils.js';
|
|
17
17
|
import type { AgentSession } from '../agent_session.js';
|
|
18
18
|
import { AudioInput, AudioOutput, type PlaybackFinishedEvent } from '../io.js';
|
|
19
19
|
|
|
@@ -203,12 +203,7 @@ export class RecorderIO {
|
|
|
203
203
|
})
|
|
204
204
|
.on('error', (err) => {
|
|
205
205
|
// Ignore errors from intentional stream closure or SIGINT during shutdown
|
|
206
|
-
if (
|
|
207
|
-
err.message?.includes('Output stream closed') ||
|
|
208
|
-
err.message?.includes('received signal 2') ||
|
|
209
|
-
err.message?.includes('SIGKILL') ||
|
|
210
|
-
err.message?.includes('SIGINT')
|
|
211
|
-
) {
|
|
206
|
+
if (isFfmpegTeardownError(err)) {
|
|
212
207
|
resolve();
|
|
213
208
|
} else {
|
|
214
209
|
this.logger.error({ err }, 'FFmpeg encoding error');
|
package/src/voice/report.test.ts
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
// SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
import { describe, expect, it } from 'vitest';
|
|
5
5
|
import { ChatContext } from '../llm/chat_context.js';
|
|
6
|
+
import type { ModelUsage } from '../metrics/model_usage.js';
|
|
6
7
|
import type { AgentSessionOptions, VoiceOptions } from './agent_session.js';
|
|
8
|
+
import { AgentSessionEventTypes, createSessionUsageUpdatedEvent } from './events.js';
|
|
9
|
+
import type { AgentSessionUsage } from './index.js';
|
|
7
10
|
import { createSessionReport, sessionReportToJSON } from './report.js';
|
|
8
11
|
|
|
9
12
|
type ReportOptions = AgentSessionOptions & Partial<VoiceOptions>;
|
|
@@ -133,4 +136,79 @@ describe('sessionReportToJSON', () => {
|
|
|
133
136
|
max_tool_steps: 3,
|
|
134
137
|
});
|
|
135
138
|
});
|
|
139
|
+
|
|
140
|
+
it('serializes model usage as usage', () => {
|
|
141
|
+
const usage: ModelUsage[] = [
|
|
142
|
+
{
|
|
143
|
+
type: 'tts_usage',
|
|
144
|
+
provider: 'elevenlabs',
|
|
145
|
+
model: 'eleven_flash_v2_5',
|
|
146
|
+
inputTokens: 0,
|
|
147
|
+
outputTokens: 0,
|
|
148
|
+
charactersCount: 42,
|
|
149
|
+
audioDurationMs: 1200,
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const report = createSessionReport({
|
|
154
|
+
jobId: 'job',
|
|
155
|
+
roomId: 'room-id',
|
|
156
|
+
room: 'room',
|
|
157
|
+
options: baseOptions(),
|
|
158
|
+
events: [],
|
|
159
|
+
chatHistory: ChatContext.empty(),
|
|
160
|
+
enableRecording: false,
|
|
161
|
+
timestamp: 0,
|
|
162
|
+
startedAt: 0,
|
|
163
|
+
modelUsage: usage,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const payload = sessionReportToJSON(report);
|
|
167
|
+
expect(payload.usage).toEqual([
|
|
168
|
+
{
|
|
169
|
+
type: 'tts_usage',
|
|
170
|
+
provider: 'elevenlabs',
|
|
171
|
+
model: 'eleven_flash_v2_5',
|
|
172
|
+
charactersCount: 42,
|
|
173
|
+
audioDurationMs: 1200,
|
|
174
|
+
},
|
|
175
|
+
]);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('omits session usage update events from serialized events', () => {
|
|
179
|
+
const report = createSessionReport({
|
|
180
|
+
jobId: 'job',
|
|
181
|
+
roomId: 'room-id',
|
|
182
|
+
room: 'room',
|
|
183
|
+
options: baseOptions(),
|
|
184
|
+
events: [
|
|
185
|
+
createSessionUsageUpdatedEvent({
|
|
186
|
+
usage: {
|
|
187
|
+
modelUsage: [
|
|
188
|
+
{
|
|
189
|
+
type: 'tts_usage',
|
|
190
|
+
provider: 'elevenlabs',
|
|
191
|
+
model: 'eleven_flash_v2_5',
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
createdAt: 123,
|
|
196
|
+
}),
|
|
197
|
+
],
|
|
198
|
+
chatHistory: ChatContext.empty(),
|
|
199
|
+
enableRecording: false,
|
|
200
|
+
timestamp: 0,
|
|
201
|
+
startedAt: 0,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const payload = sessionReportToJSON(report);
|
|
205
|
+
expect(payload.events).toEqual([]);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('exports AgentSessionUsage from the voice barrel', () => {
|
|
209
|
+
const usage: AgentSessionUsage = { modelUsage: [] };
|
|
210
|
+
const eventType: AgentSessionEventTypes = AgentSessionEventTypes.SessionUsageUpdated;
|
|
211
|
+
expect(usage.modelUsage).toEqual([]);
|
|
212
|
+
expect(eventType).toBe('session_usage_updated');
|
|
213
|
+
});
|
|
136
214
|
});
|
package/src/voice/report.ts
CHANGED
|
@@ -111,7 +111,7 @@ export function sessionReportToJSON(report: SessionReport): Record<string, unkno
|
|
|
111
111
|
options.voiceOptions?.maxEndpointingDelay;
|
|
112
112
|
|
|
113
113
|
for (const event of report.events) {
|
|
114
|
-
if (event.type === 'metrics_collected') {
|
|
114
|
+
if (event.type === 'metrics_collected' || event.type === 'session_usage_updated') {
|
|
115
115
|
continue; // metrics are too noisy, Cloud is using the chat_history as the source of truth
|
|
116
116
|
}
|
|
117
117
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 LiveKit, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { IdentityTransform } from '../../stream/identity_transform.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Regression tests proving WritableStream.close() rejects when the writer is
|
|
9
|
+
* already closed or errored — the exact scenario RoomIO.close() guards against
|
|
10
|
+
* with a try/catch.
|
|
11
|
+
*
|
|
12
|
+
* RoomIO holds a WritableStreamDefaultWriter for user transcript forwarding.
|
|
13
|
+
* During teardown, the writer may already be closed or errored (e.g. a
|
|
14
|
+
* concurrent write failed during speech interruption). Without the guard,
|
|
15
|
+
* close() throws ERR_INVALID_STATE and crashes teardown.
|
|
16
|
+
*/
|
|
17
|
+
describe('RoomIO WritableStream close guard', () => {
|
|
18
|
+
it('should reject when closing an already-closed writer', async () => {
|
|
19
|
+
const transform = new IdentityTransform<string>();
|
|
20
|
+
const writer = transform.writable.getWriter();
|
|
21
|
+
|
|
22
|
+
await writer.close();
|
|
23
|
+
|
|
24
|
+
// Proves the bug: second close() rejects — RoomIO.close() must guard this.
|
|
25
|
+
await expect(writer.close()).rejects.toThrow();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should reject when closing a writer on an errored stream', async () => {
|
|
29
|
+
const transform = new IdentityTransform<string>();
|
|
30
|
+
const writer = transform.writable.getWriter();
|
|
31
|
+
|
|
32
|
+
// Force the stream into an errored state
|
|
33
|
+
await writer.abort(new Error('simulated write failure'));
|
|
34
|
+
|
|
35
|
+
// Proves the bug: close() on errored writer rejects — RoomIO.close() must guard this.
|
|
36
|
+
await expect(writer.close()).rejects.toThrow();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -529,8 +529,13 @@ export class RoomIO {
|
|
|
529
529
|
await this.initTask?.cancelAndWait();
|
|
530
530
|
|
|
531
531
|
// Close stream FIRST so reader.read() in forwardUserTranscript can exit.
|
|
532
|
-
//
|
|
533
|
-
|
|
532
|
+
// Writer may already be closed or errored if a concurrent write failed
|
|
533
|
+
// during session teardown (e.g. speech interruption race). Safe to ignore.
|
|
534
|
+
try {
|
|
535
|
+
await this.userTranscriptWriter.close();
|
|
536
|
+
} catch (e) {
|
|
537
|
+
this.logger.debug({ error: e }, 'userTranscriptWriter already closed or errored');
|
|
538
|
+
}
|
|
534
539
|
await this.forwardUserTranscriptTask?.cancelAndWait();
|
|
535
540
|
|
|
536
541
|
await this.audioInput?.close();
|