@streamoji/aitwin 0.7.4 → 0.7.6

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/dist/index.d.ts CHANGED
@@ -15,6 +15,26 @@ export declare type AiTwinCaptionsOptions = {
15
15
  color?: string;
16
16
  };
17
17
 
18
+ export declare type AiTwinGestureCatalog = {
19
+ success: boolean;
20
+ fullBody: boolean;
21
+ kind?: string;
22
+ poses: string[];
23
+ poseDetails?: Array<{
24
+ id: string;
25
+ label: string;
26
+ description?: string;
27
+ keywords?: string[];
28
+ category?: string;
29
+ speechMapped?: boolean;
30
+ cdnPath?: string;
31
+ }>;
32
+ encrypted: boolean;
33
+ pathTemplate: string;
34
+ cropMetaPath: string;
35
+ notes?: string;
36
+ };
37
+
18
38
  export declare type AiTwinHandle = {
19
39
  speakText: (text: string, options?: AvatarTtsSpeakOptions) => Promise<void>;
20
40
  /**
@@ -40,6 +60,8 @@ export declare type AiTwinHandle = {
40
60
  clearEmotionPreview: () => void;
41
61
  isReady: () => boolean;
42
62
  getStatus: () => AvatarTtsLipsyncStatus;
63
+ /** Current utterance word queue (includes `gesture` when fullBody TTS mapped poses). */
64
+ getWordQueue: () => WordQueueItem[];
43
65
  /** Connect mic + WebSocket voice session over `/ws/voice`. */
44
66
  connect: (options?: VoiceConnectOptions) => Promise<void>;
45
67
  /** Disconnect voice session. */
@@ -146,6 +168,18 @@ export declare type AiTwinProps = {
146
168
  * Default: 500.
147
169
  */
148
170
  idleHandoffHoldMs?: number;
171
+ /**
172
+ * When true, skip loading/playing the cloud head idle MP4 (still sil only
173
+ * between speech). Demo pages can overlay a custom full-body idle instead.
174
+ * Default: false.
175
+ */
176
+ disableIdleVideo?: boolean;
177
+ /**
178
+ * Full-body (waist-up) twin: disable head idle and overlay encrypted CDN
179
+ * body idle + gesture videos under `custom-faces/{faceId}/ges/` as `G_00N.bin`.
180
+ * Create with `createAiTwinFace({ fullBody: true, … })`.
181
+ */
182
+ fullBody?: boolean;
149
183
  /**
150
184
  * Pixi only: cap WebGL MAX_TEXTURE_SIZE (e.g. 4096) to preview mobile-GPU
151
185
  * atlas handling. Omit to use the device limit.
@@ -153,6 +187,16 @@ export declare type AiTwinProps = {
153
187
  pixiMaxTextureSize?: number;
154
188
  /** Plain subtitles during TTS/voice playback. */
155
189
  captions?: boolean | AiTwinCaptionsOptions;
190
+ /** Logged-in visitor display name for conversation history / billing attribution. */
191
+ userName?: string;
192
+ /** Logged-in visitor email for conversation history. */
193
+ userEmail?: string;
194
+ /**
195
+ * Visitor note for the twin (what they want it to know).
196
+ * Passed through to speakWithReply / connect as `userContext`; backend
197
+ * injects into the LLM prompt for that request (not Redis-persisted).
198
+ */
199
+ userContext?: string;
156
200
  };
157
201
 
158
202
  export declare type AiTwinRecord = {
@@ -241,6 +285,11 @@ export declare type AiTwinWidgetProps = {
241
285
  * Default: false (inline in the mount target).
242
286
  */
243
287
  float?: boolean;
288
+ /**
289
+ * Full-body twin: body idle + gesture overlays from CDN.
290
+ * Create via `createAiTwinFace({ fullBody: true })`.
291
+ */
292
+ fullBody?: boolean;
244
293
  /**
245
294
  * Brain id for `speakWithReply` (Text mode) and `/ws/voice`.
246
295
  * When omitted, uses getAiTwin `brainId` if available.
@@ -286,6 +335,8 @@ export declare type AvatarTtsLipsyncController = {
286
335
  */
287
336
  speakWithReply: (message: string, options?: SpeakWithReplyOptions) => Promise<SpeakWithReplyResult>;
288
337
  stop: () => void;
338
+ /** Let a `delayPlayback` request become audible. */
339
+ releasePlaybackHold: () => void;
289
340
  getVisemeQueue: () => VisemeQueueItem[];
290
341
  getWordQueue: () => WordQueueItem[];
291
342
  /** Full utterance viseme queue (all SSE chunks, cumulative vtimes) for debug. */
@@ -310,6 +361,11 @@ export declare type AvatarTtsLipsyncController = {
310
361
 
311
362
  declare type AvatarTtsLipsyncControllerOptions = {
312
363
  onLipsyncDebug?: (snapshot: RealtimeLipsyncDebugSnapshot) => void;
364
+ /**
365
+ * When true, `/avatar_ttsWithPoses` uses the full-body PixVerse pose vocab
366
+ * and stamps `words[].gesture` with CDN codes (G_002, G_004, …).
367
+ */
368
+ fullBody?: boolean;
313
369
  };
314
370
 
315
371
  export declare type AvatarTtsLipsyncStatus = "idle" | "loading" | "speaking" | "done" | "error";
@@ -325,6 +381,16 @@ export declare type AvatarTtsSpeakOptions = {
325
381
  * Sent as `language` on `/avatar_ttsWithPoses`.
326
382
  */
327
383
  language?: TtsLanguage;
384
+ /**
385
+ * Override controller `fullBody` for this request. When true, backend maps
386
+ * speech to PixVerse gesture codes (G_002, …) on `words[].gesture`.
387
+ */
388
+ fullBody?: boolean;
389
+ /**
390
+ * Buffer audio and visemes, but do not start playback until
391
+ * `releasePlaybackHold()`. Used so full-body speech starts on an idle boundary.
392
+ */
393
+ delayPlayback?: boolean;
328
394
  };
329
395
 
330
396
  /** Pair transitions for playback, including sil→first and last→sil bookends. */
@@ -345,6 +411,23 @@ export declare function compactSkippableVisemes(series: VisemeQueueItem[]): Vise
345
411
 
346
412
  export declare const CONSONANT_SKIP_GROUP: Set<string>;
347
413
 
414
+ /** Upload a portrait and enqueue the twin-face pipeline (poll with getAiTwinFaceStatus). */
415
+ export declare function createAiTwinFace(options: CreateAiTwinFaceOptions): Promise<TwinFaceJobResponse>;
416
+
417
+ export declare type CreateAiTwinFaceOptions = {
418
+ /** Bearer token (Firebase ID token or `client_…` JWT). */
419
+ authToken: string;
420
+ image: Blob | File;
421
+ name?: string;
422
+ /**
423
+ * Create a full-body (waist-up) twin: NanoBanana front-facing correction,
424
+ * then PixVerse idle + gesture videos (encrypted on CDN like idle.bin).
425
+ */
426
+ fullBody?: boolean;
427
+ /** Default: package `DEFAULT_API_BASE` (https://ai.aitwin.me). */
428
+ apiBase?: string;
429
+ };
430
+
348
431
  export declare function createAvatarTtsLipsyncController(onStatus: (status: AvatarTtsLipsyncStatus) => void, apiBase?: string, options?: AvatarTtsLipsyncControllerOptions): AvatarTtsLipsyncController;
349
432
 
350
433
  export declare function createRealtimeVoiceLipsyncController(onStatus: (status: AvatarTtsLipsyncStatus) => void, initialOptions?: RealtimeVoiceOptions): RealtimeVoiceLipsyncController;
@@ -440,12 +523,43 @@ declare type FrameRenderTransitionMeta = {
440
523
  omittedByGap: number;
441
524
  };
442
525
 
526
+ /** Default PixVerse full-body pose catalog (matches pipeline). */
527
+ export declare const FULLBODY_GESTURE_POSES: readonly ["open_palm", "emphasis", "thumbs_up", "friendly_wave", "point_camera"];
528
+
529
+ export declare type FullBodyCropMeta = {
530
+ y_end: number;
531
+ silHeight: number;
532
+ silWidth: number;
533
+ seamLockPx?: number;
534
+ poses?: string[];
535
+ encrypted?: boolean;
536
+ videoBin?: string;
537
+ };
538
+
539
+ export declare type FullBodyGesturePose = (typeof FULLBODY_GESTURE_POSES)[number];
540
+
541
+ export declare function gesturesBaseForFace(faceId: string, cdnBase?: string): string;
542
+
543
+ export declare function getAiTwinFaceStatus(avatarId: string, options: {
544
+ authToken: string;
545
+ apiBase?: string;
546
+ }): Promise<TwinFaceJobResponse>;
547
+
548
+ /** Server catalog for full-body PixVerse poses (idle + gestures). */
549
+ export declare function getAiTwinGestureCatalog(apiBase?: string): Promise<AiTwinGestureCatalog>;
550
+
443
551
  /** Public CDN original portrait for custom-faces/{faceId}/ (same id as pipeline avatarId). */
444
552
  export declare function getAiTwinSourceUrl(faceId: string, cdnBase?: string, extension?: string): string;
445
553
 
446
554
  /** Public CDN thumbnail for custom-faces/{faceId}/ (same id as pipeline avatarId). */
447
555
  export declare function getAiTwinThumbnailUrl(faceId: string, cdnBase?: string): string;
448
556
 
557
+ export declare function getFullBodyCropMetaUrl(gesturesBase: string): string;
558
+
559
+ export declare function getFullBodyGestureBinUrl(gesturesBase: string, pose: string): string;
560
+
561
+ export declare function isFullBodyGesturePose(id: string | null | undefined): id is FullBodyGesturePose;
562
+
449
563
  export declare function isTtsLanguageCode(raw: string): raw is TtsLanguage;
450
564
 
451
565
  export declare function isTtsLanguageSupported(engineId: TtsEngineId, language: string): boolean;
@@ -457,6 +571,12 @@ export declare function listSkippedVisemes(queue: VisemeQueueItem[]): string[];
457
571
 
458
572
  export declare const MIC_SAMPLE_RATE = 16000;
459
573
 
574
+ /**
575
+ * Map a TTS `words[].gesture` token to a pose id.
576
+ * Accepts pose names (`open_palm`) and CDN codes (`G_002`).
577
+ */
578
+ export declare function normalizeFullBodyGesturePose(id: string | null | undefined): FullBodyGesturePose | null;
579
+
460
580
  /** Google TTS streams Oculus viseme symbols; normalize casing and unknown ids. */
461
581
  export declare function normalizeOculusViseme(symbol: string | null | undefined): string;
462
582
 
@@ -598,6 +718,15 @@ export declare type SpeakWithReplyOptions = AvatarTtsSpeakOptions & {
598
718
  brainId?: string;
599
719
  brainUrl?: string;
600
720
  history?: SpeakWithReplyMessage[];
721
+ /** Logged-in visitor display name — persisted on non-meeting conversation history. */
722
+ userName?: string;
723
+ /** Logged-in visitor email — persisted on non-meeting conversation history. */
724
+ userEmail?: string;
725
+ /**
726
+ * Visitor note for the twin (what they want the twin to know).
727
+ * Sent each turn; backend injects into the LLM prompt (not Redis-persisted).
728
+ */
729
+ userContext?: string;
601
730
  /** Called as soon as spokenText arrives on the SSE stream. */
602
731
  onSpokenText?: (spokenText: string) => void;
603
732
  /** Called as soon as displayText arrives on the SSE stream. */
@@ -905,6 +1034,33 @@ declare type TwinBrainFields = {
905
1034
  brainUrl?: string | null;
906
1035
  };
907
1036
 
1037
+ export declare type TwinFaceJobResponse = {
1038
+ avatarId: string;
1039
+ twinName: string;
1040
+ status: TwinFaceJobStatus;
1041
+ message: string;
1042
+ success: boolean;
1043
+ createdAt?: string;
1044
+ updatedAt?: string;
1045
+ error?: string;
1046
+ deliverables?: string[];
1047
+ twinPath?: string;
1048
+ r2PublicBase?: string;
1049
+ thumbnailUrl?: string;
1050
+ sourceUrl?: string;
1051
+ gender?: string;
1052
+ genderConfidence?: number;
1053
+ genderError?: string;
1054
+ /** When true, pipeline runs waist-up NanoBanana + PixVerse gestures. */
1055
+ fullBody?: boolean;
1056
+ gesturesReady?: boolean;
1057
+ gestures?: string[];
1058
+ gesturesBase?: string;
1059
+ gesturesError?: string;
1060
+ };
1061
+
1062
+ export declare type TwinFaceJobStatus = "queued" | "running" | "succeeded" | "failed";
1063
+
908
1064
  export declare const VISEME_IDS: readonly ["aa", "E", "I", "O", "U", "PP", "FF", "DD", "SS", "TH", "CH", "RR", "kk", "nn"];
909
1065
 
910
1066
  /** Minimum gap (ms) between consecutive vtimes to keep a skippable viseme. */
@@ -943,6 +1099,20 @@ export declare type VoiceConnectOptions = {
943
1099
  * Sent as `language` on `/ws/voice` and redirected `/avatar_ttsWithPoses` calls.
944
1100
  */
945
1101
  language?: TtsLanguage;
1102
+ /**
1103
+ * When true, redirected `/avatar_ttsWithPoses` uses full-body PixVerse pose vocab.
1104
+ */
1105
+ fullBody?: boolean;
1106
+ /**
1107
+ * Full-body only: resolve when the current body-idle clip ends so speech
1108
+ * does not start mid-loop. Null when the body layer is not mounted.
1109
+ */
1110
+ waitForBodyIdle?: () => {
1111
+ promise: Promise<void>;
1112
+ cancel: () => void;
1113
+ } | null;
1114
+ /** Unpark body idle if a full-body speak is cancelled before playback. */
1115
+ onBodyIdleCancelled?: () => void;
946
1116
  /** Redis brain id (from getAiTwin `brainId`). Sent as `brainId` on `/ws/voice`. */
947
1117
  brainId?: string;
948
1118
  /** @deprecated Use `brainId`. */
@@ -962,6 +1132,15 @@ export declare type VoiceConnectOptions = {
962
1132
  speakOnlyWhenSpokenTo?: boolean;
963
1133
  /** Wake name used with `speakOnlyWhenSpokenTo` (e.g. twin.agentName). */
964
1134
  avatarName?: string;
1135
+ /** Logged-in visitor display name — persisted on non-meeting conversation history. */
1136
+ userName?: string;
1137
+ /** Logged-in visitor email — persisted on non-meeting conversation history. */
1138
+ userEmail?: string;
1139
+ /**
1140
+ * Visitor note for the twin. Sent on connect; backend stores lead-scoped
1141
+ * Sent on connect; backend injects into the LLM prompt (not Redis-persisted).
1142
+ */
1143
+ userContext?: string;
965
1144
  /** HTTP API base; default `https://ai.aitwin.me`. */
966
1145
  apiBase?: string;
967
1146
  /** Full WebSocket URL override. Query params must be included. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamoji/aitwin",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "description": "AiTwin.me Player SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/aitwin.cjs",