@leia-org/luke-client 0.1.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 (51) hide show
  1. package/README.md +69 -0
  2. package/dist/Luke.css +430 -0
  3. package/dist/components/AudioControls.d.ts +12 -0
  4. package/dist/components/AudioControls.d.ts.map +1 -0
  5. package/dist/components/AudioControls.js +43 -0
  6. package/dist/components/AudioControls.js.map +1 -0
  7. package/dist/components/ConnectionStatus.d.ts +7 -0
  8. package/dist/components/ConnectionStatus.d.ts.map +1 -0
  9. package/dist/components/ConnectionStatus.js +33 -0
  10. package/dist/components/ConnectionStatus.js.map +1 -0
  11. package/dist/components/LukeProvider.d.ts +5 -0
  12. package/dist/components/LukeProvider.d.ts.map +1 -0
  13. package/dist/components/LukeProvider.js +25 -0
  14. package/dist/components/LukeProvider.js.map +1 -0
  15. package/dist/components/TranscriptionDisplay.d.ts +9 -0
  16. package/dist/components/TranscriptionDisplay.d.ts.map +1 -0
  17. package/dist/components/TranscriptionDisplay.js +22 -0
  18. package/dist/components/TranscriptionDisplay.js.map +1 -0
  19. package/dist/hooks/useLuke.d.ts +3 -0
  20. package/dist/hooks/useLuke.d.ts.map +1 -0
  21. package/dist/hooks/useLuke.js +382 -0
  22. package/dist/hooks/useLuke.js.map +1 -0
  23. package/dist/index.d.ts +11 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +12 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/types.d.ts +89 -0
  28. package/dist/types.d.ts.map +1 -0
  29. package/dist/types.js +4 -0
  30. package/dist/types.js.map +1 -0
  31. package/dist/ui/VoiceClientUI.d.ts +17 -0
  32. package/dist/ui/VoiceClientUI.d.ts.map +1 -0
  33. package/dist/ui/VoiceClientUI.js +84 -0
  34. package/dist/ui/VoiceClientUI.js.map +1 -0
  35. package/dist/ui/components/Icons.d.ts +8 -0
  36. package/dist/ui/components/Icons.d.ts.map +1 -0
  37. package/dist/ui/components/Icons.js +9 -0
  38. package/dist/ui/components/Icons.js.map +1 -0
  39. package/dist/ui/index.d.ts +3 -0
  40. package/dist/ui/index.d.ts.map +1 -0
  41. package/dist/ui/index.js +3 -0
  42. package/dist/ui/index.js.map +1 -0
  43. package/dist/worker/audio-utils.d.ts +5 -0
  44. package/dist/worker/audio-utils.d.ts.map +1 -0
  45. package/dist/worker/audio-utils.js +52 -0
  46. package/dist/worker/audio-utils.js.map +1 -0
  47. package/dist/worker/audio.worker.d.ts +2 -0
  48. package/dist/worker/audio.worker.d.ts.map +1 -0
  49. package/dist/worker/audio.worker.js +60 -0
  50. package/dist/worker/audio.worker.js.map +1 -0
  51. package/package.json +37 -0
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export function TranscriptionDisplay({ messages, className, renderMessage, }) {
3
+ // Default message rendering
4
+ const defaultRenderMessage = (message, index) => (_jsxs("div", { style: {
5
+ padding: '8px 12px',
6
+ marginBottom: 8,
7
+ borderRadius: 8,
8
+ maxWidth: '80%',
9
+ alignSelf: message.role === 'user' ? 'flex-end' : 'flex-start',
10
+ backgroundColor: message.role === 'user' ? '#3b82f6' : '#f3f4f6',
11
+ color: message.role === 'user' ? 'white' : '#1f2937',
12
+ opacity: message.final ? 1 : 0.7,
13
+ }, children: [_jsx("div", { style: { fontSize: 12, opacity: 0.7, marginBottom: 4 }, children: message.role === 'user' ? 'You' : 'Assistant' }), _jsx("div", { children: message.text })] }, `${message.timestamp}-${index}`));
14
+ return (_jsx("div", { className: className, style: {
15
+ display: 'flex',
16
+ flexDirection: 'column',
17
+ gap: 4,
18
+ padding: 16,
19
+ overflowY: 'auto',
20
+ }, children: messages.map((msg, idx) => renderMessage ? renderMessage(msg, idx) : defaultRenderMessage(msg, idx)) }));
21
+ }
22
+ //# sourceMappingURL=TranscriptionDisplay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TranscriptionDisplay.js","sourceRoot":"","sources":["../../src/components/TranscriptionDisplay.tsx"],"names":[],"mappings":";AAaA,MAAM,UAAU,oBAAoB,CAAC,EACjC,QAAQ,EACR,SAAS,EACT,aAAa,GACW;IACxB,4BAA4B;IAC5B,MAAM,oBAAoB,GAAG,CAAC,OAA6B,EAAE,KAAa,EAAE,EAAE,CAAC,CAC3E,eAEI,KAAK,EAAE;YACH,OAAO,EAAE,UAAU;YACnB,YAAY,EAAE,CAAC;YACf,YAAY,EAAE,CAAC;YACf,QAAQ,EAAE,KAAK;YACf,SAAS,EAAE,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY;YAC9D,eAAe,EAAE,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YAChE,KAAK,EAAE,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;YACpD,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;SACnC,aAED,cAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,YACtD,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,GAC5C,EACN,wBAAM,OAAO,CAAC,IAAI,GAAO,KAfpB,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,EAAE,CAgBlC,CACT,CAAC;IAEF,OAAO,CACH,cACI,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE;YACH,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,QAAQ;YACvB,GAAG,EAAE,CAAC;YACN,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,MAAM;SACpB,YAEA,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CACvB,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAC3E,GACC,CACT,CAAC;AACN,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { UseLukeConfig, UseLukeReturn } from '../types.js';
2
+ export declare function useLuke(config: UseLukeConfig): UseLukeReturn;
3
+ //# sourceMappingURL=useLuke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLuke.d.ts","sourceRoot":"","sources":["../../src/hooks/useLuke.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACR,aAAa,EACb,aAAa,EAOhB,MAAM,aAAa,CAAC;AAErB,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAya5D"}
@@ -0,0 +1,382 @@
1
+ // useLuke Hook
2
+ // Main React hook for realtime AI voice communication
3
+ import { useState, useCallback, useRef, useEffect } from 'react';
4
+ export function useLuke(config) {
5
+ // Connection state
6
+ const [connectionState, setConnectionState] = useState('disconnected');
7
+ const [error, setError] = useState(null);
8
+ // Provider and voice state
9
+ const [providers, setProviders] = useState([]);
10
+ const [selectedProvider, setSelectedProvider] = useState(null);
11
+ const [selectedVoice, setSelectedVoice] = useState(null);
12
+ // Session state
13
+ const [sessionId, setSessionId] = useState(null);
14
+ const [sampleRate, setSampleRate] = useState(null);
15
+ // Audio state
16
+ const [isRecording, setIsRecording] = useState(false);
17
+ const [audioLevel, setAudioLevel] = useState(0);
18
+ // Transcription state
19
+ const [transcription, setTranscription] = useState([]);
20
+ // Refs for WebSocket and audio
21
+ const wsRef = useRef(null);
22
+ const audioContextRef = useRef(null);
23
+ const mediaStreamRef = useRef(null);
24
+ const workletNodeRef = useRef(null);
25
+ const isRecordingRef = useRef(false);
26
+ // Playback queue for received audio
27
+ const playbackQueueRef = useRef([]);
28
+ const isPlayingRef = useRef(false);
29
+ // Build WebSocket URL with auth token
30
+ const buildWsUrl = useCallback(() => {
31
+ const url = new URL(config.serverUrl);
32
+ if (config.authToken) {
33
+ url.searchParams.set('token', config.authToken);
34
+ }
35
+ return url.toString();
36
+ }, [config.serverUrl, config.authToken]);
37
+ // Handle incoming server messages
38
+ const handleServerMessage = useCallback((event) => {
39
+ // Binary data is audio - decode and queue for playback
40
+ if (event.data instanceof ArrayBuffer) {
41
+ const decoded = decodeAudio(event.data);
42
+ playbackQueueRef.current.push(decoded);
43
+ playNextAudio();
44
+ return;
45
+ }
46
+ try {
47
+ const message = JSON.parse(event.data);
48
+ switch (message.type) {
49
+ case 'handshake':
50
+ setProviders(message.providers);
51
+ // Auto-select if only one provider or if there's a default
52
+ if (message.providers.length === 1) {
53
+ const provider = message.providers[0];
54
+ setSelectedProvider(provider);
55
+ setSelectedVoice(provider.voices[0] ?? null);
56
+ // Auto-select provider on server
57
+ if (wsRef.current?.readyState === WebSocket.OPEN) {
58
+ wsRef.current.send(JSON.stringify({ type: 'select_provider', providerId: provider.id }));
59
+ }
60
+ }
61
+ else if (message.defaultProvider) {
62
+ const defaultP = message.providers.find((p) => p.id === message.defaultProvider);
63
+ if (defaultP) {
64
+ setSelectedProvider(defaultP);
65
+ setSelectedVoice(defaultP.voices[0] ?? null);
66
+ // Auto-select default provider on server
67
+ if (wsRef.current?.readyState === WebSocket.OPEN) {
68
+ wsRef.current.send(JSON.stringify({ type: 'select_provider', providerId: defaultP.id }));
69
+ }
70
+ }
71
+ }
72
+ break;
73
+ case 'session_ready':
74
+ setSessionId(message.sessionId);
75
+ setSampleRate(message.sampleRate);
76
+ setConnectionState('connected');
77
+ config.onConnect?.();
78
+ break;
79
+ case 'transcription':
80
+ const transcriptionMsg = {
81
+ role: message.role,
82
+ text: message.text,
83
+ final: message.final,
84
+ timestamp: Date.now(),
85
+ };
86
+ setTranscription((prev) => {
87
+ if (prev.length > 0) {
88
+ const lastMsg = prev[prev.length - 1];
89
+ // 1. Update existing partial if matching role (handles streaming updates and final confirmation)
90
+ if (lastMsg.role === message.role && !lastMsg.final) {
91
+ const updated = [...prev];
92
+ updated[updated.length - 1] = transcriptionMsg;
93
+ return updated;
94
+ }
95
+ // 2. Prevent exact duplicates (same text, same role) - even if last is final
96
+ // Use normalized comparison (trim whitespace)
97
+ const normalizedLast = lastMsg.text.trim();
98
+ const normalizedNew = message.text.trim();
99
+ if (lastMsg.role === message.role && normalizedLast === normalizedNew) {
100
+ // If they match, just update the final flag if needed
101
+ if (!lastMsg.final && message.final) {
102
+ const updated = [...prev];
103
+ updated[updated.length - 1] = transcriptionMsg;
104
+ return updated;
105
+ }
106
+ return prev; // Skip duplicate
107
+ }
108
+ // 3. Cleanup "zombie" partials on role switch (interruption)
109
+ if (lastMsg.role !== message.role && !lastMsg.final && lastMsg.text.trim().length < 5) {
110
+ const cleaned = prev.slice(0, -1);
111
+ return [...cleaned, transcriptionMsg];
112
+ }
113
+ }
114
+ // Otherwise append as a new message
115
+ return [...prev, transcriptionMsg];
116
+ });
117
+ config.onTranscription?.(transcriptionMsg);
118
+ break;
119
+ case 'turn_complete':
120
+ // Model finished speaking
121
+ break;
122
+ case 'interrupted':
123
+ // Clear playback queue on interruption
124
+ playbackQueueRef.current = [];
125
+ break;
126
+ case 'error':
127
+ const err = new Error(`${message.code}: ${message.message}`);
128
+ setError(err);
129
+ config.onError?.(err);
130
+ break;
131
+ }
132
+ }
133
+ catch {
134
+ // Ignore parse errors
135
+ }
136
+ }, [config]);
137
+ // Send message to server
138
+ const sendMessage = useCallback((message) => {
139
+ if (wsRef.current?.readyState === WebSocket.OPEN) {
140
+ wsRef.current.send(JSON.stringify(message));
141
+ }
142
+ }, []);
143
+ // Connect to server
144
+ const connect = useCallback(() => {
145
+ if (wsRef.current)
146
+ return;
147
+ setConnectionState('connecting');
148
+ setError(null);
149
+ const ws = new WebSocket(buildWsUrl());
150
+ wsRef.current = ws;
151
+ ws.binaryType = 'arraybuffer';
152
+ ws.onopen = () => {
153
+ // Wait for handshake message
154
+ };
155
+ ws.onmessage = handleServerMessage;
156
+ ws.onerror = () => {
157
+ setError(new Error('WebSocket connection failed'));
158
+ setConnectionState('error');
159
+ };
160
+ ws.onclose = () => {
161
+ wsRef.current = null;
162
+ setConnectionState('disconnected');
163
+ setSessionId(null);
164
+ config.onDisconnect?.();
165
+ };
166
+ }, [buildWsUrl, handleServerMessage, config]);
167
+ // Audio encoding helper (inline, no worker needed)
168
+ const encodeAudio = useCallback((samples, targetRate) => {
169
+ // Resample from 48kHz to target rate
170
+ const ratio = 48000 / targetRate;
171
+ const outputLength = Math.ceil(samples.length / ratio);
172
+ const resampled = new Float32Array(outputLength);
173
+ for (let i = 0; i < outputLength; i++) {
174
+ const srcIndex = i * ratio;
175
+ const srcFloor = Math.floor(srcIndex);
176
+ const srcCeil = Math.min(srcFloor + 1, samples.length - 1);
177
+ const frac = srcIndex - srcFloor;
178
+ resampled[i] = samples[srcFloor] * (1 - frac) + samples[srcCeil] * frac;
179
+ }
180
+ // Convert to 16-bit PCM
181
+ const pcm = new Int16Array(resampled.length);
182
+ for (let i = 0; i < resampled.length; i++) {
183
+ const s = Math.max(-1, Math.min(1, resampled[i]));
184
+ pcm[i] = s < 0 ? s * 0x8000 : s * 0x7fff;
185
+ }
186
+ // Calculate level
187
+ let sum = 0;
188
+ for (let i = 0; i < resampled.length; i++) {
189
+ sum += resampled[i] * resampled[i];
190
+ }
191
+ setAudioLevel(Math.sqrt(sum / resampled.length));
192
+ return pcm.buffer;
193
+ }, []);
194
+ // Audio decoding helper
195
+ const decodeAudio = useCallback((pcmData) => {
196
+ const pcm = new Int16Array(pcmData);
197
+ const float32 = new Float32Array(pcm.length);
198
+ for (let i = 0; i < pcm.length; i++) {
199
+ float32[i] = pcm[i] / (pcm[i] < 0 ? 0x8000 : 0x7fff);
200
+ }
201
+ // Resample from 24kHz to 48kHz
202
+ const ratio = 24000 / 48000;
203
+ const outputLength = Math.ceil(float32.length / ratio);
204
+ const resampled = new Float32Array(outputLength);
205
+ for (let i = 0; i < outputLength; i++) {
206
+ const srcIndex = i * ratio;
207
+ const srcFloor = Math.floor(srcIndex);
208
+ const srcCeil = Math.min(srcFloor + 1, float32.length - 1);
209
+ const frac = srcIndex - srcFloor;
210
+ resampled[i] = float32[srcFloor] * (1 - frac) + float32[srcCeil] * frac;
211
+ }
212
+ return resampled;
213
+ }, []);
214
+ // Disconnect from server
215
+ const disconnect = useCallback(() => {
216
+ stopRecording();
217
+ wsRef.current?.close();
218
+ wsRef.current = null;
219
+ audioContextRef.current?.close();
220
+ audioContextRef.current = null;
221
+ }, []);
222
+ // Select provider
223
+ const selectProvider = useCallback((providerId, voiceId) => {
224
+ const provider = providers.find((p) => p.id === providerId);
225
+ if (!provider)
226
+ return;
227
+ setSelectedProvider(provider);
228
+ const voice = voiceId ? provider.voices.find((v) => v.id === voiceId) : provider.voices[0];
229
+ setSelectedVoice(voice ?? null);
230
+ sendMessage({ type: 'select_provider', providerId, voiceId: voice?.id });
231
+ }, [providers, sendMessage]);
232
+ // Select voice
233
+ const selectVoice = useCallback((voiceId) => {
234
+ if (!selectedProvider)
235
+ return;
236
+ const voice = selectedProvider.voices.find((v) => v.id === voiceId);
237
+ if (voice) {
238
+ setSelectedVoice(voice);
239
+ // Re-select provider with new voice
240
+ sendMessage({ type: 'select_provider', providerId: selectedProvider.id, voiceId });
241
+ }
242
+ }, [selectedProvider, sendMessage]);
243
+ // Start recording audio
244
+ const startRecording = useCallback(async () => {
245
+ if (isRecording)
246
+ return;
247
+ isRecordingRef.current = true;
248
+ try {
249
+ // Get microphone access
250
+ const stream = await navigator.mediaDevices.getUserMedia({
251
+ audio: {
252
+ sampleRate: 48000,
253
+ channelCount: 1,
254
+ echoCancellation: true,
255
+ noiseSuppression: true,
256
+ },
257
+ });
258
+ mediaStreamRef.current = stream;
259
+ // Create audio context
260
+ const ctx = new AudioContext({ sampleRate: 48000 });
261
+ audioContextRef.current = ctx;
262
+ // Load audio worklet
263
+ await ctx.audioWorklet.addModule(URL.createObjectURL(new Blob([AUDIO_WORKLET_CODE], { type: 'application/javascript' })));
264
+ // Create worklet node
265
+ const source = ctx.createMediaStreamSource(stream);
266
+ const worklet = new AudioWorkletNode(ctx, 'audio-processor');
267
+ workletNodeRef.current = worklet;
268
+ // Handle audio data from worklet
269
+ worklet.port.onmessage = (event) => {
270
+ if (!isRecordingRef.current)
271
+ return;
272
+ const samples = event.data;
273
+ // Encode and send to server
274
+ if (wsRef.current?.readyState === WebSocket.OPEN && sampleRate) {
275
+ const pcm = encodeAudio(new Float32Array(samples), sampleRate);
276
+ wsRef.current.send(pcm);
277
+ }
278
+ };
279
+ source.connect(worklet);
280
+ setIsRecording(true);
281
+ }
282
+ catch (err) {
283
+ isRecordingRef.current = false;
284
+ const error = err instanceof Error ? err : new Error('Failed to start recording');
285
+ setError(error);
286
+ config.onError?.(error);
287
+ }
288
+ }, [isRecording, config]);
289
+ // Stop recording
290
+ const stopRecording = useCallback(() => {
291
+ if (!isRecording)
292
+ return;
293
+ isRecordingRef.current = false;
294
+ // Clear worklet message handler first
295
+ if (workletNodeRef.current) {
296
+ workletNodeRef.current.port.onmessage = null;
297
+ workletNodeRef.current.disconnect();
298
+ workletNodeRef.current = null;
299
+ }
300
+ // Stop all media tracks
301
+ mediaStreamRef.current?.getTracks().forEach((track) => track.stop());
302
+ mediaStreamRef.current = null;
303
+ // Close audio context (but keep it for playback if needed)
304
+ // audioContextRef.current?.close();
305
+ // audioContextRef.current = null;
306
+ setIsRecording(false);
307
+ setAudioLevel(0);
308
+ }, [isRecording]);
309
+ // Play queued audio
310
+ const playNextAudio = useCallback(() => {
311
+ if (isPlayingRef.current || playbackQueueRef.current.length === 0)
312
+ return;
313
+ if (!audioContextRef.current)
314
+ return;
315
+ isPlayingRef.current = true;
316
+ const samples = playbackQueueRef.current.shift();
317
+ // Create new Float32Array with explicit ArrayBuffer type
318
+ const audioData = new Float32Array(samples.length);
319
+ audioData.set(samples);
320
+ const buffer = audioContextRef.current.createBuffer(1, audioData.length, 48000);
321
+ buffer.copyToChannel(audioData, 0);
322
+ const source = audioContextRef.current.createBufferSource();
323
+ source.buffer = buffer;
324
+ source.connect(audioContextRef.current.destination);
325
+ source.onended = () => {
326
+ isPlayingRef.current = false;
327
+ playNextAudio();
328
+ };
329
+ source.start();
330
+ }, []);
331
+ // Clear transcription
332
+ const clearTranscription = useCallback(() => {
333
+ setTranscription([]);
334
+ }, []);
335
+ // Auto-connect if configured
336
+ useEffect(() => {
337
+ if (config.autoConnect) {
338
+ connect();
339
+ }
340
+ return () => {
341
+ disconnect();
342
+ };
343
+ }, []);
344
+ return {
345
+ connectionState,
346
+ isConnected: connectionState === 'connected',
347
+ connect,
348
+ disconnect,
349
+ error,
350
+ providers,
351
+ selectedProvider,
352
+ selectProvider,
353
+ voices: selectedProvider?.voices ?? [],
354
+ selectedVoice,
355
+ selectVoice,
356
+ isRecording,
357
+ startRecording,
358
+ stopRecording,
359
+ audioLevel,
360
+ transcription,
361
+ clearTranscription,
362
+ sessionId,
363
+ sampleRate,
364
+ };
365
+ }
366
+ // AudioWorklet processor code (inlined to avoid separate file)
367
+ const AUDIO_WORKLET_CODE = `
368
+ class AudioProcessor extends AudioWorkletProcessor {
369
+ process(inputs) {
370
+ const input = inputs[0];
371
+ if (input && input.length > 0) {
372
+ const samples = input[0];
373
+ if (samples && samples.length > 0) {
374
+ this.port.postMessage(new Float32Array(samples));
375
+ }
376
+ }
377
+ return true;
378
+ }
379
+ }
380
+ registerProcessor('audio-processor', AudioProcessor);
381
+ `;
382
+ //# sourceMappingURL=useLuke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLuke.js","sourceRoot":"","sources":["../../src/hooks/useLuke.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export { LukeProvider, useLukeContext } from './components/LukeProvider.js';
2
+ export { AudioControls } from './components/AudioControls.js';
3
+ export { TranscriptionDisplay } from './components/TranscriptionDisplay.js';
4
+ export { ConnectionStatus } from './components/ConnectionStatus.js';
5
+ export { useLuke } from './hooks/useLuke.js';
6
+ export type { UseLukeConfig, UseLukeReturn, LukeProviderProps, ProviderInfo, VoiceInfo, TranscriptionMessage, ConnectionState, } from './types.js';
7
+ export type { AudioControlsProps } from './components/AudioControls.js';
8
+ export type { TranscriptionDisplayProps } from './components/TranscriptionDisplay.js';
9
+ export type { ConnectionStatusProps } from './components/ConnectionStatus.js';
10
+ export * from './ui/index.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAGpE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,YAAY,EACR,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,SAAS,EACT,oBAAoB,EACpB,eAAe,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACtF,YAAY,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAG9E,cAAc,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ // @luke/client - React client for realtime AI voice communication
2
+ // Main entry point and public exports
3
+ // Components
4
+ export { LukeProvider, useLukeContext } from './components/LukeProvider.js';
5
+ export { AudioControls } from './components/AudioControls.js';
6
+ export { TranscriptionDisplay } from './components/TranscriptionDisplay.js';
7
+ export { ConnectionStatus } from './components/ConnectionStatus.js';
8
+ // Hooks
9
+ export { useLuke } from './hooks/useLuke.js';
10
+ // UI
11
+ export * from './ui/index.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,sCAAsC;AAEtC,aAAa;AACb,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEpE,QAAQ;AACR,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAgB7C,KAAK;AACL,cAAc,eAAe,CAAC"}
@@ -0,0 +1,89 @@
1
+ export interface ProviderInfo {
2
+ id: string;
3
+ name: 'openai' | 'gemini';
4
+ sampleRate: 16000 | 24000;
5
+ voices: VoiceInfo[];
6
+ }
7
+ export interface VoiceInfo {
8
+ id: string;
9
+ name: string;
10
+ }
11
+ export interface TranscriptionMessage {
12
+ role: 'user' | 'assistant';
13
+ text: string;
14
+ final: boolean;
15
+ timestamp: number;
16
+ }
17
+ export type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'error';
18
+ export interface UseLukeConfig {
19
+ serverUrl: string;
20
+ authToken?: string;
21
+ autoConnect?: boolean;
22
+ onTranscription?: (transcription: TranscriptionMessage) => void;
23
+ onError?: (error: Error) => void;
24
+ onConnect?: () => void;
25
+ onDisconnect?: () => void;
26
+ }
27
+ export interface UseLukeReturn {
28
+ connectionState: ConnectionState;
29
+ isConnected: boolean;
30
+ connect: () => void;
31
+ disconnect: () => void;
32
+ error: Error | null;
33
+ providers: ProviderInfo[];
34
+ selectedProvider: ProviderInfo | null;
35
+ selectProvider: (providerId: string, voiceId?: string) => void;
36
+ voices: VoiceInfo[];
37
+ selectedVoice: VoiceInfo | null;
38
+ selectVoice: (voiceId: string) => void;
39
+ isRecording: boolean;
40
+ startRecording: () => Promise<void>;
41
+ stopRecording: () => void;
42
+ audioLevel: number;
43
+ transcription: TranscriptionMessage[];
44
+ clearTranscription: () => void;
45
+ sessionId: string | null;
46
+ sampleRate: number | null;
47
+ }
48
+ export interface LukeProviderProps {
49
+ serverUrl: string;
50
+ authToken?: string;
51
+ autoConnect?: boolean;
52
+ children: React.ReactNode;
53
+ }
54
+ export type ServerMessage = {
55
+ type: 'handshake';
56
+ providers: ProviderInfo[];
57
+ defaultProvider?: string;
58
+ } | {
59
+ type: 'session_ready';
60
+ sessionId: string;
61
+ sampleRate: number;
62
+ } | {
63
+ type: 'transcription';
64
+ role: 'user' | 'assistant';
65
+ text: string;
66
+ final: boolean;
67
+ } | {
68
+ type: 'turn_complete';
69
+ } | {
70
+ type: 'interrupted';
71
+ } | {
72
+ type: 'error';
73
+ code: string;
74
+ message: string;
75
+ };
76
+ export type ClientMessage = {
77
+ type: 'select_provider';
78
+ providerId: string;
79
+ voiceId?: string;
80
+ } | {
81
+ type: 'text';
82
+ content: string;
83
+ } | {
84
+ type: 'interrupt';
85
+ } | {
86
+ type: 'reconnect';
87
+ sessionId: string;
88
+ };
89
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,UAAU,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,MAAM,EAAE,SAAS,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACrB;AAGD,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,CAAC;AAGpF,MAAM,WAAW,aAAa;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,CAAC,aAAa,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAChE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAGD,MAAM,WAAW,aAAa;IAE1B,eAAe,EAAE,eAAe,CAAC;IACjC,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAGpB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,gBAAgB,EAAE,YAAY,GAAG,IAAI,CAAC;IACtC,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAG/D,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,aAAa,EAAE,SAAS,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAGvC,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IAGnB,aAAa,EAAE,oBAAoB,EAAE,CAAC;IACtC,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAG/B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAGD,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAGD,MAAM,MAAM,aAAa,GACnB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,YAAY,EAAE,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACnF;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAGvD,MAAM,MAAM,aAAa,GACnB;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ // Types for @luke/client
2
+ // Shared types between client components and hooks
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,mDAAmD"}
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ export type LukeUIMode = 'fullscreen' | 'modal';
3
+ export type LukeUIPosition = 'bottom-right' | 'bottom-left' | 'center';
4
+ export type LukeUITheme = 'light' | 'dark' | 'auto';
5
+ interface VoiceClientUIProps {
6
+ mode?: LukeUIMode;
7
+ position?: LukeUIPosition;
8
+ theme?: LukeUITheme;
9
+ title?: string;
10
+ width?: string;
11
+ height?: string;
12
+ onClose?: () => void;
13
+ showSettings?: boolean;
14
+ }
15
+ export declare const VoiceClientUI: React.FC<VoiceClientUIProps>;
16
+ export {};
17
+ //# sourceMappingURL=VoiceClientUI.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceClientUI.d.ts","sourceRoot":"","sources":["../../src/ui/VoiceClientUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAKzC,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,OAAO,CAAC;AAChD,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,aAAa,GAAG,QAAQ,CAAC;AACvE,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpD,UAAU,kBAAkB;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAiRtD,CAAC"}