@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,84 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useEffect } from 'react';
3
+ import { useLukeContext } from '../components/LukeProvider.js';
4
+ import { MicIcon, StopIcon, TrashIcon, XIcon, MaximizeIcon, MinimizeIcon } from './components/Icons';
5
+ export const VoiceClientUI = ({ mode = 'modal', position = 'bottom-right', theme = 'light', title = 'Luke AI', width, height, onClose, showSettings = true }) => {
6
+ const { isConnected, isRecording, startRecording, stopRecording, transcription, clearTranscription, audioLevel, connectionState, connect, providers, selectedProvider, selectProvider, voices, selectedVoice, selectVoice, error } = useLukeContext();
7
+ const [isExpanded, setIsExpanded] = React.useState(mode === 'fullscreen');
8
+ const [currentMode, setCurrentMode] = React.useState(mode);
9
+ const [isSettingsOpen, setIsSettingsOpen] = React.useState(false);
10
+ // Auto-scroll logic
11
+ const [autoScroll, setAutoScroll] = React.useState(true);
12
+ const [hasScroll, setHasScroll] = React.useState(false);
13
+ const messagesRef = React.useRef(null);
14
+ const prevLengthRef = React.useRef(0);
15
+ // Check if scroll is needed
16
+ useEffect(() => {
17
+ if (messagesRef.current) {
18
+ const { scrollHeight, clientHeight } = messagesRef.current;
19
+ setHasScroll(scrollHeight > clientHeight);
20
+ }
21
+ }, [transcription, currentMode, width, height]);
22
+ useEffect(() => {
23
+ // Only scroll if autoScroll is enabled AND a NEW message has been added
24
+ // We compare current length with previous length to ignore updates to existing messages
25
+ if (autoScroll && transcription.length > prevLengthRef.current) {
26
+ if (messagesRef.current) {
27
+ // Use setTimeout to ensure DOM has updated
28
+ setTimeout(() => {
29
+ if (messagesRef.current) {
30
+ messagesRef.current.scrollTo({
31
+ top: messagesRef.current.scrollHeight,
32
+ behavior: 'smooth'
33
+ });
34
+ }
35
+ }, 10);
36
+ }
37
+ }
38
+ prevLengthRef.current = transcription.length;
39
+ }, [transcription, autoScroll]);
40
+ useEffect(() => {
41
+ setCurrentMode(mode);
42
+ }, [mode]);
43
+ // Apply theme
44
+ useEffect(() => {
45
+ const root = document.documentElement;
46
+ if (theme === 'auto') {
47
+ const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
48
+ root.setAttribute('data-luke-theme', isDark ? 'dark' : 'light');
49
+ }
50
+ else {
51
+ root.setAttribute('data-luke-theme', theme);
52
+ }
53
+ }, [theme]);
54
+ const handleMicClick = () => {
55
+ if (isRecording) {
56
+ stopRecording();
57
+ }
58
+ else {
59
+ startRecording();
60
+ }
61
+ };
62
+ const toggleMaximize = () => {
63
+ if (currentMode === 'modal') {
64
+ setCurrentMode('fullscreen');
65
+ }
66
+ else {
67
+ setCurrentMode('modal');
68
+ }
69
+ };
70
+ const containerStyle = {};
71
+ if (currentMode === 'modal') {
72
+ if (width)
73
+ containerStyle.width = width;
74
+ if (height)
75
+ containerStyle.height = height;
76
+ }
77
+ return (_jsxs("div", { className: `luke-wrapper luke-mode-${currentMode} luke-pos-${position}`, style: containerStyle, "data-luke-theme": theme, children: [_jsxs("header", { className: "luke-header", children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '8px' }, children: [_jsx("div", { className: `status-dot ${connectionState === 'connected' ? 'connected' : ''}`, style: {
78
+ width: 8,
79
+ height: 8,
80
+ borderRadius: '50%',
81
+ background: connectionState === 'connected' ? 'var(--luke-success-color)' : 'var(--luke-text-secondary)'
82
+ } }), _jsx("span", { className: "luke-header-title", children: title })] }), _jsxs("div", { style: { display: 'flex', gap: '4px' }, children: [transcription.length > 0 && (_jsx("button", { onClick: clearTranscription, className: "luke-btn-icon", title: "Clear chat", children: _jsx(TrashIcon, {}) })), _jsx("button", { onClick: toggleMaximize, className: "luke-btn-icon", children: currentMode === 'modal' ? _jsx(MaximizeIcon, {}) : _jsx(MinimizeIcon, {}) }), onClose && (_jsx("button", { onClick: onClose, className: "luke-btn-icon", children: _jsx(XIcon, {}) }))] })] }), _jsxs("div", { className: "luke-body", children: [_jsx("div", { className: "luke-messages", ref: messagesRef, children: transcription.length === 0 ? (_jsx("div", { style: { flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--luke-text-secondary)', textAlign: 'center', fontSize: '14px', padding: '20px' }, children: isConnected ? 'Say hello!' : 'Connecting...' })) : (transcription.map((msg, idx) => (_jsxs("div", { className: `luke-message ${msg.role}`, children: [_jsx("span", { className: "luke-role-label", children: msg.role === 'user' ? 'You' : 'AI' }), _jsx("div", { className: "luke-bubble", children: msg.text })] }, idx)))) }), hasScroll && (_jsx("div", { style: { position: 'absolute', bottom: '260px', right: '20px', zIndex: 10 }, children: _jsx("button", { onClick: () => setAutoScroll(!autoScroll), className: `luke-btn-icon ${autoScroll ? 'active' : ''}`, title: autoScroll ? "Disable Auto-scroll" : "Enable Auto-scroll", style: { backgroundColor: autoScroll ? 'var(--luke-primary-bg)' : 'var(--luke-bg-color)', color: autoScroll ? 'var(--luke-primary-fg)' : 'var(--luke-text-secondary)', boxShadow: 'var(--luke-shadow-md)', width: 32, height: 32, borderRadius: '50%' }, children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }), _jsx("polyline", { points: "19 12 12 19 5 12" })] }) }) })), _jsxs("div", { className: "luke-controls", children: [error && (_jsx("div", { style: { padding: '8px', background: '#fee2e2', color: '#ef4444', borderRadius: '4px', fontSize: '12px' }, children: error.message })), connectionState === 'disconnected' ? (_jsx("button", { onClick: connect, style: { width: '100%', padding: '12px', background: 'var(--luke-primary-bg)', color: 'var(--luke-primary-fg)', border: 'none', borderRadius: '8px', cursor: 'pointer' }, children: "Connect" })) : (_jsxs("div", { className: "luke-mic-area", children: [_jsxs("div", { className: "luke-mic-wrapper", children: [isRecording && (_jsx("div", { className: "luke-visualizer", style: { transform: `translate(-50%, -50%) scale(${1 + audioLevel * 0.5})` } })), _jsx("button", { className: `luke-mic-btn ${isRecording ? 'active' : ''}`, onClick: handleMicClick, disabled: !isConnected, children: isRecording ? _jsx(StopIcon, {}) : _jsx(MicIcon, {}) })] }), _jsx("span", { className: "luke-status-text", children: isRecording ? 'Listening...' : 'Tap to speak' }), _jsxs("div", { className: "luke-pills-container", children: [selectedProvider && (_jsxs("div", { className: "luke-selection-pill", children: [_jsx("select", { value: selectedProvider.id, onChange: (e) => selectProvider(e.target.value), className: "luke-pill-select", children: providers.map(p => (_jsx("option", { value: p.id, children: p.name }, p.id))) }), _jsx("div", { className: "luke-pill-icon", children: _jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2zm0 18a8 8 0 1 1 8-8 8 8 0 0 1-8 8z" }), _jsx("path", { d: "M12 8v8" }), _jsx("path", { d: "M8 12h8" })] }) }), _jsx("span", { className: "luke-pill-label", children: selectedProvider.name }), _jsx("div", { className: "luke-pill-chevron", children: _jsx("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("polyline", { points: "6 9 12 15 18 9" }) }) })] })), selectedVoice && (_jsxs("div", { className: "luke-selection-pill", children: [_jsx("select", { value: selectedVoice.id, onChange: (e) => selectVoice(e.target.value), className: "luke-pill-select", children: voices.map(v => (_jsx("option", { value: v.id, children: v.name }, v.id))) }), _jsx("div", { className: "luke-pill-icon", children: _jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }), _jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }), _jsx("line", { x1: "12", y1: "19", x2: "12", y2: "23" }), _jsx("line", { x1: "8", y1: "23", x2: "16", y2: "23" })] }) }), _jsx("span", { className: "luke-pill-label", children: selectedVoice.name }), _jsx("div", { className: "luke-pill-chevron", children: _jsx("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("polyline", { points: "6 9 12 15 18 9" }) }) })] }))] })] }))] })] })] }));
83
+ };
84
+ //# sourceMappingURL=VoiceClientUI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceClientUI.js","sourceRoot":"","sources":["../../src/ui/VoiceClientUI.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare const MicIcon: () => import("react/jsx-runtime").JSX.Element;
2
+ export declare const StopIcon: () => import("react/jsx-runtime").JSX.Element;
3
+ export declare const TrashIcon: () => import("react/jsx-runtime").JSX.Element;
4
+ export declare const SettingsIcon: () => import("react/jsx-runtime").JSX.Element;
5
+ export declare const XIcon: () => import("react/jsx-runtime").JSX.Element;
6
+ export declare const MinimizeIcon: () => import("react/jsx-runtime").JSX.Element;
7
+ export declare const MaximizeIcon: () => import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=Icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Icons.d.ts","sourceRoot":"","sources":["../../../src/ui/components/Icons.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO,+CAOnB,CAAC;AAEF,eAAO,MAAM,QAAQ,+CAIpB,CAAC;AAEF,eAAO,MAAM,SAAS,+CAKrB,CAAC;AAEF,eAAO,MAAM,YAAY,+CAKxB,CAAC;AAEF,eAAO,MAAM,KAAK,+CAKjB,CAAC;AAEF,eAAO,MAAM,YAAY,+CAOxB,CAAC;AAEF,eAAO,MAAM,YAAY,+CAOxB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export const MicIcon = () => (_jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }), _jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }), _jsx("line", { x1: "12", y1: "19", x2: "12", y2: "23" }), _jsx("line", { x1: "8", y1: "23", x2: "16", y2: "23" })] }));
3
+ export const StopIcon = () => (_jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2", ry: "2" }) }));
4
+ export const TrashIcon = () => (_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("polyline", { points: "3 6 5 6 21 6" }), _jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })] }));
5
+ export const SettingsIcon = () => (_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("circle", { cx: "12", cy: "12", r: "3" }), _jsx("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" })] }));
6
+ export const XIcon = () => (_jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }));
7
+ export const MinimizeIcon = () => (_jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "4", y1: "14", x2: "10", y2: "14" }), _jsx("line", { x1: "10", y1: "14", x2: "10", y2: "20" }), _jsx("line", { x1: "20", y1: "10", x2: "14", y2: "10" }), _jsx("line", { x1: "14", y1: "10", x2: "14", y2: "4" })] }));
8
+ export const MaximizeIcon = () => (_jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "15", y1: "3", x2: "21", y2: "3" }), _jsx("line", { x1: "21", y1: "3", x2: "21", y2: "9" }), _jsx("line", { x1: "9", y1: "21", x2: "3", y2: "21" }), _jsx("line", { x1: "3", y1: "21", x2: "3", y2: "15" })] }));
9
+ //# sourceMappingURL=Icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Icons.js","sourceRoot":"","sources":["../../../src/ui/components/Icons.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './VoiceClientUI';
2
+ export * from './components/Icons';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './VoiceClientUI';
2
+ export * from './components/Icons';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function floatTo16BitPCM(float32Array: Float32Array): Int16Array;
2
+ export declare function pcm16ToFloat32(int16Array: Int16Array): Float32Array;
3
+ export declare function resampleAudio(inputSamples: Float32Array, inputRate: number, outputRate: number): Float32Array;
4
+ export declare function calculateAudioLevel(samples: Float32Array): number;
5
+ //# sourceMappingURL=audio-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-utils.d.ts","sourceRoot":"","sources":["../../src/worker/audio-utils.ts"],"names":[],"mappings":"AAIA,wBAAgB,eAAe,CAAC,YAAY,EAAE,YAAY,GAAG,UAAU,CAWtE;AAGD,wBAAgB,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,YAAY,CAQnE;AAGD,wBAAgB,aAAa,CACzB,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACnB,YAAY,CAsBd;AAGD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CASjE"}
@@ -0,0 +1,52 @@
1
+ // Audio utilities for PCM encoding/decoding
2
+ // Handles conversion between Float32Array (Web Audio) and Int16Array (PCM)
3
+ // Convert Float32 samples to 16-bit PCM
4
+ export function floatTo16BitPCM(float32Array) {
5
+ const int16Array = new Int16Array(float32Array.length);
6
+ for (let i = 0; i < float32Array.length; i++) {
7
+ // Clamp value between -1 and 1
8
+ const sample = Math.max(-1, Math.min(1, float32Array[i]));
9
+ // Convert to 16-bit integer
10
+ int16Array[i] = sample < 0 ? sample * 0x8000 : sample * 0x7fff;
11
+ }
12
+ return int16Array;
13
+ }
14
+ // Convert 16-bit PCM to Float32 samples
15
+ export function pcm16ToFloat32(int16Array) {
16
+ const float32Array = new Float32Array(int16Array.length);
17
+ for (let i = 0; i < int16Array.length; i++) {
18
+ float32Array[i] = int16Array[i] / (int16Array[i] < 0 ? 0x8000 : 0x7fff);
19
+ }
20
+ return float32Array;
21
+ }
22
+ // Resample audio to target sample rate
23
+ export function resampleAudio(inputSamples, inputRate, outputRate) {
24
+ if (inputRate === outputRate) {
25
+ return inputSamples;
26
+ }
27
+ const ratio = inputRate / outputRate;
28
+ const outputLength = Math.ceil(inputSamples.length / ratio);
29
+ const output = new Float32Array(outputLength);
30
+ for (let i = 0; i < outputLength; i++) {
31
+ const srcIndex = i * ratio;
32
+ const srcIndexFloor = Math.floor(srcIndex);
33
+ const srcIndexCeil = Math.min(srcIndexFloor + 1, inputSamples.length - 1);
34
+ const fraction = srcIndex - srcIndexFloor;
35
+ // Linear interpolation
36
+ output[i] =
37
+ inputSamples[srcIndexFloor] * (1 - fraction) +
38
+ inputSamples[srcIndexCeil] * fraction;
39
+ }
40
+ return output;
41
+ }
42
+ // Calculate RMS audio level (0-1 range)
43
+ export function calculateAudioLevel(samples) {
44
+ if (samples.length === 0)
45
+ return 0;
46
+ let sum = 0;
47
+ for (let i = 0; i < samples.length; i++) {
48
+ sum += samples[i] * samples[i];
49
+ }
50
+ return Math.sqrt(sum / samples.length);
51
+ }
52
+ //# sourceMappingURL=audio-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-utils.js","sourceRoot":"","sources":["../../src/worker/audio-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=audio.worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio.worker.d.ts","sourceRoot":"","sources":["../../src/worker/audio.worker.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ // Audio Worker
2
+ // Runs in a Web Worker to handle audio processing off the main thread
3
+ import { floatTo16BitPCM, pcm16ToFloat32, resampleAudio, calculateAudioLevel } from './audio-utils.js';
4
+ // Target sample rate (set by server based on provider)
5
+ let targetSampleRate = 16000;
6
+ // Browser audio context typically runs at 44100 or 48000 Hz
7
+ const BROWSER_SAMPLE_RATE = 48000;
8
+ // Handle incoming messages
9
+ self.onmessage = (event) => {
10
+ const message = event.data;
11
+ switch (message.type) {
12
+ case 'configure':
13
+ targetSampleRate = message.sampleRate;
14
+ break;
15
+ case 'encode':
16
+ encodeAudio(message.samples);
17
+ break;
18
+ case 'decode':
19
+ decodeAudio(message.pcmData);
20
+ break;
21
+ }
22
+ };
23
+ // Encode Float32 audio from browser to PCM for server
24
+ function encodeAudio(samples) {
25
+ // Resample to target rate
26
+ const resampled = resampleAudio(samples, BROWSER_SAMPLE_RATE, targetSampleRate);
27
+ // Calculate audio level before encoding
28
+ const level = calculateAudioLevel(resampled);
29
+ // Convert to 16-bit PCM
30
+ const pcm = floatTo16BitPCM(resampled);
31
+ // Copy to new ArrayBuffer to ensure it's transferable
32
+ const buffer = new ArrayBuffer(pcm.byteLength);
33
+ new Int16Array(buffer).set(pcm);
34
+ // Send back to main thread
35
+ const response = {
36
+ type: 'encoded',
37
+ pcmData: buffer,
38
+ level,
39
+ };
40
+ self.postMessage(response);
41
+ }
42
+ // Decode PCM from server to Float32 for playback
43
+ function decodeAudio(pcmData) {
44
+ // Convert PCM to Int16Array
45
+ const pcm = new Int16Array(pcmData);
46
+ // Convert to Float32
47
+ const float32 = pcm16ToFloat32(pcm);
48
+ // Resample from server rate (24kHz output) to browser rate
49
+ const resampled = resampleAudio(float32, 24000, BROWSER_SAMPLE_RATE);
50
+ // Create copy of samples to ensure clean transfer
51
+ const result = new Float32Array(resampled.length);
52
+ result.set(resampled);
53
+ // Send back to main thread
54
+ const response = {
55
+ type: 'decoded',
56
+ samples: result,
57
+ };
58
+ self.postMessage(response);
59
+ }
60
+ //# sourceMappingURL=audio.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio.worker.js","sourceRoot":"","sources":["../../src/worker/audio.worker.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,sEAAsE;AAEtE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAiCvG,uDAAuD;AACvD,IAAI,gBAAgB,GAAG,KAAK,CAAC;AAE7B,4DAA4D;AAC5D,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAKlC,2BAA2B;AAC3B,IAAI,CAAC,SAAS,GAAG,CAAC,KAAkC,EAAE,EAAE;IACpD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC;IAE3B,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,WAAW;YACZ,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC;YACtC,MAAM;QAEV,KAAK,QAAQ;YACT,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC7B,MAAM;QAEV,KAAK,QAAQ;YACT,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC7B,MAAM;IACd,CAAC;AACL,CAAC,CAAC;AAEF,sDAAsD;AACtD,SAAS,WAAW,CAAC,OAAqB;IACtC,0BAA0B;IAC1B,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,CAAC,CAAC;IAEhF,wCAAwC;IACxC,MAAM,KAAK,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAE7C,wBAAwB;IACxB,MAAM,GAAG,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAEvC,sDAAsD;IACtD,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC/C,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEhC,2BAA2B;IAC3B,MAAM,QAAQ,GAAoB;QAC9B,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,MAAM;QACf,KAAK;KACR,CAAC;IACF,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,iDAAiD;AACjD,SAAS,WAAW,CAAC,OAAoB;IACrC,4BAA4B;IAC5B,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;IAEpC,qBAAqB;IACrB,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAEpC,2DAA2D;IAC3D,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC;IAErE,kDAAkD;IAClD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAEtB,2BAA2B;IAC3B,MAAM,QAAQ,GAAoB;QAC9B,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,MAAM;KAClB,CAAC;IACF,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AAC/B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "version": "0.1.0",
3
+ "name": "@leia-org/luke-client",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "description": "React client for realtime AI voice communication",
8
+ "type": "module",
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ },
16
+ "./style.css": "./dist/Luke.css"
17
+ },
18
+ "devDependencies": {
19
+ "@types/react": "^19.0.2",
20
+ "typescript": "^5.7.2",
21
+ "vitest": "^2.1.8"
22
+ },
23
+ "peerDependencies": {
24
+ "react": "^18.0.0 || ^19.0.0"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "license": "MIT",
30
+ "scripts": {
31
+ "build": "tsc",
32
+ "dev": "tsc --watch",
33
+ "test": "vitest run",
34
+ "lint": "tsc --noEmit",
35
+ "postbuild": "cp src/ui/Luke.css dist/Luke.css"
36
+ }
37
+ }