@alxxsck/ai-assistant 2.26.0 → 3.0.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.
Files changed (48) hide show
  1. package/dist/{Avatar-Cr3PsHzw.js → Avatar-Bsv7Y3ZQ.js} +19082 -18842
  2. package/dist/{ChatWidgetContent-DJ2Y9kKV.js → ChatWidgetContent-Cq2Y5IHt.js} +2837 -2578
  3. package/dist/api/audio.api.d.ts +1 -1
  4. package/dist/avatar/AnimationManager.d.ts +7 -3
  5. package/dist/avatar/Avatar.d.ts +20 -3
  6. package/dist/avatar/avatarMeshes.d.ts +8 -0
  7. package/dist/avatar/loaders.d.ts +16 -0
  8. package/dist/bridge-ai-chat-widget.es.js +1 -1
  9. package/dist/constants.d.ts +1 -0
  10. package/dist/context/ChatWidgetContext.d.ts +0 -2
  11. package/dist/domain/message/message.store.d.ts +3 -0
  12. package/dist/domain/speech/SpeechPlayer.d.ts +2 -0
  13. package/dist/domain/ui/widget-geometry.d.ts +7 -5
  14. package/dist/domain/voice/media/ReliableVoiceUplink.d.ts +4 -0
  15. package/dist/domain/voice/voice-audio-meter.d.ts +12 -0
  16. package/dist/domain/voice/voice.store.d.ts +5 -1
  17. package/dist/i18n/messages.d.ts +5 -2
  18. package/dist/index-DY_Y_QHI.js +2825 -0
  19. package/dist/index.d.ts +1 -0
  20. package/dist/inter-cyrillic-wght-italic.woff2 +0 -0
  21. package/dist/inter-cyrillic-wght-normal.woff2 +0 -0
  22. package/dist/inter-latin-ext-wght-italic.woff2 +0 -0
  23. package/dist/inter-latin-ext-wght-normal.woff2 +0 -0
  24. package/dist/inter-latin-wght-italic.woff2 +0 -0
  25. package/dist/inter-latin-wght-normal.woff2 +0 -0
  26. package/dist/{mount-DCjHLj_e.js → mount-RA3wsImP.js} +6415 -5939
  27. package/dist/roboto-cyrillic-400-normal.woff2 +0 -0
  28. package/dist/roboto-cyrillic-700-normal.woff2 +0 -0
  29. package/dist/roboto-latin-400-normal.woff2 +0 -0
  30. package/dist/roboto-latin-700-normal.woff2 +0 -0
  31. package/dist/roboto-latin-ext-400-normal.woff2 +0 -0
  32. package/dist/roboto-latin-ext-700-normal.woff2 +0 -0
  33. package/dist/ui/components/ChatListItem.d.ts +4 -1
  34. package/dist/ui/components/ChatSurfaceFrameContext.d.ts +6 -0
  35. package/dist/ui/components/ChatTopControls.d.ts +5 -5
  36. package/dist/ui/components/ChatVoiceMode.d.ts +5 -1
  37. package/dist/ui/components/ChatWidgetFrame.d.ts +3 -3
  38. package/dist/ui/components/VoiceComposer.d.ts +18 -0
  39. package/dist/ui/components/voice-waveform.d.ts +15 -0
  40. package/dist/ui/responder-visual-state.d.ts +7 -0
  41. package/dist/widget-fonts-CFulYNmT.js +16 -0
  42. package/dist/widget-fonts.d.ts +1 -0
  43. package/package.json +6 -2
  44. package/dist/avatar/consolidateMaterialGroups.d.ts +0 -2
  45. package/dist/index-D01wjcEK.js +0 -2809
  46. package/dist/ui/chat-composer-layout.d.ts +0 -1
  47. package/dist/ui/components/overlays/ChatBlurOverlayTop.d.ts +0 -1
  48. package/dist/ui/components/overlays/ChatDarkOverlay.d.ts +0 -1
@@ -16,5 +16,5 @@ export declare class AudioApiError extends Error {
16
16
  readonly status: number;
17
17
  constructor(status: number, message: string);
18
18
  }
19
- export declare const fetchProtectedAudio: (config: WidgetConfig, api: AppApi, request: ProtectedAudioRequest) => Promise<Blob>;
19
+ export declare const fetchProtectedAudio: (config: WidgetConfig, api: AppApi, request: ProtectedAudioRequest, signal?: AbortSignal) => Promise<Blob>;
20
20
  export declare const fetchProtectedAudioStream: (config: WidgetConfig, api: AppApi, request: StreamingAudioRequest, signal: AbortSignal) => Promise<ReadableStream<Uint8Array>>;
