@opencx/widget 3.0.8 → 3.0.11

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.
Files changed (46) hide show
  1. package/dist/{basic.cjs → designs.cjs} +35 -35
  2. package/dist/designs.cjs.map +1 -0
  3. package/dist/designs.d.ts +2 -0
  4. package/dist/{basic.js → designs.js} +1088 -1094
  5. package/dist/designs.js.map +1 -0
  6. package/dist/index.cjs +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/react.cjs +1 -1
  9. package/dist/react.js +2 -2
  10. package/dist/src/designs/react/index.d.ts +5 -8
  11. package/dist/src/designs/react/{basic/utils → utils}/group-messages-by-type.d.ts +1 -1
  12. package/dist/src/embedded/index.d.ts +11 -0
  13. package/dist/src/headless/core/api.d.ts +42 -16
  14. package/dist/src/headless/core/context/session.d.ts +28 -50
  15. package/dist/src/headless/core/sdk/schema.d.ts +80 -4
  16. package/dist/src/headless/core/types/WidgetConfig.d.ts +22 -9
  17. package/dist/src/headless/react/hooks/useDocumentDir.d.ts +2 -1
  18. package/dist/src/headless/react/hooks/useSession.d.ts +6 -0
  19. package/dist/{useUploadFiles-Cw8s18uG.js → useUploadFiles-B-HZXbPR.js} +3 -3
  20. package/dist/{useUploadFiles-Cw8s18uG.js.map → useUploadFiles-B-HZXbPR.js.map} +1 -1
  21. package/dist/{useUploadFiles-Bp-c5Nf9.cjs → useUploadFiles-WylOvupS.cjs} +2 -2
  22. package/dist/{useUploadFiles-Bp-c5Nf9.cjs.map → useUploadFiles-WylOvupS.cjs.map} +1 -1
  23. package/dist/widget-6i5ISSQC.cjs +2 -0
  24. package/dist/widget-6i5ISSQC.cjs.map +1 -0
  25. package/dist/{widget-BeNOCqB5.js → widget-BOaF1U-p.js} +128 -69
  26. package/dist/widget-BOaF1U-p.js.map +1 -0
  27. package/dist-embed/script.js +115 -115
  28. package/dist-embed/script.js.map +1 -1
  29. package/package.json +5 -5
  30. package/dist/basic.cjs.map +0 -1
  31. package/dist/basic.d.ts +0 -2
  32. package/dist/basic.js.map +0 -1
  33. package/dist/src/designs/react/basic/index.d.ts +0 -10
  34. package/dist/src/designs/react/basic/widget-interaction-tests/widget.test.d.ts +0 -1
  35. package/dist/src/designs/react/render.d.ts +0 -2
  36. package/dist/style.css +0 -1
  37. package/dist/widget-BeNOCqB5.js.map +0 -1
  38. package/dist/widget-DlAUwHzU.cjs +0 -2
  39. package/dist/widget-DlAUwHzU.cjs.map +0 -1
  40. /package/dist/src/designs/react/{basic/WidgetPopoverTrigger.d.ts → WidgetPopoverTrigger.d.ts} +0 -0
  41. /package/dist/src/designs/react/{basic/screens → screens}/chat-screen/ChatFooter.d.ts +0 -0
  42. /package/dist/src/designs/react/{basic/screens → screens}/chat-screen/ChatHeader.d.ts +0 -0
  43. /package/dist/src/designs/react/{basic/screens → screens}/chat-screen/ChatMain.d.ts +0 -0
  44. /package/dist/src/designs/react/{basic/screens → screens}/chat-screen/ChatScreen.d.ts +0 -0
  45. /package/dist/src/designs/react/{basic/screens → screens}/root-screen.d.ts +0 -0
  46. /package/dist/src/designs/react/{basic/screens → screens}/welcome-screen/WelcomeScreen.d.ts +0 -0
