@metatell/bot-realtime 0.0.1

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.
@@ -0,0 +1,16 @@
1
+ import { MetatellError } from '@metatell/bot-sdk';
2
+ export declare class RealtimeError extends MetatellError {
3
+ readonly code: string;
4
+ readonly cause?: unknown | undefined;
5
+ constructor(code: string, message: string, cause?: unknown | undefined);
6
+ }
7
+ export declare const ErrorCodes: {
8
+ readonly ALREADY_CONNECTING: "AlreadyConnecting";
9
+ readonly UNKNOWN_TOPIC: "UnknownTopic";
10
+ readonly AUDIO_NOT_STARTED: "AudioNotStarted";
11
+ readonly NOT_CONNECTED: "NotConnected";
12
+ readonly CONNECTION_FAILED: "ConnectionFailed";
13
+ readonly SEND_FAILED: "SendFailed";
14
+ };
15
+ export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
16
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,qBAAa,aAAc,SAAQ,aAAa;aAE5B,IAAI,EAAE,MAAM;aAEZ,KAAK,CAAC,EAAE,OAAO;gBAFf,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,OAAO,YAAA;CAKlC;AAED,eAAO,MAAM,UAAU;;;;;;;CAOb,CAAA;AAEV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAA"}
package/dist/errors.js ADDED
@@ -0,0 +1,20 @@
1
+ import { MetatellError } from '@metatell/bot-sdk';
2
+ export class RealtimeError extends MetatellError {
3
+ code;
4
+ cause;
5
+ constructor(code, message, cause) {
6
+ super(message);
7
+ this.code = code;
8
+ this.cause = cause;
9
+ this.name = 'RealtimeError';
10
+ }
11
+ }
12
+ export const ErrorCodes = {
13
+ ALREADY_CONNECTING: 'AlreadyConnecting',
14
+ UNKNOWN_TOPIC: 'UnknownTopic',
15
+ AUDIO_NOT_STARTED: 'AudioNotStarted',
16
+ NOT_CONNECTED: 'NotConnected',
17
+ CONNECTION_FAILED: 'ConnectionFailed',
18
+ SEND_FAILED: 'SendFailed',
19
+ };
20
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,MAAM,OAAO,aAAc,SAAQ,aAAa;IAE5B;IAEA;IAHlB,YACkB,IAAY,EAC5B,OAAe,EACC,KAAe;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAA;QAJE,SAAI,GAAJ,IAAI,CAAQ;QAEZ,UAAK,GAAL,KAAK,CAAU;QAG/B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;IAC7B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,kBAAkB,EAAE,mBAAmB;IACvC,aAAa,EAAE,cAAc;IAC7B,iBAAiB,EAAE,iBAAiB;IACpC,aAAa,EAAE,cAAc;IAC7B,iBAAiB,EAAE,kBAAkB;IACrC,WAAW,EAAE,YAAY;CACjB,CAAA"}
@@ -0,0 +1,5 @@
1
+ export { type ErrorCode, ErrorCodes, RealtimeError } from './errors.js';
2
+ export { LiveKitAdapter } from './livekit.js';
3
+ export { MockAdapter } from './mock.js';
4
+ export type { ConnectionState, RealtimeEvent, RealtimeOptions, RealtimeTransport, TokenProvider, } from './transport.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEvE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,YAAY,EACV,eAAe,EACf,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,aAAa,GACd,MAAM,gBAAgB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { ErrorCodes, RealtimeError } from './errors.js';
2
+ export { LiveKitAdapter } from './livekit.js';
3
+ export { MockAdapter } from './mock.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEvE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,25 @@
1
+ import type { ConnectionState, RealtimeEvent, RealtimeOptions, RealtimeTransport } from './transport.js';
2
+ export declare class LiveKitAdapter implements RealtimeTransport {
3
+ state: ConnectionState;
4
+ private room?;
5
+ private audio?;
6
+ private audioStreams;
7
+ private listeners;
8
+ private options?;
9
+ private activeTopics;
10
+ constructor();
11
+ on(listener: (e: RealtimeEvent) => void): () => void;
12
+ private emit;
13
+ private setState;
14
+ connect(opts: RealtimeOptions): Promise<void>;
15
+ private setupEventHandlers;
16
+ disconnect(): Promise<void>;
17
+ send(topic: string, data: Uint8Array | string): Promise<void>;
18
+ startAudioPublisher(): Promise<void>;
19
+ pushPcmFrame(frame: Int16Array): Promise<void>;
20
+ stopAudioPublisher(): Promise<void>;
21
+ setMicEnabled(enabled: boolean): Promise<void>;
22
+ setSpeakerEnabled(enabled: boolean): Promise<void>;
23
+ private readAudioFrames;
24
+ }
25
+ //# sourceMappingURL=livekit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit.d.ts","sourceRoot":"","sources":["../src/livekit.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,eAAe,EACf,iBAAiB,EAClB,MAAM,gBAAgB,CAAA;AAEvB,qBAAa,cAAe,YAAW,iBAAiB;IACtD,KAAK,EAAE,eAAe,CAAS;IAC/B,OAAO,CAAC,IAAI,CAAC,CAAM;IACnB,OAAO,CAAC,KAAK,CAAC,CAAoE;IAClF,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,OAAO,CAAC,CAAiB;IACjC,OAAO,CAAC,YAAY,CAAa;;IAMjC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,GAAG,MAAM,IAAI;IAKpD,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,QAAQ;IAOV,OAAO,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA0CnD,OAAO,CAAC,kBAAkB;IAmGpB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB7D,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmCpC,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAqC9C,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAcnC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9C,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;YAK1C,eAAe;CAgC9B"}
@@ -0,0 +1,278 @@
1
+ import { AudioFrame, AudioSource, AudioStream, LocalAudioTrack, Room, RoomEvent, TrackKind, TrackPublishOptions, } from '@livekit/rtc-node';
2
+ import { ErrorCodes, RealtimeError } from './errors.js';
3
+ export class LiveKitAdapter {
4
+ state = 'idle';
5
+ room;
6
+ audio;
7
+ audioStreams = new Map(); // participantSid -> AudioStream
8
+ listeners = new Set();
9
+ options;
10
+ activeTopics;
11
+ constructor() {
12
+ this.activeTopics = new Set(['control', 'events', 'transcript', 'audio']);
13
+ }
14
+ on(listener) {
15
+ this.listeners.add(listener);
16
+ return () => this.listeners.delete(listener);
17
+ }
18
+ emit(event) {
19
+ this.listeners.forEach((listener) => {
20
+ try {
21
+ listener(event);
22
+ }
23
+ catch (error) {
24
+ this.options?.logger?.('error', 'Error in event listener', { error, event });
25
+ }
26
+ });
27
+ }
28
+ setState(state) {
29
+ if (this.state !== state) {
30
+ this.state = state;
31
+ this.emit({ type: 'state', state });
32
+ }
33
+ }
34
+ async connect(opts) {
35
+ if (this.state === 'connecting' || this.state === 'connected') {
36
+ throw new RealtimeError(ErrorCodes.ALREADY_CONNECTING, 'Already connecting or connected');
37
+ }
38
+ this.options = opts;
39
+ this.activeTopics = new Set(opts.topics || ['control', 'events', 'transcript', 'audio']);
40
+ this.setState('connecting');
41
+ try {
42
+ // Create a new room instance
43
+ this.room = new Room();
44
+ // Setup event handlers
45
+ this.setupEventHandlers();
46
+ // Get token from provider
47
+ const token = await opts.tokenProvider();
48
+ // Connect to the room
49
+ await this.room.connect(opts.url, token, {
50
+ autoSubscribe: opts.connect?.autoSubscribe ?? true,
51
+ dynacast: opts.connect?.dynacast ?? true,
52
+ });
53
+ this.setState('connected');
54
+ this.options?.logger?.('info', 'Successfully connected to LiveKit room', {
55
+ roomName: this.room.name,
56
+ participantCount: this.room.remoteParticipants.size,
57
+ });
58
+ }
59
+ catch (error) {
60
+ this.setState('disconnected');
61
+ this.emit({
62
+ type: 'error',
63
+ code: ErrorCodes.CONNECTION_FAILED,
64
+ message: 'Failed to connect to LiveKit',
65
+ cause: error,
66
+ });
67
+ throw new RealtimeError(ErrorCodes.CONNECTION_FAILED, 'Failed to connect to LiveKit', error);
68
+ }
69
+ }
70
+ setupEventHandlers() {
71
+ if (!this.room)
72
+ return;
73
+ // Participant events
74
+ this.room.on(RoomEvent.ParticipantConnected, (participant) => {
75
+ this.emit({
76
+ type: 'participant-joined',
77
+ identity: participant.identity || '',
78
+ sid: participant.sid || '',
79
+ });
80
+ });
81
+ this.room.on(RoomEvent.ParticipantDisconnected, (participant) => {
82
+ this.emit({
83
+ type: 'participant-left',
84
+ identity: participant.identity || '',
85
+ sid: participant.sid || '',
86
+ });
87
+ });
88
+ // Data events
89
+ this.room.on(RoomEvent.DataReceived, (payload, participant, _, topic) => {
90
+ if (topic && this.activeTopics.has(topic)) {
91
+ this.emit({
92
+ type: 'data',
93
+ topic,
94
+ payload,
95
+ from: participant?.identity,
96
+ });
97
+ }
98
+ });
99
+ // Track events
100
+ this.room.on(RoomEvent.TrackSubscribed, async (track, _publication, participant) => {
101
+ if (track.kind === TrackKind.KIND_AUDIO) {
102
+ try {
103
+ // 音声ストリームを作成
104
+ const audioStream = new AudioStream(track, {
105
+ sampleRate: 48000,
106
+ numChannels: 1,
107
+ });
108
+ this.audioStreams.set(participant.sid || '', audioStream);
109
+ // 音声フレームを読み取る
110
+ this.readAudioFrames(audioStream, participant);
111
+ this.options?.logger?.('info', 'Audio track subscribed', {
112
+ participantId: participant.identity,
113
+ participantSid: participant.sid,
114
+ trackSid: track.sid,
115
+ });
116
+ }
117
+ catch (error) {
118
+ this.options?.logger?.('error', 'Failed to create audio stream', {
119
+ error,
120
+ participantId: participant.identity,
121
+ trackSid: track.sid,
122
+ });
123
+ }
124
+ }
125
+ });
126
+ this.room.on(RoomEvent.TrackUnsubscribed, (track, _publication, participant) => {
127
+ if (track.kind === TrackKind.KIND_AUDIO && participant.sid) {
128
+ const audioStream = this.audioStreams.get(participant.sid);
129
+ if (audioStream) {
130
+ // ストリームをクリーンアップ
131
+ this.audioStreams.delete(participant.sid);
132
+ this.options?.logger?.('info', 'Audio track unsubscribed', {
133
+ participantId: participant.identity,
134
+ participantSid: participant.sid,
135
+ trackSid: track.sid,
136
+ });
137
+ }
138
+ }
139
+ });
140
+ // Connection events
141
+ this.room.on(RoomEvent.Reconnecting, () => {
142
+ this.setState('reconnecting');
143
+ });
144
+ this.room.on(RoomEvent.Reconnected, () => {
145
+ this.setState('connected');
146
+ });
147
+ this.room.on(RoomEvent.Disconnected, () => {
148
+ this.setState('disconnected');
149
+ });
150
+ }
151
+ async disconnect() {
152
+ // クリーンアップ
153
+ this.audioStreams.clear();
154
+ if (this.room) {
155
+ await this.room.disconnect();
156
+ this.room = undefined;
157
+ }
158
+ this.setState('disconnected');
159
+ }
160
+ async send(topic, data) {
161
+ if (!this.room || this.state !== 'connected') {
162
+ throw new RealtimeError(ErrorCodes.NOT_CONNECTED, 'Not connected to LiveKit room');
163
+ }
164
+ if (!this.activeTopics.has(topic)) {
165
+ throw new RealtimeError(ErrorCodes.UNKNOWN_TOPIC, `Unknown topic: ${topic}`);
166
+ }
167
+ try {
168
+ const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data;
169
+ if (!this.room?.localParticipant) {
170
+ throw new RealtimeError(ErrorCodes.NOT_CONNECTED, 'Room or local participant not available');
171
+ }
172
+ await this.room.localParticipant.publishData(bytes, {
173
+ reliable: true,
174
+ topic,
175
+ });
176
+ }
177
+ catch (error) {
178
+ throw new RealtimeError(ErrorCodes.SEND_FAILED, 'Failed to send data', error);
179
+ }
180
+ }
181
+ async startAudioPublisher() {
182
+ if (!this.room || this.state !== 'connected') {
183
+ throw new RealtimeError(ErrorCodes.NOT_CONNECTED, 'Not connected to LiveKit room');
184
+ }
185
+ const config = this.options?.audioPublish || {
186
+ sampleRate: 48000,
187
+ channels: 1,
188
+ frameDurationMs: 20,
189
+ };
190
+ // Create AudioSource and track
191
+ const source = new AudioSource(config.sampleRate, config.channels);
192
+ const track = LocalAudioTrack.createAudioTrack(config.trackName || 'agent-audio', source);
193
+ // Publish the track
194
+ if (!this.room?.localParticipant) {
195
+ throw new RealtimeError(ErrorCodes.NOT_CONNECTED, 'Room or local participant not available');
196
+ }
197
+ const publication = await this.room.localParticipant.publishTrack(track, new TrackPublishOptions());
198
+ this.audio = { source, track, trackSid: publication.sid };
199
+ this.options?.logger?.('info', 'Audio publisher started', {
200
+ sampleRate: config.sampleRate,
201
+ channels: config.channels,
202
+ trackName: config.trackName || 'agent-audio',
203
+ });
204
+ }
205
+ async pushPcmFrame(frame) {
206
+ if (!this.audio) {
207
+ throw new RealtimeError(ErrorCodes.AUDIO_NOT_STARTED, 'Audio publisher not started');
208
+ }
209
+ const config = this.options?.audioPublish || {
210
+ sampleRate: 48000,
211
+ channels: 1,
212
+ frameDurationMs: 20,
213
+ };
214
+ // 1フレームあたりのサンプル数を計算
215
+ const samplesPerChannel = (config.sampleRate * (config.frameDurationMs || 20)) / 1000;
216
+ // フレームサイズの検証
217
+ const expectedLength = samplesPerChannel * config.channels;
218
+ if (frame.length !== expectedLength) {
219
+ this.options?.logger?.('warn', 'PCM frame size mismatch', {
220
+ expected: expectedLength,
221
+ actual: frame.length,
222
+ samplesPerChannel,
223
+ channels: config.channels,
224
+ });
225
+ }
226
+ // Create AudioFrame and capture it
227
+ const int16Buffer = Int16Array.from(frame);
228
+ const audioFrame = new AudioFrame(int16Buffer, config.sampleRate, config.channels, samplesPerChannel);
229
+ await this.audio.source.captureFrame(audioFrame);
230
+ }
231
+ async stopAudioPublisher() {
232
+ if (!this.audio)
233
+ return;
234
+ // Unpublish and close track
235
+ if (this.audio.trackSid && this.room?.localParticipant) {
236
+ await this.room.localParticipant.unpublishTrack(this.audio.trackSid);
237
+ }
238
+ await this.audio.track.close();
239
+ this.audio = undefined;
240
+ this.options?.logger?.('info', 'Audio publisher stopped');
241
+ }
242
+ async setMicEnabled(enabled) {
243
+ // PoCではno-op実装
244
+ this.options?.logger?.('debug', `Mic ${enabled ? 'enabled' : 'disabled'} (no-op in PoC)`);
245
+ }
246
+ async setSpeakerEnabled(enabled) {
247
+ // PoCではno-op実装
248
+ this.options?.logger?.('debug', `Speaker ${enabled ? 'enabled' : 'disabled'} (no-op in PoC)`);
249
+ }
250
+ async readAudioFrames(audioStream, participant) {
251
+ try {
252
+ const reader = audioStream.getReader();
253
+ while (true) {
254
+ const { done, value } = await reader.read();
255
+ if (done)
256
+ break;
257
+ // AudioFrameをPCMデータに変換
258
+ if (value?.data) {
259
+ // Int16ArrayとしてPCMデータを送信
260
+ const pcmData = new Int16Array(value.data.buffer, value.data.byteOffset, value.data.byteLength / 2);
261
+ this.emit({
262
+ type: 'data',
263
+ topic: 'audio',
264
+ payload: new Uint8Array(pcmData.buffer, pcmData.byteOffset, pcmData.byteLength),
265
+ from: participant.identity,
266
+ });
267
+ }
268
+ }
269
+ }
270
+ catch (error) {
271
+ this.options?.logger?.('error', 'Error reading audio frames', {
272
+ error,
273
+ participantId: participant.identity,
274
+ });
275
+ }
276
+ }
277
+ }
278
+ //# sourceMappingURL=livekit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit.js","sourceRoot":"","sources":["../src/livekit.ts"],"names":[],"mappings":"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"}
package/dist/mock.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type { ConnectionState, RealtimeEvent, RealtimeOptions, RealtimeTransport } from './transport.js';
2
+ export declare class MockAdapter implements RealtimeTransport {
3
+ state: ConnectionState;
4
+ private listeners;
5
+ private options?;
6
+ private activeTopics;
7
+ private audioFrameCount;
8
+ private audioStarted;
9
+ private audioReceiveInterval?;
10
+ constructor();
11
+ on(listener: (e: RealtimeEvent) => void): () => void;
12
+ private emit;
13
+ private setState;
14
+ connect(opts: RealtimeOptions): Promise<void>;
15
+ disconnect(): Promise<void>;
16
+ send(topic: string, data: Uint8Array | string): Promise<void>;
17
+ startAudioPublisher(): Promise<void>;
18
+ pushPcmFrame(frame: Int16Array): Promise<void>;
19
+ stopAudioPublisher(): Promise<void>;
20
+ private startMockAudioReceive;
21
+ setMicEnabled(enabled: boolean): Promise<void>;
22
+ setSpeakerEnabled(enabled: boolean): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,eAAe,EACf,iBAAiB,EAClB,MAAM,gBAAgB,CAAA;AAEvB,qBAAa,WAAY,YAAW,iBAAiB;IACnD,KAAK,EAAE,eAAe,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,OAAO,CAAC,CAAiB;IACjC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,oBAAoB,CAAC,CAAgC;;IAM7D,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,GAAG,MAAM,IAAI;IAKpD,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,QAAQ;IAOV,OAAO,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B7C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B7D,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAUpC,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAe9C,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQzC,OAAO,CAAC,qBAAqB;IAuBvB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9C,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAIzD"}
package/dist/mock.js ADDED
@@ -0,0 +1,143 @@
1
+ import { ErrorCodes, RealtimeError } from './errors.js';
2
+ export class MockAdapter {
3
+ state = 'idle';
4
+ listeners = new Set();
5
+ options;
6
+ activeTopics;
7
+ audioFrameCount = 0;
8
+ audioStarted = false;
9
+ audioReceiveInterval;
10
+ constructor() {
11
+ this.activeTopics = new Set(['control', 'events', 'transcript', 'audio']);
12
+ }
13
+ on(listener) {
14
+ this.listeners.add(listener);
15
+ return () => this.listeners.delete(listener);
16
+ }
17
+ emit(event) {
18
+ this.listeners.forEach((listener) => {
19
+ try {
20
+ listener(event);
21
+ }
22
+ catch (error) {
23
+ this.options?.logger?.('error', 'Error in event listener', { error, event });
24
+ }
25
+ });
26
+ }
27
+ setState(state) {
28
+ if (this.state !== state) {
29
+ this.state = state;
30
+ this.emit({ type: 'state', state });
31
+ }
32
+ }
33
+ async connect(opts) {
34
+ if (this.state === 'connecting' || this.state === 'connected') {
35
+ throw new RealtimeError(ErrorCodes.ALREADY_CONNECTING, ErrorCodes.ALREADY_CONNECTING);
36
+ }
37
+ this.options = opts;
38
+ this.activeTopics = new Set(opts.topics || ['control', 'events', 'transcript', 'audio']);
39
+ this.setState('connecting');
40
+ // 接続をシミュレート(30-50ms後に接続完了)
41
+ await new Promise((resolve) => {
42
+ setTimeout(resolve, 30 + Math.random() * 20);
43
+ });
44
+ this.setState('connected');
45
+ this.options?.logger?.('info', 'Mock connected successfully');
46
+ // 参加者のシミュレート
47
+ setTimeout(() => {
48
+ this.emit({
49
+ type: 'participant-joined',
50
+ identity: 'mock-participant',
51
+ sid: 'mock-sid-123',
52
+ });
53
+ // 音声受信のシミュレートを開始
54
+ this.startMockAudioReceive();
55
+ }, 100);
56
+ }
57
+ async disconnect() {
58
+ if (this.audioReceiveInterval) {
59
+ clearInterval(this.audioReceiveInterval);
60
+ this.audioReceiveInterval = undefined;
61
+ }
62
+ this.setState('disconnected');
63
+ this.audioFrameCount = 0;
64
+ this.audioStarted = false;
65
+ }
66
+ async send(topic, data) {
67
+ if (this.state !== 'connected') {
68
+ throw new RealtimeError(ErrorCodes.NOT_CONNECTED, ErrorCodes.NOT_CONNECTED);
69
+ }
70
+ if (!this.activeTopics.has(topic)) {
71
+ throw new RealtimeError(ErrorCodes.UNKNOWN_TOPIC, ErrorCodes.UNKNOWN_TOPIC);
72
+ }
73
+ const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data;
74
+ // エコーバックをシミュレート(10ms後)
75
+ setTimeout(() => {
76
+ this.emit({
77
+ type: 'data',
78
+ topic,
79
+ payload: bytes,
80
+ from: 'mock-echo',
81
+ });
82
+ }, 10);
83
+ this.options?.logger?.('debug', `Mock sent data to topic: ${topic}`, {
84
+ size: bytes.length,
85
+ });
86
+ }
87
+ async startAudioPublisher() {
88
+ if (this.state !== 'connected') {
89
+ throw new RealtimeError(ErrorCodes.NOT_CONNECTED, ErrorCodes.NOT_CONNECTED);
90
+ }
91
+ this.audioStarted = true;
92
+ this.audioFrameCount = 0;
93
+ this.options?.logger?.('info', 'Mock audio publisher started');
94
+ }
95
+ async pushPcmFrame(frame) {
96
+ if (!this.audioStarted) {
97
+ throw new RealtimeError(ErrorCodes.AUDIO_NOT_STARTED, ErrorCodes.AUDIO_NOT_STARTED);
98
+ }
99
+ this.audioFrameCount++;
100
+ // 100フレームごとにログ
101
+ if (this.audioFrameCount % 100 === 0) {
102
+ this.options?.logger?.('debug', `Mock audio frames pushed: ${this.audioFrameCount}`, {
103
+ frameSize: frame.length,
104
+ });
105
+ }
106
+ }
107
+ async stopAudioPublisher() {
108
+ this.options?.logger?.('info', 'Mock audio publisher stopped', {
109
+ totalFrames: this.audioFrameCount,
110
+ });
111
+ this.audioStarted = false;
112
+ this.audioFrameCount = 0;
113
+ }
114
+ startMockAudioReceive() {
115
+ // 20msごとにモック音声フレームを生成
116
+ this.audioReceiveInterval = setInterval(() => {
117
+ if (this.state === 'connected' && this.activeTopics.has('audio')) {
118
+ // モックPCMデータを生成(48kHz, 1ch, 20ms = 960サンプル)
119
+ const pcmData = new Int16Array(960);
120
+ for (let i = 0; i < pcmData.length; i++) {
121
+ // 無音(小さいランダムノイズ)
122
+ pcmData[i] = Math.floor((Math.random() - 0.5) * 100);
123
+ }
124
+ const uint8Data = new Uint8Array(pcmData.buffer, pcmData.byteOffset, pcmData.byteLength);
125
+ this.emit({
126
+ type: 'data',
127
+ topic: 'audio',
128
+ payload: uint8Data,
129
+ from: 'mock-participant',
130
+ });
131
+ }
132
+ }, 20);
133
+ }
134
+ async setMicEnabled(enabled) {
135
+ // PoCではno-op実装
136
+ this.options?.logger?.('debug', `Mock: Mic ${enabled ? 'enabled' : 'disabled'}`);
137
+ }
138
+ async setSpeakerEnabled(enabled) {
139
+ // PoCではno-op実装
140
+ this.options?.logger?.('debug', `Mock: Speaker ${enabled ? 'enabled' : 'disabled'}`);
141
+ }
142
+ }
143
+ //# sourceMappingURL=mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mock.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.spec.d.ts","sourceRoot":"","sources":["../src/mock.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,164 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { ErrorCodes } from './errors.js';
3
+ import { MockAdapter } from './mock.js';
4
+ describe('MockAdapter', () => {
5
+ it('should initialize with idle state', () => {
6
+ const adapter = new MockAdapter();
7
+ expect(adapter.state).toBe('idle');
8
+ });
9
+ describe('connect', () => {
10
+ it('should transition from idle to connected', async () => {
11
+ const adapter = new MockAdapter();
12
+ const events = [];
13
+ adapter.on((e) => events.push(e));
14
+ await adapter.connect({
15
+ url: 'wss://mock.livekit.cloud',
16
+ tokenProvider: async () => 'mock-token',
17
+ });
18
+ expect(adapter.state).toBe('connected');
19
+ expect(events).toEqual([
20
+ { type: 'state', state: 'connecting' },
21
+ { type: 'state', state: 'connected' },
22
+ ]);
23
+ });
24
+ it('should emit participant-joined after connection', async () => {
25
+ const adapter = new MockAdapter();
26
+ const events = [];
27
+ adapter.on((e) => events.push(e));
28
+ await adapter.connect({
29
+ url: 'wss://mock.livekit.cloud',
30
+ tokenProvider: async () => 'mock-token',
31
+ });
32
+ // Wait for participant event
33
+ await new Promise((resolve) => setTimeout(resolve, 150));
34
+ const participantEvent = events.find((e) => e.type === 'participant-joined');
35
+ expect(participantEvent).toMatchObject({
36
+ type: 'participant-joined',
37
+ identity: 'mock-participant',
38
+ sid: 'mock-sid-123',
39
+ });
40
+ });
41
+ it('should throw if already connecting', async () => {
42
+ const adapter = new MockAdapter();
43
+ const promise1 = adapter.connect({
44
+ url: 'wss://mock.livekit.cloud',
45
+ tokenProvider: async () => 'mock-token',
46
+ });
47
+ const promise2 = adapter.connect({
48
+ url: 'wss://mock.livekit.cloud',
49
+ tokenProvider: async () => 'mock-token',
50
+ });
51
+ await expect(promise2).rejects.toThrow(ErrorCodes.ALREADY_CONNECTING);
52
+ await promise1;
53
+ });
54
+ });
55
+ describe('send', () => {
56
+ it('should echo back sent data', async () => {
57
+ const adapter = new MockAdapter();
58
+ const events = [];
59
+ adapter.on((e) => {
60
+ if (e.type === 'data')
61
+ events.push(e);
62
+ });
63
+ await adapter.connect({
64
+ url: 'wss://mock.livekit.cloud',
65
+ tokenProvider: async () => 'mock-token',
66
+ topics: ['control', 'events'],
67
+ });
68
+ await adapter.send('control', JSON.stringify({ cmd: 'hello' }));
69
+ // Wait for echo
70
+ await new Promise((resolve) => setTimeout(resolve, 20));
71
+ expect(events).toHaveLength(1);
72
+ expect(events[0]).toMatchObject({
73
+ type: 'data',
74
+ topic: 'control',
75
+ from: 'mock-echo',
76
+ });
77
+ const dataEvent = events[0];
78
+ if (!dataEvent || dataEvent.type !== 'data') {
79
+ throw new Error('Expected data event');
80
+ }
81
+ const payload = new TextDecoder().decode(dataEvent.payload);
82
+ expect(JSON.parse(payload)).toEqual({ cmd: 'hello' });
83
+ });
84
+ it('should throw for unknown topic', async () => {
85
+ const adapter = new MockAdapter();
86
+ await adapter.connect({
87
+ url: 'wss://mock.livekit.cloud',
88
+ tokenProvider: async () => 'mock-token',
89
+ topics: ['control'],
90
+ });
91
+ await expect(adapter.send('unknown', 'data')).rejects.toThrow(ErrorCodes.UNKNOWN_TOPIC);
92
+ });
93
+ it('should throw if not connected', async () => {
94
+ const adapter = new MockAdapter();
95
+ await expect(adapter.send('control', 'data')).rejects.toThrow(ErrorCodes.NOT_CONNECTED);
96
+ });
97
+ });
98
+ describe('audio publisher', () => {
99
+ it('should start and stop audio publisher', async () => {
100
+ const adapter = new MockAdapter();
101
+ const logger = vi.fn();
102
+ await adapter.connect({
103
+ url: 'wss://mock.livekit.cloud',
104
+ tokenProvider: async () => 'mock-token',
105
+ logger,
106
+ });
107
+ await adapter.startAudioPublisher();
108
+ expect(logger).toHaveBeenCalledWith('info', 'Mock audio publisher started');
109
+ await adapter.stopAudioPublisher();
110
+ expect(logger).toHaveBeenCalledWith('info', 'Mock audio publisher stopped', {
111
+ totalFrames: 0,
112
+ });
113
+ });
114
+ it('should count pushed frames', async () => {
115
+ const adapter = new MockAdapter();
116
+ const logger = vi.fn();
117
+ await adapter.connect({
118
+ url: 'wss://mock.livekit.cloud',
119
+ tokenProvider: async () => 'mock-token',
120
+ logger,
121
+ });
122
+ await adapter.startAudioPublisher();
123
+ const frame = new Int16Array(480); // 10ms at 48kHz
124
+ for (let i = 0; i < 100; i++) {
125
+ await adapter.pushPcmFrame(frame);
126
+ }
127
+ expect(logger).toHaveBeenCalledWith('debug', 'Mock audio frames pushed: 100', {
128
+ frameSize: 480,
129
+ });
130
+ await adapter.stopAudioPublisher();
131
+ expect(logger).toHaveBeenCalledWith('info', 'Mock audio publisher stopped', {
132
+ totalFrames: 100,
133
+ });
134
+ });
135
+ it('should throw if audio not started', async () => {
136
+ const adapter = new MockAdapter();
137
+ await adapter.connect({
138
+ url: 'wss://mock.livekit.cloud',
139
+ tokenProvider: async () => 'mock-token',
140
+ });
141
+ const frame = new Int16Array(480);
142
+ await expect(adapter.pushPcmFrame(frame)).rejects.toThrow(ErrorCodes.AUDIO_NOT_STARTED);
143
+ });
144
+ });
145
+ describe('disconnect', () => {
146
+ it('should transition to disconnected state', async () => {
147
+ const adapter = new MockAdapter();
148
+ const events = [];
149
+ adapter.on((e) => events.push(e));
150
+ await adapter.connect({
151
+ url: 'wss://mock.livekit.cloud',
152
+ tokenProvider: async () => 'mock-token',
153
+ });
154
+ await adapter.disconnect();
155
+ expect(adapter.state).toBe('disconnected');
156
+ const stateEvents = events.filter((e) => e.type === 'state');
157
+ expect(stateEvents[stateEvents.length - 1]).toEqual({
158
+ type: 'state',
159
+ state: 'disconnected',
160
+ });
161
+ });
162
+ });
163
+ });
164
+ //# sourceMappingURL=mock.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.spec.js","sourceRoot":"","sources":["../src/mock.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ export type ConnectionState = 'idle' | 'connecting' | 'connected' | 'reconnecting' | 'disconnected';
2
+ export type TokenProvider = () => Promise<string>;
3
+ export interface RealtimeOptions {
4
+ /** wss://<livekit-host> */
5
+ url: string;
6
+ /** AccessToken 取得(期限切れ時も再呼び出し) */
7
+ tokenProvider: TokenProvider;
8
+ /** 接続オプション(必要最低限) */
9
+ connect?: {
10
+ autoSubscribe?: boolean;
11
+ dynacast?: boolean;
12
+ };
13
+ /** 使用する論理チャネル(topic)。未宣言topicの送信はエラーにする */
14
+ topics?: string[];
15
+ /** 音声Publish(サーバー発話) */
16
+ audioPublish?: {
17
+ sampleRate: 48000 | 24000 | 16000;
18
+ channels: 1 | 2;
19
+ frameDurationMs?: 10 | 20;
20
+ trackName?: string;
21
+ };
22
+ /** タイムアウト(最低限のみ) */
23
+ timeouts?: {
24
+ connectMs?: number;
25
+ };
26
+ /** 速度優先の軽量ロガー */
27
+ logger?: (level: 'debug' | 'info' | 'warn' | 'error', msg: string, meta?: unknown) => void;
28
+ }
29
+ export type RealtimeEvent = {
30
+ type: 'state';
31
+ state: ConnectionState;
32
+ } | {
33
+ type: 'data';
34
+ topic: string;
35
+ payload: Uint8Array;
36
+ from?: string;
37
+ } | {
38
+ type: 'participant-joined';
39
+ identity: string;
40
+ sid: string;
41
+ } | {
42
+ type: 'participant-left';
43
+ identity: string;
44
+ sid: string;
45
+ } | {
46
+ type: 'warning';
47
+ code: string;
48
+ message: string;
49
+ } | {
50
+ type: 'error';
51
+ code: string;
52
+ message: string;
53
+ cause?: unknown;
54
+ };
55
+ export interface RealtimeTransport {
56
+ readonly state: ConnectionState;
57
+ on(listener: (e: RealtimeEvent) => void): () => void;
58
+ connect(opts: RealtimeOptions): Promise<void>;
59
+ disconnect(): Promise<void>;
60
+ /** データ送信(PoCはreliable/ordered固定。低遅延設定は後日でOK) */
61
+ send(topic: string, data: Uint8Array | string): Promise<void>;
62
+ /** サーバー発話(TTS等から渣されたPCM16を配信) */
63
+ startAudioPublisher(): Promise<void>;
64
+ pushPcmFrame(frame: Int16Array): Promise<void>;
65
+ stopAudioPublisher(): Promise<void>;
66
+ /** 音声制御(PoCではno-opでもOK) */
67
+ setMicEnabled?(enabled: boolean): Promise<void>;
68
+ setSpeakerEnabled?(enabled: boolean): Promise<void>;
69
+ }
70
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@metatell/bot-realtime",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc --build",
19
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
20
+ "test": "vitest",
21
+ "typecheck": "tsc --noEmit"
22
+ },
23
+ "devDependencies": {
24
+ "@types/node": "^22.10.6",
25
+ "typescript": "^5.7.2",
26
+ "vitest": "^2.1.8"
27
+ },
28
+ "license": "MIT",
29
+ "dependencies": {
30
+ "@livekit/rtc-node": "^0.13.18",
31
+ "@metatell/bot-sdk": "file:../sdk"
32
+ }
33
+ }