@memberjunction/ai-bridge-livekit 0.0.1 → 5.42.0

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,302 @@
1
+ /**
2
+ * @fileoverview `LiveKitNativeMeetingSdk` — a **real, two-way** {@link ILiveKitRoomSdk} binding over the
3
+ * **native LiveKit server/agents SDK** (the Node room-participant build: `livekit-server-sdk` for token
4
+ * minting + admin, plus a room client such as `@livekit/rtc-node` that publishes/subscribes media). It
5
+ * gives the agent both **hearing** (each remote participant's subscribed audio track → a diarized
6
+ * {@link LiveKitAudioFrame}) and a **voice** ({@link publishAudioFrame} forwards the agent's synthesized
7
+ * PCM onto the bot's published audio track), plus full video/screen publish and the data-channel "chat".
8
+ *
9
+ * ## Why a native binding
10
+ * Publishing audio *into* a LiveKit room requires a real WebRTC participant — there is no receive-only
11
+ * shortcut as there is for some 3rd-party platforms. The native LiveKit room client exposes a
12
+ * publish-track **send** path alongside per-participant subscribed-track **receive** callbacks, so a
13
+ * single binding carries **bidirectional** media. This is the binding a two-way "agent talks in the
14
+ * room" deployment uses.
15
+ *
16
+ * ## The native module seam (no SDK types leak)
17
+ * The real LiveKit Node SDK is loaded **lazily** behind an injectable {@link NativeModuleLoader}, so this
18
+ * package builds and unit-tests with **no SDK installed and no network**. The adapter depends ONLY on the
19
+ * small structural {@link NativeRoomModule} / {@link NativeRoomClient} surface declared below — none of
20
+ * LiveKit's real types leak into the package. Tests inject a fake module; production points
21
+ * {@link LiveKitNativeSdkConfig.NativeModuleSpecifier} at the real room-client wrapper.
22
+ *
23
+ * ## Auth (deployment responsibility)
24
+ * The bot joins with a signed LiveKit **access token** (room name + grants) minted upstream by MJ's
25
+ * token/credential layer from the API **key/secret**. The ws URL + key/secret resolve **upstream** (MJ
26
+ * credential system / provider `Configuration`) and are **never inlined** at a call site. When a
27
+ * pre-signed token is supplied via {@link LiveKitConnectArgs.AccessToken} the adapter forwards it; when a
28
+ * deployment lets the native module mint the token, the resolved key/secret + ws URL are handed to
29
+ * {@link NativeRoomModule.createRoomClient}.
30
+ *
31
+ * Every spot where the native module's exact surface is assumed carries a `// VERIFY against the native
32
+ * LiveKit Node SDK wrapper` note so a live test can confirm it.
33
+ *
34
+ * @module @memberjunction/ai-bridge-livekit
35
+ * @author MemberJunction.com
36
+ */
37
+ import { ILiveKitRoomSdk, LiveKitAudioFrame, LiveKitConnectArgs, LiveKitConnectResult, LiveKitParticipant, LiveKitParticipantRole } from './livekit-sdk.js';
38
+ /** One subscribed per-participant audio frame the native room client surfaces (inbound hearing + diarization). */
39
+ export interface NativeRoomAudioFrame {
40
+ /** Raw PCM bytes for this frame (`Uint8Array` view or standalone `ArrayBuffer`). */
41
+ data: Uint8Array | ArrayBuffer;
42
+ /** The LiveKit participant identity that produced the audio (the diarization speaker label). */
43
+ participantIdentity: string;
44
+ /** The participant's display name at capture time, when the client provides it. */
45
+ name?: string;
46
+ /** Optional epoch-ms capture timestamp. */
47
+ timestampMs?: number;
48
+ }
49
+ /** One participant as the native room client reports it. Mapped onto {@link LiveKitParticipant}. */
50
+ export interface NativeRoomParticipant {
51
+ /** The native participant identity (stable, application-assigned). */
52
+ identity: string;
53
+ /** The participant's display name (LiveKit's `name` attribute). */
54
+ name?: string;
55
+ /** The participant's role as the client/metadata reports it (`host` / `cohost` / `participant`). */
56
+ role?: string;
57
+ /** Whether this participant is the bot itself (LiveKit's local participant). */
58
+ isLocal?: boolean;
59
+ }
60
+ /** The arguments the native room client's `connect()` accepts. Mirrors {@link LiveKitConnectArgs}. */
61
+ export interface NativeConnectArgs {
62
+ /** The LiveKit room server ws URL (e.g. `wss://livekit.myorg.com`). Resolved upstream. */
63
+ url: string;
64
+ /** The signed LiveKit access token authorizing the bot to join (resolved upstream; never inline). */
65
+ token: string;
66
+ /** The bot's display name in the participant list. */
67
+ name: string;
68
+ }
69
+ /** What the native room client's `connect()` resolves to. */
70
+ export interface NativeConnectResult {
71
+ /** The bot's own participant identity in the joined room. */
72
+ localIdentity: string;
73
+ /** The LiveKit room name the bot joined. */
74
+ roomName: string;
75
+ }
76
+ /**
77
+ * The live native room client the module hands back. The surface mirrors {@link ILiveKitRoomSdk} but in
78
+ * the native SDK's own (lower-cased) vocabulary; this adapter maps between the two. VERIFY against the
79
+ * native LiveKit Node SDK wrapper.
80
+ */
81
+ export interface NativeRoomClient {
82
+ /** Connects to the room (async — the native connect handshake is network-bound). */
83
+ connect(args: NativeConnectArgs): Promise<NativeConnectResult>;
84
+ /** Disconnects from the room and releases native resources. */
85
+ disconnect(): Promise<void>;
86
+ /** Publishes one raw PCM frame on the bot's audio track (the agent's voice). */
87
+ publishAudio(pcm: ArrayBuffer): void;
88
+ /** Drops all pending/queued outbound audio — flushes the agent's voice on barge-in. */
89
+ flushOutbound(): void;
90
+ /** Publishes one raw frame on the bot's camera/video track. */
91
+ publishVideo(frame: ArrayBuffer): void;
92
+ /** Publishes one raw frame on the bot's screen-share track. */
93
+ publishScreen(frame: ArrayBuffer): void;
94
+ /** Registers the inbound per-participant subscribed-audio callback. "Latest handler wins." */
95
+ onAudioFrame(cb: (frame: NativeRoomAudioFrame) => void): void;
96
+ /** Registers the participant-connected callback. */
97
+ onParticipantConnected(cb: (participant: NativeRoomParticipant) => void): void;
98
+ /** Registers the participant-disconnected callback (identity of the participant that left). */
99
+ onParticipantDisconnected(cb: (participantIdentity: string) => void): void;
100
+ /** Returns the current participant roster (including the bot). */
101
+ getParticipants(): Promise<NativeRoomParticipant[]>;
102
+ /** Publishes a reliable message on the room data channel (the room-native "chat"). */
103
+ publishData(text: string): Promise<void>;
104
+ /** Registers the room-disconnected callback (SFU closed / the bot was removed). */
105
+ onDisconnected(cb: () => void): void;
106
+ }
107
+ /** The native room module surface — a factory that constructs a {@link NativeRoomClient}. */
108
+ export interface NativeRoomModule {
109
+ /**
110
+ * Constructs a native room client from resolved options (credentials already resolved upstream).
111
+ * VERIFY against the native LiveKit Node SDK wrapper (`createRoomClient` vs a `Room` constructor).
112
+ */
113
+ createRoomClient(options: NativeRoomClientOptions): NativeRoomClient;
114
+ }
115
+ /** Options passed to {@link NativeRoomModule.createRoomClient}. Credentials are resolved upstream. */
116
+ export interface NativeRoomClientOptions {
117
+ /** The LiveKit room server ws URL (resolved upstream). */
118
+ Url?: string;
119
+ /** The LiveKit API key (resolved upstream; used to mint the join token when not pre-signed). */
120
+ ApiKey?: string;
121
+ /** The LiveKit API secret (resolved upstream). Used only to sign the join token. */
122
+ ApiSecret?: string;
123
+ /**
124
+ * PCM rate (Hz) the agent's model CONSUMES — the rate inbound room audio is resampled to. Default 24000
125
+ * (OpenAI); Gemini Live = 16000. A wrapper that ignores this stays on its constructed default.
126
+ */
127
+ InboundSampleRate?: number;
128
+ /** PCM rate (Hz) the agent's model EMITS — the bot's published voice-track rate. Default 24000. */
129
+ OutboundSampleRate?: number;
130
+ }
131
+ /**
132
+ * Resolved configuration for {@link LiveKitNativeMeetingSdk}. Credentials resolve **upstream** (MJ
133
+ * credential system / provider `Configuration`) — this object carries already-resolved values; **never
134
+ * inline secrets** at a call site.
135
+ */
136
+ export interface LiveKitNativeSdkConfig {
137
+ /** The LiveKit room server ws URL (resolved upstream). */
138
+ Url?: string;
139
+ /** The LiveKit API key (resolved upstream). Used to mint the join token when not pre-signed. */
140
+ ApiKey?: string;
141
+ /** The LiveKit API secret (resolved upstream). Used only to sign the join token. */
142
+ ApiSecret?: string;
143
+ /** A pre-signed LiveKit access token, when the deployment mints it out-of-band instead of via key/secret. */
144
+ AccessToken?: string;
145
+ /** The bot's display name (defaults applied by the bridge when absent). */
146
+ BotDisplayName?: string;
147
+ /**
148
+ * The module specifier of the native LiveKit room-client wrapper to load (e.g. an internal wrapper
149
+ * package name or an absolute path to a sidecar entry). Required in production; tests inject a loader.
150
+ */
151
+ NativeModuleSpecifier?: string;
152
+ /**
153
+ * PCM rate (Hz) the agent's realtime model **consumes** — the rate inbound room audio is resampled to
154
+ * before reaching the model. Threaded from the model via the engine (`IRealtimeSession.InputSampleRate`).
155
+ * Default 24000 (OpenAI); Gemini Live = 16000. Mismatch = the agent never hears the user on the bridge.
156
+ */
157
+ InboundSampleRate?: number;
158
+ /** PCM rate (Hz) the agent's model **emits** — the bot's published voice track rate. Default 24000. */
159
+ OutboundSampleRate?: number;
160
+ }
161
+ /** Normalizes the native client's free-form role string onto the seam's {@link LiveKitParticipantRole}. */
162
+ export declare function mapNativeRole(role?: string): LiveKitParticipantRole;
163
+ /**
164
+ * **Pure mapping** of one native participant onto the seam's {@link LiveKitParticipant}. Isolated from the
165
+ * native client and from I/O so it is unit-tested directly.
166
+ */
167
+ export declare function mapNativeParticipant(p: NativeRoomParticipant): LiveKitParticipant;
168
+ /**
169
+ * Coerces a `Uint8Array` view or `ArrayBuffer` into a standalone `ArrayBuffer`, **copying** the exact
170
+ * window of a view (so the result never aliases a larger backing buffer). The LiveKit package has no
171
+ * pre-existing PCM-coercion helper to reuse, so this is defined here; it is the single such export.
172
+ */
173
+ export declare function toArrayBuffer(data: Uint8Array | ArrayBuffer): ArrayBuffer;
174
+ /**
175
+ * **Pure mapping** of one native inbound audio frame onto the seam's diarized {@link LiveKitAudioFrame}.
176
+ * Copies the PCM (see {@link toArrayBuffer}) and resolves the speaker label. Isolated for direct testing.
177
+ */
178
+ export declare function mapNativeAudioFrame(frame: NativeRoomAudioFrame): LiveKitAudioFrame;
179
+ /**
180
+ * The injectable loader for the native LiveKit room module — overridable so unit tests supply a fake
181
+ * module with no SDK and no network. Production leaves it as {@link defaultNativeLoader}, which lazily
182
+ * imports the configured {@link LiveKitNativeSdkConfig.NativeModuleSpecifier}.
183
+ */
184
+ export type NativeModuleLoader = (specifier: string) => Promise<NativeRoomModule>;
185
+ /**
186
+ * Lazily loads the native LiveKit room module at the given specifier (category: runtime plugin discovery
187
+ * from config — the wrapper path is deployment-supplied and not known at build time, hence the
188
+ * `@vite-ignore` on the dynamic import). Throws a precise, actionable error when it can't be loaded so a
189
+ * misconfigured deployment fails loudly, not silently.
190
+ *
191
+ * VERIFY against the native LiveKit Node SDK wrapper: the module's default/namespace interop + that it
192
+ * exposes `createRoomClient`.
193
+ */
194
+ export declare const defaultNativeLoader: NativeModuleLoader;
195
+ /**
196
+ * A **real, two-way** {@link ILiveKitRoomSdk} over the native LiveKit Node room SDK (publish + subscribe).
197
+ *
198
+ * Gives the agent both **hearing** (per-participant subscribed audio → diarized {@link LiveKitAudioFrame}s)
199
+ * and a **voice** ({@link publishAudioFrame} → the native publish path), plus working video/screen publish,
200
+ * the data-channel chat, and roster events. Construct via {@link BindLiveKitNative} (the factory the
201
+ * bridge's `SetSdkFactory` wants), not directly, so config resolution + the lazy loader wire consistently.
202
+ */
203
+ export declare class LiveKitNativeMeetingSdk implements ILiveKitRoomSdk {
204
+ /** Resolved config (credentials + the native module specifier). */
205
+ private readonly config;
206
+ /** The native-module loader (overridable for tests). */
207
+ private readonly loadModule;
208
+ /** The live native room client once {@link connect} succeeds. */
209
+ private client;
210
+ /** The inbound per-participant audio handler registered by the bridge. */
211
+ private audioHandler?;
212
+ /** The participant-join handler. */
213
+ private joinHandler?;
214
+ /** The participant-leave handler. */
215
+ private leaveHandler?;
216
+ /** The room-disconnected handler. */
217
+ private disconnectedHandler?;
218
+ /**
219
+ * @param config Resolved credentials + the native module specifier.
220
+ * @param loadModule The native-module loader (defaults to the lazy specifier loader).
221
+ */
222
+ constructor(config: LiveKitNativeSdkConfig, loadModule?: NativeModuleLoader);
223
+ /**
224
+ * Loads the native module, constructs a room client, wires its callbacks, and connects to the room
225
+ * with the resolved access token. Brings BOTH hearing and the agent's voice online.
226
+ *
227
+ * @param args The bridge's connect args (room ws URL, signed access token, bot name).
228
+ * @returns The bot/room identifiers.
229
+ * @throws When the native module specifier is missing or the module can't be loaded.
230
+ */
231
+ connect(args: LiveKitConnectArgs): Promise<LiveKitConnectResult>;
232
+ /** Disconnects from the room and releases the native client. Tolerant of teardown errors. */
233
+ disconnect(): Promise<void>;
234
+ /**
235
+ * Publishes one raw PCM frame on the bot's audio track — **the agent's real voice into the room**, via
236
+ * the native publish path. No-ops (without throwing) before {@link connect} so an early model frame
237
+ * never crashes the session.
238
+ *
239
+ * @param pcm The PCM audio bytes to publish into the room.
240
+ */
241
+ publishAudioFrame(pcm: ArrayBuffer): void;
242
+ /** Flushes the agent's queued outbound audio (barge-in). No-ops before connect. */
243
+ flushOutboundAudio(): void;
244
+ /**
245
+ * Publishes one raw video frame on the bot's camera track via the native publish path. No-ops before
246
+ * {@link connect}.
247
+ *
248
+ * @param frame The video frame bytes to publish.
249
+ */
250
+ publishVideoFrame(frame: ArrayBuffer): void;
251
+ /**
252
+ * Publishes one raw screen-share frame on the bot's screen track via the native publish path. No-ops
253
+ * before {@link connect}.
254
+ *
255
+ * @param frame The screen frame bytes to publish.
256
+ */
257
+ publishScreenFrame(frame: ArrayBuffer): void;
258
+ /** Registers the inbound per-participant audio handler (the diarized hearing path). */
259
+ onAudioTrack(cb: (frame: LiveKitAudioFrame) => void): void;
260
+ /** Registers the participant-join handler. */
261
+ onParticipantJoin(cb: (participant: LiveKitParticipant) => void): void;
262
+ /** Registers the participant-leave handler. */
263
+ onParticipantLeave(cb: (participantIdentity: string) => void): void;
264
+ /** Returns the current roster from the native client, mapped to {@link LiveKitParticipant}. */
265
+ getParticipants(): Promise<LiveKitParticipant[]>;
266
+ /** Registers the room-disconnected handler. */
267
+ onDisconnected(cb: () => void): void;
268
+ /**
269
+ * Sends a reliable text message on the room data channel via the native client — the room-native
270
+ * "chat". No-ops (without throwing) before {@link connect}.
271
+ *
272
+ * @param text The data/chat message text.
273
+ */
274
+ sendDataMessage(text: string): Promise<void>;
275
+ /** Wires the native client's callbacks to this adapter's handlers, mapping native shapes to the seam. */
276
+ private wireClient;
277
+ }
278
+ /**
279
+ * Builds the {@link import('./livekit-sdk.js').LiveKitRoomSdkFactory}-shaped factory that constructs a
280
+ * {@link LiveKitNativeMeetingSdk} from the bridge's per-session `Configuration`. Pass the result to
281
+ * `LiveKitBridge.SetSdkFactory(...)` so a deployment activates **two-way native LiveKit media** without
282
+ * code changes to the driver.
283
+ *
284
+ * Reads the ws URL / API key/secret / pre-signed token + bot name + the native module specifier out of
285
+ * the config map the engine passes at connect (credentials resolved upstream — **never inline secrets**).
286
+ *
287
+ * @example
288
+ * // Where bridge drivers are configured (creds already resolved from the MJ credential system):
289
+ * bridge.SetSdkFactory(BindLiveKitNative());
290
+ *
291
+ * @param loadModule Optional native-module loader override (tests inject a fake; production omits it).
292
+ * @returns A factory `(config) => LiveKitNativeMeetingSdk`.
293
+ */
294
+ export declare function BindLiveKitNative(loadModule?: NativeModuleLoader): (config?: Record<string, unknown>) => LiveKitNativeMeetingSdk;
295
+ /**
296
+ * Extracts a {@link LiveKitNativeSdkConfig} from the engine's loosely-typed `Configuration` map without
297
+ * ever widening to `any`. Each field is read + type-checked individually so a malformed config yields a
298
+ * clean, partially-resolved object (and {@link LiveKitNativeMeetingSdk.connect} then throws a precise
299
+ * error if the required specifier is absent) rather than a half-typed blob.
300
+ */
301
+ export declare function readNativeConfig(config?: Record<string, unknown>): LiveKitNativeSdkConfig;
302
+ //# sourceMappingURL=livekit-native-sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit-native-sdk.d.ts","sourceRoot":"","sources":["../src/livekit-native-sdk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,320 @@
1
+ /**
2
+ * @fileoverview `LiveKitNativeMeetingSdk` — a **real, two-way** {@link ILiveKitRoomSdk} binding over the
3
+ * **native LiveKit server/agents SDK** (the Node room-participant build: `livekit-server-sdk` for token
4
+ * minting + admin, plus a room client such as `@livekit/rtc-node` that publishes/subscribes media). It
5
+ * gives the agent both **hearing** (each remote participant's subscribed audio track → a diarized
6
+ * {@link LiveKitAudioFrame}) and a **voice** ({@link publishAudioFrame} forwards the agent's synthesized
7
+ * PCM onto the bot's published audio track), plus full video/screen publish and the data-channel "chat".
8
+ *
9
+ * ## Why a native binding
10
+ * Publishing audio *into* a LiveKit room requires a real WebRTC participant — there is no receive-only
11
+ * shortcut as there is for some 3rd-party platforms. The native LiveKit room client exposes a
12
+ * publish-track **send** path alongside per-participant subscribed-track **receive** callbacks, so a
13
+ * single binding carries **bidirectional** media. This is the binding a two-way "agent talks in the
14
+ * room" deployment uses.
15
+ *
16
+ * ## The native module seam (no SDK types leak)
17
+ * The real LiveKit Node SDK is loaded **lazily** behind an injectable {@link NativeModuleLoader}, so this
18
+ * package builds and unit-tests with **no SDK installed and no network**. The adapter depends ONLY on the
19
+ * small structural {@link NativeRoomModule} / {@link NativeRoomClient} surface declared below — none of
20
+ * LiveKit's real types leak into the package. Tests inject a fake module; production points
21
+ * {@link LiveKitNativeSdkConfig.NativeModuleSpecifier} at the real room-client wrapper.
22
+ *
23
+ * ## Auth (deployment responsibility)
24
+ * The bot joins with a signed LiveKit **access token** (room name + grants) minted upstream by MJ's
25
+ * token/credential layer from the API **key/secret**. The ws URL + key/secret resolve **upstream** (MJ
26
+ * credential system / provider `Configuration`) and are **never inlined** at a call site. When a
27
+ * pre-signed token is supplied via {@link LiveKitConnectArgs.AccessToken} the adapter forwards it; when a
28
+ * deployment lets the native module mint the token, the resolved key/secret + ws URL are handed to
29
+ * {@link NativeRoomModule.createRoomClient}.
30
+ *
31
+ * Every spot where the native module's exact surface is assumed carries a `// VERIFY against the native
32
+ * LiveKit Node SDK wrapper` note so a live test can confirm it.
33
+ *
34
+ * @module @memberjunction/ai-bridge-livekit
35
+ * @author MemberJunction.com
36
+ */
37
+ import { LogError } from '@memberjunction/core';
38
+ /** Normalizes the native client's free-form role string onto the seam's {@link LiveKitParticipantRole}. */
39
+ export function mapNativeRole(role) {
40
+ switch ((role ?? '').trim().toLowerCase()) {
41
+ case 'host':
42
+ return 'Host';
43
+ case 'cohost':
44
+ case 'co-host':
45
+ return 'CoHost';
46
+ default:
47
+ return 'Participant';
48
+ }
49
+ }
50
+ /**
51
+ * **Pure mapping** of one native participant onto the seam's {@link LiveKitParticipant}. Isolated from the
52
+ * native client and from I/O so it is unit-tested directly.
53
+ */
54
+ export function mapNativeParticipant(p) {
55
+ return {
56
+ Identity: String(p.identity),
57
+ DisplayName: p.name,
58
+ Role: mapNativeRole(p.role),
59
+ IsLocal: p.isLocal,
60
+ };
61
+ }
62
+ /**
63
+ * Coerces a `Uint8Array` view or `ArrayBuffer` into a standalone `ArrayBuffer`, **copying** the exact
64
+ * window of a view (so the result never aliases a larger backing buffer). The LiveKit package has no
65
+ * pre-existing PCM-coercion helper to reuse, so this is defined here; it is the single such export.
66
+ */
67
+ export function toArrayBuffer(data) {
68
+ if (data instanceof ArrayBuffer) {
69
+ return data;
70
+ }
71
+ const copy = new Uint8Array(data.byteLength);
72
+ copy.set(data);
73
+ return copy.buffer;
74
+ }
75
+ /**
76
+ * **Pure mapping** of one native inbound audio frame onto the seam's diarized {@link LiveKitAudioFrame}.
77
+ * Copies the PCM (see {@link toArrayBuffer}) and resolves the speaker label. Isolated for direct testing.
78
+ */
79
+ export function mapNativeAudioFrame(frame) {
80
+ return {
81
+ Pcm: toArrayBuffer(frame.data),
82
+ ParticipantIdentity: String(frame.participantIdentity),
83
+ DisplayName: frame.name,
84
+ TimestampMs: typeof frame.timestampMs === 'number' ? frame.timestampMs : Date.now(),
85
+ };
86
+ }
87
+ /** Structural guard: a value is a {@link NativeRoomModule} when it exposes a `createRoomClient` function. */
88
+ function isNativeModule(value) {
89
+ return (value != null &&
90
+ typeof value === 'object' &&
91
+ typeof value.createRoomClient === 'function');
92
+ }
93
+ /** Unwraps a `{ default }` interop wrapper (CJS-with-default), returning the inner value or the input. */
94
+ function unwrapDefault(mod) {
95
+ if (mod && typeof mod === 'object' && 'default' in mod) {
96
+ const inner = mod.default;
97
+ if (isNativeModule(inner)) {
98
+ return inner;
99
+ }
100
+ }
101
+ return mod;
102
+ }
103
+ /**
104
+ * Lazily loads the native LiveKit room module at the given specifier (category: runtime plugin discovery
105
+ * from config — the wrapper path is deployment-supplied and not known at build time, hence the
106
+ * `@vite-ignore` on the dynamic import). Throws a precise, actionable error when it can't be loaded so a
107
+ * misconfigured deployment fails loudly, not silently.
108
+ *
109
+ * VERIFY against the native LiveKit Node SDK wrapper: the module's default/namespace interop + that it
110
+ * exposes `createRoomClient`.
111
+ */
112
+ export const defaultNativeLoader = async (specifier) => {
113
+ try {
114
+ const mod = await import(/* @vite-ignore */ specifier);
115
+ const resolved = unwrapDefault(mod);
116
+ if (!isNativeModule(resolved)) {
117
+ throw new Error('resolved module has no createRoomClient() factory');
118
+ }
119
+ return resolved;
120
+ }
121
+ catch (err) {
122
+ const message = err instanceof Error ? err.message : String(err);
123
+ throw new Error(`LiveKitNativeMeetingSdk could not load the native LiveKit room module at '${specifier}'. Build/install ` +
124
+ 'the native LiveKit Node room-client wrapper (livekit-server-sdk + a room client like @livekit/rtc-node) ' +
125
+ `and set LiveKitNativeSdkConfig.NativeModuleSpecifier to it. Underlying error: ${message}`);
126
+ }
127
+ };
128
+ /**
129
+ * A **real, two-way** {@link ILiveKitRoomSdk} over the native LiveKit Node room SDK (publish + subscribe).
130
+ *
131
+ * Gives the agent both **hearing** (per-participant subscribed audio → diarized {@link LiveKitAudioFrame}s)
132
+ * and a **voice** ({@link publishAudioFrame} → the native publish path), plus working video/screen publish,
133
+ * the data-channel chat, and roster events. Construct via {@link BindLiveKitNative} (the factory the
134
+ * bridge's `SetSdkFactory` wants), not directly, so config resolution + the lazy loader wire consistently.
135
+ */
136
+ export class LiveKitNativeMeetingSdk {
137
+ /**
138
+ * @param config Resolved credentials + the native module specifier.
139
+ * @param loadModule The native-module loader (defaults to the lazy specifier loader).
140
+ */
141
+ constructor(config, loadModule = defaultNativeLoader) {
142
+ /** The live native room client once {@link connect} succeeds. */
143
+ this.client = null;
144
+ this.config = config;
145
+ this.loadModule = loadModule;
146
+ }
147
+ // ── ILiveKitRoomSdk — lifecycle ──────────────────────────────────────────────────
148
+ /**
149
+ * Loads the native module, constructs a room client, wires its callbacks, and connects to the room
150
+ * with the resolved access token. Brings BOTH hearing and the agent's voice online.
151
+ *
152
+ * @param args The bridge's connect args (room ws URL, signed access token, bot name).
153
+ * @returns The bot/room identifiers.
154
+ * @throws When the native module specifier is missing or the module can't be loaded.
155
+ */
156
+ async connect(args) {
157
+ const specifier = this.config.NativeModuleSpecifier;
158
+ if (!specifier) {
159
+ throw new Error('LiveKitNativeMeetingSdk.connect: no NativeModuleSpecifier configured. Set it to the native LiveKit ' +
160
+ 'Node room-client wrapper in the session Configuration. See the README.');
161
+ }
162
+ const mod = await this.loadModule(specifier);
163
+ const client = mod.createRoomClient({
164
+ Url: args.RoomUrl || this.config.Url,
165
+ ApiKey: this.config.ApiKey,
166
+ ApiSecret: this.config.ApiSecret,
167
+ // The model's audio format (threaded from IRealtimeSession via the engine) — so inbound room
168
+ // audio is resampled to what the model consumes (OpenAI 24 kHz; Gemini Live 16 kHz).
169
+ InboundSampleRate: this.config.InboundSampleRate,
170
+ OutboundSampleRate: this.config.OutboundSampleRate,
171
+ });
172
+ this.wireClient(client);
173
+ const result = await client.connect({
174
+ url: args.RoomUrl || this.config.Url || '',
175
+ token: args.AccessToken || this.config.AccessToken || '',
176
+ name: args.BotDisplayName || this.config.BotDisplayName || 'AI Agent',
177
+ });
178
+ this.client = client;
179
+ return {
180
+ BotIdentity: String(result.localIdentity),
181
+ RoomName: result.roomName,
182
+ };
183
+ }
184
+ /** Disconnects from the room and releases the native client. Tolerant of teardown errors. */
185
+ async disconnect() {
186
+ const client = this.client;
187
+ this.client = null;
188
+ if (client) {
189
+ try {
190
+ await client.disconnect();
191
+ }
192
+ catch (err) {
193
+ LogError(`[LiveKitNativeMeetingSdk] disconnect() failed: ${err instanceof Error ? err.message : String(err)}`);
194
+ }
195
+ }
196
+ }
197
+ // ── ILiveKitRoomSdk — two-way media (real) ───────────────────────────────────────
198
+ /**
199
+ * Publishes one raw PCM frame on the bot's audio track — **the agent's real voice into the room**, via
200
+ * the native publish path. No-ops (without throwing) before {@link connect} so an early model frame
201
+ * never crashes the session.
202
+ *
203
+ * @param pcm The PCM audio bytes to publish into the room.
204
+ */
205
+ publishAudioFrame(pcm) {
206
+ this.client?.publishAudio(pcm);
207
+ }
208
+ /** Flushes the agent's queued outbound audio (barge-in). No-ops before connect. */
209
+ flushOutboundAudio() {
210
+ this.client?.flushOutbound();
211
+ }
212
+ /**
213
+ * Publishes one raw video frame on the bot's camera track via the native publish path. No-ops before
214
+ * {@link connect}.
215
+ *
216
+ * @param frame The video frame bytes to publish.
217
+ */
218
+ publishVideoFrame(frame) {
219
+ this.client?.publishVideo(frame);
220
+ }
221
+ /**
222
+ * Publishes one raw screen-share frame on the bot's screen track via the native publish path. No-ops
223
+ * before {@link connect}.
224
+ *
225
+ * @param frame The screen frame bytes to publish.
226
+ */
227
+ publishScreenFrame(frame) {
228
+ this.client?.publishScreen(frame);
229
+ }
230
+ /** Registers the inbound per-participant audio handler (the diarized hearing path). */
231
+ onAudioTrack(cb) {
232
+ this.audioHandler = cb;
233
+ }
234
+ // ── ILiveKitRoomSdk — roster + signals ───────────────────────────────────────────
235
+ /** Registers the participant-join handler. */
236
+ onParticipantJoin(cb) {
237
+ this.joinHandler = cb;
238
+ }
239
+ /** Registers the participant-leave handler. */
240
+ onParticipantLeave(cb) {
241
+ this.leaveHandler = cb;
242
+ }
243
+ /** Returns the current roster from the native client, mapped to {@link LiveKitParticipant}. */
244
+ async getParticipants() {
245
+ if (!this.client) {
246
+ return [];
247
+ }
248
+ const natives = await this.client.getParticipants();
249
+ return natives.map(mapNativeParticipant);
250
+ }
251
+ /** Registers the room-disconnected handler. */
252
+ onDisconnected(cb) {
253
+ this.disconnectedHandler = cb;
254
+ }
255
+ // ── ILiveKitRoomSdk — data channel (real) ────────────────────────────────────────
256
+ /**
257
+ * Sends a reliable text message on the room data channel via the native client — the room-native
258
+ * "chat". No-ops (without throwing) before {@link connect}.
259
+ *
260
+ * @param text The data/chat message text.
261
+ */
262
+ async sendDataMessage(text) {
263
+ await this.client?.publishData(text);
264
+ }
265
+ // ── internals ────────────────────────────────────────────────────────────────────
266
+ /** Wires the native client's callbacks to this adapter's handlers, mapping native shapes to the seam. */
267
+ wireClient(client) {
268
+ client.onAudioFrame((frame) => this.audioHandler?.(mapNativeAudioFrame(frame)));
269
+ client.onParticipantConnected((p) => this.joinHandler?.(mapNativeParticipant(p)));
270
+ client.onParticipantDisconnected((id) => this.leaveHandler?.(String(id)));
271
+ client.onDisconnected(() => this.disconnectedHandler?.());
272
+ }
273
+ }
274
+ /**
275
+ * Builds the {@link import('./livekit-sdk.js').LiveKitRoomSdkFactory}-shaped factory that constructs a
276
+ * {@link LiveKitNativeMeetingSdk} from the bridge's per-session `Configuration`. Pass the result to
277
+ * `LiveKitBridge.SetSdkFactory(...)` so a deployment activates **two-way native LiveKit media** without
278
+ * code changes to the driver.
279
+ *
280
+ * Reads the ws URL / API key/secret / pre-signed token + bot name + the native module specifier out of
281
+ * the config map the engine passes at connect (credentials resolved upstream — **never inline secrets**).
282
+ *
283
+ * @example
284
+ * // Where bridge drivers are configured (creds already resolved from the MJ credential system):
285
+ * bridge.SetSdkFactory(BindLiveKitNative());
286
+ *
287
+ * @param loadModule Optional native-module loader override (tests inject a fake; production omits it).
288
+ * @returns A factory `(config) => LiveKitNativeMeetingSdk`.
289
+ */
290
+ export function BindLiveKitNative(loadModule = defaultNativeLoader) {
291
+ return (config) => new LiveKitNativeMeetingSdk(readNativeConfig(config), loadModule);
292
+ }
293
+ /**
294
+ * Extracts a {@link LiveKitNativeSdkConfig} from the engine's loosely-typed `Configuration` map without
295
+ * ever widening to `any`. Each field is read + type-checked individually so a malformed config yields a
296
+ * clean, partially-resolved object (and {@link LiveKitNativeMeetingSdk.connect} then throws a precise
297
+ * error if the required specifier is absent) rather than a half-typed blob.
298
+ */
299
+ export function readNativeConfig(config) {
300
+ const cfg = config ?? {};
301
+ return {
302
+ Url: readString(cfg.Url),
303
+ ApiKey: readString(cfg.ApiKey),
304
+ ApiSecret: readString(cfg.ApiSecret),
305
+ AccessToken: readString(cfg.AccessToken),
306
+ BotDisplayName: readString(cfg.BotDisplayName),
307
+ NativeModuleSpecifier: readString(cfg.NativeModuleSpecifier),
308
+ InboundSampleRate: readNumber(cfg.InboundSampleRate),
309
+ OutboundSampleRate: readNumber(cfg.OutboundSampleRate),
310
+ };
311
+ }
312
+ /** Reads a value as a non-empty string, or `undefined`. */
313
+ function readString(value) {
314
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
315
+ }
316
+ /** Reads a positive finite number from a free-form config value, or `undefined`. */
317
+ function readNumber(value) {
318
+ return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : undefined;
319
+ }
320
+ //# sourceMappingURL=livekit-native-sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"livekit-native-sdk.js","sourceRoot":"","sources":["../src/livekit-native-sdk.ts"],"names":[],"mappings":"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"}