@rqmii_immersive/agent-react-sdk 2.0.0 → 4.0.1
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 +103 -357
- package/dist/{RqmiiCloudAvatarPlayer-BnsY8xIR.js → RqmiiCloudAvatarPlayer-CESlcAGy.js} +6095 -6108
- package/dist/RqmiiCloudAvatarPlayer-CESlcAGy.js.map +1 -0
- package/dist/RqmiiCloudAvatarPlayer-D5npgPcs.cjs +2939 -0
- package/dist/RqmiiCloudAvatarPlayer-D5npgPcs.cjs.map +1 -0
- package/dist/agent-react-sdk.css +1 -1
- package/dist/components/RqmiiAgentRoom.d.ts +3 -0
- package/dist/components/RqmiiAgentRoom.d.ts.map +1 -0
- package/dist/components/RqmiiCloudAvatarPlayer.d.ts +3 -0
- package/dist/components/RqmiiCloudAvatarPlayer.d.ts.map +1 -0
- package/dist/components/RqmiiErrorBoundary.d.ts +19 -0
- package/dist/components/RqmiiErrorBoundary.d.ts.map +1 -0
- package/dist/components/pxs/EpicPixelStreamingPlayer.d.ts +5 -0
- package/dist/components/pxs/EpicPixelStreamingPlayer.d.ts.map +1 -0
- package/dist/core/constants.d.ts +81 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/events/emitter.d.ts +10 -0
- package/dist/core/events/emitter.d.ts.map +1 -0
- package/dist/core/managers/audio.d.ts +24 -0
- package/dist/core/managers/audio.d.ts.map +1 -0
- package/dist/core/managers/heartbeat.d.ts +13 -0
- package/dist/core/managers/heartbeat.d.ts.map +1 -0
- package/dist/core/managers/reconnect.d.ts +29 -0
- package/dist/core/managers/reconnect.d.ts.map +1 -0
- package/dist/core/managers/session.d.ts +20 -0
- package/dist/core/managers/session.d.ts.map +1 -0
- package/dist/core/managers/socket.d.ts +15 -0
- package/dist/core/managers/socket.d.ts.map +1 -0
- package/dist/core/state/reducer.d.ts +4 -0
- package/dist/core/state/reducer.d.ts.map +1 -0
- package/dist/core/state/selectors.d.ts +24 -0
- package/dist/core/state/selectors.d.ts.map +1 -0
- package/dist/core/state/types.d.ts +60 -0
- package/dist/core/state/types.d.ts.map +1 -0
- package/dist/core/utils/accumulator.d.ts +11 -0
- package/dist/core/utils/accumulator.d.ts.map +1 -0
- package/dist/core/utils/agent-type.d.ts +2 -0
- package/dist/core/utils/agent-type.d.ts.map +1 -0
- package/dist/core/utils/bytes.d.ts +2 -0
- package/dist/core/utils/bytes.d.ts.map +1 -0
- package/dist/core/utils/sleep.d.ts +2 -0
- package/dist/core/utils/sleep.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +12 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-agent.d.ts +2 -0
- package/dist/hooks/use-rqmii-agent.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-audio-element.d.ts +2 -0
- package/dist/hooks/use-rqmii-audio-element.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-avatar.d.ts +13 -0
- package/dist/hooks/use-rqmii-avatar.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-connection.d.ts +27 -0
- package/dist/hooks/use-rqmii-connection.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-events.d.ts +3 -0
- package/dist/hooks/use-rqmii-events.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-messages.d.ts +6 -0
- package/dist/hooks/use-rqmii-messages.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-press-to-talk.d.ts +3 -0
- package/dist/hooks/use-rqmii-press-to-talk.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-sdk.d.ts +81 -0
- package/dist/hooks/use-rqmii-sdk.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-session.d.ts +9 -0
- package/dist/hooks/use-rqmii-session.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-vad.d.ts +3 -0
- package/dist/hooks/use-rqmii-vad.d.ts.map +1 -0
- package/dist/hooks/use-rqmii-voice.d.ts +12 -0
- package/dist/hooks/use-rqmii-voice.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -340
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +270 -20
- package/dist/index.js.map +1 -1
- package/dist/provider/RqmiiAgentProvider.d.ts +4 -0
- package/dist/provider/RqmiiAgentProvider.d.ts.map +1 -0
- package/dist/provider/socket-handlers.d.ts +77 -0
- package/dist/provider/socket-handlers.d.ts.map +1 -0
- package/dist/provider/use-manager-lifecycle.d.ts +76 -0
- package/dist/provider/use-manager-lifecycle.d.ts.map +1 -0
- package/dist/types/index.d.ts +385 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/ui/Orb.d.ts +19 -0
- package/dist/ui/Orb.d.ts.map +1 -0
- package/dist/ui/RqmiiAgentChat.d.ts +4 -0
- package/dist/ui/RqmiiAgentChat.d.ts.map +1 -0
- package/dist/ui/agent-data.d.ts +17 -0
- package/dist/ui/agent-data.d.ts.map +1 -0
- package/dist/ui/chat/ChatBox.d.ts +22 -0
- package/dist/ui/chat/ChatBox.d.ts.map +1 -0
- package/dist/ui/chat/CreditsExhaustedPanel.d.ts +6 -0
- package/dist/ui/chat/CreditsExhaustedPanel.d.ts.map +1 -0
- package/dist/ui/chat/chat-box-avatar.d.ts +3 -0
- package/dist/ui/chat/chat-box-avatar.d.ts.map +1 -0
- package/dist/ui/chat/chat-box-content.d.ts +26 -0
- package/dist/ui/chat/chat-box-content.d.ts.map +1 -0
- package/dist/ui/chat/chat-box-shared.d.ts +24 -0
- package/dist/ui/chat/chat-box-shared.d.ts.map +1 -0
- package/dist/ui/chat/chat-box-text-and-voice.d.ts +3 -0
- package/dist/ui/chat/chat-box-text-and-voice.d.ts.map +1 -0
- package/dist/ui/chat/chat-box-text.d.ts +3 -0
- package/dist/ui/chat/chat-box-text.d.ts.map +1 -0
- package/dist/ui/chat/chat-box-types.d.ts +83 -0
- package/dist/ui/chat/chat-box-types.d.ts.map +1 -0
- package/dist/ui/chat/chat-box-voice.d.ts +3 -0
- package/dist/ui/chat/chat-box-voice.d.ts.map +1 -0
- package/dist/ui/chat/components.d.ts +4 -0
- package/dist/ui/chat/components.d.ts.map +1 -0
- package/dist/ui/chat/panels.d.ts +78 -0
- package/dist/ui/chat/panels.d.ts.map +1 -0
- package/dist/ui/chat/primitives.d.ts +47 -0
- package/dist/ui/chat/primitives.d.ts.map +1 -0
- package/dist/ui/chat/utils.d.ts +7 -0
- package/dist/ui/chat/utils.d.ts.map +1 -0
- package/dist/ui/faces.d.ts +3 -0
- package/dist/ui/faces.d.ts.map +1 -0
- package/dist/ui/languages.d.ts +10 -0
- package/dist/ui/languages.d.ts.map +1 -0
- package/dist/ui.cjs +122 -1
- package/dist/ui.cjs.map +1 -1
- package/dist/ui.d.ts +11 -10
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +1771 -4
- package/dist/ui.js.map +1 -1
- package/package.json +33 -5
- package/dist/RqmiiCloudAvatarPlayer-BnsY8xIR.js.map +0 -1
- package/dist/RqmiiCloudAvatarPlayer-lqCz2xlU.cjs +0 -2938
- package/dist/RqmiiCloudAvatarPlayer-lqCz2xlU.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,422 +1,168 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @rqmii_immersive/agent-react-sdk
|
|
2
2
|
|
|
3
|
-
Standalone React SDK for
|
|
3
|
+
Standalone React SDK for Rqmii Agent realtime sessions. Version 4.0.0 — complete TypeScript rewrite with reducer-based state management and event emitter system.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- room wrapper component (`RqmiiAgentRoom`)
|
|
8
|
-
- provider (`RqmiiAgentProvider`)
|
|
9
|
-
- hooks usable by any child component (`useRqmiiConnection`, `useRqmiiMessages`, `useRqmiiVoice`, `useRqmiiAvatar`)
|
|
10
|
-
|
|
11
|
-
## 1. Installation
|
|
5
|
+
## Installation
|
|
12
6
|
|
|
13
7
|
```bash
|
|
14
8
|
npm install @rqmii_immersive/agent-react-sdk
|
|
15
9
|
```
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
### Peer Dependencies
|
|
18
12
|
|
|
19
13
|
```bash
|
|
20
|
-
npm install
|
|
14
|
+
npm install react react-dom lucide-react
|
|
15
|
+
# Optional (for 3D orb):
|
|
16
|
+
npm install three @react-three/fiber @react-three/drei
|
|
21
17
|
```
|
|
22
18
|
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
You must provide both URLs to the SDK:
|
|
19
|
+
## Quick Start
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
- `wsUrl`: realtime Socket.IO URL
|
|
29
|
-
|
|
30
|
-
Typical env values:
|
|
31
|
-
|
|
32
|
-
```env
|
|
33
|
-
VITE_AGENT_API_URL=https://api.example.com
|
|
34
|
-
VITE_AGENT_WS_URL=wss://realtime.example.com
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## 3. Import Surface
|
|
38
|
-
|
|
39
|
-
From the package root:
|
|
40
|
-
|
|
41
|
-
```js
|
|
42
|
-
import {
|
|
43
|
-
RqmiiAgentProvider,
|
|
44
|
-
RqmiiAgentRoom,
|
|
45
|
-
RqmiiCloudAvatarPlayer,
|
|
46
|
-
EpicPixelStreamingPlayer,
|
|
47
|
-
useRqmiiAgent,
|
|
48
|
-
useRqmiiConnection,
|
|
49
|
-
useRqmiiMessages,
|
|
50
|
-
useRqmiiVoice,
|
|
51
|
-
useRqmiiAvatar,
|
|
52
|
-
useRqmiiAudioElement,
|
|
53
|
-
useRqmiiPressToTalk,
|
|
54
|
-
useRqmiiVAD,
|
|
55
|
-
AGENT_TYPES,
|
|
56
|
-
CONNECTION_STATE,
|
|
57
|
-
CLOUD_STREAM_STATE,
|
|
58
|
-
SOCKET_EVENTS,
|
|
59
|
-
} from "@rqmii_immersive/agent-react-sdk";
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
If your bundler requires explicit style import, also import:
|
|
63
|
-
|
|
64
|
-
```js
|
|
65
|
-
import "@rqmii_immersive/agent-react-sdk/style.css";
|
|
66
|
-
```
|
|
21
|
+
### Core Setup
|
|
67
22
|
|
|
68
|
-
|
|
23
|
+
```tsx
|
|
24
|
+
import { RqmiiAgentProvider, useRqmiiConnection, useRqmiiMessages } from '@rqmii_immersive/agent-react-sdk';
|
|
69
25
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
} from "@rqmii_immersive/agent-react-sdk";
|
|
26
|
+
function App() {
|
|
27
|
+
return (
|
|
28
|
+
<RqmiiAgentProvider wsUrl="wss://your-server" restUrl="https://your-api">
|
|
29
|
+
<Chat />
|
|
30
|
+
</RqmiiAgentProvider>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
78
33
|
|
|
79
|
-
function
|
|
34
|
+
function Chat() {
|
|
35
|
+
const { initializeSession, isConnected } = useRqmiiConnection();
|
|
80
36
|
const { messages, sendTextMessage } = useRqmiiMessages();
|
|
81
|
-
const { connectionState, isSessionReady, error } = useRqmiiConnection();
|
|
82
|
-
const { isAvatarSpeaking, cloudStreamState } = useRqmiiAvatar();
|
|
83
37
|
|
|
84
38
|
return (
|
|
85
39
|
<div>
|
|
86
|
-
<div
|
|
87
|
-
<div>Ready: {String(isSessionReady)}</div>
|
|
88
|
-
<div>Avatar Speaking: {String(isAvatarSpeaking)}</div>
|
|
89
|
-
<div>Cloud Stream: {cloudStreamState}</div>
|
|
90
|
-
{error && <div style={{ color: "red" }}>{error}</div>}
|
|
91
|
-
|
|
40
|
+
{messages.map(m => <div key={m.id}>{m.text}</div>)}
|
|
92
41
|
<button onClick={() => sendTextMessage("Hello")}>Send</button>
|
|
93
|
-
<pre>{JSON.stringify(messages, null, 2)}</pre>
|
|
94
|
-
|
|
95
|
-
<RqmiiCloudAvatarPlayer muted={false} />
|
|
96
42
|
</div>
|
|
97
43
|
);
|
|
98
44
|
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Using RqmiiAgentRoom (auto-connect)
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
import { RqmiiAgentRoom, useRqmiiMessages } from '@rqmii_immersive/agent-react-sdk';
|
|
99
51
|
|
|
100
|
-
|
|
52
|
+
function App() {
|
|
101
53
|
return (
|
|
102
54
|
<RqmiiAgentRoom
|
|
103
|
-
wsUrl=
|
|
104
|
-
restUrl=
|
|
105
|
-
session={{
|
|
106
|
-
connect
|
|
107
|
-
onError={(e) => console.error(e)}
|
|
108
|
-
onInitialized={(data) => console.log("session initialized", data)}
|
|
55
|
+
wsUrl="wss://your-server"
|
|
56
|
+
restUrl="https://your-api"
|
|
57
|
+
session={{ apiKey: 'your-key', language: 'en' }}
|
|
109
58
|
>
|
|
110
|
-
<
|
|
59
|
+
<Chat />
|
|
111
60
|
</RqmiiAgentRoom>
|
|
112
61
|
);
|
|
113
62
|
}
|
|
114
63
|
```
|
|
115
64
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
### 5.1 Cloud Avatar
|
|
119
|
-
|
|
120
|
-
Use `session.mode = 'initialize'` with `apiKey` (or `publicChatId` / `agentId`).
|
|
121
|
-
|
|
122
|
-
- backend returns `streaming_url`
|
|
123
|
-
- render `RqmiiCloudAvatarPlayer`
|
|
124
|
-
- speaking state comes from avatar events, not audio chunks
|
|
125
|
-
|
|
126
|
-
```jsx
|
|
127
|
-
<RqmiiAgentRoom
|
|
128
|
-
wsUrl={WS_URL}
|
|
129
|
-
restUrl={REST_URL}
|
|
130
|
-
session={{ mode: "initialize", apiKey: API_KEY, language: "en" }}
|
|
131
|
-
connect
|
|
132
|
-
>
|
|
133
|
-
<RqmiiCloudAvatarPlayer muted={false} />
|
|
134
|
-
</RqmiiAgentRoom>
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### 5.2 Desktop Avatar (User Join)
|
|
138
|
-
|
|
139
|
-
User joins existing desktop avatar session by `uniqueId`:
|
|
140
|
-
|
|
141
|
-
```jsx
|
|
142
|
-
<RqmiiAgentRoom
|
|
143
|
-
wsUrl={WS_URL}
|
|
144
|
-
restUrl={REST_URL}
|
|
145
|
-
session={{ mode: "join_desktop", uniqueId: "A1B2C3" }}
|
|
146
|
-
connect
|
|
147
|
-
>
|
|
148
|
-
<DesktopUI />
|
|
149
|
-
</RqmiiAgentRoom>
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### 5.3 Text Agent
|
|
153
|
-
|
|
154
|
-
- initialize session
|
|
155
|
-
- send text using `sendTextMessage`
|
|
156
|
-
- read assistant chunks/final from `messages`
|
|
157
|
-
|
|
158
|
-
### 5.4 Voice / Text-and-Voice Agent
|
|
159
|
-
|
|
160
|
-
- send microphone chunks via `sendAudioChunk`
|
|
161
|
-
- signal utterance end via `endAudioStream`
|
|
162
|
-
- audio playback handled internally via `pcm-stream-player`
|
|
163
|
-
|
|
164
|
-
## 6. Avatar State Model (Important)
|
|
165
|
-
|
|
166
|
-
`isAvatarSpeaking` is server-event driven only:
|
|
167
|
-
|
|
168
|
-
- starts on `avatar_speaking`
|
|
169
|
-
- ends on `avatar_speaking_done`
|
|
170
|
-
|
|
171
|
-
This means avatar speaking state is independent from PCM playback.
|
|
172
|
-
|
|
173
|
-
For cloud avatar rendering lifecycle, `useRqmiiAvatar()` exposes:
|
|
174
|
-
|
|
175
|
-
- `cloudStreamState`
|
|
176
|
-
- `cloudStreamError`
|
|
177
|
-
- `isCloudStreamConnected`
|
|
178
|
-
- `isCloudStreamLoading`
|
|
179
|
-
|
|
180
|
-
`cloudStreamState` values:
|
|
181
|
-
|
|
182
|
-
- `idle`
|
|
183
|
-
- `connecting`
|
|
184
|
-
- `loading`
|
|
185
|
-
- `connected`
|
|
186
|
-
- `disconnected`
|
|
187
|
-
- `error`
|
|
188
|
-
|
|
189
|
-
## 7. Reconnection Model
|
|
190
|
-
|
|
191
|
-
The backend uses one-time session JWTs, so default Socket.IO auto-reconnect with the same token is not enough.
|
|
192
|
-
|
|
193
|
-
This SDK implements the coordinator reconnect contract:
|
|
65
|
+
### Full Chat Widget
|
|
194
66
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
3. on disconnect, SDK reconnects with reconnect handshake auth
|
|
198
|
-
4. on success, server emits `reconnect_success` and rotates token
|
|
67
|
+
```tsx
|
|
68
|
+
import { RqmiiAgentChat } from '@rqmii_immersive/agent-react-sdk/ui';
|
|
199
69
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
```jsx
|
|
203
|
-
<RqmiiAgentRoom
|
|
204
|
-
wsUrl={WS_URL}
|
|
205
|
-
restUrl={REST_URL}
|
|
206
|
-
reconnectOptions={{
|
|
207
|
-
enabled: true,
|
|
208
|
-
maxAttempts: 8,
|
|
209
|
-
initialDelayMs: 500,
|
|
210
|
-
maxDelayMs: 5000,
|
|
211
|
-
timeoutMs: 8000,
|
|
212
|
-
}}
|
|
213
|
-
session={{ mode: "initialize", apiKey: API_KEY }}
|
|
214
|
-
connect
|
|
215
|
-
>
|
|
216
|
-
<UI />
|
|
217
|
-
</RqmiiAgentRoom>
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
## 8. Provider-Only Integration (No Room Wrapper)
|
|
221
|
-
|
|
222
|
-
Use this when you need full manual control:
|
|
223
|
-
|
|
224
|
-
```jsx
|
|
225
|
-
import {
|
|
226
|
-
RqmiiAgentProvider,
|
|
227
|
-
useRqmiiConnection,
|
|
228
|
-
} from "@rqmii_immersive/agent-react-sdk";
|
|
229
|
-
|
|
230
|
-
function Controller() {
|
|
231
|
-
const { initializeSession, joinDesktopSession, disconnect } =
|
|
232
|
-
useRqmiiConnection();
|
|
233
|
-
|
|
234
|
-
return (
|
|
235
|
-
<div>
|
|
236
|
-
<button
|
|
237
|
-
onClick={() => initializeSession({ apiKey: API_KEY, language: "en" })}
|
|
238
|
-
>
|
|
239
|
-
Init
|
|
240
|
-
</button>
|
|
241
|
-
<button onClick={() => joinDesktopSession({ uniqueId: "A1B2C3" })}>
|
|
242
|
-
Join Desktop
|
|
243
|
-
</button>
|
|
244
|
-
<button onClick={disconnect}>Disconnect</button>
|
|
245
|
-
</div>
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
export default function App() {
|
|
70
|
+
function App() {
|
|
250
71
|
return (
|
|
251
|
-
<
|
|
252
|
-
|
|
253
|
-
|
|
72
|
+
<RqmiiAgentChat
|
|
73
|
+
wsUrl="wss://your-server"
|
|
74
|
+
restUrl="https://your-api"
|
|
75
|
+
publicChatId="your-chat-id"
|
|
76
|
+
/>
|
|
254
77
|
);
|
|
255
78
|
}
|
|
256
79
|
```
|
|
257
80
|
|
|
258
|
-
##
|
|
259
|
-
|
|
260
|
-
### `useRqmiiConnection()`
|
|
261
|
-
|
|
262
|
-
Returns:
|
|
263
|
-
|
|
264
|
-
- `connectionState`
|
|
265
|
-
- `isConnected`
|
|
266
|
-
- `isSessionReady`
|
|
267
|
-
- `error`
|
|
268
|
-
- `reconnectAttempt`
|
|
269
|
-
- `session`
|
|
270
|
-
- `initializeSession(args)`
|
|
271
|
-
- `joinDesktopSession(args)`
|
|
272
|
-
- `disconnect()`
|
|
273
|
-
|
|
274
|
-
### `useRqmiiMessages()`
|
|
275
|
-
|
|
276
|
-
Returns:
|
|
277
|
-
|
|
278
|
-
- `messages`
|
|
279
|
-
- `sendTextMessage(text)`
|
|
280
|
-
- `clearMessages()`
|
|
281
|
-
|
|
282
|
-
Message stream behavior:
|
|
283
|
-
|
|
284
|
-
- server chunks update streaming assistant message (`agent_response_chunk`)
|
|
285
|
-
- final response completes that message (`agent_response`)
|
|
81
|
+
## Architecture
|
|
286
82
|
|
|
287
|
-
###
|
|
83
|
+
### Entry Points
|
|
288
84
|
|
|
289
|
-
|
|
85
|
+
- `@rqmii_immersive/agent-react-sdk` — Core: provider, hooks, types, constants
|
|
86
|
+
- `@rqmii_immersive/agent-react-sdk/ui` — UI components: chat widget, avatar player, orb
|
|
87
|
+
- `@rqmii_immersive/agent-react-sdk/style.css` — Chat widget styles
|
|
290
88
|
|
|
291
|
-
|
|
292
|
-
- `endAudioStream()`
|
|
293
|
-
- `isAudioPlaying`
|
|
294
|
-
- `transcript`
|
|
295
|
-
- `partialTranscript`
|
|
296
|
-
- `interrupt()`
|
|
297
|
-
- `resumeAudioPlayback()`
|
|
298
|
-
- `attachAudioElement(element)`
|
|
89
|
+
### State Management
|
|
299
90
|
|
|
300
|
-
|
|
91
|
+
State is managed via `useReducer` with a single `RqmiiState` shape. All mutations go through typed actions.
|
|
301
92
|
|
|
302
|
-
|
|
93
|
+
### Event System
|
|
303
94
|
|
|
304
|
-
|
|
305
|
-
- `isAvatarSpeaking`
|
|
306
|
-
- `speakingSource` (`'avatar_events'`)
|
|
307
|
-
- `isCloudAvatar`
|
|
308
|
-
- `isDesktopAvatar`
|
|
309
|
-
- `cloudStreamState`
|
|
310
|
-
- `cloudStreamError`
|
|
311
|
-
- `isCloudStreamConnected`
|
|
312
|
-
- `isCloudStreamLoading`
|
|
313
|
-
- `setCloudStreamState(nextState, error?)`
|
|
95
|
+
The provider exposes an `events` EventEmitter for subscribing to lifecycle events:
|
|
314
96
|
|
|
315
|
-
|
|
97
|
+
```tsx
|
|
98
|
+
import { useRqmiiAgent } from '@rqmii_immersive/agent-react-sdk';
|
|
316
99
|
|
|
317
|
-
|
|
100
|
+
function Component() {
|
|
101
|
+
const { events } = useRqmiiAgent();
|
|
318
102
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
- sends `audio_end` automatically on release
|
|
327
|
-
- exposes ready-to-spread button handlers via `eventHandlers`
|
|
328
|
-
|
|
329
|
-
Minimal usage:
|
|
330
|
-
|
|
331
|
-
```jsx
|
|
332
|
-
const { eventHandlers, isRecording } = useRqmiiPressToTalk();
|
|
333
|
-
<button {...eventHandlers}>
|
|
334
|
-
{isRecording ? "Recording..." : "Hold to Talk"}
|
|
335
|
-
</button>;
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
### `useRqmiiVAD(options?)`
|
|
339
|
-
|
|
340
|
-
Built-in VAD (voice activity detection) mode using `@ricky0123/vad-react`.
|
|
341
|
-
|
|
342
|
-
- toggle VAD listening with `toggle()`
|
|
343
|
-
- auto interrupts on speech start (configurable)
|
|
344
|
-
- handles pre-speech padding and streaming chunks/end events
|
|
345
|
-
|
|
346
|
-
Minimal usage:
|
|
347
|
-
|
|
348
|
-
```jsx
|
|
349
|
-
const { toggle, isListening, isSpeaking } = useRqmiiVAD();
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
const unsub = events.on('session:ready', (payload) => {
|
|
105
|
+
console.log('Session ready', payload);
|
|
106
|
+
});
|
|
107
|
+
return unsub;
|
|
108
|
+
}, []);
|
|
109
|
+
}
|
|
350
110
|
```
|
|
351
111
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
`RqmiiCloudAvatarPlayer` props:
|
|
355
|
-
|
|
356
|
-
- `className`
|
|
357
|
-
- `style`
|
|
358
|
-
- `autoConnect` (default `true`)
|
|
359
|
-
- `muted` (default `false`)
|
|
360
|
-
- `onConnected()`
|
|
361
|
-
- `onDisconnected()`
|
|
362
|
-
- `onError(error)`
|
|
363
|
-
|
|
364
|
-
Internally it forwards cloud stream lifecycle to context state.
|
|
365
|
-
|
|
366
|
-
## 11. Error Handling Strategy
|
|
367
|
-
|
|
368
|
-
- fatal session/socket errors populate `error` in connection state
|
|
369
|
-
- `TTS_ERROR` socket errors are treated as non-fatal by default
|
|
370
|
-
- reconnect failures transition to `connectionState = failed`
|
|
371
|
-
|
|
372
|
-
Recommended UI behavior:
|
|
373
|
-
|
|
374
|
-
- show persistent banner for `error`
|
|
375
|
-
- show reconnect indicator while `connectionState === reconnecting`
|
|
376
|
-
- offer retry button that calls `initializeSession` again
|
|
377
|
-
|
|
378
|
-
## 12. Production Checklist
|
|
379
|
-
|
|
380
|
-
- use secure `https/wss` URLs in production
|
|
381
|
-
- ensure CORS allows browser origins for REST and Socket.IO
|
|
382
|
-
- pass correct API key/public chat id per environment
|
|
383
|
-
- monitor reconnect failures and auth errors in logs
|
|
384
|
-
- handle browser autoplay policies with user gesture before first audio
|
|
112
|
+
Available events: `session:ready`, `session:joined`, `session:terminated`, `session:expired`, `message:received`, `message:sent`, `audio:playing`, `audio:stopped`, `avatar:speaking`, `avatar:speaking_done`, `state:changed`, `connection:connected`, `connection:disconnected`, `connection:reconnecting`, `connection:failed`, `error`, `credits:exhausted`, `transcript`, `partial_transcript`, `interrupted`.
|
|
385
113
|
|
|
386
|
-
##
|
|
114
|
+
## API Reference
|
|
387
115
|
|
|
388
|
-
###
|
|
116
|
+
### RqmiiAgentProvider Props
|
|
389
117
|
|
|
390
|
-
|
|
118
|
+
| Prop | Type | Default | Description |
|
|
119
|
+
|------|------|---------|-------------|
|
|
120
|
+
| `wsUrl` | `string` | required | WebSocket server URL |
|
|
121
|
+
| `restUrl` | `string` | required | REST API base URL |
|
|
122
|
+
| `reconnectOptions` | `RqmiiReconnectOptions` | `{ enabled: true, maxAttempts: 8, initialDelayMs: 500, maxDelayMs: 5000, timeoutMs: 8000 }` | Reconnection config |
|
|
123
|
+
| `enableAudio` | `boolean` | `true` | Enable PCM audio playback |
|
|
124
|
+
| `pcmOptions` | `RqmiiPCMOptions` | `{ encoding: '16bitInt', channels: 1, sampleRate: 16000 }` | PCM player config |
|
|
125
|
+
| `debug` | `boolean` | `false` | Enable debug logging |
|
|
126
|
+
| `withCredentials` | `boolean` | `false` | Include cookies in CORS requests |
|
|
127
|
+
| `heartbeatIntervalSeconds` | `number` | `15` | Heartbeat interval |
|
|
128
|
+
| `onSessionExpired` | `(payload?) => void` | — | Callback |
|
|
129
|
+
| `onSessionTerminated` | `() => void` | — | Callback |
|
|
130
|
+
| `onError` | `(payload?) => void` | — | Callback |
|
|
131
|
+
| `onDisconnect` | `(reason?) => void` | — | Callback |
|
|
132
|
+
| `onReconnectSuccess` | `(payload?) => void` | — | Callback |
|
|
133
|
+
| `onReconnectFailed` | `(payload?) => void` | — | Callback |
|
|
391
134
|
|
|
392
|
-
|
|
393
|
-
- token is passed via SDK flow (do not manually override connect handshake)
|
|
394
|
-
- backend clocks are synchronized for JWT expiry
|
|
135
|
+
### Hooks
|
|
395
136
|
|
|
396
|
-
|
|
137
|
+
| Hook | Returns |
|
|
138
|
+
|------|---------|
|
|
139
|
+
| `useRqmiiAgent()` | Full context value |
|
|
140
|
+
| `useRqmiiConnection()` | Connection state + session actions |
|
|
141
|
+
| `useRqmiiSession()` | Session state booleans |
|
|
142
|
+
| `useRqmiiMessages()` | Messages array + send/clear |
|
|
143
|
+
| `useRqmiiVoice()` | Audio controls + transcript |
|
|
144
|
+
| `useRqmiiAvatar()` | Avatar state + cloud stream |
|
|
145
|
+
| `useRqmiiAudioElement(ref)` | Attaches audio element |
|
|
146
|
+
| `useRqmiiPressToTalk(options)` | PTT recording |
|
|
147
|
+
| `useRqmiiVAD(options)` | Voice Activity Detection |
|
|
148
|
+
| `useRqmiiEvents(event, handler, deps)` | Event subscription |
|
|
397
149
|
|
|
398
|
-
|
|
150
|
+
## Breaking Changes from v3
|
|
399
151
|
|
|
400
|
-
|
|
401
|
-
- `RqmiiCloudAvatarPlayer` is rendered
|
|
402
|
-
- network allows signaling/WebRTC paths
|
|
152
|
+
1. **`useRqmiiSessionState` renamed to `useRqmiiSession`** — The hook is now `useRqmiiSession()`.
|
|
403
153
|
|
|
404
|
-
|
|
154
|
+
2. **Context value spread** — The context value now includes all state fields directly (no nested `state` object). Access `ctx.messages` instead of `ctx.state.messages`.
|
|
405
155
|
|
|
406
|
-
|
|
156
|
+
3. **Event emitter replaces some callbacks** — While legacy callbacks (`onSessionExpired`, etc.) still work, the preferred approach is using `events.on()`.
|
|
407
157
|
|
|
408
|
-
|
|
409
|
-
- your UI reads `isAvatarSpeaking` from `useRqmiiAvatar()`
|
|
158
|
+
4. **TypeScript only** — All source is now `.ts`/`.tsx`. JavaScript consumers get full type inference via bundled `.d.ts` files.
|
|
410
159
|
|
|
411
|
-
|
|
160
|
+
5. **`terminateSession` return type simplified** — Now returns `Promise<{ success: boolean }>` instead of the previous shape with `skipped` and `error` fields.
|
|
412
161
|
|
|
413
|
-
|
|
162
|
+
6. **`useRqmiiVAD` return** — Added `isErrored` field to match the VAD library's state.
|
|
414
163
|
|
|
415
|
-
|
|
416
|
-
- browser has user interaction to unlock audio context
|
|
417
|
-
- `agent_audio_chunk` events are arriving from server
|
|
164
|
+
7. **Internal module structure changed** — If you were importing from internal paths (e.g., `@rqmii_immersive/agent-react-sdk/react/core/...`), those paths no longer exist. Use the public exports only.
|
|
418
165
|
|
|
419
|
-
##
|
|
166
|
+
## License
|
|
420
167
|
|
|
421
|
-
|
|
422
|
-
Use it inside client components (`"use client"`), since realtime sockets/media APIs are browser runtime features.
|
|
168
|
+
UNLICENSED
|