@filigran/chatbot 3.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import{useState as r,useRef as a,useEffect as o,useCallback as s}from"react";import{createPortal as i}from"react-dom";import l from"react-markdown";import c from"remark-gfm";function d(e,t){return`${e}${Math.round(255*t).toString(16).padStart(2,"0")}`}const h=e=>e;function g(e,t){const n=e.event;if("nextAgentFlow"===n){const n=e.data,r=n?.nodeId;return"INPROGRESS"===n?.status&&r&&(t.activeNodeId=r),{action:"noop"}}if("start"===n)return{action:"noop"};if("token"===n){return{action:"stream",content:(e.data??"").replace(/<br\s*\/?>/g,"\n")}}if("agentReasoning"===n){const n=e.data,r=n?.usedTools;return r?.length?(t.hasUsedTools=!0,{action:"status",status:"tool_start",tools:r.map(e=>e.tool)}):t.hasUsedTools?{action:"status",status:"analyzing"}:{action:"status",status:"thinking"}}if("usedTools"===n){t.hasUsedTools=!0;const n=e.data;return{action:"status",status:"tool_start",tools:Array.isArray(n)?n.map(e=>e.tool):[]}}if("metadata"===n){const t=e.data,n=t?.chatId;return n?{action:"set_chat_id",chatId:n}:{action:"noop"}}return"error"===n?{action:"error",content:e.data||""}:"end"===n?{action:"done",content:""}:{action:"noop"}}function u(e,t){const n=e.type;if("error"===n)return{action:"error",content:e.content||""};if("status"===n){const n=e.status;return"tool_done"===n||"wind_down"===n?{action:"noop"}:"streaming"===n?{action:"status",status:"streaming"}:"thinking_text"===n?{action:"status",status:"thinking_text",thinkingContent:e.content}:"tool_start"===n?(t.hasUsedTools=!0,{action:"status",status:"tool_start",tools:e.tools}):"thinking"===n&&t.hasUsedTools?{action:"status",status:"analyzing"}:{action:"status",status:n,tools:e.tools}}return"stream"===n?{action:"stream",content:e.content}:"done"===n?{action:"done",content:e.content,conversationId:e.conversation_id,toolNames:e.tool_names,toolCallCount:e.tool_call_count,iterations:e.iterations}:{action:"noop"}}function m(e,t){const n=e.type;if("RUN_STARTED"===n)return{action:"status",status:"thinking"};if("RUN_FINISHED"===n)return{action:"done",content:""};if("RUN_ERROR"===n)return{action:"error",content:e.message||"Unknown error"};if("STEP_STARTED"===n){return{action:"status",status:e.stepName||"thinking"}}if("STEP_FINISHED"===n)return{action:"noop"};if("TEXT_MESSAGE_START"===n)return{action:"status",status:"streaming"};if("TEXT_MESSAGE_CONTENT"===n){const t=e.delta;return t?{action:"stream",content:t}:{action:"noop"}}if("TEXT_MESSAGE_END"===n)return{action:"noop"};if("TEXT_MESSAGE_CHUNK"===n){const t=e.delta;return t?{action:"stream",content:t}:{action:"noop"}}if("TOOL_CALL_START"===n){t.hasUsedTools=!0;const n=e.toolCallName;return{action:"status",status:"tool_start",tools:n?[n]:[]}}if("TOOL_CALL_ARGS"===n)return{action:"noop"};if("TOOL_CALL_END"===n)return{action:"status",status:"analyzing"};if("TOOL_CALL_RESULT"===n)return{action:"noop"};if("TOOL_CALL_CHUNK"===n){const n=e.toolCallName;return n?(t.hasUsedTools=!0,{action:"status",status:"tool_start",tools:[n]}):{action:"noop"}}return"REASONING_START"===n||"REASONING_MESSAGE_START"===n||"REASONING_MESSAGE_CONTENT"===n||"REASONING_MESSAGE_CHUNK"===n?{action:"status",status:"thinking"}:{action:"noop"}}const p="filigranChatConversationId",w="filigranChatLegacyChatId";function x({apiBaseUrl:e,apiEndpoints:t,backendType:n="rest",agentSlug:o,t:s}){const i="legacy"===n,[l,c]=r([]),[d,h]=r(""),[x,f]=r(!1),[b,k]=r(null),[v,y]=r(()=>"undefined"==typeof window?null:localStorage.getItem(p)),[N,C]=r([]),[S,_]=r(()=>"undefined"==typeof window?null:localStorage.getItem(w)),L=a(!1),I=a(null),M=a(!1),z=e=>{if(!e)return;const t=[];Array.from(e).forEach(n=>{const r=new FileReader;r.onload=()=>{t.push({name:n.name,type:n.type,size:n.size,dataUrl:r.result}),t.length===e.length&&C(e=>[...e,...t])},r.readAsDataURL(n)})};return{messages:l,inputValue:d,setInputValue:h,isLoading:x,agentStatus:b,attachedFiles:N,conversationId:v,historyLoadedRef:L,handleFileAdd:z,handlePaste:e=>{const{files:t}=e.clipboardData;t.length>0&&(e.preventDefault(),z(t))},handleSendMessage:async()=>{if(!d.trim()&&0===N.length||x)return;const r=d.trim(),a={id:crypto.randomUUID(),role:"user",content:r,timestamp:new Date,files:N.length>0?[...N]:void 0};c(e=>[...e,a]),h(""),C([]),f(!0),k({status:"thinking"}),M.current=!1;const l=crypto.randomUUID();c(e=>[...e,{id:l,role:"assistant",content:"",timestamp:new Date}]);try{const a=new AbortController;I.current=a;const d=function(e,t,n){switch(e){case"legacy":return{question:t,chatId:n.legacyChatId??void 0,streaming:!0};case"ag-ui":return{threadId:n.conversationId??crypto.randomUUID(),runId:crypto.randomUUID(),messages:[{id:crypto.randomUUID(),role:"user",content:t}],tools:[],context:[],state:{},forwardedProps:n.agentSlug?{agentSlug:n.agentSlug}:{}};default:return{content:t,conversation_id:n.conversationId,agent_slug:n.agentSlug}}}(n,r,{legacyChatId:S,conversationId:v,agentSlug:o}),h=await fetch(i||t?.singleEndpoint?e:`${e}${t?.messages??"/chat/messages"}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(d),signal:a.signal});if(!h.ok||!h.body)return void c(e=>e.map(e=>e.id===l?{...e,content:s("Unable to connect. Please check the configuration.")}:e));const x=function(e){switch(e){case"legacy":return g;case"ag-ui":return m;default:return u}}(n),f={hasUsedTools:!1,activeNodeId:""},b=h.body.getReader(),N=new TextDecoder;let C="",L="",z=!1;for(;;){const{done:e,value:t}=await b.read();if(e)break;C+=N.decode(t,{stream:!0});const n=C.split("\n");C=n.pop()||"";for(const e of n){const t=e.replace(/\r$/,"");if(!t.startsWith("data:"))continue;const n=t.startsWith("data: ")?t.slice(6):t.slice(5);try{const e=x(JSON.parse(n),f);switch(f.hasUsedTools=f.hasUsedTools||M.current,e.action){case"status":"tool_start"===e.status&&(M.current=!0),"thinking_text"===e.status?k(t=>({...t,status:t?.status??"thinking",thinkingContent:(t?.thinkingContent??"")+(e.thinkingContent??"")})):k({status:e.status,tools:e.tools});break;case"stream":L+=e.content,k({status:"streaming"}),c(e=>e.map(e=>e.id===l?{...e,content:L}:e));break;case"done":z=!0,e.conversationId&&(y(e.conversationId),localStorage.setItem(p,e.conversationId)),c(t=>t.map(t=>t.id===l?{...t,content:e.content||L,toolNames:e.toolNames,toolCallCount:e.toolCallCount,iterations:e.iterations}:t));break;case"error":return void c(t=>t.map(t=>t.id===l?{...t,content:e.content||s("Unable to connect. Please check the configuration.")}:t));case"set_chat_id":_(e.chatId),localStorage.setItem(w,e.chatId)}M.current=f.hasUsedTools}catch{}}}L&&!z&&c(e=>e.map(e=>e.id===l?{...e,content:L||"No response."}:e))}catch(e){if(e instanceof DOMException&&"AbortError"===e.name)return;c(e=>e.map(e=>e.id===l?{...e,content:s("Sorry, an error occurred. Please try again.")}:e))}finally{I.current=null,f(!1),k(null),M.current=!1}},handleNewChat:()=>{I.current?.abort(),I.current=null,c([]),h(""),C([]),f(!1),k(null),M.current=!1,L.current=!1,i?(_(null),localStorage.removeItem(w)):(y(null),localStorage.removeItem(p))},handleStopGenerating:()=>{I.current?.abort(),I.current=null,f(!1),k(null),M.current=!1,c(e=>e.filter(e=>!("assistant"===e.role&&!e.content)))},setAttachedFiles:C,setMessages:c,setConversationId:y}}const f="filigranChatAgentSlug";const b=400,k="filigranChatSidebarWidth";const v=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e("path",{d:"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"})}),y=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"}),e("path",{d:"M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"}),e("path",{d:"M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"}),e("path",{d:"M17.599 6.5a3 3 0 0 0 .399-1.375"}),e("path",{d:"M6.003 5.125A3 3 0 0 0 6.401 6.5"}),e("path",{d:"M3.477 10.896a4 4 0 0 1 .585-.396"}),e("path",{d:"M19.938 10.5a4 4 0 0 1 .585.396"}),e("path",{d:"M6 18a4 4 0 0 1-1.967-.516"}),e("path",{d:"M19.967 17.484A4 4 0 0 1 18 18"})]}),N=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e("path",{d:"M20 6 9 17l-5-5"})}),C=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e("path",{d:"m6 9 6 6 6-6"})}),S=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M18 6 6 18"}),e("path",{d:"m6 6 12 12"})]}),_=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}),e("path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"})]}),L=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}),e("path",{d:"M3 5V19A9 3 0 0 0 21 19V5"}),e("path",{d:"M3 12A9 3 0 0 0 21 12"})]}),I=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",stroke:"none",className:t,children:e("path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"})}),M=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M12 20h9"}),e("path",{d:"M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z"})]}),z=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M15 3h6v6"}),e("path",{d:"M10 14 21 3"}),e("path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"})]}),A=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}),e("path",{d:"M14 2v4a2 2 0 0 0 2 2h4"})]}),T=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M11 13H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7"}),e("rect",{width:"12",height:"12",x:"10",y:"10",rx:"2"})]}),E=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M8 3v3a2 2 0 0 1-2 2H3"}),e("path",{d:"M21 8h-3a2 2 0 0 1-2-2V3"}),e("path",{d:"M3 16h3a2 2 0 0 0 2 2v3"}),e("path",{d:"M16 21v-3a2 2 0 0 1 2-2h3"})]}),$=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M8 3H5a2 2 0 0 0-2 2v3"}),e("path",{d:"M21 8V5a2 2 0 0 0-2-2h-3"}),e("path",{d:"M3 16v3a2 2 0 0 0 2 2h3"}),e("path",{d:"M16 21h3a2 2 0 0 0 2-2v-3"})]}),R=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("circle",{cx:"12",cy:"12",r:"10"}),e("path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"}),e("path",{d:"M2 12h20"})]}),D=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("circle",{cx:"12",cy:"12",r:"10"}),e("path",{d:"M12 16v-4"}),e("path",{d:"M12 8h.01"})]}),U=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}),e("path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"})]}),j=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("circle",{cx:"11",cy:"11",r:"8"}),e("path",{d:"m21 21-4.3-4.3"})]}),W=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"m22 2-7 20-4-9-9-4Z"}),e("path",{d:"m22 2-11 11"})]}),O=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}),e("path",{d:"M15 3v18"})]}),B=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e("path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"})}),P=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("circle",{cx:"12",cy:"12",r:"10"}),e("rect",{width:"6",height:"6",x:"9",y:"9"})]}),F=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("polyline",{points:"4 17 10 11 4 5"}),e("line",{x1:"12",x2:"20",y1:"19",y2:"19"})]}),G=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}),e("circle",{cx:"9",cy:"7",r:"4"}),e("line",{x1:"19",x2:"19",y1:"8",y2:"14"}),e("line",{x1:"22",x2:"16",y1:"11",y2:"11"})]}),H=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e("path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"})});const V=({open:t,onClose:n,anchorRef:l,placement:c="bottom-start",width:d=280,children:h})=>{const g=a(null),[u,m]=r({top:0,left:0});if(function(e,t,n=!0){o(()=>{if(!n)return;const r=n=>{e.current&&!e.current.contains(n.target)&&t()};return document.addEventListener("mousedown",r),document.addEventListener("touchstart",r),()=>{document.removeEventListener("mousedown",r),document.removeEventListener("touchstart",r)}},[e,t,n])}(g,s(()=>n(),[n]),t),o(()=>{if(!t||!l.current)return;const e=l.current.getBoundingClientRect(),n="bottom-end"===c?e.right-d:e.left;m({top:e.bottom+4,left:n})},[t,l,c,d]),!t)return null;const p=function(e){let t=e;for(;t;){if(t.classList.contains("filigran-chatbot"))return t;t=t.parentElement}return document.body}(l.current);return i(e("div",{ref:g,className:"fixed z-[10000] rounded-[10px] overflow-hidden border border-gray-200 dark:border-white/10 bg-white dark:bg-[#2a2a3e] shadow-xl",style:{top:u.top,left:u.left,width:d},children:h}),p)},q=({size:t=16,className:n=""})=>e("div",{className:`animate-spin rounded-full border-2 border-current/20 border-t-[var(--chat-accent)] ${n}`,style:{width:t,height:t}});function K(e){let t=e;for(;t;){if(t.classList.contains("filigran-chatbot"))return t;t=t.parentElement}return document.body}const X=({title:n,children:o})=>{const s=a(null),[l,c]=r(!1),[d,h]=r({top:0,left:0});if(!n)return o;return t("span",{ref:s,className:"inline-flex",onMouseEnter:()=>{if(!s.current)return;const e=s.current.getBoundingClientRect();h({top:e.top-4,left:e.left+e.width/2}),c(!0)},onMouseLeave:()=>c(!1),children:[o,l&&i(e("span",{className:"pointer-events-none fixed z-[10001] -translate-x-1/2 -translate-y-full whitespace-nowrap rounded-md bg-gray-900 dark:bg-gray-100 px-2 py-1 text-xs text-white dark:text-gray-900 shadow-lg",style:{top:d.top,left:d.left},role:"tooltip",children:n}),K(s.current))]})},Z=[{mode:"floating",label:"Floating",getIcon:t=>e(T,{...t})},{mode:"sidebar",label:"Sidebar",getIcon:t=>e(O,{...t})},{mode:"fullscreen",label:"Full screen",getIcon:t=>e($,{...t})}],J=({mode:n,agentName:r,agents:o,selectedAgent:s,agentMenuOpen:i,onAgentMenuToggle:l,onAgentMenuClose:c,onSwitchAgent:d,modeMenuOpen:h,onModeMenuToggle:g,onModeMenuClose:u,onModeChange:m,onNewChat:p,onClose:w,logoIcon:x,agentDashboardUrl:f,t:b})=>{const k=a(null),v=a(null),y="sidebar"===n?O:"fullscreen"===n?E:T;return t("div",{className:"flex items-center px-3 py-2 min-h-[48px] border-b border-gray-200 dark:border-white/10 bg-gradient-to-br from-[var(--chat-accent-dark)]/[0.13] to-[var(--chat-accent)]/[0.07] "+("floating"===n?"rounded-t-xl":""),children:[t("button",{ref:k,type:"button",onClick:l,className:"flex items-center gap-1.5 text-sm font-semibold text-gray-900 dark:text-white px-2 py-1 rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 transition-colors",children:[e("span",{className:"flex items-center text-[var(--chat-accent)] [&>svg]:w-[18px] [&>svg]:h-[18px]",children:x}),r,e(C,{size:16,className:"text-gray-400 dark:text-white/30"})]}),t(V,{open:i,onClose:c,anchorRef:k,width:280,children:[e("span",{className:"block px-4 pt-3 pb-1 text-[0.68rem] tracking-[1px] uppercase text-gray-400 dark:text-white/40",children:b("Switch to another agent")}),0===o.length&&e("div",{className:"px-4 py-2",children:e(q,{size:16})}),e("div",{children:o.map(n=>t("button",{type:"button",onClick:()=>d(n),className:"w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors "+(n.id===s?.id?"bg-[var(--chat-accent)]/10":""),children:[e("div",{className:"w-7 h-7 rounded-full flex items-center justify-center shrink-0 bg-gradient-to-br from-[var(--chat-accent)]/20 to-[var(--chat-accent)]/5",children:e("span",{className:"text-[var(--chat-accent)] [&>svg]:w-4 [&>svg]:h-4",children:x})}),t("div",{className:"min-w-0",children:[e("div",{className:"text-[0.8125rem] font-medium text-gray-900 dark:text-white truncate",children:n.name}),n.description&&e("div",{className:"text-[0.7rem] text-gray-500 dark:text-white/40 truncate",children:n.description})]})]},n.id))}),e("div",{className:"h-px bg-gray-200 dark:bg-white/10 mx-2"}),t("div",{children:[f&&t("button",{type:"button",onClick:()=>{c(),window.open(`${f}/agents`,"_blank")},className:"w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors",children:[e(z,{size:18,className:"text-gray-400 dark:text-white/40 shrink-0"}),e("span",{className:"text-[0.8125rem] text-gray-700 dark:text-white/70",children:b("Browse agents")})]}),f&&t("button",{type:"button",onClick:()=>{c(),window.open(`${f}/agents/new`,"_blank")},className:"w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors",children:[e(G,{size:18,className:"text-gray-400 dark:text-white/40 shrink-0"}),e("span",{className:"text-[0.8125rem] text-gray-700 dark:text-white/70",children:b("Create agent")})]})]})]}),e("div",{className:"flex-1"}),e(X,{title:b("New chat"),children:e("button",{type:"button",onClick:p,className:"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors",children:e(M,{size:18})})}),e(X,{title:b("Switch view"),children:e("button",{ref:v,type:"button",onClick:g,className:"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors",children:e(y,{size:18})})}),t(V,{open:h,onClose:u,anchorRef:v,placement:"bottom-end",width:180,children:[e("span",{className:"block px-4 pt-3 pb-1 text-[0.68rem] tracking-[1px] uppercase text-gray-400 dark:text-white/40",children:b("Switch to")}),e("div",{className:"pb-1",children:Z.map(r=>t("button",{type:"button",onClick:()=>{m(r.mode),u()},className:"w-full flex items-center gap-3 px-4 py-1 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors "+(n===r.mode?"bg-[var(--chat-accent)]/10":""),children:[r.getIcon({size:18,className:"text-gray-400 dark:text-white/40"}),e("span",{className:"text-[0.8125rem] text-gray-700 dark:text-white/70",children:b(r.label)})]},r.mode))})]}),e(X,{title:b("Close"),children:e("button",{type:"button",onClick:w,className:"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors",children:e(S,{size:18})})})]})},Q=({inputValue:n,onInputChange:r,onSend:o,onStop:s,isLoading:i,attachedFiles:l,onFileAdd:c,onFileRemove:d,onPaste:h,t:g,mode:u})=>{const m=a(null),p=a(null),w=n.trim()||l.length>0;return t("div",{className:"px-4 py-3 border-t border-gray-200 dark:border-white/10 "+("floating"===u?"rounded-b-xl":""),children:[l.length>0&&e("div",{className:"flex gap-1.5 flex-wrap mb-2",children:l.map((n,r)=>t("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.7rem] text-gray-600 dark:text-white/60",children:[e(A,{size:14}),n.name,e("button",{type:"button",onClick:()=>d(r),className:"ml-0.5 text-gray-400 dark:text-white/30 hover:text-gray-600 dark:hover:text-white/60",children:"×"})]},r))}),t("div",{className:"flex items-center border border-gray-200 dark:border-white/10 rounded-xl px-2 py-1 transition-colors focus-within:border-[var(--chat-accent)]",children:[e("input",{ref:m,type:"file",multiple:!0,hidden:!0,onChange:e=>{c(e.target.files),e.target.value=""}}),e("button",{type:"button",onClick:()=>m.current?.click(),className:"w-8 h-8 flex items-center justify-center shrink-0 rounded-lg text-gray-400 dark:text-white/30 hover:bg-gray-100 dark:hover:bg-white/10 mr-0.5 transition-colors",children:e(v,{size:18})}),e("textarea",{ref:p,placeholder:g("Ask a question..."),value:n,onChange:e=>{r(e.target.value);const t=e.target;t.style.height="auto",t.style.height=`${Math.min(t.scrollHeight,120)}px`},onKeyDown:e=>{"Enter"!==e.key||e.shiftKey||(e.preventDefault(),o())},onPaste:h,rows:1,className:"flex-1 bg-transparent border-none outline-none resize-none text-[0.8125rem] py-1.5 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-white/30 filigran-chat-scrollable",style:{maxHeight:120}}),e(X,{title:i?g("Stop generating"):"",children:e("button",{type:"button",onClick:i?s:o,disabled:!i&&!w,className:"p-1.5 rounded-lg w-8 h-8 flex items-center justify-center transition-all duration-150 "+(i?"text-red-500 bg-red-500/10 hover:bg-red-500/20":w?"text-[var(--chat-accent)] bg-[var(--chat-accent)]/10 hover:bg-[var(--chat-accent)]/20":"text-gray-300 dark:text-white/20 cursor-not-allowed"),children:e(i?P:W,{size:18})})})]}),e("p",{className:"text-center text-[0.65rem] text-gray-400 dark:text-white/30 mt-1.5 opacity-70",children:g("Uses AI. Verify results.")})]})};function Y({content:n}){const r=a(null),s=n.replace(/```[\s\S]*?```/g," ").replace(/`([^`]+)`/g,"$1").replace(/\*\*(.+?)\*\*/g,"$1").replace(/__(.+?)__/g,"$1").replace(/\*(.+?)\*/g,"$1").replace(/_(.+?)_/g,"$1").replace(/#{1,6}\s+/g,"").replace(/[*\->]+/g," ").replace(/\s+/g," ").trim();return o(()=>{r.current&&(r.current.scrollTop=r.current.scrollHeight)},[s]),s.length<3?null:t("div",{ref:r,className:"ml-11 max-w-[70%] max-h-20 overflow-hidden relative rounded-md border-l-2 bg-[var(--chat-accent)]/[0.03] pl-3 pr-3 py-2",style:{animation:"reasoningGlow 3s ease-in-out infinite, chat-fade-in 0.5s ease-out"},children:[e("p",{className:"text-[13px] leading-[1.35rem] text-gray-400 dark:text-white/40 break-words m-0",children:s}),e("div",{className:"absolute inset-x-0 bottom-0 h-5 bg-gradient-to-t from-white/90 dark:from-[#1e1e2e]/90 to-transparent pointer-events-none"})]})}const ee=({agentStatus:r,logoIcon:a,t:o})=>{const{label:s,StatusIcon:i,showDots:l}=function(e,t){if(!e)return{label:t("Thinking..."),StatusIcon:y,showDots:!1};switch(e.status){case"tool_start":{const n=e.tools??[],r=n.map(e=>e.toLowerCase());if(r.some(e=>"spawn_background_task"===e)){const e=n.filter(e=>"spawn_background_task"===e).length;return{label:e>1?`${t("Delegating")} ${e} ${t("tasks")}…`:`${t("Delegating task")}…`,StatusIcon:G,showDots:!1}}if(r.some(e=>"check_task_status"===e)){const e=n.filter(e=>"check_task_status"===e).length,r=e>1?`${e} ${t("background tasks")}`:t("background task");return{label:`${t("Waiting for")} ${r}…`,StatusIcon:B,showDots:!1}}if(r.some(e=>"get_task_result"===e)){const e=n.filter(e=>"get_task_result"===e).length,r=e>1?`${e} ${t("tasks")}`:t("task");return{label:`${t("Collecting results from")} ${r}…`,StatusIcon:B,showDots:!1}}let a,o=H;if(r.some(e=>e.includes("search")||e.includes("list"))?o=j:r.some(e=>e.includes("read")||e.includes("get")||e.includes("query"))?o=L:r.some(e=>e.includes("send")||e.includes("create")||e.includes("draft")||e.includes("reply")||e.includes("flag"))?o=U:r.some(e=>e.includes("code")||e.includes("execute"))?o=F:r.some(e=>e.includes("web")||e.includes("browse"))&&(o=R),n.length>0){const e=n.map(e=>e.replace(/_/g," ").replace(/\b\w/g,e=>e.toUpperCase())),t=Array.from(new Set(e));a=1===t.length?`${t[0]}…`:`${t[0]} (+${t.length-1} more)…`}else a=t("Using tools…");return{label:a,StatusIcon:o,showDots:!1}}case"analyzing":return{label:t("Analyzing results…"),StatusIcon:B,showDots:!1};case"composing":return{label:t("Composing answer…"),StatusIcon:y,showDots:!0};case"consulting":{const n=e.tools?.[0]??"agent";return{label:`${t("Consulting")} ${n}…`,StatusIcon:G,showDots:!1}}case"delegating":{const n=e.tools?.filter(e=>"spawn_background_task"===e).length??0;return{label:n>1?`${t("Delegating")} ${n} ${t("tasks")}…`:`${t("Delegating task")}…`,StatusIcon:G,showDots:!1}}case"polling":{const n=e.tools?.filter(e=>"check_task_status"===e).length??0,r=n>1?`${n} ${t("background tasks")}`:t("background task");return{label:`${t("Waiting for")} ${r}…`,StatusIcon:B,showDots:!1}}case"collecting":{const n=e.tools?.filter(e=>"get_task_result"===e).length??0,r=n>1?`${n} ${t("tasks")}`:t("task");return{label:`${t("Collecting results from")} ${r}…`,StatusIcon:B,showDots:!1}}case"transferring":{const n=e.tools?.[0]??"agent";return{label:`${t("Transferring to")} ${n}…`,StatusIcon:z,showDots:!1}}default:return{label:t("Thinking..."),StatusIcon:y,showDots:!1}}}(r,o),c=r?.thinkingContent;return t(n,{children:[t("div",{className:"flex gap-3 items-center justify-start",children:[e("div",{className:"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-[var(--chat-accent)]/15 to-[var(--chat-accent)]/5",children:e("span",{className:"text-[var(--chat-accent)] [&>svg]:w-4 [&>svg]:h-4",children:a})}),t("div",{className:"rounded-lg bg-gray-50 dark:bg-white/[0.03] px-4 py-3 relative overflow-hidden",children:[e("div",{className:"absolute inset-0 bg-gradient-to-r from-[var(--chat-accent)]/[0.03] via-transparent to-[var(--chat-accent)]/[0.03] animate-pulse pointer-events-none"}),t("div",{className:"relative flex items-center gap-2.5",children:[l?e("div",{className:"flex gap-[3px] items-center h-3.5 w-3.5 justify-center",children:[0,.15,.3].map((t,n)=>e("span",{className:"h-[5px] w-[5px] rounded-full bg-[var(--chat-accent)]/50",style:{animation:`chat-dot 1s ease-in-out infinite ${t}s`}},n))}):e(i,{size:14,className:"text-[var(--chat-accent)] animate-pulse transition-all duration-300"}),e("span",{className:"text-sm text-gray-500 dark:text-white/50 transition-all duration-300",children:s})]})]})]}),c&&e(Y,{content:c})]})},te=({content:n})=>{const[a,o]=r(null);return e(l,{remarkPlugins:[c],components:{p:({children:t})=>e("p",{className:"mb-3 last:mb-0 leading-7 break-words text-[0.8125rem] text-gray-900 dark:text-white/90",children:t}),code:({className:n,children:r})=>{const s=/language-(\w+)/.exec(n||""),i=String(r).replace(/\n$/,"");return s?t("div",{className:"my-3 rounded-lg border border-gray-200 dark:border-white/10 overflow-hidden bg-gray-50 dark:bg-white/[0.03]",children:[t("div",{className:"flex items-center justify-between px-3 py-1.5 border-b border-gray-200 dark:border-white/10 bg-gray-100 dark:bg-white/[0.03]",children:[e("span",{className:"text-[0.7rem] text-gray-500 dark:text-white/40 font-mono",children:s[1]}),e("button",{type:"button",onClick:()=>{return e=i,navigator.clipboard.writeText(e),o(e),void setTimeout(()=>o(null),2e3);var e},className:"p-0.5 rounded hover:bg-gray-200 dark:hover:bg-white/10 transition-colors",children:a===i?e(N,{size:14,className:"text-green-500"}):e(_,{size:14,className:"text-gray-400 dark:text-white/40"})})]}),e("pre",{className:"m-0 px-3 py-2 overflow-x-auto",children:e("code",{className:"font-mono text-xs leading-[1.7] text-gray-800 dark:text-white/90 whitespace-pre",children:i})})]}):e("code",{className:"bg-gray-100 dark:bg-white/[0.08] px-1.5 py-0.5 rounded font-mono text-xs text-[var(--chat-accent)]",children:r})},ul:({children:t})=>e("ul",{className:"pl-5 mb-3 text-[0.8125rem] text-gray-900 dark:text-white/90 [&_li]:mb-1 marker:text-[var(--chat-accent)]/50",children:t}),ol:({children:t})=>e("ol",{className:"pl-5 mb-3 text-[0.8125rem] text-gray-900 dark:text-white/90 [&_li]:mb-1 marker:text-[var(--chat-accent)]/50",children:t}),blockquote:({children:t})=>e("blockquote",{className:"my-3 border-l-2 border-[var(--chat-accent)]/30 bg-[var(--chat-accent)]/[0.03] pl-4 pr-3 py-2 rounded-r-md italic text-gray-500 dark:text-white/60",children:t}),a:({href:t,children:n})=>e("a",{href:t,target:"_blank",rel:"noopener noreferrer",className:"text-[var(--chat-accent)] underline underline-offset-2 hover:brightness-125",children:n}),h1:({children:t})=>e("h1",{className:"mt-4 first:mt-0 mb-2 font-bold text-base text-gray-900 dark:text-white",children:t}),h2:({children:t})=>e("h2",{className:"mt-3 first:mt-0 mb-2 font-bold text-[0.9rem] text-gray-900 dark:text-white",children:t}),h3:({children:t})=>e("h3",{className:"mt-3 first:mt-0 mb-1.5 font-semibold text-[0.85rem] text-gray-900 dark:text-white",children:t}),table:({children:t})=>e("div",{className:"my-3 overflow-x-auto rounded-lg border border-gray-200 dark:border-white/10",children:e("table",{className:"w-full border-collapse text-xs",children:t})}),th:({children:t})=>e("th",{className:"px-3 py-2 text-left font-semibold bg-gray-50 dark:bg-white/[0.04] border-b border-gray-200 dark:border-white/10 text-gray-900 dark:text-white",children:t}),td:({children:t})=>e("td",{className:"px-3 py-2 border-b border-gray-200 dark:border-white/10 text-gray-700 dark:text-white/80",children:t})},children:n})},ne=({messages:s,isLoading:i,agentStatus:l,agentName:c,logoIcon:d,t:h})=>{const g=a(null),[u,m]=r(null);return o(()=>{g.current?.scrollIntoView({behavior:"smooth"})},[s]),t("div",{className:"flex-1 overflow-y-auto px-4 py-3 flex flex-col gap-4 filigran-chat-scrollable",children:[s.map(r=>{const a="assistant"===r.role,o=!r.content;return a&&o&&i?e("div",{children:e(ee,{agentStatus:l,logoIcon:d,t:h})},r.id):t("div",{className:"flex flex-col "+(a?"items-start":"items-end"),children:[a&&t("div",{className:"flex items-center gap-1.5 mb-1",children:[e("div",{className:"w-6 h-6 rounded-lg flex items-center justify-center bg-gradient-to-br from-[var(--chat-accent)]/20 to-[var(--chat-accent)]/5",children:e("span",{className:"text-[var(--chat-accent)] [&>svg]:w-3 [&>svg]:h-3",children:d})}),e("span",{className:"font-semibold text-xs text-gray-900 dark:text-white",children:c})]}),r.files&&r.files.length>0&&e("div",{className:"flex gap-1.5 flex-wrap mb-1.5",children:r.files.map((n,r)=>t("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.7rem] text-gray-600 dark:text-white/60",children:[e(A,{size:14}),n.name]},r))}),t("div",{className:"max-w-[90%] "+(a?"pl-1 py-1 text-[0.8125rem] leading-7":"px-3.5 py-2 rounded-[14px_14px_4px_14px] bg-[var(--chat-accent-dark)] text-white text-[0.8125rem] leading-6"),children:[a?e(te,{content:r.content}):r.content,a&&o&&!i&&e("span",{className:"text-[0.8125rem] text-gray-400 dark:text-white/40 italic",children:"..."}),a&&!o&&i&&e("span",{className:"inline-block w-1.5 h-4 bg-[var(--chat-accent)]/70 rounded-sm ml-0.5 animate-pulse align-text-bottom"})]}),a&&!o&&!i&&r.toolNames&&r.toolNames.length>0&&t(n,{children:[e("button",{type:"button",onClick:()=>m(u===r.id?null:r.id),className:"mt-0.5 p-1 rounded-lg opacity-50 hover:opacity-100 hover:text-[var(--chat-accent)] transition-opacity",title:h("Reasoning details"),children:e(D,{size:14})}),u===r.id&&t("div",{className:"mt-1.5 p-3 rounded-lg bg-gray-50 dark:bg-white/[0.04] border border-gray-200 dark:border-white/10",children:[t("p",{className:"text-[0.7rem] text-gray-500 dark:text-white/40 mb-1.5",children:[r.iterations&&r.iterations>1?`${r.iterations} iterations · `:"",r.toolCallCount??r.toolNames.length," ",1===(r.toolCallCount??r.toolNames.length)?h("tool call"):h("tool calls")]}),e("div",{className:"flex flex-wrap gap-1",children:Array.from(new Set(r.toolNames)).map(t=>e("span",{className:"inline-flex items-center px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.68rem] font-mono text-gray-500 dark:text-white/40",children:t.replace(/_/g," ")},t))})]})]})]},r.id)}),e("div",{ref:g})]})},re=({firstName:n,logoIcon:r,promptSuggestions:a,onPromptClick:o,t:s})=>t("div",{className:"flex-1 flex flex-col items-center justify-center px-6 pb-8",children:[e("span",{className:"text-[var(--chat-accent)] mb-4 [&>svg]:w-12 [&>svg]:h-12 drop-shadow-[0_0_12px_var(--chat-accent-40)]",children:r}),t("h2",{className:"text-xl font-medium mb-6 text-center text-gray-900 dark:text-white",style:{fontFamily:'"Geologica", sans-serif'},children:[s("How can I help you, "),n,"?"]}),t("div",{className:"w-full max-w-[320px]",children:[e("span",{className:"block text-center mb-2 text-[0.65rem] tracking-[1.5px] uppercase text-[var(--chat-accent)] font-semibold",children:s("Suggestions")}),a.map(t=>e("button",{type:"button",onClick:()=>o(t),className:"w-full text-left text-[0.8125rem] text-gray-800 dark:text-white py-1.5 px-3 mb-1 rounded-lg border border-gray-200 dark:border-white/10 bg-transparent transition-colors hover:bg-[var(--chat-accent-10)] hover:border-[var(--chat-accent-50)]",children:s(t)},t))]})]}),ae=["Help me create a new simulation scenario","What are the latest attack patterns?","How do I configure detection rules?","Summarize my recent findings"],oe=({mode:n,onClose:s,onModeChange:i,topOffset:l=0,apiBaseUrl:c,apiEndpoints:g,agentDashboardUrl:u,user:m,t:p=h,accentColor:w="#7b5cff",logoIcon:v,promptSuggestions:y=ae,resizable:N=!1,onWidthChange:C,onResizeStart:S,onResizeEnd:_,pushContentSelector:L,backendType:M="rest"})=>{const[z,A]=r(!1),{agents:T,selectedAgent:E,agentMenuOpen:$,setAgentMenuOpen:R,handleSwitchAgent:D}=function({apiBaseUrl:e,apiEndpoints:t,backendType:n="rest"}){const[a,s]=r([]),[i,l]=r(null),[c,d]=r(!1);return o(()=>{null===t?.agents||t?.singleEndpoint||"legacy"===n||fetch(`${e}${t?.agents??"/chat/agents"}`).then(e=>e.ok?e.json():[]).then(e=>{if(s(e),e.length>0&&!i){const t=localStorage.getItem(f),n=t?e.find(e=>e.slug===t):null;l(n||e[0])}}).catch(()=>{})},[e,t]),{agents:a,selectedAgent:i,setSelectedAgent:l,agentMenuOpen:c,setAgentMenuOpen:d,handleSwitchAgent:(e,t)=>{e.id!==i?.id?(l(e),e.slug&&localStorage.setItem(f,e.slug),d(!1),t?.()):d(!1)}}}({apiBaseUrl:c,apiEndpoints:g,backendType:M}),{messages:U,inputValue:j,setInputValue:W,isLoading:O,agentStatus:B,attachedFiles:P,conversationId:F,historyLoadedRef:G,handleFileAdd:H,handlePaste:V,handleSendMessage:q,handleNewChat:K,handleStopGenerating:X,setAttachedFiles:Z,setMessages:Y,setConversationId:ee}=x({apiBaseUrl:c,apiEndpoints:g,backendType:M,agentSlug:E?.slug,t:p}),{sidebarWidth:te,handleResizeStart:oe,defaultWidth:se,isResizing:ie}=function({mode:e,resizable:t,onWidthChange:n,onResizeStart:s,onResizeEnd:i}){const[l,c]=r(()=>{if("undefined"==typeof window)return b;const e=localStorage.getItem(k);if(e){const t=parseInt(e,10);if(!Number.isNaN(t)&&t>=b)return t}return b}),[d,h]=r(!1),g=a(!1),u=a(l);u.current=l;const m=a(n);m.current=n;const p=a(i);return p.current=i,o(()=>{"sidebar"===e&&t&&m.current?.(u.current)},[e,t]),o(()=>{if("sidebar"!==e||!t)return;const n=e=>{if(!g.current)return;e.preventDefault();const t=window.innerWidth-e.clientX,n=.4*window.innerWidth,r=Math.min(Math.max(t,b),n);c(r),u.current=r,m.current?.(r)},r=()=>{g.current&&(g.current=!1,h(!1),document.body.style.cursor="",document.body.style.userSelect="",localStorage.setItem(k,String(u.current)),p.current?.())},a=()=>{const e=.4*window.innerWidth;if(u.current>e){const t=Math.max(e,b);c(t),u.current=t,m.current?.(t)}};return document.addEventListener("mousemove",n),document.addEventListener("mouseup",r),window.addEventListener("resize",a),()=>{document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",r),window.removeEventListener("resize",a)}},[e,t]),{sidebarWidth:l,handleResizeStart:e=>{e.preventDefault(),g.current=!0,h(!0),document.body.style.cursor="col-resize",document.body.style.userSelect="none",s?.()},defaultWidth:b,isResizing:d}}({mode:n,resizable:N,onWidthChange:C,onResizeStart:S,onResizeEnd:_});o(()=>{const e="sidebar"===n?N?te:se:0,t=e>0?e+6:0;if(document.documentElement.style.setProperty("--chatbot-sidebar-width",`${t}px`),document.documentElement.style.setProperty("--chatbot-transition",ie?"none":"all 225ms cubic-bezier(0.4, 0, 0.2, 1)"),L){const e=document.querySelector(L);if(e){const n=e.style.paddingRight,r=e.style.transition;return e.style.paddingRight=t>0?`${t}px`:"",e.style.transition=ie?"none":"padding-right 225ms cubic-bezier(0.4, 0, 0.2, 1)",()=>{e.style.paddingRight=n,e.style.transition=r,document.documentElement.style.setProperty("--chatbot-sidebar-width","0px")}}}return()=>{document.documentElement.style.setProperty("--chatbot-sidebar-width","0px")}},[L,n,te,se,N,ie]);const le=v??e(I,{size:24}),ce=m.firstName,de=E?.name||"Assistant",he={"--chat-accent":w,"--chat-accent-10":d(w,.1),"--chat-accent-40":d(w,.25),"--chat-accent-50":d(w,.5),"--chat-accent-dark":w};o(()=>{if(null===g?.sessions||g?.singleEndpoint||"legacy"===M||"ag-ui"===M)return;if(!F||G.current||!E)return;G.current=!0;const e=()=>{ee(null),localStorage.removeItem("filigranChatConversationId")};fetch(`${c}${g?.sessions??"/chat/sessions"}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({conversation_id:F,agent_slug:E.slug})}).then(t=>t.ok?t.json():(e(),null)).then(e=>{if(!e?.messages?.length)return;const t=e.messages.map((e,t)=>({id:`restored-${t}`,role:e.role,content:e.content,timestamp:new Date}));Y(t)}).catch(()=>{e()})},[F,E,c,g,G,Y,ee]);const ge=(()=>{const e="filigran-chatbot";switch(n){case"sidebar":return`${e} fixed right-0 bottom-0 flex flex-col bg-white dark:bg-[#1e1e2e] border-l border-gray-200 dark:border-white/10 z-[1200]`;case"floating":return`${e} fixed bottom-5 right-5 flex flex-col bg-white dark:bg-[#1e1e2e] rounded-xl shadow-[0_8px_32px_rgba(0,0,0,0.15)] dark:shadow-[0_8px_32px_rgba(0,0,0,0.4)] z-[1300] border border-gray-200 dark:border-white/10`;case"fullscreen":return`${e} fixed right-0 bottom-0 left-0 flex flex-col bg-gray-50 dark:bg-[#161622] z-[1400]`;default:return e}})(),ue={...he,..."sidebar"===n?{top:l,width:N?te:se}:"floating"===n?{width:380,height:560}:{top:l}};return t("div",{className:ge,style:ue,children:["sidebar"===n&&N&&e("div",{onMouseDown:oe,className:"absolute top-0 -left-1 bottom-0 w-2 cursor-col-resize z-10 group",children:e("div",{className:"absolute top-0 left-1/2 -translate-x-1/2 bottom-0 w-0.5 rounded bg-[var(--chat-accent)] opacity-0 transition-opacity group-hover:opacity-100 group-active:opacity-100"})}),e(J,{mode:n,agentName:de,agents:T,selectedAgent:E,agentMenuOpen:$,onAgentMenuToggle:()=>R(e=>!e),onAgentMenuClose:()=>R(!1),onSwitchAgent:e=>{e&&D(e,()=>{K()})},modeMenuOpen:z,onModeMenuToggle:()=>A(e=>!e),onModeMenuClose:()=>A(!1),onModeChange:i,onNewChat:K,onClose:s,logoIcon:le,agentDashboardUrl:u,t:p}),0===U.length?e(re,{firstName:ce,logoIcon:le,promptSuggestions:y,onPromptClick:W,t:p}):e(ne,{messages:U,isLoading:O,agentStatus:B,agentName:de,logoIcon:le,t:p}),e(Q,{inputValue:j,onInputChange:W,onSend:q,onStop:X,isLoading:O,attachedFiles:P,onFileAdd:H,onFileRemove:e=>Z(t=>t.filter((t,n)=>n!==e)),onPaste:V,t:p,mode:n})]})},se=({isOpen:n,onToggle:r,label:a="Ask Assistant",accentColor:o="#7b5cff",icon:s})=>{const i=s??e(I,{size:16});return t("button",{type:"button",onClick:r,className:"filigran-chatbot inline-flex items-center gap-1.5 px-3 py-[3px] text-[0.8125rem] font-medium whitespace-nowrap rounded-md border transition-colors",style:{borderColor:n?o:d(o,.5),color:o,backgroundColor:n?d(o,.1):"transparent"},onMouseEnter:e=>{e.currentTarget.style.borderColor=o,e.currentTarget.style.backgroundColor=d(o,.1)},onMouseLeave:e=>{e.currentTarget.style.borderColor=n?o:d(o,.5),e.currentTarget.style.backgroundColor=n?d(o,.1):"transparent"},children:[e("span",{className:"[&>svg]:w-4 [&>svg]:h-4",children:i}),a]})};export{oe as ChatPanel,se as ChatToggleButton};
|
|
1
|
+
import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import{useState as r,useRef as a,useEffect as o,useCallback as s}from"react";import{createPortal as i}from"react-dom";import l from"react-markdown";import c from"remark-gfm";function d(e,t){return`${e}${Math.round(255*t).toString(16).padStart(2,"0")}`}const h=e=>e;function g(e,t){const n=e.event;if("nextAgentFlow"===n){const n=e.data,r=n?.nodeId;return"INPROGRESS"===n?.status&&r&&(t.activeNodeId=r),{action:"noop"}}if("start"===n)return{action:"noop"};if("token"===n){return{action:"stream",content:(e.data??"").replace(/<br\s*\/?>/g,"\n")}}if("agentReasoning"===n){const n=e.data,r=n?.usedTools;return r?.length?(t.hasUsedTools=!0,{action:"status",status:"tool_start",tools:r.map(e=>e.tool)}):t.hasUsedTools?{action:"status",status:"analyzing"}:{action:"status",status:"thinking"}}if("usedTools"===n){t.hasUsedTools=!0;const n=e.data;return{action:"status",status:"tool_start",tools:Array.isArray(n)?n.map(e=>e.tool):[]}}if("metadata"===n){const t=e.data,n=t?.chatId;return n?{action:"set_chat_id",chatId:n}:{action:"noop"}}return"error"===n?{action:"error",content:e.data||""}:"end"===n?{action:"done",content:""}:{action:"noop"}}function u(e,t){const n=e.type;if("error"===n)return{action:"error",content:e.content||""};if("status"===n){const n=e.status;return"tool_done"===n||"wind_down"===n?{action:"noop"}:"streaming"===n?{action:"status",status:"streaming"}:"thinking_text"===n?{action:"status",status:"thinking_text",thinkingContent:e.content}:"tool_start"===n?(t.hasUsedTools=!0,{action:"status",status:"tool_start",tools:e.tools}):"thinking"===n&&t.hasUsedTools?{action:"status",status:"analyzing"}:{action:"status",status:n,tools:e.tools}}return"stream"===n?{action:"stream",content:e.content}:"done"===n?{action:"done",content:e.content,conversationId:e.conversation_id,toolNames:e.tool_names,toolCallCount:e.tool_call_count,iterations:e.iterations}:{action:"noop"}}function m(e,t){const n=e.type;if("RUN_STARTED"===n)return{action:"status",status:"thinking"};if("RUN_FINISHED"===n)return{action:"done",content:""};if("RUN_ERROR"===n)return{action:"error",content:e.message||"Unknown error"};if("STEP_STARTED"===n){return{action:"status",status:e.stepName||"thinking"}}if("STEP_FINISHED"===n)return{action:"noop"};if("TEXT_MESSAGE_START"===n)return{action:"status",status:"streaming"};if("TEXT_MESSAGE_CONTENT"===n){const t=e.delta;return t?{action:"stream",content:t}:{action:"noop"}}if("TEXT_MESSAGE_END"===n)return{action:"noop"};if("TEXT_MESSAGE_CHUNK"===n){const t=e.delta;return t?{action:"stream",content:t}:{action:"noop"}}if("TOOL_CALL_START"===n){t.hasUsedTools=!0;const n=e.toolCallName;return{action:"status",status:"tool_start",tools:n?[n]:[]}}if("TOOL_CALL_ARGS"===n)return{action:"noop"};if("TOOL_CALL_END"===n)return{action:"status",status:"analyzing"};if("TOOL_CALL_RESULT"===n)return{action:"noop"};if("TOOL_CALL_CHUNK"===n){const n=e.toolCallName;return n?(t.hasUsedTools=!0,{action:"status",status:"tool_start",tools:[n]}):{action:"noop"}}return"REASONING_START"===n||"REASONING_MESSAGE_START"===n||"REASONING_MESSAGE_CONTENT"===n||"REASONING_MESSAGE_CHUNK"===n?{action:"status",status:"thinking"}:{action:"noop"}}const p="filigranChatConversationId",w="filigranChatLegacyChatId";function x({apiBaseUrl:e,apiEndpoints:t,backendType:n="rest",agentSlug:o,t:s}){const i="legacy"===n,[l,c]=r([]),[d,h]=r(""),[x,f]=r(!1),[b,k]=r(null),[v,y]=r(()=>"undefined"==typeof window?null:localStorage.getItem(p)),[N,C]=r([]),[S,_]=r(()=>"undefined"==typeof window?null:localStorage.getItem(w)),L=a(!1),I=a(null),M=a(!1),z=e=>{if(!e)return;const t=[];Array.from(e).forEach(n=>{const r=new FileReader;r.onload=()=>{t.push({name:n.name,type:n.type,size:n.size,dataUrl:r.result}),t.length===e.length&&C(e=>[...e,...t])},r.readAsDataURL(n)})};return{messages:l,inputValue:d,setInputValue:h,isLoading:x,agentStatus:b,attachedFiles:N,conversationId:v,historyLoadedRef:L,handleFileAdd:z,handlePaste:e=>{const{files:t}=e.clipboardData;t.length>0&&(e.preventDefault(),z(t))},handleSendMessage:async()=>{if(!d.trim()&&0===N.length||x)return;const r=d.trim(),a={id:crypto.randomUUID(),role:"user",content:r,timestamp:new Date,files:N.length>0?[...N]:void 0};c(e=>[...e,a]),h(""),C([]),f(!0),k({status:"thinking"}),M.current=!1;const l=crypto.randomUUID();c(e=>[...e,{id:l,role:"assistant",content:"",timestamp:new Date}]);try{const a=new AbortController;I.current=a;const d=function(e,t,n){switch(e){case"legacy":return{question:t,chatId:n.legacyChatId??void 0,streaming:!0};case"ag-ui":return{threadId:n.conversationId??crypto.randomUUID(),runId:crypto.randomUUID(),messages:[{id:crypto.randomUUID(),role:"user",content:t}],tools:[],context:[],state:{},forwardedProps:n.agentSlug?{agentSlug:n.agentSlug}:{}};default:return{content:t,conversation_id:n.conversationId,agent_slug:n.agentSlug}}}(n,r,{legacyChatId:S,conversationId:v,agentSlug:o}),h=await fetch(i||t?.singleEndpoint?e:`${e}${t?.messages??"/chat/messages"}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(d),signal:a.signal});if(!h.ok||!h.body)return void c(e=>e.map(e=>e.id===l?{...e,content:s("Unable to connect. Please check the configuration.")}:e));const x=function(e){switch(e){case"legacy":return g;case"ag-ui":return m;default:return u}}(n),f={hasUsedTools:!1,activeNodeId:""},b=h.body.getReader(),N=new TextDecoder;let C="",L="",z=!1;for(;;){const{done:e,value:t}=await b.read();if(e)break;C+=N.decode(t,{stream:!0});const n=C.split("\n");C=n.pop()||"";for(const e of n){const t=e.replace(/\r$/,"");if(!t.startsWith("data:"))continue;const n=t.startsWith("data: ")?t.slice(6):t.slice(5);try{const e=x(JSON.parse(n),f);switch(f.hasUsedTools=f.hasUsedTools||M.current,e.action){case"status":"tool_start"===e.status&&(M.current=!0),"thinking_text"===e.status?k(t=>({...t,status:t?.status??"thinking",thinkingContent:(t?.thinkingContent??"")+(e.thinkingContent??"")})):k(t=>({status:e.status,tools:e.tools,thinkingContent:t?.thinkingContent}));break;case"stream":L+=e.content,k({status:"streaming"}),c(e=>e.map(e=>e.id===l?{...e,content:L}:e));break;case"done":z=!0,e.conversationId&&(y(e.conversationId),localStorage.setItem(p,e.conversationId)),c(t=>t.map(t=>t.id===l?{...t,content:e.content||L,toolNames:e.toolNames,toolCallCount:e.toolCallCount,iterations:e.iterations}:t));break;case"error":return void c(t=>t.map(t=>t.id===l?{...t,content:e.content||s("Unable to connect. Please check the configuration.")}:t));case"set_chat_id":_(e.chatId),localStorage.setItem(w,e.chatId)}M.current=f.hasUsedTools}catch{}}}L&&!z&&c(e=>e.map(e=>e.id===l?{...e,content:L||"No response."}:e))}catch(e){if(e instanceof DOMException&&"AbortError"===e.name)return;c(e=>e.map(e=>e.id===l?{...e,content:s("Sorry, an error occurred. Please try again.")}:e))}finally{I.current=null,f(!1),k(null),M.current=!1}},handleNewChat:()=>{I.current?.abort(),I.current=null,c([]),h(""),C([]),f(!1),k(null),M.current=!1,L.current=!1,i?(_(null),localStorage.removeItem(w)):(y(null),localStorage.removeItem(p))},handleStopGenerating:()=>{I.current?.abort(),I.current=null,f(!1),k(null),M.current=!1,c(e=>e.filter(e=>!("assistant"===e.role&&!e.content)))},setAttachedFiles:C,setMessages:c,setConversationId:y}}const f="filigranChatAgentSlug";const b=400,k="filigranChatSidebarWidth";const v=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e("path",{d:"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"})}),y=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"}),e("path",{d:"M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"}),e("path",{d:"M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"}),e("path",{d:"M17.599 6.5a3 3 0 0 0 .399-1.375"}),e("path",{d:"M6.003 5.125A3 3 0 0 0 6.401 6.5"}),e("path",{d:"M3.477 10.896a4 4 0 0 1 .585-.396"}),e("path",{d:"M19.938 10.5a4 4 0 0 1 .585.396"}),e("path",{d:"M6 18a4 4 0 0 1-1.967-.516"}),e("path",{d:"M19.967 17.484A4 4 0 0 1 18 18"})]}),N=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e("path",{d:"M20 6 9 17l-5-5"})}),C=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e("path",{d:"m6 9 6 6 6-6"})}),S=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M18 6 6 18"}),e("path",{d:"m6 6 12 12"})]}),_=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}),e("path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"})]}),L=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}),e("path",{d:"M3 5V19A9 3 0 0 0 21 19V5"}),e("path",{d:"M3 12A9 3 0 0 0 21 12"})]}),I=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",stroke:"none",className:t,children:e("path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"})}),M=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M12 20h9"}),e("path",{d:"M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z"})]}),z=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M15 3h6v6"}),e("path",{d:"M10 14 21 3"}),e("path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"})]}),A=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}),e("path",{d:"M14 2v4a2 2 0 0 0 2 2h4"})]}),T=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M11 13H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7"}),e("rect",{width:"12",height:"12",x:"10",y:"10",rx:"2"})]}),E=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M8 3v3a2 2 0 0 1-2 2H3"}),e("path",{d:"M21 8h-3a2 2 0 0 1-2-2V3"}),e("path",{d:"M3 16h3a2 2 0 0 0 2 2v3"}),e("path",{d:"M16 21v-3a2 2 0 0 1 2-2h3"})]}),$=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M8 3H5a2 2 0 0 0-2 2v3"}),e("path",{d:"M21 8V5a2 2 0 0 0-2-2h-3"}),e("path",{d:"M3 16v3a2 2 0 0 0 2 2h3"}),e("path",{d:"M16 21h3a2 2 0 0 0 2-2v-3"})]}),R=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("circle",{cx:"12",cy:"12",r:"10"}),e("path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"}),e("path",{d:"M2 12h20"})]}),D=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("circle",{cx:"12",cy:"12",r:"10"}),e("path",{d:"M12 16v-4"}),e("path",{d:"M12 8h.01"})]}),U=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}),e("path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"})]}),j=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("circle",{cx:"11",cy:"11",r:"8"}),e("path",{d:"m21 21-4.3-4.3"})]}),W=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"m22 2-7 20-4-9-9-4Z"}),e("path",{d:"m22 2-11 11"})]}),O=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}),e("path",{d:"M15 3v18"})]}),B=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e("path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"})}),P=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("circle",{cx:"12",cy:"12",r:"10"}),e("rect",{width:"6",height:"6",x:"9",y:"9"})]}),F=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("polyline",{points:"4 17 10 11 4 5"}),e("line",{x1:"12",x2:"20",y1:"19",y2:"19"})]}),G=({className:n,size:r=24})=>t("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:n,children:[e("path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}),e("circle",{cx:"9",cy:"7",r:"4"}),e("line",{x1:"19",x2:"19",y1:"8",y2:"14"}),e("line",{x1:"22",x2:"16",y1:"11",y2:"11"})]}),H=({className:t,size:n=24})=>e("svg",{xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e("path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"})});const V=({open:t,onClose:n,anchorRef:l,placement:c="bottom-start",width:d=280,children:h})=>{const g=a(null),[u,m]=r({top:0,left:0});if(function(e,t,n=!0){o(()=>{if(!n)return;const r=n=>{e.current&&!e.current.contains(n.target)&&t()};return document.addEventListener("mousedown",r),document.addEventListener("touchstart",r),()=>{document.removeEventListener("mousedown",r),document.removeEventListener("touchstart",r)}},[e,t,n])}(g,s(()=>n(),[n]),t),o(()=>{if(!t||!l.current)return;const e=l.current.getBoundingClientRect(),n="bottom-end"===c?e.right-d:e.left;m({top:e.bottom+4,left:n})},[t,l,c,d]),!t)return null;const p=function(e){let t=e;for(;t;){if(t.classList.contains("filigran-chatbot"))return t;t=t.parentElement}return document.body}(l.current);return i(e("div",{ref:g,className:"fixed z-[10000] rounded-[10px] overflow-hidden border border-gray-200 dark:border-white/10 bg-white dark:bg-[#2a2a3e] shadow-xl",style:{top:u.top,left:u.left,width:d},children:h}),p)},q=({size:t=16,className:n=""})=>e("div",{className:`animate-spin rounded-full border-2 border-current/20 border-t-[var(--chat-accent)] ${n}`,style:{width:t,height:t}});function K(e){let t=e;for(;t;){if(t.classList.contains("filigran-chatbot"))return t;t=t.parentElement}return document.body}const X=({title:n,children:o})=>{const s=a(null),[l,c]=r(!1),[d,h]=r({top:0,left:0});if(!n)return o;return t("span",{ref:s,className:"inline-flex",onMouseEnter:()=>{if(!s.current)return;const e=s.current.getBoundingClientRect();h({top:e.top-4,left:e.left+e.width/2}),c(!0)},onMouseLeave:()=>c(!1),children:[o,l&&i(e("span",{className:"pointer-events-none fixed z-[10001] -translate-x-1/2 -translate-y-full whitespace-nowrap rounded-md bg-gray-900 dark:bg-gray-100 px-2 py-1 text-xs text-white dark:text-gray-900 shadow-lg",style:{top:d.top,left:d.left},role:"tooltip",children:n}),K(s.current))]})},Z=[{mode:"floating",label:"Floating",getIcon:t=>e(T,{...t})},{mode:"sidebar",label:"Sidebar",getIcon:t=>e(O,{...t})},{mode:"fullscreen",label:"Full screen",getIcon:t=>e($,{...t})}],J=({mode:n,agentName:r,agents:o,selectedAgent:s,agentMenuOpen:i,onAgentMenuToggle:l,onAgentMenuClose:c,onSwitchAgent:d,modeMenuOpen:h,onModeMenuToggle:g,onModeMenuClose:u,onModeChange:m,onNewChat:p,onClose:w,logoIcon:x,agentDashboardUrl:f,t:b})=>{const k=a(null),v=a(null),y="sidebar"===n?O:"fullscreen"===n?E:T;return t("div",{className:"flex items-center px-3 py-2 min-h-[48px] border-b border-gray-200 dark:border-white/10 bg-gradient-to-br from-[var(--chat-accent-dark)]/[0.13] to-[var(--chat-accent)]/[0.07] "+("floating"===n?"rounded-t-xl":""),children:[t("button",{ref:k,type:"button",onClick:l,className:"flex items-center gap-1.5 text-sm font-semibold text-gray-900 dark:text-white px-2 py-1 rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 transition-colors",children:[e("span",{className:"flex items-center text-[var(--chat-accent)] [&>svg]:w-[18px] [&>svg]:h-[18px]",children:x}),r,e(C,{size:16,className:"text-gray-400 dark:text-white/30"})]}),t(V,{open:i,onClose:c,anchorRef:k,width:280,children:[e("span",{className:"block px-4 pt-3 pb-1 text-[0.68rem] tracking-[1px] uppercase text-gray-400 dark:text-white/40",children:b("Switch to another agent")}),0===o.length&&e("div",{className:"px-4 py-2",children:e(q,{size:16})}),e("div",{children:o.map(n=>t("button",{type:"button",onClick:()=>d(n),className:"w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors "+(n.id===s?.id?"bg-[var(--chat-accent)]/10":""),children:[e("div",{className:"w-7 h-7 rounded-full flex items-center justify-center shrink-0 bg-gradient-to-br from-[var(--chat-accent)]/20 to-[var(--chat-accent)]/5",children:e("span",{className:"text-[var(--chat-accent)] [&>svg]:w-4 [&>svg]:h-4",children:x})}),t("div",{className:"min-w-0",children:[e("div",{className:"text-[0.8125rem] font-medium text-gray-900 dark:text-white truncate",children:n.name}),n.description&&e("div",{className:"text-[0.7rem] text-gray-500 dark:text-white/40 truncate",children:n.description})]})]},n.id))}),e("div",{className:"h-px bg-gray-200 dark:bg-white/10 mx-2"}),t("div",{children:[f&&t("button",{type:"button",onClick:()=>{c(),window.open(`${f}/agents`,"_blank")},className:"w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors",children:[e(z,{size:18,className:"text-gray-400 dark:text-white/40 shrink-0"}),e("span",{className:"text-[0.8125rem] text-gray-700 dark:text-white/70",children:b("Browse agents")})]}),f&&t("button",{type:"button",onClick:()=>{c(),window.open(`${f}/agents/new`,"_blank")},className:"w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors",children:[e(G,{size:18,className:"text-gray-400 dark:text-white/40 shrink-0"}),e("span",{className:"text-[0.8125rem] text-gray-700 dark:text-white/70",children:b("Create agent")})]})]})]}),e("div",{className:"flex-1"}),e(X,{title:b("New chat"),children:e("button",{type:"button",onClick:p,className:"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors",children:e(M,{size:18})})}),e(X,{title:b("Switch view"),children:e("button",{ref:v,type:"button",onClick:g,className:"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors",children:e(y,{size:18})})}),t(V,{open:h,onClose:u,anchorRef:v,placement:"bottom-end",width:180,children:[e("span",{className:"block px-4 pt-3 pb-1 text-[0.68rem] tracking-[1px] uppercase text-gray-400 dark:text-white/40",children:b("Switch to")}),e("div",{className:"pb-1",children:Z.map(r=>t("button",{type:"button",onClick:()=>{m(r.mode),u()},className:"w-full flex items-center gap-3 px-4 py-1 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors "+(n===r.mode?"bg-[var(--chat-accent)]/10":""),children:[r.getIcon({size:18,className:"text-gray-400 dark:text-white/40"}),e("span",{className:"text-[0.8125rem] text-gray-700 dark:text-white/70",children:b(r.label)})]},r.mode))})]}),e(X,{title:b("Close"),children:e("button",{type:"button",onClick:w,className:"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors",children:e(S,{size:18})})})]})},Q=({inputValue:n,onInputChange:r,onSend:o,onStop:s,isLoading:i,attachedFiles:l,onFileAdd:c,onFileRemove:d,onPaste:h,t:g,mode:u})=>{const m=a(null),p=a(null),w=n.trim()||l.length>0;return t("div",{className:"px-4 py-3 border-t border-gray-200 dark:border-white/10 "+("floating"===u?"rounded-b-xl":""),children:[l.length>0&&e("div",{className:"flex gap-1.5 flex-wrap mb-2",children:l.map((n,r)=>t("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.7rem] text-gray-600 dark:text-white/60",children:[e(A,{size:14}),n.name,e("button",{type:"button",onClick:()=>d(r),className:"ml-0.5 text-gray-400 dark:text-white/30 hover:text-gray-600 dark:hover:text-white/60",children:"×"})]},r))}),t("div",{className:"flex items-center border border-gray-200 dark:border-white/10 rounded-xl px-2 py-1 transition-colors focus-within:border-[var(--chat-accent)]",children:[e("input",{ref:m,type:"file",multiple:!0,hidden:!0,onChange:e=>{c(e.target.files),e.target.value=""}}),e("button",{type:"button",onClick:()=>m.current?.click(),className:"w-8 h-8 flex items-center justify-center shrink-0 rounded-lg text-gray-400 dark:text-white/30 hover:bg-gray-100 dark:hover:bg-white/10 mr-0.5 transition-colors",children:e(v,{size:18})}),e("textarea",{ref:p,placeholder:g("Ask a question..."),value:n,onChange:e=>{r(e.target.value);const t=e.target;t.style.height="auto",t.style.height=`${Math.min(t.scrollHeight,120)}px`},onKeyDown:e=>{"Enter"!==e.key||e.shiftKey||(e.preventDefault(),o())},onPaste:h,rows:1,className:"flex-1 bg-transparent border-none outline-none resize-none text-[0.8125rem] py-1.5 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-white/30 filigran-chat-scrollable",style:{maxHeight:120}}),e(X,{title:i?g("Stop generating"):"",children:e("button",{type:"button",onClick:i?s:o,disabled:!i&&!w,className:"p-1.5 rounded-lg w-8 h-8 flex items-center justify-center transition-all duration-150 "+(i?"text-red-500 bg-red-500/10 hover:bg-red-500/20":w?"text-[var(--chat-accent)] bg-[var(--chat-accent)]/10 hover:bg-[var(--chat-accent)]/20":"text-gray-300 dark:text-white/20 cursor-not-allowed"),children:e(i?P:W,{size:18})})})]}),e("p",{className:"text-center text-[0.65rem] text-gray-400 dark:text-white/30 mt-1.5 opacity-70",children:g("Uses AI. Verify results.")})]})};function Y({content:n}){const r=a(null),s=n.replace(/```[\s\S]*?```/g," ").replace(/`([^`]+)`/g,"$1").replace(/\*\*(.+?)\*\*/g,"$1").replace(/__(.+?)__/g,"$1").replace(/\*(.+?)\*/g,"$1").replace(/_(.+?)_/g,"$1").replace(/#{1,6}\s+/g,"").replace(/[*\->]+/g," ").replace(/\s+/g," ").trim();return o(()=>{r.current&&(r.current.scrollTop=r.current.scrollHeight)},[s]),s.length<3?null:t("div",{ref:r,className:"ml-11 max-w-[70%] max-h-20 overflow-hidden relative rounded-md border-l-2 bg-[var(--chat-accent)]/[0.03] pl-3 pr-3 py-2",style:{animation:"reasoningGlow 3s ease-in-out infinite, chat-fade-in 0.5s ease-out"},children:[e("p",{className:"text-[13px] leading-[1.35rem] text-gray-400 dark:text-white/40 break-words m-0",children:s}),e("div",{className:"absolute inset-x-0 bottom-0 h-5 bg-gradient-to-t from-white/90 dark:from-[#1e1e2e]/90 to-transparent pointer-events-none"})]})}const ee=({agentStatus:r,logoIcon:a,t:o})=>{const{label:s,StatusIcon:i,showDots:l}=function(e,t){if(!e)return{label:t("Thinking..."),StatusIcon:y,showDots:!1};switch(e.status){case"tool_start":{const n=e.tools??[],r=n.map(e=>e.toLowerCase());if(r.some(e=>"spawn_background_task"===e)){const e=n.filter(e=>"spawn_background_task"===e).length;return{label:e>1?`${t("Delegating")} ${e} ${t("tasks")}…`:`${t("Delegating task")}…`,StatusIcon:G,showDots:!1}}if(r.some(e=>"check_task_status"===e)){const e=n.filter(e=>"check_task_status"===e).length,r=e>1?`${e} ${t("background tasks")}`:t("background task");return{label:`${t("Waiting for")} ${r}…`,StatusIcon:B,showDots:!1}}if(r.some(e=>"get_task_result"===e)){const e=n.filter(e=>"get_task_result"===e).length,r=e>1?`${e} ${t("tasks")}`:t("task");return{label:`${t("Collecting results from")} ${r}…`,StatusIcon:B,showDots:!1}}let a,o=H;if(r.some(e=>e.includes("search")||e.includes("list"))?o=j:r.some(e=>e.includes("read")||e.includes("get")||e.includes("query"))?o=L:r.some(e=>e.includes("send")||e.includes("create")||e.includes("draft")||e.includes("reply")||e.includes("flag"))?o=U:r.some(e=>e.includes("code")||e.includes("execute"))?o=F:r.some(e=>e.includes("web")||e.includes("browse"))&&(o=R),n.length>0){const e=n.map(e=>e.replace(/_/g," ").replace(/\b\w/g,e=>e.toUpperCase())),t=Array.from(new Set(e));a=1===t.length?`${t[0]}…`:`${t[0]} (+${t.length-1} more)…`}else a=t("Using tools…");return{label:a,StatusIcon:o,showDots:!1}}case"analyzing":return{label:t("Analyzing results…"),StatusIcon:B,showDots:!1};case"composing":return{label:t("Composing answer…"),StatusIcon:y,showDots:!0};case"consulting":{const n=e.tools?.[0]??"agent";return{label:`${t("Consulting")} ${n}…`,StatusIcon:G,showDots:!1}}case"delegating":{const n=e.tools?.filter(e=>"spawn_background_task"===e).length??0;return{label:n>1?`${t("Delegating")} ${n} ${t("tasks")}…`:`${t("Delegating task")}…`,StatusIcon:G,showDots:!1}}case"polling":{const n=e.tools?.filter(e=>"check_task_status"===e).length??0,r=n>1?`${n} ${t("background tasks")}`:t("background task");return{label:`${t("Waiting for")} ${r}…`,StatusIcon:B,showDots:!1}}case"collecting":{const n=e.tools?.filter(e=>"get_task_result"===e).length??0,r=n>1?`${n} ${t("tasks")}`:t("task");return{label:`${t("Collecting results from")} ${r}…`,StatusIcon:B,showDots:!1}}case"transferring":{const n=e.tools?.[0]??"agent";return{label:`${t("Transferring to")} ${n}…`,StatusIcon:z,showDots:!1}}default:return{label:t("Thinking..."),StatusIcon:y,showDots:!1}}}(r,o),c=r?.thinkingContent;return t(n,{children:[t("div",{className:"flex gap-3 items-center justify-start",children:[e("div",{className:"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-[var(--chat-accent)]/15 to-[var(--chat-accent)]/5",children:e("span",{className:"text-[var(--chat-accent)] [&>svg]:w-4 [&>svg]:h-4",children:a})}),t("div",{className:"rounded-lg bg-gray-50 dark:bg-white/[0.03] px-4 py-3 relative overflow-hidden",children:[e("div",{className:"absolute inset-0 bg-gradient-to-r from-[var(--chat-accent)]/[0.03] via-transparent to-[var(--chat-accent)]/[0.03] animate-pulse pointer-events-none"}),t("div",{className:"relative flex items-center gap-2.5",children:[l?e("div",{className:"flex gap-[3px] items-center h-3.5 w-3.5 justify-center",children:[0,.15,.3].map((t,n)=>e("span",{className:"h-[5px] w-[5px] rounded-full bg-[var(--chat-accent)]/50",style:{animation:`chat-dot 1s ease-in-out infinite ${t}s`}},n))}):e(i,{size:14,className:"text-[var(--chat-accent)] animate-pulse transition-all duration-300"}),e("span",{className:"text-sm text-gray-500 dark:text-white/50 transition-all duration-300",children:s})]})]})]}),c&&e(Y,{content:c})]})},te=({content:n})=>{const[a,o]=r(null);return e(l,{remarkPlugins:[c],components:{p:({children:t})=>e("p",{className:"mb-3 last:mb-0 leading-7 break-words text-[0.8125rem] text-gray-900 dark:text-white/90",children:t}),code:({className:n,children:r})=>{const s=/language-(\w+)/.exec(n||""),i=String(r).replace(/\n$/,"");return s?t("div",{className:"my-3 rounded-lg border border-gray-200 dark:border-white/10 overflow-hidden bg-gray-50 dark:bg-white/[0.03]",children:[t("div",{className:"flex items-center justify-between px-3 py-1.5 border-b border-gray-200 dark:border-white/10 bg-gray-100 dark:bg-white/[0.03]",children:[e("span",{className:"text-[0.7rem] text-gray-500 dark:text-white/40 font-mono",children:s[1]}),e("button",{type:"button",onClick:()=>{return e=i,navigator.clipboard.writeText(e),o(e),void setTimeout(()=>o(null),2e3);var e},className:"p-0.5 rounded hover:bg-gray-200 dark:hover:bg-white/10 transition-colors",children:a===i?e(N,{size:14,className:"text-green-500"}):e(_,{size:14,className:"text-gray-400 dark:text-white/40"})})]}),e("pre",{className:"m-0 px-3 py-2 overflow-x-auto",children:e("code",{className:"font-mono text-xs leading-[1.7] text-gray-800 dark:text-white/90 whitespace-pre",children:i})})]}):e("code",{className:"bg-gray-100 dark:bg-white/[0.08] px-1.5 py-0.5 rounded font-mono text-xs text-[var(--chat-accent)]",children:r})},ul:({children:t})=>e("ul",{className:"pl-5 mb-3 text-[0.8125rem] text-gray-900 dark:text-white/90 [&_li]:mb-1 marker:text-[var(--chat-accent)]/50",children:t}),ol:({children:t})=>e("ol",{className:"pl-5 mb-3 text-[0.8125rem] text-gray-900 dark:text-white/90 [&_li]:mb-1 marker:text-[var(--chat-accent)]/50",children:t}),blockquote:({children:t})=>e("blockquote",{className:"my-3 border-l-2 border-[var(--chat-accent)]/30 bg-[var(--chat-accent)]/[0.03] pl-4 pr-3 py-2 rounded-r-md italic text-gray-500 dark:text-white/60",children:t}),a:({href:t,children:n})=>e("a",{href:t,target:"_blank",rel:"noopener noreferrer",className:"text-[var(--chat-accent)] underline underline-offset-2 hover:brightness-125",children:n}),h1:({children:t})=>e("h1",{className:"mt-4 first:mt-0 mb-2 font-bold text-base text-gray-900 dark:text-white",children:t}),h2:({children:t})=>e("h2",{className:"mt-3 first:mt-0 mb-2 font-bold text-[0.9rem] text-gray-900 dark:text-white",children:t}),h3:({children:t})=>e("h3",{className:"mt-3 first:mt-0 mb-1.5 font-semibold text-[0.85rem] text-gray-900 dark:text-white",children:t}),table:({children:t})=>e("div",{className:"my-3 overflow-x-auto rounded-lg border border-gray-200 dark:border-white/10",children:e("table",{className:"w-full border-collapse text-xs",children:t})}),th:({children:t})=>e("th",{className:"px-3 py-2 text-left font-semibold bg-gray-50 dark:bg-white/[0.04] border-b border-gray-200 dark:border-white/10 text-gray-900 dark:text-white",children:t}),td:({children:t})=>e("td",{className:"px-3 py-2 border-b border-gray-200 dark:border-white/10 text-gray-700 dark:text-white/80",children:t})},children:n})},ne=({messages:s,isLoading:i,agentStatus:l,agentName:c,logoIcon:d,t:h})=>{const g=a(null),[u,m]=r(null);return o(()=>{g.current?.scrollIntoView({behavior:"smooth"})},[s]),t("div",{className:"flex-1 overflow-y-auto px-4 py-3 flex flex-col gap-4 filigran-chat-scrollable",children:[s.map(r=>{const a="assistant"===r.role,o=!r.content;return a&&o&&i?e("div",{children:e(ee,{agentStatus:l,logoIcon:d,t:h})},r.id):t("div",{className:"flex flex-col "+(a?"items-start":"items-end"),children:[a&&t("div",{className:"flex items-center gap-1.5 mb-1",children:[e("div",{className:"w-6 h-6 rounded-lg flex items-center justify-center bg-gradient-to-br from-[var(--chat-accent)]/20 to-[var(--chat-accent)]/5",children:e("span",{className:"text-[var(--chat-accent)] [&>svg]:w-3 [&>svg]:h-3",children:d})}),e("span",{className:"font-semibold text-xs text-gray-900 dark:text-white",children:c})]}),r.files&&r.files.length>0&&e("div",{className:"flex gap-1.5 flex-wrap mb-1.5",children:r.files.map((n,r)=>t("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.7rem] text-gray-600 dark:text-white/60",children:[e(A,{size:14}),n.name]},r))}),t("div",{className:"max-w-[90%] "+(a?"pl-1 py-1 text-[0.8125rem] leading-7":"px-3.5 py-2 rounded-[14px_14px_4px_14px] bg-[var(--chat-accent-dark)] text-white text-[0.8125rem] leading-6"),children:[a?e(te,{content:r.content}):r.content,a&&o&&!i&&e("span",{className:"text-[0.8125rem] text-gray-400 dark:text-white/40 italic",children:"..."}),a&&!o&&i&&e("span",{className:"inline-block w-1.5 h-4 bg-[var(--chat-accent)]/70 rounded-sm ml-0.5 animate-pulse align-text-bottom"})]}),a&&!o&&!i&&r.toolNames&&r.toolNames.length>0&&t(n,{children:[e("button",{type:"button",onClick:()=>m(u===r.id?null:r.id),className:"mt-0.5 p-1 rounded-lg opacity-50 hover:opacity-100 hover:text-[var(--chat-accent)] transition-opacity",title:h("Reasoning details"),children:e(D,{size:14})}),u===r.id&&t("div",{className:"mt-1.5 p-3 rounded-lg bg-gray-50 dark:bg-white/[0.04] border border-gray-200 dark:border-white/10",children:[t("p",{className:"text-[0.7rem] text-gray-500 dark:text-white/40 mb-1.5",children:[r.iterations&&r.iterations>1?`${r.iterations} iterations · `:"",r.toolCallCount??r.toolNames.length," ",1===(r.toolCallCount??r.toolNames.length)?h("tool call"):h("tool calls")]}),e("div",{className:"flex flex-wrap gap-1",children:Array.from(new Set(r.toolNames)).map(t=>e("span",{className:"inline-flex items-center px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.68rem] font-mono text-gray-500 dark:text-white/40",children:t.replace(/_/g," ")},t))})]})]})]},r.id)}),e("div",{ref:g})]})},re=({firstName:n,logoIcon:r,promptSuggestions:a,onPromptClick:o,t:s})=>t("div",{className:"flex-1 flex flex-col items-center justify-center px-6 pb-8",children:[e("span",{className:"text-[var(--chat-accent)] mb-4 [&>svg]:w-12 [&>svg]:h-12 drop-shadow-[0_0_12px_var(--chat-accent-40)]",children:r}),t("h2",{className:"text-xl font-medium mb-6 text-center text-gray-900 dark:text-white",style:{fontFamily:'"Geologica", sans-serif'},children:[s("How can I help you, "),n,"?"]}),t("div",{className:"w-full max-w-[320px]",children:[e("span",{className:"block text-center mb-2 text-[0.65rem] tracking-[1.5px] uppercase text-[var(--chat-accent)] font-semibold",children:s("Suggestions")}),a.map(t=>e("button",{type:"button",onClick:()=>o(t),className:"w-full text-left text-[0.8125rem] text-gray-800 dark:text-white py-1.5 px-3 mb-1 rounded-lg border border-gray-200 dark:border-white/10 bg-transparent transition-colors hover:bg-[var(--chat-accent-10)] hover:border-[var(--chat-accent-50)]",children:s(t)},t))]})]}),ae=["Help me create a new simulation scenario","What are the latest attack patterns?","How do I configure detection rules?","Summarize my recent findings"],oe=({mode:n,onClose:s,onModeChange:i,topOffset:l=0,apiBaseUrl:c,apiEndpoints:g,agentDashboardUrl:u,user:m,t:p=h,accentColor:w="#7b5cff",logoIcon:v,promptSuggestions:y=ae,resizable:N=!1,onWidthChange:C,onResizeStart:S,onResizeEnd:_,pushContentSelector:L,backendType:M="rest"})=>{const[z,A]=r(!1),{agents:T,selectedAgent:E,agentMenuOpen:$,setAgentMenuOpen:R,handleSwitchAgent:D}=function({apiBaseUrl:e,apiEndpoints:t,backendType:n="rest"}){const[a,s]=r([]),[i,l]=r(null),[c,d]=r(!1);return o(()=>{null===t?.agents||t?.singleEndpoint||"legacy"===n||fetch(`${e}${t?.agents??"/chat/agents"}`).then(e=>e.ok?e.json():[]).then(e=>{if(s(e),e.length>0&&!i){const t=localStorage.getItem(f),n=t?e.find(e=>e.slug===t):null;l(n||e[0])}}).catch(()=>{})},[e,t]),{agents:a,selectedAgent:i,setSelectedAgent:l,agentMenuOpen:c,setAgentMenuOpen:d,handleSwitchAgent:(e,t)=>{e.id!==i?.id?(l(e),e.slug&&localStorage.setItem(f,e.slug),d(!1),t?.()):d(!1)}}}({apiBaseUrl:c,apiEndpoints:g,backendType:M}),{messages:U,inputValue:j,setInputValue:W,isLoading:O,agentStatus:B,attachedFiles:P,conversationId:F,historyLoadedRef:G,handleFileAdd:H,handlePaste:V,handleSendMessage:q,handleNewChat:K,handleStopGenerating:X,setAttachedFiles:Z,setMessages:Y,setConversationId:ee}=x({apiBaseUrl:c,apiEndpoints:g,backendType:M,agentSlug:E?.slug,t:p}),{sidebarWidth:te,handleResizeStart:oe,defaultWidth:se,isResizing:ie}=function({mode:e,resizable:t,onWidthChange:n,onResizeStart:s,onResizeEnd:i}){const[l,c]=r(()=>{if("undefined"==typeof window)return b;const e=localStorage.getItem(k);if(e){const t=parseInt(e,10);if(!Number.isNaN(t)&&t>=b)return t}return b}),[d,h]=r(!1),g=a(!1),u=a(l);u.current=l;const m=a(n);m.current=n;const p=a(i);return p.current=i,o(()=>{"sidebar"===e&&t&&m.current?.(u.current)},[e,t]),o(()=>{if("sidebar"!==e||!t)return;const n=e=>{if(!g.current)return;e.preventDefault();const t=window.innerWidth-e.clientX,n=.4*window.innerWidth,r=Math.min(Math.max(t,b),n);c(r),u.current=r,m.current?.(r)},r=()=>{g.current&&(g.current=!1,h(!1),document.body.style.cursor="",document.body.style.userSelect="",localStorage.setItem(k,String(u.current)),p.current?.())},a=()=>{const e=.4*window.innerWidth;if(u.current>e){const t=Math.max(e,b);c(t),u.current=t,m.current?.(t)}};return document.addEventListener("mousemove",n),document.addEventListener("mouseup",r),window.addEventListener("resize",a),()=>{document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",r),window.removeEventListener("resize",a)}},[e,t]),{sidebarWidth:l,handleResizeStart:e=>{e.preventDefault(),g.current=!0,h(!0),document.body.style.cursor="col-resize",document.body.style.userSelect="none",s?.()},defaultWidth:b,isResizing:d}}({mode:n,resizable:N,onWidthChange:C,onResizeStart:S,onResizeEnd:_});o(()=>{const e="sidebar"===n?N?te:se:0,t=e>0?e+6:0;if(document.documentElement.style.setProperty("--chatbot-sidebar-width",`${t}px`),document.documentElement.style.setProperty("--chatbot-transition",ie?"none":"all 225ms cubic-bezier(0.4, 0, 0.2, 1)"),L){const e=document.querySelector(L);if(e){const n=e.style.paddingRight,r=e.style.transition;return e.style.paddingRight=t>0?`${t}px`:"",e.style.transition=ie?"none":"padding-right 225ms cubic-bezier(0.4, 0, 0.2, 1)",()=>{e.style.paddingRight=n,e.style.transition=r,document.documentElement.style.setProperty("--chatbot-sidebar-width","0px")}}}return()=>{document.documentElement.style.setProperty("--chatbot-sidebar-width","0px")}},[L,n,te,se,N,ie]);const le=v??e(I,{size:24}),ce=m.firstName,de=E?.name||"Assistant",he={"--chat-accent":w,"--chat-accent-10":d(w,.1),"--chat-accent-40":d(w,.25),"--chat-accent-50":d(w,.5),"--chat-accent-dark":w};o(()=>{if(null===g?.sessions||g?.singleEndpoint||"legacy"===M||"ag-ui"===M)return;if(!F||G.current||!E)return;G.current=!0;const e=()=>{ee(null),localStorage.removeItem("filigranChatConversationId")};fetch(`${c}${g?.sessions??"/chat/sessions"}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({conversation_id:F,agent_slug:E.slug})}).then(t=>t.ok?t.json():(e(),null)).then(e=>{if(!e?.messages?.length)return;const t=e.messages.map((e,t)=>({id:`restored-${t}`,role:e.role,content:e.content,timestamp:new Date}));Y(t)}).catch(()=>{e()})},[F,E,c,g,G,Y,ee]);const ge=(()=>{const e="filigran-chatbot";switch(n){case"sidebar":return`${e} fixed right-0 bottom-0 flex flex-col bg-white dark:bg-[#1e1e2e] border-l border-gray-200 dark:border-white/10 z-[1200]`;case"floating":return`${e} fixed bottom-5 right-5 flex flex-col bg-white dark:bg-[#1e1e2e] rounded-xl shadow-[0_8px_32px_rgba(0,0,0,0.15)] dark:shadow-[0_8px_32px_rgba(0,0,0,0.4)] z-[1300] border border-gray-200 dark:border-white/10`;case"fullscreen":return`${e} fixed right-0 bottom-0 left-0 flex flex-col bg-gray-50 dark:bg-[#161622] z-[1400]`;default:return e}})(),ue={...he,..."sidebar"===n?{top:l,width:N?te:se}:"floating"===n?{width:380,height:560}:{top:l}};return t("div",{className:ge,style:ue,children:["sidebar"===n&&N&&e("div",{onMouseDown:oe,className:"absolute top-0 -left-1 bottom-0 w-2 cursor-col-resize z-10 group",children:e("div",{className:"absolute top-0 left-1/2 -translate-x-1/2 bottom-0 w-0.5 rounded bg-[var(--chat-accent)] opacity-0 transition-opacity group-hover:opacity-100 group-active:opacity-100"})}),e(J,{mode:n,agentName:de,agents:T,selectedAgent:E,agentMenuOpen:$,onAgentMenuToggle:()=>R(e=>!e),onAgentMenuClose:()=>R(!1),onSwitchAgent:e=>{e&&D(e,()=>{K()})},modeMenuOpen:z,onModeMenuToggle:()=>A(e=>!e),onModeMenuClose:()=>A(!1),onModeChange:i,onNewChat:K,onClose:s,logoIcon:le,agentDashboardUrl:u,t:p}),0===U.length?e(re,{firstName:ce,logoIcon:le,promptSuggestions:y,onPromptClick:W,t:p}):e(ne,{messages:U,isLoading:O,agentStatus:B,agentName:de,logoIcon:le,t:p}),e(Q,{inputValue:j,onInputChange:W,onSend:q,onStop:X,isLoading:O,attachedFiles:P,onFileAdd:H,onFileRemove:e=>Z(t=>t.filter((t,n)=>n!==e)),onPaste:V,t:p,mode:n})]})},se=({isOpen:n,onToggle:r,label:a="Ask Assistant",accentColor:o="#7b5cff",icon:s})=>{const i=s??e(I,{size:16});return t("button",{type:"button",onClick:r,className:"filigran-chatbot inline-flex items-center gap-1.5 px-3 py-[3px] text-[0.8125rem] font-medium whitespace-nowrap rounded-md border transition-colors",style:{borderColor:n?o:d(o,.5),color:o,backgroundColor:n?d(o,.1):"transparent"},onMouseEnter:e=>{e.currentTarget.style.borderColor=o,e.currentTarget.style.backgroundColor=d(o,.1)},onMouseLeave:e=>{e.currentTarget.style.borderColor=n?o:d(o,.5),e.currentTarget.style.backgroundColor=n?d(o,.1):"transparent"},children:[e("span",{className:"[&>svg]:w-4 [&>svg]:h-4",children:i}),a]})};export{oe as ChatPanel,se as ChatToggleButton};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/utils/index.ts","../../src/hooks/protocols/parseLegacyEvent.ts","../../src/hooks/protocols/parseRestEvent.ts","../../src/hooks/protocols/parseAgUiEvent.ts","../../src/hooks/useChat.ts","../../src/hooks/useAgents.ts","../../src/hooks/useSidebarResize.ts","../../src/components/icons/AttachFileIcon.tsx","../../src/components/icons/BrainIcon.tsx","../../src/components/icons/CheckIcon.tsx","../../src/components/icons/ChevronDownIcon.tsx","../../src/components/icons/CloseIcon.tsx","../../src/components/icons/CopyIcon.tsx","../../src/components/icons/DatabaseIcon.tsx","../../src/components/icons/DefaultLogoIcon.tsx","../../src/components/icons/EditIcon.tsx","../../src/components/icons/ExternalLinkIcon.tsx","../../src/components/icons/FileIcon.tsx","../../src/components/icons/FloatingIcon.tsx","../../src/components/icons/FullscreenExitIcon.tsx","../../src/components/icons/FullscreenIcon.tsx","../../src/components/icons/GlobeIcon.tsx","../../src/components/icons/InfoIcon.tsx","../../src/components/icons/MailIcon.tsx","../../src/components/icons/SearchIcon.tsx","../../src/components/icons/SendIcon.tsx","../../src/components/icons/SidebarIcon.tsx","../../src/components/icons/SparklesIcon.tsx","../../src/components/icons/StopCircleIcon.tsx","../../src/components/icons/TerminalIcon.tsx","../../src/components/icons/UserPlusIcon.tsx","../../src/components/icons/WrenchIcon.tsx","../../src/components/Dropdown.tsx","../../src/hooks/useClickOutside.ts","../../src/components/Spinner.tsx","../../src/components/Tooltip.tsx","../../src/components/ChatHeader.tsx","../../src/components/ChatInput.tsx","../../src/components/ChatThinking.tsx","../../src/components/MarkdownMessage.tsx","../../src/components/ChatMessages.tsx","../../src/components/ChatWelcome.tsx","../../src/components/ChatPanel.tsx","../../src/components/ChatToggleButton.tsx"],"sourcesContent":["export function hexAlpha(hex: string, alpha: number): string {\n const a = Math.round(alpha * 255)\n .toString(16)\n .padStart(2, '0');\n return `${hex}${a}`;\n}\n\nexport const identity = (key: string) => key;\n","import type { ParsedAction, ProtocolContext } from './types';\n\n/**\n * Parse a Flowise-style SSE event into a normalized action.\n */\nexport function parseLegacyEvent(evt: Record<string, unknown>, ctx: ProtocolContext): ParsedAction {\n const eventType = evt.event as string | undefined;\n\n if (eventType === 'nextAgentFlow') {\n const data = evt.data as Record<string, unknown> | undefined;\n const nodeId = data?.nodeId as string | undefined;\n if (data?.status === 'INPROGRESS' && nodeId) {\n ctx.activeNodeId = nodeId;\n }\n return { action: 'noop' };\n }\n\n if (eventType === 'start') {\n return { action: 'noop' };\n }\n\n if (eventType === 'token') {\n const tokenData = ((evt.data as string) ?? '').replace(/<br\\s*\\/?>/g, '\\n');\n return { action: 'stream', content: tokenData };\n }\n\n if (eventType === 'agentReasoning') {\n const reasoning = evt.data as Record<string, unknown> | undefined;\n const usedTools = reasoning?.usedTools as Array<{ tool: string }> | undefined;\n if (usedTools?.length) {\n ctx.hasUsedTools = true;\n return { action: 'status', status: 'tool_start', tools: usedTools.map((t) => t.tool) };\n }\n if (ctx.hasUsedTools) {\n return { action: 'status', status: 'analyzing' };\n }\n return { action: 'status', status: 'thinking' };\n }\n\n if (eventType === 'usedTools') {\n ctx.hasUsedTools = true;\n const data = evt.data as Array<{ tool: string }> | undefined;\n const toolNames = Array.isArray(data) ? data.map((t) => t.tool) : [];\n return { action: 'status', status: 'tool_start', tools: toolNames };\n }\n\n if (eventType === 'metadata') {\n const data = evt.data as Record<string, unknown> | undefined;\n const chatId = data?.chatId as string | undefined;\n if (chatId) {\n return { action: 'set_chat_id', chatId };\n }\n return { action: 'noop' };\n }\n\n if (eventType === 'error') {\n return { action: 'error', content: (evt.data as string) || '' };\n }\n\n if (eventType === 'end') {\n return { action: 'done', content: '' };\n }\n\n return { action: 'noop' };\n}\n","import type { ParsedAction, ProtocolContext } from './types';\n\n/**\n * Parse an XTM One (REST) SSE event into a normalized action.\n */\nexport function parseRestEvent(evt: Record<string, unknown>, ctx: ProtocolContext): ParsedAction {\n const type = evt.type as string | undefined;\n\n if (type === 'error') {\n return { action: 'error', content: (evt.content as string) || '' };\n }\n\n if (type === 'status') {\n const st = evt.status as string;\n if (st === 'tool_done' || st === 'wind_down') {\n return { action: 'noop' };\n }\n if (st === 'streaming') {\n return { action: 'status', status: 'streaming' };\n }\n if (st === 'thinking_text') {\n return { action: 'status', status: 'thinking_text', thinkingContent: evt.content as string };\n }\n if (st === 'tool_start') {\n ctx.hasUsedTools = true;\n return { action: 'status', status: 'tool_start', tools: evt.tools as string[] | undefined };\n }\n if (st === 'thinking' && ctx.hasUsedTools) {\n return { action: 'status', status: 'analyzing' };\n }\n return { action: 'status', status: st, tools: evt.tools as string[] | undefined };\n }\n\n if (type === 'stream') {\n return { action: 'stream', content: evt.content as string };\n }\n\n if (type === 'done') {\n return {\n action: 'done',\n content: evt.content as string,\n conversationId: evt.conversation_id as string | undefined,\n toolNames: evt.tool_names as string[] | undefined,\n toolCallCount: evt.tool_call_count as number | undefined,\n iterations: evt.iterations as number | undefined,\n };\n }\n\n return { action: 'noop' };\n}\n","import type { ParsedAction, ProtocolContext } from './types';\n\n/**\n * AG-UI protocol event types.\n * @see https://github.com/ag-ui-protocol/ag-ui\n */\n\n/**\n * Parse an AG-UI protocol SSE event into a normalized action.\n *\n * AG-UI uses a Start/Content/End lifecycle for messages and tool calls.\n * We map these to the same internal actions used by the other protocols.\n */\nexport function parseAgUiEvent(evt: Record<string, unknown>, ctx: ProtocolContext): ParsedAction {\n const type = evt.type as string | undefined;\n\n // --- Run lifecycle ---\n\n if (type === 'RUN_STARTED') {\n return { action: 'status', status: 'thinking' };\n }\n\n if (type === 'RUN_FINISHED') {\n return { action: 'done', content: '' };\n }\n\n if (type === 'RUN_ERROR') {\n return { action: 'error', content: (evt.message as string) || 'Unknown error' };\n }\n\n // --- Step lifecycle ---\n\n if (type === 'STEP_STARTED') {\n const stepName = evt.stepName as string | undefined;\n return { action: 'status', status: stepName || 'thinking' };\n }\n\n if (type === 'STEP_FINISHED') {\n return { action: 'noop' };\n }\n\n // --- Text message streaming ---\n\n if (type === 'TEXT_MESSAGE_START') {\n return { action: 'status', status: 'streaming' };\n }\n\n if (type === 'TEXT_MESSAGE_CONTENT') {\n const delta = evt.delta as string;\n if (delta) {\n return { action: 'stream', content: delta };\n }\n return { action: 'noop' };\n }\n\n if (type === 'TEXT_MESSAGE_END') {\n return { action: 'noop' };\n }\n\n // TEXT_MESSAGE_CHUNK is a convenience event that combines Start+Content+End\n if (type === 'TEXT_MESSAGE_CHUNK') {\n const delta = evt.delta as string | undefined;\n if (delta) {\n return { action: 'stream', content: delta };\n }\n return { action: 'noop' };\n }\n\n // --- Tool call lifecycle ---\n\n if (type === 'TOOL_CALL_START') {\n ctx.hasUsedTools = true;\n const toolName = evt.toolCallName as string | undefined;\n return { action: 'status', status: 'tool_start', tools: toolName ? [toolName] : [] };\n }\n\n if (type === 'TOOL_CALL_ARGS') {\n // Tool arguments streaming — no UI equivalent, skip\n return { action: 'noop' };\n }\n\n if (type === 'TOOL_CALL_END') {\n return { action: 'status', status: 'analyzing' };\n }\n\n if (type === 'TOOL_CALL_RESULT') {\n // Tool result — no direct UI mapping, skip\n return { action: 'noop' };\n }\n\n if (type === 'TOOL_CALL_CHUNK') {\n // Convenience form — treat like TOOL_CALL_START if it has a name\n const toolName = evt.toolCallName as string | undefined;\n if (toolName) {\n ctx.hasUsedTools = true;\n return { action: 'status', status: 'tool_start', tools: [toolName] };\n }\n return { action: 'noop' };\n }\n\n // --- Reasoning / thinking ---\n\n if (type === 'REASONING_START' || type === 'REASONING_MESSAGE_START') {\n return { action: 'status', status: 'thinking' };\n }\n\n if (type === 'REASONING_MESSAGE_CONTENT' || type === 'REASONING_MESSAGE_CHUNK') {\n // Reasoning text — show as thinking status (content not surfaced to chat)\n return { action: 'status', status: 'thinking' };\n }\n\n if (type === 'REASONING_MESSAGE_END' || type === 'REASONING_END' || type === 'REASONING_ENCRYPTED_VALUE') {\n return { action: 'noop' };\n }\n\n // --- State management ---\n\n if (type === 'STATE_SNAPSHOT' || type === 'STATE_DELTA' || type === 'MESSAGES_SNAPSHOT') {\n // State sync — not mapped to chat UI currently\n return { action: 'noop' };\n }\n\n // --- Activity events ---\n\n if (type === 'ACTIVITY_SNAPSHOT' || type === 'ACTIVITY_DELTA') {\n return { action: 'noop' };\n }\n\n // --- Pass-through / custom ---\n\n if (type === 'RAW' || type === 'CUSTOM') {\n return { action: 'noop' };\n }\n\n return { action: 'noop' };\n}\n","import { useRef, useState } from 'react';\nimport type { AgentStatusState, ApiEndpoints, BackendType, ChatFile, ChatMessage } from '../types';\nimport type { ParsedAction, ProtocolContext } from './protocols';\nimport { parseAgUiEvent, parseLegacyEvent, parseRestEvent } from './protocols';\n\nconst STORAGE_KEY = 'filigranChatConversationId';\nconst LEGACY_CHAT_ID_KEY = 'filigranChatLegacyChatId';\n\ninterface UseChatOptions {\n apiBaseUrl: string;\n apiEndpoints?: ApiEndpoints;\n backendType?: BackendType;\n agentSlug: string | null | undefined;\n t: (key: string) => string;\n}\n\ninterface UseChatReturn {\n messages: ChatMessage[];\n inputValue: string;\n setInputValue: (value: string) => void;\n isLoading: boolean;\n agentStatus: AgentStatusState | null;\n attachedFiles: ChatFile[];\n conversationId: string | null;\n historyLoadedRef: React.MutableRefObject<boolean>;\n handleFileAdd: (fileList: FileList | null) => void;\n handlePaste: (e: React.ClipboardEvent) => void;\n handleSendMessage: () => Promise<void>;\n handleNewChat: () => void;\n handleStopGenerating: () => void;\n setAttachedFiles: React.Dispatch<React.SetStateAction<ChatFile[]>>;\n setMessages: React.Dispatch<React.SetStateAction<ChatMessage[]>>;\n setConversationId: React.Dispatch<React.SetStateAction<string | null>>;\n}\n\nfunction getParser(backendType: BackendType): (evt: Record<string, unknown>, ctx: ProtocolContext) => ParsedAction {\n switch (backendType) {\n case 'legacy':\n return parseLegacyEvent;\n case 'ag-ui':\n return parseAgUiEvent;\n default:\n return parseRestEvent;\n }\n}\n\nfunction buildRequestBody(\n backendType: BackendType,\n content: string,\n opts: { legacyChatId: string | null; conversationId: string | null; agentSlug: string | null | undefined },\n): Record<string, unknown> {\n switch (backendType) {\n case 'legacy':\n return { question: content, chatId: opts.legacyChatId ?? undefined, streaming: true };\n case 'ag-ui':\n return {\n threadId: opts.conversationId ?? crypto.randomUUID(),\n runId: crypto.randomUUID(),\n messages: [{ id: crypto.randomUUID(), role: 'user', content }],\n tools: [],\n context: [],\n state: {},\n forwardedProps: opts.agentSlug ? { agentSlug: opts.agentSlug } : {},\n };\n default:\n return { content, conversation_id: opts.conversationId, agent_slug: opts.agentSlug };\n }\n}\n\nexport function useChat({ apiBaseUrl, apiEndpoints, backendType = 'rest', agentSlug, t }: UseChatOptions): UseChatReturn {\n const isLegacy = backendType === 'legacy';\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [inputValue, setInputValue] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [agentStatus, setAgentStatus] = useState<AgentStatusState | null>(null);\n const [conversationId, setConversationId] = useState<string | null>(() => {\n if (typeof window === 'undefined') return null;\n return localStorage.getItem(STORAGE_KEY);\n });\n const [attachedFiles, setAttachedFiles] = useState<ChatFile[]>([]);\n const [legacyChatId, setLegacyChatId] = useState<string | null>(() => {\n if (typeof window === 'undefined') return null;\n return localStorage.getItem(LEGACY_CHAT_ID_KEY);\n });\n\n const historyLoadedRef = useRef(false);\n const abortControllerRef = useRef<AbortController | null>(null);\n const hasUsedToolsRef = useRef(false);\n\n // Determine message endpoint URL\n const getMessagesUrl = () => {\n if (isLegacy || apiEndpoints?.singleEndpoint) {\n return apiBaseUrl; // POST directly to base URL\n }\n return `${apiBaseUrl}${apiEndpoints?.messages ?? '/chat/messages'}`;\n };\n\n const handleFileAdd = (fileList: FileList | null) => {\n if (!fileList) return;\n const newFiles: ChatFile[] = [];\n Array.from(fileList).forEach((file) => {\n const reader = new FileReader();\n reader.onload = () => {\n newFiles.push({\n name: file.name,\n type: file.type,\n size: file.size,\n dataUrl: reader.result as string,\n });\n if (newFiles.length === fileList.length) {\n setAttachedFiles((prev) => [...prev, ...newFiles]);\n }\n };\n reader.readAsDataURL(file);\n });\n };\n\n const handlePaste = (e: React.ClipboardEvent) => {\n const { files } = e.clipboardData;\n if (files.length > 0) {\n e.preventDefault();\n handleFileAdd(files);\n }\n };\n\n const handleSendMessage = async () => {\n if ((!inputValue.trim() && attachedFiles.length === 0) || isLoading) return;\n const content = inputValue.trim();\n\n const userMsg: ChatMessage = {\n id: crypto.randomUUID(),\n role: 'user',\n content,\n timestamp: new Date(),\n files: attachedFiles.length > 0 ? [...attachedFiles] : undefined,\n };\n setMessages((prev) => [...prev, userMsg]);\n setInputValue('');\n setAttachedFiles([]);\n setIsLoading(true);\n setAgentStatus({ status: 'thinking' });\n hasUsedToolsRef.current = false;\n\n const assistantId = crypto.randomUUID();\n setMessages((prev) => [...prev, { id: assistantId, role: 'assistant', content: '', timestamp: new Date() }]);\n\n try {\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n const requestBody = buildRequestBody(backendType, content, { legacyChatId, conversationId, agentSlug });\n\n const res = await fetch(getMessagesUrl(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n signal: controller.signal,\n });\n\n if (!res.ok || !res.body) {\n setMessages((prev) =>\n prev.map((m) => (m.id === assistantId ? { ...m, content: t('Unable to connect. Please check the configuration.') } : m)),\n );\n return;\n }\n\n const parseEvent = getParser(backendType);\n const ctx: ProtocolContext = { hasUsedTools: false, activeNodeId: '' };\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let accumulated = '';\n let doneReceived = false;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n for (const rawLine of lines) {\n const line = rawLine.replace(/\\r$/, '');\n if (!line.startsWith('data:')) continue;\n const jsonStr = line.startsWith('data: ') ? line.slice(6) : line.slice(5);\n try {\n const evt = JSON.parse(jsonStr) as Record<string, unknown>;\n const parsed: ParsedAction = parseEvent(evt, ctx);\n\n // Sync ref → context for cross-event tracking\n ctx.hasUsedTools = ctx.hasUsedTools || hasUsedToolsRef.current;\n\n switch (parsed.action) {\n case 'status':\n if (parsed.status === 'tool_start') hasUsedToolsRef.current = true;\n if (parsed.status === 'thinking_text') {\n setAgentStatus((prev) => ({\n ...prev,\n status: prev?.status ?? 'thinking',\n thinkingContent: (prev?.thinkingContent ?? '') + (parsed.thinkingContent ?? ''),\n }));\n } else {\n setAgentStatus({ status: parsed.status, tools: parsed.tools });\n }\n break;\n\n case 'stream':\n accumulated += parsed.content;\n setAgentStatus({ status: 'streaming' });\n setMessages((prev) => prev.map((m) => (m.id === assistantId ? { ...m, content: accumulated } : m)));\n break;\n\n case 'done':\n doneReceived = true;\n if (parsed.conversationId) {\n setConversationId(parsed.conversationId);\n localStorage.setItem(STORAGE_KEY, parsed.conversationId);\n }\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? {\n ...m,\n content: parsed.content || accumulated,\n toolNames: parsed.toolNames,\n toolCallCount: parsed.toolCallCount,\n iterations: parsed.iterations,\n }\n : m,\n ),\n );\n break;\n\n case 'error':\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId ? { ...m, content: parsed.content || t('Unable to connect. Please check the configuration.') } : m,\n ),\n );\n return;\n\n case 'set_chat_id':\n setLegacyChatId(parsed.chatId);\n localStorage.setItem(LEGACY_CHAT_ID_KEY, parsed.chatId);\n break;\n\n case 'noop':\n break;\n }\n\n // Keep ref in sync with context\n hasUsedToolsRef.current = ctx.hasUsedTools;\n } catch {\n /* skip malformed SSE */\n }\n }\n }\n if (accumulated && !doneReceived) {\n setMessages((prev) => prev.map((m) => (m.id === assistantId ? { ...m, content: accumulated || 'No response.' } : m)));\n }\n } catch (err) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n setMessages((prev) =>\n prev.map((m) => (m.id === assistantId ? { ...m, content: t('Sorry, an error occurred. Please try again.') } : m)),\n );\n } finally {\n abortControllerRef.current = null;\n setIsLoading(false);\n setAgentStatus(null);\n hasUsedToolsRef.current = false;\n }\n };\n\n const handleNewChat = () => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = null;\n setMessages([]);\n setInputValue('');\n setAttachedFiles([]);\n setIsLoading(false);\n setAgentStatus(null);\n hasUsedToolsRef.current = false;\n historyLoadedRef.current = false;\n if (isLegacy) {\n setLegacyChatId(null);\n localStorage.removeItem(LEGACY_CHAT_ID_KEY);\n } else {\n setConversationId(null);\n localStorage.removeItem(STORAGE_KEY);\n }\n };\n\n const handleStopGenerating = () => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = null;\n setIsLoading(false);\n setAgentStatus(null);\n hasUsedToolsRef.current = false;\n setMessages((prev) => prev.filter((m) => !(m.role === 'assistant' && !m.content)));\n };\n\n return {\n messages,\n inputValue,\n setInputValue,\n isLoading,\n agentStatus,\n attachedFiles,\n conversationId,\n historyLoadedRef,\n handleFileAdd,\n handlePaste,\n handleSendMessage,\n handleNewChat,\n handleStopGenerating,\n setAttachedFiles,\n setMessages,\n setConversationId,\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { ApiEndpoints, BackendType, XtmAgent } from '../types';\n\nconst STORAGE_AGENT_KEY = 'filigranChatAgentSlug';\n\ninterface UseAgentsOptions {\n apiBaseUrl: string;\n apiEndpoints?: ApiEndpoints;\n backendType?: BackendType;\n}\n\ninterface UseAgentsReturn {\n agents: XtmAgent[];\n selectedAgent: XtmAgent | null;\n setSelectedAgent: React.Dispatch<React.SetStateAction<XtmAgent | null>>;\n agentMenuOpen: boolean;\n setAgentMenuOpen: React.Dispatch<React.SetStateAction<boolean>>;\n handleSwitchAgent: (agent: XtmAgent, onSwitch?: () => void) => void;\n}\n\nexport function useAgents({ apiBaseUrl, apiEndpoints, backendType = 'rest' }: UseAgentsOptions): UseAgentsReturn {\n const [agents, setAgents] = useState<XtmAgent[]>([]);\n const [selectedAgent, setSelectedAgent] = useState<XtmAgent | null>(null);\n const [agentMenuOpen, setAgentMenuOpen] = useState(false);\n\n useEffect(() => {\n // Skip agents fetch if disabled, using single endpoint mode, or legacy backend\n if (apiEndpoints?.agents === null || apiEndpoints?.singleEndpoint || backendType === 'legacy') {\n return;\n }\n const agentsUrl = `${apiBaseUrl}${apiEndpoints?.agents ?? '/chat/agents'}`;\n fetch(agentsUrl)\n .then((res) => (res.ok ? res.json() : []))\n .then((data: XtmAgent[]) => {\n setAgents(data);\n if (data.length > 0 && !selectedAgent) {\n const savedSlug = localStorage.getItem(STORAGE_AGENT_KEY);\n const match = savedSlug ? data.find((a) => a.slug === savedSlug) : null;\n setSelectedAgent(match || data[0]);\n }\n })\n .catch(() => {});\n }, [apiBaseUrl, apiEndpoints]);\n\n const handleSwitchAgent = (agent: XtmAgent, onSwitch?: () => void) => {\n if (agent.id === selectedAgent?.id) {\n setAgentMenuOpen(false);\n return;\n }\n setSelectedAgent(agent);\n if (agent.slug) localStorage.setItem(STORAGE_AGENT_KEY, agent.slug);\n setAgentMenuOpen(false);\n onSwitch?.();\n };\n\n return {\n agents,\n selectedAgent,\n setSelectedAgent,\n agentMenuOpen,\n setAgentMenuOpen,\n handleSwitchAgent,\n };\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { ChatMode } from '../types';\n\nconst SIDEBAR_WIDTH = 400;\nconst SIDEBAR_WIDTH_STORAGE_KEY = 'filigranChatSidebarWidth';\nconst MAX_SIDEBAR_RATIO = 0.4;\n\ninterface UseSidebarResizeOptions {\n mode: ChatMode;\n resizable: boolean;\n onWidthChange?: (width: number) => void;\n onResizeStart?: () => void;\n onResizeEnd?: () => void;\n}\n\ninterface UseSidebarResizeReturn {\n sidebarWidth: number;\n handleResizeStart: (e: React.MouseEvent) => void;\n defaultWidth: number;\n isResizing: boolean;\n}\n\nexport function useSidebarResize({\n mode,\n resizable,\n onWidthChange,\n onResizeStart,\n onResizeEnd,\n}: UseSidebarResizeOptions): UseSidebarResizeReturn {\n const [sidebarWidth, setSidebarWidth] = useState<number>(() => {\n if (typeof window === 'undefined') return SIDEBAR_WIDTH;\n const stored = localStorage.getItem(SIDEBAR_WIDTH_STORAGE_KEY);\n if (stored) {\n const parsed = parseInt(stored, 10);\n if (!Number.isNaN(parsed) && parsed >= SIDEBAR_WIDTH) return parsed;\n }\n return SIDEBAR_WIDTH;\n });\n const [isResizing, setIsResizing] = useState(false);\n\n const isResizingRef = useRef(false);\n const sidebarWidthRef = useRef(sidebarWidth);\n sidebarWidthRef.current = sidebarWidth;\n const onWidthChangeRef = useRef(onWidthChange);\n onWidthChangeRef.current = onWidthChange;\n const onResizeEndRef = useRef(onResizeEnd);\n onResizeEndRef.current = onResizeEnd;\n\n // Notify parent of sidebar width when entering sidebar mode\n useEffect(() => {\n if (mode === 'sidebar' && resizable) {\n onWidthChangeRef.current?.(sidebarWidthRef.current);\n }\n }, [mode, resizable]);\n\n // Resize event handlers\n useEffect(() => {\n if (mode !== 'sidebar' || !resizable) return undefined;\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!isResizingRef.current) return;\n e.preventDefault();\n const newWidth = window.innerWidth - e.clientX;\n const maxWidth = window.innerWidth * MAX_SIDEBAR_RATIO;\n const clamped = Math.min(Math.max(newWidth, SIDEBAR_WIDTH), maxWidth);\n setSidebarWidth(clamped);\n sidebarWidthRef.current = clamped;\n onWidthChangeRef.current?.(clamped);\n };\n\n const handleMouseUp = () => {\n if (!isResizingRef.current) return;\n isResizingRef.current = false;\n setIsResizing(false);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(sidebarWidthRef.current));\n onResizeEndRef.current?.();\n };\n\n const handleWindowResize = () => {\n const maxWidth = window.innerWidth * MAX_SIDEBAR_RATIO;\n if (sidebarWidthRef.current > maxWidth) {\n const clamped = Math.max(maxWidth, SIDEBAR_WIDTH);\n setSidebarWidth(clamped);\n sidebarWidthRef.current = clamped;\n onWidthChangeRef.current?.(clamped);\n }\n };\n\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n window.addEventListener('resize', handleWindowResize);\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n window.removeEventListener('resize', handleWindowResize);\n };\n }, [mode, resizable]);\n\n const handleResizeStart = (e: React.MouseEvent) => {\n e.preventDefault();\n isResizingRef.current = true;\n setIsResizing(true);\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n onResizeStart?.();\n };\n\n return {\n sidebarWidth,\n handleResizeStart,\n defaultWidth: SIDEBAR_WIDTH,\n isResizing,\n };\n}\n","import type { IconProps } from '../../types';\n\nexport const AttachFileIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const BrainIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z\" />\n <path d=\"M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z\" />\n <path d=\"M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4\" />\n <path d=\"M17.599 6.5a3 3 0 0 0 .399-1.375\" />\n <path d=\"M6.003 5.125A3 3 0 0 0 6.401 6.5\" />\n <path d=\"M3.477 10.896a4 4 0 0 1 .585-.396\" />\n <path d=\"M19.938 10.5a4 4 0 0 1 .585.396\" />\n <path d=\"M6 18a4 4 0 0 1-1.967-.516\" />\n <path d=\"M19.967 17.484A4 4 0 0 1 18 18\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const CheckIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const ChevronDownIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const CloseIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const CopyIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const DatabaseIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5V19A9 3 0 0 0 21 19V5\" />\n <path d=\"M3 12A9 3 0 0 0 21 12\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const DefaultLogoIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\" className={className}>\n <path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const EditIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M12 20h9\" />\n <path d=\"M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const ExternalLinkIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const FileIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\" />\n <path d=\"M14 2v4a2 2 0 0 0 2 2h4\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const FloatingIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M11 13H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7\" />\n <rect width=\"12\" height=\"12\" x=\"10\" y=\"10\" rx=\"2\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const FullscreenExitIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3\" />\n <path d=\"M21 8h-3a2 2 0 0 1-2-2V3\" />\n <path d=\"M3 16h3a2 2 0 0 0 2 2v3\" />\n <path d=\"M16 21v-3a2 2 0 0 1 2-2h3\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const FullscreenIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3\" />\n <path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" />\n <path d=\"M3 16v3a2 2 0 0 0 2 2h3\" />\n <path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const GlobeIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n <path d=\"M2 12h20\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const InfoIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4\" />\n <path d=\"M12 8h.01\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const MailIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const SearchIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const SendIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"m22 2-7 20-4-9-9-4Z\" />\n <path d=\"m22 2-11 11\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const SidebarIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M15 3v18\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const SparklesIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const StopCircleIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <rect width=\"6\" height=\"6\" x=\"9\" y=\"9\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const TerminalIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <polyline points=\"4 17 10 11 4 5\" />\n <line x1=\"12\" x2=\"20\" y1=\"19\" y2=\"19\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const UserPlusIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <line x1=\"19\" x2=\"19\" y1=\"8\" y2=\"14\" />\n <line x1=\"22\" x2=\"16\" y1=\"11\" y2=\"11\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const WrenchIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z\" />\n </svg>\n);\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useClickOutside } from '../hooks/useClickOutside';\n\ninterface DropdownProps {\n open: boolean;\n onClose: () => void;\n anchorRef: React.RefObject<HTMLElement | null>;\n placement?: 'bottom-start' | 'bottom-end';\n width?: number;\n children: React.ReactNode;\n}\n\nfunction findChatbotRoot(el: HTMLElement | null): HTMLElement {\n let node = el;\n while (node) {\n if (node.classList.contains('filigran-chatbot')) return node;\n node = node.parentElement;\n }\n return document.body;\n}\n\nexport const Dropdown = ({ open, onClose, anchorRef, placement = 'bottom-start', width = 280, children }: DropdownProps) => {\n const panelRef = useRef<HTMLDivElement>(null);\n const [pos, setPos] = useState({ top: 0, left: 0 });\n\n const stableOnClose = useCallback(() => onClose(), [onClose]);\n useClickOutside(panelRef, stableOnClose, open);\n\n useEffect(() => {\n if (!open || !anchorRef.current) return;\n const rect = anchorRef.current.getBoundingClientRect();\n const left = placement === 'bottom-end' ? rect.right - width : rect.left;\n setPos({ top: rect.bottom + 4, left });\n }, [open, anchorRef, placement, width]);\n\n if (!open) return null;\n\n const portalTarget = findChatbotRoot(anchorRef.current);\n\n return createPortal(\n <div\n ref={panelRef}\n className=\"fixed z-[10000] rounded-[10px] overflow-hidden border border-gray-200 dark:border-white/10 bg-white dark:bg-[#2a2a3e] shadow-xl\"\n style={{ top: pos.top, left: pos.left, width }}\n >\n {children}\n </div>,\n portalTarget,\n );\n};\n","import { useEffect, type RefObject } from 'react';\n\nexport function useClickOutside(ref: RefObject<HTMLElement | null>, handler: () => void, active = true) {\n useEffect(() => {\n if (!active) return undefined;\n const listener = (e: MouseEvent | TouchEvent) => {\n if (!ref.current || ref.current.contains(e.target as Node)) return;\n handler();\n };\n document.addEventListener('mousedown', listener);\n document.addEventListener('touchstart', listener);\n return () => {\n document.removeEventListener('mousedown', listener);\n document.removeEventListener('touchstart', listener);\n };\n }, [ref, handler, active]);\n}\n","interface SpinnerProps {\n size?: number;\n className?: string;\n}\n\nexport const Spinner = ({ size = 16, className = '' }: SpinnerProps) => (\n <div\n className={`animate-spin rounded-full border-2 border-current/20 border-t-[var(--chat-accent)] ${className}`}\n style={{ width: size, height: size }}\n />\n);\n","import { useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\ninterface TooltipProps {\n title: string;\n children: React.ReactElement;\n}\n\nfunction findChatbotRoot(el: HTMLElement | null): HTMLElement {\n let node = el;\n while (node) {\n if (node.classList.contains('filigran-chatbot')) return node;\n node = node.parentElement;\n }\n return document.body;\n}\n\nexport const Tooltip = ({ title, children }: TooltipProps) => {\n const ref = useRef<HTMLSpanElement>(null);\n const [show, setShow] = useState(false);\n const [pos, setPos] = useState({ top: 0, left: 0 });\n\n if (!title) return children;\n\n const handleEnter = () => {\n if (!ref.current) return;\n const rect = ref.current.getBoundingClientRect();\n setPos({\n top: rect.top - 4,\n left: rect.left + rect.width / 2,\n });\n setShow(true);\n };\n\n return (\n <span\n ref={ref}\n className=\"inline-flex\"\n onMouseEnter={handleEnter}\n onMouseLeave={() => setShow(false)}\n >\n {children}\n {show &&\n createPortal(\n <span\n className=\"pointer-events-none fixed z-[10001] -translate-x-1/2 -translate-y-full whitespace-nowrap rounded-md bg-gray-900 dark:bg-gray-100 px-2 py-1 text-xs text-white dark:text-gray-900 shadow-lg\"\n style={{ top: pos.top, left: pos.left }}\n role=\"tooltip\"\n >\n {title}\n </span>,\n findChatbotRoot(ref.current),\n )}\n </span>\n );\n};\n","import { useRef } from 'react';\nimport type { ChatMode, XtmAgent } from '../types';\nimport {\n ChevronDownIcon,\n CloseIcon,\n EditIcon,\n ExternalLinkIcon,\n FloatingIcon,\n FullscreenExitIcon,\n FullscreenIcon,\n SidebarIcon,\n UserPlusIcon,\n} from './icons';\nimport { Dropdown } from './Dropdown';\nimport { Spinner } from './Spinner';\nimport { Tooltip } from './Tooltip';\n\ninterface ChatHeaderProps {\n mode: ChatMode;\n agentName: string;\n agents: XtmAgent[];\n selectedAgent: XtmAgent | null;\n agentMenuOpen: boolean;\n onAgentMenuToggle: () => void;\n onAgentMenuClose: () => void;\n onSwitchAgent: (agent: XtmAgent) => void;\n modeMenuOpen: boolean;\n onModeMenuToggle: () => void;\n onModeMenuClose: () => void;\n onModeChange: (mode: ChatMode) => void;\n onNewChat: () => void;\n onClose: () => void;\n logoIcon: React.ReactNode;\n agentDashboardUrl?: string;\n t: (key: string) => string;\n}\n\nconst modeOptions: { mode: ChatMode; label: string; getIcon: (p: { size: number; className: string }) => React.ReactNode }[] = [\n { mode: 'floating', label: 'Floating', getIcon: (p) => <FloatingIcon {...p} /> },\n { mode: 'sidebar', label: 'Sidebar', getIcon: (p) => <SidebarIcon {...p} /> },\n { mode: 'fullscreen', label: 'Full screen', getIcon: (p) => <FullscreenIcon {...p} /> },\n];\n\nexport const ChatHeader = ({\n mode,\n agentName,\n agents,\n selectedAgent,\n agentMenuOpen,\n onAgentMenuToggle,\n onAgentMenuClose,\n onSwitchAgent,\n modeMenuOpen,\n onModeMenuToggle,\n onModeMenuClose,\n onModeChange,\n onNewChat,\n onClose,\n logoIcon,\n agentDashboardUrl,\n t,\n}: ChatHeaderProps) => {\n const agentAnchorRef = useRef<HTMLButtonElement>(null);\n const modeAnchorRef = useRef<HTMLButtonElement>(null);\n\n const CurrentModeIcon = mode === 'sidebar' ? SidebarIcon : mode === 'fullscreen' ? FullscreenExitIcon : FloatingIcon;\n\n return (\n <div className={`flex items-center px-3 py-2 min-h-[48px] border-b border-gray-200 dark:border-white/10 bg-gradient-to-br from-[var(--chat-accent-dark)]/[0.13] to-[var(--chat-accent)]/[0.07] ${mode === 'floating' ? 'rounded-t-xl' : ''}`}>\n <button\n ref={agentAnchorRef}\n type=\"button\"\n onClick={onAgentMenuToggle}\n className=\"flex items-center gap-1.5 text-sm font-semibold text-gray-900 dark:text-white px-2 py-1 rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 transition-colors\"\n >\n <span className=\"flex items-center text-[var(--chat-accent)] [&>svg]:w-[18px] [&>svg]:h-[18px]\">{logoIcon}</span>\n {agentName}\n <ChevronDownIcon size={16} className=\"text-gray-400 dark:text-white/30\" />\n </button>\n\n <Dropdown open={agentMenuOpen} onClose={onAgentMenuClose} anchorRef={agentAnchorRef} width={280}>\n <span className=\"block px-4 pt-3 pb-1 text-[0.68rem] tracking-[1px] uppercase text-gray-400 dark:text-white/40\">\n {t('Switch to another agent')}\n </span>\n {agents.length === 0 && (\n <div className=\"px-4 py-2\">\n <Spinner size={16} />\n </div>\n )}\n <div>\n {agents.map((agent) => (\n <button\n key={agent.id}\n type=\"button\"\n onClick={() => onSwitchAgent(agent)}\n className={`w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors ${\n agent.id === selectedAgent?.id ? 'bg-[var(--chat-accent)]/10' : ''\n }`}\n >\n <div className=\"w-7 h-7 rounded-full flex items-center justify-center shrink-0 bg-gradient-to-br from-[var(--chat-accent)]/20 to-[var(--chat-accent)]/5\">\n <span className=\"text-[var(--chat-accent)] [&>svg]:w-4 [&>svg]:h-4\">{logoIcon}</span>\n </div>\n <div className=\"min-w-0\">\n <div className=\"text-[0.8125rem] font-medium text-gray-900 dark:text-white truncate\">{agent.name}</div>\n {agent.description && <div className=\"text-[0.7rem] text-gray-500 dark:text-white/40 truncate\">{agent.description}</div>}\n </div>\n </button>\n ))}\n </div>\n <div className=\"h-px bg-gray-200 dark:bg-white/10 mx-2\" />\n <div>\n {agentDashboardUrl && (\n <button\n type=\"button\"\n onClick={() => {\n onAgentMenuClose();\n window.open(`${agentDashboardUrl}/agents`, '_blank');\n }}\n className=\"w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors\"\n >\n <ExternalLinkIcon size={18} className=\"text-gray-400 dark:text-white/40 shrink-0\" />\n <span className=\"text-[0.8125rem] text-gray-700 dark:text-white/70\">{t('Browse agents')}</span>\n </button>\n )}\n {agentDashboardUrl && (\n <button\n type=\"button\"\n onClick={() => {\n onAgentMenuClose();\n window.open(`${agentDashboardUrl}/agents/new`, '_blank');\n }}\n className=\"w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors\"\n >\n <UserPlusIcon size={18} className=\"text-gray-400 dark:text-white/40 shrink-0\" />\n <span className=\"text-[0.8125rem] text-gray-700 dark:text-white/70\">{t('Create agent')}</span>\n </button>\n )}\n </div>\n </Dropdown>\n\n <div className=\"flex-1\" />\n\n <Tooltip title={t('New chat')}>\n <button\n type=\"button\"\n onClick={onNewChat}\n className=\"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors\"\n >\n <EditIcon size={18} />\n </button>\n </Tooltip>\n\n <Tooltip title={t('Switch view')}>\n <button\n ref={modeAnchorRef}\n type=\"button\"\n onClick={onModeMenuToggle}\n className=\"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors\"\n >\n <CurrentModeIcon size={18} />\n </button>\n </Tooltip>\n\n <Dropdown open={modeMenuOpen} onClose={onModeMenuClose} anchorRef={modeAnchorRef} placement=\"bottom-end\" width={180}>\n <span className=\"block px-4 pt-3 pb-1 text-[0.68rem] tracking-[1px] uppercase text-gray-400 dark:text-white/40\">{t('Switch to')}</span>\n <div className=\"pb-1\">\n {modeOptions.map((opt) => (\n <button\n key={opt.mode}\n type=\"button\"\n onClick={() => {\n onModeChange(opt.mode);\n onModeMenuClose();\n }}\n className={`w-full flex items-center gap-3 px-4 py-1 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors ${\n mode === opt.mode ? 'bg-[var(--chat-accent)]/10' : ''\n }`}\n >\n {opt.getIcon({ size: 18, className: 'text-gray-400 dark:text-white/40' })}\n <span className=\"text-[0.8125rem] text-gray-700 dark:text-white/70\">{t(opt.label)}</span>\n </button>\n ))}\n </div>\n </Dropdown>\n\n <Tooltip title={t('Close')}>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors\"\n >\n <CloseIcon size={18} />\n </button>\n </Tooltip>\n </div>\n );\n};\n","import { useRef, type KeyboardEvent } from 'react';\nimport type { ChatFile, ChatMode } from '../types';\nimport { AttachFileIcon, FileIcon, SendIcon, StopCircleIcon } from './icons';\nimport { Tooltip } from './Tooltip';\n\ninterface ChatInputProps {\n inputValue: string;\n onInputChange: (value: string) => void;\n onSend: () => void;\n onStop: () => void;\n isLoading: boolean;\n attachedFiles: ChatFile[];\n onFileAdd: (files: FileList | null) => void;\n onFileRemove: (index: number) => void;\n onPaste: (e: React.ClipboardEvent) => void;\n t: (key: string) => string;\n mode?: ChatMode;\n}\n\nexport const ChatInput = ({ inputValue, onInputChange, onSend, onStop, isLoading, attachedFiles, onFileAdd, onFileRemove, onPaste, t, mode }: ChatInputProps) => {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n onSend();\n }\n };\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n onInputChange(e.target.value);\n const el = e.target;\n el.style.height = 'auto';\n el.style.height = `${Math.min(el.scrollHeight, 120)}px`;\n };\n\n const hasContent = inputValue.trim() || attachedFiles.length > 0;\n\n return (\n <div className={`px-4 py-3 border-t border-gray-200 dark:border-white/10 ${mode === 'floating' ? 'rounded-b-xl' : ''}`}>\n {attachedFiles.length > 0 && (\n <div className=\"flex gap-1.5 flex-wrap mb-2\">\n {attachedFiles.map((f, i) => (\n <span\n key={i}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.7rem] text-gray-600 dark:text-white/60\"\n >\n <FileIcon size={14} />\n {f.name}\n <button\n type=\"button\"\n onClick={() => onFileRemove(i)}\n className=\"ml-0.5 text-gray-400 dark:text-white/30 hover:text-gray-600 dark:hover:text-white/60\"\n >\n ×\n </button>\n </span>\n ))}\n </div>\n )}\n\n <div className=\"flex items-center border border-gray-200 dark:border-white/10 rounded-xl px-2 py-1 transition-colors focus-within:border-[var(--chat-accent)]\">\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n hidden\n onChange={(e) => {\n onFileAdd(e.target.files);\n e.target.value = '';\n }}\n />\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n className=\"w-8 h-8 flex items-center justify-center shrink-0 rounded-lg text-gray-400 dark:text-white/30 hover:bg-gray-100 dark:hover:bg-white/10 mr-0.5 transition-colors\"\n >\n <AttachFileIcon size={18} />\n </button>\n <textarea\n ref={textareaRef}\n placeholder={t('Ask a question...')}\n value={inputValue}\n onChange={handleInput}\n onKeyDown={handleKeyDown}\n onPaste={onPaste}\n rows={1}\n className=\"flex-1 bg-transparent border-none outline-none resize-none text-[0.8125rem] py-1.5 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-white/30 filigran-chat-scrollable\"\n style={{ maxHeight: 120 }}\n />\n <Tooltip title={isLoading ? t('Stop generating') : ''}>\n <button\n type=\"button\"\n onClick={isLoading ? onStop : onSend}\n disabled={!isLoading && !hasContent}\n className={`p-1.5 rounded-lg w-8 h-8 flex items-center justify-center transition-all duration-150 ${\n isLoading\n ? 'text-red-500 bg-red-500/10 hover:bg-red-500/20'\n : hasContent\n ? 'text-[var(--chat-accent)] bg-[var(--chat-accent)]/10 hover:bg-[var(--chat-accent)]/20'\n : 'text-gray-300 dark:text-white/20 cursor-not-allowed'\n }`}\n >\n {isLoading ? <StopCircleIcon size={18} /> : <SendIcon size={18} />}\n </button>\n </Tooltip>\n </div>\n\n <p className=\"text-center text-[0.65rem] text-gray-400 dark:text-white/30 mt-1.5 opacity-70\">{t('Uses AI. Verify results.')}</p>\n </div>\n );\n};\n","import { useEffect, useRef } from 'react';\nimport type { AgentStatusState, IconProps } from '../types';\nimport { BrainIcon, DatabaseIcon, ExternalLinkIcon, GlobeIcon, MailIcon, SearchIcon, SparklesIcon, TerminalIcon, UserPlusIcon, WrenchIcon } from './icons';\n\ninterface ChatThinkingProps {\n agentStatus: AgentStatusState | null;\n logoIcon?: React.ReactNode;\n t: (key: string) => string;\n}\n\ntype IconComponent = (props: IconProps) => React.JSX.Element;\n\ninterface StatusVisual {\n label: string;\n StatusIcon: IconComponent;\n showDots: boolean;\n}\n\nfunction resolveStatusVisual(agentStatus: AgentStatusState | null, t: (key: string) => string): StatusVisual {\n if (!agentStatus) {\n return { label: t('Thinking...'), StatusIcon: BrainIcon, showDots: false };\n }\n switch (agentStatus.status) {\n case 'tool_start': {\n const rawNames = agentStatus.tools ?? [];\n const lower = rawNames.map((n) => n.toLowerCase());\n\n // Delegation tools have dedicated statuses\n if (lower.some((n) => n === 'spawn_background_task')) {\n const count = rawNames.filter((n) => n === 'spawn_background_task').length;\n const label = count > 1\n ? `${t('Delegating')} ${count} ${t('tasks')}…`\n : `${t('Delegating task')}…`;\n return { label, StatusIcon: UserPlusIcon, showDots: false };\n }\n if (lower.some((n) => n === 'check_task_status')) {\n const count = rawNames.filter((n) => n === 'check_task_status').length;\n const target = count > 1 ? `${count} ${t('background tasks')}` : t('background task');\n return { label: `${t('Waiting for')} ${target}…`, StatusIcon: SparklesIcon, showDots: false };\n }\n if (lower.some((n) => n === 'get_task_result')) {\n const count = rawNames.filter((n) => n === 'get_task_result').length;\n const from = count > 1 ? `${count} ${t('tasks')}` : t('task');\n return { label: `${t('Collecting results from')} ${from}…`, StatusIcon: SparklesIcon, showDots: false };\n }\n\n let StatusIcon: IconComponent = WrenchIcon;\n if (lower.some((n) => n.includes('search') || n.includes('list'))) {\n StatusIcon = SearchIcon;\n } else if (lower.some((n) => n.includes('read') || n.includes('get') || n.includes('query'))) {\n StatusIcon = DatabaseIcon;\n } else if (lower.some((n) => n.includes('send') || n.includes('create') || n.includes('draft') || n.includes('reply') || n.includes('flag'))) {\n StatusIcon = MailIcon;\n } else if (lower.some((n) => n.includes('code') || n.includes('execute'))) {\n StatusIcon = TerminalIcon;\n } else if (lower.some((n) => n.includes('web') || n.includes('browse'))) {\n StatusIcon = GlobeIcon;\n }\n let label: string;\n if (rawNames.length > 0) {\n const display = rawNames.map((n) => n.replace(/_/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase()));\n const unique = Array.from(new Set(display));\n label = unique.length === 1 ? `${unique[0]}…` : `${unique[0]} (+${unique.length - 1} more)…`;\n } else {\n label = t('Using tools…');\n }\n return { label, StatusIcon, showDots: false };\n }\n case 'analyzing':\n return { label: t('Analyzing results…'), StatusIcon: SparklesIcon, showDots: false };\n case 'composing':\n return { label: t('Composing answer…'), StatusIcon: BrainIcon, showDots: true };\n case 'consulting': {\n const consultName = agentStatus.tools?.[0] ?? 'agent';\n return { label: `${t('Consulting')} ${consultName}…`, StatusIcon: UserPlusIcon, showDots: false };\n }\n case 'delegating': {\n const count = agentStatus.tools?.filter((n) => n === 'spawn_background_task').length ?? 0;\n return { label: count > 1 ? `${t('Delegating')} ${count} ${t('tasks')}…` : `${t('Delegating task')}…`, StatusIcon: UserPlusIcon, showDots: false };\n }\n case 'polling': {\n const checkCount = agentStatus.tools?.filter((n) => n === 'check_task_status').length ?? 0;\n const target = checkCount > 1 ? `${checkCount} ${t('background tasks')}` : t('background task');\n return { label: `${t('Waiting for')} ${target}…`, StatusIcon: SparklesIcon, showDots: false };\n }\n case 'collecting': {\n const fetchCount = agentStatus.tools?.filter((n) => n === 'get_task_result').length ?? 0;\n const from = fetchCount > 1 ? `${fetchCount} ${t('tasks')}` : t('task');\n return { label: `${t('Collecting results from')} ${from}…`, StatusIcon: SparklesIcon, showDots: false };\n }\n case 'transferring': {\n const targetName = agentStatus.tools?.[0] ?? 'agent';\n return { label: `${t('Transferring to')} ${targetName}…`, StatusIcon: ExternalLinkIcon, showDots: false };\n }\n case 'thinking':\n default:\n return { label: t('Thinking...'), StatusIcon: BrainIcon, showDots: false };\n }\n}\n\nfunction stripMarkdown(text: string): string {\n return text\n .replace(/```[\\s\\S]*?```/g, ' ')\n .replace(/`([^`]+)`/g, '$1')\n .replace(/\\*\\*(.+?)\\*\\*/g, '$1')\n .replace(/__(.+?)__/g, '$1')\n .replace(/\\*(.+?)\\*/g, '$1')\n .replace(/_(.+?)_/g, '$1')\n .replace(/#{1,6}\\s+/g, '')\n .replace(/[*\\->]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction ThinkingTextBubble({ content }: { content: string }) {\n const ref = useRef<HTMLDivElement>(null);\n const cleaned = stripMarkdown(content);\n\n useEffect(() => {\n if (ref.current) ref.current.scrollTop = ref.current.scrollHeight;\n }, [cleaned]);\n\n if (cleaned.length < 3) return null;\n\n return (\n <div\n ref={ref}\n className=\"ml-11 max-w-[70%] max-h-20 overflow-hidden relative rounded-md border-l-2 bg-[var(--chat-accent)]/[0.03] pl-3 pr-3 py-2\"\n style={{ animation: 'reasoningGlow 3s ease-in-out infinite, chat-fade-in 0.5s ease-out' }}\n >\n <p className=\"text-[13px] leading-[1.35rem] text-gray-400 dark:text-white/40 break-words m-0\">\n {cleaned}\n </p>\n <div className=\"absolute inset-x-0 bottom-0 h-5 bg-gradient-to-t from-white/90 dark:from-[#1e1e2e]/90 to-transparent pointer-events-none\" />\n </div>\n );\n}\n\nexport const ChatThinking = ({ agentStatus, logoIcon, t }: ChatThinkingProps) => {\n const { label, StatusIcon, showDots } = resolveStatusVisual(agentStatus, t);\n const thinkingContent = agentStatus?.thinkingContent;\n\n return (\n <>\n <div className=\"flex gap-3 items-center justify-start\">\n <div className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-[var(--chat-accent)]/15 to-[var(--chat-accent)]/5\">\n <span className=\"text-[var(--chat-accent)] [&>svg]:w-4 [&>svg]:h-4\">{logoIcon}</span>\n </div>\n <div className=\"rounded-lg bg-gray-50 dark:bg-white/[0.03] px-4 py-3 relative overflow-hidden\">\n <div className=\"absolute inset-0 bg-gradient-to-r from-[var(--chat-accent)]/[0.03] via-transparent to-[var(--chat-accent)]/[0.03] animate-pulse pointer-events-none\" />\n <div className=\"relative flex items-center gap-2.5\">\n {showDots ? (\n <div className=\"flex gap-[3px] items-center h-3.5 w-3.5 justify-center\">\n {[0, 0.15, 0.3].map((delay, i) => (\n <span\n key={i}\n className=\"h-[5px] w-[5px] rounded-full bg-[var(--chat-accent)]/50\"\n style={{ animation: `chat-dot 1s ease-in-out infinite ${delay}s` }}\n />\n ))}\n </div>\n ) : (\n <StatusIcon size={14} className=\"text-[var(--chat-accent)] animate-pulse transition-all duration-300\" />\n )}\n <span className=\"text-sm text-gray-500 dark:text-white/50 transition-all duration-300\">{label}</span>\n </div>\n </div>\n </div>\n {thinkingContent && <ThinkingTextBubble content={thinkingContent} />}\n </>\n );\n};\n","import { useState } from 'react';\nimport Markdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { CheckIcon, CopyIcon } from './icons';\n\ninterface MarkdownMessageProps {\n content: string;\n}\n\nexport const MarkdownMessage = ({ content }: MarkdownMessageProps) => {\n const [copiedBlock, setCopiedBlock] = useState<string | null>(null);\n\n const handleCopyCode = (code: string) => {\n navigator.clipboard.writeText(code);\n setCopiedBlock(code);\n setTimeout(() => setCopiedBlock(null), 2000);\n };\n\n return (\n <Markdown\n remarkPlugins={[remarkGfm]}\n components={{\n p: ({ children }) => (\n <p className=\"mb-3 last:mb-0 leading-7 break-words text-[0.8125rem] text-gray-900 dark:text-white/90\">{children}</p>\n ),\n code: ({ className, children }) => {\n const match = /language-(\\w+)/.exec(className || '');\n const codeStr = String(children).replace(/\\n$/, '');\n if (match) {\n return (\n <div className=\"my-3 rounded-lg border border-gray-200 dark:border-white/10 overflow-hidden bg-gray-50 dark:bg-white/[0.03]\">\n <div className=\"flex items-center justify-between px-3 py-1.5 border-b border-gray-200 dark:border-white/10 bg-gray-100 dark:bg-white/[0.03]\">\n <span className=\"text-[0.7rem] text-gray-500 dark:text-white/40 font-mono\">{match[1]}</span>\n <button\n type=\"button\"\n onClick={() => handleCopyCode(codeStr)}\n className=\"p-0.5 rounded hover:bg-gray-200 dark:hover:bg-white/10 transition-colors\"\n >\n {copiedBlock === codeStr ? (\n <CheckIcon size={14} className=\"text-green-500\" />\n ) : (\n <CopyIcon size={14} className=\"text-gray-400 dark:text-white/40\" />\n )}\n </button>\n </div>\n <pre className=\"m-0 px-3 py-2 overflow-x-auto\">\n <code className=\"font-mono text-xs leading-[1.7] text-gray-800 dark:text-white/90 whitespace-pre\">{codeStr}</code>\n </pre>\n </div>\n );\n }\n return (\n <code className=\"bg-gray-100 dark:bg-white/[0.08] px-1.5 py-0.5 rounded font-mono text-xs text-[var(--chat-accent)]\">{children}</code>\n );\n },\n ul: ({ children }) => (\n <ul className=\"pl-5 mb-3 text-[0.8125rem] text-gray-900 dark:text-white/90 [&_li]:mb-1 marker:text-[var(--chat-accent)]/50\">\n {children}\n </ul>\n ),\n ol: ({ children }) => (\n <ol className=\"pl-5 mb-3 text-[0.8125rem] text-gray-900 dark:text-white/90 [&_li]:mb-1 marker:text-[var(--chat-accent)]/50\">\n {children}\n </ol>\n ),\n blockquote: ({ children }) => (\n <blockquote className=\"my-3 border-l-2 border-[var(--chat-accent)]/30 bg-[var(--chat-accent)]/[0.03] pl-4 pr-3 py-2 rounded-r-md italic text-gray-500 dark:text-white/60\">\n {children}\n </blockquote>\n ),\n a: ({ href, children }) => (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-[var(--chat-accent)] underline underline-offset-2 hover:brightness-125\"\n >\n {children}\n </a>\n ),\n h1: ({ children }) => <h1 className=\"mt-4 first:mt-0 mb-2 font-bold text-base text-gray-900 dark:text-white\">{children}</h1>,\n h2: ({ children }) => <h2 className=\"mt-3 first:mt-0 mb-2 font-bold text-[0.9rem] text-gray-900 dark:text-white\">{children}</h2>,\n h3: ({ children }) => <h3 className=\"mt-3 first:mt-0 mb-1.5 font-semibold text-[0.85rem] text-gray-900 dark:text-white\">{children}</h3>,\n table: ({ children }) => (\n <div className=\"my-3 overflow-x-auto rounded-lg border border-gray-200 dark:border-white/10\">\n <table className=\"w-full border-collapse text-xs\">{children}</table>\n </div>\n ),\n th: ({ children }) => (\n <th className=\"px-3 py-2 text-left font-semibold bg-gray-50 dark:bg-white/[0.04] border-b border-gray-200 dark:border-white/10 text-gray-900 dark:text-white\">\n {children}\n </th>\n ),\n td: ({ children }) => (\n <td className=\"px-3 py-2 border-b border-gray-200 dark:border-white/10 text-gray-700 dark:text-white/80\">{children}</td>\n ),\n }}\n >\n {content}\n </Markdown>\n );\n};\n","import { useEffect, useRef, useState } from 'react';\nimport type { AgentStatusState, ChatMessage } from '../types';\nimport { FileIcon, InfoIcon } from './icons';\nimport { ChatThinking } from './ChatThinking';\nimport { MarkdownMessage } from './MarkdownMessage';\n\ninterface ChatMessagesProps {\n messages: ChatMessage[];\n isLoading: boolean;\n agentStatus: AgentStatusState | null;\n agentName: string;\n logoIcon: React.ReactNode;\n t: (key: string) => string;\n}\n\nexport const ChatMessages = ({ messages, isLoading, agentStatus, agentName, logoIcon, t }: ChatMessagesProps) => {\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const [toolDetailMsgId, setToolDetailMsgId] = useState<string | null>(null);\n\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages]);\n\n return (\n <div className=\"flex-1 overflow-y-auto px-4 py-3 flex flex-col gap-4 filigran-chat-scrollable\">\n {messages.map((msg) => {\n const isAssistant = msg.role === 'assistant';\n const isEmpty = !msg.content;\n const isThinking = isAssistant && isEmpty && isLoading;\n\n if (isThinking) {\n return (\n <div key={msg.id}>\n <ChatThinking agentStatus={agentStatus} logoIcon={logoIcon} t={t} />\n </div>\n );\n }\n\n return (\n <div key={msg.id} className={`flex flex-col ${isAssistant ? 'items-start' : 'items-end'}`}>\n {isAssistant && (\n <div className=\"flex items-center gap-1.5 mb-1\">\n <div className=\"w-6 h-6 rounded-lg flex items-center justify-center bg-gradient-to-br from-[var(--chat-accent)]/20 to-[var(--chat-accent)]/5\">\n <span className=\"text-[var(--chat-accent)] [&>svg]:w-3 [&>svg]:h-3\">{logoIcon}</span>\n </div>\n <span className=\"font-semibold text-xs text-gray-900 dark:text-white\">{agentName}</span>\n </div>\n )}\n\n {msg.files && msg.files.length > 0 && (\n <div className=\"flex gap-1.5 flex-wrap mb-1.5\">\n {msg.files.map((f, i) => (\n <span\n key={i}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.7rem] text-gray-600 dark:text-white/60\"\n >\n <FileIcon size={14} />\n {f.name}\n </span>\n ))}\n </div>\n )}\n\n <div\n className={`max-w-[90%] ${\n isAssistant\n ? 'pl-1 py-1 text-[0.8125rem] leading-7'\n : 'px-3.5 py-2 rounded-[14px_14px_4px_14px] bg-[var(--chat-accent-dark)] text-white text-[0.8125rem] leading-6'\n }`}\n >\n {isAssistant ? <MarkdownMessage content={msg.content} /> : msg.content}\n {isAssistant && isEmpty && !isLoading && <span className=\"text-[0.8125rem] text-gray-400 dark:text-white/40 italic\">...</span>}\n {isAssistant && !isEmpty && isLoading && (\n <span className=\"inline-block w-1.5 h-4 bg-[var(--chat-accent)]/70 rounded-sm ml-0.5 animate-pulse align-text-bottom\" />\n )}\n </div>\n\n {isAssistant && !isEmpty && !isLoading && msg.toolNames && msg.toolNames.length > 0 && (\n <>\n <button\n type=\"button\"\n onClick={() => setToolDetailMsgId(toolDetailMsgId === msg.id ? null : msg.id)}\n className=\"mt-0.5 p-1 rounded-lg opacity-50 hover:opacity-100 hover:text-[var(--chat-accent)] transition-opacity\"\n title={t('Reasoning details')}\n >\n <InfoIcon size={14} />\n </button>\n {toolDetailMsgId === msg.id && (\n <div className=\"mt-1.5 p-3 rounded-lg bg-gray-50 dark:bg-white/[0.04] border border-gray-200 dark:border-white/10\">\n <p className=\"text-[0.7rem] text-gray-500 dark:text-white/40 mb-1.5\">\n {msg.iterations && msg.iterations > 1 ? `${msg.iterations} iterations · ` : ''}\n {msg.toolCallCount ?? msg.toolNames.length}{' '}\n {(msg.toolCallCount ?? msg.toolNames.length) === 1 ? t('tool call') : t('tool calls')}\n </p>\n <div className=\"flex flex-wrap gap-1\">\n {Array.from(new Set(msg.toolNames)).map((tn) => (\n <span\n key={tn}\n className=\"inline-flex items-center px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.68rem] font-mono text-gray-500 dark:text-white/40\"\n >\n {tn.replace(/_/g, ' ')}\n </span>\n ))}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n );\n })}\n <div ref={messagesEndRef} />\n </div>\n );\n};\n","interface ChatWelcomeProps {\n firstName: string;\n logoIcon: React.ReactNode;\n promptSuggestions: string[];\n onPromptClick: (prompt: string) => void;\n t: (key: string) => string;\n}\n\nexport const ChatWelcome = ({ firstName, logoIcon, promptSuggestions, onPromptClick, t }: ChatWelcomeProps) => (\n <div className=\"flex-1 flex flex-col items-center justify-center px-6 pb-8\">\n <span className=\"text-[var(--chat-accent)] mb-4 [&>svg]:w-12 [&>svg]:h-12 drop-shadow-[0_0_12px_var(--chat-accent-40)]\">{logoIcon}</span>\n <h2 className=\"text-xl font-medium mb-6 text-center text-gray-900 dark:text-white\" style={{ fontFamily: '\"Geologica\", sans-serif' }}>\n {t('How can I help you, ')}\n {firstName}?\n </h2>\n <div className=\"w-full max-w-[320px]\">\n <span className=\"block text-center mb-2 text-[0.65rem] tracking-[1.5px] uppercase text-[var(--chat-accent)] font-semibold\">\n {t('Suggestions')}\n </span>\n {promptSuggestions.map((prompt) => (\n <button\n key={prompt}\n type=\"button\"\n onClick={() => onPromptClick(prompt)}\n className=\"w-full text-left text-[0.8125rem] text-gray-800 dark:text-white py-1.5 px-3 mb-1 rounded-lg border border-gray-200 dark:border-white/10 bg-transparent transition-colors hover:bg-[var(--chat-accent-10)] hover:border-[var(--chat-accent-50)]\"\n >\n {t(prompt)}\n </button>\n ))}\n </div>\n </div>\n);\n","import { type FunctionComponent, useEffect, useState } from 'react';\nimport type { ChatMessage, ChatPanelProps } from '../types';\nimport { hexAlpha, identity } from '../utils';\nimport { useChat } from '../hooks/useChat';\nimport { useAgents } from '../hooks/useAgents';\nimport { useSidebarResize } from '../hooks/useSidebarResize';\nimport { DefaultLogoIcon } from './icons';\nimport { ChatHeader } from './ChatHeader';\nimport { ChatInput } from './ChatInput';\nimport { ChatMessages } from './ChatMessages';\nimport { ChatWelcome } from './ChatWelcome';\n\nconst FLOATING_WIDTH = 380;\nconst FLOATING_HEIGHT = 560;\nconst SIDEBAR_GAP = 6;\n\nconst DEFAULT_SUGGESTIONS = [\n 'Help me create a new simulation scenario',\n 'What are the latest attack patterns?',\n 'How do I configure detection rules?',\n 'Summarize my recent findings',\n];\n\nexport const ChatPanel: FunctionComponent<ChatPanelProps> = ({\n mode,\n onClose,\n onModeChange,\n topOffset = 0,\n apiBaseUrl,\n apiEndpoints,\n agentDashboardUrl,\n user,\n t = identity,\n accentColor = '#7b5cff',\n logoIcon,\n promptSuggestions = DEFAULT_SUGGESTIONS,\n resizable = false,\n onWidthChange,\n onResizeStart,\n onResizeEnd,\n pushContentSelector,\n backendType = 'rest',\n}) => {\n const [modeMenuOpen, setModeMenuOpen] = useState(false);\n\n const { agents, selectedAgent, agentMenuOpen, setAgentMenuOpen, handleSwitchAgent } = useAgents({ apiBaseUrl, apiEndpoints, backendType });\n\n const {\n messages,\n inputValue,\n setInputValue,\n isLoading,\n agentStatus,\n attachedFiles,\n conversationId,\n historyLoadedRef,\n handleFileAdd,\n handlePaste,\n handleSendMessage,\n handleNewChat,\n handleStopGenerating,\n setAttachedFiles,\n setMessages,\n setConversationId,\n } = useChat({ apiBaseUrl, apiEndpoints, backendType, agentSlug: selectedAgent?.slug, t });\n\n const { sidebarWidth, handleResizeStart, defaultWidth, isResizing } = useSidebarResize({\n mode,\n resizable,\n onWidthChange,\n onResizeStart,\n onResizeEnd,\n });\n\n // Push content when sidebar mode is active using CSS variable\n useEffect(() => {\n const width = mode === 'sidebar' ? (resizable ? sidebarWidth : defaultWidth) : 0;\n const pushWidth = width > 0 ? width + SIDEBAR_GAP : 0;\n \n // Set CSS variable on :root for any component to use\n document.documentElement.style.setProperty('--chatbot-sidebar-width', `${pushWidth}px`);\n document.documentElement.style.setProperty(\n '--chatbot-transition',\n isResizing ? 'none' : 'all 225ms cubic-bezier(0.4, 0, 0.2, 1)'\n );\n\n // Also apply to pushContentSelector if provided (for simple cases)\n if (pushContentSelector) {\n const contentElement = document.querySelector<HTMLElement>(pushContentSelector);\n if (contentElement) {\n const originalPaddingRight = contentElement.style.paddingRight;\n const originalTransition = contentElement.style.transition;\n \n contentElement.style.paddingRight = pushWidth > 0 ? `${pushWidth}px` : '';\n contentElement.style.transition = isResizing \n ? 'none' \n : 'padding-right 225ms cubic-bezier(0.4, 0, 0.2, 1)';\n\n return () => {\n contentElement.style.paddingRight = originalPaddingRight;\n contentElement.style.transition = originalTransition;\n document.documentElement.style.setProperty('--chatbot-sidebar-width', '0px');\n };\n }\n }\n\n return () => {\n document.documentElement.style.setProperty('--chatbot-sidebar-width', '0px');\n };\n }, [pushContentSelector, mode, sidebarWidth, defaultWidth, resizable, isResizing]);\n\n const resolvedLogo = logoIcon ?? <DefaultLogoIcon size={24} />;\n const firstName = user.firstName;\n const agentName = selectedAgent?.name || 'Assistant';\n\n const cssVars = {\n '--chat-accent': accentColor,\n '--chat-accent-10': hexAlpha(accentColor, 0.1),\n '--chat-accent-40': hexAlpha(accentColor, 0.25),\n '--chat-accent-50': hexAlpha(accentColor, 0.5),\n '--chat-accent-dark': accentColor,\n } as React.CSSProperties;\n\n // Load conversation history when agent is selected\n useEffect(() => {\n // Skip session history if disabled, using single endpoint mode, or non-REST backend\n if (apiEndpoints?.sessions === null || apiEndpoints?.singleEndpoint || backendType === 'legacy' || backendType === 'ag-ui') return;\n if (!conversationId || historyLoadedRef.current || !selectedAgent) return;\n historyLoadedRef.current = true;\n const sessionsUrl = `${apiBaseUrl}${apiEndpoints?.sessions ?? '/chat/sessions'}`;\n\n const clearStaleConversation = () => {\n setConversationId(null);\n localStorage.removeItem('filigranChatConversationId');\n };\n\n fetch(sessionsUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n conversation_id: conversationId,\n agent_slug: selectedAgent.slug,\n }),\n })\n .then((res) => {\n if (!res.ok) {\n clearStaleConversation();\n return null;\n }\n return res.json();\n })\n .then((data) => {\n if (!data?.messages?.length) return;\n const restored: ChatMessage[] = data.messages.map((m: { role: string; content: string }, i: number) => ({\n id: `restored-${i}`,\n role: m.role as 'user' | 'assistant',\n content: m.content,\n timestamp: new Date(),\n }));\n setMessages(restored);\n })\n .catch(() => {\n clearStaleConversation();\n });\n }, [conversationId, selectedAgent, apiBaseUrl, apiEndpoints, historyLoadedRef, setMessages, setConversationId]);\n\n const onSwitchAgent = (agent: typeof selectedAgent) => {\n if (!agent) return;\n handleSwitchAgent(agent, () => {\n handleNewChat();\n });\n };\n\n const containerClasses = (() => {\n const base = 'filigran-chatbot';\n switch (mode) {\n case 'sidebar':\n return `${base} fixed right-0 bottom-0 flex flex-col bg-white dark:bg-[#1e1e2e] border-l border-gray-200 dark:border-white/10 z-[1200]`;\n case 'floating':\n return `${base} fixed bottom-5 right-5 flex flex-col bg-white dark:bg-[#1e1e2e] rounded-xl shadow-[0_8px_32px_rgba(0,0,0,0.15)] dark:shadow-[0_8px_32px_rgba(0,0,0,0.4)] z-[1300] border border-gray-200 dark:border-white/10`;\n case 'fullscreen':\n return `${base} fixed right-0 bottom-0 left-0 flex flex-col bg-gray-50 dark:bg-[#161622] z-[1400]`;\n default:\n return base;\n }\n })();\n\n const containerStyle: React.CSSProperties = {\n ...cssVars,\n ...(mode === 'sidebar'\n ? { top: topOffset, width: resizable ? sidebarWidth : defaultWidth }\n : mode === 'floating'\n ? { width: FLOATING_WIDTH, height: FLOATING_HEIGHT }\n : { top: topOffset }),\n };\n\n return (\n <div className={containerClasses} style={containerStyle}>\n {mode === 'sidebar' && resizable && (\n <div\n onMouseDown={handleResizeStart}\n className=\"absolute top-0 -left-1 bottom-0 w-2 cursor-col-resize z-10 group\"\n >\n <div className=\"absolute top-0 left-1/2 -translate-x-1/2 bottom-0 w-0.5 rounded bg-[var(--chat-accent)] opacity-0 transition-opacity group-hover:opacity-100 group-active:opacity-100\" />\n </div>\n )}\n <ChatHeader\n mode={mode}\n agentName={agentName}\n agents={agents}\n selectedAgent={selectedAgent}\n agentMenuOpen={agentMenuOpen}\n onAgentMenuToggle={() => setAgentMenuOpen((p) => !p)}\n onAgentMenuClose={() => setAgentMenuOpen(false)}\n onSwitchAgent={onSwitchAgent}\n modeMenuOpen={modeMenuOpen}\n onModeMenuToggle={() => setModeMenuOpen((p) => !p)}\n onModeMenuClose={() => setModeMenuOpen(false)}\n onModeChange={onModeChange}\n onNewChat={handleNewChat}\n onClose={onClose}\n logoIcon={resolvedLogo}\n agentDashboardUrl={agentDashboardUrl}\n t={t}\n />\n {messages.length === 0 ? (\n <ChatWelcome firstName={firstName} logoIcon={resolvedLogo} promptSuggestions={promptSuggestions} onPromptClick={setInputValue} t={t} />\n ) : (\n <ChatMessages messages={messages} isLoading={isLoading} agentStatus={agentStatus} agentName={agentName} logoIcon={resolvedLogo} t={t} />\n )}\n <ChatInput\n inputValue={inputValue}\n onInputChange={setInputValue}\n onSend={handleSendMessage}\n onStop={handleStopGenerating}\n isLoading={isLoading}\n attachedFiles={attachedFiles}\n onFileAdd={handleFileAdd}\n onFileRemove={(i) => setAttachedFiles((prev) => prev.filter((_, j) => j !== i))}\n onPaste={handlePaste}\n t={t}\n mode={mode}\n />\n </div>\n );\n};\n","import type { FunctionComponent } from 'react';\nimport type { ChatToggleButtonProps } from '../types';\nimport { hexAlpha } from '../utils';\nimport { DefaultLogoIcon } from './icons';\n\nexport const ChatToggleButton: FunctionComponent<ChatToggleButtonProps> = ({ isOpen, onToggle, label = 'Ask Assistant', accentColor = '#7b5cff', icon }) => {\n const resolvedIcon = icon ?? <DefaultLogoIcon size={16} />;\n\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"filigran-chatbot inline-flex items-center gap-1.5 px-3 py-[3px] text-[0.8125rem] font-medium whitespace-nowrap rounded-md border transition-colors\"\n style={{\n borderColor: isOpen ? accentColor : hexAlpha(accentColor, 0.5),\n color: accentColor,\n backgroundColor: isOpen ? hexAlpha(accentColor, 0.1) : 'transparent',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.borderColor = accentColor;\n e.currentTarget.style.backgroundColor = hexAlpha(accentColor, 0.1);\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.borderColor = isOpen ? accentColor : hexAlpha(accentColor, 0.5);\n e.currentTarget.style.backgroundColor = isOpen ? hexAlpha(accentColor, 0.1) : 'transparent';\n }}\n >\n <span className=\"[&>svg]:w-4 [&>svg]:h-4\">{resolvedIcon}</span>\n {label}\n </button>\n );\n};\n"],"names":["hexAlpha","hex","alpha","Math","round","toString","padStart","identity","key","parseLegacyEvent","evt","ctx","eventType","event","data","nodeId","status","activeNodeId","action","content","replace","reasoning","usedTools","length","hasUsedTools","tools","map","t","tool","Array","isArray","chatId","parseRestEvent","type","st","thinkingContent","conversationId","conversation_id","toolNames","tool_names","toolCallCount","tool_call_count","iterations","parseAgUiEvent","message","stepName","delta","toolName","toolCallName","STORAGE_KEY","LEGACY_CHAT_ID_KEY","useChat","apiBaseUrl","apiEndpoints","backendType","agentSlug","isLegacy","messages","setMessages","useState","inputValue","setInputValue","isLoading","setIsLoading","agentStatus","setAgentStatus","setConversationId","window","localStorage","getItem","attachedFiles","setAttachedFiles","legacyChatId","setLegacyChatId","historyLoadedRef","useRef","abortControllerRef","hasUsedToolsRef","handleFileAdd","fileList","newFiles","from","forEach","file","reader","FileReader","onload","push","name","size","dataUrl","result","prev","readAsDataURL","handlePaste","e","files","clipboardData","preventDefault","handleSendMessage","async","trim","userMsg","id","crypto","randomUUID","role","timestamp","Date","undefined","current","assistantId","controller","AbortController","requestBody","opts","question","streaming","threadId","runId","context","state","forwardedProps","agent_slug","buildRequestBody","res","fetch","singleEndpoint","method","headers","body","JSON","stringify","signal","ok","m","parseEvent","getParser","getReader","decoder","TextDecoder","buffer","accumulated","doneReceived","done","value","read","decode","stream","lines","split","pop","rawLine","line","startsWith","jsonStr","slice","parsed","parse","setItem","err","DOMException","handleNewChat","abort","removeItem","handleStopGenerating","filter","STORAGE_AGENT_KEY","SIDEBAR_WIDTH","SIDEBAR_WIDTH_STORAGE_KEY","AttachFileIcon","className","_jsx","xmlns","width","height","viewBox","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","children","d","BrainIcon","_jsxs","CheckIcon","ChevronDownIcon","CloseIcon","CopyIcon","x","y","rx","ry","DatabaseIcon","cx","cy","DefaultLogoIcon","EditIcon","ExternalLinkIcon","FileIcon","FloatingIcon","FullscreenExitIcon","FullscreenIcon","GlobeIcon","r","InfoIcon","MailIcon","SearchIcon","SendIcon","SidebarIcon","SparklesIcon","StopCircleIcon","TerminalIcon","points","x1","x2","y1","y2","UserPlusIcon","WrenchIcon","Dropdown","open","onClose","anchorRef","placement","panelRef","pos","setPos","top","left","ref","handler","active","useEffect","listener","contains","target","document","addEventListener","removeEventListener","useClickOutside","useCallback","rect","getBoundingClientRect","right","bottom","portalTarget","el","node","classList","parentElement","findChatbotRoot","createPortal","style","Spinner","Tooltip","title","show","setShow","onMouseEnter","onMouseLeave","modeOptions","mode","label","getIcon","p","ChatHeader","agentName","agents","selectedAgent","agentMenuOpen","onAgentMenuToggle","onAgentMenuClose","onSwitchAgent","modeMenuOpen","onModeMenuToggle","onModeMenuClose","onModeChange","onNewChat","logoIcon","agentDashboardUrl","agentAnchorRef","modeAnchorRef","CurrentModeIcon","onClick","agent","description","opt","ChatInput","onInputChange","onSend","onStop","onFileAdd","onFileRemove","onPaste","fileInputRef","textareaRef","hasContent","f","i","multiple","hidden","onChange","click","placeholder","min","scrollHeight","onKeyDown","shiftKey","rows","maxHeight","disabled","ThinkingTextBubble","cleaned","scrollTop","animation","ChatThinking","StatusIcon","showDots","rawNames","lower","n","toLowerCase","some","count","includes","display","c","toUpperCase","unique","Set","consultName","checkCount","fetchCount","targetName","resolveStatusVisual","_Fragment","delay","MarkdownMessage","copiedBlock","setCopiedBlock","Markdown","remarkPlugins","remarkGfm","components","code","match","exec","codeStr","String","handleCopyCode","navigator","clipboard","writeText","setTimeout","ul","ol","blockquote","a","href","rel","h1","h2","h3","table","th","td","ChatMessages","messagesEndRef","toolDetailMsgId","setToolDetailMsgId","scrollIntoView","behavior","msg","isAssistant","isEmpty","tn","ChatWelcome","firstName","promptSuggestions","onPromptClick","fontFamily","prompt","DEFAULT_SUGGESTIONS","ChatPanel","topOffset","user","accentColor","resizable","onWidthChange","onResizeStart","onResizeEnd","pushContentSelector","setModeMenuOpen","setAgentMenuOpen","handleSwitchAgent","setAgents","setSelectedAgent","then","json","savedSlug","find","slug","catch","onSwitch","useAgents","sidebarWidth","handleResizeStart","defaultWidth","isResizing","setSidebarWidth","stored","parseInt","Number","isNaN","setIsResizing","isResizingRef","sidebarWidthRef","onWidthChangeRef","onResizeEndRef","handleMouseMove","newWidth","innerWidth","clientX","maxWidth","clamped","max","handleMouseUp","cursor","userSelect","handleWindowResize","useSidebarResize","pushWidth","documentElement","setProperty","contentElement","querySelector","originalPaddingRight","paddingRight","originalTransition","transition","resolvedLogo","cssVars","sessions","clearStaleConversation","restored","containerClasses","base","containerStyle","onMouseDown","_","j","ChatToggleButton","isOpen","onToggle","icon","resolvedIcon","borderColor","color","backgroundColor","currentTarget"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/utils/index.ts","../../src/hooks/protocols/parseLegacyEvent.ts","../../src/hooks/protocols/parseRestEvent.ts","../../src/hooks/protocols/parseAgUiEvent.ts","../../src/hooks/useChat.ts","../../src/hooks/useAgents.ts","../../src/hooks/useSidebarResize.ts","../../src/components/icons/AttachFileIcon.tsx","../../src/components/icons/BrainIcon.tsx","../../src/components/icons/CheckIcon.tsx","../../src/components/icons/ChevronDownIcon.tsx","../../src/components/icons/CloseIcon.tsx","../../src/components/icons/CopyIcon.tsx","../../src/components/icons/DatabaseIcon.tsx","../../src/components/icons/DefaultLogoIcon.tsx","../../src/components/icons/EditIcon.tsx","../../src/components/icons/ExternalLinkIcon.tsx","../../src/components/icons/FileIcon.tsx","../../src/components/icons/FloatingIcon.tsx","../../src/components/icons/FullscreenExitIcon.tsx","../../src/components/icons/FullscreenIcon.tsx","../../src/components/icons/GlobeIcon.tsx","../../src/components/icons/InfoIcon.tsx","../../src/components/icons/MailIcon.tsx","../../src/components/icons/SearchIcon.tsx","../../src/components/icons/SendIcon.tsx","../../src/components/icons/SidebarIcon.tsx","../../src/components/icons/SparklesIcon.tsx","../../src/components/icons/StopCircleIcon.tsx","../../src/components/icons/TerminalIcon.tsx","../../src/components/icons/UserPlusIcon.tsx","../../src/components/icons/WrenchIcon.tsx","../../src/components/Dropdown.tsx","../../src/hooks/useClickOutside.ts","../../src/components/Spinner.tsx","../../src/components/Tooltip.tsx","../../src/components/ChatHeader.tsx","../../src/components/ChatInput.tsx","../../src/components/ChatThinking.tsx","../../src/components/MarkdownMessage.tsx","../../src/components/ChatMessages.tsx","../../src/components/ChatWelcome.tsx","../../src/components/ChatPanel.tsx","../../src/components/ChatToggleButton.tsx"],"sourcesContent":["export function hexAlpha(hex: string, alpha: number): string {\n const a = Math.round(alpha * 255)\n .toString(16)\n .padStart(2, '0');\n return `${hex}${a}`;\n}\n\nexport const identity = (key: string) => key;\n","import type { ParsedAction, ProtocolContext } from './types';\n\n/**\n * Parse a Flowise-style SSE event into a normalized action.\n */\nexport function parseLegacyEvent(evt: Record<string, unknown>, ctx: ProtocolContext): ParsedAction {\n const eventType = evt.event as string | undefined;\n\n if (eventType === 'nextAgentFlow') {\n const data = evt.data as Record<string, unknown> | undefined;\n const nodeId = data?.nodeId as string | undefined;\n if (data?.status === 'INPROGRESS' && nodeId) {\n ctx.activeNodeId = nodeId;\n }\n return { action: 'noop' };\n }\n\n if (eventType === 'start') {\n return { action: 'noop' };\n }\n\n if (eventType === 'token') {\n const tokenData = ((evt.data as string) ?? '').replace(/<br\\s*\\/?>/g, '\\n');\n return { action: 'stream', content: tokenData };\n }\n\n if (eventType === 'agentReasoning') {\n const reasoning = evt.data as Record<string, unknown> | undefined;\n const usedTools = reasoning?.usedTools as Array<{ tool: string }> | undefined;\n if (usedTools?.length) {\n ctx.hasUsedTools = true;\n return { action: 'status', status: 'tool_start', tools: usedTools.map((t) => t.tool) };\n }\n if (ctx.hasUsedTools) {\n return { action: 'status', status: 'analyzing' };\n }\n return { action: 'status', status: 'thinking' };\n }\n\n if (eventType === 'usedTools') {\n ctx.hasUsedTools = true;\n const data = evt.data as Array<{ tool: string }> | undefined;\n const toolNames = Array.isArray(data) ? data.map((t) => t.tool) : [];\n return { action: 'status', status: 'tool_start', tools: toolNames };\n }\n\n if (eventType === 'metadata') {\n const data = evt.data as Record<string, unknown> | undefined;\n const chatId = data?.chatId as string | undefined;\n if (chatId) {\n return { action: 'set_chat_id', chatId };\n }\n return { action: 'noop' };\n }\n\n if (eventType === 'error') {\n return { action: 'error', content: (evt.data as string) || '' };\n }\n\n if (eventType === 'end') {\n return { action: 'done', content: '' };\n }\n\n return { action: 'noop' };\n}\n","import type { ParsedAction, ProtocolContext } from './types';\n\n/**\n * Parse an XTM One (REST) SSE event into a normalized action.\n */\nexport function parseRestEvent(evt: Record<string, unknown>, ctx: ProtocolContext): ParsedAction {\n const type = evt.type as string | undefined;\n\n if (type === 'error') {\n return { action: 'error', content: (evt.content as string) || '' };\n }\n\n if (type === 'status') {\n const st = evt.status as string;\n if (st === 'tool_done' || st === 'wind_down') {\n return { action: 'noop' };\n }\n if (st === 'streaming') {\n return { action: 'status', status: 'streaming' };\n }\n if (st === 'thinking_text') {\n return { action: 'status', status: 'thinking_text', thinkingContent: evt.content as string };\n }\n if (st === 'tool_start') {\n ctx.hasUsedTools = true;\n return { action: 'status', status: 'tool_start', tools: evt.tools as string[] | undefined };\n }\n if (st === 'thinking' && ctx.hasUsedTools) {\n return { action: 'status', status: 'analyzing' };\n }\n return { action: 'status', status: st, tools: evt.tools as string[] | undefined };\n }\n\n if (type === 'stream') {\n return { action: 'stream', content: evt.content as string };\n }\n\n if (type === 'done') {\n return {\n action: 'done',\n content: evt.content as string,\n conversationId: evt.conversation_id as string | undefined,\n toolNames: evt.tool_names as string[] | undefined,\n toolCallCount: evt.tool_call_count as number | undefined,\n iterations: evt.iterations as number | undefined,\n };\n }\n\n return { action: 'noop' };\n}\n","import type { ParsedAction, ProtocolContext } from './types';\n\n/**\n * AG-UI protocol event types.\n * @see https://github.com/ag-ui-protocol/ag-ui\n */\n\n/**\n * Parse an AG-UI protocol SSE event into a normalized action.\n *\n * AG-UI uses a Start/Content/End lifecycle for messages and tool calls.\n * We map these to the same internal actions used by the other protocols.\n */\nexport function parseAgUiEvent(evt: Record<string, unknown>, ctx: ProtocolContext): ParsedAction {\n const type = evt.type as string | undefined;\n\n // --- Run lifecycle ---\n\n if (type === 'RUN_STARTED') {\n return { action: 'status', status: 'thinking' };\n }\n\n if (type === 'RUN_FINISHED') {\n return { action: 'done', content: '' };\n }\n\n if (type === 'RUN_ERROR') {\n return { action: 'error', content: (evt.message as string) || 'Unknown error' };\n }\n\n // --- Step lifecycle ---\n\n if (type === 'STEP_STARTED') {\n const stepName = evt.stepName as string | undefined;\n return { action: 'status', status: stepName || 'thinking' };\n }\n\n if (type === 'STEP_FINISHED') {\n return { action: 'noop' };\n }\n\n // --- Text message streaming ---\n\n if (type === 'TEXT_MESSAGE_START') {\n return { action: 'status', status: 'streaming' };\n }\n\n if (type === 'TEXT_MESSAGE_CONTENT') {\n const delta = evt.delta as string;\n if (delta) {\n return { action: 'stream', content: delta };\n }\n return { action: 'noop' };\n }\n\n if (type === 'TEXT_MESSAGE_END') {\n return { action: 'noop' };\n }\n\n // TEXT_MESSAGE_CHUNK is a convenience event that combines Start+Content+End\n if (type === 'TEXT_MESSAGE_CHUNK') {\n const delta = evt.delta as string | undefined;\n if (delta) {\n return { action: 'stream', content: delta };\n }\n return { action: 'noop' };\n }\n\n // --- Tool call lifecycle ---\n\n if (type === 'TOOL_CALL_START') {\n ctx.hasUsedTools = true;\n const toolName = evt.toolCallName as string | undefined;\n return { action: 'status', status: 'tool_start', tools: toolName ? [toolName] : [] };\n }\n\n if (type === 'TOOL_CALL_ARGS') {\n // Tool arguments streaming — no UI equivalent, skip\n return { action: 'noop' };\n }\n\n if (type === 'TOOL_CALL_END') {\n return { action: 'status', status: 'analyzing' };\n }\n\n if (type === 'TOOL_CALL_RESULT') {\n // Tool result — no direct UI mapping, skip\n return { action: 'noop' };\n }\n\n if (type === 'TOOL_CALL_CHUNK') {\n // Convenience form — treat like TOOL_CALL_START if it has a name\n const toolName = evt.toolCallName as string | undefined;\n if (toolName) {\n ctx.hasUsedTools = true;\n return { action: 'status', status: 'tool_start', tools: [toolName] };\n }\n return { action: 'noop' };\n }\n\n // --- Reasoning / thinking ---\n\n if (type === 'REASONING_START' || type === 'REASONING_MESSAGE_START') {\n return { action: 'status', status: 'thinking' };\n }\n\n if (type === 'REASONING_MESSAGE_CONTENT' || type === 'REASONING_MESSAGE_CHUNK') {\n // Reasoning text — show as thinking status (content not surfaced to chat)\n return { action: 'status', status: 'thinking' };\n }\n\n if (type === 'REASONING_MESSAGE_END' || type === 'REASONING_END' || type === 'REASONING_ENCRYPTED_VALUE') {\n return { action: 'noop' };\n }\n\n // --- State management ---\n\n if (type === 'STATE_SNAPSHOT' || type === 'STATE_DELTA' || type === 'MESSAGES_SNAPSHOT') {\n // State sync — not mapped to chat UI currently\n return { action: 'noop' };\n }\n\n // --- Activity events ---\n\n if (type === 'ACTIVITY_SNAPSHOT' || type === 'ACTIVITY_DELTA') {\n return { action: 'noop' };\n }\n\n // --- Pass-through / custom ---\n\n if (type === 'RAW' || type === 'CUSTOM') {\n return { action: 'noop' };\n }\n\n return { action: 'noop' };\n}\n","import { useRef, useState } from 'react';\nimport type { AgentStatusState, ApiEndpoints, BackendType, ChatFile, ChatMessage } from '../types';\nimport type { ParsedAction, ProtocolContext } from './protocols';\nimport { parseAgUiEvent, parseLegacyEvent, parseRestEvent } from './protocols';\n\nconst STORAGE_KEY = 'filigranChatConversationId';\nconst LEGACY_CHAT_ID_KEY = 'filigranChatLegacyChatId';\n\ninterface UseChatOptions {\n apiBaseUrl: string;\n apiEndpoints?: ApiEndpoints;\n backendType?: BackendType;\n agentSlug: string | null | undefined;\n t: (key: string) => string;\n}\n\ninterface UseChatReturn {\n messages: ChatMessage[];\n inputValue: string;\n setInputValue: (value: string) => void;\n isLoading: boolean;\n agentStatus: AgentStatusState | null;\n attachedFiles: ChatFile[];\n conversationId: string | null;\n historyLoadedRef: React.MutableRefObject<boolean>;\n handleFileAdd: (fileList: FileList | null) => void;\n handlePaste: (e: React.ClipboardEvent) => void;\n handleSendMessage: () => Promise<void>;\n handleNewChat: () => void;\n handleStopGenerating: () => void;\n setAttachedFiles: React.Dispatch<React.SetStateAction<ChatFile[]>>;\n setMessages: React.Dispatch<React.SetStateAction<ChatMessage[]>>;\n setConversationId: React.Dispatch<React.SetStateAction<string | null>>;\n}\n\nfunction getParser(backendType: BackendType): (evt: Record<string, unknown>, ctx: ProtocolContext) => ParsedAction {\n switch (backendType) {\n case 'legacy':\n return parseLegacyEvent;\n case 'ag-ui':\n return parseAgUiEvent;\n default:\n return parseRestEvent;\n }\n}\n\nfunction buildRequestBody(\n backendType: BackendType,\n content: string,\n opts: { legacyChatId: string | null; conversationId: string | null; agentSlug: string | null | undefined },\n): Record<string, unknown> {\n switch (backendType) {\n case 'legacy':\n return { question: content, chatId: opts.legacyChatId ?? undefined, streaming: true };\n case 'ag-ui':\n return {\n threadId: opts.conversationId ?? crypto.randomUUID(),\n runId: crypto.randomUUID(),\n messages: [{ id: crypto.randomUUID(), role: 'user', content }],\n tools: [],\n context: [],\n state: {},\n forwardedProps: opts.agentSlug ? { agentSlug: opts.agentSlug } : {},\n };\n default:\n return { content, conversation_id: opts.conversationId, agent_slug: opts.agentSlug };\n }\n}\n\nexport function useChat({ apiBaseUrl, apiEndpoints, backendType = 'rest', agentSlug, t }: UseChatOptions): UseChatReturn {\n const isLegacy = backendType === 'legacy';\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [inputValue, setInputValue] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [agentStatus, setAgentStatus] = useState<AgentStatusState | null>(null);\n const [conversationId, setConversationId] = useState<string | null>(() => {\n if (typeof window === 'undefined') return null;\n return localStorage.getItem(STORAGE_KEY);\n });\n const [attachedFiles, setAttachedFiles] = useState<ChatFile[]>([]);\n const [legacyChatId, setLegacyChatId] = useState<string | null>(() => {\n if (typeof window === 'undefined') return null;\n return localStorage.getItem(LEGACY_CHAT_ID_KEY);\n });\n\n const historyLoadedRef = useRef(false);\n const abortControllerRef = useRef<AbortController | null>(null);\n const hasUsedToolsRef = useRef(false);\n\n // Determine message endpoint URL\n const getMessagesUrl = () => {\n if (isLegacy || apiEndpoints?.singleEndpoint) {\n return apiBaseUrl; // POST directly to base URL\n }\n return `${apiBaseUrl}${apiEndpoints?.messages ?? '/chat/messages'}`;\n };\n\n const handleFileAdd = (fileList: FileList | null) => {\n if (!fileList) return;\n const newFiles: ChatFile[] = [];\n Array.from(fileList).forEach((file) => {\n const reader = new FileReader();\n reader.onload = () => {\n newFiles.push({\n name: file.name,\n type: file.type,\n size: file.size,\n dataUrl: reader.result as string,\n });\n if (newFiles.length === fileList.length) {\n setAttachedFiles((prev) => [...prev, ...newFiles]);\n }\n };\n reader.readAsDataURL(file);\n });\n };\n\n const handlePaste = (e: React.ClipboardEvent) => {\n const { files } = e.clipboardData;\n if (files.length > 0) {\n e.preventDefault();\n handleFileAdd(files);\n }\n };\n\n const handleSendMessage = async () => {\n if ((!inputValue.trim() && attachedFiles.length === 0) || isLoading) return;\n const content = inputValue.trim();\n\n const userMsg: ChatMessage = {\n id: crypto.randomUUID(),\n role: 'user',\n content,\n timestamp: new Date(),\n files: attachedFiles.length > 0 ? [...attachedFiles] : undefined,\n };\n setMessages((prev) => [...prev, userMsg]);\n setInputValue('');\n setAttachedFiles([]);\n setIsLoading(true);\n setAgentStatus({ status: 'thinking' });\n hasUsedToolsRef.current = false;\n\n const assistantId = crypto.randomUUID();\n setMessages((prev) => [...prev, { id: assistantId, role: 'assistant', content: '', timestamp: new Date() }]);\n\n try {\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n const requestBody = buildRequestBody(backendType, content, { legacyChatId, conversationId, agentSlug });\n\n const res = await fetch(getMessagesUrl(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n signal: controller.signal,\n });\n\n if (!res.ok || !res.body) {\n setMessages((prev) =>\n prev.map((m) => (m.id === assistantId ? { ...m, content: t('Unable to connect. Please check the configuration.') } : m)),\n );\n return;\n }\n\n const parseEvent = getParser(backendType);\n const ctx: ProtocolContext = { hasUsedTools: false, activeNodeId: '' };\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let accumulated = '';\n let doneReceived = false;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n for (const rawLine of lines) {\n const line = rawLine.replace(/\\r$/, '');\n if (!line.startsWith('data:')) continue;\n const jsonStr = line.startsWith('data: ') ? line.slice(6) : line.slice(5);\n try {\n const evt = JSON.parse(jsonStr) as Record<string, unknown>;\n const parsed: ParsedAction = parseEvent(evt, ctx);\n\n // Sync ref → context for cross-event tracking\n ctx.hasUsedTools = ctx.hasUsedTools || hasUsedToolsRef.current;\n\n switch (parsed.action) {\n case 'status':\n if (parsed.status === 'tool_start') hasUsedToolsRef.current = true;\n if (parsed.status === 'thinking_text') {\n setAgentStatus((prev) => ({\n ...prev,\n status: prev?.status ?? 'thinking',\n thinkingContent: (prev?.thinkingContent ?? '') + (parsed.thinkingContent ?? ''),\n }));\n } else {\n setAgentStatus((prev) => ({\n status: parsed.status,\n tools: parsed.tools,\n thinkingContent: prev?.thinkingContent,\n }));\n }\n break;\n\n case 'stream':\n accumulated += parsed.content;\n setAgentStatus({ status: 'streaming' });\n setMessages((prev) => prev.map((m) => (m.id === assistantId ? { ...m, content: accumulated } : m)));\n break;\n\n case 'done':\n doneReceived = true;\n if (parsed.conversationId) {\n setConversationId(parsed.conversationId);\n localStorage.setItem(STORAGE_KEY, parsed.conversationId);\n }\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? {\n ...m,\n content: parsed.content || accumulated,\n toolNames: parsed.toolNames,\n toolCallCount: parsed.toolCallCount,\n iterations: parsed.iterations,\n }\n : m,\n ),\n );\n break;\n\n case 'error':\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId ? { ...m, content: parsed.content || t('Unable to connect. Please check the configuration.') } : m,\n ),\n );\n return;\n\n case 'set_chat_id':\n setLegacyChatId(parsed.chatId);\n localStorage.setItem(LEGACY_CHAT_ID_KEY, parsed.chatId);\n break;\n\n case 'noop':\n break;\n }\n\n // Keep ref in sync with context\n hasUsedToolsRef.current = ctx.hasUsedTools;\n } catch {\n /* skip malformed SSE */\n }\n }\n }\n if (accumulated && !doneReceived) {\n setMessages((prev) => prev.map((m) => (m.id === assistantId ? { ...m, content: accumulated || 'No response.' } : m)));\n }\n } catch (err) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n setMessages((prev) =>\n prev.map((m) => (m.id === assistantId ? { ...m, content: t('Sorry, an error occurred. Please try again.') } : m)),\n );\n } finally {\n abortControllerRef.current = null;\n setIsLoading(false);\n setAgentStatus(null);\n hasUsedToolsRef.current = false;\n }\n };\n\n const handleNewChat = () => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = null;\n setMessages([]);\n setInputValue('');\n setAttachedFiles([]);\n setIsLoading(false);\n setAgentStatus(null);\n hasUsedToolsRef.current = false;\n historyLoadedRef.current = false;\n if (isLegacy) {\n setLegacyChatId(null);\n localStorage.removeItem(LEGACY_CHAT_ID_KEY);\n } else {\n setConversationId(null);\n localStorage.removeItem(STORAGE_KEY);\n }\n };\n\n const handleStopGenerating = () => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = null;\n setIsLoading(false);\n setAgentStatus(null);\n hasUsedToolsRef.current = false;\n setMessages((prev) => prev.filter((m) => !(m.role === 'assistant' && !m.content)));\n };\n\n return {\n messages,\n inputValue,\n setInputValue,\n isLoading,\n agentStatus,\n attachedFiles,\n conversationId,\n historyLoadedRef,\n handleFileAdd,\n handlePaste,\n handleSendMessage,\n handleNewChat,\n handleStopGenerating,\n setAttachedFiles,\n setMessages,\n setConversationId,\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { ApiEndpoints, BackendType, XtmAgent } from '../types';\n\nconst STORAGE_AGENT_KEY = 'filigranChatAgentSlug';\n\ninterface UseAgentsOptions {\n apiBaseUrl: string;\n apiEndpoints?: ApiEndpoints;\n backendType?: BackendType;\n}\n\ninterface UseAgentsReturn {\n agents: XtmAgent[];\n selectedAgent: XtmAgent | null;\n setSelectedAgent: React.Dispatch<React.SetStateAction<XtmAgent | null>>;\n agentMenuOpen: boolean;\n setAgentMenuOpen: React.Dispatch<React.SetStateAction<boolean>>;\n handleSwitchAgent: (agent: XtmAgent, onSwitch?: () => void) => void;\n}\n\nexport function useAgents({ apiBaseUrl, apiEndpoints, backendType = 'rest' }: UseAgentsOptions): UseAgentsReturn {\n const [agents, setAgents] = useState<XtmAgent[]>([]);\n const [selectedAgent, setSelectedAgent] = useState<XtmAgent | null>(null);\n const [agentMenuOpen, setAgentMenuOpen] = useState(false);\n\n useEffect(() => {\n // Skip agents fetch if disabled, using single endpoint mode, or legacy backend\n if (apiEndpoints?.agents === null || apiEndpoints?.singleEndpoint || backendType === 'legacy') {\n return;\n }\n const agentsUrl = `${apiBaseUrl}${apiEndpoints?.agents ?? '/chat/agents'}`;\n fetch(agentsUrl)\n .then((res) => (res.ok ? res.json() : []))\n .then((data: XtmAgent[]) => {\n setAgents(data);\n if (data.length > 0 && !selectedAgent) {\n const savedSlug = localStorage.getItem(STORAGE_AGENT_KEY);\n const match = savedSlug ? data.find((a) => a.slug === savedSlug) : null;\n setSelectedAgent(match || data[0]);\n }\n })\n .catch(() => {});\n }, [apiBaseUrl, apiEndpoints]);\n\n const handleSwitchAgent = (agent: XtmAgent, onSwitch?: () => void) => {\n if (agent.id === selectedAgent?.id) {\n setAgentMenuOpen(false);\n return;\n }\n setSelectedAgent(agent);\n if (agent.slug) localStorage.setItem(STORAGE_AGENT_KEY, agent.slug);\n setAgentMenuOpen(false);\n onSwitch?.();\n };\n\n return {\n agents,\n selectedAgent,\n setSelectedAgent,\n agentMenuOpen,\n setAgentMenuOpen,\n handleSwitchAgent,\n };\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { ChatMode } from '../types';\n\nconst SIDEBAR_WIDTH = 400;\nconst SIDEBAR_WIDTH_STORAGE_KEY = 'filigranChatSidebarWidth';\nconst MAX_SIDEBAR_RATIO = 0.4;\n\ninterface UseSidebarResizeOptions {\n mode: ChatMode;\n resizable: boolean;\n onWidthChange?: (width: number) => void;\n onResizeStart?: () => void;\n onResizeEnd?: () => void;\n}\n\ninterface UseSidebarResizeReturn {\n sidebarWidth: number;\n handleResizeStart: (e: React.MouseEvent) => void;\n defaultWidth: number;\n isResizing: boolean;\n}\n\nexport function useSidebarResize({\n mode,\n resizable,\n onWidthChange,\n onResizeStart,\n onResizeEnd,\n}: UseSidebarResizeOptions): UseSidebarResizeReturn {\n const [sidebarWidth, setSidebarWidth] = useState<number>(() => {\n if (typeof window === 'undefined') return SIDEBAR_WIDTH;\n const stored = localStorage.getItem(SIDEBAR_WIDTH_STORAGE_KEY);\n if (stored) {\n const parsed = parseInt(stored, 10);\n if (!Number.isNaN(parsed) && parsed >= SIDEBAR_WIDTH) return parsed;\n }\n return SIDEBAR_WIDTH;\n });\n const [isResizing, setIsResizing] = useState(false);\n\n const isResizingRef = useRef(false);\n const sidebarWidthRef = useRef(sidebarWidth);\n sidebarWidthRef.current = sidebarWidth;\n const onWidthChangeRef = useRef(onWidthChange);\n onWidthChangeRef.current = onWidthChange;\n const onResizeEndRef = useRef(onResizeEnd);\n onResizeEndRef.current = onResizeEnd;\n\n // Notify parent of sidebar width when entering sidebar mode\n useEffect(() => {\n if (mode === 'sidebar' && resizable) {\n onWidthChangeRef.current?.(sidebarWidthRef.current);\n }\n }, [mode, resizable]);\n\n // Resize event handlers\n useEffect(() => {\n if (mode !== 'sidebar' || !resizable) return undefined;\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!isResizingRef.current) return;\n e.preventDefault();\n const newWidth = window.innerWidth - e.clientX;\n const maxWidth = window.innerWidth * MAX_SIDEBAR_RATIO;\n const clamped = Math.min(Math.max(newWidth, SIDEBAR_WIDTH), maxWidth);\n setSidebarWidth(clamped);\n sidebarWidthRef.current = clamped;\n onWidthChangeRef.current?.(clamped);\n };\n\n const handleMouseUp = () => {\n if (!isResizingRef.current) return;\n isResizingRef.current = false;\n setIsResizing(false);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(sidebarWidthRef.current));\n onResizeEndRef.current?.();\n };\n\n const handleWindowResize = () => {\n const maxWidth = window.innerWidth * MAX_SIDEBAR_RATIO;\n if (sidebarWidthRef.current > maxWidth) {\n const clamped = Math.max(maxWidth, SIDEBAR_WIDTH);\n setSidebarWidth(clamped);\n sidebarWidthRef.current = clamped;\n onWidthChangeRef.current?.(clamped);\n }\n };\n\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n window.addEventListener('resize', handleWindowResize);\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n window.removeEventListener('resize', handleWindowResize);\n };\n }, [mode, resizable]);\n\n const handleResizeStart = (e: React.MouseEvent) => {\n e.preventDefault();\n isResizingRef.current = true;\n setIsResizing(true);\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n onResizeStart?.();\n };\n\n return {\n sidebarWidth,\n handleResizeStart,\n defaultWidth: SIDEBAR_WIDTH,\n isResizing,\n };\n}\n","import type { IconProps } from '../../types';\n\nexport const AttachFileIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const BrainIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z\" />\n <path d=\"M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z\" />\n <path d=\"M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4\" />\n <path d=\"M17.599 6.5a3 3 0 0 0 .399-1.375\" />\n <path d=\"M6.003 5.125A3 3 0 0 0 6.401 6.5\" />\n <path d=\"M3.477 10.896a4 4 0 0 1 .585-.396\" />\n <path d=\"M19.938 10.5a4 4 0 0 1 .585.396\" />\n <path d=\"M6 18a4 4 0 0 1-1.967-.516\" />\n <path d=\"M19.967 17.484A4 4 0 0 1 18 18\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const CheckIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const ChevronDownIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const CloseIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const CopyIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const DatabaseIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5V19A9 3 0 0 0 21 19V5\" />\n <path d=\"M3 12A9 3 0 0 0 21 12\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const DefaultLogoIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\" className={className}>\n <path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const EditIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M12 20h9\" />\n <path d=\"M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const ExternalLinkIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const FileIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\" />\n <path d=\"M14 2v4a2 2 0 0 0 2 2h4\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const FloatingIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M11 13H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7\" />\n <rect width=\"12\" height=\"12\" x=\"10\" y=\"10\" rx=\"2\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const FullscreenExitIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3\" />\n <path d=\"M21 8h-3a2 2 0 0 1-2-2V3\" />\n <path d=\"M3 16h3a2 2 0 0 0 2 2v3\" />\n <path d=\"M16 21v-3a2 2 0 0 1 2-2h3\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const FullscreenIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3\" />\n <path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" />\n <path d=\"M3 16v3a2 2 0 0 0 2 2h3\" />\n <path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const GlobeIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n <path d=\"M2 12h20\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const InfoIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4\" />\n <path d=\"M12 8h.01\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const MailIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const SearchIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const SendIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"m22 2-7 20-4-9-9-4Z\" />\n <path d=\"m22 2-11 11\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const SidebarIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M15 3v18\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const SparklesIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const StopCircleIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <rect width=\"6\" height=\"6\" x=\"9\" y=\"9\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const TerminalIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <polyline points=\"4 17 10 11 4 5\" />\n <line x1=\"12\" x2=\"20\" y1=\"19\" y2=\"19\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const UserPlusIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <line x1=\"19\" x2=\"19\" y1=\"8\" y2=\"14\" />\n <line x1=\"22\" x2=\"16\" y1=\"11\" y2=\"11\" />\n </svg>\n);\n","import type { IconProps } from '../../types';\n\nexport const WrenchIcon = ({ className, size = 24 }: IconProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z\" />\n </svg>\n);\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useClickOutside } from '../hooks/useClickOutside';\n\ninterface DropdownProps {\n open: boolean;\n onClose: () => void;\n anchorRef: React.RefObject<HTMLElement | null>;\n placement?: 'bottom-start' | 'bottom-end';\n width?: number;\n children: React.ReactNode;\n}\n\nfunction findChatbotRoot(el: HTMLElement | null): HTMLElement {\n let node = el;\n while (node) {\n if (node.classList.contains('filigran-chatbot')) return node;\n node = node.parentElement;\n }\n return document.body;\n}\n\nexport const Dropdown = ({ open, onClose, anchorRef, placement = 'bottom-start', width = 280, children }: DropdownProps) => {\n const panelRef = useRef<HTMLDivElement>(null);\n const [pos, setPos] = useState({ top: 0, left: 0 });\n\n const stableOnClose = useCallback(() => onClose(), [onClose]);\n useClickOutside(panelRef, stableOnClose, open);\n\n useEffect(() => {\n if (!open || !anchorRef.current) return;\n const rect = anchorRef.current.getBoundingClientRect();\n const left = placement === 'bottom-end' ? rect.right - width : rect.left;\n setPos({ top: rect.bottom + 4, left });\n }, [open, anchorRef, placement, width]);\n\n if (!open) return null;\n\n const portalTarget = findChatbotRoot(anchorRef.current);\n\n return createPortal(\n <div\n ref={panelRef}\n className=\"fixed z-[10000] rounded-[10px] overflow-hidden border border-gray-200 dark:border-white/10 bg-white dark:bg-[#2a2a3e] shadow-xl\"\n style={{ top: pos.top, left: pos.left, width }}\n >\n {children}\n </div>,\n portalTarget,\n );\n};\n","import { useEffect, type RefObject } from 'react';\n\nexport function useClickOutside(ref: RefObject<HTMLElement | null>, handler: () => void, active = true) {\n useEffect(() => {\n if (!active) return undefined;\n const listener = (e: MouseEvent | TouchEvent) => {\n if (!ref.current || ref.current.contains(e.target as Node)) return;\n handler();\n };\n document.addEventListener('mousedown', listener);\n document.addEventListener('touchstart', listener);\n return () => {\n document.removeEventListener('mousedown', listener);\n document.removeEventListener('touchstart', listener);\n };\n }, [ref, handler, active]);\n}\n","interface SpinnerProps {\n size?: number;\n className?: string;\n}\n\nexport const Spinner = ({ size = 16, className = '' }: SpinnerProps) => (\n <div\n className={`animate-spin rounded-full border-2 border-current/20 border-t-[var(--chat-accent)] ${className}`}\n style={{ width: size, height: size }}\n />\n);\n","import { useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\ninterface TooltipProps {\n title: string;\n children: React.ReactElement;\n}\n\nfunction findChatbotRoot(el: HTMLElement | null): HTMLElement {\n let node = el;\n while (node) {\n if (node.classList.contains('filigran-chatbot')) return node;\n node = node.parentElement;\n }\n return document.body;\n}\n\nexport const Tooltip = ({ title, children }: TooltipProps) => {\n const ref = useRef<HTMLSpanElement>(null);\n const [show, setShow] = useState(false);\n const [pos, setPos] = useState({ top: 0, left: 0 });\n\n if (!title) return children;\n\n const handleEnter = () => {\n if (!ref.current) return;\n const rect = ref.current.getBoundingClientRect();\n setPos({\n top: rect.top - 4,\n left: rect.left + rect.width / 2,\n });\n setShow(true);\n };\n\n return (\n <span\n ref={ref}\n className=\"inline-flex\"\n onMouseEnter={handleEnter}\n onMouseLeave={() => setShow(false)}\n >\n {children}\n {show &&\n createPortal(\n <span\n className=\"pointer-events-none fixed z-[10001] -translate-x-1/2 -translate-y-full whitespace-nowrap rounded-md bg-gray-900 dark:bg-gray-100 px-2 py-1 text-xs text-white dark:text-gray-900 shadow-lg\"\n style={{ top: pos.top, left: pos.left }}\n role=\"tooltip\"\n >\n {title}\n </span>,\n findChatbotRoot(ref.current),\n )}\n </span>\n );\n};\n","import { useRef } from 'react';\nimport type { ChatMode, XtmAgent } from '../types';\nimport {\n ChevronDownIcon,\n CloseIcon,\n EditIcon,\n ExternalLinkIcon,\n FloatingIcon,\n FullscreenExitIcon,\n FullscreenIcon,\n SidebarIcon,\n UserPlusIcon,\n} from './icons';\nimport { Dropdown } from './Dropdown';\nimport { Spinner } from './Spinner';\nimport { Tooltip } from './Tooltip';\n\ninterface ChatHeaderProps {\n mode: ChatMode;\n agentName: string;\n agents: XtmAgent[];\n selectedAgent: XtmAgent | null;\n agentMenuOpen: boolean;\n onAgentMenuToggle: () => void;\n onAgentMenuClose: () => void;\n onSwitchAgent: (agent: XtmAgent) => void;\n modeMenuOpen: boolean;\n onModeMenuToggle: () => void;\n onModeMenuClose: () => void;\n onModeChange: (mode: ChatMode) => void;\n onNewChat: () => void;\n onClose: () => void;\n logoIcon: React.ReactNode;\n agentDashboardUrl?: string;\n t: (key: string) => string;\n}\n\nconst modeOptions: { mode: ChatMode; label: string; getIcon: (p: { size: number; className: string }) => React.ReactNode }[] = [\n { mode: 'floating', label: 'Floating', getIcon: (p) => <FloatingIcon {...p} /> },\n { mode: 'sidebar', label: 'Sidebar', getIcon: (p) => <SidebarIcon {...p} /> },\n { mode: 'fullscreen', label: 'Full screen', getIcon: (p) => <FullscreenIcon {...p} /> },\n];\n\nexport const ChatHeader = ({\n mode,\n agentName,\n agents,\n selectedAgent,\n agentMenuOpen,\n onAgentMenuToggle,\n onAgentMenuClose,\n onSwitchAgent,\n modeMenuOpen,\n onModeMenuToggle,\n onModeMenuClose,\n onModeChange,\n onNewChat,\n onClose,\n logoIcon,\n agentDashboardUrl,\n t,\n}: ChatHeaderProps) => {\n const agentAnchorRef = useRef<HTMLButtonElement>(null);\n const modeAnchorRef = useRef<HTMLButtonElement>(null);\n\n const CurrentModeIcon = mode === 'sidebar' ? SidebarIcon : mode === 'fullscreen' ? FullscreenExitIcon : FloatingIcon;\n\n return (\n <div className={`flex items-center px-3 py-2 min-h-[48px] border-b border-gray-200 dark:border-white/10 bg-gradient-to-br from-[var(--chat-accent-dark)]/[0.13] to-[var(--chat-accent)]/[0.07] ${mode === 'floating' ? 'rounded-t-xl' : ''}`}>\n <button\n ref={agentAnchorRef}\n type=\"button\"\n onClick={onAgentMenuToggle}\n className=\"flex items-center gap-1.5 text-sm font-semibold text-gray-900 dark:text-white px-2 py-1 rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 transition-colors\"\n >\n <span className=\"flex items-center text-[var(--chat-accent)] [&>svg]:w-[18px] [&>svg]:h-[18px]\">{logoIcon}</span>\n {agentName}\n <ChevronDownIcon size={16} className=\"text-gray-400 dark:text-white/30\" />\n </button>\n\n <Dropdown open={agentMenuOpen} onClose={onAgentMenuClose} anchorRef={agentAnchorRef} width={280}>\n <span className=\"block px-4 pt-3 pb-1 text-[0.68rem] tracking-[1px] uppercase text-gray-400 dark:text-white/40\">\n {t('Switch to another agent')}\n </span>\n {agents.length === 0 && (\n <div className=\"px-4 py-2\">\n <Spinner size={16} />\n </div>\n )}\n <div>\n {agents.map((agent) => (\n <button\n key={agent.id}\n type=\"button\"\n onClick={() => onSwitchAgent(agent)}\n className={`w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors ${\n agent.id === selectedAgent?.id ? 'bg-[var(--chat-accent)]/10' : ''\n }`}\n >\n <div className=\"w-7 h-7 rounded-full flex items-center justify-center shrink-0 bg-gradient-to-br from-[var(--chat-accent)]/20 to-[var(--chat-accent)]/5\">\n <span className=\"text-[var(--chat-accent)] [&>svg]:w-4 [&>svg]:h-4\">{logoIcon}</span>\n </div>\n <div className=\"min-w-0\">\n <div className=\"text-[0.8125rem] font-medium text-gray-900 dark:text-white truncate\">{agent.name}</div>\n {agent.description && <div className=\"text-[0.7rem] text-gray-500 dark:text-white/40 truncate\">{agent.description}</div>}\n </div>\n </button>\n ))}\n </div>\n <div className=\"h-px bg-gray-200 dark:bg-white/10 mx-2\" />\n <div>\n {agentDashboardUrl && (\n <button\n type=\"button\"\n onClick={() => {\n onAgentMenuClose();\n window.open(`${agentDashboardUrl}/agents`, '_blank');\n }}\n className=\"w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors\"\n >\n <ExternalLinkIcon size={18} className=\"text-gray-400 dark:text-white/40 shrink-0\" />\n <span className=\"text-[0.8125rem] text-gray-700 dark:text-white/70\">{t('Browse agents')}</span>\n </button>\n )}\n {agentDashboardUrl && (\n <button\n type=\"button\"\n onClick={() => {\n onAgentMenuClose();\n window.open(`${agentDashboardUrl}/agents/new`, '_blank');\n }}\n className=\"w-full flex items-center gap-2 px-4 py-1.5 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors\"\n >\n <UserPlusIcon size={18} className=\"text-gray-400 dark:text-white/40 shrink-0\" />\n <span className=\"text-[0.8125rem] text-gray-700 dark:text-white/70\">{t('Create agent')}</span>\n </button>\n )}\n </div>\n </Dropdown>\n\n <div className=\"flex-1\" />\n\n <Tooltip title={t('New chat')}>\n <button\n type=\"button\"\n onClick={onNewChat}\n className=\"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors\"\n >\n <EditIcon size={18} />\n </button>\n </Tooltip>\n\n <Tooltip title={t('Switch view')}>\n <button\n ref={modeAnchorRef}\n type=\"button\"\n onClick={onModeMenuToggle}\n className=\"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors\"\n >\n <CurrentModeIcon size={18} />\n </button>\n </Tooltip>\n\n <Dropdown open={modeMenuOpen} onClose={onModeMenuClose} anchorRef={modeAnchorRef} placement=\"bottom-end\" width={180}>\n <span className=\"block px-4 pt-3 pb-1 text-[0.68rem] tracking-[1px] uppercase text-gray-400 dark:text-white/40\">{t('Switch to')}</span>\n <div className=\"pb-1\">\n {modeOptions.map((opt) => (\n <button\n key={opt.mode}\n type=\"button\"\n onClick={() => {\n onModeChange(opt.mode);\n onModeMenuClose();\n }}\n className={`w-full flex items-center gap-3 px-4 py-1 text-left hover:bg-gray-100 dark:hover:bg-white/10 transition-colors ${\n mode === opt.mode ? 'bg-[var(--chat-accent)]/10' : ''\n }`}\n >\n {opt.getIcon({ size: 18, className: 'text-gray-400 dark:text-white/40' })}\n <span className=\"text-[0.8125rem] text-gray-700 dark:text-white/70\">{t(opt.label)}</span>\n </button>\n ))}\n </div>\n </Dropdown>\n\n <Tooltip title={t('Close')}>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-white/10 text-gray-500 dark:text-white/40 hover:text-gray-700 dark:hover:text-white/70 transition-colors\"\n >\n <CloseIcon size={18} />\n </button>\n </Tooltip>\n </div>\n );\n};\n","import { useRef, type KeyboardEvent } from 'react';\nimport type { ChatFile, ChatMode } from '../types';\nimport { AttachFileIcon, FileIcon, SendIcon, StopCircleIcon } from './icons';\nimport { Tooltip } from './Tooltip';\n\ninterface ChatInputProps {\n inputValue: string;\n onInputChange: (value: string) => void;\n onSend: () => void;\n onStop: () => void;\n isLoading: boolean;\n attachedFiles: ChatFile[];\n onFileAdd: (files: FileList | null) => void;\n onFileRemove: (index: number) => void;\n onPaste: (e: React.ClipboardEvent) => void;\n t: (key: string) => string;\n mode?: ChatMode;\n}\n\nexport const ChatInput = ({ inputValue, onInputChange, onSend, onStop, isLoading, attachedFiles, onFileAdd, onFileRemove, onPaste, t, mode }: ChatInputProps) => {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n onSend();\n }\n };\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n onInputChange(e.target.value);\n const el = e.target;\n el.style.height = 'auto';\n el.style.height = `${Math.min(el.scrollHeight, 120)}px`;\n };\n\n const hasContent = inputValue.trim() || attachedFiles.length > 0;\n\n return (\n <div className={`px-4 py-3 border-t border-gray-200 dark:border-white/10 ${mode === 'floating' ? 'rounded-b-xl' : ''}`}>\n {attachedFiles.length > 0 && (\n <div className=\"flex gap-1.5 flex-wrap mb-2\">\n {attachedFiles.map((f, i) => (\n <span\n key={i}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.7rem] text-gray-600 dark:text-white/60\"\n >\n <FileIcon size={14} />\n {f.name}\n <button\n type=\"button\"\n onClick={() => onFileRemove(i)}\n className=\"ml-0.5 text-gray-400 dark:text-white/30 hover:text-gray-600 dark:hover:text-white/60\"\n >\n ×\n </button>\n </span>\n ))}\n </div>\n )}\n\n <div className=\"flex items-center border border-gray-200 dark:border-white/10 rounded-xl px-2 py-1 transition-colors focus-within:border-[var(--chat-accent)]\">\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n hidden\n onChange={(e) => {\n onFileAdd(e.target.files);\n e.target.value = '';\n }}\n />\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n className=\"w-8 h-8 flex items-center justify-center shrink-0 rounded-lg text-gray-400 dark:text-white/30 hover:bg-gray-100 dark:hover:bg-white/10 mr-0.5 transition-colors\"\n >\n <AttachFileIcon size={18} />\n </button>\n <textarea\n ref={textareaRef}\n placeholder={t('Ask a question...')}\n value={inputValue}\n onChange={handleInput}\n onKeyDown={handleKeyDown}\n onPaste={onPaste}\n rows={1}\n className=\"flex-1 bg-transparent border-none outline-none resize-none text-[0.8125rem] py-1.5 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-white/30 filigran-chat-scrollable\"\n style={{ maxHeight: 120 }}\n />\n <Tooltip title={isLoading ? t('Stop generating') : ''}>\n <button\n type=\"button\"\n onClick={isLoading ? onStop : onSend}\n disabled={!isLoading && !hasContent}\n className={`p-1.5 rounded-lg w-8 h-8 flex items-center justify-center transition-all duration-150 ${\n isLoading\n ? 'text-red-500 bg-red-500/10 hover:bg-red-500/20'\n : hasContent\n ? 'text-[var(--chat-accent)] bg-[var(--chat-accent)]/10 hover:bg-[var(--chat-accent)]/20'\n : 'text-gray-300 dark:text-white/20 cursor-not-allowed'\n }`}\n >\n {isLoading ? <StopCircleIcon size={18} /> : <SendIcon size={18} />}\n </button>\n </Tooltip>\n </div>\n\n <p className=\"text-center text-[0.65rem] text-gray-400 dark:text-white/30 mt-1.5 opacity-70\">{t('Uses AI. Verify results.')}</p>\n </div>\n );\n};\n","import { useEffect, useRef } from 'react';\nimport type { AgentStatusState, IconProps } from '../types';\nimport { BrainIcon, DatabaseIcon, ExternalLinkIcon, GlobeIcon, MailIcon, SearchIcon, SparklesIcon, TerminalIcon, UserPlusIcon, WrenchIcon } from './icons';\n\ninterface ChatThinkingProps {\n agentStatus: AgentStatusState | null;\n logoIcon?: React.ReactNode;\n t: (key: string) => string;\n}\n\ntype IconComponent = (props: IconProps) => React.JSX.Element;\n\ninterface StatusVisual {\n label: string;\n StatusIcon: IconComponent;\n showDots: boolean;\n}\n\nfunction resolveStatusVisual(agentStatus: AgentStatusState | null, t: (key: string) => string): StatusVisual {\n if (!agentStatus) {\n return { label: t('Thinking...'), StatusIcon: BrainIcon, showDots: false };\n }\n switch (agentStatus.status) {\n case 'tool_start': {\n const rawNames = agentStatus.tools ?? [];\n const lower = rawNames.map((n) => n.toLowerCase());\n\n // Delegation tools have dedicated statuses\n if (lower.some((n) => n === 'spawn_background_task')) {\n const count = rawNames.filter((n) => n === 'spawn_background_task').length;\n const label = count > 1\n ? `${t('Delegating')} ${count} ${t('tasks')}…`\n : `${t('Delegating task')}…`;\n return { label, StatusIcon: UserPlusIcon, showDots: false };\n }\n if (lower.some((n) => n === 'check_task_status')) {\n const count = rawNames.filter((n) => n === 'check_task_status').length;\n const target = count > 1 ? `${count} ${t('background tasks')}` : t('background task');\n return { label: `${t('Waiting for')} ${target}…`, StatusIcon: SparklesIcon, showDots: false };\n }\n if (lower.some((n) => n === 'get_task_result')) {\n const count = rawNames.filter((n) => n === 'get_task_result').length;\n const from = count > 1 ? `${count} ${t('tasks')}` : t('task');\n return { label: `${t('Collecting results from')} ${from}…`, StatusIcon: SparklesIcon, showDots: false };\n }\n\n let StatusIcon: IconComponent = WrenchIcon;\n if (lower.some((n) => n.includes('search') || n.includes('list'))) {\n StatusIcon = SearchIcon;\n } else if (lower.some((n) => n.includes('read') || n.includes('get') || n.includes('query'))) {\n StatusIcon = DatabaseIcon;\n } else if (lower.some((n) => n.includes('send') || n.includes('create') || n.includes('draft') || n.includes('reply') || n.includes('flag'))) {\n StatusIcon = MailIcon;\n } else if (lower.some((n) => n.includes('code') || n.includes('execute'))) {\n StatusIcon = TerminalIcon;\n } else if (lower.some((n) => n.includes('web') || n.includes('browse'))) {\n StatusIcon = GlobeIcon;\n }\n let label: string;\n if (rawNames.length > 0) {\n const display = rawNames.map((n) => n.replace(/_/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase()));\n const unique = Array.from(new Set(display));\n label = unique.length === 1 ? `${unique[0]}…` : `${unique[0]} (+${unique.length - 1} more)…`;\n } else {\n label = t('Using tools…');\n }\n return { label, StatusIcon, showDots: false };\n }\n case 'analyzing':\n return { label: t('Analyzing results…'), StatusIcon: SparklesIcon, showDots: false };\n case 'composing':\n return { label: t('Composing answer…'), StatusIcon: BrainIcon, showDots: true };\n case 'consulting': {\n const consultName = agentStatus.tools?.[0] ?? 'agent';\n return { label: `${t('Consulting')} ${consultName}…`, StatusIcon: UserPlusIcon, showDots: false };\n }\n case 'delegating': {\n const count = agentStatus.tools?.filter((n) => n === 'spawn_background_task').length ?? 0;\n return { label: count > 1 ? `${t('Delegating')} ${count} ${t('tasks')}…` : `${t('Delegating task')}…`, StatusIcon: UserPlusIcon, showDots: false };\n }\n case 'polling': {\n const checkCount = agentStatus.tools?.filter((n) => n === 'check_task_status').length ?? 0;\n const target = checkCount > 1 ? `${checkCount} ${t('background tasks')}` : t('background task');\n return { label: `${t('Waiting for')} ${target}…`, StatusIcon: SparklesIcon, showDots: false };\n }\n case 'collecting': {\n const fetchCount = agentStatus.tools?.filter((n) => n === 'get_task_result').length ?? 0;\n const from = fetchCount > 1 ? `${fetchCount} ${t('tasks')}` : t('task');\n return { label: `${t('Collecting results from')} ${from}…`, StatusIcon: SparklesIcon, showDots: false };\n }\n case 'transferring': {\n const targetName = agentStatus.tools?.[0] ?? 'agent';\n return { label: `${t('Transferring to')} ${targetName}…`, StatusIcon: ExternalLinkIcon, showDots: false };\n }\n case 'thinking':\n default:\n return { label: t('Thinking...'), StatusIcon: BrainIcon, showDots: false };\n }\n}\n\nfunction stripMarkdown(text: string): string {\n return text\n .replace(/```[\\s\\S]*?```/g, ' ')\n .replace(/`([^`]+)`/g, '$1')\n .replace(/\\*\\*(.+?)\\*\\*/g, '$1')\n .replace(/__(.+?)__/g, '$1')\n .replace(/\\*(.+?)\\*/g, '$1')\n .replace(/_(.+?)_/g, '$1')\n .replace(/#{1,6}\\s+/g, '')\n .replace(/[*\\->]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction ThinkingTextBubble({ content }: { content: string }) {\n const ref = useRef<HTMLDivElement>(null);\n const cleaned = stripMarkdown(content);\n\n useEffect(() => {\n if (ref.current) ref.current.scrollTop = ref.current.scrollHeight;\n }, [cleaned]);\n\n if (cleaned.length < 3) return null;\n\n return (\n <div\n ref={ref}\n className=\"ml-11 max-w-[70%] max-h-20 overflow-hidden relative rounded-md border-l-2 bg-[var(--chat-accent)]/[0.03] pl-3 pr-3 py-2\"\n style={{ animation: 'reasoningGlow 3s ease-in-out infinite, chat-fade-in 0.5s ease-out' }}\n >\n <p className=\"text-[13px] leading-[1.35rem] text-gray-400 dark:text-white/40 break-words m-0\">\n {cleaned}\n </p>\n <div className=\"absolute inset-x-0 bottom-0 h-5 bg-gradient-to-t from-white/90 dark:from-[#1e1e2e]/90 to-transparent pointer-events-none\" />\n </div>\n );\n}\n\nexport const ChatThinking = ({ agentStatus, logoIcon, t }: ChatThinkingProps) => {\n const { label, StatusIcon, showDots } = resolveStatusVisual(agentStatus, t);\n const thinkingContent = agentStatus?.thinkingContent;\n\n return (\n <>\n <div className=\"flex gap-3 items-center justify-start\">\n <div className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-[var(--chat-accent)]/15 to-[var(--chat-accent)]/5\">\n <span className=\"text-[var(--chat-accent)] [&>svg]:w-4 [&>svg]:h-4\">{logoIcon}</span>\n </div>\n <div className=\"rounded-lg bg-gray-50 dark:bg-white/[0.03] px-4 py-3 relative overflow-hidden\">\n <div className=\"absolute inset-0 bg-gradient-to-r from-[var(--chat-accent)]/[0.03] via-transparent to-[var(--chat-accent)]/[0.03] animate-pulse pointer-events-none\" />\n <div className=\"relative flex items-center gap-2.5\">\n {showDots ? (\n <div className=\"flex gap-[3px] items-center h-3.5 w-3.5 justify-center\">\n {[0, 0.15, 0.3].map((delay, i) => (\n <span\n key={i}\n className=\"h-[5px] w-[5px] rounded-full bg-[var(--chat-accent)]/50\"\n style={{ animation: `chat-dot 1s ease-in-out infinite ${delay}s` }}\n />\n ))}\n </div>\n ) : (\n <StatusIcon size={14} className=\"text-[var(--chat-accent)] animate-pulse transition-all duration-300\" />\n )}\n <span className=\"text-sm text-gray-500 dark:text-white/50 transition-all duration-300\">{label}</span>\n </div>\n </div>\n </div>\n {thinkingContent && <ThinkingTextBubble content={thinkingContent} />}\n </>\n );\n};\n","import { useState } from 'react';\nimport Markdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { CheckIcon, CopyIcon } from './icons';\n\ninterface MarkdownMessageProps {\n content: string;\n}\n\nexport const MarkdownMessage = ({ content }: MarkdownMessageProps) => {\n const [copiedBlock, setCopiedBlock] = useState<string | null>(null);\n\n const handleCopyCode = (code: string) => {\n navigator.clipboard.writeText(code);\n setCopiedBlock(code);\n setTimeout(() => setCopiedBlock(null), 2000);\n };\n\n return (\n <Markdown\n remarkPlugins={[remarkGfm]}\n components={{\n p: ({ children }) => (\n <p className=\"mb-3 last:mb-0 leading-7 break-words text-[0.8125rem] text-gray-900 dark:text-white/90\">{children}</p>\n ),\n code: ({ className, children }) => {\n const match = /language-(\\w+)/.exec(className || '');\n const codeStr = String(children).replace(/\\n$/, '');\n if (match) {\n return (\n <div className=\"my-3 rounded-lg border border-gray-200 dark:border-white/10 overflow-hidden bg-gray-50 dark:bg-white/[0.03]\">\n <div className=\"flex items-center justify-between px-3 py-1.5 border-b border-gray-200 dark:border-white/10 bg-gray-100 dark:bg-white/[0.03]\">\n <span className=\"text-[0.7rem] text-gray-500 dark:text-white/40 font-mono\">{match[1]}</span>\n <button\n type=\"button\"\n onClick={() => handleCopyCode(codeStr)}\n className=\"p-0.5 rounded hover:bg-gray-200 dark:hover:bg-white/10 transition-colors\"\n >\n {copiedBlock === codeStr ? (\n <CheckIcon size={14} className=\"text-green-500\" />\n ) : (\n <CopyIcon size={14} className=\"text-gray-400 dark:text-white/40\" />\n )}\n </button>\n </div>\n <pre className=\"m-0 px-3 py-2 overflow-x-auto\">\n <code className=\"font-mono text-xs leading-[1.7] text-gray-800 dark:text-white/90 whitespace-pre\">{codeStr}</code>\n </pre>\n </div>\n );\n }\n return (\n <code className=\"bg-gray-100 dark:bg-white/[0.08] px-1.5 py-0.5 rounded font-mono text-xs text-[var(--chat-accent)]\">{children}</code>\n );\n },\n ul: ({ children }) => (\n <ul className=\"pl-5 mb-3 text-[0.8125rem] text-gray-900 dark:text-white/90 [&_li]:mb-1 marker:text-[var(--chat-accent)]/50\">\n {children}\n </ul>\n ),\n ol: ({ children }) => (\n <ol className=\"pl-5 mb-3 text-[0.8125rem] text-gray-900 dark:text-white/90 [&_li]:mb-1 marker:text-[var(--chat-accent)]/50\">\n {children}\n </ol>\n ),\n blockquote: ({ children }) => (\n <blockquote className=\"my-3 border-l-2 border-[var(--chat-accent)]/30 bg-[var(--chat-accent)]/[0.03] pl-4 pr-3 py-2 rounded-r-md italic text-gray-500 dark:text-white/60\">\n {children}\n </blockquote>\n ),\n a: ({ href, children }) => (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-[var(--chat-accent)] underline underline-offset-2 hover:brightness-125\"\n >\n {children}\n </a>\n ),\n h1: ({ children }) => <h1 className=\"mt-4 first:mt-0 mb-2 font-bold text-base text-gray-900 dark:text-white\">{children}</h1>,\n h2: ({ children }) => <h2 className=\"mt-3 first:mt-0 mb-2 font-bold text-[0.9rem] text-gray-900 dark:text-white\">{children}</h2>,\n h3: ({ children }) => <h3 className=\"mt-3 first:mt-0 mb-1.5 font-semibold text-[0.85rem] text-gray-900 dark:text-white\">{children}</h3>,\n table: ({ children }) => (\n <div className=\"my-3 overflow-x-auto rounded-lg border border-gray-200 dark:border-white/10\">\n <table className=\"w-full border-collapse text-xs\">{children}</table>\n </div>\n ),\n th: ({ children }) => (\n <th className=\"px-3 py-2 text-left font-semibold bg-gray-50 dark:bg-white/[0.04] border-b border-gray-200 dark:border-white/10 text-gray-900 dark:text-white\">\n {children}\n </th>\n ),\n td: ({ children }) => (\n <td className=\"px-3 py-2 border-b border-gray-200 dark:border-white/10 text-gray-700 dark:text-white/80\">{children}</td>\n ),\n }}\n >\n {content}\n </Markdown>\n );\n};\n","import { useEffect, useRef, useState } from 'react';\nimport type { AgentStatusState, ChatMessage } from '../types';\nimport { FileIcon, InfoIcon } from './icons';\nimport { ChatThinking } from './ChatThinking';\nimport { MarkdownMessage } from './MarkdownMessage';\n\ninterface ChatMessagesProps {\n messages: ChatMessage[];\n isLoading: boolean;\n agentStatus: AgentStatusState | null;\n agentName: string;\n logoIcon: React.ReactNode;\n t: (key: string) => string;\n}\n\nexport const ChatMessages = ({ messages, isLoading, agentStatus, agentName, logoIcon, t }: ChatMessagesProps) => {\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const [toolDetailMsgId, setToolDetailMsgId] = useState<string | null>(null);\n\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages]);\n\n return (\n <div className=\"flex-1 overflow-y-auto px-4 py-3 flex flex-col gap-4 filigran-chat-scrollable\">\n {messages.map((msg) => {\n const isAssistant = msg.role === 'assistant';\n const isEmpty = !msg.content;\n const isThinking = isAssistant && isEmpty && isLoading;\n\n if (isThinking) {\n return (\n <div key={msg.id}>\n <ChatThinking agentStatus={agentStatus} logoIcon={logoIcon} t={t} />\n </div>\n );\n }\n\n return (\n <div key={msg.id} className={`flex flex-col ${isAssistant ? 'items-start' : 'items-end'}`}>\n {isAssistant && (\n <div className=\"flex items-center gap-1.5 mb-1\">\n <div className=\"w-6 h-6 rounded-lg flex items-center justify-center bg-gradient-to-br from-[var(--chat-accent)]/20 to-[var(--chat-accent)]/5\">\n <span className=\"text-[var(--chat-accent)] [&>svg]:w-3 [&>svg]:h-3\">{logoIcon}</span>\n </div>\n <span className=\"font-semibold text-xs text-gray-900 dark:text-white\">{agentName}</span>\n </div>\n )}\n\n {msg.files && msg.files.length > 0 && (\n <div className=\"flex gap-1.5 flex-wrap mb-1.5\">\n {msg.files.map((f, i) => (\n <span\n key={i}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.7rem] text-gray-600 dark:text-white/60\"\n >\n <FileIcon size={14} />\n {f.name}\n </span>\n ))}\n </div>\n )}\n\n <div\n className={`max-w-[90%] ${\n isAssistant\n ? 'pl-1 py-1 text-[0.8125rem] leading-7'\n : 'px-3.5 py-2 rounded-[14px_14px_4px_14px] bg-[var(--chat-accent-dark)] text-white text-[0.8125rem] leading-6'\n }`}\n >\n {isAssistant ? <MarkdownMessage content={msg.content} /> : msg.content}\n {isAssistant && isEmpty && !isLoading && <span className=\"text-[0.8125rem] text-gray-400 dark:text-white/40 italic\">...</span>}\n {isAssistant && !isEmpty && isLoading && (\n <span className=\"inline-block w-1.5 h-4 bg-[var(--chat-accent)]/70 rounded-sm ml-0.5 animate-pulse align-text-bottom\" />\n )}\n </div>\n\n {isAssistant && !isEmpty && !isLoading && msg.toolNames && msg.toolNames.length > 0 && (\n <>\n <button\n type=\"button\"\n onClick={() => setToolDetailMsgId(toolDetailMsgId === msg.id ? null : msg.id)}\n className=\"mt-0.5 p-1 rounded-lg opacity-50 hover:opacity-100 hover:text-[var(--chat-accent)] transition-opacity\"\n title={t('Reasoning details')}\n >\n <InfoIcon size={14} />\n </button>\n {toolDetailMsgId === msg.id && (\n <div className=\"mt-1.5 p-3 rounded-lg bg-gray-50 dark:bg-white/[0.04] border border-gray-200 dark:border-white/10\">\n <p className=\"text-[0.7rem] text-gray-500 dark:text-white/40 mb-1.5\">\n {msg.iterations && msg.iterations > 1 ? `${msg.iterations} iterations · ` : ''}\n {msg.toolCallCount ?? msg.toolNames.length}{' '}\n {(msg.toolCallCount ?? msg.toolNames.length) === 1 ? t('tool call') : t('tool calls')}\n </p>\n <div className=\"flex flex-wrap gap-1\">\n {Array.from(new Set(msg.toolNames)).map((tn) => (\n <span\n key={tn}\n className=\"inline-flex items-center px-2 py-0.5 rounded-full border border-gray-200 dark:border-white/10 text-[0.68rem] font-mono text-gray-500 dark:text-white/40\"\n >\n {tn.replace(/_/g, ' ')}\n </span>\n ))}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n );\n })}\n <div ref={messagesEndRef} />\n </div>\n );\n};\n","interface ChatWelcomeProps {\n firstName: string;\n logoIcon: React.ReactNode;\n promptSuggestions: string[];\n onPromptClick: (prompt: string) => void;\n t: (key: string) => string;\n}\n\nexport const ChatWelcome = ({ firstName, logoIcon, promptSuggestions, onPromptClick, t }: ChatWelcomeProps) => (\n <div className=\"flex-1 flex flex-col items-center justify-center px-6 pb-8\">\n <span className=\"text-[var(--chat-accent)] mb-4 [&>svg]:w-12 [&>svg]:h-12 drop-shadow-[0_0_12px_var(--chat-accent-40)]\">{logoIcon}</span>\n <h2 className=\"text-xl font-medium mb-6 text-center text-gray-900 dark:text-white\" style={{ fontFamily: '\"Geologica\", sans-serif' }}>\n {t('How can I help you, ')}\n {firstName}?\n </h2>\n <div className=\"w-full max-w-[320px]\">\n <span className=\"block text-center mb-2 text-[0.65rem] tracking-[1.5px] uppercase text-[var(--chat-accent)] font-semibold\">\n {t('Suggestions')}\n </span>\n {promptSuggestions.map((prompt) => (\n <button\n key={prompt}\n type=\"button\"\n onClick={() => onPromptClick(prompt)}\n className=\"w-full text-left text-[0.8125rem] text-gray-800 dark:text-white py-1.5 px-3 mb-1 rounded-lg border border-gray-200 dark:border-white/10 bg-transparent transition-colors hover:bg-[var(--chat-accent-10)] hover:border-[var(--chat-accent-50)]\"\n >\n {t(prompt)}\n </button>\n ))}\n </div>\n </div>\n);\n","import { type FunctionComponent, useEffect, useState } from 'react';\nimport type { ChatMessage, ChatPanelProps } from '../types';\nimport { hexAlpha, identity } from '../utils';\nimport { useChat } from '../hooks/useChat';\nimport { useAgents } from '../hooks/useAgents';\nimport { useSidebarResize } from '../hooks/useSidebarResize';\nimport { DefaultLogoIcon } from './icons';\nimport { ChatHeader } from './ChatHeader';\nimport { ChatInput } from './ChatInput';\nimport { ChatMessages } from './ChatMessages';\nimport { ChatWelcome } from './ChatWelcome';\n\nconst FLOATING_WIDTH = 380;\nconst FLOATING_HEIGHT = 560;\nconst SIDEBAR_GAP = 6;\n\nconst DEFAULT_SUGGESTIONS = [\n 'Help me create a new simulation scenario',\n 'What are the latest attack patterns?',\n 'How do I configure detection rules?',\n 'Summarize my recent findings',\n];\n\nexport const ChatPanel: FunctionComponent<ChatPanelProps> = ({\n mode,\n onClose,\n onModeChange,\n topOffset = 0,\n apiBaseUrl,\n apiEndpoints,\n agentDashboardUrl,\n user,\n t = identity,\n accentColor = '#7b5cff',\n logoIcon,\n promptSuggestions = DEFAULT_SUGGESTIONS,\n resizable = false,\n onWidthChange,\n onResizeStart,\n onResizeEnd,\n pushContentSelector,\n backendType = 'rest',\n}) => {\n const [modeMenuOpen, setModeMenuOpen] = useState(false);\n\n const { agents, selectedAgent, agentMenuOpen, setAgentMenuOpen, handleSwitchAgent } = useAgents({ apiBaseUrl, apiEndpoints, backendType });\n\n const {\n messages,\n inputValue,\n setInputValue,\n isLoading,\n agentStatus,\n attachedFiles,\n conversationId,\n historyLoadedRef,\n handleFileAdd,\n handlePaste,\n handleSendMessage,\n handleNewChat,\n handleStopGenerating,\n setAttachedFiles,\n setMessages,\n setConversationId,\n } = useChat({ apiBaseUrl, apiEndpoints, backendType, agentSlug: selectedAgent?.slug, t });\n\n const { sidebarWidth, handleResizeStart, defaultWidth, isResizing } = useSidebarResize({\n mode,\n resizable,\n onWidthChange,\n onResizeStart,\n onResizeEnd,\n });\n\n // Push content when sidebar mode is active using CSS variable\n useEffect(() => {\n const width = mode === 'sidebar' ? (resizable ? sidebarWidth : defaultWidth) : 0;\n const pushWidth = width > 0 ? width + SIDEBAR_GAP : 0;\n \n // Set CSS variable on :root for any component to use\n document.documentElement.style.setProperty('--chatbot-sidebar-width', `${pushWidth}px`);\n document.documentElement.style.setProperty(\n '--chatbot-transition',\n isResizing ? 'none' : 'all 225ms cubic-bezier(0.4, 0, 0.2, 1)'\n );\n\n // Also apply to pushContentSelector if provided (for simple cases)\n if (pushContentSelector) {\n const contentElement = document.querySelector<HTMLElement>(pushContentSelector);\n if (contentElement) {\n const originalPaddingRight = contentElement.style.paddingRight;\n const originalTransition = contentElement.style.transition;\n \n contentElement.style.paddingRight = pushWidth > 0 ? `${pushWidth}px` : '';\n contentElement.style.transition = isResizing \n ? 'none' \n : 'padding-right 225ms cubic-bezier(0.4, 0, 0.2, 1)';\n\n return () => {\n contentElement.style.paddingRight = originalPaddingRight;\n contentElement.style.transition = originalTransition;\n document.documentElement.style.setProperty('--chatbot-sidebar-width', '0px');\n };\n }\n }\n\n return () => {\n document.documentElement.style.setProperty('--chatbot-sidebar-width', '0px');\n };\n }, [pushContentSelector, mode, sidebarWidth, defaultWidth, resizable, isResizing]);\n\n const resolvedLogo = logoIcon ?? <DefaultLogoIcon size={24} />;\n const firstName = user.firstName;\n const agentName = selectedAgent?.name || 'Assistant';\n\n const cssVars = {\n '--chat-accent': accentColor,\n '--chat-accent-10': hexAlpha(accentColor, 0.1),\n '--chat-accent-40': hexAlpha(accentColor, 0.25),\n '--chat-accent-50': hexAlpha(accentColor, 0.5),\n '--chat-accent-dark': accentColor,\n } as React.CSSProperties;\n\n // Load conversation history when agent is selected\n useEffect(() => {\n // Skip session history if disabled, using single endpoint mode, or non-REST backend\n if (apiEndpoints?.sessions === null || apiEndpoints?.singleEndpoint || backendType === 'legacy' || backendType === 'ag-ui') return;\n if (!conversationId || historyLoadedRef.current || !selectedAgent) return;\n historyLoadedRef.current = true;\n const sessionsUrl = `${apiBaseUrl}${apiEndpoints?.sessions ?? '/chat/sessions'}`;\n\n const clearStaleConversation = () => {\n setConversationId(null);\n localStorage.removeItem('filigranChatConversationId');\n };\n\n fetch(sessionsUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n conversation_id: conversationId,\n agent_slug: selectedAgent.slug,\n }),\n })\n .then((res) => {\n if (!res.ok) {\n clearStaleConversation();\n return null;\n }\n return res.json();\n })\n .then((data) => {\n if (!data?.messages?.length) return;\n const restored: ChatMessage[] = data.messages.map((m: { role: string; content: string }, i: number) => ({\n id: `restored-${i}`,\n role: m.role as 'user' | 'assistant',\n content: m.content,\n timestamp: new Date(),\n }));\n setMessages(restored);\n })\n .catch(() => {\n clearStaleConversation();\n });\n }, [conversationId, selectedAgent, apiBaseUrl, apiEndpoints, historyLoadedRef, setMessages, setConversationId]);\n\n const onSwitchAgent = (agent: typeof selectedAgent) => {\n if (!agent) return;\n handleSwitchAgent(agent, () => {\n handleNewChat();\n });\n };\n\n const containerClasses = (() => {\n const base = 'filigran-chatbot';\n switch (mode) {\n case 'sidebar':\n return `${base} fixed right-0 bottom-0 flex flex-col bg-white dark:bg-[#1e1e2e] border-l border-gray-200 dark:border-white/10 z-[1200]`;\n case 'floating':\n return `${base} fixed bottom-5 right-5 flex flex-col bg-white dark:bg-[#1e1e2e] rounded-xl shadow-[0_8px_32px_rgba(0,0,0,0.15)] dark:shadow-[0_8px_32px_rgba(0,0,0,0.4)] z-[1300] border border-gray-200 dark:border-white/10`;\n case 'fullscreen':\n return `${base} fixed right-0 bottom-0 left-0 flex flex-col bg-gray-50 dark:bg-[#161622] z-[1400]`;\n default:\n return base;\n }\n })();\n\n const containerStyle: React.CSSProperties = {\n ...cssVars,\n ...(mode === 'sidebar'\n ? { top: topOffset, width: resizable ? sidebarWidth : defaultWidth }\n : mode === 'floating'\n ? { width: FLOATING_WIDTH, height: FLOATING_HEIGHT }\n : { top: topOffset }),\n };\n\n return (\n <div className={containerClasses} style={containerStyle}>\n {mode === 'sidebar' && resizable && (\n <div\n onMouseDown={handleResizeStart}\n className=\"absolute top-0 -left-1 bottom-0 w-2 cursor-col-resize z-10 group\"\n >\n <div className=\"absolute top-0 left-1/2 -translate-x-1/2 bottom-0 w-0.5 rounded bg-[var(--chat-accent)] opacity-0 transition-opacity group-hover:opacity-100 group-active:opacity-100\" />\n </div>\n )}\n <ChatHeader\n mode={mode}\n agentName={agentName}\n agents={agents}\n selectedAgent={selectedAgent}\n agentMenuOpen={agentMenuOpen}\n onAgentMenuToggle={() => setAgentMenuOpen((p) => !p)}\n onAgentMenuClose={() => setAgentMenuOpen(false)}\n onSwitchAgent={onSwitchAgent}\n modeMenuOpen={modeMenuOpen}\n onModeMenuToggle={() => setModeMenuOpen((p) => !p)}\n onModeMenuClose={() => setModeMenuOpen(false)}\n onModeChange={onModeChange}\n onNewChat={handleNewChat}\n onClose={onClose}\n logoIcon={resolvedLogo}\n agentDashboardUrl={agentDashboardUrl}\n t={t}\n />\n {messages.length === 0 ? (\n <ChatWelcome firstName={firstName} logoIcon={resolvedLogo} promptSuggestions={promptSuggestions} onPromptClick={setInputValue} t={t} />\n ) : (\n <ChatMessages messages={messages} isLoading={isLoading} agentStatus={agentStatus} agentName={agentName} logoIcon={resolvedLogo} t={t} />\n )}\n <ChatInput\n inputValue={inputValue}\n onInputChange={setInputValue}\n onSend={handleSendMessage}\n onStop={handleStopGenerating}\n isLoading={isLoading}\n attachedFiles={attachedFiles}\n onFileAdd={handleFileAdd}\n onFileRemove={(i) => setAttachedFiles((prev) => prev.filter((_, j) => j !== i))}\n onPaste={handlePaste}\n t={t}\n mode={mode}\n />\n </div>\n );\n};\n","import type { FunctionComponent } from 'react';\nimport type { ChatToggleButtonProps } from '../types';\nimport { hexAlpha } from '../utils';\nimport { DefaultLogoIcon } from './icons';\n\nexport const ChatToggleButton: FunctionComponent<ChatToggleButtonProps> = ({ isOpen, onToggle, label = 'Ask Assistant', accentColor = '#7b5cff', icon }) => {\n const resolvedIcon = icon ?? <DefaultLogoIcon size={16} />;\n\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"filigran-chatbot inline-flex items-center gap-1.5 px-3 py-[3px] text-[0.8125rem] font-medium whitespace-nowrap rounded-md border transition-colors\"\n style={{\n borderColor: isOpen ? accentColor : hexAlpha(accentColor, 0.5),\n color: accentColor,\n backgroundColor: isOpen ? hexAlpha(accentColor, 0.1) : 'transparent',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.borderColor = accentColor;\n e.currentTarget.style.backgroundColor = hexAlpha(accentColor, 0.1);\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.borderColor = isOpen ? accentColor : hexAlpha(accentColor, 0.5);\n e.currentTarget.style.backgroundColor = isOpen ? hexAlpha(accentColor, 0.1) : 'transparent';\n }}\n >\n <span className=\"[&>svg]:w-4 [&>svg]:h-4\">{resolvedIcon}</span>\n {label}\n </button>\n );\n};\n"],"names":["hexAlpha","hex","alpha","Math","round","toString","padStart","identity","key","parseLegacyEvent","evt","ctx","eventType","event","data","nodeId","status","activeNodeId","action","content","replace","reasoning","usedTools","length","hasUsedTools","tools","map","t","tool","Array","isArray","chatId","parseRestEvent","type","st","thinkingContent","conversationId","conversation_id","toolNames","tool_names","toolCallCount","tool_call_count","iterations","parseAgUiEvent","message","stepName","delta","toolName","toolCallName","STORAGE_KEY","LEGACY_CHAT_ID_KEY","useChat","apiBaseUrl","apiEndpoints","backendType","agentSlug","isLegacy","messages","setMessages","useState","inputValue","setInputValue","isLoading","setIsLoading","agentStatus","setAgentStatus","setConversationId","window","localStorage","getItem","attachedFiles","setAttachedFiles","legacyChatId","setLegacyChatId","historyLoadedRef","useRef","abortControllerRef","hasUsedToolsRef","handleFileAdd","fileList","newFiles","from","forEach","file","reader","FileReader","onload","push","name","size","dataUrl","result","prev","readAsDataURL","handlePaste","e","files","clipboardData","preventDefault","handleSendMessage","async","trim","userMsg","id","crypto","randomUUID","role","timestamp","Date","undefined","current","assistantId","controller","AbortController","requestBody","opts","question","streaming","threadId","runId","context","state","forwardedProps","agent_slug","buildRequestBody","res","fetch","singleEndpoint","method","headers","body","JSON","stringify","signal","ok","m","parseEvent","getParser","getReader","decoder","TextDecoder","buffer","accumulated","doneReceived","done","value","read","decode","stream","lines","split","pop","rawLine","line","startsWith","jsonStr","slice","parsed","parse","setItem","err","DOMException","handleNewChat","abort","removeItem","handleStopGenerating","filter","STORAGE_AGENT_KEY","SIDEBAR_WIDTH","SIDEBAR_WIDTH_STORAGE_KEY","AttachFileIcon","className","_jsx","xmlns","width","height","viewBox","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","children","d","BrainIcon","_jsxs","CheckIcon","ChevronDownIcon","CloseIcon","CopyIcon","x","y","rx","ry","DatabaseIcon","cx","cy","DefaultLogoIcon","EditIcon","ExternalLinkIcon","FileIcon","FloatingIcon","FullscreenExitIcon","FullscreenIcon","GlobeIcon","r","InfoIcon","MailIcon","SearchIcon","SendIcon","SidebarIcon","SparklesIcon","StopCircleIcon","TerminalIcon","points","x1","x2","y1","y2","UserPlusIcon","WrenchIcon","Dropdown","open","onClose","anchorRef","placement","panelRef","pos","setPos","top","left","ref","handler","active","useEffect","listener","contains","target","document","addEventListener","removeEventListener","useClickOutside","useCallback","rect","getBoundingClientRect","right","bottom","portalTarget","el","node","classList","parentElement","findChatbotRoot","createPortal","style","Spinner","Tooltip","title","show","setShow","onMouseEnter","onMouseLeave","modeOptions","mode","label","getIcon","p","ChatHeader","agentName","agents","selectedAgent","agentMenuOpen","onAgentMenuToggle","onAgentMenuClose","onSwitchAgent","modeMenuOpen","onModeMenuToggle","onModeMenuClose","onModeChange","onNewChat","logoIcon","agentDashboardUrl","agentAnchorRef","modeAnchorRef","CurrentModeIcon","onClick","agent","description","opt","ChatInput","onInputChange","onSend","onStop","onFileAdd","onFileRemove","onPaste","fileInputRef","textareaRef","hasContent","f","i","multiple","hidden","onChange","click","placeholder","min","scrollHeight","onKeyDown","shiftKey","rows","maxHeight","disabled","ThinkingTextBubble","cleaned","scrollTop","animation","ChatThinking","StatusIcon","showDots","rawNames","lower","n","toLowerCase","some","count","includes","display","c","toUpperCase","unique","Set","consultName","checkCount","fetchCount","targetName","resolveStatusVisual","_Fragment","delay","MarkdownMessage","copiedBlock","setCopiedBlock","Markdown","remarkPlugins","remarkGfm","components","code","match","exec","codeStr","String","handleCopyCode","navigator","clipboard","writeText","setTimeout","ul","ol","blockquote","a","href","rel","h1","h2","h3","table","th","td","ChatMessages","messagesEndRef","toolDetailMsgId","setToolDetailMsgId","scrollIntoView","behavior","msg","isAssistant","isEmpty","tn","ChatWelcome","firstName","promptSuggestions","onPromptClick","fontFamily","prompt","DEFAULT_SUGGESTIONS","ChatPanel","topOffset","user","accentColor","resizable","onWidthChange","onResizeStart","onResizeEnd","pushContentSelector","setModeMenuOpen","setAgentMenuOpen","handleSwitchAgent","setAgents","setSelectedAgent","then","json","savedSlug","find","slug","catch","onSwitch","useAgents","sidebarWidth","handleResizeStart","defaultWidth","isResizing","setSidebarWidth","stored","parseInt","Number","isNaN","setIsResizing","isResizingRef","sidebarWidthRef","onWidthChangeRef","onResizeEndRef","handleMouseMove","newWidth","innerWidth","clientX","maxWidth","clamped","max","handleMouseUp","cursor","userSelect","handleWindowResize","useSidebarResize","pushWidth","documentElement","setProperty","contentElement","querySelector","originalPaddingRight","paddingRight","originalTransition","transition","resolvedLogo","cssVars","sessions","clearStaleConversation","restored","containerClasses","base","containerStyle","onMouseDown","_","j","ChatToggleButton","isOpen","onToggle","icon","resolvedIcon","borderColor","color","backgroundColor","currentTarget"],"mappings":"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"}
|