@metatell/bot-realtime 0.0.9 → 0.0.10

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 (40) hide show
  1. package/dist/create-transport.d.ts +21 -0
  2. package/dist/create-transport.d.ts.map +1 -0
  3. package/dist/create-transport.js +26 -0
  4. package/dist/create-transport.js.map +1 -0
  5. package/dist/create-transport.spec.d.ts +2 -0
  6. package/dist/create-transport.spec.d.ts.map +1 -0
  7. package/dist/create-transport.spec.js +70 -0
  8. package/dist/create-transport.spec.js.map +1 -0
  9. package/dist/errors.d.ts +6 -2
  10. package/dist/errors.d.ts.map +1 -1
  11. package/dist/errors.js +5 -0
  12. package/dist/errors.js.map +1 -1
  13. package/dist/index.d.ts +3 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +5 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/livekit.d.ts.map +1 -1
  18. package/dist/livekit.js +57 -5
  19. package/dist/livekit.js.map +1 -1
  20. package/dist/voice/agent-bridge.d.ts +13 -0
  21. package/dist/voice/agent-bridge.d.ts.map +1 -0
  22. package/dist/voice/agent-bridge.js +199 -0
  23. package/dist/voice/agent-bridge.js.map +1 -0
  24. package/dist/voice/agent-bridge.spec.d.ts +2 -0
  25. package/dist/voice/agent-bridge.spec.d.ts.map +1 -0
  26. package/dist/voice/agent-bridge.spec.js +339 -0
  27. package/dist/voice/agent-bridge.spec.js.map +1 -0
  28. package/dist/voice/frame-utils.d.ts +30 -0
  29. package/dist/voice/frame-utils.d.ts.map +1 -0
  30. package/dist/voice/frame-utils.js +63 -0
  31. package/dist/voice/frame-utils.js.map +1 -0
  32. package/dist/voice/frame-utils.spec.d.ts +2 -0
  33. package/dist/voice/frame-utils.spec.d.ts.map +1 -0
  34. package/dist/voice/frame-utils.spec.js +82 -0
  35. package/dist/voice/frame-utils.spec.js.map +1 -0
  36. package/dist/voice/types.d.ts +69 -0
  37. package/dist/voice/types.d.ts.map +1 -0
  38. package/dist/voice/types.js +2 -0
  39. package/dist/voice/types.js.map +1 -0
  40. package/package.json +3 -3