@@ -1,5 +1,6 @@
1
- import { Object3D, Group } from "three";
1
+ import { Object3D } from "three";
2
2
  import type { Viseme } from "@/domain/speech/LipSyncRuntime";
3
+ import { type AnimatedAsset } from "./loaders";
3
4
  import type { Avatar } from "./Avatar";
4
5
  export declare const BLEND_SHAPE_KEYS: readonly ["blendShape1.AE", "blendShape1.ChJ", "blendShape1.FV", "blendShape1.Oh", "blendShape1.Ah", "blendShape1.Ih", "blendShape1.L", "blendShape1.SZ", "blendShape1.Woo", "blendShape1.MBP", "blendShape1.Smile_Closed", "blendShape1.Smile_Open", "blendShape1.Kiss"];
5
6
  export type BlendShapeKey = (typeof BLEND_SHAPE_KEYS)[number];
@@ -16,7 +17,7 @@ type InitialAnimationAssets = {
16
17
  animationData: AnimationAssetsData;
17
18
  mandatoryAnimations: Array<{
18
19
  data: AnimationAsset;
19
- animation: Group;
20
+ animation: AnimatedAsset;
20
21
  }>;
21
22
  };
22
23
  export default class AnimationManager {
@@ -29,9 +30,11 @@ export default class AnimationManager {
29
30
  private lazyAnimations;
30
31
  private animationLoads;
31
32
  private loadingManager;
32
- private fbxLoader;
33
+ private animationLoader;
33
34
  private initialAssets;
34
35
  private backgroundPreloadCancelled;
36
+ private backgroundPreloadGeneration;
37
+ private backgroundPreloadComplete;
35
38
  private latestActionRequest;
36
39
  private pendingActionLoads;
37
40
  private idleFallbackPending;
@@ -47,6 +50,7 @@ export default class AnimationManager {
47
50
  private loadAnimationLazy;
48
51
  loadAction(name: string): Promise<void>;
49
52
  cancelBackgroundPreload(): void;
53
+ setBackgroundPreloadEnabled(enabled: boolean): void;
50
54
  private scheduleBackgroundPreload;
51
55
  private waitForBackgroundOpportunity;
52
56
  private preloadRemainingAnimations;
@@ -1,5 +1,5 @@
1
1
  import { Mesh, Vector3 } from "three";
2
- import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader.js";
2
+ import type { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
3
3
  import type { AppApi } from "@/App";
4
4
  import type { LipSyncSnapshot } from "@/domain/speech/LipSyncRuntime";
5
5
  import type { ExternallyAvailableActions } from "./publicAnimations";
@@ -9,12 +9,18 @@ type CameraParams = {
9
9
  lookAt: Vector3;
10
10
  fov: number;
11
11
  };
12
+ export type AvatarFramingMode = "default" | "chat-surface";
12
13
  export declare class Avatar extends EventTarget {
13
14
  private canvas;
14
15
  private videoContainer;
15
16
  api: AppApi;
16
- initialAssetsfbxLoader: FBXLoader;
17
+ initialAssetsLoader: GLTFLoader;
17
18
  head: Mesh;
19
+ /**
20
+ * The brows are a separate primitive in glTF but share the head's blend
21
+ * shapes, so they have to follow the same influences array. See syncFaceMorphs.
22
+ */
23
+ private brows?;
18
24
  private renderer;
19
25
  private sound?;
20
26
  private cubeTexture;
@@ -26,6 +32,7 @@ export declare class Avatar extends EventTarget {
26
32
  private body;
27
33
  private animationManager;
28
34
  private cameraParams;
35
+ private framingMode;
29
36
  private locale?;
30
37
  private animationFrame;
31
38
  private renderingEnabled;
@@ -33,6 +40,7 @@ export declare class Avatar extends EventTarget {
33
40
  constructor(canvas: HTMLCanvasElement, videoContainer: HTMLDivElement, api: AppApi);
34
41
  private lightAmbient;
35
42
  private lightDirectional;
43
+ private lightRim;
36
44
  private loadingManager;
37
45
  private criticalAssetsReady;
38
46
  private sounds;
@@ -40,13 +48,22 @@ export declare class Avatar extends EventTarget {
40
48
  init(): Promise<void>;
41
49
  initSounds(locale: string): void;
42
50
  private tempLookAt;
43
- setCamera(params: CameraParams, cb?: () => void): void;
51
+ setCamera(params: CameraParams, cb?: () => void, duration?: number): void;
52
+ setFramingMode(mode: AvatarFramingMode): void;
44
53
  private width;
45
54
  private height;
46
55
  onResize: (width?: number, height?: number) => void;
47
56
  animate: () => void;
57
+ /**
58
+ * The head and the brows are two meshes sharing one set of blend shapes.
59
+ * Everything that drives the face (lip sync, blend shape scenarios, gsap
60
+ * tweens) writes into `head.morphTargetInfluences`, and some of it swaps the
61
+ * array outright, so the brows follow the head's current array every frame.
62
+ */
63
+ private syncFaceMorphs;
48
64
  setRenderingEnabled(enabled: boolean): void;
49
65
  cancelBackgroundPreload(): void;
66
+ setBackgroundPreloadEnabled(enabled: boolean): void;
50
67
  waitForCriticalAssets(): Promise<void>;
51
68
  private SPEAKING_ANIMATION_NAME_1;
52
69
  private SPEAKING_ANIMATION_NAME_2;
@@ -0,0 +1,8 @@
1
+ import type { Object3D, SkinnedMesh } from "three";
2
+ export type AvatarMeshSlot = "eyes" | "hair" | "head" | "brows" | "shell" | "body";
3
+ export type AvatarMeshes = Partial<Record<AvatarMeshSlot, SkinnedMesh>>;
4
+ /** Maps the meshes of a loaded avatar rig onto the slots the renderer knows about. */
5
+ export declare function collectAvatarMeshes(root: Object3D): AvatarMeshes;
6
+ /** Slots the avatar cannot render without. */
7
+ export declare const REQUIRED_AVATAR_MESH_SLOTS: AvatarMeshSlot[];
8
+ export declare function findMissingAvatarMeshes(meshes: AvatarMeshes): AvatarMeshSlot[];
@@ -0,0 +1,16 @@
1
+ import type { AnimationClip, LoadingManager } from "three";
2
+ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
3
+ /**
4
+ * Anything the avatar loads carries animation clips: the rig itself has none,
5
+ * an animation asset has exactly one. Narrowing to this shape keeps the call
6
+ * sites independent of whether a GLTF or a plain Object3D came back.
7
+ */
8
+ export type AnimatedAsset = {
9
+ animations: AnimationClip[];
10
+ };
11
+ /**
12
+ * Avatar assets are glTF binaries compressed with EXT_meshopt_compression
13
+ * (see scripts/asset-pipeline/optimize-assets.mjs). The decoder ships its
14
+ * WebAssembly inline, so no extra file has to be served.
15
+ */
16
+ export declare function createAvatarLoader(manager?: LoadingManager): GLTFLoader;
@@ -1,4 +1,4 @@
1
- import { C as A, E as e, S as s, d as E, c } from "./index-D01wjcEK.js";
1
+ import { C as A, E as e, S as s, d as E, c } from "./index-DY_Y_QHI.js";
2
2
  export {
3
3
  A as ChatWidgetInstance,
4
4
  e as EXTERNALLY_AVAILABLE_ACTIONS,
@@ -1,2 +1,3 @@
1
1
  export declare const SM_BREAKPOINT = 640;
2
+ export declare function isPhoneViewport(): boolean;
2
3
  export declare const SHOW_REACTION_MESSAGE_DURATION = 5000;
@@ -10,8 +10,6 @@ type ChatWidgetContextValue = {
10
10
  transitionSurface: (open: boolean, context: SurfaceTransitionContext) => void;
11
11
  openCompactPreview: (context: SurfaceTransitionContext) => Promise<boolean> | null;
12
12
  surfaceEpisodeId: string | null;
13
- isFullscreen: boolean;
14
- setFullscreen: (fullscreen: boolean) => void;
15
13
  contentActivated: boolean;
16
14
  isAvatarCoveredByChatList: boolean;
17
15
  setAvatarCoveredByChatList: (covered: boolean) => void;
@@ -3,11 +3,14 @@ import type { AppApi } from "@/App";
3
3
  import type { WidgetConfig } from "@/index.types";
4
4
  import { type MessageStreamState } from "./message-stream";
5
5
  import type { ChatAttachment, ChatTypingState } from "./chat-experience";
6
+ import { type SafeResponderPresentation } from "@/domain/support-presentation/support-presentation.types";
6
7
  import type { ResponderPresentationChanged, ScenarioConversationCreated } from "./cable/widget-message";
7
8
  import { type ScenarioChoiceLifecycleChanged, type ScenarioChoiceSubmissionResult } from "@/domain/scenario/scenario-choice";
8
9
  export interface ThreadSummary {
9
10
  threadId: string;
11
+ title: string | null;
10
12
  lastMessage: MessageData;
13
+ responderPresentation: SafeResponderPresentation;
11
14
  }
12
15
  export type AgentResponsePhase = "idle" | "awaiting-first-token" | "streaming";
13
16
  export type ConversationNavigationRequest = {
@@ -1,6 +1,8 @@
1
1
  export type SpeechPlaybackOptions = {
2
2
  onStarted?: () => void;
3
3
  onStopped?: (completed: boolean) => void;
4
+ onLevel?: (level: number) => void;
5
+ levelContext?: AudioContext;
4
6
  };
5
7
  export type PcmStreamLoader = (signal: AbortSignal) => Promise<ReadableStream<Uint8Array>>;
6
8
  export type PcmPlaybackOptions = SpeechPlaybackOptions & {
@@ -31,10 +31,11 @@ export type CompactPreviewLayout = {
31
31
  export declare const LAUNCHER_SIZE = 52;
32
32
  export declare const LAUNCHER_EDGE_INSET = 24;
33
33
  export declare const VIEWPORT_MARGIN = 16;
34
- export declare const MIN_WIDGET_WIDTH = 240;
35
- export declare const DEFAULT_WIDGET_WIDTH = 360;
36
- export declare const MIN_WIDGET_HEIGHT = 320;
34
+ export declare const CHAT_SURFACE_ASPECT_RATIO: number;
35
+ export declare const MIN_WIDGET_HEIGHT = 519;
36
+ export declare const MIN_WIDGET_WIDTH: number;
37
37
  export declare const DEFAULT_WIDGET_HEIGHT = 680;
38
+ export declare const DEFAULT_WIDGET_WIDTH: number;
38
39
  export declare const COMPACT_PREVIEW_MAX_WIDTH = 320;
39
40
  export declare const COMPACT_PREVIEW_MARGIN = 12;
40
41
  export declare const COMPACT_PREVIEW_GAP = 12;
@@ -45,7 +46,8 @@ export declare function dockLauncherPosition(point: Point, viewport: Viewport):
45
46
  export declare function launcherPointFromDock(launcher: DockedLauncher, viewport: Viewport): Point;
46
47
  export declare function clampLauncherPosition(point: Point, viewport: Viewport): Point;
47
48
  export declare function clampPanelRect(rect: Rect, viewport: Viewport): Rect;
49
+ export declare function dockPanelRect(rect: Rect, viewport: Viewport): Rect;
50
+ export declare function dockPanelRectToSide(rect: Rect, viewport: Viewport, side: LauncherSide): Rect;
48
51
  export declare function placePanelFromLauncher(launcher: Point, size: Size, viewport: Viewport): Rect;
49
52
  export declare function placeCompactPreview(launcher: Point, measuredSize: Size, viewport: Viewport, side: LauncherSide, avoidRect?: Rect | null): CompactPreviewLayout;
50
- export declare function resizePanelFromNorthWest(start: Rect, delta: Point, axes: "top" | "left" | "corner", viewport: Viewport): Rect;
51
- export declare function resizePanelFromSouthEast(start: Rect, delta: Point, viewport: Viewport): Rect;
53
+ export declare function resizePanelFromTopCorner(start: Rect, delta: Point, corner: "northWest" | "northEast", viewport: Viewport): Rect;
@@ -6,10 +6,14 @@ export declare class ReliableVoiceUplink {
6
6
  private readonly queue;
7
7
  private sending;
8
8
  private closed;
9
+ private enabled;
10
+ private epoch;
9
11
  private firstCaptureSample;
10
12
  private firstDispatchAtMs;
11
13
  constructor(send: (chunk: CapturedAudioChunk) => Promise<VoiceAudioAcknowledgement>, onFailure: (error: Error) => void);
14
+ get isAcceptingInput(): boolean;
12
15
  enqueue(chunk: CapturedAudioChunk): void;
16
+ setEnabled(enabled: boolean): void;
13
17
  close(): void;
14
18
  private drain;
15
19
  private waitForPacing;
@@ -0,0 +1,12 @@
1
+ export type VoiceAudioMeterChannel = "input" | "output";
2
+ type VoiceAudioMeterListener = (level: number) => void;
3
+ export declare class VoiceAudioMeter {
4
+ private readonly levels;
5
+ private readonly listeners;
6
+ write(channel: VoiceAudioMeterChannel, value: unknown): void;
7
+ read(channel: VoiceAudioMeterChannel): number;
8
+ subscribe(channel: VoiceAudioMeterChannel, listener: VoiceAudioMeterListener): () => void;
9
+ reset(channel?: VoiceAudioMeterChannel): void;
10
+ }
11
+ export declare const voiceAudioMeter: VoiceAudioMeter;
12
+ export {};
@@ -1,6 +1,7 @@
1
1
  import { type Socket } from "socket.io-client";
2
2
  import type { AppApi } from "@/App";
3
3
  import type { VoiceSessionData } from "@/api/voice.api.types";
4
+ import { ReliableVoiceUplink } from "./media/ReliableVoiceUplink";
4
5
  import type { SpeakTextCommandContext, StartVoiceConversationCommandContext } from "@/domain/command/command.types";
5
6
  import type { WidgetConfig } from "@/index.types";
6
7
  type VoiceStatus = "idle" | "connecting" | "listening" | "speaking" | "error";
@@ -16,20 +17,23 @@ type VoiceStore = {
16
17
  localStream: MediaStream | null;
17
18
  inputAudioContext: AudioContext | null;
18
19
  inputAudioNode: AudioWorkletNode | null;
20
+ inputAudioUplink: ReliableVoiceUplink | null;
19
21
  pendingInvitation: StartVoiceConversationCommandContext | null;
20
22
  customerMessageTranscript: string;
21
23
  customerMessageTranscriptVisible: boolean;
22
24
  assistantMessageTranscript: string;
23
25
  assistantMessageTranscriptVisible: boolean;
24
26
  assistantResponseInProgress: boolean;
27
+ assistantAudioPlaying: boolean;
25
28
  microphoneEnabled: boolean;
29
+ microphoneMutedByUser: boolean;
26
30
  generation: number;
27
31
  actions: VoiceStoreActions;
28
32
  };
29
33
  type VoiceStoreActions = {
30
34
  updateSession: (config: WidgetConfig, api: AppApi) => Promise<void>;
31
35
  startListening: (config: WidgetConfig, api: AppApi) => Promise<void>;
32
- offerConversation: (invitation: StartVoiceConversationCommandContext) => Promise<void>;
36
+ offerConversation: (invitation: StartVoiceConversationCommandContext, config: WidgetConfig, api: AppApi) => Promise<void>;
33
37
  acceptConversation: (config: WidgetConfig, api: AppApi) => Promise<void>;
34
38
  declineConversation: (config: WidgetConfig, api: AppApi) => Promise<void>;
35
39
  speakText: (config: WidgetConfig, api: AppApi, speech: SpeakTextCommandContext) => Promise<void>;
@@ -14,6 +14,7 @@ declare const en: {
14
14
  };
15
15
  readonly controls: {
16
16
  readonly close: "Close chat";
17
+ readonly collapse: "Collapse chat";
17
18
  readonly move: "Move Lola";
18
19
  readonly exitFullscreen: "Exit fullscreen";
19
20
  readonly enterFullscreen: "Enter fullscreen";
@@ -25,6 +26,7 @@ declare const en: {
25
26
  readonly identity: {
26
27
  readonly support: "Support";
27
28
  readonly system: "System";
29
+ readonly online: "online";
28
30
  readonly aiAssistant: "AI assistant";
29
31
  readonly waiting: "Waiting for a specialist";
30
32
  readonly operator: "Support operator";
@@ -33,8 +35,9 @@ declare const en: {
33
35
  };
34
36
  readonly chat: {
35
37
  readonly back: "Back to chat";
36
- readonly listTitle: "Chats";
38
+ readonly listTitle: "Chat history";
37
39
  readonly new: "New chat";
40
+ readonly createNew: "Create new chat";
38
41
  readonly loadOlder: "Load older chats";
39
42
  readonly retryOlder: "Retry older chats";
40
43
  readonly olderLoadFailed: "Couldn't load older chats.";
@@ -47,7 +50,7 @@ declare const en: {
47
50
  readonly switchToVoice: "Switch to voice chat";
48
51
  readonly talk: "Talk";
49
52
  readonly messageLabel: "Message";
50
- readonly messagePlaceholder: "Message…";
53
+ readonly messagePlaceholder: "Write to Lola";
51
54
  readonly send: "Send message";
52
55
  readonly thinking: "AI is thinking";
53
56
  readonly unread: "Unread messages";