realtime-avatar 0.22.0 → 0.24.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/README.md +98 -0
- package/dist/{chunk-T3RZSVRI.js → chunk-FUJI3KIH.js} +1 -1
- package/dist/{chunk-N76M4MEU.js → chunk-ZXPLFSG7.js} +15 -4
- package/dist/express.d.ts +2 -2
- package/dist/express.js +2 -2
- package/dist/hono.d.ts +2 -2
- package/dist/hono.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/nextjs.d.ts +2 -2
- package/dist/nextjs.js +2 -2
- package/dist/{proxy-client-6ndCkiio.d.ts → proxy-client-DlFXaXtn.d.ts} +130 -6
- package/dist/react-native.d.ts +2 -2
- package/dist/react-native.js +61 -14
- package/dist/react.d.ts +15 -3
- package/dist/react.js +283 -15
- package/dist/recording-DjswTx5B.d.ts +198 -0
- package/dist/recording.d.ts +34 -133
- package/dist/recording.js +42 -4
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/dist/tanstack-start.d.ts +2 -2
- package/dist/tanstack-start.js +2 -2
- package/dist/{types-k6pW-wKA.d.ts → types-CpqMHna3.d.ts} +1 -1
- package/dist/{types-Cmto2uGs.d.ts → types-D77jgSms.d.ts} +482 -7
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -25,6 +25,47 @@ return call.raw; // relay to the browser byte-for-byte
|
|
|
25
25
|
|
|
26
26
|
That is the whole server half. The client joins with the payload and renders her.
|
|
27
27
|
|
|
28
|
+
## React Native compatibility
|
|
29
|
+
|
|
30
|
+
The next release requires **LiveKit React Native 3** for `/react-native`; it does not claim
|
|
31
|
+
compatibility with LiveKit React Native 2. Install the tested group together:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install --save-exact @livekit/react-native@3.0.0 @livekit/react-native-webrtc@144.2.0 livekit-client@2.22.3 @livekit/components-react@2.9.21
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`@livekit/components-react@2.9.21` retains `@livekit/components-core@0.12.13`; both satisfy the
|
|
38
|
+
native 3.0.0 peer contracts. Keep a single resolved components-react instance: the native room
|
|
39
|
+
provides its context and the SDK's shared hooks consume that same context. SDK checks use React
|
|
40
|
+
19.2.7 and React Native 0.81.5. The web binding also uses client 2.22.3; no components upgrade or
|
|
41
|
+
stream-handling patch is required for this tuple. Peer ranges allow compatible updates, but only
|
|
42
|
+
this exact tuple has been checked here. Client 2.22.3 introduces `machina@7.0.1`, whose Node
|
|
43
|
+
engine is `>=22.22`; use Node 22.22 or newer for client/native tooling (verified on 22.23.1).
|
|
44
|
+
This does not change the dependency-free server entry's Node floor. Node 20 tooling is not
|
|
45
|
+
verified for the new LiveKit group.
|
|
46
|
+
|
|
47
|
+
Call the SDK's re-exported `registerGlobals()` once at app startup, before creating rooms. RN3
|
|
48
|
+
configures iOS audio natively by default; do not reintroduce the deprecated JavaScript audio
|
|
49
|
+
management callback. `RealtimeAvatarLiveKitRoom` retains the existing `AudioSession.startAudioSession`
|
|
50
|
+
and `stopAudioSession` lifecycle while a grant and `connect` intent are present. Apps that own audio
|
|
51
|
+
configuration or coordinate overlapping calls must pass `manageAudioSession={false}` and own that
|
|
52
|
+
lifecycle; the hook is not a shared audio-session lease. Camera publication still requires both the
|
|
53
|
+
server grant's permission and the caller's opt-in. Room callbacks/options continue to use LiveKit's
|
|
54
|
+
public types and implementation; no separate connection state machine is introduced.
|
|
55
|
+
|
|
56
|
+
**This is a native build upgrade, not an OTA-only change.** Rebuild iOS and Android binaries with
|
|
57
|
+
RN3/WebRTC 144.2.0 before shipping JavaScript that requires them. Retain the previous SDK group for
|
|
58
|
+
installed binaries that still use RN2, and isolate their OTA runtime/channel appropriately.
|
|
59
|
+
|
|
60
|
+
The packaged-entry regression suite mounts the built `/react-native` adapter with the installed
|
|
61
|
+
RN3 room and audio implementations, real React/LiveKit hooks, and shared contexts. It checks room
|
|
62
|
+
props, microphone/camera policy, callbacks, start/stop intent, redial, and listener cleanup. It mocks
|
|
63
|
+
native module calls, network connection and media capture; it does **not** prove native binary
|
|
64
|
+
linking, `registerGlobals`, RTCView rendering, permissions, Bluetooth/speaker routing, interruption
|
|
65
|
+
recovery, asynchronous OS audio teardown, or overlapping-room ownership. Test these on iOS and
|
|
66
|
+
Android devices, including repeated call/redial and background/foreground transitions, before a
|
|
67
|
+
consumer release.
|
|
68
|
+
|
|
28
69
|
## Optional call recordings
|
|
29
70
|
|
|
30
71
|
Your server decides whether to record after your application obtains consent:
|
|
@@ -143,6 +184,32 @@ Two facts follow from that picture and drive everything else:
|
|
|
143
184
|
|
|
144
185
|
---
|
|
145
186
|
|
|
187
|
+
## Input source on room messages
|
|
188
|
+
|
|
189
|
+
On React and React Native, `session.sendTurn(text)` automatically observes text.
|
|
190
|
+
For already recognized speech, bind
|
|
191
|
+
`session.createTranscriptSender({ inputSource: "client_stt" })` once per session.
|
|
192
|
+
The adapter defaults to `client_stt`; it captures its own default, and accepts a
|
|
193
|
+
per-send `{ inputSource: "text" }` override. `sendTurn` accepts the same optional
|
|
194
|
+
declaration. Only `text` and `client_stt` are valid client declarations. No speech
|
|
195
|
+
recognition engine is included. `instructions` still work on either sender.
|
|
196
|
+
|
|
197
|
+
`retryTurn()` preserves the resolved source and declaration scope after a timeout,
|
|
198
|
+
with a new `turn_id` and `retry_of_turn_id` pointing to the previous attempt.
|
|
199
|
+
Room consumers receive the attributes through the existing `lk.chat` text stream.
|
|
200
|
+
`useChat().chatMessages` exposes them as `message.attributes`; an imperative receiver
|
|
201
|
+
can read `reader.info.attributes` in `registerTextStreamHandler("lk.chat", handler)`.
|
|
202
|
+
The observation is `rta.observed_input_source`; the optional declaration and scope
|
|
203
|
+
are `rta.declared_input_source` and `rta.input_source_declaration_scope`. Missing
|
|
204
|
+
legacy attributes remain unknown. Use one handler owner per topic; a `useChat`
|
|
205
|
+
consumer should not register a duplicate raw handler on the same room.
|
|
206
|
+
|
|
207
|
+
This path needs no inference or platform changes. The consumer must already be
|
|
208
|
+
connected to the room, and text-stream messages are not durable webhook deliveries.
|
|
209
|
+
The legacy `lk-chat-topic` compatibility path omits attributes. Automatic RTA server
|
|
210
|
+
STT attribution and final transcript webhook provenance are separate work. Existing
|
|
211
|
+
webhook types and behavior are unchanged.
|
|
212
|
+
|
|
146
213
|
## API
|
|
147
214
|
|
|
148
215
|
Everything is on one class. The full types are in
|
|
@@ -359,3 +426,34 @@ for building your own queue UI, and the zod schemas `sessionBehaviorSchema` / `s
|
|
|
359
426
|
- The API is versioned at `/api/v1`; breaking changes get a new version, not a silent edit.
|
|
360
427
|
|
|
361
428
|
MIT licensed.
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
### Continuous participant recordings
|
|
432
|
+
|
|
433
|
+
Use `recording: "participants"` on your server to retain the two participants
|
|
434
|
+
separately. A camera-enabled call has four logical media tracks in two MP4 files:
|
|
435
|
+
user camera/microphone and character video/voice. Each file is continuous through
|
|
436
|
+
camera mute, unpublish and republish; the user's microphone continues while their
|
|
437
|
+
camera is off. `camera: true` is still a separate publication permission, and
|
|
438
|
+
recording alone never opens a camera. Voice-only participants get audio-only MP4s.
|
|
439
|
+
|
|
440
|
+
The returned `call.recordings` contains both pending artifacts, while legacy
|
|
441
|
+
modes retain `call.recording`. Once finalized, use `listRecordings({ sessionId })`
|
|
442
|
+
and `getRecordingAccess(recordingId)` to retrieve authorized, renewable URLs.
|
|
443
|
+
`recording.participant.role` identifies the user or character; media timestamps
|
|
444
|
+
align the files without fixing their visual layout. Keep failed/missing files
|
|
445
|
+
visible instead of treating the surviving participant as a complete recording.
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
import { RecordingPlayer } from "realtime-avatar/react";
|
|
449
|
+
|
|
450
|
+
// assets comes from your authenticated application endpoint.
|
|
451
|
+
// Each item is { recording, url }; refresh expiring URLs through your server.
|
|
452
|
+
<RecordingPlayer assets={assets} />
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
The player provides one play/pause control and one seek bar for both files. It
|
|
456
|
+
plays each file's audio once, preserves start offsets, waits for buffering and
|
|
457
|
+
refuses to guess synchronization when media timestamps are missing. Original
|
|
458
|
+
files remain independently playable and editable. Participant departure ends
|
|
459
|
+
that file; a new call is a new session, not an automatic concatenation.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RealtimeAvatar, isQueued, RealtimeAvatarHttpError } from './chunk-
|
|
1
|
+
import { RealtimeAvatar, isQueued, RealtimeAvatarHttpError } from './chunk-ZXPLFSG7.js';
|
|
2
2
|
|
|
3
3
|
// ../proxy/src/config.ts
|
|
4
4
|
var json = (body, status = 200) => new Response(JSON.stringify(body), {
|
|
@@ -234,15 +234,22 @@ var schema26 = z.strictObject({
|
|
|
234
234
|
var clipLibraryResponseSchema = schema24;
|
|
235
235
|
var clipLibraryUpdateSchema = schema26;
|
|
236
236
|
var RECORDED_MEDIA_MODES = ["audio", "video", "audio_video"];
|
|
237
|
-
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES]).describe("Server-owned recording policy; omitted means off.
|
|
237
|
+
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES, "participants"]).describe("Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices.");
|
|
238
238
|
var RECORDING_STATUSES = ["pending", "recording", "processing", "ready", "failed", "expired"];
|
|
239
239
|
z.enum(RECORDING_STATUSES);
|
|
240
|
+
var recordingParticipantSchema = z.object({
|
|
241
|
+
participantIdentity: z.string().min(1).max(160),
|
|
242
|
+
role: z.enum(["user", "avatar"])
|
|
243
|
+
}).strict();
|
|
240
244
|
var recordingMetadataSchema = z.object({
|
|
241
245
|
sessionId: z.string().min(1),
|
|
242
246
|
recordingId: z.string().min(1),
|
|
243
|
-
mode:
|
|
247
|
+
mode: z.enum(RECORDED_MEDIA_MODES),
|
|
244
248
|
createdAt: z.string().datetime({ offset: true }),
|
|
245
|
-
retainedUntil: z.string().datetime({ offset: true })
|
|
249
|
+
retainedUntil: z.string().datetime({ offset: true }),
|
|
250
|
+
participant: recordingParticipantSchema.optional(),
|
|
251
|
+
mediaStartedAt: z.string().datetime({ offset: true }).optional(),
|
|
252
|
+
mediaEndedAt: z.string().datetime({ offset: true }).optional()
|
|
246
253
|
});
|
|
247
254
|
var recordingArtifactSchema = z.discriminatedUnion("status", [
|
|
248
255
|
recordingMetadataSchema.extend({ status: z.enum(["pending", "recording", "processing", "expired"]) }).strict(),
|
|
@@ -548,6 +555,8 @@ z.object({
|
|
|
548
555
|
}).strict();
|
|
549
556
|
var liveKitSessionGrantSchema = z.object({
|
|
550
557
|
recording: recordingArtifactSchema.optional(),
|
|
558
|
+
recording_mode: recordingModeSchema.optional(),
|
|
559
|
+
recordings: z.array(recordingArtifactSchema).max(2).optional(),
|
|
551
560
|
connection_history: connectionHistoryGrantSchema.optional(),
|
|
552
561
|
status: z.literal("ready").default("ready"),
|
|
553
562
|
session_id: z.string().min(1),
|
|
@@ -645,7 +654,7 @@ z.enum([
|
|
|
645
654
|
|
|
646
655
|
// ../http-client/src/client.ts
|
|
647
656
|
var DEFAULT_BASE_URL = "https://realtimeavatar.ai/api/v1";
|
|
648
|
-
var SDK_VERSION = "0.
|
|
657
|
+
var SDK_VERSION = "0.24.0";
|
|
649
658
|
var RealtimeAvatar = class {
|
|
650
659
|
#apiKey;
|
|
651
660
|
#baseUrl;
|
|
@@ -718,6 +727,8 @@ var RealtimeAvatar = class {
|
|
|
718
727
|
return {
|
|
719
728
|
status: "ready",
|
|
720
729
|
...grant.recording === void 0 ? {} : { recording: grant.recording },
|
|
730
|
+
...grant.recording_mode === void 0 ? {} : { recordingMode: grant.recording_mode },
|
|
731
|
+
...grant.recordings === void 0 ? {} : { recordings: grant.recordings },
|
|
721
732
|
sessionId: grant.session_id,
|
|
722
733
|
roomName: grant.room_name,
|
|
723
734
|
livekitUrl: grant.livekit_url,
|
package/dist/express.d.ts
CHANGED
package/dist/express.js
CHANGED
package/dist/hono.d.ts
CHANGED
package/dist/hono.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as CallPolicy, C as CallMode, S as StartCallResult, E as EndCallOptions, A as Avatar, b as AvatarUpdate, c as AvatarSourceSwap, d as ClipLibraryDeclaration, e as ClipLibraryUpdate, L as LoopRedirect, f as ClipLibrary, g as AssetKind, h as Asset, i as ListSessionsOptions, U as UsageSessionPage, j as UsageSession, k as ListRecordingsQuery, l as ListRecordingsResponse, R as RecordingArtifact, m as RecordingAccessResponse, n as CreditBalance, T as TranscriptPayload } from './types-
|
|
2
|
-
export { o as AvatarClip, p as CallConnection, q as CallQueued, r as ClipDeclaration, s as ClipLibraryPlan, t as ClipSource, u as ContextMessage, v as EndCallReason, w as RecordingArtifactStatus, x as RecordingMode, V as VideoPolicy, y as isQueued, z as listRecordingsResponseSchema, B as recordingAccessResponseSchema, D as recordingArtifactSchema, F as recordingModeSchema } from './types-
|
|
1
|
+
import { a as CallPolicy, C as CallMode, S as StartCallResult, E as EndCallOptions, A as Avatar, b as AvatarUpdate, c as AvatarSourceSwap, d as ClipLibraryDeclaration, e as ClipLibraryUpdate, L as LoopRedirect, f as ClipLibrary, g as AssetKind, h as Asset, i as ListSessionsOptions, U as UsageSessionPage, j as UsageSession, k as ListRecordingsQuery, l as ListRecordingsResponse, R as RecordingArtifact, m as RecordingAccessResponse, n as CreditBalance, T as TranscriptPayload } from './types-D77jgSms.js';
|
|
2
|
+
export { o as AvatarClip, p as CallConnection, q as CallQueued, r as ClipDeclaration, s as ClipLibraryPlan, t as ClipSource, u as ContextMessage, v as EndCallReason, w as RecordingArtifactStatus, x as RecordingMode, V as VideoPolicy, y as isQueued, z as listRecordingsResponseSchema, B as recordingAccessResponseSchema, D as recordingArtifactSchema, F as recordingModeSchema } from './types-D77jgSms.js';
|
|
3
3
|
import { ConnectionHistoryResponse } from './connection-history.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, listRecordingsResponseSchema, recordingAccessResponseSchema, recordingArtifactSchema, recordingModeSchema, verifyTranscript } from './chunk-
|
|
1
|
+
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, listRecordingsResponseSchema, recordingAccessResponseSchema, recordingArtifactSchema, recordingModeSchema, verifyTranscript } from './chunk-ZXPLFSG7.js';
|
|
2
2
|
import './chunk-MCIXU6XP.js';
|
package/dist/nextjs.d.ts
CHANGED
package/dist/nextjs.js
CHANGED
|
@@ -135,8 +135,8 @@ declare const liveKitSessionRequestSchema: z.ZodObject<{
|
|
|
135
135
|
instructions: z.ZodOptional<z.ZodString>;
|
|
136
136
|
initialContext: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
137
137
|
role: z.ZodEnum<{
|
|
138
|
-
system: "system";
|
|
139
138
|
user: "user";
|
|
139
|
+
system: "system";
|
|
140
140
|
assistant: "assistant";
|
|
141
141
|
}>;
|
|
142
142
|
content: z.ZodString;
|
|
@@ -253,6 +253,15 @@ declare const liveKitSessionGrantSchema: z.ZodObject<{
|
|
|
253
253
|
}>;
|
|
254
254
|
createdAt: z.ZodString;
|
|
255
255
|
retainedUntil: z.ZodString;
|
|
256
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
257
|
+
participantIdentity: z.ZodString;
|
|
258
|
+
role: z.ZodEnum<{
|
|
259
|
+
user: "user";
|
|
260
|
+
avatar: "avatar";
|
|
261
|
+
}>;
|
|
262
|
+
}, z.core.$strict>>;
|
|
263
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
264
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
256
265
|
status: z.ZodEnum<{
|
|
257
266
|
pending: "pending";
|
|
258
267
|
recording: "recording";
|
|
@@ -269,6 +278,15 @@ declare const liveKitSessionGrantSchema: z.ZodObject<{
|
|
|
269
278
|
}>;
|
|
270
279
|
createdAt: z.ZodString;
|
|
271
280
|
retainedUntil: z.ZodString;
|
|
281
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
282
|
+
participantIdentity: z.ZodString;
|
|
283
|
+
role: z.ZodEnum<{
|
|
284
|
+
user: "user";
|
|
285
|
+
avatar: "avatar";
|
|
286
|
+
}>;
|
|
287
|
+
}, z.core.$strict>>;
|
|
288
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
289
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
272
290
|
status: z.ZodLiteral<"ready">;
|
|
273
291
|
mediaType: z.ZodEnum<{
|
|
274
292
|
"audio/mp4": "audio/mp4";
|
|
@@ -286,12 +304,104 @@ declare const liveKitSessionGrantSchema: z.ZodObject<{
|
|
|
286
304
|
}>;
|
|
287
305
|
createdAt: z.ZodString;
|
|
288
306
|
retainedUntil: z.ZodString;
|
|
307
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
308
|
+
participantIdentity: z.ZodString;
|
|
309
|
+
role: z.ZodEnum<{
|
|
310
|
+
user: "user";
|
|
311
|
+
avatar: "avatar";
|
|
312
|
+
}>;
|
|
313
|
+
}, z.core.$strict>>;
|
|
314
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
315
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
289
316
|
status: z.ZodLiteral<"failed">;
|
|
290
317
|
errorCode: z.ZodEnum<{
|
|
291
318
|
recording_failed: "recording_failed";
|
|
292
319
|
recording_unavailable: "recording_unavailable";
|
|
293
320
|
}>;
|
|
294
321
|
}, z.core.$strict>], "status">>;
|
|
322
|
+
recording_mode: z.ZodOptional<z.ZodEnum<{
|
|
323
|
+
audio: "audio";
|
|
324
|
+
video: "video";
|
|
325
|
+
audio_video: "audio_video";
|
|
326
|
+
off: "off";
|
|
327
|
+
participants: "participants";
|
|
328
|
+
}>>;
|
|
329
|
+
recordings: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
330
|
+
sessionId: z.ZodString;
|
|
331
|
+
recordingId: z.ZodString;
|
|
332
|
+
mode: z.ZodEnum<{
|
|
333
|
+
audio: "audio";
|
|
334
|
+
video: "video";
|
|
335
|
+
audio_video: "audio_video";
|
|
336
|
+
}>;
|
|
337
|
+
createdAt: z.ZodString;
|
|
338
|
+
retainedUntil: z.ZodString;
|
|
339
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
340
|
+
participantIdentity: z.ZodString;
|
|
341
|
+
role: z.ZodEnum<{
|
|
342
|
+
user: "user";
|
|
343
|
+
avatar: "avatar";
|
|
344
|
+
}>;
|
|
345
|
+
}, z.core.$strict>>;
|
|
346
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
347
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
348
|
+
status: z.ZodEnum<{
|
|
349
|
+
pending: "pending";
|
|
350
|
+
recording: "recording";
|
|
351
|
+
processing: "processing";
|
|
352
|
+
expired: "expired";
|
|
353
|
+
}>;
|
|
354
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
355
|
+
sessionId: z.ZodString;
|
|
356
|
+
recordingId: z.ZodString;
|
|
357
|
+
mode: z.ZodEnum<{
|
|
358
|
+
audio: "audio";
|
|
359
|
+
video: "video";
|
|
360
|
+
audio_video: "audio_video";
|
|
361
|
+
}>;
|
|
362
|
+
createdAt: z.ZodString;
|
|
363
|
+
retainedUntil: z.ZodString;
|
|
364
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
365
|
+
participantIdentity: z.ZodString;
|
|
366
|
+
role: z.ZodEnum<{
|
|
367
|
+
user: "user";
|
|
368
|
+
avatar: "avatar";
|
|
369
|
+
}>;
|
|
370
|
+
}, z.core.$strict>>;
|
|
371
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
372
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
373
|
+
status: z.ZodLiteral<"ready">;
|
|
374
|
+
mediaType: z.ZodEnum<{
|
|
375
|
+
"audio/mp4": "audio/mp4";
|
|
376
|
+
"video/mp4": "video/mp4";
|
|
377
|
+
}>;
|
|
378
|
+
sizeBytes: z.ZodNumber;
|
|
379
|
+
durationMs: z.ZodNullable<z.ZodNumber>;
|
|
380
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
381
|
+
sessionId: z.ZodString;
|
|
382
|
+
recordingId: z.ZodString;
|
|
383
|
+
mode: z.ZodEnum<{
|
|
384
|
+
audio: "audio";
|
|
385
|
+
video: "video";
|
|
386
|
+
audio_video: "audio_video";
|
|
387
|
+
}>;
|
|
388
|
+
createdAt: z.ZodString;
|
|
389
|
+
retainedUntil: z.ZodString;
|
|
390
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
391
|
+
participantIdentity: z.ZodString;
|
|
392
|
+
role: z.ZodEnum<{
|
|
393
|
+
user: "user";
|
|
394
|
+
avatar: "avatar";
|
|
395
|
+
}>;
|
|
396
|
+
}, z.core.$strict>>;
|
|
397
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
398
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
399
|
+
status: z.ZodLiteral<"failed">;
|
|
400
|
+
errorCode: z.ZodEnum<{
|
|
401
|
+
recording_failed: "recording_failed";
|
|
402
|
+
recording_unavailable: "recording_unavailable";
|
|
403
|
+
}>;
|
|
404
|
+
}, z.core.$strict>], "status">>>;
|
|
295
405
|
connection_history: z.ZodOptional<z.ZodObject<{
|
|
296
406
|
endpoint: z.ZodString;
|
|
297
407
|
token: z.ZodString;
|
|
@@ -1468,6 +1578,9 @@ type TurnState = "listening" | "thinking" | "speaking" | "quiet";
|
|
|
1468
1578
|
*/
|
|
1469
1579
|
declare function mapTurnState(assistantState: string | null | undefined): TurnState;
|
|
1470
1580
|
|
|
1581
|
+
/** Source an application declares for text sent to an in-room consumer. */
|
|
1582
|
+
type DeclaredInputSource = "text" | "client_stt";
|
|
1583
|
+
|
|
1471
1584
|
/** How early `onApproachingEnd` fires before the hard cap (room to compose the goodbye). */
|
|
1472
1585
|
declare const DEFAULT_APPROACHING_END_LEAD_SECONDS = 45;
|
|
1473
1586
|
/** How early the grace window opens before the cap (fits LLM excuse + send RTT + TTS + playout). */
|
|
@@ -1486,6 +1599,17 @@ type ClosingTurnResult = {
|
|
|
1486
1599
|
type ExtendResult = {
|
|
1487
1600
|
ok: boolean;
|
|
1488
1601
|
};
|
|
1602
|
+
type SendTurnOptions = {
|
|
1603
|
+
instructions?: string;
|
|
1604
|
+
/** Optional declaration; the SDK still observes a text transport. */
|
|
1605
|
+
inputSource?: DeclaredInputSource;
|
|
1606
|
+
};
|
|
1607
|
+
type TranscriptSenderOptions = {
|
|
1608
|
+
/** Captured once for this sender. Defaults to client_stt. */
|
|
1609
|
+
inputSource?: DeclaredInputSource;
|
|
1610
|
+
};
|
|
1611
|
+
/** Send an already recognized transcript. This adapter does not capture or recognize audio. */
|
|
1612
|
+
type TranscriptSender = (text: string, opts?: SendTurnOptions) => Promise<void>;
|
|
1489
1613
|
type ApproachingEndEvent = {
|
|
1490
1614
|
secondsLeft: number;
|
|
1491
1615
|
reason: ApproachingEndReason;
|
|
@@ -1619,10 +1743,10 @@ type RealtimeSessionApi = SessionLifecycleApi & {
|
|
|
1619
1743
|
proof?: string;
|
|
1620
1744
|
}) => ExtendResult;
|
|
1621
1745
|
/** Send a normal turn THROUGH the SDK (arms the turn-timeout watchdog + enables retryTurn). */
|
|
1622
|
-
sendTurn: (text: string, opts?:
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
/** Re-send the last turn
|
|
1746
|
+
sendTurn: (text: string, opts?: SendTurnOptions) => Promise<void>;
|
|
1747
|
+
/** Bind a transcript source once; a send's explicit inputSource takes precedence. */
|
|
1748
|
+
createTranscriptSender: (opts?: TranscriptSenderOptions) => TranscriptSender;
|
|
1749
|
+
/** Re-send the last turn with its resolved provenance, a new ID, and retry_of_turn_id. */
|
|
1626
1750
|
retryTurn: () => void;
|
|
1627
1751
|
/** End gracefully now (the user tapped End). */
|
|
1628
1752
|
end: (reason?: EndReason) => void;
|
|
@@ -1744,4 +1868,4 @@ interface ProxyClientOptions {
|
|
|
1744
1868
|
}
|
|
1745
1869
|
declare function createProxyClient(options: ProxyClientOptions): AvatarSessionClient;
|
|
1746
1870
|
|
|
1747
|
-
export { type
|
|
1871
|
+
export { type ProxyClientOptions as $, type AvatarVideoFit as A, type BehaviorSnapshot as B, type CallTranscript as C, DEFAULT_APPROACHING_END_LEAD_SECONDS as D, type EndReason as E, type FishTtsModel as F, type Governor as G, type GovernorSignal as H, type GovernorState as I, type GraceWindowClosedEvent as J, type GraceWindowOpenEvent as K, type LiveKitSessionGrant as L, type GraceWindowState as M, type IdleWarningEvent as N, type InboundRtpCursor as O, type InboundRtpReading as P, type KnownBehaviorState as Q, type LLMProvider as R, type LLMSelection as S, type LiveKitAvatarGrantState as T, type LiveKitAvatarGrantStatus as U, type LiveKitCapacityState as V, type LiveKitConnectionStatus as W, type LiveKitSessionRequest as X, type LiveKitSessionStartResult as Y, MAX_RECONNECT_ATTEMPTS as Z, MAX_SESSION_INSTRUCTIONS_CHARS as _, AdaptivePlayoutController as a, shouldReplayPendingTurn as a$, type QualityCap as a0, RECONNECT_BACKOFF_MS as a1, type RealtimeAvatarRequestOptions as a2, type RealtimeSessionApi as a3, type RealtimeSessionMedia as a4, type RealtimeSessionRoomSinks as a5, type ReconnectPolicy as a6, type ReconnectingEvent as a7, type RecoveryState as a8, type RetryStep as a9, mapTurnState as aA, readInboundRtp as aB, sessionBehaviorSchema as aC, sessionClipSchema as aD, splitCallTranscript as aE, useAvatarAdaptivePlayoutDelay as aF, useAvatarCamera as aG, useAvatarPlayoutDelay as aH, useAvatarQualityGovernor as aI, useCallTranscript as aJ, useLiveKitAvatarGrant as aK, useLiveTrackProducing as aL, useMicLease as aM, useRealtimeSession as aN, useReleaseMicLeaseOnTrackEnded as aO, useSessionLifecycle as aP, AvatarVideoSurface as aQ, type AvatarVideoSurfaceProps as aR, type LivePlaybackKeeper as aS, MIC_LEASE_ENDED_TIMEOUT_MS as aT, type MicLease as aU, NETWORK_QUALITY_POLICY as aV, type NetworkQualityStatus as aW, type PlayableVideoElement as aX, RealtimeAvatarCapacityError as aY, RealtimeAvatarLiveKitRoom as aZ, type RealtimeAvatarLiveKitRoomProps as a_, type SendTurnOptions as aa, type SessionBehavior as ab, type SessionClip as ac, type SessionClocks as ad, type SessionEndReason as ae, type SessionLifecycleApi as af, type SessionLifecyclePhase as ag, type SessionLifecyclePhaseKind as ah, SessionLifecycleRoomBridge as ai, type SessionLifecycleRoomBridgeProps as aj, type SurfaceLayers as ak, type TranscriptSender as al, type TranscriptSenderOptions as am, type TurnState as an, type TurnTimeoutEvent as ao, type UseAvatarQualityGovernorInput as ap, type UseLiveKitAvatarGrantInput as aq, type UseRealtimeSessionInput as ar, type UseSessionLifecycleInput as as, type VoiceSpec as at, type VoiceSpecInput as au, capacityErrorFromBusy as av, capacityStateFromGrant as aw, createProxyClient as ax, isNativeLiveTrackSubscribed as ay, knownBehaviorStates as az, type AdaptivePlayoutDecision as b, type AdaptivePlayoutOptions as c, type AdaptivePlayoutSample as d, type ApproachingEndEvent as e, type ApproachingEndReason as f, type AvatarConnectionDetails as g, type AvatarSessionClient as h, type CallTranscriptSegment as i, type CartesiaTtsModel as j, type ClipResult as k, type ClosingTurnResult as l, type CreditsLowEvent as m, DEFAULT_CREDITS_LOW_LEAD_SECONDS as n, DEFAULT_GOVERNOR_CONFIG as o, DEFAULT_GRACE_CEILING_SECONDS as p, DEFAULT_GRACE_WINDOW_LEAD_SECONDS as q, DEFAULT_IDLE_SECONDS as r, DEFAULT_IDLE_WARN_LEAD_SECONDS as s, DEFAULT_TURN_TIMEOUT_SECONDS as t, type DeclaredInputSource as u, type EndedEvent as v, type ExtendResult as w, type FreezeReadingFn as x, type GovernorAction as y, type GovernorConfig as z };
|
package/dist/react-native.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LiveKitRoomProps } from '@livekit/react-native';
|
|
2
2
|
export { AudioSession, VideoTrack, VideoTrackProps, registerGlobals } from '@livekit/react-native';
|
|
3
|
-
import { L as LiveKitSessionGrant, A as AvatarVideoFit } from './proxy-client-
|
|
4
|
-
export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, g as AvatarConnectionDetails, h as AvatarSessionClient, B as BehaviorSnapshot, C as CallTranscript, i as CallTranscriptSegment, j as CartesiaTtsModel, k as ClipResult, l as ClosingTurnResult, m as CreditsLowEvent, D as DEFAULT_APPROACHING_END_LEAD_SECONDS, n as DEFAULT_CREDITS_LOW_LEAD_SECONDS, o as DEFAULT_GOVERNOR_CONFIG, p as DEFAULT_GRACE_CEILING_SECONDS, q as DEFAULT_GRACE_WINDOW_LEAD_SECONDS, r as DEFAULT_IDLE_SECONDS, s as DEFAULT_IDLE_WARN_LEAD_SECONDS, t as DEFAULT_TURN_TIMEOUT_SECONDS, E as EndReason,
|
|
3
|
+
import { L as LiveKitSessionGrant, A as AvatarVideoFit } from './proxy-client-DlFXaXtn.js';
|
|
4
|
+
export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, g as AvatarConnectionDetails, h as AvatarSessionClient, B as BehaviorSnapshot, C as CallTranscript, i as CallTranscriptSegment, j as CartesiaTtsModel, k as ClipResult, l as ClosingTurnResult, m as CreditsLowEvent, D as DEFAULT_APPROACHING_END_LEAD_SECONDS, n as DEFAULT_CREDITS_LOW_LEAD_SECONDS, o as DEFAULT_GOVERNOR_CONFIG, p as DEFAULT_GRACE_CEILING_SECONDS, q as DEFAULT_GRACE_WINDOW_LEAD_SECONDS, r as DEFAULT_IDLE_SECONDS, s as DEFAULT_IDLE_WARN_LEAD_SECONDS, t as DEFAULT_TURN_TIMEOUT_SECONDS, u as DeclaredInputSource, E as EndReason, v as EndedEvent, w as ExtendResult, F as FishTtsModel, x as FreezeReadingFn, G as Governor, y as GovernorAction, z as GovernorConfig, H as GovernorSignal, I as GovernorState, J as GraceWindowClosedEvent, K as GraceWindowOpenEvent, M as GraceWindowState, N as IdleWarningEvent, O as InboundRtpCursor, P as InboundRtpReading, Q as KnownBehaviorState, R as LLMProvider, S as LLMSelection, T as LiveKitAvatarGrantState, U as LiveKitAvatarGrantStatus, V as LiveKitCapacityState, W as LiveKitConnectionStatus, X as LiveKitSessionRequest, Y as LiveKitSessionStartResult, Z as MAX_RECONNECT_ATTEMPTS, _ as MAX_SESSION_INSTRUCTIONS_CHARS, $ as ProxyClientOptions, a0 as QualityCap, a1 as RECONNECT_BACKOFF_MS, a2 as RealtimeAvatarRequestOptions, a3 as RealtimeSessionApi, a4 as RealtimeSessionMedia, a5 as RealtimeSessionRoomSinks, a6 as ReconnectPolicy, a7 as ReconnectingEvent, a8 as RecoveryState, a9 as RetryStep, aa as SendTurnOptions, ab as SessionBehavior, ac as SessionClip, ad as SessionClocks, ae as SessionEndReason, af as SessionLifecycleApi, ag as SessionLifecyclePhase, ah as SessionLifecyclePhaseKind, ai as SessionLifecycleRoomBridge, aj as SessionLifecycleRoomBridgeProps, ak as SurfaceLayers, al as TranscriptSender, am as TranscriptSenderOptions, an as TurnState, ao as TurnTimeoutEvent, ap as UseAvatarQualityGovernorInput, aq as UseLiveKitAvatarGrantInput, ar as UseRealtimeSessionInput, as as UseSessionLifecycleInput, at as VoiceSpec, au as VoiceSpecInput, av as capacityErrorFromBusy, aw as capacityStateFromGrant, ax as createProxyClient, ay as isNativeLiveTrackSubscribed, az as knownBehaviorStates, aA as mapTurnState, aB as readInboundRtp, aC as sessionBehaviorSchema, aD as sessionClipSchema, aE as splitCallTranscript, aF as useAvatarAdaptivePlayoutDelay, aG as useAvatarCamera, aH as useAvatarPlayoutDelay, aI as useAvatarQualityGovernor, aJ as useCallTranscript, aK as useLiveKitAvatarGrant, aL as useLiveTrackProducing, aM as useMicLease, aN as useRealtimeSession, aO as useReleaseMicLeaseOnTrackEnded, aP as useSessionLifecycle } from './proxy-client-DlFXaXtn.js';
|
|
5
5
|
import { ReactNode, ReactElement } from 'react';
|
|
6
6
|
import { StyleProp, ViewStyle } from 'react-native';
|
|
7
7
|
export { useChat, useConnectionState, useLocalParticipant, useRoomContext, useTrackToggle, useTranscriptions, useVoiceAssistant } from '@livekit/components-react';
|
package/dist/react-native.js
CHANGED
|
@@ -1585,15 +1585,22 @@ var styles = StyleSheet.create({
|
|
|
1585
1585
|
}
|
|
1586
1586
|
});
|
|
1587
1587
|
var RECORDED_MEDIA_MODES = ["audio", "video", "audio_video"];
|
|
1588
|
-
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES]).describe("Server-owned recording policy; omitted means off.
|
|
1588
|
+
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES, "participants"]).describe("Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices.");
|
|
1589
1589
|
var RECORDING_STATUSES = ["pending", "recording", "processing", "ready", "failed", "expired"];
|
|
1590
1590
|
z.enum(RECORDING_STATUSES);
|
|
1591
|
+
var recordingParticipantSchema = z.object({
|
|
1592
|
+
participantIdentity: z.string().min(1).max(160),
|
|
1593
|
+
role: z.enum(["user", "avatar"])
|
|
1594
|
+
}).strict();
|
|
1591
1595
|
var recordingMetadataSchema = z.object({
|
|
1592
1596
|
sessionId: z.string().min(1),
|
|
1593
1597
|
recordingId: z.string().min(1),
|
|
1594
|
-
mode:
|
|
1598
|
+
mode: z.enum(RECORDED_MEDIA_MODES),
|
|
1595
1599
|
createdAt: z.string().datetime({ offset: true }),
|
|
1596
|
-
retainedUntil: z.string().datetime({ offset: true })
|
|
1600
|
+
retainedUntil: z.string().datetime({ offset: true }),
|
|
1601
|
+
participant: recordingParticipantSchema.optional(),
|
|
1602
|
+
mediaStartedAt: z.string().datetime({ offset: true }).optional(),
|
|
1603
|
+
mediaEndedAt: z.string().datetime({ offset: true }).optional()
|
|
1597
1604
|
});
|
|
1598
1605
|
var recordingArtifactSchema = z.discriminatedUnion("status", [
|
|
1599
1606
|
recordingMetadataSchema.extend({ status: z.enum(["pending", "recording", "processing", "expired"]) }).strict(),
|
|
@@ -1900,6 +1907,8 @@ z.object({
|
|
|
1900
1907
|
}).strict();
|
|
1901
1908
|
z.object({
|
|
1902
1909
|
recording: recordingArtifactSchema.optional(),
|
|
1910
|
+
recording_mode: recordingModeSchema.optional(),
|
|
1911
|
+
recordings: z.array(recordingArtifactSchema).max(2).optional(),
|
|
1903
1912
|
connection_history: connectionHistoryGrantSchema.optional(),
|
|
1904
1913
|
status: z.literal("ready").default("ready"),
|
|
1905
1914
|
session_id: z.string().min(1),
|
|
@@ -1920,6 +1929,11 @@ var RTA_LIFECYCLE_TOPIC = "rta.lifecycle";
|
|
|
1920
1929
|
var RTA_TURN_INSTRUCTIONS_ATTR = "rta.turn_instructions";
|
|
1921
1930
|
var RTA_CLOSING_TURN_ATTR = "rta.closing_turn";
|
|
1922
1931
|
var RTA_TURN_ID_ATTR = "rta.turn_id";
|
|
1932
|
+
var RTA_RETRY_OF_TURN_ID_ATTR = "rta.retry_of_turn_id";
|
|
1933
|
+
var RTA_INPUT_SOURCE_VERSION_ATTR = "rta.input_source_version";
|
|
1934
|
+
var RTA_OBSERVED_INPUT_SOURCE_ATTR = "rta.observed_input_source";
|
|
1935
|
+
var RTA_DECLARED_INPUT_SOURCE_ATTR = "rta.declared_input_source";
|
|
1936
|
+
var RTA_INPUT_SOURCE_DECLARATION_SCOPE_ATTR = "rta.input_source_declaration_scope";
|
|
1923
1937
|
var sessionEndReasonSchema = z.enum([
|
|
1924
1938
|
"user_ended",
|
|
1925
1939
|
"session_cap",
|
|
@@ -2855,6 +2869,11 @@ var DEFAULT_CREDITS_LOW_LEAD_SECONDS = 300;
|
|
|
2855
2869
|
function positive(value, fallbackSeconds) {
|
|
2856
2870
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallbackSeconds;
|
|
2857
2871
|
}
|
|
2872
|
+
function validateInputSource(value) {
|
|
2873
|
+
if (value !== void 0 && value !== "text" && value !== "client_stt") {
|
|
2874
|
+
throw new TypeError('inputSource must be "text" or "client_stt"');
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2858
2877
|
function useRealtimeSession(input) {
|
|
2859
2878
|
const {
|
|
2860
2879
|
session,
|
|
@@ -2912,7 +2931,8 @@ function useRealtimeSession(input) {
|
|
|
2912
2931
|
const turnSenderRef = useRef(null);
|
|
2913
2932
|
const dataPublisherRef = useRef(null);
|
|
2914
2933
|
const lastTurnRef = useRef(null);
|
|
2915
|
-
const
|
|
2934
|
+
const turnSequenceRef = useRef(0);
|
|
2935
|
+
const [, setClockTick] = useState(0);
|
|
2916
2936
|
const endsAt = endsAtFrom({
|
|
2917
2937
|
serverStartedAtUnixMs: serverClock?.startedAtUnixMs ?? null,
|
|
2918
2938
|
maxSessionSeconds: serverClock?.maxSessionSeconds ?? null
|
|
@@ -2934,8 +2954,8 @@ function useRealtimeSession(input) {
|
|
|
2934
2954
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
2935
2955
|
} catch {
|
|
2936
2956
|
}
|
|
2937
|
-
return `t-${Date.now()}-${
|
|
2938
|
-
}, [
|
|
2957
|
+
return `t-${Date.now()}-${++turnSequenceRef.current}`;
|
|
2958
|
+
}, []);
|
|
2939
2959
|
const onLifecycleData = useCallback((frame) => {
|
|
2940
2960
|
const parsed = lifecycleServerFrameSchema.safeParse(frame);
|
|
2941
2961
|
if (!parsed.success) return;
|
|
@@ -3035,8 +3055,8 @@ function useRealtimeSession(input) {
|
|
|
3035
3055
|
if (gw === "open" || gw === "delivering") stayConnected();
|
|
3036
3056
|
}
|
|
3037
3057
|
const turnInfo = lastTurnRef.current;
|
|
3038
|
-
if (turnInfo && now - turnInfo.sentAt >= turnTimeoutMs) {
|
|
3039
|
-
|
|
3058
|
+
if (turnInfo && turnInfo.sentAt !== null && now - turnInfo.sentAt >= turnTimeoutMs) {
|
|
3059
|
+
turnInfo.sentAt = null;
|
|
3040
3060
|
cbRef.current.onTurnTimeout?.({ turnId: turnInfo.id });
|
|
3041
3061
|
}
|
|
3042
3062
|
setClockTick((value) => value + 1);
|
|
@@ -3065,6 +3085,7 @@ function useRealtimeSession(input) {
|
|
|
3065
3085
|
}, [phaseKind, lifecycle.phase, lifecycle.attempt]);
|
|
3066
3086
|
useEffect(() => {
|
|
3067
3087
|
if (phaseKind === "ended") {
|
|
3088
|
+
lastTurnRef.current = null;
|
|
3068
3089
|
if (!endedFiredRef.current) {
|
|
3069
3090
|
endedFiredRef.current = true;
|
|
3070
3091
|
const inner2 = lifecycle.phase.kind === "ended" ? lifecycle.phase.reason : void 0;
|
|
@@ -3101,23 +3122,47 @@ function useRealtimeSession(input) {
|
|
|
3101
3122
|
setGraceWindow({ kind: "closed" });
|
|
3102
3123
|
return { ok: true };
|
|
3103
3124
|
}, []);
|
|
3104
|
-
const
|
|
3125
|
+
const sendResolvedTurn = useCallback(async (text, attributes, retryOfTurnId) => {
|
|
3105
3126
|
const trimmed = text.trim();
|
|
3106
3127
|
const sender = turnSenderRef.current;
|
|
3107
3128
|
if (!sender || !trimmed) return;
|
|
3108
3129
|
const turnId = newTurnId();
|
|
3109
|
-
|
|
3130
|
+
const outgoing = { ...attributes, [RTA_TURN_ID_ATTR]: turnId };
|
|
3131
|
+
if (retryOfTurnId) outgoing[RTA_RETRY_OF_TURN_ID_ATTR] = retryOfTurnId;
|
|
3132
|
+
lastTurnRef.current = { text: trimmed, attributes: { ...outgoing }, id: turnId, sentAt: Date.now() };
|
|
3110
3133
|
lifecycle.markActivity();
|
|
3111
|
-
|
|
3112
|
-
await sender(trimmed, attributes ? { attributes } : void 0);
|
|
3134
|
+
await sender(trimmed, { attributes: outgoing });
|
|
3113
3135
|
}, [lifecycle, newTurnId]);
|
|
3136
|
+
const sendInput = useCallback(async (text, opts, adapterSource) => {
|
|
3137
|
+
const turnSource = opts?.inputSource;
|
|
3138
|
+
validateInputSource(turnSource);
|
|
3139
|
+
const declaredSource = turnSource ?? adapterSource;
|
|
3140
|
+
const attributes = {
|
|
3141
|
+
[RTA_INPUT_SOURCE_VERSION_ATTR]: "1",
|
|
3142
|
+
[RTA_OBSERVED_INPUT_SOURCE_ATTR]: "text"
|
|
3143
|
+
};
|
|
3144
|
+
if (declaredSource !== void 0) {
|
|
3145
|
+
attributes[RTA_DECLARED_INPUT_SOURCE_ATTR] = declaredSource;
|
|
3146
|
+
attributes[RTA_INPUT_SOURCE_DECLARATION_SCOPE_ATTR] = turnSource !== void 0 ? "turn" : "adapter";
|
|
3147
|
+
}
|
|
3148
|
+
if (opts?.instructions) attributes[RTA_TURN_INSTRUCTIONS_ATTR] = opts.instructions;
|
|
3149
|
+
await sendResolvedTurn(text, attributes);
|
|
3150
|
+
}, [sendResolvedTurn]);
|
|
3151
|
+
const sendTurn = useCallback((text, opts) => sendInput(text, opts), [sendInput]);
|
|
3152
|
+
const createTranscriptSender = useCallback((opts) => {
|
|
3153
|
+
const source = opts?.inputSource;
|
|
3154
|
+
validateInputSource(source);
|
|
3155
|
+
const boundSource = source ?? "client_stt";
|
|
3156
|
+
return (text, turnOpts) => sendInput(text, turnOpts, boundSource);
|
|
3157
|
+
}, [sendInput]);
|
|
3114
3158
|
const retryTurn = useCallback(() => {
|
|
3115
3159
|
const last = lastTurnRef.current;
|
|
3116
3160
|
if (!last) return;
|
|
3117
|
-
void
|
|
3118
|
-
}, [
|
|
3161
|
+
void sendResolvedTurn(last.text, last.attributes, last.id).catch(() => void 0);
|
|
3162
|
+
}, [sendResolvedTurn]);
|
|
3119
3163
|
const end = useCallback((reason) => {
|
|
3120
3164
|
if (reason) lastLabeledEndReasonRef.current = reason;
|
|
3165
|
+
lastTurnRef.current = null;
|
|
3121
3166
|
requestGracefulClose();
|
|
3122
3167
|
lifecycle.reset();
|
|
3123
3168
|
}, [lifecycle, requestGracefulClose]);
|
|
@@ -3184,6 +3229,7 @@ function useRealtimeSession(input) {
|
|
|
3184
3229
|
requestGracefulClose,
|
|
3185
3230
|
extend,
|
|
3186
3231
|
sendTurn,
|
|
3232
|
+
createTranscriptSender,
|
|
3187
3233
|
retryTurn,
|
|
3188
3234
|
end,
|
|
3189
3235
|
behavior,
|
|
@@ -3206,6 +3252,7 @@ function useRealtimeSession(input) {
|
|
|
3206
3252
|
requestGracefulClose,
|
|
3207
3253
|
extend,
|
|
3208
3254
|
sendTurn,
|
|
3255
|
+
createTranscriptSender,
|
|
3209
3256
|
retryTurn,
|
|
3210
3257
|
end,
|
|
3211
3258
|
behavior,
|