@foisit/react-wrapper 2.4.5 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,7 +33,7 @@ Transform your React app into an intelligent, voice-ready platform. Foisit provi
33
33
  - **Programmatic UI Triggers** - Direct command execution via `runCommand()`
34
34
  - **Rich Markdown Rendering** - Enhanced response formatting with headings, code, and links
35
35
  - **Advanced File Validations** - Comprehensive client-side file validation with size, type, and dimension checks
36
- - **Premium UI** - Glassmorphic overlay with dark/light mode support
36
+ - **Premium UI** - Glass or solid theme with dark/light mode support
37
37
  - **Zero Backend Required** - Secure proxy architecture keeps API keys server-side
38
38
  - **React Native** - Uses Hooks, Context API, and modern React patterns
39
39
  - **Type-Safe** - Full TypeScript support with comprehensive types
@@ -441,9 +441,53 @@ interface AssistantConfig {
441
441
  customHtml?: string;
442
442
  position?: { bottom: string; right: string };
443
443
  };
444
+
445
+ // Theme mode: 'glass' (default) or 'solid'
446
+ theme?: 'glass' | 'solid';
447
+
448
+ // Custom colors for solid theme (ignored in glass mode)
449
+ themeColors?: ThemeColors;
444
450
  }
445
451
  ```
446
452
 
453
+ ### `ThemeColors`
454
+
455
+ Custom colors for solid theme mode:
456
+
457
+ ```typescript
458
+ interface ThemeColors {
459
+ background?: string; // Background color (e.g., '#1e1e2e')
460
+ text?: string; // Primary text color (e.g., '#ffffff')
461
+ accent?: string; // Accent color for highlights (e.g., '#89b4fa' or a gradient)
462
+ userBubbleBg?: string; // User message bubble background
463
+ systemBubbleBg?: string; // System message bubble background
464
+ border?: string; // Border color
465
+ }
466
+ ```
467
+
468
+ ### Theme Customization Example
469
+
470
+ ```tsx
471
+ const config = {
472
+ commands: [...],
473
+ // Use solid theme with custom colors
474
+ theme: 'solid',
475
+ themeColors: {
476
+ background: '#1e1e2e',
477
+ text: '#cdd6f4',
478
+ accent: '#89b4fa',
479
+ userBubbleBg: 'rgba(137, 180, 250, 0.2)',
480
+ systemBubbleBg: 'rgba(255, 255, 255, 0.05)',
481
+ },
482
+ };
483
+
484
+ <AssistantProvider config={config}>
485
+ <App />
486
+ </AssistantProvider>
487
+ ```
488
+
489
+ > **Note**: Glass theme (default) uses glassmorphism with blur effects and adapts to light/dark mode via `prefers-color-scheme`. Solid theme ignores system preferences and uses configured colors.
490
+
447
491
  ---
448
492
 
449
493
  ## Advanced Usage
package/index.d.ts CHANGED
@@ -4,3 +4,4 @@ export * from './lib/components/AssistantActivator';
4
4
  export * from './lib/hooks/useAssistant';
5
5
  export * from './lib/hooks/useAssistantState';
6
6
  export * from './lib/services/AssistantService';
7
+ export type { ThemeColors } from '../../core/src/index.ts';
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("react/jsx-runtime"),S=require("react"),O={};function N(){return E.jsx("div",{className:O.container,children:E.jsx("h1",{children:"Welcome to ReactWrapper!"})})}class H{constructor(t){this.endpoint=t||"https://foisit-ninja.netlify.app/.netlify/functions/intent"}async determineIntent(t,e,i){try{const s={userInput:t,commands:e.map(o=>({id:o.id,command:o.command,description:o.description,parameters:o.parameters})),context:i},n=await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!n.ok)throw new Error(`Proxy API Error: ${n.statusText}`);return await n.json()}catch(s){return console.error("OpenAIService Error:",s),{type:"unknown"}}}}class z{constructor(t=!0){if(this.commands=new Map,this.openAIService=null,this.context=null,this.pendingConfirmation=null,this.enableSmartIntent=!0,this.selectOptionsCache=new Map,typeof t=="boolean"){this.enableSmartIntent=t,this.enableSmartIntent&&(this.openAIService=new H);return}this.enableSmartIntent=t.enableSmartIntent??!0,this.enableSmartIntent&&(this.openAIService=new H(t.intentEndpoint))}addCommand(t,e){let i;if(typeof t=="string"){if(!e)throw new Error("Action required when adding command by string.");i={id:t.toLowerCase().replace(/\s+/g,"_"),command:t.toLowerCase(),action:e}}else i={...t},i.id||(i.id=i.command.toLowerCase().replace(/\s+/g,"_"));this.commands.set(i.command.toLowerCase(),i),i.id&&(i.id,i.command)}removeCommand(t){this.commands.delete(t.toLowerCase())}async executeCommand(t){if(typeof t=="object"&&t!==null){if(this.isStructured(t)){const c=String(t.commandId),f=t.params??{},r=this.getCommandById(c);if(!r)return{message:"That command is not available.",type:"error"};const p=this.sanitizeParamsForCommand(r,f),m=(r.parameters??[]).filter(C=>C.required).filter(C=>p[C.name]==null||p[C.name]==="");return m.length>0?(this.context={commandId:this.getCommandIdentifier(r),params:p},{message:`Please provide the required details for "${r.command}".`,type:"form",fields:m}):r.critical?(this.pendingConfirmation={commandId:this.getCommandIdentifier(r),params:p},this.buildConfirmResponse(r)):this.safeRunAction(r,p)}if(!this.context)return{message:"Session expired or invalid context.",type:"error"};const n=this.getCommandById(this.context.commandId);if(!n)return this.context=null,{message:"Session expired or invalid context.",type:"error"};if(Array.isArray(t))return{message:"Invalid form payload.",type:"error"};const a={...this.context.params,...t};if(n.critical)return this.context=null,this.pendingConfirmation={commandId:this.getCommandIdentifier(n),params:a},this.buildConfirmResponse(n);const o=await this.safeRunAction(n,a);return this.context=null,this.normalizeResponse(o)}const e=t.trim().toLowerCase();if(this.pendingConfirmation){const n=e;if(["yes","y","confirm","ok","okay"].includes(n)){const{commandId:a,params:o}=this.pendingConfirmation;this.pendingConfirmation=null;const c=this.getCommandById(a);return c?this.safeRunAction(c,o):{message:"That action is no longer available.",type:"error"}}return["no","n","cancel","stop"].includes(n)?(this.pendingConfirmation=null,{message:"Cancelled.",type:"success"}):{message:"Please confirm: Yes or No.",type:"confirm",options:[{label:"Yes",value:"yes"},{label:"No",value:"no"}]}}const i=this.commands.get(e);if(i){const n=i;if(n.macro)return this.safeRunAction(n,{});const a=(n.parameters??[]).filter(o=>o.required);return a.length>0?(this.context={commandId:this.getCommandIdentifier(n),params:{}},{message:`Please provide the required details for "${n.command}".`,type:"form",fields:a}):n.critical?(this.pendingConfirmation={commandId:this.getCommandIdentifier(n),params:{}},this.buildConfirmResponse(n)):this.safeRunAction(n,{})}const s=await this.tryDeterministicMatch(e);if(s)return s;if(this.enableSmartIntent&&this.openAIService){const n=await this.getCommandsForAI(),a=await this.openAIService.determineIntent(e,n,this.context);return this.handleAIResult(a)}return this.enableSmartIntent?this.listAllCommands():{message:"I'm not sure what you mean.",type:"error"}}async handleAIResult(t){if(t.type==="match"&&t.match){const e=this.getCommandById(t.match);if(!e)return{message:"I'm not sure what you mean.",type:"error"};if(e.macro)return this.safeRunAction(e,{});const i=t.params??{},s=this.sanitizeParamsForCommand(e,i),n=e.allowAiParamExtraction===!1?{}:s,o=(e.parameters??[]).filter(f=>f.required).filter(f=>n[f.name]==null||n[f.name]==="");if(t.incomplete||o.length>0){if(this.context={commandId:this.getCommandIdentifier(e),params:n},!(e.collectRequiredViaForm!==!1)&&this.shouldAskSingleQuestion(o)){const p=o.map(g=>g.name).join(" and ");return{message:t.message||`Please provide ${p}.`,type:"question"}}return{message:t.message||`Please fill in the missing details for "${e.command}".`,type:"form",fields:o}}if(e.critical)return this.pendingConfirmation={commandId:this.getCommandIdentifier(e),params:n},this.buildConfirmResponse(e);const c=await e.action(n);return this.normalizeResponse(c)}return t.type==="ambiguous"&&t.options&&t.options.length?{message:t.message||"Did you mean one of these?",type:"ambiguous",options:t.options.map(e=>({label:e.label,value:e.commandId??e.label,commandId:e.commandId}))}:this.listAllCommands()}sanitizeParamsForCommand(t,e){const i={...e??{}};for(const s of t.parameters??[]){const n=i[s.name];if(s.type==="string"){if(typeof n!="string"){delete i[s.name];continue}const a=n.trim();if(!a){delete i[s.name];continue}i[s.name]=a}if(s.type==="number"){const a=typeof n=="number"?n:Number(n==null?void 0:n.toString().trim());if(Number.isNaN(a)){delete i[s.name];continue}if(typeof s.min=="number"&&a<s.min){delete i[s.name];continue}if(typeof s.max=="number"&&a>s.max){delete i[s.name];continue}i[s.name]=a}if(s.type==="date"){const a=i[s.name];if(typeof a=="string"){const o=a.trim();this.isIsoDateString(o)?i[s.name]=o:delete i[s.name]}else delete i[s.name]}if(s.type==="select"){const a=typeof n=="string"?n:n==null?void 0:n.toString();if(!a){delete i[s.name];continue}if(Array.isArray(s.options)&&s.options.length>0&&!s.options.some(c=>String(c.value)===String(a))){delete i[s.name];continue}i[s.name]=a}if(s.type==="file"){const a=i[s.name],o=a&&typeof a=="object"&&typeof a.name=="string"&&typeof a.size=="number",c=typeof a=="string"&&/^data:[^;]+;base64,/.test(a);(s.delivery??"file")==="base64"?!c&&!o&&delete i[s.name]:o||delete i[s.name]}}return i}isIsoDateString(t){if(!/^\d{4}-\d{2}-\d{2}$/.test(t))return!1;const e=new Date(`${t}T00:00:00Z`);return!Number.isNaN(e.getTime())}shouldAskSingleQuestion(t){if(t.length!==1)return!1;const e=t[0].type;return e==="string"||e==="number"||e==="date"}buildConfirmResponse(t){return{message:`Are you sure you want to run "${t.command}"?`,type:"confirm",options:[{label:"Yes",value:"yes"},{label:"No",value:"no"}]}}async tryDeterministicMatch(t){const e=[];for(const o of this.commands.values()){let c=0;const f=o.command.toLowerCase();t.includes(f)&&(c+=5);const r=o.keywords??[];for(const p of r){const g=p.toLowerCase().trim();g&&(t===g?c+=4:t.includes(g)&&(c+=3))}c>0&&e.push({cmd:o,score:c})}if(e.length===0)return null;e.sort((o,c)=>c.score-o.score);const i=e[0].score,s=e.filter(o=>o.score===i).slice(0,3);if(s.length>1)return{message:"I think you mean one of these. Which one should I run?",type:"ambiguous",options:s.map(o=>({label:o.cmd.command,value:o.cmd.command,commandId:o.cmd.id}))};const n=s[0].cmd,a=(n.parameters??[]).filter(o=>o.required);return a.length>0?(this.context={commandId:this.getCommandIdentifier(n),params:{}},{message:`Please provide the required details for "${n.command}".`,type:"form",fields:a}):n.critical?(this.pendingConfirmation={commandId:this.getCommandIdentifier(n),params:{}},this.buildConfirmResponse(n)):this.safeRunAction(n,{})}async safeRunAction(t,e){try{const i=await t.action(e??{});return this.normalizeResponse(i)}catch{return{message:"Something went wrong while running that command.",type:"error"}}}async getCommandsForAI(){const t=Array.from(this.commands.values()).map(e=>({...e,parameters:e.parameters?e.parameters.map(i=>({...i})):void 0}));return await Promise.all(t.map(async e=>{e.parameters&&await Promise.all(e.parameters.map(async i=>{if(i.type!=="select"||!i.getOptions||i.options&&i.options.length)return;const s=`${e.id??e.command}:${i.name}`,n=this.selectOptionsCache.get(s),a=Date.now();if(n&&a-n.ts<6e4){i.options=n.options;return}try{const o=await i.getOptions();this.selectOptionsCache.set(s,{options:o,ts:a}),i.options=o}catch{}}))})),t}getCommandById(t){for(const e of this.commands.values())if(e.id===t)return e}listAllCommands(){return{message:"Here are the available commands:",type:"ambiguous",options:Array.from(this.commands.values()).map(e=>({label:e.command,value:e.id??e.command,commandId:e.id??e.command}))}}normalizeResponse(t){return typeof t=="string"?{message:t,type:"success"}:t&&typeof t=="object"?t:{message:"Done",type:"success"}}isStructured(t){return typeof t.commandId=="string"}getCommandIdentifier(t){return t.id||(t.id=t.command.toLowerCase().replace(/\s+/g,"_")),t.id}getCommands(){return Array.from(this.commands.keys())}}class P{constructor(){this.synth=typeof window<"u"?window.speechSynthesis:null}speak(t,e){if(!this.synth){console.error("SpeechSynthesis API is not supported in this environment.");return}const i=new SpeechSynthesisUtterance(t);e&&(i.pitch=e.pitch||1,i.rate=e.rate||1,i.volume=e.volume||1),typeof window<"u"&&(i.onstart=()=>{window.dispatchEvent(new CustomEvent("foisit:tts-start"))},i.onend=()=>{console.log("Speech finished."),window.dispatchEvent(new CustomEvent("foisit:tts-end"))}),i.onerror=s=>{console.error("Error during speech synthesis:",s.error)},this.synth.speak(i)}stopSpeaking(){this.synth&&this.synth.cancel()}}class W{constructor(){this.fallbackMessage="Sorry, I didn’t understand that."}setFallbackMessage(t){this.fallbackMessage=t}handleFallback(t){t&&console.log(`Fallback triggered for: "${t}"`),console.log(this.fallbackMessage),new P().speak(this.fallbackMessage)}getFallbackMessage(){return this.fallbackMessage}}const $=()=>{if(typeof window>"u")return null;const d=window;return d.SpeechRecognition??d.webkitSpeechRecognition??null};class B{constructor(t="en-US",e={}){this.recognition=null,this.isListening=!1,this.engineActive=!1,this.intentionallyStopped=!1,this.restartAllowed=!0,this.lastStart=0,this.backoffMs=250,this.destroyed=!1,this.resultCallback=null,this.ttsSpeaking=!1,this.debugEnabled=!0,this.restartTimer=null,this.prewarmed=!1,this.hadResultThisSession=!1,this.onTTSStart=()=>{var s;this.ttsSpeaking=!0;try{(s=this.recognition)==null||s.stop()}catch{}this.isListening&&this.emitStatus("speaking")},this.onTTSEnd=()=>{this.ttsSpeaking=!1,this.isListening&&this.restartAllowed?this.safeRestart():this.emitStatus(this.isListening?"listening":"idle")};const i=$();if(i){this.recognition=new i,this.recognition.lang=t,this.recognition.interimResults=e.interimResults??!0,this.recognition.continuous=e.continuous??!0,this.recognition.onresult=n=>this.handleResult(n,e),this.recognition.onend=()=>this.handleEnd(),this.recognition.onstart=()=>{this.log("recognition onstart"),this.engineActive=!0,this.hadResultThisSession=!1,this.restartTimer&&(clearTimeout(this.restartTimer),this.restartTimer=null),this.backoffMs=250,this.isListening&&!this.ttsSpeaking&&this.emitStatus("listening")};const s=this.recognition;s.onaudiostart=()=>this.log("onaudiostart"),s.onsoundstart=()=>this.log("onsoundstart"),s.onspeechstart=()=>this.log("onspeechstart"),s.onspeechend=()=>this.log("onspeechend"),s.onsoundend=()=>this.log("onsoundend"),s.onaudioend=()=>this.log("onaudioend"),this.recognition.onerror=n=>this.handleError(n)}else this.recognition=null,this.emitStatus("unsupported");typeof window<"u"?(window.addEventListener("foisit:tts-start",this.onTTSStart),window.addEventListener("foisit:tts-end",this.onTTSEnd),this.visibilityHandler=()=>{var s;if(typeof document<"u"&&document.hidden){try{(s=this.recognition)==null||s.stop()}catch{}this.emitStatus(this.ttsSpeaking?"speaking":"idle")}else this.isListening&&!this.ttsSpeaking&&this.safeRestart()},typeof document<"u"&&document.addEventListener("visibilitychange",this.visibilityHandler)):this.visibilityHandler=void 0}log(t){this.debugEnabled&&t&&console.log("[VoiceProcessor]",t)}warn(t){this.debugEnabled&&t&&console.warn("[VoiceProcessor]",t)}error(t){this.debugEnabled&&t&&console.error("[VoiceProcessor]",t)}isSupported(){return $()!==null}onStatusChange(t){this.statusCallback=t}startListening(t){if(!this.isSupported()||!this.recognition){this.warn("VoiceProcessor: SpeechRecognition is not supported in this browser."),this.emitStatus("unsupported");return}if(this.isListening){this.warn("VoiceProcessor: Already listening."),this.resultCallback=t;return}this.resultCallback=t,this.intentionallyStopped=!1,this.restartAllowed=!0,this.isListening=!0,this.emitStatus("listening"),this.prewarmAudio().finally(()=>{this.safeRestart()})}stopListening(){var t;this.intentionallyStopped=!0,this.restartAllowed=!1,this.isListening=!1,this.emitStatus(this.ttsSpeaking?"speaking":"idle");try{(t=this.recognition)==null||t.stop()}catch{}}destroy(){this.destroyed=!0,this.stopListening(),this.resultCallback=null,window.removeEventListener("foisit:tts-start",this.onTTSStart),window.removeEventListener("foisit:tts-end",this.onTTSEnd),this.visibilityHandler&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=void 0)}handleResult(t,e){var s,n;if(!this.resultCallback)return;const i=e.confidenceThreshold??.6;for(let a=t.resultIndex;a<t.results.length;a++){const o=t.results[a],c=o&&o[0],f=((n=(s=c==null?void 0:c.transcript)==null?void 0:s.trim)==null?void 0:n.call(s))||"",r=(c==null?void 0:c.confidence)??0;if(f&&!(!o.isFinal&&e.interimResults===!1)&&!(o.isFinal&&r<i))try{this.hadResultThisSession=!0,this.resultCallback(f,!!o.isFinal)}catch{this.error("VoiceProcessor: result callback error")}}}handleEnd(){if(this.log("recognition onend"),this.engineActive=!1,this.destroyed||this.intentionallyStopped||!this.restartAllowed||this.ttsSpeaking){this.ttsSpeaking||(this.isListening=!1,this.emitStatus("idle"));return}this.isListening=!0,this.scheduleRestart()}handleError(t){const e=t==null?void 0:t.error;if(this.warn(`Error occurred: ${e??"unknown"}`),e&&["not-allowed","service-not-allowed","bad-grammar","language-not-supported"].includes(e)){this.intentionallyStopped=!0,this.restartAllowed=!1,this.isListening=!1,this.emitStatus("error",{error:e});return}this.scheduleRestart()}safeRestart(){if(!this.recognition)return;if(this.engineActive){this.log("safeRestart: engine already active, skipping start");return}const t=Date.now();if(t-this.lastStart<300){setTimeout(()=>this.safeRestart(),300);return}this.lastStart=t;try{this.log("calling recognition.start()"),this.recognition.start(),this.backoffMs=250,this.isListening&&!this.ttsSpeaking&&this.emitStatus("listening")}catch{this.error("recognition.start() threw; scheduling restart"),this.scheduleRestart()}}scheduleRestart(){if(this.destroyed||this.intentionallyStopped||!this.restartAllowed||this.ttsSpeaking)return;if(this.engineActive){this.log("scheduleRestart: engine active, not scheduling");return}const t=Math.min(this.backoffMs,2e3);if(this.log(`scheduleRestart in ${t}ms`),this.restartTimer){this.log("scheduleRestart: restart already scheduled");return}this.restartTimer=setTimeout(()=>{this.restartTimer=null,!(this.destroyed||this.intentionallyStopped||!this.restartAllowed||this.ttsSpeaking)&&this.safeRestart()},t),this.backoffMs=Math.min(this.backoffMs*2,2e3)}async prewarmAudio(){if(!this.prewarmed)try{if(typeof navigator>"u"||!("mediaDevices"in navigator))return;const t=navigator.mediaDevices;if(!(t!=null&&t.getUserMedia))return;this.log("prewarmAudio: requesting mic");const e=await t.getUserMedia({audio:!0});for(const i of e.getTracks())i.stop();this.prewarmed=!0,this.log("prewarmAudio: mic ready")}catch{this.warn("prewarmAudio: failed to get mic")}}emitStatus(t,e){if(this.statusCallback)try{this.statusCallback(t,e)}catch{this.error("VoiceProcessor: status callback error")}}}class R{constructor(){this.lastTap=0,this.tapCount=0}setupTripleTapListener(t){this.destroy(),this.clickListener=()=>{this.tapCount++,this.tapCount===1?this.tapTimeout=window.setTimeout(()=>{this.tapCount=0},500):this.tapCount===3&&(clearTimeout(this.tapTimeout),this.tapCount=0,t())},document.addEventListener("click",this.clickListener),this.touchEndListener=()=>{const e=new Date().getTime(),i=e-this.lastTap;i<500&&i>0?(this.tapCount++,this.tapCount===3&&(this.tapCount=0,t())):this.tapCount=1,this.lastTap=e},document.addEventListener("touchend",this.touchEndListener)}destroy(){this.dblClickListener&&document.removeEventListener("dblclick",this.dblClickListener),this.touchEndListener&&document.removeEventListener("touchend",this.touchEndListener),this.clickListener&&document.removeEventListener("click",this.clickListener),this.tapTimeout&&clearTimeout(this.tapTimeout),this.dblClickListener=void 0,this.touchEndListener=void 0,this.clickListener=void 0,this.tapTimeout=void 0,this.tapCount=0}}function j(){if(document.querySelector("#assistant-styles")){console.log("Styles already injected");return}const t=document.createElement("style");t.id="assistant-styles",t.innerHTML=`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("react/jsx-runtime"),S=require("react"),O={};function B(){return E.jsx("div",{className:O.container,children:E.jsx("h1",{children:"Welcome to ReactWrapper!"})})}class ${constructor(t){this.endpoint=t||"https://foisit-ninja.netlify.app/.netlify/functions/intent"}async determineIntent(t,e,i){try{const s={userInput:t,commands:e.map(o=>({id:o.id,command:o.command,description:o.description,parameters:o.parameters})),context:i},n=await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!n.ok)throw new Error(`Proxy API Error: ${n.statusText}`);return await n.json()}catch(s){return console.error("OpenAIService Error:",s),{type:"unknown"}}}}class N{constructor(t=!0){if(this.commands=new Map,this.openAIService=null,this.context=null,this.pendingConfirmation=null,this.enableSmartIntent=!0,this.selectOptionsCache=new Map,typeof t=="boolean"){this.enableSmartIntent=t,this.enableSmartIntent&&(this.openAIService=new $);return}this.enableSmartIntent=t.enableSmartIntent??!0,this.enableSmartIntent&&(this.openAIService=new $(t.intentEndpoint))}addCommand(t,e){let i;if(typeof t=="string"){if(!e)throw new Error("Action required when adding command by string.");i={id:t.toLowerCase().replace(/\s+/g,"_"),command:t.toLowerCase(),action:e}}else i={...t},i.id||(i.id=i.command.toLowerCase().replace(/\s+/g,"_"));this.commands.set(i.command.toLowerCase(),i),i.id&&(i.id,i.command)}removeCommand(t){this.commands.delete(t.toLowerCase())}async executeCommand(t){if(typeof t=="object"&&t!==null){if(this.isStructured(t)){const c=String(t.commandId),u=t.params??{},r=this.getCommandById(c);if(!r)return{message:"That command is not available.",type:"error"};const p=this.sanitizeParamsForCommand(r,u),m=(r.parameters??[]).filter(C=>C.required).filter(C=>p[C.name]==null||p[C.name]==="");return m.length>0?(this.context={commandId:this.getCommandIdentifier(r),params:p},{message:`Please provide the required details for "${r.command}".`,type:"form",fields:m}):r.critical?(this.pendingConfirmation={commandId:this.getCommandIdentifier(r),params:p},this.buildConfirmResponse(r)):this.safeRunAction(r,p)}if(!this.context)return{message:"Session expired or invalid context.",type:"error"};const n=this.getCommandById(this.context.commandId);if(!n)return this.context=null,{message:"Session expired or invalid context.",type:"error"};if(Array.isArray(t))return{message:"Invalid form payload.",type:"error"};const a={...this.context.params,...t};if(n.critical)return this.context=null,this.pendingConfirmation={commandId:this.getCommandIdentifier(n),params:a},this.buildConfirmResponse(n);const o=await this.safeRunAction(n,a);return this.context=null,this.normalizeResponse(o)}const e=t.trim().toLowerCase();if(this.pendingConfirmation){const n=e;if(["yes","y","confirm","ok","okay"].includes(n)){const{commandId:a,params:o}=this.pendingConfirmation;this.pendingConfirmation=null;const c=this.getCommandById(a);return c?this.safeRunAction(c,o):{message:"That action is no longer available.",type:"error"}}return["no","n","cancel","stop"].includes(n)?(this.pendingConfirmation=null,{message:"Cancelled.",type:"success"}):{message:"Please confirm: Yes or No.",type:"confirm",options:[{label:"Yes",value:"yes"},{label:"No",value:"no"}]}}const i=this.commands.get(e);if(i){const n=i;if(n.macro)return this.safeRunAction(n,{});const a=(n.parameters??[]).filter(o=>o.required);return a.length>0?(this.context={commandId:this.getCommandIdentifier(n),params:{}},{message:`Please provide the required details for "${n.command}".`,type:"form",fields:a}):n.critical?(this.pendingConfirmation={commandId:this.getCommandIdentifier(n),params:{}},this.buildConfirmResponse(n)):this.safeRunAction(n,{})}const s=await this.tryDeterministicMatch(e);if(s)return s;if(this.enableSmartIntent&&this.openAIService){const n=await this.getCommandsForAI(),a=await this.openAIService.determineIntent(e,n,this.context);return this.handleAIResult(a)}return this.enableSmartIntent?this.listAllCommands():{message:"I'm not sure what you mean.",type:"error"}}async handleAIResult(t){if(t.type==="match"&&t.match){const e=this.getCommandById(t.match);if(!e)return{message:"I'm not sure what you mean.",type:"error"};if(e.macro)return this.safeRunAction(e,{});const i=t.params??{},s=this.sanitizeParamsForCommand(e,i),n=e.allowAiParamExtraction===!1?{}:s,o=(e.parameters??[]).filter(u=>u.required).filter(u=>n[u.name]==null||n[u.name]==="");if(t.incomplete||o.length>0){if(this.context={commandId:this.getCommandIdentifier(e),params:n},!(e.collectRequiredViaForm!==!1)&&this.shouldAskSingleQuestion(o)){const p=o.map(g=>g.name).join(" and ");return{message:t.message||`Please provide ${p}.`,type:"question"}}return{message:t.message||`Please fill in the missing details for "${e.command}".`,type:"form",fields:o}}if(e.critical)return this.pendingConfirmation={commandId:this.getCommandIdentifier(e),params:n},this.buildConfirmResponse(e);const c=await e.action(n);return this.normalizeResponse(c)}return t.type==="ambiguous"&&t.options&&t.options.length?{message:t.message||"Did you mean one of these?",type:"ambiguous",options:t.options.map(e=>({label:e.label,value:e.commandId??e.label,commandId:e.commandId}))}:this.listAllCommands()}sanitizeParamsForCommand(t,e){const i={...e??{}};for(const s of t.parameters??[]){const n=i[s.name];if(s.type==="string"){if(typeof n!="string"){delete i[s.name];continue}const a=n.trim();if(!a){delete i[s.name];continue}i[s.name]=a}if(s.type==="number"){const a=typeof n=="number"?n:Number(n==null?void 0:n.toString().trim());if(Number.isNaN(a)){delete i[s.name];continue}if(typeof s.min=="number"&&a<s.min){delete i[s.name];continue}if(typeof s.max=="number"&&a>s.max){delete i[s.name];continue}i[s.name]=a}if(s.type==="date"){const a=i[s.name];if(typeof a=="string"){const o=a.trim();this.isIsoDateString(o)?i[s.name]=o:delete i[s.name]}else delete i[s.name]}if(s.type==="select"){const a=typeof n=="string"?n:n==null?void 0:n.toString();if(!a){delete i[s.name];continue}if(Array.isArray(s.options)&&s.options.length>0&&!s.options.some(c=>String(c.value)===String(a))){delete i[s.name];continue}i[s.name]=a}if(s.type==="file"){const a=i[s.name],o=a&&typeof a=="object"&&typeof a.name=="string"&&typeof a.size=="number",c=typeof a=="string"&&/^data:[^;]+;base64,/.test(a);(s.delivery??"file")==="base64"?!c&&!o&&delete i[s.name]:o||delete i[s.name]}}return i}isIsoDateString(t){if(!/^\d{4}-\d{2}-\d{2}$/.test(t))return!1;const e=new Date(`${t}T00:00:00Z`);return!Number.isNaN(e.getTime())}shouldAskSingleQuestion(t){if(t.length!==1)return!1;const e=t[0].type;return e==="string"||e==="number"||e==="date"}buildConfirmResponse(t){return{message:`Are you sure you want to run "${t.command}"?`,type:"confirm",options:[{label:"Yes",value:"yes"},{label:"No",value:"no"}]}}async tryDeterministicMatch(t){const e=[];for(const o of this.commands.values()){let c=0;const u=o.command.toLowerCase();t.includes(u)&&(c+=5);const r=o.keywords??[];for(const p of r){const g=p.toLowerCase().trim();g&&(t===g?c+=4:t.includes(g)&&(c+=3))}c>0&&e.push({cmd:o,score:c})}if(e.length===0)return null;e.sort((o,c)=>c.score-o.score);const i=e[0].score,s=e.filter(o=>o.score===i).slice(0,3);if(s.length>1)return{message:"I think you mean one of these. Which one should I run?",type:"ambiguous",options:s.map(o=>({label:o.cmd.command,value:o.cmd.command,commandId:o.cmd.id}))};const n=s[0].cmd,a=(n.parameters??[]).filter(o=>o.required);return a.length>0?(this.context={commandId:this.getCommandIdentifier(n),params:{}},{message:`Please provide the required details for "${n.command}".`,type:"form",fields:a}):n.critical?(this.pendingConfirmation={commandId:this.getCommandIdentifier(n),params:{}},this.buildConfirmResponse(n)):this.safeRunAction(n,{})}async safeRunAction(t,e){try{const i=await t.action(e??{});return this.normalizeResponse(i)}catch{return{message:"Something went wrong while running that command.",type:"error"}}}async getCommandsForAI(){const t=Array.from(this.commands.values()).map(e=>({...e,parameters:e.parameters?e.parameters.map(i=>({...i})):void 0}));return await Promise.all(t.map(async e=>{e.parameters&&await Promise.all(e.parameters.map(async i=>{if(i.type!=="select"||!i.getOptions||i.options&&i.options.length)return;const s=`${e.id??e.command}:${i.name}`,n=this.selectOptionsCache.get(s),a=Date.now();if(n&&a-n.ts<6e4){i.options=n.options;return}try{const o=await i.getOptions();this.selectOptionsCache.set(s,{options:o,ts:a}),i.options=o}catch{}}))})),t}getCommandById(t){for(const e of this.commands.values())if(e.id===t)return e}listAllCommands(){return{message:"Here are the available commands:",type:"ambiguous",options:Array.from(this.commands.values()).map(e=>({label:e.command,value:e.id??e.command,commandId:e.id??e.command}))}}normalizeResponse(t){return typeof t=="string"?{message:t,type:"success"}:t&&typeof t=="object"?t:{message:"Done",type:"success"}}isStructured(t){return typeof t.commandId=="string"}getCommandIdentifier(t){return t.id||(t.id=t.command.toLowerCase().replace(/\s+/g,"_")),t.id}getCommands(){return Array.from(this.commands.keys())}}class P{constructor(){this.synth=typeof window<"u"?window.speechSynthesis:null}speak(t,e){if(!this.synth){console.error("SpeechSynthesis API is not supported in this environment.");return}const i=new SpeechSynthesisUtterance(t);e&&(i.pitch=e.pitch||1,i.rate=e.rate||1,i.volume=e.volume||1),typeof window<"u"&&(i.onstart=()=>{window.dispatchEvent(new CustomEvent("foisit:tts-start"))},i.onend=()=>{console.log("Speech finished."),window.dispatchEvent(new CustomEvent("foisit:tts-end"))}),i.onerror=s=>{console.error("Error during speech synthesis:",s.error)},this.synth.speak(i)}stopSpeaking(){this.synth&&this.synth.cancel()}}class z{constructor(){this.fallbackMessage="Sorry, I didn’t understand that."}setFallbackMessage(t){this.fallbackMessage=t}handleFallback(t){t&&console.log(`Fallback triggered for: "${t}"`),console.log(this.fallbackMessage),new P().speak(this.fallbackMessage)}getFallbackMessage(){return this.fallbackMessage}}const H=()=>{if(typeof window>"u")return null;const d=window;return d.SpeechRecognition??d.webkitSpeechRecognition??null};class W{constructor(t="en-US",e={}){this.recognition=null,this.isListening=!1,this.engineActive=!1,this.intentionallyStopped=!1,this.restartAllowed=!0,this.lastStart=0,this.backoffMs=250,this.destroyed=!1,this.resultCallback=null,this.ttsSpeaking=!1,this.debugEnabled=!0,this.restartTimer=null,this.prewarmed=!1,this.hadResultThisSession=!1,this.onTTSStart=()=>{var s;this.ttsSpeaking=!0;try{(s=this.recognition)==null||s.stop()}catch{}this.isListening&&this.emitStatus("speaking")},this.onTTSEnd=()=>{this.ttsSpeaking=!1,this.isListening&&this.restartAllowed?this.safeRestart():this.emitStatus(this.isListening?"listening":"idle")};const i=H();if(i){this.recognition=new i,this.recognition.lang=t,this.recognition.interimResults=e.interimResults??!0,this.recognition.continuous=e.continuous??!0,this.recognition.onresult=n=>this.handleResult(n,e),this.recognition.onend=()=>this.handleEnd(),this.recognition.onstart=()=>{this.log("recognition onstart"),this.engineActive=!0,this.hadResultThisSession=!1,this.restartTimer&&(clearTimeout(this.restartTimer),this.restartTimer=null),this.backoffMs=250,this.isListening&&!this.ttsSpeaking&&this.emitStatus("listening")};const s=this.recognition;s.onaudiostart=()=>this.log("onaudiostart"),s.onsoundstart=()=>this.log("onsoundstart"),s.onspeechstart=()=>this.log("onspeechstart"),s.onspeechend=()=>this.log("onspeechend"),s.onsoundend=()=>this.log("onsoundend"),s.onaudioend=()=>this.log("onaudioend"),this.recognition.onerror=n=>this.handleError(n)}else this.recognition=null,this.emitStatus("unsupported");typeof window<"u"?(window.addEventListener("foisit:tts-start",this.onTTSStart),window.addEventListener("foisit:tts-end",this.onTTSEnd),this.visibilityHandler=()=>{var s;if(typeof document<"u"&&document.hidden){try{(s=this.recognition)==null||s.stop()}catch{}this.emitStatus(this.ttsSpeaking?"speaking":"idle")}else this.isListening&&!this.ttsSpeaking&&this.safeRestart()},typeof document<"u"&&document.addEventListener("visibilitychange",this.visibilityHandler)):this.visibilityHandler=void 0}log(t){this.debugEnabled&&t&&console.log("[VoiceProcessor]",t)}warn(t){this.debugEnabled&&t&&console.warn("[VoiceProcessor]",t)}error(t){this.debugEnabled&&t&&console.error("[VoiceProcessor]",t)}isSupported(){return H()!==null}onStatusChange(t){this.statusCallback=t}startListening(t){if(!this.isSupported()||!this.recognition){this.warn("VoiceProcessor: SpeechRecognition is not supported in this browser."),this.emitStatus("unsupported");return}if(this.isListening){this.warn("VoiceProcessor: Already listening."),this.resultCallback=t;return}this.resultCallback=t,this.intentionallyStopped=!1,this.restartAllowed=!0,this.isListening=!0,this.emitStatus("listening"),this.prewarmAudio().finally(()=>{this.safeRestart()})}stopListening(){var t;this.intentionallyStopped=!0,this.restartAllowed=!1,this.isListening=!1,this.emitStatus(this.ttsSpeaking?"speaking":"idle");try{(t=this.recognition)==null||t.stop()}catch{}}destroy(){this.destroyed=!0,this.stopListening(),this.resultCallback=null,window.removeEventListener("foisit:tts-start",this.onTTSStart),window.removeEventListener("foisit:tts-end",this.onTTSEnd),this.visibilityHandler&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=void 0)}handleResult(t,e){var s,n;if(!this.resultCallback)return;const i=e.confidenceThreshold??.6;for(let a=t.resultIndex;a<t.results.length;a++){const o=t.results[a],c=o&&o[0],u=((n=(s=c==null?void 0:c.transcript)==null?void 0:s.trim)==null?void 0:n.call(s))||"",r=(c==null?void 0:c.confidence)??0;if(u&&!(!o.isFinal&&e.interimResults===!1)&&!(o.isFinal&&r<i))try{this.hadResultThisSession=!0,this.resultCallback(u,!!o.isFinal)}catch{this.error("VoiceProcessor: result callback error")}}}handleEnd(){if(this.log("recognition onend"),this.engineActive=!1,this.destroyed||this.intentionallyStopped||!this.restartAllowed||this.ttsSpeaking){this.ttsSpeaking||(this.isListening=!1,this.emitStatus("idle"));return}this.isListening=!0,this.scheduleRestart()}handleError(t){const e=t==null?void 0:t.error;if(this.warn(`Error occurred: ${e??"unknown"}`),e&&["not-allowed","service-not-allowed","bad-grammar","language-not-supported"].includes(e)){this.intentionallyStopped=!0,this.restartAllowed=!1,this.isListening=!1,this.emitStatus("error",{error:e});return}this.scheduleRestart()}safeRestart(){if(!this.recognition)return;if(this.engineActive){this.log("safeRestart: engine already active, skipping start");return}const t=Date.now();if(t-this.lastStart<300){setTimeout(()=>this.safeRestart(),300);return}this.lastStart=t;try{this.log("calling recognition.start()"),this.recognition.start(),this.backoffMs=250,this.isListening&&!this.ttsSpeaking&&this.emitStatus("listening")}catch{this.error("recognition.start() threw; scheduling restart"),this.scheduleRestart()}}scheduleRestart(){if(this.destroyed||this.intentionallyStopped||!this.restartAllowed||this.ttsSpeaking)return;if(this.engineActive){this.log("scheduleRestart: engine active, not scheduling");return}const t=Math.min(this.backoffMs,2e3);if(this.log(`scheduleRestart in ${t}ms`),this.restartTimer){this.log("scheduleRestart: restart already scheduled");return}this.restartTimer=setTimeout(()=>{this.restartTimer=null,!(this.destroyed||this.intentionallyStopped||!this.restartAllowed||this.ttsSpeaking)&&this.safeRestart()},t),this.backoffMs=Math.min(this.backoffMs*2,2e3)}async prewarmAudio(){if(!this.prewarmed)try{if(typeof navigator>"u"||!("mediaDevices"in navigator))return;const t=navigator.mediaDevices;if(!(t!=null&&t.getUserMedia))return;this.log("prewarmAudio: requesting mic");const e=await t.getUserMedia({audio:!0});for(const i of e.getTracks())i.stop();this.prewarmed=!0,this.log("prewarmAudio: mic ready")}catch{this.warn("prewarmAudio: failed to get mic")}}emitStatus(t,e){if(this.statusCallback)try{this.statusCallback(t,e)}catch{this.error("VoiceProcessor: status callback error")}}}class R{constructor(){this.lastTap=0,this.tapCount=0}setupTripleTapListener(t){this.destroy(),this.clickListener=()=>{this.tapCount++,this.tapCount===1?this.tapTimeout=window.setTimeout(()=>{this.tapCount=0},500):this.tapCount===3&&(clearTimeout(this.tapTimeout),this.tapCount=0,t())},document.addEventListener("click",this.clickListener),this.touchEndListener=()=>{const e=new Date().getTime(),i=e-this.lastTap;i<500&&i>0?(this.tapCount++,this.tapCount===3&&(this.tapCount=0,t())):this.tapCount=1,this.lastTap=e},document.addEventListener("touchend",this.touchEndListener)}destroy(){this.dblClickListener&&document.removeEventListener("dblclick",this.dblClickListener),this.touchEndListener&&document.removeEventListener("touchend",this.touchEndListener),this.clickListener&&document.removeEventListener("click",this.clickListener),this.tapTimeout&&clearTimeout(this.tapTimeout),this.dblClickListener=void 0,this.touchEndListener=void 0,this.clickListener=void 0,this.tapTimeout=void 0,this.tapCount=0}}function j(){if(document.querySelector("#assistant-styles")){console.log("Styles already injected");return}const t=document.createElement("style");t.id="assistant-styles",t.innerHTML=`
2
2
  /* Rounded shape with gradient animation */
3
3
  .gradient-indicator {
4
4
  position: fixed;
@@ -31,57 +31,86 @@
31
31
  border-radius: 50%;
32
32
  }
33
33
  }
34
- `,document.head.appendChild(t),console.log("Gradient styles injected")}function U(){if(document.querySelector("#gradient-indicator"))return;const d=document.createElement("div");d.id="gradient-indicator",j(),d.classList.add("gradient-indicator"),document.body.appendChild(d),console.log("Gradient indicator added to the DOM")}function D(){const d=document.querySelector("#gradient-indicator");d&&(d.remove(),console.log("Gradient indicator removed from the DOM"))}function V(){return typeof window<"u"&&typeof document<"u"}class _{constructor(){this.state="idle",this.subscribers=[]}getState(){return this.state}setState(t){this.state=t,this.notifySubscribers(),console.log("State updated:",t),t==="listening"?U():D()}subscribe(t){this.subscribers.push(t)}notifySubscribers(){this.subscribers.forEach(t=>t(this.state))}}class G{constructor(t){this.container=null,this.chatWindow=null,this.messagesContainer=null,this.input=null,this.isOpen=!1,this.loadingEl=null,this.commandHandlers=new Map,this.active=V(),this.handleClickOutside=e=>{const i=e.target;this.chatWindow&&this.chatWindow.contains(i)||i.closest(".foisit-floating-btn")||this.toggle()},this.config=t,this.active&&this.init()}registerCommandHandler(t,e){!t||typeof e!="function"||this.commandHandlers.set(t,e)}hasCommandHandler(t){return this.commandHandlers.has(t)}setExternalCommandExecutor(t){this.externalCommandExecutor=t}unregisterCommandHandler(t){t&&this.commandHandlers.delete(t)}async runCommand(t){if(!t||!t.commandId)throw new Error("runCommand requires a commandId");const{commandId:e,params:i,openOverlay:s=!0,showInvocation:n=!0}=t;s&&!this.isOpen&&this.toggle();const a=this.commandHandlers.get(e);if(a&&n&&this.messagesContainer&&this.addMessage(`Command: ${e}`,"user"),a)try{this.showLoading();const o=await a(i);if(this.hideLoading(),typeof o=="string")this.addMessage(o,"system");else if(o&&typeof o=="object")try{this.addMessage(JSON.stringify(o,null,2),"system")}catch{this.addMessage(String(o),"system")}else o==null||this.addMessage(String(o),"system");return o}catch(o){throw this.hideLoading(),this.addMessage(`Command "${e}" failed: ${String(o)}`,"system"),o}if(this.externalCommandExecutor)try{this.showLoading();const o=await this.externalCommandExecutor({commandId:e,params:i});return this.hideLoading(),o}catch(o){throw this.hideLoading(),this.addMessage(`Command "${e}" failed: ${String(o)}`,"system"),o}this.addMessage(`No handler registered for command "${e}".`,"system")}init(){var e,i;if(this.container)return;this.injectOverlayStyles();const t=document.getElementById("foisit-overlay-container");if(t&&t instanceof HTMLElement){this.container=t,this.chatWindow=t.querySelector(".foisit-chat"),this.messagesContainer=t.querySelector(".foisit-messages"),this.input=t.querySelector("input.foisit-input"),((e=this.config.floatingButton)==null?void 0:e.visible)!==!1&&!t.querySelector(".foisit-floating-btn")&&this.renderFloatingButton(),this.chatWindow||this.renderChatWindow(),this.config.enableGestureActivation&&(this.gestureHandler=new R,this.gestureHandler.setupTripleTapListener(()=>this.toggle()));return}this.container=document.createElement("div"),this.container.id="foisit-overlay-container",this.container.className="foisit-overlay-container",document.body.appendChild(this.container),((i=this.config.floatingButton)==null?void 0:i.visible)!==!1&&this.renderFloatingButton(),this.renderChatWindow(),this.config.enableGestureActivation&&(this.gestureHandler=new R,this.gestureHandler.setupTripleTapListener(()=>this.toggle()))}renderFloatingButton(){var s,n,a,o,c,f;const t=document.createElement("button");t.innerHTML=((s=this.config.floatingButton)==null?void 0:s.customHtml)||"🎙️";const e=((a=(n=this.config.floatingButton)==null?void 0:n.position)==null?void 0:a.bottom)||"20px",i=((c=(o=this.config.floatingButton)==null?void 0:o.position)==null?void 0:c.right)||"20px";t.className="foisit-floating-btn",t.style.bottom=e,t.style.right=i,t.onclick=()=>this.toggle(),t.onmouseenter=()=>t.style.transform="scale(1.05)",t.onmouseleave=()=>t.style.transform="scale(1)",(f=this.container)==null||f.appendChild(t)}renderChatWindow(){var n;if(this.chatWindow)return;this.chatWindow=document.createElement("div"),this.chatWindow.className="foisit-chat";const t=document.createElement("div");t.className="foisit-header";const e=document.createElement("span");e.className="foisit-title",e.textContent="Foisit";const i=document.createElement("button");i.type="button",i.className="foisit-close",i.setAttribute("aria-label","Close"),i.innerHTML="&times;",i.addEventListener("click",()=>this.toggle()),t.appendChild(e),t.appendChild(i),this.messagesContainer=document.createElement("div"),this.messagesContainer.className="foisit-messages";const s=document.createElement("div");s.className="foisit-input-area",this.input=document.createElement("input"),this.input.placeholder=this.config.inputPlaceholder||"Type a command...",this.input.className="foisit-input",this.input.addEventListener("keydown",a=>{var o;if(a.key==="Enter"&&((o=this.input)!=null&&o.value.trim())){const c=this.input.value.trim();this.input.value="",this.onSubmit&&this.onSubmit(c)}}),s.appendChild(this.input),this.chatWindow.appendChild(t),this.chatWindow.appendChild(this.messagesContainer),this.chatWindow.appendChild(s),(n=this.container)==null||n.appendChild(this.chatWindow)}registerCallbacks(t,e){this.active&&(this.onSubmit=t,this.onClose=e)}toggle(t,e){this.active&&(t&&(this.onSubmit=t),e&&(this.onClose=e),this.isOpen=!this.isOpen,this.chatWindow&&(this.isOpen?(this.container&&(this.container.style.pointerEvents="auto"),this.chatWindow.style.display="flex",requestAnimationFrame(()=>{this.chatWindow&&(this.chatWindow.style.opacity="1",this.chatWindow.style.transform="translateY(0) scale(1)")}),setTimeout(()=>{var i;return(i=this.input)==null?void 0:i.focus()},100),this.addClickOutsideListener()):(this.chatWindow.style.opacity="0",this.chatWindow.style.transform="translateY(20px) scale(0.95)",setTimeout(()=>{this.chatWindow&&!this.isOpen&&(this.chatWindow.style.display="none")},200),this.onClose&&this.onClose(),this.removeClickOutsideListener(),this.container&&(this.container.style.pointerEvents="none"))))}addClickOutsideListener(){this.container&&(this.removeClickOutsideListener(),this.container.addEventListener("click",this.handleClickOutside))}removeClickOutsideListener(){this.container&&this.container.removeEventListener("click",this.handleClickOutside)}addMessage(t,e){if(!this.messagesContainer)return;const i=document.createElement("div");e==="system"?i.innerHTML=this.renderMarkdown(t):i.textContent=t,i.className=e==="user"?"foisit-bubble user":"foisit-bubble system";const s=(t||"").length||0,n=Math.max(120,700-Math.min(600,Math.floor(s*6)));i.style.opacity="0",i.style.transform="translateY(8px)",i.style.transition="none",this.messagesContainer.appendChild(i),this.animateMessageEntrance(i,n),this.scrollToBottom()}addOptions(t){if(!this.messagesContainer)return;const e=document.createElement("div");e.className="foisit-options-container",t.forEach(i=>{const s=document.createElement("button");s.textContent=i.label,s.className="foisit-option-chip",s.setAttribute("type","button"),s.setAttribute("aria-label",i.label);const n=()=>{if(i.commandId){this.onSubmit&&this.onSubmit({commandId:i.commandId});return}const a=i&&typeof i.value=="string"&&i.value.trim()?i.value:i.label;this.onSubmit&&this.onSubmit(a)};s.onclick=n,s.onkeydown=a=>{(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),n())},e.appendChild(s)}),this.messagesContainer.appendChild(e),this.scrollToBottom()}addForm(t,e,i){if(!this.messagesContainer)return;this.addMessage(t,"system");const s=document.createElement("form");s.className="foisit-form";const n=[],a=(r,p)=>{const g=document.createElement("div");return g.className="foisit-form-label",g.innerHTML=r+(p?' <span class="foisit-req-star">*</span>':""),g},o=()=>{const r=document.createElement("div");return r.className="foisit-form-error",r.style.display="none",r};(e??[]).forEach(r=>{const p=document.createElement("div");p.className="foisit-form-group";const g=r.description||r.name;p.appendChild(a(g,r.required));let m;if(r.type==="select"){const l=document.createElement("select");l.className="foisit-form-input";const y=document.createElement("option");y.value="",y.textContent="Select...",l.appendChild(y);const w=h=>{(h??[]).forEach(x=>{const b=document.createElement("option");b.value=String(x.value??x.label??""),b.textContent=String(x.label??x.value??""),l.appendChild(b)})};if(Array.isArray(r.options)&&r.options.length)w(r.options);else if(typeof r.getOptions=="function"){const h=r.getOptions,x=document.createElement("option");x.value="",x.textContent="Loading...",l.appendChild(x),Promise.resolve().then(()=>h()).then(b=>{for(;l.options.length>1;)l.remove(1);w(b)}).catch(()=>{for(;l.options.length>1;)l.remove(1);const b=document.createElement("option");b.value="",b.textContent="Error loading options",l.appendChild(b)})}r.defaultValue!=null&&(l.value=String(r.defaultValue)),m=l}else if(r.type==="file"){const l=r,y=document.createElement("input");y.className="foisit-form-input",y.type="file",l.accept&&Array.isArray(l.accept)&&(y.accept=l.accept.join(",")),l.multiple&&(y.multiple=!0),l.capture&&(l.capture===!0?y.setAttribute("capture",""):y.setAttribute("capture",String(l.capture))),y.addEventListener("change",async()=>{const w=Array.from(y.files||[]),h=C;if(h.style.display="none",h.textContent="",w.length===0)return;const x=l.maxFiles??(l.multiple?10:1);if(w.length>x){h.textContent=`Please select at most ${x} file(s).`,h.style.display="block";return}const b=l.maxSizeBytes??1/0,u=w.reduce((v,A)=>v+A.size,0);if(w.some(v=>v.size>b)){h.textContent=`One or more files exceed the maximum size of ${Math.round(b/1024)} KB.`,h.style.display="block";return}const k=l.maxTotalBytes??1/0;if(u>k){h.textContent=`Total selected files exceed the maximum of ${Math.round(k/1024)} KB.`,h.style.display="block";return}if(l.accept&&Array.isArray(l.accept)){const v=l.accept;if(!w.every(L=>L.type?v.some(M=>M.startsWith(".")?L.name.toLowerCase().endsWith(M.toLowerCase()):L.type===M||L.type.startsWith(M.split("/")[0]+"/")):!0)){h.textContent="One or more files have an unsupported type.",h.style.display="block";return}}}),m=y}else{const l=document.createElement("input");l.className="foisit-form-input",r.type==="string"&&(l.placeholder=r.placeholder||"Type here..."),r.type==="number"?(l.type="number",typeof r.min=="number"&&(l.min=String(r.min)),typeof r.max=="number"&&(l.max=String(r.max)),typeof r.step=="number"&&(l.step=String(r.step)),r.defaultValue!=null&&(l.value=String(r.defaultValue))):r.type==="date"?(l.type="date",typeof r.min=="string"&&(l.min=r.min),typeof r.max=="string"&&(l.max=r.max),r.defaultValue!=null&&(l.value=String(r.defaultValue))):(l.type="text",r.defaultValue!=null&&(l.value=String(r.defaultValue))),m=l}const C=o();p.appendChild(m),p.appendChild(C),n.push({name:r.name,type:r.type,el:m,required:r.required}),s.appendChild(p)});const c=document.createElement("div");c.className="foisit-form-actions";const f=document.createElement("button");f.type="submit",f.textContent="Submit",f.className="foisit-option-chip",f.style.fontWeight="600",c.appendChild(f),s.appendChild(c),s.onsubmit=async r=>{r.preventDefault();const p={};let g=!1;s.querySelectorAll(".foisit-form-error").forEach(m=>{m.style.display="none",m.textContent=""}),s.querySelectorAll(".foisit-form-input").forEach(m=>{m.classList.remove("foisit-error-border")});for(const m of n){if(m.type==="file"){const w=m.el.parentElement,h=w==null?void 0:w.querySelector(".foisit-form-error"),x=m.el,b=Array.from(x.files||[]);if(m.required&&b.length===0){g=!0,x.classList.add("foisit-error-border"),h&&(h.textContent="This file is required",h.style.display="block");continue}if(b.length===0)continue;const u=(e??[]).find(v=>v.name===m.name),k=(u==null?void 0:u.delivery)??"file";if(u!=null&&u.maxWidth||u!=null&&u.maxHeight)try{const v=await this.getImageDimensions(b[0]);if(u.maxWidth&&v.width>u.maxWidth){g=!0,h&&(h.textContent=`Image width must be ≤ ${u.maxWidth}px`,h.style.display="block");continue}if(u.maxHeight&&v.height>u.maxHeight){g=!0,h&&(h.textContent=`Image height must be ≤ ${u.maxHeight}px`,h.style.display="block");continue}}catch{}if(u!=null&&u.maxDurationSec)try{const v=await this.getMediaDuration(b[0]);if(v&&v>u.maxDurationSec){g=!0,h&&(h.textContent=`Media duration must be ≤ ${u.maxDurationSec}s`,h.style.display="block");continue}}catch{}if(k==="file")p[m.name]=u!=null&&u.multiple?b:b[0];else if(k==="base64")try{const v=await Promise.all(b.map(A=>this.readFileAsDataURL(A)));p[m.name]=u!=null&&u.multiple?v:v[0]}catch{g=!0,h&&(h.textContent="Failed to encode file(s) to base64.",h.style.display="block");continue}continue}const C=(m.el.value??"").toString().trim(),l=m.el.parentElement,y=l==null?void 0:l.querySelector(".foisit-form-error");if(m.required&&(C==null||C==="")){g=!0,m.el.classList.add("foisit-error-border"),y&&(y.textContent="This field is required",y.style.display="block");continue}if(C!=="")if(m.type==="number"){const w=Number(C);Number.isNaN(w)||(p[m.name]=w)}else p[m.name]=C}if(g){s.classList.add("foisit-shake"),setTimeout(()=>s.classList.remove("foisit-shake"),400);return}f.disabled=!0,f.style.opacity="0.6",n.forEach(m=>{m.el.disabled=!0}),i(p)},this.messagesContainer.appendChild(s),this.scrollToBottom()}showLoading(){if(this.messagesContainer&&!this.loadingEl){this.loadingEl=document.createElement("div"),this.loadingEl.className="foisit-loading-dots foisit-bubble system";for(let t=0;t<3;t++){const e=document.createElement("div");e.className="foisit-dot",e.style.animation=`foisitPulse 1.4s infinite ease-in-out ${t*.2}s`,this.loadingEl.appendChild(e)}this.messagesContainer.appendChild(this.loadingEl),this.scrollToBottom()}}hideLoading(){var t;(t=this.loadingEl)==null||t.remove(),this.loadingEl=null}scrollToBottom(){this.messagesContainer&&(this.messagesContainer.scrollTop=this.messagesContainer.scrollHeight)}animateMessageEntrance(t,e){if(!t)return;t.style.transition=`opacity ${e}ms cubic-bezier(0.22, 0.9, 0.32, 1), transform ${Math.max(120,e)}ms cubic-bezier(0.22, 0.9, 0.32, 1)`,requestAnimationFrame(()=>{t.style.opacity="1",t.style.transform="translateY(0)"});const i=()=>{try{t.style.transition=""}catch{}t.removeEventListener("transitionend",i)};t.addEventListener("transitionend",i)}animateScrollToBottom(t){if(!this.messagesContainer)return;const e=this.messagesContainer,i=e.scrollTop,s=e.scrollHeight-e.clientHeight;if(s<=i||t<=0){e.scrollTop=s;return}const n=s-i,a=performance.now(),o=c=>{const f=Math.min(1,(c-a)/t),r=1-Math.pow(1-f,3);e.scrollTop=Math.round(i+n*r),f<1&&requestAnimationFrame(o)};requestAnimationFrame(o)}destroy(){var t;this.removeClickOutsideListener(),(t=this.container)==null||t.remove(),this.container=null,this.chatWindow=null,this.messagesContainer=null,this.input=null,this.isOpen=!1}escapeHtml(t){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"};return t.replace(/[&<>"']/g,i=>e[i])}renderMarkdown(t){let e=this.escapeHtml(t);return e=e.replace(/```(\w*)\n([\s\S]*?)```/g,(i,s,n)=>`<pre class="foisit-code-block"><code${s?` class="language-${s}"`:""}>${n.trim()}</code></pre>`),e=e.replace(/`([^`]+)`/g,'<code class="foisit-inline-code">$1</code>'),e=e.replace(/^###### (.+)$/gm,'<h6 class="foisit-md-h6">$1</h6>'),e=e.replace(/^##### (.+)$/gm,'<h5 class="foisit-md-h5">$1</h5>'),e=e.replace(/^#### (.+)$/gm,'<h4 class="foisit-md-h4">$1</h4>'),e=e.replace(/^### (.+)$/gm,'<h3 class="foisit-md-h3">$1</h3>'),e=e.replace(/^## (.+)$/gm,'<h2 class="foisit-md-h2">$1</h2>'),e=e.replace(/^# (.+)$/gm,'<h1 class="foisit-md-h1">$1</h1>'),e=e.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),e=e.replace(/__([^_]+)__/g,"<strong>$1</strong>"),e=e.replace(/\*([^*]+)\*/g,"<em>$1</em>"),e=e.replace(new RegExp("(?<!_)_([^_]+)_(?!_)","g"),"<em>$1</em>"),e=e.replace(/~~([^~]+)~~/g,"<del>$1</del>"),e=e.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer" class="foisit-md-link">$1</a>'),e=e.replace(/^[\-\*] (.+)$/gm,'<li class="foisit-md-li">$1</li>'),e=e.replace(/(<li class="foisit-md-li">.*<\/li>\n?)+/g,i=>`<ul class="foisit-md-ul">${i}</ul>`),e=e.replace(/^\d+\. (.+)$/gm,'<li class="foisit-md-li">$1</li>'),e=e.replace(new RegExp('(?<!<\\/ul>)(<li class="foisit-md-li">.*<\\/li>\\n?)+',"g"),i=>i.includes("<ul")?i:`<ol class="foisit-md-ol">${i}</ol>`),e=e.replace(/^&gt; (.+)$/gm,'<blockquote class="foisit-md-blockquote">$1</blockquote>'),e=e.replace(/^(---|___|\*\*\*)$/gm,'<hr class="foisit-md-hr">'),e=e.replace(/\n\n+/g,'</p><p class="foisit-md-p">'),e=e.replace(/\n/g,"<br>"),e.match(/^<(h[1-6]|ul|ol|pre|blockquote|hr|p)/)||(e=`<p class="foisit-md-p">${e}</p>`),e}readFileAsDataURL(t){return new Promise((e,i)=>{const s=new FileReader;s.onerror=()=>i(new Error("Failed to read file")),s.onload=()=>e(String(s.result)),s.readAsDataURL(t)})}getImageDimensions(t){return new Promise(e=>{try{const i=URL.createObjectURL(t),s=new Image;s.onload=()=>{const n={width:s.naturalWidth||s.width,height:s.naturalHeight||s.height};URL.revokeObjectURL(i),e(n)},s.onerror=()=>{URL.revokeObjectURL(i),e({width:0,height:0})},s.src=i}catch{e({width:0,height:0})}})}getMediaDuration(t){return new Promise(e=>{try{const i=URL.createObjectURL(t),s=t.type.startsWith("audio")?document.createElement("audio"):document.createElement("video");let n=!1;const a=setTimeout(()=>{n||(n=!0,URL.revokeObjectURL(i),e(0))},5e3);s.preload="metadata",s.onloadedmetadata=()=>{if(n)return;n=!0,clearTimeout(a);const c=s.duration||0;URL.revokeObjectURL(i),e(c)},s.onerror=()=>{n||(n=!0,clearTimeout(a),URL.revokeObjectURL(i),e(0))},s.src=i}catch{e(0)}})}injectOverlayStyles(){if(document.getElementById("foisit-overlay-styles"))return;const t=document.createElement("style");t.id="foisit-overlay-styles",t.textContent=`
35
- :root {
36
- /* LIGHT MODE (Default) - Smoother gradient */
37
- /* Changed: Softer, right-focused radial highlight to avoid a heavy white bottom */
38
- --foisit-bg: radial-gradient(ellipse at 75% 30%, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.03));
39
- --foisit-border: 1px solid rgba(255, 255, 255, 0.25);
40
- --foisit-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
41
- --foisit-text: #333;
42
-
43
- /* Input */
44
- --foisit-input-color: #333;
45
- --foisit-input-placeholder: rgba(60, 60, 67, 0.6);
34
+ `,document.head.appendChild(t),console.log("Gradient styles injected")}function U(){if(document.querySelector("#gradient-indicator"))return;const d=document.createElement("div");d.id="gradient-indicator",j(),d.classList.add("gradient-indicator"),document.body.appendChild(d),console.log("Gradient indicator added to the DOM")}function D(){const d=document.querySelector("#gradient-indicator");d&&(d.remove(),console.log("Gradient indicator removed from the DOM"))}function V(){return typeof window<"u"&&typeof document<"u"}class _{constructor(){this.state="idle",this.subscribers=[]}getState(){return this.state}setState(t){this.state=t,this.notifySubscribers(),console.log("State updated:",t),t==="listening"?U():D()}subscribe(t){this.subscribers.push(t)}notifySubscribers(){this.subscribers.forEach(t=>t(this.state))}}class G{constructor(t){this.container=null,this.chatWindow=null,this.messagesContainer=null,this.input=null,this.isOpen=!1,this.loadingEl=null,this.commandHandlers=new Map,this.active=V(),this.handleClickOutside=e=>{const i=e.target;this.chatWindow&&this.chatWindow.contains(i)||i.closest(".foisit-floating-btn")||this.toggle()},this.config=t,this.active&&this.init()}registerCommandHandler(t,e){!t||typeof e!="function"||this.commandHandlers.set(t,e)}hasCommandHandler(t){return this.commandHandlers.has(t)}setExternalCommandExecutor(t){this.externalCommandExecutor=t}unregisterCommandHandler(t){t&&this.commandHandlers.delete(t)}async runCommand(t){if(!t||!t.commandId)throw new Error("runCommand requires a commandId");const{commandId:e,params:i,openOverlay:s=!0,showInvocation:n=!0}=t;s&&!this.isOpen&&this.toggle();const a=this.commandHandlers.get(e);if(a&&n&&this.messagesContainer&&this.addMessage(`Command: ${e}`,"user"),a)try{this.showLoading();const o=await a(i);if(this.hideLoading(),typeof o=="string")this.addMessage(o,"system");else if(o&&typeof o=="object")try{this.addMessage(JSON.stringify(o,null,2),"system")}catch{this.addMessage(String(o),"system")}else o==null||this.addMessage(String(o),"system");return o}catch(o){throw this.hideLoading(),this.addMessage(`Command "${e}" failed: ${String(o)}`,"system"),o}if(this.externalCommandExecutor)try{this.showLoading();const o=await this.externalCommandExecutor({commandId:e,params:i});return this.hideLoading(),o}catch(o){throw this.hideLoading(),this.addMessage(`Command "${e}" failed: ${String(o)}`,"system"),o}this.addMessage(`No handler registered for command "${e}".`,"system")}init(){var e,i;if(this.container)return;this.injectOverlayStyles();const t=document.getElementById("foisit-overlay-container");if(t&&t instanceof HTMLElement){this.container=t,this.chatWindow=t.querySelector(".foisit-chat"),this.messagesContainer=t.querySelector(".foisit-messages"),this.input=t.querySelector("input.foisit-input"),((e=this.config.floatingButton)==null?void 0:e.visible)!==!1&&!t.querySelector(".foisit-floating-btn")&&this.renderFloatingButton(),this.chatWindow||this.renderChatWindow(),this.config.enableGestureActivation&&(this.gestureHandler=new R,this.gestureHandler.setupTripleTapListener(()=>this.toggle()));return}this.container=document.createElement("div"),this.container.id="foisit-overlay-container",this.container.className="foisit-overlay-container",document.body.appendChild(this.container),((i=this.config.floatingButton)==null?void 0:i.visible)!==!1&&this.renderFloatingButton(),this.renderChatWindow(),this.config.enableGestureActivation&&(this.gestureHandler=new R,this.gestureHandler.setupTripleTapListener(()=>this.toggle()))}renderFloatingButton(){var s,n,a,o,c,u;const t=document.createElement("button");t.innerHTML=((s=this.config.floatingButton)==null?void 0:s.customHtml)||"🎙️";const e=((a=(n=this.config.floatingButton)==null?void 0:n.position)==null?void 0:a.bottom)||"20px",i=((c=(o=this.config.floatingButton)==null?void 0:o.position)==null?void 0:c.right)||"20px";t.className="foisit-floating-btn",t.style.bottom=e,t.style.right=i,t.onclick=()=>this.toggle(),t.onmouseenter=()=>t.style.transform="scale(1.05)",t.onmouseleave=()=>t.style.transform="scale(1)",(u=this.container)==null||u.appendChild(t)}renderChatWindow(){var n;if(this.chatWindow)return;this.chatWindow=document.createElement("div"),this.chatWindow.className="foisit-chat";const t=document.createElement("div");t.className="foisit-header";const e=document.createElement("span");e.className="foisit-title",e.textContent="Foisit";const i=document.createElement("button");i.type="button",i.className="foisit-close",i.setAttribute("aria-label","Close"),i.innerHTML="&times;",i.addEventListener("click",()=>this.toggle()),t.appendChild(e),t.appendChild(i),this.messagesContainer=document.createElement("div"),this.messagesContainer.className="foisit-messages";const s=document.createElement("div");s.className="foisit-input-area",this.input=document.createElement("input"),this.input.placeholder=this.config.inputPlaceholder||"Type a command...",this.input.className="foisit-input",this.input.addEventListener("keydown",a=>{var o;if(a.key==="Enter"&&((o=this.input)!=null&&o.value.trim())){const c=this.input.value.trim();this.input.value="",this.onSubmit&&this.onSubmit(c)}}),s.appendChild(this.input),this.chatWindow.appendChild(t),this.chatWindow.appendChild(this.messagesContainer),this.chatWindow.appendChild(s),(n=this.container)==null||n.appendChild(this.chatWindow)}registerCallbacks(t,e){this.active&&(this.onSubmit=t,this.onClose=e)}toggle(t,e){this.active&&(t&&(this.onSubmit=t),e&&(this.onClose=e),this.isOpen=!this.isOpen,this.chatWindow&&(this.isOpen?(this.container&&(this.container.style.pointerEvents="auto"),this.chatWindow.style.display="flex",requestAnimationFrame(()=>{this.chatWindow&&(this.chatWindow.style.opacity="1",this.chatWindow.style.transform="translateY(0) scale(1)")}),setTimeout(()=>{var i;return(i=this.input)==null?void 0:i.focus()},100),this.addClickOutsideListener()):(this.chatWindow.style.opacity="0",this.chatWindow.style.transform="translateY(20px) scale(0.95)",setTimeout(()=>{this.chatWindow&&!this.isOpen&&(this.chatWindow.style.display="none")},200),this.onClose&&this.onClose(),this.removeClickOutsideListener(),this.container&&(this.container.style.pointerEvents="none"))))}addClickOutsideListener(){this.container&&(this.removeClickOutsideListener(),this.container.addEventListener("click",this.handleClickOutside))}removeClickOutsideListener(){this.container&&this.container.removeEventListener("click",this.handleClickOutside)}addMessage(t,e){if(!this.messagesContainer)return;const i=document.createElement("div");e==="system"?i.innerHTML=this.renderMarkdown(t):i.textContent=t,i.className=e==="user"?"foisit-bubble user":"foisit-bubble system";const s=(t||"").length||0,n=Math.max(120,700-Math.min(600,Math.floor(s*6)));i.style.opacity="0",i.style.transform="translateY(8px)",i.style.transition="none",this.messagesContainer.appendChild(i),this.animateMessageEntrance(i,n),this.scrollToBottom()}addOptions(t){if(!this.messagesContainer)return;const e=document.createElement("div");e.className="foisit-options-container",t.forEach(i=>{const s=document.createElement("button");s.textContent=i.label,s.className="foisit-option-chip",s.setAttribute("type","button"),s.setAttribute("aria-label",i.label);const n=()=>{if(i.commandId){this.onSubmit&&this.onSubmit({commandId:i.commandId});return}const a=i&&typeof i.value=="string"&&i.value.trim()?i.value:i.label;this.onSubmit&&this.onSubmit(a)};s.onclick=n,s.onkeydown=a=>{(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),n())},e.appendChild(s)}),this.messagesContainer.appendChild(e),this.scrollToBottom()}addForm(t,e,i){if(!this.messagesContainer)return;this.addMessage(t,"system");const s=document.createElement("form");s.className="foisit-form";const n=[],a=(r,p)=>{const g=document.createElement("div");return g.className="foisit-form-label",g.innerHTML=r+(p?' <span class="foisit-req-star">*</span>':""),g},o=()=>{const r=document.createElement("div");return r.className="foisit-form-error",r.style.display="none",r};(e??[]).forEach(r=>{const p=document.createElement("div");p.className="foisit-form-group";const g=r.description||r.name;p.appendChild(a(g,r.required));let m;if(r.type==="select"){const l=document.createElement("select");l.className="foisit-form-input";const y=document.createElement("option");y.value="",y.textContent="Select...",l.appendChild(y);const x=h=>{(h??[]).forEach(w=>{const b=document.createElement("option");b.value=String(w.value??w.label??""),b.textContent=String(w.label??w.value??""),l.appendChild(b)})};if(Array.isArray(r.options)&&r.options.length)x(r.options);else if(typeof r.getOptions=="function"){const h=r.getOptions,w=document.createElement("option");w.value="",w.textContent="Loading...",l.appendChild(w),Promise.resolve().then(()=>h()).then(b=>{for(;l.options.length>1;)l.remove(1);x(b)}).catch(()=>{for(;l.options.length>1;)l.remove(1);const b=document.createElement("option");b.value="",b.textContent="Error loading options",l.appendChild(b)})}r.defaultValue!=null&&(l.value=String(r.defaultValue)),m=l}else if(r.type==="file"){const l=r,y=document.createElement("input");y.className="foisit-form-input",y.type="file",l.accept&&Array.isArray(l.accept)&&(y.accept=l.accept.join(",")),l.multiple&&(y.multiple=!0),l.capture&&(l.capture===!0?y.setAttribute("capture",""):y.setAttribute("capture",String(l.capture))),y.addEventListener("change",async()=>{const x=Array.from(y.files||[]),h=C;if(h.style.display="none",h.textContent="",x.length===0)return;const w=l.maxFiles??(l.multiple?10:1);if(x.length>w){h.textContent=`Please select at most ${w} file(s).`,h.style.display="block";return}const b=l.maxSizeBytes??1/0,f=x.reduce((v,A)=>v+A.size,0);if(x.some(v=>v.size>b)){h.textContent=`One or more files exceed the maximum size of ${Math.round(b/1024)} KB.`,h.style.display="block";return}const k=l.maxTotalBytes??1/0;if(f>k){h.textContent=`Total selected files exceed the maximum of ${Math.round(k/1024)} KB.`,h.style.display="block";return}if(l.accept&&Array.isArray(l.accept)){const v=l.accept;if(!x.every(L=>L.type?v.some(M=>M.startsWith(".")?L.name.toLowerCase().endsWith(M.toLowerCase()):L.type===M||L.type.startsWith(M.split("/")[0]+"/")):!0)){h.textContent="One or more files have an unsupported type.",h.style.display="block";return}}}),m=y}else{const l=document.createElement("input");l.className="foisit-form-input",r.type==="string"&&(l.placeholder=r.placeholder||"Type here..."),r.type==="number"?(l.type="number",typeof r.min=="number"&&(l.min=String(r.min)),typeof r.max=="number"&&(l.max=String(r.max)),typeof r.step=="number"&&(l.step=String(r.step)),r.defaultValue!=null&&(l.value=String(r.defaultValue))):r.type==="date"?(l.type="date",typeof r.min=="string"&&(l.min=r.min),typeof r.max=="string"&&(l.max=r.max),r.defaultValue!=null&&(l.value=String(r.defaultValue))):(l.type="text",r.defaultValue!=null&&(l.value=String(r.defaultValue))),m=l}const C=o();p.appendChild(m),p.appendChild(C),n.push({name:r.name,type:r.type,el:m,required:r.required}),s.appendChild(p)});const c=document.createElement("div");c.className="foisit-form-actions";const u=document.createElement("button");u.type="submit",u.textContent="Submit",u.className="foisit-option-chip",u.style.fontWeight="600",c.appendChild(u),s.appendChild(c),s.onsubmit=async r=>{r.preventDefault();const p={};let g=!1;s.querySelectorAll(".foisit-form-error").forEach(m=>{m.style.display="none",m.textContent=""}),s.querySelectorAll(".foisit-form-input").forEach(m=>{m.classList.remove("foisit-error-border")});for(const m of n){if(m.type==="file"){const x=m.el.parentElement,h=x==null?void 0:x.querySelector(".foisit-form-error"),w=m.el,b=Array.from(w.files||[]);if(m.required&&b.length===0){g=!0,w.classList.add("foisit-error-border"),h&&(h.textContent="This file is required",h.style.display="block");continue}if(b.length===0)continue;const f=(e??[]).find(v=>v.name===m.name),k=(f==null?void 0:f.delivery)??"file";if(f!=null&&f.maxWidth||f!=null&&f.maxHeight)try{const v=await this.getImageDimensions(b[0]);if(f.maxWidth&&v.width>f.maxWidth){g=!0,h&&(h.textContent=`Image width must be ≤ ${f.maxWidth}px`,h.style.display="block");continue}if(f.maxHeight&&v.height>f.maxHeight){g=!0,h&&(h.textContent=`Image height must be ≤ ${f.maxHeight}px`,h.style.display="block");continue}}catch{}if(f!=null&&f.maxDurationSec)try{const v=await this.getMediaDuration(b[0]);if(v&&v>f.maxDurationSec){g=!0,h&&(h.textContent=`Media duration must be ≤ ${f.maxDurationSec}s`,h.style.display="block");continue}}catch{}if(k==="file")p[m.name]=f!=null&&f.multiple?b:b[0];else if(k==="base64")try{const v=await Promise.all(b.map(A=>this.readFileAsDataURL(A)));p[m.name]=f!=null&&f.multiple?v:v[0]}catch{g=!0,h&&(h.textContent="Failed to encode file(s) to base64.",h.style.display="block");continue}continue}const C=(m.el.value??"").toString().trim(),l=m.el.parentElement,y=l==null?void 0:l.querySelector(".foisit-form-error");if(m.required&&(C==null||C==="")){g=!0,m.el.classList.add("foisit-error-border"),y&&(y.textContent="This field is required",y.style.display="block");continue}if(C!=="")if(m.type==="number"){const x=Number(C);Number.isNaN(x)||(p[m.name]=x)}else p[m.name]=C}if(g){s.classList.add("foisit-shake"),setTimeout(()=>s.classList.remove("foisit-shake"),400);return}u.disabled=!0,u.style.opacity="0.6",n.forEach(m=>{m.el.disabled=!0}),i(p)},this.messagesContainer.appendChild(s),this.scrollToBottom()}showLoading(){if(this.messagesContainer&&!this.loadingEl){this.loadingEl=document.createElement("div"),this.loadingEl.className="foisit-loading-dots foisit-bubble system";for(let t=0;t<3;t++){const e=document.createElement("div");e.className="foisit-dot",e.style.animation=`foisitPulse 1.4s infinite ease-in-out ${t*.2}s`,this.loadingEl.appendChild(e)}this.messagesContainer.appendChild(this.loadingEl),this.scrollToBottom()}}hideLoading(){var t;(t=this.loadingEl)==null||t.remove(),this.loadingEl=null}scrollToBottom(){this.messagesContainer&&(this.messagesContainer.scrollTop=this.messagesContainer.scrollHeight)}animateMessageEntrance(t,e){if(!t)return;t.style.transition=`opacity ${e}ms cubic-bezier(0.22, 0.9, 0.32, 1), transform ${Math.max(120,e)}ms cubic-bezier(0.22, 0.9, 0.32, 1)`,requestAnimationFrame(()=>{t.style.opacity="1",t.style.transform="translateY(0)"});const i=()=>{try{t.style.transition=""}catch{}t.removeEventListener("transitionend",i)};t.addEventListener("transitionend",i)}animateScrollToBottom(t){if(!this.messagesContainer)return;const e=this.messagesContainer,i=e.scrollTop,s=e.scrollHeight-e.clientHeight;if(s<=i||t<=0){e.scrollTop=s;return}const n=s-i,a=performance.now(),o=c=>{const u=Math.min(1,(c-a)/t),r=1-Math.pow(1-u,3);e.scrollTop=Math.round(i+n*r),u<1&&requestAnimationFrame(o)};requestAnimationFrame(o)}destroy(){var t;this.removeClickOutsideListener(),(t=this.container)==null||t.remove(),this.container=null,this.chatWindow=null,this.messagesContainer=null,this.input=null,this.isOpen=!1}escapeHtml(t){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"};return t.replace(/[&<>"']/g,i=>e[i])}renderMarkdown(t){let e=this.escapeHtml(t);return e=e.replace(/```(\w*)\n([\s\S]*?)```/g,(i,s,n)=>`<pre class="foisit-code-block"><code${s?` class="language-${s}"`:""}>${n.trim()}</code></pre>`),e=e.replace(/`([^`]+)`/g,'<code class="foisit-inline-code">$1</code>'),e=e.replace(/^###### (.+)$/gm,'<h6 class="foisit-md-h6">$1</h6>'),e=e.replace(/^##### (.+)$/gm,'<h5 class="foisit-md-h5">$1</h5>'),e=e.replace(/^#### (.+)$/gm,'<h4 class="foisit-md-h4">$1</h4>'),e=e.replace(/^### (.+)$/gm,'<h3 class="foisit-md-h3">$1</h3>'),e=e.replace(/^## (.+)$/gm,'<h2 class="foisit-md-h2">$1</h2>'),e=e.replace(/^# (.+)$/gm,'<h1 class="foisit-md-h1">$1</h1>'),e=e.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),e=e.replace(/__([^_]+)__/g,"<strong>$1</strong>"),e=e.replace(/\*([^*]+)\*/g,"<em>$1</em>"),e=e.replace(new RegExp("(?<!_)_([^_]+)_(?!_)","g"),"<em>$1</em>"),e=e.replace(/~~([^~]+)~~/g,"<del>$1</del>"),e=e.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer" class="foisit-md-link">$1</a>'),e=e.replace(/^[\-\*] (.+)$/gm,'<li class="foisit-md-li">$1</li>'),e=e.replace(/(<li class="foisit-md-li">.*<\/li>\n?)+/g,i=>`<ul class="foisit-md-ul">${i}</ul>`),e=e.replace(/^\d+\. (.+)$/gm,'<li class="foisit-md-li">$1</li>'),e=e.replace(new RegExp('(?<!<\\/ul>)(<li class="foisit-md-li">.*<\\/li>\\n?)+',"g"),i=>i.includes("<ul")?i:`<ol class="foisit-md-ol">${i}</ol>`),e=e.replace(/^&gt; (.+)$/gm,'<blockquote class="foisit-md-blockquote">$1</blockquote>'),e=e.replace(/^(---|___|\*\*\*)$/gm,'<hr class="foisit-md-hr">'),e=e.replace(/\n\n+/g,'</p><p class="foisit-md-p">'),e=e.replace(/\n/g,"<br>"),e.match(/^<(h[1-6]|ul|ol|pre|blockquote|hr|p)/)||(e=`<p class="foisit-md-p">${e}</p>`),e}readFileAsDataURL(t){return new Promise((e,i)=>{const s=new FileReader;s.onerror=()=>i(new Error("Failed to read file")),s.onload=()=>e(String(s.result)),s.readAsDataURL(t)})}getImageDimensions(t){return new Promise(e=>{try{const i=URL.createObjectURL(t),s=new Image;s.onload=()=>{const n={width:s.naturalWidth||s.width,height:s.naturalHeight||s.height};URL.revokeObjectURL(i),e(n)},s.onerror=()=>{URL.revokeObjectURL(i),e({width:0,height:0})},s.src=i}catch{e({width:0,height:0})}})}getMediaDuration(t){return new Promise(e=>{try{const i=URL.createObjectURL(t),s=t.type.startsWith("audio")?document.createElement("audio"):document.createElement("video");let n=!1;const a=setTimeout(()=>{n||(n=!0,URL.revokeObjectURL(i),e(0))},5e3);s.preload="metadata",s.onloadedmetadata=()=>{if(n)return;n=!0,clearTimeout(a);const c=s.duration||0;URL.revokeObjectURL(i),e(c)},s.onerror=()=>{n||(n=!0,clearTimeout(a),URL.revokeObjectURL(i),e(0))},s.src=i}catch{e(0)}})}injectOverlayStyles(){if(document.getElementById("foisit-overlay-styles"))return;const t=document.createElement("style");t.id="foisit-overlay-styles";const e=this.config.theme||"glass",i=this.config.themeColors||{};if(e==="solid"){const s=i.background||"#1a1a2e",n=i.text||"#ffffff",a=i.accent||"linear-gradient(135deg, #667eea 0%, #764ba2 100%)",o=i.userBubbleBg||"rgba(102, 126, 234, 0.2)",c=i.systemBubbleBg||"rgba(255, 255, 255, 0.08)",u=i.border||"rgba(255, 255, 255, 0.1)";t.textContent=`
35
+ :root {
36
+ /* SOLID THEME - Custom Colors */
37
+ --foisit-bg: ${s};
38
+ --foisit-border: 1px solid ${u};
39
+ --foisit-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
40
+ --foisit-text: ${n};
41
+ --foisit-accent: ${a};
42
+ --foisit-backdrop: none;
46
43
 
47
- /* Bubbles */
48
- --foisit-bubble-user-bg: rgba(0, 0, 0, 0.04);
49
- --foisit-bubble-user-text: #333;
44
+ /* Input */
45
+ --foisit-input-color: ${n};
46
+ --foisit-input-placeholder: ${n}99;
50
47
 
51
- --foisit-bubble-sys-bg: rgba(255, 255, 255, 0.45);
52
- --foisit-bubble-sys-text: #333;
48
+ /* Bubbles */
49
+ --foisit-bubble-user-bg: ${o};
50
+ --foisit-bubble-user-text: ${n};
53
51
 
54
- /* Form Colors */
55
- --foisit-req-star: #ef4444; /* Red asterisk */
56
- --foisit-error-text: #dc2626;
57
- --foisit-error-border: #fca5a5;
58
- }
52
+ --foisit-bubble-sys-bg: ${c};
53
+ --foisit-bubble-sys-text: ${n}ee;
59
54
 
60
- @media (prefers-color-scheme: dark) {
55
+ /* Form Colors */
56
+ --foisit-req-star: #f87171;
57
+ --foisit-error-text: #fca5a5;
58
+ --foisit-error-border: #f87171;
59
+ }
60
+ `}else t.textContent=`
61
61
  :root {
62
- /* DARK MODE */
63
- --foisit-bg: linear-gradient(135deg, rgba(40, 40, 40, 0.65), rgba(40, 40, 40, 0.25));
64
- --foisit-border: 1px solid rgba(255, 255, 255, 0.1);
65
- --foisit-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
66
- --foisit-text: #fff;
62
+ /* LIGHT MODE (Default) - Smoother gradient */
63
+ /* Changed: Softer, right-focused radial highlight to avoid a heavy white bottom */
64
+ --foisit-bg: radial-gradient(ellipse at 75% 30%, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.03));
65
+ --foisit-border: 1px solid rgba(255, 255, 255, 0.25);
66
+ --foisit-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
67
+ --foisit-text: #333;
68
+ --foisit-backdrop: blur(20px);
67
69
 
68
70
  /* Input */
69
- --foisit-input-color: white;
70
- --foisit-input-placeholder: rgba(235, 235, 245, 0.5);
71
+ --foisit-input-color: #333;
72
+ --foisit-input-placeholder: rgba(60, 60, 67, 0.6);
71
73
 
72
74
  /* Bubbles */
73
- --foisit-bubble-user-bg: rgba(255, 255, 255, 0.1);
74
- --foisit-bubble-user-text: white;
75
+ --foisit-bubble-user-bg: rgba(0, 0, 0, 0.04);
76
+ --foisit-bubble-user-text: #333;
75
77
 
76
- --foisit-bubble-sys-bg: rgba(255, 255, 255, 0.05);
77
- --foisit-bubble-sys-text: rgba(255, 255, 255, 0.9);
78
+ --foisit-bubble-sys-bg: rgba(255, 255, 255, 0.45);
79
+ --foisit-bubble-sys-text: #333;
78
80
 
79
81
  /* Form Colors */
80
- --foisit-req-star: #f87171;
81
- --foisit-error-text: #fca5a5;
82
- --foisit-error-border: #f87171;
82
+ --foisit-req-star: #ef4444; /* Red asterisk */
83
+ --foisit-error-text: #dc2626;
84
+ --foisit-error-border: #fca5a5;
83
85
  }
84
- }
86
+
87
+ @media (prefers-color-scheme: dark) {
88
+ :root {
89
+ /* DARK MODE */
90
+ --foisit-bg: linear-gradient(135deg, rgba(40, 40, 40, 0.65), rgba(40, 40, 40, 0.25));
91
+ --foisit-border: 1px solid rgba(255, 255, 255, 0.1);
92
+ --foisit-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
93
+ --foisit-text: #fff;
94
+ --foisit-backdrop: blur(20px);
95
+
96
+ /* Input */
97
+ --foisit-input-color: white;
98
+ --foisit-input-placeholder: rgba(235, 235, 245, 0.5);
99
+
100
+ /* Bubbles */
101
+ --foisit-bubble-user-bg: rgba(255, 255, 255, 0.1);
102
+ --foisit-bubble-user-text: white;
103
+
104
+ --foisit-bubble-sys-bg: rgba(255, 255, 255, 0.05);
105
+ --foisit-bubble-sys-text: rgba(255, 255, 255, 0.9);
106
+
107
+ /* Form Colors */
108
+ --foisit-req-star: #f87171;
109
+ --foisit-error-text: #fca5a5;
110
+ --foisit-error-border: #f87171;
111
+ }
112
+ }
113
+ `;t.textContent+=`
85
114
 
86
115
  @keyframes foisitPulse {
87
116
  0%, 100% { transform: scale(0.8); opacity: 0.5; }
@@ -129,8 +158,8 @@
129
158
  border: var(--foisit-border);
130
159
  box-shadow: var(--foisit-shadow);
131
160
 
132
- backdrop-filter: blur(20px);
133
- -webkit-backdrop-filter: blur(20px);
161
+ backdrop-filter: var(--foisit-backdrop);
162
+ -webkit-backdrop-filter: var(--foisit-backdrop);
134
163
 
135
164
  border-radius: 18px;
136
165
  display: none;
@@ -339,8 +368,8 @@
339
368
  border: 1px solid rgba(255,255,255,0.2);
340
369
  background: var(--foisit-bg);
341
370
  color: var(--foisit-text);
342
- backdrop-filter: blur(10px);
343
- -webkit-backdrop-filter: blur(10px);
371
+ backdrop-filter: var(--foisit-backdrop);
372
+ -webkit-backdrop-filter: var(--foisit-backdrop);
344
373
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
345
374
  cursor: pointer;
346
375
  pointer-events: auto;
@@ -437,4 +466,4 @@
437
466
  .foisit-bubble.system .foisit-code-block { background: rgba(255,255,255,0.08); }
438
467
  .foisit-bubble.system .foisit-inline-code { background: rgba(255,255,255,0.1); }
439
468
  }
440
- `,document.head.appendChild(t)}}class q{constructor(t){this.config=t,this.isActivated=!1,this.lastProcessedInput="",this.processingLock=!1,this.defaultIntroMessage="How can I help you?",this.commandHandler=new z({enableSmartIntent:this.config.enableSmartIntent!==!1,intentEndpoint:this.config.intentEndpoint}),this.fallbackHandler=new W,typeof window<"u"&&typeof document<"u"?(this.voiceProcessor=new B,this.textToSpeech=new P,this.stateManager=new _,this.gestureHandler=new R,this.overlayManager=new G({floatingButton:this.config.floatingButton,inputPlaceholder:this.config.inputPlaceholder,enableGestureActivation:this.config.enableGestureActivation}),this.overlayManager.setExternalCommandExecutor(async e=>this.commandHandler.executeCommand(e)),this.config.commands.forEach(e=>this.commandHandler.addCommand(e)),this.config.fallbackResponse&&this.fallbackHandler.setFallbackMessage(this.config.fallbackResponse),this.overlayManager.registerCallbacks(async e=>{if(typeof e=="string"){this.overlayManager.addMessage(e,"user"),await this.handleCommand(e);return}if(e&&typeof e=="object"){const i=e,s=i.label??i.commandId??"Selection";this.overlayManager.addMessage(String(s),"user"),this.overlayManager.showLoading();const n=await this.commandHandler.executeCommand(i);this.overlayManager.hideLoading(),this.processResponse(n)}},()=>console.log("AssistantService: Overlay closed."))):(this.voiceProcessor=void 0,this.textToSpeech=void 0,this.stateManager=void 0,this.gestureHandler=void 0,this.overlayManager=void 0,this.config.commands.forEach(e=>this.commandHandler.addCommand(e)),this.config.fallbackResponse&&this.fallbackHandler.setFallbackMessage(this.config.fallbackResponse))}startListening(){if(typeof window>"u"||!this.voiceProcessor){console.log("AssistantService: Voice is disabled or unavailable; startListening() is a no-op.");return}}stopListening(){if(typeof window>"u"||!this.voiceProcessor){console.log("AssistantService: Voice unavailable; stopListening() is a no-op."),this.isActivated=!1;return}this.voiceProcessor.stopListening(),this.isActivated=!1}reactivate(){console.log("AssistantService: Reactivating assistant..."),this.isActivated=!1;try{this.startListening()}catch{}}async processActivation(t){var i;const e=(i=this.config.activationCommand)==null?void 0:i.toLowerCase();e&&(t===e?(console.log("AssistantService: Activation matched."),this.isActivated=!0,this.textToSpeech.speak(this.config.introMessage||this.defaultIntroMessage)):console.log("AssistantService: Activation command not recognized."))}async handleCommand(t){this.overlayManager.showLoading();let e;try{e=await this.commandHandler.executeCommand(t)}finally{this.overlayManager.hideLoading()}if(e.type==="form"&&e.fields){this.overlayManager.addForm(e.message,e.fields,async i=>{this.overlayManager.showLoading();let s;try{s=await this.commandHandler.executeCommand(i)}finally{this.overlayManager.hideLoading()}this.processResponse(s)});return}if(e.type==="error"){this.fallbackHandler.handleFallback(t),this.overlayManager.addMessage(this.fallbackHandler.getFallbackMessage(),"system");return}if((e.type==="ambiguous"||e.type==="confirm")&&e.options){e.message&&this.overlayManager.addMessage(e.message,"system"),this.overlayManager.addOptions(e.options);return}e.message&&this.overlayManager.addMessage(e.message,"system")}destroy(){this.voiceProcessor.stopListening(),this.gestureHandler.destroy(),this.overlayManager.destroy()}processResponse(t){if(t){if(t.type==="form"&&t.fields){this.overlayManager.addForm(t.message,t.fields,async e=>{this.overlayManager.showLoading();let i;try{i=await this.commandHandler.executeCommand(e)}finally{this.overlayManager.hideLoading()}this.processResponse(i)});return}if((t.type==="ambiguous"||t.type==="confirm")&&t.options){t.message&&this.overlayManager.addMessage(t.message,"system"),this.overlayManager.addOptions(t.options);return}t.message&&this.overlayManager.addMessage(t.message,"system")}}addCommand(t,e){console.log(typeof t=="string"?`AssistantService: Adding command "${t}".`:`AssistantService: Adding rich command "${t.command}".`),this.commandHandler.addCommand(t,e)}removeCommand(t){console.log(`AssistantService: Removing command "${t}".`),this.commandHandler.removeCommand(t)}registerCommandHandler(t,e){this.overlayManager&&this.overlayManager.registerCommandHandler(t,e)}unregisterCommandHandler(t){this.overlayManager&&this.overlayManager.unregisterCommandHandler(t)}async runCommand(t){if(!this.overlayManager)throw new Error("Overlay manager not available.");const e=await this.overlayManager.runCommand(t);return e&&typeof e=="object"&&"type"in e&&this.processResponse(e),e}getCommands(){return this.commandHandler.getCommands()}toggle(t,e){console.log("AssistantService: Toggling overlay..."),this.overlayManager.toggle(async i=>{if(typeof i=="string"){this.overlayManager.addMessage(i,"user"),t&&t(i),await this.handleCommand(i);return}if(i&&typeof i=="object"){const s=i,n=s.label??s.commandId??"Selection";this.overlayManager.addMessage(String(n),"user"),this.overlayManager.showLoading();let a;try{a=await this.commandHandler.executeCommand(s)}finally{this.overlayManager.hideLoading()}this.processResponse(a)}},()=>{console.log("AssistantService: Overlay closed."),e&&e()})}}const T=S.createContext(null);let I=null;const Y=({config:d,children:t})=>{const[e,i]=S.useState(null),[s,n]=S.useState(!1);return S.useEffect(()=>{I?console.warn("Multiple AssistantProvider instances detected. Reusing global AssistantService."):(console.log("Initializing global AssistantService..."),I=new q(d));const a=I;return i(a),n(!0),()=>{var o;console.log("Cleaning up AssistantService..."),(o=a.destroy)==null||o.call(a),I=null}},[d]),!s||!e?E.jsx("div",{children:"Loading Assistant..."}):E.jsx(T.Provider,{value:e,children:t})},F=()=>{const d=S.useContext(T);if(console.log("assistant",d),!d)throw new Error("useAssistant must be used within an AssistantProvider");return d},K=({label:d="Activate Assistant",onActivate:t})=>{const e=F(),i=()=>{t&&t(),e.reactivate()};return E.jsx("button",{onClick:i,className:"assistant-activator",children:d})},X=d=>{const[t,e]=S.useState(d.getState());return S.useEffect(()=>{const i=s=>{e(s)};return d.subscribe(i),()=>{d.subscribe(()=>{})}},[d]),t};exports.AssistantActivator=K;exports.AssistantContext=T;exports.AssistantProvider=Y;exports.AssistantService=q;exports.ReactWrapper=N;exports.useAssistant=F;exports.useAssistantState=X;
469
+ `,document.head.appendChild(t)}}class q{constructor(t){this.config=t,this.isActivated=!1,this.lastProcessedInput="",this.processingLock=!1,this.defaultIntroMessage="How can I help you?",this.commandHandler=new N({enableSmartIntent:this.config.enableSmartIntent!==!1,intentEndpoint:this.config.intentEndpoint}),this.fallbackHandler=new z,typeof window<"u"&&typeof document<"u"?(this.voiceProcessor=new W,this.textToSpeech=new P,this.stateManager=new _,this.gestureHandler=new R,this.overlayManager=new G({floatingButton:this.config.floatingButton,inputPlaceholder:this.config.inputPlaceholder,enableGestureActivation:this.config.enableGestureActivation,theme:this.config.theme,themeColors:this.config.themeColors}),this.overlayManager.setExternalCommandExecutor(async e=>this.commandHandler.executeCommand(e)),this.config.commands.forEach(e=>this.commandHandler.addCommand(e)),this.config.fallbackResponse&&this.fallbackHandler.setFallbackMessage(this.config.fallbackResponse),this.overlayManager.registerCallbacks(async e=>{if(typeof e=="string"){this.overlayManager.addMessage(e,"user"),await this.handleCommand(e);return}if(e&&typeof e=="object"){const i=e,s=i.label??i.commandId??"Selection";this.overlayManager.addMessage(String(s),"user"),this.overlayManager.showLoading();const n=await this.commandHandler.executeCommand(i);this.overlayManager.hideLoading(),this.processResponse(n)}},()=>console.log("AssistantService: Overlay closed."))):(this.voiceProcessor=void 0,this.textToSpeech=void 0,this.stateManager=void 0,this.gestureHandler=void 0,this.overlayManager=void 0,this.config.commands.forEach(e=>this.commandHandler.addCommand(e)),this.config.fallbackResponse&&this.fallbackHandler.setFallbackMessage(this.config.fallbackResponse))}startListening(){if(typeof window>"u"||!this.voiceProcessor){console.log("AssistantService: Voice is disabled or unavailable; startListening() is a no-op.");return}}stopListening(){if(typeof window>"u"||!this.voiceProcessor){console.log("AssistantService: Voice unavailable; stopListening() is a no-op."),this.isActivated=!1;return}this.voiceProcessor.stopListening(),this.isActivated=!1}reactivate(){console.log("AssistantService: Reactivating assistant..."),this.isActivated=!1;try{this.startListening()}catch{}}async processActivation(t){var i;const e=(i=this.config.activationCommand)==null?void 0:i.toLowerCase();e&&(t===e?(console.log("AssistantService: Activation matched."),this.isActivated=!0,this.textToSpeech.speak(this.config.introMessage||this.defaultIntroMessage)):console.log("AssistantService: Activation command not recognized."))}async handleCommand(t){this.overlayManager.showLoading();let e;try{e=await this.commandHandler.executeCommand(t)}finally{this.overlayManager.hideLoading()}if(e.type==="form"&&e.fields){this.overlayManager.addForm(e.message,e.fields,async i=>{this.overlayManager.showLoading();let s;try{s=await this.commandHandler.executeCommand(i)}finally{this.overlayManager.hideLoading()}this.processResponse(s)});return}if(e.type==="error"){this.fallbackHandler.handleFallback(t),this.overlayManager.addMessage(this.fallbackHandler.getFallbackMessage(),"system");return}if((e.type==="ambiguous"||e.type==="confirm")&&e.options){e.message&&this.overlayManager.addMessage(e.message,"system"),this.overlayManager.addOptions(e.options);return}e.message&&this.overlayManager.addMessage(e.message,"system")}destroy(){this.voiceProcessor.stopListening(),this.gestureHandler.destroy(),this.overlayManager.destroy()}processResponse(t){if(t){if(t.type==="form"&&t.fields){this.overlayManager.addForm(t.message,t.fields,async e=>{this.overlayManager.showLoading();let i;try{i=await this.commandHandler.executeCommand(e)}finally{this.overlayManager.hideLoading()}this.processResponse(i)});return}if((t.type==="ambiguous"||t.type==="confirm")&&t.options){t.message&&this.overlayManager.addMessage(t.message,"system"),this.overlayManager.addOptions(t.options);return}t.message&&this.overlayManager.addMessage(t.message,"system")}}addCommand(t,e){console.log(typeof t=="string"?`AssistantService: Adding command "${t}".`:`AssistantService: Adding rich command "${t.command}".`),this.commandHandler.addCommand(t,e)}removeCommand(t){console.log(`AssistantService: Removing command "${t}".`),this.commandHandler.removeCommand(t)}registerCommandHandler(t,e){this.overlayManager&&this.overlayManager.registerCommandHandler(t,e)}unregisterCommandHandler(t){this.overlayManager&&this.overlayManager.unregisterCommandHandler(t)}async runCommand(t){if(!this.overlayManager)throw new Error("Overlay manager not available.");const e=await this.overlayManager.runCommand(t);return e&&typeof e=="object"&&"type"in e&&this.processResponse(e),e}getCommands(){return this.commandHandler.getCommands()}toggle(t,e){console.log("AssistantService: Toggling overlay..."),this.overlayManager.toggle(async i=>{if(typeof i=="string"){this.overlayManager.addMessage(i,"user"),t&&t(i),await this.handleCommand(i);return}if(i&&typeof i=="object"){const s=i,n=s.label??s.commandId??"Selection";this.overlayManager.addMessage(String(n),"user"),this.overlayManager.showLoading();let a;try{a=await this.commandHandler.executeCommand(s)}finally{this.overlayManager.hideLoading()}this.processResponse(a)}},()=>{console.log("AssistantService: Overlay closed."),e&&e()})}}const T=S.createContext(null);let I=null;const Y=({config:d,children:t})=>{const[e,i]=S.useState(null),[s,n]=S.useState(!1);return S.useEffect(()=>{I?console.warn("Multiple AssistantProvider instances detected. Reusing global AssistantService."):(console.log("Initializing global AssistantService..."),I=new q(d));const a=I;return i(a),n(!0),()=>{var o;console.log("Cleaning up AssistantService..."),(o=a.destroy)==null||o.call(a),I=null}},[d]),!s||!e?E.jsx("div",{children:"Loading Assistant..."}):E.jsx(T.Provider,{value:e,children:t})},F=()=>{const d=S.useContext(T);if(console.log("assistant",d),!d)throw new Error("useAssistant must be used within an AssistantProvider");return d},K=({label:d="Activate Assistant",onActivate:t})=>{const e=F(),i=()=>{t&&t(),e.reactivate()};return E.jsx("button",{onClick:i,className:"assistant-activator",children:d})},X=d=>{const[t,e]=S.useState(d.getState());return S.useEffect(()=>{const i=s=>{e(s)};return d.subscribe(i),()=>{d.subscribe(()=>{})}},[d]),t};exports.AssistantActivator=K;exports.AssistantContext=T;exports.AssistantProvider=Y;exports.AssistantService=q;exports.ReactWrapper=B;exports.useAssistant=F;exports.useAssistantState=X;
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx as k } from "react/jsx-runtime";
2
- import { createContext as F, useState as I, useEffect as $, useContext as N } from "react";
2
+ import { createContext as F, useState as I, useEffect as H, useContext as B } from "react";
3
3
  const O = {};
4
4
  function Q() {
5
5
  return /* @__PURE__ */ k("div", { className: O.container, children: /* @__PURE__ */ k("h1", { children: "Welcome to ReactWrapper!" }) });
@@ -35,7 +35,7 @@ class T {
35
35
  }
36
36
  }
37
37
  }
38
- class z {
38
+ class N {
39
39
  constructor(t = !0) {
40
40
  if (this.commands = /* @__PURE__ */ new Map(), this.openAIService = null, this.context = null, this.pendingConfirmation = null, this.enableSmartIntent = !0, this.selectOptionsCache = /* @__PURE__ */ new Map(), typeof t == "boolean") {
41
41
  this.enableSmartIntent = t, this.enableSmartIntent && (this.openAIService = new T());
@@ -66,9 +66,9 @@ class z {
66
66
  async executeCommand(t) {
67
67
  if (typeof t == "object" && t !== null) {
68
68
  if (this.isStructured(t)) {
69
- const c = String(t.commandId), f = t.params ?? {}, r = this.getCommandById(c);
69
+ const c = String(t.commandId), u = t.params ?? {}, r = this.getCommandById(c);
70
70
  if (!r) return { message: "That command is not available.", type: "error" };
71
- const p = this.sanitizeParamsForCommand(r, f), m = (r.parameters ?? []).filter((C) => C.required).filter((C) => p[C.name] == null || p[C.name] === "");
71
+ const p = this.sanitizeParamsForCommand(r, u), m = (r.parameters ?? []).filter((C) => C.required).filter((C) => p[C.name] == null || p[C.name] === "");
72
72
  return m.length > 0 ? (this.context = { commandId: this.getCommandIdentifier(r), params: p }, {
73
73
  message: `Please provide the required details for "${r.command}".`,
74
74
  type: "form",
@@ -143,7 +143,7 @@ class z {
143
143
  return { message: "I'm not sure what you mean.", type: "error" };
144
144
  if (e.macro)
145
145
  return this.safeRunAction(e, {});
146
- const i = t.params ?? {}, s = this.sanitizeParamsForCommand(e, i), n = e.allowAiParamExtraction === !1 ? {} : s, o = (e.parameters ?? []).filter((f) => f.required).filter((f) => n[f.name] == null || n[f.name] === "");
146
+ const i = t.params ?? {}, s = this.sanitizeParamsForCommand(e, i), n = e.allowAiParamExtraction === !1 ? {} : s, o = (e.parameters ?? []).filter((u) => u.required).filter((u) => n[u.name] == null || n[u.name] === "");
147
147
  if (t.incomplete || o.length > 0) {
148
148
  if (this.context = { commandId: this.getCommandIdentifier(e), params: n }, !(e.collectRequiredViaForm !== !1) && this.shouldAskSingleQuestion(o)) {
149
149
  const p = o.map((g) => g.name).join(" and ");
@@ -259,8 +259,8 @@ class z {
259
259
  const e = [];
260
260
  for (const o of this.commands.values()) {
261
261
  let c = 0;
262
- const f = o.command.toLowerCase();
263
- t.includes(f) && (c += 5);
262
+ const u = o.command.toLowerCase();
263
+ t.includes(u) && (c += 5);
264
264
  const r = o.keywords ?? [];
265
265
  for (const p of r) {
266
266
  const g = p.toLowerCase().trim();
@@ -372,7 +372,7 @@ class P {
372
372
  this.synth && this.synth.cancel();
373
373
  }
374
374
  }
375
- class W {
375
+ class z {
376
376
  constructor() {
377
377
  this.fallbackMessage = "Sorry, I didn’t understand that.";
378
378
  }
@@ -386,12 +386,12 @@ class W {
386
386
  return this.fallbackMessage;
387
387
  }
388
388
  }
389
- const H = () => {
389
+ const $ = () => {
390
390
  if (typeof window > "u") return null;
391
391
  const d = window;
392
392
  return d.SpeechRecognition ?? d.webkitSpeechRecognition ?? null;
393
393
  };
394
- class B {
394
+ class W {
395
395
  constructor(t = "en-US", e = {}) {
396
396
  this.recognition = null, this.isListening = !1, this.engineActive = !1, this.intentionallyStopped = !1, this.restartAllowed = !0, this.lastStart = 0, this.backoffMs = 250, this.destroyed = !1, this.resultCallback = null, this.ttsSpeaking = !1, this.debugEnabled = !0, this.restartTimer = null, this.prewarmed = !1, this.hadResultThisSession = !1, this.onTTSStart = () => {
397
397
  var s;
@@ -404,7 +404,7 @@ class B {
404
404
  }, this.onTTSEnd = () => {
405
405
  this.ttsSpeaking = !1, this.isListening && this.restartAllowed ? this.safeRestart() : this.emitStatus(this.isListening ? "listening" : "idle");
406
406
  };
407
- const i = H();
407
+ const i = $();
408
408
  if (i) {
409
409
  this.recognition = new i(), this.recognition.lang = t, this.recognition.interimResults = e.interimResults ?? !0, this.recognition.continuous = e.continuous ?? !0, this.recognition.onresult = (n) => this.handleResult(n, e), this.recognition.onend = () => this.handleEnd(), this.recognition.onstart = () => {
410
410
  this.log("recognition onstart"), this.engineActive = !0, this.hadResultThisSession = !1, this.restartTimer && (clearTimeout(this.restartTimer), this.restartTimer = null), this.backoffMs = 250, this.isListening && !this.ttsSpeaking && this.emitStatus("listening");
@@ -436,7 +436,7 @@ class B {
436
436
  }
437
437
  /** Check if SpeechRecognition is available */
438
438
  isSupported() {
439
- return H() !== null;
439
+ return $() !== null;
440
440
  }
441
441
  /** Allow consumers (wrappers) to observe status changes */
442
442
  onStatusChange(t) {
@@ -475,10 +475,10 @@ class B {
475
475
  if (!this.resultCallback) return;
476
476
  const i = e.confidenceThreshold ?? 0.6;
477
477
  for (let a = t.resultIndex; a < t.results.length; a++) {
478
- const o = t.results[a], c = o && o[0], f = ((n = (s = c == null ? void 0 : c.transcript) == null ? void 0 : s.trim) == null ? void 0 : n.call(s)) || "", r = (c == null ? void 0 : c.confidence) ?? 0;
479
- if (f && !(!o.isFinal && e.interimResults === !1) && !(o.isFinal && r < i))
478
+ const o = t.results[a], c = o && o[0], u = ((n = (s = c == null ? void 0 : c.transcript) == null ? void 0 : s.trim) == null ? void 0 : n.call(s)) || "", r = (c == null ? void 0 : c.confidence) ?? 0;
479
+ if (u && !(!o.isFinal && e.interimResults === !1) && !(o.isFinal && r < i))
480
480
  try {
481
- this.hadResultThisSession = !0, this.resultCallback(f, !!o.isFinal);
481
+ this.hadResultThisSession = !0, this.resultCallback(u, !!o.isFinal);
482
482
  } catch {
483
483
  this.error("VoiceProcessor: result callback error");
484
484
  }
@@ -681,8 +681,14 @@ class G {
681
681
  * - `showInvocation`: if true, show the invocation as a user message
682
682
  */
683
683
  async runCommand(t) {
684
- if (!t || !t.commandId) throw new Error("runCommand requires a commandId");
685
- const { commandId: e, params: i, openOverlay: s = !0, showInvocation: n = !0 } = t;
684
+ if (!t || !t.commandId)
685
+ throw new Error("runCommand requires a commandId");
686
+ const {
687
+ commandId: e,
688
+ params: i,
689
+ openOverlay: s = !0,
690
+ showInvocation: n = !0
691
+ } = t;
686
692
  s && !this.isOpen && this.toggle();
687
693
  const a = this.commandHandlers.get(e);
688
694
  if (a && n && this.messagesContainer && this.addMessage(`Command: ${e}`, "user"), a)
@@ -700,7 +706,10 @@ class G {
700
706
  else o == null || this.addMessage(String(o), "system");
701
707
  return o;
702
708
  } catch (o) {
703
- throw this.hideLoading(), this.addMessage(`Command "${e}" failed: ${String(o)}`, "system"), o;
709
+ throw this.hideLoading(), this.addMessage(
710
+ `Command "${e}" failed: ${String(o)}`,
711
+ "system"
712
+ ), o;
704
713
  }
705
714
  if (this.externalCommandExecutor)
706
715
  try {
@@ -708,9 +717,15 @@ class G {
708
717
  const o = await this.externalCommandExecutor({ commandId: e, params: i });
709
718
  return this.hideLoading(), o;
710
719
  } catch (o) {
711
- throw this.hideLoading(), this.addMessage(`Command "${e}" failed: ${String(o)}`, "system"), o;
712
- }
713
- this.addMessage(`No handler registered for command "${e}".`, "system");
720
+ throw this.hideLoading(), this.addMessage(
721
+ `Command "${e}" failed: ${String(o)}`,
722
+ "system"
723
+ ), o;
724
+ }
725
+ this.addMessage(
726
+ `No handler registered for command "${e}".`,
727
+ "system"
728
+ );
714
729
  }
715
730
  init() {
716
731
  var e, i;
@@ -718,17 +733,23 @@ class G {
718
733
  this.injectOverlayStyles();
719
734
  const t = document.getElementById("foisit-overlay-container");
720
735
  if (t && t instanceof HTMLElement) {
721
- this.container = t, this.chatWindow = t.querySelector(".foisit-chat"), this.messagesContainer = t.querySelector(".foisit-messages"), this.input = t.querySelector("input.foisit-input"), ((e = this.config.floatingButton) == null ? void 0 : e.visible) !== !1 && !t.querySelector(".foisit-floating-btn") && this.renderFloatingButton(), this.chatWindow || this.renderChatWindow(), this.config.enableGestureActivation && (this.gestureHandler = new R(), this.gestureHandler.setupTripleTapListener(() => this.toggle()));
736
+ this.container = t, this.chatWindow = t.querySelector(
737
+ ".foisit-chat"
738
+ ), this.messagesContainer = t.querySelector(
739
+ ".foisit-messages"
740
+ ), this.input = t.querySelector(
741
+ "input.foisit-input"
742
+ ), ((e = this.config.floatingButton) == null ? void 0 : e.visible) !== !1 && !t.querySelector(".foisit-floating-btn") && this.renderFloatingButton(), this.chatWindow || this.renderChatWindow(), this.config.enableGestureActivation && (this.gestureHandler = new R(), this.gestureHandler.setupTripleTapListener(() => this.toggle()));
722
743
  return;
723
744
  }
724
745
  this.container = document.createElement("div"), this.container.id = "foisit-overlay-container", this.container.className = "foisit-overlay-container", document.body.appendChild(this.container), ((i = this.config.floatingButton) == null ? void 0 : i.visible) !== !1 && this.renderFloatingButton(), this.renderChatWindow(), this.config.enableGestureActivation && (this.gestureHandler = new R(), this.gestureHandler.setupTripleTapListener(() => this.toggle()));
725
746
  }
726
747
  renderFloatingButton() {
727
- var s, n, a, o, c, f;
748
+ var s, n, a, o, c, u;
728
749
  const t = document.createElement("button");
729
750
  t.innerHTML = ((s = this.config.floatingButton) == null ? void 0 : s.customHtml) || "🎙️";
730
751
  const e = ((a = (n = this.config.floatingButton) == null ? void 0 : n.position) == null ? void 0 : a.bottom) || "20px", i = ((c = (o = this.config.floatingButton) == null ? void 0 : o.position) == null ? void 0 : c.right) || "20px";
731
- t.className = "foisit-floating-btn", t.style.bottom = e, t.style.right = i, t.onclick = () => this.toggle(), t.onmouseenter = () => t.style.transform = "scale(1.05)", t.onmouseleave = () => t.style.transform = "scale(1)", (f = this.container) == null || f.appendChild(t);
752
+ t.className = "foisit-floating-btn", t.style.bottom = e, t.style.right = i, t.onclick = () => this.toggle(), t.onmouseenter = () => t.style.transform = "scale(1.05)", t.onmouseleave = () => t.style.transform = "scale(1)", (u = this.container) == null || u.appendChild(t);
732
753
  }
733
754
  renderChatWindow() {
734
755
  var n;
@@ -817,19 +838,19 @@ class G {
817
838
  l.className = "foisit-form-input";
818
839
  const y = document.createElement("option");
819
840
  y.value = "", y.textContent = "Select...", l.appendChild(y);
820
- const w = (h) => {
821
- (h ?? []).forEach((x) => {
841
+ const x = (h) => {
842
+ (h ?? []).forEach((w) => {
822
843
  const b = document.createElement("option");
823
- b.value = String(x.value ?? x.label ?? ""), b.textContent = String(x.label ?? x.value ?? ""), l.appendChild(b);
844
+ b.value = String(w.value ?? w.label ?? ""), b.textContent = String(w.label ?? w.value ?? ""), l.appendChild(b);
824
845
  });
825
846
  };
826
847
  if (Array.isArray(r.options) && r.options.length)
827
- w(r.options);
848
+ x(r.options);
828
849
  else if (typeof r.getOptions == "function") {
829
- const h = r.getOptions, x = document.createElement("option");
830
- x.value = "", x.textContent = "Loading...", l.appendChild(x), Promise.resolve().then(() => h()).then((b) => {
850
+ const h = r.getOptions, w = document.createElement("option");
851
+ w.value = "", w.textContent = "Loading...", l.appendChild(w), Promise.resolve().then(() => h()).then((b) => {
831
852
  for (; l.options.length > 1; ) l.remove(1);
832
- w(b);
853
+ x(b);
833
854
  }).catch(() => {
834
855
  for (; l.options.length > 1; ) l.remove(1);
835
856
  const b = document.createElement("option");
@@ -840,26 +861,32 @@ class G {
840
861
  } else if (r.type === "file") {
841
862
  const l = r, y = document.createElement("input");
842
863
  y.className = "foisit-form-input", y.type = "file", l.accept && Array.isArray(l.accept) && (y.accept = l.accept.join(",")), l.multiple && (y.multiple = !0), l.capture && (l.capture === !0 ? y.setAttribute("capture", "") : y.setAttribute("capture", String(l.capture))), y.addEventListener("change", async () => {
843
- const w = Array.from(y.files || []), h = C;
844
- if (h.style.display = "none", h.textContent = "", w.length === 0) return;
845
- const x = l.maxFiles ?? (l.multiple ? 10 : 1);
846
- if (w.length > x) {
847
- h.textContent = `Please select at most ${x} file(s).`, h.style.display = "block";
864
+ const x = Array.from(y.files || []), h = C;
865
+ if (h.style.display = "none", h.textContent = "", x.length === 0) return;
866
+ const w = l.maxFiles ?? (l.multiple ? 10 : 1);
867
+ if (x.length > w) {
868
+ h.textContent = `Please select at most ${w} file(s).`, h.style.display = "block";
848
869
  return;
849
870
  }
850
- const b = l.maxSizeBytes ?? 1 / 0, u = w.reduce((v, E) => v + E.size, 0);
851
- if (w.some((v) => v.size > b)) {
852
- h.textContent = `One or more files exceed the maximum size of ${Math.round(b / 1024)} KB.`, h.style.display = "block";
871
+ const b = l.maxSizeBytes ?? 1 / 0, f = x.reduce((v, E) => v + E.size, 0);
872
+ if (x.some((v) => v.size > b)) {
873
+ h.textContent = `One or more files exceed the maximum size of ${Math.round(
874
+ b / 1024
875
+ )} KB.`, h.style.display = "block";
853
876
  return;
854
877
  }
855
878
  const S = l.maxTotalBytes ?? 1 / 0;
856
- if (u > S) {
857
- h.textContent = `Total selected files exceed the maximum of ${Math.round(S / 1024)} KB.`, h.style.display = "block";
879
+ if (f > S) {
880
+ h.textContent = `Total selected files exceed the maximum of ${Math.round(
881
+ S / 1024
882
+ )} KB.`, h.style.display = "block";
858
883
  return;
859
884
  }
860
885
  if (l.accept && Array.isArray(l.accept)) {
861
886
  const v = l.accept;
862
- if (!w.every((L) => L.type ? v.some((A) => A.startsWith(".") ? L.name.toLowerCase().endsWith(A.toLowerCase()) : L.type === A || L.type.startsWith(A.split("/")[0] + "/")) : !0)) {
887
+ if (!x.every((L) => L.type ? v.some(
888
+ (A) => A.startsWith(".") ? L.name.toLowerCase().endsWith(A.toLowerCase()) : L.type === A || L.type.startsWith(A.split("/")[0] + "/")
889
+ ) : !0)) {
863
890
  h.textContent = "One or more files have an unsupported type.", h.style.display = "block";
864
891
  return;
865
892
  }
@@ -879,8 +906,8 @@ class G {
879
906
  });
880
907
  const c = document.createElement("div");
881
908
  c.className = "foisit-form-actions";
882
- const f = document.createElement("button");
883
- f.type = "submit", f.textContent = "Submit", f.className = "foisit-option-chip", f.style.fontWeight = "600", c.appendChild(f), s.appendChild(c), s.onsubmit = async (r) => {
909
+ const u = document.createElement("button");
910
+ u.type = "submit", u.textContent = "Submit", u.className = "foisit-option-chip", u.style.fontWeight = "600", c.appendChild(u), s.appendChild(c), s.onsubmit = async (r) => {
884
911
  r.preventDefault();
885
912
  const p = {};
886
913
  let g = !1;
@@ -891,56 +918,62 @@ class G {
891
918
  });
892
919
  for (const m of n) {
893
920
  if (m.type === "file") {
894
- const w = m.el.parentElement, h = w == null ? void 0 : w.querySelector(".foisit-form-error"), x = m.el, b = Array.from(x.files || []);
921
+ const x = m.el.parentElement, h = x == null ? void 0 : x.querySelector(
922
+ ".foisit-form-error"
923
+ ), w = m.el, b = Array.from(w.files || []);
895
924
  if (m.required && b.length === 0) {
896
- g = !0, x.classList.add("foisit-error-border"), h && (h.textContent = "This file is required", h.style.display = "block");
925
+ g = !0, w.classList.add("foisit-error-border"), h && (h.textContent = "This file is required", h.style.display = "block");
897
926
  continue;
898
927
  }
899
928
  if (b.length === 0) continue;
900
- const u = (e ?? []).find((v) => v.name === m.name), S = (u == null ? void 0 : u.delivery) ?? "file";
901
- if (u != null && u.maxWidth || u != null && u.maxHeight)
929
+ const f = (e ?? []).find((v) => v.name === m.name), S = (f == null ? void 0 : f.delivery) ?? "file";
930
+ if (f != null && f.maxWidth || f != null && f.maxHeight)
902
931
  try {
903
932
  const v = await this.getImageDimensions(b[0]);
904
- if (u.maxWidth && v.width > u.maxWidth) {
905
- g = !0, h && (h.textContent = `Image width must be ≤ ${u.maxWidth}px`, h.style.display = "block");
933
+ if (f.maxWidth && v.width > f.maxWidth) {
934
+ g = !0, h && (h.textContent = `Image width must be ≤ ${f.maxWidth}px`, h.style.display = "block");
906
935
  continue;
907
936
  }
908
- if (u.maxHeight && v.height > u.maxHeight) {
909
- g = !0, h && (h.textContent = `Image height must be ≤ ${u.maxHeight}px`, h.style.display = "block");
937
+ if (f.maxHeight && v.height > f.maxHeight) {
938
+ g = !0, h && (h.textContent = `Image height must be ≤ ${f.maxHeight}px`, h.style.display = "block");
910
939
  continue;
911
940
  }
912
941
  } catch {
913
942
  }
914
- if (u != null && u.maxDurationSec)
943
+ if (f != null && f.maxDurationSec)
915
944
  try {
916
945
  const v = await this.getMediaDuration(b[0]);
917
- if (v && v > u.maxDurationSec) {
918
- g = !0, h && (h.textContent = `Media duration must be ≤ ${u.maxDurationSec}s`, h.style.display = "block");
946
+ if (v && v > f.maxDurationSec) {
947
+ g = !0, h && (h.textContent = `Media duration must be ≤ ${f.maxDurationSec}s`, h.style.display = "block");
919
948
  continue;
920
949
  }
921
950
  } catch {
922
951
  }
923
952
  if (S === "file")
924
- p[m.name] = u != null && u.multiple ? b : b[0];
953
+ p[m.name] = f != null && f.multiple ? b : b[0];
925
954
  else if (S === "base64")
926
955
  try {
927
- const v = await Promise.all(b.map((E) => this.readFileAsDataURL(E)));
928
- p[m.name] = u != null && u.multiple ? v : v[0];
956
+ const v = await Promise.all(
957
+ b.map((E) => this.readFileAsDataURL(E))
958
+ );
959
+ p[m.name] = f != null && f.multiple ? v : v[0];
929
960
  } catch {
930
961
  g = !0, h && (h.textContent = "Failed to encode file(s) to base64.", h.style.display = "block");
931
962
  continue;
932
963
  }
933
964
  continue;
934
965
  }
935
- const C = (m.el.value ?? "").toString().trim(), l = m.el.parentElement, y = l == null ? void 0 : l.querySelector(".foisit-form-error");
966
+ const C = (m.el.value ?? "").toString().trim(), l = m.el.parentElement, y = l == null ? void 0 : l.querySelector(
967
+ ".foisit-form-error"
968
+ );
936
969
  if (m.required && (C == null || C === "")) {
937
970
  g = !0, m.el.classList.add("foisit-error-border"), y && (y.textContent = "This field is required", y.style.display = "block");
938
971
  continue;
939
972
  }
940
973
  if (C !== "")
941
974
  if (m.type === "number") {
942
- const w = Number(C);
943
- Number.isNaN(w) || (p[m.name] = w);
975
+ const x = Number(C);
976
+ Number.isNaN(x) || (p[m.name] = x);
944
977
  } else
945
978
  p[m.name] = C;
946
979
  }
@@ -948,7 +981,7 @@ class G {
948
981
  s.classList.add("foisit-shake"), setTimeout(() => s.classList.remove("foisit-shake"), 400);
949
982
  return;
950
983
  }
951
- f.disabled = !0, f.style.opacity = "0.6", n.forEach((m) => {
984
+ u.disabled = !0, u.style.opacity = "0.6", n.forEach((m) => {
952
985
  m.el.disabled = !0;
953
986
  }), i(p);
954
987
  }, this.messagesContainer.appendChild(s), this.scrollToBottom();
@@ -973,7 +1006,10 @@ class G {
973
1006
  /** Subtle entrance animation for new messages */
974
1007
  animateMessageEntrance(t, e) {
975
1008
  if (!t) return;
976
- t.style.transition = `opacity ${e}ms cubic-bezier(0.22, 0.9, 0.32, 1), transform ${Math.max(120, e)}ms cubic-bezier(0.22, 0.9, 0.32, 1)`, requestAnimationFrame(() => {
1009
+ t.style.transition = `opacity ${e}ms cubic-bezier(0.22, 0.9, 0.32, 1), transform ${Math.max(
1010
+ 120,
1011
+ e
1012
+ )}ms cubic-bezier(0.22, 0.9, 0.32, 1)`, requestAnimationFrame(() => {
977
1013
  t.style.opacity = "1", t.style.transform = "translateY(0)";
978
1014
  });
979
1015
  const i = () => {
@@ -994,8 +1030,8 @@ class G {
994
1030
  return;
995
1031
  }
996
1032
  const n = s - i, a = performance.now(), o = (c) => {
997
- const f = Math.min(1, (c - a) / t), r = 1 - Math.pow(1 - f, 3);
998
- e.scrollTop = Math.round(i + n * r), f < 1 && requestAnimationFrame(o);
1033
+ const u = Math.min(1, (c - a) / t), r = 1 - Math.pow(1 - u, 3);
1034
+ e.scrollTop = Math.round(i + n * r), u < 1 && requestAnimationFrame(o);
999
1035
  };
1000
1036
  requestAnimationFrame(o);
1001
1037
  }
@@ -1017,7 +1053,22 @@ class G {
1017
1053
  /** Simple markdown renderer for AI responses */
1018
1054
  renderMarkdown(t) {
1019
1055
  let e = this.escapeHtml(t);
1020
- return e = e.replace(/```(\w*)\n([\s\S]*?)```/g, (i, s, n) => `<pre class="foisit-code-block"><code${s ? ` class="language-${s}"` : ""}>${n.trim()}</code></pre>`), e = e.replace(/`([^`]+)`/g, '<code class="foisit-inline-code">$1</code>'), e = e.replace(/^###### (.+)$/gm, '<h6 class="foisit-md-h6">$1</h6>'), e = e.replace(/^##### (.+)$/gm, '<h5 class="foisit-md-h5">$1</h5>'), e = e.replace(/^#### (.+)$/gm, '<h4 class="foisit-md-h4">$1</h4>'), e = e.replace(/^### (.+)$/gm, '<h3 class="foisit-md-h3">$1</h3>'), e = e.replace(/^## (.+)$/gm, '<h2 class="foisit-md-h2">$1</h2>'), e = e.replace(/^# (.+)$/gm, '<h1 class="foisit-md-h1">$1</h1>'), e = e.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>"), e = e.replace(/__([^_]+)__/g, "<strong>$1</strong>"), e = e.replace(/\*([^*]+)\*/g, "<em>$1</em>"), e = e.replace(new RegExp("(?<!_)_([^_]+)_(?!_)", "g"), "<em>$1</em>"), e = e.replace(/~~([^~]+)~~/g, "<del>$1</del>"), e = e.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer" class="foisit-md-link">$1</a>'), e = e.replace(/^[\-\*] (.+)$/gm, '<li class="foisit-md-li">$1</li>'), e = e.replace(/(<li class="foisit-md-li">.*<\/li>\n?)+/g, (i) => `<ul class="foisit-md-ul">${i}</ul>`), e = e.replace(/^\d+\. (.+)$/gm, '<li class="foisit-md-li">$1</li>'), e = e.replace(new RegExp('(?<!<\\/ul>)(<li class="foisit-md-li">.*<\\/li>\\n?)+', "g"), (i) => i.includes("<ul") ? i : `<ol class="foisit-md-ol">${i}</ol>`), e = e.replace(/^&gt; (.+)$/gm, '<blockquote class="foisit-md-blockquote">$1</blockquote>'), e = e.replace(/^(---|___|\*\*\*)$/gm, '<hr class="foisit-md-hr">'), e = e.replace(/\n\n+/g, '</p><p class="foisit-md-p">'), e = e.replace(/\n/g, "<br>"), e.match(/^<(h[1-6]|ul|ol|pre|blockquote|hr|p)/) || (e = `<p class="foisit-md-p">${e}</p>`), e;
1056
+ return e = e.replace(/```(\w*)\n([\s\S]*?)```/g, (i, s, n) => `<pre class="foisit-code-block"><code${s ? ` class="language-${s}"` : ""}>${n.trim()}</code></pre>`), e = e.replace(
1057
+ /`([^`]+)`/g,
1058
+ '<code class="foisit-inline-code">$1</code>'
1059
+ ), e = e.replace(/^###### (.+)$/gm, '<h6 class="foisit-md-h6">$1</h6>'), e = e.replace(/^##### (.+)$/gm, '<h5 class="foisit-md-h5">$1</h5>'), e = e.replace(/^#### (.+)$/gm, '<h4 class="foisit-md-h4">$1</h4>'), e = e.replace(/^### (.+)$/gm, '<h3 class="foisit-md-h3">$1</h3>'), e = e.replace(/^## (.+)$/gm, '<h2 class="foisit-md-h2">$1</h2>'), e = e.replace(/^# (.+)$/gm, '<h1 class="foisit-md-h1">$1</h1>'), e = e.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>"), e = e.replace(/__([^_]+)__/g, "<strong>$1</strong>"), e = e.replace(/\*([^*]+)\*/g, "<em>$1</em>"), e = e.replace(new RegExp("(?<!_)_([^_]+)_(?!_)", "g"), "<em>$1</em>"), e = e.replace(/~~([^~]+)~~/g, "<del>$1</del>"), e = e.replace(
1060
+ /\[([^\]]+)\]\(([^)]+)\)/g,
1061
+ '<a href="$2" target="_blank" rel="noopener noreferrer" class="foisit-md-link">$1</a>'
1062
+ ), e = e.replace(/^[\-\*] (.+)$/gm, '<li class="foisit-md-li">$1</li>'), e = e.replace(
1063
+ /(<li class="foisit-md-li">.*<\/li>\n?)+/g,
1064
+ (i) => `<ul class="foisit-md-ul">${i}</ul>`
1065
+ ), e = e.replace(/^\d+\. (.+)$/gm, '<li class="foisit-md-li">$1</li>'), e = e.replace(
1066
+ new RegExp('(?<!<\\/ul>)(<li class="foisit-md-li">.*<\\/li>\\n?)+', "g"),
1067
+ (i) => i.includes("<ul") ? i : `<ol class="foisit-md-ol">${i}</ol>`
1068
+ ), e = e.replace(
1069
+ /^&gt; (.+)$/gm,
1070
+ '<blockquote class="foisit-md-blockquote">$1</blockquote>'
1071
+ ), e = e.replace(/^(---|___|\*\*\*)$/gm, '<hr class="foisit-md-hr">'), e = e.replace(/\n\n+/g, '</p><p class="foisit-md-p">'), e = e.replace(/\n/g, "<br>"), e.match(/^<(h[1-6]|ul|ol|pre|blockquote|hr|p)/) || (e = `<p class="foisit-md-p">${e}</p>`), e;
1021
1072
  }
1022
1073
  readFileAsDataURL(t) {
1023
1074
  return new Promise((e, i) => {
@@ -1030,7 +1081,10 @@ class G {
1030
1081
  try {
1031
1082
  const i = URL.createObjectURL(t), s = new Image();
1032
1083
  s.onload = () => {
1033
- const n = { width: s.naturalWidth || s.width, height: s.naturalHeight || s.height };
1084
+ const n = {
1085
+ width: s.naturalWidth || s.width,
1086
+ height: s.naturalHeight || s.height
1087
+ };
1034
1088
  URL.revokeObjectURL(i), e(n);
1035
1089
  }, s.onerror = () => {
1036
1090
  URL.revokeObjectURL(i), e({ width: 0, height: 0 });
@@ -1064,57 +1118,93 @@ class G {
1064
1118
  injectOverlayStyles() {
1065
1119
  if (document.getElementById("foisit-overlay-styles")) return;
1066
1120
  const t = document.createElement("style");
1067
- t.id = "foisit-overlay-styles", t.textContent = `
1068
- :root {
1069
- /* LIGHT MODE (Default) - Smoother gradient */
1070
- /* Changed: Softer, right-focused radial highlight to avoid a heavy white bottom */
1071
- --foisit-bg: radial-gradient(ellipse at 75% 30%, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.03));
1072
- --foisit-border: 1px solid rgba(255, 255, 255, 0.25);
1073
- --foisit-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
1074
- --foisit-text: #333;
1075
-
1076
- /* Input */
1077
- --foisit-input-color: #333;
1078
- --foisit-input-placeholder: rgba(60, 60, 67, 0.6);
1121
+ t.id = "foisit-overlay-styles";
1122
+ const e = this.config.theme || "glass", i = this.config.themeColors || {};
1123
+ if (e === "solid") {
1124
+ const s = i.background || "#1a1a2e", n = i.text || "#ffffff", a = i.accent || "linear-gradient(135deg, #667eea 0%, #764ba2 100%)", o = i.userBubbleBg || "rgba(102, 126, 234, 0.2)", c = i.systemBubbleBg || "rgba(255, 255, 255, 0.08)", u = i.border || "rgba(255, 255, 255, 0.1)";
1125
+ t.textContent = `
1126
+ :root {
1127
+ /* SOLID THEME - Custom Colors */
1128
+ --foisit-bg: ${s};
1129
+ --foisit-border: 1px solid ${u};
1130
+ --foisit-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
1131
+ --foisit-text: ${n};
1132
+ --foisit-accent: ${a};
1133
+ --foisit-backdrop: none;
1079
1134
 
1080
- /* Bubbles */
1081
- --foisit-bubble-user-bg: rgba(0, 0, 0, 0.04);
1082
- --foisit-bubble-user-text: #333;
1135
+ /* Input */
1136
+ --foisit-input-color: ${n};
1137
+ --foisit-input-placeholder: ${n}99;
1083
1138
 
1084
- --foisit-bubble-sys-bg: rgba(255, 255, 255, 0.45);
1085
- --foisit-bubble-sys-text: #333;
1139
+ /* Bubbles */
1140
+ --foisit-bubble-user-bg: ${o};
1141
+ --foisit-bubble-user-text: ${n};
1086
1142
 
1087
- /* Form Colors */
1088
- --foisit-req-star: #ef4444; /* Red asterisk */
1089
- --foisit-error-text: #dc2626;
1090
- --foisit-error-border: #fca5a5;
1091
- }
1143
+ --foisit-bubble-sys-bg: ${c};
1144
+ --foisit-bubble-sys-text: ${n}ee;
1092
1145
 
1093
- @media (prefers-color-scheme: dark) {
1146
+ /* Form Colors */
1147
+ --foisit-req-star: #f87171;
1148
+ --foisit-error-text: #fca5a5;
1149
+ --foisit-error-border: #f87171;
1150
+ }
1151
+ `;
1152
+ } else
1153
+ t.textContent = `
1094
1154
  :root {
1095
- /* DARK MODE */
1096
- --foisit-bg: linear-gradient(135deg, rgba(40, 40, 40, 0.65), rgba(40, 40, 40, 0.25));
1097
- --foisit-border: 1px solid rgba(255, 255, 255, 0.1);
1098
- --foisit-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
1099
- --foisit-text: #fff;
1155
+ /* LIGHT MODE (Default) - Smoother gradient */
1156
+ /* Changed: Softer, right-focused radial highlight to avoid a heavy white bottom */
1157
+ --foisit-bg: radial-gradient(ellipse at 75% 30%, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.03));
1158
+ --foisit-border: 1px solid rgba(255, 255, 255, 0.25);
1159
+ --foisit-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
1160
+ --foisit-text: #333;
1161
+ --foisit-backdrop: blur(20px);
1100
1162
 
1101
1163
  /* Input */
1102
- --foisit-input-color: white;
1103
- --foisit-input-placeholder: rgba(235, 235, 245, 0.5);
1164
+ --foisit-input-color: #333;
1165
+ --foisit-input-placeholder: rgba(60, 60, 67, 0.6);
1104
1166
 
1105
1167
  /* Bubbles */
1106
- --foisit-bubble-user-bg: rgba(255, 255, 255, 0.1);
1107
- --foisit-bubble-user-text: white;
1168
+ --foisit-bubble-user-bg: rgba(0, 0, 0, 0.04);
1169
+ --foisit-bubble-user-text: #333;
1108
1170
 
1109
- --foisit-bubble-sys-bg: rgba(255, 255, 255, 0.05);
1110
- --foisit-bubble-sys-text: rgba(255, 255, 255, 0.9);
1171
+ --foisit-bubble-sys-bg: rgba(255, 255, 255, 0.45);
1172
+ --foisit-bubble-sys-text: #333;
1111
1173
 
1112
1174
  /* Form Colors */
1113
- --foisit-req-star: #f87171;
1114
- --foisit-error-text: #fca5a5;
1115
- --foisit-error-border: #f87171;
1175
+ --foisit-req-star: #ef4444; /* Red asterisk */
1176
+ --foisit-error-text: #dc2626;
1177
+ --foisit-error-border: #fca5a5;
1116
1178
  }
1117
- }
1179
+
1180
+ @media (prefers-color-scheme: dark) {
1181
+ :root {
1182
+ /* DARK MODE */
1183
+ --foisit-bg: linear-gradient(135deg, rgba(40, 40, 40, 0.65), rgba(40, 40, 40, 0.25));
1184
+ --foisit-border: 1px solid rgba(255, 255, 255, 0.1);
1185
+ --foisit-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
1186
+ --foisit-text: #fff;
1187
+ --foisit-backdrop: blur(20px);
1188
+
1189
+ /* Input */
1190
+ --foisit-input-color: white;
1191
+ --foisit-input-placeholder: rgba(235, 235, 245, 0.5);
1192
+
1193
+ /* Bubbles */
1194
+ --foisit-bubble-user-bg: rgba(255, 255, 255, 0.1);
1195
+ --foisit-bubble-user-text: white;
1196
+
1197
+ --foisit-bubble-sys-bg: rgba(255, 255, 255, 0.05);
1198
+ --foisit-bubble-sys-text: rgba(255, 255, 255, 0.9);
1199
+
1200
+ /* Form Colors */
1201
+ --foisit-req-star: #f87171;
1202
+ --foisit-error-text: #fca5a5;
1203
+ --foisit-error-border: #f87171;
1204
+ }
1205
+ }
1206
+ `;
1207
+ t.textContent += `
1118
1208
 
1119
1209
  @keyframes foisitPulse {
1120
1210
  0%, 100% { transform: scale(0.8); opacity: 0.5; }
@@ -1162,8 +1252,8 @@ class G {
1162
1252
  border: var(--foisit-border);
1163
1253
  box-shadow: var(--foisit-shadow);
1164
1254
 
1165
- backdrop-filter: blur(20px);
1166
- -webkit-backdrop-filter: blur(20px);
1255
+ backdrop-filter: var(--foisit-backdrop);
1256
+ -webkit-backdrop-filter: var(--foisit-backdrop);
1167
1257
 
1168
1258
  border-radius: 18px;
1169
1259
  display: none;
@@ -1372,8 +1462,8 @@ class G {
1372
1462
  border: 1px solid rgba(255,255,255,0.2);
1373
1463
  background: var(--foisit-bg);
1374
1464
  color: var(--foisit-text);
1375
- backdrop-filter: blur(10px);
1376
- -webkit-backdrop-filter: blur(10px);
1465
+ backdrop-filter: var(--foisit-backdrop);
1466
+ -webkit-backdrop-filter: var(--foisit-backdrop);
1377
1467
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
1378
1468
  cursor: pointer;
1379
1469
  pointer-events: auto;
@@ -1475,14 +1565,18 @@ class G {
1475
1565
  }
1476
1566
  class Y {
1477
1567
  constructor(t) {
1478
- this.config = t, this.isActivated = !1, this.lastProcessedInput = "", this.processingLock = !1, this.defaultIntroMessage = "How can I help you?", this.commandHandler = new z({
1568
+ this.config = t, this.isActivated = !1, this.lastProcessedInput = "", this.processingLock = !1, this.defaultIntroMessage = "How can I help you?", this.commandHandler = new N({
1479
1569
  enableSmartIntent: this.config.enableSmartIntent !== !1,
1480
1570
  intentEndpoint: this.config.intentEndpoint
1481
- }), this.fallbackHandler = new W(), typeof window < "u" && typeof document < "u" ? (this.voiceProcessor = new B(), this.textToSpeech = new P(), this.stateManager = new _(), this.gestureHandler = new R(), this.overlayManager = new G({
1571
+ }), this.fallbackHandler = new z(), typeof window < "u" && typeof document < "u" ? (this.voiceProcessor = new W(), this.textToSpeech = new P(), this.stateManager = new _(), this.gestureHandler = new R(), this.overlayManager = new G({
1482
1572
  floatingButton: this.config.floatingButton,
1483
1573
  inputPlaceholder: this.config.inputPlaceholder,
1484
- enableGestureActivation: this.config.enableGestureActivation
1485
- }), this.overlayManager.setExternalCommandExecutor(async (e) => this.commandHandler.executeCommand(e)), this.config.commands.forEach((e) => this.commandHandler.addCommand(e)), this.config.fallbackResponse && this.fallbackHandler.setFallbackMessage(this.config.fallbackResponse), this.overlayManager.registerCallbacks(
1574
+ enableGestureActivation: this.config.enableGestureActivation,
1575
+ theme: this.config.theme,
1576
+ themeColors: this.config.themeColors
1577
+ }), this.overlayManager.setExternalCommandExecutor(async (e) => this.commandHandler.executeCommand(e)), this.config.commands.forEach(
1578
+ (e) => this.commandHandler.addCommand(e)
1579
+ ), this.config.fallbackResponse && this.fallbackHandler.setFallbackMessage(this.config.fallbackResponse), this.overlayManager.registerCallbacks(
1486
1580
  async (e) => {
1487
1581
  if (typeof e == "string") {
1488
1582
  this.overlayManager.addMessage(e, "user"), await this.handleCommand(e);
@@ -1491,24 +1585,32 @@ class Y {
1491
1585
  if (e && typeof e == "object") {
1492
1586
  const i = e, s = i.label ?? i.commandId ?? "Selection";
1493
1587
  this.overlayManager.addMessage(String(s), "user"), this.overlayManager.showLoading();
1494
- const n = await this.commandHandler.executeCommand(i);
1588
+ const n = await this.commandHandler.executeCommand(
1589
+ i
1590
+ );
1495
1591
  this.overlayManager.hideLoading(), this.processResponse(n);
1496
1592
  }
1497
1593
  },
1498
1594
  () => console.log("AssistantService: Overlay closed.")
1499
- )) : (this.voiceProcessor = void 0, this.textToSpeech = void 0, this.stateManager = void 0, this.gestureHandler = void 0, this.overlayManager = void 0, this.config.commands.forEach((e) => this.commandHandler.addCommand(e)), this.config.fallbackResponse && this.fallbackHandler.setFallbackMessage(this.config.fallbackResponse));
1595
+ )) : (this.voiceProcessor = void 0, this.textToSpeech = void 0, this.stateManager = void 0, this.gestureHandler = void 0, this.overlayManager = void 0, this.config.commands.forEach(
1596
+ (e) => this.commandHandler.addCommand(e)
1597
+ ), this.config.fallbackResponse && this.fallbackHandler.setFallbackMessage(this.config.fallbackResponse));
1500
1598
  }
1501
1599
  /** Start listening for activation and commands */
1502
1600
  startListening() {
1503
1601
  if (typeof window > "u" || !this.voiceProcessor) {
1504
- console.log("AssistantService: Voice is disabled or unavailable; startListening() is a no-op.");
1602
+ console.log(
1603
+ "AssistantService: Voice is disabled or unavailable; startListening() is a no-op."
1604
+ );
1505
1605
  return;
1506
1606
  }
1507
1607
  }
1508
1608
  /** Stop listening */
1509
1609
  stopListening() {
1510
1610
  if (typeof window > "u" || !this.voiceProcessor) {
1511
- console.log("AssistantService: Voice unavailable; stopListening() is a no-op."), this.isActivated = !1;
1611
+ console.log(
1612
+ "AssistantService: Voice unavailable; stopListening() is a no-op."
1613
+ ), this.isActivated = !1;
1512
1614
  return;
1513
1615
  }
1514
1616
  this.voiceProcessor.stopListening(), this.isActivated = !1;
@@ -1559,7 +1661,10 @@ class Y {
1559
1661
  return;
1560
1662
  }
1561
1663
  if (e.type === "error") {
1562
- this.fallbackHandler.handleFallback(t), this.overlayManager.addMessage(this.fallbackHandler.getFallbackMessage(), "system");
1664
+ this.fallbackHandler.handleFallback(t), this.overlayManager.addMessage(
1665
+ this.fallbackHandler.getFallbackMessage(),
1666
+ "system"
1667
+ );
1563
1668
  return;
1564
1669
  }
1565
1670
  if ((e.type === "ambiguous" || e.type === "confirm") && e.options) {
@@ -1585,7 +1690,9 @@ class Y {
1585
1690
  this.overlayManager.showLoading();
1586
1691
  let i;
1587
1692
  try {
1588
- i = await this.commandHandler.executeCommand(e);
1693
+ i = await this.commandHandler.executeCommand(
1694
+ e
1695
+ );
1589
1696
  } finally {
1590
1697
  this.overlayManager.hideLoading();
1591
1698
  }
@@ -1639,7 +1746,9 @@ class Y {
1639
1746
  this.overlayManager.addMessage(String(n), "user"), this.overlayManager.showLoading();
1640
1747
  let a;
1641
1748
  try {
1642
- a = await this.commandHandler.executeCommand(s);
1749
+ a = await this.commandHandler.executeCommand(
1750
+ s
1751
+ );
1643
1752
  } finally {
1644
1753
  this.overlayManager.hideLoading();
1645
1754
  }
@@ -1656,7 +1765,7 @@ const q = F(null);
1656
1765
  let M = null;
1657
1766
  const Z = ({ config: d, children: t }) => {
1658
1767
  const [e, i] = I(null), [s, n] = I(!1);
1659
- return $(() => {
1768
+ return H(() => {
1660
1769
  M ? console.warn(
1661
1770
  "Multiple AssistantProvider instances detected. Reusing global AssistantService."
1662
1771
  ) : (console.log("Initializing global AssistantService..."), M = new Y(d));
@@ -1667,7 +1776,7 @@ const Z = ({ config: d, children: t }) => {
1667
1776
  };
1668
1777
  }, [d]), !s || !e ? /* @__PURE__ */ k("div", { children: "Loading Assistant..." }) : /* @__PURE__ */ k(q.Provider, { value: e, children: t });
1669
1778
  }, K = () => {
1670
- const d = N(q);
1779
+ const d = B(q);
1671
1780
  if (console.log("assistant", d), !d)
1672
1781
  throw new Error("useAssistant must be used within an AssistantProvider");
1673
1782
  return d;
@@ -1681,7 +1790,7 @@ const Z = ({ config: d, children: t }) => {
1681
1790
  }, className: "assistant-activator", children: d });
1682
1791
  }, et = (d) => {
1683
1792
  const [t, e] = I(d.getState());
1684
- return $(() => {
1793
+ return H(() => {
1685
1794
  const i = (s) => {
1686
1795
  e(s);
1687
1796
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foisit/react-wrapper",
3
- "version": "2.4.5",
3
+ "version": "3.0.0",
4
4
  "main": "./index.js",
5
5
  "types": "./index.d.ts",
6
6
  "exports": {
@@ -29,7 +29,7 @@
29
29
  "accessibility",
30
30
  "website-integration"
31
31
  ],
32
- "homepage": "https://foisit-react-demo.netlify.app/",
32
+ "homepage": "https://foisit-react.netlify.app/",
33
33
  "funding": {
34
34
  "type": "github",
35
35
  "url": "https://github.com/sponsors/boluwatifee4"