@craftedxp/voice-js 0.4.2 → 0.6.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.
- package/CONSUMING.md +10 -2
- package/README.md +69 -11
- package/dist/browser.d.mts +242 -1
- package/dist/browser.d.ts +242 -1
- package/dist/browser.js +301 -2
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs +301 -1
- package/dist/browser.mjs.map +1 -1
- package/dist/embed.iife.js +43 -3
- package/dist/node.d.mts +240 -1
- package/dist/node.d.ts +240 -1
- package/dist/node.js +27 -2
- package/dist/node.js.map +1 -1
- package/dist/node.mjs +25 -1
- package/dist/node.mjs.map +1 -1
- package/package.json +5 -1
package/dist/node.d.mts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { RemoteTrack, LocalVideoTrack } from 'livekit-client';
|
|
2
|
+
|
|
1
3
|
interface ClientTool {
|
|
2
4
|
description: string;
|
|
3
5
|
parameters: Record<string, unknown>;
|
|
@@ -79,6 +81,199 @@ interface BuildWsUrlArgs {
|
|
|
79
81
|
}
|
|
80
82
|
declare function buildWsUrl(args: BuildWsUrlArgs): string;
|
|
81
83
|
|
|
84
|
+
type SystemMessage = {
|
|
85
|
+
kind: 'room.starting';
|
|
86
|
+
at: string;
|
|
87
|
+
} | {
|
|
88
|
+
kind: 'room.ending.soon';
|
|
89
|
+
minutesRemaining: 5 | 1;
|
|
90
|
+
} | {
|
|
91
|
+
kind: 'room.ended';
|
|
92
|
+
reason: 'duration_reached' | 'manual' | 'empty';
|
|
93
|
+
} | {
|
|
94
|
+
kind: 'role.promoted';
|
|
95
|
+
participantId: string;
|
|
96
|
+
name: string;
|
|
97
|
+
} | {
|
|
98
|
+
kind: 'role.demoted';
|
|
99
|
+
participantId: string;
|
|
100
|
+
name: string;
|
|
101
|
+
} | {
|
|
102
|
+
kind: 'participant.removed';
|
|
103
|
+
participantId: string;
|
|
104
|
+
name: string;
|
|
105
|
+
byHost?: string;
|
|
106
|
+
} | {
|
|
107
|
+
kind: 'notetaker.connected';
|
|
108
|
+
} | {
|
|
109
|
+
kind: 'notetaker.disconnected';
|
|
110
|
+
} | {
|
|
111
|
+
kind: 'notetaker.partial_degraded';
|
|
112
|
+
participantId: string;
|
|
113
|
+
};
|
|
114
|
+
type TranscriptMessage = {
|
|
115
|
+
kind: 'partial';
|
|
116
|
+
participantId: string;
|
|
117
|
+
speakerName: string;
|
|
118
|
+
text: string;
|
|
119
|
+
startedAt: string;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
interface JoinRoomOptions {
|
|
123
|
+
/** Full HTTPS URL of the Voissia server. Same shape as VoiceClientConfig.apiBase. */
|
|
124
|
+
apiBase: string;
|
|
125
|
+
/** Server-generated room id (`rm_…`). */
|
|
126
|
+
roomId: string;
|
|
127
|
+
/** Shared room join token from the invite link. Mints a fresh participant each call. */
|
|
128
|
+
joinCode: string;
|
|
129
|
+
/** Display name the joiner registers under for this participant. */
|
|
130
|
+
name: string;
|
|
131
|
+
}
|
|
132
|
+
interface RoomParticipantInfo {
|
|
133
|
+
/** Stable participant id (`p_…`); strips any `guest:` LiveKit identity prefix. */
|
|
134
|
+
participantId: string;
|
|
135
|
+
/** Display name as the worker registered it; may be empty. */
|
|
136
|
+
name: string;
|
|
137
|
+
}
|
|
138
|
+
type RoomTrackKind = 'audio' | 'video';
|
|
139
|
+
/** What a track is — lets consumers tell a camera apart from a screen share
|
|
140
|
+
* (a participant can publish both at once). Mirrors livekit `Track.Source`. */
|
|
141
|
+
type RoomTrackSource = 'camera' | 'microphone' | 'screen_share' | 'screen_share_audio' | 'unknown';
|
|
142
|
+
interface RoomTrackEvent {
|
|
143
|
+
/** Stable participant id (`p_…`); `guest:` prefix stripped. */
|
|
144
|
+
participantId: string;
|
|
145
|
+
kind: RoomTrackKind;
|
|
146
|
+
/** Distinguishes camera vs screen_share so each can render as its own tile. */
|
|
147
|
+
source: RoomTrackSource;
|
|
148
|
+
/** livekit-client track — call `.attach(el)` / `.detach()` to render. */
|
|
149
|
+
track: RemoteTrack;
|
|
150
|
+
}
|
|
151
|
+
type RoomEventName = 'participant.joined' | 'participant.left' | 'transcript.partial' | 'transcript.final' | 'system.message' | 'room.ended' | 'track.subscribed' | 'track.unsubscribed' | 'active.speakers';
|
|
152
|
+
interface RoomEventPayloads {
|
|
153
|
+
'participant.joined': RoomParticipantInfo;
|
|
154
|
+
'participant.left': RoomParticipantInfo;
|
|
155
|
+
'transcript.partial': TranscriptMessage;
|
|
156
|
+
/**
|
|
157
|
+
* Reserved — the worker currently emits only partials over the transcript
|
|
158
|
+
* topic. Final-utterance events will land in Phase 8 once the worker
|
|
159
|
+
* publishes a `final` kind; the SDK keeps the slot reserved so consumers
|
|
160
|
+
* can register handlers today.
|
|
161
|
+
*/
|
|
162
|
+
'transcript.final': {
|
|
163
|
+
participantId: string;
|
|
164
|
+
speakerName: string;
|
|
165
|
+
text: string;
|
|
166
|
+
startedAt: string;
|
|
167
|
+
};
|
|
168
|
+
'system.message': SystemMessage;
|
|
169
|
+
'room.ended': undefined;
|
|
170
|
+
'track.subscribed': RoomTrackEvent;
|
|
171
|
+
'track.unsubscribed': RoomTrackEvent;
|
|
172
|
+
/** participantIds currently speaking (drives an active-speaker UI). */
|
|
173
|
+
'active.speakers': string[];
|
|
174
|
+
}
|
|
175
|
+
type Handler<E extends RoomEventName> = (payload: RoomEventPayloads[E]) => void;
|
|
176
|
+
interface RoomSession {
|
|
177
|
+
/** This session's own stable participant id (`p_…`). Useful to filter
|
|
178
|
+
* yourself out of `active.speakers`, which includes the local participant. */
|
|
179
|
+
readonly participantId: string;
|
|
180
|
+
/** Snapshot of the remote participants currently connected. */
|
|
181
|
+
readonly participants: RoomParticipantInfo[];
|
|
182
|
+
/** Subscribe to a typed event. No unsubscribe surface yet (mirrors `Call.onX`). */
|
|
183
|
+
on<E extends RoomEventName>(event: E, handler: Handler<E>): void;
|
|
184
|
+
/** Publish the local mic track. Resolves once the track is live on LiveKit. */
|
|
185
|
+
publishMic(): Promise<void>;
|
|
186
|
+
/** Publish the local camera track. */
|
|
187
|
+
publishCamera(): Promise<void>;
|
|
188
|
+
/** Mid-call mute/unmute of the local mic. */
|
|
189
|
+
setMicEnabled(on: boolean): Promise<void>;
|
|
190
|
+
/** Mid-call camera on/off. */
|
|
191
|
+
setCameraEnabled(on: boolean): Promise<void>;
|
|
192
|
+
/** Current local mic state (for toggle UI). */
|
|
193
|
+
isMicEnabled(): boolean;
|
|
194
|
+
/** Current local camera state (for toggle UI). */
|
|
195
|
+
isCameraEnabled(): boolean;
|
|
196
|
+
/** The local camera track for self-view, or null before publishCamera resolves. */
|
|
197
|
+
getLocalCameraTrack(): LocalVideoTrack | null;
|
|
198
|
+
/**
|
|
199
|
+
* Remote tracks already subscribed at this moment. A late joiner misses the
|
|
200
|
+
* live `track.subscribed` events for tracks published before it connected
|
|
201
|
+
* (LiveKit delivers them during `connect`, before consumer listeners attach).
|
|
202
|
+
* Call this right after registering `track.subscribed` to backfill them.
|
|
203
|
+
*/
|
|
204
|
+
getRemoteTracks(): RoomTrackEvent[];
|
|
205
|
+
/**
|
|
206
|
+
* Start/stop sharing the screen (via `getDisplayMedia`). Pass `{ audio: true }`
|
|
207
|
+
* to also capture shared/system audio where the browser allows it (Chrome:
|
|
208
|
+
* tab or system audio; macOS Chrome is tab-audio only; Safari/Firefox don't
|
|
209
|
+
* capture share audio). Publishes a `screen_share` video track (+ optional
|
|
210
|
+
* `screen_share_audio`); remote peers receive them via `track.subscribed`.
|
|
211
|
+
*/
|
|
212
|
+
setScreenShareEnabled(on: boolean, opts?: {
|
|
213
|
+
audio?: boolean;
|
|
214
|
+
}): Promise<void>;
|
|
215
|
+
/** Current local screen-share state (for toggle UI). */
|
|
216
|
+
isScreenShareEnabled(): boolean;
|
|
217
|
+
/** The local screen-share video track for self-preview, or null when off. */
|
|
218
|
+
getLocalScreenTrack(): LocalVideoTrack | null;
|
|
219
|
+
/** Disconnect from LiveKit. Idempotent. Triggers `room.ended` via Disconnected. */
|
|
220
|
+
leave(): Promise<void>;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Browser-friendly text-channel chat session. Mint a `ct_` token with
|
|
225
|
+
* `channel: 'text'` on your backend, then call `startTextSession({...})`
|
|
226
|
+
* to open the SSE stream.
|
|
227
|
+
*
|
|
228
|
+
* Each `.send(text)` is a fresh POST; SSE-per-turn means the connection
|
|
229
|
+
* closes when each turn ends. Conversation state lives server-side on the
|
|
230
|
+
* underlying CallRecord.
|
|
231
|
+
*/
|
|
232
|
+
type ChatEvent = {
|
|
233
|
+
type: 'chat.started';
|
|
234
|
+
chatId: string;
|
|
235
|
+
callId: string;
|
|
236
|
+
} | {
|
|
237
|
+
type: 'token';
|
|
238
|
+
text: string;
|
|
239
|
+
} | {
|
|
240
|
+
type: 'tool.call';
|
|
241
|
+
name: string;
|
|
242
|
+
args: unknown;
|
|
243
|
+
} | {
|
|
244
|
+
type: 'tool.result';
|
|
245
|
+
name: string;
|
|
246
|
+
ok?: boolean;
|
|
247
|
+
[key: string]: unknown;
|
|
248
|
+
} | {
|
|
249
|
+
type: 'turn.end';
|
|
250
|
+
finishReason: 'stop' | 'aborted' | 'length' | 'tool_error';
|
|
251
|
+
committedText?: string;
|
|
252
|
+
} | {
|
|
253
|
+
type: 'error';
|
|
254
|
+
code: string;
|
|
255
|
+
message: string;
|
|
256
|
+
};
|
|
257
|
+
interface StartTextSessionOpts {
|
|
258
|
+
baseUrl: string;
|
|
259
|
+
token: string;
|
|
260
|
+
agentId: string;
|
|
261
|
+
/** Optional inline first user message; otherwise the agent's greeting opens the stream. */
|
|
262
|
+
text?: string;
|
|
263
|
+
/** Override the global fetch (useful for tests; defaults to globalThis.fetch). */
|
|
264
|
+
fetch?: typeof fetch;
|
|
265
|
+
}
|
|
266
|
+
interface TextSession {
|
|
267
|
+
id: string;
|
|
268
|
+
callId: string;
|
|
269
|
+
/** Async iterable for the opening turn — greeting tokens / first reply if text was inlined. */
|
|
270
|
+
greeting: AsyncIterable<ChatEvent>;
|
|
271
|
+
/** Send a user message; returns an async iterable for the agent's reply. */
|
|
272
|
+
send(text: string): Promise<AsyncIterable<ChatEvent>>;
|
|
273
|
+
/** End the session — DELETE /v1/calls/:callId. */
|
|
274
|
+
end(): Promise<void>;
|
|
275
|
+
}
|
|
276
|
+
|
|
82
277
|
interface FetchTokenArgs {
|
|
83
278
|
/** The agent the SDK is about to call. */
|
|
84
279
|
agentId: string;
|
|
@@ -228,6 +423,25 @@ interface VoiceClientFactory {
|
|
|
228
423
|
* don't reject this promise.
|
|
229
424
|
*/
|
|
230
425
|
startCall: (options: StartCallOptions) => Promise<Call>;
|
|
426
|
+
/**
|
|
427
|
+
* Phase 7 (multi-party rooms). Browser only. Exchange a single-use
|
|
428
|
+
* joinCode for a LiveKit JWT and connect to the room. The returned
|
|
429
|
+
* `RoomSession` exposes a typed event surface
|
|
430
|
+
* (participant.joined / participant.left / transcript.partial /
|
|
431
|
+
* transcript.final / system.message / room.ended) plus
|
|
432
|
+
* publishMic / publishCamera / leave. The Node bundle does NOT
|
|
433
|
+
* implement this — livekit-client is a browser-only WebRTC client.
|
|
434
|
+
*/
|
|
435
|
+
joinRoom?: (options: Omit<JoinRoomOptions, 'apiBase'>) => Promise<RoomSession>;
|
|
436
|
+
/**
|
|
437
|
+
* Open a text-channel chat session (no microphone / audio required).
|
|
438
|
+
* Mint a `ct_` token with `channel: 'text'` server-side, then call
|
|
439
|
+
* this to connect. Returns a `TextSession` with:
|
|
440
|
+
* - `.greeting` — async iterable for the opening turn
|
|
441
|
+
* - `.send(text)` — send a user message; returns an async iterable for the reply
|
|
442
|
+
* - `.end()` — close the session (DELETE /v1/calls/:callId)
|
|
443
|
+
*/
|
|
444
|
+
startTextSession?: (opts: Omit<StartTextSessionOpts, 'baseUrl' | 'fetch'>) => Promise<TextSession>;
|
|
231
445
|
}
|
|
232
446
|
|
|
233
447
|
type RWSEvent = {
|
|
@@ -308,6 +522,31 @@ interface NodeVoiceClientFactory {
|
|
|
308
522
|
startCall: (options: NodeStartCallOptions) => Promise<NodeCall>;
|
|
309
523
|
}
|
|
310
524
|
|
|
525
|
+
/**
|
|
526
|
+
* Canonical payload a tenant places in their VoIP/FCM push so an
|
|
527
|
+
* agent-initiated call can connect. It is the `callTokens.mint` result
|
|
528
|
+
* (token + transport) plus two optional display fields for the native
|
|
529
|
+
* incoming-call UI. The host receives the push, runs `parseIncomingCall`,
|
|
530
|
+
* and on accept passes `token` (+ transport / webrtcGatewayBase) into the
|
|
531
|
+
* voice client. Web background-wake is best-effort (Web Push); native is
|
|
532
|
+
* the real target. See docs/sdks.md "Agent-initiated calls".
|
|
533
|
+
*/
|
|
534
|
+
interface IncomingCallPayload {
|
|
535
|
+
token: string;
|
|
536
|
+
agentId: string;
|
|
537
|
+
transport: 'ws' | 'webrtc';
|
|
538
|
+
webrtcGatewayBase?: string;
|
|
539
|
+
expiresAt?: number;
|
|
540
|
+
agentName?: string;
|
|
541
|
+
agentAvatarUrl?: string;
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Validate + normalise a raw push payload into an IncomingCallPayload.
|
|
545
|
+
* Throws synchronously on malformed input. Unknown transports fall back to
|
|
546
|
+
* 'ws'; webrtcGatewayBase is ignored unless transport === 'webrtc'.
|
|
547
|
+
*/
|
|
548
|
+
declare const parseIncomingCall: (raw: unknown) => IncomingCallPayload;
|
|
549
|
+
|
|
311
550
|
/**
|
|
312
551
|
* One-time SDK setup for Node.js / Electron-main consumers. Returns a
|
|
313
552
|
* factory you call `startCall` on for every voice call. Same shape as
|
|
@@ -338,4 +577,4 @@ interface NodeVoiceClientFactory {
|
|
|
338
577
|
*/
|
|
339
578
|
declare function configureVoiceClient(config: VoiceClientConfig): NodeVoiceClientFactory;
|
|
340
579
|
|
|
341
|
-
export { type Call, type CallEndEvent, type CallEndReason, type CallError, type CallErrorCode, type CallState, type ClientTool, type ClientToolMap, type FetchToken, type FetchTokenArgs, type FetchTokenResult, type NodeCall, type NodeStartCallOptions, type NodeVoiceClientFactory, type ProtocolCallbacks, type ProtocolState, type RWSEvent, type RWSOptions, type ReconnectingWebSocket, type ServerMessage, type StartCallOptions, type TranscriptEntry, type VoiceClientConfig, type VoiceClientFactory, type VolumeEvent, type WebSocketFactory, type WebSocketLike, buildWsUrl, configureVoiceClient, createProtocolState, createReconnectingWebSocket, handleServerMessage };
|
|
580
|
+
export { type Call, type CallEndEvent, type CallEndReason, type CallError, type CallErrorCode, type CallState, type ClientTool, type ClientToolMap, type FetchToken, type FetchTokenArgs, type FetchTokenResult, type IncomingCallPayload, type NodeCall, type NodeStartCallOptions, type NodeVoiceClientFactory, type ProtocolCallbacks, type ProtocolState, type RWSEvent, type RWSOptions, type ReconnectingWebSocket, type ServerMessage, type StartCallOptions, type TranscriptEntry, type VoiceClientConfig, type VoiceClientFactory, type VolumeEvent, type WebSocketFactory, type WebSocketLike, buildWsUrl, configureVoiceClient, createProtocolState, createReconnectingWebSocket, handleServerMessage, parseIncomingCall };
|
package/dist/node.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { RemoteTrack, LocalVideoTrack } from 'livekit-client';
|
|
2
|
+
|
|
1
3
|
interface ClientTool {
|
|
2
4
|
description: string;
|
|
3
5
|
parameters: Record<string, unknown>;
|
|
@@ -79,6 +81,199 @@ interface BuildWsUrlArgs {
|
|
|
79
81
|
}
|
|
80
82
|
declare function buildWsUrl(args: BuildWsUrlArgs): string;
|
|
81
83
|
|
|
84
|
+
type SystemMessage = {
|
|
85
|
+
kind: 'room.starting';
|
|
86
|
+
at: string;
|
|
87
|
+
} | {
|
|
88
|
+
kind: 'room.ending.soon';
|
|
89
|
+
minutesRemaining: 5 | 1;
|
|
90
|
+
} | {
|
|
91
|
+
kind: 'room.ended';
|
|
92
|
+
reason: 'duration_reached' | 'manual' | 'empty';
|
|
93
|
+
} | {
|
|
94
|
+
kind: 'role.promoted';
|
|
95
|
+
participantId: string;
|
|
96
|
+
name: string;
|
|
97
|
+
} | {
|
|
98
|
+
kind: 'role.demoted';
|
|
99
|
+
participantId: string;
|
|
100
|
+
name: string;
|
|
101
|
+
} | {
|
|
102
|
+
kind: 'participant.removed';
|
|
103
|
+
participantId: string;
|
|
104
|
+
name: string;
|
|
105
|
+
byHost?: string;
|
|
106
|
+
} | {
|
|
107
|
+
kind: 'notetaker.connected';
|
|
108
|
+
} | {
|
|
109
|
+
kind: 'notetaker.disconnected';
|
|
110
|
+
} | {
|
|
111
|
+
kind: 'notetaker.partial_degraded';
|
|
112
|
+
participantId: string;
|
|
113
|
+
};
|
|
114
|
+
type TranscriptMessage = {
|
|
115
|
+
kind: 'partial';
|
|
116
|
+
participantId: string;
|
|
117
|
+
speakerName: string;
|
|
118
|
+
text: string;
|
|
119
|
+
startedAt: string;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
interface JoinRoomOptions {
|
|
123
|
+
/** Full HTTPS URL of the Voissia server. Same shape as VoiceClientConfig.apiBase. */
|
|
124
|
+
apiBase: string;
|
|
125
|
+
/** Server-generated room id (`rm_…`). */
|
|
126
|
+
roomId: string;
|
|
127
|
+
/** Shared room join token from the invite link. Mints a fresh participant each call. */
|
|
128
|
+
joinCode: string;
|
|
129
|
+
/** Display name the joiner registers under for this participant. */
|
|
130
|
+
name: string;
|
|
131
|
+
}
|
|
132
|
+
interface RoomParticipantInfo {
|
|
133
|
+
/** Stable participant id (`p_…`); strips any `guest:` LiveKit identity prefix. */
|
|
134
|
+
participantId: string;
|
|
135
|
+
/** Display name as the worker registered it; may be empty. */
|
|
136
|
+
name: string;
|
|
137
|
+
}
|
|
138
|
+
type RoomTrackKind = 'audio' | 'video';
|
|
139
|
+
/** What a track is — lets consumers tell a camera apart from a screen share
|
|
140
|
+
* (a participant can publish both at once). Mirrors livekit `Track.Source`. */
|
|
141
|
+
type RoomTrackSource = 'camera' | 'microphone' | 'screen_share' | 'screen_share_audio' | 'unknown';
|
|
142
|
+
interface RoomTrackEvent {
|
|
143
|
+
/** Stable participant id (`p_…`); `guest:` prefix stripped. */
|
|
144
|
+
participantId: string;
|
|
145
|
+
kind: RoomTrackKind;
|
|
146
|
+
/** Distinguishes camera vs screen_share so each can render as its own tile. */
|
|
147
|
+
source: RoomTrackSource;
|
|
148
|
+
/** livekit-client track — call `.attach(el)` / `.detach()` to render. */
|
|
149
|
+
track: RemoteTrack;
|
|
150
|
+
}
|
|
151
|
+
type RoomEventName = 'participant.joined' | 'participant.left' | 'transcript.partial' | 'transcript.final' | 'system.message' | 'room.ended' | 'track.subscribed' | 'track.unsubscribed' | 'active.speakers';
|
|
152
|
+
interface RoomEventPayloads {
|
|
153
|
+
'participant.joined': RoomParticipantInfo;
|
|
154
|
+
'participant.left': RoomParticipantInfo;
|
|
155
|
+
'transcript.partial': TranscriptMessage;
|
|
156
|
+
/**
|
|
157
|
+
* Reserved — the worker currently emits only partials over the transcript
|
|
158
|
+
* topic. Final-utterance events will land in Phase 8 once the worker
|
|
159
|
+
* publishes a `final` kind; the SDK keeps the slot reserved so consumers
|
|
160
|
+
* can register handlers today.
|
|
161
|
+
*/
|
|
162
|
+
'transcript.final': {
|
|
163
|
+
participantId: string;
|
|
164
|
+
speakerName: string;
|
|
165
|
+
text: string;
|
|
166
|
+
startedAt: string;
|
|
167
|
+
};
|
|
168
|
+
'system.message': SystemMessage;
|
|
169
|
+
'room.ended': undefined;
|
|
170
|
+
'track.subscribed': RoomTrackEvent;
|
|
171
|
+
'track.unsubscribed': RoomTrackEvent;
|
|
172
|
+
/** participantIds currently speaking (drives an active-speaker UI). */
|
|
173
|
+
'active.speakers': string[];
|
|
174
|
+
}
|
|
175
|
+
type Handler<E extends RoomEventName> = (payload: RoomEventPayloads[E]) => void;
|
|
176
|
+
interface RoomSession {
|
|
177
|
+
/** This session's own stable participant id (`p_…`). Useful to filter
|
|
178
|
+
* yourself out of `active.speakers`, which includes the local participant. */
|
|
179
|
+
readonly participantId: string;
|
|
180
|
+
/** Snapshot of the remote participants currently connected. */
|
|
181
|
+
readonly participants: RoomParticipantInfo[];
|
|
182
|
+
/** Subscribe to a typed event. No unsubscribe surface yet (mirrors `Call.onX`). */
|
|
183
|
+
on<E extends RoomEventName>(event: E, handler: Handler<E>): void;
|
|
184
|
+
/** Publish the local mic track. Resolves once the track is live on LiveKit. */
|
|
185
|
+
publishMic(): Promise<void>;
|
|
186
|
+
/** Publish the local camera track. */
|
|
187
|
+
publishCamera(): Promise<void>;
|
|
188
|
+
/** Mid-call mute/unmute of the local mic. */
|
|
189
|
+
setMicEnabled(on: boolean): Promise<void>;
|
|
190
|
+
/** Mid-call camera on/off. */
|
|
191
|
+
setCameraEnabled(on: boolean): Promise<void>;
|
|
192
|
+
/** Current local mic state (for toggle UI). */
|
|
193
|
+
isMicEnabled(): boolean;
|
|
194
|
+
/** Current local camera state (for toggle UI). */
|
|
195
|
+
isCameraEnabled(): boolean;
|
|
196
|
+
/** The local camera track for self-view, or null before publishCamera resolves. */
|
|
197
|
+
getLocalCameraTrack(): LocalVideoTrack | null;
|
|
198
|
+
/**
|
|
199
|
+
* Remote tracks already subscribed at this moment. A late joiner misses the
|
|
200
|
+
* live `track.subscribed` events for tracks published before it connected
|
|
201
|
+
* (LiveKit delivers them during `connect`, before consumer listeners attach).
|
|
202
|
+
* Call this right after registering `track.subscribed` to backfill them.
|
|
203
|
+
*/
|
|
204
|
+
getRemoteTracks(): RoomTrackEvent[];
|
|
205
|
+
/**
|
|
206
|
+
* Start/stop sharing the screen (via `getDisplayMedia`). Pass `{ audio: true }`
|
|
207
|
+
* to also capture shared/system audio where the browser allows it (Chrome:
|
|
208
|
+
* tab or system audio; macOS Chrome is tab-audio only; Safari/Firefox don't
|
|
209
|
+
* capture share audio). Publishes a `screen_share` video track (+ optional
|
|
210
|
+
* `screen_share_audio`); remote peers receive them via `track.subscribed`.
|
|
211
|
+
*/
|
|
212
|
+
setScreenShareEnabled(on: boolean, opts?: {
|
|
213
|
+
audio?: boolean;
|
|
214
|
+
}): Promise<void>;
|
|
215
|
+
/** Current local screen-share state (for toggle UI). */
|
|
216
|
+
isScreenShareEnabled(): boolean;
|
|
217
|
+
/** The local screen-share video track for self-preview, or null when off. */
|
|
218
|
+
getLocalScreenTrack(): LocalVideoTrack | null;
|
|
219
|
+
/** Disconnect from LiveKit. Idempotent. Triggers `room.ended` via Disconnected. */
|
|
220
|
+
leave(): Promise<void>;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Browser-friendly text-channel chat session. Mint a `ct_` token with
|
|
225
|
+
* `channel: 'text'` on your backend, then call `startTextSession({...})`
|
|
226
|
+
* to open the SSE stream.
|
|
227
|
+
*
|
|
228
|
+
* Each `.send(text)` is a fresh POST; SSE-per-turn means the connection
|
|
229
|
+
* closes when each turn ends. Conversation state lives server-side on the
|
|
230
|
+
* underlying CallRecord.
|
|
231
|
+
*/
|
|
232
|
+
type ChatEvent = {
|
|
233
|
+
type: 'chat.started';
|
|
234
|
+
chatId: string;
|
|
235
|
+
callId: string;
|
|
236
|
+
} | {
|
|
237
|
+
type: 'token';
|
|
238
|
+
text: string;
|
|
239
|
+
} | {
|
|
240
|
+
type: 'tool.call';
|
|
241
|
+
name: string;
|
|
242
|
+
args: unknown;
|
|
243
|
+
} | {
|
|
244
|
+
type: 'tool.result';
|
|
245
|
+
name: string;
|
|
246
|
+
ok?: boolean;
|
|
247
|
+
[key: string]: unknown;
|
|
248
|
+
} | {
|
|
249
|
+
type: 'turn.end';
|
|
250
|
+
finishReason: 'stop' | 'aborted' | 'length' | 'tool_error';
|
|
251
|
+
committedText?: string;
|
|
252
|
+
} | {
|
|
253
|
+
type: 'error';
|
|
254
|
+
code: string;
|
|
255
|
+
message: string;
|
|
256
|
+
};
|
|
257
|
+
interface StartTextSessionOpts {
|
|
258
|
+
baseUrl: string;
|
|
259
|
+
token: string;
|
|
260
|
+
agentId: string;
|
|
261
|
+
/** Optional inline first user message; otherwise the agent's greeting opens the stream. */
|
|
262
|
+
text?: string;
|
|
263
|
+
/** Override the global fetch (useful for tests; defaults to globalThis.fetch). */
|
|
264
|
+
fetch?: typeof fetch;
|
|
265
|
+
}
|
|
266
|
+
interface TextSession {
|
|
267
|
+
id: string;
|
|
268
|
+
callId: string;
|
|
269
|
+
/** Async iterable for the opening turn — greeting tokens / first reply if text was inlined. */
|
|
270
|
+
greeting: AsyncIterable<ChatEvent>;
|
|
271
|
+
/** Send a user message; returns an async iterable for the agent's reply. */
|
|
272
|
+
send(text: string): Promise<AsyncIterable<ChatEvent>>;
|
|
273
|
+
/** End the session — DELETE /v1/calls/:callId. */
|
|
274
|
+
end(): Promise<void>;
|
|
275
|
+
}
|
|
276
|
+
|
|
82
277
|
interface FetchTokenArgs {
|
|
83
278
|
/** The agent the SDK is about to call. */
|
|
84
279
|
agentId: string;
|
|
@@ -228,6 +423,25 @@ interface VoiceClientFactory {
|
|
|
228
423
|
* don't reject this promise.
|
|
229
424
|
*/
|
|
230
425
|
startCall: (options: StartCallOptions) => Promise<Call>;
|
|
426
|
+
/**
|
|
427
|
+
* Phase 7 (multi-party rooms). Browser only. Exchange a single-use
|
|
428
|
+
* joinCode for a LiveKit JWT and connect to the room. The returned
|
|
429
|
+
* `RoomSession` exposes a typed event surface
|
|
430
|
+
* (participant.joined / participant.left / transcript.partial /
|
|
431
|
+
* transcript.final / system.message / room.ended) plus
|
|
432
|
+
* publishMic / publishCamera / leave. The Node bundle does NOT
|
|
433
|
+
* implement this — livekit-client is a browser-only WebRTC client.
|
|
434
|
+
*/
|
|
435
|
+
joinRoom?: (options: Omit<JoinRoomOptions, 'apiBase'>) => Promise<RoomSession>;
|
|
436
|
+
/**
|
|
437
|
+
* Open a text-channel chat session (no microphone / audio required).
|
|
438
|
+
* Mint a `ct_` token with `channel: 'text'` server-side, then call
|
|
439
|
+
* this to connect. Returns a `TextSession` with:
|
|
440
|
+
* - `.greeting` — async iterable for the opening turn
|
|
441
|
+
* - `.send(text)` — send a user message; returns an async iterable for the reply
|
|
442
|
+
* - `.end()` — close the session (DELETE /v1/calls/:callId)
|
|
443
|
+
*/
|
|
444
|
+
startTextSession?: (opts: Omit<StartTextSessionOpts, 'baseUrl' | 'fetch'>) => Promise<TextSession>;
|
|
231
445
|
}
|
|
232
446
|
|
|
233
447
|
type RWSEvent = {
|
|
@@ -308,6 +522,31 @@ interface NodeVoiceClientFactory {
|
|
|
308
522
|
startCall: (options: NodeStartCallOptions) => Promise<NodeCall>;
|
|
309
523
|
}
|
|
310
524
|
|
|
525
|
+
/**
|
|
526
|
+
* Canonical payload a tenant places in their VoIP/FCM push so an
|
|
527
|
+
* agent-initiated call can connect. It is the `callTokens.mint` result
|
|
528
|
+
* (token + transport) plus two optional display fields for the native
|
|
529
|
+
* incoming-call UI. The host receives the push, runs `parseIncomingCall`,
|
|
530
|
+
* and on accept passes `token` (+ transport / webrtcGatewayBase) into the
|
|
531
|
+
* voice client. Web background-wake is best-effort (Web Push); native is
|
|
532
|
+
* the real target. See docs/sdks.md "Agent-initiated calls".
|
|
533
|
+
*/
|
|
534
|
+
interface IncomingCallPayload {
|
|
535
|
+
token: string;
|
|
536
|
+
agentId: string;
|
|
537
|
+
transport: 'ws' | 'webrtc';
|
|
538
|
+
webrtcGatewayBase?: string;
|
|
539
|
+
expiresAt?: number;
|
|
540
|
+
agentName?: string;
|
|
541
|
+
agentAvatarUrl?: string;
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Validate + normalise a raw push payload into an IncomingCallPayload.
|
|
545
|
+
* Throws synchronously on malformed input. Unknown transports fall back to
|
|
546
|
+
* 'ws'; webrtcGatewayBase is ignored unless transport === 'webrtc'.
|
|
547
|
+
*/
|
|
548
|
+
declare const parseIncomingCall: (raw: unknown) => IncomingCallPayload;
|
|
549
|
+
|
|
311
550
|
/**
|
|
312
551
|
* One-time SDK setup for Node.js / Electron-main consumers. Returns a
|
|
313
552
|
* factory you call `startCall` on for every voice call. Same shape as
|
|
@@ -338,4 +577,4 @@ interface NodeVoiceClientFactory {
|
|
|
338
577
|
*/
|
|
339
578
|
declare function configureVoiceClient(config: VoiceClientConfig): NodeVoiceClientFactory;
|
|
340
579
|
|
|
341
|
-
export { type Call, type CallEndEvent, type CallEndReason, type CallError, type CallErrorCode, type CallState, type ClientTool, type ClientToolMap, type FetchToken, type FetchTokenArgs, type FetchTokenResult, type NodeCall, type NodeStartCallOptions, type NodeVoiceClientFactory, type ProtocolCallbacks, type ProtocolState, type RWSEvent, type RWSOptions, type ReconnectingWebSocket, type ServerMessage, type StartCallOptions, type TranscriptEntry, type VoiceClientConfig, type VoiceClientFactory, type VolumeEvent, type WebSocketFactory, type WebSocketLike, buildWsUrl, configureVoiceClient, createProtocolState, createReconnectingWebSocket, handleServerMessage };
|
|
580
|
+
export { type Call, type CallEndEvent, type CallEndReason, type CallError, type CallErrorCode, type CallState, type ClientTool, type ClientToolMap, type FetchToken, type FetchTokenArgs, type FetchTokenResult, type IncomingCallPayload, type NodeCall, type NodeStartCallOptions, type NodeVoiceClientFactory, type ProtocolCallbacks, type ProtocolState, type RWSEvent, type RWSOptions, type ReconnectingWebSocket, type ServerMessage, type StartCallOptions, type TranscriptEntry, type VoiceClientConfig, type VoiceClientFactory, type VolumeEvent, type WebSocketFactory, type WebSocketLike, buildWsUrl, configureVoiceClient, createProtocolState, createReconnectingWebSocket, handleServerMessage, parseIncomingCall };
|
package/dist/node.js
CHANGED
|
@@ -34,7 +34,8 @@ __export(node_exports, {
|
|
|
34
34
|
configureVoiceClient: () => configureVoiceClient,
|
|
35
35
|
createProtocolState: () => createProtocolState,
|
|
36
36
|
createReconnectingWebSocket: () => createReconnectingWebSocket,
|
|
37
|
-
handleServerMessage: () => handleServerMessage
|
|
37
|
+
handleServerMessage: () => handleServerMessage,
|
|
38
|
+
parseIncomingCall: () => parseIncomingCall
|
|
38
39
|
});
|
|
39
40
|
module.exports = __toCommonJS(node_exports);
|
|
40
41
|
|
|
@@ -617,6 +618,29 @@ var NodeVoiceClient = class {
|
|
|
617
618
|
}
|
|
618
619
|
};
|
|
619
620
|
|
|
621
|
+
// src/incomingCall.ts
|
|
622
|
+
var parseIncomingCall = (raw) => {
|
|
623
|
+
if (typeof raw !== "object" || raw === null) {
|
|
624
|
+
throw new Error("parseIncomingCall: payload must be an object");
|
|
625
|
+
}
|
|
626
|
+
const p = raw;
|
|
627
|
+
if (typeof p.token !== "string" || !p.token.startsWith("ct_")) {
|
|
628
|
+
throw new Error("parseIncomingCall: missing or invalid `token` (expected a ct_ string)");
|
|
629
|
+
}
|
|
630
|
+
if (typeof p.agentId !== "string" || p.agentId.length === 0) {
|
|
631
|
+
throw new Error("parseIncomingCall: missing `agentId`");
|
|
632
|
+
}
|
|
633
|
+
const transport = p.transport === "webrtc" ? "webrtc" : "ws";
|
|
634
|
+
const out = { token: p.token, agentId: p.agentId, transport };
|
|
635
|
+
if (transport === "webrtc" && typeof p.webrtcGatewayBase === "string") {
|
|
636
|
+
out.webrtcGatewayBase = p.webrtcGatewayBase;
|
|
637
|
+
}
|
|
638
|
+
if (typeof p.expiresAt === "number") out.expiresAt = p.expiresAt;
|
|
639
|
+
if (typeof p.agentName === "string") out.agentName = p.agentName;
|
|
640
|
+
if (typeof p.agentAvatarUrl === "string") out.agentAvatarUrl = p.agentAvatarUrl;
|
|
641
|
+
return out;
|
|
642
|
+
};
|
|
643
|
+
|
|
620
644
|
// src/node.ts
|
|
621
645
|
var cachedWsCtor = null;
|
|
622
646
|
var loadWsCtor = async () => {
|
|
@@ -689,6 +713,7 @@ function configureVoiceClient(config) {
|
|
|
689
713
|
configureVoiceClient,
|
|
690
714
|
createProtocolState,
|
|
691
715
|
createReconnectingWebSocket,
|
|
692
|
-
handleServerMessage
|
|
716
|
+
handleServerMessage,
|
|
717
|
+
parseIncomingCall
|
|
693
718
|
});
|
|
694
719
|
//# sourceMappingURL=node.js.map
|