@alxxsck/ai-assistant 1.8.0 → 2.2.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 +121 -314
- package/dist/App.d.ts +0 -7
- package/dist/{Avatar-BAlmduYw.js → Avatar-DKGkEfXe.js} +2608 -2716
- package/dist/ChatWidgetContent-Coj_NDep.js +8570 -0
- package/dist/avatar/AnimationManager.d.ts +45 -15
- package/dist/avatar/Avatar.d.ts +15 -19
- package/dist/avatar/publicAnimations.d.ts +3 -0
- package/dist/bridge-ai-chat-widget.es.js +4 -14123
- package/dist/config/runtime-config.d.ts +4 -0
- package/dist/context/ChatWidgetContext.d.ts +6 -5
- package/dist/domain/command/CommandRuntime.d.ts +1 -0
- package/dist/domain/command/command.types.d.ts +15 -24
- package/dist/domain/message/cable/AnyCable.service.d.ts +2 -1
- package/dist/domain/message/cable/CableContext.d.ts +2 -1
- package/dist/domain/message/cable/CableContext.types.d.ts +2 -4
- package/dist/domain/speech/LipSyncCueSource.d.ts +25 -0
- package/dist/domain/speech/LipSyncRuntime.d.ts +54 -0
- package/dist/domain/speech/RealtimeLipSyncCueSource.d.ts +13 -0
- package/dist/domain/speech/SpeechPlayer.d.ts +10 -0
- package/dist/domain/ui/ui.service.d.ts +7 -1
- package/dist/domain/ui/widget-geometry.d.ts +23 -0
- package/dist/domain/voice/voice.store.d.ts +1 -0
- package/dist/index-Dt2DYOP-.js +9632 -0
- package/dist/index.d.ts +18 -21
- package/dist/index.types.d.ts +6 -43
- package/dist/lib/isAuthenticationError.d.ts +1 -0
- package/dist/lib/logger.d.ts +5 -2
- package/dist/lib/markdownRenderer.d.ts +4 -0
- package/dist/types/index.d.ts +4 -6
- package/dist/ui/chat-routes.d.ts +2 -0
- package/dist/ui/components/ChatAvatarStage.d.ts +1 -0
- package/dist/ui/components/ChatWidget.d.ts +0 -2
- package/dist/ui/components/ChatWidgetContent.d.ts +1 -0
- package/dist/ui/components/ChatWidgetFrame.d.ts +13 -0
- package/dist/ui/components/StreamingMessageText.d.ts +2 -1
- package/dist/ui/hooks/useSmoothStreamingText.d.ts +2 -1
- package/dist/ui/streaming/smooth-text.d.ts +5 -0
- package/package.json +7 -20
- package/dist/OrbitControls-BhEr8WlG.js +0 -458
- package/dist/lil-gui.esm-BicvE3D7.js +0 -1263
- package/dist/ui/components/ChatFooter.d.ts +0 -2
package/README.md
CHANGED
|
@@ -1,365 +1,172 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Lola AI Assistant
|
|
2
2
|
|
|
3
|
-
Embeddable
|
|
3
|
+
Embeddable browser library for the Lola assistant. The package owns its DOM host,
|
|
4
|
+
Shadow DOM, chat UI, avatar, realtime transports, voice flow, and backend command
|
|
5
|
+
runtime. A product frontend supplies only an authenticated interaction session and
|
|
6
|
+
the few integrations that must cross into the host application.
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
- optional realtime voice mode backed by the Lola Socket.IO proxy and xAI
|
|
7
|
-
- optional animated 3D avatar (three.js)
|
|
8
|
-
- WebSocket live message updates (AnyCable)
|
|
9
|
-
- Shadow DOM isolation for host-page style safety
|
|
8
|
+
## Install and build
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
The package requires React 19 or newer as a peer dependency.
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
The instance mounts a React app into a host element's Shadow DOM, fetches static asset mappings from a remote manifest, initializes chat/voice/avatar modules, and exposes a small integration API (`setOpen`, `destroy`, `setCustomerInteractionSession`, events).
|
|
18
|
-
|
|
19
|
-
## Tech Stack
|
|
20
|
-
|
|
21
|
-
- React 19
|
|
22
|
-
- TypeScript
|
|
23
|
-
- Vite (dev app + library build)
|
|
24
|
-
- Tailwind CSS 4
|
|
25
|
-
- Zustand (state stores)
|
|
26
|
-
- three.js + FBX assets (avatar rendering/animation)
|
|
27
|
-
- AnyCable Web client (live chat transport)
|
|
28
|
-
- Socket.IO + AudioWorklet (realtime voice mode through Lola Backend)
|
|
29
|
-
|
|
30
|
-
## Repository Layout
|
|
31
|
-
|
|
32
|
-
High-level structure:
|
|
33
|
-
|
|
34
|
-
- `src/index.ts` - public library entry (`ChatWidgetInstance`)
|
|
35
|
-
- `src/index.types.ts` - public config/types surface
|
|
36
|
-
- `src/App.tsx` - provider composition root
|
|
37
|
-
- `src/react/mount.tsx` - React root mount helper
|
|
38
|
-
- `src/ui/components` - UI components (chat widget, routes, controls)
|
|
39
|
-
- `src/domain/message` - message store + websocket channel integration
|
|
40
|
-
- `src/domain/voice` - Lola voice session, PCM media, and xAI realtime events
|
|
41
|
-
- `src/avatar` - three.js avatar scene, animation manager, blend shapes
|
|
42
|
-
- `src/api` - HTTP clients for messages/voice/session-related calls
|
|
43
|
-
- `src/context/ChatWidgetContext.tsx` - widget-level UI state/context
|
|
44
|
-
- `src/dev` - local/dev/demo stand bootstrap (non-library integration path)
|
|
45
|
-
- `src/assets` - local assets used by the widget and avatar (not used directly, rather this whole folder is getting pushed to assets repo)
|
|
46
|
-
- `scripts` - utility scripts (for example asset sync to remote static repo)
|
|
47
|
-
|
|
48
|
-
## Runtime Architecture
|
|
49
|
-
|
|
50
|
-
### 1) Host Integration Layer
|
|
51
|
-
|
|
52
|
-
`ChatWidgetInstance` (`src/index.ts`) is the host-facing API:
|
|
53
|
-
|
|
54
|
-
- validates `mountElementId`
|
|
55
|
-
- creates `shadowRoot` on mount element
|
|
56
|
-
- injects bundled CSS into shadow root
|
|
57
|
-
- fetches `${ASSETS_URL}/manifest.json`
|
|
58
|
-
- resolves hashed asset paths via `resolveAssetPath(path)`
|
|
59
|
-
- optionally merges remote config (`remoteConfig`)
|
|
60
|
-
- mounts React app and wires `AppApi` callbacks/events
|
|
61
|
-
|
|
62
|
-
### 2) React App + Providers
|
|
63
|
-
|
|
64
|
-
`App` composes:
|
|
65
|
-
|
|
66
|
-
- `ChatWidgetContextProvider` (widget open state, sizing, config, loading progress)
|
|
67
|
-
- `CableProvider` (AnyCable websocket service + network status)
|
|
68
|
-
- `HashRouter` (voice/text/list routes)
|
|
69
|
-
|
|
70
|
-
### 3) Messaging Domain
|
|
71
|
-
|
|
72
|
-
`useMessageStore` handles:
|
|
73
|
-
|
|
74
|
-
- initial thread bootstrap (`ListMessages`, `ListMessagesForThreads`)
|
|
75
|
-
- optimistic and server-driven message updates
|
|
76
|
-
- thread map and per-thread message derivation
|
|
77
|
-
- message send (`CreateMessage`)
|
|
78
|
-
- agentic steps merge/update and rendering support
|
|
79
|
-
|
|
80
|
-
Live updates arrive via AnyCable channel events and are pushed into the store.
|
|
81
|
-
Versioned `messageDelta` updates are applied by `messageId` and increasing
|
|
82
|
-
`sequence`; each frame contains the current accumulated text, so duplicate or
|
|
83
|
-
stale frames cannot append content twice. The UI renders every accepted frame
|
|
84
|
-
immediately and animates only the newly arrived suffix. See
|
|
85
|
-
[`docs/chat-streaming.ru.md`](docs/chat-streaming.ru.md) for the wire contract,
|
|
86
|
-
lifecycle, rendering, and scroll behavior.
|
|
87
|
-
|
|
88
|
-
### 4) Voice Domain
|
|
89
|
-
|
|
90
|
-
`useVoiceStore` manages the Lola voice turn lifecycle:
|
|
91
|
-
|
|
92
|
-
- creates a canonical `POST /voice/sessions` session
|
|
93
|
-
- captures mono microphone input and converts it to PCM16 24 kHz in an AudioWorklet
|
|
94
|
-
- connects to the authenticated `/assistant` Socket.IO namespace, activates the
|
|
95
|
-
provider session with `voice.connect`, and sends sequenced Lola protocol v4
|
|
96
|
-
`voice.audio.append` events with acknowledgements
|
|
97
|
-
- plays `response.output_audio.delta` through a continuous AudioWorklet queue
|
|
98
|
-
- unwraps canonical `voice.event` envelopes, renders Grok realtime transcripts,
|
|
99
|
-
and keeps avatar talking state in sync
|
|
100
|
-
- creates a fresh VoiceSession after an unexpected voice socket disconnect
|
|
101
|
-
- closes the session through `voice.disconnect` with the REST endpoint as a fallback
|
|
102
|
-
|
|
103
|
-
### 5) Avatar Domain
|
|
104
|
-
|
|
105
|
-
`Avatar` + `AnimationManager`:
|
|
106
|
-
|
|
107
|
-
- initializes three.js renderer/camera/lights/materials
|
|
108
|
-
- loads model + texture + animation assets from resolved remote paths
|
|
109
|
-
- emits `loading_progress`
|
|
110
|
-
- starts animation mixer loops
|
|
111
|
-
- maps viseme timeline to morph target animation during speech
|
|
112
|
-
- exposes external animation actions (`excited`, `fix_hair`, `spin`, `kiss`)
|
|
113
|
-
|
|
114
|
-
When all assets load, widget emits `avatar_ready` through `ChatWidgetInstance`.
|
|
115
|
-
|
|
116
|
-
## Public API
|
|
117
|
-
|
|
118
|
-
Import:
|
|
119
|
-
|
|
120
|
-
```ts
|
|
121
|
-
import {
|
|
122
|
-
ChatWidgetInstance,
|
|
123
|
-
type WidgetConfig,
|
|
124
|
-
} from "bridgeapp-ai-chat-widget";
|
|
12
|
+
```bash
|
|
13
|
+
npm install
|
|
14
|
+
npm run build-lib
|
|
125
15
|
```
|
|
126
16
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
- `mountElementId: string`
|
|
130
|
-
- - `configName: string` - remote config, lives at the same place as other static assets
|
|
131
|
-
- `customerInteractionSession?: { accessToken; chatId; expiresAt }` - if there's no session (separate case for dev/demo mode) - we look for customerId in remote config and create session ourselves.
|
|
132
|
-
|
|
133
|
-
### `RemoteWidgetConfig`
|
|
17
|
+
Library transport and asset origins are embedded at build time:
|
|
134
18
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
- `apiUrl: string`
|
|
141
|
-
- `AIAvatar?: boolean` - is 3D avatar be used
|
|
142
|
-
- `voiceEnabled?: boolean` - is voice mode enebled
|
|
143
|
-
- `voiceConfig?: { voice: "ara" | "eve" | "leo" | "rex" | "sal" }` - optional xAI voice
|
|
144
|
-
- `background?: boolean` - clear or visible background
|
|
145
|
-
- `footer?: boolean` - is footer rendered
|
|
146
|
-
- `debug?: boolean` (avatar debug GUI)
|
|
147
|
-
- `manualOpen?: boolean` - is widget trigger rendered or should it be open only programatically
|
|
148
|
-
|
|
149
|
-
### Instance Methods
|
|
150
|
-
|
|
151
|
-
- `setOpen(open: boolean): void` - open/close widget
|
|
152
|
-
- `setCustomerInteractionSession(session): void` - update session after initialization (on session expire)
|
|
153
|
-
- `playAnimation(name): void`
|
|
154
|
-
- `destroy(): void`
|
|
19
|
+
```dotenv
|
|
20
|
+
VITE_LOLA_API_URL=https://api.example.test/api/v1
|
|
21
|
+
VITE_LOLA_WS_URL=wss://ws.example.test/cable
|
|
22
|
+
VITE_AI_ASSISTANT_ASSETS_URL=https://assets.example.test
|
|
23
|
+
```
|
|
155
24
|
|
|
156
|
-
|
|
25
|
+
All three values are required absolute URLs. The library build fails when a value
|
|
26
|
+
is missing, malformed, or uses an incompatible protocol. `VITE_*` values are
|
|
27
|
+
public client configuration: never place service-account keys, access tokens, or
|
|
28
|
+
other credentials in them. CI values override the placeholders in `.env`.
|
|
157
29
|
|
|
158
|
-
|
|
159
|
-
- `renew_session` - emitted when session is expired or near expiry
|
|
30
|
+
## Minimal integration
|
|
160
31
|
|
|
161
|
-
|
|
32
|
+
The product backend creates a Lola customer interaction session. The product
|
|
33
|
+
frontend passes the short-lived result to the library:
|
|
162
34
|
|
|
163
35
|
```ts
|
|
164
|
-
import { ChatWidgetInstance } from "
|
|
36
|
+
import { ChatWidgetInstance } from "@alxxsck/ai-assistant";
|
|
165
37
|
|
|
166
38
|
const widget = new ChatWidgetInstance({
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
footer: false,
|
|
173
|
-
manualOpen: true,
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
widget.addEventListener("avatar_ready", () => {
|
|
177
|
-
widget.setOpen(true);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
widget.addEventListener("renew_session", async () => {
|
|
181
|
-
const newSession = await fetchNewSessionSomehow();
|
|
182
|
-
widget.setCustomerInteractionSession(newSession);
|
|
39
|
+
customerInteractionSession: {
|
|
40
|
+
accessToken: session.accessToken,
|
|
41
|
+
interactionSessionId: session.interactionSessionId,
|
|
42
|
+
expiresAt: session.expiresAt,
|
|
43
|
+
},
|
|
183
44
|
});
|
|
184
45
|
```
|
|
185
46
|
|
|
186
|
-
|
|
47
|
+
`CustomerInteractionSession` contains exactly:
|
|
187
48
|
|
|
188
49
|
```ts
|
|
189
|
-
|
|
50
|
+
type CustomerInteractionSession = {
|
|
51
|
+
readonly accessToken: string;
|
|
52
|
+
readonly interactionSessionId: string;
|
|
53
|
+
readonly expiresAt: string;
|
|
54
|
+
};
|
|
190
55
|
```
|
|
191
56
|
|
|
192
|
-
|
|
57
|
+
Realtime settings, voice availability, provider voice selection, and project
|
|
58
|
+
settings belong to Lola Backend. They are not widget constructor properties and
|
|
59
|
+
must not be copied into the interaction session.
|
|
193
60
|
|
|
194
|
-
|
|
61
|
+
The instance creates a dedicated host below `document.body` and attaches an open
|
|
62
|
+
Shadow DOM to it. Multiple instances remain isolated. Call `destroy()` to unmount
|
|
63
|
+
the widget, disconnect its runtime, clear pending work, and remove the owned host.
|
|
195
64
|
|
|
196
|
-
|
|
197
|
-
npm install
|
|
198
|
-
```
|
|
65
|
+
## Lifecycle
|
|
199
66
|
|
|
200
|
-
|
|
67
|
+
The supported instance methods are:
|
|
201
68
|
|
|
202
|
-
```
|
|
203
|
-
|
|
69
|
+
```ts
|
|
70
|
+
widget.setOpen(true);
|
|
71
|
+
widget.setCustomerInteractionSession(nextSession);
|
|
72
|
+
widget.destroy();
|
|
204
73
|
```
|
|
205
74
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
- `vite.config.ts` is for app/dev runtime.
|
|
211
|
-
- `vite.config.lib.ts` is for distributable library build.
|
|
212
|
-
|
|
213
|
-
## Build, Publish, and Deployment
|
|
214
|
-
|
|
215
|
-
### Build local dev app
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
npm run build-dev
|
|
219
|
-
```
|
|
75
|
+
`setOpen` may be called before asynchronous widget initialization completes; the
|
|
76
|
+
latest requested state is applied when the UI is ready. Session replacement updates
|
|
77
|
+
authenticated HTTP, realtime, message, voice, and command dependencies without
|
|
78
|
+
recreating the public widget instance.
|
|
220
79
|
|
|
221
|
-
|
|
80
|
+
The widget emits `renew_session` before expiry and after supported authentication
|
|
81
|
+
failures. Refresh through the product backend and replace the session:
|
|
222
82
|
|
|
223
|
-
```
|
|
224
|
-
|
|
83
|
+
```ts
|
|
84
|
+
widget.addEventListener("renew_session", async () => {
|
|
85
|
+
const nextSession = await productApi.createLolaInteractionSession();
|
|
86
|
+
widget.setCustomerInteractionSession(nextSession);
|
|
87
|
+
});
|
|
225
88
|
```
|
|
226
89
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
- `dist/bridge-ai-chat-widget.es.js`
|
|
230
|
-
- `dist/index.types.d.ts`
|
|
90
|
+
The constructor and replacement method reject empty tokens, empty interaction
|
|
91
|
+
session identifiers, and invalid expiry timestamps.
|
|
231
92
|
|
|
232
|
-
|
|
93
|
+
## Launcher control
|
|
233
94
|
|
|
234
|
-
-
|
|
235
|
-
|
|
95
|
+
The built-in launcher is visible by default. Products that render their own button
|
|
96
|
+
can hide it while keeping the same programmatic open path:
|
|
236
97
|
|
|
237
|
-
|
|
98
|
+
```ts
|
|
99
|
+
const widget = new ChatWidgetInstance({
|
|
100
|
+
customerInteractionSession: session,
|
|
101
|
+
hideOpenButton: true,
|
|
102
|
+
});
|
|
238
103
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
static config files.
|
|
104
|
+
productButton.addEventListener("click", () => widget.setOpen(true));
|
|
105
|
+
```
|
|
242
106
|
|
|
243
|
-
-
|
|
244
|
-
|
|
245
|
-
- `npm run format`
|
|
246
|
-
- `npm run format:check`
|
|
247
|
-
- deployment scripts for S3 buckets (project-specific, to be reworked)
|
|
248
|
-
- `npm run push-assets-metamediastatic` (sync `src/assets` into remote static assets repo)
|
|
107
|
+
Closing a hidden-launcher widget leaves it non-interactive until the product calls
|
|
108
|
+
`setOpen(true)` again. The runtime and active interaction session remain mounted.
|
|
249
109
|
|
|
250
|
-
##
|
|
110
|
+
## Host handlers
|
|
251
111
|
|
|
252
|
-
|
|
112
|
+
`handlers` is optional and is the only command integration surface. Use it when a
|
|
113
|
+
backend command must navigate the product, open a product modal, or customize an
|
|
114
|
+
element highlight:
|
|
253
115
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
116
|
+
```ts
|
|
117
|
+
const widget = new ChatWidgetInstance({
|
|
118
|
+
customerInteractionSession: session,
|
|
119
|
+
handlers: {
|
|
120
|
+
openPage: ({ route }) => productRouter.push(route),
|
|
121
|
+
openModal: ({ modalName }) => productModals.open(modalName),
|
|
122
|
+
highlight: ({ element, active }) => {
|
|
123
|
+
element?.classList.toggle("lola-highlight", active);
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
```
|
|
257
128
|
|
|
258
|
-
|
|
129
|
+
Page and modal targets arrive in canonical Lola command envelopes. The built-in
|
|
130
|
+
element fallback resolves stable `[data-lola="..."]` attributes. CTA display,
|
|
131
|
+
chat open/close, speech, voice conversations, and avatar animation stay internal.
|
|
259
132
|
|
|
260
|
-
|
|
133
|
+
Command lifecycle events are available as `command_received`,
|
|
134
|
+
`command_succeeded`, `command_failed`, `command_expired`, and
|
|
135
|
+
`command_unsupported`.
|
|
261
136
|
|
|
262
|
-
|
|
263
|
-
the authenticated session identifier; chat history is keyed independently by
|
|
264
|
-
`conversationId` (`threadId` in realtime compatibility messages).
|
|
137
|
+
## Diagnostics
|
|
265
138
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
for the current interaction session.
|
|
271
|
-
- `POST /chat/messages` sends `conversationId` and adopts the canonical
|
|
272
|
-
`conversationId` returned by the backend when a chat is resolved or created.
|
|
139
|
+
Set `debug: true` to enable verbose lifecycle, realtime, speech, and voice logs
|
|
140
|
+
prefixed with `[Lola-Widget]`. Initialization and runtime errors remain visible
|
|
141
|
+
without this flag. The option does not restore the removed debug GUI or avatar
|
|
142
|
+
debug controls.
|
|
273
143
|
|
|
274
|
-
|
|
275
|
-
as a chat error and the open conversation list is refreshed; only `401`
|
|
276
|
-
requests trigger interaction-session renewal.
|
|
144
|
+
## Breaking migration
|
|
277
145
|
|
|
278
|
-
|
|
146
|
+
This release intentionally removes the former dev/demo and host-configuration
|
|
147
|
+
surface. Remove these constructor properties from integrations:
|
|
279
148
|
|
|
280
|
-
|
|
281
|
-
`
|
|
282
|
-
|
|
283
|
-
|
|
149
|
+
- `mountElementId`, `agentId`, `customerId`, `configName`
|
|
150
|
+
- `apiUrl`, `wsUrl`
|
|
151
|
+
- `AIAvatar`, `background`, `footer`, `voiceEnabled`, `voiceConfig`, `locale`
|
|
152
|
+
- `manualOpen`, `avatarDebug`, `uiTargets`, `commandHandlers`
|
|
284
153
|
|
|
285
|
-
|
|
286
|
-
|
|
154
|
+
Replace `manualOpen` with `hideOpenButton: true` only when the standard launcher
|
|
155
|
+
must be hidden. Remove calls to `playAnimation`, `executeReaction`,
|
|
156
|
+
`sendServiceMessage`, `setLocale`, `registerUiTarget`, and
|
|
157
|
+
`registerCommandHandler`. Backend commands retain the supported assistant
|
|
158
|
+
behaviour internally.
|
|
287
159
|
|
|
288
|
-
The
|
|
289
|
-
|
|
290
|
-
|
|
160
|
+
The repository ships only the library build. It no longer contains an app-mode
|
|
161
|
+
HTML entry, local session creation, remote JSON widget configs, a debug GUI,
|
|
162
|
+
preview/deploy demo scripts, or a Vite dev-server configuration.
|
|
291
163
|
|
|
292
|
-
|
|
293
|
-
provides typed callbacks:
|
|
164
|
+
## Verification
|
|
294
165
|
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
sessionId,
|
|
302
|
-
expiresAt,
|
|
303
|
-
},
|
|
304
|
-
handlers: {
|
|
305
|
-
openModal: ({ modalName }) => modalRegistry.open(modalName),
|
|
306
|
-
openPage: ({ route }) => router.push(route),
|
|
307
|
-
},
|
|
308
|
-
// Temporary fallback for legacy commands without data.target.
|
|
309
|
-
uiTargets: {
|
|
310
|
-
deposit_button: {
|
|
311
|
-
kind: "button",
|
|
312
|
-
selector: '[data-lola-action="deposit"]',
|
|
313
|
-
},
|
|
314
|
-
deposit_modal: {
|
|
315
|
-
kind: "modal",
|
|
316
|
-
modalName: "deposit",
|
|
317
|
-
},
|
|
318
|
-
account_page: {
|
|
319
|
-
kind: "page",
|
|
320
|
-
route: "/account",
|
|
321
|
-
query: { source: "lola" },
|
|
322
|
-
},
|
|
323
|
-
},
|
|
324
|
-
});
|
|
166
|
+
```bash
|
|
167
|
+
npm run typecheck
|
|
168
|
+
npm test
|
|
169
|
+
npm run lint
|
|
170
|
+
npm run format:check
|
|
171
|
+
npm run build-lib
|
|
325
172
|
```
|
|
326
|
-
|
|
327
|
-
Targets and handlers can also be registered after construction with
|
|
328
|
-
`registerUiTarget(code, target)` and `registerCommandHandler(name, handler)`.
|
|
329
|
-
Both return an unregister callback.
|
|
330
|
-
|
|
331
|
-
Built-in handlers cover assistant/chat visibility, supported avatar animations,
|
|
332
|
-
CTA rendering inside the text chat, and element highlighting. Highlight targets
|
|
333
|
-
fall back to `[data-lola="code"]` or `[data-lola-action="code"]`. The default
|
|
334
|
-
highlight is a fixed overlay attached to `document.body`, so it is not clipped
|
|
335
|
-
by an element's `overflow` or container bounds and follows resize and scroll. A registered page
|
|
336
|
-
URL fallback uses `history.pushState` and emits `popstate`, so an explicitly
|
|
337
|
-
configured query such as `?lola_modal=deposit` can be handled without reloading the
|
|
338
|
-
host SPA. A registered modal selector can also open a native `HTMLDialogElement`.
|
|
339
|
-
`data.target` is authoritative. Legacy commands without it are resolved through
|
|
340
|
-
`payload.modalId`/`pageId` and `uiTargets`. If no safe handler/fallback exists, the widget sends
|
|
341
|
-
`unsupported` and emits `command_unsupported`; other lifecycle events are
|
|
342
|
-
`command_received`, `command_succeeded`, `command_failed`, and `command_expired`.
|
|
343
|
-
|
|
344
|
-
## Asset Pipeline
|
|
345
|
-
|
|
346
|
-
Runtime asset resolution:
|
|
347
|
-
|
|
348
|
-
1. fetch remote manifest from `https://metamediastatic.com/manifest.json`
|
|
349
|
-
2. map logical path (for example `animations/idle_1.fbx`) to hashed URL
|
|
350
|
-
3. load via `resolveAssetPath`
|
|
351
|
-
|
|
352
|
-
This allows cache-friendly hashed asset delivery without changing code references.
|
|
353
|
-
|
|
354
|
-
## Troubleshooting
|
|
355
|
-
|
|
356
|
-
- Widget does not mount:
|
|
357
|
-
- verify mount element exists and `mountElementId` is correct
|
|
358
|
-
- No messages or send failures:
|
|
359
|
-
- verify `apiUrl`, `accessToken`, and `chatId`
|
|
360
|
-
- No live updates:
|
|
361
|
-
- verify `wsUrl`, websocket reachability, and token validity
|
|
362
|
-
- Voice fails to start:
|
|
363
|
-
- verify mic permission, Lola `apiUrl`, Socket.IO reachability, and backend `Project.settings.voiceEnabled`
|
|
364
|
-
- Avatar never becomes ready:
|
|
365
|
-
- verify manifest URL + asset availability under static host
|
package/dist/App.d.ts
CHANGED
|
@@ -13,14 +13,7 @@ export type AppApi = {
|
|
|
13
13
|
playAvatarAnimation: (name: ExternallyAvailableActions, expiresAt?: string | null) => Promise<void>;
|
|
14
14
|
onSessionExpired: () => void;
|
|
15
15
|
registerSetOpen: (fn: ((open: boolean) => void) | null) => void;
|
|
16
|
-
registerExecuteReaction: (fn: ((params: {
|
|
17
|
-
animation: string;
|
|
18
|
-
voice: string;
|
|
19
|
-
text: string;
|
|
20
|
-
}) => void) | null) => void;
|
|
21
16
|
resolveAssetPath: (path: string) => string;
|
|
22
|
-
registerSendServiceMessage: (fn: ((message: string, animationName: ExternallyAvailableActions) => void) | null) => void;
|
|
23
|
-
registerSetLocale: (fn: ((locale: string) => void) | null) => void;
|
|
24
17
|
registerSetSession: (fn: ((session: CustomerInteractionSession) => void) | null) => void;
|
|
25
18
|
commandRuntime: CommandRuntime;
|
|
26
19
|
};
|