@navsi.ai/sdk 1.0.2 → 1.0.4

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.
@@ -1,2 +1,2 @@
1
- export{f as ChatbotProvider,g as ChatbotWidget}from'../chunk-UQND4TVW.js';import'../chunk-ZCUOPOFP.js';//# sourceMappingURL=index.js.map
1
+ export{f as ChatbotProvider,g as ChatbotWidget}from'../chunk-NVT44CWP.js';import'../chunk-BM6443KF.js';//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
@@ -101,4 +101,50 @@ interface UseActionExecutionReturn {
101
101
  */
102
102
  declare function useActionExecution(): UseActionExecutionReturn;
103
103
 
104
- export { type UseActionExecutionReturn, type UseChatbotReturn, type UseWebSocketReturn, useActionExecution, useChatbot, useWebSocket };
104
+ /**
105
+ * useVoice Hook — Low-latency STT + TTS for the Navsi chatbot.
106
+ *
107
+ * Design goals:
108
+ * • Fast start: reuses a single SpeechRecognition instance across activations.
109
+ * • Low latency: fires an auto-send after a configurable silence gap so the
110
+ * user doesn't have to wait for the browser's default end-of-speech timeout.
111
+ * • Clean separation: all voice state is encapsulated here; ChatbotWidget
112
+ * only consumes the returned API.
113
+ * • TTS warm-up: a silent utterance is queued once so the first real TTS play
114
+ * doesn't incur a cold-start delay.
115
+ *
116
+ * Only depends on the Web Speech API — no extra packages.
117
+ */
118
+ interface UseVoiceOptions {
119
+ /** BCP-47 language for STT & TTS (e.g. 'en-US'). */
120
+ lang: string;
121
+ /** Called with the final transcript when the user finishes speaking. */
122
+ onTranscript: (text: string) => void;
123
+ /** Milliseconds of silence before auto-sending (default 1200). */
124
+ silenceMs?: number;
125
+ /** Whether TTS should speak new assistant messages triggered by voice input. */
126
+ autoSpeak?: boolean;
127
+ }
128
+ interface UseVoiceReturn {
129
+ /** Whether the Web Speech API is available in this browser. */
130
+ isSupported: boolean;
131
+ /** Whether the mic is currently active / recording. */
132
+ isListening: boolean;
133
+ /** Live interim transcript while recording. */
134
+ transcript: string;
135
+ /** Human-readable error, or null. */
136
+ error: string | null;
137
+ /** Start recording. No-op if already listening. */
138
+ start: () => void;
139
+ /** Stop recording (fires onTranscript if there is accumulated text). */
140
+ stop: () => void;
141
+ /** Speak text aloud via TTS. */
142
+ speak: (text: string) => void;
143
+ /** Cancel any ongoing TTS playback. */
144
+ cancelSpeech: () => void;
145
+ /** Whether TTS is currently speaking. */
146
+ isSpeaking: boolean;
147
+ }
148
+ declare function useVoice({ lang, onTranscript, silenceMs, autoSpeak, }: UseVoiceOptions): UseVoiceReturn;
149
+
150
+ export { type UseActionExecutionReturn, type UseChatbotReturn, type UseVoiceOptions, type UseVoiceReturn, type UseWebSocketReturn, useActionExecution, useChatbot, useVoice, useWebSocket };
@@ -1,2 +1,2 @@
1
- import'../chunk-427NHGTX.js';export{d as useActionExecution,c as useChatbot,e as useWebSocket}from'../chunk-ZCUOPOFP.js';//# sourceMappingURL=index.js.map
1
+ import'../chunk-EL7YGOTY.js';export{d as useActionExecution,c as useChatbot,f as useVoice,e as useWebSocket}from'../chunk-BM6443KF.js';//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { ChatbotProvider, ChatbotProviderProps, ChatbotWidget, ChatbotWidgetProps } from './components/index.js';
2
- export { UseActionExecutionReturn, UseChatbotReturn, UseWebSocketReturn, useActionExecution, useChatbot, useWebSocket } from './hooks/index.js';
2
+ export { UseActionExecutionReturn, UseChatbotReturn, UseVoiceOptions, UseVoiceReturn, UseWebSocketReturn, useActionExecution, useChatbot, useVoice, useWebSocket } from './hooks/index.js';
3
3
  import * as React from 'react';
4
4
  import { WidgetConfig, Message, ChatMode, ConnectionState as ConnectionState$1, ExecutionState, ServerAction, ClientMessage, WebSocketEvents, NavigationAdapter, PageContext } from '@navsi.ai/shared';
5
5
  export { ActionDefinition, ChatMode, Command, ExecutionState, Message, NavigationAdapter, PageContext, SDKConfig, ServerAction, WidgetConfig, WidgetTheme } from '@navsi.ai/shared';
@@ -86,9 +86,17 @@ declare class WebSocketClient {
86
86
  */
87
87
  connect(): void;
88
88
  /**
89
- * Disconnect from the server
89
+ * Disconnect from the server.
90
+ * Clears timers and closes the socket but preserves event listeners
91
+ * so that a subsequent connect() call works correctly.
92
+ * Use destroy() for full teardown including listener removal.
90
93
  */
91
94
  disconnect(): void;
95
+ /**
96
+ * Fully tear down the client — clears all timers, listeners, and the socket.
97
+ * Use this when the client will not be reused (e.g., on component unmount).
98
+ */
99
+ destroy(): void;
92
100
  /**
93
101
  * Send a message to the server
94
102
  */
@@ -116,6 +124,8 @@ declare class WebSocketClient {
116
124
  private createWebSocket;
117
125
  private handleOpen;
118
126
  private handleMessage;
127
+ /** Close codes that indicate permanent failures — reconnecting would be futile */
128
+ private static readonly NON_RETRIABLE_CLOSE_CODES;
119
129
  private handleClose;
120
130
  private handleError;
121
131
  private handleConnected;
@@ -131,6 +141,15 @@ declare class WebSocketClient {
131
141
  private handleConnectionFailure;
132
142
  private flushMessageQueue;
133
143
  private setState;
144
+ /**
145
+ * Close the socket and timers but preserve event listeners.
146
+ * Used by disconnect() to allow reconnection with existing listeners.
147
+ */
148
+ private closeSocket;
149
+ /**
150
+ * Full cleanup — closes socket, timers, AND clears all event listeners.
151
+ * Used by destroy() for permanent teardown.
152
+ */
134
153
  private cleanup;
135
154
  private log;
136
155
  }
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export{f as ChatbotProvider,g as ChatbotWidget,d as NavigationController,a as WebSocketClient,c as createMemoryAdapter,e as createNavigationController,b as createWebSocketClient}from'./chunk-UQND4TVW.js';import'./chunk-427NHGTX.js';export{a as ChatbotContext,d as useActionExecution,c as useChatbot,b as useChatbotContext,e as useWebSocket}from'./chunk-ZCUOPOFP.js';import {useRef,useEffect,useCallback}from'react';function T(s,o){let i=useRef(new Set),n=useRef(o.pathname);useEffect(()=>{o.pathname!==n.current&&(n.current=o.pathname,i.current.forEach(t=>{t(o.pathname);}));},[o.pathname]);let r=useCallback(t=>{s(t);},[s]),u=useCallback(()=>n.current,[]),a=useCallback(t=>(i.current.add(t),()=>{i.current.delete(t);}),[]),f=useCallback(async(t,d=1e4)=>new Promise(p=>{if(n.current===t){p(true);return}let c=false,g=a(C=>{C===t&&!c&&(c=true,g(),p(true));});setTimeout(()=>{c||(c=true,g(),p(n.current===t));},d);}),[a]),e=useRef(null);return e.current?(e.current.navigate=r,e.current.getCurrentPath=u,e.current.onRouteChange=a,e.current.waitForRoute=f):e.current={navigate:r,getCurrentPath:u,onRouteChange:a,waitForRoute:f},e.current}function E(s,o,i){let n=new Set;return i(r=>{n.forEach(u=>u(r.pathname));}),{navigate(r){s()(r);},getCurrentPath(){return o().pathname},onRouteChange(r){return n.add(r),()=>n.delete(r)},async waitForRoute(r,u=1e4){return new Promise(a=>{if(o().pathname===r){a(true);return}let e=false,t=this.onRouteChange(d=>{d===r&&!e&&(e=true,t(),a(true));});setTimeout(()=>{e||(e=true,t(),a(o().pathname===r));},u);})}}}function k(s,o){let i=useRef(new Set),n=useRef(o);useEffect(()=>{o!==n.current&&(n.current=o,i.current.forEach(t=>{t(o);}));},[o]);let r=useCallback(t=>{s.push(t);},[s]),u=useCallback(()=>n.current,[]),a=useCallback(t=>(i.current.add(t),()=>{i.current.delete(t);}),[]),f=useCallback(async(t,d=1e4)=>new Promise(p=>{if(n.current===t){p(true);return}let c=false,g=a(C=>{C===t&&!c&&(c=true,g(),p(true));});setTimeout(()=>{c||(c=true,g(),p(n.current===t));},d);}),[a]),e=useRef(null);return e.current?(e.current.navigate=r,e.current.getCurrentPath=u,e.current.onRouteChange=a,e.current.waitForRoute=f):e.current={navigate:r,getCurrentPath:u,onRouteChange:a,waitForRoute:f},e.current}export{E as createReactRouterAdapter,k as useNextRouterAdapter,T as useReactRouterAdapter};//# sourceMappingURL=index.js.map
1
+ export{f as ChatbotProvider,g as ChatbotWidget,d as NavigationController,a as WebSocketClient,c as createMemoryAdapter,e as createNavigationController,b as createWebSocketClient}from'./chunk-NVT44CWP.js';import'./chunk-EL7YGOTY.js';export{a as ChatbotContext,d as useActionExecution,c as useChatbot,b as useChatbotContext,f as useVoice,e as useWebSocket}from'./chunk-BM6443KF.js';import {useRef,useEffect,useCallback}from'react';function T(s,o){let i=useRef(new Set),n=useRef(o.pathname);useEffect(()=>{o.pathname!==n.current&&(n.current=o.pathname,i.current.forEach(t=>{t(o.pathname);}));},[o.pathname]);let r=useCallback(t=>{s(t);},[s]),u=useCallback(()=>n.current,[]),a=useCallback(t=>(i.current.add(t),()=>{i.current.delete(t);}),[]),f=useCallback(async(t,d=1e4)=>new Promise(p=>{if(n.current===t){p(true);return}let c=false,g=a(C=>{C===t&&!c&&(c=true,g(),p(true));});setTimeout(()=>{c||(c=true,g(),p(n.current===t));},d);}),[a]),e=useRef(null);return e.current?(e.current.navigate=r,e.current.getCurrentPath=u,e.current.onRouteChange=a,e.current.waitForRoute=f):e.current={navigate:r,getCurrentPath:u,onRouteChange:a,waitForRoute:f},e.current}function E(s,o,i){let n=new Set;return i(r=>{n.forEach(u=>u(r.pathname));}),{navigate(r){s()(r);},getCurrentPath(){return o().pathname},onRouteChange(r){return n.add(r),()=>n.delete(r)},async waitForRoute(r,u=1e4){return new Promise(a=>{if(o().pathname===r){a(true);return}let e=false,t=this.onRouteChange(d=>{d===r&&!e&&(e=true,t(),a(true));});setTimeout(()=>{e||(e=true,t(),a(o().pathname===r));},u);})}}}function U(s,o){let i=useRef(new Set),n=useRef(o);useEffect(()=>{o!==n.current&&(n.current=o,i.current.forEach(t=>{t(o);}));},[o]);let r=useCallback(t=>{s.push(t);},[s]),u=useCallback(()=>n.current,[]),a=useCallback(t=>(i.current.add(t),()=>{i.current.delete(t);}),[]),f=useCallback(async(t,d=1e4)=>new Promise(p=>{if(n.current===t){p(true);return}let c=false,g=a(C=>{C===t&&!c&&(c=true,g(),p(true));});setTimeout(()=>{c||(c=true,g(),p(n.current===t));},d);}),[a]),e=useRef(null);return e.current?(e.current.navigate=r,e.current.getCurrentPath=u,e.current.onRouteChange=a,e.current.waitForRoute=f):e.current={navigate:r,getCurrentPath:u,onRouteChange:a,waitForRoute:f},e.current}export{E as createReactRouterAdapter,U as useNextRouterAdapter,T as useReactRouterAdapter};//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/navigation/react-router-adapter.ts","../src/core/navigation/nextjs-adapter.ts"],"names":["useReactRouterAdapter","navigate","location","listenersRef","useRef","currentPathRef","useEffect","callback","navigateTo","useCallback","path","getCurrentPath","onRouteChange","waitForRoute","timeout","resolve","resolved","unsubscribe","newPath","adapterRef","createReactRouterAdapter","getNavigate","getLocation","subscribeToLocation","listeners","useNextRouterAdapter","router","pathname"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * React Router v6 Adapter\n * \n * Provides navigation adapter implementation for React Router v6.\n * This is a hook that creates an adapter from React Router hooks.\n */\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport type { NavigationAdapter } from '@navsi.ai/shared';\nimport { DEFAULT_ROUTE_TIMEOUT } from './adapter.js';\n\n/**\n * Type for React Router's navigate function\n */\nexport type NavigateFunction = (to: string) => void;\n\n/**\n * Type for React Router's location object\n */\nexport interface RouterLocation {\n pathname: string;\n}\n\n/**\n * Creates a React Router v6 navigation adapter\n * \n * @example\n * ```tsx\n * import { useNavigate, useLocation } from 'react-router-dom';\n * \n * function App() {\n * const navigate = useNavigate();\n * const location = useLocation();\n * const adapter = useReactRouterAdapter(navigate, location);\n * \n * return (\n * <ChatbotProvider navigationAdapter={adapter}>\n * ...\n * </ChatbotProvider>\n * );\n * }\n * ```\n */\nexport function useReactRouterAdapter(\n navigate: NavigateFunction,\n location: RouterLocation\n): NavigationAdapter {\n const listenersRef = useRef<Set<(path: string) => void>>(new Set());\n const currentPathRef = useRef(location.pathname);\n\n // Update current path and notify listeners when location changes\n useEffect(() => {\n if (location.pathname !== currentPathRef.current) {\n currentPathRef.current = location.pathname;\n listenersRef.current.forEach((callback) => {\n callback(location.pathname);\n });\n }\n }, [location.pathname]);\n\n const navigateTo = useCallback((path: string) => {\n navigate(path);\n }, [navigate]);\n\n const getCurrentPath = useCallback(() => {\n return currentPathRef.current;\n }, []);\n\n const onRouteChange = useCallback((callback: (path: string) => void) => {\n listenersRef.current.add(callback);\n return () => {\n listenersRef.current.delete(callback);\n };\n }, []);\n\n const waitForRoute = useCallback(async (path: string, timeout = DEFAULT_ROUTE_TIMEOUT): Promise<boolean> => {\n return new Promise((resolve) => {\n if (currentPathRef.current === path) {\n resolve(true);\n return;\n }\n\n let resolved = false;\n\n const unsubscribe = onRouteChange((newPath) => {\n if (newPath === path && !resolved) {\n resolved = true;\n unsubscribe();\n resolve(true);\n }\n });\n\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n unsubscribe();\n resolve(currentPathRef.current === path);\n }\n }, timeout);\n });\n }, [onRouteChange]);\n\n // Return a stable reference to the adapter\n const adapterRef = useRef<NavigationAdapter | null>(null);\n\n if (!adapterRef.current) {\n adapterRef.current = {\n navigate: navigateTo,\n getCurrentPath,\n onRouteChange,\n waitForRoute,\n };\n } else {\n // Update functions to use latest refs\n adapterRef.current.navigate = navigateTo;\n adapterRef.current.getCurrentPath = getCurrentPath;\n adapterRef.current.onRouteChange = onRouteChange;\n adapterRef.current.waitForRoute = waitForRoute;\n }\n\n return adapterRef.current;\n}\n\n/**\n * Create a React Router adapter from outside React context\n * Useful when you need to create the adapter before rendering\n * \n * @param getNavigate Function that returns the navigate function\n * @param getLocation Function that returns the current location\n */\nexport function createReactRouterAdapter(\n getNavigate: () => NavigateFunction,\n getLocation: () => RouterLocation,\n subscribeToLocation: (callback: (location: RouterLocation) => void) => () => void\n): NavigationAdapter {\n const listeners = new Set<(path: string) => void>();\n\n // Subscribe to location changes\n subscribeToLocation((location) => {\n listeners.forEach((callback) => callback(location.pathname));\n });\n\n return {\n navigate(path: string): void {\n getNavigate()(path);\n },\n\n getCurrentPath(): string {\n return getLocation().pathname;\n },\n\n onRouteChange(callback: (path: string) => void): () => void {\n listeners.add(callback);\n return () => listeners.delete(callback);\n },\n\n async waitForRoute(path: string, timeout = DEFAULT_ROUTE_TIMEOUT): Promise<boolean> {\n return new Promise((resolve) => {\n const currentPath = getLocation().pathname;\n\n if (currentPath === path) {\n resolve(true);\n return;\n }\n\n let resolved = false;\n\n const unsubscribe = this.onRouteChange((newPath) => {\n if (newPath === path && !resolved) {\n resolved = true;\n unsubscribe();\n resolve(true);\n }\n });\n\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n unsubscribe();\n resolve(getLocation().pathname === path);\n }\n }, timeout);\n });\n },\n };\n}\n","'use client';\n/**\n * Next.js App Router Adapter\n *\n * Provides navigation adapter implementation for Next.js App Router.\n * Uses next/navigation: useRouter(), usePathname().\n */\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport type { NavigationAdapter } from '@navsi.ai/shared';\nimport { DEFAULT_ROUTE_TIMEOUT } from './adapter.js';\n\n/** Next.js App Router: router from useRouter(), pathname from usePathname() */\nexport type NextRouterLike = { push: (href: string) => void };\n\n/**\n * Creates a Next.js App Router navigation adapter.\n * Must be used in a Client Component. Requires next to be installed.\n *\n * @example\n * ```tsx\n * 'use client';\n * import { useRouter, usePathname } from 'next/navigation';\n * import { ChatbotProvider, ChatbotWidget, useNextRouterAdapter } from '@navsi.ai/sdk';\n *\n * function ChatbotWrapper({ children }: { children: React.ReactNode }) {\n * const router = useRouter();\n * const pathname = usePathname();\n * const adapter = useNextRouterAdapter(router, pathname);\n * return (\n * <ChatbotProvider apiKey=\"...\" serverUrl=\"...\" navigationAdapter={adapter}>\n * {children}\n * <ChatbotWidget />\n * </ChatbotProvider>\n * );\n * }\n * ```\n */\nexport function useNextRouterAdapter(\n router: NextRouterLike,\n pathname: string\n): NavigationAdapter {\n const listenersRef = useRef<Set<(path: string) => void>>(new Set());\n const currentPathRef = useRef(pathname);\n\n useEffect(() => {\n if (pathname !== currentPathRef.current) {\n currentPathRef.current = pathname;\n listenersRef.current.forEach((callback) => {\n callback(pathname);\n });\n }\n }, [pathname]);\n\n const navigateTo = useCallback(\n (path: string) => {\n router.push(path);\n },\n [router]\n );\n\n const getCurrentPath = useCallback(() => {\n return currentPathRef.current;\n }, []);\n\n const onRouteChange = useCallback((callback: (path: string) => void) => {\n listenersRef.current.add(callback);\n return () => {\n listenersRef.current.delete(callback);\n };\n }, []);\n\n const waitForRoute = useCallback(\n async (path: string, timeout = DEFAULT_ROUTE_TIMEOUT): Promise<boolean> => {\n return new Promise((resolve) => {\n if (currentPathRef.current === path) {\n resolve(true);\n return;\n }\n\n let resolved = false;\n\n const unsubscribe = onRouteChange((newPath) => {\n if (newPath === path && !resolved) {\n resolved = true;\n unsubscribe();\n resolve(true);\n }\n });\n\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n unsubscribe();\n resolve(currentPathRef.current === path);\n }\n }, timeout);\n });\n },\n [onRouteChange]\n );\n\n const adapterRef = useRef<NavigationAdapter | null>(null);\n\n if (!adapterRef.current) {\n adapterRef.current = {\n navigate: navigateTo,\n getCurrentPath,\n onRouteChange,\n waitForRoute,\n };\n } else {\n adapterRef.current.navigate = navigateTo;\n adapterRef.current.getCurrentPath = getCurrentPath;\n adapterRef.current.onRouteChange = onRouteChange;\n adapterRef.current.waitForRoute = waitForRoute;\n }\n\n return adapterRef.current;\n}\n"]}
1
+ {"version":3,"sources":["../src/core/navigation/react-router-adapter.ts","../src/core/navigation/nextjs-adapter.ts"],"names":["useReactRouterAdapter","navigate","location","listenersRef","useRef","currentPathRef","useEffect","callback","navigateTo","useCallback","path","getCurrentPath","onRouteChange","waitForRoute","timeout","resolve","resolved","unsubscribe","newPath","adapterRef","createReactRouterAdapter","getNavigate","getLocation","subscribeToLocation","listeners","useNextRouterAdapter","router","pathname"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * React Router v6 Adapter\n * \n * Provides navigation adapter implementation for React Router v6.\n * This is a hook that creates an adapter from React Router hooks.\n */\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport type { NavigationAdapter } from '@navsi.ai/shared';\nimport { DEFAULT_ROUTE_TIMEOUT } from './adapter.js';\n\n/**\n * Type for React Router's navigate function\n */\nexport type NavigateFunction = (to: string) => void;\n\n/**\n * Type for React Router's location object\n */\nexport interface RouterLocation {\n pathname: string;\n}\n\n/**\n * Creates a React Router v6 navigation adapter\n * \n * @example\n * ```tsx\n * import { useNavigate, useLocation } from 'react-router-dom';\n * \n * function App() {\n * const navigate = useNavigate();\n * const location = useLocation();\n * const adapter = useReactRouterAdapter(navigate, location);\n * \n * return (\n * <ChatbotProvider navigationAdapter={adapter}>\n * ...\n * </ChatbotProvider>\n * );\n * }\n * ```\n */\nexport function useReactRouterAdapter(\n navigate: NavigateFunction,\n location: RouterLocation\n): NavigationAdapter {\n const listenersRef = useRef<Set<(path: string) => void>>(new Set());\n const currentPathRef = useRef(location.pathname);\n\n // Update current path and notify listeners when location changes\n useEffect(() => {\n if (location.pathname !== currentPathRef.current) {\n currentPathRef.current = location.pathname;\n listenersRef.current.forEach((callback) => {\n callback(location.pathname);\n });\n }\n }, [location.pathname]);\n\n const navigateTo = useCallback((path: string) => {\n navigate(path);\n }, [navigate]);\n\n const getCurrentPath = useCallback(() => {\n return currentPathRef.current;\n }, []);\n\n const onRouteChange = useCallback((callback: (path: string) => void) => {\n listenersRef.current.add(callback);\n return () => {\n listenersRef.current.delete(callback);\n };\n }, []);\n\n const waitForRoute = useCallback(async (path: string, timeout = DEFAULT_ROUTE_TIMEOUT): Promise<boolean> => {\n return new Promise((resolve) => {\n if (currentPathRef.current === path) {\n resolve(true);\n return;\n }\n\n let resolved = false;\n\n const unsubscribe = onRouteChange((newPath) => {\n if (newPath === path && !resolved) {\n resolved = true;\n unsubscribe();\n resolve(true);\n }\n });\n\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n unsubscribe();\n resolve(currentPathRef.current === path);\n }\n }, timeout);\n });\n }, [onRouteChange]);\n\n // Return a stable reference to the adapter\n const adapterRef = useRef<NavigationAdapter | null>(null);\n\n if (!adapterRef.current) {\n adapterRef.current = {\n navigate: navigateTo,\n getCurrentPath,\n onRouteChange,\n waitForRoute,\n };\n } else {\n // Update functions to use latest refs\n adapterRef.current.navigate = navigateTo;\n adapterRef.current.getCurrentPath = getCurrentPath;\n adapterRef.current.onRouteChange = onRouteChange;\n adapterRef.current.waitForRoute = waitForRoute;\n }\n\n return adapterRef.current;\n}\n\n/**\n * Create a React Router adapter from outside React context\n * Useful when you need to create the adapter before rendering\n * \n * @param getNavigate Function that returns the navigate function\n * @param getLocation Function that returns the current location\n */\nexport function createReactRouterAdapter(\n getNavigate: () => NavigateFunction,\n getLocation: () => RouterLocation,\n subscribeToLocation: (callback: (location: RouterLocation) => void) => () => void\n): NavigationAdapter {\n const listeners = new Set<(path: string) => void>();\n\n // Subscribe to location changes\n subscribeToLocation((location) => {\n listeners.forEach((callback) => callback(location.pathname));\n });\n\n return {\n navigate(path: string): void {\n getNavigate()(path);\n },\n\n getCurrentPath(): string {\n return getLocation().pathname;\n },\n\n onRouteChange(callback: (path: string) => void): () => void {\n listeners.add(callback);\n return () => listeners.delete(callback);\n },\n\n async waitForRoute(path: string, timeout = DEFAULT_ROUTE_TIMEOUT): Promise<boolean> {\n return new Promise((resolve) => {\n const currentPath = getLocation().pathname;\n\n if (currentPath === path) {\n resolve(true);\n return;\n }\n\n let resolved = false;\n\n const unsubscribe = this.onRouteChange((newPath) => {\n if (newPath === path && !resolved) {\n resolved = true;\n unsubscribe();\n resolve(true);\n }\n });\n\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n unsubscribe();\n resolve(getLocation().pathname === path);\n }\n }, timeout);\n });\n },\n };\n}\n","'use client';\n/**\n * Next.js App Router Adapter\n *\n * Provides navigation adapter implementation for Next.js App Router.\n * Uses next/navigation: useRouter(), usePathname().\n */\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport type { NavigationAdapter } from '@navsi.ai/shared';\nimport { DEFAULT_ROUTE_TIMEOUT } from './adapter.js';\n\n/** Next.js App Router: router from useRouter(), pathname from usePathname() */\nexport type NextRouterLike = { push: (href: string) => void };\n\n/**\n * Creates a Next.js App Router navigation adapter.\n * Must be used in a Client Component. Requires next to be installed.\n *\n * @example\n * ```tsx\n * 'use client';\n * import { useRouter, usePathname } from 'next/navigation';\n * import { ChatbotProvider, ChatbotWidget, useNextRouterAdapter } from '@navsi.ai/sdk';\n *\n * function ChatbotWrapper({ children }: { children: React.ReactNode }) {\n * const router = useRouter();\n * const pathname = usePathname();\n * const adapter = useNextRouterAdapter(router, pathname);\n * return (\n * <ChatbotProvider apiKey=\"...\" serverUrl=\"...\" navigationAdapter={adapter}>\n * {children}\n * <ChatbotWidget />\n * </ChatbotProvider>\n * );\n * }\n * ```\n */\nexport function useNextRouterAdapter(\n router: NextRouterLike,\n pathname: string\n): NavigationAdapter {\n const listenersRef = useRef<Set<(path: string) => void>>(new Set());\n const currentPathRef = useRef(pathname);\n\n useEffect(() => {\n if (pathname !== currentPathRef.current) {\n currentPathRef.current = pathname;\n listenersRef.current.forEach((callback) => {\n callback(pathname);\n });\n }\n }, [pathname]);\n\n const navigateTo = useCallback(\n (path: string) => {\n router.push(path);\n },\n [router]\n );\n\n const getCurrentPath = useCallback(() => {\n return currentPathRef.current;\n }, []);\n\n const onRouteChange = useCallback((callback: (path: string) => void) => {\n listenersRef.current.add(callback);\n return () => {\n listenersRef.current.delete(callback);\n };\n }, []);\n\n const waitForRoute = useCallback(\n async (path: string, timeout = DEFAULT_ROUTE_TIMEOUT): Promise<boolean> => {\n return new Promise((resolve) => {\n if (currentPathRef.current === path) {\n resolve(true);\n return;\n }\n\n let resolved = false;\n\n const unsubscribe = onRouteChange((newPath) => {\n if (newPath === path && !resolved) {\n resolved = true;\n unsubscribe();\n resolve(true);\n }\n });\n\n setTimeout(() => {\n if (!resolved) {\n resolved = true;\n unsubscribe();\n resolve(currentPathRef.current === path);\n }\n }, timeout);\n });\n },\n [onRouteChange]\n );\n\n const adapterRef = useRef<NavigationAdapter | null>(null);\n\n if (!adapterRef.current) {\n adapterRef.current = {\n navigate: navigateTo,\n getCurrentPath,\n onRouteChange,\n waitForRoute,\n };\n } else {\n adapterRef.current.navigate = navigateTo;\n adapterRef.current.getCurrentPath = getCurrentPath;\n adapterRef.current.onRouteChange = onRouteChange;\n adapterRef.current.waitForRoute = waitForRoute;\n }\n\n return adapterRef.current;\n}\n"]}
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@navsi.ai/sdk",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "React SDK for Navsi AI chatbot - Ask and Navigate modes",
5
5
  "author": "Kushagra Tiwari",
6
6
  "license": "MIT",
7
7
  "type": "module",
8
- "sideEffects": false,
8
+ "sideEffects": [
9
+ "./dist/injectStyles.js",
10
+ "./src/injectStyles.ts"
11
+ ],
9
12
  "repository": {
10
13
  "type": "git",
11
14
  "url": "https://github.com/Bolona-ai/navsi-packages.git",
@@ -40,13 +43,6 @@
40
43
  "files": [
41
44
  "dist"
42
45
  ],
43
- "scripts": {
44
- "build": "tsup",
45
- "dev": "tsup --watch",
46
- "clean": "rm -rf dist",
47
- "lint": "eslint \"src/**/*.{ts,tsx}\"",
48
- "typecheck": "tsc --noEmit"
49
- },
50
46
  "dependencies": {
51
47
  "@navsi.ai/shared": "^1.0.1",
52
48
  "zod": "^3.22.0"
@@ -69,5 +65,12 @@
69
65
  "react-dom": "^18.2.0",
70
66
  "tsup": "^8.0.0",
71
67
  "typescript": "^5.3.0"
68
+ },
69
+ "scripts": {
70
+ "build": "tsup",
71
+ "dev": "tsup --watch",
72
+ "clean": "rm -rf dist",
73
+ "lint": "eslint \"src/**/*.{ts,tsx}\"",
74
+ "typecheck": "tsc --noEmit"
72
75
  }
73
- }
76
+ }
@@ -1,2 +0,0 @@
1
- //# sourceMappingURL=chunk-427NHGTX.js.map
2
- //# sourceMappingURL=chunk-427NHGTX.js.map
@@ -1,19 +0,0 @@
1
- import {a,c,d,e}from'./chunk-ZCUOPOFP.js';import Ke,{useMemo,useReducer,useRef,useState,useEffect,useCallback}from'react';import {z}from'zod';import {createLogger,normalizeWidgetConfig,createMessageId}from'@navsi.ai/shared';import {jsx,jsxs,Fragment}from'react/jsx-runtime';var Ue=class{queue=[];maxSize;constructor(e=100){this.maxSize=e;}enqueue(e){this.queue.length>=this.maxSize&&this.queue.shift(),this.queue.push(e);}dequeueAll(){let e=[...this.queue];return this.queue=[],e}get length(){return this.queue.length}clear(){this.queue=[];}},ge=class{ws=null;config;state="disconnected";logger=createLogger("SDK.WebSocket");reconnectAttempts=0;reconnectTimeout=null;heartbeatInterval=null;lastPongTime=0;messageQueue=new Ue;sessionId=null;refreshToken=null;tokenExpiresAt=0;tokenRefreshTimeout=null;listeners=new Map;constructor(e){this.config={serverUrl:e.serverUrl,apiKey:e.apiKey,autoReconnect:e.autoReconnect??true,maxReconnectAttempts:e.maxReconnectAttempts??10,reconnectDelay:e.reconnectDelay??1e3,heartbeatInterval:e.heartbeatInterval??3e4,debug:e.debug??false},this.logger=createLogger("SDK.WebSocket",{enabled:this.config.debug,level:"debug"});}connect(){if(this.state==="connecting"||this.state==="connected"){this.log("Already connected or connecting");return}this.setState("connecting"),this.createWebSocket();}disconnect(){this.cleanup(),this.setState("disconnected"),this.log("Disconnected");}send(e){this.state==="connected"&&this.ws?.readyState===WebSocket.OPEN?(this.ws.send(JSON.stringify(e)),this.log("Sent message:",e.type,Qe(e))):(this.messageQueue.enqueue(e),this.log("Queued message (offline):",e.type,Qe(e)));}getState(){return this.state}getSessionId(){return this.sessionId}isConnected(){return this.state==="connected"}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>{this.listeners.get(e)?.delete(t);}}emit(e,t){this.listeners.get(e)?.forEach(n=>{try{n(t);}catch(r){this.logger.error(`Error in ${e} listener`,r);}});}createWebSocket(){try{let e=new URL(this.config.serverUrl);this.sessionId&&e.searchParams.set("sessionId",this.sessionId);let t=e.toString();this.ws=new WebSocket(t),this.ws.onopen=this.handleOpen.bind(this),this.ws.onmessage=this.handleMessage.bind(this),this.ws.onclose=this.handleClose.bind(this),this.ws.onerror=this.handleError.bind(this);}catch(e){this.logger.error("Failed to create WebSocket",e),this.handleConnectionFailure();}}handleOpen(){this.log("WebSocket connected, sending auth message..."),this.ws?.send(JSON.stringify({type:"auth",apiKey:this.config.apiKey,sessionId:this.sessionId}));}handleMessage(e){try{let t=JSON.parse(e.data);switch(this.log("Received message:",t.type),t.type){case "connected":this.handleConnected();break;case "auth_success":this.handleAuthSuccess(t);break;case "auth_error":this.handleAuthError(t);break;case "pong":this.handlePong(t);break;case "token_refreshed":this.handleTokenRefreshed(t);break;default:this.emit("message",t);}}catch(t){this.logger.warn("Failed to parse message",t);}}handleClose(e){this.log("WebSocket closed:",e.code,e.reason),this.stopHeartbeat(),this.state!=="disconnected"&&(this.emit("disconnected",{reason:e.reason,code:e.code}),this.config.autoReconnect?this.scheduleReconnect():this.setState("disconnected"));}handleError(e){this.logger.error("WebSocket error",e),this.emit("error",{error:new Error("WebSocket error")});}handleConnected(){this.log("Server connection acknowledged");}handleAuthSuccess(e){this.sessionId=e.sessionId,this.refreshToken=e.refreshToken,this.tokenExpiresAt=e.expiresAt,this.reconnectAttempts=0,this.setState("connected"),this.startHeartbeat(),this.scheduleTokenRefresh(),this.flushMessageQueue(),this.emit("authenticated",{sessionId:e.sessionId,expiresAt:e.expiresAt}),this.emit("connected",{sessionId:e.sessionId}),this.log("Authenticated successfully, session:",e.sessionId);}handleAuthError(e){this.logger.warn("Authentication failed",e.error),this.emit("error",{error:new Error(e.error),code:e.code}),this.disconnect();}scheduleTokenRefresh(){this.tokenRefreshTimeout&&clearTimeout(this.tokenRefreshTimeout);let e=Math.max(0,this.tokenExpiresAt-Date.now()-300*1e3);this.tokenRefreshTimeout=setTimeout(()=>{this.refreshAccessToken();},e),this.log("Token refresh scheduled in",Math.round(e/1e3),"seconds");}refreshAccessToken(){!this.refreshToken||this.state!=="connected"||(this.log("Refreshing token..."),this.ws?.send(JSON.stringify({type:"token_refresh",refreshToken:this.refreshToken})));}handleTokenRefreshed(e){this.refreshToken=e.refreshToken,this.tokenExpiresAt=e.expiresAt,this.scheduleTokenRefresh(),this.emit("token_refreshed",{expiresAt:e.expiresAt}),this.log("Token refreshed successfully");}startHeartbeat(){this.stopHeartbeat(),this.lastPongTime=Date.now(),this.heartbeatInterval=setInterval(()=>{if(this.state==="connected"){if(Date.now()-this.lastPongTime>this.config.heartbeatInterval*2){this.logger.warn("Heartbeat timeout, reconnecting..."),this.ws?.close();return}this.ws?.send(JSON.stringify({type:"ping",timestamp:Date.now()})),this.log("Sent ping");}},this.config.heartbeatInterval);}stopHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null);}handlePong(e){this.lastPongTime=Date.now();let t=Date.now()-e.timestamp;this.log("Received pong, latency:",t,"ms");}scheduleReconnect(){if(this.reconnectAttempts>=this.config.maxReconnectAttempts){this.handleConnectionFailure();return}this.setState("reconnecting"),this.reconnectAttempts++;let e=Math.min(this.config.reconnectDelay*Math.pow(2,this.reconnectAttempts-1),3e4);this.log(`Reconnecting in ${e}ms (attempt ${this.reconnectAttempts}/${this.config.maxReconnectAttempts})`),this.emit("reconnecting",{attempt:this.reconnectAttempts,maxAttempts:this.config.maxReconnectAttempts}),this.reconnectTimeout=setTimeout(()=>{this.createWebSocket();},e);}handleConnectionFailure(){this.setState("failed"),this.emit("reconnect_failed",{reason:"Max reconnection attempts reached"}),this.logger.error("Connection failed - max reconnection attempts reached");}flushMessageQueue(){let e=this.messageQueue.dequeueAll();e.length>0&&(this.log(`Flushing ${e.length} queued messages`),e.forEach(t=>this.send(t)));}setState(e){this.state!==e&&(this.log("State:",this.state,"->",e),this.state=e);}cleanup(){if(this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null),this.tokenRefreshTimeout&&(clearTimeout(this.tokenRefreshTimeout),this.tokenRefreshTimeout=null),this.stopHeartbeat(),this.listeners.clear(),this.ws){let e=this.ws;if(e.onopen=null,e.onmessage=null,e.onclose=null,e.onerror=null,this.ws=null,e.readyState===WebSocket.CONNECTING||e.readyState===WebSocket.OPEN)try{e.close(1e3,"Client disconnect");}catch{}}}log(...e){this.logger.debug(...e);}};function Qe(i){switch(i.type){case "message":return {messageId:i.messageId,mode:i.mode,length:i.content.length,route:i.context?.route};case "context":return {route:i.context?.route,actions:i.context?.actions?.length??0,headings:i.context?.content?.headings?.length??0};case "action_result":return {actionId:i.actionId,success:i.success,commandId:i.commandId};case "server_action_request":return {actionId:i.actionId,requestId:i.requestId};case "auth":return {hasSessionId:!!i.sessionId};case "token_refresh":return {};case "ping":return {timestamp:i.timestamp};default:return {}}}function Gt(i){return new ge(i)}function Ze(i="/"){let e=i,t=new Set;return {navigate(n){e=n,t.forEach(r=>r(n));},getCurrentPath(){return e},onRouteChange(n){return t.add(n),()=>t.delete(n)},async waitForRoute(n,r=1e4){return new Promise(o=>{if(e===n){o(true);return}let s=this.onRouteChange(a=>{a===n&&(s(),o(true));});setTimeout(()=>{s(),o(e===n);},r);})}}}var fe=class{adapter;config;scanCallback=null;logger=createLogger("SDK.Navigation");constructor(e,t={}){this.adapter=e,this.config={domStabilityDelay:t.domStabilityDelay??300,domStabilityTimeout:t.domStabilityTimeout??5e3,debug:t.debug??false,onDOMStable:t.onDOMStable},this.logger=createLogger("SDK.Navigation",{enabled:this.config.debug,level:"debug"});}setScanner(e){this.scanCallback=e;}getCurrentRoute(){return this.adapter.getCurrentPath()}async navigateTo(e,t){if(this.adapter.getCurrentPath()===e)return this.log("Already on route:",e),true;this.log("Navigating to:",e),this.adapter.navigate(e);let r=await this.adapter.waitForRoute(e,t);return r||this.log("Navigation timeout for route:",e),r}async executeNavigation(e){if(!await this.navigateTo(e))return this.log("Navigation failed to:",e),null;if(await this.waitForDOMStable(),this.scanCallback){let n=await this.scanCallback();return this.log("Rescanned context on route:",e),n}return null}async waitForDOMStable(){this.logger.debug("Waiting for DOM stability",{delayMs:this.config.domStabilityDelay,timeoutMs:this.config.domStabilityTimeout});let e=()=>{this.config.onDOMStable?.();};return new Promise(t=>{let n=false,r=()=>{n||(n=true,e(),t());};if(typeof document>"u"||typeof MutationObserver>"u"){r();return}let o,s,a=Date.now(),c=()=>{u.disconnect(),clearTimeout(o),clearTimeout(s);},u=new MutationObserver(()=>{if(clearTimeout(o),Date.now()-a>=this.config.domStabilityTimeout){c(),this.log("DOM stability timeout reached"),r();return}o=setTimeout(()=>{c(),this.log("DOM is stable"),r();},this.config.domStabilityDelay);});u.observe(document.body,{childList:true,subtree:true,attributes:false}),o=setTimeout(()=>{c(),this.log("DOM is stable (no initial mutations)"),r();},this.config.domStabilityDelay),s=setTimeout(()=>{c(),this.log("DOM stability max timeout reached"),r();},this.config.domStabilityTimeout);})}onRouteChange(e){return this.adapter.onRouteChange(e)}log(...e){this.logger.debug(...e);}};function Qt(i,e){return new fe(i,e)}var ht=["button:not([disabled])","a[href]:not([disabled])",'input:not([type="hidden"]):not([disabled])',"select:not([disabled])","textarea:not([disabled])",'[contenteditable="true"]','[contenteditable="plaintext-only"]','[role="textbox"]','[role="searchbox"]','[role="combobox"]','[role="checkbox"]','[role="switch"]','[role="radio"]','[role="button"]:not([disabled])','[role="link"]','[role="menuitem"]','[role="tab"]',"[onclick]","[data-chatbot-action]"],gt=["[data-chatbot-ignore]",'[aria-hidden="true"]',"[hidden]",".chatbot-widget",".navsi-chatbot-container",'[type="password"]','[autocomplete*="cc-"]'];function ft(i){let e=i.getAttribute("data-chatbot-action");if(e)return `[data-chatbot-action="${e}"]`;if(i.id)return `#${CSS.escape(i.id)}`;let t=i.getAttribute("data-testid");if(t)return `[data-testid="${CSS.escape(t)}"]`;let n=i.getAttribute("aria-label");if(n){let o=`[aria-label="${CSS.escape(n)}"]`;if(document.querySelectorAll(o).length===1)return o}let r=i.getAttribute?.("name");if(r&&/^(input|select|textarea|button)$/i.test(i.tagName)){let o=`${i.tagName.toLowerCase()}[name="${CSS.escape(r)}"]`;if(document.querySelectorAll(o).length===1)return o}if(i.className&&typeof i.className=="string"){let o=i.className.split(/\s+/).filter(Boolean).slice(0,3);if(o.length>0){let s=`${i.tagName.toLowerCase()}.${o.map(c=>CSS.escape(c)).join(".")}`;if(document.querySelectorAll(s).length===1)return s}}return mt(i)}function mt(i){let e=[],t=i;for(;t&&t!==document.body;){let n=t.tagName.toLowerCase();if(t.id){n=`#${CSS.escape(t.id)}`,e.unshift(n);break}let r=t.parentElement;if(r){let o=t.tagName,s=r.children,a=[];for(let c=0;c<s.length;c++)s[c].tagName===o&&a.push(s[c]);if(a.length>1){let c=a.indexOf(t)+1;n+=`:nth-of-type(${c})`;}}e.unshift(n),t=r;}return e.join(" > ")}function pt(i){let e=window.getComputedStyle(i);if(e.display==="none"||e.visibility==="hidden"||e.opacity==="0")return false;let t=i.getBoundingClientRect();return !(t.width===0&&t.height===0||i.closest('[aria-hidden="true"]'))}function bt(i){for(let e of gt)if(i.matches(e)||i.closest(e))return true;return false}function vt(i){let e=i.tagName.toLowerCase(),t=i.getAttribute("role")?.toLowerCase();if(e==="input"){let n=i.type;return n==="checkbox"||n==="radio"?"click":"type"}return e==="textarea"?"type":e==="select"?"select":t==="textbox"||t==="searchbox"?"type":"click"}function yt(i){let e=i.getAttribute("data-chatbot-action");if(e)return e.replace(/-/g," ");let t=i.getAttribute("aria-label");if(t)return t;let n=i.getAttribute("aria-labelledby");if(n){let c=n.split(/\s+/).map(u=>document.getElementById(u)?.textContent?.trim()).filter(Boolean).join(" ");if(c)return c}let r=i.getAttribute("title");if(r)return r;let o=i.textContent?.trim();if(o&&o.length<50)return o;let s=i.getAttribute("placeholder");if(s)return s;let a=i.getAttribute("name");if(a)return a.replace(/[-_]/g," ");if(i.id){let c=document.querySelector(`label[for="${i.id}"]`);if(c?.textContent)return c.textContent.trim()}return i.tagName.toLowerCase()}var Et=["tr",'[role="row"]',"article",'[role="listitem"]',"section",'[role="group"]',"main",'[role="region"]'],nt=120;function St(i){let e=i,t=0,n=8;for(;e&&e!==document.body&&t<n;){for(let r of Et)try{if(e.matches(r)){let o=e.textContent?.trim().replace(/\s+/g," ");if(o&&o.length>0)return o.length>nt?o.slice(0,nt)+"\u2026":o;break}}catch{}e=e.parentElement,t++;}}function wt(i){let e=i.parentElement,t=0,n=5;for(;e&&t<n;){let r=e.querySelector("h1, h2, h3, h4, h5, h6");if(r?.textContent)return r.textContent.trim();let o=e.previousElementSibling;for(;o;){if(/^H[1-6]$/.test(o.tagName))return o.textContent?.trim();o=o.previousElementSibling;}e=e.parentElement,t++;}}var Me=class{config;mutationObserver=null;scanTimeout=null;onChangeCallback=null;logger=createLogger("SDK.Scanner");constructor(e={}){this.config={root:e.root??(typeof document<"u"?document.body:null),debug:e.debug??false,maxActions:e.maxActions??100,debounceMs:e.debounceMs??300},this.logger=createLogger("SDK.Scanner",{enabled:this.config.debug,level:"debug"});}scan(){if(typeof document>"u")return [];let e=this.config.root??document.body,t=[],n=typeof window<"u"?window.location.pathname:"/",r=ht.join(", "),o=this.collectInteractiveElements(e,r);this.log(`Found ${o.length} potential interactive elements`);for(let s of o){if(t.length>=this.config.maxActions)break;if(bt(s)||!pt(s))continue;let a=this.createElement(s,n);a&&t.push(a);}return this.log(`Discovered ${t.length} actions`),t}createElement(e,t){try{let n=ft(e),r=yt(e),o=vt(e),s=wt(e),u={id:`action_${btoa(unescape(encodeURIComponent(n))).replace(/[^a-zA-Z0-9]/g,"").slice(0,16)}`,type:o,selector:n,label:r,route:t,isAutoDiscovered:!0,priority:e.hasAttribute("data-chatbot-action")?10:1},f=St(e);return (s||f)&&(u.metadata={...s?{context:s}:{},...f?{containerText:f}:{}}),u}catch(n){return this.log("Error creating action:",n),null}}collectInteractiveElements(e,t){let n=new Set,r=[e];for(;r.length>0;){let o=r.shift();if(!o)break;let a=(o).querySelectorAll(t);for(let f of a)n.add(f);let u=(o).querySelectorAll("*");for(let f of u){let A=f.shadowRoot;A&&r.push(A);}}return Array.from(n)}observe(e){typeof MutationObserver>"u"||(this.disconnect(),this.onChangeCallback=e,this.mutationObserver=new MutationObserver(()=>{this.debouncedScan();}),this.mutationObserver.observe(this.config.root??document.body,{childList:true,subtree:true,attributes:true,attributeFilter:["disabled","hidden","aria-hidden"]}));}disconnect(){this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=null),this.scanTimeout&&(clearTimeout(this.scanTimeout),this.scanTimeout=null);}debouncedScan(){this.scanTimeout&&clearTimeout(this.scanTimeout),this.scanTimeout=setTimeout(()=>{let e=this.scan();this.onChangeCallback?.(e);},this.config.debounceMs);}log(...e){this.logger.debug(...e);}};var Ne=class{actionsByRoute=new Map;serverActions=new Map;manualActions=new Map;debug;logger=createLogger("SDK.Registry");constructor(e={}){this.debug=e.debug??false,this.logger=createLogger("SDK.Registry",{enabled:this.debug,level:"debug"});}registerDiscoveredActions(e,t){this.actionsByRoute.has(e)||this.actionsByRoute.set(e,new Map);let n=this.actionsByRoute.get(e);for(let[r,o]of n)o.isAutoDiscovered&&n.delete(r);for(let r of t){let o=this.manualActions.get(r.id);o?n.set(r.id,{...r,...o}):n.set(r.id,r);}this.log(`Registered ${t.length} discovered actions for route: ${e}`);}registerManualAction(e){this.manualActions.set(e.id,e);let t=this.actionsByRoute.get(e.route);if(t?.has(e.id)){let n=t.get(e.id);t.set(e.id,{...n,...e,isAutoDiscovered:false});}this.log(`Registered manual action: ${e.id}`);}getActionsForRoute(e){let t=this.actionsByRoute.get(e);return t?Array.from(t.values()).sort((n,r)=>(r.priority??0)-(n.priority??0)):[]}findActionById(e){for(let t of this.actionsByRoute.values()){let n=t.get(e);if(n)return n}return null}findActionBySelector(e,t){let n=this.actionsByRoute.get(e);if(!n)return null;for(let r of n.values())if(r.selector===t)return r;return null}findActionByLabel(e,t,n){let r=this.actionsByRoute.get(e);if(!r)return null;let o=t.toLowerCase().trim(),s=n?.toLowerCase().trim(),a=c=>{if(!s)return true;let u=c.metadata?.containerText?.toLowerCase(),f=c.metadata?.context?.toLowerCase();return (u?.includes(s)??false)||(f?.includes(s)??false)};if(s){for(let c of r.values())if(c.label.toLowerCase()===o&&a(c))return c;for(let c of r.values())if(c.label.toLowerCase().includes(o)&&a(c))return c}for(let c of r.values())if(c.label.toLowerCase()===o)return c;for(let c of r.values())if(c.label.toLowerCase().includes(o))return c;return null}clearRoute(e){this.actionsByRoute.delete(e);}clearAll(){this.actionsByRoute.clear();}registerServerAction(e){this.serverActions.set(e.id,e),this.log(`Registered server action: ${e.id}`);}getServerActions(){return Array.from(this.serverActions.values())}findServerActionById(e){return this.serverActions.get(e)??null}findServerActionByName(e){let t=e.toLowerCase().trim();for(let n of this.serverActions.values())if(n.name.toLowerCase()===t)return n;for(let n of this.serverActions.values())if(n.name.toLowerCase().includes(t))return n;return null}removeServerAction(e){this.serverActions.delete(e);}getStats(){let e=0;for(let t of this.actionsByRoute.values())e+=t.size;return {routes:this.actionsByRoute.size,actions:e,serverActions:this.serverActions.size}}log(...e){this.logger.debug(...e);}};function Ct(i){return i.replace(/\s+/g," ").trim()}function xt(){if(typeof document>"u")return [];let i=["chatbot","ai assistant","ask mode","navigate mode","navsi","intelligent agent"],e=[],t=document.querySelectorAll("h1, h2, h3, h4, h5, h6");for(let n of t){if(n.closest(".chatbot-widget")||n.closest(".navsi-chatbot-container"))continue;let r=n.textContent?.trim();if(r&&r.length<200){let o=r.toLowerCase();i.some(a=>o.includes(a))||e.push(r);}}return e.slice(0,20)}function Rt(i){if(typeof document>"u")return "";let e=document.querySelector("main")??document.querySelector('[role="main"]')??document.querySelector("article")??document.querySelector(".content")??document.body,t=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,{acceptNode:o=>{let s=o.parentElement;if(!s)return NodeFilter.FILTER_REJECT;let a=s.tagName.toLowerCase();return ["script","style","noscript"].includes(a)||s.closest(".chatbot-widget")||s.closest(".navsi-chatbot-container")?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}}),n="",r;for(;(r=t.nextNode())&&n.length<i;){let o=r.textContent?.trim();o&&o.length>0&&(n+=o+" ");}return Ct(n).slice(0,i)}function At(){if(typeof document>"u")return [];let i=[],e=document.querySelectorAll("form");for(let t of e){if(t.closest(".chatbot-widget")||t.closest(".navsi-chatbot-container"))continue;let n=[],r=t.querySelectorAll("input, select, textarea");for(let o of r){let s=o;if(s.type==="hidden")continue;let a;s.id&&(a=document.querySelector(`label[for="${s.id}"]`)?.textContent?.trim()),!a&&s.getAttribute("aria-label")&&(a=s.getAttribute("aria-label")??void 0),n.push({name:s.name||s.id||"",type:s.type||s.tagName.toLowerCase(),label:a,placeholder:"placeholder"in s?s.placeholder:void 0,required:s.required});}n.length>0&&i.push({id:t.id||`form_${i.length}`,name:t.name||void 0,action:t.action?(()=>{try{return new URL(t.action).pathname}catch{return}})():void 0,method:t.method||void 0,fields:n});}return i.slice(0,10)}function Tt(){return typeof document>"u"?void 0:document.querySelector('meta[name="description"]')?.getAttribute("content")??void 0}var Ie=class{config;logger=createLogger("SDK.Context");constructor(e={}){this.config={maxContentLength:e.maxContentLength??2e3,maxActions:e.maxActions??50,debug:e.debug??false},this.logger=createLogger("SDK.Context",{enabled:this.config.debug,level:"debug"});}build(e,t,n){let r=n??(typeof window<"u"?window.location.pathname:"/"),o=typeof document<"u"?document.title:"",s={headings:xt(),mainContent:Rt(this.config.maxContentLength),forms:At(),metaDescription:Tt()},a=e.slice(0,this.config.maxActions),c={route:r,title:o,actions:a,serverActions:t,content:s,timestamp:Date.now()};return this.log("Built page context:",{route:c.route,title:c.title,actions:c.actions.length,serverActions:c.serverActions.length,headings:c.content.headings.length,forms:c.content.forms.length}),c}buildMinimal(e,t,n){return {route:n??(typeof window<"u"?window.location.pathname:"/"),title:typeof document<"u"?document.title:"",actions:e.slice(0,this.config.maxActions),serverActions:t,content:{headings:[],mainContent:"",forms:[]},timestamp:Date.now()}}log(...e){this.logger.debug(...e);}};function be(i,e){let t=e?.preferVisible??false,n=[document],r=null;for(;n.length>0;){let o=n.shift(),s=o.querySelector(i);if(s){if(!t||ve(s))return s;r||(r=s);}let a=o instanceof Document?o.body??o.documentElement:o;if(!a)continue;let c=a.querySelectorAll("*");for(let u of c){let f=u.shadowRoot;f&&n.push(f);}}return t?r:null}async function me(i,e,t=true){let r=o=>o?!t||ve(o):false;return new Promise(o=>{let s=be(i,{preferVisible:t});if(r(s)){o(s);return}let a=false,c=null,u=null,f=()=>{a=true,c&&clearInterval(c),u&&clearTimeout(u),A.disconnect();},A=new MutationObserver(()=>{if(a)return;let w=be(i,{preferVisible:t});r(w)&&(f(),o(w));});A.observe(document.body,{childList:true,subtree:true}),c=setInterval(()=>{if(a)return;let w=be(i,{preferVisible:t});r(w)&&(f(),o(w));},100),u=setTimeout(()=>{if(a)return;f();let w=be(i,{preferVisible:t});o(r(w)?w:null);},e);})}function ve(i){let e=window.getComputedStyle(i);if(e.display==="none"||e.visibility==="hidden"||e.opacity==="0")return false;let t=i.getBoundingClientRect();if(t.width===0&&t.height===0)return false;let n=window.innerWidth||document.documentElement.clientWidth,r=window.innerHeight||document.documentElement.clientHeight,o=t.right>0&&t.left<n,s=t.bottom>0&&t.top<r;return o&&s}function kt(i){let e=i.getBoundingClientRect();return {x:e.left+e.width/2,y:e.top+e.height/2}}function Ve(i,e){let t=i instanceof HTMLInputElement?HTMLInputElement.prototype:HTMLTextAreaElement.prototype,n=Object.getOwnPropertyDescriptor(t,"value")?.set;n?n.call(i,e):i.value=e;}function De(i){i.scrollIntoView({behavior:"smooth",block:"center",inline:"center"});}function pe(i,e=500){let t=i,n=t.style.outline,r=t.style.transition;t.style.transition="outline 0.2s ease",t.style.outline="3px solid #6366f1",setTimeout(()=>{t.style.outline=n,t.style.transition=r;},e);}async function Mt(i,e,t){i.focus(),Ve(i,""),i.dispatchEvent(new Event("input",{bubbles:true}));for(let n of e){try{typeof InputEvent<"u"&&i.dispatchEvent(new InputEvent("beforeinput",{bubbles:!0,cancelable:!0,data:n,inputType:"insertText"}));}catch{}let r=(i.value??"")+n;Ve(i,r),i.dispatchEvent(new Event("input",{bubbles:true})),i.dispatchEvent(new KeyboardEvent("keydown",{key:n,bubbles:true})),i.dispatchEvent(new KeyboardEvent("keypress",{key:n,bubbles:true})),i.dispatchEvent(new KeyboardEvent("keyup",{key:n,bubbles:true})),t>0&&await new Promise(o=>setTimeout(o,t));}i.dispatchEvent(new Event("change",{bubbles:true}));}async function Nt(i,e,t){i.focus(),i.textContent="",i.dispatchEvent(new Event("input",{bubbles:true}));for(let n of e){try{typeof InputEvent<"u"&&i.dispatchEvent(new InputEvent("beforeinput",{bubbles:!0,cancelable:!0,data:n,inputType:"insertText"}));}catch{}i.textContent=(i.textContent??"")+n,i.dispatchEvent(new Event("input",{bubbles:true})),i.dispatchEvent(new KeyboardEvent("keydown",{key:n,bubbles:true})),i.dispatchEvent(new KeyboardEvent("keypress",{key:n,bubbles:true})),i.dispatchEvent(new KeyboardEvent("keyup",{key:n,bubbles:true})),t>0&&await new Promise(r=>setTimeout(r,t));}i.dispatchEvent(new Event("change",{bubbles:true}));}function W(i){let e=i.getBoundingClientRect(),t=i.tagName.toLowerCase(),n={};if(i instanceof HTMLElement)for(let r of Array.from(i.attributes))(r.name.startsWith("data-")||r.name==="aria-label"||r.name==="name"||r.name==="id")&&(n[r.name]=r.value);return {tagName:t,text:(i.textContent??"").trim().slice(0,80),rect:{x:e.x,y:e.y,width:e.width,height:e.height},attributes:n}}var Oe=class i{config;logger=createLogger("SDK.Executor");constructor(e={}){this.config={elementTimeout:e.elementTimeout??6e3,typeDelay:e.typeDelay??30,scrollIntoView:e.scrollIntoView??true,highlightOnInteract:e.highlightOnInteract??true,debug:e.debug??false},this.logger=createLogger("SDK.Executor",{enabled:this.config.debug,level:"debug"});}static RETRY_DELAY_MS=600;static MAX_RETRIES=2;async click(e){let t=Date.now(),n=async()=>{let o=await me(e,this.config.elementTimeout,true);if(!o)return this.createResult(e,"click",t,false,"Element not found","ELEMENT_NOT_FOUND");if(this.config.scrollIntoView&&(De(o),await new Promise(f=>setTimeout(f,200))),this.config.highlightOnInteract&&pe(o),!ve(o))return this.createResult(e,"click",t,false,"Element is not visible","NOT_VISIBLE",W(o));let s=o;if(s.disabled===true||s.getAttribute("aria-disabled")==="true")return this.createResult(e,"click",t,false,"Element is disabled","DISABLED",W(o));s.focus();let{x:c,y:u}=kt(o);try{typeof PointerEvent<"u"&&(o.dispatchEvent(new PointerEvent("pointerover",{bubbles:!0,cancelable:!0,clientX:c,clientY:u})),o.dispatchEvent(new PointerEvent("pointerenter",{bubbles:!0,cancelable:!0,clientX:c,clientY:u})),o.dispatchEvent(new PointerEvent("pointermove",{bubbles:!0,cancelable:!0,clientX:c,clientY:u})));}catch{}o.dispatchEvent(new MouseEvent("mouseover",{bubbles:true,cancelable:true,clientX:c,clientY:u})),o.dispatchEvent(new MouseEvent("mouseenter",{bubbles:true,cancelable:true,clientX:c,clientY:u})),o.dispatchEvent(new MouseEvent("mousemove",{bubbles:true,cancelable:true,clientX:c,clientY:u}));try{typeof PointerEvent<"u"&&(o.dispatchEvent(new PointerEvent("pointerdown",{bubbles:!0,cancelable:!0,button:0,clientX:c,clientY:u})),o.dispatchEvent(new PointerEvent("pointerup",{bubbles:!0,cancelable:!0,button:0,clientX:c,clientY:u})));}catch{}return o.dispatchEvent(new MouseEvent("mousedown",{bubbles:true,cancelable:true,clientX:c,clientY:u})),o.dispatchEvent(new MouseEvent("mouseup",{bubbles:true,cancelable:true,clientX:c,clientY:u})),o.dispatchEvent(new MouseEvent("click",{bubbles:true,cancelable:true,clientX:c,clientY:u})),s.click(),this.log("Clicked:",e),this.createResult(e,"click",t,true,void 0,void 0,W(o))};return (async()=>{let o=null;for(let s=0;s<=i.MAX_RETRIES;s++){s>0&&(this.log(`Click retry ${s}/${i.MAX_RETRIES} for:`,e),await new Promise(a=>setTimeout(a,i.RETRY_DELAY_MS*s)));try{if(o=await n(),o.success)return o}catch(a){o=this.createResult(e,"click",t,false,String(a),"RUNTIME_ERROR");}}return o})()}async type(e,t,n=true){let r=Date.now(),o=async()=>{let a=await me(e,this.config.elementTimeout,true);if(!a)return this.createResult(e,"type",r,false,"Element not found","ELEMENT_NOT_FOUND");if(!this.isTypeable(a))return this.createResult(e,"type",r,false,"Element is not typeable","TYPE_MISMATCH",W(a));this.config.scrollIntoView&&(De(a),await new Promise(u=>setTimeout(u,200))),this.config.highlightOnInteract&&pe(a);let c=W(a);if(!ve(a))return this.createResult(e,"type",r,false,"Element is not visible","NOT_VISIBLE",c);if(a instanceof HTMLInputElement||a instanceof HTMLTextAreaElement){let u=a;if(u.disabled||u.getAttribute("aria-disabled")==="true")return this.createResult(e,"type",r,false,"Element is disabled","DISABLED",c);n?await Mt(u,t,this.config.typeDelay):(u.focus(),Ve(u,(u.value??"")+t),u.dispatchEvent(new Event("input",{bubbles:true})),u.dispatchEvent(new Event("change",{bubbles:true})));}else if(a instanceof HTMLElement&&a.isContentEditable){if(a.getAttribute("aria-disabled")==="true")return this.createResult(e,"type",r,false,"Element is disabled","DISABLED",c);await Nt(a,t,this.config.typeDelay);}else return this.createResult(e,"type",r,false,"Element is not a supported type target","TYPE_MISMATCH",c);return this.log("Typed into:",e,"text:",t.slice(0,20)+(t.length>20?"...":"")),this.createResult(e,"type",r,true,void 0,void 0,{...c,textLength:t.length})};return (async()=>{let a=null;for(let c=0;c<=i.MAX_RETRIES;c++){c>0&&(this.log(`Type retry ${c}/${i.MAX_RETRIES} for:`,e),await new Promise(u=>setTimeout(u,i.RETRY_DELAY_MS*c)));try{if(a=await o(),a.success)return a}catch(u){a=this.createResult(e,"type",r,false,String(u),"RUNTIME_ERROR");}}return a})()}async select(e,t){let n=Date.now(),r=async()=>{let s=await me(e,this.config.elementTimeout,true);if(!s)return this.createResult(e,"select",n,false,"Element not found","ELEMENT_NOT_FOUND");if(s.tagName.toLowerCase()!=="select")return this.createResult(e,"select",n,false,"Element is not a select","TYPE_MISMATCH",W(s));if(this.config.scrollIntoView&&(De(s),await new Promise(A=>setTimeout(A,200))),this.config.highlightOnInteract&&pe(s),!ve(s))return this.createResult(e,"select",n,false,"Element is not visible","NOT_VISIBLE",W(s));let a=s;if(a.disabled||a.getAttribute("aria-disabled")==="true")return this.createResult(e,"select",n,false,"Element is disabled","DISABLED",W(s));let c=false,u="";for(let A of a.options)if(A.value===t||A.textContent?.toLowerCase().includes(t.toLowerCase())){u=A.value,c=true;break}if(!c)return this.createResult(e,"select",n,false,`Option not found: ${t}`,"OPTION_NOT_FOUND",{...W(s),attemptedValue:t});let f=Object.getOwnPropertyDescriptor(HTMLSelectElement.prototype,"value")?.set;return f?f.call(a,u):a.value=u,a.dispatchEvent(new Event("input",{bubbles:true})),a.dispatchEvent(new Event("change",{bubbles:true})),this.log("Selected:",e,"value:",t),this.createResult(e,"select",n,true,void 0,void 0,{...W(s),selectedValue:t})};return (async()=>{let s=null;for(let a=0;a<=i.MAX_RETRIES;a++){a>0&&(this.log(`Select retry ${a}/${i.MAX_RETRIES} for:`,e),await new Promise(c=>setTimeout(c,i.RETRY_DELAY_MS*a)));try{if(s=await r(),s.success)return s}catch(c){s=this.createResult(e,"select",n,false,String(c),"RUNTIME_ERROR");}}return s})()}async scroll(e){let t=Date.now(),n=typeof e=="string"?e:`${e.x},${e.y}`;try{if(typeof e=="string"){let r=await me(e,this.config.elementTimeout,!1);if(!r)return this.createResult(n,"scroll",t,!1,"Element not found","ELEMENT_NOT_FOUND");this.config.highlightOnInteract&&pe(r),De(r);}else window.scrollTo({left:e.x,top:e.y,behavior:"smooth"});return this.log("Scrolled to:",e),this.createResult(n,"scroll",t,!0,void 0,void 0,typeof e=="string"?(()=>{let r=be(e);return r?W(r):{selector:e}})():{position:e})}catch(r){return this.createResult(n,"scroll",t,false,String(r),"RUNTIME_ERROR")}}async submit(e){let t=Date.now();try{let n=await me(e,this.config.elementTimeout,!0);if(!n)return this.createResult(e,"submit",t,!1,"Element not found","ELEMENT_NOT_FOUND");let r=n.tagName.toLowerCase()==="form"?n:n.closest("form");if(!r){let s=n.querySelector('button[type="submit"], input[type="submit"]');return s?this.click(this.generateSelector(s)):this.createResult(e,"submit",t,!1,"No form found","NO_FORM",W(n))}this.config.highlightOnInteract&&pe(r);let o=r.querySelector('button[type="submit"], input[type="submit"]');if(typeof r.requestSubmit=="function")r.requestSubmit(o??void 0);else {let s=new Event("submit",{bubbles:!0,cancelable:!0});r.dispatchEvent(s)&&r.submit();}return this.log("Submitted form:",e),this.createResult(e,"submit",t,!0,void 0,void 0,W(r))}catch(n){return this.createResult(e,"submit",t,false,String(n),"RUNTIME_ERROR")}}isTypeable(e){let t=e.tagName.toLowerCase();if(t==="input"){let n=e.type;return ["text","email","password","search","tel","url","number"].includes(n)}return !!(t==="textarea"||e.hasAttribute("contenteditable"))}generateSelector(e){if(e.id)return `#${e.id}`;let t=e.getAttribute("data-testid");return t?`[data-testid="${t}"]`:e.tagName.toLowerCase()}createResult(e,t,n,r,o,s,a){return r||this.logger.warn("Action failed",{action:t,selector:e,error:o,errorCode:s,metadata:a}),{success:r,selector:e,action:t,duration:Date.now()-n,errorCode:s,error:o,metadata:a}}log(...e){this.logger.debug(...e);}};var Le=class{config;executor;navController;registry;logger=createLogger("SDK.Processor");isExecuting=false;shouldAbort=false;listeners=new Map;serverActionHandler=null;constructor(e,t,n,r={}){this.executor=e,this.navController=t,this.registry=n,this.config={commandDelay:r.commandDelay??650,commandTimeout:r.commandTimeout??3e4,debug:r.debug??false},this.logger=createLogger("SDK.Processor",{enabled:this.config.debug,level:"debug"});}setServerActionHandler(e){this.serverActionHandler=e;}async execute(e){if(this.isExecuting)throw new Error("Already executing commands");this.isExecuting=true,this.shouldAbort=false;let t=[],n=null;try{for(let r=0;r<e.length;r++){if(this.shouldAbort){this.log("Execution aborted");break}let o=e[r],s=["click","type","select","scroll"].includes(o.type),a=n&&["navigate","wait_for_route"].includes(n);s&&a&&(this.log("Auto-waiting for DOM stability before:",o.type),await this.navController.waitForDOMStable(),await new Promise(u=>setTimeout(u,200))),this.emit("stateChange",{isExecuting:!0,currentCommand:o,currentIndex:r,totalCommands:e.length,description:this.describeCommand(o)}),this.emit("commandStart",o,r);let c=await this.executeCommand(o);if(t.push(c),this.emit("commandComplete",c),n=o.type,!c.success){this.logger.warn("Command failed, stopping execution",{type:o.type,error:c.error,result:c.result});break}r<e.length-1&&await new Promise(u=>setTimeout(u,this.config.commandDelay));}return this.emit("complete",t),t}catch(r){let o=r instanceof Error?r:new Error(String(r));throw this.logger.error("Execution error",o),this.emit("error",o),o}finally{this.isExecuting=false,this.emit("stateChange",{isExecuting:false,currentCommand:void 0,currentIndex:0,totalCommands:e.length,description:void 0});}}abort(){this.shouldAbort=true;}getIsExecuting(){return this.isExecuting}async executeCommand(e){let t=Date.now();try{switch(e.type){case "navigate":return await this.executeNavigate(e,t);case "wait_for_route":return await this.executeWaitForRoute(e,t);case "wait_for_dom_stable":return await this.executeWaitForDomStable(e,t);case "scan_context":return await this.executeScanContext(e,t);case "click":return await this.executeClick(e,t);case "type":return await this.executeType(e,t);case "select":return await this.executeSelect(e,t);case "scroll":return await this.executeScroll(e,t);case "server_action":return await this.executeServerAction(e,t);case "report_result":return await this.executeReportResult(e,t);default:return this.createResult(e,t,!1,"Unknown command type")}}catch(n){return this.logger.error("Command execution error",{type:e.type,error:String(n)}),this.createResult(e,t,false,String(n))}}async executeNavigate(e,t){return this.log("Navigating to:",e.target),await this.navController.executeNavigation(e.target)?this.createResult(e,t,true):this.createResult(e,t,false,"Navigation failed")}async executeWaitForRoute(e,t){this.log("Waiting for route:",e.target);let n=await this.navController.navigateTo(e.target,e.timeout);return this.createResult(e,t,n,n?void 0:"Route timeout")}async executeWaitForDomStable(e,t){return this.log("Waiting for DOM to stabilize"),await this.navController.waitForDOMStable(),this.createResult(e,t,true)}async executeScanContext(e,t){return this.log("Scanning page context"),this.createResult(e,t,true)}async executeClick(e,t){let n=e.selector,r=this.navController.getCurrentRoute();if(n){if(this.log("Clicking with selector:",n),(await this.executor.click(n)).success)return this.createResult(e,t,true);this.log("Selector failed, trying text fallback:",e.text||n);}if(e.text){let s=this.registry.findActionByLabel(r,e.text,e.context);if(s&&s.selector!==n&&(this.log("Found action by label, clicking:",s.selector),(await this.executor.click(s.selector)).success))return this.createResult(e,t,true)}if(e.text){let s=e.text.toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,""),a=`[data-chatbot-action*="${CSS.escape(s)}"]`;if(this.log("Trying data-chatbot-action selector:",a),(await this.executor.click(a)).success)return this.createResult(e,t,true)}if(e.text){let s=`[aria-label="${CSS.escape(e.text)}"]`;if(this.log("Trying aria-label selector:",s),(await this.executor.click(s)).success)return this.createResult(e,t,true)}if(e.text){let s=e.text.toLowerCase().trim(),a=document.querySelectorAll('button, a, [role="button"], [data-chatbot-action]');for(let c of a){let u=c.textContent?.toLowerCase().trim()||"",f=c.getAttribute("aria-label")?.toLowerCase().trim()||"",A=c.getAttribute("data-chatbot-action")?.toLowerCase().replace(/-/g," ")||"";if(u===s||f===s||u.includes(s)||A===s||A.includes(s.replace(/\s+/g,"-"))){let w="";if(c.id?w=`#${CSS.escape(c.id)}`:c.getAttribute("data-chatbot-action")?w=`[data-chatbot-action="${CSS.escape(c.getAttribute("data-chatbot-action")??"")}"]`:c.getAttribute("aria-label")&&(w=`[aria-label="${CSS.escape(c.getAttribute("aria-label")??"")}"]`),w&&(this.log("Found element by text content, clicking:",w),(await this.executor.click(w)).success))return this.createResult(e,t,true)}}}let o=n?`Element not found or click failed: ${n}`:`No selector found for: ${e.text||"unknown"}`;return this.createResult(e,t,false,o)}async executeType(e,t){let n=e.selector;if(!n&&e.text){let o=this.registry.findActionByLabel(this.navController.getCurrentRoute(),e.text);o&&(n=o.selector);}if(!n)return this.createResult(e,t,false,"No selector provided");this.log("Typing into:",n,"value:",e.value);let r=await this.executor.type(n,e.value,e.clear??true);if(!r.success&&e.text&&r.error?.includes("not found")){let o=this.registry.findActionByLabel(this.navController.getCurrentRoute(),e.text);o&&(r=await this.executor.type(o.selector,e.value,e.clear??true));}return this.createResult(e,t,r.success,r.error)}async executeSelect(e,t){let n=e.selector;if(!n&&e.text){let o=this.registry.findActionByLabel(this.navController.getCurrentRoute(),e.text);o&&(n=o.selector);}if(!n)return this.createResult(e,t,false,"No selector provided");this.log("Selecting:",n,"value:",e.value);let r=await this.executor.select(n,e.value);if(!r.success&&e.text&&r.error?.includes("not found")){let o=this.registry.findActionByLabel(this.navController.getCurrentRoute(),e.text);o&&(r=await this.executor.select(o.selector,e.value));}return this.createResult(e,t,r.success,r.error)}async executeScroll(e,t){let n=e.selector??e.position??{x:0,y:0};this.log("Scrolling to:",n);let r=await this.executor.scroll(n);return this.createResult(e,t,r.success,r.error)}async executeServerAction(e,t){if(!this.serverActionHandler)return this.createResult(e,t,false,"No server action handler set");if(!this.registry.findServerActionById(e.actionId))return this.createResult(e,t,false,`Server action not found: ${e.actionId}`);this.log("Executing server action:",e.actionId);try{let r=await this.serverActionHandler(e.actionId,e.params);return this.createResult(e,t,!0,void 0,r)}catch(r){return this.createResult(e,t,false,String(r))}}async executeReportResult(e,t){return this.log("Report result command executed"),this.createResult(e,t,true)}createResult(e,t,n,r,o){return {command:e,success:n,result:o,error:r,duration:Date.now()-t}}describeCommand(e){switch(e.type){case "click":return e.text?`Click "${e.text}"`:`Click element${e.selector?` (${e.selector})`:""}`;case "type":return e.text?`Type into "${e.text}"`:`Type into element${e.selector?` (${e.selector})`:""}`;case "select":return e.text?`Select "${e.value}" in "${e.text}"`:`Select "${e.value}"${e.selector?` (${e.selector})`:""}`;case "scroll":return e.selector?`Scroll to element (${e.selector})`:e.position?`Scroll to (${e.position.x}, ${e.position.y})`:"Scroll";case "navigate":return `Navigate to "${e.target}"`;case "wait_for_route":return `Wait for route "${e.target}"`;case "wait_for_dom_stable":return "Wait for page to finish loading";case "scan_context":return "Scan page for available actions";case "server_action":return `Execute server action "${e.actionId}"`;case "report_result":return "Report result to server";default:return "Execute action"}}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>{this.listeners.get(e)?.delete(t);}}emit(e,...t){this.listeners.get(e)?.forEach(n=>{try{n(...t);}catch(r){this.logger.error(`Error in ${e} listener`,r);}});}log(...e){this.logger.debug(...e);}};var Pe=class{config;actions=new Map;context=null;logger=createLogger("SDK.ServerAction");constructor(e={}){this.config={defaultTimeout:e.defaultTimeout??3e4,debug:e.debug??false,webhookHeaders:e.webhookHeaders??{},baseUrl:e.baseUrl??""},this.logger=createLogger("SDK.ServerAction",{enabled:this.config.debug,level:"debug"});}setContext(e){this.context=e;}register(e){this.actions.set(e.id,e),this.log(`Registered server action: ${e.id}`);}registerMany(e){for(let t of e)this.register(t);}unregister(e){this.actions.delete(e);}getActions(){return Array.from(this.actions.values())}getAction(e){return this.actions.get(e)}async execute(e,t){let n=this.actions.get(e);if(!n)return {success:false,error:`Server action not found: ${e}`};if(!this.context)return {success:false,error:"No execution context set"};let r=n.parameters.filter(s=>s.required&&!(s.name in t)).map(s=>s.name);if(r.length>0)return {success:false,error:`Missing required parameters: ${r.join(", ")}`};let o={...t};for(let s of n.parameters)!(s.name in o)&&s.defaultValue!==void 0&&(o[s.name]=s.defaultValue);this.log(`Executing server action: ${e}`,o);try{return n.handler?await this.executeHandler(n,o):n.webhookUrl?await this.executeWebhook(n,o):{success:!1,error:"Server action has no handler or webhookUrl"}}catch(s){let a=s instanceof Error?s.message:String(s);return this.log(`Server action error: ${a}`),{success:false,error:a}}}async executeHandler(e,t){if(!e.handler)return {success:false,error:"No handler defined"};let n=e.timeout??this.config.defaultTimeout;return await Promise.race([e.handler(t,this.context),new Promise((o,s)=>setTimeout(()=>s(new Error("Timeout")),n))])}async executeWebhook(e,t){if(!e.webhookUrl)return {success:false,error:"No webhookUrl defined"};let n=e.timeout??this.config.defaultTimeout,r=e.webhookUrl.startsWith("http")?e.webhookUrl:`${this.config.baseUrl}${e.webhookUrl}`,o={"Content-Type":"application/json",...this.config.webhookHeaders};if(e.webhookSecret){let c=await this.generateSignature(JSON.stringify(t),e.webhookSecret);o["X-Signature"]=c;}this.context&&(o["X-Session-Id"]=this.context.sessionId,this.context.authToken&&(o.Authorization=`Bearer ${this.context.authToken}`));let s=new AbortController,a=setTimeout(()=>s.abort(),n);try{let c=await fetch(r,{method:"POST",headers:o,body:JSON.stringify({actionId:e.id,params:t,context:{sessionId:this.context?.sessionId,userId:this.context?.userId,currentRoute:this.context?.currentRoute}}),signal:s.signal});if(clearTimeout(a),!c.ok)return this.logger.warn("Webhook failed",{actionId:e.id,status:c.status}),{success:!1,error:`Webhook failed with status ${c.status}`};let u=await c.json();return this.logger.debug("Webhook success",{actionId:e.id}),{success:!0,data:u}}catch(c){if(clearTimeout(a),c instanceof Error&&c.name==="AbortError")return {success:false,error:"Request timeout"};throw c}}async generateSignature(e,t){if(typeof crypto>"u"||!crypto.subtle)throw new Error("Web Crypto API (crypto.subtle) is unavailable. Webhook HMAC signing requires a secure context (HTTPS). Either serve the page over HTTPS or remove the webhookSecret.");let n=new TextEncoder,r=await crypto.subtle.importKey("raw",n.encode(t),{name:"HMAC",hash:"SHA-256"},false,["sign"]),o=await crypto.subtle.sign("HMAC",r,n.encode(e));return btoa(String.fromCharCode(...new Uint8Array(o)))}log(...e){this.logger.debug(...e);}};var Ot=z.object({type:z.enum(["click","type","navigate","scroll","select","submit","wait_for_dom_stable","wait_for_route","server_action","report_result"]),selector:z.string().max(500).optional(),text:z.string().max(1e3).optional(),value:z.string().max(5e3).optional(),target:z.string().max(1e3).optional(),actionId:z.string().max(255).optional(),params:z.record(z.string(),z.unknown()).optional(),context:z.string().max(500).optional()}),Lt=z.object({type:z.literal("command"),batchId:z.string().max(255),commands:z.array(Ot).max(50),message:z.string().max(5e3).optional()}),Pt=z.object({id:z.string(),role:z.enum(["user","assistant","system"]),content:z.string().max(32e3),timestamp:z.number(),status:z.enum(["sending","sent","error"]).optional()}),_e=createLogger("SDK.Storage",{enabled:true,level:"warn"});function _t(i){let e=null;return function(n){typeof window>"u"||(e&&clearTimeout(e),e=setTimeout(()=>{try{let r=n.slice(-100);localStorage.setItem(`${i}-messages`,JSON.stringify(r));}catch(r){_e.warn("Failed to save messages to localStorage",r);try{let o=n.slice(-50);localStorage.setItem(`${i}-messages`,JSON.stringify(o));}catch(o){_e.warn("Failed to save even reduced messages",o);}}},500));}}function $t(i){let e=_t(i);return function(n,r){let o;switch(r.type){case "ADD_MESSAGE":return o={...n,messages:[...n.messages,r.message]},e(o.messages),o;case "UPDATE_MESSAGE":return o={...n,messages:n.messages.map(s=>s.id===r.id?{...s,...r.updates}:s)},e(o.messages),o;case "SET_MESSAGES":return o={...n,messages:r.messages},e(o.messages),o;case "CLEAR_MESSAGES":return o={...n,messages:[]},e([]),o;case "SET_MODE":return {...n,mode:r.mode};case "SET_CONNECTION_STATE":return {...n,connectionState:r.state};case "SET_EXECUTING":return {...n,isExecuting:r.isExecuting};case "SET_EXECUTION_STATE":return {...n,executionState:r.state};case "SET_ERROR":return {...n,error:r.error};case "CLEAR_ERROR":return {...n,error:null};default:return n}}}function Wt(i="chatbot"){let e=[],t="ask";if(typeof window<"u"){try{let r=localStorage.getItem(`${i}-messages`);if(r){let o=JSON.parse(r);Array.isArray(o)?e=o.filter(a=>{let c=Pt.safeParse(a);return c.success||_e.warn("Skipping invalid persisted message",a),c.success}):localStorage.removeItem(`${i}-messages`);}}catch(r){_e.warn("Failed to load messages from localStorage",r);}let n=localStorage.getItem(`${i}-mode`);(n==="ask"||n==="navigate")&&(t=n);}return {messages:e,mode:t,connectionState:"disconnected",isExecuting:false,executionState:null,error:null}}function Bt({apiKey:i,serverUrl:e,navigationAdapter:t,serverActions:n=[],config:r,options:o,routes:s,debug:a$1=false,autoConnect:c=true,children:u}){let f=useMemo(()=>`chatbot-${i.slice(0,8)}`,[i]),A=useMemo(()=>createLogger("SDK",{enabled:a$1,level:"debug"}),[a$1]),w=useMemo(()=>normalizeWidgetConfig(r??void 0),[r]),B=useMemo(()=>{let l={...w};return o?.theme&&(l.theme={...l.theme,...o.theme}),{...l,...o,theme:l.theme}},[w,o]),K=useMemo(()=>$t(f),[f]),[R,b]=useReducer(K,f,Wt),Y=useRef(R.messages),[L,ae]=useState(()=>{if(typeof window<"u"){let l=localStorage.getItem(`${f}-widget-open`);if(l!==null)return l==="true"}return o?.defaultOpen??false}),[j,re]=useState(null),ce=j??B?.voiceLanguage??void 0,le=useRef(false);useEffect(()=>{if(le.current)return;let l=B.defaultMode;(l==="ask"||l==="navigate")&&(b({type:"SET_MODE",mode:l}),le.current=true);},[B.defaultMode]),useEffect(()=>{typeof window<"u"&&localStorage.setItem(`${f}-widget-open`,String(L));},[L,f]),useEffect(()=>{Y.current=R.messages;},[R.messages]),useEffect(()=>{typeof window<"u"&&localStorage.setItem(`${f}-mode`,R.mode);},[R.mode,f]);let T=useRef(null),oe=useRef(null),J=useRef(new Map),P=useRef(null),ue=useRef(null),z=useRef(null),_=useRef(null),We=useRef(null),ie=useRef(null),H=useRef(null),$=useRef(void 0);useEffect(()=>{$.current=s;},[s]);let X=useMemo(()=>t??Ze(),[t]);useEffect(()=>{let l=new ge({serverUrl:e,apiKey:i,debug:a$1});return T.current=l,l.on("connected",({sessionId:g})=>{v("Connected, session:",g),b({type:"SET_CONNECTION_STATE",state:"connected"});}),l.on("authenticated",({sessionId:g})=>{let m=H.current,C=X.getCurrentPath();m&&m.setContext({sessionId:g,currentRoute:C});}),l.on("disconnected",()=>{b({type:"SET_CONNECTION_STATE",state:"disconnected"});}),l.on("reconnecting",({attempt:g,maxAttempts:m})=>{v(`Reconnecting ${g}/${m}`),b({type:"SET_CONNECTION_STATE",state:"reconnecting"});}),l.on("reconnect_failed",()=>{b({type:"SET_CONNECTION_STATE",state:"failed"}),b({type:"SET_ERROR",error:new Error("Connection failed")});}),l.on("error",({error:g})=>{b({type:"SET_ERROR",error:g});}),l.on("message",g=>{we.current(g);}),c&&(l.connect(),b({type:"SET_CONNECTION_STATE",state:"connecting"})),()=>{l.disconnect(),T.current=null;}},[e,i,a$1,c]),useEffect(()=>{let l=new Ne({debug:a$1}),g=new Me({debug:a$1}),m=new Ie({debug:a$1}),C=new Oe({debug:a$1}),E=new Pe({debug:a$1});z.current=l,ue.current=g,_.current=m,We.current=C,H.current=E;let F=p=>{P.current=p,T.current?.send({type:"context",context:p});},S=p=>{E.setContext({sessionId:T.current?.getSessionId()??"",currentRoute:p});},D=()=>{let p=oe.current,U=p?p.getCurrentRoute():typeof window<"u"?window.location.pathname:"/",ze=g.scan();l.registerDiscoveredActions(U,ze);let Fe={...m.build(ze,l.getServerActions(),U),...s?.length?{routes:s}:{}};return S(Fe.route),F(Fe),Fe},N=new fe(X,{debug:a$1,onDOMStable:()=>D()});oe.current=N,N.setScanner(async()=>D());let k=new Le(C,N,l,{debug:a$1});ie.current=k,k.setServerActionHandler(async(p,U)=>E.execute(p,U));let ee=[];a$1&&(ee.push(k.on("commandStart",(p,U)=>{v("Command start:",{index:U,type:p.type,command:p});})),ee.push(k.on("commandComplete",p=>{v("Command complete:",{type:p.command.type,success:p.success,duration:p.duration,error:p.error});})),ee.push(k.on("complete",p=>{v("Command batch complete:",{total:p.length,failed:p.filter(U=>!U.success).length});})),ee.push(k.on("error",p=>{v("Command processor error:",p);}))),n.forEach(p=>{J.current.set(p.id,p),l.registerServerAction(p),E.register(p);}),g.observe(p=>{l.registerDiscoveredActions(N.getCurrentRoute(),p);let U={...m.build(p,l.getServerActions(),N.getCurrentRoute()),...s?.length?{routes:s}:{}};S(U.route),F(U);});let He=N.onRouteChange(()=>{S(N.getCurrentRoute()),D();});return typeof window<"u"&&(document.readyState==="complete"?(S(N.getCurrentRoute()),D()):window.addEventListener("load",()=>{S(N.getCurrentRoute()),D();},{once:true})),()=>{g.disconnect(),k.abort(),ee.forEach(p=>p()),He();}},[X,a$1,s]),useEffect(()=>{let l=z.current,g=H.current;!l||!g||n.forEach(m=>{J.current.set(m.id,m),l.registerServerAction(m),g.register(m);});},[n]);let G=useRef([]),Q=useRef(false),se=useCallback(async()=>{if(Q.current||G.current.length===0)return;Q.current=true;let l=G.current.shift();try{await Be(l.commands,l.batchId);}finally{Q.current=false,se();}},[]),Se=useCallback((l,g)=>{G.current.push({commands:l,batchId:g}),se();},[se]),Be=useCallback(async(l,g)=>{let m=ie.current;if(!m)return;b({type:"SET_EXECUTING",isExecuting:true});let C=[];C.push(m.on("stateChange",E=>{b({type:"SET_EXECUTION_STATE",state:E}),b({type:"SET_EXECUTING",isExecuting:E.isExecuting});})),C.push(m.on("error",E=>{b({type:"SET_ERROR",error:E});}));try{let E=await m.execute(l),F=T.current;if(E.forEach(S=>{F&&(S.command.type==="server_action"?F.send({type:"action_result",actionId:S.command.actionId,success:S.success,result:S.result,error:S.error,commandId:g}):F.send({type:"action_result",actionId:S.command.type,success:S.success,error:S.error,commandId:g}));}),ue.current&&z.current&&_.current&&oe.current){let S=ue.current.scan(),D=oe.current.getCurrentRoute();z.current.registerDiscoveredActions(D,S);let k={..._.current.build(S,z.current.getServerActions(),D),...$.current?.length?{routes:$.current}:{}};P.current=k,T.current&&T.current.send({type:"context",context:k});}}catch(E){let F=E instanceof Error?E:new Error(String(E));b({type:"SET_ERROR",error:F});let S=T.current,D=F.message||"Execution failed";l.forEach(N=>{if(!S)return;let k=N.type==="server_action"?N.actionId:N.type;S.send({type:"action_result",actionId:k,success:false,error:D,commandId:g});});}finally{C.forEach(E=>E()),b({type:"SET_EXECUTING",isExecuting:false}),b({type:"SET_EXECUTION_STATE",state:null});}},[]),we=useRef(()=>{}),Z=useCallback(l=>{switch(v("Server message received:",l.type,l),l.type){case "response":{let g=Y.current.find(m=>m.id===l.messageId);g&&g.role==="assistant"?b({type:"UPDATE_MESSAGE",id:g.id,updates:{content:l.message,timestamp:Date.now(),status:"sent"}}):b({type:"ADD_MESSAGE",message:{id:g?createMessageId():l.messageId,role:"assistant",content:l.message,timestamp:Date.now(),status:"sent"}});}break;case "command":{let g=Lt.safeParse(l);if(!g.success){v("Rejected invalid command message from server:",g.error.issues);break}let m=g.data;v("Received commands:",m.commands);let C=m.commands,E=m.batchId;if(m.message&&b({type:"ADD_MESSAGE",message:{id:createMessageId(),role:"assistant",content:m.message,timestamp:Date.now(),commands:C.length>0?C:void 0}}),C.length===0)break;if(!ie.current){b({type:"SET_ERROR",error:new Error("Action runner not ready")}),C.forEach(S=>{let D=S.type==="server_action"?S.actionId:S.type;T.current&&T.current.send({type:"action_result",actionId:D,success:false,error:"Action runner not ready",commandId:E});});break}Se(C,E);break}case "typing":break;case "server_action_result":v("Server action result:",l.actionId,l.result);break;case "error":v("Server error:",l.code,l.error,l.details),b({type:"SET_ERROR",error:new Error(l.error)});break;case "request_context":P.current&&T.current&&T.current.send({type:"context",context:P.current});break}},[Se]);useEffect(()=>{we.current=Z;},[Z]);let Ce=useCallback(l=>{let g=createMessageId();v("Sending message:",{messageId:g,mode:R.mode,length:l.length,connectionState:R.connectionState,route:P.current?.route??X.getCurrentPath()}),b({type:"ADD_MESSAGE",message:{id:g,role:"user",content:l,timestamp:Date.now(),status:"sending"}});let m=P.current??{route:X.getCurrentPath(),title:typeof document<"u"?document.title:"",actions:[],serverActions:Array.from(J.current.values()),content:{headings:[],mainContent:"",forms:[]},timestamp:Date.now(),...$.current?.length?{routes:$.current}:{}},C=j??B?.voiceLanguage??void 0;T.current?.send({type:"message",content:l,context:m,mode:R.mode,messageId:g,...C!=null?{locale:C}:{}}),b({type:"UPDATE_MESSAGE",id:g,updates:{status:"sent"}});},[R.mode,X,j,B?.voiceLanguage]),xe=useCallback(l=>{re(l??null);},[]),Re=useCallback(l=>{b({type:"SET_MODE",mode:l});},[]),Ae=useCallback(async(l,g)=>{let m=H.current;if(!m)throw new Error("Server action bridge not ready");if(!m.getAction(l)){let E=J.current.get(l);E&&m.register(E);}let C=await m.execute(l,g??{});return T.current&&T.current.send({type:"action_result",actionId:l,success:C.success,result:C.data,error:C.error}),C},[]),Te=useCallback(l=>{J.current.set(l.id,l),z.current?.registerServerAction(l),H.current?.register(l),A.debug("Registered server action:",l.id);},[A]),de=useCallback(()=>{b({type:"CLEAR_MESSAGES"});},[]),he=useCallback(()=>{b({type:"CLEAR_ERROR"});},[]),ke=useCallback(()=>{ie.current?.abort();},[]),d=useCallback(()=>{b({type:"SET_CONNECTION_STATE",state:"connecting"}),T.current?.connect();},[]),y=useCallback(()=>{T.current?.disconnect(),b({type:"SET_CONNECTION_STATE",state:"disconnected"});},[]);function v(...l){A.debug(...l);}let V=useMemo(()=>({widgetConfig:B,messages:R.messages,mode:R.mode,connectionState:R.connectionState,isExecuting:R.isExecuting,executionState:R.executionState,error:R.error,isWidgetOpen:L,setWidgetOpen:ae,voiceLanguage:ce,setVoiceLanguage:xe,sendMessage:Ce,setMode:Re,executeAction:Ae,registerServerAction:Te,clearMessages:de,clearError:he,stopExecution:ke,connect:d,disconnect:y,isConnected:R.connectionState==="connected"}),[B,R,L,ce,xe,Ce,Re,Ae,Te,de,he,ke,d,y]);return jsx(a.Provider,{value:V,children:u})}function dt(i){let e=[],t=0,n=i;for(;n.length>0;){let r=n.indexOf("**");if(r===-1){e.push(jsx(Ke.Fragment,{children:n},t++));break}let o=n.slice(0,r),s=n.slice(r+2),a=s.indexOf("**");if(a===-1){e.push(jsx(Ke.Fragment,{children:n},t++));break}o&&e.push(jsx(Ke.Fragment,{children:o},t++)),e.push(jsx("strong",{children:s.slice(0,a)},t++)),n=s.slice(a+2);}return e.length===1?e[0]:jsx(Fragment,{children:e})}function Ut({content:i,isUser:e}){if(e)return jsx(Fragment,{children:i});let t=typeof i=="string"?i:"";if(!t.trim())return jsx(Fragment,{children:"\xA0"});let n=t.split(/\n/),r=[],o=[],s=()=>{o.length>0&&(r.push(jsx("ul",{className:"navsi-chatbot-message-list",children:o.map((a,c)=>jsx("li",{className:"navsi-chatbot-message-list-item",children:dt(a)},c))},r.length)),o=[]);};for(let a=0;a<n.length;a++){let u=n[a].trim(),f=u.match(/^[*-]\s+(.*)$/);f?(s(),o.push(f[1].trim())):(s(),u&&r.push(jsx("p",{className:"navsi-chatbot-message-paragraph",children:dt(u)},r.length)));}return s(),r.length===0?jsx(Fragment,{children:t}):jsx("div",{className:"navsi-chatbot-message-content",children:r})}function Vt(){if(typeof window>"u")return null;let i=window;return i.SpeechRecognition??i.webkitSpeechRecognition??null}function qt(){return typeof navigator<"u"&&"brave"in navigator}function Kt(i){if(i==="network"){if(!(typeof navigator<"u"?navigator.onLine:true))return "Voice input error: network. You appear to be offline.";if(qt())return "Voice input error: network. Brave may block speech services; disable Shields or try Chrome/Edge.";let t=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");return !(typeof window<"u"&&window.location.protocol==="https:")&&!t?"Voice input error: network. Microphone access requires HTTPS.":"Voice input error: network. Check microphone permission and reload the page."}return i==="not-allowed"||i==="service-not-allowed"?"Voice input error: microphone permission blocked.":i==="no-speech"?"Voice input error: no speech detected.":i==="audio-capture"?"Voice input error: no microphone found.":`Voice input error: ${i}`}function zt({className:i,windowClassName:e$1,buttonClassName:t}){let[n,r]=useState(""),[o,s]=useState(false),[a,c$1]=useState(""),[u,f]=useState(null),A=useRef(null),w=useRef(null),B=useRef(null),K=useRef(""),R=useRef(null),b=useRef(false),Y=useRef(false),{messages:L,sendMessage:ae,isConnected:j,mode:re,setMode:ce,isExecuting:le,error:T,clearError:oe,clearMessages:J,isWidgetOpen:P,setWidgetOpen:ue,stopExecution:z,widgetConfig:_,voiceLanguage:We,setVoiceLanguage:ie}=c(),H=We??_?.voiceLanguage??(typeof navigator<"u"?navigator.language:void 0)??"en-US",{progress:$}=d(),{isReconnecting:X}=e(),G=useMemo(Vt,[]),Q=!!G;useEffect(()=>{L.length>0&&w.current&&P&&requestAnimationFrame(()=>{w.current&&w.current.scrollTo({top:w.current.scrollHeight,behavior:"smooth"});});},[L,P]),useEffect(()=>{if(!b.current){let d=[...L].reverse().find(y=>y.role==="assistant");R.current=d?.id??null,b.current=true;}},[]),useEffect(()=>{let d=[...L].reverse().find(g=>g.role==="assistant");if(!d||!b.current||d.id===R.current||o||!Y.current||typeof window>"u"||!("speechSynthesis"in window))return;let y=d.content?.trim();if(!y)return;let v=y.replace(/\*\*(.*?)\*\*/g,"$1").replace(/[*_~`]/g,""),V=H;window.speechSynthesis.cancel();let l=new SpeechSynthesisUtterance(v);l.lang=V,window.speechSynthesis.speak(l),R.current=d.id,Y.current=false;},[L,o,H]);let se=()=>{n.trim()&&(Y.current=false,ae(n.trim()),r(""));},Se=d=>{d.key==="Enter"&&!d.shiftKey&&(d.preventDefault(),se());},Be=useCallback(()=>{if(o)return;if(!G){f("Voice input is not supported in this browser.");return}f(null),K.current="";let d=new G;B.current=d,d.continuous=false,d.interimResults=true,d.maxAlternatives=1,d.lang=H,d.onstart=()=>{s(true),c$1(""),typeof window<"u"&&"speechSynthesis"in window&&window.speechSynthesis.cancel();},d.onresult=y=>{let v="",V="";for(let l=y.resultIndex;l<y.results.length;l+=1){let g=y.results[l],m=g[0]?.transcript??"";g.isFinal?V+=m:v+=m;}V?(K.current=`${K.current} ${V}`.trim(),c$1(K.current)):v&&c$1(v.trim());},d.onerror=y=>{f(y.error?Kt(y.error):"Voice input error");},d.onend=()=>{s(false);let y=K.current.trim();K.current="",c$1(""),y&&(Y.current=true,ae(y),r(""));},d.start();},[o,G,ae,H]),we=useCallback(()=>{B.current?.stop();},[]);useEffect(()=>()=>{B.current?.abort(),typeof window<"u"&&"speechSynthesis"in window&&window.speechSynthesis.cancel();},[]);function Z(d,y){return d&&(/^#[0-9a-fA-F]{3,8}$/.test(d)||/^rgba?\(\s*[\d.,\s%]+\)$/.test(d)||/^hsla?\(\s*[\d.,\s%]+\)$/.test(d)||/^[a-zA-Z]{2,30}$/.test(d))?d:y}function Ce(d,y){if(!d)return y;let v=d.replace(/[^a-zA-Z0-9\s,'_-]/g,"").trim();return v.length>0&&v.length<=200?v:y}useEffect(()=>{let d=_?.theme,y="navsi-chatbot-theme-vars",v=document.getElementById(y);v||(v=document.createElement("style"),v.id=y,document.head.appendChild(v));let V=Z(d?.primaryColor,"#2563eb"),l=Z(d?.secondaryColor,"#1d4ed8"),g=Z(d?.backgroundColor,"#ffffff"),m=Z(d?.textColor,"#1f2937"),C=Ce(d?.fontFamily,"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"),E=Math.min(50,Math.max(0,Number(d?.borderRadius)||12)),F=Math.min(800,Math.max(280,Number(d?.windowWidth)||360)),S=Math.min(1e3,Math.max(300,Number(d?.windowHeight)||520)),D=Math.min(120,Math.max(32,Number(d?.buttonSize)||56)),k=["bottom-right","bottom-left","top-right","top-left"].includes(d?.position??"")?d?.position??"bottom-right":"bottom-right",ee=k==="bottom-right"||k==="top-right",He=k==="bottom-right"||k==="bottom-left";v.textContent=`
2
- .navsi-chatbot-container {
3
- --navsi-primary: ${V};
4
- --navsi-primary-hover: ${l};
5
- --navsi-bg: ${g};
6
- --navsi-text: ${m};
7
- --navsi-font: ${C};
8
- --navsi-radius: ${E}px;
9
- --navsi-radius-sm: ${Math.max(4,Math.round(E*.5))}px;
10
- --navsi-radius-full: 9999px;
11
- --navsi-window-width: ${F}px;
12
- --navsi-window-height: ${S}px;
13
- --navsi-button-size: ${D}px;
14
- font-family: var(--navsi-font);
15
- ${He?"bottom: 24px; top: auto;":"top: 24px; bottom: auto;"}
16
- ${ee?"right: 24px; left: auto;":"left: 24px; right: auto;"}
17
- }
18
- `;},[_?.theme]);let xe={position:"fixed",zIndex:9999},Re=_?.headerTitle??"AI Assistant",Ae=_?.welcomeMessage??"How can I help you today?",Te=_?.subtitle??"Type a message to get started",de=_?.askPlaceholder??"Ask a question...",he=_?.navigatePlaceholder??"What should I do? Try: Go to cart, Add product 1 to cart",ke=_?.supportedLanguages??[{code:"en-US",label:"EN"},{code:"hi-IN",label:"\u0939\u093F\u0902\u0926\u0940"}];return jsxs("div",{style:xe,className:`navsi-chatbot-container ${i||""}`,children:[P&&jsxs("div",{className:`navsi-chatbot-window ${e$1||""}`,children:[jsxs("div",{className:"navsi-chatbot-header",children:[jsx("div",{className:"navsi-chatbot-header-left",children:jsxs("div",{children:[jsx("div",{className:"navsi-chatbot-title",children:Re}),jsx("div",{className:"navsi-chatbot-status",children:j?"Connected":X?"Reconnecting":"Disconnected"}),o&&jsxs("div",{className:"navsi-chatbot-voice-indicator","aria-live":"polite",children:[jsxs("svg",{width:"14",height:"14",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"})]}),"Listening\u2026"]})]})}),jsxs("div",{className:"navsi-chatbot-mode-toggle",children:[jsx("button",{className:`navsi-chatbot-mode-button ${re==="ask"?"navsi-chatbot-mode-active":""}`,onClick:()=>ce("ask"),children:"Ask"}),jsx("button",{className:`navsi-chatbot-mode-button ${re==="navigate"?"navsi-chatbot-mode-active":""}`,onClick:()=>ce("navigate"),children:"Action"})]}),jsx("div",{className:"navsi-chatbot-lang-toggle",role:"group","aria-label":"Voice and response language",children:ke.map(d=>jsx("button",{type:"button",className:`navsi-chatbot-lang-button ${H.startsWith(d.code.split("-")[0])?"navsi-chatbot-lang-active":""}`,onClick:()=>ie(d.code),title:d.label,"aria-pressed":H.startsWith(d.code.split("-")[0]),children:d.label},d.code))}),L.length>0&&jsx("button",{type:"button",onClick:()=>J(),className:"navsi-chatbot-clear",title:"Clear chat","aria-label":"Clear chat",children:"Clear"})]}),le&&jsxs("div",{className:"navsi-chatbot-banner",children:[jsx("span",{children:"\u26A1 Executing actions\u2026"}),$&&jsxs(Fragment,{children:[jsxs("span",{className:"navsi-chatbot-pill",children:[$.current+1,"/",$.total]}),$.description&&jsx("span",{className:"navsi-chatbot-step",children:$.description})]})]}),$&&jsx("div",{className:"navsi-chatbot-progress-container",children:jsx("div",{className:"navsi-chatbot-progress-bar",children:jsx("div",{className:"navsi-chatbot-progress-fill",style:{width:`${$.percentage??0}%`}})})}),T&&jsxs("div",{className:"navsi-chatbot-error",children:[jsx("span",{children:T.message}),jsx("button",{className:"navsi-chatbot-error-close",onClick:oe,children:"\u2715"})]}),u&&jsx("div",{className:"navsi-chatbot-voice-error",role:"alert",children:u}),jsxs("div",{ref:w,className:"navsi-chatbot-messages",role:"log","aria-live":"polite","aria-label":"Chat messages",children:[L.length===0&&jsxs("div",{className:"navsi-chatbot-welcome",children:[jsx("div",{className:"navsi-chatbot-welcome-icon",children:"\u{1F44B}"}),jsx("div",{className:"navsi-chatbot-welcome-text",children:Ae}),jsx("div",{className:"navsi-chatbot-welcome-hint",children:Te})]}),L.map(d=>jsx("div",{className:`navsi-chatbot-message ${d.role==="user"?"navsi-chatbot-message-user":"navsi-chatbot-message-assistant"}`,children:jsx(Ut,{content:d.content,isUser:d.role==="user"})},d.id)),jsx("div",{ref:A})]}),jsxs("div",{className:"navsi-chatbot-input-area",children:[jsx("input",{type:"text",value:n,onChange:d=>r(d.target.value),onKeyDown:Se,placeholder:re==="ask"?de:he,className:"navsi-chatbot-input",maxLength:8e3,"aria-label":re==="ask"?de:he}),jsx("button",{className:`navsi-chatbot-voice-button ${o?"navsi-chatbot-voice-button-active":""}`,onClick:()=>{o?we():Be();},disabled:!j||!Q,"aria-label":Q?o?"Stop voice input":"Start voice input":"Voice input not supported in this browser","aria-pressed":o,title:Q?o?"Click to stop and send":"Click to start listening":"Voice input is not available in this browser",type:"button",children:o?jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsx("circle",{cx:"12",cy:"12",r:"8"})}):jsxs("svg",{width:"20",height:"20",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"})]})}),le?jsx("button",{className:"navsi-chatbot-stop-button",onClick:z,"aria-label":"Stop",title:"Stop current action",children:jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsx("rect",{x:"6",y:"6",width:"12",height:"12",rx:"1"})})}):jsx("button",{className:"navsi-chatbot-send-button",onClick:se,disabled:!j,children:jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsx("path",{d:"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"})})})]}),a&&jsx("div",{className:"navsi-chatbot-voice-transcript","aria-live":"polite",children:a})]}),jsx("button",{className:`navsi-chatbot-toggle ${t||""}`,onClick:()=>ue(!P),"aria-label":P?"Close chat":"Open chat",children:P?jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"currentColor",children:jsx("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"})}):jsx("svg",{width:"28",height:"28",viewBox:"0 0 24 24",fill:"currentColor",children:jsx("path",{d:"M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z"})})})]})}export{ge as a,Gt as b,Ze as c,fe as d,Qt as e,Bt as f,zt as g};//# sourceMappingURL=chunk-UQND4TVW.js.map
19
- //# sourceMappingURL=chunk-UQND4TVW.js.map