mind-link-ai-widget
Version:
A react widget for React Web and React-Native Mobile integrations.
12 lines (10 loc) • 11.5 kB
JavaScript
"use strict";const a=require("react"),fe=require("dompurify"),be=require("marked"),j=require("react-icons/io5");var H={exports:{}},C={};/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var se;function xe(){if(se)return C;se=1;var n=a,s=Symbol.for("react.element"),l=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,p=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,d={key:!0,ref:!0,__self:!0,__source:!0};function g(w,h,y){var f,b={},k=null,S=null;y!==void 0&&(k=""+y),h.key!==void 0&&(k=""+h.key),h.ref!==void 0&&(S=h.ref);for(f in h)i.call(h,f)&&!d.hasOwnProperty(f)&&(b[f]=h[f]);if(w&&w.defaultProps)for(f in h=w.defaultProps,h)b[f]===void 0&&(b[f]=h[f]);return{$$typeof:s,type:w,key:k,ref:S,props:b,_owner:p.current}}return C.Fragment=l,C.jsx=g,C.jsxs=g,C}var oe;function ge(){return oe||(oe=1,H.exports=xe()),H.exports}var t=ge();const u=[];for(let n=0;n<256;++n)u.push((n+256).toString(16).slice(1));function ye(n,s=0){return(u[n[s+0]]+u[n[s+1]]+u[n[s+2]]+u[n[s+3]]+"-"+u[n[s+4]]+u[n[s+5]]+"-"+u[n[s+6]]+u[n[s+7]]+"-"+u[n[s+8]]+u[n[s+9]]+"-"+u[n[s+10]]+u[n[s+11]]+u[n[s+12]]+u[n[s+13]]+u[n[s+14]]+u[n[s+15]]).toLowerCase()}let z;const we=new Uint8Array(16);function ke(){if(!z){if(typeof crypto>"u"||!crypto.getRandomValues)throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");z=crypto.getRandomValues.bind(crypto)}return z(we)}const je=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),ae={randomUUID:je};function Se(n,s,l){if(ae.randomUUID&&!n)return ae.randomUUID();n=n||{};const i=n.random??n.rng?.()??ke();if(i.length<16)throw new Error("Random bytes length must be >= 16");return i[6]=i[6]&15|64,i[8]=i[8]&63|128,ye(i)}const ve=Ne();function Ne(){return Se()}function R(){return Math.random().toString(36).slice(2)}const J="https://uat.api-az.carelonhealth.com/mindlink/api/v1",Te=`${J}/auth/token`,Ie=`${J}/antwell/documents/chat`,_e=`${J}/antwell/documents/chat-feedback`,Z="ai-smart-search",ie="7a3b9c2d-5e6f-4a1b-8c2d-3e9f1a7b6c4d",ce="HS256",Ce="Basic bWluZGxpbmstYW50d2VsbDo3ZTNiMmMxZC01ZjZhLTRiMWMtOGQyZS0zZjlhMWI3YzZkNGU=";function Re(n){try{const[,s]=n.split("."),l=JSON.parse(atob(s));return typeof l.exp=="number"?l.exp:null}catch{return null}}let P=null;async function le(){const n=Math.floor(Date.now()/1e3);if(P&&n<P.exp-20)return P.accessToken;const s=await fetch(Te,{method:"GET",headers:{"Content-Type":"application/json","sender-app":Z,alg:ce,Authorization:Ce}});if(!s.ok){const d=await s.text().catch(()=>"");throw new Error(`Auth failed (${s.status}) ${d}`)}const l=await s.json(),i=l.access_token,p=Re(i)??Math.floor(Date.now()/1e3)+(l.expires_in??3600);return P={accessToken:i,exp:p},i}async function Ee(n){const s=await le(),l=await fetch(_e,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`,apikey:ie,"sender-app":Z,"x-csid":ve},body:JSON.stringify(n)});if(!l.ok)throw new Error(`Feedback submission failed: ${l.statusText}`)}async function re(n,s,l,i){const p=await le(),d=await fetch(Ie,{method:"POST",signal:i,headers:{"sender-app":Z,apikey:ie,"x-csid":l,alg:ce,Authorization:`Bearer ${p}`,"Content-Type":"application/json"},body:JSON.stringify({config:n,query:s})});if(!d.ok){const g=await d.text().catch(()=>"");throw new Error(`Chat failed (${d.status}) ${g}`)}return await d.json()}const De=({isOpen:n,onClose:s,onSubmit:l,rating:i})=>{const[p,d]=a.useState(""),[g,w]=a.useState(!1);if(!n)return null;const h=async y=>{if(y.preventDefault(),!g){w(!0);try{await l(p),d(""),s()}catch(f){console.error("Failed to submit feedback:",f)}finally{w(!1)}}};return t.jsx("div",{className:"feedback-dialog-overlay",children:t.jsxs("div",{className:"feedback-dialog",children:[t.jsx("h3",{children:"Provide Additional Feedback"}),t.jsx("p",{children:"Your feedback helps us improve our responses."}),t.jsxs("form",{onSubmit:h,children:[t.jsxs("div",{className:"form-group",children:[t.jsx("label",{htmlFor:"comments",children:i==="like"?"What did you like about this response?":"How can we improve this response?"}),t.jsx("textarea",{id:"comments",value:p,onChange:y=>d(y.target.value),rows:4,placeholder:"Enter your feedback here...",required:!0})]}),t.jsxs("div",{className:"dialog-actions",children:[t.jsx("button",{type:"button",className:"btn-secondary",onClick:s,disabled:g,children:"Cancel"}),t.jsx("button",{type:"submit",className:"btn-primary",disabled:g,children:g?"Submitting...":"Submit Feedback"})]})]})]})})};function Oe(n){const s=be.marked.parse(n,{breaks:!0});return fe.sanitize(s,{ADD_ATTR:["target","rel"]})}function Ue({brand:n,stateCode:s,category:l,language:i,userQuery:p,uuid:d}){const[,g]=a.useState(!1),[w,h]=a.useState(new Set),[y,f]=a.useState(!1),[b,k]=a.useState([]),[S,E]=a.useState(""),[v,D]=a.useState(!1),[B,M]=a.useState(null),[N,F]=a.useState({}),[I,O]=a.useState(null),[G,$]=a.useState("");a.useEffect(()=>{if(p&&b.length===0){const e={id:R(),role:"user",content:p};k([e])}},[p]);const[T,L]=a.useState({isOpen:!1,messageId:null,rating:null}),V=10,W=a.useRef(null),_=a.useRef(null),U=a.useRef(null),Y=a.useRef(!1),ue=e=>{const o=N[e]==="up"?null:"up";F(c=>({...c,[e]:o})),o==="up"?L({isOpen:!0,messageId:e,rating:"like"}):q(e,"like","")},de=e=>{const o=N[e]==="down"?null:"down";F(c=>({...c,[e]:o})),o==="down"?L({isOpen:!0,messageId:e,rating:"dislike"}):q(e,"dislike","")},q=async(e,r,o)=>{try{const c=b.findIndex(x=>x.id===e);if(c>0){const x=b[c],m=b[c-1];x&&m&&m.role==="user"&&await Ee({message_id:e,rating:r,comments:o||`User gave a thumbs ${r}`,conversation:{query:m.content,response:x.content,context:{brand:n,state:s,category:l,language:i}}})}}catch(c){console.error("Failed to send feedback:",c),F(x=>({...x,[e]:null}))}},pe=async e=>{T.messageId&&T.rating&&await q(T.messageId,T.rating,e)},K=()=>{W.current?.scrollIntoView({behavior:"smooth"})};a.useEffect(()=>{K()},[b,v,G]);const X=()=>({brand:n.toLowerCase(),state:s.toUpperCase(),category:l,language:i?.toLowerCase()});a.useEffect(()=>{const e=new ResizeObserver(()=>{K()});return _.current&&e.observe(_.current),()=>{_.current&&e.unobserve(_.current)}},[]),a.useEffect(()=>{if(!Y.current&&p){Y.current=!0;const e=X();D(!0),re(e,p,d).then(r=>{const o=R(),c=r?.message?.content??"Sorry, I couldn't parse the response.",{cleanContent:x,prompts:m}=Q(c);k(A=>[...A,{id:o,role:"assistant",content:x,followUpPrompts:m.length>0?m:void 0}]),O(o)}).catch(r=>{M(r?.message||"Something went wrong."),k(o=>[...o,{id:R(),role:"assistant",content:"I’m having trouble reaching the service right now. Please try again."}]),O(null)}).finally(()=>{D(!1)})}},[n,s,l,i,p,d]);const Q=e=>{const r=/[-*] \[(.*?)\]\(#followUps\)/g,o=[];let c=e;return c=c.replace(r,(x,m)=>(o.push(m),"")),c=c.replace(/\n{3,}/g,`
`).trim(),{cleanContent:c,prompts:o}},ee=a.useCallback(async e=>{M(null),D(!0);const r={id:R(),role:"user",content:e};k(o=>[...o,r]),U.current?.abort(),U.current=new AbortController;try{const o=X(),x=(await re(o,e,d,U.current.signal))?.message?.content??"Sorry, I couldn't parse the response.",{cleanContent:m,prompts:A}=Q(x),ne={id:R(),role:"assistant",content:m,followUpPrompts:A.length>0?A:void 0};k(me=>[...me,ne]),O(ne.id)}catch(o){o.name!=="AbortError"&&(M("Failed to get response. Please try again."),console.error("API Error:",o))}finally{D(!1),U.current=null}},[n,s,l,i,d]),he=a.useCallback(e=>{g(!0),E(e),setTimeout(()=>{const r=document.querySelector(".chat-input-wrap");r&&r.requestSubmit()},100)},[E]);a.useEffect(()=>{if(!I)return;const e=b.find(m=>m.id===I);if(!e)return;let r=0;const o=e.content;$("");function c(){e&&(r<o.length?($(o.substring(0,r+1)),r++,setTimeout(c,V)):(O(null),$(""),h(m=>new Set(m).add(e.id))))}const x=setTimeout(c,V);return()=>clearTimeout(x)},[I,b]);const te=a.useCallback(e=>{e?.preventDefault(),!(v||!S.trim())&&(g(!0),ee(S),E(""))},[S,v,ee]);return t.jsxs("div",{className:"chat-shell",children:[t.jsx("header",{className:"chat-header",children:t.jsxs("div",{className:"chat-header-title",children:[t.jsx(j.IoSparklesSharp,{}),t.jsx("span",{className:"chat-header-title-text",children:"AI Search Assistant"}),t.jsxs("div",{className:"help-button-container",children:[t.jsx("button",{className:"help-icon-button",onClick:()=>f(!y),"aria-label":"Show help information","aria-expanded":y,children:t.jsx(j.IoHelpCircleOutline,{})}),y&&t.jsx("div",{className:"help-tooltip",children:t.jsx("p",{children:"The AI Search Assistant is powered by artificial intelligence. Please double-check important information."})})]})]})}),t.jsxs("main",{className:"chat-main",children:[t.jsx(De,{isOpen:T.isOpen,onClose:()=>L({isOpen:!1,messageId:null,rating:null}),onSubmit:pe,rating:T.rating||"like"}),t.jsxs("div",{className:"messages-container",ref:_,children:[b.map(e=>t.jsx("section",{className:`message ${e.role}`,children:e.role==="assistant"?t.jsx(t.Fragment,{children:t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"message-assistant",children:[t.jsx("div",{className:"message-content",dangerouslySetInnerHTML:{__html:Oe(I===e.id?G:e.content).replaceAll("<a ",'<a target="_blank" rel="noopener noreferrer" ')}}),e.followUpPrompts&&e.followUpPrompts.length>0&&!I&&t.jsx("div",{className:"followup-prompts",children:e.followUpPrompts.map((r,o)=>t.jsx("button",{type:"button",className:"followup-prompt",onClick:()=>he(r),children:r},o))})]}),w.has(e.id)&&t.jsx("div",{className:"message-actions-container",children:t.jsxs("div",{className:"message-actions",children:[t.jsx("button",{type:"button",className:`icon-btn ${N[e.id]==="up"?"active":""}`,"aria-label":"Thumbs up",onClick:()=>ue(e.id),children:N[e.id]==="up"?t.jsx(j.IoThumbsUp,{color:"#1a3673"}):t.jsx(j.IoThumbsUpOutline,{color:"#1a3673"})}),t.jsx("button",{type:"button",className:`icon-btn ${N[e.id]==="down"?"active":""}`,"aria-label":"Thumbs down",onClick:()=>de(e.id),children:N[e.id]==="down"?t.jsx(j.IoThumbsDown,{color:"#1a3673"}):t.jsx(j.IoThumbsDownOutline,{color:"#1a3673"})}),t.jsx("button",{type:"button",className:"icon-btn","aria-label":"Copy",onClick:async()=>{try{await navigator.clipboard.writeText(e.content)}catch{alert("Failed to copy text")}},children:t.jsx(j.IoCopyOutline,{color:"#1a3673"})}),t.jsx("button",{type:"button",className:"icon-btn","aria-label":"Get shareable link",onClick:()=>alert(`Share this response: ${e.content}`),children:t.jsx(j.IoRepeatSharp,{color:"#1a3673"})})]})})]})}):t.jsx("div",{className:"message-user",style:{textAlign:"right",alignSelf:"flex-end"},children:e.content})},e.id)),v&&t.jsx("section",{className:"message assistant",children:t.jsx("div",{className:"message-assistant",children:t.jsx("div",{className:"thinking-indicator",children:"Thinking..."})})}),B&&t.jsx("div",{className:"error-banner",children:B}),t.jsx("div",{ref:W})]})]}),t.jsxs("form",{className:"chat-input-wrap",onSubmit:te,children:[t.jsx("input",{className:"chat-input",placeholder:"Send a message",value:S,onChange:e=>E(e.target.value),onKeyDown:e=>{e.key==="Enter"&&!e.shiftKey&&(te(),e.preventDefault())},disabled:v,autoFocus:!0}),t.jsx("button",{type:"submit",className:"send-btn",disabled:!S.trim()||v,children:v?t.jsx(Ae,{}):t.jsx(j.IoSendSharp,{})})]})]})}function Ae(){return t.jsx("span",{className:"spinner","aria-hidden":"true"})}module.exports=Ue;