diff --git a/dist/assets/index-CEauQ61c.js b/dist/assets/index-BRSJQ8EZ.js similarity index 92% rename from dist/assets/index-CEauQ61c.js rename to dist/assets/index-BRSJQ8EZ.js index 012f582..bbfc0c2 100644 --- a/dist/assets/index-CEauQ61c.js +++ b/dist/assets/index-BRSJQ8EZ.js @@ -60,14 +60,14 @@ Please change the parent to d.replace(/^\||\|$/g,"").split("|").map(N=>N.trim()),v=h(u[0]),y=h(u[1]);if(v.length<2||y.length<2||!y.every(d=>/^[ :\-]+$/.test(d)&&/-/.test(d)))return s;const S=y.map(d=>{const N=d.replace(/\s+/g,""),P=N.startsWith(":"),M=N.endsWith(":");return P&&M?"center":M?"right":"left"}),C=u.slice(2).filter(d=>/^\|/.test(d.trim())),E=d=>` style="text-align:${S[d]||"left"};vertical-align:top;padding:.6rem .75rem"`,L=v.map((d,N)=>`${d}`).join(""),m=C.map(d=>`${h(d).map((M,O)=>`${M}`).join("")}`).join("");return`${L}${m}
`+(a?` `:"")}),l=l.replace(/^---\s*$/gm,"
");let i=l.replace(/\*\*(.+?)\*\*/g,"$1").replace(new RegExp("(?$1").replace(/`(.+?)`/g,"$1");return i=i.replace(/\[([^\]]+?)\]\(([^)]+?)\)/g,'$1 $2'),i=i.replace(/\n/g,"
"),i=i.replace(/
\s*(
    )/g,"$1").replace(/(<\/ul>)\s*
    /g,"$1").replace(/
    \s*(
    ]*>)/g,"$1").replace(/(<\/div>)\s*
    /g,"$1").replace(/
    \s*(]*>)/g,"$1").replace(/(<\/table>)\s*
    /g,"$1").replace(/
    \s*(
    )/g,"$1").replace(/(<\/blockquote>)\s*
    /g,"$1"),i=i.replace(/(
    )[ \t]+/g,"$1").replace(/(
    )(?:[ \t]*
    )+/g,"$1").replace(/(<\/blockquote>)(?:[ \t]*
    )+/g,"$1").replace(/(<\/ul>)(?:[ \t]*
    )+/g,"$1"),i=i.replace(/@@CODEBLOCK(\d+)@@/g,(s,a)=>{const{lang:u,code:h}=n[+a],v=u&&u.trim()?u.trim():"code",y=h.replace(/&/g,"&").replace(//g,">"),S=`
    ${v}
    `,C=`
    ${y}
    `;return`
    ${S}${C}
    `}),i=i.replace(/
    \s*(?=
    ]*>[\s\S]*?<\/div>)\s*
    /g,"$1"),i}function Ny(e){const t=e.split(/\r?\n/);let n=null;for(let r=0;r/i,n=/<\/think(?:ing)?>/i,r=e.match(t);if(!r)return{think:null,answer:e};const l=r.index,o=r[0].length,i=e.substring(0,l).trim();let s=e.substring(l+o);const a=s.match(n);let u=null,h=i;return a?(u=s.substring(0,a.index).trim(),h+=s.substring(a.index+a[0].length)):u=s.trim(),{think:u||null,answer:h.trim()}}function _y({content:e,streamOutput:t,sources:n}){const{think:r,answer:l}=hp(e||""),[o,i]=Me.useState(!1),s=!!r;return p.jsxs("div",{className:"assistant-message",children:[s&&p.jsxs("div",{className:"assistant-thoughts",children:[p.jsxs("button",{className:"think-toggle",onClick:()=>i(a=>!a),"aria-expanded":o?"true":"false","aria-controls":"think-content",children:[p.jsx("span",{className:"think-toggle-icon","aria-hidden":"true",children:o?"▾":"▸"}),"Thoughts"]}),o&&p.jsx("div",{id:"think-content",className:"think-content",dangerouslySetInnerHTML:{__html:_c(r)}})]}),p.jsx("div",{className:"msg-content",dangerouslySetInnerHTML:{__html:_c(l||e||"")}}),Array.isArray(n)&&n.length>0&&p.jsx("div",{className:"msg-sources chips",children:n.map((a,u)=>{let h=a,v=!1;try{const y=new URL(a);if(y.protocol==="file:"){v=!0;const S=y.pathname.split("/").filter(Boolean);h=decodeURIComponent(S[S.length-1]||a)}else h=(y.hostname||a).replace(/^www\./i,"")}catch{}return p.jsx("a",{className:"chip",href:a,target:"_blank",rel:"noreferrer",title:a,onClick:y=>{var S,C;if(v){y.preventDefault();try{const E=new URL(a);(C=(S=window.electronAPI)==null?void 0:S.openPath)==null||C.call(S,decodeURIComponent(E.pathname))}catch{}}},children:h},a+u)})})]})}const Lc="websearch.searxUrl",Pc="websearch.engines",jc="chat.libraryBySession",Rc="http://127.0.0.1:8888";let mp="http://127.0.0.1:8000";const Ly=48,Py=24;function jy(e){return e.backendApiUrl||e.ollamaApiUrl||mp}function Ry(e){const t=typeof e=="string"?e.trim():"";return!t||t==="http://localhost:8888"?Rc:t}function Ty(){var eu;const[e,t]=g.useState([]),[n,r]=g.useState(null),[l,o]=g.useState("chats"),[i,s]=g.useState("General"),[a,u]=g.useState(null),[h,v]=g.useState(null),[y,S]=g.useState([]),[C,E]=g.useState([]),[L,m]=g.useState(null),[f,d]=g.useState(()=>{try{const c=localStorage.getItem(jc);return c?JSON.parse(c):{}}catch{return{}}}),[N,P]=g.useState(!1),[M,O]=g.useState(""),[F,B]=g.useState(""),[U,q]=g.useState(!1),[ge,We]=g.useState(""),[be,_]=g.useState(""),T=g.useRef(null),H=g.useRef(null),R=g.useRef(null),[z,b]=g.useState(mp),[Z,pe]=g.useState("Default"),[kt,ht]=g.useState(!1),[Rn,Ve]=g.useState(""),[Tn,Qo]=g.useState(!1),[hr,gp]=g.useState(()=>Ry(localStorage.getItem(Lc))),[un,vp]=g.useState(()=>Ey(localStorage.getItem(Pc)));g.useEffect(()=>{localStorage.setItem(Lc,hr||"")},[hr]),g.useEffect(()=>{try{localStorage.setItem(Pc,JSON.stringify(Lo(un)))}catch{}},[un]);const[pl,yp]=g.useState(!1),[Dt,Ko]=g.useState(!1),[$a,Yo]=g.useState(!0),[wp,$n]=g.useState([]),[hl,Ma]=g.useState({}),[za,Sp]=g.useState(!1),Oa=g.useRef(!1),[xp,Go]=g.useState(null),[Jo,ml]=g.useState("");function kp(c){const w=c.content||"";if(c.role==="assistant")try{const{answer:x}=hp(w);return(x||w).trim()}catch{return w.trim()}return w}async function Fa(c){try{await navigator.clipboard.writeText(kp(c))}catch(w){console.error("Failed to copy message:",w)}}function cn(c,w,x,k={}){const{removeIfEmpty:$=!1}=k;t(D=>D.map(W=>{if(W.session_id!==c)return W;const A=[];for(const V of W.messages||[]){if(V.id!==w){A.push(V);continue}$&&!x||A.push({...V,content:x})}return{...W,messages:A}}))}function At(c){return(c==null?void 0:c.name)==="AbortError"}function gl(c){return c instanceof Error&&c.message?c.message:String(c)}async function Xo(c){const w=await c.json().catch(()=>null);if(c.ok)return w;const x=typeof(w==null?void 0:w.detail)=="string"?w.detail:typeof(w==null?void 0:w.message)=="string"?w.message:"";throw new Error(x||`HTTP ${c.status}`)}async function Ep(){const c=await fetch(`${z}/ollama/startup-status`);return Xo(c)}async function Cp(){const c=await fetch(`${z}/startup/prepare-models`,{method:"POST"});return Xo(c)}async function Ia(c,w,x){if(!c)return{contextBlock:null,sources:[]};const $=await(await fetch(`${z}/libraries/${c}/context`,{method:"POST",headers:{"Content-Type":"application/json"},signal:x,body:JSON.stringify({prompt:w,top_k:5})})).json();return{contextBlock:typeof($==null?void 0:$.context_block)=="string"&&$.context_block.trim()?$.context_block.trim():null,sources:Array.isArray($==null?void 0:$.sources)?$.sources:[]}}function Np(c,w){Go(c),ml(w||"")}function vl(){Go(null),ml("")}async function _p(c){var D;const w=(((D=Fn[c])==null?void 0:D.content)||"").trim(),k=(Jo??"").trim();if(k.length===0){vl();return}if(k===w){vl();return}const $=n;if($){t(W=>W.map(A=>{if(A.session_id!==$)return A;const Le=(A.messages||[]).slice(0,c+1).map((ve,Ze)=>Ze===c?{...ve,content:k}:ve);return{...A,messages:Le}})),Go(null),ml(""),requestAnimationFrame(()=>ri("auto",$));try{const W=await fetch(`${z}/sessions/${$}/messages/${c}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:k})});if(!W.ok)throw new Error(`HTTP ${W.status}`)}catch(W){console.error("Failed to update message:",W),t(A=>A.map(V=>{if(V.session_id!==$)return V;const ve=(V.messages||[]).map((Ze,Q)=>Q===c?{...Ze,content:w}:Ze);return{...V,messages:ve}}));return}await Da(c,k)}}async function Da(c,w=null){var Le,ve,Ze,Q,fe,ke;const x=n;if(Dt||!x||typeof c!="number")return;const k=((Le=e.find(J=>J.session_id===x))==null?void 0:Le.messages)||[];let $=c;for(let J=c;J>=0;J--)if(((ve=k[J])==null?void 0:ve.role)==="user"){$=J;break}t(J=>J.map(oe=>oe.session_id===x?{...oe,messages:(oe.messages||[]).slice(0,$+1)}:oe));const D=ba(x);let W=w??(((Ze=k[$])==null?void 0:Ze.content)||""),A=[];const V=[];try{const J=Ya(x),oe=w??(((Q=k[$])==null?void 0:Q.content)||"");if((fe=J==null?void 0:J.states)!=null&&fe.is_indexed)try{const K=await Ia(J.slug,oe,D.signal);K.contextBlock&&V.push(K.contextBlock),Array.isArray(K.sources)&&A.push(...K.sources)}catch(K){if(At(K))throw K;console.warn("local library enrichment (regenerate) failed",K)}if(pl)try{const K=k.slice(Math.max(0,$-7),$+1).map(he=>({role:he.role,content:he.content||""}));K.length>0&&(K[K.length-1]={role:"user",content:oe});const te=await(await fetch(`${z}/websearch`,{method:"POST",headers:{"Content-Type":"application/json"},signal:D.signal,body:JSON.stringify({prompt:oe,model:ge,messages:K,history_limit:8,searx_url:hr||null,engines:Array.isArray(un)?un:null})})).json();te&&typeof te.context_block=="string"&&te.context_block.trim()&&V.push(te.context_block.trim()),Array.isArray(te==null?void 0:te.sources)&&A.push(...te.sources)}catch(K){if(At(K))throw K;console.warn("web search enrichment (regenerate) failed",K)}if(A=[...new Set(A)],V.length>0?W=`${oe} +`+r}return e}function _y(e){return(e||"").replace(/[\s\S]*?<\/think(?:ing)?>/gi,"").replace(/[*#]/g,"").replace(/\s+/g," ").trim()}function hp(e){if(!e)return{think:null,answer:""};const t=//i,n=/<\/think(?:ing)?>/i,r=e.match(t);if(!r)return{think:null,answer:e};const l=r.index,o=r[0].length,i=e.substring(0,l).trim();let s=e.substring(l+o);const a=s.match(n);let u=null,h=i;return a?(u=s.substring(0,a.index).trim(),h+=s.substring(a.index+a[0].length)):u=s.trim(),{think:u||null,answer:h.trim()}}function Ly({content:e,streamOutput:t,sources:n}){const{think:r,answer:l}=hp(e||""),[o,i]=Me.useState(!1),s=!!r;return p.jsxs("div",{className:"assistant-message",children:[s&&p.jsxs("div",{className:"assistant-thoughts",children:[p.jsxs("button",{className:"think-toggle",onClick:()=>i(a=>!a),"aria-expanded":o?"true":"false","aria-controls":"think-content",children:[p.jsx("span",{className:"think-toggle-icon","aria-hidden":"true",children:o?"▾":"▸"}),"Thoughts"]}),o&&p.jsx("div",{id:"think-content",className:"think-content",dangerouslySetInnerHTML:{__html:_c(r)}})]}),p.jsx("div",{className:"msg-content",dangerouslySetInnerHTML:{__html:_c(l||e||"")}}),Array.isArray(n)&&n.length>0&&p.jsx("div",{className:"msg-sources chips",children:n.map((a,u)=>{let h=a,v=!1;try{const y=new URL(a);if(y.protocol==="file:"){v=!0;const S=y.pathname.split("/").filter(Boolean);h=decodeURIComponent(S[S.length-1]||a)}else h=(y.hostname||a).replace(/^www\./i,"")}catch{}return p.jsx("a",{className:"chip",href:a,target:"_blank",rel:"noreferrer",title:a,onClick:y=>{var S,C;if(v){y.preventDefault();try{const E=new URL(a);(C=(S=window.electronAPI)==null?void 0:S.openPath)==null||C.call(S,decodeURIComponent(E.pathname))}catch{}}},children:h},a+u)})})]})}const Lc="websearch.searxUrl",Pc="websearch.engines",jc="chat.libraryBySession",Rc="http://127.0.0.1:8888";let mp="http://127.0.0.1:8000";const Py=48,jy=24;function Ry(e){return e.backendApiUrl||e.ollamaApiUrl||mp}function Ty(e){const t=typeof e=="string"?e.trim():"";return!t||t==="http://localhost:8888"?Rc:t}function $y(){var eu;const[e,t]=g.useState([]),[n,r]=g.useState(null),[l,o]=g.useState("chats"),[i,s]=g.useState("General"),[a,u]=g.useState(null),[h,v]=g.useState(null),[y,S]=g.useState([]),[C,E]=g.useState([]),[L,m]=g.useState(null),[f,d]=g.useState(()=>{try{const c=localStorage.getItem(jc);return c?JSON.parse(c):{}}catch{return{}}}),[N,P]=g.useState(!1),[M,O]=g.useState(""),[F,B]=g.useState(""),[U,q]=g.useState(!1),[ge,We]=g.useState(""),[be,_]=g.useState(""),T=g.useRef(null),H=g.useRef(null),R=g.useRef(null),[z,b]=g.useState(mp),[Z,pe]=g.useState("Default"),[kt,ht]=g.useState(!1),[Rn,Ve]=g.useState(""),[Tn,Qo]=g.useState(!1),[hr,gp]=g.useState(()=>Ty(localStorage.getItem(Lc))),[un,vp]=g.useState(()=>Ey(localStorage.getItem(Pc)));g.useEffect(()=>{localStorage.setItem(Lc,hr||"")},[hr]),g.useEffect(()=>{try{localStorage.setItem(Pc,JSON.stringify(Lo(un)))}catch{}},[un]);const[pl,yp]=g.useState(!1),[Dt,Ko]=g.useState(!1),[$a,Yo]=g.useState(!0),[wp,$n]=g.useState([]),[hl,Ma]=g.useState({}),[za,Sp]=g.useState(!1),Oa=g.useRef(!1),[xp,Go]=g.useState(null),[Jo,ml]=g.useState("");function kp(c){const w=c.content||"";if(c.role==="assistant")try{const{answer:x}=hp(w);return(x||w).trim()}catch{return w.trim()}return w}async function Fa(c){try{await navigator.clipboard.writeText(kp(c))}catch(w){console.error("Failed to copy message:",w)}}function cn(c,w,x,k={}){const{removeIfEmpty:$=!1}=k;t(D=>D.map(W=>{if(W.session_id!==c)return W;const A=[];for(const V of W.messages||[]){if(V.id!==w){A.push(V);continue}$&&!x||A.push({...V,content:x})}return{...W,messages:A}}))}function At(c){return(c==null?void 0:c.name)==="AbortError"}function gl(c){return c instanceof Error&&c.message?c.message:String(c)}async function Xo(c){const w=await c.json().catch(()=>null);if(c.ok)return w;const x=typeof(w==null?void 0:w.detail)=="string"?w.detail:typeof(w==null?void 0:w.message)=="string"?w.message:"";throw new Error(x||`HTTP ${c.status}`)}async function Ep(){const c=await fetch(`${z}/ollama/startup-status`);return Xo(c)}async function Cp(){const c=await fetch(`${z}/startup/prepare-models`,{method:"POST"});return Xo(c)}async function Ia(c,w,x){if(!c)return{contextBlock:null,sources:[]};const $=await(await fetch(`${z}/libraries/${c}/context`,{method:"POST",headers:{"Content-Type":"application/json"},signal:x,body:JSON.stringify({prompt:w,top_k:5})})).json();return{contextBlock:typeof($==null?void 0:$.context_block)=="string"&&$.context_block.trim()?$.context_block.trim():null,sources:Array.isArray($==null?void 0:$.sources)?$.sources:[]}}function Np(c,w){Go(c),ml(w||"")}function vl(){Go(null),ml("")}async function _p(c){var D;const w=(((D=Fn[c])==null?void 0:D.content)||"").trim(),k=(Jo??"").trim();if(k.length===0){vl();return}if(k===w){vl();return}const $=n;if($){t(W=>W.map(A=>{if(A.session_id!==$)return A;const Le=(A.messages||[]).slice(0,c+1).map((ve,Ze)=>Ze===c?{...ve,content:k}:ve);return{...A,messages:Le}})),Go(null),ml(""),requestAnimationFrame(()=>ri("auto",$));try{const W=await fetch(`${z}/sessions/${$}/messages/${c}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:k})});if(!W.ok)throw new Error(`HTTP ${W.status}`)}catch(W){console.error("Failed to update message:",W),t(A=>A.map(V=>{if(V.session_id!==$)return V;const ve=(V.messages||[]).map((Ze,Q)=>Q===c?{...Ze,content:w}:Ze);return{...V,messages:ve}}));return}await Da(c,k)}}async function Da(c,w=null){var Le,ve,Ze,Q,fe,ke;const x=n;if(Dt||!x||typeof c!="number")return;const k=((Le=e.find(J=>J.session_id===x))==null?void 0:Le.messages)||[];let $=c;for(let J=c;J>=0;J--)if(((ve=k[J])==null?void 0:ve.role)==="user"){$=J;break}t(J=>J.map(oe=>oe.session_id===x?{...oe,messages:(oe.messages||[]).slice(0,$+1)}:oe));const D=ba(x);let W=w??(((Ze=k[$])==null?void 0:Ze.content)||""),A=[];const V=[];try{const J=Ya(x),oe=w??(((Q=k[$])==null?void 0:Q.content)||"");if((fe=J==null?void 0:J.states)!=null&&fe.is_indexed)try{const K=await Ia(J.slug,oe,D.signal);K.contextBlock&&V.push(K.contextBlock),Array.isArray(K.sources)&&A.push(...K.sources)}catch(K){if(At(K))throw K;console.warn("local library enrichment (regenerate) failed",K)}if(pl)try{const K=k.slice(Math.max(0,$-7),$+1).map(he=>({role:he.role,content:he.content||""}));K.length>0&&(K[K.length-1]={role:"user",content:oe});const te=await(await fetch(`${z}/websearch`,{method:"POST",headers:{"Content-Type":"application/json"},signal:D.signal,body:JSON.stringify({prompt:oe,model:ge,messages:K,history_limit:8,searx_url:hr||null,engines:Array.isArray(un)?un:null})})).json();te&&typeof te.context_block=="string"&&te.context_block.trim()&&V.push(te.context_block.trim()),Array.isArray(te==null?void 0:te.sources)&&A.push(...te.sources)}catch(K){if(At(K))throw K;console.warn("web search enrichment (regenerate) failed",K)}if(A=[...new Set(A)],V.length>0?W=`${oe} ${V.join(` -`)}`:W=null,kt){const K=`msg-${Date.now()}-${Math.random()}`;let Ct="";t(te=>te.map(he=>he.session_id===x?{...he,messages:[...he.messages||[],{id:K,role:"assistant",content:"",sources:A}]}:he));try{const te=await fetch(`${z}/sessions/${x}/regenerate`,{method:"POST",headers:{"Content-Type":"application/json"},signal:D.signal,body:JSON.stringify({index:c,model:ge,stream:!0,enriched_message:W,sources:A||[]})});if(!te.ok)throw new Error(`HTTP ${te.status}`);const he=(ke=te.body)==null?void 0:ke.getReader();if(!he)throw new Error("Missing response body");const Bt=new TextDecoder;let mt=!1;for(;;){const{value:pn,done:Gp}=await he.read();if(Gp)break;const Jp=Bt.decode(pn,{stream:!0});Ct+=Jp,cn(x,K,Ct),!mt&&_e.current!==x&&(mt=!0,fn(li=>({...li,[x]:K})),$n(li=>[...new Set([...li,x])]))}_e.current!==x?(fn(pn=>({...pn,[x]:K})),$n(pn=>[...new Set([...pn,x])])):Mn.current[x]?zn(pn=>({...pn,[x]:K})):requestAnimationFrame(()=>In(K,"smooth",x))}catch(te){if(At(te)){cn(x,K,Ct,{removeIfEmpty:!0});return}console.error(te),cn(x,K,`Error: ${gl(te)}`,{removeIfEmpty:!0});return}}else{const K=await fetch(`${z}/sessions/${x}/regenerate`,{method:"POST",headers:{"Content-Type":"application/json"},signal:D.signal,body:JSON.stringify({index:c,model:ge,stream:!1,enriched_message:W,sources:A||[]})});if(!K.ok)throw new Error(`HTTP ${K.status}`);const Ct=await K.json(),te=`msg-${Date.now()}`;t(he=>he.map(Bt=>Bt.session_id===x?{...Bt,messages:[...Bt.messages||[],{role:"assistant",content:Ct.reply,id:te,sources:A}]}:Bt)),_e.current!==x?(fn(he=>({...he,[x]:te})),$n(he=>[...new Set([...he,x])])):Mn.current[x]?zn(he=>({...he,[x]:te})):requestAnimationFrame(()=>In(te,"smooth",x))}}catch(J){At(J)||console.error(J)}finally{Zo(D)}}const[Aa,Lp]=g.useState({}),Mn=g.useRef({}),[Pp,fn]=g.useState({}),dn=g.useRef({}),Ua=g.useRef({}),[Ba,zn]=g.useState({}),[jp,Ha]=g.useState({}),Wa=(c,w,x)=>c!=null&&c.id?c.id:`${x}:${w}`;g.useEffect(()=>{var w;if(!n)return;const c=((w=e.find(x=>x.session_id===n))==null?void 0:w.messages)||[];Ha(x=>{const k={};return c.forEach(($,D)=>{if($.role!=="user")return;const W=Wa($,D,n),V=($.content||"").split(/\r\n|\r|\n/).length>30;k[W]=V?x[W]??!0:!1}),k})},[e,n]);function Rp(c){Ha(w=>({...w,[c]:!(w[c]??!0)}))}const mr=Me.useCallback((c,w)=>{Lp(x=>{const k={...x,[c]:w};return Mn.current=k,k})},[]),On=g.useRef(null),Tp=g.useRef(!1),$p=g.useRef(null),_e=g.useRef(n);g.useEffect(()=>{_e.current=n},[n]);const ba=Me.useCallback(c=>{const w=new AbortController;return On.current={controller:w,sessionId:c},Ko(!0),w},[]),Zo=Me.useCallback(c=>{var w;((w=On.current)==null?void 0:w.controller)===c&&(On.current=null,Ko(!1))},[]),Mp=Me.useCallback(()=>{const c=On.current;c&&(On.current=null,c.controller.abort(),Ko(!1))},[]);g.useEffect(()=>()=>{var c;(c=On.current)==null||c.controller.abort()},[]);const Ut=g.useRef(null),[zp,Op]=g.useState(230),[yl,Va]=g.useState(!1),Fp=Me.useCallback(c=>{Va(!0)},[]),qo=Me.useCallback(()=>{Va(!1)},[]),ei=Me.useCallback(c=>{if(yl){const w=Math.max(230,Math.min(500,c.clientX));Op(w)}},[yl]);Me.useEffect(()=>(window.addEventListener("mousemove",ei),window.addEventListener("mouseup",qo),()=>{window.removeEventListener("mousemove",ei),window.removeEventListener("mouseup",qo)}),[ei,qo]),Me.useEffect(()=>{yl?document.body.classList.add("no-select"):document.body.classList.remove("no-select")},[yl]),Me.useEffect(()=>{const c=async w=>{const x=w.target.closest(".codeblock__copy");if(!x)return;const k=x.closest(".codeblock"),$=k==null?void 0:k.querySelector("pre > code");if($)try{await navigator.clipboard.writeText($.textContent||""),x.classList.add("copied"),setTimeout(()=>x.classList.remove("copied"),800)}catch(D){console.error("Copy failed:",D)}};return document.addEventListener("click",c),()=>document.removeEventListener("click",c)},[]),g.useEffect(()=>{window.electronAPI.getSettings().then(w=>{b(jy(w)),pe(w.colorScheme||"Default"),We(w.chatModel||""),ht(w.streamOutput||!1),Ma(w.scrollPositions||{}),ll(w.colorScheme||"Default")}).finally(()=>{Sp(!0)});const c=()=>{var w;l==="chats"&&((w=H.current)==null||w.focus())};return window.electronAPI.onWindowFocus(c),()=>{}},[l]),g.useEffect(()=>{if(!za||$a||!z||Oa.current)return;Oa.current=!0;let c=!1;const w=window.setTimeout(()=>{(async()=>{let x=!1;try{let k=await Ep();if(c)return;if(!(k!=null&&k.ollama_running)&&(k!=null&&k.can_manage_locally)){const W=window.confirm(`Ollama is not running at ${k.ollama_url}. Start it in the background now with "ollama serve"?`);if(c)return;if(W){x=!0,Qo(!0),Ve("Starting Ollama in the background...");const A=await fetch(`${z}/ollama/start`,{method:"POST"});if(k=await Xo(A),c)return}}const $=!(k!=null&&k.whisper_model_available),D=!!(k!=null&&k.ollama_running&&(k!=null&&k.can_manage_locally)&&!(k!=null&&k.embedding_model_available));if(($||D)&&(x=!0,Qo(!0),Ve($&&D?`Downloading Whisper ${(k==null?void 0:k.whisper_model)||"base"} and ${k.selected_embed_model}. This can take a while on first install.`:$?`Downloading Whisper ${(k==null?void 0:k.whisper_model)||"base"}. This can take a while on first install.`:`Downloading ${k.selected_embed_model} from Ollama. This can take a while on first install.`),await Cp(),c))return}catch(k){c||(console.warn("startup Ollama check failed",k),x&&window.alert(`Startup action failed: ${gl(k)}`))}finally{c||(Qo(!1),Ve(""))}})()},1200);return()=>{c=!0,window.clearTimeout(w)}},[z,$a,za]),g.useEffect(()=>{ll(Z)},[Z]);const Ip=c=>{!c||!z||fetch(`${z}/history?session_id=${encodeURIComponent(c)}`).then(w=>w.json()).then(w=>{t(x=>x.map(k=>k.session_id===c?{...k,messages:w.messages||[]}:k))}).catch(()=>{})};async function gr(){if(z)try{const w=await(await fetch(`${z}/libraries`)).json(),x=Array.isArray(w.libraries)?w.libraries:[];if(S(x),x.length===0){m(null);return}x.some(k=>k.slug===L)||m(x[0].slug)}catch(c){console.warn("Failed to load libraries",c)}}async function wl(){if(z)try{const w=await(await fetch(`${z}/jobs`)).json();E(Array.isArray(w.jobs)?w.jobs:[])}catch(c){console.warn("Failed to load library jobs",c)}}async function Qa(c=null){const x=(typeof c=="string"?c:M).trim();if(!x){B("Name is required.");return}try{B("");const k=await fetch(`${z}/libraries`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:x})});if(!k.ok){const D=await k.text();throw new Error(D||`HTTP ${k.status}`)}const $=await k.json();P(!1),O(""),await gr(),$!=null&&$.slug&&m($.slug)}catch(k){console.error("Failed to create library",k),B(String((k==null?void 0:k.message)||k))}}async function Dp(){S([]),E([]),m(null),v(null),q(!1),d({}),await gr(),await wl()}g.useEffect(()=>{z&&(Yo(!0),fetch(`${z}/sessions`).then(c=>c.json()).then(c=>{const w=c.sessions.map(x=>({...x,messages:[]}));t(w),w.length>0?r(w[0].session_id):r(null),Yo(!1)}).catch(()=>{Yo(!1)}))},[z]),g.useEffect(()=>{z&&(gr(),wl())},[z]),g.useEffect(()=>{try{localStorage.setItem(jc,JSON.stringify(f||{}))}catch{}},[f]),g.useEffect(()=>{if(!z)return;const c=setInterval(()=>{gr(),wl()},3e3);return()=>clearInterval(c)},[z,l,L]),g.useEffect(()=>{Ip(n)},[n,z]),g.useEffect(()=>{const c=new Set(y.map(w=>w.slug));d(w=>{let x=!1;const k={};for(const[$,D]of Object.entries(w||{}))c.has(D)?k[$]=D:x=!0;return x?k:w})},[y]);const ti=c=>{o(c)},Ap=c=>{bp(c)},Fn=g.useMemo(()=>{var c;return((c=e.find(w=>w.session_id===n))==null?void 0:c.messages)||[]},[n,e]),Sl=g.useMemo(()=>y.find(c=>c.slug===L)||null,[L,y]),Et=n&&f[n]||null,ot=g.useMemo(()=>y.find(c=>c.slug===Et)||null,[Et,y]),Ka=g.useMemo(()=>Et?C.some(c=>c.slug===Et&&(c.status==="queued"||c.status==="running")):!1,[Et,C]),ni=g.useMemo(()=>{var c,w;return ot?(c=ot.files)!=null&&c.length?(w=ot.states)!=null&&w.is_indexed?"":Ka?" (syncing)":" (needs sync)":" (empty)":""},[ot,Ka]);function Up(c){return c&&f[c]||null}function Ya(c){const w=Up(c);return w&&y.find(x=>x.slug===w)||null}function Ga(c){return c?C.some(w=>w.slug===c&&(w.status==="queued"||w.status==="running")):!1}function Ja(c,w){c&&d(x=>{const k={...x||{}};return w?k[c]=w:delete k[c],k})}function Bp(c){c&&d(w=>{let x=!1;const k={};for(const[$,D]of Object.entries(w||{})){if(D===c){x=!0;continue}k[$]=D}return x?k:w})}g.useEffect(()=>{if(!U)return;const c=w=>{var x;(x=R.current)!=null&&x.contains(w.target)||q(!1)};return document.addEventListener("mousedown",c),()=>document.removeEventListener("mousedown",c)},[U]),g.useEffect(()=>{q(!1)},[n,l]),g.useEffect(()=>{const c=n,w=l;return()=>{if(w==="chats"&&c){const x=typeof dn.current[c]=="number"?dn.current[c]:T.current?T.current.scrollTop:0;Ma(k=>{const $={...k,[c]:x};return window.electronAPI.updateSettings({scrollPositions:$}),$})}}},[n,l]),g.useEffect(()=>{const c=T.current;if(!c)return;const w=()=>{const{scrollTop:x,scrollHeight:k,clientHeight:$}=c,D=k-x-$<=Py;if(n){const W=Ua.current[n],A=typeof W=="number"&&xc.removeEventListener("scroll",w)},[n,mr]),g.useEffect(()=>{const c=n;c&&Aa[c]===!1&&zn(w=>{if(!(c in w))return w;const x={...w};return delete x[c],x})},[n,Aa]),g.useLayoutEffect(()=>{if(l!=="chats"||!n)return;const c=T.current;if(!c)return;Ut.current=null;const w=()=>{if(Ut.current===n)return;const W=typeof dn.current[n]=="number"?dn.current[n]:void 0,A=typeof W=="number"?W:hl[n];if(typeof A=="number"){c.scrollTop=A,Ut.current=n;return}Fn.length>0&&(c.scrollTop=c.scrollHeight,Ut.current=n)};w();const x=requestAnimationFrame(w),k=()=>{Ut.current!==n&&requestAnimationFrame(w)},$=new MutationObserver(k);$.observe(c,{childList:!0,subtree:!0});const D=new ResizeObserver(k);return D.observe(c),()=>{cancelAnimationFrame(x),$.disconnect(),D.disconnect()}},[n,l,Fn.length,hl]),g.useEffect(()=>{if(l!=="chats"||!n||Ut.current===n)return;const c=typeof dn.current[n]=="number"?dn.current[n]:void 0;typeof(typeof c=="number"?c:hl[n])!="number"&&Fn.length>0&&requestAnimationFrame(()=>{const x=T.current;x&&(x.scrollTop=x.scrollHeight,Ut.current=n)})},[Fn.length,n,l,hl]);const ri=(c="smooth",w=null)=>{const x=T.current;if(!x)return;const k=w??_e.current;_e.current===k&&(x.scrollTo({top:x.scrollHeight,behavior:c}),mr(k,!1))},In=(c,w="auto",x=null)=>{const k=T.current;if(!k)return;const $=x??_e.current;if(_e.current!==$)return;const D=document.getElementById(c);if(D){const W=Math.max(0,D.offsetTop-Ly);k.scrollTo({top:W,behavior:w})}},Hp=()=>{const c=_e.current,w=Ba[c];w&&(In(w,"smooth",c),zn(x=>{const{[c]:k,...$}=x;return $}))};async function Xa(){var $,D,W;if(Dt||!be.trim()||!ge)return;let c=n,w=!1;if(c){const A=e.find(V=>V.session_id===c);w=A&&A.name==="New Chat"&&A.messages.length===0}else{const A=await Za();await new Promise(V=>setTimeout(V,200)),c=A.session_id,w=!0}const x={role:"user",content:be.trim(),id:`msg-${Date.now()}-${Math.random()}`};Tp.current=!0,$p.current=c,mr(c,!1),_e.current===c&&(Ut.current=_e.current),bd.flushSync(()=>{t(A=>A.map(V=>V.session_id===c?{...V,messages:[...V.messages||[],x]}:V)),_("")}),requestAnimationFrame(()=>ri("auto",c));const k=ba(c);try{let A=[];try{A=[...((($=e.find(ke=>ke.session_id===c))==null?void 0:$.messages)||[]).slice(-8).map(ke=>({role:ke.role,content:ke.content||""})),{role:"user",content:x.content}]}catch{}let V=x.content,Le=[];const ve=[],Ze=Ya(c);if((D=Ze==null?void 0:Ze.states)!=null&&D.is_indexed)try{const Q=await Ia(Ze.slug,x.content,k.signal);Q.contextBlock&&ve.push(Q.contextBlock),Array.isArray(Q.sources)&&Le.push(...Q.sources)}catch(Q){if(At(Q))throw Q;console.warn("local library enrichment failed",Q)}if(pl)try{const fe=await(await fetch(`${z}/websearch`,{method:"POST",headers:{"Content-Type":"application/json"},signal:k.signal,body:JSON.stringify({prompt:x.content,model:ge,messages:A,history_limit:8,searx_url:hr||null,engines:Array.isArray(un)?un:null})})).json();fe&&typeof fe.context_block=="string"&&fe.context_block.trim()&&ve.push(fe.context_block.trim()),Array.isArray(fe==null?void 0:fe.sources)&&Le.push(...fe.sources)}catch(Q){if(At(Q))throw Q;console.warn("web search enrichment failed",Q)}if(Le=[...new Set(Le)],ve.length>0&&(V=`${x.content} +`)}`:W=null,kt){const K=`msg-${Date.now()}-${Math.random()}`;let Ct="";t(te=>te.map(he=>he.session_id===x?{...he,messages:[...he.messages||[],{id:K,role:"assistant",content:"",sources:A}]}:he));try{const te=await fetch(`${z}/sessions/${x}/regenerate`,{method:"POST",headers:{"Content-Type":"application/json"},signal:D.signal,body:JSON.stringify({index:c,model:ge,stream:!0,enriched_message:W,sources:A||[]})});if(!te.ok)throw new Error(`HTTP ${te.status}`);const he=(ke=te.body)==null?void 0:ke.getReader();if(!he)throw new Error("Missing response body");const Bt=new TextDecoder;let mt=!1;for(;;){const{value:pn,done:Gp}=await he.read();if(Gp)break;const Jp=Bt.decode(pn,{stream:!0});Ct+=Jp,cn(x,K,Ct),!mt&&_e.current!==x&&(mt=!0,fn(li=>({...li,[x]:K})),$n(li=>[...new Set([...li,x])]))}_e.current!==x?(fn(pn=>({...pn,[x]:K})),$n(pn=>[...new Set([...pn,x])])):Mn.current[x]?zn(pn=>({...pn,[x]:K})):requestAnimationFrame(()=>In(K,"smooth",x))}catch(te){if(At(te)){cn(x,K,Ct,{removeIfEmpty:!0});return}console.error(te),cn(x,K,`Error: ${gl(te)}`,{removeIfEmpty:!0});return}}else{const K=await fetch(`${z}/sessions/${x}/regenerate`,{method:"POST",headers:{"Content-Type":"application/json"},signal:D.signal,body:JSON.stringify({index:c,model:ge,stream:!1,enriched_message:W,sources:A||[]})});if(!K.ok)throw new Error(`HTTP ${K.status}`);const Ct=await K.json(),te=`msg-${Date.now()}`;t(he=>he.map(Bt=>Bt.session_id===x?{...Bt,messages:[...Bt.messages||[],{role:"assistant",content:Ct.reply,id:te,sources:A}]}:Bt)),_e.current!==x?(fn(he=>({...he,[x]:te})),$n(he=>[...new Set([...he,x])])):Mn.current[x]?zn(he=>({...he,[x]:te})):requestAnimationFrame(()=>In(te,"smooth",x))}}catch(J){At(J)||console.error(J)}finally{Zo(D)}}const[Aa,Lp]=g.useState({}),Mn=g.useRef({}),[Pp,fn]=g.useState({}),dn=g.useRef({}),Ua=g.useRef({}),[Ba,zn]=g.useState({}),[jp,Ha]=g.useState({}),Wa=(c,w,x)=>c!=null&&c.id?c.id:`${x}:${w}`;g.useEffect(()=>{var w;if(!n)return;const c=((w=e.find(x=>x.session_id===n))==null?void 0:w.messages)||[];Ha(x=>{const k={};return c.forEach(($,D)=>{if($.role!=="user")return;const W=Wa($,D,n),V=($.content||"").split(/\r\n|\r|\n/).length>30;k[W]=V?x[W]??!0:!1}),k})},[e,n]);function Rp(c){Ha(w=>({...w,[c]:!(w[c]??!0)}))}const mr=Me.useCallback((c,w)=>{Lp(x=>{const k={...x,[c]:w};return Mn.current=k,k})},[]),On=g.useRef(null),Tp=g.useRef(!1),$p=g.useRef(null),_e=g.useRef(n);g.useEffect(()=>{_e.current=n},[n]);const ba=Me.useCallback(c=>{const w=new AbortController;return On.current={controller:w,sessionId:c},Ko(!0),w},[]),Zo=Me.useCallback(c=>{var w;((w=On.current)==null?void 0:w.controller)===c&&(On.current=null,Ko(!1))},[]),Mp=Me.useCallback(()=>{const c=On.current;c&&(On.current=null,c.controller.abort(),Ko(!1))},[]);g.useEffect(()=>()=>{var c;(c=On.current)==null||c.controller.abort()},[]);const Ut=g.useRef(null),[zp,Op]=g.useState(230),[yl,Va]=g.useState(!1),Fp=Me.useCallback(c=>{Va(!0)},[]),qo=Me.useCallback(()=>{Va(!1)},[]),ei=Me.useCallback(c=>{if(yl){const w=Math.max(230,Math.min(500,c.clientX));Op(w)}},[yl]);Me.useEffect(()=>(window.addEventListener("mousemove",ei),window.addEventListener("mouseup",qo),()=>{window.removeEventListener("mousemove",ei),window.removeEventListener("mouseup",qo)}),[ei,qo]),Me.useEffect(()=>{yl?document.body.classList.add("no-select"):document.body.classList.remove("no-select")},[yl]),Me.useEffect(()=>{const c=async w=>{const x=w.target.closest(".codeblock__copy");if(!x)return;const k=x.closest(".codeblock"),$=k==null?void 0:k.querySelector("pre > code");if($)try{await navigator.clipboard.writeText($.textContent||""),x.classList.add("copied"),setTimeout(()=>x.classList.remove("copied"),800)}catch(D){console.error("Copy failed:",D)}};return document.addEventListener("click",c),()=>document.removeEventListener("click",c)},[]),g.useEffect(()=>{window.electronAPI.getSettings().then(w=>{b(Ry(w)),pe(w.colorScheme||"Default"),We(w.chatModel||""),ht(w.streamOutput||!1),Ma(w.scrollPositions||{}),ll(w.colorScheme||"Default")}).finally(()=>{Sp(!0)});const c=()=>{var w;l==="chats"&&((w=H.current)==null||w.focus())};return window.electronAPI.onWindowFocus(c),()=>{}},[l]),g.useEffect(()=>{if(!za||$a||!z||Oa.current)return;Oa.current=!0;let c=!1;const w=window.setTimeout(()=>{(async()=>{let x=!1;try{let k=await Ep();if(c)return;if(!(k!=null&&k.ollama_running)&&(k!=null&&k.can_manage_locally)){const W=window.confirm(`Ollama is not running at ${k.ollama_url}. Start it in the background now with "ollama serve"?`);if(c)return;if(W){x=!0,Qo(!0),Ve("Starting Ollama in the background...");const A=await fetch(`${z}/ollama/start`,{method:"POST"});if(k=await Xo(A),c)return}}const $=!(k!=null&&k.whisper_model_available),D=!!(k!=null&&k.ollama_running&&(k!=null&&k.can_manage_locally)&&!(k!=null&&k.embedding_model_available));if(($||D)&&(x=!0,Qo(!0),Ve($&&D?`Downloading Whisper ${(k==null?void 0:k.whisper_model)||"base"} and ${k.selected_embed_model}. This can take a while on first install.`:$?`Downloading Whisper ${(k==null?void 0:k.whisper_model)||"base"}. This can take a while on first install.`:`Downloading ${k.selected_embed_model} from Ollama. This can take a while on first install.`),await Cp(),c))return}catch(k){c||(console.warn("startup Ollama check failed",k),x&&window.alert(`Startup action failed: ${gl(k)}`))}finally{c||(Qo(!1),Ve(""))}})()},1200);return()=>{c=!0,window.clearTimeout(w)}},[z,$a,za]),g.useEffect(()=>{ll(Z)},[Z]);const Ip=c=>{!c||!z||fetch(`${z}/history?session_id=${encodeURIComponent(c)}`).then(w=>w.json()).then(w=>{t(x=>x.map(k=>k.session_id===c?{...k,messages:w.messages||[]}:k))}).catch(()=>{})};async function gr(){if(z)try{const w=await(await fetch(`${z}/libraries`)).json(),x=Array.isArray(w.libraries)?w.libraries:[];if(S(x),x.length===0){m(null);return}x.some(k=>k.slug===L)||m(x[0].slug)}catch(c){console.warn("Failed to load libraries",c)}}async function wl(){if(z)try{const w=await(await fetch(`${z}/jobs`)).json();E(Array.isArray(w.jobs)?w.jobs:[])}catch(c){console.warn("Failed to load library jobs",c)}}async function Qa(c=null){const x=(typeof c=="string"?c:M).trim();if(!x){B("Name is required.");return}try{B("");const k=await fetch(`${z}/libraries`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:x})});if(!k.ok){const D=await k.text();throw new Error(D||`HTTP ${k.status}`)}const $=await k.json();P(!1),O(""),await gr(),$!=null&&$.slug&&m($.slug)}catch(k){console.error("Failed to create library",k),B(String((k==null?void 0:k.message)||k))}}async function Dp(){S([]),E([]),m(null),v(null),q(!1),d({}),await gr(),await wl()}g.useEffect(()=>{z&&(Yo(!0),fetch(`${z}/sessions`).then(c=>c.json()).then(c=>{const w=c.sessions.map(x=>({...x,messages:[]}));t(w),w.length>0?r(w[0].session_id):r(null),Yo(!1)}).catch(()=>{Yo(!1)}))},[z]),g.useEffect(()=>{z&&(gr(),wl())},[z]),g.useEffect(()=>{try{localStorage.setItem(jc,JSON.stringify(f||{}))}catch{}},[f]),g.useEffect(()=>{if(!z)return;const c=setInterval(()=>{gr(),wl()},3e3);return()=>clearInterval(c)},[z,l,L]),g.useEffect(()=>{Ip(n)},[n,z]),g.useEffect(()=>{const c=new Set(y.map(w=>w.slug));d(w=>{let x=!1;const k={};for(const[$,D]of Object.entries(w||{}))c.has(D)?k[$]=D:x=!0;return x?k:w})},[y]);const ti=c=>{o(c)},Ap=c=>{bp(c)},Fn=g.useMemo(()=>{var c;return((c=e.find(w=>w.session_id===n))==null?void 0:c.messages)||[]},[n,e]),Sl=g.useMemo(()=>y.find(c=>c.slug===L)||null,[L,y]),Et=n&&f[n]||null,ot=g.useMemo(()=>y.find(c=>c.slug===Et)||null,[Et,y]),Ka=g.useMemo(()=>Et?C.some(c=>c.slug===Et&&(c.status==="queued"||c.status==="running")):!1,[Et,C]),ni=g.useMemo(()=>{var c,w;return ot?(c=ot.files)!=null&&c.length?(w=ot.states)!=null&&w.is_indexed?"":Ka?" (syncing)":" (needs sync)":" (empty)":""},[ot,Ka]);function Up(c){return c&&f[c]||null}function Ya(c){const w=Up(c);return w&&y.find(x=>x.slug===w)||null}function Ga(c){return c?C.some(w=>w.slug===c&&(w.status==="queued"||w.status==="running")):!1}function Ja(c,w){c&&d(x=>{const k={...x||{}};return w?k[c]=w:delete k[c],k})}function Bp(c){c&&d(w=>{let x=!1;const k={};for(const[$,D]of Object.entries(w||{})){if(D===c){x=!0;continue}k[$]=D}return x?k:w})}g.useEffect(()=>{if(!U)return;const c=w=>{var x;(x=R.current)!=null&&x.contains(w.target)||q(!1)};return document.addEventListener("mousedown",c),()=>document.removeEventListener("mousedown",c)},[U]),g.useEffect(()=>{q(!1)},[n,l]),g.useEffect(()=>{const c=n,w=l;return()=>{if(w==="chats"&&c){const x=typeof dn.current[c]=="number"?dn.current[c]:T.current?T.current.scrollTop:0;Ma(k=>{const $={...k,[c]:x};return window.electronAPI.updateSettings({scrollPositions:$}),$})}}},[n,l]),g.useEffect(()=>{const c=T.current;if(!c)return;const w=()=>{const{scrollTop:x,scrollHeight:k,clientHeight:$}=c,D=k-x-$<=jy;if(n){const W=Ua.current[n],A=typeof W=="number"&&xc.removeEventListener("scroll",w)},[n,mr]),g.useEffect(()=>{const c=n;c&&Aa[c]===!1&&zn(w=>{if(!(c in w))return w;const x={...w};return delete x[c],x})},[n,Aa]),g.useLayoutEffect(()=>{if(l!=="chats"||!n)return;const c=T.current;if(!c)return;Ut.current=null;const w=()=>{if(Ut.current===n)return;const W=typeof dn.current[n]=="number"?dn.current[n]:void 0,A=typeof W=="number"?W:hl[n];if(typeof A=="number"){c.scrollTop=A,Ut.current=n;return}Fn.length>0&&(c.scrollTop=c.scrollHeight,Ut.current=n)};w();const x=requestAnimationFrame(w),k=()=>{Ut.current!==n&&requestAnimationFrame(w)},$=new MutationObserver(k);$.observe(c,{childList:!0,subtree:!0});const D=new ResizeObserver(k);return D.observe(c),()=>{cancelAnimationFrame(x),$.disconnect(),D.disconnect()}},[n,l,Fn.length,hl]),g.useEffect(()=>{if(l!=="chats"||!n||Ut.current===n)return;const c=typeof dn.current[n]=="number"?dn.current[n]:void 0;typeof(typeof c=="number"?c:hl[n])!="number"&&Fn.length>0&&requestAnimationFrame(()=>{const x=T.current;x&&(x.scrollTop=x.scrollHeight,Ut.current=n)})},[Fn.length,n,l,hl]);const ri=(c="smooth",w=null)=>{const x=T.current;if(!x)return;const k=w??_e.current;_e.current===k&&(x.scrollTo({top:x.scrollHeight,behavior:c}),mr(k,!1))},In=(c,w="auto",x=null)=>{const k=T.current;if(!k)return;const $=x??_e.current;if(_e.current!==$)return;const D=document.getElementById(c);if(D){const W=Math.max(0,D.offsetTop-Py);k.scrollTo({top:W,behavior:w})}},Hp=()=>{const c=_e.current,w=Ba[c];w&&(In(w,"smooth",c),zn(x=>{const{[c]:k,...$}=x;return $}))};async function Xa(){var $,D,W;if(Dt||!be.trim()||!ge)return;let c=n,w=!1;if(c){const A=e.find(V=>V.session_id===c);w=A&&A.name==="New Chat"&&A.messages.length===0}else{const A=await Za();await new Promise(V=>setTimeout(V,200)),c=A.session_id,w=!0}const x={role:"user",content:be.trim(),id:`msg-${Date.now()}-${Math.random()}`};Tp.current=!0,$p.current=c,mr(c,!1),_e.current===c&&(Ut.current=_e.current),bd.flushSync(()=>{t(A=>A.map(V=>V.session_id===c?{...V,messages:[...V.messages||[],x]}:V)),_("")}),requestAnimationFrame(()=>ri("auto",c));const k=ba(c);try{let A=[];try{A=[...((($=e.find(ke=>ke.session_id===c))==null?void 0:$.messages)||[]).slice(-8).map(ke=>({role:ke.role,content:ke.content||""})),{role:"user",content:x.content}]}catch{}let V=x.content,Le=[];const ve=[],Ze=Ya(c);if((D=Ze==null?void 0:Ze.states)!=null&&D.is_indexed)try{const Q=await Ia(Ze.slug,x.content,k.signal);Q.contextBlock&&ve.push(Q.contextBlock),Array.isArray(Q.sources)&&Le.push(...Q.sources)}catch(Q){if(At(Q))throw Q;console.warn("local library enrichment failed",Q)}if(pl)try{const fe=await(await fetch(`${z}/websearch`,{method:"POST",headers:{"Content-Type":"application/json"},signal:k.signal,body:JSON.stringify({prompt:x.content,model:ge,messages:A,history_limit:8,searx_url:hr||null,engines:Array.isArray(un)?un:null})})).json();fe&&typeof fe.context_block=="string"&&fe.context_block.trim()&&ve.push(fe.context_block.trim()),Array.isArray(fe==null?void 0:fe.sources)&&Le.push(...fe.sources)}catch(Q){if(At(Q))throw Q;console.warn("web search enrichment failed",Q)}if(Le=[...new Set(Le)],ve.length>0&&(V=`${x.content} ${ve.join(` -`)}`),kt){const Q=`msg-${Date.now()}-${Math.random()}`;let fe="";const ke={role:"assistant",content:"",id:Q,sources:Le};t(J=>J.map(oe=>oe.session_id===c?{...oe,messages:[...oe.messages||[],ke]}:oe));try{const J=await fetch(`${z}/chat`,{method:"POST",headers:{"Content-Type":"application/json"},signal:k.signal,body:JSON.stringify({session_id:c,model:ge,message:x.content,enriched_message:ve.length>0?V:null,stream:!0,sources:Le||[]})});if(!J.ok)throw new Error(`HTTP ${J.status}`);const oe=(W=J.body)==null?void 0:W.getReader();if(!oe)throw new Error("Missing response body");const K=new TextDecoder;let Ct=!1;for(;;){const{value:te,done:he}=await oe.read();if(he){cn(c,Q,fe),_e.current===c?Mn.current[c]?zn(mt=>({...mt,[c]:Q})):requestAnimationFrame(()=>In(Q,"smooth",c)):(fn(mt=>({...mt,[c]:Q})),$n(mt=>[...new Set([...mt,c])]));break}const Bt=K.decode(te,{stream:!0});fe+=Bt,cn(c,Q,fe),_e.current===c&&!Mn.current[c]&&ri("auto",c),_e.current!==c&&!Ct&&(fn(mt=>({...mt,[c]:Q})),Ct=!0)}}catch(J){if(At(J)){cn(c,Q,fe,{removeIfEmpty:!0});return}console.error("Failed to send message:",J),cn(c,Q,"Error: "+gl(J),{removeIfEmpty:!0});return}}else{const Q=await fetch(`${z}/chat`,{method:"POST",headers:{"Content-Type":"application/json"},signal:k.signal,body:JSON.stringify({session_id:c,model:ge,message:x.content,enriched_message:ve.length>0?V:null,stream:!1,sources:Le||[]})});if(!Q.ok)throw new Error(`HTTP ${Q.status}`);const fe=await Q.json(),ke=`msg-${Date.now()}`,J={role:"assistant",content:fe.reply,id:ke,sources:Le};t(oe=>oe.map(K=>K.session_id===c?{...K,messages:[...K.messages||[],J]}:K)),ke&&(_e.current===c?Mn.current[c]?zn(oe=>({...oe,[c]:ke})):requestAnimationFrame(()=>In(ke,"smooth",c)):fn(oe=>({...oe,[c]:ke})))}_e.current!==c&&$n(Q=>[...new Set([...Q,c])]),w&&fetch(`${z}/generate-title`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:c,message:x.content,model:ge})}).then(Q=>Q.json()).then(Q=>{const fe=Q.title.replace(/[\s\S]*?<\/think(?:ing)?>/i,"").trim();t(ke=>ke.map(J=>J.session_id===c?{...J,name:fe}:J))})}catch(A){if(At(A)){Zo(k);return}console.error("Failed to send message:",A);const V={role:"assistant",content:"Error: "+gl(A),id:`msg-${Date.now()}-${Math.random()}`};t(Le=>Le.map(ve=>ve.session_id===c?{...ve,messages:[...ve.messages,V]}:ve))}finally{Zo(k)}}function Wp(){yp(c=>!c)}async function Za(){var $;const c="sess-"+Math.random().toString(36).slice(2)+Date.now().toString(36),x=await(await fetch(`${z}/sessions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:c})})).json(),k={...x,messages:[]};return t(D=>[k,...D]),r(x.session_id),($=H.current)==null||$.focus(),x}function bp(c){r(c),$n(x=>x.filter(k=>k!==c));const w=Pp[c];w&&requestAnimationFrame(()=>{let x=12;const k=()=>{if(!T.current)return;let D=document.getElementById(w);if(!D){const W=e.find(A=>A.session_id===c);if(W&&Array.isArray(W.messages))for(let A=W.messages.length-1;A>=0;A--){const V=W.messages[A];if(V.role==="assistant"&&V.id){D=document.getElementById(V.id);break}}}D?(In(D.id,"smooth",c),fn(W=>{const{[c]:A,...V}=W;return V})):x-- >0&&requestAnimationFrame(k)};requestAnimationFrame(k)})}function Vp(c,w){fetch(`${z}/sessions/${c}/rename`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:w})}).then(()=>{t(x=>x.map(k=>k.session_id===c?{...k,name:w}:k)),u(null)})}function Qp(c,w){const x=(w||"").trim(),k=y.find($=>$.slug===c);if(!k){v(null);return}if(!x||x===k.name){v(null);return}fetch(`${z}/libraries/${c}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:x})}).then(()=>{S($=>$.map(D=>D.slug===c?{...D,name:x}:D)),v(null)})}function qa(c){fetch(`${z}/sessions/${c}`,{method:"DELETE"}).then(()=>{const w=e.filter(x=>x.session_id!==c);t(w),d(x=>{const k={...x||{}};return delete k[c],k}),n===c&&r(w.length>0?w[0].session_id:null)})}function Kp(c){fetch(`${z}/libraries/${c}`,{method:"DELETE"}).then(async w=>{var k;if(!w.ok){const $=await w.text();throw new Error($||`HTTP ${w.status}`)}const x=y.filter($=>$.slug!==c);S(x),E($=>$.filter(D=>D.slug!==c)),v($=>$===c?null:$),L===c&&m(((k=x[0])==null?void 0:k.slug)||null),Bp(c)}).catch(w=>{console.error("Failed to delete library",w)})}g.useEffect(()=>{const c=e.filter(w=>w.name==="New Chat"&&w.session_id!==n&&w.messages.length===0);c.length>0&&c.forEach(w=>{qa(w.session_id)})},[n,e,z]);const Yp=c=>{var x;window.getSelection().toString().length>0||document.activeElement!==H.current&&(c.target.closest(".msg")||(x=H.current)==null||x.focus())};return p.jsxs("div",{className:"app",style:{gridTemplateColumns:`${zp}px 1fr`},children:[p.jsxs("div",{className:"sidebar",children:[p.jsxs("div",{className:"sidebar-header",children:[p.jsx("div",{className:`sidebar-tab ${l==="chats"?"active":""}`,onClick:()=>ti("chats"),children:"Chats"}),p.jsx("div",{className:`sidebar-tab ${l==="dbs"?"active":""}`,onClick:()=>ti("dbs"),children:"DBs"}),p.jsx("div",{className:`sidebar-tab ${l==="settings"?"active":""}`,onClick:()=>ti("settings"),children:"Settings"})]}),p.jsxs("div",{className:"sidebar-content",children:[l==="chats"&&p.jsx("div",{className:"chat-list",children:e.map(c=>p.jsx("div",{className:`chat-item ${c.session_id===n?"active":""}`,onClick:()=>Ap(c.session_id),children:a===c.session_id?p.jsx("input",{type:"text",className:"rename-input",defaultValue:c.name,onBlur:()=>u(null),onKeyDown:w=>{w.key==="Enter"?Vp(c.session_id,w.target.value):w.key==="Escape"&&u(null)},autoFocus:!0}):p.jsxs(p.Fragment,{children:[p.jsx("span",{children:c.name}),p.jsxs("div",{className:"chat-item-buttons",children:[wp.includes(c.session_id)&&p.jsx("div",{className:"unread-dot"}),p.jsx("button",{className:"icon-button",onClick:w=>{w.stopPropagation(),u(c.session_id)},children:p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"feather feather-edit-2",children:p.jsx("path",{d:"M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"})})}),p.jsx("button",{className:"icon-button",onClick:w=>{w.stopPropagation(),qa(c.session_id)},children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"feather feather-x",children:[p.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),p.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]})]})},c.session_id))}),l==="dbs"&&p.jsx("div",{className:"db-list",children:y.length===0?p.jsx("div",{className:"empty-list-message",children:"No databases yet."}):y.map(c=>p.jsx("div",{className:`chat-item ${c.slug===L?"active":""}`,onClick:()=>m(c.slug),children:h===c.slug?p.jsx("input",{type:"text",className:"rename-input",defaultValue:c.name,onBlur:()=>v(null),onKeyDown:w=>{w.key==="Enter"?Qp(c.slug,w.target.value):w.key==="Escape"&&v(null)},autoFocus:!0}):p.jsxs(p.Fragment,{children:[p.jsx("span",{children:c.name}),p.jsxs("div",{className:"chat-item-buttons",children:[Et===c.slug&&p.jsx("div",{className:"db-active-badge",children:"Chat"}),Ga(c.slug)&&p.jsx("div",{className:"db-active-badge",children:"Syncing"}),p.jsx("button",{className:"icon-button",onClick:w=>{w.stopPropagation(),v(c.slug)},children:p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"feather feather-edit-2",children:p.jsx("path",{d:"M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"})})}),p.jsx("button",{className:"icon-button",onClick:w=>{w.stopPropagation(),Kp(c.slug)},children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"feather feather-x",children:[p.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),p.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]})]})},c.slug))}),l==="settings"&&p.jsxs("div",{className:"settings-list",children:[p.jsx("div",{className:`settings-item ${i==="General"?"active":""}`,onClick:()=>s("General"),children:"General"}),p.jsx("div",{className:`settings-item ${i==="Interface"?"active":""}`,onClick:()=>s("Interface"),children:"Interface"}),p.jsx("div",{className:`settings-item ${i==="Websearch"?"active":""}`,onClick:()=>s("Websearch"),children:"Websearch"})]})]}),l!=="settings"&&p.jsxs("div",{className:"sidebar-footer",children:[l==="chats"&&p.jsx("button",{className:"button new-chat-button",onClick:Za,children:"New Chat"}),l==="dbs"&&(N?p.jsxs("div",{className:"new-db-form",children:[p.jsx("input",{type:"text",className:"rename-input",value:M,onChange:c=>O(c.target.value),onKeyDown:c=>{c.key==="Enter"?Qa():c.key==="Escape"&&(P(!1),O(""),B(""))},placeholder:"Database name",autoFocus:!0}),F&&p.jsx("div",{className:"form-error",children:F}),p.jsxs("div",{className:"new-db-actions",children:[p.jsx("button",{className:"button new-db-button",onClick:()=>Qa(),children:"Create"}),p.jsx("button",{className:"button ghost",onClick:()=>{P(!1),O(""),B("")},children:"Cancel"})]})]}):p.jsx("button",{className:"button new-db-button",onClick:()=>{P(!0),B("")},children:"New Database"}))]}),p.jsx("div",{className:"resizer",onMouseDown:Fp})]}),p.jsxs("div",{className:"main-content",children:[Rn&&p.jsxs("div",{className:"startup-task-banner",role:"status","aria-live":"polite",children:[Tn&&p.jsx("div",{className:"spinner startup-task-banner__spinner"}),p.jsx("div",{className:"startup-task-banner__text",children:Rn})]}),l==="chats"&&p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:"header",children:[p.jsxs("strong",{children:["Chat - ",((eu=e.find(c=>c.session_id===n))==null?void 0:eu.name)||"New Chat"]}),ot&&p.jsx("span",{className:"header-subtle",children:`DB: ${ot.name}${ni}`})]}),p.jsx("div",{className:"chat",ref:T,onClick:Yp,children:Fn.map((c,w)=>{const x=c.role==="user"&&xp===w;return p.jsx("div",{id:c.id,className:"msg "+(c.role==="user"?"user":"assistant")+(x?" editing":""),children:c.role==="assistant"?p.jsxs("div",{className:"assistant-message-wrapper",children:[p.jsx(_y,{content:c.content,streamOutput:kt,sources:c.sources}),!Dt&&p.jsxs("div",{className:"message-options-bar assistant-options",children:[p.jsx("button",{className:"icon-button",title:"Copy message",onClick:()=>Fa(c),children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[p.jsx("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),p.jsx("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})}),p.jsx("button",{className:"icon-button",title:"Regenerate response",onClick:()=>Da(w),children:p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:p.jsx("path",{d:"M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.3"})})})]})]}):p.jsxs("div",{className:"user-message-wrapper",children:[x?p.jsxs("div",{className:"msg-content msg-content--user editing",children:[p.jsx("div",{className:"user-edit-shadow","aria-hidden":"true",children:Jo}),p.jsx(Sc,{className:"edit-message-input edit-overlay",value:Jo,onChange:k=>ml(k.target.value),onBlur:vl,onKeyDown:k=>{k.key==="Escape"&&(k.preventDefault(),vl()),k.key==="Enter"&&!k.shiftKey&&(k.preventDefault(),_p(w))},autoFocus:!0,minRows:1})]}):(()=>{const k=c.content||"",$=k.split(/\r\n|\r|\n/),D=$.length>30,W=Wa(c,w,n),A=D?jp[W]??!0:!1,V=A?$.slice(0,30).join(` +`)}`),kt){const Q=`msg-${Date.now()}-${Math.random()}`;let fe="";const ke={role:"assistant",content:"",id:Q,sources:Le};t(J=>J.map(oe=>oe.session_id===c?{...oe,messages:[...oe.messages||[],ke]}:oe));try{const J=await fetch(`${z}/chat`,{method:"POST",headers:{"Content-Type":"application/json"},signal:k.signal,body:JSON.stringify({session_id:c,model:ge,message:x.content,enriched_message:ve.length>0?V:null,stream:!0,sources:Le||[]})});if(!J.ok)throw new Error(`HTTP ${J.status}`);const oe=(W=J.body)==null?void 0:W.getReader();if(!oe)throw new Error("Missing response body");const K=new TextDecoder;let Ct=!1;for(;;){const{value:te,done:he}=await oe.read();if(he){cn(c,Q,fe),_e.current===c?Mn.current[c]?zn(mt=>({...mt,[c]:Q})):requestAnimationFrame(()=>In(Q,"smooth",c)):(fn(mt=>({...mt,[c]:Q})),$n(mt=>[...new Set([...mt,c])]));break}const Bt=K.decode(te,{stream:!0});fe+=Bt,cn(c,Q,fe),_e.current===c&&!Mn.current[c]&&ri("auto",c),_e.current!==c&&!Ct&&(fn(mt=>({...mt,[c]:Q})),Ct=!0)}}catch(J){if(At(J)){cn(c,Q,fe,{removeIfEmpty:!0});return}console.error("Failed to send message:",J),cn(c,Q,"Error: "+gl(J),{removeIfEmpty:!0});return}}else{const Q=await fetch(`${z}/chat`,{method:"POST",headers:{"Content-Type":"application/json"},signal:k.signal,body:JSON.stringify({session_id:c,model:ge,message:x.content,enriched_message:ve.length>0?V:null,stream:!1,sources:Le||[]})});if(!Q.ok)throw new Error(`HTTP ${Q.status}`);const fe=await Q.json(),ke=`msg-${Date.now()}`,J={role:"assistant",content:fe.reply,id:ke,sources:Le};t(oe=>oe.map(K=>K.session_id===c?{...K,messages:[...K.messages||[],J]}:K)),ke&&(_e.current===c?Mn.current[c]?zn(oe=>({...oe,[c]:ke})):requestAnimationFrame(()=>In(ke,"smooth",c)):fn(oe=>({...oe,[c]:ke})))}_e.current!==c&&$n(Q=>[...new Set([...Q,c])]),w&&fetch(`${z}/generate-title`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:c,message:x.content,model:ge})}).then(Q=>Q.json()).then(Q=>{const fe=_y(Q.title);t(ke=>ke.map(J=>J.session_id===c?{...J,name:fe}:J))})}catch(A){if(At(A)){Zo(k);return}console.error("Failed to send message:",A);const V={role:"assistant",content:"Error: "+gl(A),id:`msg-${Date.now()}-${Math.random()}`};t(Le=>Le.map(ve=>ve.session_id===c?{...ve,messages:[...ve.messages,V]}:ve))}finally{Zo(k)}}function Wp(){yp(c=>!c)}async function Za(){var $;const c="sess-"+Math.random().toString(36).slice(2)+Date.now().toString(36),x=await(await fetch(`${z}/sessions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:c})})).json(),k={...x,messages:[]};return t(D=>[k,...D]),r(x.session_id),($=H.current)==null||$.focus(),x}function bp(c){r(c),$n(x=>x.filter(k=>k!==c));const w=Pp[c];w&&requestAnimationFrame(()=>{let x=12;const k=()=>{if(!T.current)return;let D=document.getElementById(w);if(!D){const W=e.find(A=>A.session_id===c);if(W&&Array.isArray(W.messages))for(let A=W.messages.length-1;A>=0;A--){const V=W.messages[A];if(V.role==="assistant"&&V.id){D=document.getElementById(V.id);break}}}D?(In(D.id,"smooth",c),fn(W=>{const{[c]:A,...V}=W;return V})):x-- >0&&requestAnimationFrame(k)};requestAnimationFrame(k)})}function Vp(c,w){fetch(`${z}/sessions/${c}/rename`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:w})}).then(()=>{t(x=>x.map(k=>k.session_id===c?{...k,name:w}:k)),u(null)})}function Qp(c,w){const x=(w||"").trim(),k=y.find($=>$.slug===c);if(!k){v(null);return}if(!x||x===k.name){v(null);return}fetch(`${z}/libraries/${c}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:x})}).then(()=>{S($=>$.map(D=>D.slug===c?{...D,name:x}:D)),v(null)})}function qa(c){fetch(`${z}/sessions/${c}`,{method:"DELETE"}).then(()=>{const w=e.filter(x=>x.session_id!==c);t(w),d(x=>{const k={...x||{}};return delete k[c],k}),n===c&&r(w.length>0?w[0].session_id:null)})}function Kp(c){fetch(`${z}/libraries/${c}`,{method:"DELETE"}).then(async w=>{var k;if(!w.ok){const $=await w.text();throw new Error($||`HTTP ${w.status}`)}const x=y.filter($=>$.slug!==c);S(x),E($=>$.filter(D=>D.slug!==c)),v($=>$===c?null:$),L===c&&m(((k=x[0])==null?void 0:k.slug)||null),Bp(c)}).catch(w=>{console.error("Failed to delete library",w)})}g.useEffect(()=>{const c=e.filter(w=>w.name==="New Chat"&&w.session_id!==n&&w.messages.length===0);c.length>0&&c.forEach(w=>{qa(w.session_id)})},[n,e,z]);const Yp=c=>{var x;window.getSelection().toString().length>0||document.activeElement!==H.current&&(c.target.closest(".msg")||(x=H.current)==null||x.focus())};return p.jsxs("div",{className:"app",style:{gridTemplateColumns:`${zp}px 1fr`},children:[p.jsxs("div",{className:"sidebar",children:[p.jsxs("div",{className:"sidebar-header",children:[p.jsx("div",{className:`sidebar-tab ${l==="chats"?"active":""}`,onClick:()=>ti("chats"),children:"Chats"}),p.jsx("div",{className:`sidebar-tab ${l==="dbs"?"active":""}`,onClick:()=>ti("dbs"),children:"DBs"}),p.jsx("div",{className:`sidebar-tab ${l==="settings"?"active":""}`,onClick:()=>ti("settings"),children:"Settings"})]}),p.jsxs("div",{className:"sidebar-content",children:[l==="chats"&&p.jsx("div",{className:"chat-list",children:e.map(c=>p.jsx("div",{className:`chat-item ${c.session_id===n?"active":""}`,onClick:()=>Ap(c.session_id),children:a===c.session_id?p.jsx("input",{type:"text",className:"rename-input",defaultValue:c.name,onBlur:()=>u(null),onKeyDown:w=>{w.key==="Enter"?Vp(c.session_id,w.target.value):w.key==="Escape"&&u(null)},autoFocus:!0}):p.jsxs(p.Fragment,{children:[p.jsx("span",{children:c.name}),p.jsxs("div",{className:"chat-item-buttons",children:[wp.includes(c.session_id)&&p.jsx("div",{className:"unread-dot"}),p.jsx("button",{className:"icon-button",onClick:w=>{w.stopPropagation(),u(c.session_id)},children:p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"feather feather-edit-2",children:p.jsx("path",{d:"M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"})})}),p.jsx("button",{className:"icon-button",onClick:w=>{w.stopPropagation(),qa(c.session_id)},children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"feather feather-x",children:[p.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),p.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]})]})},c.session_id))}),l==="dbs"&&p.jsx("div",{className:"db-list",children:y.length===0?p.jsx("div",{className:"empty-list-message",children:"No databases yet."}):y.map(c=>p.jsx("div",{className:`chat-item ${c.slug===L?"active":""}`,onClick:()=>m(c.slug),children:h===c.slug?p.jsx("input",{type:"text",className:"rename-input",defaultValue:c.name,onBlur:()=>v(null),onKeyDown:w=>{w.key==="Enter"?Qp(c.slug,w.target.value):w.key==="Escape"&&v(null)},autoFocus:!0}):p.jsxs(p.Fragment,{children:[p.jsx("span",{children:c.name}),p.jsxs("div",{className:"chat-item-buttons",children:[Et===c.slug&&p.jsx("div",{className:"db-active-badge",children:"Chat"}),Ga(c.slug)&&p.jsx("div",{className:"db-active-badge",children:"Syncing"}),p.jsx("button",{className:"icon-button",onClick:w=>{w.stopPropagation(),v(c.slug)},children:p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"feather feather-edit-2",children:p.jsx("path",{d:"M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"})})}),p.jsx("button",{className:"icon-button",onClick:w=>{w.stopPropagation(),Kp(c.slug)},children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"feather feather-x",children:[p.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),p.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]})]})},c.slug))}),l==="settings"&&p.jsxs("div",{className:"settings-list",children:[p.jsx("div",{className:`settings-item ${i==="General"?"active":""}`,onClick:()=>s("General"),children:"General"}),p.jsx("div",{className:`settings-item ${i==="Interface"?"active":""}`,onClick:()=>s("Interface"),children:"Interface"}),p.jsx("div",{className:`settings-item ${i==="Websearch"?"active":""}`,onClick:()=>s("Websearch"),children:"Websearch"})]})]}),l!=="settings"&&p.jsxs("div",{className:"sidebar-footer",children:[l==="chats"&&p.jsx("button",{className:"button new-chat-button",onClick:Za,children:"New Chat"}),l==="dbs"&&(N?p.jsxs("div",{className:"new-db-form",children:[p.jsx("input",{type:"text",className:"rename-input",value:M,onChange:c=>O(c.target.value),onKeyDown:c=>{c.key==="Enter"?Qa():c.key==="Escape"&&(P(!1),O(""),B(""))},placeholder:"Database name",autoFocus:!0}),F&&p.jsx("div",{className:"form-error",children:F}),p.jsxs("div",{className:"new-db-actions",children:[p.jsx("button",{className:"button new-db-button",onClick:()=>Qa(),children:"Create"}),p.jsx("button",{className:"button ghost",onClick:()=>{P(!1),O(""),B("")},children:"Cancel"})]})]}):p.jsx("button",{className:"button new-db-button",onClick:()=>{P(!0),B("")},children:"New Database"}))]}),p.jsx("div",{className:"resizer",onMouseDown:Fp})]}),p.jsxs("div",{className:"main-content",children:[Rn&&p.jsxs("div",{className:"startup-task-banner",role:"status","aria-live":"polite",children:[Tn&&p.jsx("div",{className:"spinner startup-task-banner__spinner"}),p.jsx("div",{className:"startup-task-banner__text",children:Rn})]}),l==="chats"&&p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:"header",children:[p.jsxs("strong",{children:["Chat - ",((eu=e.find(c=>c.session_id===n))==null?void 0:eu.name)||"New Chat"]}),ot&&p.jsx("span",{className:"header-subtle",children:`DB: ${ot.name}${ni}`})]}),p.jsx("div",{className:"chat",ref:T,onClick:Yp,children:Fn.map((c,w)=>{const x=c.role==="user"&&xp===w;return p.jsx("div",{id:c.id,className:"msg "+(c.role==="user"?"user":"assistant")+(x?" editing":""),children:c.role==="assistant"?p.jsxs("div",{className:"assistant-message-wrapper",children:[p.jsx(Ly,{content:c.content,streamOutput:kt,sources:c.sources}),!Dt&&p.jsxs("div",{className:"message-options-bar assistant-options",children:[p.jsx("button",{className:"icon-button",title:"Copy message",onClick:()=>Fa(c),children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[p.jsx("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),p.jsx("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})}),p.jsx("button",{className:"icon-button",title:"Regenerate response",onClick:()=>Da(w),children:p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:p.jsx("path",{d:"M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.3"})})})]})]}):p.jsxs("div",{className:"user-message-wrapper",children:[x?p.jsxs("div",{className:"msg-content msg-content--user editing",children:[p.jsx("div",{className:"user-edit-shadow","aria-hidden":"true",children:Jo}),p.jsx(Sc,{className:"edit-message-input edit-overlay",value:Jo,onChange:k=>ml(k.target.value),onBlur:vl,onKeyDown:k=>{k.key==="Escape"&&(k.preventDefault(),vl()),k.key==="Enter"&&!k.shiftKey&&(k.preventDefault(),_p(w))},autoFocus:!0,minRows:1})]}):(()=>{const k=c.content||"",$=k.split(/\r\n|\r|\n/),D=$.length>30,W=Wa(c,w,n),A=D?jp[W]??!0:!1,V=A?$.slice(0,30).join(` `)+` -…`:k;return p.jsxs(p.Fragment,{children:[p.jsx("div",{className:"msg-content msg-content--user",children:V}),D&&p.jsx("button",{className:"user-msg-expand",onClick:()=>Rp(W),"aria-expanded":A?"false":"true",children:A?"Show entire message":"Collapse"})]})})(),!Dt&&!x&&p.jsxs("div",{className:"message-options-bar user-options",children:[p.jsx("button",{className:"icon-button",title:"Edit message",onClick:()=>Np(w,c.content),children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[p.jsx("path",{d:"M12 20h9"}),p.jsx("path",{d:"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"})]})}),p.jsx("button",{className:"icon-button",title:"Copy message",onClick:()=>Fa(c),children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[p.jsx("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),p.jsx("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})})]})]})},c.id||w)})},n),Ba[n]&&p.jsxs("button",{className:"new-msg-tip",onClick:Hp,title:"Jump to the new message","aria-label":"Jump to the new message",children:["New message",p.jsx("span",{style:{marginLeft:6},children:"↓"})]}),p.jsx("div",{className:"footer",children:p.jsxs("div",{className:"footer-content-wrapper",children:[p.jsx(Sc,{ref:H,className:"input",value:be,onChange:c=>_(c.target.value),onKeyDown:c=>{c.key==="Enter"&&!c.shiftKey&&(c.preventDefault(),Xa())},placeholder:"Ask any question...",maxRows:13}),p.jsxs("div",{className:"footer-tool-group",ref:R,children:[p.jsx("button",{type:"button",className:"db-picker-toggle"+(ot?" active":""),onClick:()=>{n&&q(c=>!c)},title:ot?`Database: ${ot.name}${ni}`:"Select database for this chat","aria-haspopup":"menu","aria-expanded":U,disabled:!n,children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[p.jsx("ellipse",{cx:"12",cy:"5",rx:"8",ry:"3"}),p.jsx("path",{d:"M4 5v6c0 1.7 3.6 3 8 3s8-1.3 8-3V5"}),p.jsx("path",{d:"M4 11v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"})]})}),U&&p.jsxs("div",{className:"db-picker-menu",role:"menu",children:[p.jsxs("button",{type:"button",className:"db-picker-option"+(Et?"":" selected"),onClick:()=>{Ja(n,null),q(!1)},children:[p.jsx("span",{children:"No database"}),!Et&&p.jsx("span",{className:"db-picker-status",children:"Selected"})]}),y.length===0?p.jsx("div",{className:"db-picker-empty",children:"No databases yet."}):y.map(c=>{var $,D,W;const w=Et===c.slug,x=Ga(c.slug),k=($=c.files)!=null&&$.length?(D=c.states)!=null&&D.is_indexed?"Ready":x?"Syncing":"Needs sync":"Empty";return p.jsxs("button",{type:"button",className:"db-picker-option"+(w?" selected":""),disabled:!((W=c.files)!=null&&W.length),onClick:()=>{Ja(n,c.slug),q(!1)},children:[p.jsx("span",{children:c.name}),p.jsx("span",{className:"db-picker-status",children:w?"Selected":k})]},c.slug)})]})]}),p.jsx("button",{type:"button",className:"websearch-toggle"+(pl?" active":""),onClick:Wp,title:"Toggle web search","aria-pressed":pl,children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[p.jsx("circle",{cx:"12",cy:"12",r:"10"}),p.jsx("line",{x1:"2",y1:"12",x2:"22",y2:"12"}),p.jsx("path",{d:"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"})]})}),p.jsx("button",{className:"button",onClick:Dt?Mp:Xa,title:Dt?"Cancel generation":"Send","aria-label":Dt?"Cancel generation":"Send",children:Dt?p.jsx("div",{className:"spinner"}):"Send"})]})})]}),l==="dbs"&&p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:"header",children:[p.jsx("strong",{children:(Sl==null?void 0:Sl.name)||"Databases"}),ot&&p.jsx("span",{className:"header-subtle",children:`Current chat DB: ${ot.name}${ni}`})]}),p.jsx(Sy,{apiBase:z,library:Sl,jobs:C,onRefresh:async()=>{await gr(),await wl()}})]}),l==="settings"&&p.jsxs(p.Fragment,{children:[p.jsx("div",{className:"header",children:p.jsxs("strong",{children:[i," Settings"]})}),i==="General"&&p.jsx(hy,{onModelChange:We,streamOutput:kt,onStreamOutputChange:ht,onLibrariesPurged:Dp}),i==="Interface"&&p.jsx(yy,{}),i==="Websearch"&&p.jsx(Cy,{searxUrl:hr,setSearxUrl:gp,engines:un,setEngines:c=>vp(Lo(c))})]})]})]})}function $y(){return g.useEffect(()=>{window.electronAPI.getSettings().then(e=>{ll(e.colorScheme||"Default")})},[]),p.jsx(Me.StrictMode,{children:p.jsx(Fv,{children:p.jsx(pv,{children:p.jsx(rp,{path:"/",element:p.jsx(Ty,{})})})})})}const My=Vd(document.getElementById("root"));My.render(p.jsx($y,{})); +…`:k;return p.jsxs(p.Fragment,{children:[p.jsx("div",{className:"msg-content msg-content--user",children:V}),D&&p.jsx("button",{className:"user-msg-expand",onClick:()=>Rp(W),"aria-expanded":A?"false":"true",children:A?"Show entire message":"Collapse"})]})})(),!Dt&&!x&&p.jsxs("div",{className:"message-options-bar user-options",children:[p.jsx("button",{className:"icon-button",title:"Edit message",onClick:()=>Np(w,c.content),children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[p.jsx("path",{d:"M12 20h9"}),p.jsx("path",{d:"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"})]})}),p.jsx("button",{className:"icon-button",title:"Copy message",onClick:()=>Fa(c),children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[p.jsx("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),p.jsx("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})})]})]})},c.id||w)})},n),Ba[n]&&p.jsxs("button",{className:"new-msg-tip",onClick:Hp,title:"Jump to the new message","aria-label":"Jump to the new message",children:["New message",p.jsx("span",{style:{marginLeft:6},children:"↓"})]}),p.jsx("div",{className:"footer",children:p.jsxs("div",{className:"footer-content-wrapper",children:[p.jsx(Sc,{ref:H,className:"input",value:be,onChange:c=>_(c.target.value),onKeyDown:c=>{c.key==="Enter"&&!c.shiftKey&&(c.preventDefault(),Xa())},placeholder:"Ask any question...",maxRows:13}),p.jsxs("div",{className:"footer-tool-group",ref:R,children:[p.jsx("button",{type:"button",className:"db-picker-toggle"+(ot?" active":""),onClick:()=>{n&&q(c=>!c)},title:ot?`Database: ${ot.name}${ni}`:"Select database for this chat","aria-haspopup":"menu","aria-expanded":U,disabled:!n,children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[p.jsx("ellipse",{cx:"12",cy:"5",rx:"8",ry:"3"}),p.jsx("path",{d:"M4 5v6c0 1.7 3.6 3 8 3s8-1.3 8-3V5"}),p.jsx("path",{d:"M4 11v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"})]})}),U&&p.jsxs("div",{className:"db-picker-menu",role:"menu",children:[p.jsxs("button",{type:"button",className:"db-picker-option"+(Et?"":" selected"),onClick:()=>{Ja(n,null),q(!1)},children:[p.jsx("span",{children:"No database"}),!Et&&p.jsx("span",{className:"db-picker-status",children:"Selected"})]}),y.length===0?p.jsx("div",{className:"db-picker-empty",children:"No databases yet."}):y.map(c=>{var $,D,W;const w=Et===c.slug,x=Ga(c.slug),k=($=c.files)!=null&&$.length?(D=c.states)!=null&&D.is_indexed?"Ready":x?"Syncing":"Needs sync":"Empty";return p.jsxs("button",{type:"button",className:"db-picker-option"+(w?" selected":""),disabled:!((W=c.files)!=null&&W.length),onClick:()=>{Ja(n,c.slug),q(!1)},children:[p.jsx("span",{children:c.name}),p.jsx("span",{className:"db-picker-status",children:w?"Selected":k})]},c.slug)})]})]}),p.jsx("button",{type:"button",className:"websearch-toggle"+(pl?" active":""),onClick:Wp,title:"Toggle web search","aria-pressed":pl,children:p.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[p.jsx("circle",{cx:"12",cy:"12",r:"10"}),p.jsx("line",{x1:"2",y1:"12",x2:"22",y2:"12"}),p.jsx("path",{d:"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"})]})}),p.jsx("button",{className:"button",onClick:Dt?Mp:Xa,title:Dt?"Cancel generation":"Send","aria-label":Dt?"Cancel generation":"Send",children:Dt?p.jsx("div",{className:"spinner"}):"Send"})]})})]}),l==="dbs"&&p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:"header",children:[p.jsx("strong",{children:(Sl==null?void 0:Sl.name)||"Databases"}),ot&&p.jsx("span",{className:"header-subtle",children:`Current chat DB: ${ot.name}${ni}`})]}),p.jsx(Sy,{apiBase:z,library:Sl,jobs:C,onRefresh:async()=>{await gr(),await wl()}})]}),l==="settings"&&p.jsxs(p.Fragment,{children:[p.jsx("div",{className:"header",children:p.jsxs("strong",{children:[i," Settings"]})}),i==="General"&&p.jsx(hy,{onModelChange:We,streamOutput:kt,onStreamOutputChange:ht,onLibrariesPurged:Dp}),i==="Interface"&&p.jsx(yy,{}),i==="Websearch"&&p.jsx(Cy,{searxUrl:hr,setSearxUrl:gp,engines:un,setEngines:c=>vp(Lo(c))})]})]})]})}function My(){return g.useEffect(()=>{window.electronAPI.getSettings().then(e=>{ll(e.colorScheme||"Default")})},[]),p.jsx(Me.StrictMode,{children:p.jsx(Fv,{children:p.jsx(pv,{children:p.jsx(rp,{path:"/",element:p.jsx($y,{})})})})})}const zy=Vd(document.getElementById("root"));zy.render(p.jsx(My,{})); diff --git a/dist/index.html b/dist/index.html index 8613624..ffabd0c 100644 --- a/dist/index.html +++ b/dist/index.html @@ -5,7 +5,7 @@ LLM Desktop - +