@opencx/widget 3.0.84 → 3.0.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@opencx/widget",
3
3
  "private": false,
4
- "version": "3.0.84",
4
+ "version": "3.0.85",
5
5
  "type": "module",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -1,5 +0,0 @@
1
- "use strict";const M=require("openapi-fetch"),O=require("lodash.isequal"),E=require("uuid"),F=d=>{console.log(d.error)},_=d=>{const n=M({baseUrl:d.baseUrl}),i={onRequest:d.onRequest,onResponse:d.onResponse,onError:d.onError||F};return n.use(i),n};class U{constructor({config:n}){var a,s;this.userToken=null,this.constructClientOptions=t=>{const e=this.config.apiUrl||"https://api.open.cx",o={"X-Bot-Token":this.config.token,"Content-Type":"application/json",Accept:"application/json",Authorization:t?`Bearer ${t}`:void 0};return{baseUrl:e,headers:o}},this.createOpenAPIClient=({baseUrl:t,headers:e})=>_({baseUrl:t,onRequest:({request:o})=>{Object.entries(e).forEach(([l,r])=>{r&&o.headers.set(l,r)})}}),this.setAuthToken=t=>{this.userToken=t;const{baseUrl:e,headers:o}=this.constructClientOptions(t);this.client=this.createOpenAPIClient({baseUrl:e,headers:o})},this.getExternalWidgetConfig=async()=>await this.client.GET("/backend/widget/v2/config",{params:{header:{"X-Bot-Token":this.config.token}}}),this.widgetPrelude=async()=>await this.client.GET("/backend/widget/v2/prelude",{params:{header:{"X-Bot-Token":this.config.token}}}),this.sendMessage=async(t,e)=>await this.client.POST("/backend/widget/v2/chat/send",{body:t,signal:e}),this.createUnverifiedContact=async t=>await this.client.POST("/backend/widget/v2/contact/create-unverified",{params:{header:{"x-bot-token":this.config.token}},body:t}),this.createSession=async t=>await this.client.POST("/backend/widget/v2/create-session",{body:t}),this.pollSessionAndHistory=async({sessionId:t,lastMessageTimestamp:e,abortSignal:o})=>{const l=e?{lastMessageTimestamp:e}:void 0;return await this.client.GET("/backend/widget/v2/poll/{sessionId}",{params:{path:{sessionId:t},query:l},signal:o})},this.getSessions=async({cursor:t,filters:e,abortSignal:o})=>await this.client.GET("/backend/widget/v2/sessions",{params:{query:{cursor:t,filters:JSON.stringify(e)}},signal:o}),this.uploadFile=async({file:t,abortSignal:e,onProgress:o})=>new Promise((l,r)=>{var v;const g=new FormData;g.append("file",t);const c=new XMLHttpRequest;if(e&&(e.addEventListener("abort",()=>{c.abort(),r(new DOMException("Aborted","AbortError"))}),e.aborted)){r(new DOMException("Aborted","AbortError"));return}c.upload.addEventListener("progress",u=>{if(u.lengthComputable&&o){const S=Math.round(u.loaded/u.total*100);o(S)}}),c.addEventListener("load",()=>{if(c.status>=200&&c.status<300)try{const u=JSON.parse(c.responseText);l(u)}catch(u){r(new Error(`Failed to parse response: ${u}`))}else r(new Error(`Upload failed with status: ${c.status}`))}),c.addEventListener("error",()=>{r(new Error("Network error occurred"))}),c.addEventListener("timeout",()=>{r(new Error("Upload timed out"))});const{baseUrl:C}=this.constructClientOptions(this.userToken),p=`${C}/backend/widget/v2/upload`;c.open("POST",p),c.setRequestHeader("X-Bot-Token",this.config.token),this.userToken??((v=this.config.user)==null?void 0:v.token)?c.setRequestHeader("Authorization",`Bearer ${this.userToken}`):console.error("User token not set"),c.send(g)}),this.vote=async t=>await this.client.POST("/backend/widget/v2/chat/vote",{body:t}),this.resolveSession=async(t,e)=>await this.client.POST("/backend/widget/v2/session/resolve",{body:t,signal:e}),this.config=n,this.userToken=((a=n.user)==null?void 0:a.token)||null;const{baseUrl:i,headers:h}=this.constructClientOptions((s=n.user)==null?void 0:s.token);this.client=this.createOpenAPIClient({baseUrl:i,headers:h})}}class b{constructor(n){this.subscribers=new Set,this.get=()=>this.state,this.set=i=>{O(this.state,i)||(this.state=i,this.notifySubscribers(i))},this.setPartial=i=>{if(i==null)return;const h={...this.state,...i};this.set(h)},this.reset=()=>{this.set(this.initialState)},this.notifySubscribers=i=>{Array.from(this.subscribers).forEach(a=>{try{a(i)}catch(s){console.error(s)}})},this.subscribe=i=>(this.subscribers.add(i),()=>{this.subscribers.delete(i)}),this.state=n,this.initialState=n}}class A{constructor(){this.state=new b({isPolling:!1,isError:!1}),this.abortController=new AbortController,this.reset=()=>{var n;this.abortController.abort("Resetting poller"),(n=this.stopPolling)==null||n.call(this),this.stopPolling=null},this.stopPolling=null,this.startPolling=(n,i)=>{if(this.stopPolling)return;const h=[],a=async()=>{this.abortController=new AbortController,this.state.setPartial({isPolling:!0});try{await n(this.abortController.signal)}catch(s){if(this.abortController.signal.aborted)return;console.error("Failed to poll:",s),this.state.setPartial({isError:!0})}finally{this.state.setPartial({isPolling:!1})}this.abortController.signal.aborted?console.log("Poller aborted, not scheduling anymore"):h.push(setTimeout(a,i))};a(),this.stopPolling=()=>{h.forEach(clearTimeout),this.state.reset()}}}}function D(d){try{const n=d();return n instanceof Promise?n.then(i=>({data:i})).catch(i=>({error:i})):{data:n}}catch(n){return{error:n}}}class L{constructor({api:n,config:i,sessionCtx:h,messageCtx:a,sessionPollingIntervalSeconds:s}){this.poller=new A,this.registerPolling=()=>{this.sessionCtx.sessionState.subscribe(({session:t})=>{t!=null&&t.id?this.poller.startPolling(async e=>{this.hackAndSlash(t.id,e)},this.sessionPollingIntervalSeconds*1e3):this.poller.reset()})},this.hackAndSlash=async(t,e)=>{var g;this.messageCtx.state.get().messages.length===0&&this.messageCtx.state.setPartial({isInitialFetchLoading:!0});const o=this.messageCtx.state.get().messages,l=o.length>0?(g=o[o.length-1])==null?void 0:g.timestamp:void 0,{data:r}=await this.api.pollSessionAndHistory({sessionId:t,abortSignal:e,lastMessageTimestamp:l});if(r!=null&&r.session&&(this.sessionCtx.sessionState.setPartial({session:r.session}),this.sessionCtx.setSessions([r.session])),r!=null&&r.history&&r.history.length>0){const c=this.messageCtx.state.get().messages,C=r.history.map(this.mapHistoryToMessage).filter(x=>!c.some(p=>p.id===x.id));this.messageCtx.state.setPartial({messages:[...c,...C]})}this.messageCtx.state.get().isInitialFetchLoading&&this.messageCtx.state.setPartial({isInitialFetchLoading:!1})},this.mapHistoryToMessage=t=>{var l,r;const e={id:t.publicId,timestamp:t.sentAt||"",attachments:t.attachments||void 0};if(t.sender.kind==="user")return{...e,type:"FROM_USER",content:t.content.text||"",deliveredAt:t.sentAt||""};if(t.sender.kind==="agent")return{...e,type:"FROM_AGENT",component:"agent_message",data:{message:t.content.text||""},agent:{name:t.sender.name||"",avatar:t.sender.avatar||"",id:null,isAi:!1}};const o=t.actionCalls&&t.actionCalls.length>0?t.actionCalls[t.actionCalls.length-1]:void 0;return{...e,type:"FROM_BOT",component:"bot_message",agent:{id:null,name:((l=this.config.bot)==null?void 0:l.name)||"",isAi:!0,avatar:((r=this.config.bot)==null?void 0:r.avatar)||""},data:{message:t.content.text||"",action:o?{name:o.actionName,data:this.extractActionResult(o)}:void 0}}},this.extractActionResult=t=>{const e=t.result;if(e===null||typeof e!="object")return e;if("responseBodyText"in e&&typeof e.responseBodyText=="string"){const o=e.responseBodyText,l=D(()=>JSON.parse(o)).data;if(l)return l}return t.result},this.api=n,this.config=i,this.sessionCtx=h,this.messageCtx=a,this.sessionPollingIntervalSeconds=s,this.registerPolling()}}class B{constructor({config:n,api:i,storageCtx:h}){var a;this.shouldCollectData=()=>{var s;return!!(!((s=this.state.get().contact)!=null&&s.token)&&this.config.collectUserData)},this.autoCreateUnverifiedUserIfNotExists=async()=>{var s,t,e,o,l,r,g,c,C,x,p,w,v,u;if(!((s=this.config.user)!=null&&s.token)){if(this.config.collectUserData&&!((e=(t=this.config.user)==null?void 0:t.data)!=null&&e.email)){if((o=this.config.extraDataCollectionFields)!=null&&o.length)return;const S=await((l=this.storageCtx)==null?void 0:l.getContactToken());S&&await this.setUnverifiedContact(S);return}if(!((g=(r=this.config.user)==null?void 0:r.data)!=null&&g.email)){const S=await((c=this.storageCtx)==null?void 0:c.getContactToken());if(S){await this.setUnverifiedContact(S);return}}await this.createUnverifiedContact({email:(x=(C=this.config.user)==null?void 0:C.data)==null?void 0:x.email,non_verified_name:((w=(p=this.config.user)==null?void 0:p.data)==null?void 0:w.name)||"Anonymous",non_verified_custom_data:(u=(v=this.config.user)==null?void 0:v.data)==null?void 0:u.customData})}},this.createUnverifiedContact=async(s,t)=>{this.state.setPartial({extraCollectedData:t});try{this.state.setPartial({isCreatingUnverifiedContact:!0,isErrorCreatingUnverifiedContact:!1});const{data:e}=await this.api.createUnverifiedContact(s);e!=null&&e.token?await this.setUnverifiedContact(e.token):this.state.setPartial({isErrorCreatingUnverifiedContact:!0})}finally{this.state.setPartial({isCreatingUnverifiedContact:!1})}},this.setUnverifiedContact=async s=>{var o,l,r,g;const t=await((o=this.storageCtx)==null?void 0:o.getExternalContactId()),e=((l=this.config.user)==null?void 0:l.externalId)||t||E.v4();this.api.setAuthToken(s),await((r=this.storageCtx)==null?void 0:r.setContactToken(s)),await((g=this.storageCtx)==null?void 0:g.setExternalContactId(e)),this.state.setPartial({contact:{token:s,externalId:e}})},this.config=n,this.storageCtx=h,this.api=i,this.state=new b({contact:(a=n.user)!=null&&a.token?{token:n.user.token,externalId:n.user.externalId}:null,extraCollectedData:void 0,isCreatingUnverifiedContact:!1,isErrorCreatingUnverifiedContact:!1}),this.autoCreateUnverifiedUserIfNotExists()}}function y(){return E.v4()}class q{constructor({api:n,contactCtx:i,sessionsPollingIntervalSeconds:h}){this.sessionsRefresher=new A,this.sessionState=new b({session:null,isCreatingSession:!1}),this.sessionsState=new b({data:[],cursor:void 0,isLastPage:!1,didStartInitialFetch:!1,isInitialFetchLoading:!0}),this.reset=async()=>{this.sessionState.reset()},this.registerSessionsRefresherWrapper=()=>{var a;(a=this.contactCtx.state.get().contact)!=null&&a.token&&!this.sessionsState.get().didStartInitialFetch?this.registerSessionsRefresher():this.contactCtx.state.subscribe(({contact:s})=>{s!=null&&s.token&&!this.sessionsState.get().didStartInitialFetch&&this.registerSessionsRefresher()})},this.registerSessionsRefresher=()=>{this.sessionsRefresher.startPolling(async()=>{this.sessionsState.get().didStartInitialFetch===!1&&this.sessionsState.setPartial({didStartInitialFetch:!0}),await this.refreshSessions(),this.sessionsState.get().isInitialFetchLoading===!0&&this.sessionsState.setPartial({isInitialFetchLoading:!1})},this.sessionsPollingIntervalSeconds*1e3)},this.createSession=async()=>{var e;this.sessionState.setPartial({session:null,isCreatingSession:!0});const a=(e=this.contactCtx.state.get().contact)==null?void 0:e.externalId,{data:s,error:t}=await this.api.createSession({customData:a?{external_id:a}:void 0});return s?(this.sessionState.setPartial({session:s,isCreatingSession:!1}),s):(console.error("Failed to create session:",t),null)},this.loadMoreSessions=async()=>{if(this.sessionsState.get().isLastPage)return;const{data:a}=await this.getSessions({cursor:this.sessionsState.get().cursor});if(a){const t=[...this.sessionsState.get().data,...a.items].filter((e,o,l)=>o===l.findIndex(r=>e.id===r.id));this.sessionsState.setPartial({data:t,cursor:a.next||void 0,isLastPage:a.next===null})}},this.getSessions=async({cursor:a})=>{var t,e;if(!((t=this.contactCtx.state.get().contact)!=null&&t.token))return{data:null};const s=(e=this.contactCtx.state.get().contact)==null?void 0:e.externalId;return await this.api.getSessions({cursor:a,filters:s?{external_id:s}:{}})},this.setSessions=a=>{const s=[...a,...this.sessionsState.get().data].filter((t,e,o)=>e===o.findIndex(l=>t.id===l.id));this.sessionsState.setPartial({data:s})},this.refreshSessions=async()=>{const{data:a}=await this.getSessions({cursor:void 0});a&&this.setSessions(a.items)},this.resolveSession=async()=>{const a=this.sessionState.get().session;if(!a||!a.isOpened)return;const{data:s}=await this.api.resolveSession({session_id:a.id});s&&this.sessionState.setPartial({session:s})},this.api=n,this.contactCtx=i,this.sessionsPollingIntervalSeconds=h,this.registerSessionsRefresherWrapper()}}class ${constructor({config:n,api:i,sessionCtx:h,contactCtx:a}){this.state=new b({messages:[],isSendingMessage:!1,lastAIResMightSolveUserIssue:!1,isInitialFetchLoading:!1}),this.sendMessageAbortController=new AbortController,this.reset=()=>{this.sendMessageAbortController.abort("Resetting chat"),this.state.reset()},this.sendMessage=async s=>{var r,g,c,C,x,p,w,v;if(!s.content.trim()&&(!s.attachments||s.attachments.length===0)){console.warn("Cannot send an empty message of no content or attachments");return}const t=this.state.get().isSendingMessage,e=((r=this.sessionCtx.sessionState.get().session)==null?void 0:r.assignee.kind)==="ai",o=this.state.get().messages,l=o.length>0?o[o.length-1]:void 0;if(e&&t||e&&(l==null?void 0:l.type)==="FROM_USER"){console.warn("Cannot send messages while awaiting AI response");return}this.sendMessageAbortController=new AbortController,this.state.setPartial({lastAIResMightSolveUserIssue:!1});try{this.state.setPartial({isSendingMessage:!0});const u=this.toUserMessage(s.content.trim(),s.attachments||void 0),S=this.state.get().messages;if(this.state.setPartial({messages:[...S,u]}),!((g=this.sessionCtx.sessionState.get().session)!=null&&g.id)){if(!await this.sessionCtx.createSession()){console.error("Failed to create session");return}this.sessionCtx.refreshSessions()}const T=(c=this.sessionCtx.sessionState.get().session)==null?void 0:c.id;if(!T)return;const{data:f}=await this.api.sendMessage({uuid:u.id,bot_token:this.config.token,headers:this.config.headers,query_params:this.config.queryParams,body_properties:this.config.bodyProperties,session_id:T,content:u.content,attachments:s.attachments,clientContext:this.config.context,custom_data:{...this.config.messageCustomData||{},...s.customData||{}},language:this.config.language},this.sendMessageAbortController.signal);if(f!=null&&f.success){const P=this.toBotMessage(f);if(P){const I=this.state.get().messages;if(!!I.some(R=>R.id===P.id)){this.state.setPartial({lastAIResMightSolveUserIssue:((C=f.autopilotResponse)==null?void 0:C.mightSolveUserIssue)||((x=f.uiResponse)==null?void 0:x.mightSolveUserIssue)});return}this.state.setPartial({messages:[...I,P],lastAIResMightSolveUserIssue:((p=f.autopilotResponse)==null?void 0:p.mightSolveUserIssue)||((w=f.uiResponse)==null?void 0:w.mightSolveUserIssue)})}}else{const P=this.toBotErrorMessage(((v=f==null?void 0:f.error)==null?void 0:v.message)||"Unknown error occurred"),I=this.state.get().messages;this.state.setPartial({messages:[...I,P]})}}catch(u){this.sendMessageAbortController.signal.aborted||console.error("Failed to send message:",u)}finally{this.state.setPartial({isSendingMessage:!1})}},this.toUserMessage=(s,t)=>{const e=(()=>{const o=this.contactCtx.state.get().extraCollectedData;return this.state.get().messages.length===0&&o&&Object.keys(o).length>0?`${Object.entries(o).filter(([r,g])=>!!g).map(([r,g])=>`${r}: ${g}`).join(`
2
- `)}
3
-
4
- ${s}`:s})();return{id:y(),type:"FROM_USER",content:e,deliveredAt:new Date().toISOString(),attachments:t,timestamp:new Date().toISOString()}},this.toBotMessage=s=>{var t;return s.success&&s.autopilotResponse?{type:"FROM_BOT",id:s.autopilotResponse.id||y(),timestamp:new Date().toISOString(),component:"bot_message",agent:this.config.bot?{name:this.config.bot.name||"",isAi:!0,avatar:this.config.bot.avatar||"",id:null}:void 0,data:{message:s.autopilotResponse.value.content,action:(t=s.uiResponse)!=null&&t.value.name?{name:s.uiResponse.value.name,data:s.uiResponse.value.request_response}:void 0}}:null},this.toBotErrorMessage=s=>({type:"FROM_BOT",id:y(),timestamp:new Date().toISOString(),component:"TEXT",data:{message:s,variant:"error",action:void 0}}),this.config=n,this.api=i,this.sessionCtx=h,this.contactCtx=a}}class N{constructor({config:n,contactCtx:i,sessionCtx:h,resetChat:a}){this.registerRoutingListener=()=>{this.contactCtx.state.subscribe(({contact:s})=>{s!=null&&s.token&&this.state.get().screen==="welcome"&&this.state.setPartial({screen:"sessions"})}),this.sessionCtx.sessionsState.subscribe(({isInitialFetchLoading:s,data:t})=>{var e;t.length||((e=this.config.router)==null?void 0:e.goToChatIfNoSessions)!==!1&&!s&&this.state.get().screen!=="chat"&&this.toChatScreen()})},this.toSessionsScreen=()=>{this.resetChat(),this.state.setPartial({screen:"sessions"})},this.toChatScreen=s=>{if(this.resetChat(),s){const t=this.sessionCtx.sessionsState.get().data.find(e=>e.id===s);if(!t)return;this.sessionCtx.sessionState.setPartial({session:t})}this.state.setPartial({screen:"chat"})},this.state=new b({screen:i.shouldCollectData()?"welcome":"sessions"}),this.config=n,this.contactCtx=i,this.sessionCtx=h,this.resetChat=a,this.registerRoutingListener()}}class H{constructor({storage:n}){this.KEYS={contactToken:"opencx__widget__contactToken",externalContactId:"opencx__widget__externalContactId"},this.setContactToken=async i=>{await this.storage.set(this.KEYS.contactToken,i)},this.getContactToken=async()=>this.storage.get(this.KEYS.contactToken),this.setExternalContactId=async i=>{await this.storage.set(this.KEYS.externalContactId,i)},this.getExternalContactId=async()=>this.storage.get(this.KEYS.externalContactId),this.storage=n}}const m=class m{constructor({config:n,storage:i}){if(this.resetChat=()=>{this.sessionCtx.reset(),this.messageCtx.reset()},!m.pollingIntervalsSeconds)throw Error("Widget polling values are not defined, did you call WidgetCtx.initialize()");this.config=n,this.api=new U({config:n}),this.storageCtx=i?new H({storage:i}):void 0,this.contactCtx=new B({api:this.api,config:this.config,storageCtx:this.storageCtx}),this.sessionCtx=new q({api:this.api,contactCtx:this.contactCtx,sessionsPollingIntervalSeconds:m.pollingIntervalsSeconds.sessions}),this.messageCtx=new $({config:this.config,api:this.api,sessionCtx:this.sessionCtx,contactCtx:this.contactCtx}),this.activeSessionPollingCtx=new L({api:this.api,config:this.config,sessionCtx:this.sessionCtx,messageCtx:this.messageCtx,sessionPollingIntervalSeconds:m.pollingIntervalsSeconds.session}),this.routerCtx=new N({config:this.config,contactCtx:this.contactCtx,sessionCtx:this.sessionCtx,resetChat:this.resetChat})}};m.pollingIntervalsSeconds=null,m.initialize=async({config:n,storage:i})=>{var a,s;const h=await new U({config:n}).getExternalWidgetConfig();return m.pollingIntervalsSeconds={session:((a=h.data)==null?void 0:a.sessionPollingIntervalSeconds)||10,sessions:((s=h.data)==null?void 0:s.sessionsPollingIntervalSeconds)||60},new m({config:n,storage:i})};let k=m;exports.PrimitiveState=b;exports.WidgetCtx=k;
5
- //# sourceMappingURL=widget.ctx-CoJrM0OY.cjs.map