@lofcz/orb-ui 0.7.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 (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +330 -0
  3. package/dist/adapters/audio-level.d.ts +28 -0
  4. package/dist/adapters/elevenlabs/index.d.ts +85 -0
  5. package/dist/adapters/gemini-live/index.d.ts +70 -0
  6. package/dist/adapters/index.d.ts +8 -0
  7. package/dist/adapters/livekit/browser.d.ts +49 -0
  8. package/dist/adapters/livekit/index.d.ts +136 -0
  9. package/dist/adapters/openai-realtime/index.d.ts +37 -0
  10. package/dist/adapters/pipecat/index.d.ts +62 -0
  11. package/dist/adapters/types.d.ts +7 -0
  12. package/dist/adapters/vapi/index.d.ts +42 -0
  13. package/dist/adapters.cjs +1 -0
  14. package/dist/adapters.js +829 -0
  15. package/dist/components/Orb/Orb.d.ts +2 -0
  16. package/dist/components/Orb/Orb.types.d.ts +87 -0
  17. package/dist/components/Orb/index.d.ts +2 -0
  18. package/dist/components/Orb/signals.d.ts +3 -0
  19. package/dist/index.d.ts +4 -0
  20. package/dist/livekit-D-s4sYba.cjs +1 -0
  21. package/dist/livekit-Z3IMmWaG.js +316 -0
  22. package/dist/livekit-adapter.cjs +1 -0
  23. package/dist/livekit-adapter.js +30 -0
  24. package/dist/orb-ui.cjs +203 -0
  25. package/dist/orb-ui.js +984 -0
  26. package/dist/themes/bars/BarsTheme.d.ts +14 -0
  27. package/dist/themes/bars/index.d.ts +1 -0
  28. package/dist/themes/circle/CircleTheme.d.ts +14 -0
  29. package/dist/themes/circle/index.d.ts +1 -0
  30. package/dist/themes/cloud/CloudTheme.d.ts +14 -0
  31. package/dist/themes/cloud/index.d.ts +1 -0
  32. package/dist/themes/debug/DebugTheme.d.ts +15 -0
  33. package/dist/themes/debug/index.d.ts +1 -0
  34. package/dist/themes/index.d.ts +5 -0
  35. package/dist/themes/radial/RadialTheme.d.ts +13 -0
  36. package/dist/themes/radial/index.d.ts +1 -0
  37. package/package.json +122 -0
@@ -0,0 +1,2 @@
1
+ import { OrbProps } from './Orb.types.js';
2
+ export declare function Orb({ signal: signalProp, state: stateProp, volume: volumeProp, adapter, theme, size, className, style, disabled, interactive: interactiveProp, onStart, onStop, ...htmlProps }: OrbProps): import("react").JSX.Element;
@@ -0,0 +1,87 @@
1
+ import { AriaAttributes, CSSProperties } from 'react';
2
+ export type OrbStyle = CSSProperties & {
3
+ /** Background color revealed around the radial theme's floating phone control. */
4
+ '--orb-ui-radial-control-surround'?: string;
5
+ };
6
+ export type OrbState = 'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking' | 'error';
7
+ export type OrbTheme = 'debug' | 'circle' | 'bars' | 'cloud' | 'radial';
8
+ export interface OrbSignal {
9
+ state: OrbState;
10
+ volume?: number;
11
+ inputVolume?: number;
12
+ outputVolume?: number;
13
+ error?: unknown;
14
+ }
15
+ export type OrbSignalListener = (signal: OrbSignal) => void;
16
+ export interface OrbAdapter {
17
+ /**
18
+ * Subscribe to normalized signal changes from a voice provider.
19
+ * Returns an unsubscribe function to clean up listeners.
20
+ */
21
+ subscribe(listener: OrbSignalListener): () => void;
22
+ /** Start the voice session. Called internally by Orb on click. */
23
+ start?: () => void | Promise<void>;
24
+ /** Stop the voice session. Called internally by Orb on click. */
25
+ stop?: () => void | Promise<void>;
26
+ }
27
+ type DataAttributeValue = string | number | boolean | null | undefined;
28
+ export interface OrbHtmlAttributes extends AriaAttributes {
29
+ /** Forwarded to the rendered orb control/container. */
30
+ id?: string;
31
+ /** Forwarded to the rendered orb control/container. */
32
+ title?: string;
33
+ /** Override the rendered role when you need custom semantics. */
34
+ role?: string;
35
+ /** Forwarded tab index for non-default keyboard ordering. */
36
+ tabIndex?: number;
37
+ /** Forward data-* attributes, e.g. data-testid. */
38
+ [dataAttribute: `data-${string}`]: DataAttributeValue;
39
+ }
40
+ export interface OrbProps extends OrbHtmlAttributes {
41
+ /**
42
+ * Current voice signal. Use this controlled mode when your app has separate
43
+ * input and output volume levels.
44
+ */
45
+ signal?: OrbSignal;
46
+ /**
47
+ * Current conversation state. Required in controlled mode (no adapter).
48
+ * Overrides signal and adapter state if provided.
49
+ */
50
+ state?: OrbState;
51
+ /**
52
+ * Current audio volume, normalized 0–1.
53
+ * Overrides signal and adapter volume if provided.
54
+ */
55
+ volume?: number;
56
+ /**
57
+ * Provider adapter (Vapi, ElevenLabs, etc.).
58
+ * Handles signal updates automatically from the SDK.
59
+ */
60
+ adapter?: OrbAdapter;
61
+ /** Visual theme. Defaults to 'debug'. */
62
+ theme?: OrbTheme;
63
+ /** Size in pixels. Defaults to 200. */
64
+ size?: number;
65
+ /** Optional class name for the rendered orb container/control. */
66
+ className?: string;
67
+ /** Optional inline styles for the rendered orb container/control. */
68
+ style?: OrbStyle;
69
+ /** Disable interactive theme and debug start/stop controls. */
70
+ disabled?: boolean;
71
+ /**
72
+ * Allow the rendered theme control to start and stop an adapter-backed session.
73
+ * Set this to false when session controls live elsewhere in your UI.
74
+ */
75
+ interactive?: boolean;
76
+ /**
77
+ * Called when a clickable theme is activated while idle/error.
78
+ * Overrides adapter.start() when provided.
79
+ */
80
+ onStart?: () => void;
81
+ /**
82
+ * Called when a clickable theme is activated while active.
83
+ * Overrides adapter.stop() when provided.
84
+ */
85
+ onStop?: () => void;
86
+ }
87
+ export {};
@@ -0,0 +1,2 @@
1
+ export { Orb } from './Orb.js';
2
+ export type { OrbAdapter, OrbProps, OrbSignal, OrbSignalListener, OrbState, OrbStyle, OrbTheme, } from './Orb.types.js';
@@ -0,0 +1,3 @@
1
+ import { OrbSignal, OrbState } from './Orb.types.js';
2
+ export declare function deriveOrbState(state: OrbState | undefined, signal: OrbSignal | undefined, adapterSignal: OrbSignal): OrbState;
3
+ export declare function deriveOrbVolume(volume: number | undefined, state: OrbState, signal: OrbSignal): number;
@@ -0,0 +1,4 @@
1
+ export { Orb } from './components/Orb/index.js';
2
+ export type { OrbAdapter, OrbProps, OrbSignal, OrbSignalListener, OrbState, OrbStyle, OrbTheme, } from './components/Orb/index.js';
3
+ export { Orb as VoiceOrb } from './components/Orb/index.js';
4
+ export type { OrbProps as VoiceOrbProps } from './components/Orb/index.js';
@@ -0,0 +1 @@
1
+ function e(e){let t=Math.min(e/.5,1);return t**=1.3,t}var t={noiseFloor:0,gain:4,exponent:.8,attack:1,release:1};function n(e,t,n){return Math.min(n,Math.max(t,e))}function r(e,t){return typeof e==`number`&&Number.isFinite(e)?e:t}function i(e){let i=typeof e==`function`?e():e;return{noiseFloor:n(r(i?.noiseFloor,t.noiseFloor),0,1),gain:Math.max(0,r(i?.gain,t.gain)),exponent:Math.max(.01,r(i?.exponent,t.exponent)),attack:n(r(i?.attack,t.attack),0,1),release:n(r(i?.release,t.release),0,1)}}function a(e,t,r){let a=Number.isFinite(e)?n(e,0,1):0,o=i(r),s=n((a<=o.noiseFloor?0:a-o.noiseFloor)*o.gain,0,1)**+o.exponent,c=s>t?o.attack:o.release;return{raw:a,shaped:s,normalized:n(t+(s-t)*c,0,1)}}function o(e,t,n){let r;try{if(r=t(),!r)return;let i=r;i.state===`suspended`&&i.resume().catch(()=>void 0);let a=i.createMediaStreamSource(new MediaStream([e])),o=i.createAnalyser();o.fftSize=512,o.smoothingTimeConstant=.25,a.connect(o);let s=new Float32Array(o.fftSize),c=setInterval(()=>{o.getFloatTimeDomainData(s);let e=0;for(let t of s)e+=t*t;n(Math.sqrt(e/s.length))},33);return{async stop(){clearInterval(c);try{a.disconnect(),o.disconnect()}finally{i.state!==`closed`&&await i.close()}}}}catch{r?.state!==`closed`&&r?.close().catch(()=>void 0);return}}var s=4,c={fftSize:512,smoothingTimeConstant:.25,minDecibels:-85,maxDecibels:-20},l={noiseFloor:.015,gain:4.6,exponent:1.15,attack:.1,release:.48};function u(e){switch(e){case`speaking`:return`speaking`;case`thinking`:return`thinking`;case`listening`:case`idle`:return`listening`;case`connecting`:case`pre-connect-buffering`:case`initializing`:return`connecting`;case`disconnected`:return`idle`;case`failed`:return`error`;default:return`idle`}}function d(e){return`RoomClass`in e}function f(e){return typeof e==`function`?e():e}function p(e){if(!e)return{};let t={},n=(e,n)=>{n!==void 0&&(t[e]=n)};return n(`roomName`,f(e.roomName)),n(`participantName`,f(e.participantName)),n(`participantIdentity`,f(e.participantIdentity)),n(`participantMetadata`,f(e.participantMetadata)),n(`participantAttributes`,typeof e.participantAttributes==`function`?e.participantAttributes():e.participantAttributes),n(`agentName`,f(e.agentName)),n(`agentMetadata`,f(e.agentMetadata)),n(`deployment`,f(e.deployment)),t}function m(e){if(!e.serverUrl||!e.participantToken)throw Error(`[orb-ui/livekit] connection details must include serverUrl and participantToken.`);return e}async function h(e){let t=p(e.tokenOptions);return typeof e.getConnectionDetails==`function`?m(await e.getConnectionDetails(t)):e.tokenSource?m(await e.tokenSource.fetch(t)):m({serverUrl:e.serverUrl,participantToken:e.participantToken})}function g(e){for(let[,t]of e.remoteParticipants)if(!t.isLocal&&(t.kind===s||t.attributes?.[`lk.agent.state`]!==void 0))return t;return null}function _(e,t,n){let r=e.off;if(r){r.call(e,t,n);return}e.removeListener?.call(e,t,n)}function v(e,t,n){e.on.call(e,t,n)}function y(t){let n=d(t),r=t.createAudioAnalyser,i={current:n?null:t.room},o=new Set,f={state:`idle`,volume:0,inputVolume:0,outputVolume:0},p=`idle`,m=null,y=null,b=null,x=null,S=null,C=null,w=null,T=0,E=null;function D(e){f=e,o.forEach(t=>t(e))}function O(e){D({...f,...e,state:e.state??f.state})}function k(){let e=typeof t.outputVolumeCalibration==`function`?t.outputVolumeCalibration():t.outputVolumeCalibration;return{...l,...e}}function A(e){let n=a(e,T,k);return T=n.normalized,t.onOutputVolumeSample?.(n),n.normalized}function j(){T=0,O({volume:0,outputVolume:0})}function M({emitZero:e=!0}={}){S&&=(clearInterval(S),null),x&&=(x.cleanup().catch(()=>{}),null),e&&O({volume:0,inputVolume:0})}function N(t){if(!(m===t&&x)){M({emitZero:!1}),m=t;try{x=r(t,c)}catch(e){console.warn(`[orb-ui/livekit] local createAudioAnalyser failed:`,e);return}S=setInterval(()=>{if(!x||p!==`listening`)return;let t=e(x.calculateVolume());O({volume:t,inputVolume:t,outputVolume:0})},33)}}function P({emitZero:e=!0}={}){w&&=(clearInterval(w),null),C&&=(C.cleanup().catch(()=>{}),null),T=0,e&&O({volume:0,outputVolume:0})}function F(e){P();try{C=r(e,c)}catch(e){console.warn(`[orb-ui/livekit] remote createAudioAnalyser failed:`,e);return}w=setInterval(()=>{if(!C||p!==`speaking`)return;let e=A(C.calculateVolume());O({volume:e,inputVolume:0,outputVolume:e})},33)}function I(e){p=e,O({state:e,volume:0,inputVolume:0,outputVolume:0}),e===`speaking`&&y?F(y):e!==`speaking`&&P({emitZero:!1})}function L(e){b||typeof document>`u`||(b=e.attach(),b.id=`orb-ui-livekit-agent-audio`,document.body.appendChild(b))}function R(){b&&=(b.remove(),null)}function z(e){y=e,L(e),p===`speaking`&&F(e)}function B(e){N(e)}function V(e){let t=e.getTrackPublication?.(`microphone`);t?.track&&B(t.track)}function H(e){let t=u(e);t!==p&&I(t)}function U(e){let t=e.attributes?.[`lk.agent.state`];t&&H(t);let n=e.getTrackPublication(`microphone`);n?.track&&z(n.track)}function W(e){if(E)return;let t=(e,t)=>{if(t.isLocal)return;let n=e[`lk.agent.state`];n&&H(n)},n=(e,t,n)=>{n.isLocal||n.kind!==s&&n.attributes?.[`lk.agent.state`]===void 0||e.mediaStreamTrack.kind!==`audio`||z(e)},r=e=>{y===e&&(y=null,R(),P())},i=e=>{e.source===`microphone`&&e.track&&B(e.track)},a=e=>{e.source===`microphone`&&(m=null,M())},o=()=>{m=null,y=null,R(),M({emitZero:!1}),P({emitZero:!1}),I(`idle`)};if(v(e,`participantAttributesChanged`,t),v(e,`trackSubscribed`,n),v(e,`trackUnsubscribed`,r),v(e,`localTrackPublished`,i),v(e,`localTrackUnpublished`,a),v(e,`disconnected`,o),E=()=>{_(e,`participantAttributesChanged`,t),_(e,`trackSubscribed`,n),_(e,`trackUnsubscribed`,r),_(e,`localTrackPublished`,i),_(e,`localTrackUnpublished`,a),_(e,`disconnected`,o)},V(e.localParticipant),e.state===`connected`){let t=g(e);t?U(t):I(`connecting`)}else I(`idle`)}function G(){E?.(),E=null,m=null,y=null,R(),M({emitZero:!1}),P({emitZero:!1}),O({volume:0,inputVolume:0,outputVolume:0})}let K=e=>{o.add(e),e(f);let t=i.current;return t&&W(t),()=>{o.delete(e),o.size===0&&G()}};return n?{subscribe:K,async start(){if(i.current)return;let e=t,n=new e.RoomClass;I(`connecting`);try{let t=await h(e);if(await n.connect(t.serverUrl,t.participantToken,e.connectOptions),i.current=n,W(n),e.enableMicrophone!==!1){let e=(await n.localParticipant.setMicrophoneEnabled(!0))?.track??n.localParticipant.getTrackPublication?.(`microphone`)?.track;e&&B(e)}}catch(e){throw console.error(`[orb-ui/livekit] connect failed:`,e),i.current===n&&G(),n.disconnect(),i.current=null,I(`error`),j(),O({error:e}),e}},async stop(){let e=i.current;if(!e){I(`idle`);return}G(),e.disconnect(),i.current=null,I(`idle`)}}:{subscribe:K}}Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return y}});
@@ -0,0 +1,316 @@
1
+ //#region src/adapters/types.ts
2
+ function e(e) {
3
+ let t = Math.min(e / .5, 1);
4
+ return t **= 1.3, t;
5
+ }
6
+ //#endregion
7
+ //#region src/adapters/audio-level.ts
8
+ var t = {
9
+ noiseFloor: 0,
10
+ gain: 4,
11
+ exponent: .8,
12
+ attack: 1,
13
+ release: 1
14
+ };
15
+ function n(e, t, n) {
16
+ return Math.min(n, Math.max(t, e));
17
+ }
18
+ function r(e, t) {
19
+ return typeof e == "number" && Number.isFinite(e) ? e : t;
20
+ }
21
+ function i(e) {
22
+ let i = typeof e == "function" ? e() : e;
23
+ return {
24
+ noiseFloor: n(r(i?.noiseFloor, t.noiseFloor), 0, 1),
25
+ gain: Math.max(0, r(i?.gain, t.gain)),
26
+ exponent: Math.max(.01, r(i?.exponent, t.exponent)),
27
+ attack: n(r(i?.attack, t.attack), 0, 1),
28
+ release: n(r(i?.release, t.release), 0, 1)
29
+ };
30
+ }
31
+ function a(e, t, r) {
32
+ let a = Number.isFinite(e) ? n(e, 0, 1) : 0, o = i(r), s = n((a <= o.noiseFloor ? 0 : a - o.noiseFloor) * o.gain, 0, 1) ** +o.exponent, c = s > t ? o.attack : o.release;
33
+ return {
34
+ raw: a,
35
+ shaped: s,
36
+ normalized: n(t + (s - t) * c, 0, 1)
37
+ };
38
+ }
39
+ function o(e, t, n) {
40
+ let r;
41
+ try {
42
+ if (r = t(), !r) return;
43
+ let i = r;
44
+ i.state === "suspended" && i.resume().catch(() => void 0);
45
+ let a = i.createMediaStreamSource(new MediaStream([e])), o = i.createAnalyser();
46
+ o.fftSize = 512, o.smoothingTimeConstant = .25, a.connect(o);
47
+ let s = new Float32Array(o.fftSize), c = setInterval(() => {
48
+ o.getFloatTimeDomainData(s);
49
+ let e = 0;
50
+ for (let t of s) e += t * t;
51
+ n(Math.sqrt(e / s.length));
52
+ }, 33);
53
+ return { async stop() {
54
+ clearInterval(c);
55
+ try {
56
+ a.disconnect(), o.disconnect();
57
+ } finally {
58
+ i.state !== "closed" && await i.close();
59
+ }
60
+ } };
61
+ } catch {
62
+ r?.state !== "closed" && r?.close().catch(() => void 0);
63
+ return;
64
+ }
65
+ }
66
+ //#endregion
67
+ //#region src/adapters/livekit/index.ts
68
+ var s = 4, c = {
69
+ fftSize: 512,
70
+ smoothingTimeConstant: .25,
71
+ minDecibels: -85,
72
+ maxDecibels: -20
73
+ }, l = {
74
+ noiseFloor: .015,
75
+ gain: 4.6,
76
+ exponent: 1.15,
77
+ attack: .1,
78
+ release: .48
79
+ };
80
+ function u(e) {
81
+ switch (e) {
82
+ case "speaking": return "speaking";
83
+ case "thinking": return "thinking";
84
+ case "listening":
85
+ case "idle": return "listening";
86
+ case "connecting":
87
+ case "pre-connect-buffering":
88
+ case "initializing": return "connecting";
89
+ case "disconnected": return "idle";
90
+ case "failed": return "error";
91
+ default: return "idle";
92
+ }
93
+ }
94
+ function d(e) {
95
+ return "RoomClass" in e;
96
+ }
97
+ function f(e) {
98
+ return typeof e == "function" ? e() : e;
99
+ }
100
+ function p(e) {
101
+ if (!e) return {};
102
+ let t = {}, n = (e, n) => {
103
+ n !== void 0 && (t[e] = n);
104
+ };
105
+ return n("roomName", f(e.roomName)), n("participantName", f(e.participantName)), n("participantIdentity", f(e.participantIdentity)), n("participantMetadata", f(e.participantMetadata)), n("participantAttributes", typeof e.participantAttributes == "function" ? e.participantAttributes() : e.participantAttributes), n("agentName", f(e.agentName)), n("agentMetadata", f(e.agentMetadata)), n("deployment", f(e.deployment)), t;
106
+ }
107
+ function m(e) {
108
+ if (!e.serverUrl || !e.participantToken) throw Error("[orb-ui/livekit] connection details must include serverUrl and participantToken.");
109
+ return e;
110
+ }
111
+ async function h(e) {
112
+ let t = p(e.tokenOptions);
113
+ return typeof e.getConnectionDetails == "function" ? m(await e.getConnectionDetails(t)) : e.tokenSource ? m(await e.tokenSource.fetch(t)) : m({
114
+ serverUrl: e.serverUrl,
115
+ participantToken: e.participantToken
116
+ });
117
+ }
118
+ function g(e) {
119
+ for (let [, t] of e.remoteParticipants) if (!t.isLocal && (t.kind === s || t.attributes?.["lk.agent.state"] !== void 0)) return t;
120
+ return null;
121
+ }
122
+ function _(e, t, n) {
123
+ let r = e.off;
124
+ if (r) {
125
+ r.call(e, t, n);
126
+ return;
127
+ }
128
+ e.removeListener?.call(e, t, n);
129
+ }
130
+ function v(e, t, n) {
131
+ e.on.call(e, t, n);
132
+ }
133
+ function y(t) {
134
+ let n = d(t), r = t.createAudioAnalyser, i = { current: n ? null : t.room }, o = /* @__PURE__ */ new Set(), f = {
135
+ state: "idle",
136
+ volume: 0,
137
+ inputVolume: 0,
138
+ outputVolume: 0
139
+ }, p = "idle", m = null, y = null, b = null, x = null, S = null, C = null, w = null, T = 0, E = null;
140
+ function D(e) {
141
+ f = e, o.forEach((t) => t(e));
142
+ }
143
+ function O(e) {
144
+ D({
145
+ ...f,
146
+ ...e,
147
+ state: e.state ?? f.state
148
+ });
149
+ }
150
+ function k() {
151
+ let e = typeof t.outputVolumeCalibration == "function" ? t.outputVolumeCalibration() : t.outputVolumeCalibration;
152
+ return {
153
+ ...l,
154
+ ...e
155
+ };
156
+ }
157
+ function A(e) {
158
+ let n = a(e, T, k);
159
+ return T = n.normalized, t.onOutputVolumeSample?.(n), n.normalized;
160
+ }
161
+ function j() {
162
+ T = 0, O({
163
+ volume: 0,
164
+ outputVolume: 0
165
+ });
166
+ }
167
+ function M({ emitZero: e = !0 } = {}) {
168
+ S &&= (clearInterval(S), null), x &&= (x.cleanup().catch(() => {}), null), e && O({
169
+ volume: 0,
170
+ inputVolume: 0
171
+ });
172
+ }
173
+ function N(t) {
174
+ if (!(m === t && x)) {
175
+ M({ emitZero: !1 }), m = t;
176
+ try {
177
+ x = r(t, c);
178
+ } catch (e) {
179
+ console.warn("[orb-ui/livekit] local createAudioAnalyser failed:", e);
180
+ return;
181
+ }
182
+ S = setInterval(() => {
183
+ if (!x || p !== "listening") return;
184
+ let t = e(x.calculateVolume());
185
+ O({
186
+ volume: t,
187
+ inputVolume: t,
188
+ outputVolume: 0
189
+ });
190
+ }, 33);
191
+ }
192
+ }
193
+ function P({ emitZero: e = !0 } = {}) {
194
+ w &&= (clearInterval(w), null), C &&= (C.cleanup().catch(() => {}), null), T = 0, e && O({
195
+ volume: 0,
196
+ outputVolume: 0
197
+ });
198
+ }
199
+ function F(e) {
200
+ P();
201
+ try {
202
+ C = r(e, c);
203
+ } catch (e) {
204
+ console.warn("[orb-ui/livekit] remote createAudioAnalyser failed:", e);
205
+ return;
206
+ }
207
+ w = setInterval(() => {
208
+ if (!C || p !== "speaking") return;
209
+ let e = A(C.calculateVolume());
210
+ O({
211
+ volume: e,
212
+ inputVolume: 0,
213
+ outputVolume: e
214
+ });
215
+ }, 33);
216
+ }
217
+ function I(e) {
218
+ p = e, O({
219
+ state: e,
220
+ volume: 0,
221
+ inputVolume: 0,
222
+ outputVolume: 0
223
+ }), e === "speaking" && y ? F(y) : e !== "speaking" && P({ emitZero: !1 });
224
+ }
225
+ function L(e) {
226
+ b || typeof document > "u" || (b = e.attach(), b.id = "orb-ui-livekit-agent-audio", document.body.appendChild(b));
227
+ }
228
+ function R() {
229
+ b &&= (b.remove(), null);
230
+ }
231
+ function z(e) {
232
+ y = e, L(e), p === "speaking" && F(e);
233
+ }
234
+ function B(e) {
235
+ N(e);
236
+ }
237
+ function V(e) {
238
+ let t = e.getTrackPublication?.("microphone");
239
+ t?.track && B(t.track);
240
+ }
241
+ function H(e) {
242
+ let t = u(e);
243
+ t !== p && I(t);
244
+ }
245
+ function U(e) {
246
+ let t = e.attributes?.["lk.agent.state"];
247
+ t && H(t);
248
+ let n = e.getTrackPublication("microphone");
249
+ n?.track && z(n.track);
250
+ }
251
+ function W(e) {
252
+ if (E) return;
253
+ let t = (e, t) => {
254
+ if (t.isLocal) return;
255
+ let n = e["lk.agent.state"];
256
+ n && H(n);
257
+ }, n = (e, t, n) => {
258
+ n.isLocal || n.kind !== s && n.attributes?.["lk.agent.state"] === void 0 || e.mediaStreamTrack.kind !== "audio" || z(e);
259
+ }, r = (e) => {
260
+ y === e && (y = null, R(), P());
261
+ }, i = (e) => {
262
+ e.source === "microphone" && e.track && B(e.track);
263
+ }, a = (e) => {
264
+ e.source === "microphone" && (m = null, M());
265
+ }, o = () => {
266
+ m = null, y = null, R(), M({ emitZero: !1 }), P({ emitZero: !1 }), I("idle");
267
+ };
268
+ if (v(e, "participantAttributesChanged", t), v(e, "trackSubscribed", n), v(e, "trackUnsubscribed", r), v(e, "localTrackPublished", i), v(e, "localTrackUnpublished", a), v(e, "disconnected", o), E = () => {
269
+ _(e, "participantAttributesChanged", t), _(e, "trackSubscribed", n), _(e, "trackUnsubscribed", r), _(e, "localTrackPublished", i), _(e, "localTrackUnpublished", a), _(e, "disconnected", o);
270
+ }, V(e.localParticipant), e.state === "connected") {
271
+ let t = g(e);
272
+ t ? U(t) : I("connecting");
273
+ } else I("idle");
274
+ }
275
+ function G() {
276
+ E?.(), E = null, m = null, y = null, R(), M({ emitZero: !1 }), P({ emitZero: !1 }), O({
277
+ volume: 0,
278
+ inputVolume: 0,
279
+ outputVolume: 0
280
+ });
281
+ }
282
+ let K = (e) => {
283
+ o.add(e), e(f);
284
+ let t = i.current;
285
+ return t && W(t), () => {
286
+ o.delete(e), o.size === 0 && G();
287
+ };
288
+ };
289
+ return n ? {
290
+ subscribe: K,
291
+ async start() {
292
+ if (i.current) return;
293
+ let e = t, n = new e.RoomClass();
294
+ I("connecting");
295
+ try {
296
+ let t = await h(e);
297
+ if (await n.connect(t.serverUrl, t.participantToken, e.connectOptions), i.current = n, W(n), e.enableMicrophone !== !1) {
298
+ let e = (await n.localParticipant.setMicrophoneEnabled(!0))?.track ?? n.localParticipant.getTrackPublication?.("microphone")?.track;
299
+ e && B(e);
300
+ }
301
+ } catch (e) {
302
+ throw console.error("[orb-ui/livekit] connect failed:", e), i.current === n && G(), n.disconnect(), i.current = null, I("error"), j(), O({ error: e }), e;
303
+ }
304
+ },
305
+ async stop() {
306
+ let e = i.current;
307
+ if (!e) {
308
+ I("idle");
309
+ return;
310
+ }
311
+ G(), e.disconnect(), i.current = null, I("idle");
312
+ }
313
+ } : { subscribe: K };
314
+ }
315
+ //#endregion
316
+ export { o as i, t as n, a as r, y as t };
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./livekit-D-s4sYba.cjs");let t=require("livekit-client");function n(){return`orb-${globalThis.crypto?.randomUUID?.()??`${Date.now()}-${Math.random().toString(36).slice(2)}`}`}function r(r){let{agentMetadata:i,agentName:a,connectOptions:o,deployment:s,enableMicrophone:c,participantAttributes:l,participantIdentity:u,participantMetadata:d,participantName:f,roomName:p=n,outputVolumeCalibration:m,onOutputVolumeSample:h}=r,g=r.tokenEndpoint===void 0?t.TokenSource.sandboxTokenServer(r.sandboxId,r.sandboxOptions):t.TokenSource.endpoint(r.tokenEndpoint,r.tokenEndpointOptions);return e.t({tokenSource:g,tokenOptions:{agentMetadata:i,agentName:a,deployment:s,participantAttributes:l,participantIdentity:u,participantMetadata:d,participantName:f,roomName:p},connectOptions:o,enableMicrophone:c,outputVolumeCalibration:m,onOutputVolumeSample:h,createAudioAnalyser:t.createAudioAnalyser,RoomClass:t.Room})}exports.createLiveKitAdapter=r;
@@ -0,0 +1,30 @@
1
+ import { t as e } from "./livekit-Z3IMmWaG.js";
2
+ import { Room as t, TokenSource as n, createAudioAnalyser as r } from "livekit-client";
3
+ //#region src/adapters/livekit/browser.ts
4
+ function i() {
5
+ return `orb-${globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`}`;
6
+ }
7
+ function a(a) {
8
+ let { agentMetadata: o, agentName: s, connectOptions: c, deployment: l, enableMicrophone: u, participantAttributes: d, participantIdentity: f, participantMetadata: p, participantName: m, roomName: h = i, outputVolumeCalibration: g, onOutputVolumeSample: _ } = a, v = a.tokenEndpoint === void 0 ? n.sandboxTokenServer(a.sandboxId, a.sandboxOptions) : n.endpoint(a.tokenEndpoint, a.tokenEndpointOptions);
9
+ return e({
10
+ tokenSource: v,
11
+ tokenOptions: {
12
+ agentMetadata: o,
13
+ agentName: s,
14
+ deployment: l,
15
+ participantAttributes: d,
16
+ participantIdentity: f,
17
+ participantMetadata: p,
18
+ participantName: m,
19
+ roomName: h
20
+ },
21
+ connectOptions: c,
22
+ enableMicrophone: u,
23
+ outputVolumeCalibration: g,
24
+ onOutputVolumeSample: _,
25
+ createAudioAnalyser: r,
26
+ RoomClass: t
27
+ });
28
+ }
29
+ //#endregion
30
+ export { a as createLiveKitAdapter };