@rqmii_immersive/agent-react-sdk 1.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.
- package/README.frameworks.md +244 -0
- package/README.md +430 -0
- package/README.simple.md +114 -0
- package/dist/index.d.ts +285 -0
- package/dist/rqmii-react-agent-sdk.cjs +2938 -0
- package/dist/rqmii-react-agent-sdk.cjs.map +1 -0
- package/dist/rqmii-react-agent-sdk.css +1 -0
- package/dist/rqmii-react-agent-sdk.js +17085 -0
- package/dist/rqmii-react-agent-sdk.js.map +1 -0
- package/package.json +44 -0
package/README.simple.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Rqmii React Agent SDK (Simple Guide)
|
|
2
|
+
|
|
3
|
+
Minimal guide to integrate quickly.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @rqmii_immersive/agent-react-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Required Config
|
|
12
|
+
|
|
13
|
+
You need:
|
|
14
|
+
|
|
15
|
+
- `restUrl` -> FastAPI backend URL
|
|
16
|
+
- `wsUrl` -> realtime Socket.IO URL
|
|
17
|
+
|
|
18
|
+
Example env:
|
|
19
|
+
|
|
20
|
+
```env
|
|
21
|
+
VITE_FASTAPI_BACKEND_URL=https://api.example.com
|
|
22
|
+
VITE_WS_AUDIO_URL=wss://realtime.example.com
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Basic Usage
|
|
26
|
+
|
|
27
|
+
```jsx
|
|
28
|
+
import {
|
|
29
|
+
RqmiiAgentRoom,
|
|
30
|
+
useRqmiiConnection,
|
|
31
|
+
useRqmiiMessages,
|
|
32
|
+
useRqmiiPressToTalk,
|
|
33
|
+
} from "@rqmii_immersive/agent-react-sdk";
|
|
34
|
+
|
|
35
|
+
function ChatUI() {
|
|
36
|
+
const { connectionState, isSessionReady, error } = useRqmiiConnection();
|
|
37
|
+
const { messages, sendTextMessage } = useRqmiiMessages();
|
|
38
|
+
const { eventHandlers, isRecording } = useRqmiiPressToTalk();
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div>
|
|
42
|
+
<div>{connectionState}</div>
|
|
43
|
+
<div>ready: {String(isSessionReady)}</div>
|
|
44
|
+
{error && <div style={{ color: "red" }}>{error}</div>}
|
|
45
|
+
|
|
46
|
+
<button onClick={() => sendTextMessage("Hello")}>Send</button>
|
|
47
|
+
<button {...eventHandlers}>
|
|
48
|
+
{isRecording ? "Recording..." : "Hold to Talk"}
|
|
49
|
+
</button>
|
|
50
|
+
<pre>{JSON.stringify(messages, null, 2)}</pre>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default function App() {
|
|
56
|
+
return (
|
|
57
|
+
<RqmiiAgentRoom
|
|
58
|
+
wsUrl={import.meta.env.VITE_WS_AUDIO_URL}
|
|
59
|
+
restUrl={import.meta.env.VITE_FASTAPI_BACKEND_URL}
|
|
60
|
+
session={{ mode: "initialize", apiKey: "YOUR_API_KEY", language: "en" }}
|
|
61
|
+
connect
|
|
62
|
+
>
|
|
63
|
+
<ChatUI />
|
|
64
|
+
</RqmiiAgentRoom>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Cloud Avatar
|
|
70
|
+
|
|
71
|
+
```jsx
|
|
72
|
+
import {
|
|
73
|
+
RqmiiCloudAvatarPlayer,
|
|
74
|
+
useRqmiiAvatar,
|
|
75
|
+
} from "@rqmii_immersive/agent-react-sdk";
|
|
76
|
+
|
|
77
|
+
function CloudAvatarUI() {
|
|
78
|
+
const { isAvatarSpeaking, cloudStreamState } = useRqmiiAvatar();
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<>
|
|
82
|
+
<div>speaking: {String(isAvatarSpeaking)}</div>
|
|
83
|
+
<div>stream: {cloudStreamState}</div>
|
|
84
|
+
<RqmiiCloudAvatarPlayer muted={false} />
|
|
85
|
+
</>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Desktop Avatar Join
|
|
91
|
+
|
|
92
|
+
```jsx
|
|
93
|
+
<RqmiiAgentRoom
|
|
94
|
+
wsUrl={WS_URL}
|
|
95
|
+
restUrl={REST_URL}
|
|
96
|
+
session={{ mode: "join_desktop", uniqueId: "A1B2C3" }}
|
|
97
|
+
connect
|
|
98
|
+
>
|
|
99
|
+
<YourUI />
|
|
100
|
+
</RqmiiAgentRoom>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Voice Input / Output
|
|
104
|
+
|
|
105
|
+
- send mic chunks: `sendAudioChunk(chunk)`
|
|
106
|
+
- end utterance: `endAudioStream()`
|
|
107
|
+
- interrupt: `interrupt()`
|
|
108
|
+
- SDK plays output audio internally using `pcm-stream-player`
|
|
109
|
+
|
|
110
|
+
## Notes
|
|
111
|
+
|
|
112
|
+
- Reconnection is built-in and follows backend reconnect credential flow.
|
|
113
|
+
- Avatar speaking state comes from backend avatar events.
|
|
114
|
+
- For full docs, see `README.md`.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
export type AgentType =
|
|
4
|
+
| 'text'
|
|
5
|
+
| 'voice'
|
|
6
|
+
| 'text_and_voice'
|
|
7
|
+
| 'cloud_avatar'
|
|
8
|
+
| 'desktop_avatar'
|
|
9
|
+
| (string & {});
|
|
10
|
+
|
|
11
|
+
export type ConnectionState =
|
|
12
|
+
| 'idle'
|
|
13
|
+
| 'initializing'
|
|
14
|
+
| 'connecting'
|
|
15
|
+
| 'connected'
|
|
16
|
+
| 'reconnecting'
|
|
17
|
+
| 'failed'
|
|
18
|
+
| 'ended'
|
|
19
|
+
| (string & {});
|
|
20
|
+
|
|
21
|
+
export type CloudStreamState =
|
|
22
|
+
| 'idle'
|
|
23
|
+
| 'connecting'
|
|
24
|
+
| 'loading'
|
|
25
|
+
| 'connected'
|
|
26
|
+
| 'disconnected'
|
|
27
|
+
| 'error'
|
|
28
|
+
| (string & {});
|
|
29
|
+
|
|
30
|
+
export interface RqmiiSessionInfo {
|
|
31
|
+
sessionId: string | null;
|
|
32
|
+
role: string | null;
|
|
33
|
+
agentType: AgentType | null;
|
|
34
|
+
streamingUrl: string | null;
|
|
35
|
+
uniqueId: string | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface RqmiiMessage {
|
|
39
|
+
id: string;
|
|
40
|
+
role: 'assistant' | 'user' | string;
|
|
41
|
+
text: string;
|
|
42
|
+
streaming?: boolean;
|
|
43
|
+
timestamp?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface RqmiiReconnectOptions {
|
|
47
|
+
enabled?: boolean;
|
|
48
|
+
maxAttempts?: number;
|
|
49
|
+
initialDelayMs?: number;
|
|
50
|
+
maxDelayMs?: number;
|
|
51
|
+
timeoutMs?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface RqmiiPCMOptions {
|
|
55
|
+
encoding?: string;
|
|
56
|
+
channels?: number;
|
|
57
|
+
sampleRate?: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface InitializeSessionArgs {
|
|
61
|
+
apiKey?: string;
|
|
62
|
+
publicChatId?: string;
|
|
63
|
+
agentId?: string;
|
|
64
|
+
language?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface JoinDesktopSessionArgs {
|
|
68
|
+
uniqueId: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface RqmiiAgentProviderProps {
|
|
72
|
+
children?: React.ReactNode;
|
|
73
|
+
wsUrl: string;
|
|
74
|
+
restUrl: string;
|
|
75
|
+
reconnectOptions?: RqmiiReconnectOptions;
|
|
76
|
+
enableAudio?: boolean;
|
|
77
|
+
pcmOptions?: RqmiiPCMOptions;
|
|
78
|
+
debug?: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface RqmiiAgentRoomSessionInitialize {
|
|
82
|
+
mode?: 'initialize';
|
|
83
|
+
apiKey?: string;
|
|
84
|
+
publicChatId?: string;
|
|
85
|
+
agentId?: string;
|
|
86
|
+
language?: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface RqmiiAgentRoomSessionJoinDesktop {
|
|
90
|
+
mode: 'join_desktop';
|
|
91
|
+
uniqueId: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type RqmiiAgentRoomSession =
|
|
95
|
+
| RqmiiAgentRoomSessionInitialize
|
|
96
|
+
| RqmiiAgentRoomSessionJoinDesktop;
|
|
97
|
+
|
|
98
|
+
export interface RqmiiAgentRoomProps extends RqmiiAgentProviderProps {
|
|
99
|
+
session?: RqmiiAgentRoomSession;
|
|
100
|
+
connect?: boolean;
|
|
101
|
+
onError?: (error: unknown) => void;
|
|
102
|
+
onInitialized?: (data: any) => void;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface RqmiiCloudAvatarPlayerProps {
|
|
106
|
+
className?: string;
|
|
107
|
+
style?: React.CSSProperties;
|
|
108
|
+
autoConnect?: boolean;
|
|
109
|
+
muted?: boolean;
|
|
110
|
+
onConnected?: () => void;
|
|
111
|
+
onDisconnected?: () => void;
|
|
112
|
+
onError?: (error: unknown) => void;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface EpicPixelStreamingPlayerProps {
|
|
116
|
+
signallingUrl?: string;
|
|
117
|
+
autoConnect?: boolean;
|
|
118
|
+
width?: string | number;
|
|
119
|
+
height?: string | number;
|
|
120
|
+
onConnecting?: () => void;
|
|
121
|
+
onLoading?: () => void;
|
|
122
|
+
onConnected?: () => void;
|
|
123
|
+
onDisconnected?: () => void;
|
|
124
|
+
onError?: (error: unknown) => void;
|
|
125
|
+
muted?: boolean;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface UseRqmiiConnectionReturn {
|
|
129
|
+
connectionState: ConnectionState;
|
|
130
|
+
isConnected: boolean;
|
|
131
|
+
isSessionReady: boolean;
|
|
132
|
+
error: string | null;
|
|
133
|
+
reconnectAttempt: number;
|
|
134
|
+
session: RqmiiSessionInfo;
|
|
135
|
+
initializeSession: (args?: InitializeSessionArgs) => Promise<any>;
|
|
136
|
+
joinDesktopSession: (args: JoinDesktopSessionArgs) => Promise<any>;
|
|
137
|
+
disconnect: () => void;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface UseRqmiiMessagesReturn {
|
|
141
|
+
messages: RqmiiMessage[];
|
|
142
|
+
sendTextMessage: (text: string) => boolean;
|
|
143
|
+
clearMessages: () => void;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface UseRqmiiVoiceReturn {
|
|
147
|
+
sendAudioChunk: (audio: ArrayBuffer | Uint8Array | unknown) => boolean;
|
|
148
|
+
endAudioStream: () => boolean;
|
|
149
|
+
isAudioPlaying: boolean;
|
|
150
|
+
transcript: unknown;
|
|
151
|
+
partialTranscript: unknown;
|
|
152
|
+
interrupt: () => boolean;
|
|
153
|
+
resumeAudioPlayback: () => Promise<void>;
|
|
154
|
+
attachAudioElement: (element: HTMLAudioElement | null) => void;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface UseRqmiiAvatarReturn {
|
|
158
|
+
streamingUrl: string | null;
|
|
159
|
+
isAvatarSpeaking: boolean;
|
|
160
|
+
speakingSource: 'avatar_events';
|
|
161
|
+
isCloudAvatar: boolean;
|
|
162
|
+
isDesktopAvatar: boolean;
|
|
163
|
+
cloudStreamState: CloudStreamState;
|
|
164
|
+
cloudStreamError: string | null;
|
|
165
|
+
isCloudStreamConnected: boolean;
|
|
166
|
+
isCloudStreamLoading: boolean;
|
|
167
|
+
setCloudStreamState: (nextState: CloudStreamState, error?: unknown) => void;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface UseRqmiiPressToTalkOptions {
|
|
171
|
+
onAudioChunk?: (chunk: ArrayBuffer) => void;
|
|
172
|
+
onAudioEnd?: () => void;
|
|
173
|
+
onError?: (error: unknown) => void;
|
|
174
|
+
holdDelayMs?: number;
|
|
175
|
+
timesliceMs?: number;
|
|
176
|
+
interruptOnHoldStart?: boolean;
|
|
177
|
+
audioConstraints?: MediaTrackConstraints;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface UseRqmiiPressToTalkReturn {
|
|
181
|
+
isPressing: boolean;
|
|
182
|
+
isRecording: boolean;
|
|
183
|
+
micError: string | null;
|
|
184
|
+
startRecording: () => Promise<boolean>;
|
|
185
|
+
stopRecording: (args?: { discard?: boolean }) => boolean;
|
|
186
|
+
startPress: () => void;
|
|
187
|
+
stopPress: () => void;
|
|
188
|
+
eventHandlers: React.HTMLAttributes<HTMLElement>;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface UseRqmiiVADOptions {
|
|
192
|
+
onAudioChunk?: (chunk: ArrayBuffer) => void;
|
|
193
|
+
onAudioEnd?: () => void;
|
|
194
|
+
onSpeechStart?: () => void;
|
|
195
|
+
onSpeechEnd?: () => void;
|
|
196
|
+
onVADMisfire?: () => void;
|
|
197
|
+
onError?: (error: unknown) => void;
|
|
198
|
+
interruptOnSpeechStart?: boolean;
|
|
199
|
+
forceAudioMp4?: boolean;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export interface UseRqmiiVADReturn {
|
|
203
|
+
isListening: boolean;
|
|
204
|
+
isLoading: boolean;
|
|
205
|
+
isSpeaking: boolean;
|
|
206
|
+
micError: string | null;
|
|
207
|
+
toggle: () => void;
|
|
208
|
+
start: () => void;
|
|
209
|
+
pause: () => void;
|
|
210
|
+
userSpeaking: boolean;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface RqmiiAgentContextValue extends UseRqmiiConnectionReturn {
|
|
214
|
+
isAudioPlaying: boolean;
|
|
215
|
+
isAvatarSpeaking: boolean;
|
|
216
|
+
cloudStream: {
|
|
217
|
+
state: CloudStreamState;
|
|
218
|
+
error: string | null;
|
|
219
|
+
};
|
|
220
|
+
transcript: unknown;
|
|
221
|
+
partialTranscript: unknown;
|
|
222
|
+
messages: RqmiiMessage[];
|
|
223
|
+
initializeSession: (args?: InitializeSessionArgs) => Promise<any>;
|
|
224
|
+
joinDesktopSession: (args: JoinDesktopSessionArgs) => Promise<any>;
|
|
225
|
+
disconnect: () => void;
|
|
226
|
+
emit: (event: string, payload?: unknown) => boolean;
|
|
227
|
+
sendTextMessage: (text: string) => boolean;
|
|
228
|
+
sendAudioChunk: (audio: ArrayBuffer | Uint8Array | unknown) => boolean;
|
|
229
|
+
endAudioStream: () => boolean;
|
|
230
|
+
interrupt: () => boolean;
|
|
231
|
+
refreshSessionActivity: () => boolean;
|
|
232
|
+
clearSessionHistory: () => boolean;
|
|
233
|
+
clearMessages: () => void;
|
|
234
|
+
resumeAudioPlayback: () => Promise<void>;
|
|
235
|
+
attachAudioElement: (element: HTMLAudioElement | null) => void;
|
|
236
|
+
setCloudStreamState: (nextState: CloudStreamState, error?: unknown) => void;
|
|
237
|
+
audioElement: HTMLAudioElement | null;
|
|
238
|
+
socket: any;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export const AGENT_TYPES: {
|
|
242
|
+
readonly TEXT: 'text';
|
|
243
|
+
readonly VOICE: 'voice';
|
|
244
|
+
readonly TEXT_AND_VOICE: 'text_and_voice';
|
|
245
|
+
readonly CLOUD_AVATAR: 'cloud_avatar';
|
|
246
|
+
readonly DESKTOP_AVATAR: 'desktop_avatar';
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
export const SOCKET_EVENTS: Record<string, string>;
|
|
250
|
+
|
|
251
|
+
export const CONNECTION_STATE: {
|
|
252
|
+
readonly IDLE: 'idle';
|
|
253
|
+
readonly INITIALIZING: 'initializing';
|
|
254
|
+
readonly CONNECTING: 'connecting';
|
|
255
|
+
readonly CONNECTED: 'connected';
|
|
256
|
+
readonly RECONNECTING: 'reconnecting';
|
|
257
|
+
readonly FAILED: 'failed';
|
|
258
|
+
readonly ENDED: 'ended';
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
export const CLOUD_STREAM_STATE: {
|
|
262
|
+
readonly IDLE: 'idle';
|
|
263
|
+
readonly CONNECTING: 'connecting';
|
|
264
|
+
readonly LOADING: 'loading';
|
|
265
|
+
readonly CONNECTED: 'connected';
|
|
266
|
+
readonly DISCONNECTED: 'disconnected';
|
|
267
|
+
readonly ERROR: 'error';
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
export function RqmiiAgentProvider(props: RqmiiAgentProviderProps): React.JSX.Element;
|
|
271
|
+
export function useRqmiiAgentContext(): RqmiiAgentContextValue;
|
|
272
|
+
|
|
273
|
+
export function useRqmiiAgent(): RqmiiAgentContextValue;
|
|
274
|
+
export function useRqmiiConnection(): UseRqmiiConnectionReturn;
|
|
275
|
+
export function useRqmiiMessages(): UseRqmiiMessagesReturn;
|
|
276
|
+
export function useRqmiiVoice(): UseRqmiiVoiceReturn;
|
|
277
|
+
export function useRqmiiAvatar(): UseRqmiiAvatarReturn;
|
|
278
|
+
export function useRqmiiAudioElement(audioRef: React.RefObject<HTMLAudioElement | null>): void;
|
|
279
|
+
export function useRqmiiPressToTalk(options?: UseRqmiiPressToTalkOptions): UseRqmiiPressToTalkReturn;
|
|
280
|
+
export function useRqmiiVAD(options?: UseRqmiiVADOptions): UseRqmiiVADReturn;
|
|
281
|
+
|
|
282
|
+
export function RqmiiAgentRoom(props: RqmiiAgentRoomProps): React.JSX.Element;
|
|
283
|
+
export function RqmiiCloudAvatarPlayer(props: RqmiiCloudAvatarPlayerProps): React.JSX.Element | null;
|
|
284
|
+
export const EpicPixelStreamingPlayer: React.ComponentType<EpicPixelStreamingPlayerProps>;
|
|
285
|
+
|