@livekit/agents 1.0.14 → 1.0.16
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/cli.cjs +12 -12
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +3 -3
- package/dist/cli.d.ts +3 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +13 -13
- package/dist/cli.js.map +1 -1
- package/dist/inference/stt.cjs.map +1 -1
- package/dist/inference/stt.d.ts.map +1 -1
- package/dist/inference/stt.js +1 -1
- package/dist/inference/stt.js.map +1 -1
- package/dist/inference/tts.cjs.map +1 -1
- package/dist/inference/tts.d.cts +2 -1
- package/dist/inference/tts.d.ts +2 -1
- package/dist/inference/tts.d.ts.map +1 -1
- package/dist/inference/tts.js +1 -5
- package/dist/inference/tts.js.map +1 -1
- package/dist/llm/chat_context.cjs +78 -0
- package/dist/llm/chat_context.cjs.map +1 -1
- package/dist/llm/chat_context.d.cts +16 -0
- package/dist/llm/chat_context.d.ts +16 -0
- package/dist/llm/chat_context.d.ts.map +1 -1
- package/dist/llm/chat_context.js +78 -0
- package/dist/llm/chat_context.js.map +1 -1
- package/dist/llm/chat_context.test.cjs +531 -0
- package/dist/llm/chat_context.test.cjs.map +1 -1
- package/dist/llm/chat_context.test.js +531 -0
- package/dist/llm/chat_context.test.js.map +1 -1
- package/dist/llm/tool_context.cjs +43 -2
- package/dist/llm/tool_context.cjs.map +1 -1
- package/dist/llm/tool_context.d.cts +39 -11
- package/dist/llm/tool_context.d.ts +39 -11
- package/dist/llm/tool_context.d.ts.map +1 -1
- package/dist/llm/tool_context.js +42 -3
- package/dist/llm/tool_context.js.map +1 -1
- package/dist/llm/tool_context.test.cjs +197 -0
- package/dist/llm/tool_context.test.cjs.map +1 -1
- package/dist/llm/tool_context.test.js +175 -0
- package/dist/llm/tool_context.test.js.map +1 -1
- package/dist/llm/utils.cjs +17 -11
- package/dist/llm/utils.cjs.map +1 -1
- package/dist/llm/utils.d.cts +1 -2
- package/dist/llm/utils.d.ts +1 -2
- package/dist/llm/utils.d.ts.map +1 -1
- package/dist/llm/utils.js +17 -11
- package/dist/llm/utils.js.map +1 -1
- package/dist/llm/zod-utils.cjs +99 -0
- package/dist/llm/zod-utils.cjs.map +1 -0
- package/dist/llm/zod-utils.d.cts +65 -0
- package/dist/llm/zod-utils.d.ts +65 -0
- package/dist/llm/zod-utils.d.ts.map +1 -0
- package/dist/llm/zod-utils.js +61 -0
- package/dist/llm/zod-utils.js.map +1 -0
- package/dist/llm/zod-utils.test.cjs +389 -0
- package/dist/llm/zod-utils.test.cjs.map +1 -0
- package/dist/llm/zod-utils.test.js +372 -0
- package/dist/llm/zod-utils.test.js.map +1 -0
- package/dist/metrics/base.cjs.map +1 -1
- package/dist/metrics/base.d.cts +7 -0
- package/dist/metrics/base.d.ts +7 -0
- package/dist/metrics/base.d.ts.map +1 -1
- package/dist/stt/stt.cjs +1 -0
- package/dist/stt/stt.cjs.map +1 -1
- package/dist/stt/stt.d.cts +7 -1
- package/dist/stt/stt.d.ts +7 -1
- package/dist/stt/stt.d.ts.map +1 -1
- package/dist/stt/stt.js +1 -0
- package/dist/stt/stt.js.map +1 -1
- package/dist/vad.cjs +16 -0
- package/dist/vad.cjs.map +1 -1
- package/dist/vad.d.cts +6 -0
- package/dist/vad.d.ts +6 -0
- package/dist/vad.d.ts.map +1 -1
- package/dist/vad.js +16 -0
- package/dist/vad.js.map +1 -1
- package/dist/voice/agent_activity.cjs +83 -8
- package/dist/voice/agent_activity.cjs.map +1 -1
- package/dist/voice/agent_activity.d.cts +6 -2
- package/dist/voice/agent_activity.d.ts +6 -2
- package/dist/voice/agent_activity.d.ts.map +1 -1
- package/dist/voice/agent_activity.js +83 -8
- package/dist/voice/agent_activity.js.map +1 -1
- package/dist/voice/agent_session.cjs +3 -2
- package/dist/voice/agent_session.cjs.map +1 -1
- package/dist/voice/agent_session.d.cts +2 -1
- package/dist/voice/agent_session.d.ts +2 -1
- package/dist/voice/agent_session.d.ts.map +1 -1
- package/dist/voice/agent_session.js +3 -2
- package/dist/voice/agent_session.js.map +1 -1
- package/dist/voice/audio_recognition.cjs +138 -16
- package/dist/voice/audio_recognition.cjs.map +1 -1
- package/dist/voice/audio_recognition.d.cts +11 -0
- package/dist/voice/audio_recognition.d.ts +11 -0
- package/dist/voice/audio_recognition.d.ts.map +1 -1
- package/dist/voice/audio_recognition.js +138 -16
- package/dist/voice/audio_recognition.js.map +1 -1
- package/dist/voice/generation.cjs +8 -3
- package/dist/voice/generation.cjs.map +1 -1
- package/dist/voice/generation.d.ts.map +1 -1
- package/dist/voice/generation.js +8 -3
- package/dist/voice/generation.js.map +1 -1
- package/dist/voice/room_io/_input.cjs.map +1 -1
- package/dist/voice/room_io/_input.d.ts.map +1 -1
- package/dist/voice/room_io/_input.js +0 -1
- package/dist/voice/room_io/_input.js.map +1 -1
- package/dist/worker.cjs +17 -11
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.cts +16 -9
- package/dist/worker.d.ts +16 -9
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +16 -12
- package/dist/worker.js.map +1 -1
- package/package.json +5 -4
- package/src/cli.ts +17 -17
- package/src/inference/stt.ts +2 -1
- package/src/inference/tts.ts +2 -5
- package/src/llm/__snapshots__/zod-utils.test.ts.snap +341 -0
- package/src/llm/chat_context.test.ts +607 -0
- package/src/llm/chat_context.ts +106 -0
- package/src/llm/tool_context.test.ts +210 -1
- package/src/llm/tool_context.ts +101 -17
- package/src/llm/utils.ts +18 -15
- package/src/llm/zod-utils.test.ts +476 -0
- package/src/llm/zod-utils.ts +144 -0
- package/src/metrics/base.ts +7 -0
- package/src/stt/stt.ts +6 -0
- package/src/vad.ts +18 -0
- package/src/voice/agent_activity.ts +119 -9
- package/src/voice/agent_session.ts +3 -1
- package/src/voice/audio_recognition.ts +235 -57
- package/src/voice/generation.ts +8 -3
- package/src/voice/room_io/_input.ts +1 -1
- package/src/worker.ts +29 -18
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import * as z3 from "zod/v3";
|
|
4
|
+
import * as z4 from "zod/v4";
|
|
5
|
+
import {
|
|
6
|
+
isZod4Schema,
|
|
7
|
+
isZodObjectSchema,
|
|
8
|
+
isZodSchema,
|
|
9
|
+
parseZodSchema,
|
|
10
|
+
zodSchemaToJsonSchema
|
|
11
|
+
} from "./zod-utils.js";
|
|
12
|
+
describe("Zod Utils", () => {
|
|
13
|
+
describe("isZod4Schema", () => {
|
|
14
|
+
it("should detect Zod v4 schemas", () => {
|
|
15
|
+
const v4Schema = z4.string();
|
|
16
|
+
expect(isZod4Schema(v4Schema)).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
it("should detect Zod v3 schemas", () => {
|
|
19
|
+
const v3Schema = z3.string();
|
|
20
|
+
expect(isZod4Schema(v3Schema)).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
it("should handle default z import (follows installed version)", () => {
|
|
23
|
+
const schema = z.string();
|
|
24
|
+
expect(typeof isZod4Schema(schema)).toBe("boolean");
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe("isZodSchema", () => {
|
|
28
|
+
it("should detect Zod v4 schemas", () => {
|
|
29
|
+
const v4Schema = z4.object({ name: z4.string() });
|
|
30
|
+
expect(isZodSchema(v4Schema)).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
it("should detect Zod v3 schemas", () => {
|
|
33
|
+
const v3Schema = z3.object({ name: z3.string() });
|
|
34
|
+
expect(isZodSchema(v3Schema)).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
it("should return false for non-Zod values", () => {
|
|
37
|
+
expect(isZodSchema({})).toBe(false);
|
|
38
|
+
expect(isZodSchema(null)).toBe(false);
|
|
39
|
+
expect(isZodSchema(void 0)).toBe(false);
|
|
40
|
+
expect(isZodSchema("string")).toBe(false);
|
|
41
|
+
expect(isZodSchema(123)).toBe(false);
|
|
42
|
+
expect(isZodSchema({ _def: {} })).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe("isZodObjectSchema", () => {
|
|
46
|
+
it("should detect Zod v4 object schemas", () => {
|
|
47
|
+
const objectSchema = z4.object({ name: z4.string() });
|
|
48
|
+
expect(isZodObjectSchema(objectSchema)).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
it("should detect Zod v3 object schemas", () => {
|
|
51
|
+
const objectSchema = z3.object({ name: z3.string() });
|
|
52
|
+
expect(isZodObjectSchema(objectSchema)).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
it("should return false for non-object Zod schemas", () => {
|
|
55
|
+
expect(isZodObjectSchema(z4.string())).toBe(false);
|
|
56
|
+
expect(isZodObjectSchema(z4.number())).toBe(false);
|
|
57
|
+
expect(isZodObjectSchema(z4.array(z4.string()))).toBe(false);
|
|
58
|
+
expect(isZodObjectSchema(z3.string())).toBe(false);
|
|
59
|
+
expect(isZodObjectSchema(z3.number())).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe("zodSchemaToJsonSchema", () => {
|
|
63
|
+
describe("Zod v4 schemas", () => {
|
|
64
|
+
it("should convert basic v4 object schema to JSON Schema", () => {
|
|
65
|
+
const schema = z4.object({
|
|
66
|
+
name: z4.string(),
|
|
67
|
+
age: z4.number()
|
|
68
|
+
});
|
|
69
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
70
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
71
|
+
});
|
|
72
|
+
it.skip("should handle v4 schemas with descriptions", () => {
|
|
73
|
+
const schema = z4.object({
|
|
74
|
+
location: z4.string().describe("The location to search")
|
|
75
|
+
});
|
|
76
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
77
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
78
|
+
});
|
|
79
|
+
it("should handle v4 schemas with optional fields", () => {
|
|
80
|
+
const schema = z4.object({
|
|
81
|
+
required: z4.string(),
|
|
82
|
+
optional: z4.string().optional()
|
|
83
|
+
});
|
|
84
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
85
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
86
|
+
});
|
|
87
|
+
it("should handle v4 enum schemas", () => {
|
|
88
|
+
const schema = z4.object({
|
|
89
|
+
color: z4.enum(["red", "blue", "green"])
|
|
90
|
+
});
|
|
91
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
92
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
93
|
+
});
|
|
94
|
+
it("should handle v4 array schemas", () => {
|
|
95
|
+
const schema = z4.object({
|
|
96
|
+
tags: z4.array(z4.string())
|
|
97
|
+
});
|
|
98
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
99
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
100
|
+
});
|
|
101
|
+
it("should handle v4 nested object schemas", () => {
|
|
102
|
+
const schema = z4.object({
|
|
103
|
+
user: z4.object({
|
|
104
|
+
name: z4.string(),
|
|
105
|
+
email: z4.string()
|
|
106
|
+
})
|
|
107
|
+
});
|
|
108
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
109
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
110
|
+
});
|
|
111
|
+
it("should handle v4 schemas with multiple optional fields", () => {
|
|
112
|
+
const schema = z4.object({
|
|
113
|
+
id: z4.string(),
|
|
114
|
+
name: z4.string().optional(),
|
|
115
|
+
age: z4.number().optional(),
|
|
116
|
+
email: z4.string()
|
|
117
|
+
});
|
|
118
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
119
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
120
|
+
});
|
|
121
|
+
it("should handle v4 schemas with default values", () => {
|
|
122
|
+
const schema = z4.object({
|
|
123
|
+
name: z4.string(),
|
|
124
|
+
role: z4.string().default("user"),
|
|
125
|
+
active: z4.boolean().default(true)
|
|
126
|
+
});
|
|
127
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
128
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
describe("Zod v3 schemas", () => {
|
|
132
|
+
it("should convert basic v3 object schema to JSON Schema", () => {
|
|
133
|
+
const schema = z3.object({
|
|
134
|
+
name: z3.string(),
|
|
135
|
+
age: z3.number()
|
|
136
|
+
});
|
|
137
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
138
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
139
|
+
});
|
|
140
|
+
it("should handle v3 schemas with descriptions", () => {
|
|
141
|
+
const schema = z3.object({
|
|
142
|
+
location: z3.string().describe("The location to search")
|
|
143
|
+
});
|
|
144
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
145
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
146
|
+
});
|
|
147
|
+
it.skip("should handle v3 schemas with optional fields", () => {
|
|
148
|
+
const schema = z3.object({
|
|
149
|
+
required: z3.string(),
|
|
150
|
+
optional: z3.string().optional()
|
|
151
|
+
});
|
|
152
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
153
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
154
|
+
});
|
|
155
|
+
it("should handle v3 enum schemas", () => {
|
|
156
|
+
const schema = z3.object({
|
|
157
|
+
color: z3.enum(["red", "blue", "green"])
|
|
158
|
+
});
|
|
159
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
160
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
161
|
+
});
|
|
162
|
+
it("should handle v3 array schemas", () => {
|
|
163
|
+
const schema = z3.object({
|
|
164
|
+
tags: z3.array(z3.string())
|
|
165
|
+
});
|
|
166
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
167
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
168
|
+
});
|
|
169
|
+
it("should handle v3 nested object schemas", () => {
|
|
170
|
+
const schema = z3.object({
|
|
171
|
+
user: z3.object({
|
|
172
|
+
name: z3.string(),
|
|
173
|
+
email: z3.string()
|
|
174
|
+
})
|
|
175
|
+
});
|
|
176
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
177
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
178
|
+
});
|
|
179
|
+
it("should handle v3 schemas with multiple optional fields", () => {
|
|
180
|
+
const schema = z3.object({
|
|
181
|
+
id: z3.string(),
|
|
182
|
+
name: z3.string().optional(),
|
|
183
|
+
age: z3.number().optional(),
|
|
184
|
+
email: z3.string()
|
|
185
|
+
});
|
|
186
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
187
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
188
|
+
});
|
|
189
|
+
it("should handle v3 schemas with default values", () => {
|
|
190
|
+
const schema = z3.object({
|
|
191
|
+
name: z3.string(),
|
|
192
|
+
role: z3.string().default("user"),
|
|
193
|
+
active: z3.boolean().default(true)
|
|
194
|
+
});
|
|
195
|
+
const jsonSchema = zodSchemaToJsonSchema(schema);
|
|
196
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
describe("isOpenai parameter", () => {
|
|
200
|
+
it("should respect isOpenai parameter for v3 schemas", () => {
|
|
201
|
+
const schema = z3.object({ name: z3.string() });
|
|
202
|
+
const openaiSchema = zodSchemaToJsonSchema(schema, true);
|
|
203
|
+
const jsonSchema7 = zodSchemaToJsonSchema(schema, false);
|
|
204
|
+
expect(openaiSchema).toHaveProperty("properties");
|
|
205
|
+
expect(jsonSchema7).toHaveProperty("properties");
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
describe("parseZodSchema", () => {
|
|
210
|
+
describe("Zod v4 schemas", () => {
|
|
211
|
+
it("should successfully parse valid v4 data", async () => {
|
|
212
|
+
const schema = z4.object({
|
|
213
|
+
name: z4.string(),
|
|
214
|
+
age: z4.number()
|
|
215
|
+
});
|
|
216
|
+
const result = await parseZodSchema(schema, { name: "John", age: 30 });
|
|
217
|
+
expect(result.success).toBe(true);
|
|
218
|
+
if (result.success) {
|
|
219
|
+
expect(result.data).toEqual({ name: "John", age: 30 });
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
it("should fail to parse invalid v4 data", async () => {
|
|
223
|
+
const schema = z4.object({
|
|
224
|
+
name: z4.string(),
|
|
225
|
+
age: z4.number()
|
|
226
|
+
});
|
|
227
|
+
const result = await parseZodSchema(schema, { name: "John", age: "invalid" });
|
|
228
|
+
expect(result.success).toBe(false);
|
|
229
|
+
if (!result.success) {
|
|
230
|
+
expect(result.error).toBeDefined();
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
it("should handle v4 optional fields", async () => {
|
|
234
|
+
const schema = z4.object({
|
|
235
|
+
name: z4.string(),
|
|
236
|
+
email: z4.string().optional()
|
|
237
|
+
});
|
|
238
|
+
const result1 = await parseZodSchema(schema, { name: "John" });
|
|
239
|
+
expect(result1.success).toBe(true);
|
|
240
|
+
const result2 = await parseZodSchema(schema, { name: "John", email: "john@example.com" });
|
|
241
|
+
expect(result2.success).toBe(true);
|
|
242
|
+
});
|
|
243
|
+
it("should handle v4 default values", async () => {
|
|
244
|
+
const schema = z4.object({
|
|
245
|
+
name: z4.string(),
|
|
246
|
+
role: z4.string().default("user")
|
|
247
|
+
});
|
|
248
|
+
const result = await parseZodSchema(schema, { name: "John" });
|
|
249
|
+
expect(result.success).toBe(true);
|
|
250
|
+
if (result.success) {
|
|
251
|
+
expect(result.data).toEqual({ name: "John", role: "user" });
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
describe("Zod v3 schemas", () => {
|
|
256
|
+
it("should successfully parse valid v3 data", async () => {
|
|
257
|
+
const schema = z3.object({
|
|
258
|
+
name: z3.string(),
|
|
259
|
+
age: z3.number()
|
|
260
|
+
});
|
|
261
|
+
const result = await parseZodSchema(schema, { name: "John", age: 30 });
|
|
262
|
+
expect(result.success).toBe(true);
|
|
263
|
+
if (result.success) {
|
|
264
|
+
expect(result.data).toEqual({ name: "John", age: 30 });
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
it("should fail to parse invalid v3 data", async () => {
|
|
268
|
+
const schema = z3.object({
|
|
269
|
+
name: z3.string(),
|
|
270
|
+
age: z3.number()
|
|
271
|
+
});
|
|
272
|
+
const result = await parseZodSchema(schema, { name: "John", age: "invalid" });
|
|
273
|
+
expect(result.success).toBe(false);
|
|
274
|
+
if (!result.success) {
|
|
275
|
+
expect(result.error).toBeDefined();
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
it("should handle v3 optional fields", async () => {
|
|
279
|
+
const schema = z3.object({
|
|
280
|
+
name: z3.string(),
|
|
281
|
+
email: z3.string().optional()
|
|
282
|
+
});
|
|
283
|
+
const result1 = await parseZodSchema(schema, { name: "John" });
|
|
284
|
+
expect(result1.success).toBe(true);
|
|
285
|
+
const result2 = await parseZodSchema(schema, { name: "John", email: "john@example.com" });
|
|
286
|
+
expect(result2.success).toBe(true);
|
|
287
|
+
});
|
|
288
|
+
it("should handle v3 default values", async () => {
|
|
289
|
+
const schema = z3.object({
|
|
290
|
+
name: z3.string(),
|
|
291
|
+
role: z3.string().default("user")
|
|
292
|
+
});
|
|
293
|
+
const result = await parseZodSchema(schema, { name: "John" });
|
|
294
|
+
expect(result.success).toBe(true);
|
|
295
|
+
if (result.success) {
|
|
296
|
+
expect(result.data).toEqual({ name: "John", role: "user" });
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
describe("Cross-version compatibility", () => {
|
|
302
|
+
it("should handle mixed v3 and v4 schemas in the same codebase", async () => {
|
|
303
|
+
const v3Schema = z3.object({ name: z3.string() });
|
|
304
|
+
const v4Schema = z4.object({ name: z4.string() });
|
|
305
|
+
const v3Result = await parseZodSchema(v3Schema, { name: "John" });
|
|
306
|
+
const v4Result = await parseZodSchema(v4Schema, { name: "Jane" });
|
|
307
|
+
expect(v3Result.success).toBe(true);
|
|
308
|
+
expect(v4Result.success).toBe(true);
|
|
309
|
+
});
|
|
310
|
+
it("should convert both v3 and v4 basic schemas to compatible JSON Schema", () => {
|
|
311
|
+
var _a, _b;
|
|
312
|
+
const v3Schema = z3.object({ count: z3.number() });
|
|
313
|
+
const v4Schema = z4.object({ count: z4.number() });
|
|
314
|
+
const v3Json = zodSchemaToJsonSchema(v3Schema);
|
|
315
|
+
const v4Json = zodSchemaToJsonSchema(v4Schema);
|
|
316
|
+
expect(v3Json.type).toBe("object");
|
|
317
|
+
expect(v4Json.type).toBe("object");
|
|
318
|
+
expect((_a = v3Json.properties.count) == null ? void 0 : _a.type).toBe("number");
|
|
319
|
+
expect((_b = v4Json.properties.count) == null ? void 0 : _b.type).toBe("number");
|
|
320
|
+
});
|
|
321
|
+
it("should handle optional fields consistently across v3 and v4", () => {
|
|
322
|
+
const v3Schema = z3.object({
|
|
323
|
+
required: z3.string(),
|
|
324
|
+
optional: z3.string().optional()
|
|
325
|
+
});
|
|
326
|
+
const v4Schema = z4.object({
|
|
327
|
+
required: z4.string(),
|
|
328
|
+
optional: z4.string().optional()
|
|
329
|
+
});
|
|
330
|
+
const v3Json = zodSchemaToJsonSchema(v3Schema);
|
|
331
|
+
const v4Json = zodSchemaToJsonSchema(v4Schema);
|
|
332
|
+
expect(v3Json.required).toContain("required");
|
|
333
|
+
expect(v4Json.required).toContain("required");
|
|
334
|
+
expect(v4Json.required).not.toContain("optional");
|
|
335
|
+
});
|
|
336
|
+
it("should handle complex schemas with nested objects and arrays consistently", () => {
|
|
337
|
+
const v3Schema = z3.object({
|
|
338
|
+
user: z3.object({
|
|
339
|
+
name: z3.string(),
|
|
340
|
+
email: z3.string().optional()
|
|
341
|
+
}),
|
|
342
|
+
tags: z3.array(z3.string()),
|
|
343
|
+
status: z3.enum(["active", "inactive"])
|
|
344
|
+
});
|
|
345
|
+
const v4Schema = z4.object({
|
|
346
|
+
user: z4.object({
|
|
347
|
+
name: z4.string(),
|
|
348
|
+
email: z4.string().optional()
|
|
349
|
+
}),
|
|
350
|
+
tags: z4.array(z4.string()),
|
|
351
|
+
status: z4.enum(["active", "inactive"])
|
|
352
|
+
});
|
|
353
|
+
const v3Json = zodSchemaToJsonSchema(v3Schema);
|
|
354
|
+
const v4Json = zodSchemaToJsonSchema(v4Schema);
|
|
355
|
+
expect(v3Json.type).toBe(v4Json.type);
|
|
356
|
+
expect(Object.keys(v3Json.properties || {})).toEqual(Object.keys(v4Json.properties || {}));
|
|
357
|
+
const v3User = v3Json.properties.user;
|
|
358
|
+
const v4User = v4Json.properties.user;
|
|
359
|
+
expect(v3User == null ? void 0 : v3User.type).toBe("object");
|
|
360
|
+
expect(v4User == null ? void 0 : v4User.type).toBe("object");
|
|
361
|
+
const v3Tags = v3Json.properties.tags;
|
|
362
|
+
const v4Tags = v4Json.properties.tags;
|
|
363
|
+
expect(v3Tags == null ? void 0 : v3Tags.type).toBe("array");
|
|
364
|
+
expect(v4Tags == null ? void 0 : v4Tags.type).toBe("array");
|
|
365
|
+
const v3Status = v3Json.properties.status;
|
|
366
|
+
const v4Status = v4Json.properties.status;
|
|
367
|
+
expect(v3Status == null ? void 0 : v3Status.enum).toEqual(["active", "inactive"]);
|
|
368
|
+
expect(v4Status == null ? void 0 : v4Status.enum).toEqual(["active", "inactive"]);
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
//# sourceMappingURL=zod-utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/llm/zod-utils.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { describe, expect, it } from 'vitest';\nimport { z } from 'zod';\nimport * as z3 from 'zod/v3';\nimport * as z4 from 'zod/v4';\nimport {\n isZod4Schema,\n isZodObjectSchema,\n isZodSchema,\n parseZodSchema,\n zodSchemaToJsonSchema,\n} from './zod-utils.js';\n\ntype JSONSchemaProperties = Record<string, Record<string, unknown>>;\n\ndescribe('Zod Utils', () => {\n describe('isZod4Schema', () => {\n it('should detect Zod v4 schemas', () => {\n const v4Schema = z4.string();\n expect(isZod4Schema(v4Schema)).toBe(true);\n });\n\n it('should detect Zod v3 schemas', () => {\n const v3Schema = z3.string();\n expect(isZod4Schema(v3Schema)).toBe(false);\n });\n\n it('should handle default z import (follows installed version)', () => {\n const schema = z.string();\n expect(typeof isZod4Schema(schema)).toBe('boolean');\n });\n });\n\n describe('isZodSchema', () => {\n it('should detect Zod v4 schemas', () => {\n const v4Schema = z4.object({ name: z4.string() });\n expect(isZodSchema(v4Schema)).toBe(true);\n });\n\n it('should detect Zod v3 schemas', () => {\n const v3Schema = z3.object({ name: z3.string() });\n expect(isZodSchema(v3Schema)).toBe(true);\n });\n\n it('should return false for non-Zod values', () => {\n expect(isZodSchema({})).toBe(false);\n expect(isZodSchema(null)).toBe(false);\n expect(isZodSchema(undefined)).toBe(false);\n expect(isZodSchema('string')).toBe(false);\n expect(isZodSchema(123)).toBe(false);\n expect(isZodSchema({ _def: {} })).toBe(false); // missing typeName\n });\n });\n\n describe('isZodObjectSchema', () => {\n it('should detect Zod v4 object schemas', () => {\n const objectSchema = z4.object({ name: z4.string() });\n expect(isZodObjectSchema(objectSchema)).toBe(true);\n });\n\n it('should detect Zod v3 object schemas', () => {\n const objectSchema = z3.object({ name: z3.string() });\n expect(isZodObjectSchema(objectSchema)).toBe(true);\n });\n\n it('should return false for non-object Zod schemas', () => {\n expect(isZodObjectSchema(z4.string())).toBe(false);\n expect(isZodObjectSchema(z4.number())).toBe(false);\n expect(isZodObjectSchema(z4.array(z4.string()))).toBe(false);\n expect(isZodObjectSchema(z3.string())).toBe(false);\n expect(isZodObjectSchema(z3.number())).toBe(false);\n });\n });\n\n describe('zodSchemaToJsonSchema', () => {\n describe('Zod v4 schemas', () => {\n it('should convert basic v4 object schema to JSON Schema', () => {\n const schema = z4.object({\n name: z4.string(),\n age: z4.number(),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it.skip('should handle v4 schemas with descriptions', () => {\n // NOTE: This test is skipped because Zod 3.25.76's v4 alpha doesn't fully support\n // descriptions in toJSONSchema yet. This will work in final Zod v4 release.\n const schema = z4.object({\n location: z4.string().describe('The location to search'),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v4 schemas with optional fields', () => {\n const schema = z4.object({\n required: z4.string(),\n optional: z4.string().optional(),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v4 enum schemas', () => {\n const schema = z4.object({\n color: z4.enum(['red', 'blue', 'green']),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v4 array schemas', () => {\n const schema = z4.object({\n tags: z4.array(z4.string()),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v4 nested object schemas', () => {\n const schema = z4.object({\n user: z4.object({\n name: z4.string(),\n email: z4.string(),\n }),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v4 schemas with multiple optional fields', () => {\n const schema = z4.object({\n id: z4.string(),\n name: z4.string().optional(),\n age: z4.number().optional(),\n email: z4.string(),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v4 schemas with default values', () => {\n const schema = z4.object({\n name: z4.string(),\n role: z4.string().default('user'),\n active: z4.boolean().default(true),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n });\n\n describe('Zod v3 schemas', () => {\n it('should convert basic v3 object schema to JSON Schema', () => {\n const schema = z3.object({\n name: z3.string(),\n age: z3.number(),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v3 schemas with descriptions', () => {\n const schema = z3.object({\n location: z3.string().describe('The location to search'),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it.skip('should handle v3 schemas with optional fields', () => {\n // NOTE: This test is skipped because in Zod 3.25.76, the v3 export's optional()\n // handling in zod-to-json-schema has some quirks. The behavior is correct for\n // the default z import which is what users will typically use.\n const schema = z3.object({\n required: z3.string(),\n optional: z3.string().optional(),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v3 enum schemas', () => {\n const schema = z3.object({\n color: z3.enum(['red', 'blue', 'green']),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v3 array schemas', () => {\n const schema = z3.object({\n tags: z3.array(z3.string()),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v3 nested object schemas', () => {\n const schema = z3.object({\n user: z3.object({\n name: z3.string(),\n email: z3.string(),\n }),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v3 schemas with multiple optional fields', () => {\n const schema = z3.object({\n id: z3.string(),\n name: z3.string().optional(),\n age: z3.number().optional(),\n email: z3.string(),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n\n it('should handle v3 schemas with default values', () => {\n const schema = z3.object({\n name: z3.string(),\n role: z3.string().default('user'),\n active: z3.boolean().default(true),\n });\n\n const jsonSchema = zodSchemaToJsonSchema(schema);\n expect(jsonSchema).toMatchSnapshot();\n });\n });\n\n describe('isOpenai parameter', () => {\n it('should respect isOpenai parameter for v3 schemas', () => {\n const schema = z3.object({ name: z3.string() });\n\n const openaiSchema = zodSchemaToJsonSchema(schema, true);\n const jsonSchema7 = zodSchemaToJsonSchema(schema, false);\n\n // Both should work, just different internal handling\n expect(openaiSchema).toHaveProperty('properties');\n expect(jsonSchema7).toHaveProperty('properties');\n });\n });\n });\n\n describe('parseZodSchema', () => {\n describe('Zod v4 schemas', () => {\n it('should successfully parse valid v4 data', async () => {\n const schema = z4.object({\n name: z4.string(),\n age: z4.number(),\n });\n\n const result = await parseZodSchema(schema, { name: 'John', age: 30 });\n\n expect(result.success).toBe(true);\n if (result.success) {\n expect(result.data).toEqual({ name: 'John', age: 30 });\n }\n });\n\n it('should fail to parse invalid v4 data', async () => {\n const schema = z4.object({\n name: z4.string(),\n age: z4.number(),\n });\n\n const result = await parseZodSchema(schema, { name: 'John', age: 'invalid' });\n\n expect(result.success).toBe(false);\n if (!result.success) {\n expect(result.error).toBeDefined();\n }\n });\n\n it('should handle v4 optional fields', async () => {\n const schema = z4.object({\n name: z4.string(),\n email: z4.string().optional(),\n });\n\n const result1 = await parseZodSchema(schema, { name: 'John' });\n expect(result1.success).toBe(true);\n\n const result2 = await parseZodSchema(schema, { name: 'John', email: 'john@example.com' });\n expect(result2.success).toBe(true);\n });\n\n it('should handle v4 default values', async () => {\n const schema = z4.object({\n name: z4.string(),\n role: z4.string().default('user'),\n });\n\n const result = await parseZodSchema(schema, { name: 'John' });\n\n expect(result.success).toBe(true);\n if (result.success) {\n expect(result.data).toEqual({ name: 'John', role: 'user' });\n }\n });\n });\n\n describe('Zod v3 schemas', () => {\n it('should successfully parse valid v3 data', async () => {\n const schema = z3.object({\n name: z3.string(),\n age: z3.number(),\n });\n\n const result = await parseZodSchema(schema, { name: 'John', age: 30 });\n\n expect(result.success).toBe(true);\n if (result.success) {\n expect(result.data).toEqual({ name: 'John', age: 30 });\n }\n });\n\n it('should fail to parse invalid v3 data', async () => {\n const schema = z3.object({\n name: z3.string(),\n age: z3.number(),\n });\n\n const result = await parseZodSchema(schema, { name: 'John', age: 'invalid' });\n\n expect(result.success).toBe(false);\n if (!result.success) {\n expect(result.error).toBeDefined();\n }\n });\n\n it('should handle v3 optional fields', async () => {\n const schema = z3.object({\n name: z3.string(),\n email: z3.string().optional(),\n });\n\n const result1 = await parseZodSchema(schema, { name: 'John' });\n expect(result1.success).toBe(true);\n\n const result2 = await parseZodSchema(schema, { name: 'John', email: 'john@example.com' });\n expect(result2.success).toBe(true);\n });\n\n it('should handle v3 default values', async () => {\n const schema = z3.object({\n name: z3.string(),\n role: z3.string().default('user'),\n });\n\n const result = await parseZodSchema(schema, { name: 'John' });\n\n expect(result.success).toBe(true);\n if (result.success) {\n expect(result.data).toEqual({ name: 'John', role: 'user' });\n }\n });\n });\n });\n\n describe('Cross-version compatibility', () => {\n it('should handle mixed v3 and v4 schemas in the same codebase', async () => {\n const v3Schema = z3.object({ name: z3.string() });\n const v4Schema = z4.object({ name: z4.string() });\n\n const v3Result = await parseZodSchema(v3Schema, { name: 'John' });\n const v4Result = await parseZodSchema(v4Schema, { name: 'Jane' });\n\n expect(v3Result.success).toBe(true);\n expect(v4Result.success).toBe(true);\n });\n\n it('should convert both v3 and v4 basic schemas to compatible JSON Schema', () => {\n const v3Schema = z3.object({ count: z3.number() });\n const v4Schema = z4.object({ count: z4.number() });\n\n const v3Json = zodSchemaToJsonSchema(v3Schema);\n const v4Json = zodSchemaToJsonSchema(v4Schema);\n\n // Both should produce valid JSON Schema with same structure\n expect(v3Json.type).toBe('object');\n expect(v4Json.type).toBe('object');\n expect((v3Json.properties as JSONSchemaProperties).count?.type).toBe('number');\n expect((v4Json.properties as JSONSchemaProperties).count?.type).toBe('number');\n });\n\n it('should handle optional fields consistently across v3 and v4', () => {\n const v3Schema = z3.object({\n required: z3.string(),\n optional: z3.string().optional(),\n });\n const v4Schema = z4.object({\n required: z4.string(),\n optional: z4.string().optional(),\n });\n\n const v3Json = zodSchemaToJsonSchema(v3Schema);\n const v4Json = zodSchemaToJsonSchema(v4Schema);\n\n // Both should mark 'required' as required\n expect(v3Json.required).toContain('required');\n expect(v4Json.required).toContain('required');\n\n // v4 should NOT mark 'optional' as required\n expect(v4Json.required).not.toContain('optional');\n\n // NOTE: v3's optional handling in zod-to-json-schema (for the v3 export) has quirks\n // in the alpha version 3.25.76. The default z import works correctly for users.\n });\n\n it('should handle complex schemas with nested objects and arrays consistently', () => {\n const v3Schema = z3.object({\n user: z3.object({\n name: z3.string(),\n email: z3.string().optional(),\n }),\n tags: z3.array(z3.string()),\n status: z3.enum(['active', 'inactive']),\n });\n\n const v4Schema = z4.object({\n user: z4.object({\n name: z4.string(),\n email: z4.string().optional(),\n }),\n tags: z4.array(z4.string()),\n status: z4.enum(['active', 'inactive']),\n });\n\n const v3Json = zodSchemaToJsonSchema(v3Schema);\n const v4Json = zodSchemaToJsonSchema(v4Schema);\n\n // Check structure compatibility\n expect(v3Json.type).toBe(v4Json.type);\n expect(Object.keys(v3Json.properties || {})).toEqual(Object.keys(v4Json.properties || {}));\n\n // Check nested object\n const v3User = (v3Json.properties as JSONSchemaProperties).user;\n const v4User = (v4Json.properties as JSONSchemaProperties).user;\n expect(v3User?.type).toBe('object');\n expect(v4User?.type).toBe('object');\n\n // Check array\n const v3Tags = (v3Json.properties as JSONSchemaProperties).tags;\n const v4Tags = (v4Json.properties as JSONSchemaProperties).tags;\n expect(v3Tags?.type).toBe('array');\n expect(v4Tags?.type).toBe('array');\n\n // Check enum\n const v3Status = (v3Json.properties as JSONSchemaProperties).status;\n const v4Status = (v4Json.properties as JSONSchemaProperties).status;\n expect(v3Status?.enum).toEqual(['active', 'inactive']);\n expect(v4Status?.enum).toEqual(['active', 'inactive']);\n });\n });\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/metrics/base.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nexport type AgentMetrics =\n | STTMetrics\n | LLMMetrics\n | TTSMetrics\n | VADMetrics\n | EOUMetrics\n | RealtimeModelMetrics;\n\nexport type LLMMetrics = {\n type: 'llm_metrics';\n label: string;\n requestId: string;\n timestamp: number;\n /** Duration of the request in milliseconds. */\n durationMs: number;\n /** Time to first token in milliseconds. */\n ttftMs: number;\n cancelled: boolean;\n completionTokens: number;\n promptTokens: number;\n promptCachedTokens: number;\n totalTokens: number;\n tokensPerSecond: number;\n speechId?: string;\n};\n\nexport type STTMetrics = {\n type: 'stt_metrics';\n label: string;\n requestId: string;\n timestamp: number;\n /**\n * The request duration in milliseconds, 0.0 if the STT is streaming.\n */\n durationMs: number;\n /**\n * The duration of the pushed audio in milliseconds.\n */\n audioDurationMs: number;\n /**\n * Whether the STT is streaming (e.g using websocket).\n */\n streamed: boolean;\n};\n\nexport type TTSMetrics = {\n type: 'tts_metrics';\n label: string;\n requestId: string;\n timestamp: number;\n /** Time to first byte in milliseconds. */\n ttfbMs: number;\n /** Total synthesis duration in milliseconds. */\n durationMs: number;\n /** Generated audio duration in milliseconds. */\n audioDurationMs: number;\n cancelled: boolean;\n charactersCount: number;\n streamed: boolean;\n segmentId?: string;\n speechId?: string;\n};\n\nexport type VADMetrics = {\n type: 'vad_metrics';\n label: string;\n timestamp: number;\n idleTimeMs: number;\n inferenceDurationTotalMs: number;\n inferenceCount: number;\n};\n\nexport type EOUMetrics = {\n type: 'eou_metrics';\n timestamp: number;\n /**\n * Amount of time between the end of speech from VAD and the decision to end the user's turn.\n * Set to 0.0 if the end of speech was not detected.\n */\n endOfUtteranceDelayMs: number;\n /**\n * Time taken to obtain the transcript after the end of the user's speech.\n * Set to 0.0 if the end of speech was not detected.\n */\n transcriptionDelayMs: number;\n /**\n * Time taken to invoke the user's `Agent.onUserTurnCompleted` callback.\n */\n onUserTurnCompletedDelayMs: number;\n speechId?: string;\n};\n\nexport type RealtimeModelMetricsCachedTokenDetails = {\n audioTokens: number;\n textTokens: number;\n imageTokens: number;\n};\n\nexport type RealtimeModelMetricsInputTokenDetails = {\n audioTokens: number;\n textTokens: number;\n imageTokens: number;\n cachedTokens: number;\n cachedTokensDetails?: RealtimeModelMetricsCachedTokenDetails;\n};\n\nexport type RealtimeModelMetricsOutputTokenDetails = {\n textTokens: number;\n audioTokens: number;\n imageTokens: number;\n};\n\nexport type RealtimeModelMetrics = {\n type: 'realtime_model_metrics';\n label: string;\n requestId: string;\n /**\n * The timestamp of the response creation.\n */\n timestamp: number;\n /**\n * The duration of the response from created to done in milliseconds.\n */\n durationMs: number;\n /**\n * Time to first audio token in milliseconds. -1 if no audio token was sent.\n */\n ttftMs: number;\n /**\n * Whether the request was cancelled.\n */\n cancelled: boolean;\n /**\n * The number of input tokens used in the Response, including text and audio tokens.\n */\n inputTokens: number;\n /**\n * The number of output tokens sent in the Response, including text and audio tokens.\n */\n outputTokens: number;\n /**\n * The total number of tokens in the Response.\n */\n totalTokens: number;\n /**\n * The number of tokens per second.\n */\n tokensPerSecond: number;\n /**\n * Details about the input tokens used in the Response.\n */\n inputTokenDetails: RealtimeModelMetricsInputTokenDetails;\n /**\n * Details about the output tokens used in the Response.\n */\n outputTokenDetails: RealtimeModelMetricsOutputTokenDetails;\n};\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/base.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nexport type AgentMetrics =\n | STTMetrics\n | LLMMetrics\n | TTSMetrics\n | VADMetrics\n | EOUMetrics\n | RealtimeModelMetrics;\n\nexport type LLMMetrics = {\n type: 'llm_metrics';\n label: string;\n requestId: string;\n timestamp: number;\n /** Duration of the request in milliseconds. */\n durationMs: number;\n /** Time to first token in milliseconds. */\n ttftMs: number;\n cancelled: boolean;\n completionTokens: number;\n promptTokens: number;\n promptCachedTokens: number;\n totalTokens: number;\n tokensPerSecond: number;\n speechId?: string;\n};\n\nexport type STTMetrics = {\n type: 'stt_metrics';\n label: string;\n requestId: string;\n timestamp: number;\n /**\n * The request duration in milliseconds, 0.0 if the STT is streaming.\n */\n durationMs: number;\n /**\n * The duration of the pushed audio in milliseconds.\n */\n audioDurationMs: number;\n /**\n * Whether the STT is streaming (e.g using websocket).\n */\n streamed: boolean;\n};\n\nexport type TTSMetrics = {\n type: 'tts_metrics';\n label: string;\n requestId: string;\n timestamp: number;\n /** Time to first byte in milliseconds. */\n ttfbMs: number;\n /** Total synthesis duration in milliseconds. */\n durationMs: number;\n /** Generated audio duration in milliseconds. */\n audioDurationMs: number;\n cancelled: boolean;\n charactersCount: number;\n streamed: boolean;\n segmentId?: string;\n speechId?: string;\n};\n\nexport type VADMetrics = {\n type: 'vad_metrics';\n label: string;\n timestamp: number;\n idleTimeMs: number;\n inferenceDurationTotalMs: number;\n inferenceCount: number;\n};\n\nexport type EOUMetrics = {\n type: 'eou_metrics';\n timestamp: number;\n /**\n * Amount of time between the end of speech from VAD and the decision to end the user's turn.\n * Set to 0.0 if the end of speech was not detected.\n */\n endOfUtteranceDelayMs: number;\n /**\n * Time taken to obtain the transcript after the end of the user's speech.\n * Set to 0.0 if the end of speech was not detected.\n */\n transcriptionDelayMs: number;\n /**\n * Time taken to invoke the user's `Agent.onUserTurnCompleted` callback.\n */\n onUserTurnCompletedDelayMs: number;\n /**\n * The time the user stopped speaking.\n */\n lastSpeakingTimeMs: number;\n /**\n * The ID of the speech handle.\n */\n speechId?: string;\n};\n\nexport type RealtimeModelMetricsCachedTokenDetails = {\n audioTokens: number;\n textTokens: number;\n imageTokens: number;\n};\n\nexport type RealtimeModelMetricsInputTokenDetails = {\n audioTokens: number;\n textTokens: number;\n imageTokens: number;\n cachedTokens: number;\n cachedTokensDetails?: RealtimeModelMetricsCachedTokenDetails;\n};\n\nexport type RealtimeModelMetricsOutputTokenDetails = {\n textTokens: number;\n audioTokens: number;\n imageTokens: number;\n};\n\nexport type RealtimeModelMetrics = {\n type: 'realtime_model_metrics';\n label: string;\n requestId: string;\n /**\n * The timestamp of the response creation.\n */\n timestamp: number;\n /**\n * The duration of the response from created to done in milliseconds.\n */\n durationMs: number;\n /**\n * Time to first audio token in milliseconds. -1 if no audio token was sent.\n */\n ttftMs: number;\n /**\n * Whether the request was cancelled.\n */\n cancelled: boolean;\n /**\n * The number of input tokens used in the Response, including text and audio tokens.\n */\n inputTokens: number;\n /**\n * The number of output tokens sent in the Response, including text and audio tokens.\n */\n outputTokens: number;\n /**\n * The total number of tokens in the Response.\n */\n totalTokens: number;\n /**\n * The number of tokens per second.\n */\n tokensPerSecond: number;\n /**\n * Details about the input tokens used in the Response.\n */\n inputTokenDetails: RealtimeModelMetricsInputTokenDetails;\n /**\n * Details about the output tokens used in the Response.\n */\n outputTokenDetails: RealtimeModelMetricsOutputTokenDetails;\n};\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
package/dist/metrics/base.d.cts
CHANGED
|
@@ -76,6 +76,13 @@ export type EOUMetrics = {
|
|
|
76
76
|
* Time taken to invoke the user's `Agent.onUserTurnCompleted` callback.
|
|
77
77
|
*/
|
|
78
78
|
onUserTurnCompletedDelayMs: number;
|
|
79
|
+
/**
|
|
80
|
+
* The time the user stopped speaking.
|
|
81
|
+
*/
|
|
82
|
+
lastSpeakingTimeMs: number;
|
|
83
|
+
/**
|
|
84
|
+
* The ID of the speech handle.
|
|
85
|
+
*/
|
|
79
86
|
speechId?: string;
|
|
80
87
|
};
|
|
81
88
|
export type RealtimeModelMetricsCachedTokenDetails = {
|
package/dist/metrics/base.d.ts
CHANGED
|
@@ -76,6 +76,13 @@ export type EOUMetrics = {
|
|
|
76
76
|
* Time taken to invoke the user's `Agent.onUserTurnCompleted` callback.
|
|
77
77
|
*/
|
|
78
78
|
onUserTurnCompletedDelayMs: number;
|
|
79
|
+
/**
|
|
80
|
+
* The time the user stopped speaking.
|
|
81
|
+
*/
|
|
82
|
+
lastSpeakingTimeMs: number;
|
|
83
|
+
/**
|
|
84
|
+
* The ID of the speech handle.
|
|
85
|
+
*/
|
|
79
86
|
speechId?: string;
|
|
80
87
|
};
|
|
81
88
|
export type RealtimeModelMetricsCachedTokenDetails = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/metrics/base.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/metrics/base.ts"],"names":[],"mappings":"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"}
|
package/dist/stt/stt.cjs
CHANGED
|
@@ -37,6 +37,7 @@ var SpeechEventType = /* @__PURE__ */ ((SpeechEventType2) => {
|
|
|
37
37
|
SpeechEventType2[SpeechEventType2["FINAL_TRANSCRIPT"] = 2] = "FINAL_TRANSCRIPT";
|
|
38
38
|
SpeechEventType2[SpeechEventType2["END_OF_SPEECH"] = 3] = "END_OF_SPEECH";
|
|
39
39
|
SpeechEventType2[SpeechEventType2["RECOGNITION_USAGE"] = 4] = "RECOGNITION_USAGE";
|
|
40
|
+
SpeechEventType2[SpeechEventType2["PREFLIGHT_TRANSCRIPT"] = 5] = "PREFLIGHT_TRANSCRIPT";
|
|
40
41
|
return SpeechEventType2;
|
|
41
42
|
})(SpeechEventType || {});
|
|
42
43
|
class STT extends import_node_events.EventEmitter {
|
package/dist/stt/stt.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/stt/stt.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type AudioFrame, AudioResampler } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport { APIConnectionError, APIError } from '../_exceptions.js';\nimport { calculateAudioDurationSeconds } from '../audio.js';\nimport { log } from '../log.js';\nimport type { STTMetrics } from '../metrics/base.js';\nimport { DeferredReadableStream } from '../stream/deferred_stream.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../types.js';\nimport type { AudioBuffer } from '../utils.js';\nimport { AsyncIterableQueue, delay, startSoon, toError } from '../utils.js';\n\n/** Indicates start/middle/end of speech */\nexport enum SpeechEventType {\n /**\n * Indicate the start of speech.\n * If the STT doesn't support this event, this will be emitted at the same time\n * as the first INTERIM_TRANSCRIPT.\n */\n START_OF_SPEECH = 0,\n /**\n * Interim transcript, useful for real-time transcription.\n */\n INTERIM_TRANSCRIPT = 1,\n /**\n * Final transcript, emitted when the STT is confident enough that a certain\n * portion of the speech will not change.\n */\n FINAL_TRANSCRIPT = 2,\n /**\n * Indicate the end of speech, emitted when the user stops speaking.\n * The first alternative is a combination of all the previous FINAL_TRANSCRIPT events.\n */\n END_OF_SPEECH = 3,\n /** Usage event, emitted periodically to indicate usage metrics. */\n RECOGNITION_USAGE = 4,\n}\n\n/** SpeechData contains metadata about this {@link SpeechEvent}. */\nexport interface SpeechData {\n language: string;\n text: string;\n startTime: number;\n endTime: number;\n confidence: number;\n}\n\nexport interface RecognitionUsage {\n audioDuration: number;\n}\n\n/** SpeechEvent is a packet of speech-to-text data. */\nexport interface SpeechEvent {\n type: SpeechEventType;\n alternatives?: [SpeechData, ...SpeechData[]];\n requestId?: string;\n recognitionUsage?: RecognitionUsage;\n}\n\n/**\n * Describes the capabilities of the STT provider.\n *\n * @remarks\n * At present, the framework only supports providers that have a streaming endpoint.\n */\nexport interface STTCapabilities {\n streaming: boolean;\n interimResults: boolean;\n}\n\nexport interface STTError {\n type: 'stt_error';\n timestamp: number;\n label: string;\n error: Error;\n recoverable: boolean;\n}\n\nexport type STTCallbacks = {\n ['metrics_collected']: (metrics: STTMetrics) => void;\n ['error']: (error: STTError) => void;\n};\n\n/**\n * An instance of a speech-to-text adapter.\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child STT class, which inherits this class's methods.\n */\nexport abstract class STT extends (EventEmitter as new () => TypedEmitter<STTCallbacks>) {\n abstract label: string;\n #capabilities: STTCapabilities;\n\n constructor(capabilities: STTCapabilities) {\n super();\n this.#capabilities = capabilities;\n }\n\n /** Returns this STT's capabilities */\n get capabilities(): STTCapabilities {\n return this.#capabilities;\n }\n\n /** Receives an audio buffer and returns transcription in the form of a {@link SpeechEvent} */\n async recognize(frame: AudioBuffer): Promise<SpeechEvent> {\n const startTime = process.hrtime.bigint();\n const event = await this._recognize(frame);\n const durationMs = Number((process.hrtime.bigint() - startTime) / BigInt(1000000));\n this.emit('metrics_collected', {\n type: 'stt_metrics',\n requestId: event.requestId ?? '',\n timestamp: Date.now(),\n durationMs,\n label: this.label,\n audioDurationMs: Math.round(calculateAudioDurationSeconds(frame) * 1000),\n streamed: false,\n });\n return event;\n }\n protected abstract _recognize(frame: AudioBuffer): Promise<SpeechEvent>;\n\n /**\n * Returns a {@link SpeechStream} that can be used to push audio frames and receive\n * transcriptions\n */\n abstract stream(): SpeechStream;\n}\n\n/**\n * An instance of a speech-to-text stream, as an asynchronous iterable iterator.\n *\n * @example Looping through frames\n * ```ts\n * for await (const event of stream) {\n * if (event.type === SpeechEventType.FINAL_TRANSCRIPT) {\n * console.log(event.alternatives[0].text)\n * }\n * }\n * ```\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child SpeechStream class, which inherits this class's methods.\n */\nexport abstract class SpeechStream implements AsyncIterableIterator<SpeechEvent> {\n protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');\n protected input = new AsyncIterableQueue<AudioFrame | typeof SpeechStream.FLUSH_SENTINEL>();\n protected output = new AsyncIterableQueue<SpeechEvent>();\n protected queue = new AsyncIterableQueue<SpeechEvent>();\n protected neededSampleRate?: number;\n protected resampler?: AudioResampler;\n abstract label: string;\n protected closed = false;\n #stt: STT;\n private deferredInputStream: DeferredReadableStream<AudioFrame>;\n private logger = log();\n private _connOptions: APIConnectOptions;\n\n constructor(\n stt: STT,\n sampleRate?: number,\n connectionOptions: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,\n ) {\n this.#stt = stt;\n this._connOptions = connectionOptions;\n this.deferredInputStream = new DeferredReadableStream<AudioFrame>();\n this.neededSampleRate = sampleRate;\n this.monitorMetrics();\n this.pumpInput();\n\n // this is a hack to immitate asyncio.create_task so that mainTask\n // is run **after** the constructor has finished. Otherwise we get\n // runtime error when trying to access class variables in the\n // `run` method.\n startSoon(() => this.mainTask().then(() => this.queue.close()));\n }\n\n private async mainTask() {\n for (let i = 0; i < this._connOptions.maxRetry + 1; i++) {\n try {\n return await this.run();\n } catch (error) {\n if (error instanceof APIError) {\n const retryInterval = this._connOptions._intervalForRetry(i);\n\n if (this._connOptions.maxRetry === 0 || !error.retryable) {\n this.emitError({ error, recoverable: false });\n throw error;\n } else if (i === this._connOptions.maxRetry) {\n this.emitError({ error, recoverable: false });\n throw new APIConnectionError({\n message: `failed to recognize speech after ${this._connOptions.maxRetry + 1} attempts`,\n options: { retryable: false },\n });\n } else {\n this.emitError({ error, recoverable: true });\n this.logger.warn(\n { tts: this.#stt.label, attempt: i + 1, error },\n `failed to recognize speech, retrying in ${retryInterval}s`,\n );\n }\n\n if (retryInterval > 0) {\n await delay(retryInterval);\n }\n } else {\n this.emitError({ error: toError(error), recoverable: false });\n throw error;\n }\n }\n }\n }\n\n private emitError({ error, recoverable }: { error: Error; recoverable: boolean }) {\n this.#stt.emit('error', {\n type: 'stt_error',\n timestamp: Date.now(),\n label: this.#stt.label,\n error,\n recoverable,\n });\n }\n\n protected async pumpInput() {\n // TODO(AJS-35): Implement STT with webstreams API\n const inputStream = this.deferredInputStream.stream;\n const reader = inputStream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n this.pushFrame(value);\n }\n } catch (error) {\n this.logger.error('Error in STTStream mainTask:', error);\n } finally {\n reader.releaseLock();\n }\n }\n\n protected async monitorMetrics() {\n for await (const event of this.queue) {\n this.output.put(event);\n if (event.type !== SpeechEventType.RECOGNITION_USAGE) continue;\n const metrics: STTMetrics = {\n type: 'stt_metrics',\n timestamp: Date.now(),\n requestId: event.requestId!,\n durationMs: 0,\n label: this.#stt.label,\n audioDurationMs: Math.round(event.recognitionUsage!.audioDuration * 1000),\n streamed: true,\n };\n this.#stt.emit('metrics_collected', metrics);\n }\n this.output.close();\n }\n\n protected abstract run(): Promise<void>;\n\n updateInputStream(audioStream: ReadableStream<AudioFrame>) {\n this.deferredInputStream.setSource(audioStream);\n }\n\n detachInputStream() {\n this.deferredInputStream.detachSource();\n }\n\n /** Push an audio frame to the STT */\n pushFrame(frame: AudioFrame) {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n\n if (this.neededSampleRate && frame.sampleRate !== this.neededSampleRate) {\n if (!this.resampler) {\n this.resampler = new AudioResampler(frame.sampleRate, this.neededSampleRate);\n }\n }\n\n if (this.resampler) {\n const frames = this.resampler.push(frame);\n for (const frame of frames) {\n this.input.put(frame);\n }\n } else {\n this.input.put(frame);\n }\n }\n\n /** Flush the STT, causing it to process all pending text */\n flush() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.put(SpeechStream.FLUSH_SENTINEL);\n }\n\n /** Mark the input as ended and forbid additional pushes */\n endInput() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.close();\n }\n\n next(): Promise<IteratorResult<SpeechEvent>> {\n return this.output.next();\n }\n\n /** Close both the input and output of the STT stream */\n close() {\n this.input.close();\n this.queue.close();\n this.output.close();\n this.closed = true;\n }\n\n [Symbol.asyncIterator](): SpeechStream {\n return this;\n }\n}\n"],"mappings":"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","names":["SpeechEventType","frame"]}
|
|
1
|
+
{"version":3,"sources":["../../src/stt/stt.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type AudioFrame, AudioResampler } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport { APIConnectionError, APIError } from '../_exceptions.js';\nimport { calculateAudioDurationSeconds } from '../audio.js';\nimport { log } from '../log.js';\nimport type { STTMetrics } from '../metrics/base.js';\nimport { DeferredReadableStream } from '../stream/deferred_stream.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../types.js';\nimport type { AudioBuffer } from '../utils.js';\nimport { AsyncIterableQueue, delay, startSoon, toError } from '../utils.js';\n\n/** Indicates start/middle/end of speech */\nexport enum SpeechEventType {\n /**\n * Indicate the start of speech.\n * If the STT doesn't support this event, this will be emitted at the same time\n * as the first INTERIM_TRANSCRIPT.\n */\n START_OF_SPEECH = 0,\n /**\n * Interim transcript, useful for real-time transcription.\n */\n INTERIM_TRANSCRIPT = 1,\n /**\n * Final transcript, emitted when the STT is confident enough that a certain\n * portion of the speech will not change.\n */\n FINAL_TRANSCRIPT = 2,\n /**\n * Indicate the end of speech, emitted when the user stops speaking.\n * The first alternative is a combination of all the previous FINAL_TRANSCRIPT events.\n */\n END_OF_SPEECH = 3,\n /** Usage event, emitted periodically to indicate usage metrics. */\n RECOGNITION_USAGE = 4,\n /**\n * Preflight transcript, emitted before final transcript when STT has high confidence\n * but hasn't fully committed yet. Includes all pre-committed transcripts including\n * final transcript from the previous STT run.\n */\n PREFLIGHT_TRANSCRIPT = 5,\n}\n\n/** SpeechData contains metadata about this {@link SpeechEvent}. */\nexport interface SpeechData {\n language: string;\n text: string;\n startTime: number;\n endTime: number;\n confidence: number;\n}\n\nexport interface RecognitionUsage {\n audioDuration: number;\n}\n\n/** SpeechEvent is a packet of speech-to-text data. */\nexport interface SpeechEvent {\n type: SpeechEventType;\n alternatives?: [SpeechData, ...SpeechData[]];\n requestId?: string;\n recognitionUsage?: RecognitionUsage;\n}\n\n/**\n * Describes the capabilities of the STT provider.\n *\n * @remarks\n * At present, the framework only supports providers that have a streaming endpoint.\n */\nexport interface STTCapabilities {\n streaming: boolean;\n interimResults: boolean;\n}\n\nexport interface STTError {\n type: 'stt_error';\n timestamp: number;\n label: string;\n error: Error;\n recoverable: boolean;\n}\n\nexport type STTCallbacks = {\n ['metrics_collected']: (metrics: STTMetrics) => void;\n ['error']: (error: STTError) => void;\n};\n\n/**\n * An instance of a speech-to-text adapter.\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child STT class, which inherits this class's methods.\n */\nexport abstract class STT extends (EventEmitter as new () => TypedEmitter<STTCallbacks>) {\n abstract label: string;\n #capabilities: STTCapabilities;\n\n constructor(capabilities: STTCapabilities) {\n super();\n this.#capabilities = capabilities;\n }\n\n /** Returns this STT's capabilities */\n get capabilities(): STTCapabilities {\n return this.#capabilities;\n }\n\n /** Receives an audio buffer and returns transcription in the form of a {@link SpeechEvent} */\n async recognize(frame: AudioBuffer): Promise<SpeechEvent> {\n const startTime = process.hrtime.bigint();\n const event = await this._recognize(frame);\n const durationMs = Number((process.hrtime.bigint() - startTime) / BigInt(1000000));\n this.emit('metrics_collected', {\n type: 'stt_metrics',\n requestId: event.requestId ?? '',\n timestamp: Date.now(),\n durationMs,\n label: this.label,\n audioDurationMs: Math.round(calculateAudioDurationSeconds(frame) * 1000),\n streamed: false,\n });\n return event;\n }\n protected abstract _recognize(frame: AudioBuffer): Promise<SpeechEvent>;\n\n /**\n * Returns a {@link SpeechStream} that can be used to push audio frames and receive\n * transcriptions\n */\n abstract stream(): SpeechStream;\n}\n\n/**\n * An instance of a speech-to-text stream, as an asynchronous iterable iterator.\n *\n * @example Looping through frames\n * ```ts\n * for await (const event of stream) {\n * if (event.type === SpeechEventType.FINAL_TRANSCRIPT) {\n * console.log(event.alternatives[0].text)\n * }\n * }\n * ```\n *\n * @remarks\n * This class is abstract, and as such cannot be used directly. Instead, use a provider plugin that\n * exports its own child SpeechStream class, which inherits this class's methods.\n */\nexport abstract class SpeechStream implements AsyncIterableIterator<SpeechEvent> {\n protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');\n protected input = new AsyncIterableQueue<AudioFrame | typeof SpeechStream.FLUSH_SENTINEL>();\n protected output = new AsyncIterableQueue<SpeechEvent>();\n protected queue = new AsyncIterableQueue<SpeechEvent>();\n protected neededSampleRate?: number;\n protected resampler?: AudioResampler;\n abstract label: string;\n protected closed = false;\n #stt: STT;\n private deferredInputStream: DeferredReadableStream<AudioFrame>;\n private logger = log();\n private _connOptions: APIConnectOptions;\n\n constructor(\n stt: STT,\n sampleRate?: number,\n connectionOptions: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,\n ) {\n this.#stt = stt;\n this._connOptions = connectionOptions;\n this.deferredInputStream = new DeferredReadableStream<AudioFrame>();\n this.neededSampleRate = sampleRate;\n this.monitorMetrics();\n this.pumpInput();\n\n // this is a hack to immitate asyncio.create_task so that mainTask\n // is run **after** the constructor has finished. Otherwise we get\n // runtime error when trying to access class variables in the\n // `run` method.\n startSoon(() => this.mainTask().then(() => this.queue.close()));\n }\n\n private async mainTask() {\n for (let i = 0; i < this._connOptions.maxRetry + 1; i++) {\n try {\n return await this.run();\n } catch (error) {\n if (error instanceof APIError) {\n const retryInterval = this._connOptions._intervalForRetry(i);\n\n if (this._connOptions.maxRetry === 0 || !error.retryable) {\n this.emitError({ error, recoverable: false });\n throw error;\n } else if (i === this._connOptions.maxRetry) {\n this.emitError({ error, recoverable: false });\n throw new APIConnectionError({\n message: `failed to recognize speech after ${this._connOptions.maxRetry + 1} attempts`,\n options: { retryable: false },\n });\n } else {\n this.emitError({ error, recoverable: true });\n this.logger.warn(\n { tts: this.#stt.label, attempt: i + 1, error },\n `failed to recognize speech, retrying in ${retryInterval}s`,\n );\n }\n\n if (retryInterval > 0) {\n await delay(retryInterval);\n }\n } else {\n this.emitError({ error: toError(error), recoverable: false });\n throw error;\n }\n }\n }\n }\n\n private emitError({ error, recoverable }: { error: Error; recoverable: boolean }) {\n this.#stt.emit('error', {\n type: 'stt_error',\n timestamp: Date.now(),\n label: this.#stt.label,\n error,\n recoverable,\n });\n }\n\n protected async pumpInput() {\n // TODO(AJS-35): Implement STT with webstreams API\n const inputStream = this.deferredInputStream.stream;\n const reader = inputStream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n this.pushFrame(value);\n }\n } catch (error) {\n this.logger.error('Error in STTStream mainTask:', error);\n } finally {\n reader.releaseLock();\n }\n }\n\n protected async monitorMetrics() {\n for await (const event of this.queue) {\n this.output.put(event);\n if (event.type !== SpeechEventType.RECOGNITION_USAGE) continue;\n const metrics: STTMetrics = {\n type: 'stt_metrics',\n timestamp: Date.now(),\n requestId: event.requestId!,\n durationMs: 0,\n label: this.#stt.label,\n audioDurationMs: Math.round(event.recognitionUsage!.audioDuration * 1000),\n streamed: true,\n };\n this.#stt.emit('metrics_collected', metrics);\n }\n this.output.close();\n }\n\n protected abstract run(): Promise<void>;\n\n updateInputStream(audioStream: ReadableStream<AudioFrame>) {\n this.deferredInputStream.setSource(audioStream);\n }\n\n detachInputStream() {\n this.deferredInputStream.detachSource();\n }\n\n /** Push an audio frame to the STT */\n pushFrame(frame: AudioFrame) {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n\n if (this.neededSampleRate && frame.sampleRate !== this.neededSampleRate) {\n if (!this.resampler) {\n this.resampler = new AudioResampler(frame.sampleRate, this.neededSampleRate);\n }\n }\n\n if (this.resampler) {\n const frames = this.resampler.push(frame);\n for (const frame of frames) {\n this.input.put(frame);\n }\n } else {\n this.input.put(frame);\n }\n }\n\n /** Flush the STT, causing it to process all pending text */\n flush() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.put(SpeechStream.FLUSH_SENTINEL);\n }\n\n /** Mark the input as ended and forbid additional pushes */\n endInput() {\n if (this.input.closed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.input.close();\n }\n\n next(): Promise<IteratorResult<SpeechEvent>> {\n return this.output.next();\n }\n\n /** Close both the input and output of the STT stream */\n close() {\n this.input.close();\n this.queue.close();\n this.output.close();\n this.closed = true;\n }\n\n [Symbol.asyncIterator](): SpeechStream {\n return this;\n }\n}\n"],"mappings":"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","names":["SpeechEventType","frame"]}
|
package/dist/stt/stt.d.cts
CHANGED
|
@@ -29,7 +29,13 @@ export declare enum SpeechEventType {
|
|
|
29
29
|
*/
|
|
30
30
|
END_OF_SPEECH = 3,
|
|
31
31
|
/** Usage event, emitted periodically to indicate usage metrics. */
|
|
32
|
-
RECOGNITION_USAGE = 4
|
|
32
|
+
RECOGNITION_USAGE = 4,
|
|
33
|
+
/**
|
|
34
|
+
* Preflight transcript, emitted before final transcript when STT has high confidence
|
|
35
|
+
* but hasn't fully committed yet. Includes all pre-committed transcripts including
|
|
36
|
+
* final transcript from the previous STT run.
|
|
37
|
+
*/
|
|
38
|
+
PREFLIGHT_TRANSCRIPT = 5
|
|
33
39
|
}
|
|
34
40
|
/** SpeechData contains metadata about this {@link SpeechEvent}. */
|
|
35
41
|
export interface SpeechData {
|
package/dist/stt/stt.d.ts
CHANGED
|
@@ -29,7 +29,13 @@ export declare enum SpeechEventType {
|
|
|
29
29
|
*/
|
|
30
30
|
END_OF_SPEECH = 3,
|
|
31
31
|
/** Usage event, emitted periodically to indicate usage metrics. */
|
|
32
|
-
RECOGNITION_USAGE = 4
|
|
32
|
+
RECOGNITION_USAGE = 4,
|
|
33
|
+
/**
|
|
34
|
+
* Preflight transcript, emitted before final transcript when STT has high confidence
|
|
35
|
+
* but hasn't fully committed yet. Includes all pre-committed transcripts including
|
|
36
|
+
* final transcript from the previous STT run.
|
|
37
|
+
*/
|
|
38
|
+
PREFLIGHT_TRANSCRIPT = 5
|
|
33
39
|
}
|
|
34
40
|
/** SpeechData contains metadata about this {@link SpeechEvent}. */
|
|
35
41
|
export interface SpeechData {
|
package/dist/stt/stt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stt.d.ts","sourceRoot":"","sources":["../../src/stt/stt.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,KAAK,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,IAAI,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAItD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,KAAK,iBAAiB,EAA+B,MAAM,aAAa,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAA6B,MAAM,aAAa,CAAC;AAE5E,2CAA2C;AAC3C,oBAAY,eAAe;IACzB;;;;OAIG;IACH,eAAe,IAAI;IACnB;;OAEG;IACH,kBAAkB,IAAI;IACtB;;;OAGG;IACH,gBAAgB,IAAI;IACpB;;;OAGG;IACH,aAAa,IAAI;IACjB,mEAAmE;IACnE,iBAAiB,IAAI;
|
|
1
|
+
{"version":3,"file":"stt.d.ts","sourceRoot":"","sources":["../../src/stt/stt.ts"],"names":[],"mappings":"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"}
|
package/dist/stt/stt.js
CHANGED
|
@@ -12,6 +12,7 @@ var SpeechEventType = /* @__PURE__ */ ((SpeechEventType2) => {
|
|
|
12
12
|
SpeechEventType2[SpeechEventType2["FINAL_TRANSCRIPT"] = 2] = "FINAL_TRANSCRIPT";
|
|
13
13
|
SpeechEventType2[SpeechEventType2["END_OF_SPEECH"] = 3] = "END_OF_SPEECH";
|
|
14
14
|
SpeechEventType2[SpeechEventType2["RECOGNITION_USAGE"] = 4] = "RECOGNITION_USAGE";
|
|
15
|
+
SpeechEventType2[SpeechEventType2["PREFLIGHT_TRANSCRIPT"] = 5] = "PREFLIGHT_TRANSCRIPT";
|
|
15
16
|
return SpeechEventType2;
|
|
16
17
|
})(SpeechEventType || {});
|
|
17
18
|
class STT extends EventEmitter {
|