@navai/voice-frontend 0.1.2 → 0.1.3
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/dist/Orb-B4OSC3XR.js +6 -0
- package/dist/chunk-KBBRQQLK.js +531 -0
- package/dist/index.cjs +903 -0
- package/dist/index.d.cts +101 -1
- package/dist/index.d.ts +101 -1
- package/dist/index.js +354 -0
- package/package.json +2 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { RealtimeAgent } from '@openai/agents/realtime';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
4
|
|
|
3
5
|
type NavaiFunctionPayload = Record<string, unknown>;
|
|
4
6
|
type NavaiFunctionContext = {
|
|
@@ -130,4 +132,102 @@ type UseWebVoiceAgentResult = {
|
|
|
130
132
|
};
|
|
131
133
|
declare function useWebVoiceAgent(options: UseWebVoiceAgentOptions): UseWebVoiceAgentResult;
|
|
132
134
|
|
|
133
|
-
|
|
135
|
+
type OrbProps = {
|
|
136
|
+
hue?: number;
|
|
137
|
+
autoHueShift?: boolean;
|
|
138
|
+
hueShiftMin?: number;
|
|
139
|
+
hueShiftMax?: number;
|
|
140
|
+
hueShiftHalfCycleSeconds?: number;
|
|
141
|
+
hoverIntensity?: number;
|
|
142
|
+
rotateOnHover?: boolean;
|
|
143
|
+
forceHoverState?: boolean;
|
|
144
|
+
enablePointerHover?: boolean;
|
|
145
|
+
backgroundColor?: string;
|
|
146
|
+
animate?: boolean;
|
|
147
|
+
};
|
|
148
|
+
declare function Orb({ hue, autoHueShift, hueShiftMin, hueShiftMax, hueShiftHalfCycleSeconds, hoverIntensity, rotateOnHover, forceHoverState, enablePointerHover, backgroundColor, animate }: OrbProps): react_jsx_runtime.JSX.Element;
|
|
149
|
+
|
|
150
|
+
type NavaiHeroOrbProps = {
|
|
151
|
+
className?: string;
|
|
152
|
+
backgroundColor?: string;
|
|
153
|
+
isAgentSpeaking?: boolean;
|
|
154
|
+
hoverIntensitySpeaking?: number;
|
|
155
|
+
hoverIntensityIdle?: number;
|
|
156
|
+
revealDelayMs?: number;
|
|
157
|
+
autoplayDelayMs?: number;
|
|
158
|
+
};
|
|
159
|
+
declare function clampNavaiOrbDelayMs(value: number, fallback: number): number;
|
|
160
|
+
declare function NavaiHeroOrb({ className, backgroundColor, isAgentSpeaking, hoverIntensitySpeaking, hoverIntensityIdle, revealDelayMs, autoplayDelayMs }: NavaiHeroOrbProps): react_jsx_runtime.JSX.Element | null;
|
|
161
|
+
|
|
162
|
+
type NavaiVoiceOrbThemeMode = "light" | "dark";
|
|
163
|
+
type NavaiVoiceOrbPlacement = "inline" | "bottom-right" | "bottom-left";
|
|
164
|
+
type NavaiWebVoiceAgentLike = Pick<UseWebVoiceAgentResult, "status" | "agentVoiceState" | "error" | "isConnecting" | "isConnected" | "isAgentSpeaking" | "start" | "stop">;
|
|
165
|
+
type NavaiVoiceOrbMessages = {
|
|
166
|
+
ariaStart: string;
|
|
167
|
+
ariaStop: string;
|
|
168
|
+
idle: string;
|
|
169
|
+
connecting: string;
|
|
170
|
+
listening: string;
|
|
171
|
+
speaking: string;
|
|
172
|
+
errorPrefix: string;
|
|
173
|
+
};
|
|
174
|
+
type NavaiVoiceOrbRuntimeSnapshot = {
|
|
175
|
+
status: UseWebVoiceAgentResult["status"];
|
|
176
|
+
agentVoiceState: UseWebVoiceAgentResult["agentVoiceState"];
|
|
177
|
+
isAgentSpeaking: boolean;
|
|
178
|
+
error: string | null;
|
|
179
|
+
};
|
|
180
|
+
type NavaiVoiceOrbBaseProps = {
|
|
181
|
+
className?: string;
|
|
182
|
+
style?: CSSProperties;
|
|
183
|
+
themeMode?: NavaiVoiceOrbThemeMode;
|
|
184
|
+
placement?: NavaiVoiceOrbPlacement;
|
|
185
|
+
backgroundColorLight?: string;
|
|
186
|
+
backgroundColorDark?: string;
|
|
187
|
+
showStatus?: boolean;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
type NavaiMiniOrbDockProps = {
|
|
191
|
+
className?: string;
|
|
192
|
+
style?: CSSProperties;
|
|
193
|
+
themeMode?: NavaiVoiceOrbThemeMode;
|
|
194
|
+
placement?: NavaiVoiceOrbPlacement;
|
|
195
|
+
isActive?: boolean;
|
|
196
|
+
isConnected?: boolean;
|
|
197
|
+
isDisabled?: boolean;
|
|
198
|
+
isAgentSpeaking?: boolean;
|
|
199
|
+
animateOrb?: boolean;
|
|
200
|
+
backgroundColor?: string;
|
|
201
|
+
buttonAriaLabel: string;
|
|
202
|
+
buttonIcon?: ReactNode;
|
|
203
|
+
buttonType?: "button" | "submit" | "reset";
|
|
204
|
+
onButtonClick?: () => void;
|
|
205
|
+
statusMessage?: string;
|
|
206
|
+
isError?: boolean;
|
|
207
|
+
ariaMessage?: string;
|
|
208
|
+
};
|
|
209
|
+
declare function NavaiMiniOrbDock({ className, style, themeMode, placement, isActive, isConnected, isDisabled, isAgentSpeaking, animateOrb, backgroundColor, buttonAriaLabel, buttonIcon, buttonType, onButtonClick, statusMessage, isError, ariaMessage }: NavaiMiniOrbDockProps): react_jsx_runtime.JSX.Element;
|
|
210
|
+
|
|
211
|
+
type NavaiVoiceHeroOrbProps = Omit<NavaiHeroOrbProps, "backgroundColor" | "isAgentSpeaking"> & {
|
|
212
|
+
agent: NavaiWebVoiceAgentLike;
|
|
213
|
+
themeMode?: NavaiVoiceOrbThemeMode;
|
|
214
|
+
backgroundColorLight?: string;
|
|
215
|
+
backgroundColorDark?: string;
|
|
216
|
+
onRuntimeSnapshotChange?: (snapshot: NavaiVoiceOrbRuntimeSnapshot) => void;
|
|
217
|
+
};
|
|
218
|
+
declare function NavaiVoiceHeroOrb({ agent, themeMode, backgroundColorLight, backgroundColorDark, onRuntimeSnapshotChange, ...orbProps }: NavaiVoiceHeroOrbProps): react_jsx_runtime.JSX.Element;
|
|
219
|
+
|
|
220
|
+
declare function resolveNavaiVoiceOrbRuntimeSnapshot(agent: Pick<UseWebVoiceAgentResult, "status" | "agentVoiceState" | "isAgentSpeaking" | "error">): NavaiVoiceOrbRuntimeSnapshot;
|
|
221
|
+
type NavaiVoiceOrbDockProps = NavaiVoiceOrbBaseProps & {
|
|
222
|
+
agent: NavaiWebVoiceAgentLike;
|
|
223
|
+
messages?: Partial<NavaiVoiceOrbMessages>;
|
|
224
|
+
};
|
|
225
|
+
declare function NavaiVoiceOrbDock({ agent, className, style, themeMode, placement, backgroundColorLight, backgroundColorDark, showStatus, messages }: NavaiVoiceOrbDockProps): react_jsx_runtime.JSX.Element;
|
|
226
|
+
|
|
227
|
+
type NavaiVoiceOrbDockMicIconProps = {
|
|
228
|
+
isActive?: boolean;
|
|
229
|
+
size?: number;
|
|
230
|
+
};
|
|
231
|
+
declare function NavaiVoiceOrbDockMicIcon({ isActive, size }: NavaiVoiceOrbDockMicIconProps): react_jsx_runtime.JSX.Element;
|
|
232
|
+
|
|
233
|
+
export { type BuildNavaiAgentOptions, type BuildNavaiAgentResult, type CreateNavaiBackendClientOptions, type ExecuteNavaiBackendFunction, type ExecuteNavaiBackendFunctionInput, type NavaiBackendClient, type NavaiBackendFunctionDefinition, type NavaiFunctionContext, type NavaiFunctionDefinition, type NavaiFunctionModuleLoaders, type NavaiFunctionPayload, type NavaiFunctionsRegistry, NavaiHeroOrb, type NavaiHeroOrbProps, NavaiMiniOrbDock, type NavaiMiniOrbDockProps, type NavaiRoute, NavaiVoiceHeroOrb, type NavaiVoiceHeroOrbProps, type NavaiVoiceOrbBaseProps, NavaiVoiceOrbDock, NavaiVoiceOrbDockMicIcon, type NavaiVoiceOrbDockProps, type NavaiVoiceOrbMessages, type NavaiVoiceOrbPlacement, type NavaiVoiceOrbRuntimeSnapshot, type NavaiVoiceOrbThemeMode, type NavaiWebVoiceAgentLike, Orb, type OrbProps, type ResolveNavaiFrontendRuntimeConfigOptions, type ResolveNavaiFrontendRuntimeConfigResult, type UseWebVoiceAgentOptions, type UseWebVoiceAgentResult, buildNavaiAgent, clampNavaiOrbDelayMs, createNavaiBackendClient, getNavaiRoutePromptLines, loadNavaiFunctions, resolveNavaiFrontendRuntimeConfig, resolveNavaiRoute, resolveNavaiVoiceOrbRuntimeSnapshot, useWebVoiceAgent };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { RealtimeAgent } from '@openai/agents/realtime';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
4
|
|
|
3
5
|
type NavaiFunctionPayload = Record<string, unknown>;
|
|
4
6
|
type NavaiFunctionContext = {
|
|
@@ -130,4 +132,102 @@ type UseWebVoiceAgentResult = {
|
|
|
130
132
|
};
|
|
131
133
|
declare function useWebVoiceAgent(options: UseWebVoiceAgentOptions): UseWebVoiceAgentResult;
|
|
132
134
|
|
|
133
|
-
|
|
135
|
+
type OrbProps = {
|
|
136
|
+
hue?: number;
|
|
137
|
+
autoHueShift?: boolean;
|
|
138
|
+
hueShiftMin?: number;
|
|
139
|
+
hueShiftMax?: number;
|
|
140
|
+
hueShiftHalfCycleSeconds?: number;
|
|
141
|
+
hoverIntensity?: number;
|
|
142
|
+
rotateOnHover?: boolean;
|
|
143
|
+
forceHoverState?: boolean;
|
|
144
|
+
enablePointerHover?: boolean;
|
|
145
|
+
backgroundColor?: string;
|
|
146
|
+
animate?: boolean;
|
|
147
|
+
};
|
|
148
|
+
declare function Orb({ hue, autoHueShift, hueShiftMin, hueShiftMax, hueShiftHalfCycleSeconds, hoverIntensity, rotateOnHover, forceHoverState, enablePointerHover, backgroundColor, animate }: OrbProps): react_jsx_runtime.JSX.Element;
|
|
149
|
+
|
|
150
|
+
type NavaiHeroOrbProps = {
|
|
151
|
+
className?: string;
|
|
152
|
+
backgroundColor?: string;
|
|
153
|
+
isAgentSpeaking?: boolean;
|
|
154
|
+
hoverIntensitySpeaking?: number;
|
|
155
|
+
hoverIntensityIdle?: number;
|
|
156
|
+
revealDelayMs?: number;
|
|
157
|
+
autoplayDelayMs?: number;
|
|
158
|
+
};
|
|
159
|
+
declare function clampNavaiOrbDelayMs(value: number, fallback: number): number;
|
|
160
|
+
declare function NavaiHeroOrb({ className, backgroundColor, isAgentSpeaking, hoverIntensitySpeaking, hoverIntensityIdle, revealDelayMs, autoplayDelayMs }: NavaiHeroOrbProps): react_jsx_runtime.JSX.Element | null;
|
|
161
|
+
|
|
162
|
+
type NavaiVoiceOrbThemeMode = "light" | "dark";
|
|
163
|
+
type NavaiVoiceOrbPlacement = "inline" | "bottom-right" | "bottom-left";
|
|
164
|
+
type NavaiWebVoiceAgentLike = Pick<UseWebVoiceAgentResult, "status" | "agentVoiceState" | "error" | "isConnecting" | "isConnected" | "isAgentSpeaking" | "start" | "stop">;
|
|
165
|
+
type NavaiVoiceOrbMessages = {
|
|
166
|
+
ariaStart: string;
|
|
167
|
+
ariaStop: string;
|
|
168
|
+
idle: string;
|
|
169
|
+
connecting: string;
|
|
170
|
+
listening: string;
|
|
171
|
+
speaking: string;
|
|
172
|
+
errorPrefix: string;
|
|
173
|
+
};
|
|
174
|
+
type NavaiVoiceOrbRuntimeSnapshot = {
|
|
175
|
+
status: UseWebVoiceAgentResult["status"];
|
|
176
|
+
agentVoiceState: UseWebVoiceAgentResult["agentVoiceState"];
|
|
177
|
+
isAgentSpeaking: boolean;
|
|
178
|
+
error: string | null;
|
|
179
|
+
};
|
|
180
|
+
type NavaiVoiceOrbBaseProps = {
|
|
181
|
+
className?: string;
|
|
182
|
+
style?: CSSProperties;
|
|
183
|
+
themeMode?: NavaiVoiceOrbThemeMode;
|
|
184
|
+
placement?: NavaiVoiceOrbPlacement;
|
|
185
|
+
backgroundColorLight?: string;
|
|
186
|
+
backgroundColorDark?: string;
|
|
187
|
+
showStatus?: boolean;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
type NavaiMiniOrbDockProps = {
|
|
191
|
+
className?: string;
|
|
192
|
+
style?: CSSProperties;
|
|
193
|
+
themeMode?: NavaiVoiceOrbThemeMode;
|
|
194
|
+
placement?: NavaiVoiceOrbPlacement;
|
|
195
|
+
isActive?: boolean;
|
|
196
|
+
isConnected?: boolean;
|
|
197
|
+
isDisabled?: boolean;
|
|
198
|
+
isAgentSpeaking?: boolean;
|
|
199
|
+
animateOrb?: boolean;
|
|
200
|
+
backgroundColor?: string;
|
|
201
|
+
buttonAriaLabel: string;
|
|
202
|
+
buttonIcon?: ReactNode;
|
|
203
|
+
buttonType?: "button" | "submit" | "reset";
|
|
204
|
+
onButtonClick?: () => void;
|
|
205
|
+
statusMessage?: string;
|
|
206
|
+
isError?: boolean;
|
|
207
|
+
ariaMessage?: string;
|
|
208
|
+
};
|
|
209
|
+
declare function NavaiMiniOrbDock({ className, style, themeMode, placement, isActive, isConnected, isDisabled, isAgentSpeaking, animateOrb, backgroundColor, buttonAriaLabel, buttonIcon, buttonType, onButtonClick, statusMessage, isError, ariaMessage }: NavaiMiniOrbDockProps): react_jsx_runtime.JSX.Element;
|
|
210
|
+
|
|
211
|
+
type NavaiVoiceHeroOrbProps = Omit<NavaiHeroOrbProps, "backgroundColor" | "isAgentSpeaking"> & {
|
|
212
|
+
agent: NavaiWebVoiceAgentLike;
|
|
213
|
+
themeMode?: NavaiVoiceOrbThemeMode;
|
|
214
|
+
backgroundColorLight?: string;
|
|
215
|
+
backgroundColorDark?: string;
|
|
216
|
+
onRuntimeSnapshotChange?: (snapshot: NavaiVoiceOrbRuntimeSnapshot) => void;
|
|
217
|
+
};
|
|
218
|
+
declare function NavaiVoiceHeroOrb({ agent, themeMode, backgroundColorLight, backgroundColorDark, onRuntimeSnapshotChange, ...orbProps }: NavaiVoiceHeroOrbProps): react_jsx_runtime.JSX.Element;
|
|
219
|
+
|
|
220
|
+
declare function resolveNavaiVoiceOrbRuntimeSnapshot(agent: Pick<UseWebVoiceAgentResult, "status" | "agentVoiceState" | "isAgentSpeaking" | "error">): NavaiVoiceOrbRuntimeSnapshot;
|
|
221
|
+
type NavaiVoiceOrbDockProps = NavaiVoiceOrbBaseProps & {
|
|
222
|
+
agent: NavaiWebVoiceAgentLike;
|
|
223
|
+
messages?: Partial<NavaiVoiceOrbMessages>;
|
|
224
|
+
};
|
|
225
|
+
declare function NavaiVoiceOrbDock({ agent, className, style, themeMode, placement, backgroundColorLight, backgroundColorDark, showStatus, messages }: NavaiVoiceOrbDockProps): react_jsx_runtime.JSX.Element;
|
|
226
|
+
|
|
227
|
+
type NavaiVoiceOrbDockMicIconProps = {
|
|
228
|
+
isActive?: boolean;
|
|
229
|
+
size?: number;
|
|
230
|
+
};
|
|
231
|
+
declare function NavaiVoiceOrbDockMicIcon({ isActive, size }: NavaiVoiceOrbDockMicIconProps): react_jsx_runtime.JSX.Element;
|
|
232
|
+
|
|
233
|
+
export { type BuildNavaiAgentOptions, type BuildNavaiAgentResult, type CreateNavaiBackendClientOptions, type ExecuteNavaiBackendFunction, type ExecuteNavaiBackendFunctionInput, type NavaiBackendClient, type NavaiBackendFunctionDefinition, type NavaiFunctionContext, type NavaiFunctionDefinition, type NavaiFunctionModuleLoaders, type NavaiFunctionPayload, type NavaiFunctionsRegistry, NavaiHeroOrb, type NavaiHeroOrbProps, NavaiMiniOrbDock, type NavaiMiniOrbDockProps, type NavaiRoute, NavaiVoiceHeroOrb, type NavaiVoiceHeroOrbProps, type NavaiVoiceOrbBaseProps, NavaiVoiceOrbDock, NavaiVoiceOrbDockMicIcon, type NavaiVoiceOrbDockProps, type NavaiVoiceOrbMessages, type NavaiVoiceOrbPlacement, type NavaiVoiceOrbRuntimeSnapshot, type NavaiVoiceOrbThemeMode, type NavaiWebVoiceAgentLike, Orb, type OrbProps, type ResolveNavaiFrontendRuntimeConfigOptions, type ResolveNavaiFrontendRuntimeConfigResult, type UseWebVoiceAgentOptions, type UseWebVoiceAgentResult, buildNavaiAgent, clampNavaiOrbDelayMs, createNavaiBackendClient, getNavaiRoutePromptLines, loadNavaiFunctions, resolveNavaiFrontendRuntimeConfig, resolveNavaiRoute, resolveNavaiVoiceOrbRuntimeSnapshot, useWebVoiceAgent };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Orb,
|
|
3
|
+
useNavaiVoiceOrbStyles
|
|
4
|
+
} from "./chunk-KBBRQQLK.js";
|
|
5
|
+
|
|
1
6
|
// src/agent.ts
|
|
2
7
|
import { RealtimeAgent, tool } from "@openai/agents/realtime";
|
|
3
8
|
import { z } from "zod";
|
|
@@ -880,12 +885,361 @@ function useWebVoiceAgent(options) {
|
|
|
880
885
|
stop
|
|
881
886
|
};
|
|
882
887
|
}
|
|
888
|
+
|
|
889
|
+
// src/orb/NavaiHeroOrb.tsx
|
|
890
|
+
import { useEffect as useEffect3, useMemo as useMemo2, useState as useState3 } from "react";
|
|
891
|
+
|
|
892
|
+
// src/orb/dynamic.tsx
|
|
893
|
+
import { lazy, Suspense, useEffect as useEffect2, useState as useState2 } from "react";
|
|
894
|
+
import { jsx } from "react/jsx-runtime";
|
|
895
|
+
function dynamic(loader, options = {}) {
|
|
896
|
+
const { ssr = true, loading: LoadingComponent } = options;
|
|
897
|
+
const LazyComponent = lazy(async () => {
|
|
898
|
+
const loaded = await loader();
|
|
899
|
+
if (typeof loaded === "function") {
|
|
900
|
+
return { default: loaded };
|
|
901
|
+
}
|
|
902
|
+
return loaded;
|
|
903
|
+
});
|
|
904
|
+
function DynamicComponent(props) {
|
|
905
|
+
const [isClientReady, setIsClientReady] = useState2(ssr);
|
|
906
|
+
useEffect2(() => {
|
|
907
|
+
if (!ssr) {
|
|
908
|
+
setIsClientReady(true);
|
|
909
|
+
}
|
|
910
|
+
}, [ssr]);
|
|
911
|
+
if (!isClientReady) {
|
|
912
|
+
return null;
|
|
913
|
+
}
|
|
914
|
+
const fallback = LoadingComponent ? /* @__PURE__ */ jsx(LoadingComponent, {}) : null;
|
|
915
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback, children: /* @__PURE__ */ jsx(LazyComponent, { ...props }) });
|
|
916
|
+
}
|
|
917
|
+
DynamicComponent.displayName = "DynamicComponent";
|
|
918
|
+
return DynamicComponent;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// src/orb/NavaiHeroOrb.tsx
|
|
922
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
923
|
+
var Orb2 = dynamic(() => import("./Orb-B4OSC3XR.js"), {
|
|
924
|
+
ssr: false
|
|
925
|
+
});
|
|
926
|
+
var ORB_DELAY_MS_MIN = 0;
|
|
927
|
+
var ORB_DELAY_MS_MAX = 6e4;
|
|
928
|
+
var DEFAULT_AUTOPLAY_DELAY_MS = 9e3;
|
|
929
|
+
var DEFAULT_REVEAL_DELAY_MS = 5200;
|
|
930
|
+
function clampNavaiOrbDelayMs(value, fallback) {
|
|
931
|
+
const numericValue = Number.isFinite(value) ? value : fallback;
|
|
932
|
+
return Math.min(ORB_DELAY_MS_MAX, Math.max(ORB_DELAY_MS_MIN, numericValue));
|
|
933
|
+
}
|
|
934
|
+
function NavaiHeroOrb({
|
|
935
|
+
className = "",
|
|
936
|
+
backgroundColor = "#000000",
|
|
937
|
+
isAgentSpeaking = false,
|
|
938
|
+
hoverIntensitySpeaking = 0.66,
|
|
939
|
+
hoverIntensityIdle = 0.08,
|
|
940
|
+
revealDelayMs = DEFAULT_REVEAL_DELAY_MS,
|
|
941
|
+
autoplayDelayMs = DEFAULT_AUTOPLAY_DELAY_MS
|
|
942
|
+
}) {
|
|
943
|
+
useNavaiVoiceOrbStyles();
|
|
944
|
+
const resolvedRevealDelayMs = clampNavaiOrbDelayMs(revealDelayMs, DEFAULT_REVEAL_DELAY_MS);
|
|
945
|
+
const resolvedAutoplayDelayMs = clampNavaiOrbDelayMs(autoplayDelayMs, DEFAULT_AUTOPLAY_DELAY_MS);
|
|
946
|
+
const [isOrbReady, setIsOrbReady] = useState3(resolvedRevealDelayMs === 0);
|
|
947
|
+
const [isOrbAutoAnimating, setIsOrbAutoAnimating] = useState3(resolvedAutoplayDelayMs === 0);
|
|
948
|
+
useEffect3(() => {
|
|
949
|
+
if (typeof window === "undefined" || resolvedRevealDelayMs === 0) {
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
const revealOrb = () => setIsOrbReady(true);
|
|
953
|
+
window.addEventListener("pointerdown", revealOrb, { passive: true, once: true });
|
|
954
|
+
window.addEventListener("touchstart", revealOrb, { passive: true, once: true });
|
|
955
|
+
window.addEventListener("keydown", revealOrb, { once: true });
|
|
956
|
+
const timeoutId = window.setTimeout(revealOrb, resolvedRevealDelayMs);
|
|
957
|
+
return () => {
|
|
958
|
+
window.removeEventListener("pointerdown", revealOrb);
|
|
959
|
+
window.removeEventListener("touchstart", revealOrb);
|
|
960
|
+
window.removeEventListener("keydown", revealOrb);
|
|
961
|
+
window.clearTimeout(timeoutId);
|
|
962
|
+
};
|
|
963
|
+
}, [resolvedRevealDelayMs]);
|
|
964
|
+
useEffect3(() => {
|
|
965
|
+
if (typeof window === "undefined" || resolvedAutoplayDelayMs === 0) {
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
let started = false;
|
|
969
|
+
const startOrbAnimation = () => {
|
|
970
|
+
if (started) {
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
973
|
+
started = true;
|
|
974
|
+
setIsOrbAutoAnimating(true);
|
|
975
|
+
};
|
|
976
|
+
if (navigator.userActivation?.hasBeenActive) {
|
|
977
|
+
startOrbAnimation();
|
|
978
|
+
}
|
|
979
|
+
window.addEventListener("pointerdown", startOrbAnimation, { passive: true, once: true });
|
|
980
|
+
window.addEventListener("touchstart", startOrbAnimation, { passive: true, once: true });
|
|
981
|
+
window.addEventListener("keydown", startOrbAnimation, { once: true });
|
|
982
|
+
const timeoutId = window.setTimeout(startOrbAnimation, resolvedAutoplayDelayMs);
|
|
983
|
+
return () => {
|
|
984
|
+
window.removeEventListener("pointerdown", startOrbAnimation);
|
|
985
|
+
window.removeEventListener("touchstart", startOrbAnimation);
|
|
986
|
+
window.removeEventListener("keydown", startOrbAnimation);
|
|
987
|
+
window.clearTimeout(timeoutId);
|
|
988
|
+
};
|
|
989
|
+
}, [resolvedAutoplayDelayMs]);
|
|
990
|
+
const orbHoverIntensity = useMemo2(() => {
|
|
991
|
+
return isAgentSpeaking ? hoverIntensitySpeaking : hoverIntensityIdle;
|
|
992
|
+
}, [hoverIntensityIdle, hoverIntensitySpeaking, isAgentSpeaking]);
|
|
993
|
+
if (!isOrbReady) {
|
|
994
|
+
return null;
|
|
995
|
+
}
|
|
996
|
+
return /* @__PURE__ */ jsx2("div", { className: ["navai-voice-orb-hero", className].filter(Boolean).join(" "), children: /* @__PURE__ */ jsx2(
|
|
997
|
+
Orb2,
|
|
998
|
+
{
|
|
999
|
+
hoverIntensity: orbHoverIntensity,
|
|
1000
|
+
rotateOnHover: true,
|
|
1001
|
+
forceHoverState: isAgentSpeaking,
|
|
1002
|
+
enablePointerHover: false,
|
|
1003
|
+
animate: isAgentSpeaking || isOrbAutoAnimating,
|
|
1004
|
+
backgroundColor
|
|
1005
|
+
}
|
|
1006
|
+
) });
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
// src/orb/NavaiMiniOrbDock.tsx
|
|
1010
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
1011
|
+
var Orb3 = dynamic(() => import("./Orb-B4OSC3XR.js"), {
|
|
1012
|
+
ssr: false
|
|
1013
|
+
});
|
|
1014
|
+
function NavaiMiniOrbDock({
|
|
1015
|
+
className = "",
|
|
1016
|
+
style,
|
|
1017
|
+
themeMode = "dark",
|
|
1018
|
+
placement = "bottom-right",
|
|
1019
|
+
isActive = false,
|
|
1020
|
+
isConnected = false,
|
|
1021
|
+
isDisabled = false,
|
|
1022
|
+
isAgentSpeaking = false,
|
|
1023
|
+
animateOrb = true,
|
|
1024
|
+
backgroundColor = "#060914",
|
|
1025
|
+
buttonAriaLabel,
|
|
1026
|
+
buttonIcon,
|
|
1027
|
+
buttonType = "button",
|
|
1028
|
+
onButtonClick,
|
|
1029
|
+
statusMessage = "",
|
|
1030
|
+
isError = false,
|
|
1031
|
+
ariaMessage = ""
|
|
1032
|
+
}) {
|
|
1033
|
+
useNavaiVoiceOrbStyles();
|
|
1034
|
+
const dockClassName = ["navai-voice-orb-dock", `is-${placement}`, themeMode === "light" ? "is-light" : "", className].filter(Boolean).join(" ");
|
|
1035
|
+
const shouldHighlightOrb = isAgentSpeaking || isActive;
|
|
1036
|
+
const orbHoverIntensity = isAgentSpeaking ? 0.66 : 0.08;
|
|
1037
|
+
return /* @__PURE__ */ jsxs("aside", { className: dockClassName, style, children: [
|
|
1038
|
+
/* @__PURE__ */ jsxs("div", { className: "navai-voice-orb-wrap", children: [
|
|
1039
|
+
/* @__PURE__ */ jsx3("div", { className: ["navai-voice-orb-surface", shouldHighlightOrb ? "is-highlighted" : ""].filter(Boolean).join(" "), children: /* @__PURE__ */ jsx3(
|
|
1040
|
+
Orb3,
|
|
1041
|
+
{
|
|
1042
|
+
hoverIntensity: orbHoverIntensity,
|
|
1043
|
+
rotateOnHover: true,
|
|
1044
|
+
forceHoverState: isAgentSpeaking,
|
|
1045
|
+
enablePointerHover: false,
|
|
1046
|
+
animate: animateOrb,
|
|
1047
|
+
backgroundColor
|
|
1048
|
+
}
|
|
1049
|
+
) }),
|
|
1050
|
+
/* @__PURE__ */ jsx3("div", { className: ["navai-voice-orb-button-shell", isConnected ? "is-active" : ""].filter(Boolean).join(" "), children: /* @__PURE__ */ jsx3(
|
|
1051
|
+
"button",
|
|
1052
|
+
{
|
|
1053
|
+
type: buttonType,
|
|
1054
|
+
className: [
|
|
1055
|
+
"navai-voice-orb-button",
|
|
1056
|
+
isConnected ? "is-active" : "",
|
|
1057
|
+
isActive && !isConnected ? "is-connecting" : ""
|
|
1058
|
+
].filter(Boolean).join(" "),
|
|
1059
|
+
onClick: onButtonClick,
|
|
1060
|
+
disabled: isDisabled,
|
|
1061
|
+
"aria-label": buttonAriaLabel,
|
|
1062
|
+
children: buttonIcon
|
|
1063
|
+
}
|
|
1064
|
+
) })
|
|
1065
|
+
] }),
|
|
1066
|
+
statusMessage ? /* @__PURE__ */ jsx3("p", { className: ["navai-voice-orb-status", isError ? "is-error" : ""].filter(Boolean).join(" "), role: "status", children: statusMessage }) : null,
|
|
1067
|
+
/* @__PURE__ */ jsx3("span", { className: "navai-voice-orb-live", "aria-live": "polite", children: ariaMessage })
|
|
1068
|
+
] });
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// src/orb/NavaiVoiceHeroOrb.tsx
|
|
1072
|
+
import { useEffect as useEffect4 } from "react";
|
|
1073
|
+
|
|
1074
|
+
// src/orb/NavaiVoiceOrbDock.tsx
|
|
1075
|
+
import { useCallback as useCallback2, useMemo as useMemo3 } from "react";
|
|
1076
|
+
|
|
1077
|
+
// src/orb/NavaiVoiceOrbDockMicIcon.tsx
|
|
1078
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1079
|
+
function NavaiVoiceOrbDockMicIcon({
|
|
1080
|
+
isActive = false,
|
|
1081
|
+
size = 20
|
|
1082
|
+
}) {
|
|
1083
|
+
return /* @__PURE__ */ jsxs2(
|
|
1084
|
+
"svg",
|
|
1085
|
+
{
|
|
1086
|
+
width: size,
|
|
1087
|
+
height: size,
|
|
1088
|
+
viewBox: "0 0 24 24",
|
|
1089
|
+
fill: "none",
|
|
1090
|
+
stroke: "currentColor",
|
|
1091
|
+
strokeWidth: "2",
|
|
1092
|
+
strokeLinecap: "round",
|
|
1093
|
+
strokeLinejoin: "round",
|
|
1094
|
+
"aria-hidden": "true",
|
|
1095
|
+
className: ["navai-voice-orb-icon", isActive ? "is-pulsing" : ""].filter(Boolean).join(" "),
|
|
1096
|
+
children: [
|
|
1097
|
+
/* @__PURE__ */ jsx4("path", { d: "M12 3a3 3 0 0 0-3 3v6a3 3 0 1 0 6 0V6a3 3 0 0 0-3-3Z" }),
|
|
1098
|
+
/* @__PURE__ */ jsx4("path", { d: "M19 10v2a7 7 0 1 1-14 0v-2" }),
|
|
1099
|
+
/* @__PURE__ */ jsx4("path", { d: "M12 19v3" })
|
|
1100
|
+
]
|
|
1101
|
+
}
|
|
1102
|
+
);
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// src/orb/NavaiVoiceOrbDockSpinnerIcon.tsx
|
|
1106
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1107
|
+
function NavaiVoiceOrbDockSpinnerIcon({
|
|
1108
|
+
size = 20
|
|
1109
|
+
}) {
|
|
1110
|
+
const style = {
|
|
1111
|
+
width: size,
|
|
1112
|
+
height: size
|
|
1113
|
+
};
|
|
1114
|
+
return /* @__PURE__ */ jsx5("span", { "aria-hidden": "true", className: "navai-voice-orb-spinner", style });
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
// src/orb/NavaiVoiceOrbDock.tsx
|
|
1118
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
1119
|
+
var DEFAULT_MESSAGES = {
|
|
1120
|
+
ariaStart: "Activate NAVAI voice",
|
|
1121
|
+
ariaStop: "Deactivate NAVAI voice",
|
|
1122
|
+
idle: "NAVAI ready to start.",
|
|
1123
|
+
connecting: "Connecting NAVAI voice...",
|
|
1124
|
+
listening: "NAVAI is listening.",
|
|
1125
|
+
speaking: "NAVAI is speaking.",
|
|
1126
|
+
errorPrefix: "NAVAI error"
|
|
1127
|
+
};
|
|
1128
|
+
function resolveNavaiVoiceOrbRuntimeSnapshot(agent) {
|
|
1129
|
+
return {
|
|
1130
|
+
status: agent.status,
|
|
1131
|
+
agentVoiceState: agent.agentVoiceState,
|
|
1132
|
+
isAgentSpeaking: agent.isAgentSpeaking,
|
|
1133
|
+
error: agent.error
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
1136
|
+
function resolveStatusMessage(runtimeSnapshot, messages) {
|
|
1137
|
+
if (runtimeSnapshot.error) {
|
|
1138
|
+
return `${messages.errorPrefix}: ${runtimeSnapshot.error}`;
|
|
1139
|
+
}
|
|
1140
|
+
if (runtimeSnapshot.isAgentSpeaking) {
|
|
1141
|
+
return messages.speaking;
|
|
1142
|
+
}
|
|
1143
|
+
if (runtimeSnapshot.status === "connecting") {
|
|
1144
|
+
return messages.connecting;
|
|
1145
|
+
}
|
|
1146
|
+
if (runtimeSnapshot.status === "connected") {
|
|
1147
|
+
return messages.listening;
|
|
1148
|
+
}
|
|
1149
|
+
return messages.idle;
|
|
1150
|
+
}
|
|
1151
|
+
function NavaiVoiceOrbDock({
|
|
1152
|
+
agent,
|
|
1153
|
+
className,
|
|
1154
|
+
style,
|
|
1155
|
+
themeMode = "dark",
|
|
1156
|
+
placement = "bottom-right",
|
|
1157
|
+
backgroundColorLight = "#f4f6fb",
|
|
1158
|
+
backgroundColorDark = "#060914",
|
|
1159
|
+
showStatus = true,
|
|
1160
|
+
messages
|
|
1161
|
+
}) {
|
|
1162
|
+
const resolvedMessages = useMemo3(() => ({ ...DEFAULT_MESSAGES, ...messages }), [messages]);
|
|
1163
|
+
const runtimeSnapshot = useMemo3(() => resolveNavaiVoiceOrbRuntimeSnapshot(agent), [agent]);
|
|
1164
|
+
const statusMessage = showStatus ? resolveStatusMessage(runtimeSnapshot, resolvedMessages) : "";
|
|
1165
|
+
const isError = runtimeSnapshot.status === "error" || Boolean(runtimeSnapshot.error);
|
|
1166
|
+
const isConnecting = runtimeSnapshot.status === "connecting";
|
|
1167
|
+
const isActive = runtimeSnapshot.status === "connecting" || runtimeSnapshot.status === "connected";
|
|
1168
|
+
const isDisabled = agent.isConnecting;
|
|
1169
|
+
const shouldAnimateOrb = runtimeSnapshot.status !== "error";
|
|
1170
|
+
const handleToggle = useCallback2(() => {
|
|
1171
|
+
if (agent.isConnecting) {
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
if (agent.isConnected) {
|
|
1175
|
+
agent.stop();
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
void agent.start();
|
|
1179
|
+
}, [agent]);
|
|
1180
|
+
return /* @__PURE__ */ jsx6(
|
|
1181
|
+
NavaiMiniOrbDock,
|
|
1182
|
+
{
|
|
1183
|
+
className,
|
|
1184
|
+
style,
|
|
1185
|
+
themeMode,
|
|
1186
|
+
placement,
|
|
1187
|
+
isActive,
|
|
1188
|
+
isConnected: agent.isConnected,
|
|
1189
|
+
isDisabled,
|
|
1190
|
+
isAgentSpeaking: agent.isAgentSpeaking,
|
|
1191
|
+
animateOrb: shouldAnimateOrb,
|
|
1192
|
+
backgroundColor: themeMode === "light" ? backgroundColorLight : backgroundColorDark,
|
|
1193
|
+
buttonAriaLabel: isConnecting ? resolvedMessages.connecting : agent.isConnected ? resolvedMessages.ariaStop : resolvedMessages.ariaStart,
|
|
1194
|
+
buttonIcon: isConnecting ? /* @__PURE__ */ jsx6(NavaiVoiceOrbDockSpinnerIcon, {}) : /* @__PURE__ */ jsx6(NavaiVoiceOrbDockMicIcon, { isActive: agent.isConnected || agent.isAgentSpeaking }),
|
|
1195
|
+
onButtonClick: handleToggle,
|
|
1196
|
+
statusMessage,
|
|
1197
|
+
isError,
|
|
1198
|
+
ariaMessage: statusMessage
|
|
1199
|
+
}
|
|
1200
|
+
);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
// src/orb/NavaiVoiceHeroOrb.tsx
|
|
1204
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1205
|
+
function NavaiVoiceHeroOrb({
|
|
1206
|
+
agent,
|
|
1207
|
+
themeMode = "dark",
|
|
1208
|
+
backgroundColorLight = "#ffffff",
|
|
1209
|
+
backgroundColorDark = "#000000",
|
|
1210
|
+
onRuntimeSnapshotChange,
|
|
1211
|
+
...orbProps
|
|
1212
|
+
}) {
|
|
1213
|
+
const runtimeSnapshot = resolveNavaiVoiceOrbRuntimeSnapshot(agent);
|
|
1214
|
+
useEffect4(() => {
|
|
1215
|
+
if (typeof onRuntimeSnapshotChange === "function") {
|
|
1216
|
+
onRuntimeSnapshotChange(runtimeSnapshot);
|
|
1217
|
+
}
|
|
1218
|
+
}, [onRuntimeSnapshotChange, runtimeSnapshot]);
|
|
1219
|
+
return /* @__PURE__ */ jsx7(
|
|
1220
|
+
NavaiHeroOrb,
|
|
1221
|
+
{
|
|
1222
|
+
...orbProps,
|
|
1223
|
+
isAgentSpeaking: runtimeSnapshot.isAgentSpeaking,
|
|
1224
|
+
backgroundColor: themeMode === "light" ? backgroundColorLight : backgroundColorDark,
|
|
1225
|
+
className: themeMode === "light" ? "is-light" : ""
|
|
1226
|
+
}
|
|
1227
|
+
);
|
|
1228
|
+
}
|
|
883
1229
|
export {
|
|
1230
|
+
NavaiHeroOrb,
|
|
1231
|
+
NavaiMiniOrbDock,
|
|
1232
|
+
NavaiVoiceHeroOrb,
|
|
1233
|
+
NavaiVoiceOrbDock,
|
|
1234
|
+
NavaiVoiceOrbDockMicIcon,
|
|
1235
|
+
Orb,
|
|
884
1236
|
buildNavaiAgent,
|
|
1237
|
+
clampNavaiOrbDelayMs,
|
|
885
1238
|
createNavaiBackendClient,
|
|
886
1239
|
getNavaiRoutePromptLines,
|
|
887
1240
|
loadNavaiFunctions,
|
|
888
1241
|
resolveNavaiFrontendRuntimeConfig,
|
|
889
1242
|
resolveNavaiRoute,
|
|
1243
|
+
resolveNavaiVoiceOrbRuntimeSnapshot,
|
|
890
1244
|
useWebVoiceAgent
|
|
891
1245
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@navai/voice-frontend",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Frontend helpers to build OpenAI Realtime voice agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@openai/agents": "^0.4.14",
|
|
35
|
+
"ogl": "^1.0.11",
|
|
35
36
|
"zod": "^4.0.0"
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|