@intelliweave/embedded 1.6.53 → 1.6.55

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.
@@ -140,6 +140,8 @@ interface KnowledgeBaseSource {
140
140
  query?: (query: string) => (KnowledgeBaseItem[] | Promise<KnowledgeBaseItem[]>);
141
141
  /** URL query for remote sources */
142
142
  url?: string;
143
+ /** Pre-packaged knowledge base entries */
144
+ entries?: KnowledgeBaseItem[];
143
145
  }
144
146
  /** Knowledge base item */
145
147
  interface KnowledgeBaseItem {
@@ -565,6 +567,8 @@ declare class IntelliWeave extends EventTarget {
565
567
  userID: string;
566
568
  /** Extra data that will be passed to external knowledge base actions. */
567
569
  extra: any;
570
+ /** URL of the IntelliWeave Hub API */
571
+ hubAPI: string;
568
572
  /** Set model and load data from an API key */
569
573
  load(apiKey: string): Promise<WebWeaverGPTConfig>;
570
574
  /** Set the current model */
@@ -6,7 +6,7 @@ import{v4 as ne}from"uuid";function q(d){let s=(d||"").split(`
6
6
  `);for(let l of c){n=l.indexOf(": ");let a=l.slice(0,n),h=l.slice(n+2);n==-1&&(a=l,h=""),a&&(r[a]!==void 0?r[a]+=`
7
7
  `+h:r[a]=h)}yield r}},t=new TextDecoder,i=d.getReader();for(;;){let{done:n,value:o}=await i.read();if(n)break;s+=t.decode(o,{stream:!0}),yield*e()}s+=t.decode()+`
8
8
 
9
- `,yield*e()}function ae(){if(p().userID)return p().userID;if(typeof localStorage<"u"){let d=localStorage.getItem("intelliweave.uid")||"";return d||(d=ne(),localStorage.setItem("intelliweave.uid",d),d)}else return ne()}var T=class T{constructor(s){this.module="IntelliWeave";this.module=s}get debugEnabled(){return T.debug?!0:typeof window<"u"&&p().debug}log(...s){this.debugEnabled&&console.log(`[IntelliWeave > ${this.module}]`,...s)}debug(...s){this.debugEnabled&&console.debug(`[IntelliWeave > ${this.module}]`,...s)}info(...s){this.debugEnabled&&console.info(`[IntelliWeave > ${this.module}]`,...s)}warn(...s){console.warn(`[IntelliWeave > ${this.module}]`,...s)}error(...s){console.error(`[IntelliWeave > ${this.module}]`,...s)}timer(s,...e){let t=Date.now();return this.debug(`[${s} 0ms] Started`,...e),(...i)=>this.debug(`[${s} ${Math.floor(Date.now()-t)}ms]`,...i)}};T.debug=!1;var u=T;var y=new u("ChatGPT"),L=class{constructor(s){this.id="";this.metadata={};this.config={apiKey:"",endpoint:"",model:"gpt-4-turbo",systemMessage:"",userID:"",stream:!0,maxTokens:4096};this.messages=[];this.tools=[];this.maxToolCallsPerMessage=10;this._hasRemovedToolCallHistorySinceLastMessage=0;this.stats={tokensUsed:0};this.config={...this.config,...s}}async sendMessage(s){this.messages.push({role:"user",content:s}),await this.processMessages(),this._hasRemovedToolCallHistorySinceLastMessage=0;let e=this.messages[this.messages.length-1];return e?.role=="assistant"&&e.content||""}async processMessages(){await this.config.onBeforeMessageProcessing?.(),y.debug("Process message state:",{context:this.config.systemMessage,tools:this.tools.slice(),messages:this.messages.slice(),removedToolCallHistory:this._hasRemovedToolCallHistorySinceLastMessage});let s=this.messages[this.messages.length-1];if(s?.role=="user"||s?.role=="tool")await this.trimMessages(),await this.sendToAPI(),await this.processMessages();else if(s?.role=="assistant"&&s?.tool_calls?.length){for(let e of s.tool_calls)await this.processToolCall(e);await this.processMessages()}}async trimMessages(){for(;;){let s=await this.sendToAPI(!0);if(JSON.stringify(s).length/3.8<this.config.maxTokens)break;if(this.messages.length<2){y.warn("[ChatGPT] Unable to trim messages, no messages left! Please check the size of the system message and the LLM's context window size.");break}for(this.messages=this.messages.slice(Math.floor(this.messages.length/2));this.messages.length&&this.messages[0].role=="tool";)this.messages.shift()}}async sendToAPI(s){let e=0;for(let c=this.messages.length-1;c>=0;c--)if(this.messages[c].role=="assistant"&&this.messages[c].tool_calls){if(e+=1,e>=this.maxToolCallsPerMessage)throw new Error(`Exceeded the maximum tool calls per message limit of ${this.maxToolCallsPerMessage}.`)}else if(this.messages[c].role=="user")break;y.debug("Before LLM state:",{context:this.config.systemMessage,tools:this.tools.slice(),messages:this.messages.slice(),removedToolCallHistory:this._hasRemovedToolCallHistorySinceLastMessage});let t={model:this.config.model,temperature:.2,user:this.config.userID,tools:[],stream:!!this.config.stream,max_tokens:1024,messages:[{role:"system",content:this.config.systemMessage},...this.messages]};for(let c of this.tools){c.description&&c.description.length>1024&&y.warn(`Tool description for "${c.name}" is too long, it will be truncated.`);let l={type:"function",function:{name:c.name,description:(c.description||"").substring(0,1024),parameters:{type:"object",properties:{}}}};if(Array.isArray(c.params))for(let a of c.params)l.function.parameters.properties[a.name]={type:a.type,description:a.description};else if(c.params){let a=c.params;for(let h in a)l.function.parameters.properties[h]={type:"string",description:a[h]}}t.tools.push(l)}t.user||delete t.user,t.tools.length||delete t.tools;let i={};if(i["Content-Type"]="application/json",this.config.apiKey&&(i.Authorization=`Bearer ${this.config.apiKey}`),s)return t;let n=await fetch(this.config.endpoint||"https://api.openai.com/v1/chat/completions",{method:"POST",headers:i,body:JSON.stringify(t)});if(!n.ok){let c=`${n.status} ${n.statusText}`;try{let a=await n.json();c=a.errorText||a.error?.message||a.error||c}catch{}let l=new Error(c);throw l.code=n.status,l}let o=null,r=null;if(this.config.stream)for await(let c of oe(n.body)){if(c.data=="[DONE]")break;if(!c.data)continue;let l=JSON.parse(c.data);if(r){for(let a in l.choices[0].delta)if(typeof l.choices[0].delta[a]=="string"){if(a=="role"&&r[a]==l.choices[0].delta[a])continue;r[a]=(r[a]||"")+l.choices[0].delta[a]}for(let a of l.choices[0].delta.tool_calls||[]){if(r.tool_calls||(r.tool_calls=[]),!r.tool_calls[a.index]){r.tool_calls[a.index]=a;continue}let h=r.tool_calls[a.index];h.function=h.function||{},h.function.name=(h.function.name||"")+(a.function?.name||""),h.function.arguments=(h.function.arguments||"")+(a.function?.arguments||"")}}else r={chunkID:l.id,...l.choices[0].delta};r?.content&&!r.content.startsWith("{")&&this.config.onAIMessage?.(r.content,!0)}else o=await n.json(),this.stats.tokensUsed+=o.usage?.total_tokens||0,y.debug(`Used ${o.usage?.total_tokens||0} tokens, total used: ${this.stats.tokensUsed}`),r=o.choices?.[0]?.message;if(r||(y.warn("No response block in API response."),r={role:"assistant",content:""}),r.role=="user")throw new Error("API returned a user message, which is not allowed.");this.processIncomingMessage(r),this.messages.push(r),r.content&&this.config.onAIMessage?.(r.content,!1)}processIncomingMessage(s){}registerTool(s){this.tools.push(s)}async processToolCall(s){try{let e=this.tools.find(n=>n.name==s.function.name);if(!e)throw new Error(`Tool "${s.function.name}" not found.`);let t=JSON.parse(s.function.arguments);this.config.onAIToolStart?.(s.function.name,t);let i=await e.callback(t);if(typeof i!="string"&&(i=JSON.stringify(i)||""),(i===""||i==="undefined")&&(i="success"),this._hasRemovedToolCallHistorySinceLastMessage<3&&e.removeFromMessageHistory){y.debug(`Removing tool call history for "${e.name}"`),this._hasRemovedToolCallHistorySinceLastMessage++,this.messages=this.messages.filter(n=>n.role!="assistant"||!n.tool_calls?.find(o=>o.id==s.id));return}else e.removeFromMessageHistory&&y.info(`The AI attempted to reuse a tool call that we removed from history. Skipping... "${e.name}"`);this.messages.push({role:"tool",content:i,tool_call_id:s.id})}catch(e){y.warn(`Unable to process tool call for "${s?.function?.name}"`,e),this.messages.push({role:"tool",content:`Error: ${e.message}`,tool_call_id:s.id})}}resetConversation(){this.messages=[]}};import{v4 as de}from"uuid";import ve from"minisearch";var re=[{id:"search",type:"action",name:"Search the knowledge base.",content:"Search the knowledge base for information, actions, tools, tours, UI elements, etc. Use this on EVERY request if you don't have information. If the user asks for personal information, use this. If the user asks you to do something, use this to find the tool you need.",isContext:!0,removeFromMessageHistory:!0,parameters:[{name:"query",type:"string",description:"The search query"}],action:async(d,s)=>{let e=await s.knowledgeBase.search(d.query),t=s;t._lastKBsearch=d.query,t._nextRequestUseKBitems=e,s.submitAnalyticsEvent({type:"kb-search",query:d.query,results:e});let i=e.filter(o=>o.type!="action").map(o=>"id="+o.id).join(", ")||"(none)",n=e.filter(o=>o.type=="action").map(o=>"name="+o._functionID).join(", ")||"(none)";return`Search complete, context has been updated. New info entries found: ${i}. New tools available: ${n}.`}}];var x=new u("KnowledgeBase"),le=1,k=class d{constructor(s){this._sources=[{id:"core.internal",query:async()=>re}];this._windowSources=[];this.lastResults=[];this.manualEntries=[];this.ai=s}registerSource(s,e){let t=s;return typeof s=="function"&&(e=s,t=`source.${le++}`),this._sources.push({id:t,query:e}),t}removeSource(s){this._sources=this.sources.filter(e=>e.id!==s&&e.query!==s)}addEntry(s){this.manualEntries.push(s)}removeEntry(s){this.manualEntries=this.manualEntries.filter(e=>e.id!==s)}get sources(){let s=this._sources;return typeof window<"u"&&p().knowledgeBaseSources&&(s=s.concat(p().knowledgeBaseSources.map(e=>({id:e.name,query:e})))),s=s.concat(this._windowSources),s=s.filter(e=>!e.disabled),s}async search(s){x.debug(`Searching knowledge base for: ${s}`);let e=new Event("webweaver_kb_search",{bubbles:!0,cancelable:!0});e.query=s,e.entries=[],e.sources=[],typeof document<"u"&&document.dispatchEvent(e),this._windowSources=e.sources;let i=(await Promise.all(this.sources.map(async c=>{try{let l=Date.now(),a=await c.query(s);return x.debug(`Source '${c.id}' took ${Date.now()-l}ms`),a||[]}catch(l){return x.warn(`Knowledge source '${c.id}' failed:`,l),[]}}))).flat();i=i.concat(e.entries),i=i.concat(this.manualEntries),p().knowledgeBase&&(i=i.concat(p().knowledgeBase)),i=i.filter(c=>c&&!c.disabled);for(let c=0;c<i.length;c++){let l=i[c];if(l.id=l.id||`temp.${c}`,l._functionID=l.id.replaceAll(/[^a-zA-Z0-9_]/g,"_"),!l.action&&l.type=="tour"&&(l.action=a=>{throw new Error("This tour does not have an action. You must perform the tour content manually.")}),!l.action&&l.type=="info"&&(l.action=a=>{throw new Error("This item does not have an action. Use the content to provide information to the user instead.")}),l.parameters&&!Array.isArray(l.parameters)){let a=l.parameters,h=[];for(let w in a)h.push({name:w,type:"string",description:l.parameters[w]});l.parameters=h}}let n=new ve({fields:["id","type","name","content","tags"],storeFields:[],searchOptions:{boost:{name:3,tags:2},fuzzy:.2}});n.addAll(i);let r=n.search(s).map(c=>i.find(l=>l.id==c.id));for(let c of i)c.isContext&&(r.find(l=>l.id===c.id)||r.push(c));return this.lastResults=r,x.debug("Found results:",r),r}getCachedEntry(s){return this.lastResults.find(e=>e.id==s||e._functionID==s)}registerSourceFromURL(s,e){e||(e=`external.${le++}`),x.debug(`Registering remote knowledge base source: ${s}`);let t=[],i=[],n=!0,o=async(c,l)=>{x.debug(`Calling remote knowledge base action: ${c.id}`);let a={type:"action",userID:this.ai.userID,extra:this.ai.extra,actionID:c.id,parameters:l},h=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!h.ok)throw new Error(`HTTP Error ${h.status} ${h.statusText}`);let w=await h.json();return r(w.updateItems||[]),w.response},r=c=>{for(let l of c){if(!l.id){x.warn("KB item skipped since it has no ID.",l);continue}let a=t.find(h=>h.id==l.id);if(a){a.name=l.name||a.name||"",a.content=l.content||a.content||"",a.disabled=l.disabled??a.disabled,a.isContext=l.isContext??a.isContext,a.parameters=l.parameters||a.parameters||[],a.tags=l.tags||a.tags,a.type=l.type||a.type;continue}t.push({...l,action:h=>o(l,h)})}};this.registerSource(e,async c=>{if(n&&i.includes(c))return t;let l={type:"search",userID:this.ai?.userID||"",extra:this.ai?.extra||{},query:c},a=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(!a.ok)throw new Error(`HTTP Error ${a.status} ${a.statusText}`);let h=await a.json();return n=!h.noCache,i.includes(c)||i.push(c),r(h.items),t})}clone(){let s=new d(this.ai);return s._sources=this._sources,s._windowSources=this._windowSources,s.manualEntries=this.manualEntries,s}};var ce={name:"@intelliweave/embedded",version:"1.6.53",description:"Integrate IntelliWeave into your app or website.",main:"./dist/webpack/index.js",types:"./dist/webpack/index.d.ts",type:"module",exports:{".":"./dist/webpack/index.js","./component":"./dist/component/component.js","./node":"./dist/node/node.js","./react":"./dist/react/react.js","./webpack":"./dist/webpack/index.js"},scripts:{build:"npm run build:lib && npm run build:docs","build:lib":"tsx build.ts","build:dev":"cross-env DEVELOPMENT=1 npm run build","build:docs":"typedoc src/index.mts --out dist/docs/",deploy:'npm run build && gsutil cp ./dist/web-weaver.min.js gs://metapress-cdn/web-weaver.min.js && gcloud compute url-maps invalidate-cdn-cache mp-cdn-loadbalancer --project="mp-backend-api" --path "/web-weaver.min.js" --async',"start:server":"cd server && npm run start","deploy:server":"cd server && npm run deploy","llm:build":"cd llm-server && docker build -t web-weaver-llm .","llm:start":"npm run llm:build && docker run -it --rm -p 8000:80 --gpus=all web-weaver-llm","llm:deploy.docker":"npm run llm:build && gcloud auth configure-docker us-central1-docker.pkg.dev && docker tag web-weaver-llm us-central1-docker.pkg.dev/ydangle-web-companion/docker-artifacts/web-weaver-llm && docker push us-central1-docker.pkg.dev/ydangle-web-companion/docker-artifacts/web-weaver-llm","llm:deploy":'npm run llm:deploy.docker && gcloud run deploy web-weaver-llm --project=ydangle-web-companion --image=us-central1-docker.pkg.dev/ydangle-web-companion/docker-artifacts/web-weaver-llm --allow-unauthenticated --region=us-central1 --description="Web Weaver LLM" --concurrency=2 --min-instances=0 --timeout=5m --memory=16Gi --cpu=8',prepack:"npm run build",test:"npm run build && tsx --test"},keywords:["web","weaver","ai","assistant","chat"],author:"jjv360",license:"UNLICENSED",devDependencies:{"@types/audioworklet":"^0.0.64","@types/lodash":"^4.17.13","@types/react":"^18.3.12","@types/uuid":"^10.0.0",bestzip:"^2.2.1","cross-env":"^7.0.3","find-cache-dir":"^5.0.0",lodash:"^4.17.21","onnxruntime-web":"^1.20.0",react:"^18.3.1","replace-in-file":"^8.2.0",tsup:"^8.3.5",tsx:"^4.19.2",typedoc:"^0.27.6"},peerDependencies:{"onnxruntime-web":"^1.20.0",react:"^18 || ^19"},dependencies:{minisearch:"^6.3.0","rehype-document":"^7.0.3","rehype-external-links":"^3.0.0","rehype-format":"^5.0.0","rehype-stringify":"^10.0.0","remark-parse":"^11.0.0","remark-rehype":"^11.1.0",unified:"^11.0.4",uuid:"^10.0.0"}};var B=class{constructor(s){this.ai=s}async boolean(s,e){let t=this.ai.clone();t.resetConversation(),t.getContextPrefix=async()=>'You will receive a question and some data. Answer the question by replying only with the word "true" or "false".';let i=await t.sendMessage(s+`
9
+ `,yield*e()}function ae(){if(p().userID)return p().userID;if(typeof localStorage<"u"){let d=localStorage.getItem("intelliweave.uid")||"";return d||(d=ne(),localStorage.setItem("intelliweave.uid",d),d)}else return ne()}var T=class T{constructor(s){this.module="IntelliWeave";this.module=s}get debugEnabled(){return T.debug?!0:typeof window<"u"&&p().debug}log(...s){this.debugEnabled&&console.log(`[IntelliWeave > ${this.module}]`,...s)}debug(...s){this.debugEnabled&&console.debug(`[IntelliWeave > ${this.module}]`,...s)}info(...s){this.debugEnabled&&console.info(`[IntelliWeave > ${this.module}]`,...s)}warn(...s){console.warn(`[IntelliWeave > ${this.module}]`,...s)}error(...s){console.error(`[IntelliWeave > ${this.module}]`,...s)}timer(s,...e){let t=Date.now();return this.debug(`[${s} 0ms] Started`,...e),(...i)=>this.debug(`[${s} ${Math.floor(Date.now()-t)}ms]`,...i)}};T.debug=!1;var u=T;var y=new u("ChatGPT"),L=class{constructor(s){this.id="";this.metadata={};this.config={apiKey:"",endpoint:"",model:"gpt-4-turbo",systemMessage:"",userID:"",stream:!0,maxTokens:4096};this.messages=[];this.tools=[];this.maxToolCallsPerMessage=10;this._hasRemovedToolCallHistorySinceLastMessage=0;this.stats={tokensUsed:0};this.config={...this.config,...s}}async sendMessage(s){this.messages.push({role:"user",content:s}),await this.processMessages(),this._hasRemovedToolCallHistorySinceLastMessage=0;let e=this.messages[this.messages.length-1];return e?.role=="assistant"&&e.content||""}async processMessages(){await this.config.onBeforeMessageProcessing?.(),y.debug("Process message state:",{context:this.config.systemMessage,tools:this.tools.slice(),messages:this.messages.slice(),removedToolCallHistory:this._hasRemovedToolCallHistorySinceLastMessage});let s=this.messages[this.messages.length-1];if(s?.role=="user"||s?.role=="tool")await this.trimMessages(),await this.sendToAPI(),await this.processMessages();else if(s?.role=="assistant"&&s?.tool_calls?.length){for(let e of s.tool_calls)await this.processToolCall(e);await this.processMessages()}}async trimMessages(){for(;;){let s=await this.sendToAPI(!0);if(JSON.stringify(s).length/3.8<this.config.maxTokens)break;if(this.messages.length<2){y.warn("[ChatGPT] Unable to trim messages, no messages left! Please check the size of the system message and the LLM's context window size.");break}for(this.messages=this.messages.slice(Math.floor(this.messages.length/2));this.messages.length&&this.messages[0].role=="tool";)this.messages.shift()}}async sendToAPI(s){let e=0;for(let c=this.messages.length-1;c>=0;c--)if(this.messages[c].role=="assistant"&&this.messages[c].tool_calls){if(e+=1,e>=this.maxToolCallsPerMessage)throw new Error(`Exceeded the maximum tool calls per message limit of ${this.maxToolCallsPerMessage}.`)}else if(this.messages[c].role=="user")break;y.debug("Before LLM state:",{context:this.config.systemMessage,tools:this.tools.slice(),messages:this.messages.slice(),removedToolCallHistory:this._hasRemovedToolCallHistorySinceLastMessage});let t={model:this.config.model,temperature:.2,user:this.config.userID,tools:[],stream:!!this.config.stream,max_tokens:1024,messages:[{role:"system",content:this.config.systemMessage},...this.messages]};for(let c of this.tools){c.description&&c.description.length>1024&&y.warn(`Tool description for "${c.name}" is too long, it will be truncated.`);let l={type:"function",function:{name:c.name,description:(c.description||"").substring(0,1024),parameters:{type:"object",properties:{}}}};if(Array.isArray(c.params))for(let a of c.params)l.function.parameters.properties[a.name]={type:a.type,description:a.description};else if(c.params){let a=c.params;for(let h in a)l.function.parameters.properties[h]={type:"string",description:a[h]}}t.tools.push(l)}t.user||delete t.user,t.tools.length||delete t.tools;let i={};if(i["Content-Type"]="application/json",this.config.apiKey&&(i.Authorization=`Bearer ${this.config.apiKey}`),s)return t;let n=await fetch(this.config.endpoint||"https://api.openai.com/v1/chat/completions",{method:"POST",headers:i,body:JSON.stringify(t)});if(!n.ok){let c=`${n.status} ${n.statusText}`;try{let a=await n.json();c=a.errorText||a.error?.message||a.error||c}catch{}let l=new Error(c);throw l.code=n.status,l}let o=null,r=null;if(this.config.stream)for await(let c of oe(n.body)){if(c.data=="[DONE]")break;if(!c.data)continue;let l=JSON.parse(c.data);if(r){for(let a in l.choices[0].delta)if(typeof l.choices[0].delta[a]=="string"){if(a=="role"&&r[a]==l.choices[0].delta[a])continue;r[a]=(r[a]||"")+l.choices[0].delta[a]}for(let a of l.choices[0].delta.tool_calls||[]){if(r.tool_calls||(r.tool_calls=[]),!r.tool_calls[a.index]){r.tool_calls[a.index]=a;continue}let h=r.tool_calls[a.index];h.function=h.function||{},h.function.name=(h.function.name||"")+(a.function?.name||""),h.function.arguments=(h.function.arguments||"")+(a.function?.arguments||"")}}else r={chunkID:l.id,...l.choices[0].delta};r?.content&&!r.content.startsWith("{")&&this.config.onAIMessage?.(r.content,!0)}else o=await n.json(),this.stats.tokensUsed+=o.usage?.total_tokens||0,y.debug(`Used ${o.usage?.total_tokens||0} tokens, total used: ${this.stats.tokensUsed}`),r=o.choices?.[0]?.message;if(r||(y.warn("No response block in API response."),r={role:"assistant",content:""}),r.role=="user")throw new Error("API returned a user message, which is not allowed.");this.processIncomingMessage(r),this.messages.push(r),r.content&&this.config.onAIMessage?.(r.content,!1)}processIncomingMessage(s){}registerTool(s){this.tools.push(s)}async processToolCall(s){try{let e=this.tools.find(n=>n.name==s.function.name);if(!e)throw new Error(`Tool "${s.function.name}" not found.`);let t=JSON.parse(s.function.arguments);this.config.onAIToolStart?.(s.function.name,t);let i=await e.callback(t);if(typeof i!="string"&&(i=JSON.stringify(i)||""),(i===""||i==="undefined")&&(i="success"),this._hasRemovedToolCallHistorySinceLastMessage<3&&e.removeFromMessageHistory){y.debug(`Removing tool call history for "${e.name}"`),this._hasRemovedToolCallHistorySinceLastMessage++,this.messages=this.messages.filter(n=>n.role!="assistant"||!n.tool_calls?.find(o=>o.id==s.id));return}else e.removeFromMessageHistory&&y.info(`The AI attempted to reuse a tool call that we removed from history. Skipping... "${e.name}"`);this.messages.push({role:"tool",content:i,tool_call_id:s.id})}catch(e){y.warn(`Unable to process tool call for "${s?.function?.name}"`,e),this.messages.push({role:"tool",content:`Error: ${e.message}`,tool_call_id:s.id})}}resetConversation(){this.messages=[]}};import{v4 as de}from"uuid";import ve from"minisearch";var re=[{id:"search",type:"action",name:"Search the knowledge base.",content:"Search the knowledge base for information, actions, tools, tours, UI elements, etc. Use this on EVERY request if you don't have information. If the user asks for personal information, use this. If the user asks you to do something, use this to find the tool you need.",isContext:!0,removeFromMessageHistory:!0,parameters:[{name:"query",type:"string",description:"The search query"}],action:async(d,s)=>{let e=await s.knowledgeBase.search(d.query),t=s;t._lastKBsearch=d.query,t._nextRequestUseKBitems=e,s.submitAnalyticsEvent({type:"kb-search",query:d.query,results:e});let i=e.filter(o=>o.type!="action").map(o=>"id="+o.id).join(", ")||"(none)",n=e.filter(o=>o.type=="action").map(o=>"name="+o._functionID).join(", ")||"(none)";return`Search complete, context has been updated. New info entries found: ${i}. New tools available: ${n}.`}}];var x=new u("KnowledgeBase"),le=1,k=class d{constructor(s){this._sources=[{id:"core.internal",query:async()=>re}];this._windowSources=[];this.lastResults=[];this.manualEntries=[];this.ai=s}registerSource(s,e){let t=s;return typeof s=="function"&&(e=s,t=`source.${le++}`),this._sources.push({id:t,query:e}),t}removeSource(s){this._sources=this.sources.filter(e=>e.id!==s&&e.query!==s)}addEntry(s){this.manualEntries.push(s)}removeEntry(s){this.manualEntries=this.manualEntries.filter(e=>e.id!==s)}get sources(){let s=this._sources;return typeof window<"u"&&p().knowledgeBaseSources&&(s=s.concat(p().knowledgeBaseSources.map(e=>({id:e.name,query:e})))),s=s.concat(this._windowSources),s=s.filter(e=>!e.disabled),s}async search(s){x.debug(`Searching knowledge base for: ${s}`);let e=new Event("webweaver_kb_search",{bubbles:!0,cancelable:!0});e.query=s,e.entries=[],e.sources=[],typeof document<"u"&&document.dispatchEvent(e),this._windowSources=e.sources;let i=(await Promise.all(this.sources.map(async c=>{try{let l=Date.now(),a=await c.query(s);return x.debug(`Source '${c.id}' took ${Date.now()-l}ms`),a||[]}catch(l){return x.warn(`Knowledge source '${c.id}' failed:`,l),[]}}))).flat();i=i.concat(e.entries),i=i.concat(this.manualEntries),p().knowledgeBase&&(i=i.concat(p().knowledgeBase)),i=i.filter(c=>c&&!c.disabled);for(let c=0;c<i.length;c++){let l=i[c];if(l.id=l.id||`temp.${c}`,l._functionID=l.id.replaceAll(/[^a-zA-Z0-9_]/g,"_"),!l.action&&l.type=="tour"&&(l.action=a=>{throw new Error("This tour does not have an action. You must perform the tour content manually.")}),!l.action&&l.type=="info"&&(l.action=a=>{throw new Error("This item does not have an action. Use the content to provide information to the user instead.")}),l.parameters&&!Array.isArray(l.parameters)){let a=l.parameters,h=[];for(let w in a)h.push({name:w,type:"string",description:l.parameters[w]});l.parameters=h}}let n=new ve({fields:["id","type","name","content","tags"],storeFields:[],searchOptions:{boost:{name:3,tags:2},fuzzy:.2}});n.addAll(i);let r=n.search(s).map(c=>i.find(l=>l.id==c.id));for(let c of i)c.isContext&&(r.find(l=>l.id===c.id)||r.push(c));return this.lastResults=r,x.debug("Found results:",r),r}getCachedEntry(s){return this.lastResults.find(e=>e.id==s||e._functionID==s)}registerSourceFromURL(s,e){e||(e=`external.${le++}`),x.debug(`Registering remote knowledge base source: ${s}`);let t=[],i=[],n=!0,o=async(c,l)=>{x.debug(`Calling remote knowledge base action: ${c.id}`);let a={type:"action",userID:this.ai.userID,extra:this.ai.extra,actionID:c.id,parameters:l},h=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!h.ok)throw new Error(`HTTP Error ${h.status} ${h.statusText}`);let w=await h.json();return r(w.updateItems||[]),w.response},r=c=>{for(let l of c){if(!l.id){x.warn("KB item skipped since it has no ID.",l);continue}let a=t.find(h=>h.id==l.id);if(a){a.name=l.name||a.name||"",a.content=l.content||a.content||"",a.disabled=l.disabled??a.disabled,a.isContext=l.isContext??a.isContext,a.parameters=l.parameters||a.parameters||[],a.tags=l.tags||a.tags,a.type=l.type||a.type;continue}t.push({...l,action:h=>o(l,h)})}};this.registerSource(e,async c=>{if(n&&i.includes(c))return t;let l={type:"search",userID:this.ai?.userID||"",extra:this.ai?.extra||{},query:c},a=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(!a.ok)throw new Error(`HTTP Error ${a.status} ${a.statusText}`);let h=await a.json();return n=!h.noCache,i.includes(c)||i.push(c),r(h.items),t})}clone(){let s=new d(this.ai);return s._sources=this._sources,s._windowSources=this._windowSources,s.manualEntries=this.manualEntries,s}};var ce={name:"@intelliweave/embedded",version:"1.6.55",description:"Integrate IntelliWeave into your app or website.",main:"./dist/webpack/index.js",types:"./dist/webpack/index.d.ts",type:"module",exports:{".":"./dist/webpack/index.js","./component":"./dist/component/component.js","./node":"./dist/node/node.js","./react":"./dist/react/react.js","./webpack":"./dist/webpack/index.js"},scripts:{build:"npm run build:lib && npm run build:docs","build:lib":"tsx build.ts","build:dev":"cross-env DEVELOPMENT=1 npm run build","build:docs":"typedoc src/index.mts --out dist/docs/",deploy:'npm run build && gsutil cp ./dist/web-weaver.min.js gs://metapress-cdn/web-weaver.min.js && gcloud compute url-maps invalidate-cdn-cache mp-cdn-loadbalancer --project="mp-backend-api" --path "/web-weaver.min.js" --async',"start:server":"cd server && npm run start","deploy:server":"cd server && npm run deploy","llm:build":"cd llm-server && docker build -t web-weaver-llm .","llm:start":"npm run llm:build && docker run -it --rm -p 8000:80 --gpus=all web-weaver-llm","llm:deploy.docker":"npm run llm:build && gcloud auth configure-docker us-central1-docker.pkg.dev && docker tag web-weaver-llm us-central1-docker.pkg.dev/ydangle-web-companion/docker-artifacts/web-weaver-llm && docker push us-central1-docker.pkg.dev/ydangle-web-companion/docker-artifacts/web-weaver-llm","llm:deploy":'npm run llm:deploy.docker && gcloud run deploy web-weaver-llm --project=ydangle-web-companion --image=us-central1-docker.pkg.dev/ydangle-web-companion/docker-artifacts/web-weaver-llm --allow-unauthenticated --region=us-central1 --description="Web Weaver LLM" --concurrency=2 --min-instances=0 --timeout=5m --memory=16Gi --cpu=8',prepack:"npm run build",test:"npm run build && tsx --test"},keywords:["web","weaver","ai","assistant","chat"],author:"jjv360",license:"UNLICENSED",devDependencies:{"@types/audioworklet":"^0.0.64","@types/lodash":"^4.17.13","@types/react":"^18.3.12","@types/uuid":"^10.0.0",bestzip:"^2.2.1","cross-env":"^7.0.3","find-cache-dir":"^5.0.0",lodash:"^4.17.21","onnxruntime-web":"^1.20.0",react:"^18.3.1","replace-in-file":"^8.2.0",tsup:"^8.3.5",tsx:"^4.19.2",typedoc:"^0.27.6"},peerDependencies:{"onnxruntime-web":"^1.20.0",react:"^18 || ^19"},dependencies:{minisearch:"^6.3.0","rehype-document":"^7.0.3","rehype-external-links":"^3.0.0","rehype-format":"^5.0.0","rehype-stringify":"^10.0.0","remark-parse":"^11.0.0","remark-rehype":"^11.1.0",unified:"^11.0.4",uuid:"^10.0.0"}};var B=class{constructor(s){this.ai=s}async boolean(s,e){let t=this.ai.clone();t.resetConversation(),t.getContextPrefix=async()=>'You will receive a question and some data. Answer the question by replying only with the word "true" or "false".';let i=await t.sendMessage(s+`
10
10
 
11
11
  `+JSON.stringify(e))||"";if(i.toLowerCase().includes("true"))return!0;if(i.toLowerCase().includes("false"))return!1;throw new Error("The AI did not give a boolean answer: "+i)}async choose(s,e,t){t=t.map(o=>o.trim());let i=this.ai.clone();i.resetConversation(),i.getContextPrefix=async()=>"You will receive a question and some data and options. Answer the question by replying with the option you want to choose. Only say the option you want, no additional text.";let n=await i.sendMessage("question:"+s+`
12
12
 
@@ -17,11 +17,11 @@ options:`+t.join(`
17
17
 
18
18
  data:`+JSON.stringify(e)+`
19
19
 
20
- extractions:`+JSON.stringify(i))||"";o=o.replace(/```json/g,"").replace(/```/g,"").replace(/\n/g,"");let r=o.split(",").map(c=>c.trim()).join(",");return JSON.parse(r)}async generateMarkdown(s,e){return this.instruct("Generate a Markdown document based on the input text. Always include a header on every response. Give long detailed answers with many paragraphs, and explain concepts step by step.",s,e)}async instruct(s,e,t){let i=this.ai.clone();return i.resetConversation(),i.getContextPrefix=async()=>s,t&&i.addEventListener("output",o=>{t(o.detail.message)}),await i.sendMessage(e)}};var Z=new u("Main"),P=class P extends EventTarget{constructor(){super(...arguments);this.conversationID=de();this.knowledgeBase=new k(this);this._lastKBsearch="";this.models=[];this.audio=null;this.apiKey="";this.logic=new B(this);this.userID=ae();this.extra=p().extra||{};this._lastSystemMsg="";this.isProcessing=!1}get loaded(){return!!(this.config&&this.currentModel)}async load(e){if(this.apiKey=e,!e)throw new Error("API key is required to load the AI.");try{await Promise.all([(async()=>{Z.debug("Loading configuration...");let t=await fetch("https://intelliweave.ai/api/config/get",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e})});if(!t.ok)throw new Error(`Failed to load configuration: ${t.status} ${t.statusText}`);this.config=await t.json(),Z.debug("Configuration loaded")})(),(async()=>{try{let t=await fetch("https://cdn.intelliweave.ai/models/silero_vad_3.onnx");if(!t.ok)throw new Error(`Failed to load VAD model: ${t.status} ${t.statusText}`);this.vadModel=await t.blob()}catch(t){Z.warn(`Failed to load VAD model, some features will be unavailable. ${t.message}`)}})()]),this.models=[{id:this.config.id,config:this.config.model}],this.setModel(this.config.id);for(let t of this.config.knowledge||[])t.url&&this.knowledgeBase.registerSourceFromURL(t.url);return this.resetConversation(),this.dispatchEvent(new CustomEvent("load",{detail:{ai:this}})),typeof window<"u"&&window.dispatchEvent(new CustomEvent("webweaver_loaded",{detail:{ai:this}})),this.config}catch(t){throw Z.warn("Failed to load:",t),this.error=t,this.dispatchEvent(new CustomEvent("error",{detail:{ai:this,error:t}})),typeof window<"u"&&window.dispatchEvent(new CustomEvent("webweaver_error",{detail:{ai:this,error:t}})),t}}setModel(e){let t=this.models.find(i=>i.id==e);if(!t)throw new Error(`Model with ID "${e}" not found.`);this.currentModel=new L({...t.config,onBeforeMessageProcessing:this.onBeforeMessageProcessing.bind(this),onAIMessage:this.processIncomingMessage.bind(this),onAIToolStart:(i,n)=>{let o=this.knowledgeBase.getCachedEntry(i);this.onAIToolStart?.(o?.id||i,n)}}),this.currentModel.id=t.id,this.currentModel.metadata=t}async getContextPrefix(){let e=p().pageSummary||`You are ${this.config?.name||"IntelliWeave"}. ${this.config?.instructions||"Speak in short sentences."}`;return typeof e=="function"&&(e=await e()),e}async onBeforeMessageProcessing(){this._lastKBsearch||(this._lastKBsearch="__intelliweaveblanksearchforcontextitems__");let e=this._nextRequestUseKBitems||await this.knowledgeBase.search(this._lastKBsearch);this._nextRequestUseKBitems=void 0;let t=await this.getContextPrefix(),i=(this.currentModel.config.maxTokens||4e3)*.5*4,n=0;for(;;){let o=e.slice(),r=0;for(;r<n;){let a=o.findLastIndex(h=>!h.isContext);if(a==-1)throw new Error('Too much context, and no more items to remove. Check the size and number of "isContext: true" knowledge base entries, or use an LLM with a larger context window.');o.splice(a,1)}let c=`${t}
20
+ extractions:`+JSON.stringify(i))||"";o=o.replace(/```json/g,"").replace(/```/g,"").replace(/\n/g,"");let r=o.split(",").map(c=>c.trim()).join(",");return JSON.parse(r)}async generateMarkdown(s,e){return this.instruct("Generate a Markdown document based on the input text. Always include a header on every response. Give long detailed answers with many paragraphs, and explain concepts step by step.",s,e)}async instruct(s,e,t){let i=this.ai.clone();return i.resetConversation(),i.getContextPrefix=async()=>s,t&&i.addEventListener("output",o=>{t(o.detail.message)}),await i.sendMessage(e)}};var Z=new u("Main"),P=class P extends EventTarget{constructor(){super(...arguments);this.conversationID=de();this.knowledgeBase=new k(this);this._lastKBsearch="";this.models=[];this.audio=null;this.apiKey="";this.logic=new B(this);this.userID=ae();this.extra=p().extra||{};this.hubAPI="https://intelliweave.ai/api";this._lastSystemMsg="";this.isProcessing=!1}get loaded(){return!!(this.config&&this.currentModel)}async load(e){if(this.apiKey=e,!e)throw new Error("API key is required to load the AI.");try{await Promise.all([(async()=>{Z.debug("Loading configuration...");let t=await fetch(this.hubAPI+"/config/get",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e})});if(!t.ok)throw new Error(`Failed to load configuration: ${t.status} ${t.statusText}`);this.config=await t.json(),Z.debug("Configuration loaded")})(),(async()=>{try{let t=await fetch("https://cdn.intelliweave.ai/models/silero_vad_3.onnx");if(!t.ok)throw new Error(`Failed to load VAD model: ${t.status} ${t.statusText}`);this.vadModel=await t.blob()}catch(t){Z.warn(`Failed to load VAD model, some features will be unavailable. ${t.message}`)}})()]),this.models=[{id:this.config.id,config:this.config.model}],this.setModel(this.config.id);for(let t of this.config.knowledge||[])t.url&&this.knowledgeBase.registerSourceFromURL(t.url);for(let t of this.config.knowledge||[])t.entries?.length&&this.knowledgeBase.registerSource(t.id,()=>t.entries||[]);return this.resetConversation(),this.dispatchEvent(new CustomEvent("load",{detail:{ai:this}})),typeof window<"u"&&window.dispatchEvent(new CustomEvent("webweaver_loaded",{detail:{ai:this}})),this.config}catch(t){throw Z.warn("Failed to load:",t),this.error=t,this.dispatchEvent(new CustomEvent("error",{detail:{ai:this,error:t}})),typeof window<"u"&&window.dispatchEvent(new CustomEvent("webweaver_error",{detail:{ai:this,error:t}})),t}}setModel(e){let t=this.models.find(i=>i.id==e);if(!t)throw new Error(`Model with ID "${e}" not found.`);this.currentModel=new L({...t.config,onBeforeMessageProcessing:this.onBeforeMessageProcessing.bind(this),onAIMessage:this.processIncomingMessage.bind(this),onAIToolStart:(i,n)=>{let o=this.knowledgeBase.getCachedEntry(i);this.onAIToolStart?.(o?.id||i,n)}}),this.currentModel.id=t.id,this.currentModel.metadata=t}async getContextPrefix(){let e=p().pageSummary||`You are ${this.config?.name||"IntelliWeave"}. ${this.config?.instructions||"Speak in short sentences."}`;return typeof e=="function"&&(e=await e()),e}async onBeforeMessageProcessing(){this._lastKBsearch||(this._lastKBsearch="__intelliweaveblanksearchforcontextitems__");let e=this._nextRequestUseKBitems||await this.knowledgeBase.search(this._lastKBsearch);this._nextRequestUseKBitems=void 0;let t=await this.getContextPrefix(),i=(this.currentModel.config.maxTokens||4e3)*.5*4,n=0;for(;;){let o=e.slice(),r=0;for(;r<n;){let a=o.findLastIndex(h=>!h.isContext);if(a==-1)throw new Error('Too much context, and no more items to remove. Check the size and number of "isContext: true" knowledge base entries, or use an LLM with a larger context window.');o.splice(a,1)}let c=`${t}
21
21
 
22
22
  You have access to a database of knowledge base items. These include "info" type items which provide information, "tour" type items which contain instructions you should follow (only do the first one from the list!), and "action" type items which become available as tool calls. Current info and tour items:
23
23
  `;c+=o.filter(a=>a.type=="info"||a.type=="tour"||a.type=="input-event").map(a=>{let h=q(typeof a.content=="function"?a.content():a.content);return JSON.stringify({id:a.id,type:a.type,name:a.name,content:h})}).join(`
24
- `),this.currentModel.config.systemMessage=c,this.currentModel.tools=o.filter(a=>a.type=="action"||a.type=="output-event").map(a=>{let h=q(typeof a.content=="function"?a.content():a.content);return{name:a._functionID,description:h,params:a.parameters||[{name:"value",type:"string",description:"Input"}],removeFromMessageHistory:!!a.removeFromMessageHistory,callback:w=>this.toolRunKBAction(a,w),kb:a}});let l=this.currentModel.config.systemMessage;if(l+=JSON.stringify(this.currentModel.tools.map(a=>({name:a.name,description:a.description,params:a.params}))),l.length<=i)break;n+=1}this._lastSystemMsg!=this.currentModel.config.systemMessage&&(this._lastSystemMsg=this.currentModel.config.systemMessage,this.submitAnalyticsEvent({type:"system-msg",txt:this.currentModel.config.systemMessage}))}processIncomingMessage(e,t){t||this.submitAnalyticsEvent({type:"message",role:"assistant",message:e});let i="";this._lastOutput===void 0?(i=e,this._lastOutput=e):e.startsWith(this._lastOutput)?(i=e.substring(this._lastOutput.length),this._lastOutput=e):(Z.warn("Message was changed during chunking. This should not happen.",e,this._lastOutput),i=e,this._lastOutput=e),t||(this._lastOutput=void 0),this.dispatchEvent(new CustomEvent("output",{detail:{ai:this,isChunk:t,message:e,messageChunk:i}})),this.onAIMessage?.(e,!!t)}async sendMessage(e){if(!this.currentModel)throw new Error("No model selected. Please call load() first.");if(this.isProcessing)return Z.warn("Cannot send message while another message is being processed."),null;this.isProcessing=!0;try{return this.submitAnalyticsEvent({type:"message",role:"user",message:e}),this.dispatchEvent(new CustomEvent("input",{detail:{ai:this,message:e}})),await this.currentModel.sendMessage(e)}finally{this.isProcessing=!1}}async toolRunKBAction(e,t){try{this.dispatchEvent(new CustomEvent("toolstart",{detail:{knowledgeBaseEntry:e,input:t,ai:this}}));let i=await e.action(t,this);return this.submitAnalyticsEvent({type:"action",action:e.id,value:t,result:i}),this.dispatchEvent(new CustomEvent("tool",{detail:{knowledgeBaseEntry:e,input:t,ai:this,result:i}})),i}catch(i){throw this.submitAnalyticsEvent({type:"action",action:e.id,value:t,error:i.message}),this.dispatchEvent(new CustomEvent("tool",{detail:{knowledgeBaseEntry:e,input:t,ai:this,error:i}})),i}}submitAnalyticsEvent(e){p().analytics===!1||this.config?.analytics===!1||fetch("https://intelliweave.ai/api/analytics/post",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...e,apiKey:this.apiKey,time:Date.now(),conversationID:this.conversationID})}).catch(t=>{Z.debug("Failed to submit analytics event:",t)})}resetConversation(){this.currentModel&&(this.currentModel.resetConversation(),this.conversationID=de(),this._lastSystemMsg="")}insertAssistantMessage(e){if(!this.currentModel)throw new Error("No model selected. Please call load() first.");this.currentModel.messages.push({role:"assistant",content:e})}exportState(){return{type:"intelliweave/state/v1",conversationID:this.conversationID,messages:this.currentModel?.messages}}importState(e){if(!this.currentModel)throw new Error("No model selected. Please call load() first.");if(e?.type!="intelliweave/state/v1")throw new Error(`Invalid state type: ${e.type}`);this.conversationID=e.conversationID,this.currentModel.messages=e.messages}clone(){let e=new P;return e.apiKey=this.apiKey,e.config=this.config,e.models=this.models,this.config?.id&&e.setModel(this.config.id),e.audio=this.audio,e.vadModel=this.vadModel,e.userID=this.userID,e.extra=this.extra,e.knowledgeBase=this.knowledgeBase.clone(),e}};P.version=ce.version;var G=P;var m=class extends HTMLElement{constructor(){super(...arguments);this._state={}}get root(){return this._shadow}static register(){this._isRegistered||(this._isRegistered=!0,this.tagName||(this.tagName="anonymous-component-"+this.name.toLowerCase().replace(/[^a-z0-9-]/g,"-")+"--"+Math.random().toString(36).substring(2)),window.customElements.define(this.tagName,this))}static create(e={},t=""){this.register();let i=document.createElement(this.tagName);for(let n in e)i.setAttribute(n,e[n]);return i.onBeforeCreate(),i.innerHTML=t,i}static add(e={},t=""){return this.register(),`<${this.tagName} ${Object.keys(e).map(i=>`${i}="${(e[i]+"").replaceAll('"',"&quot;")}"`).join(" ")}>${t}</${this.tagName}>`}static createElement(){return this.register(),document.createElement(this.tagName)}connectedCallback(){this._shadow||(this._shadow=this.attachShadow({mode:"closed"}),this._shadow.innerHTML=this.html(),this.onCreate()),this.onUpdate()}disconnectedCallback(){this._shadow=void 0,this.onDestroy()}html(){return""}onBeforeCreate(){}onCreate(){}onUpdate(){}onDestroy(){}attributeChangedCallback(e,t,i){this._shadow&&this.onUpdate()}get attr(){if(this._attrProxy)return this._attrProxy;let e=t=>(N=N||document.createElement("div"),N.innerText=t||"",N.innerHTML);return this._attrProxy=new Proxy({},{get:(t,i)=>e(this.getAttribute(i.toString())||""),set:(t,i,n)=>(this.getAttribute(i.toString())===n||(n?this.setAttribute(i.toString(),n):this.removeAttribute(i.toString()),this._shadow&&this.onUpdate()),!0)}),this._attrProxy}get state(){return this._stateProxy?this._stateProxy:(this._stateProxy=new Proxy({},{get:(e,t)=>this._state[t],set:(e,t,i)=>(this._state[t]=i,this._shadow&&this.onUpdate(),!0)}),this._stateProxy)}hasChild(e){return!!this.root?.getElementById(e)}child(e){let t=this.root?.getElementById(e);if(!t)throw new Error(`Child with ID ${e} not found`);return t}};m.observedAttributes=[],m.tagName="",m._isRegistered=!1;var N;var he='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" width="200" height="200" style="shape-rendering: auto; display: block; " xmlns:xlink="http://www.w3.org/1999/xlink"><g><circle cx="84" cy="50" r="10" fill="%23797979">%0A <animate attributeName="r" repeatCount="indefinite" dur="0.5s" calcMode="spline" keyTimes="0;1" values="10;0" keySplines="0 0.5 0.5 1" begin="0s"></animate>%0A <animate attributeName="fill" repeatCount="indefinite" dur="2s" calcMode="discrete" keyTimes="0;0.25;0.5;0.75;1" values="%23797979;%23797979;%23797979;%23797979;%23797979" begin="0s"></animate>%0A</circle><circle cx="16" cy="50" r="10" fill="%23797979">%0A <animate attributeName="r" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="0s"></animate>%0A <animate attributeName="cx" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="0s"></animate>%0A</circle><circle cx="50" cy="50" r="10" fill="%23797979">%0A <animate attributeName="r" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-0.5s"></animate>%0A <animate attributeName="cx" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-0.5s"></animate>%0A</circle><circle cx="84" cy="50" r="10" fill="%23797979">%0A <animate attributeName="r" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-1s"></animate>%0A <animate attributeName="cx" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-1s"></animate>%0A</circle><circle cx="16" cy="50" r="10" fill="%23797979">%0A <animate attributeName="r" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-1.5s"></animate>%0A <animate attributeName="cx" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-1.5s"></animate>%0A</circle><g></g></g><!-- [ldio] generated by https://loading.io --></svg>';var ue='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 475.085 475.085" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><path d="M237.541 328.897c25.128 0 46.632-8.946 64.523-26.83 17.888-17.884 26.833-39.399 26.833-64.525V91.365c0-25.126-8.938-46.632-26.833-64.525C284.173 8.951 262.669 0 237.541 0c-25.125 0-46.632 8.951-64.524 26.84-17.893 17.89-26.838 39.399-26.838 64.525v146.177c0 25.125 8.949 46.641 26.838 64.525 17.889 17.884 39.399 26.83 64.524 26.83z" fill="%23ffffff" opacity="1" data-original="%23000000" class=""></path><path d="M396.563 188.15c-3.606-3.617-7.898-5.426-12.847-5.426-4.944 0-9.226 1.809-12.847 5.426-3.613 3.616-5.421 7.898-5.421 12.845v36.547c0 35.214-12.518 65.333-37.548 90.362-25.022 25.03-55.145 37.545-90.36 37.545-35.214 0-65.334-12.515-90.365-37.545-25.028-25.022-37.541-55.147-37.541-90.362v-36.547c0-4.947-1.809-9.229-5.424-12.845-3.617-3.617-7.895-5.426-12.847-5.426s-9.235 1.809-12.85 5.426c-3.618 3.616-5.426 7.898-5.426 12.845v36.547c0 42.065 14.04 78.659 42.112 109.776 28.073 31.118 62.762 48.961 104.068 53.526v37.691h-73.089c-4.949 0-9.231 1.811-12.847 5.428-3.617 3.614-5.426 7.898-5.426 12.847 0 4.941 1.809 9.233 5.426 12.847 3.616 3.614 7.898 5.428 12.847 5.428h182.719c4.948 0 9.236-1.813 12.847-5.428 3.621-3.613 5.431-7.905 5.431-12.847 0-4.948-1.81-9.232-5.431-12.847-3.61-3.617-7.898-5.428-12.847-5.428h-73.08v-37.691c41.299-4.565 75.985-22.408 104.061-53.526 28.076-31.117 42.12-67.711 42.12-109.776v-36.547c0-4.946-1.813-9.225-5.435-12.845z" fill="%23ffffff" opacity="1" data-original="%23000000" class=""></path></g></svg>';var pe='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 448.075 448.075" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><path d="M352.021 16.075c0-6.08-3.52-11.84-8.96-14.4-5.76-2.88-12.16-1.92-16.96 1.92l-141.76 112.96 167.68 167.68zM443.349 420.747l-416-416c-6.24-6.24-16.384-6.24-22.624 0s-6.24 16.384 0 22.624l100.672 100.704h-9.376c-9.92 0-18.56 4.48-24.32 11.52-4.8 5.44-7.68 12.8-7.68 20.48v128c0 17.6 14.4 32 32 32h74.24l155.84 124.48c2.88 2.24 6.4 3.52 9.92 3.52 2.24 0 4.8-.64 7.04-1.6 5.44-2.56 8.96-8.32 8.96-14.4v-57.376l68.672 68.672c3.136 3.136 7.232 4.704 11.328 4.704s8.192-1.568 11.328-4.672c6.24-6.272 6.24-16.384 0-22.656z" fill="%23ffffff" opacity="1" data-original="%23000000" class=""></path></g></svg>';var K=class extends m{constructor(){super(...arguments);this.html=()=>`
24
+ `),this.currentModel.config.systemMessage=c,this.currentModel.tools=o.filter(a=>a.type=="action"||a.type=="output-event").map(a=>{let h=q(typeof a.content=="function"?a.content():a.content);return{name:a._functionID,description:h,params:a.parameters||[{name:"value",type:"string",description:"Input"}],removeFromMessageHistory:!!a.removeFromMessageHistory,callback:w=>this.toolRunKBAction(a,w),kb:a}});let l=this.currentModel.config.systemMessage;if(l+=JSON.stringify(this.currentModel.tools.map(a=>({name:a.name,description:a.description,params:a.params}))),l.length<=i)break;n+=1}this._lastSystemMsg!=this.currentModel.config.systemMessage&&(this._lastSystemMsg=this.currentModel.config.systemMessage,this.submitAnalyticsEvent({type:"system-msg",txt:this.currentModel.config.systemMessage}))}processIncomingMessage(e,t){t||this.submitAnalyticsEvent({type:"message",role:"assistant",message:e});let i="";this._lastOutput===void 0?(i=e,this._lastOutput=e):e.startsWith(this._lastOutput)?(i=e.substring(this._lastOutput.length),this._lastOutput=e):(Z.warn("Message was changed during chunking. This should not happen.",e,this._lastOutput),i=e,this._lastOutput=e),t||(this._lastOutput=void 0),this.dispatchEvent(new CustomEvent("output",{detail:{ai:this,isChunk:t,message:e,messageChunk:i}})),this.onAIMessage?.(e,!!t)}async sendMessage(e){if(!this.currentModel)throw new Error("No model selected. Please call load() first.");if(this.isProcessing)return Z.warn("Cannot send message while another message is being processed."),null;this.isProcessing=!0;try{return this.submitAnalyticsEvent({type:"message",role:"user",message:e}),this.dispatchEvent(new CustomEvent("input",{detail:{ai:this,message:e}})),await this.currentModel.sendMessage(e)}finally{this.isProcessing=!1}}async toolRunKBAction(e,t){try{this.dispatchEvent(new CustomEvent("toolstart",{detail:{knowledgeBaseEntry:e,input:t,ai:this}}));let i=await e.action(t,this);return this.submitAnalyticsEvent({type:"action",action:e.id,value:t,result:i}),this.dispatchEvent(new CustomEvent("tool",{detail:{knowledgeBaseEntry:e,input:t,ai:this,result:i}})),i}catch(i){throw this.submitAnalyticsEvent({type:"action",action:e.id,value:t,error:i.message}),this.dispatchEvent(new CustomEvent("tool",{detail:{knowledgeBaseEntry:e,input:t,ai:this,error:i}})),i}}submitAnalyticsEvent(e){p().analytics===!1||this.config?.analytics===!1||fetch(this.hubAPI+"/analytics/post",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...e,apiKey:this.apiKey,time:Date.now(),conversationID:this.conversationID})}).catch(t=>{Z.debug("Failed to submit analytics event:",t)})}resetConversation(){this.currentModel&&(this.currentModel.resetConversation(),this.conversationID=de(),this._lastSystemMsg="")}insertAssistantMessage(e){if(!this.currentModel)throw new Error("No model selected. Please call load() first.");this.currentModel.messages.push({role:"assistant",content:e})}exportState(){return{type:"intelliweave/state/v1",conversationID:this.conversationID,messages:this.currentModel?.messages}}importState(e){if(!this.currentModel)throw new Error("No model selected. Please call load() first.");if(e?.type!="intelliweave/state/v1")throw new Error(`Invalid state type: ${e.type}`);this.conversationID=e.conversationID,this.currentModel.messages=e.messages}clone(){let e=new P;return e.apiKey=this.apiKey,e.config=this.config,e.models=this.models,this.config?.id&&e.setModel(this.config.id),e.audio=this.audio,e.vadModel=this.vadModel,e.userID=this.userID,e.extra=this.extra,e.knowledgeBase=this.knowledgeBase.clone(),e}};P.version=ce.version;var G=P;var m=class extends HTMLElement{constructor(){super(...arguments);this._state={}}get root(){return this._shadow}static register(){this._isRegistered||(this._isRegistered=!0,this.tagName||(this.tagName="anonymous-component-"+this.name.toLowerCase().replace(/[^a-z0-9-]/g,"-")+"--"+Math.random().toString(36).substring(2)),window.customElements.define(this.tagName,this))}static create(e={},t=""){this.register();let i=document.createElement(this.tagName);for(let n in e)i.setAttribute(n,e[n]);return i.onBeforeCreate(),i.innerHTML=t,i}static add(e={},t=""){return this.register(),`<${this.tagName} ${Object.keys(e).map(i=>`${i}="${(e[i]+"").replaceAll('"',"&quot;")}"`).join(" ")}>${t}</${this.tagName}>`}static createElement(){return this.register(),document.createElement(this.tagName)}connectedCallback(){this._shadow||(this._shadow=this.attachShadow({mode:"closed"}),this._shadow.innerHTML=this.html(),this.onCreate()),this.onUpdate()}disconnectedCallback(){this._shadow=void 0,this.onDestroy()}html(){return""}onBeforeCreate(){}onCreate(){}onUpdate(){}onDestroy(){}attributeChangedCallback(e,t,i){this._shadow&&this.onUpdate()}get attr(){if(this._attrProxy)return this._attrProxy;let e=t=>(N=N||document.createElement("div"),N.innerText=t||"",N.innerHTML);return this._attrProxy=new Proxy({},{get:(t,i)=>e(this.getAttribute(i.toString())||""),set:(t,i,n)=>(this.getAttribute(i.toString())===n||(n?this.setAttribute(i.toString(),n):this.removeAttribute(i.toString()),this._shadow&&this.onUpdate()),!0)}),this._attrProxy}get state(){return this._stateProxy?this._stateProxy:(this._stateProxy=new Proxy({},{get:(e,t)=>this._state[t],set:(e,t,i)=>(this._state[t]=i,this._shadow&&this.onUpdate(),!0)}),this._stateProxy)}hasChild(e){return!!this.root?.getElementById(e)}child(e){let t=this.root?.getElementById(e);if(!t)throw new Error(`Child with ID ${e} not found`);return t}};m.observedAttributes=[],m.tagName="",m._isRegistered=!1;var N;var he='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" width="200" height="200" style="shape-rendering: auto; display: block; " xmlns:xlink="http://www.w3.org/1999/xlink"><g><circle cx="84" cy="50" r="10" fill="%23797979">%0A <animate attributeName="r" repeatCount="indefinite" dur="0.5s" calcMode="spline" keyTimes="0;1" values="10;0" keySplines="0 0.5 0.5 1" begin="0s"></animate>%0A <animate attributeName="fill" repeatCount="indefinite" dur="2s" calcMode="discrete" keyTimes="0;0.25;0.5;0.75;1" values="%23797979;%23797979;%23797979;%23797979;%23797979" begin="0s"></animate>%0A</circle><circle cx="16" cy="50" r="10" fill="%23797979">%0A <animate attributeName="r" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="0s"></animate>%0A <animate attributeName="cx" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="0s"></animate>%0A</circle><circle cx="50" cy="50" r="10" fill="%23797979">%0A <animate attributeName="r" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-0.5s"></animate>%0A <animate attributeName="cx" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-0.5s"></animate>%0A</circle><circle cx="84" cy="50" r="10" fill="%23797979">%0A <animate attributeName="r" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-1s"></animate>%0A <animate attributeName="cx" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-1s"></animate>%0A</circle><circle cx="16" cy="50" r="10" fill="%23797979">%0A <animate attributeName="r" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-1.5s"></animate>%0A <animate attributeName="cx" repeatCount="indefinite" dur="2s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-1.5s"></animate>%0A</circle><g></g></g><!-- [ldio] generated by https://loading.io --></svg>';var ue='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 475.085 475.085" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><path d="M237.541 328.897c25.128 0 46.632-8.946 64.523-26.83 17.888-17.884 26.833-39.399 26.833-64.525V91.365c0-25.126-8.938-46.632-26.833-64.525C284.173 8.951 262.669 0 237.541 0c-25.125 0-46.632 8.951-64.524 26.84-17.893 17.89-26.838 39.399-26.838 64.525v146.177c0 25.125 8.949 46.641 26.838 64.525 17.889 17.884 39.399 26.83 64.524 26.83z" fill="%23ffffff" opacity="1" data-original="%23000000" class=""></path><path d="M396.563 188.15c-3.606-3.617-7.898-5.426-12.847-5.426-4.944 0-9.226 1.809-12.847 5.426-3.613 3.616-5.421 7.898-5.421 12.845v36.547c0 35.214-12.518 65.333-37.548 90.362-25.022 25.03-55.145 37.545-90.36 37.545-35.214 0-65.334-12.515-90.365-37.545-25.028-25.022-37.541-55.147-37.541-90.362v-36.547c0-4.947-1.809-9.229-5.424-12.845-3.617-3.617-7.895-5.426-12.847-5.426s-9.235 1.809-12.85 5.426c-3.618 3.616-5.426 7.898-5.426 12.845v36.547c0 42.065 14.04 78.659 42.112 109.776 28.073 31.118 62.762 48.961 104.068 53.526v37.691h-73.089c-4.949 0-9.231 1.811-12.847 5.428-3.617 3.614-5.426 7.898-5.426 12.847 0 4.941 1.809 9.233 5.426 12.847 3.616 3.614 7.898 5.428 12.847 5.428h182.719c4.948 0 9.236-1.813 12.847-5.428 3.621-3.613 5.431-7.905 5.431-12.847 0-4.948-1.81-9.232-5.431-12.847-3.61-3.617-7.898-5.428-12.847-5.428h-73.08v-37.691c41.299-4.565 75.985-22.408 104.061-53.526 28.076-31.117 42.12-67.711 42.12-109.776v-36.547c0-4.946-1.813-9.225-5.435-12.845z" fill="%23ffffff" opacity="1" data-original="%23000000" class=""></path></g></svg>';var pe='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 448.075 448.075" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><path d="M352.021 16.075c0-6.08-3.52-11.84-8.96-14.4-5.76-2.88-12.16-1.92-16.96 1.92l-141.76 112.96 167.68 167.68zM443.349 420.747l-416-416c-6.24-6.24-16.384-6.24-22.624 0s-6.24 16.384 0 22.624l100.672 100.704h-9.376c-9.92 0-18.56 4.48-24.32 11.52-4.8 5.44-7.68 12.8-7.68 20.48v128c0 17.6 14.4 32 32 32h74.24l155.84 124.48c2.88 2.24 6.4 3.52 9.92 3.52 2.24 0 4.8-.64 7.04-1.6 5.44-2.56 8.96-8.32 8.96-14.4v-57.376l68.672 68.672c3.136 3.136 7.232 4.704 11.328 4.704s8.192-1.568 11.328-4.672c6.24-6.272 6.24-16.384 0-22.656z" fill="%23ffffff" opacity="1" data-original="%23000000" class=""></path></g></svg>';var K=class extends m{constructor(){super(...arguments);this.html=()=>`
25
25
 
26
26
  <!-- Styling -->
27
27
  <style>
@@ -250,32 +250,34 @@ You have access to a database of knowledge base items. These include "info" type
250
250
  <div class='llm-selector-item-icon' style="background-image: url('${t.icon}'); "></div>
251
251
  <div class='llm-selector-item-name'>${t.name}</div>
252
252
  <div class='llm-selector-item-provider'>${t.provider}</div>
253
- `,i.addEventListener("click",n=>{this.dispatchEvent(new CustomEvent("select",{detail:t.id}))}),e.appendChild(i)}}};R.observedAttributes=["open"];var X=new u("ONNXModel"),g=class d{constructor(s){this.stateTensors={};this.constantTensors={};this._runActive=!1;this.ignoreIfBusy=!1;this.session=s,X.debug(`Model input parameters: ${s.inputNames.join(", ")}`),X.debug(`Model output parameters: ${s.outputNames.join(", ")}`)}static isSupported(){return!!d.lib}static async load(s){if(!d.lib)throw new Error("ONNX runtime not loaded, please set the runtime loader. Example: ONNXModel.lib = () => import('onnxruntime-web')");this.onnx||(X.debug("Loading ONNX runtime"),this.onnx=await d.lib()),X.debug(`Loading model: ${s}`);let e=await this.onnx.InferenceSession.create(s);return new d(e)}makeTensor(s,e,t=0){let i=1;for(let o of e)i*=o;let n;if(s=="float32")n=new d.onnx.Tensor(new Float32Array(i),e);else if(s=="int8")n=new d.onnx.Tensor(new Int8Array(i),e);else if(s=="int16")n=new d.onnx.Tensor(new Int16Array(i),e);else if(s=="int32")n=new d.onnx.Tensor(new Int32Array(i),e);else if(s=="int64")n=new d.onnx.Tensor(new BigInt64Array(i),e);else if(s=="uint8")n=new d.onnx.Tensor(new Uint8Array(i),e);else if(s=="uint16")n=new d.onnx.Tensor(new Uint16Array(i),e);else if(s=="uint32")n=new d.onnx.Tensor(new Uint32Array(i),e);else if(s=="uint64")n=new d.onnx.Tensor(new BigUint64Array(i),e);else throw new Error(`Invalid type: ${s}`);return t!==0&&(s=="int64"||s=="uint64")?n.data.fill(BigInt(t)):t!==0&&n.data.fill(t),n}registerConstant(s,e){if(!this.session.inputNames.includes(s))throw new Error(`Model does not have an input named: ${s}`);return this.constantTensors[s]=e,e}makeConstant(s,e,t,i=0){return this.registerConstant(s,this.makeTensor(e,t,i))}registerState(s,e,t){if(e||(e=s),!this.session.inputNames.includes(s))throw new Error(`Model does not have an input named: ${s}`);if(!this.session.outputNames.includes(e))throw new Error(`Model does not have an output named: ${e}`);return this.stateTensors[s]={outputName:e,tensor:t},t}makeState(s,e,t,i,n=0){return this.registerState(s,e,this.makeTensor(t,i,n))}async run(s={}){if(this._runActive&&this.ignoreIfBusy)return X.debug("Ignoring run request because a previous run is still active");if(this._runActive)throw new Error("A previous run is still active");this._runActive=!0;for(let e in this.stateTensors)s[e]=this.stateTensors[e].tensor;for(let e in this.constantTensors)s[e]=this.constantTensors[e];try{let e=await this.session.run(s);for(let t in this.stateTensors){let i=e[this.stateTensors[t].outputName];this.stateTensors[t].tensor=i}return e}finally{this._runActive=!1}}resetState(){X.debug("Resetting state tensors");for(let s in this.stateTensors)this.stateTensors[s].tensor.data.fill(0)}};var me="data:application/javascript;base64,dmFyIGM9Y2xhc3N7Y29uc3RydWN0b3IoaSx0KXt0aGlzLm91dHB1dEJ1ZmZlclNpemU9MDt0aGlzLnBhcnRpYWxCdWZmZXJzPVtdO3RoaXMucGFydGlhbEJ1ZmZlck9mZnNldD0wO2lmKCFpKXRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhcnJheSBjbGFzczogJHtpfWApO2lmKCF0fHx0PD0wKXRocm93IG5ldyBFcnJvcihgSW52YWxpZCBvdXRwdXQgYnVmZmVyIHNpemU6ICR7dH1gKTt0aGlzLkFycmF5Q2xhc3M9aSx0aGlzLm91dHB1dEJ1ZmZlclNpemU9dH1nZXQgcXVldWVkU2l6ZSgpe3JldHVybiB0aGlzLnBhcnRpYWxCdWZmZXJzLnJlZHVjZSgoaSx0KT0+aSt0Lmxlbmd0aCwwKX1mZWVkKGkpe3RoaXMucGFydGlhbEJ1ZmZlcnMucHVzaChpKX1nZXQgY2FuRHJhaW4oKXtyZXR1cm4gdGhpcy5wYXJ0aWFsQnVmZmVycy5yZWR1Y2UoKHQscik9PnQrci5sZW5ndGgsMCktdGhpcy5wYXJ0aWFsQnVmZmVyT2Zmc2V0Pj10aGlzLm91dHB1dEJ1ZmZlclNpemV9ZHJhaW4oKXtpZighdGhpcy5jYW5EcmFpbilyZXR1cm4gbnVsbDtsZXQgaT10aGlzLkFycmF5Q2xhc3MsdD1uZXcgaSh0aGlzLm91dHB1dEJ1ZmZlclNpemUpLHI9MDtmb3IoO3IhPXQubGVuZ3RoOyl7aWYocj50Lmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoYEJ1ZmZlciBvdmVyZmxvdzogJHtyfSA+ICR7dC5sZW5ndGh9YCk7bGV0IGE9dC5sZW5ndGgtcixzPXRoaXMucGFydGlhbEJ1ZmZlcnNbMF0sZj1zLmxlbmd0aC10aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQ7ZjxhPyh0LnNldChzLnN1YmFycmF5KHRoaXMucGFydGlhbEJ1ZmZlck9mZnNldCkscikscis9Zix0aGlzLnBhcnRpYWxCdWZmZXJzLnNoaWZ0KCksdGhpcy5wYXJ0aWFsQnVmZmVyT2Zmc2V0PTApOih0LnNldChzLnN1YmFycmF5KHRoaXMucGFydGlhbEJ1ZmZlck9mZnNldCx0aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQrYSkscikscis9YSx0aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQrPWEpfXJldHVybiB0fXBhZCgpe2xldCBpPXRoaXMucXVldWVkU2l6ZSV0aGlzLm91dHB1dEJ1ZmZlclNpemU7aWYoaT09MClyZXR1cm47bGV0IHQ9dGhpcy5BcnJheUNsYXNzLHI9bmV3IHQoaSk7dGhpcy5mZWVkKHIpfX07dmFyIGQ9Y2xhc3N7Y29uc3RydWN0b3IoaSx0LHIsYSl7aWYoIWl8fCF0fHwhcil0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgc2V0dGluZ3Mgc3BlY2lmaWVkIGZvciB0aGUgcmVzYW1wbGVyLiIpO3RoaXMucmVzYW1wbGVyPW51bGwsdGhpcy5mcm9tU2FtcGxlUmF0ZT1pLHRoaXMudG9TYW1wbGVSYXRlPXQsdGhpcy5jaGFubmVscz1yfHwwLHRoaXMuaW5wdXRCdWZmZXJTaXplPWEsdGhpcy5pbml0aWFsaXplKCl9aW5pdGlhbGl6ZSgpe3RoaXMuZnJvbVNhbXBsZVJhdGU9PXRoaXMudG9TYW1wbGVSYXRlPyh0aGlzLnJlc2FtcGxlcj1pPT5pLHRoaXMucmF0aW9XZWlnaHQ9MSk6KHRoaXMuZnJvbVNhbXBsZVJhdGU8dGhpcy50b1NhbXBsZVJhdGU/KHRoaXMubGluZWFySW50ZXJwb2xhdGlvbigpLHRoaXMubGFzdFdlaWdodD0xKToodGhpcy5tdWx0aVRhcCgpLHRoaXMudGFpbEV4aXN0cz0hMSx0aGlzLmxhc3RXZWlnaHQ9MCksdGhpcy5pbml0aWFsaXplQnVmZmVycygpLHRoaXMucmF0aW9XZWlnaHQ9dGhpcy5mcm9tU2FtcGxlUmF0ZS90aGlzLnRvU2FtcGxlUmF0ZSl9YnVmZmVyU2xpY2UoaSl7dHJ5e3JldHVybiB0aGlzLm91dHB1dEJ1ZmZlci5zdWJhcnJheSgwLGkpfWNhdGNoe3RyeXtyZXR1cm4gdGhpcy5vdXRwdXRCdWZmZXIubGVuZ3RoPWksdGhpcy5vdXRwdXRCdWZmZXJ9Y2F0Y2h7cmV0dXJuIHRoaXMub3V0cHV0QnVmZmVyLnNsaWNlKDAsaSl9fX1pbml0aWFsaXplQnVmZmVycygpe3RoaXMub3V0cHV0QnVmZmVyU2l6ZT1NYXRoLmNlaWwodGhpcy5pbnB1dEJ1ZmZlclNpemUqdGhpcy50b1NhbXBsZVJhdGUvdGhpcy5mcm9tU2FtcGxlUmF0ZS90aGlzLmNoYW5uZWxzKjEuMDAwMDAwNDc2ODM3MTU4MikrdGhpcy5jaGFubmVscyt0aGlzLmNoYW5uZWxzO3RyeXt0aGlzLm91dHB1dEJ1ZmZlcj1uZXcgRmxvYXQzMkFycmF5KHRoaXMub3V0cHV0QnVmZmVyU2l6ZSksdGhpcy5sYXN0T3V0cHV0PW5ldyBGbG9hdDMyQXJyYXkodGhpcy5jaGFubmVscyl9Y2F0Y2h7dGhpcy5vdXRwdXRCdWZmZXI9W10sdGhpcy5sYXN0T3V0cHV0PVtdfX1saW5lYXJJbnRlcnBvbGF0aW9uKCl7dGhpcy5yZXNhbXBsZXI9aT0+e2xldCB0PWkubGVuZ3RoLHI9dGhpcy5jaGFubmVscyxhLHMsZixoLGUsbix1LG8sbDtpZih0JXIhPT0wKXRocm93IG5ldyBFcnJvcigiQnVmZmVyIHdhcyBvZiBpbmNvcnJlY3Qgc2FtcGxlIGxlbmd0aC4iKTtpZih0PD0wKXJldHVybltdO2ZvcihhPXRoaXMub3V0cHV0QnVmZmVyU2l6ZSxzPXRoaXMucmF0aW9XZWlnaHQsZj10aGlzLmxhc3RXZWlnaHQsaD0wLGU9MCxuPTAsdT0wLG89dGhpcy5vdXRwdXRCdWZmZXI7ZjwxO2YrPXMpZm9yKGU9ZiUxLGg9MS1lLHRoaXMubGFzdFdlaWdodD1mJTEsbD0wO2w8dGhpcy5jaGFubmVsczsrK2wpb1t1KytdPXRoaXMubGFzdE91dHB1dFtsXSpoK2lbbF0qZTtmb3IoZi09MSx0LT1yLG49TWF0aC5mbG9vcihmKSpyO3U8YSYmbjx0Oyl7Zm9yKGU9ZiUxLGg9MS1lLGw9MDtsPHRoaXMuY2hhbm5lbHM7KytsKW9bdSsrXT1pW24rKGw+MD9sOjApXSpoK2lbbisocitsKV0qZTtmKz1zLG49TWF0aC5mbG9vcihmKSpyfWZvcihsPTA7bDxyOysrbCl0aGlzLmxhc3RPdXRwdXRbbF09aVtuKytdO3JldHVybiB0aGlzLmJ1ZmZlclNsaWNlKHUpfX1tdWx0aVRhcCgpe3RoaXMucmVzYW1wbGVyPWk9PntsZXQgdD1pLmxlbmd0aCxyLGEscz10aGlzLmNoYW5uZWxzLGYsaCxlLG4sdSxvLGwsbSxnO2lmKHQlcyE9PTApdGhyb3cgbmV3IEVycm9yKCJCdWZmZXIgd2FzIG9mIGluY29ycmVjdCBzYW1wbGUgbGVuZ3RoLiIpO2lmKHQ8PTApcmV0dXJuW107Zm9yKHI9dGhpcy5vdXRwdXRCdWZmZXJTaXplLGE9W10sZj10aGlzLnJhdGlvV2VpZ2h0LGg9MCxuPTAsdT0wLG89IXRoaXMudGFpbEV4aXN0cyx0aGlzLnRhaWxFeGlzdHM9ITEsbD10aGlzLm91dHB1dEJ1ZmZlcixtPTAsZz0wLGU9MDtlPHM7KytlKWFbZV09MDtkb3tpZihvKWZvcihoPWYsZT0wO2U8czsrK2UpYVtlXT0wO2Vsc2V7Zm9yKGg9dGhpcy5sYXN0V2VpZ2h0LGU9MDtlPHM7KytlKWFbZV09dGhpcy5sYXN0T3V0cHV0W2VdO289ITB9Zm9yKDtoPjAmJm48dDspaWYodT0xK24tZyxoPj11KXtmb3IoZT0wO2U8czsrK2UpYVtlXSs9aVtuKytdKnU7Zz1uLGgtPXV9ZWxzZXtmb3IoZT0wO2U8czsrK2UpYVtlXSs9aVtuKyhlPjA/ZTowKV0qaDtnKz1oLGg9MDticmVha31pZihoPT09MClmb3IoZT0wO2U8czsrK2UpbFttKytdPWFbZV0vZjtlbHNle2Zvcih0aGlzLmxhc3RXZWlnaHQ9aCxlPTA7ZTxzOysrZSl0aGlzLmxhc3RPdXRwdXRbZV09YVtlXTt0aGlzLnRhaWxFeGlzdHM9ITA7YnJlYWt9fXdoaWxlKG48dCYmbTxyKTtyZXR1cm4gdGhpcy5idWZmZXJTbGljZShtKX19cmVzYW1wbGUoaSl7cmV0dXJuIHRoaXMuZnJvbVNhbXBsZVJhdGU9PXRoaXMudG9TYW1wbGVSYXRlP3RoaXMucmF0aW9XZWlnaHQ9MToodGhpcy5mcm9tU2FtcGxlUmF0ZTx0aGlzLnRvU2FtcGxlUmF0ZT90aGlzLmxhc3RXZWlnaHQ9MToodGhpcy50YWlsRXhpc3RzPSExLHRoaXMubGFzdFdlaWdodD0wKSx0aGlzLmluaXRpYWxpemVCdWZmZXJzKCksdGhpcy5yYXRpb1dlaWdodD10aGlzLmZyb21TYW1wbGVSYXRlL3RoaXMudG9TYW1wbGVSYXRlKSx0aGlzLnJlc2FtcGxlcihpKX19O2Z1bmN0aW9uIFMocCl7bGV0IGk9cC5sZW5ndGgsdD1uZXcgRmxvYXQzMkFycmF5KGkpO2Zvcig7aS0tOyl7bGV0IHI9cFtpXTt0W2ldPXI+PTMyNzY4Py0oNjU1MzYtcikvMzI3Njg6ci8zMjc2N31yZXR1cm4gdH12YXIgeT0xMDI0KjgsQj1jbGFzcyBleHRlbmRzIEF1ZGlvV29ya2xldFByb2Nlc3Nvcntjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KTt0aGlzLmNodW5rcz1bXTt0aGlzLmNodW5rUG9zaXRpb249MDt0aGlzLmlzRW5kZWQ9ITE7dGhpcy5pc0NhbmNlbGxlZD0hMTt0aGlzLnNhbXBsZVJhdGU9MDt0aGlzLmZvcm1hdD0iaW50MTYiO3RoaXMuYnVmZmVyT2Zmc2V0PTA7dGhpcy5sYXN0UGxheWVkQnVmZmVyU2l6ZT0wO3RoaXMuX2hhc1NlbnRFbmRFdmVudD0hMTt0aGlzLnBvcnQub25tZXNzYWdlPXI9PnRoaXMub25NZXNzYWdlKHIpfW9uTWVzc2FnZSh0KXtpZih0LmRhdGEuYWN0aW9uPT0ic3RhcnQiKXRoaXMuZm9ybWF0PXQuZGF0YS5mb3JtYXQsdGhpcy5zYW1wbGVSYXRlPXQuZGF0YS5pbnB1dFNhbXBsZVJhdGUsdGhpcy5yZXNhbXBsZXI9bmV3IGQodC5kYXRhLmlucHV0U2FtcGxlUmF0ZSx0LmRhdGEub3V0cHV0U2FtcGxlUmF0ZSwxLHkpLHRoaXMuZm9ybWF0PT0iaW50MTYiP3RoaXMuaW5wdXRCdWZmZXI9bmV3IGMoVWludDhBcnJheSx5KjIpOnRoaXMuZm9ybWF0PT0iZmxvYXQzMiImJih0aGlzLmlucHV0QnVmZmVyPW5ldyBjKFVpbnQ4QXJyYXkseSo0KSk7ZWxzZSBpZih0LmRhdGEuYWN0aW9uPT0iZGF0YSIpe2xldCByPW5ldyBVaW50OEFycmF5KHQuZGF0YS5idWZmZXIpO2Zvcih0aGlzLmlucHV0QnVmZmVyLmZlZWQocik7dGhpcy5pbnB1dEJ1ZmZlci5jYW5EcmFpbjspdGhpcy5kcmFpbkJ1ZmZlcigpfWVsc2UgdC5kYXRhLmFjdGlvbj09ImVuZCI/KHRoaXMubGFzdFBsYXllZEJ1ZmZlclNpemUmJnRoaXMuY2h1bmtzLnB1c2gobmV3IEZsb2F0MzJBcnJheSh0aGlzLmxhc3RQbGF5ZWRCdWZmZXJTaXplKjIpKSx0aGlzLmlzRW5kZWQ9ITApOnQuZGF0YS5hY3Rpb249PSJjYW5jZWwiJiYodGhpcy5pc0VuZGVkPSEwLHRoaXMuaXNDYW5jZWxsZWQ9ITApfWRyYWluQnVmZmVyKCl7bGV0IHQ9dGhpcy5pbnB1dEJ1ZmZlci5kcmFpbigpO2lmKCF0KXJldHVybjtsZXQgcjtpZih0aGlzLmZvcm1hdD09ImludDE2Iil7bGV0IHM9bmV3IEludDE2QXJyYXkodC5idWZmZXIsdC5ieXRlT2Zmc2V0LHQuYnl0ZUxlbmd0aC8yKTtyPVMocyl9ZWxzZSBpZih0aGlzLmZvcm1hdD09ImZsb2F0MzIiKXI9bmV3IEZsb2F0MzJBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQsdC5ieXRlTGVuZ3RoLzQpO2Vsc2UgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGZvcm1hdDogJHt0aGlzLmZvcm1hdH1gKTtsZXQgYT10aGlzLnJlc2FtcGxlci5yZXNhbXBsZShyKTt0aGlzLmNodW5rcy5wdXNoKGEpfW5leHRGbG9hdCgpe2lmKCF0aGlzLmNodW5rcy5sZW5ndGgpcmV0dXJuIDA7bGV0IHQ9dGhpcy5jaHVua3NbMF1bdGhpcy5jaHVua1Bvc2l0aW9uXTtyZXR1cm4gdGhpcy5jaHVua1Bvc2l0aW9uKyssdGhpcy5jaHVua1Bvc2l0aW9uPHRoaXMuY2h1bmtzWzBdLmxlbmd0aHx8KHRoaXMuY2h1bmtzLnNoaWZ0KCksdGhpcy5jaHVua1Bvc2l0aW9uPTApLHR9cHJvY2Vzcyh0LHIsYSl7aWYodGhpcy5pc0NhbmNlbGxlZClyZXR1cm4hMTtpZih0aGlzLmlzRW5kZWQmJiF0aGlzLmNodW5rcy5sZW5ndGgpcmV0dXJuIHRoaXMuX2hhc1NlbnRFbmRFdmVudHx8KHRoaXMuX2hhc1NlbnRFbmRFdmVudD0hMCx0aGlzLnBvcnQucG9zdE1lc3NhZ2Uoe2FjdGlvbjoiZW5kIn0pKSwhMTtsZXQgcz1yWzBdPy5bMF0/Lmxlbmd0aDtpZighcylyZXR1cm4hMDt0aGlzLmxhc3RQbGF5ZWRCdWZmZXJTaXplPXM7Zm9yKGxldCBmPTA7ZjxzO2YrKyl7bGV0IGg9dGhpcy5uZXh0RmxvYXQoKTtmb3IobGV0IGU9MDtlPHIubGVuZ3RoO2UrKylmb3IobGV0IG49MDtuPHJbZV0ubGVuZ3RoO24rKylyW2VdW25dW2ZdPWh9cmV0dXJuITB9fTtyZWdpc3RlclByb2Nlc3NvcigicGNtLXBsYXllci1ub2RlIixCKTsK";var ge="data:application/javascript;base64,dmFyIGc9Y2xhc3N7Y29uc3RydWN0b3IoZSx0LGksZil7aWYoIWV8fCF0fHwhaSl0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgc2V0dGluZ3Mgc3BlY2lmaWVkIGZvciB0aGUgcmVzYW1wbGVyLiIpO3RoaXMucmVzYW1wbGVyPW51bGwsdGhpcy5mcm9tU2FtcGxlUmF0ZT1lLHRoaXMudG9TYW1wbGVSYXRlPXQsdGhpcy5jaGFubmVscz1pfHwwLHRoaXMuaW5wdXRCdWZmZXJTaXplPWYsdGhpcy5pbml0aWFsaXplKCl9aW5pdGlhbGl6ZSgpe3RoaXMuZnJvbVNhbXBsZVJhdGU9PXRoaXMudG9TYW1wbGVSYXRlPyh0aGlzLnJlc2FtcGxlcj1lPT5lLHRoaXMucmF0aW9XZWlnaHQ9MSk6KHRoaXMuZnJvbVNhbXBsZVJhdGU8dGhpcy50b1NhbXBsZVJhdGU/KHRoaXMubGluZWFySW50ZXJwb2xhdGlvbigpLHRoaXMubGFzdFdlaWdodD0xKToodGhpcy5tdWx0aVRhcCgpLHRoaXMudGFpbEV4aXN0cz0hMSx0aGlzLmxhc3RXZWlnaHQ9MCksdGhpcy5pbml0aWFsaXplQnVmZmVycygpLHRoaXMucmF0aW9XZWlnaHQ9dGhpcy5mcm9tU2FtcGxlUmF0ZS90aGlzLnRvU2FtcGxlUmF0ZSl9YnVmZmVyU2xpY2UoZSl7dHJ5e3JldHVybiB0aGlzLm91dHB1dEJ1ZmZlci5zdWJhcnJheSgwLGUpfWNhdGNoe3RyeXtyZXR1cm4gdGhpcy5vdXRwdXRCdWZmZXIubGVuZ3RoPWUsdGhpcy5vdXRwdXRCdWZmZXJ9Y2F0Y2h7cmV0dXJuIHRoaXMub3V0cHV0QnVmZmVyLnNsaWNlKDAsZSl9fX1pbml0aWFsaXplQnVmZmVycygpe3RoaXMub3V0cHV0QnVmZmVyU2l6ZT1NYXRoLmNlaWwodGhpcy5pbnB1dEJ1ZmZlclNpemUqdGhpcy50b1NhbXBsZVJhdGUvdGhpcy5mcm9tU2FtcGxlUmF0ZS90aGlzLmNoYW5uZWxzKjEuMDAwMDAwNDc2ODM3MTU4MikrdGhpcy5jaGFubmVscyt0aGlzLmNoYW5uZWxzO3RyeXt0aGlzLm91dHB1dEJ1ZmZlcj1uZXcgRmxvYXQzMkFycmF5KHRoaXMub3V0cHV0QnVmZmVyU2l6ZSksdGhpcy5sYXN0T3V0cHV0PW5ldyBGbG9hdDMyQXJyYXkodGhpcy5jaGFubmVscyl9Y2F0Y2h7dGhpcy5vdXRwdXRCdWZmZXI9W10sdGhpcy5sYXN0T3V0cHV0PVtdfX1saW5lYXJJbnRlcnBvbGF0aW9uKCl7dGhpcy5yZXNhbXBsZXI9ZT0+e2xldCB0PWUubGVuZ3RoLGk9dGhpcy5jaGFubmVscyxmLGgsYSxzLHIsdSxuLHAsbDtpZih0JWkhPT0wKXRocm93IG5ldyBFcnJvcigiQnVmZmVyIHdhcyBvZiBpbmNvcnJlY3Qgc2FtcGxlIGxlbmd0aC4iKTtpZih0PD0wKXJldHVybltdO2ZvcihmPXRoaXMub3V0cHV0QnVmZmVyU2l6ZSxoPXRoaXMucmF0aW9XZWlnaHQsYT10aGlzLmxhc3RXZWlnaHQscz0wLHI9MCx1PTAsbj0wLHA9dGhpcy5vdXRwdXRCdWZmZXI7YTwxO2ErPWgpZm9yKHI9YSUxLHM9MS1yLHRoaXMubGFzdFdlaWdodD1hJTEsbD0wO2w8dGhpcy5jaGFubmVsczsrK2wpcFtuKytdPXRoaXMubGFzdE91dHB1dFtsXSpzK2VbbF0qcjtmb3IoYS09MSx0LT1pLHU9TWF0aC5mbG9vcihhKSppO248ZiYmdTx0Oyl7Zm9yKHI9YSUxLHM9MS1yLGw9MDtsPHRoaXMuY2hhbm5lbHM7KytsKXBbbisrXT1lW3UrKGw+MD9sOjApXSpzK2VbdSsoaStsKV0qcjthKz1oLHU9TWF0aC5mbG9vcihhKSppfWZvcihsPTA7bDxpOysrbCl0aGlzLmxhc3RPdXRwdXRbbF09ZVt1KytdO3JldHVybiB0aGlzLmJ1ZmZlclNsaWNlKG4pfX1tdWx0aVRhcCgpe3RoaXMucmVzYW1wbGVyPWU9PntsZXQgdD1lLmxlbmd0aCxpLGYsaD10aGlzLmNoYW5uZWxzLGEscyxyLHUsbixwLGwsbSxCO2lmKHQlaCE9PTApdGhyb3cgbmV3IEVycm9yKCJCdWZmZXIgd2FzIG9mIGluY29ycmVjdCBzYW1wbGUgbGVuZ3RoLiIpO2lmKHQ8PTApcmV0dXJuW107Zm9yKGk9dGhpcy5vdXRwdXRCdWZmZXJTaXplLGY9W10sYT10aGlzLnJhdGlvV2VpZ2h0LHM9MCx1PTAsbj0wLHA9IXRoaXMudGFpbEV4aXN0cyx0aGlzLnRhaWxFeGlzdHM9ITEsbD10aGlzLm91dHB1dEJ1ZmZlcixtPTAsQj0wLHI9MDtyPGg7KytyKWZbcl09MDtkb3tpZihwKWZvcihzPWEscj0wO3I8aDsrK3IpZltyXT0wO2Vsc2V7Zm9yKHM9dGhpcy5sYXN0V2VpZ2h0LHI9MDtyPGg7KytyKWZbcl09dGhpcy5sYXN0T3V0cHV0W3JdO3A9ITB9Zm9yKDtzPjAmJnU8dDspaWYobj0xK3UtQixzPj1uKXtmb3Iocj0wO3I8aDsrK3IpZltyXSs9ZVt1KytdKm47Qj11LHMtPW59ZWxzZXtmb3Iocj0wO3I8aDsrK3IpZltyXSs9ZVt1KyhyPjA/cjowKV0qcztCKz1zLHM9MDticmVha31pZihzPT09MClmb3Iocj0wO3I8aDsrK3IpbFttKytdPWZbcl0vYTtlbHNle2Zvcih0aGlzLmxhc3RXZWlnaHQ9cyxyPTA7cjxoOysrcil0aGlzLmxhc3RPdXRwdXRbcl09ZltyXTt0aGlzLnRhaWxFeGlzdHM9ITA7YnJlYWt9fXdoaWxlKHU8dCYmbTxpKTtyZXR1cm4gdGhpcy5idWZmZXJTbGljZShtKX19cmVzYW1wbGUoZSl7cmV0dXJuIHRoaXMuZnJvbVNhbXBsZVJhdGU9PXRoaXMudG9TYW1wbGVSYXRlP3RoaXMucmF0aW9XZWlnaHQ9MToodGhpcy5mcm9tU2FtcGxlUmF0ZTx0aGlzLnRvU2FtcGxlUmF0ZT90aGlzLmxhc3RXZWlnaHQ9MToodGhpcy50YWlsRXhpc3RzPSExLHRoaXMubGFzdFdlaWdodD0wKSx0aGlzLmluaXRpYWxpemVCdWZmZXJzKCksdGhpcy5yYXRpb1dlaWdodD10aGlzLmZyb21TYW1wbGVSYXRlL3RoaXMudG9TYW1wbGVSYXRlKSx0aGlzLnJlc2FtcGxlcihlKX19O2Z1bmN0aW9uIGQobyl7bGV0IGU9by5sZW5ndGgsdD1uZXcgSW50MTZBcnJheShlKTtmb3IoO2UtLTspe2xldCBpPU1hdGgubWF4KC0xLE1hdGgubWluKDEsb1tlXSkpO3RbZV09aTwwP2kqMzI3Njg6aSozMjc2N31yZXR1cm4gdH1mdW5jdGlvbiB3KG8pe2xldCBlPW8ubGVuZ3RoLHQ9bmV3IEJpZ0ludDY0QXJyYXkoZSk7Zm9yKDtlLS07KXtsZXQgaT1NYXRoLm1heCgtMSxNYXRoLm1pbigxLG9bZV0pKTt0W2VdPUJpZ0ludChNYXRoLmZsb29yKGk8MD9pKjMyNzY4OmkqMzI3NjcpKSoweDEwMDAwMDAwMDAwMG59cmV0dXJuIHR9dmFyIGM9Y2xhc3N7Y29uc3RydWN0b3IoZSx0KXt0aGlzLm91dHB1dEJ1ZmZlclNpemU9MDt0aGlzLnBhcnRpYWxCdWZmZXJzPVtdO3RoaXMucGFydGlhbEJ1ZmZlck9mZnNldD0wO2lmKCFlKXRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhcnJheSBjbGFzczogJHtlfWApO2lmKCF0fHx0PD0wKXRocm93IG5ldyBFcnJvcihgSW52YWxpZCBvdXRwdXQgYnVmZmVyIHNpemU6ICR7dH1gKTt0aGlzLkFycmF5Q2xhc3M9ZSx0aGlzLm91dHB1dEJ1ZmZlclNpemU9dH1nZXQgcXVldWVkU2l6ZSgpe3JldHVybiB0aGlzLnBhcnRpYWxCdWZmZXJzLnJlZHVjZSgoZSx0KT0+ZSt0Lmxlbmd0aCwwKX1mZWVkKGUpe3RoaXMucGFydGlhbEJ1ZmZlcnMucHVzaChlKX1nZXQgY2FuRHJhaW4oKXtyZXR1cm4gdGhpcy5wYXJ0aWFsQnVmZmVycy5yZWR1Y2UoKHQsaSk9PnQraS5sZW5ndGgsMCktdGhpcy5wYXJ0aWFsQnVmZmVyT2Zmc2V0Pj10aGlzLm91dHB1dEJ1ZmZlclNpemV9ZHJhaW4oKXtpZighdGhpcy5jYW5EcmFpbilyZXR1cm4gbnVsbDtsZXQgZT10aGlzLkFycmF5Q2xhc3MsdD1uZXcgZSh0aGlzLm91dHB1dEJ1ZmZlclNpemUpLGk9MDtmb3IoO2khPXQubGVuZ3RoOyl7aWYoaT50Lmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoYEJ1ZmZlciBvdmVyZmxvdzogJHtpfSA+ICR7dC5sZW5ndGh9YCk7bGV0IGY9dC5sZW5ndGgtaSxoPXRoaXMucGFydGlhbEJ1ZmZlcnNbMF0sYT1oLmxlbmd0aC10aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQ7YTxmPyh0LnNldChoLnN1YmFycmF5KHRoaXMucGFydGlhbEJ1ZmZlck9mZnNldCksaSksaSs9YSx0aGlzLnBhcnRpYWxCdWZmZXJzLnNoaWZ0KCksdGhpcy5wYXJ0aWFsQnVmZmVyT2Zmc2V0PTApOih0LnNldChoLnN1YmFycmF5KHRoaXMucGFydGlhbEJ1ZmZlck9mZnNldCx0aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQrZiksaSksaSs9Zix0aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQrPWYpfXJldHVybiB0fXBhZCgpe2xldCBlPXRoaXMucXVldWVkU2l6ZSV0aGlzLm91dHB1dEJ1ZmZlclNpemU7aWYoZT09MClyZXR1cm47bGV0IHQ9dGhpcy5BcnJheUNsYXNzLGk9bmV3IHQoZSk7dGhpcy5mZWVkKGkpfX07dmFyIHk9Y2xhc3MgZXh0ZW5kcyBBdWRpb1dvcmtsZXRQcm9jZXNzb3J7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5mb3JtYXQ9ImludDE2Ijt0aGlzLmlucHV0QnVmZmVyPW5ldyBjKEZsb2F0MzJBcnJheSw0MDk2KTt0aGlzLnBvcnQub25tZXNzYWdlPWk9PnRoaXMub25NZXNzYWdlKGkpfW9uTWVzc2FnZSh0KXt0LmRhdGEuYWN0aW9uPT0ic3RhcnQiJiYodGhpcy5mb3JtYXQ9dC5kYXRhLmZvcm1hdCx0aGlzLnJlc2FtcGxlcj1uZXcgZyh0LmRhdGEuaW5wdXRTYW1wbGVSYXRlLHQuZGF0YS5vdXRwdXRTYW1wbGVSYXRlLDEsNDA5NiksdGhpcy5mb3JtYXQ9PSJpbnQxNiI/dGhpcy5vdXRwdXRCdWZmZXI9bmV3IGMoSW50MTZBcnJheSx0LmRhdGEuYnVmZmVyU2l6ZSk6dGhpcy5mb3JtYXQ9PSJpbnQ2NCI/dGhpcy5vdXRwdXRCdWZmZXI9bmV3IGMoQmlnSW50NjRBcnJheSx0LmRhdGEuYnVmZmVyU2l6ZSk6dGhpcy5mb3JtYXQ9PSJmbG9hdDMyIiYmKHRoaXMub3V0cHV0QnVmZmVyPW5ldyBjKEZsb2F0MzJBcnJheSx0LmRhdGEuYnVmZmVyU2l6ZSkpKX1wcm9jZXNzKHQsaSxmKXtmb3IobGV0IGE9MDthPGkubGVuZ3RoO2ErKyl7bGV0IHM9TWF0aC5taW4oaVthXS5sZW5ndGgsdFswXS5sZW5ndGgpO2ZvcihsZXQgcj0wO3I8cztyKyspaVthXVtyXS5zZXQodFswXVtyXSl9aWYoIXRoaXMucmVzYW1wbGVyKXJldHVybiEwO2xldCBoPW5ldyBGbG9hdDMyQXJyYXkoaVswXVswXS5sZW5ndGgpO2ZvcihoLnNldChpWzBdWzBdKSx0aGlzLmlucHV0QnVmZmVyLmZlZWQoaCk7dGhpcy5pbnB1dEJ1ZmZlci5jYW5EcmFpbjspe2xldCBhPXRoaXMuaW5wdXRCdWZmZXIuZHJhaW4oKSxzPXRoaXMucmVzYW1wbGVyLnJlc2FtcGxlKGEpO3RoaXMuZm9ybWF0PT0iaW50MTYiP3RoaXMub3V0cHV0QnVmZmVyLmZlZWQoZChzKSk6dGhpcy5mb3JtYXQ9PSJpbnQ2NCI/dGhpcy5vdXRwdXRCdWZmZXIuZmVlZCh3KHMpKTp0aGlzLmZvcm1hdD09ImZsb2F0MzIiJiZ0aGlzLm91dHB1dEJ1ZmZlci5mZWVkKHMpfWZvcig7dGhpcy5vdXRwdXRCdWZmZXIuY2FuRHJhaW47KXtsZXQgYT10aGlzLm91dHB1dEJ1ZmZlci5kcmFpbigpO2lmKCFhKWJyZWFrO3RoaXMucG9ydC5wb3N0TWVzc2FnZSh7YWN0aW9uOiJkYXRhIixidWZmZXI6YS5idWZmZXJ9LFthLmJ1ZmZlcl0pfXJldHVybiEwfX07cmVnaXN0ZXJQcm9jZXNzb3IoInBjbS1yZWNlaXZlci1ub2RlIix5KTsK";var Ie=new u("PCMPlayerNode"),z=class extends AudioWorkletNode{constructor(e,t,i){super(e,"pcm-player-node",{numberOfInputs:0});this.sampleRate=0;this.format="int16";this.isCancelled=!1;if(!t||t<=0)throw new Error(`Invalid sample rate: ${t}`);if(!i||i!="int16"&&i!="float32")throw new Error(`Invalid format: ${i}`);this.sampleRate=t,this.format=i,this.port.onmessage=n=>this.onWorkletMessage(n),this.port.postMessage({action:"start",inputSampleRate:t,outputSampleRate:e.sampleRate,format:i})}feed(e){this.port.postMessage({action:"data",buffer:e.buffer},[e.buffer])}async play(e){if(this.isCancelled)throw new Error("PCMPlayerNode has already been cancelled.");if(this._playPromise)throw new Error("Already playing a stream");this._playPromise=new Promise(t=>this._playPromiseResolve=t),this.dispatchEvent(new CustomEvent("start",{detail:{player:this,stream:e}}));try{let t=e.getReader();for(;!this.isCancelled;){let{done:i,value:n}=await t.read();if(i||!n)break;this.feed(n)}}catch(t){Ie.warn("Stream error:",t),this.dispatchEvent(new CustomEvent("error",{detail:{player:this,stream:e,error:t}}))}this.port.postMessage({action:"end"}),await this._playPromise}onWorkletMessage(e){e.data.action=="end"&&(this._playPromiseResolve?.(),this.dispatchEvent(new CustomEvent("end",{detail:{player:this}})))}stop(){this.isCancelled=!0,this.port.postMessage({action:"cancel"}),this._playPromiseResolve?.()}};var F=new u("SpeechOutput"),fe=.5,Me=.8,A=class extends EventTarget{constructor(s){super(),this.ai=s,this.ai.addEventListener("output",e=>this.onTextOutputFromAI(e)),this.ai.audio?.speechRecognition.addEventListener("speechstart",e=>this.interrupt()),this.ai.knowledgeBase.registerSource(()=>[{id:"system.voice",type:"info",name:"Voice active",isContext:!0,disabled:!1,content:"Text-to-speech is active. The user can hear your voice."}])}onTextOutputFromAI(s){s.detail.isChunk||this.ai?.audio?.speechRecognition.isRunning&&this.speak(s.detail.message)}async speak(s){if(!this.ai?.config?.voice?.providerID)return F.warn("No voice provider configured");let e=`speech-${Ve++}`;await this.ai.audio.beginAccess(e);try{await this._speakWithLock(s)}finally{this.ai.audio.endAccess(e)}}async _speakWithLock(s){this.interrupt(),this.ai.audio.speechRecognition.voiceDetection&&(this.ai.audio.speechRecognition.voiceDetection.sensitivity=Me);let e=this.ai?._voiceTracker||F.timer(`${this.ai.config.voice.providerID} voice`);e(`Speak: ${s}`),this.currentPlayerVolume?.disconnect(),this.currentPlayerVolume=this.ai.audio.context.createGain(),this.currentPlayerVolume.connect(this.ai.audio.context.destination);let t=this.currentPlayerVolume,i=new z(this.ai.audio.context,24e3,"int16");this.currentPlayer=i,i.connect(t),i.addEventListener("end",o=>{let r=o;e(`PCM stream ${r.detail.interrupted?"interrupted":"ended"}`),this.currentPlayer==i&&!r.detail.interrupted&&(this.currentPlayer=void 0,this.onSpeechEnd())});let n;if(this.ai.config.voice.providerID=="openai")n=await fetch("https://api.openai.com/v1/audio/speech",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.ai.config.voice.apiKey}`},body:JSON.stringify({model:"tts-1",input:s,voice:this.ai.config.voice.voiceID,response_format:"pcm"})});else if(this.ai.config.voice.providerID=="elevenlabs")n=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${this.ai.config.voice.voiceID}?output_format=pcm_24000`,{method:"POST",headers:{"xi-api-key":`${this.ai.config.voice.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({text:s})});else{F.warn(`Unknown voice provider: ${this.ai.config.voice.providerID}`);return}if(e(`Received response ${n.status} ${n.statusText}`),!n.ok){F.warn(`Failed to generate voice sample: ${n.status} ${n.statusText}`);return}this.dispatchEvent(new CustomEvent("speechstart",{detail:{ai:this.ai,message:s}})),e("Playing PCM stream"),await i.play(n.body),e("Audio has ended")}get isSpeaking(){return!!this.currentPlayer}async interrupt(){if(!this.currentPlayerVolume)return;let s=this.currentPlayerVolume,e=this.currentPlayer;this.currentPlayerVolume=void 0,this.currentPlayer=void 0,this.ai?.audio?.speechRecognition.voiceDetection&&(this.ai.audio.speechRecognition.voiceDetection.sensitivity=fe);let t=400;s.gain.linearRampToValueAtTime(0,t/1e3),await new Promise(i=>setTimeout(i,t+250)),s.disconnect(),e?.stop(),e?.disconnect()}onSpeechEnd(){this.dispatchEvent(new CustomEvent("speechend",{detail:{ai:this.ai}})),this.ai?.audio?.speechRecognition.voiceDetection&&(this.ai.audio.speechRecognition.voiceDetection.sensitivity=fe)}},Ve=1;function Y(d,s){let e=s.reduce((c,l)=>c+l.byteLength,0),t=new DataView(new ArrayBuffer(44));t.setUint8(0,82),t.setUint8(1,73),t.setUint8(2,70),t.setUint8(3,70),t.setUint32(4,44+e,!0),t.setUint8(8,87),t.setUint8(9,65),t.setUint8(10,86),t.setUint8(11,69);let i=1,n=32,o=i*n/8,r=d*o;return t.setUint8(12,102),t.setUint8(13,109),t.setUint8(14,116),t.setUint8(15,32),t.setUint32(16,16,!0),t.setUint16(20,3,!0),t.setUint16(22,i,!0),t.setUint32(24,d,!0),t.setUint32(28,r,!0),t.setUint16(32,o,!0),t.setUint16(34,n,!0),t.setUint8(36,100),t.setUint8(37,97),t.setUint8(38,116),t.setUint8(39,97),t.setUint32(40,e,!0),new File([t,...s],"audio.wav",{type:"audio/wav"})}var H=class extends AudioWorkletNode{constructor(e,t,i,n){super(e,"pcm-receiver-node",{numberOfInputs:1});this.format="int16";this.format=i;let o=["int16","int64","float32"];if(!t||t<=0)throw new Error(`Invalid sample rate: ${t}`);if(!o.includes(i))throw new Error(`Invalid format ${i}, must be one of: ${o.join(", ")}`);if(!n||n<=0)throw new Error(`Invalid buffer size: ${n}`);this.port.onmessage=r=>this.onWorkletMessage(r),this.port.postMessage({action:"start",inputSampleRate:e.sampleRate,outputSampleRate:t,format:i,bufferSize:n})}onWorkletMessage(e){if(e.data.action=="data"){let t=null;if(this.format=="int16"&&(t=new Int16Array(e.data.buffer)),this.format=="int64"&&(t=new BigInt64Array(e.data.buffer)),this.format=="float32"&&(t=new Float32Array(e.data.buffer)),!t)throw new Error(`Invalid format: ${this.format}`);this.onData(t),this.dispatchEvent(new CustomEvent("data",{detail:{data:t}}))}}onData(e){}};var te=16e3,D=256,W=8,C=new u("VoiceDetectionNode"),E=class E extends H{constructor(e){super(e,te,"float32",D*W);this.isVoiceActive=!1;this.lastVoiceActiveDate=0;this.voiceEndTimeout=50;this.sensitivity=.5;this.sentivityEnd=.2;this.nextVadReset=0;this.currentProbability=0;this._lastVoiceActive=!1;if(!E.vadModelURL)throw new Error("VAD model url not set, please load it and set it to VoiceDetectionNode.vadModelURL");this.loadModel()}get isVoicePossiblyEnding(){return this.isVoiceActive&&this.currentProbability<this.sensitivity}get sampleRate(){return te}get numberOfSamples(){return D}get numberOfSampleChunks(){return W}get outputBufferSize(){return D*W}get isModelLoaded(){return!!this.vad}async loadModel(){C.debug("Loading VAD model"),this.vad=await g.load(E.vadModelURL),this.vad.ignoreIfBusy=!0,C.debug("Model loaded"),this.vad.makeConstant("sr","int64",[1],te),this.vad.makeState("h","hn","float32",[2,W,64]),this.vad.makeState("c","cn","float32",[2,W,64])}async onData(e){if(this.vad)try{let t=await this.vad.run({input:new g.onnx.Tensor(e,[W,D])});if(!t)return;this.currentProbability=0;for(let o=0;o<t.output.data.length;o++)t.output.data[o]>this.currentProbability&&(this.currentProbability=t.output.data[o]);let i=this.isVoiceActive?this.sentivityEnd:this.sensitivity,n=this.currentProbability>i;if(!n&&this._lastVoiceActive&&(this.nextVadReset=Date.now(),this.vad.resetState()),this._lastVoiceActive=n,n&&!this.isVoiceActive?(this.lastVoiceActiveDate=Date.now(),this.isVoiceActive=!0,this.dispatchEvent(new CustomEvent("speechstart")),this.onSpeechStart(),C.debug("Started speaking")):n?this.lastVoiceActiveDate=Date.now():!n&&this.isVoiceActive&&Date.now()<this.lastVoiceActiveDate+this.voiceEndTimeout||!n&&this.isVoiceActive&&(this.isVoiceActive=!1,this.dispatchEvent(new CustomEvent("speechend")),this.onSpeechEnd(),C.debug("Stopped speaking after timeout")),!n){let o=Date.now();o>this.nextVadReset&&(this.nextVadReset=o+5e3,this.vad.resetState())}}catch(t){C.error("VAD failed:",t)}}onSpeechStart(){}onSpeechEnd(){}};E.vadModelURL="";var S=E;var ye=new u("VoiceChunkOutputNode"),I=class extends S{constructor(){super(...arguments);this.buffers=[];this.recordedBuffers=[];this._voiceRecording=!1;this.backBufferDurationSeconds=3}get bufferDuration(){return this.buffers.reduce((e,t)=>e+t.length,0)/8e3}async onData(e){if(await super.onData(e),this.isVoiceActive&&!this._voiceRecording){ye.debug(`Voice detected, sending ${this.buffers.length} existing chunks`),this._voiceRecording=!0;for(let t of this.buffers)this.recordedBuffers.push(t),this.dispatchEvent(new CustomEvent("voicedata",{detail:{data:t,isFinal:!1}})),this.onVoiceChunk(t);this.recordedBuffers.push(e),this.dispatchEvent(new CustomEvent("voicedata",{detail:{data:e,isFinal:!1}})),this.onVoiceChunk(e),this.buffers=[]}else if(this.isVoiceActive)this.recordedBuffers.push(e),this.dispatchEvent(new CustomEvent("voicedata",{detail:{data:e,isFinal:!1}})),this.onVoiceChunk(e);else if(!this.isVoiceActive&&this._voiceRecording){this.recordedBuffers.push(e),this.dispatchEvent(new CustomEvent("voicedata",{detail:{data:e,isFinal:!0}})),this.onVoiceChunk(e),this._voiceRecording=!1;let t=this.recordedBuffers.reduce((i,n)=>i+n.length,0);ye.debug(`Voice complete, recorded ${(t/8e3).toFixed(2)} seconds of audio, ${t*4/1024} KB of data`),this.dispatchEvent(new CustomEvent("voicedataend",{detail:{data:this.recordedBuffers}})),this.onVoiceEnd(this.recordedBuffers),this.recordedBuffers=[]}else for(this.buffers.push(e);this.bufferDuration>this.backBufferDurationSeconds;)this.buffers.shift()}onVoiceChunk(e){}onVoiceEnd(e){}};var J=new u("OpenAITranscriptionNode"),U=class extends I{constructor(e,t){super(e);this.apiKey="";this.pendingBuffers=[];this.isTranscribing=!1;this.apiKey=t}async onVoiceEnd(e){let t=J.timer("OpenAI Transcribe");this.isTranscribing=!0,this.pendingBuffers.push(...e);let i=Y(this.sampleRate,this.pendingBuffers);this.lastRequestAbortController?.abort(),this.lastRequestAbortController=new AbortController;let n="";try{let o=new FormData;o.append("file",i),o.append("model","whisper-1"),o.append("response_format","text");let r=await fetch("https://api.openai.com/v1/audio/transcriptions",{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:o,signal:this.lastRequestAbortController.signal});if(!r.ok)throw new Error(`Failed to generate voice sample: ${r.status} ${r.statusText}`);t("Response received"),n=await r.text(),t("Content received: "+n),this.lastRequestAbortController=void 0}catch(o){J.error(`Failed to transcribe speech: ${o.message}`);return}finally{this.isTranscribing=!1}if(this.pendingBuffers=[],!n)return J.debug("Transcription complete, but no text was found");J.debug(`Transcription: ${n}`),this.onVoiceTranscription(n),this.dispatchEvent(new CustomEvent("transcription",{detail:{text:n}}))}onVoiceTranscription(e){}};var O=class extends WebSocket{constructor(e){super(e);this.pendingData=[];this.addEventListener("open",()=>this._onOpen())}send(e){this.readyState==WebSocket.OPEN?super.send(e):this.pendingData.push(e)}_onOpen(){for(let e of this.pendingData)super.send(e);this.pendingData=[]}};var f=new u("IntelliWeaveTranscriptionNode"),Re="wss://speech.intelliweave.ai/api/v1/transcribe",Q=class Q extends I{constructor(e,t){super(e);this.apiAddress=Re;this.apiKey="";this.isTranscribing=!1;this.apiKey=t}async onVoiceChunk(e){this.isTranscribing=!0,this.ws?this.ws.send(e):(f.debug("Opening WebSocket connection"),this.ws=new O(this.apiAddress),this.ws.send(JSON.stringify({type:"hello",sampleRate:16e3,channels:1,format:"float32",apiKey:this.apiKey})),this.ws.send(e.buffer),this.ws.onopen=()=>{f.debug("WebSocket connection opened")},this.ws.addEventListener("message",i=>{let n=JSON.parse(i.data);if(n.error)return f.warn("Error: "+n.error);if(n.type!="transcription")return f.warn("Invalid response type",n);if(n.streaming&&!n.final)return f.debug("Partial transcription: "+n.partialText);if(this.isTranscribing=!1,!n.text.trim())return f.warn(`Empty transcription (${n.processingTime}ms)`);f.debug(`Transcription: ${n.text} (${n.processingTime}ms)`),this.onVoiceTranscription(n.text),this.dispatchEvent(new CustomEvent("transcription",{detail:{text:n.text}}))}),this.ws.addEventListener("close",()=>this.onSocketClose()),this.ws.addEventListener("error",i=>f.warn("WebSocket error")));let t=1e3*60*1;this.shutdownTimer&&clearTimeout(this.shutdownTimer),this.shutdownTimer=setTimeout(()=>{f.debug("Shutting down WebSocket connection"),this.ws?.close(),this.ws=void 0},t)}async onVoiceEnd(e){if(this.ws?.send(JSON.stringify({type:"end"})),Q.debugExportWav){let t=Y(this.sampleRate,e),i=document.createElement("a");i.href=URL.createObjectURL(t),i.download="recording.wav",i.click()}}onVoiceTranscription(e){}onSocketClose(){f.debug("WebSocket connection closed"),this.ws=void 0,this.isTranscribing=!1}};Q.debugExportWav=!1;var j=Q;var ie=new u("SpeechRecognition"),_=class extends EventTarget{constructor(e){super();this.isRunning=!1;this._skipEvents=!1;this.maxVolumeHeard=0;this.ai=e,this.ai.knowledgeBase.registerSource(()=>[{id:"system.microphone.enable",type:"action",name:"Enable or disable microphone",isContext:!0,content:`Starts or stops listening to input from the user through the microphone. ${this.isRunning?"Microphone access is currently enabled and you can hear the user.":"Microphone access is currently disabled."}.`,parameters:[{name:"enable",type:"boolean",description:"If true, enables the microphone. If false, disables it."}],action:async t=>{t.enable?await this.start():this.stop()}}])}get isSupported(){if(!g.lib||!this.ai?.vadModel||!b().AudioWorkletNode)return!1;if(this.ai?.config?.transcription?.providerID!="intelliweave"){if(!(this.ai?.config?.transcription?.providerID=="openai"&&this.ai.config?.transcription?.apiKey))return!1}return!0}async start(){if(!this.isSupported)throw new Error("Speech recognition not supported in this persona and browser.");if(!this.isRunning){this.isRunning=!0;try{await this.ai.audio.beginAccess("speech-recognition"),this.micStream=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,echoCancellation:!0,autoGainControl:!0,noiseSuppression:!0}});let e=this.ai.audio.context.createMediaStreamSource(this.micStream);this.analyserNode=this.ai.audio.context.createAnalyser(),this.analyserNode.fftSize=32,e.connect(this.analyserNode),this.analyserBuffer=new Float32Array(this.analyserNode.fftSize),S.vadModelURL=URL.createObjectURL(this.ai.vadModel),this.ai?.config?.transcription?.providerID=="openai"?(this.voiceDetection=new U(this.ai.audio.context,this.ai.config.transcription.apiKey),e.connect(this.voiceDetection)):(this.voiceDetection=new j(this.ai.audio.context,this.ai.apiKey),this.voiceDetection.apiAddress=this.ai?.config?.transcription?.url||this.voiceDetection.apiAddress,e.connect(this.voiceDetection)),this.voiceDetection.addEventListener("speechstart",t=>{this.ai._voiceTracker=ie.timer("voice interaction","Speech started"),this.dispatchEvent(new CustomEvent(t.type,{detail:t.detail}))}),this.voiceDetection.addEventListener("speechend",t=>{this.ai._voiceTracker?.("Speech ended"),this.dispatchEvent(new CustomEvent(t.type,{detail:t.detail}))}),this.voiceDetection.addEventListener("transcription",t=>{this.ai._voiceTracker?.(`Transcription: ${t.detail.text}`),this.onTranscription(t)}),this._skipEvents||this.dispatchEvent(new CustomEvent("start",{detail:{speechRecognition:this}}))}catch(e){ie.error("Failed to start speech recognition:",e),this.stop()}}}stop(){this.isRunning&&(this.isRunning=!1,this.ai.audio.endAccess("speech-recognition"),this.voiceDetection?.disconnect(),this.voiceDetection=void 0,this.micStream?.getTracks().forEach(e=>e.stop()),this.micStream=void 0,this.analyserNode=void 0,this.analyserBuffer=void 0,this._skipEvents||this.dispatchEvent(new CustomEvent("end",{detail:{speechRecognition:this}})))}get volumeLevel(){if(!this.analyserNode||!this.analyserBuffer)return 0;this.analyserNode.getFloatTimeDomainData(this.analyserBuffer);let e=0;for(let i of this.analyserBuffer)e+=i*i;let t=Math.sqrt(e/this.analyserBuffer.length);return t>this.maxVolumeHeard&&(this.maxVolumeHeard=t),this.maxVolumeHeard*=.999,this.maxVolumeHeard<.01&&(this.maxVolumeHeard=.01),Math.min(1,Math.max(0,t/this.maxVolumeHeard))}get wordsCurrentlyBeingSpoken(){return!!this.voiceDetection?.isVoiceActive}get isTranscribing(){return!!this.voiceDetection?.isTranscribing}onTranscription(e){let t=e.detail.text;ie.debug("Heard:",t),this.dispatchEvent(new CustomEvent("speech",{detail:{transcript:t,isFinal:!0}}))}async reset(){if(this.isRunning){this._skipEvents=!0;try{this.stop(),await this.start(),this._skipEvents=!1}catch(e){throw this._skipEvents=!1,e}}}};var $=new u("AudioSystem"),M=class{constructor(s){this.locks=[];if(!s)throw new Error("AI reference is required. Please pass in the IntelliWeave instance to the constructor.");this.ai=s,this.ai.audio=this,this.speechRecognition=new _(this.ai),this.speechOutput=new A(this.ai)}static get isSupported(){return!(!g.lib||!b().AudioWorkletNode)}async beginAccess(s){$.debug(`Began access for: ${s}`),this.locks.includes(s)||this.locks.push(s),!this.context&&($.debug("Creating AudioContext"),this.context=new AudioContext({latencyHint:"interactive"}),this.context.resume(),await Promise.all([this.context.audioWorklet.addModule(me),this.context.audioWorklet.addModule(ge)]))}endAccess(s){$.debug(`Ended access for: ${s}`),this.locks=this.locks.filter(e=>e!=s),!this.locks.length&&($.debug("Closing AudioContext"),this.context?.close(),this.context=void 0)}};var bi=new u("Stream");import xi,{createContext as Ce,useContext as Zi,useEffect as Gi,useMemo as Xi,useState as Wi}from"react";var Ci=new u("React");var Ei=Ce(void 0);var se=new u("Embed"),v=class extends m{constructor(){super();this.config={};this.suggestions=[];this.html=()=>`
253
+ `,i.addEventListener("click",n=>{this.dispatchEvent(new CustomEvent("select",{detail:t.id}))}),e.appendChild(i)}}};R.observedAttributes=["open"];var X=new u("ONNXModel"),g=class d{constructor(s){this.stateTensors={};this.constantTensors={};this._runActive=!1;this.ignoreIfBusy=!1;this.session=s,X.debug(`Model input parameters: ${s.inputNames.join(", ")}`),X.debug(`Model output parameters: ${s.outputNames.join(", ")}`)}static isSupported(){return!!d.lib}static async load(s){if(!d.lib)throw new Error("ONNX runtime not loaded, please set the runtime loader. Example: ONNXModel.lib = () => import('onnxruntime-web')");this.onnx||(X.debug("Loading ONNX runtime"),this.onnx=await d.lib()),X.debug(`Loading model: ${s}`);let e=await this.onnx.InferenceSession.create(s);return new d(e)}makeTensor(s,e,t=0){let i=1;for(let o of e)i*=o;let n;if(s=="float32")n=new d.onnx.Tensor(new Float32Array(i),e);else if(s=="int8")n=new d.onnx.Tensor(new Int8Array(i),e);else if(s=="int16")n=new d.onnx.Tensor(new Int16Array(i),e);else if(s=="int32")n=new d.onnx.Tensor(new Int32Array(i),e);else if(s=="int64")n=new d.onnx.Tensor(new BigInt64Array(i),e);else if(s=="uint8")n=new d.onnx.Tensor(new Uint8Array(i),e);else if(s=="uint16")n=new d.onnx.Tensor(new Uint16Array(i),e);else if(s=="uint32")n=new d.onnx.Tensor(new Uint32Array(i),e);else if(s=="uint64")n=new d.onnx.Tensor(new BigUint64Array(i),e);else throw new Error(`Invalid type: ${s}`);return t!==0&&(s=="int64"||s=="uint64")?n.data.fill(BigInt(t)):t!==0&&n.data.fill(t),n}registerConstant(s,e){if(!this.session.inputNames.includes(s))throw new Error(`Model does not have an input named: ${s}`);return this.constantTensors[s]=e,e}makeConstant(s,e,t,i=0){return this.registerConstant(s,this.makeTensor(e,t,i))}registerState(s,e,t){if(e||(e=s),!this.session.inputNames.includes(s))throw new Error(`Model does not have an input named: ${s}`);if(!this.session.outputNames.includes(e))throw new Error(`Model does not have an output named: ${e}`);return this.stateTensors[s]={outputName:e,tensor:t},t}makeState(s,e,t,i,n=0){return this.registerState(s,e,this.makeTensor(t,i,n))}async run(s={}){if(this._runActive&&this.ignoreIfBusy)return X.debug("Ignoring run request because a previous run is still active");if(this._runActive)throw new Error("A previous run is still active");this._runActive=!0;for(let e in this.stateTensors)s[e]=this.stateTensors[e].tensor;for(let e in this.constantTensors)s[e]=this.constantTensors[e];try{let e=await this.session.run(s);for(let t in this.stateTensors){let i=e[this.stateTensors[t].outputName];this.stateTensors[t].tensor=i}return e}finally{this._runActive=!1}}resetState(){X.debug("Resetting state tensors");for(let s in this.stateTensors)this.stateTensors[s].tensor.data.fill(0)}};var me="data:application/javascript;base64,dmFyIGM9Y2xhc3N7Y29uc3RydWN0b3IoaSx0KXt0aGlzLm91dHB1dEJ1ZmZlclNpemU9MDt0aGlzLnBhcnRpYWxCdWZmZXJzPVtdO3RoaXMucGFydGlhbEJ1ZmZlck9mZnNldD0wO2lmKCFpKXRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhcnJheSBjbGFzczogJHtpfWApO2lmKCF0fHx0PD0wKXRocm93IG5ldyBFcnJvcihgSW52YWxpZCBvdXRwdXQgYnVmZmVyIHNpemU6ICR7dH1gKTt0aGlzLkFycmF5Q2xhc3M9aSx0aGlzLm91dHB1dEJ1ZmZlclNpemU9dH1nZXQgcXVldWVkU2l6ZSgpe3JldHVybiB0aGlzLnBhcnRpYWxCdWZmZXJzLnJlZHVjZSgoaSx0KT0+aSt0Lmxlbmd0aCwwKX1mZWVkKGkpe3RoaXMucGFydGlhbEJ1ZmZlcnMucHVzaChpKX1nZXQgY2FuRHJhaW4oKXtyZXR1cm4gdGhpcy5wYXJ0aWFsQnVmZmVycy5yZWR1Y2UoKHQscik9PnQrci5sZW5ndGgsMCktdGhpcy5wYXJ0aWFsQnVmZmVyT2Zmc2V0Pj10aGlzLm91dHB1dEJ1ZmZlclNpemV9ZHJhaW4oKXtpZighdGhpcy5jYW5EcmFpbilyZXR1cm4gbnVsbDtsZXQgaT10aGlzLkFycmF5Q2xhc3MsdD1uZXcgaSh0aGlzLm91dHB1dEJ1ZmZlclNpemUpLHI9MDtmb3IoO3IhPXQubGVuZ3RoOyl7aWYocj50Lmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoYEJ1ZmZlciBvdmVyZmxvdzogJHtyfSA+ICR7dC5sZW5ndGh9YCk7bGV0IGE9dC5sZW5ndGgtcixzPXRoaXMucGFydGlhbEJ1ZmZlcnNbMF0sZj1zLmxlbmd0aC10aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQ7ZjxhPyh0LnNldChzLnN1YmFycmF5KHRoaXMucGFydGlhbEJ1ZmZlck9mZnNldCkscikscis9Zix0aGlzLnBhcnRpYWxCdWZmZXJzLnNoaWZ0KCksdGhpcy5wYXJ0aWFsQnVmZmVyT2Zmc2V0PTApOih0LnNldChzLnN1YmFycmF5KHRoaXMucGFydGlhbEJ1ZmZlck9mZnNldCx0aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQrYSkscikscis9YSx0aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQrPWEpfXJldHVybiB0fXBhZCgpe2xldCBpPXRoaXMucXVldWVkU2l6ZSV0aGlzLm91dHB1dEJ1ZmZlclNpemU7aWYoaT09MClyZXR1cm47bGV0IHQ9dGhpcy5BcnJheUNsYXNzLHI9bmV3IHQoaSk7dGhpcy5mZWVkKHIpfX07dmFyIGQ9Y2xhc3N7Y29uc3RydWN0b3IoaSx0LHIsYSl7aWYoIWl8fCF0fHwhcil0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgc2V0dGluZ3Mgc3BlY2lmaWVkIGZvciB0aGUgcmVzYW1wbGVyLiIpO3RoaXMucmVzYW1wbGVyPW51bGwsdGhpcy5mcm9tU2FtcGxlUmF0ZT1pLHRoaXMudG9TYW1wbGVSYXRlPXQsdGhpcy5jaGFubmVscz1yfHwwLHRoaXMuaW5wdXRCdWZmZXJTaXplPWEsdGhpcy5pbml0aWFsaXplKCl9aW5pdGlhbGl6ZSgpe3RoaXMuZnJvbVNhbXBsZVJhdGU9PXRoaXMudG9TYW1wbGVSYXRlPyh0aGlzLnJlc2FtcGxlcj1pPT5pLHRoaXMucmF0aW9XZWlnaHQ9MSk6KHRoaXMuZnJvbVNhbXBsZVJhdGU8dGhpcy50b1NhbXBsZVJhdGU/KHRoaXMubGluZWFySW50ZXJwb2xhdGlvbigpLHRoaXMubGFzdFdlaWdodD0xKToodGhpcy5tdWx0aVRhcCgpLHRoaXMudGFpbEV4aXN0cz0hMSx0aGlzLmxhc3RXZWlnaHQ9MCksdGhpcy5pbml0aWFsaXplQnVmZmVycygpLHRoaXMucmF0aW9XZWlnaHQ9dGhpcy5mcm9tU2FtcGxlUmF0ZS90aGlzLnRvU2FtcGxlUmF0ZSl9YnVmZmVyU2xpY2UoaSl7dHJ5e3JldHVybiB0aGlzLm91dHB1dEJ1ZmZlci5zdWJhcnJheSgwLGkpfWNhdGNoe3RyeXtyZXR1cm4gdGhpcy5vdXRwdXRCdWZmZXIubGVuZ3RoPWksdGhpcy5vdXRwdXRCdWZmZXJ9Y2F0Y2h7cmV0dXJuIHRoaXMub3V0cHV0QnVmZmVyLnNsaWNlKDAsaSl9fX1pbml0aWFsaXplQnVmZmVycygpe3RoaXMub3V0cHV0QnVmZmVyU2l6ZT1NYXRoLmNlaWwodGhpcy5pbnB1dEJ1ZmZlclNpemUqdGhpcy50b1NhbXBsZVJhdGUvdGhpcy5mcm9tU2FtcGxlUmF0ZS90aGlzLmNoYW5uZWxzKjEuMDAwMDAwNDc2ODM3MTU4MikrdGhpcy5jaGFubmVscyt0aGlzLmNoYW5uZWxzO3RyeXt0aGlzLm91dHB1dEJ1ZmZlcj1uZXcgRmxvYXQzMkFycmF5KHRoaXMub3V0cHV0QnVmZmVyU2l6ZSksdGhpcy5sYXN0T3V0cHV0PW5ldyBGbG9hdDMyQXJyYXkodGhpcy5jaGFubmVscyl9Y2F0Y2h7dGhpcy5vdXRwdXRCdWZmZXI9W10sdGhpcy5sYXN0T3V0cHV0PVtdfX1saW5lYXJJbnRlcnBvbGF0aW9uKCl7dGhpcy5yZXNhbXBsZXI9aT0+e2xldCB0PWkubGVuZ3RoLHI9dGhpcy5jaGFubmVscyxhLHMsZixoLGUsbix1LG8sbDtpZih0JXIhPT0wKXRocm93IG5ldyBFcnJvcigiQnVmZmVyIHdhcyBvZiBpbmNvcnJlY3Qgc2FtcGxlIGxlbmd0aC4iKTtpZih0PD0wKXJldHVybltdO2ZvcihhPXRoaXMub3V0cHV0QnVmZmVyU2l6ZSxzPXRoaXMucmF0aW9XZWlnaHQsZj10aGlzLmxhc3RXZWlnaHQsaD0wLGU9MCxuPTAsdT0wLG89dGhpcy5vdXRwdXRCdWZmZXI7ZjwxO2YrPXMpZm9yKGU9ZiUxLGg9MS1lLHRoaXMubGFzdFdlaWdodD1mJTEsbD0wO2w8dGhpcy5jaGFubmVsczsrK2wpb1t1KytdPXRoaXMubGFzdE91dHB1dFtsXSpoK2lbbF0qZTtmb3IoZi09MSx0LT1yLG49TWF0aC5mbG9vcihmKSpyO3U8YSYmbjx0Oyl7Zm9yKGU9ZiUxLGg9MS1lLGw9MDtsPHRoaXMuY2hhbm5lbHM7KytsKW9bdSsrXT1pW24rKGw+MD9sOjApXSpoK2lbbisocitsKV0qZTtmKz1zLG49TWF0aC5mbG9vcihmKSpyfWZvcihsPTA7bDxyOysrbCl0aGlzLmxhc3RPdXRwdXRbbF09aVtuKytdO3JldHVybiB0aGlzLmJ1ZmZlclNsaWNlKHUpfX1tdWx0aVRhcCgpe3RoaXMucmVzYW1wbGVyPWk9PntsZXQgdD1pLmxlbmd0aCxyLGEscz10aGlzLmNoYW5uZWxzLGYsaCxlLG4sdSxvLGwsbSxnO2lmKHQlcyE9PTApdGhyb3cgbmV3IEVycm9yKCJCdWZmZXIgd2FzIG9mIGluY29ycmVjdCBzYW1wbGUgbGVuZ3RoLiIpO2lmKHQ8PTApcmV0dXJuW107Zm9yKHI9dGhpcy5vdXRwdXRCdWZmZXJTaXplLGE9W10sZj10aGlzLnJhdGlvV2VpZ2h0LGg9MCxuPTAsdT0wLG89IXRoaXMudGFpbEV4aXN0cyx0aGlzLnRhaWxFeGlzdHM9ITEsbD10aGlzLm91dHB1dEJ1ZmZlcixtPTAsZz0wLGU9MDtlPHM7KytlKWFbZV09MDtkb3tpZihvKWZvcihoPWYsZT0wO2U8czsrK2UpYVtlXT0wO2Vsc2V7Zm9yKGg9dGhpcy5sYXN0V2VpZ2h0LGU9MDtlPHM7KytlKWFbZV09dGhpcy5sYXN0T3V0cHV0W2VdO289ITB9Zm9yKDtoPjAmJm48dDspaWYodT0xK24tZyxoPj11KXtmb3IoZT0wO2U8czsrK2UpYVtlXSs9aVtuKytdKnU7Zz1uLGgtPXV9ZWxzZXtmb3IoZT0wO2U8czsrK2UpYVtlXSs9aVtuKyhlPjA/ZTowKV0qaDtnKz1oLGg9MDticmVha31pZihoPT09MClmb3IoZT0wO2U8czsrK2UpbFttKytdPWFbZV0vZjtlbHNle2Zvcih0aGlzLmxhc3RXZWlnaHQ9aCxlPTA7ZTxzOysrZSl0aGlzLmxhc3RPdXRwdXRbZV09YVtlXTt0aGlzLnRhaWxFeGlzdHM9ITA7YnJlYWt9fXdoaWxlKG48dCYmbTxyKTtyZXR1cm4gdGhpcy5idWZmZXJTbGljZShtKX19cmVzYW1wbGUoaSl7cmV0dXJuIHRoaXMuZnJvbVNhbXBsZVJhdGU9PXRoaXMudG9TYW1wbGVSYXRlP3RoaXMucmF0aW9XZWlnaHQ9MToodGhpcy5mcm9tU2FtcGxlUmF0ZTx0aGlzLnRvU2FtcGxlUmF0ZT90aGlzLmxhc3RXZWlnaHQ9MToodGhpcy50YWlsRXhpc3RzPSExLHRoaXMubGFzdFdlaWdodD0wKSx0aGlzLmluaXRpYWxpemVCdWZmZXJzKCksdGhpcy5yYXRpb1dlaWdodD10aGlzLmZyb21TYW1wbGVSYXRlL3RoaXMudG9TYW1wbGVSYXRlKSx0aGlzLnJlc2FtcGxlcihpKX19O2Z1bmN0aW9uIFMocCl7bGV0IGk9cC5sZW5ndGgsdD1uZXcgRmxvYXQzMkFycmF5KGkpO2Zvcig7aS0tOyl7bGV0IHI9cFtpXTt0W2ldPXI+PTMyNzY4Py0oNjU1MzYtcikvMzI3Njg6ci8zMjc2N31yZXR1cm4gdH12YXIgeT0xMDI0KjgsQj1jbGFzcyBleHRlbmRzIEF1ZGlvV29ya2xldFByb2Nlc3Nvcntjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KTt0aGlzLmNodW5rcz1bXTt0aGlzLmNodW5rUG9zaXRpb249MDt0aGlzLmlzRW5kZWQ9ITE7dGhpcy5pc0NhbmNlbGxlZD0hMTt0aGlzLnNhbXBsZVJhdGU9MDt0aGlzLmZvcm1hdD0iaW50MTYiO3RoaXMuYnVmZmVyT2Zmc2V0PTA7dGhpcy5sYXN0UGxheWVkQnVmZmVyU2l6ZT0wO3RoaXMuX2hhc1NlbnRFbmRFdmVudD0hMTt0aGlzLnBvcnQub25tZXNzYWdlPXI9PnRoaXMub25NZXNzYWdlKHIpfW9uTWVzc2FnZSh0KXtpZih0LmRhdGEuYWN0aW9uPT0ic3RhcnQiKXRoaXMuZm9ybWF0PXQuZGF0YS5mb3JtYXQsdGhpcy5zYW1wbGVSYXRlPXQuZGF0YS5pbnB1dFNhbXBsZVJhdGUsdGhpcy5yZXNhbXBsZXI9bmV3IGQodC5kYXRhLmlucHV0U2FtcGxlUmF0ZSx0LmRhdGEub3V0cHV0U2FtcGxlUmF0ZSwxLHkpLHRoaXMuZm9ybWF0PT0iaW50MTYiP3RoaXMuaW5wdXRCdWZmZXI9bmV3IGMoVWludDhBcnJheSx5KjIpOnRoaXMuZm9ybWF0PT0iZmxvYXQzMiImJih0aGlzLmlucHV0QnVmZmVyPW5ldyBjKFVpbnQ4QXJyYXkseSo0KSk7ZWxzZSBpZih0LmRhdGEuYWN0aW9uPT0iZGF0YSIpe2xldCByPW5ldyBVaW50OEFycmF5KHQuZGF0YS5idWZmZXIpO2Zvcih0aGlzLmlucHV0QnVmZmVyLmZlZWQocik7dGhpcy5pbnB1dEJ1ZmZlci5jYW5EcmFpbjspdGhpcy5kcmFpbkJ1ZmZlcigpfWVsc2UgdC5kYXRhLmFjdGlvbj09ImVuZCI/KHRoaXMubGFzdFBsYXllZEJ1ZmZlclNpemUmJnRoaXMuY2h1bmtzLnB1c2gobmV3IEZsb2F0MzJBcnJheSh0aGlzLmxhc3RQbGF5ZWRCdWZmZXJTaXplKjIpKSx0aGlzLmlzRW5kZWQ9ITApOnQuZGF0YS5hY3Rpb249PSJjYW5jZWwiJiYodGhpcy5pc0VuZGVkPSEwLHRoaXMuaXNDYW5jZWxsZWQ9ITApfWRyYWluQnVmZmVyKCl7bGV0IHQ9dGhpcy5pbnB1dEJ1ZmZlci5kcmFpbigpO2lmKCF0KXJldHVybjtsZXQgcjtpZih0aGlzLmZvcm1hdD09ImludDE2Iil7bGV0IHM9bmV3IEludDE2QXJyYXkodC5idWZmZXIsdC5ieXRlT2Zmc2V0LHQuYnl0ZUxlbmd0aC8yKTtyPVMocyl9ZWxzZSBpZih0aGlzLmZvcm1hdD09ImZsb2F0MzIiKXI9bmV3IEZsb2F0MzJBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQsdC5ieXRlTGVuZ3RoLzQpO2Vsc2UgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGZvcm1hdDogJHt0aGlzLmZvcm1hdH1gKTtsZXQgYT10aGlzLnJlc2FtcGxlci5yZXNhbXBsZShyKTt0aGlzLmNodW5rcy5wdXNoKGEpfW5leHRGbG9hdCgpe2lmKCF0aGlzLmNodW5rcy5sZW5ndGgpcmV0dXJuIDA7bGV0IHQ9dGhpcy5jaHVua3NbMF1bdGhpcy5jaHVua1Bvc2l0aW9uXTtyZXR1cm4gdGhpcy5jaHVua1Bvc2l0aW9uKyssdGhpcy5jaHVua1Bvc2l0aW9uPHRoaXMuY2h1bmtzWzBdLmxlbmd0aHx8KHRoaXMuY2h1bmtzLnNoaWZ0KCksdGhpcy5jaHVua1Bvc2l0aW9uPTApLHR9cHJvY2Vzcyh0LHIsYSl7aWYodGhpcy5pc0NhbmNlbGxlZClyZXR1cm4hMTtpZih0aGlzLmlzRW5kZWQmJiF0aGlzLmNodW5rcy5sZW5ndGgpcmV0dXJuIHRoaXMuX2hhc1NlbnRFbmRFdmVudHx8KHRoaXMuX2hhc1NlbnRFbmRFdmVudD0hMCx0aGlzLnBvcnQucG9zdE1lc3NhZ2Uoe2FjdGlvbjoiZW5kIn0pKSwhMTtsZXQgcz1yWzBdPy5bMF0/Lmxlbmd0aDtpZighcylyZXR1cm4hMDt0aGlzLmxhc3RQbGF5ZWRCdWZmZXJTaXplPXM7Zm9yKGxldCBmPTA7ZjxzO2YrKyl7bGV0IGg9dGhpcy5uZXh0RmxvYXQoKTtmb3IobGV0IGU9MDtlPHIubGVuZ3RoO2UrKylmb3IobGV0IG49MDtuPHJbZV0ubGVuZ3RoO24rKylyW2VdW25dW2ZdPWh9cmV0dXJuITB9fTtyZWdpc3RlclByb2Nlc3NvcigicGNtLXBsYXllci1ub2RlIixCKTsK";var ge="data:application/javascript;base64,dmFyIGc9Y2xhc3N7Y29uc3RydWN0b3IoZSx0LGksZil7aWYoIWV8fCF0fHwhaSl0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgc2V0dGluZ3Mgc3BlY2lmaWVkIGZvciB0aGUgcmVzYW1wbGVyLiIpO3RoaXMucmVzYW1wbGVyPW51bGwsdGhpcy5mcm9tU2FtcGxlUmF0ZT1lLHRoaXMudG9TYW1wbGVSYXRlPXQsdGhpcy5jaGFubmVscz1pfHwwLHRoaXMuaW5wdXRCdWZmZXJTaXplPWYsdGhpcy5pbml0aWFsaXplKCl9aW5pdGlhbGl6ZSgpe3RoaXMuZnJvbVNhbXBsZVJhdGU9PXRoaXMudG9TYW1wbGVSYXRlPyh0aGlzLnJlc2FtcGxlcj1lPT5lLHRoaXMucmF0aW9XZWlnaHQ9MSk6KHRoaXMuZnJvbVNhbXBsZVJhdGU8dGhpcy50b1NhbXBsZVJhdGU/KHRoaXMubGluZWFySW50ZXJwb2xhdGlvbigpLHRoaXMubGFzdFdlaWdodD0xKToodGhpcy5tdWx0aVRhcCgpLHRoaXMudGFpbEV4aXN0cz0hMSx0aGlzLmxhc3RXZWlnaHQ9MCksdGhpcy5pbml0aWFsaXplQnVmZmVycygpLHRoaXMucmF0aW9XZWlnaHQ9dGhpcy5mcm9tU2FtcGxlUmF0ZS90aGlzLnRvU2FtcGxlUmF0ZSl9YnVmZmVyU2xpY2UoZSl7dHJ5e3JldHVybiB0aGlzLm91dHB1dEJ1ZmZlci5zdWJhcnJheSgwLGUpfWNhdGNoe3RyeXtyZXR1cm4gdGhpcy5vdXRwdXRCdWZmZXIubGVuZ3RoPWUsdGhpcy5vdXRwdXRCdWZmZXJ9Y2F0Y2h7cmV0dXJuIHRoaXMub3V0cHV0QnVmZmVyLnNsaWNlKDAsZSl9fX1pbml0aWFsaXplQnVmZmVycygpe3RoaXMub3V0cHV0QnVmZmVyU2l6ZT1NYXRoLmNlaWwodGhpcy5pbnB1dEJ1ZmZlclNpemUqdGhpcy50b1NhbXBsZVJhdGUvdGhpcy5mcm9tU2FtcGxlUmF0ZS90aGlzLmNoYW5uZWxzKjEuMDAwMDAwNDc2ODM3MTU4MikrdGhpcy5jaGFubmVscyt0aGlzLmNoYW5uZWxzO3RyeXt0aGlzLm91dHB1dEJ1ZmZlcj1uZXcgRmxvYXQzMkFycmF5KHRoaXMub3V0cHV0QnVmZmVyU2l6ZSksdGhpcy5sYXN0T3V0cHV0PW5ldyBGbG9hdDMyQXJyYXkodGhpcy5jaGFubmVscyl9Y2F0Y2h7dGhpcy5vdXRwdXRCdWZmZXI9W10sdGhpcy5sYXN0T3V0cHV0PVtdfX1saW5lYXJJbnRlcnBvbGF0aW9uKCl7dGhpcy5yZXNhbXBsZXI9ZT0+e2xldCB0PWUubGVuZ3RoLGk9dGhpcy5jaGFubmVscyxmLGgsYSxzLHIsdSxuLHAsbDtpZih0JWkhPT0wKXRocm93IG5ldyBFcnJvcigiQnVmZmVyIHdhcyBvZiBpbmNvcnJlY3Qgc2FtcGxlIGxlbmd0aC4iKTtpZih0PD0wKXJldHVybltdO2ZvcihmPXRoaXMub3V0cHV0QnVmZmVyU2l6ZSxoPXRoaXMucmF0aW9XZWlnaHQsYT10aGlzLmxhc3RXZWlnaHQscz0wLHI9MCx1PTAsbj0wLHA9dGhpcy5vdXRwdXRCdWZmZXI7YTwxO2ErPWgpZm9yKHI9YSUxLHM9MS1yLHRoaXMubGFzdFdlaWdodD1hJTEsbD0wO2w8dGhpcy5jaGFubmVsczsrK2wpcFtuKytdPXRoaXMubGFzdE91dHB1dFtsXSpzK2VbbF0qcjtmb3IoYS09MSx0LT1pLHU9TWF0aC5mbG9vcihhKSppO248ZiYmdTx0Oyl7Zm9yKHI9YSUxLHM9MS1yLGw9MDtsPHRoaXMuY2hhbm5lbHM7KytsKXBbbisrXT1lW3UrKGw+MD9sOjApXSpzK2VbdSsoaStsKV0qcjthKz1oLHU9TWF0aC5mbG9vcihhKSppfWZvcihsPTA7bDxpOysrbCl0aGlzLmxhc3RPdXRwdXRbbF09ZVt1KytdO3JldHVybiB0aGlzLmJ1ZmZlclNsaWNlKG4pfX1tdWx0aVRhcCgpe3RoaXMucmVzYW1wbGVyPWU9PntsZXQgdD1lLmxlbmd0aCxpLGYsaD10aGlzLmNoYW5uZWxzLGEscyxyLHUsbixwLGwsbSxCO2lmKHQlaCE9PTApdGhyb3cgbmV3IEVycm9yKCJCdWZmZXIgd2FzIG9mIGluY29ycmVjdCBzYW1wbGUgbGVuZ3RoLiIpO2lmKHQ8PTApcmV0dXJuW107Zm9yKGk9dGhpcy5vdXRwdXRCdWZmZXJTaXplLGY9W10sYT10aGlzLnJhdGlvV2VpZ2h0LHM9MCx1PTAsbj0wLHA9IXRoaXMudGFpbEV4aXN0cyx0aGlzLnRhaWxFeGlzdHM9ITEsbD10aGlzLm91dHB1dEJ1ZmZlcixtPTAsQj0wLHI9MDtyPGg7KytyKWZbcl09MDtkb3tpZihwKWZvcihzPWEscj0wO3I8aDsrK3IpZltyXT0wO2Vsc2V7Zm9yKHM9dGhpcy5sYXN0V2VpZ2h0LHI9MDtyPGg7KytyKWZbcl09dGhpcy5sYXN0T3V0cHV0W3JdO3A9ITB9Zm9yKDtzPjAmJnU8dDspaWYobj0xK3UtQixzPj1uKXtmb3Iocj0wO3I8aDsrK3IpZltyXSs9ZVt1KytdKm47Qj11LHMtPW59ZWxzZXtmb3Iocj0wO3I8aDsrK3IpZltyXSs9ZVt1KyhyPjA/cjowKV0qcztCKz1zLHM9MDticmVha31pZihzPT09MClmb3Iocj0wO3I8aDsrK3IpbFttKytdPWZbcl0vYTtlbHNle2Zvcih0aGlzLmxhc3RXZWlnaHQ9cyxyPTA7cjxoOysrcil0aGlzLmxhc3RPdXRwdXRbcl09ZltyXTt0aGlzLnRhaWxFeGlzdHM9ITA7YnJlYWt9fXdoaWxlKHU8dCYmbTxpKTtyZXR1cm4gdGhpcy5idWZmZXJTbGljZShtKX19cmVzYW1wbGUoZSl7cmV0dXJuIHRoaXMuZnJvbVNhbXBsZVJhdGU9PXRoaXMudG9TYW1wbGVSYXRlP3RoaXMucmF0aW9XZWlnaHQ9MToodGhpcy5mcm9tU2FtcGxlUmF0ZTx0aGlzLnRvU2FtcGxlUmF0ZT90aGlzLmxhc3RXZWlnaHQ9MToodGhpcy50YWlsRXhpc3RzPSExLHRoaXMubGFzdFdlaWdodD0wKSx0aGlzLmluaXRpYWxpemVCdWZmZXJzKCksdGhpcy5yYXRpb1dlaWdodD10aGlzLmZyb21TYW1wbGVSYXRlL3RoaXMudG9TYW1wbGVSYXRlKSx0aGlzLnJlc2FtcGxlcihlKX19O2Z1bmN0aW9uIGQobyl7bGV0IGU9by5sZW5ndGgsdD1uZXcgSW50MTZBcnJheShlKTtmb3IoO2UtLTspe2xldCBpPU1hdGgubWF4KC0xLE1hdGgubWluKDEsb1tlXSkpO3RbZV09aTwwP2kqMzI3Njg6aSozMjc2N31yZXR1cm4gdH1mdW5jdGlvbiB3KG8pe2xldCBlPW8ubGVuZ3RoLHQ9bmV3IEJpZ0ludDY0QXJyYXkoZSk7Zm9yKDtlLS07KXtsZXQgaT1NYXRoLm1heCgtMSxNYXRoLm1pbigxLG9bZV0pKTt0W2VdPUJpZ0ludChNYXRoLmZsb29yKGk8MD9pKjMyNzY4OmkqMzI3NjcpKSoweDEwMDAwMDAwMDAwMG59cmV0dXJuIHR9dmFyIGM9Y2xhc3N7Y29uc3RydWN0b3IoZSx0KXt0aGlzLm91dHB1dEJ1ZmZlclNpemU9MDt0aGlzLnBhcnRpYWxCdWZmZXJzPVtdO3RoaXMucGFydGlhbEJ1ZmZlck9mZnNldD0wO2lmKCFlKXRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhcnJheSBjbGFzczogJHtlfWApO2lmKCF0fHx0PD0wKXRocm93IG5ldyBFcnJvcihgSW52YWxpZCBvdXRwdXQgYnVmZmVyIHNpemU6ICR7dH1gKTt0aGlzLkFycmF5Q2xhc3M9ZSx0aGlzLm91dHB1dEJ1ZmZlclNpemU9dH1nZXQgcXVldWVkU2l6ZSgpe3JldHVybiB0aGlzLnBhcnRpYWxCdWZmZXJzLnJlZHVjZSgoZSx0KT0+ZSt0Lmxlbmd0aCwwKX1mZWVkKGUpe3RoaXMucGFydGlhbEJ1ZmZlcnMucHVzaChlKX1nZXQgY2FuRHJhaW4oKXtyZXR1cm4gdGhpcy5wYXJ0aWFsQnVmZmVycy5yZWR1Y2UoKHQsaSk9PnQraS5sZW5ndGgsMCktdGhpcy5wYXJ0aWFsQnVmZmVyT2Zmc2V0Pj10aGlzLm91dHB1dEJ1ZmZlclNpemV9ZHJhaW4oKXtpZighdGhpcy5jYW5EcmFpbilyZXR1cm4gbnVsbDtsZXQgZT10aGlzLkFycmF5Q2xhc3MsdD1uZXcgZSh0aGlzLm91dHB1dEJ1ZmZlclNpemUpLGk9MDtmb3IoO2khPXQubGVuZ3RoOyl7aWYoaT50Lmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoYEJ1ZmZlciBvdmVyZmxvdzogJHtpfSA+ICR7dC5sZW5ndGh9YCk7bGV0IGY9dC5sZW5ndGgtaSxoPXRoaXMucGFydGlhbEJ1ZmZlcnNbMF0sYT1oLmxlbmd0aC10aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQ7YTxmPyh0LnNldChoLnN1YmFycmF5KHRoaXMucGFydGlhbEJ1ZmZlck9mZnNldCksaSksaSs9YSx0aGlzLnBhcnRpYWxCdWZmZXJzLnNoaWZ0KCksdGhpcy5wYXJ0aWFsQnVmZmVyT2Zmc2V0PTApOih0LnNldChoLnN1YmFycmF5KHRoaXMucGFydGlhbEJ1ZmZlck9mZnNldCx0aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQrZiksaSksaSs9Zix0aGlzLnBhcnRpYWxCdWZmZXJPZmZzZXQrPWYpfXJldHVybiB0fXBhZCgpe2xldCBlPXRoaXMucXVldWVkU2l6ZSV0aGlzLm91dHB1dEJ1ZmZlclNpemU7aWYoZT09MClyZXR1cm47bGV0IHQ9dGhpcy5BcnJheUNsYXNzLGk9bmV3IHQoZSk7dGhpcy5mZWVkKGkpfX07dmFyIHk9Y2xhc3MgZXh0ZW5kcyBBdWRpb1dvcmtsZXRQcm9jZXNzb3J7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5mb3JtYXQ9ImludDE2Ijt0aGlzLmlucHV0QnVmZmVyPW5ldyBjKEZsb2F0MzJBcnJheSw0MDk2KTt0aGlzLnBvcnQub25tZXNzYWdlPWk9PnRoaXMub25NZXNzYWdlKGkpfW9uTWVzc2FnZSh0KXt0LmRhdGEuYWN0aW9uPT0ic3RhcnQiJiYodGhpcy5mb3JtYXQ9dC5kYXRhLmZvcm1hdCx0aGlzLnJlc2FtcGxlcj1uZXcgZyh0LmRhdGEuaW5wdXRTYW1wbGVSYXRlLHQuZGF0YS5vdXRwdXRTYW1wbGVSYXRlLDEsNDA5NiksdGhpcy5mb3JtYXQ9PSJpbnQxNiI/dGhpcy5vdXRwdXRCdWZmZXI9bmV3IGMoSW50MTZBcnJheSx0LmRhdGEuYnVmZmVyU2l6ZSk6dGhpcy5mb3JtYXQ9PSJpbnQ2NCI/dGhpcy5vdXRwdXRCdWZmZXI9bmV3IGMoQmlnSW50NjRBcnJheSx0LmRhdGEuYnVmZmVyU2l6ZSk6dGhpcy5mb3JtYXQ9PSJmbG9hdDMyIiYmKHRoaXMub3V0cHV0QnVmZmVyPW5ldyBjKEZsb2F0MzJBcnJheSx0LmRhdGEuYnVmZmVyU2l6ZSkpKX1wcm9jZXNzKHQsaSxmKXtmb3IobGV0IGE9MDthPGkubGVuZ3RoO2ErKyl7bGV0IHM9TWF0aC5taW4oaVthXS5sZW5ndGgsdFswXS5sZW5ndGgpO2ZvcihsZXQgcj0wO3I8cztyKyspaVthXVtyXS5zZXQodFswXVtyXSl9aWYoIXRoaXMucmVzYW1wbGVyKXJldHVybiEwO2xldCBoPW5ldyBGbG9hdDMyQXJyYXkoaVswXVswXS5sZW5ndGgpO2ZvcihoLnNldChpWzBdWzBdKSx0aGlzLmlucHV0QnVmZmVyLmZlZWQoaCk7dGhpcy5pbnB1dEJ1ZmZlci5jYW5EcmFpbjspe2xldCBhPXRoaXMuaW5wdXRCdWZmZXIuZHJhaW4oKSxzPXRoaXMucmVzYW1wbGVyLnJlc2FtcGxlKGEpO3RoaXMuZm9ybWF0PT0iaW50MTYiP3RoaXMub3V0cHV0QnVmZmVyLmZlZWQoZChzKSk6dGhpcy5mb3JtYXQ9PSJpbnQ2NCI/dGhpcy5vdXRwdXRCdWZmZXIuZmVlZCh3KHMpKTp0aGlzLmZvcm1hdD09ImZsb2F0MzIiJiZ0aGlzLm91dHB1dEJ1ZmZlci5mZWVkKHMpfWZvcig7dGhpcy5vdXRwdXRCdWZmZXIuY2FuRHJhaW47KXtsZXQgYT10aGlzLm91dHB1dEJ1ZmZlci5kcmFpbigpO2lmKCFhKWJyZWFrO3RoaXMucG9ydC5wb3N0TWVzc2FnZSh7YWN0aW9uOiJkYXRhIixidWZmZXI6YS5idWZmZXJ9LFthLmJ1ZmZlcl0pfXJldHVybiEwfX07cmVnaXN0ZXJQcm9jZXNzb3IoInBjbS1yZWNlaXZlci1ub2RlIix5KTsK";var Se=new u("PCMPlayerNode"),z=class extends AudioWorkletNode{constructor(e,t,i){super(e,"pcm-player-node",{numberOfInputs:0});this.sampleRate=0;this.format="int16";this.isCancelled=!1;if(!t||t<=0)throw new Error(`Invalid sample rate: ${t}`);if(!i||i!="int16"&&i!="float32")throw new Error(`Invalid format: ${i}`);this.sampleRate=t,this.format=i,this.port.onmessage=n=>this.onWorkletMessage(n),this.port.postMessage({action:"start",inputSampleRate:t,outputSampleRate:e.sampleRate,format:i})}feed(e){this.port.postMessage({action:"data",buffer:e.buffer},[e.buffer])}async play(e){if(this.isCancelled)throw new Error("PCMPlayerNode has already been cancelled.");if(this._playPromise)throw new Error("Already playing a stream");this._playPromise=new Promise(t=>this._playPromiseResolve=t),this.dispatchEvent(new CustomEvent("start",{detail:{player:this,stream:e}}));try{let t=e.getReader();for(;!this.isCancelled;){let{done:i,value:n}=await t.read();if(i||!n)break;this.feed(n)}}catch(t){Se.warn("Stream error:",t),this.dispatchEvent(new CustomEvent("error",{detail:{player:this,stream:e,error:t}}))}this.port.postMessage({action:"end"}),await this._playPromise}onWorkletMessage(e){e.data.action=="end"&&(this._playPromiseResolve?.(),this.dispatchEvent(new CustomEvent("end",{detail:{player:this}})))}stop(){this.isCancelled=!0,this.port.postMessage({action:"cancel"}),this._playPromiseResolve?.()}};var F=new u("SpeechOutput"),fe=.5,Me=.8,A=class extends EventTarget{constructor(s){super(),this.ai=s,this.ai.addEventListener("output",e=>this.onTextOutputFromAI(e)),this.ai.audio?.speechRecognition.addEventListener("speechstart",e=>this.interrupt()),this.ai.knowledgeBase.registerSource(()=>[{id:"system.voice",type:"info",name:"Voice active",isContext:!0,disabled:!1,content:"Text-to-speech is active. The user can hear your voice."}])}onTextOutputFromAI(s){s.detail.isChunk||this.ai?.audio?.speechRecognition.isRunning&&this.speak(s.detail.message)}async speak(s){if(!this.ai?.config?.voice?.providerID)return F.warn("No voice provider configured");let e=`speech-${Ve++}`;await this.ai.audio.beginAccess(e);try{await this._speakWithLock(s)}finally{this.ai.audio.endAccess(e)}}async _speakWithLock(s){this.interrupt(),this.ai.audio.speechRecognition.voiceDetection&&(this.ai.audio.speechRecognition.voiceDetection.sensitivity=Me);let e=this.ai?._voiceTracker||F.timer(`${this.ai.config.voice.providerID} voice`);e(`Speak: ${s}`),this.currentPlayerVolume?.disconnect(),this.currentPlayerVolume=this.ai.audio.context.createGain(),this.currentPlayerVolume.connect(this.ai.audio.context.destination);let t=this.currentPlayerVolume,i=new z(this.ai.audio.context,24e3,"int16");this.currentPlayer=i,i.connect(t),i.addEventListener("end",o=>{let r=o;e(`PCM stream ${r.detail.interrupted?"interrupted":"ended"}`),this.currentPlayer==i&&!r.detail.interrupted&&(this.currentPlayer=void 0,this.onSpeechEnd())});let n;if(this.ai.config.voice.providerID=="openai")n=await fetch("https://api.openai.com/v1/audio/speech",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.ai.config.voice.apiKey}`},body:JSON.stringify({model:"tts-1",input:s,voice:this.ai.config.voice.voiceID,response_format:"pcm"})});else if(this.ai.config.voice.providerID=="elevenlabs")n=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${this.ai.config.voice.voiceID}?output_format=pcm_24000`,{method:"POST",headers:{"xi-api-key":`${this.ai.config.voice.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({text:s})});else{F.warn(`Unknown voice provider: ${this.ai.config.voice.providerID}`);return}if(e(`Received response ${n.status} ${n.statusText}`),!n.ok){F.warn(`Failed to generate voice sample: ${n.status} ${n.statusText}`);return}this.dispatchEvent(new CustomEvent("speechstart",{detail:{ai:this.ai,message:s}})),e("Playing PCM stream"),await i.play(n.body),e("Audio has ended")}get isSpeaking(){return!!this.currentPlayer}async interrupt(){if(!this.currentPlayerVolume)return;let s=this.currentPlayerVolume,e=this.currentPlayer;this.currentPlayerVolume=void 0,this.currentPlayer=void 0,this.ai?.audio?.speechRecognition.voiceDetection&&(this.ai.audio.speechRecognition.voiceDetection.sensitivity=fe);let t=400;s.gain.linearRampToValueAtTime(0,t/1e3),await new Promise(i=>setTimeout(i,t+250)),s.disconnect(),e?.stop(),e?.disconnect()}onSpeechEnd(){this.dispatchEvent(new CustomEvent("speechend",{detail:{ai:this.ai}})),this.ai?.audio?.speechRecognition.voiceDetection&&(this.ai.audio.speechRecognition.voiceDetection.sensitivity=fe)}},Ve=1;function Y(d,s){let e=s.reduce((c,l)=>c+l.byteLength,0),t=new DataView(new ArrayBuffer(44));t.setUint8(0,82),t.setUint8(1,73),t.setUint8(2,70),t.setUint8(3,70),t.setUint32(4,44+e,!0),t.setUint8(8,87),t.setUint8(9,65),t.setUint8(10,86),t.setUint8(11,69);let i=1,n=32,o=i*n/8,r=d*o;return t.setUint8(12,102),t.setUint8(13,109),t.setUint8(14,116),t.setUint8(15,32),t.setUint32(16,16,!0),t.setUint16(20,3,!0),t.setUint16(22,i,!0),t.setUint32(24,d,!0),t.setUint32(28,r,!0),t.setUint16(32,o,!0),t.setUint16(34,n,!0),t.setUint8(36,100),t.setUint8(37,97),t.setUint8(38,116),t.setUint8(39,97),t.setUint32(40,e,!0),new File([t,...s],"audio.wav",{type:"audio/wav"})}var H=class extends AudioWorkletNode{constructor(e,t,i,n){super(e,"pcm-receiver-node",{numberOfInputs:1});this.format="int16";this.format=i;let o=["int16","int64","float32"];if(!t||t<=0)throw new Error(`Invalid sample rate: ${t}`);if(!o.includes(i))throw new Error(`Invalid format ${i}, must be one of: ${o.join(", ")}`);if(!n||n<=0)throw new Error(`Invalid buffer size: ${n}`);this.port.onmessage=r=>this.onWorkletMessage(r),this.port.postMessage({action:"start",inputSampleRate:e.sampleRate,outputSampleRate:t,format:i,bufferSize:n})}onWorkletMessage(e){if(e.data.action=="data"){let t=null;if(this.format=="int16"&&(t=new Int16Array(e.data.buffer)),this.format=="int64"&&(t=new BigInt64Array(e.data.buffer)),this.format=="float32"&&(t=new Float32Array(e.data.buffer)),!t)throw new Error(`Invalid format: ${this.format}`);this.onData(t),this.dispatchEvent(new CustomEvent("data",{detail:{data:t}}))}}onData(e){}};var te=16e3,D=256,W=8,C=new u("VoiceDetectionNode"),E=class E extends H{constructor(e){super(e,te,"float32",D*W);this.isVoiceActive=!1;this.lastVoiceActiveDate=0;this.voiceEndTimeout=50;this.sensitivity=.5;this.sentivityEnd=.2;this.nextVadReset=0;this.currentProbability=0;this._lastVoiceActive=!1;if(!E.vadModelURL)throw new Error("VAD model url not set, please load it and set it to VoiceDetectionNode.vadModelURL");this.loadModel()}get isVoicePossiblyEnding(){return this.isVoiceActive&&this.currentProbability<this.sensitivity}get sampleRate(){return te}get numberOfSamples(){return D}get numberOfSampleChunks(){return W}get outputBufferSize(){return D*W}get isModelLoaded(){return!!this.vad}async loadModel(){C.debug("Loading VAD model"),this.vad=await g.load(E.vadModelURL),this.vad.ignoreIfBusy=!0,C.debug("Model loaded"),this.vad.makeConstant("sr","int64",[1],te),this.vad.makeState("h","hn","float32",[2,W,64]),this.vad.makeState("c","cn","float32",[2,W,64])}async onData(e){if(this.vad)try{let t=await this.vad.run({input:new g.onnx.Tensor(e,[W,D])});if(!t)return;this.currentProbability=0;for(let o=0;o<t.output.data.length;o++)t.output.data[o]>this.currentProbability&&(this.currentProbability=t.output.data[o]);let i=this.isVoiceActive?this.sentivityEnd:this.sensitivity,n=this.currentProbability>i;if(!n&&this._lastVoiceActive&&(this.nextVadReset=Date.now(),this.vad.resetState()),this._lastVoiceActive=n,n&&!this.isVoiceActive?(this.lastVoiceActiveDate=Date.now(),this.isVoiceActive=!0,this.dispatchEvent(new CustomEvent("speechstart")),this.onSpeechStart(),C.debug("Started speaking")):n?this.lastVoiceActiveDate=Date.now():!n&&this.isVoiceActive&&Date.now()<this.lastVoiceActiveDate+this.voiceEndTimeout||!n&&this.isVoiceActive&&(this.isVoiceActive=!1,this.dispatchEvent(new CustomEvent("speechend")),this.onSpeechEnd(),C.debug("Stopped speaking after timeout")),!n){let o=Date.now();o>this.nextVadReset&&(this.nextVadReset=o+5e3,this.vad.resetState())}}catch(t){C.error("VAD failed:",t)}}onSpeechStart(){}onSpeechEnd(){}};E.vadModelURL="";var I=E;var ye=new u("VoiceChunkOutputNode"),S=class extends I{constructor(){super(...arguments);this.buffers=[];this.recordedBuffers=[];this._voiceRecording=!1;this.backBufferDurationSeconds=3}get bufferDuration(){return this.buffers.reduce((e,t)=>e+t.length,0)/8e3}async onData(e){if(await super.onData(e),this.isVoiceActive&&!this._voiceRecording){ye.debug(`Voice detected, sending ${this.buffers.length} existing chunks`),this._voiceRecording=!0;for(let t of this.buffers)this.recordedBuffers.push(t),this.dispatchEvent(new CustomEvent("voicedata",{detail:{data:t,isFinal:!1}})),this.onVoiceChunk(t);this.recordedBuffers.push(e),this.dispatchEvent(new CustomEvent("voicedata",{detail:{data:e,isFinal:!1}})),this.onVoiceChunk(e),this.buffers=[]}else if(this.isVoiceActive)this.recordedBuffers.push(e),this.dispatchEvent(new CustomEvent("voicedata",{detail:{data:e,isFinal:!1}})),this.onVoiceChunk(e);else if(!this.isVoiceActive&&this._voiceRecording){this.recordedBuffers.push(e),this.dispatchEvent(new CustomEvent("voicedata",{detail:{data:e,isFinal:!0}})),this.onVoiceChunk(e),this._voiceRecording=!1;let t=this.recordedBuffers.reduce((i,n)=>i+n.length,0);ye.debug(`Voice complete, recorded ${(t/8e3).toFixed(2)} seconds of audio, ${t*4/1024} KB of data`),this.dispatchEvent(new CustomEvent("voicedataend",{detail:{data:this.recordedBuffers}})),this.onVoiceEnd(this.recordedBuffers),this.recordedBuffers=[]}else for(this.buffers.push(e);this.bufferDuration>this.backBufferDurationSeconds;)this.buffers.shift()}onVoiceChunk(e){}onVoiceEnd(e){}};var J=new u("OpenAITranscriptionNode"),U=class extends S{constructor(e,t){super(e);this.apiKey="";this.pendingBuffers=[];this.isTranscribing=!1;this.apiKey=t}async onVoiceEnd(e){let t=J.timer("OpenAI Transcribe");this.isTranscribing=!0,this.pendingBuffers.push(...e);let i=Y(this.sampleRate,this.pendingBuffers);this.lastRequestAbortController?.abort(),this.lastRequestAbortController=new AbortController;let n="";try{let o=new FormData;o.append("file",i),o.append("model","whisper-1"),o.append("response_format","text");let r=await fetch("https://api.openai.com/v1/audio/transcriptions",{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:o,signal:this.lastRequestAbortController.signal});if(!r.ok)throw new Error(`Failed to generate voice sample: ${r.status} ${r.statusText}`);t("Response received"),n=await r.text(),t("Content received: "+n),this.lastRequestAbortController=void 0}catch(o){J.error(`Failed to transcribe speech: ${o.message}`);return}finally{this.isTranscribing=!1}if(this.pendingBuffers=[],!n)return J.debug("Transcription complete, but no text was found");J.debug(`Transcription: ${n}`),this.onVoiceTranscription(n),this.dispatchEvent(new CustomEvent("transcription",{detail:{text:n}}))}onVoiceTranscription(e){}};var O=class extends WebSocket{constructor(e){super(e);this.pendingData=[];this.addEventListener("open",()=>this._onOpen())}send(e){this.readyState==WebSocket.OPEN?super.send(e):this.pendingData.push(e)}_onOpen(){for(let e of this.pendingData)super.send(e);this.pendingData=[]}};var f=new u("IntelliWeaveTranscriptionNode"),Re="wss://speech.intelliweave.ai/api/v1/transcribe",Q=class Q extends S{constructor(e,t){super(e);this.apiAddress=Re;this.apiKey="";this.isTranscribing=!1;this.apiKey=t}async onVoiceChunk(e){this.isTranscribing=!0,this.ws?this.ws.send(e):(f.debug("Opening WebSocket connection"),this.ws=new O(this.apiAddress),this.ws.send(JSON.stringify({type:"hello",sampleRate:16e3,channels:1,format:"float32",apiKey:this.apiKey})),this.ws.send(e.buffer),this.ws.onopen=()=>{f.debug("WebSocket connection opened")},this.ws.addEventListener("message",i=>{let n=JSON.parse(i.data);if(n.error)return f.warn("Error: "+n.error);if(n.type!="transcription")return f.warn("Invalid response type",n);if(n.streaming&&!n.final)return f.debug("Partial transcription: "+n.partialText);if(this.isTranscribing=!1,!n.text.trim())return f.warn(`Empty transcription (${n.processingTime}ms)`);f.debug(`Transcription: ${n.text} (${n.processingTime}ms)`),this.onVoiceTranscription(n.text),this.dispatchEvent(new CustomEvent("transcription",{detail:{text:n.text}}))}),this.ws.addEventListener("close",()=>this.onSocketClose()),this.ws.addEventListener("error",i=>f.warn("WebSocket error")));let t=1e3*60*1;this.shutdownTimer&&clearTimeout(this.shutdownTimer),this.shutdownTimer=setTimeout(()=>{f.debug("Shutting down WebSocket connection"),this.ws?.close(),this.ws=void 0},t)}async onVoiceEnd(e){if(this.ws?.send(JSON.stringify({type:"end"})),Q.debugExportWav){let t=Y(this.sampleRate,e),i=document.createElement("a");i.href=URL.createObjectURL(t),i.download="recording.wav",i.click()}}onVoiceTranscription(e){}onSocketClose(){f.debug("WebSocket connection closed"),this.ws=void 0,this.isTranscribing=!1}};Q.debugExportWav=!1;var j=Q;var ie=new u("SpeechRecognition"),_=class extends EventTarget{constructor(e){super();this.isRunning=!1;this._skipEvents=!1;this.maxVolumeHeard=0;this.ai=e,this.ai.knowledgeBase.registerSource(()=>[{id:"system.microphone.enable",type:"action",name:"Enable or disable microphone",isContext:!0,content:`Starts or stops listening to input from the user through the microphone. ${this.isRunning?"Microphone access is currently enabled and you can hear the user.":"Microphone access is currently disabled."}.`,parameters:[{name:"enable",type:"boolean",description:"If true, enables the microphone. If false, disables it."}],action:async t=>{t.enable?await this.start():this.stop()}}])}get isSupported(){if(!g.lib||!this.ai?.vadModel||!b().AudioWorkletNode)return!1;if(this.ai?.config?.transcription?.providerID!="intelliweave"){if(!(this.ai?.config?.transcription?.providerID=="openai"&&this.ai.config?.transcription?.apiKey))return!1}return!0}async start(){if(!this.isSupported)throw new Error("Speech recognition not supported in this persona and browser.");if(!this.isRunning){this.isRunning=!0;try{await this.ai.audio.beginAccess("speech-recognition"),this.micStream=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,echoCancellation:!0,autoGainControl:!0,noiseSuppression:!0}});let e=this.ai.audio.context.createMediaStreamSource(this.micStream);this.analyserNode=this.ai.audio.context.createAnalyser(),this.analyserNode.fftSize=32,e.connect(this.analyserNode),this.analyserBuffer=new Float32Array(this.analyserNode.fftSize),I.vadModelURL=URL.createObjectURL(this.ai.vadModel),this.ai?.config?.transcription?.providerID=="openai"?(this.voiceDetection=new U(this.ai.audio.context,this.ai.config.transcription.apiKey),e.connect(this.voiceDetection)):(this.voiceDetection=new j(this.ai.audio.context,this.ai.apiKey),this.voiceDetection.apiAddress=this.ai?.config?.transcription?.url||this.voiceDetection.apiAddress,e.connect(this.voiceDetection)),this.voiceDetection.addEventListener("speechstart",t=>{this.ai._voiceTracker=ie.timer("voice interaction","Speech started"),this.dispatchEvent(new CustomEvent(t.type,{detail:t.detail}))}),this.voiceDetection.addEventListener("speechend",t=>{this.ai._voiceTracker?.("Speech ended"),this.dispatchEvent(new CustomEvent(t.type,{detail:t.detail}))}),this.voiceDetection.addEventListener("transcription",t=>{this.ai._voiceTracker?.(`Transcription: ${t.detail.text}`),this.onTranscription(t)}),this._skipEvents||this.dispatchEvent(new CustomEvent("start",{detail:{speechRecognition:this}}))}catch(e){ie.error("Failed to start speech recognition:",e),this.stop()}}}stop(){this.isRunning&&(this.isRunning=!1,this.ai.audio.endAccess("speech-recognition"),this.voiceDetection?.disconnect(),this.voiceDetection=void 0,this.micStream?.getTracks().forEach(e=>e.stop()),this.micStream=void 0,this.analyserNode=void 0,this.analyserBuffer=void 0,this._skipEvents||this.dispatchEvent(new CustomEvent("end",{detail:{speechRecognition:this}})))}get volumeLevel(){if(!this.analyserNode||!this.analyserBuffer)return 0;this.analyserNode.getFloatTimeDomainData(this.analyserBuffer);let e=0;for(let i of this.analyserBuffer)e+=i*i;let t=Math.sqrt(e/this.analyserBuffer.length);return t>this.maxVolumeHeard&&(this.maxVolumeHeard=t),this.maxVolumeHeard*=.999,this.maxVolumeHeard<.01&&(this.maxVolumeHeard=.01),Math.min(1,Math.max(0,t/this.maxVolumeHeard))}get wordsCurrentlyBeingSpoken(){return!!this.voiceDetection?.isVoiceActive}get isTranscribing(){return!!this.voiceDetection?.isTranscribing}onTranscription(e){let t=e.detail.text;ie.debug("Heard:",t),this.dispatchEvent(new CustomEvent("speech",{detail:{transcript:t,isFinal:!0}}))}async reset(){if(this.isRunning){this._skipEvents=!0;try{this.stop(),await this.start(),this._skipEvents=!1}catch(e){throw this._skipEvents=!1,e}}}};var $=new u("AudioSystem"),M=class{constructor(s){this.locks=[];if(!s)throw new Error("AI reference is required. Please pass in the IntelliWeave instance to the constructor.");this.ai=s,this.ai.audio=this,this.speechRecognition=new _(this.ai),this.speechOutput=new A(this.ai)}static get isSupported(){return!(!g.lib||!b().AudioWorkletNode)}async beginAccess(s){$.debug(`Began access for: ${s}`),this.locks.includes(s)||this.locks.push(s),!this.context&&($.debug("Creating AudioContext"),this.context=new AudioContext({latencyHint:"interactive"}),this.context.resume(),await Promise.all([this.context.audioWorklet.addModule(me),this.context.audioWorklet.addModule(ge)]))}endAccess(s){$.debug(`Ended access for: ${s}`),this.locks=this.locks.filter(e=>e!=s),!this.locks.length&&($.debug("Closing AudioContext"),this.context?.close(),this.context=void 0)}};var bi=new u("Stream");import xi,{createContext as Ce,useContext as Zi,useEffect as Gi,useMemo as Xi,useState as Wi}from"react";var Ci=new u("React");var Ei=Ce(void 0);var se=new u("Embed"),v=class extends m{constructor(){super();this.config={};this.suggestions=[];this.html=()=>`
254
254
 
255
255
  <!-- Styling -->
256
256
  <style>
257
257
 
258
258
  #root {
259
259
  position: fixed;
260
- display: flex;
261
- flex-direction: column;
262
260
  width: 64px;
263
261
  height: 64px;
264
262
  z-index: 200000;
265
263
  background-color: #20262C;
266
- border-radius: 32px;
264
+ border-radius: 50%;
267
265
  box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
268
266
  transition: width 0.25s, height 0.25s, border-radius 0.25s;
269
267
  overflow: hidden;
270
268
  color: white;
271
269
  font-family: "Karla", sans-serif;
270
+ overlow: hidden;
272
271
  }
273
272
  #root.open {
274
273
  border-radius: 32px 32px 16px 16px;
274
+ display: flex;
275
+ flex-direction: column;
275
276
  width: 400px;
276
277
  height: 600px;
277
278
  max-width: calc(100vw - 40px);
278
279
  max-height: calc(max(50vh, 100vh - 320px));
280
+ overflow: visible;
279
281
  }
280
282
 
281
283
  #root #web-weaver-logo {
@@ -285,6 +287,7 @@ You have access to a database of knowledge base items. These include "info" type
285
287
  top: 0px;
286
288
  left: 0px;
287
289
  background-color: #21262c;
290
+ border-radius:50%;
288
291
  z-index:999;
289
292
  }
290
293
 
@@ -303,6 +306,8 @@ You have access to a database of knowledge base items. These include "info" type
303
306
  overflow: hidden;
304
307
  font-size: 9px;
305
308
  color: #abacad;
309
+ border-bottom-right-radius: 16px;
310
+ border-bottom-left-radius: 16px;
306
311
  }