@@ -0,0 +1,2 @@
1
+ "use strict";var T=Object.defineProperty;var A=a=>{throw TypeError(a)};var I=(a,t,e)=>t in a?T(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var s=(a,t,e)=>I(a,typeof t!="symbol"?t+"":t,e),M=(a,t,e)=>t.has(a)||A("Cannot "+e);var h=(a,t,e)=>(M(a,t,"read from private field"),e?e.call(a):t.get(a)),P=(a,t,e)=>t.has(a)?A("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(a):t.set(a,e),C=(a,t,e,i)=>(M(a,t,"write to private field"),i?i.call(a,e):t.set(a,e),e);const R=require("axios"),E=require("openapi-fetch"),F=require("lodash.isequal"),L=require("uuid"),D=a=>{console.log(a.error)},q=a=>{const t=E({baseUrl:a.baseUrl}),e={onRequest:a.onRequest,onResponse:a.onResponse,onError:a.onError||D};return t.use(e),t};class _{constructor({config:t}){s(this,"client");s(this,"uploadFileClient");s(this,"config");s(this,"constructClientOptions",t=>{const e=this.config.apiUrl||"https://api.open.cx",i={"X-Bot-Token":this.config.token,"Content-Type":"application/json",Accept:"application/json",Authorization:t?`Bearer ${t}`:void 0};return{baseUrl:e,headers:i}});s(this,"createOpenAPIClient",({baseUrl:t,headers:e})=>q({baseUrl:t,onRequest:({request:i})=>{Object.entries(e).forEach(([n,r])=>{r&&i.headers.set(n,r)})}}));s(this,"createAxiosUploadClient",({baseUrl:t,headers:e})=>R.create({baseURL:`${t}/backend/widget/v2/upload`,headers:e}));s(this,"setAuthToken",t=>{const{baseUrl:e,headers:i}=this.constructClientOptions(t);this.client=this.createOpenAPIClient({baseUrl:e,headers:i}),this.uploadFileClient=this.createAxiosUploadClient({baseUrl:e,headers:i})});s(this,"widgetPrelude",async()=>await this.client.GET("/backend/widget/v2/prelude",{params:{header:{"X-Bot-Token":this.config.token}}}));s(this,"sendMessage",async(t,e)=>await this.client.POST("/backend/widget/v2/chat/send",{body:t,signal:e}));s(this,"getSessionHistory",async({sessionId:t,lastMessageTimestamp:e,abortSignal:i})=>{const n=e?{lastMessageTimestamp:e}:void 0;return await this.client.GET("/backend/widget/v2/session/history/{sessionId}",{params:{path:{sessionId:t},query:n},signal:i})});s(this,"createUnverifiedContact",async t=>await this.client.POST("/backend/widget/v2/contact/create-unverified",{params:{header:{"x-bot-token":this.config.token}},body:t}));s(this,"createSession",async t=>await this.client.POST("/backend/widget/v2/create-session",{body:t}));s(this,"getSession",async({sessionId:t,abortSignal:e})=>await this.client.GET("/backend/widget/v2/session/{sessionId}",{params:{path:{sessionId:t}},signal:e}));s(this,"getSessions",async({cursor:t,filters:e,abortSignal:i})=>await this.client.GET("/backend/widget/v2/sessions",{params:{query:{cursor:t,filters:JSON.stringify(e)}},signal:i}));s(this,"uploadFile",async(t,e={})=>{const i=new FormData;i.append("file",t.file);const{data:n}=await this.uploadFileClient.post("",i,{headers:{"Content-Type":"multipart/form-data"},...e});return n});s(this,"vote",async t=>await this.client.POST("/backend/widget/v2/chat/vote",{body:t}));var n;this.config=t;const{baseUrl:e,headers:i}=this.constructClientOptions((n=t.user)==null?void 0:n.token);this.client=this.createOpenAPIClient({baseUrl:e,headers:i}),this.uploadFileClient=this.createAxiosUploadClient({baseUrl:e,headers:i})}}var l,m;class b{constructor(t){s(this,"subscribers",new Set);P(this,l);s(this,"initialState");P(this,m);s(this,"lifecycleListeners",new Map);s(this,"emitLifecycle",(t,e)=>{const i=this.lifecycleListeners.get(t);if(i){const n={type:t,timestamp:Date.now(),data:e};i.forEach(r=>{try{r(n)}catch{}})}});s(this,"notifySubscribers",t=>{Array.from(this.subscribers).forEach(i=>{try{i(t)}catch(n){this.emitLifecycle("error",{error:n})}})});s(this,"subscribe",t=>(this.subscribers.add(t),()=>{this.subscribers.delete(t)}));s(this,"onLifecycle",(t,e)=>{this.lifecycleListeners.has(t)||this.lifecycleListeners.set(t,new Set);const i=this.lifecycleListeners.get(t);return i.add(e),()=>{i.delete(e),i.size===0&&this.lifecycleListeners.delete(t)}});s(this,"get",()=>h(this,l));s(this,"set",t=>{this.emitLifecycle("beforeUpdate",{previousState:h(this,l),nextState:t}),F(h(this,l),t)||(C(this,l,t),C(this,m,Date.now()),this.emitLifecycle("stateChange",{state:t}),this.notifySubscribers(t)),this.emitLifecycle("afterUpdate",{state:t})});s(this,"setPartial",t=>{if(t==null)return;const e={...h(this,l),...t};this.set(e)});s(this,"clear",()=>{this.emitLifecycle("destroy"),this.subscribers=new Set,this.lifecycleListeners=new Map});s(this,"reset",()=>{this.set(this.initialState)});s(this,"lastUpdated",()=>h(this,m));C(this,l,t),this.initialState=t,C(this,m,Date.now()),this.emitLifecycle("init",{initialState:h(this,l)})}}l=new WeakMap,m=new WeakMap;class B{constructor({config:t,api:e}){s(this,"config");s(this,"api");s(this,"state");s(this,"shouldCollectData",()=>{var e;return!!(!((e=this.state.get().contact)!=null&&e.token)&&this.config.collectUserData)});s(this,"autoCreateUnverifiedUser",async()=>{var t,e,i,n;await this.createUnverifiedContact({name:((e=(t=this.config.user)==null?void 0:t.data)==null?void 0:e.name)||"Anonymous",email:(n=(i=this.config.user)==null?void 0:i.data)==null?void 0:n.email})});s(this,"createUnverifiedContact",async t=>{try{this.state.setPartial({isCreatingUnverifiedContact:!0,isErrorCreatingUnverifiedContact:!1});const{data:e}=await this.api.createUnverifiedContact(t);e!=null&&e.token?(this.api.setAuthToken(e.token),this.state.setPartial({contact:{token:e.token}})):this.state.setPartial({isErrorCreatingUnverifiedContact:!0})}finally{this.state.setPartial({isCreatingUnverifiedContact:!1})}});var i,n,r;this.config=t,this.api=e,this.state=new b({contact:(i=t.user)!=null&&i.token?{token:(n=t.user)==null?void 0:n.token}:null,isCreatingUnverifiedContact:!1,isErrorCreatingUnverifiedContact:!1}),!((r=t.user)!=null&&r.token)&&!t.collectUserData&&this.autoCreateUnverifiedUser()}}class U{constructor(){s(this,"state",new b({isPolling:!1,isError:!1}));s(this,"abortController",new AbortController);s(this,"reset",()=>{var t;this.abortController.abort("Resetting poller"),(t=this.stopPolling)==null||t.call(this),this.stopPolling=null});s(this,"stopPolling",null);s(this,"startPolling",(t,e)=>{if(this.stopPolling)return;const i=[],n=async()=>{this.abortController=new AbortController,this.state.setPartial({isPolling:!0});try{await t(this.abortController.signal)}catch(r){if(this.abortController.signal.aborted)return;console.error("Failed to poll:",r),this.state.setPartial({isError:!0})}finally{this.state.setPartial({isPolling:!1})}this.abortController.signal.aborted?console.log("Poller aborted, not scheduling anymore"):i.push(setTimeout(n,e))};n(),this.stopPolling=()=>{i.forEach(clearTimeout),this.state.reset()}})}}function S(){return L.v4()}class H{constructor({config:t,api:e,contactCtx:i}){s(this,"config");s(this,"api");s(this,"contactCtx");s(this,"poller",new U);s(this,"state",new b({session:null,sessions:{data:[],cursor:void 0,isLastPage:!1,didInitialFetch:!1},isCreatingSession:!1}));s(this,"reset",async()=>{this.state.reset(),this.poller.reset()});s(this,"registerPolling",()=>{this.state.subscribe(({session:t})=>{t!=null&&t.id?this.poller.startPolling(async e=>{const{data:i}=await this.api.getSession({sessionId:t.id,abortSignal:e});i&&this.state.setPartial({session:i})},1e3):this.poller.reset()})});s(this,"registerInitialSessionsFetch",()=>{this.contactCtx.state.subscribe(({contact:t})=>{t!=null&&t.token&&!this.state.get().sessions.didInitialFetch&&(this.state.setPartial({sessions:{...this.state.get().sessions,didInitialFetch:!0}}),this.loadMoreSessions())})});s(this,"createSession",async()=>{var i,n;this.state.setPartial({session:null,isCreatingSession:!0});const{data:t,error:e}=await this.api.createSession({customData:(i=this.config.user)!=null&&i.externalId?{external_id:(n=this.config.user)==null?void 0:n.externalId}:void 0});return t?(this.state.setPartial({session:t,isCreatingSession:!1}),t):(console.error("Failed to create session:",e),null)});s(this,"loadMoreSessions",async()=>{var e,i;if(this.state.get().sessions.isLastPage||!((e=this.contactCtx.state.get().contact)!=null&&e.token))return;const{data:t}=await this.api.getSessions({cursor:this.state.get().sessions.cursor,filters:(i=this.config.user)!=null&&i.externalId?{external_id:this.config.user.externalId}:{}});if(t){const r=[...this.state.get().sessions.data,...t.items].filter((c,d,g)=>d===g.findIndex(u=>c.id===u.id));this.state.setPartial({sessions:{...this.state.get().sessions,data:r,cursor:t.next||void 0,isLastPage:t.next===null}})}});this.config=t,this.api=e,this.contactCtx=i,this.registerPolling(),this.registerInitialSessionsFetch()}}class p{constructor({config:t,api:e,sessionCtx:i}){s(this,"config");s(this,"api");s(this,"sessionCtx");s(this,"poller",new U);s(this,"state",new b({messages:[],isSendingMessage:!1,suggestedReplies:null}));s(this,"sendMessageAbortController",new AbortController);s(this,"reset",()=>{this.sendMessageAbortController.abort("Resetting chat"),this.state.reset(),this.poller.reset()});s(this,"registerPolling",()=>{this.sessionCtx.state.subscribe(({session:t})=>{t!=null&&t.id?this.poller.startPolling(async e=>{await this.fetchAndSetHistory(t.id,e)},1e3):this.poller.reset()})});s(this,"sendMessage",async t=>{var n,r,c,d,g,u,x;this.sendMessageAbortController=new AbortController;const e=this.state.get().isSendingMessage,i=((n=this.sessionCtx.state.get().session)==null?void 0:n.assignee.kind)==="ai";if(e&&i){console.warn("Cannot send messages while awaiting AI response");return}this.state.setPartial({suggestedReplies:null});try{this.state.setPartial({isSendingMessage:!0});const y=p.toUserMessage(t.content,t.attachments||void 0),k=this.state.get().messages;if(this.state.setPartial({messages:[...k,y]}),!((r=this.sessionCtx.state.get().session)!=null&&r.id)&&!await this.sessionCtx.createSession()){console.error("Failed to create session");return}const v=(c=this.sessionCtx.state.get().session)==null?void 0:c.id;if(!v)return;const{data:o}=await this.api.sendMessage({uuid:y.id,bot_token:this.config.token,headers:this.config.headers,query_params:this.config.queryParams,session_id:v,user:(d=this.config.user)==null?void 0:d.data,...t},this.sendMessageAbortController.signal);if(o!=null&&o.success){const f=p.toBotMessage(o);if(f){const w=this.state.get().messages;if(!!w.some(O=>O.id===f.id))return;this.state.setPartial({messages:[...w,f]})}else(g=o.options)!=null&&g.value&&((u=o.options)==null?void 0:u.value.length)>0&&this.state.setPartial({suggestedReplies:o.options.value})}else{const f=p.toErrorMessage(((x=o==null?void 0:o.error)==null?void 0:x.message)||"Unknown error occurred"),w=this.state.get().messages;this.state.setPartial({messages:[...w,f]})}}catch(y){this.sendMessageAbortController.signal.aborted||console.error("Failed to send message:",y)}finally{this.state.setPartial({isSendingMessage:!1})}});s(this,"fetchAndSetHistory",async(t,e)=>{var r;const i=(r=this.state.get().messages.at(-1))==null?void 0:r.timestamp,{data:n}=await this.api.getSessionHistory({sessionId:t,lastMessageTimestamp:i,abortSignal:e});if(n&&n.length>0){const c=this.state.get().messages,d=n.map(p.mapHistoryToMessage).filter(g=>!c.some(u=>u.id===g.id));this.state.setPartial({messages:[...c,...d]})}});this.config=t,this.api=e,this.sessionCtx=i,this.registerPolling()}static mapHistoryToMessage(t){const e={id:t.publicId,timestamp:t.sentAt||"",attachments:t.attachments||void 0};return t.sender.kind==="user"?{...e,type:"FROM_USER",content:t.content.text||"",deliveredAt:t.sentAt||""}:t.sender.kind==="agent"?{...e,type:"FROM_AGENT",component:"agent_message",data:{message:t.content.text||""}}:{...e,type:"FROM_BOT",component:"bot_message",agent:{id:null,name:t.sender.name||"",isAi:t.sender.kind==="ai",avatar:t.sender.avatar||null},data:{message:t.content.text}}}static toUserMessage(t,e){return{id:S(),type:"FROM_USER",content:t,deliveredAt:new Date().toISOString(),attachments:e,timestamp:new Date().toISOString()}}static toBotMessage(t){if(t.success&&t.autopilotResponse)return{type:"FROM_BOT",id:t.autopilotResponse.id||S(),timestamp:new Date().toISOString(),component:"bot_message",data:{message:t.autopilotResponse.value.content}};if(t.success&&t.uiResponse){const e=t.uiResponse.value;return{type:"FROM_BOT",id:S(),timestamp:new Date().toISOString(),component:e.name,data:e.request_response}}return null}static toErrorMessage(t){return{type:"FROM_BOT",id:S(),timestamp:new Date().toISOString(),component:"TEXT",data:{message:t,variant:"error"}}}}class G{constructor({config:t}){s(this,"config");s(this,"api");s(this,"contactCtx");s(this,"sessionCtx");s(this,"messageCtx");s(this,"resetChat",()=>{this.sessionCtx.reset(),this.messageCtx.reset()});this.config=t,this.api=new _({config:t}),this.contactCtx=new B({api:this.api,config:this.config}),this.sessionCtx=new H({config:this.config,api:this.api,contactCtx:this.contactCtx}),this.messageCtx=new p({config:this.config,api:this.api,sessionCtx:this.sessionCtx})}}exports.PubSub=b;exports.WidgetCtx=G;
2
+ //# sourceMappingURL=widget-6i5ISSQC.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-6i5ISSQC.cjs","sources":["../src/headless/core/sdk/index.ts","../src/headless/core/api.ts","../src/headless/core/utils/PubSub.ts","../src/headless/core/context/contact.ts","../src/headless/core/utils/Poller.ts","../src/headless/core/utils/uuid.ts","../src/headless/core/context/session.ts","../src/headless/core/context/message.ts","../src/headless/core/context/widget.ts"],"sourcesContent":["import createClient, { type Middleware } from \"openapi-fetch\";\nimport type { paths } from \"./schema\";\nimport type { components } from \"./schema\";\n\ntype Options = {\n baseUrl: string;\n onRequest?: Middleware[\"onRequest\"];\n onResponse?: Middleware[\"onResponse\"];\n onError?: Middleware[\"onError\"];\n};\n\nconst defaultOnError: Middleware[\"onError\"] = (onErrorOptions) => {\n console.log(onErrorOptions.error);\n};\n\nexport const basicClient = (options: Options) => {\n const client = createClient<paths>({\n baseUrl: options.baseUrl,\n });\n\n const middlewares: Middleware = {\n onRequest: options.onRequest,\n onResponse: options.onResponse,\n onError: options.onError || defaultOnError,\n };\n\n client.use(middlewares);\n return client;\n};\n\nexport type Endpoint = keyof paths;\nexport type Dto = components[\"schemas\"];\n","import axios, { type AxiosInstance, type AxiosRequestConfig } from \"axios\";\nimport { type Dto, type Endpoint, basicClient } from \"./sdk\";\nimport type { WidgetConfig } from \"./types/WidgetConfig\";\nimport type { SendMessageDto, VoteInputDto } from \"./types/schemas\";\n\nexport class ApiCaller {\n private client: ReturnType<typeof basicClient>;\n private uploadFileClient: AxiosInstance;\n private config: WidgetConfig;\n\n constructor({\n config,\n }: {\n config: WidgetConfig;\n }) {\n this.config = config;\n const { baseUrl, headers } = this.constructClientOptions(\n config.user?.token,\n );\n this.client = this.createOpenAPIClient({ baseUrl, headers });\n this.uploadFileClient = this.createAxiosUploadClient({ baseUrl, headers });\n }\n\n private constructClientOptions = (token: string | null | undefined) => {\n const baseUrl = this.config.apiUrl || \"https://api.open.cx\";\n const headers = {\n \"X-Bot-Token\": this.config.token,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n Authorization: token ? `Bearer ${token}` : undefined,\n };\n\n return { baseUrl, headers };\n };\n\n private createOpenAPIClient = ({\n baseUrl,\n headers,\n }: ReturnType<typeof this.constructClientOptions>) => {\n return basicClient({\n baseUrl,\n onRequest: ({ request }) => {\n Object.entries(headers).forEach(([key, value]) => {\n if (value) {\n request.headers.set(key, value);\n }\n });\n },\n });\n };\n private createAxiosUploadClient = ({\n baseUrl,\n headers,\n }: ReturnType<typeof this.constructClientOptions>) => {\n const uploadPath = \"/backend/widget/v2/upload\" satisfies Endpoint;\n return axios.create({\n baseURL: `${baseUrl}${uploadPath}`,\n headers,\n });\n };\n\n setAuthToken = (token: string) => {\n const { baseUrl, headers } = this.constructClientOptions(token);\n this.client = this.createOpenAPIClient({ baseUrl, headers });\n this.uploadFileClient = this.createAxiosUploadClient({ baseUrl, headers });\n };\n\n widgetPrelude = async () => {\n return await this.client.GET(\"/backend/widget/v2/prelude\", {\n params: { header: { \"X-Bot-Token\": this.config.token } },\n });\n };\n\n sendMessage = async (body: SendMessageDto, abortSignal?: AbortSignal) => {\n return await this.client.POST(\"/backend/widget/v2/chat/send\", {\n body,\n signal: abortSignal,\n });\n };\n\n getSessionHistory = async ({\n sessionId,\n lastMessageTimestamp,\n abortSignal,\n }: {\n sessionId: string;\n lastMessageTimestamp?: string;\n abortSignal: AbortSignal;\n }) => {\n const query = lastMessageTimestamp ? { lastMessageTimestamp } : undefined;\n return await this.client.GET(\n \"/backend/widget/v2/session/history/{sessionId}\",\n { params: { path: { sessionId }, query }, signal: abortSignal },\n );\n };\n\n createUnverifiedContact = async (body: Dto[\"CreateUnverifiedContactDto\"]) => {\n return await this.client.POST(\n \"/backend/widget/v2/contact/create-unverified\",\n {\n params: { header: { \"x-bot-token\": this.config.token } },\n body,\n },\n );\n };\n\n createSession = async (body: Dto[\"CreateWidgetChatSessionDto\"]) => {\n return await this.client.POST(\"/backend/widget/v2/create-session\", {\n body,\n });\n };\n\n getSession = async ({\n sessionId,\n abortSignal,\n }: { sessionId: string; abortSignal: AbortSignal }) => {\n return await this.client.GET(\"/backend/widget/v2/session/{sessionId}\", {\n params: { path: { sessionId } },\n signal: abortSignal,\n });\n };\n\n getSessions = async ({\n cursor,\n filters,\n abortSignal,\n }: {\n cursor: string | undefined;\n filters: Record<string, string>;\n abortSignal?: AbortSignal;\n }) => {\n return await this.client.GET(\"/backend/widget/v2/sessions\", {\n params: { query: { cursor, filters: JSON.stringify(filters) } },\n signal: abortSignal,\n });\n };\n\n uploadFile = async (\n file: {\n id: string;\n file: File;\n },\n config: Partial<AxiosRequestConfig> = {},\n ) => {\n const formData = new FormData();\n formData.append(\"file\", file.file);\n\n // Couldn't get this to work with the openapi client... dunno why...\n const { data } = await this.uploadFileClient.post<\n Dto[\"UploadWidgetFileResponseDto\"]\n >(\"\", formData, {\n headers: {\n \"Content-Type\": \"multipart/form-data\",\n },\n ...config,\n });\n return data;\n };\n\n vote = async (body: VoteInputDto) => {\n return await this.client.POST(\"/backend/widget/v2/chat/vote\", { body });\n };\n}\n","import isEqual from \"lodash.isequal\";\n\nexport type Subscriber<T> = (data: T) => void;\n\nexport enum LifecycleEvent {\n INIT = \"init\",\n STATE_CHANGE = \"stateChange\",\n BEFORE_UPDATE = \"beforeUpdate\",\n AFTER_UPDATE = \"afterUpdate\",\n DESTROY = \"destroy\",\n ERROR = \"error\",\n}\n\ntype LifecycleListener = (event: {\n type: LifecycleEvent;\n timestamp: number;\n data?: any;\n}) => void;\n\nexport class PubSub<S> {\n private subscribers = new Set<Subscriber<S>>();\n #state: S;\n private initialState: S;\n #lastUpdated: number | null;\n private lifecycleListeners: Map<LifecycleEvent, Set<LifecycleListener>> =\n new Map();\n\n constructor(state: S) {\n this.#state = state;\n this.initialState = state;\n this.#lastUpdated = Date.now();\n this.emitLifecycle(LifecycleEvent.INIT, { initialState: this.#state });\n }\n\n private emitLifecycle = (event: LifecycleEvent, data?: any) => {\n const listeners = this.lifecycleListeners.get(event);\n if (listeners) {\n const eventData = {\n type: event,\n timestamp: Date.now(),\n data,\n };\n listeners.forEach((listener) => {\n try {\n listener(eventData);\n } catch {\n // ignore error\n }\n });\n }\n };\n\n private notifySubscribers = (state: S) => {\n const subscribersArray = Array.from(this.subscribers);\n subscribersArray.forEach((callback) => {\n try {\n callback(state);\n } catch (error) {\n this.emitLifecycle(LifecycleEvent.ERROR, { error });\n }\n });\n };\n\n /**\n * Subscribe to state changes\n * @param callback Function to call when state changes\n * @returns Unsubscribe function\n */\n subscribe = (callback: Subscriber<S>): (() => void) => {\n this.subscribers.add(callback);\n // Don't call the callback immediately with current state\n return () => {\n this.subscribers.delete(callback);\n };\n };\n\n onLifecycle = (\n event: LifecycleEvent,\n listener: LifecycleListener,\n ): (() => void) => {\n if (!this.lifecycleListeners.has(event)) {\n this.lifecycleListeners.set(event, new Set());\n }\n const listeners = this.lifecycleListeners.get(event)!;\n listeners.add(listener);\n\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.lifecycleListeners.delete(event);\n }\n };\n };\n\n /** Get the current state */\n get = (): S => {\n return this.#state;\n };\n\n // TODO make this provide prev state\n /**\n * Set the state and notify subscribers if the state changes\n * @param newState The new state to set\n */\n set = (newState: S): void => {\n this.emitLifecycle(LifecycleEvent.BEFORE_UPDATE, {\n previousState: this.#state,\n nextState: newState,\n });\n\n if (!isEqual(this.#state, newState)) {\n this.#state = newState;\n this.#lastUpdated = Date.now();\n this.emitLifecycle(LifecycleEvent.STATE_CHANGE, { state: newState });\n this.notifySubscribers(newState);\n }\n\n this.emitLifecycle(LifecycleEvent.AFTER_UPDATE, { state: newState });\n };\n\n // TODO make this provide prev state\n setPartial = (_s: Partial<S>): void => {\n if (_s === undefined || _s === null) return;\n const newState = { ...this.#state, ..._s };\n this.set(newState);\n };\n\n /**\n * Clear all subscriptions\n */\n clear = (): void => {\n this.emitLifecycle(LifecycleEvent.DESTROY);\n this.subscribers = new Set(); // Create a new Set instead of just clearing\n this.lifecycleListeners = new Map();\n };\n\n reset = (): void => {\n this.set(this.initialState);\n };\n\n lastUpdated = (): number | null => {\n return this.#lastUpdated;\n };\n}\n","import { PubSub } from \"../utils/PubSub\";\nimport { ApiCaller } from \"../api\";\nimport { type WidgetConfig } from \"../types/WidgetConfig\";\nimport { type Dto } from \"../sdk\";\n\ntype ContactState = {\n contact: { token: string } | null;\n isCreatingUnverifiedContact: boolean;\n isErrorCreatingUnverifiedContact: boolean;\n};\n\nexport class ContactCtx {\n private config: WidgetConfig;\n private api: ApiCaller;\n state: PubSub<ContactState>;\n\n constructor({\n config,\n api,\n }: {\n api: ApiCaller;\n config: WidgetConfig;\n }) {\n this.config = config;\n this.api = api;\n\n this.state = new PubSub<ContactState>({\n contact: config.user?.token ? { token: config.user?.token } : null,\n isCreatingUnverifiedContact: false,\n isErrorCreatingUnverifiedContact: false,\n });\n\n if (!config.user?.token && !config.collectUserData) {\n this.autoCreateUnverifiedUser();\n }\n }\n\n shouldCollectData = (): boolean => {\n const currentState = this.state.get();\n\n if (!currentState.contact?.token && this.config.collectUserData) {\n return true;\n } else {\n return false;\n }\n };\n\n autoCreateUnverifiedUser = async () => {\n await this.createUnverifiedContact({\n name: this.config.user?.data?.name || \"Anonymous\",\n email: this.config.user?.data?.email,\n });\n };\n\n createUnverifiedContact = async (\n payload: Dto[\"CreateUnverifiedContactDto\"],\n ): Promise<void> => {\n try {\n this.state.setPartial({\n isCreatingUnverifiedContact: true,\n isErrorCreatingUnverifiedContact: false,\n });\n\n const { data } = await this.api.createUnverifiedContact(payload);\n if (data?.token) {\n this.api.setAuthToken(data.token);\n // Set token in state after setting the token in the api handler\n this.state.setPartial({ contact: { token: data.token } });\n } else {\n this.state.setPartial({ isErrorCreatingUnverifiedContact: true });\n }\n } finally {\n this.state.setPartial({ isCreatingUnverifiedContact: false });\n }\n };\n}\n","import { PubSub } from \"./PubSub\";\n\nexport type PollingState = {\n isPolling: boolean;\n isError: boolean;\n};\n\nexport class Poller {\n state = new PubSub<PollingState>({\n isPolling: false,\n isError: false,\n });\n private abortController = new AbortController();\n\n reset = () => {\n this.abortController.abort(\"Resetting poller\");\n this.stopPolling?.();\n this.stopPolling = null;\n };\n\n stopPolling: (() => void) | null = null;\n\n startPolling = (\n cb: (abortSignal: AbortSignal) => Promise<void>,\n interval: number,\n ) => {\n if (this.stopPolling) return;\n\n const timeouts: NodeJS.Timeout[] = [];\n\n const poll = async () => {\n this.abortController = new AbortController();\n this.state.setPartial({ isPolling: true });\n\n try {\n await cb(this.abortController.signal);\n } catch (error) {\n if (this.abortController.signal.aborted) {\n // If aborted, just return and do not schedule the nest poll\n return;\n } else {\n console.error(\"Failed to poll:\", error);\n this.state.setPartial({ isError: true });\n } \n } finally {\n this.state.setPartial({ isPolling: false });\n }\n\n // Another check to stop scheduling polls in case someone removes the early return in the catch above\n if (this.abortController.signal.aborted) {\n console.log(\"Poller aborted, not scheduling anymore\");\n } else {\n timeouts.push(setTimeout(poll, interval));\n }\n };\n\n poll();\n\n this.stopPolling = () => {\n timeouts.forEach(clearTimeout);\n this.state.reset();\n };\n };\n}\n","import { v4 as uuidv4 } from \"uuid\";\n\nexport function genUuid() {\n return uuidv4();\n}\n","import type { ApiCaller } from \"../api\";\nimport type { Dto } from \"../sdk\";\nimport type { SessionDto } from \"../types/schemas\";\nimport type { WidgetConfig } from \"../types/WidgetConfig\";\nimport { Poller } from \"../utils/Poller\";\nimport { PubSub } from \"../utils/PubSub\";\nimport type { ContactCtx } from \"./contact\";\n\ntype SessionCtxState = {\n /** The currently selected session */\n session: SessionDto | null;\n sessions: {\n /** List of all user sessions */\n data: SessionDto[];\n /** A cursor to get the next page of sessions */\n cursor: string | undefined;\n /** Indicates if no more pages are left */\n isLastPage: boolean;\n /** Did fetch for the first time */\n didInitialFetch: boolean;\n };\n isCreatingSession: boolean;\n};\n\nexport class SessionCtx {\n private config: WidgetConfig;\n private api: ApiCaller;\n private contactCtx: ContactCtx;\n private poller = new Poller();\n\n public state = new PubSub<SessionCtxState>({\n session: null,\n sessions: {\n data: [],\n cursor: undefined,\n isLastPage: false,\n didInitialFetch: false,\n },\n isCreatingSession: false,\n });\n\n constructor({\n config,\n api,\n contactCtx,\n }: { config: WidgetConfig; api: ApiCaller; contactCtx: ContactCtx }) {\n this.config = config;\n this.api = api;\n this.contactCtx = contactCtx;\n\n this.registerPolling();\n this.registerInitialSessionsFetch();\n }\n\n /** Clears the session and stops polling */\n reset = async () => {\n this.state.reset();\n // The poller should automatically reset, since we're subscribed to the session state, and whenever it's null, the poller resets... but just in case, let's reset it here as well\n this.poller.reset();\n };\n\n registerPolling = () => {\n this.state.subscribe(({ session }) => {\n if (session?.id) {\n this.poller.startPolling(async (abortSignal) => {\n const { data } = await this.api.getSession({\n sessionId: session.id,\n abortSignal,\n });\n data && this.state.setPartial({ session: data });\n }, 1000);\n } else {\n this.poller.reset();\n }\n });\n };\n\n registerInitialSessionsFetch = () => {\n this.contactCtx.state.subscribe(({ contact }) => {\n if (contact?.token && !this.state.get().sessions.didInitialFetch) {\n this.state.setPartial({\n sessions: {\n ...this.state.get().sessions,\n didInitialFetch: true,\n },\n });\n // Call this for the first time to get the first page of sessions\n this.loadMoreSessions();\n }\n });\n };\n\n createSession = async () => {\n this.state.setPartial({ session: null, isCreatingSession: true });\n\n const { data: session, error } = await this.api.createSession({\n customData: this.config.user?.externalId\n ? {\n external_id: this.config.user?.externalId,\n }\n : undefined,\n });\n if (session) {\n this.state.setPartial({ session, isCreatingSession: false });\n return session;\n }\n\n console.error(\"Failed to create session:\", error);\n return null;\n };\n\n loadMoreSessions = async () => {\n if (this.state.get().sessions.isLastPage) return;\n if (!this.contactCtx.state.get().contact?.token) return;\n\n const { data } = await this.api.getSessions({\n cursor: this.state.get().sessions.cursor,\n filters: this.config.user?.externalId\n ? {\n external_id: this.config.user.externalId,\n }\n : {},\n });\n\n if (data) {\n const allSessions = [...this.state.get().sessions.data, ...data.items];\n const deduped = allSessions.filter(\n (s, i, self) => i === self.findIndex((_s) => s.id === _s.id),\n );\n\n this.state.setPartial({\n sessions: {\n ...this.state.get().sessions,\n data: deduped,\n cursor: data.next || undefined,\n isLastPage: data.next === null,\n },\n });\n }\n };\n}\n","import { ApiCaller } from \"../api\";\nimport type { WidgetConfig } from \"../types/WidgetConfig\";\nimport type { SafeOmit, SomeOptional } from \"../types/helpers\";\nimport type {\n BotMessageType,\n MessageType,\n UserMessageType,\n} from \"../types/messages\";\nimport type {\n MessageAttachmentType,\n MessageDto,\n SendMessageDto,\n SendMessageOutputDto,\n} from \"../types/schemas\";\nimport { Poller } from \"../utils/Poller\";\nimport { PubSub } from \"../utils/PubSub\";\nimport { genUuid } from \"../utils/uuid\";\nimport { SessionCtx } from \"./session\";\n\nexport class MessageCtx {\n private config: WidgetConfig;\n private api: ApiCaller;\n private sessionCtx: SessionCtx;\n private poller = new Poller();\n\n public state = new PubSub<{\n messages: MessageType[];\n isSendingMessage: boolean;\n suggestedReplies: string[] | null;\n }>({\n messages: [],\n isSendingMessage: false,\n suggestedReplies: null,\n });\n\n private sendMessageAbortController = new AbortController();\n\n constructor({\n config,\n api,\n sessionCtx,\n }: { config: WidgetConfig; api: ApiCaller; sessionCtx: SessionCtx }) {\n this.config = config;\n this.api = api;\n this.sessionCtx = sessionCtx;\n\n this.registerPolling();\n }\n\n reset = () => {\n this.sendMessageAbortController.abort(\"Resetting chat\");\n this.state.reset();\n // The poller should automatically reset, since we're subscribed to the session state, and whenever it's null, the poller resets... but just in case, let's reset it here as well\n this.poller.reset();\n };\n\n registerPolling = () => {\n this.sessionCtx.state.subscribe(({ session }) => {\n if (session?.id) {\n this.poller.startPolling(async (abortSignal) => {\n await this.fetchAndSetHistory(session.id, abortSignal);\n }, 1000);\n } else {\n this.poller.reset();\n }\n });\n };\n\n sendMessage = async (\n input: SomeOptional<\n SafeOmit<SendMessageDto, \"bot_token\" | \"uuid\">,\n \"session_id\" | \"user\"\n >,\n ): Promise<void> => {\n this.sendMessageAbortController = new AbortController();\n /* ------------------------------------------------------ */\n /* Prevent sending while waiting for AI res */\n /* ------------------------------------------------------ */\n const isSending = this.state.get().isSendingMessage;\n const isAssignedToAI =\n this.sessionCtx.state.get().session?.assignee.kind === \"ai\";\n if (isSending && isAssignedToAI) {\n console.warn(\"Cannot send messages while awaiting AI response\");\n return;\n }\n\n /* ------------------------------------------------------ */\n /* Clear suggested replies */\n /* ------------------------------------------------------ */\n this.state.setPartial({ suggestedReplies: null });\n\n try {\n this.state.setPartial({ isSendingMessage: true });\n /* ------------------------------------------------------ */\n /* Optimistically add message to rendered messages */\n /* ------------------------------------------------------ */\n const userMessage = MessageCtx.toUserMessage(\n input.content,\n input.attachments || undefined,\n );\n const currentMessages = this.state.get().messages;\n this.state.setPartial({\n messages: [...currentMessages, userMessage],\n });\n\n /* ------------------------------------------------------ */\n /* Create session if not exists */\n /* ------------------------------------------------------ */\n if (!this.sessionCtx.state.get().session?.id) {\n const createdSession = await this.sessionCtx.createSession();\n\n // TODO: apply some retry logic here\n if (!createdSession) {\n console.error(\"Failed to create session\");\n return;\n }\n }\n const sessionId = this.sessionCtx.state.get().session?.id;\n if (!sessionId) return;\n\n /* ------------------------------------------------------ */\n /* Send and wait for bot response */\n /* ------------------------------------------------------ */\n const { data } = await this.api.sendMessage(\n {\n uuid: userMessage.id,\n bot_token: this.config.token,\n headers: this.config.headers,\n query_params: this.config.queryParams,\n session_id: sessionId,\n user: this.config.user?.data,\n ...input,\n },\n this.sendMessageAbortController.signal,\n );\n\n if (data?.success) {\n /* ------------------------------------------------------ */\n /* Append bot reply if not fetched from polling */\n /* ------------------------------------------------------ */\n const botMessage = MessageCtx.toBotMessage(data);\n if (botMessage) {\n const prevMessages = this.state.get().messages;\n const shouldAppend = !prevMessages.some(\n (m) => m.id === botMessage.id,\n );\n if (!shouldAppend) return;\n this.state.setPartial({ messages: [...prevMessages, botMessage] });\n } else {\n /* ------------------------------------------------------ */\n /* Check if bot responded with suggested replies */\n /* ------------------------------------------------------ */\n if (data.options?.value && data.options?.value.length > 0) {\n this.state.setPartial({ suggestedReplies: data.options.value });\n }\n }\n } else {\n const errorMessage = MessageCtx.toErrorMessage(\n data?.error?.message || \"Unknown error occurred\",\n );\n const currentMessages = this.state.get().messages;\n this.state.setPartial({\n messages: [...currentMessages, errorMessage],\n });\n }\n } catch (error) {\n if (!this.sendMessageAbortController.signal.aborted) {\n console.error(\"Failed to send message:\", error);\n }\n } finally {\n this.state.setPartial({ isSendingMessage: false });\n }\n };\n\n fetchAndSetHistory = async (\n sessionId: string,\n abortSignal: AbortSignal,\n ): Promise<void> => {\n const lastMessageTimestamp = this.state.get().messages.at(-1)?.timestamp;\n\n const { data: response } = await this.api.getSessionHistory({\n sessionId,\n lastMessageTimestamp,\n abortSignal,\n });\n\n if (response && response.length > 0) {\n // Get a fresh reference to current messages after the poll is done\n const prevMessages = this.state.get().messages;\n const newMessages = response\n .map(MessageCtx.mapHistoryToMessage)\n .filter(\n (newMsg) =>\n !prevMessages.some((existingMsg) => existingMsg.id === newMsg.id),\n );\n this.state.setPartial({\n messages: [...prevMessages, ...newMessages],\n });\n\n // if (newMessages.length > 0) {\n // // const playSoundEffects = config?.settings?.playSoundEffects;\n // // Play notification sound for new messages if enabled\n // // if (\n // // playSoundEffects &&\n // // platform?.audio &&\n // // isAudioAvailable(platform.audio)\n // // ) {\n // // const botMessages = newMessages.filter(\n // // (msg) => msg.type === \"FROM_BOT\",\n // // );\n // // if (botMessages.length > 0) {\n // // await safeAudioOperation(\n // // () => platform.audio!.playNotification(),\n // // \"Failed to play notification sound for new messages\",\n // // );\n // // }\n // // }\n\n // }\n }\n };\n\n /** Not the best name but whatever */\n static mapHistoryToMessage(history: MessageDto): MessageType {\n const commonFields = {\n id: history.publicId,\n timestamp: history.sentAt || \"\",\n attachments: history.attachments || undefined,\n };\n\n if (history.sender.kind === \"user\") {\n return {\n ...commonFields,\n type: \"FROM_USER\",\n content: history.content.text || \"\",\n deliveredAt: history.sentAt || \"\",\n };\n }\n\n if (history.sender.kind === \"agent\") {\n return {\n ...commonFields,\n type: \"FROM_AGENT\",\n component: \"agent_message\",\n data: {\n message: history.content.text || \"\",\n },\n };\n }\n\n return {\n ...commonFields,\n type: \"FROM_BOT\",\n component: \"bot_message\",\n agent: {\n id: null,\n name: history.sender.name || \"\",\n isAi: history.sender.kind === \"ai\",\n avatar: history.sender.avatar || null,\n },\n data: {\n message: history.content.text,\n },\n };\n }\n\n static toUserMessage(\n content: string,\n attachments?: MessageAttachmentType[],\n ): UserMessageType {\n return {\n id: genUuid(),\n type: \"FROM_USER\",\n content,\n deliveredAt: new Date().toISOString(),\n attachments,\n timestamp: new Date().toISOString(),\n };\n }\n\n static toBotMessage(response: SendMessageOutputDto): BotMessageType | null {\n if (response.success && response.autopilotResponse) {\n return {\n type: \"FROM_BOT\",\n id: response.autopilotResponse.id || genUuid(),\n timestamp: new Date().toISOString(),\n component: \"bot_message\",\n data: {\n message: response.autopilotResponse.value.content,\n },\n };\n }\n\n if (response.success && response.uiResponse) {\n const uiVal = response.uiResponse.value;\n return {\n type: \"FROM_BOT\" as const,\n id: genUuid(),\n timestamp: new Date().toISOString(),\n component: uiVal.name,\n data: uiVal.request_response,\n };\n }\n\n return null;\n }\n\n static toErrorMessage(message: string) {\n return {\n type: \"FROM_BOT\" as const,\n id: genUuid(),\n timestamp: new Date().toISOString(),\n component: \"TEXT\",\n data: {\n message,\n variant: \"error\",\n },\n };\n }\n}\n","import { ApiCaller } from \"../api\";\nimport type { WidgetConfig } from \"../types/WidgetConfig\";\nimport { ContactCtx } from \"./contact\";\nimport { MessageCtx } from \"./message\";\nimport { SessionCtx } from \"./session\";\n\nexport class WidgetCtx {\n public config: WidgetConfig;\n public api: ApiCaller;\n public contactCtx: ContactCtx;\n public sessionCtx: SessionCtx;\n public messageCtx: MessageCtx;\n\n constructor({ config }: { config: WidgetConfig }) {\n this.config = config;\n this.api = new ApiCaller({ config });\n\n this.contactCtx = new ContactCtx({\n api: this.api,\n config: this.config,\n });\n\n this.sessionCtx = new SessionCtx({\n config: this.config,\n api: this.api,\n contactCtx: this.contactCtx,\n });\n this.messageCtx = new MessageCtx({\n config: this.config,\n api: this.api,\n sessionCtx: this.sessionCtx,\n });\n }\n\n resetChat = () => {\n this.sessionCtx.reset();\n this.messageCtx.reset();\n };\n}\n"],"names":["defaultOnError","onErrorOptions","basicClient","options","client","createClient","middlewares","ApiCaller","config","__publicField","token","baseUrl","headers","request","key","value","axios","body","abortSignal","sessionId","lastMessageTimestamp","query","cursor","filters","file","formData","data","_a","PubSub","state","__privateAdd","_state","_lastUpdated","event","listeners","eventData","listener","callback","error","__privateGet","newState","isEqual","__privateSet","_s","ContactCtx","api","_b","_d","_c","payload","Poller","cb","interval","timeouts","poll","genUuid","uuidv4","SessionCtx","contactCtx","session","contact","deduped","s","i","self","MessageCtx","sessionCtx","input","isSending","isAssignedToAI","userMessage","currentMessages","botMessage","prevMessages","m","_e","_f","errorMessage","_g","response","newMessages","newMsg","existingMsg","history","commonFields","content","attachments","uiVal","message","WidgetCtx"],"mappings":"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"}
@@ -1,17 +1,17 @@
1
- var x = Object.defineProperty;
1
+ var T = Object.defineProperty;
2
2
  var A = (a) => {
3
3
  throw TypeError(a);
4
4
  };
5
- var O = (a, t, e) => t in a ? x(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
6
- var s = (a, t, e) => O(a, typeof t != "symbol" ? t + "" : t, e), U = (a, t, e) => t.has(a) || A("Cannot " + e);
7
- var c = (a, t, e) => (U(a, t, "read from private field"), e ? e.call(a) : t.get(a)), S = (a, t, e) => t.has(a) ? A("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(a) : t.set(a, e), p = (a, t, e, i) => (U(a, t, "write to private field"), i ? i.call(a, e) : t.set(a, e), e);
5
+ var I = (a, t, e) => t in a ? T(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
6
+ var s = (a, t, e) => I(a, typeof t != "symbol" ? t + "" : t, e), M = (a, t, e) => t.has(a) || A("Cannot " + e);
7
+ var h = (a, t, e) => (M(a, t, "read from private field"), e ? e.call(a) : t.get(a)), P = (a, t, e) => t.has(a) ? A("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(a) : t.set(a, e), C = (a, t, e, i) => (M(a, t, "write to private field"), i ? i.call(a, e) : t.set(a, e), e);
8
8
  import R from "axios";
9
9
  import E from "openapi-fetch";
10
10
  import F from "lodash.isequal";
11
11
  import { v4 as L } from "uuid";
12
12
  const D = (a) => {
13
13
  console.log(a.error);
14
- }, I = (a) => {
14
+ }, _ = (a) => {
15
15
  const t = E({
16
16
  baseUrl: a.baseUrl
17
17
  }), e = {
@@ -21,7 +21,7 @@ const D = (a) => {
21
21
  };
22
22
  return t.use(e), t;
23
23
  };
24
- class B {
24
+ class q {
25
25
  constructor({
26
26
  config: t
27
27
  }) {
@@ -40,7 +40,7 @@ class B {
40
40
  s(this, "createOpenAPIClient", ({
41
41
  baseUrl: t,
42
42
  headers: e
43
- }) => I({
43
+ }) => _({
44
44
  baseUrl: t,
45
45
  onRequest: ({ request: i }) => {
46
46
  Object.entries(e).forEach(([n, r]) => {
@@ -84,7 +84,9 @@ class B {
84
84
  body: t
85
85
  }
86
86
  ));
87
- s(this, "createSession", async () => await this.client.POST("/backend/widget/v2/create-session"));
87
+ s(this, "createSession", async (t) => await this.client.POST("/backend/widget/v2/create-session", {
88
+ body: t
89
+ }));
88
90
  s(this, "getSession", async ({
89
91
  sessionId: t,
90
92
  abortSignal: e
@@ -92,6 +94,14 @@ class B {
92
94
  params: { path: { sessionId: t } },
93
95
  signal: e
94
96
  }));
97
+ s(this, "getSessions", async ({
98
+ cursor: t,
99
+ filters: e,
100
+ abortSignal: i
101
+ }) => await this.client.GET("/backend/widget/v2/sessions", {
102
+ params: { query: { cursor: t, filters: JSON.stringify(e) } },
103
+ signal: i
104
+ }));
95
105
  s(this, "uploadFile", async (t, e = {}) => {
96
106
  const i = new FormData();
97
107
  i.append("file", t.file);
@@ -104,20 +114,21 @@ class B {
104
114
  return n;
105
115
  });
106
116
  s(this, "vote", async (t) => await this.client.POST("/backend/widget/v2/chat/vote", { body: t }));
117
+ var n;
107
118
  this.config = t;
108
119
  const { baseUrl: e, headers: i } = this.constructClientOptions(
109
- t.contactToken
120
+ (n = t.user) == null ? void 0 : n.token
110
121
  );
111
122
  this.client = this.createOpenAPIClient({ baseUrl: e, headers: i }), this.uploadFileClient = this.createAxiosUploadClient({ baseUrl: e, headers: i });
112
123
  }
113
124
  }
114
- var l, g;
115
- class P {
125
+ var l, m;
126
+ class S {
116
127
  constructor(t) {
117
128
  s(this, "subscribers", /* @__PURE__ */ new Set());
118
- S(this, l);
129
+ P(this, l);
119
130
  s(this, "initialState");
120
- S(this, g);
131
+ P(this, m);
121
132
  s(this, "lifecycleListeners", /* @__PURE__ */ new Map());
122
133
  s(this, "emitLifecycle", (t, e) => {
123
134
  const i = this.lifecycleListeners.get(t);
@@ -160,7 +171,7 @@ class P {
160
171
  };
161
172
  });
162
173
  /** Get the current state */
163
- s(this, "get", () => c(this, l));
174
+ s(this, "get", () => h(this, l));
164
175
  // TODO make this provide prev state
165
176
  /**
166
177
  * Set the state and notify subscribers if the state changes
@@ -168,14 +179,14 @@ class P {
168
179
  */
169
180
  s(this, "set", (t) => {
170
181
  this.emitLifecycle("beforeUpdate", {
171
- previousState: c(this, l),
182
+ previousState: h(this, l),
172
183
  nextState: t
173
- }), F(c(this, l), t) || (p(this, l, t), p(this, g, Date.now()), this.emitLifecycle("stateChange", { state: t }), this.notifySubscribers(t)), this.emitLifecycle("afterUpdate", { state: t });
184
+ }), F(h(this, l), t) || (C(this, l, t), C(this, m, Date.now()), this.emitLifecycle("stateChange", { state: t }), this.notifySubscribers(t)), this.emitLifecycle("afterUpdate", { state: t });
174
185
  });
175
186
  // TODO make this provide prev state
176
187
  s(this, "setPartial", (t) => {
177
188
  if (t == null) return;
178
- const e = { ...c(this, l), ...t };
189
+ const e = { ...h(this, l), ...t };
179
190
  this.set(e);
180
191
  });
181
192
  /**
@@ -190,12 +201,12 @@ class P {
190
201
  s(this, "reset", () => {
191
202
  this.set(this.initialState);
192
203
  });
193
- s(this, "lastUpdated", () => c(this, g));
194
- p(this, l, t), this.initialState = t, p(this, g, Date.now()), this.emitLifecycle("init", { initialState: c(this, l) });
204
+ s(this, "lastUpdated", () => h(this, m));
205
+ C(this, l, t), this.initialState = t, C(this, m, Date.now()), this.emitLifecycle("init", { initialState: h(this, l) });
195
206
  }
196
207
  }
197
- l = new WeakMap(), g = new WeakMap();
198
- class q {
208
+ l = new WeakMap(), m = new WeakMap();
209
+ class B {
199
210
  constructor({
200
211
  config: t,
201
212
  api: e
@@ -208,10 +219,10 @@ class q {
208
219
  return !!(!((e = this.state.get().contact) != null && e.token) && this.config.collectUserData);
209
220
  });
210
221
  s(this, "autoCreateUnverifiedUser", async () => {
211
- var t, e;
222
+ var t, e, i, n;
212
223
  await this.createUnverifiedContact({
213
- name: ((t = this.config.user) == null ? void 0 : t.name) || "Anonymous",
214
- email: (e = this.config.user) == null ? void 0 : e.email
224
+ name: ((e = (t = this.config.user) == null ? void 0 : t.data) == null ? void 0 : e.name) || "Anonymous",
225
+ email: (n = (i = this.config.user) == null ? void 0 : i.data) == null ? void 0 : n.email
215
226
  });
216
227
  });
217
228
  s(this, "createUnverifiedContact", async (t) => {
@@ -221,21 +232,22 @@ class q {
221
232
  isErrorCreatingUnverifiedContact: !1
222
233
  });
223
234
  const { data: e } = await this.api.createUnverifiedContact(t);
224
- e != null && e.token ? (this.state.setPartial({ contact: { token: e.token } }), this.api.setAuthToken(e.token)) : this.state.setPartial({ isErrorCreatingUnverifiedContact: !0 });
235
+ e != null && e.token ? (this.api.setAuthToken(e.token), this.state.setPartial({ contact: { token: e.token } })) : this.state.setPartial({ isErrorCreatingUnverifiedContact: !0 });
225
236
  } finally {
226
237
  this.state.setPartial({ isCreatingUnverifiedContact: !1 });
227
238
  }
228
239
  });
229
- this.config = t, this.api = e, this.state = new P({
230
- contact: t.contactToken ? { token: t.contactToken } : null,
240
+ var i, n, r;
241
+ this.config = t, this.api = e, this.state = new S({
242
+ contact: (i = t.user) != null && i.token ? { token: (n = t.user) == null ? void 0 : n.token } : null,
231
243
  isCreatingUnverifiedContact: !1,
232
244
  isErrorCreatingUnverifiedContact: !1
233
- }), !t.contactToken && !t.collectUserData && this.autoCreateUnverifiedUser();
245
+ }), !((r = t.user) != null && r.token) && !t.collectUserData && this.autoCreateUnverifiedUser();
234
246
  }
235
247
  }
236
- class M {
248
+ class U {
237
249
  constructor() {
238
- s(this, "state", new P({
250
+ s(this, "state", new S({
239
251
  isPolling: !1,
240
252
  isError: !1
241
253
  }));
@@ -269,12 +281,24 @@ class M {
269
281
  function w() {
270
282
  return L();
271
283
  }
272
- class _ {
273
- constructor(t) {
284
+ class H {
285
+ constructor({
286
+ config: t,
287
+ api: e,
288
+ contactCtx: i
289
+ }) {
290
+ s(this, "config");
274
291
  s(this, "api");
275
- s(this, "poller", new M());
276
- s(this, "state", new P({
292
+ s(this, "contactCtx");
293
+ s(this, "poller", new U());
294
+ s(this, "state", new S({
277
295
  session: null,
296
+ sessions: {
297
+ data: [],
298
+ cursor: void 0,
299
+ isLastPage: !1,
300
+ didInitialFetch: !1
301
+ },
278
302
  isCreatingSession: !1
279
303
  }));
280
304
  /** Clears the session and stops polling */
@@ -284,30 +308,61 @@ class _ {
284
308
  s(this, "registerPolling", () => {
285
309
  this.state.subscribe(({ session: t }) => {
286
310
  t != null && t.id ? this.poller.startPolling(async (e) => {
287
- const { data: i } = await this.fetch(t.id, e);
311
+ const { data: i } = await this.api.getSession({
312
+ sessionId: t.id,
313
+ abortSignal: e
314
+ });
288
315
  i && this.state.setPartial({ session: i });
289
316
  }, 1e3) : this.poller.reset();
290
317
  });
291
318
  });
292
- /**
293
- * Creates a new session
294
- * @returns The session
295
- */
319
+ s(this, "registerInitialSessionsFetch", () => {
320
+ this.contactCtx.state.subscribe(({ contact: t }) => {
321
+ t != null && t.token && !this.state.get().sessions.didInitialFetch && (this.state.setPartial({
322
+ sessions: {
323
+ ...this.state.get().sessions,
324
+ didInitialFetch: !0
325
+ }
326
+ }), this.loadMoreSessions());
327
+ });
328
+ });
296
329
  s(this, "createSession", async () => {
330
+ var i, n;
297
331
  this.state.setPartial({ session: null, isCreatingSession: !0 });
298
- const { data: t, error: e } = await this.api.createSession();
332
+ const { data: t, error: e } = await this.api.createSession({
333
+ customData: (i = this.config.user) != null && i.externalId ? {
334
+ external_id: (n = this.config.user) == null ? void 0 : n.externalId
335
+ } : void 0
336
+ });
299
337
  return t ? (this.state.setPartial({ session: t, isCreatingSession: !1 }), t) : (console.error("Failed to create session:", e), null);
300
338
  });
301
- /**
302
- * Fetches the session from the API
303
- * @param id - The ID of the session to fetch
304
- * @returns The session
305
- */
306
- s(this, "fetch", async (t, e) => this.api.getSession({ sessionId: t, abortSignal: e }));
307
- this.api = t, this.registerPolling();
339
+ s(this, "loadMoreSessions", async () => {
340
+ var e, i;
341
+ if (this.state.get().sessions.isLastPage || !((e = this.contactCtx.state.get().contact) != null && e.token)) return;
342
+ const { data: t } = await this.api.getSessions({
343
+ cursor: this.state.get().sessions.cursor,
344
+ filters: (i = this.config.user) != null && i.externalId ? {
345
+ external_id: this.config.user.externalId
346
+ } : {}
347
+ });
348
+ if (t) {
349
+ const r = [...this.state.get().sessions.data, ...t.items].filter(
350
+ (c, d, g) => d === g.findIndex((u) => c.id === u.id)
351
+ );
352
+ this.state.setPartial({
353
+ sessions: {
354
+ ...this.state.get().sessions,
355
+ data: r,
356
+ cursor: t.next || void 0,
357
+ isLastPage: t.next === null
358
+ }
359
+ });
360
+ }
361
+ });
362
+ this.config = t, this.api = e, this.contactCtx = i, this.registerPolling(), this.registerInitialSessionsFetch();
308
363
  }
309
364
  }
310
- class d {
365
+ class f {
311
366
  constructor({
312
367
  config: t,
313
368
  api: e,
@@ -316,8 +371,8 @@ class d {
316
371
  s(this, "config");
317
372
  s(this, "api");
318
373
  s(this, "sessionCtx");
319
- s(this, "poller", new M());
320
- s(this, "state", new P({
374
+ s(this, "poller", new U());
375
+ s(this, "state", new S({
321
376
  messages: [],
322
377
  isSendingMessage: !1,
323
378
  suggestedReplies: null
@@ -334,7 +389,7 @@ class d {
334
389
  });
335
390
  });
336
391
  s(this, "sendMessage", async (t) => {
337
- var n, r, u, f, m, C;
392
+ var n, r, c, d, g, u, x;
338
393
  this.sendMessageAbortController = new AbortController();
339
394
  const e = this.state.get().isSendingMessage, i = ((n = this.sessionCtx.state.get().session) == null ? void 0 : n.assignee.kind) === "ai";
340
395
  if (e && i) {
@@ -344,7 +399,7 @@ class d {
344
399
  this.state.setPartial({ suggestedReplies: null });
345
400
  try {
346
401
  this.state.setPartial({ isSendingMessage: !0 });
347
- const b = d.toUserMessage(
402
+ const b = f.toUserMessage(
348
403
  t.content,
349
404
  t.attachments || void 0
350
405
  ), k = this.state.get().messages;
@@ -354,7 +409,7 @@ class d {
354
409
  console.error("Failed to create session");
355
410
  return;
356
411
  }
357
- const v = (u = this.sessionCtx.state.get().session) == null ? void 0 : u.id;
412
+ const v = (c = this.sessionCtx.state.get().session) == null ? void 0 : c.id;
358
413
  if (!v) return;
359
414
  const { data: o } = await this.api.sendMessage(
360
415
  {
@@ -363,27 +418,27 @@ class d {
363
418
  headers: this.config.headers,
364
419
  query_params: this.config.queryParams,
365
420
  session_id: v,
366
- user: this.config.user,
421
+ user: (d = this.config.user) == null ? void 0 : d.data,
367
422
  ...t
368
423
  },
369
424
  this.sendMessageAbortController.signal
370
425
  );
371
426
  if (o != null && o.success) {
372
- const h = d.toBotMessage(o);
373
- if (h) {
427
+ const p = f.toBotMessage(o);
428
+ if (p) {
374
429
  const y = this.state.get().messages;
375
430
  if (!!y.some(
376
- (T) => T.id === h.id
431
+ (O) => O.id === p.id
377
432
  )) return;
378
- this.state.setPartial({ messages: [...y, h] });
433
+ this.state.setPartial({ messages: [...y, p] });
379
434
  } else
380
- (f = o.options) != null && f.value && ((m = o.options) == null ? void 0 : m.value.length) > 0 && this.state.setPartial({ suggestedReplies: o.options.value });
435
+ (g = o.options) != null && g.value && ((u = o.options) == null ? void 0 : u.value.length) > 0 && this.state.setPartial({ suggestedReplies: o.options.value });
381
436
  } else {
382
- const h = d.toErrorMessage(
383
- ((C = o == null ? void 0 : o.error) == null ? void 0 : C.message) || "Unknown error occurred"
437
+ const p = f.toErrorMessage(
438
+ ((x = o == null ? void 0 : o.error) == null ? void 0 : x.message) || "Unknown error occurred"
384
439
  ), y = this.state.get().messages;
385
440
  this.state.setPartial({
386
- messages: [...y, h]
441
+ messages: [...y, p]
387
442
  });
388
443
  }
389
444
  } catch (b) {
@@ -400,11 +455,11 @@ class d {
400
455
  abortSignal: e
401
456
  });
402
457
  if (n && n.length > 0) {
403
- const u = this.state.get().messages, f = n.map(d.mapHistoryToMessage).filter(
404
- (m) => !u.some((C) => C.id === m.id)
458
+ const c = this.state.get().messages, d = n.map(f.mapHistoryToMessage).filter(
459
+ (g) => !c.some((u) => u.id === g.id)
405
460
  );
406
461
  this.state.setPartial({
407
- messages: [...u, ...f]
462
+ messages: [...c, ...d]
408
463
  });
409
464
  }
410
465
  });
@@ -500,10 +555,14 @@ class W {
500
555
  s(this, "resetChat", () => {
501
556
  this.sessionCtx.reset(), this.messageCtx.reset();
502
557
  });
503
- this.config = t, this.api = new B({ config: t }), this.contactCtx = new q({
558
+ this.config = t, this.api = new q({ config: t }), this.contactCtx = new B({
504
559
  api: this.api,
505
560
  config: this.config
506
- }), this.sessionCtx = new _(this.api), this.messageCtx = new d({
561
+ }), this.sessionCtx = new H({
562
+ config: this.config,
563
+ api: this.api,
564
+ contactCtx: this.contactCtx
565
+ }), this.messageCtx = new f({
507
566
  config: this.config,
508
567
  api: this.api,
509
568
  sessionCtx: this.sessionCtx
@@ -511,7 +570,7 @@ class W {
511
570
  }
512
571
  }
513
572
  export {
514
- P,
573
+ S as P,
515
574
  W
516
575
  };
517
- //# sourceMappingURL=widget-BeNOCqB5.js.map
576
+ //# sourceMappingURL=widget-BOaF1U-p.js.map