@foisit/react-wrapper 2.1.2 → 2.4.2
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 +118 -44
- package/index.js +247 -304
- package/index.mjs +1180 -789
- package/lib/services/AssistantService.d.ts +7 -2
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("react/jsx-runtime"),u=require("react"),I={};function E(){return g.jsx("div",{className:I.container,children:g.jsx("h1",{children:"Welcome to ReactWrapper!"})})}class L{constructor(){this.endpoint="https://foisit-ninja.netlify.app/.netlify/functions/intent"}async determineIntent(e,t,s){try{const i=await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userInput:e,context:s,commands:t.map(c=>({id:c.id,command:c.command,description:c.description,keywords:c.keywords,parameters:c.parameters}))})});if(!i.ok)throw new Error("Proxy API request failed");return await i.json()}catch(i){return console.error("Foisit AI Error:",i),{type:"unknown"}}}}class M{constructor(e=!0){this.commands=new Map,this.pendingConfirmation=null,this.conversationContext=null,this.enableSmartIntent=!0,this.enableSmartIntent=e,this.aiService=new L}addCommand(e,t){let s;if(typeof e=="string"){if(!t)throw new Error("Action is required when passing a command string.");s={command:e,action:t,id:`cmd_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}}else s=e,s.id||(s.id=`cmd_${Date.now()}_${Math.random().toString(36).substr(2,9)}`);const i=s.command.toLowerCase();this.commands.set(i,s)}removeCommand(e){const t=e.toLowerCase();this.commands.has(t)&&this.commands.delete(t)}async executeCommand(e){var c;if(typeof e=="object"&&this.conversationContext){const o=Array.from(this.commands.values()).find(a=>{var n;return a.id===((n=this.conversationContext)==null?void 0:n.commandId)});if(o){const a={...this.conversationContext.params,...e};return this.conversationContext=null,this.runAction(o,a)}}const t=(typeof e=="string"?e:"").toLowerCase().trim();if(this.pendingConfirmation)if(t==="yes"||t==="y"||t==="confirm"){const o=this.pendingConfirmation;return this.pendingConfirmation=null,this.runAction(o)}else return t==="no"||t==="n"||t==="cancel"?(this.pendingConfirmation=null,{type:"success",message:"Action cancelled."}):{type:"ambiguous",message:`Please confirm: Are you sure you want to ${this.pendingConfirmation.description||this.pendingConfirmation.command}?`,options:[{label:"Yes",value:"yes"},{label:"No",value:"no"}]};if(!this.conversationContext){const o=this.commands.get(t);if(o){if(!o.parameters||o.parameters.length===0)return o.critical?(this.pendingConfirmation=o,{type:"ambiguous",message:`Are you sure you want to ${o.description||o.command}?`,options:[{label:"Yes",value:"yes"},{label:"No",value:"no"}]}):this.runAction(o);this.conversationContext={commandId:o.id||"",params:{}};const a=await Promise.all(o.parameters.map(async n=>{let h=n.options;if(n.getOptions)try{h=await n.getOptions()}catch(m){console.error(`Error fetching options for ${n.name}`,m)}return{name:n.name,label:n.name.charAt(0).toUpperCase()+n.name.slice(1),value:"",required:n.required,type:n.type||"string",options:h}}));return{type:"form",message:o.description||`Please fill in the details for ${o.command}:`,fields:a}}}const s=Array.from(this.commands.values());if(this.enableSmartIntent){const o=await this.aiService.determineIntent(t,s,this.conversationContext);if(o.type==="match"&&o.match){const a=s.find(n=>n.id===o.match);if(a){const n={...((c=this.conversationContext)==null?void 0:c.params)||{},...o.params||{}};if(o.incomplete){if(this.conversationContext={commandId:a.id,params:n},a.parameters&&a.parameters.length>0){const h=await Promise.all(a.parameters.map(async m=>{let d=m.options;if(m.getOptions)try{d=await m.getOptions()}catch(f){console.error(`Error fetching options for ${m.name}`,f)}return{name:m.name,label:m.name.charAt(0).toUpperCase()+m.name.slice(1),value:n[m.name]||"",required:m.required,type:m.type||"string",options:d}}));return{type:"form",message:o.message||`Please fill in the details for ${a.command}:`,fields:h}}return{type:"ambiguous",message:o.message||`Need more info for ${a.command}...`}}return this.conversationContext=null,a.critical?(this.pendingConfirmation={...a,action:()=>a.action(n)},{type:"ambiguous",message:`Are you sure you want to ${a.description||a.command}?`,options:[{label:"Yes",value:"yes"},{label:"No",value:"no"}]}):this.runAction(a,n)}}else if(o.type==="ambiguous"&&o.options)return{type:"ambiguous",message:"Did you mean...",options:o.options.map(a=>({label:a.label,value:a.label}))}}return{type:"ambiguous",message:"I'm not sure what you mean. Here is what I can do:",options:s.map(o=>({label:o.command,value:o.command}))}}async runAction(e,t){try{const s=await e.action(t);return typeof s=="string"?{type:"success",message:s}:s&&s.type?s:{type:"success",message:`Executed: ${e.command}`}}catch(s){return{type:"error",message:s.message||"An error occurred during execution."}}}getCommands(){return Array.from(this.commands.keys())}}class k{constructor(){this.synth=window.speechSynthesis}speak(e,t){if(!this.synth){console.error("SpeechSynthesis API is not supported in this browser.");return}const s=new SpeechSynthesisUtterance(e);t&&(s.pitch=t.pitch||1,s.rate=t.rate||1,s.volume=t.volume||1),s.onend=()=>{console.log("Speech finished.")},s.onerror=i=>{console.error("Error during speech synthesis:",i.error)},this.synth.speak(s)}stopSpeaking(){this.synth&&this.synth.cancel()}}class P{constructor(){this.fallbackMessage="Sorry, I didn’t understand that."}setFallbackMessage(e){this.fallbackMessage=e}handleFallback(e){console.log(this.fallbackMessage),new k().speak(this.fallbackMessage)}}class T{constructor(e="en-US"){this.isListening=!1,this.isStoppedSpeechRecog=!1,this.restartAllowed=!0}startListening(e){console.warn("VoiceProcessor: Voice interaction is currently DISABLED.")}stopListening(){if(console.log("VoiceProcessor: Stopping listening..."),this.isStoppedSpeechRecog=!0,this.restartAllowed=!1,!this.isListening){console.warn("VoiceProcessor: Already stopped. Skipping stop...");return}try{this.recognition.stop(),this.isListening=!1,console.log("VoiceProcessor: Listening stopped.")}catch(e){console.error("VoiceProcessor: Failed to stop SpeechRecognition:",e)}}handleResult(e,t){}handleEnd(){console.log("VoiceProcessor: Session ended."),this.isListening=!1,this.restartAllowed&&!this.isStoppedSpeechRecog&&(console.log("VoiceProcessor: Restarting session due to unexpected stop..."),setTimeout(()=>this.startListening(()=>{}),560))}handleError(e){console.error("VoiceProcessor: Error occurred:",e.error),e.error==="no-speech"?console.log("VoiceProcessor: No speech detected."):e.error==="audio-capture"&&console.log("VoiceProcessor: Microphone not detected."),this.isListening=!1}}class B{constructor(){this.lastTap=0}setupDoubleTapListener(e){document.addEventListener("dblclick",()=>{e()}),document.addEventListener("touchend",t=>{const s=new Date().getTime(),i=s-this.lastTap;i<300&&i>0&&e(),this.lastTap=s})}}function D(){if(document.querySelector("#assistant-styles")){console.log("Styles already injected");return}const e=document.createElement("style");e.id="assistant-styles",e.innerHTML=`
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const A=require("react/jsx-runtime"),C=require("react"),N={};function W(){return A.jsx("div",{className:N.container,children:A.jsx("h1",{children:"Welcome to ReactWrapper!"})})}class T{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(r=>({id:r.id,command:r.command,description:r.description,parameters:r.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 B{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 T);return}this.enableSmartIntent=t.enableSmartIntent??!0,this.enableSmartIntent&&(this.openAIService=new T(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??{},a=this.getCommandById(c);if(!a)return{message:"That command is not available.",type:"error"};const p=this.sanitizeParamsForCommand(a,f),m=(a.parameters??[]).filter(S=>S.required).filter(S=>p[S.name]==null||p[S.name]==="");return m.length>0?(this.context={commandId:this.getCommandIdentifier(a),params:p},{message:`Please provide the required details for "${a.command}".`,type:"form",fields:m}):a.critical?(this.pendingConfirmation={commandId:this.getCommandIdentifier(a),params:p},this.buildConfirmResponse(a)):this.safeRunAction(a,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 o={...this.context.params,...t};if(n.critical)return this.context=null,this.pendingConfirmation={commandId:this.getCommandIdentifier(n),params:o},this.buildConfirmResponse(n);const r=await this.safeRunAction(n,o);return this.context=null,this.normalizeResponse(r)}const e=t.trim().toLowerCase();if(this.pendingConfirmation){const n=e;if(["yes","y","confirm","ok","okay"].includes(n)){const{commandId:o,params:r}=this.pendingConfirmation;this.pendingConfirmation=null;const c=this.getCommandById(o);return c?this.safeRunAction(c,r):{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,o=(n.parameters??[]).filter(r=>r.required);return o.length>0?(this.context={commandId:this.getCommandIdentifier(n),params:{}},{message:`Please provide the required details for "${n.command}".`,type:"form",fields:o}):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(),o=await this.openAIService.determineIntent(e,n,this.context);return this.handleAIResult(o)}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"};const i=t.params??{},s=this.sanitizeParamsForCommand(e,i),n=e.allowAiParamExtraction===!1?{}:s,r=(e.parameters??[]).filter(f=>f.required).filter(f=>n[f.name]==null||n[f.name]==="");if(t.incomplete||r.length>0){if(this.context={commandId:this.getCommandIdentifier(e),params:n},!(e.collectRequiredViaForm!==!1)&&this.shouldAskSingleQuestion(r)){const p=r.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:r}}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 o=n.trim();if(!o){delete i[s.name];continue}i[s.name]=o}if(s.type==="number"){const o=typeof n=="number"?n:Number(n==null?void 0:n.toString().trim());if(Number.isNaN(o)){delete i[s.name];continue}if(typeof s.min=="number"&&o<s.min){delete i[s.name];continue}if(typeof s.max=="number"&&o>s.max){delete i[s.name];continue}i[s.name]=o}if(s.type==="date"){const o=i[s.name];if(typeof o=="string"){const r=o.trim();this.isIsoDateString(r)?i[s.name]=r:delete i[s.name]}else delete i[s.name]}if(s.type==="select"){const o=typeof n=="string"?n:n==null?void 0:n.toString();if(!o){delete i[s.name];continue}if(Array.isArray(s.options)&&s.options.length>0&&!s.options.some(c=>String(c.value)===String(o))){delete i[s.name];continue}i[s.name]=o}if(s.type==="file"){const o=i[s.name],r=o&&typeof o=="object"&&typeof o.name=="string"&&typeof o.size=="number",c=typeof o=="string"&&/^data:[^;]+;base64,/.test(o);(s.delivery??"file")==="base64"?!c&&!r&&delete i[s.name]:r||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 r of this.commands.values()){let c=0;const f=r.command.toLowerCase();t.includes(f)&&(c+=5);const a=r.keywords??[];for(const p of a){const g=p.toLowerCase().trim();g&&(t===g?c+=4:t.includes(g)&&(c+=3))}c>0&&e.push({cmd:r,score:c})}if(e.length===0)return null;e.sort((r,c)=>c.score-r.score);const i=e[0].score,s=e.filter(r=>r.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(r=>({label:r.cmd.command,value:r.cmd.command,commandId:r.cmd.id}))};const n=s[0].cmd,o=(n.parameters??[]).filter(r=>r.required);return o.length>0?(this.context={commandId:this.getCommandIdentifier(n),params:{}},{message:`Please provide the required details for "${n.command}".`,type:"form",fields:o}):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),o=Date.now();if(n&&o-n.ts<6e4){i.options=n.options;return}try{const r=await i.getOptions();this.selectOptionsCache.set(s,{options:r,ts:o}),i.options=r}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 q{constructor(){this.synth=window.speechSynthesis}speak(t,e){if(!this.synth){console.error("SpeechSynthesis API is not supported in this browser.");return}const i=new SpeechSynthesisUtterance(t);e&&(i.pitch=e.pitch||1,i.rate=e.rate||1,i.volume=e.volume||1),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 q().speak(this.fallbackMessage)}getFallbackMessage(){return this.fallbackMessage}}const P=()=>{const d=window;return d.SpeechRecognition??d.webkitSpeechRecognition??null};class O{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=P();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");window.addEventListener("foisit:tts-start",this.onTTSStart),window.addEventListener("foisit:tts-end",this.onTTSEnd),this.visibilityHandler=()=>{var s;if(document.hidden){try{(s=this.recognition)==null||s.stop()}catch{}this.emitStatus(this.ttsSpeaking?"speaking":"idle")}else this.isListening&&!this.ttsSpeaking&&this.safeRestart()},document.addEventListener("visibilitychange",this.visibilityHandler)}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 P()!==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 o=t.resultIndex;o<t.results.length;o++){const r=t.results[o],c=r&&r[0],f=((n=(s=c==null?void 0:c.transcript)==null?void 0:s.trim)==null?void 0:n.call(s))||"",a=(c==null?void 0:c.confidence)??0;if(f&&!(!r.isFinal&&e.interimResults===!1)&&!(r.isFinal&&a<i))try{this.hadResultThisSession=!0,this.resultCallback(f,!!r.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 j{constructor(){this.lastTap=0}setupDoubleTapListener(t){this.destroy(),this.dblClickListener=()=>{t()},document.addEventListener("dblclick",this.dblClickListener),this.touchEndListener=()=>{const e=new Date().getTime(),i=e-this.lastTap;i<300&&i>0&&t(),this.lastTap=e},document.addEventListener("touchend",this.touchEndListener)}destroy(){this.dblClickListener&&document.removeEventListener("dblclick",this.dblClickListener),this.touchEndListener&&document.removeEventListener("touchend",this.touchEndListener),this.dblClickListener=void 0,this.touchEndListener=void 0}}function U(){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,382 +31,325 @@
|
|
|
31
31
|
border-radius: 50%;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
`,document.head.appendChild(e),console.log("Gradient styles injected")}function R(){if(document.querySelector("#gradient-indicator"))return;const r=document.createElement("div");r.id="gradient-indicator",D(),r.classList.add("gradient-indicator"),document.body.appendChild(r),console.log("Gradient indicator added to the DOM")}function H(){const r=document.querySelector("#gradient-indicator");r&&(r.remove(),console.log("Gradient indicator removed from the DOM"))}class N{constructor(){this.state="idle",this.subscribers=[]}getState(){return this.state}setState(e){this.state=e,this.notifySubscribers(),console.log("State updated:",e),e==="listening"?R():H()}subscribe(e){this.subscribers.push(e)}notifySubscribers(){this.subscribers.forEach(e=>e(this.state))}}const l=class l{constructor(e){this.isOpen=!1,this.submitCallback=null,this.closeCallback=null,this.chatContainer=null,this.config={},e&&(this.config=e),this.injectStyles(),this.injectOverlay(),this.injectFloatingButton(),this.setupEventListeners(),this.chatContainer=document.getElementById("foisit-chat-history")}destroy(){const e=document.getElementById(l.OVERLAY_ID);e&&e.remove();const t=document.getElementById(l.STYLES_ID);t&&t.remove();const s=document.getElementById("foisit-floating-btn");s&&s.remove(),this.isOpen=!1,this.chatContainer=null,this.submitCallback=null,this.closeCallback=null}registerCallbacks(e,t){this.submitCallback=e,this.closeCallback=t||null}show(e,t){const s=document.getElementById(l.OVERLAY_ID),i=document.getElementById(l.INPUT_ID);this.chatContainer=document.getElementById("foisit-chat-history"),s&&i&&(this.submitCallback=e,this.closeCallback=t||null,s.style.display="flex",setTimeout(()=>{s.classList.add("visible"),i.focus(),i.focus(),i.value="",this.chatContainer&&(this.chatContainer.innerHTML="")},10),this.isOpen=!0)}hide(){const e=document.getElementById(l.OVERLAY_ID);e&&(e.classList.remove("visible"),setTimeout(()=>{e.style.display="none"},300),this.isOpen=!1,this.closeCallback&&this.closeCallback())}toggle(e,t){this.isOpen?this.hide():this.show(e,t)}addMessage(e,t="system"){if(!this.chatContainer)return;const s=document.createElement("div");s.className=`foisit-bubble ${t}`,s.textContent=e,this.chatContainer.appendChild(s),this.scrollToBottom()}addOptions(e){if(!this.chatContainer)return;const t=document.createElement("div");t.className="foisit-options-container",e.forEach(s=>{const i=document.createElement("button");i.className="foisit-option-chip",i.textContent=s.label,i.onclick=()=>{this.addMessage(s.label,"user"),this.submitCallback&&this.submitCallback(s.value)},t.appendChild(i)}),this.chatContainer.appendChild(t),this.scrollToBottom()}injectFloatingButton(){var i,c,o,a;if(((i=this.config.floatingButton)==null?void 0:i.visible)===!1)return;const e=document.getElementById("foisit-floating-btn");e&&e.remove();const t=document.createElement("div");t.id="foisit-floating-btn",t.className="foisit-floating-btn",t.title=((c=this.config.floatingButton)==null?void 0:c.tooltip)||"Open Foisit Assistant";const s=(o=this.config.floatingButton)==null?void 0:o.position;s&&(t.style.bottom=s.bottom,t.style.right=s.right),(a=this.config.floatingButton)!=null&&a.customHtml?t.innerHTML=this.config.floatingButton.customHtml:t.innerHTML=`
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
34
|
+
`,document.head.appendChild(t),console.log("Gradient styles injected")}function D(){if(document.querySelector("#gradient-indicator"))return;const d=document.createElement("div");d.id="gradient-indicator",U(),d.classList.add("gradient-indicator"),document.body.appendChild(d),console.log("Gradient indicator added to the DOM")}function $(){const d=document.querySelector("#gradient-indicator");d&&(d.remove(),console.log("Gradient indicator removed from the DOM"))}class V{constructor(){this.state="idle",this.subscribers=[]}getState(){return this.state}setState(t){this.state=t,this.notifySubscribers(),console.log("State updated:",t),t==="listening"?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.config=t,this.init()}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();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()}renderFloatingButton(){var s,n,o,r,c,f;const t=document.createElement("button");t.innerHTML=((s=this.config.floatingButton)==null?void 0:s.customHtml)||"🎙️";const e=((o=(n=this.config.floatingButton)==null?void 0:n.position)==null?void 0:o.bottom)||"20px",i=((c=(r=this.config.floatingButton)==null?void 0:r.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="×",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",o=>{var r;if(o.key==="Enter"&&((r=this.input)!=null&&r.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.onSubmit=t,this.onClose=e}toggle(t,e){t&&(this.onSubmit=t),e&&(this.onClose=e),this.isOpen=!this.isOpen,this.chatWindow&&(this.isOpen?(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.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()))}addMessage(t,e){if(!this.messagesContainer)return;const i=document.createElement("div");i.textContent=t,i.className=e==="user"?"foisit-bubble user":"foisit-bubble system",this.messagesContainer.appendChild(i),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 o=i&&typeof i.value=="string"&&i.value.trim()?i.value:i.label;this.onSubmit&&this.onSubmit(o)};s.onclick=n,s.onkeydown=o=>{(o.key==="Enter"||o.key===" ")&&(o.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=[],o=(a,p)=>{const g=document.createElement("div");return g.className="foisit-form-label",g.innerHTML=a+(p?' <span class="foisit-req-star">*</span>':""),g},r=()=>{const a=document.createElement("div");return a.className="foisit-form-error",a.style.display="none",a};(e??[]).forEach(a=>{const p=document.createElement("div");p.className="foisit-form-group";const g=a.description||a.name;p.appendChild(o(g,a.required));let m;if(a.type==="select"){const l=document.createElement("select");l.className="foisit-form-input";const b=document.createElement("option");b.value="",b.textContent="Select...",l.appendChild(b);const x=h=>{(h??[]).forEach(w=>{const y=document.createElement("option");y.value=String(w.value??w.label??""),y.textContent=String(w.label??w.value??""),l.appendChild(y)})};if(Array.isArray(a.options)&&a.options.length)x(a.options);else if(typeof a.getOptions=="function"){const h=a.getOptions,w=document.createElement("option");w.value="",w.textContent="Loading...",l.appendChild(w),Promise.resolve().then(()=>h()).then(y=>{for(;l.options.length>1;)l.remove(1);x(y)}).catch(()=>{for(;l.options.length>1;)l.remove(1);const y=document.createElement("option");y.value="",y.textContent="Error loading options",l.appendChild(y)})}a.defaultValue!=null&&(l.value=String(a.defaultValue)),m=l}else if(a.type==="file"){const l=a,b=document.createElement("input");b.className="foisit-form-input",b.type="file",l.accept&&Array.isArray(l.accept)&&(b.accept=l.accept.join(",")),l.multiple&&(b.multiple=!0),l.capture&&(l.capture===!0?b.setAttribute("capture",""):b.setAttribute("capture",String(l.capture))),b.addEventListener("change",async()=>{const x=Array.from(b.files||[]),h=S;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 y=l.maxSizeBytes??1/0,u=x.reduce((v,E)=>v+E.size,0);if(x.some(v=>v.size>y)){h.textContent=`One or more files exceed the maximum size of ${Math.round(y/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(!x.every(L=>L.type?v.some(I=>I.startsWith(".")?L.name.toLowerCase().endsWith(I.toLowerCase()):L.type===I||L.type.startsWith(I.split("/")[0]+"/")):!0)){h.textContent="One or more files have an unsupported type.",h.style.display="block";return}}}),m=b}else{const l=document.createElement("input");l.className="foisit-form-input",a.type==="string"&&(l.placeholder=a.placeholder||"Type here..."),a.type==="number"?(l.type="number",typeof a.min=="number"&&(l.min=String(a.min)),typeof a.max=="number"&&(l.max=String(a.max)),typeof a.step=="number"&&(l.step=String(a.step)),a.defaultValue!=null&&(l.value=String(a.defaultValue))):a.type==="date"?(l.type="date",typeof a.min=="string"&&(l.min=a.min),typeof a.max=="string"&&(l.max=a.max),a.defaultValue!=null&&(l.value=String(a.defaultValue))):(l.type="text",a.defaultValue!=null&&(l.value=String(a.defaultValue))),m=l}const S=r();p.appendChild(m),p.appendChild(S),n.push({name:a.name,type:a.type,el:m,required:a.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 a=>{a.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,y=Array.from(w.files||[]);if(m.required&&y.length===0){g=!0,w.classList.add("foisit-error-border"),h&&(h.textContent="This file is required",h.style.display="block");continue}if(y.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(y[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(y[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?y:y[0];else if(k==="base64")try{const v=await Promise.all(y.map(E=>this.readFileAsDataURL(E)));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 S=(m.el.value??"").toString().trim(),l=m.el.parentElement,b=l==null?void 0:l.querySelector(".foisit-form-error");if(m.required&&(S==null||S==="")){g=!0,m.el.classList.add("foisit-error-border"),b&&(b.textContent="This field is required",b.style.display="block");continue}if(S!=="")if(m.type==="number"){const x=Number(S);Number.isNaN(x)||(p[m.name]=x)}else p[m.name]=S}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)}destroy(){var t;(t=this.container)==null||t.remove(),this.container=null,this.chatWindow=null,this.messagesContainer=null,this.input=null,this.isOpen=!1}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 o=setTimeout(()=>{n||(n=!0,URL.revokeObjectURL(i),e(0))},5e3);s.preload="metadata",s.onloadedmetadata=()=>{if(n)return;n=!0,clearTimeout(o);const c=s.duration||0;URL.revokeObjectURL(i),e(c)},s.onerror=()=>{n||(n=!0,clearTimeout(o),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);
|
|
46
|
+
|
|
47
|
+
/* Bubbles */
|
|
48
|
+
--foisit-bubble-user-bg: rgba(0, 0, 0, 0.04);
|
|
49
|
+
--foisit-bubble-user-text: #333;
|
|
50
|
+
|
|
51
|
+
--foisit-bubble-sys-bg: rgba(255, 255, 255, 0.45);
|
|
52
|
+
--foisit-bubble-sys-text: #333;
|
|
53
|
+
|
|
54
|
+
/* Form Colors */
|
|
55
|
+
--foisit-req-star: #ef4444; /* Red asterisk */
|
|
56
|
+
--foisit-error-text: #dc2626;
|
|
57
|
+
--foisit-error-border: #fca5a5;
|
|
51
58
|
}
|
|
52
59
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
@media (prefers-color-scheme: dark) {
|
|
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;
|
|
67
|
+
|
|
68
|
+
/* Input */
|
|
69
|
+
--foisit-input-color: white;
|
|
70
|
+
--foisit-input-placeholder: rgba(235, 235, 245, 0.5);
|
|
71
|
+
|
|
72
|
+
/* Bubbles */
|
|
73
|
+
--foisit-bubble-user-bg: rgba(255, 255, 255, 0.1);
|
|
74
|
+
--foisit-bubble-user-text: white;
|
|
75
|
+
|
|
76
|
+
--foisit-bubble-sys-bg: rgba(255, 255, 255, 0.05);
|
|
77
|
+
--foisit-bubble-sys-text: rgba(255, 255, 255, 0.9);
|
|
78
|
+
|
|
79
|
+
/* Form Colors */
|
|
80
|
+
--foisit-req-star: #f87171;
|
|
81
|
+
--foisit-error-text: #fca5a5;
|
|
82
|
+
--foisit-error-border: #f87171;
|
|
83
|
+
}
|
|
56
84
|
}
|
|
57
85
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
border-radius: 16px;
|
|
62
|
-
overflow: hidden;
|
|
63
|
-
/* Stronger Frosted Look (User Provided) */
|
|
64
|
-
background: linear-gradient(
|
|
65
|
-
135deg,
|
|
66
|
-
rgba(255, 255, 255, 0.25),
|
|
67
|
-
rgba(255, 255, 255, 0.05)
|
|
68
|
-
);
|
|
69
|
-
backdrop-filter: blur(20px);
|
|
70
|
-
-webkit-backdrop-filter: blur(20px);
|
|
71
|
-
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
|
|
72
|
-
border: 1px solid rgba(255, 255, 255, 0.4);
|
|
73
|
-
display: flex;
|
|
74
|
-
flex-direction: column;
|
|
86
|
+
@keyframes foisitPulse {
|
|
87
|
+
0%, 100% { transform: scale(0.8); opacity: 0.5; }
|
|
88
|
+
50% { transform: scale(1.2); opacity: 1; }
|
|
75
89
|
}
|
|
76
90
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
font-size: 16px;
|
|
82
|
-
color: #333;
|
|
83
|
-
padding: 18px 20px 12px 20px;
|
|
84
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
85
|
-
outline: none;
|
|
86
|
-
text-align: left;
|
|
87
|
-
resize: none;
|
|
88
|
-
min-height: 48px;
|
|
89
|
-
max-height: 200px;
|
|
90
|
-
overflow-y: auto;
|
|
91
|
+
@keyframes foisitShake {
|
|
92
|
+
0%, 100% { transform: translateX(0); }
|
|
93
|
+
25% { transform: translateX(-4px); }
|
|
94
|
+
75% { transform: translateX(4px); }
|
|
91
95
|
}
|
|
96
|
+
.foisit-shake { animation: foisitShake 0.4s ease-in-out; }
|
|
92
97
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
/* Container */
|
|
99
|
+
.foisit-overlay-container {
|
|
100
|
+
position: fixed;
|
|
101
|
+
inset: 0;
|
|
102
|
+
z-index: 2147483647;
|
|
103
|
+
pointer-events: none;
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: column;
|
|
106
|
+
justify-content: flex-end;
|
|
107
|
+
align-items: flex-end;
|
|
108
|
+
padding: 20px;
|
|
109
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
96
110
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
background: linear-gradient(
|
|
101
|
-
135deg,
|
|
102
|
-
rgba(40, 40, 40, 0.65),
|
|
103
|
-
rgba(40, 40, 40, 0.25)
|
|
104
|
-
);
|
|
105
|
-
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
106
|
-
}
|
|
107
|
-
#${l.INPUT_ID} {
|
|
108
|
-
color: white;
|
|
109
|
-
}
|
|
110
|
-
#${l.INPUT_ID}::placeholder {
|
|
111
|
-
color: rgba(235, 235, 245, 0.6);
|
|
112
|
-
}
|
|
113
|
-
.foisit-watermark {
|
|
114
|
-
color: rgba(255, 255, 255, 0.5);
|
|
115
|
-
}
|
|
111
|
+
|
|
112
|
+
.foisit-overlay-container * {
|
|
113
|
+
box-sizing: border-box;
|
|
116
114
|
}
|
|
117
115
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
116
|
+
/* Chat Window - Dynamic Height */
|
|
117
|
+
.foisit-chat {
|
|
118
|
+
position: absolute;
|
|
119
|
+
top: 20px;
|
|
120
|
+
right: 20px;
|
|
121
|
+
width: min(420px, 92vw);
|
|
122
|
+
|
|
123
|
+
/* FIX: Auto height to prevent empty space */
|
|
124
|
+
height: auto;
|
|
125
|
+
min-height: 120px;
|
|
126
|
+
max-height: 80vh;
|
|
123
127
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
text-transform: capitalize;
|
|
128
|
+
background: var(--foisit-bg);
|
|
129
|
+
border: var(--foisit-border);
|
|
130
|
+
box-shadow: var(--foisit-shadow);
|
|
128
131
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
backdrop-filter: blur(20px);
|
|
133
|
+
-webkit-backdrop-filter: blur(20px);
|
|
134
|
+
|
|
135
|
+
border-radius: 18px;
|
|
136
|
+
display: none;
|
|
137
|
+
flex-direction: column;
|
|
138
|
+
overflow: hidden;
|
|
139
|
+
pointer-events: auto;
|
|
140
|
+
transform-origin: top right;
|
|
141
|
+
transition: opacity 0.2s, transform 0.2s cubic-bezier(0.2, 0.9, 0.2, 1);
|
|
142
|
+
}
|
|
132
143
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
144
|
+
.foisit-header {
|
|
145
|
+
display: flex;
|
|
146
|
+
align-items: center;
|
|
147
|
+
justify-content: space-between;
|
|
148
|
+
padding: 12px 16px;
|
|
149
|
+
font-weight: 600;
|
|
150
|
+
font-size: 14px;
|
|
151
|
+
color: var(--foisit-text);
|
|
152
|
+
border-bottom: 1px solid rgba(127,127,127,0.08); /* Subtle separator */
|
|
153
|
+
}
|
|
136
154
|
|
|
155
|
+
.foisit-close {
|
|
156
|
+
background: transparent;
|
|
157
|
+
border: none;
|
|
158
|
+
color: var(--foisit-text);
|
|
159
|
+
opacity: 0.5;
|
|
160
|
+
font-size: 24px;
|
|
161
|
+
line-height: 1;
|
|
162
|
+
cursor: pointer;
|
|
163
|
+
padding: 0;
|
|
164
|
+
width: 28px;
|
|
165
|
+
height: 28px;
|
|
166
|
+
display: flex;
|
|
167
|
+
align-items: center;
|
|
168
|
+
justify-content: center;
|
|
169
|
+
transition: opacity 0.2s;
|
|
170
|
+
}
|
|
171
|
+
.foisit-close:hover { opacity: 1; }
|
|
137
172
|
|
|
138
|
-
/*
|
|
139
|
-
|
|
173
|
+
/* Message Area */
|
|
174
|
+
.foisit-messages {
|
|
140
175
|
flex: 1;
|
|
141
176
|
overflow-y: auto;
|
|
142
177
|
padding: 16px;
|
|
143
178
|
display: flex;
|
|
144
179
|
flex-direction: column;
|
|
145
|
-
gap:
|
|
146
|
-
|
|
180
|
+
gap: 10px;
|
|
181
|
+
/* Ensure it doesn't get too tall initially */
|
|
182
|
+
min-height: 60px;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* Make sure empty state isn't huge */
|
|
186
|
+
.foisit-messages:empty {
|
|
187
|
+
display: none;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* Only show messages container if it has children */
|
|
191
|
+
.foisit-messages:not(:empty) {
|
|
192
|
+
display: flex;
|
|
147
193
|
}
|
|
148
194
|
|
|
195
|
+
/* Bubbles */
|
|
149
196
|
.foisit-bubble {
|
|
150
|
-
max-width:
|
|
151
|
-
padding: 8px
|
|
152
|
-
border-radius:
|
|
153
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
197
|
+
max-width: 90%;
|
|
198
|
+
padding: 8px 14px;
|
|
199
|
+
border-radius: 14px;
|
|
154
200
|
font-size: 14px;
|
|
155
201
|
line-height: 1.4;
|
|
202
|
+
word-wrap: break-word;
|
|
156
203
|
}
|
|
157
204
|
|
|
158
205
|
.foisit-bubble.user {
|
|
159
206
|
align-self: flex-end;
|
|
160
|
-
background:
|
|
161
|
-
color:
|
|
207
|
+
background: var(--foisit-bubble-user-bg);
|
|
208
|
+
color: var(--foisit-bubble-user-text);
|
|
162
209
|
border-bottom-right-radius: 4px;
|
|
163
210
|
}
|
|
164
211
|
|
|
165
212
|
.foisit-bubble.system {
|
|
166
213
|
align-self: flex-start;
|
|
167
|
-
background:
|
|
168
|
-
color:
|
|
214
|
+
background: var(--foisit-bubble-sys-bg);
|
|
215
|
+
color: var(--foisit-bubble-sys-text);
|
|
169
216
|
border-bottom-left-radius: 4px;
|
|
217
|
+
border: 1px solid rgba(255,255,255,0.1);
|
|
170
218
|
}
|
|
171
219
|
|
|
220
|
+
/* Input Area */
|
|
221
|
+
.foisit-input-area {
|
|
222
|
+
padding: 0;
|
|
223
|
+
width: 100%;
|
|
224
|
+
border-top: 1px solid rgba(127,127,127,0.08);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.foisit-input {
|
|
228
|
+
width: 100%;
|
|
229
|
+
background: transparent;
|
|
230
|
+
border: none;
|
|
231
|
+
font-size: 16px;
|
|
232
|
+
color: var(--foisit-input-color);
|
|
233
|
+
padding: 16px 20px;
|
|
234
|
+
outline: none;
|
|
235
|
+
text-align: left;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.foisit-input::placeholder {
|
|
239
|
+
color: var(--foisit-input-placeholder);
|
|
240
|
+
font-weight: 400;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Options & Buttons */
|
|
172
244
|
.foisit-options-container {
|
|
173
245
|
display: flex;
|
|
174
246
|
flex-wrap: wrap;
|
|
175
247
|
gap: 8px;
|
|
176
|
-
margin-left:
|
|
248
|
+
margin-left: 2px;
|
|
249
|
+
margin-top: 4px;
|
|
177
250
|
}
|
|
178
251
|
|
|
179
252
|
.foisit-option-chip {
|
|
180
|
-
padding: 6px
|
|
181
|
-
background:
|
|
182
|
-
border: 1px solid rgba(
|
|
253
|
+
padding: 6px 14px;
|
|
254
|
+
background: var(--foisit-bubble-sys-bg);
|
|
255
|
+
border: 1px solid rgba(127,127,127,0.1);
|
|
183
256
|
border-radius: 20px;
|
|
184
257
|
font-size: 13px;
|
|
185
|
-
color:
|
|
258
|
+
color: var(--foisit-text);
|
|
186
259
|
cursor: pointer;
|
|
187
260
|
transition: all 0.2s;
|
|
261
|
+
font-weight: 500;
|
|
188
262
|
}
|
|
189
|
-
|
|
190
263
|
.foisit-option-chip:hover {
|
|
191
|
-
background: rgba(
|
|
192
|
-
transform: translateY(-1px);
|
|
193
|
-
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
|
|
264
|
+
background: rgba(127,127,127,0.15);
|
|
194
265
|
}
|
|
195
266
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
color: white;
|
|
200
|
-
}
|
|
201
|
-
.foisit-bubble.system {
|
|
202
|
-
background: rgba(255, 255, 255, 0.05);
|
|
203
|
-
color: rgba(255, 255, 255, 0.9);
|
|
204
|
-
}
|
|
205
|
-
.foisit-option-chip {
|
|
206
|
-
background: rgba(255, 255, 255, 0.1);
|
|
207
|
-
border-color: rgba(255, 255, 255, 0.2);
|
|
208
|
-
color: white;
|
|
209
|
-
}
|
|
210
|
-
.foisit-option-chip:hover {
|
|
211
|
-
background: rgba(255, 255, 255, 0.2);
|
|
212
|
-
}
|
|
213
|
-
/* Loading State */
|
|
214
|
-
.foisit-loading-dots {
|
|
215
|
-
display: inline-flex;
|
|
216
|
-
gap: 4px;
|
|
217
|
-
align-items: center;
|
|
218
|
-
padding: 4px 8px;
|
|
219
|
-
background: rgba(255, 255, 255, 0.4);
|
|
220
|
-
border-radius: 12px;
|
|
221
|
-
margin-left: 12px;
|
|
222
|
-
align-self: flex-start;
|
|
223
|
-
}
|
|
224
|
-
.foisit-dot {
|
|
225
|
-
width: 6px;
|
|
226
|
-
height: 6px;
|
|
227
|
-
background: #666;
|
|
228
|
-
border-radius: 50%;
|
|
229
|
-
animation: foisit-bounce 1.4s infinite ease-in-out both;
|
|
230
|
-
}
|
|
231
|
-
.foisit-dot:nth-child(1) { animation-delay: -0.32s; }
|
|
232
|
-
.foisit-dot:nth-child(2) { animation-delay: -0.16s; }
|
|
233
|
-
|
|
234
|
-
@keyframes foisit-bounce {
|
|
235
|
-
0%, 80%, 100% { transform: scale(0); }
|
|
236
|
-
40% { transform: scale(1); }
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/* Floating Trigger Button - Glassmorphism Style */
|
|
240
|
-
.foisit-floating-btn {
|
|
241
|
-
position: fixed;
|
|
242
|
-
bottom: 20px;
|
|
243
|
-
right: 20px;
|
|
244
|
-
width: 52px;
|
|
245
|
-
height: 52px;
|
|
246
|
-
/* Frosted Glass Effect */
|
|
247
|
-
background: linear-gradient(
|
|
248
|
-
135deg,
|
|
249
|
-
rgba(255, 255, 255, 0.25),
|
|
250
|
-
rgba(255, 255, 255, 0.08)
|
|
251
|
-
);
|
|
252
|
-
backdrop-filter: blur(16px);
|
|
253
|
-
-webkit-backdrop-filter: blur(16px);
|
|
254
|
-
border-radius: 50%;
|
|
255
|
-
display: flex;
|
|
256
|
-
align-items: center;
|
|
257
|
-
justify-content: center;
|
|
258
|
-
cursor: pointer;
|
|
259
|
-
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
|
260
|
-
border: 1px solid rgba(255, 255, 255, 0.35);
|
|
261
|
-
z-index: 9998;
|
|
262
|
-
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
.foisit-floating-btn:hover {
|
|
266
|
-
transform: scale(1.08);
|
|
267
|
-
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/* Dark mode for floating button */
|
|
271
|
-
@media (prefers-color-scheme: dark) {
|
|
272
|
-
.foisit-floating-btn {
|
|
273
|
-
background: linear-gradient(
|
|
274
|
-
135deg,
|
|
275
|
-
rgba(60, 60, 60, 0.6),
|
|
276
|
-
rgba(40, 40, 40, 0.35)
|
|
277
|
-
);
|
|
278
|
-
border-color: rgba(255, 255, 255, 0.15);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
.foisit-floating-btn img {
|
|
283
|
-
width: 100%;
|
|
284
|
-
height: 100%;
|
|
285
|
-
object-fit: cover;
|
|
286
|
-
border-radius: 50%;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/* Dark mode support for inputs */
|
|
290
|
-
@media (prefers-color-scheme: dark) {
|
|
291
|
-
.foisit-field-input {
|
|
292
|
-
background: rgba(40, 40, 40, 0.6);
|
|
293
|
-
color: white;
|
|
294
|
-
border-color: rgba(255, 255, 255, 0.1);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
.foisit-watermark {
|
|
298
|
-
color: rgba(255, 255, 255, 0.3);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/* Loading Animation */
|
|
303
|
-
.foisit-bubble.loading span {
|
|
304
|
-
animation: foisit-dots 1.4s infinite ease-in-out both;
|
|
305
|
-
font-size: 20px;
|
|
306
|
-
line-height: 10px;
|
|
307
|
-
margin: 0 1px;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
.foisit-bubble.loading span:nth-child(1) { animation-delay: -0.32s; }
|
|
311
|
-
.foisit-bubble.loading span:nth-child(2) { animation-delay: -0.16s; }
|
|
312
|
-
|
|
313
|
-
@keyframes foisit-dots {
|
|
314
|
-
0%, 80%, 100% { transform: scale(0); opacity: 0.5; }
|
|
315
|
-
40% { transform: scale(1); opacity: 1; }
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/* Form Styles */
|
|
319
|
-
.foisit-form-card {
|
|
320
|
-
align-self: flex-start;
|
|
321
|
-
background: rgba(255, 255, 255, 0.4);
|
|
267
|
+
/* Form Styling */
|
|
268
|
+
.foisit-form {
|
|
269
|
+
background: var(--foisit-bubble-sys-bg);
|
|
322
270
|
padding: 16px;
|
|
323
|
-
border-radius:
|
|
324
|
-
width: 100%;
|
|
325
|
-
box-sizing: border-box;
|
|
326
|
-
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
271
|
+
border-radius: 14px;
|
|
327
272
|
display: flex;
|
|
328
273
|
flex-direction: column;
|
|
329
274
|
gap: 12px;
|
|
275
|
+
width: 100%;
|
|
276
|
+
border: 1px solid rgba(127,127,127,0.1);
|
|
330
277
|
}
|
|
331
278
|
|
|
332
|
-
.foisit-form-
|
|
333
|
-
font-
|
|
334
|
-
font-
|
|
335
|
-
color:
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
.foisit-field-group {
|
|
341
|
-
display: flex;
|
|
342
|
-
flex-direction: column;
|
|
343
|
-
gap: 4px;
|
|
279
|
+
.foisit-form-label {
|
|
280
|
+
font-size: 12px;
|
|
281
|
+
font-weight: 600;
|
|
282
|
+
color: var(--foisit-text);
|
|
283
|
+
opacity: 0.9;
|
|
284
|
+
margin-bottom: 2px;
|
|
344
285
|
}
|
|
345
286
|
|
|
346
|
-
.foisit-
|
|
347
|
-
|
|
348
|
-
font-weight:
|
|
349
|
-
text-transform: uppercase;
|
|
350
|
-
color: rgba(0, 0, 0, 0.5);
|
|
287
|
+
.foisit-req-star {
|
|
288
|
+
color: var(--foisit-req-star);
|
|
289
|
+
font-weight: bold;
|
|
351
290
|
}
|
|
352
291
|
|
|
353
|
-
.foisit-
|
|
354
|
-
|
|
355
|
-
|
|
292
|
+
.foisit-form-input {
|
|
293
|
+
width: 100%;
|
|
294
|
+
padding: 10px;
|
|
356
295
|
border-radius: 8px;
|
|
357
|
-
|
|
296
|
+
border: 1px solid rgba(127,127,127,0.2);
|
|
297
|
+
background: rgba(255,255,255,0.05); /* Very subtle fill */
|
|
298
|
+
color: var(--foisit-text);
|
|
358
299
|
font-size: 14px;
|
|
359
|
-
color: #333;
|
|
360
300
|
outline: none;
|
|
301
|
+
transition: border 0.2s;
|
|
302
|
+
}
|
|
303
|
+
.foisit-form-input:focus {
|
|
304
|
+
border-color: var(--foisit-text);
|
|
305
|
+
background: rgba(255,255,255,0.1);
|
|
361
306
|
}
|
|
362
307
|
|
|
363
|
-
.foisit-
|
|
364
|
-
border-color:
|
|
308
|
+
.foisit-error-border {
|
|
309
|
+
border-color: var(--foisit-error-border) !important;
|
|
365
310
|
}
|
|
366
311
|
|
|
367
|
-
.foisit-form-
|
|
368
|
-
|
|
369
|
-
color:
|
|
370
|
-
border: none;
|
|
371
|
-
border-radius: 8px;
|
|
372
|
-
padding: 10px;
|
|
373
|
-
font-size: 14px;
|
|
374
|
-
font-weight: 500;
|
|
375
|
-
cursor: pointer;
|
|
376
|
-
transition: opacity 0.2s;
|
|
312
|
+
.foisit-form-error {
|
|
313
|
+
font-size: 11px;
|
|
314
|
+
color: var(--foisit-error-text);
|
|
377
315
|
margin-top: 4px;
|
|
378
316
|
}
|
|
379
317
|
|
|
380
|
-
|
|
381
|
-
|
|
318
|
+
/* Loading */
|
|
319
|
+
.foisit-loading-dots {
|
|
320
|
+
display: inline-flex;
|
|
321
|
+
gap: 4px;
|
|
322
|
+
padding: 10px 14px;
|
|
323
|
+
align-self: flex-start;
|
|
382
324
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
.foisit-form-message {
|
|
390
|
-
color: white;
|
|
391
|
-
}
|
|
392
|
-
.foisit-field-group label {
|
|
393
|
-
color: rgba(255, 255, 255, 0.5);
|
|
394
|
-
}
|
|
395
|
-
.foisit-field-input {
|
|
396
|
-
background: rgba(0, 0, 0, 0.2);
|
|
397
|
-
border-color: rgba(255, 255, 255, 0.1);
|
|
398
|
-
color: white;
|
|
399
|
-
}
|
|
400
|
-
.foisit-form-submit {
|
|
401
|
-
background: #fff;
|
|
402
|
-
color: #000;
|
|
403
|
-
}
|
|
325
|
+
.foisit-dot {
|
|
326
|
+
width: 6px;
|
|
327
|
+
height: 6px;
|
|
328
|
+
border-radius: 50%;
|
|
329
|
+
background: var(--foisit-text);
|
|
330
|
+
opacity: 0.4;
|
|
404
331
|
}
|
|
405
332
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
333
|
+
/* Floating Button */
|
|
334
|
+
.foisit-floating-btn {
|
|
335
|
+
position: absolute;
|
|
336
|
+
width: 56px;
|
|
337
|
+
height: 56px;
|
|
338
|
+
border-radius: 50%;
|
|
339
|
+
border: 1px solid rgba(255,255,255,0.2);
|
|
340
|
+
background: var(--foisit-bg);
|
|
341
|
+
color: var(--foisit-text);
|
|
342
|
+
backdrop-filter: blur(10px);
|
|
343
|
+
-webkit-backdrop-filter: blur(10px);
|
|
344
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
345
|
+
cursor: pointer;
|
|
346
|
+
pointer-events: auto;
|
|
347
|
+
display: flex;
|
|
348
|
+
align-items: center;
|
|
349
|
+
justify-content: center;
|
|
350
|
+
font-size: 24px;
|
|
351
|
+
z-index: 100000;
|
|
352
|
+
transition: transform 0.2s;
|
|
353
|
+
}
|
|
354
|
+
.foisit-floating-btn:hover { transform: scale(1.05); }
|
|
355
|
+
`,document.head.appendChild(t)}}class H{constructor(t){this.config=t,this.isActivated=!1,this.lastProcessedInput="",this.processingLock=!1,this.defaultIntroMessage="How can I help you?",this.commandHandler=new B({enableSmartIntent:this.config.enableSmartIntent!==!1,intentEndpoint:this.config.intentEndpoint}),this.fallbackHandler=new z,this.voiceProcessor=new O,this.textToSpeech=new q,this.stateManager=new V,this.gestureHandler=new j,this.overlayManager=new G({floatingButton:this.config.floatingButton,inputPlaceholder:this.config.inputPlaceholder}),this.config.commands.forEach(e=>this.commandHandler.addCommand(e)),this.config.fallbackResponse&&this.fallbackHandler.setFallbackMessage(this.config.fallbackResponse),this.gestureHandler.setupDoubleTapListener(()=>this.toggle()),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."))}startListening(){console.log("AssistantService: Voice is disabled; startListening() is a no-op.")}stopListening(){console.log("AssistantService: Voice is disabled; stopListening() is a no-op."),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)}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 o;try{o=await this.commandHandler.executeCommand(s)}finally{this.overlayManager.hideLoading()}this.processResponse(o)}},()=>{console.log("AssistantService: Overlay closed."),e&&e()})}}const M=C.createContext(null);let R=null;const Y=({config:d,children:t})=>{const[e,i]=C.useState(null),[s,n]=C.useState(!1);return C.useEffect(()=>{R?console.warn("Multiple AssistantProvider instances detected. Reusing global AssistantService."):(console.log("Initializing global AssistantService..."),R=new H(d));const o=R;return i(o),n(!0),()=>{var r;console.log("Cleaning up AssistantService..."),(r=o.destroy)==null||r.call(o),R=null}},[d]),!s||!e?A.jsx("div",{children:"Loading Assistant..."}):A.jsx(M.Provider,{value:e,children:t})},F=()=>{const d=C.useContext(M);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 A.jsx("button",{onClick:i,className:"assistant-activator",children:d})},X=d=>{const[t,e]=C.useState(d.getState());return C.useEffect(()=>{const i=s=>{e(s)};return d.subscribe(i),()=>{d.subscribe(()=>{})}},[d]),t};exports.AssistantActivator=K;exports.AssistantContext=M;exports.AssistantProvider=Y;exports.AssistantService=H;exports.ReactWrapper=W;exports.useAssistant=F;exports.useAssistantState=X;
|