307
312
 
308
313
  #root .green-accent {
@@ -424,4 +429,4 @@ You have access to a database of knowledge base items. These include "info" type
424
429
 
425
430
  </div>
426
431
 
427
- `;this._isProcessing=!1;this.ai=new G,M.isSupported&&(this.ai.audio=new M(this.ai))}onCreate(){p().embed&&se.warn("Only one <web-weaver-embed> element should be on the page."),p().embed=this,this.child("root").addEventListener("click",i=>this.onContainerClick(i)),this.child("web-weaver-logo").addEventListener("click",i=>this.onLogoClick(i)),this.child("interaction-bar").addEventListener("input-message",i=>this.processInput(i.detail)),this.child("interaction-bar").addEventListener("llm-button-click",i=>this.state.llmPanelOpen=!this.state.llmPanelOpen),this.child("llm-selector-panel").addEventListener("select",i=>this.onLLMModelSelect(i)),this.child("interaction-bar").connectAI(this.ai),this.ai.onAIMessage=this.onAIMessage.bind(this),this.ai.onAIToolStart=this.onAIToolStart.bind(this),this.ai.knowledgeBase.addEntry({id:"ui.suggestResponse",type:"action",name:"Suggest a response",content:"Add a button with a suggested response for the user's next message. Supports multiple calls at once.",isContext:!0,parameters:[{name:"text",type:"string",description:"The suggested response for the user's next message."}],action:i=>(this.suggestions.push(i.text),this.ai.submitAnalyticsEvent({type:"suggest-response",text:i.text}),"Suggestion button added")});let t=this.attr.apiKey||p().apiKey;if(!t)return se.warn("No API key specified, some features may be unavailable.");this.state.loading=!0,this.ai.load(t).then(i=>{this.config=i,p().introductionMessage=this.config.introductionMessage,p().analytics=this.config.analytics!==void 0?!!this.config.analytics:p().analytics,this.state.loading=!1,this.resetConversation()})}onUpdate(){this.child("web-weaver-embed-inner").style.display=this.attr.open?"":"none",this.child("interaction-bar").style.display=this.attr.open?"":"none",this.child("root").className=this.attr.open?"open":"",this.child("llm-selector-panel").attr.open=this.state.llmPanelOpen,this.child("pulseanim").style.display=this.attr.open?"none":"",this.child("root").style.right=this.attr.offsetX?this.attr.offsetX+"px":"20px",this.child("root").style.bottom=this.attr.offsetY?this.attr.offsetY+"px":"20px",this.child("interaction-bar").attr.loading=this.state.loading,this.child("interaction-bar").attr.llmName=this.ai.currentModel?.metadata?.name||this.ai.currentModel?.id||"None",this.child("interaction-bar").attr.llmButtonVisible=this.ai.models.length>1;let e=this.child("web-weaver-logo");e.attr.focusID=this.attr.focusID,e.refreshLayout(),this.child("llm-selector-panel").state.items=this.ai.models.sort((t,i)=>(i.priority||0)-(t.priority||0)),this.child("llm-selector-panel").state.selectedID=this.ai.currentModel?.id}onDestroy(){p().embed==this&&(p().embed=null)}onContainerClick(e){this.attr.open||(e.preventDefault(),this.attr.open=!0)}onLogoClick(e){e.preventDefault(),e.stopPropagation(),this.attr.focusID?this.attr.focusID="":this.attr.open=!this.attr.open}open(){this.attr.open=!0}close(){this.attr.open=!1}resetConversation(){let e=this.child("web-weaver-embed-inner");for(this.state.llmPanelOpen=!1;e.children.length>0;)e.children[0].remove();this.ai.resetConversation(),this.suggestions=[];let t=document.createElement("div");t.className="introduction-message",t.innerHTML=p().introductionMessage||`Welcome to <b>${document.title||"Web Weaver"}</b>. How can I help you?`,e.appendChild(t),this.ai.insertAssistantMessage(t.innerText);for(let i of p().introductionSuggestions||[]){let n=document.createElement("div");n.className="suggestion-button",n.innerText=i,n.addEventListener("click",o=>this.onSuggestionClick(o,i)),e.appendChild(n)}}async processInput(e){if(this._isProcessing)return;this._isProcessing=!0,this.state.loading=!0,this.state.llmPanelOpen=!1;let t=this.child("web-weaver-embed-inner");this.suggestions=[];try{for(let n of Array.from(t.querySelectorAll(".suggestion-button")))n.remove();this.attr.focusID="";let i=document.createElement("div");i.className="input",i.innerText=e,t.appendChild(i),t.lastElementChild?.scrollIntoView({behavior:"instant",block:"end"}),await this.ai.sendMessage(e);for(let n of this.suggestions){let o=document.createElement("div");o.className="suggestion-button",o.innerText=n,o.addEventListener("click",r=>this.onSuggestionClick(r,n)),t.appendChild(o)}t.lastElementChild?.scrollIntoView({behavior:"instant",block:"end"})}catch(i){se.error("Failed to process input:",i);let n=document.createElement("div");n.className="output",n.innerText="Sorry, there was a problem getting a response. "+i.message,t.appendChild(n);let o=document.createElement("div");o.className="suggestion-button",o.innerText="Reset conversation",o.addEventListener("click",r=>this.resetConversation()),t.appendChild(o)}this.state.loading=!1,this._isProcessing=!1}async onAIMessage(e){let t=await Pe().use(ke).use(Be).use(Ee,{target:"_blank",rel:["noopener","noreferrer"]}).use(Te).use(Le).processSync(e),i=this.child("web-weaver-embed-inner"),n=i.lastElementChild;if(n&&n.classList.contains("output"))n.innerHTML=t.toString("utf-8");else{let o=document.createElement("div");o.className="output",o.innerHTML=t.toString("utf-8"),i.appendChild(o)}for(let o of Array.from(i.querySelectorAll(".tool")))o.remove();i.lastElementChild?.scrollIntoView({behavior:"instant",block:"end"})}onAIToolStart(e,t){let i=`Running: ${e}`;e=="search"&&(i=`Searching: ${t?.query}`),e=="ui.focusElement"&&(i=`Focusing: #${t?.elementID}`),e=="ui.suggestResponse"&&(i=`Suggested response: ${t?.text}`);let n=this.child("web-weaver-embed-inner"),o=document.createElement("div");o.className="tool",o.innerText=i,n.appendChild(o),n.lastElementChild?.scrollIntoView({behavior:"instant",block:"end"})}onSuggestionClick(e,t){this.processInput(t)}onLLMModelSelect(e){e.preventDefault(),this.ai.setModel(e.detail),this.state.llmPanelOpen=!1}};v.tagName="intelliweave-embed",v.observedAttributes=["logo","focusID","open"];var vs=v;g.lib=()=>import("onnxruntime-web");v.register();export{vs as default};
432
+ `;this._isProcessing=!1;this.ai=new G,M.isSupported&&(this.ai.audio=new M(this.ai))}onCreate(){p().embed&&se.warn("Only one <web-weaver-embed> element should be on the page."),p().embed=this,this.child("root").addEventListener("click",i=>this.onContainerClick(i)),this.child("web-weaver-logo").addEventListener("click",i=>this.onLogoClick(i)),this.child("interaction-bar").addEventListener("input-message",i=>this.processInput(i.detail)),this.child("interaction-bar").addEventListener("llm-button-click",i=>this.state.llmPanelOpen=!this.state.llmPanelOpen),this.child("llm-selector-panel").addEventListener("select",i=>this.onLLMModelSelect(i)),this.child("interaction-bar").connectAI(this.ai),this.ai.onAIMessage=this.onAIMessage.bind(this),this.ai.onAIToolStart=this.onAIToolStart.bind(this),this.ai.knowledgeBase.addEntry({id:"ui.suggestResponse",type:"action",name:"Suggest a response",content:"Add a button with a suggested response for the user's next message. Supports multiple calls at once.",isContext:!0,parameters:[{name:"text",type:"string",description:"The suggested response for the user's next message."}],action:i=>(this.suggestions.push(i.text),this.ai.submitAnalyticsEvent({type:"suggest-response",text:i.text}),"Suggestion button added")});let t=this.attr.apiKey||p().apiKey;if(!t)return se.warn("No API key specified, some features may be unavailable.");this.state.loading=!0,this.attr.hubAPI&&(this.ai.hubAPI=this.attr.hubAPI),this.ai.load(t).then(i=>{this.config=i,p().introductionMessage=this.config.introductionMessage,p().analytics=this.config.analytics!==void 0?!!this.config.analytics:p().analytics,this.state.loading=!1,this.resetConversation()})}onUpdate(){this.child("web-weaver-embed-inner").style.display=this.attr.open?"":"none",this.child("interaction-bar").style.display=this.attr.open?"":"none",this.child("root").className=this.attr.open?"open":"",this.child("llm-selector-panel").attr.open=this.state.llmPanelOpen,this.child("pulseanim").style.display=this.attr.open?"none":"",this.child("root").style.right=this.attr.offsetX?this.attr.offsetX+"px":"20px",this.child("root").style.bottom=this.attr.offsetY?this.attr.offsetY+"px":"20px",this.child("interaction-bar").attr.loading=this.state.loading,this.child("interaction-bar").attr.llmName=this.ai.currentModel?.metadata?.name||this.ai.currentModel?.id||"None",this.child("interaction-bar").attr.llmButtonVisible=this.ai.models.length>1;let e=this.child("web-weaver-logo");e.attr.focusID=this.attr.focusID,e.refreshLayout(),this.child("llm-selector-panel").state.items=this.ai.models.sort((t,i)=>(i.priority||0)-(t.priority||0)),this.child("llm-selector-panel").state.selectedID=this.ai.currentModel?.id}onDestroy(){p().embed==this&&(p().embed=null)}onContainerClick(e){this.attr.open||(e.preventDefault(),this.attr.open=!0)}onLogoClick(e){e.preventDefault(),e.stopPropagation(),this.attr.focusID?this.attr.focusID="":this.attr.open=!this.attr.open}open(){this.attr.open=!0}close(){this.attr.open=!1}resetConversation(){let e=this.child("web-weaver-embed-inner");for(this.state.llmPanelOpen=!1;e.children.length>0;)e.children[0].remove();this.ai.resetConversation(),this.suggestions=[];let t=document.createElement("div");t.className="introduction-message",t.innerHTML=p().introductionMessage||`Welcome to <b>${document.title||"Web Weaver"}</b>. How can I help you?`,e.appendChild(t),this.ai.insertAssistantMessage(t.innerText);for(let i of p().introductionSuggestions||[]){let n=document.createElement("div");n.className="suggestion-button",n.innerText=i,n.addEventListener("click",o=>this.onSuggestionClick(o,i)),e.appendChild(n)}}async processInput(e){if(this._isProcessing)return;this._isProcessing=!0,this.state.loading=!0,this.state.llmPanelOpen=!1;let t=this.child("web-weaver-embed-inner");this.suggestions=[];try{for(let n of Array.from(t.querySelectorAll(".suggestion-button")))n.remove();this.attr.focusID="";let i=document.createElement("div");i.className="input",i.innerText=e,t.appendChild(i),t.lastElementChild?.scrollIntoView({behavior:"instant",block:"end"}),await this.ai.sendMessage(e);for(let n of this.suggestions){let o=document.createElement("div");o.className="suggestion-button",o.innerText=n,o.addEventListener("click",r=>this.onSuggestionClick(r,n)),t.appendChild(o)}t.lastElementChild?.scrollIntoView({behavior:"instant",block:"end"})}catch(i){se.error("Failed to process input:",i);let n=document.createElement("div");n.className="output",n.innerText="Sorry, there was a problem getting a response. "+i.message,t.appendChild(n);let o=document.createElement("div");o.className="suggestion-button",o.innerText="Reset conversation",o.addEventListener("click",r=>this.resetConversation()),t.appendChild(o)}this.state.loading=!1,this._isProcessing=!1}async onAIMessage(e){let t=await Pe().use(ke).use(Be).use(Ee,{target:"_blank",rel:["noopener","noreferrer"]}).use(Te).use(Le).processSync(e),i=this.child("web-weaver-embed-inner"),n=i.lastElementChild;if(n&&n.classList.contains("output"))n.innerHTML=t.toString("utf-8");else{let o=document.createElement("div");o.className="output",o.innerHTML=t.toString("utf-8"),i.appendChild(o)}for(let o of Array.from(i.querySelectorAll(".tool")))o.remove();i.lastElementChild?.scrollIntoView({behavior:"instant",block:"end"})}onAIToolStart(e,t){let i=`Running: ${e}`;e=="search"&&(i=`Searching: ${t?.query}`),e=="ui.focusElement"&&(i=`Focusing: #${t?.elementID}`),e=="ui.suggestResponse"&&(i=`Suggested response: ${t?.text}`);let n=this.child("web-weaver-embed-inner"),o=document.createElement("div");o.className="tool",o.innerText=i,n.appendChild(o),n.lastElementChild?.scrollIntoView({behavior:"instant",block:"end"})}onSuggestionClick(e,t){this.processInput(t)}onLLMModelSelect(e){e.preventDefault(),this.ai.setModel(e.detail),this.state.llmPanelOpen=!1}};v.tagName="intelliweave-embed",v.observedAttributes=["logo","focusID","open"];var vs=v;g.lib=()=>import("onnxruntime-web");v.register();export{vs as default};
Binary file
@@ -871,6 +871,8 @@ declare class IntelliWeave extends EventTarget {
871
871
  userID: string;
872
872
  /** Extra data that will be passed to external knowledge base actions. */
873
873
  extra: any;
874
+ /** URL of the IntelliWeave Hub API */
875
+ hubAPI: string;
874
876
  /** Set model and load data from an API key */
875
877
  load(apiKey: string): Promise<WebWeaverGPTConfig>;
876
878
  /** Set the current model */
@@ -963,6 +965,8 @@ interface KnowledgeBaseSource {
963
965
  query?: (query: string) => (KnowledgeBaseItem[] | Promise<KnowledgeBaseItem[]>);
964
966
  /** URL query for remote sources */
965
967
  url?: string;
968
+ /** Pre-packaged knowledge base entries */
969
+ entries?: KnowledgeBaseItem[];
966
970
  }
967
971
  /** Knowledge base item */
968
972
  interface KnowledgeBaseItem {