@@ -0,0 +1,339 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { InvalidAudioFrameError } from '../errors.js';
3
+ import { MockAdapter } from '../mock.js';
4
+ import { attachVoice } from './agent-bridge.js';
5
+ // Mock VoiceCapableClient
6
+ function createMockAgent() {
7
+ return {
8
+ sendVoiceFrame: vi.fn().mockRejectedValue(new Error('Voice not implemented')),
9
+ muteVoice: vi.fn().mockResolvedValue(undefined),
10
+ getSessionId: vi.fn().mockReturnValue('test-session-id'),
11
+ };
12
+ }
13
+ describe('agent-bridge', () => {
14
+ let agent;
15
+ let transport;
16
+ let handlers;
17
+ beforeEach(async () => {
18
+ agent = createMockAgent();
19
+ transport = new MockAdapter();
20
+ // Spy on transport methods
21
+ vi.spyOn(transport, 'pushPcmFrame');
22
+ vi.spyOn(transport, 'startAudioPublisher');
23
+ vi.spyOn(transport, 'stopAudioPublisher');
24
+ // Connect transport for tests that need it
25
+ await transport.connect({
26
+ url: 'wss://test',
27
+ tokenProvider: async () => 'test-token',
28
+ });
29
+ handlers = {
30
+ onRemotePcm: vi.fn(),
31
+ getLocalPcmStream: vi.fn(),
32
+ };
33
+ });
34
+ afterEach(async () => {
35
+ await transport.disconnect();
36
+ vi.clearAllMocks();
37
+ });
38
+ describe('attachVoice', () => {
39
+ it('should return detach function', async () => {
40
+ const attachment = attachVoice(agent, transport, handlers);
41
+ expect(attachment).toHaveProperty('detach');
42
+ expect(typeof attachment.detach).toBe('function');
43
+ await attachment.detach();
44
+ });
45
+ it('should add audio topic if not present', async () => {
46
+ // MockAdapter has activeTopics
47
+ const mockTransport = transport;
48
+ const activeTopics = mockTransport.activeTopics;
49
+ activeTopics.delete('audio');
50
+ expect(activeTopics.has('audio')).toBe(false);
51
+ const attachment = attachVoice(agent, transport, handlers);
52
+ expect(activeTopics.has('audio')).toBe(true);
53
+ await attachment.detach();
54
+ });
55
+ it('should not add audio topic if disabled', async () => {
56
+ const mockTransport = transport;
57
+ const activeTopics = mockTransport.activeTopics;
58
+ activeTopics.delete('audio');
59
+ const attachment = attachVoice(agent, transport, handlers, {
60
+ enableTopicAutoAdd: false,
61
+ });
62
+ expect(activeTopics.has('audio')).toBe(false);
63
+ await attachment.detach();
64
+ });
65
+ });
66
+ describe('receive processing', () => {
67
+ it('should call onRemotePcm when audio data received', async () => {
68
+ const attachment = attachVoice(agent, transport, handlers);
69
+ // Wait for mock audio to be emitted (participant joins after 100ms, then audio starts)
70
+ await new Promise((resolve) => setTimeout(resolve, 150));
71
+ expect(handlers.onRemotePcm).toHaveBeenCalled();
72
+ const mockHandler = handlers.onRemotePcm;
73
+ const call = mockHandler.mock.calls[0];
74
+ expect(call[0]).toBeInstanceOf(Int16Array);
75
+ expect(call[0].length).toBe(960); // 20ms at 48kHz
76
+ expect(call[1]).toMatchObject({ fromIdentity: 'mock-participant' });
77
+ await attachment.detach();
78
+ });
79
+ it('should handle onRemotePcm errors gracefully', async () => {
80
+ handlers.onRemotePcm = vi.fn().mockRejectedValue(new Error('Handler error'));
81
+ const attachment = attachVoice(agent, transport, handlers);
82
+ // Should not throw even if handler fails
83
+ await new Promise((resolve) => setTimeout(resolve, 150));
84
+ expect(handlers.onRemotePcm).toHaveBeenCalled();
85
+ await attachment.detach();
86
+ });
87
+ it('should not setup receive if no handler', async () => {
88
+ delete handlers.onRemotePcm;
89
+ const mockTransport = transport;
90
+ const listenersCount = mockTransport.listeners.size;
91
+ const attachment = attachVoice(agent, transport, handlers);
92
+ // No new listener should be added
93
+ expect(mockTransport.listeners.size).toBe(listenersCount);
94
+ await attachment.detach();
95
+ });
96
+ });
97
+ describe('send patching', () => {
98
+ it('should patch sendVoiceFrame to use transport', async () => {
99
+ // Set autoStartPublish to true and provide a stream
100
+ handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
101
+ yield new Int16Array(960);
102
+ });
103
+ const attachment = attachVoice(agent, transport, handlers, {
104
+ autoStartPublish: true,
105
+ });
106
+ // Wait for auto publish to start
107
+ await new Promise((resolve) => setTimeout(resolve, 50));
108
+ // Start audio publisher first
109
+ await transport.startAudioPublisher();
110
+ const pcm = new Int16Array(960); // 20ms frame
111
+ await agent.sendVoiceFrame?.(pcm);
112
+ expect(transport.pushPcmFrame).toHaveBeenCalledWith(pcm);
113
+ await attachment.detach();
114
+ });
115
+ it('should validate frame size for 20ms', async () => {
116
+ const attachment = attachVoice(agent, transport, handlers, {
117
+ frameDurationMs: 20,
118
+ });
119
+ const invalidPcm = new Int16Array(480); // Wrong size for 20ms
120
+ await expect(agent.sendVoiceFrame?.(invalidPcm)).rejects.toThrow(InvalidAudioFrameError);
121
+ await expect(agent.sendVoiceFrame?.(invalidPcm)).rejects.toThrow('expected=960');
122
+ await attachment.detach();
123
+ });
124
+ it('should validate frame size for 10ms', async () => {
125
+ const attachment = attachVoice(agent, transport, handlers, {
126
+ frameDurationMs: 10,
127
+ });
128
+ await transport.startAudioPublisher();
129
+ const validPcm = new Int16Array(480); // Correct for 10ms
130
+ await agent.sendVoiceFrame?.(validPcm);
131
+ expect(transport.pushPcmFrame).toHaveBeenCalledWith(validPcm);
132
+ const invalidPcm = new Int16Array(960); // Wrong size for 10ms
133
+ await expect(agent.sendVoiceFrame?.(invalidPcm)).rejects.toThrow('expected=480');
134
+ await attachment.detach();
135
+ });
136
+ it('should restore original sendVoiceFrame after detach', async () => {
137
+ const _originalSendVoice = agent.sendVoiceFrame;
138
+ const attachment = attachVoice(agent, transport, handlers);
139
+ await transport.startAudioPublisher();
140
+ // Patched version works
141
+ const pcm = new Int16Array(960);
142
+ await agent.sendVoiceFrame?.(pcm);
143
+ expect(transport.pushPcmFrame).toHaveBeenCalled();
144
+ await attachment.detach();
145
+ // Original throws again
146
+ await expect(agent.sendVoiceFrame?.(pcm)).rejects.toThrow('Voice not implemented');
147
+ });
148
+ });
149
+ describe('mute control', () => {
150
+ it('should patch muteVoice to use transport', async () => {
151
+ transport.setMicEnabled = vi.fn();
152
+ const attachment = attachVoice(agent, transport, handlers);
153
+ await agent.muteVoice?.(true);
154
+ expect(transport.setMicEnabled).toHaveBeenCalledWith(false);
155
+ await agent.muteVoice?.(false);
156
+ expect(transport.setMicEnabled).toHaveBeenCalledWith(true);
157
+ await attachment.detach();
158
+ });
159
+ it('should fallback to original if no setMicEnabled', async () => {
160
+ // Create a transport without setMicEnabled
161
+ const transportNoMic = new MockAdapter();
162
+ await transportNoMic.connect({
163
+ url: 'wss://test',
164
+ tokenProvider: async () => 'test-token',
165
+ });
166
+ // Spy on transport to verify setMicEnabled is not called
167
+ const setMicSpy = vi.spyOn(transportNoMic, 'setMicEnabled');
168
+ delete transportNoMic
169
+ .setMicEnabled;
170
+ const attachment = attachVoice(agent, transportNoMic, handlers);
171
+ // muteVoice should work without error (fallback to original)
172
+ await expect(agent.muteVoice?.(true)).resolves.toBeUndefined();
173
+ // Verify setMicEnabled was not called (it doesn't exist)
174
+ expect(setMicSpy).not.toHaveBeenCalled();
175
+ // Verify function was patched (it's a different function now)
176
+ const patchedFunction = agent.muteVoice;
177
+ await attachment.detach();
178
+ // Verify function was restored
179
+ expect(agent.muteVoice).not.toBe(patchedFunction);
180
+ await transportNoMic.disconnect();
181
+ });
182
+ it('should restore original muteVoice after detach', async () => {
183
+ transport.setMicEnabled = vi.fn();
184
+ const originalMute = agent.muteVoice;
185
+ const attachment = attachVoice(agent, transport, handlers);
186
+ await agent.muteVoice?.(true);
187
+ expect(transport.setMicEnabled).toHaveBeenCalled();
188
+ await attachment.detach();
189
+ // Clear previous calls
190
+ vi.clearAllMocks();
191
+ await agent.muteVoice?.(false);
192
+ expect(transport.setMicEnabled).not.toHaveBeenCalled();
193
+ expect(originalMute).toHaveBeenCalledWith(false);
194
+ });
195
+ });
196
+ describe('auto publish', () => {
197
+ it('should start publisher when autoStartPublish is true', async () => {
198
+ handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
199
+ yield new Int16Array(960);
200
+ });
201
+ const attachment = attachVoice(agent, transport, handlers, {
202
+ autoStartPublish: true,
203
+ });
204
+ // Give time for async start
205
+ await new Promise((resolve) => setTimeout(resolve, 50));
206
+ expect(transport.startAudioPublisher).toHaveBeenCalled();
207
+ expect(handlers.getLocalPcmStream).toHaveBeenCalled();
208
+ await attachment.detach();
209
+ });
210
+ it('should not start publisher when autoStartPublish is false', async () => {
211
+ const attachment = attachVoice(agent, transport, handlers, {
212
+ autoStartPublish: false,
213
+ });
214
+ await new Promise((resolve) => setTimeout(resolve, 50));
215
+ expect(transport.startAudioPublisher).not.toHaveBeenCalled();
216
+ await attachment.detach();
217
+ });
218
+ it('should handle stream chunks with different sizes', async () => {
219
+ const frames = [];
220
+ transport.pushPcmFrame = vi.fn().mockImplementation(async (frame) => {
221
+ frames.push(frame);
222
+ });
223
+ handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
224
+ yield new Int16Array(1920); // 40ms - will be chunked
225
+ yield new Int16Array(480); // 10ms - will be padded
226
+ yield new Int16Array(960); // 20ms - exact
227
+ });
228
+ const attachment = attachVoice(agent, transport, handlers, {
229
+ frameDurationMs: 20,
230
+ });
231
+ // Wait for processing
232
+ await new Promise((resolve) => setTimeout(resolve, 100));
233
+ // Should have received proper frames
234
+ expect(frames.length).toBeGreaterThanOrEqual(3);
235
+ expect(frames.every((f) => f.length === 960)).toBe(true);
236
+ await attachment.detach();
237
+ });
238
+ it('should stop on detach', async () => {
239
+ let keepRunning = true;
240
+ handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
241
+ while (keepRunning) {
242
+ yield new Int16Array(960);
243
+ await new Promise((resolve) => setTimeout(resolve, 10));
244
+ }
245
+ });
246
+ const attachment = attachVoice(agent, transport, handlers);
247
+ await new Promise((resolve) => setTimeout(resolve, 50));
248
+ const mockPushPcm = transport.pushPcmFrame;
249
+ const callCount = mockPushPcm.mock.calls.length;
250
+ expect(callCount).toBeGreaterThan(0);
251
+ keepRunning = false;
252
+ await attachment.detach();
253
+ await new Promise((resolve) => setTimeout(resolve, 50));
254
+ expect(transport.stopAudioPublisher).toHaveBeenCalled();
255
+ });
256
+ });
257
+ describe('multiple attachments', () => {
258
+ it('should detach previous when attaching again', async () => {
259
+ // This test verifies that multiple attachments are properly managed
260
+ // and the previous attachment is auto-detached
261
+ // First attachment
262
+ const attachment1 = attachVoice(agent, transport, handlers);
263
+ // Verify patching occurred
264
+ const patchedFunction1 = agent.sendVoiceFrame;
265
+ // Second attachment - should auto-detach first
266
+ const attachment2 = attachVoice(agent, transport, handlers);
267
+ // Verify it's a new patched function
268
+ const patchedFunction2 = agent.sendVoiceFrame;
269
+ expect(patchedFunction2).not.toBe(patchedFunction1);
270
+ // Manually detach second attachment
271
+ await attachment2.detach();
272
+ // Verify detach is idempotent (safe to call multiple times)
273
+ await attachment1.detach();
274
+ await attachment2.detach();
275
+ // Function should be restored (will throw original error)
276
+ // Note: The restored function is a bound version, not the exact original reference
277
+ const restoredFunction = agent.sendVoiceFrame;
278
+ expect(restoredFunction).not.toBe(patchedFunction1);
279
+ expect(restoredFunction).not.toBe(patchedFunction2);
280
+ });
281
+ it('should handle multiple agents independently', async () => {
282
+ const agent2 = createMockAgent();
283
+ const transport2 = new MockAdapter();
284
+ vi.spyOn(transport2, 'pushPcmFrame');
285
+ await transport2.connect({
286
+ url: 'wss://test',
287
+ tokenProvider: async () => 'test-token',
288
+ });
289
+ const attachment1 = attachVoice(agent, transport, handlers);
290
+ const attachment2 = attachVoice(agent2, transport2, handlers);
291
+ await transport.startAudioPublisher();
292
+ await transport2.startAudioPublisher();
293
+ const pcm = new Int16Array(960);
294
+ await agent.sendVoiceFrame?.(pcm);
295
+ await agent2.sendVoiceFrame?.(pcm);
296
+ expect(transport.pushPcmFrame).toHaveBeenCalledWith(pcm);
297
+ expect(transport2.pushPcmFrame).toHaveBeenCalledWith(pcm);
298
+ await attachment1.detach();
299
+ // agent1 restored, agent2 still patched
300
+ await expect(agent.sendVoiceFrame?.(pcm)).rejects.toThrow('Voice not implemented');
301
+ await agent2.sendVoiceFrame?.(pcm);
302
+ await attachment2.detach();
303
+ await transport2.disconnect();
304
+ });
305
+ });
306
+ describe('error handling', () => {
307
+ it('should handle publisher start failure', async () => {
308
+ transport.startAudioPublisher = vi.fn().mockRejectedValue(new Error('Start failed'));
309
+ handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
310
+ yield new Int16Array(960);
311
+ });
312
+ // Should not throw
313
+ const attachment = attachVoice(agent, transport, handlers);
314
+ await new Promise((resolve) => setTimeout(resolve, 50));
315
+ await attachment.detach();
316
+ });
317
+ it('should handle stream errors', async () => {
318
+ handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
319
+ yield new Int16Array(960);
320
+ throw new Error('Stream error');
321
+ });
322
+ const attachment = attachVoice(agent, transport, handlers);
323
+ await new Promise((resolve) => setTimeout(resolve, 100));
324
+ // Should have processed first frame before error
325
+ expect(transport.pushPcmFrame).toHaveBeenCalledTimes(1);
326
+ await attachment.detach();
327
+ });
328
+ it('should handle detach errors gracefully', async () => {
329
+ transport.stopAudioPublisher = vi.fn().mockRejectedValue(new Error('Stop failed'));
330
+ const attachment = attachVoice(agent, transport, handlers);
331
+ await transport.startAudioPublisher();
332
+ // Should not throw
333
+ await attachment.detach();
334
+ // Methods should still be restored
335
+ await expect(agent.sendVoiceFrame?.(new Int16Array(960))).rejects.toThrow('Voice not implemented');
336
+ });
337
+ });
338
+ });
339
+ //# sourceMappingURL=agent-bridge.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-bridge.spec.js","sourceRoot":"","sources":["../../src/voice/agent-bridge.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * フレーム処理ユーティリティ
3
+ * ブリッジ内でのフレーム整形(chunk/pad/truncate)を提供
4
+ * resampleは行わない(SDK側のpcm-utilsを利用してもらう)
5
+ */
6
+ /**
7
+ * Uint8Array → Int16Array のビュー化(コピー回避, LE前提)
8
+ * @param u8 - 入力バイト配列
9
+ * @returns Int16Arrayビュー
10
+ */
11
+ export declare function toInt16View(u8: Uint8Array): Int16Array;
12
+ /**
13
+ * 入力 Int16Array を expectedSamples のフレーム群に整える
14
+ * - 短い:zero-pad
15
+ * - 長い:切り出し(余りもpadして出力)
16
+ * - ちょうど:そのまま
17
+ *
18
+ * @param src - 入力PCMデータ
19
+ * @param expectedSamples - 期待されるサンプル数(480 or 960)
20
+ * @yields 整形されたフレーム
21
+ */
22
+ export declare function chunkToFrames(src: Int16Array, expectedSamples: number): Generator<Int16Array, void, unknown>;
23
+ /**
24
+ * フレーム検証用ヘルパー
25
+ * @param frame - 検証対象のフレーム
26
+ * @param expectedSamples - 期待されるサンプル数
27
+ * @returns 有効なフレームかどうか
28
+ */
29
+ export declare function isValidFrame(frame: Int16Array, expectedSamples: number): boolean;
30
+ //# sourceMappingURL=frame-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-utils.d.ts","sourceRoot":"","sources":["../../src/voice/frame-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,UAAU,GAAG,UAAU,CAItD;AAED;;;;;;;;;GASG;AACH,wBAAiB,aAAa,CAC5B,GAAG,EAAE,UAAU,EACf,eAAe,EAAE,MAAM,GACtB,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CA4BtC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAEhF"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * フレーム処理ユーティリティ
3
+ * ブリッジ内でのフレーム整形(chunk/pad/truncate)を提供
4
+ * resampleは行わない(SDK側のpcm-utilsを利用してもらう)
5
+ */
6
+ /**
7
+ * Uint8Array → Int16Array のビュー化(コピー回避, LE前提)
8
+ * @param u8 - 入力バイト配列
9
+ * @returns Int16Arrayビュー
10
+ */
11
+ export function toInt16View(u8) {
12
+ // バイト長が奇数の場合は最後の1バイトを切り捨て
13
+ const length = Math.floor(u8.byteLength / 2);
14
+ return new Int16Array(u8.buffer, u8.byteOffset, length);
15
+ }
16
+ /**
17
+ * 入力 Int16Array を expectedSamples のフレーム群に整える
18
+ * - 短い:zero-pad
19
+ * - 長い:切り出し(余りもpadして出力)
20
+ * - ちょうど:そのまま
21
+ *
22
+ * @param src - 入力PCMデータ
23
+ * @param expectedSamples - 期待されるサンプル数(480 or 960)
24
+ * @yields 整形されたフレーム
25
+ */
26
+ export function* chunkToFrames(src, expectedSamples) {
27
+ // ちょうどの場合
28
+ if (src.length === expectedSamples) {
29
+ yield src;
30
+ return;
31
+ }
32
+ // 長い場合:切り出し
33
+ if (src.length > expectedSamples) {
34
+ for (let i = 0; i < src.length; i += expectedSamples) {
35
+ const end = i + expectedSamples;
36
+ if (end <= src.length) {
37
+ // 完全なフレーム
38
+ yield src.subarray(i, end);
39
+ }
40
+ else {
41
+ // 最後の端数:zero-pad
42
+ const out = new Int16Array(expectedSamples);
43
+ out.set(src.subarray(i));
44
+ yield out;
45
+ }
46
+ }
47
+ return;
48
+ }
49
+ // 短い場合:zero-pad
50
+ const out = new Int16Array(expectedSamples);
51
+ out.set(src);
52
+ yield out;
53
+ }
54
+ /**
55
+ * フレーム検証用ヘルパー
56
+ * @param frame - 検証対象のフレーム
57
+ * @param expectedSamples - 期待されるサンプル数
58
+ * @returns 有効なフレームかどうか
59
+ */
60
+ export function isValidFrame(frame, expectedSamples) {
61
+ return frame.length === expectedSamples;
62
+ }
63
+ //# sourceMappingURL=frame-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-utils.js","sourceRoot":"","sources":["../../src/voice/frame-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,EAAc;IACxC,0BAA0B;IAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;IAC5C,OAAO,IAAI,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;AACzD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,SAAS,CAAC,CAAC,aAAa,CAC5B,GAAe,EACf,eAAuB;IAEvB,UAAU;IACV,IAAI,GAAG,CAAC,MAAM,KAAK,eAAe,EAAE,CAAC;QACnC,MAAM,GAAG,CAAA;QACT,OAAM;IACR,CAAC;IAED,YAAY;IACZ,IAAI,GAAG,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,eAAe,EAAE,CAAC;YACrD,MAAM,GAAG,GAAG,CAAC,GAAG,eAAe,CAAA;YAC/B,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;gBACtB,UAAU;gBACV,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;YAC5B,CAAC;iBAAM,CAAC;gBACN,iBAAiB;gBACjB,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,eAAe,CAAC,CAAA;gBAC3C,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;gBACxB,MAAM,GAAG,CAAA;YACX,CAAC;QACH,CAAC;QACD,OAAM;IACR,CAAC;IAED,gBAAgB;IAChB,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,eAAe,CAAC,CAAA;IAC3C,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACZ,MAAM,GAAG,CAAA;AACX,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAiB,EAAE,eAAuB;IACrE,OAAO,KAAK,CAAC,MAAM,KAAK,eAAe,CAAA;AACzC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=frame-utils.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-utils.spec.d.ts","sourceRoot":"","sources":["../../src/voice/frame-utils.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,82 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { chunkToFrames, isValidFrame, toInt16View } from './frame-utils.js';
3
+ describe('frame-utils', () => {
4
+ describe('toInt16View', () => {
5
+ it('should convert Uint8Array to Int16Array view', () => {
6
+ const u8 = new Uint8Array([0x00, 0x01, 0x00, 0x02]);
7
+ const i16 = toInt16View(u8);
8
+ expect(i16.length).toBe(2);
9
+ expect(i16[0]).toBe(256); // 0x0100 in LE
10
+ expect(i16[1]).toBe(512); // 0x0200 in LE
11
+ });
12
+ it('should handle odd byte length by truncating', () => {
13
+ const u8 = new Uint8Array([0x00, 0x01, 0xff]); // 3 bytes
14
+ const i16 = toInt16View(u8);
15
+ expect(i16.length).toBe(1); // 最後の1バイトは切り捨て
16
+ expect(i16[0]).toBe(256);
17
+ });
18
+ it('should work with buffer offsets', () => {
19
+ const buffer = new ArrayBuffer(8);
20
+ const u8 = new Uint8Array(buffer, 2, 4); // offset=2, length=4
21
+ u8.set([0x00, 0x01, 0x00, 0x02]);
22
+ const i16 = toInt16View(u8);
23
+ expect(i16.length).toBe(2);
24
+ expect(i16.byteOffset).toBe(2);
25
+ });
26
+ });
27
+ describe('chunkToFrames', () => {
28
+ it('should yield as-is when exact match', () => {
29
+ const src = new Int16Array(960); // 20ms frame
30
+ const frames = [...chunkToFrames(src, 960)];
31
+ expect(frames.length).toBe(1);
32
+ expect(frames[0]).toBe(src);
33
+ });
34
+ it('should zero-pad when shorter', () => {
35
+ const src = new Int16Array([1, 2, 3]); // 3 samples
36
+ const frames = [...chunkToFrames(src, 480)]; // expects 480
37
+ expect(frames.length).toBe(1);
38
+ expect(frames[0].length).toBe(480);
39
+ expect(frames[0][0]).toBe(1);
40
+ expect(frames[0][1]).toBe(2);
41
+ expect(frames[0][2]).toBe(3);
42
+ expect(frames[0][3]).toBe(0); // padded
43
+ expect(frames[0][479]).toBe(0); // padded
44
+ });
45
+ it('should chunk when longer', () => {
46
+ const src = new Int16Array(2400); // 50ms worth
47
+ for (let i = 0; i < src.length; i++) {
48
+ src[i] = i; // 識別用の値
49
+ }
50
+ const frames = [...chunkToFrames(src, 480)]; // 10ms chunks
51
+ expect(frames.length).toBe(5);
52
+ // 各フレームの検証
53
+ for (let i = 0; i < 5; i++) {
54
+ expect(frames[i].length).toBe(480);
55
+ expect(frames[i][0]).toBe(i * 480);
56
+ expect(frames[i][479]).toBe(i * 480 + 479);
57
+ }
58
+ });
59
+ it('should pad remainder when not divisible', () => {
60
+ const src = new Int16Array(1000); // 960 + 40
61
+ const frames = [...chunkToFrames(src, 960)];
62
+ expect(frames.length).toBe(2);
63
+ expect(frames[0].length).toBe(960);
64
+ expect(frames[1].length).toBe(960); // 40 samples + 920 zeros
65
+ // 2番目のフレームの最後はゼロ
66
+ expect(frames[1][40]).toBe(0);
67
+ expect(frames[1][959]).toBe(0);
68
+ });
69
+ });
70
+ describe('isValidFrame', () => {
71
+ it('should validate frame size', () => {
72
+ const valid480 = new Int16Array(480);
73
+ const valid960 = new Int16Array(960);
74
+ const invalid = new Int16Array(500);
75
+ expect(isValidFrame(valid480, 480)).toBe(true);
76
+ expect(isValidFrame(valid960, 960)).toBe(true);
77
+ expect(isValidFrame(invalid, 480)).toBe(false);
78
+ expect(isValidFrame(invalid, 960)).toBe(false);
79
+ });
80
+ });
81
+ });
82
+ //# sourceMappingURL=frame-utils.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-utils.spec.js","sourceRoot":"","sources":["../../src/voice/frame-utils.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import type { VoiceCapableClient } from '@metatell/bot-core';
2
+ import type { RealtimeTransport } from '../transport.js';
3
+ /**
4
+ * 音声メタデータ
5
+ */
6
+ export interface VoiceMetadata {
7
+ /** 送信者のidentity */
8
+ fromIdentity?: string;
9
+ /** 送信者のSID(将来拡張) */
10
+ fromSid?: string;
11
+ /** トラックSID(将来拡張) */
12
+ trackSid?: string;
13
+ }
14
+ /**
15
+ * 音声ハンドラー
16
+ */
17
+ export interface VoiceHandlers {
18
+ /**
19
+ * 受信PCM処理(48kHz/PCM16/mono)
20
+ * @param pcm - 受信したPCMデータ
21
+ * @param meta - メタデータ
22
+ */
23
+ onRemotePcm?: (pcm: Int16Array, meta: VoiceMetadata) => Promise<void> | void;
24
+ /**
25
+ * ローカルPCM供給元(TTS など)
26
+ * @returns 10ms/20ms のPCMフレームを返すAsyncIterable
27
+ */
28
+ getLocalPcmStream?: () => AsyncIterable<Int16Array>;
29
+ }
30
+ /**
31
+ * attachVoice のオプション
32
+ */
33
+ export interface AttachVoiceOptions {
34
+ /** フレーム長(ミリ秒) default: 20 */
35
+ frameDurationMs?: 10 | 20;
36
+ /** サンプルレート(情報目的、内部は48kHz固定) default: 48000 */
37
+ sampleRate?: 48000 | 24000 | 16000;
38
+ /** チャンネル数(送信は1ch必須) default: 1 */
39
+ channels?: 1 | 2;
40
+ /** 自動パブリッシュ開始 default: true */
41
+ autoStartPublish?: boolean;
42
+ /** audioトピックの自動追加 default: true */
43
+ enableTopicAutoAdd?: boolean;
44
+ /** ログタグ default: 'voice.bridge' */
45
+ loggerTag?: string;
46
+ }
47
+ /**
48
+ * VoiceAttachment インターフェース
49
+ */
50
+ export interface VoiceAttachment {
51
+ /** ブリッジを解除する */
52
+ detach(): Promise<void>;
53
+ }
54
+ /**
55
+ * 内部状態管理用(エクスポートしない)
56
+ */
57
+ export interface AttachmentState {
58
+ agent: VoiceCapableClient;
59
+ transport: RealtimeTransport;
60
+ original: {
61
+ sendVoiceFrame?: VoiceCapableClient['sendVoiceFrame'];
62
+ muteVoice?: VoiceCapableClient['muteVoice'];
63
+ };
64
+ removeListener?: () => void;
65
+ abortController?: AbortController;
66
+ isPublishing: boolean;
67
+ expectedSamples: 480 | 960;
68
+ }
69
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/voice/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mBAAmB;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAE5E;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,aAAa,CAAC,UAAU,CAAC,CAAA;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,6BAA6B;IAC7B,eAAe,CAAC,EAAE,EAAE,GAAG,EAAE,CAAA;IACzB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAA;IAClC,kCAAkC;IAClC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IAChB,+BAA+B;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,mCAAmC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,gBAAgB;IAChB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,kBAAkB,CAAA;IACzB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,QAAQ,EAAE;QACR,cAAc,CAAC,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,CAAA;QACrD,SAAS,CAAC,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAA;KAC5C,CAAA;IACD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,YAAY,EAAE,OAAO,CAAA;IACrB,eAAe,EAAE,GAAG,GAAG,GAAG,CAAA;CAC3B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/voice/types.ts"],"names":[],"mappings":""}