@runfusion/fusion 0.32.0 → 0.34.0
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/bin.js +24129 -11045
- package/dist/client/.vite/manifest.json +62 -61
- package/dist/client/assets/{AgentDetailView-CnFf_eBZ.js → AgentDetailView-CzqwIIpv.js} +3 -3
- package/dist/client/assets/{AgentPermissionPolicyEditor-Cmkt9Z01.js → AgentPermissionPolicyEditor-2eoM2XQH.js} +2 -2
- package/dist/client/assets/AgentsView-BrtAvhJl.js +29 -0
- package/dist/client/assets/ChatView-BuIe4MhL.js +6 -0
- package/dist/client/assets/DevServerView-CF6FPLRb.js +1 -0
- package/dist/client/assets/{DirectoryPicker-DctpCNrd.js → DirectoryPicker-BpvHQxhu.js} +1 -1
- package/dist/client/assets/{DocumentsView-DORp5JjC.js → DocumentsView-RMWZBJ-y.js} +1 -1
- package/dist/client/assets/{EvalsView-CYVJ1pbc.js → EvalsView-DtVxpc4T.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-BULVNAiq.js → ExperimentalAgentOnboardingModal-fzJmb-yG.js} +2 -2
- package/dist/client/assets/{GoalsView-bmpZKOI_.js → GoalsView-BAchggxo.js} +1 -1
- package/dist/client/assets/{InsightsView-mmtem0RU.js → InsightsView-B8892IbG.js} +1 -1
- package/dist/client/assets/{MemoryView-HVpO1fCH.js → MemoryView-Cfp1WmAm.js} +2 -2
- package/dist/client/assets/NodesView-Dt26DSEQ.js +14 -0
- package/dist/client/assets/{PiExtensionsManager-Cyfas2VT.js → PiExtensionsManager-xHU56SMh.js} +2 -2
- package/dist/client/assets/{PluginManager-C7QDE3Lk.js → PluginManager-37WUEOmp.js} +1 -1
- package/dist/client/assets/ResearchView-pu88M5xL.js +1 -0
- package/dist/client/assets/SecretsView-BT7ofJLN.js +1 -0
- package/dist/client/assets/{SecretsView-BFhVwJu6.css → SecretsView-D5bHZ-wM.css} +1 -1
- package/dist/client/assets/SettingsModal-0gevFhXV.css +1 -0
- package/dist/client/assets/SettingsModal-Cz9MHNGg.js +31 -0
- package/dist/client/assets/{SettingsModal-YCJM5is3.js → SettingsModal-DxYXsn08.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-BT-mj3VD.js → SetupWizardModal-yWTk3Cac.js} +1 -1
- package/dist/client/assets/{SkillsView-Db7dYpqd.js → SkillsView-CWNfKNTs.js} +1 -1
- package/dist/client/assets/{StashRecoveryView-CSYYcWux.js → StashRecoveryView-D0t4IIX-.js} +1 -1
- package/dist/client/assets/{TodoView-zqCqfy26.js → TodoView-B4W1Lhy6.js} +2 -2
- package/dist/client/assets/{dashboard-view-PpcsMDvN.js → dashboard-view-4OCJIthP.js} +1 -1
- package/dist/client/assets/{folder-open-mxsFQlAX.js → folder-open-BTdhwFQ5.js} +1 -1
- package/dist/client/assets/index-D4nQgFjo.js +742 -0
- package/dist/client/assets/index-k4s0JWir.css +1 -0
- package/dist/client/assets/{upload-j7JjaJzG.js → upload-kESyjow_.js} +1 -1
- package/dist/client/assets/{users-DZ_0WcB6.js → users-DNXMrdcp.js} +1 -1
- package/dist/client/index.html +102 -3
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +18838 -6745
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/src/dashboard/__tests__/ReportsView.test.tsx +15 -0
- package/dist/plugins/fusion-plugin-reports/src/dashboard/test-setup.ts +9 -1
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -1
- package/skill/fusion/references/extension-tools.md +4 -1
- package/skill/fusion/references/fusion-capabilities.md +1 -1
- package/dist/client/assets/AgentsView-LkVv9hph.js +0 -34
- package/dist/client/assets/ChatView-DYjECCRG.js +0 -1
- package/dist/client/assets/DevServerView-D7legPr1.js +0 -1
- package/dist/client/assets/NodesView-CM0eoCP8.js +0 -14
- package/dist/client/assets/ResearchView-Bn2WxwnQ.js +0 -1
- package/dist/client/assets/SecretsView-DgrrgzFc.js +0 -1
- package/dist/client/assets/SettingsModal-BCZrCLl3.js +0 -31
- package/dist/client/assets/SettingsModal-BZBV2kLr.css +0 -1
- package/dist/client/assets/index-Ba-F8c1g.js +0 -732
- package/dist/client/assets/index-D4HhaIOp.css +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as s,a as sn,j as t,R as nn}from"./vendor-react-K0fH_qHe.js";import{a8 as an,a6 as rn,ba as on,i as St,bb as vs,ab as cn,bc as ln,t as dn,bd as un,be as xs,bf as mn,bg as Ot,w as hn,bh as fn,bi as gn,bj as pn,bk as bn,bl as vn,bm as xn,bn as yn,s as wn,bo as Sn,k as $s,bp as jn,bq as Cn,br as Nn,bs as kn,p as Mn,bt as Rn,bu as An,u as En,h as Ps,bv as Tn,ag as Fs,ah as Ls,bw as In,bx as Dn,S as $n,Y as Gt,P as at,J as nt,au as Pn,by as ys,a as bt,bz as ws,bA as Ss,B as rt,ad as Fn,ae as Ln,a$ as wt,bB as zn,bC as _n,aY as Un,bD as js,bE as Hn,T as On,bF as Cs,bG as Gn,j as Ns,m as Kn}from"./index-Ba-F8c1g.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const Kt="kb-chat-active-session";function ks(n){const r=typeof n=="string"?n.trim():"",d=r.indexOf("/");return!r||d<=0||d>=r.length-1?{}:{modelProvider:r.slice(0,d),modelId:r.slice(d+1)}}function Bn(n){const r=n?.toolCalls;if(!Array.isArray(r))return;const d=r.map(i=>{if(!i||typeof i!="object")return null;const f=i,p=typeof f.toolName=="string"?f.toolName:"";if(!p)return null;const m=f.args;return{toolName:p,...m&&typeof m=="object"?{args:m}:{},isError:!!f.isError,result:f.result,status:"completed"}}).filter(i=>i!==null);return d.length>0?d:void 0}function Wn(n){const r=n?.fallback;if(!r||typeof r!="object")return;const d=r,i=typeof d.primaryModel=="string"?d.primaryModel:"",f=typeof d.fallbackModel=="string"?d.fallbackModel:"",p=d.triggerPoint;if(!(!i||!f||p!=="session-creation"&&p!=="prompt-time"))return{primaryModel:i,fallbackModel:f,triggerPoint:p}}function Vn(n){const r=n?.failureInfo;if(!r||typeof r!="object")return;const d=r,i=typeof d.summary=="string"?d.summary.trim():"";if(!i)return;const f=(()=>{const p=d.reference;if(!p||typeof p!="object")return;const m=p,S=typeof m.kind=="string"?m.kind.trim():"",F=typeof m.id=="string"?m.id.trim():"";if(!(!S||!F))return{kind:S,id:F,...typeof m.label=="string"&&m.label.trim()?{label:m.label.trim()}:{}}})();return{summary:i,...typeof d.errorClass=="string"&&d.errorClass.trim()?{errorClass:d.errorClass.trim()}:{},...typeof d.code=="string"&&d.code.trim()?{code:d.code.trim()}:{},...typeof d.detail=="string"&&d.detail.trim()?{detail:d.detail.trim()}:{},...f?{reference:f}:{}}}function Ms(n){return typeof n=="string"?{summary:n.trim()||"Failed to get response"}:{summary:typeof n.summary=="string"&&n.summary.trim()?n.summary.trim():"Failed to get response",...typeof n.errorClass=="string"&&n.errorClass.trim()?{errorClass:n.errorClass.trim()}:{},...typeof n.code=="string"&&n.code.trim()?{code:n.code.trim()}:{},...typeof n.detail=="string"&&n.detail.trim()?{detail:n.detail.trim()}:{},...n.reference?{reference:n.reference}:{}}}function Bt(n){return{id:n.id,sessionId:n.sessionId,role:n.role,content:n.content,thinkingOutput:n.thinkingOutput,toolCalls:Bn(n.metadata),fallbackInfo:Wn(n.metadata),failureInfo:Vn(n.metadata),attachments:n.attachments,createdAt:n.createdAt}}function qn(n,r){const d=s.useCallback(l=>l?`${an.CHAT_SESSIONS_PREFIX}${l}`:null,[]),i=s.useCallback(l=>{const h=d(l);return h?rn(h,{maxAgeMs:on})??[]:[]},[d]),[f,p]=s.useState(()=>i(n)),[m,S]=s.useState(null),[F,G]=s.useState(()=>i(n).length===0),[Z,v]=s.useState([]),[U,N]=s.useState(!1),[te,j]=s.useState(!1),[K,y]=s.useState(""),[I,C]=s.useState(""),[L,w]=s.useState([]),[se,V]=s.useState(""),[$,u]=s.useState(""),[R,o]=s.useState(!0),[D,H]=s.useState(new Map),g=s.useRef(null),B=s.useRef(null),ue=s.useRef(!1),me=s.useRef(""),ye=s.useRef(null),we=s.useRef(f),ee=s.useRef(m),O=s.useRef(te);we.current=f,ee.current=m,O.current=te,s.useEffect(()=>{me.current=se},[se]);const Me=s.useRef(new Set),ie=s.useRef(0),Se=s.useRef(n);Se.current!==n&&(Se.current=n,ie.current++),s.useEffect(()=>{const l=ie.current;St(void 0,n).then(h=>{if(ie.current!==l)return;const x=new Map;for(const k of h)x.set(k.id,k);H(x)}).catch(()=>{})},[n]);const he=s.useCallback(async()=>{we.current.length===0&&G(!0);try{const h=[...(await vs(n)).sessions].sort((k,Y)=>new Date(Y.updatedAt).getTime()-new Date(k.updatedAt).getTime());p(h);const x=d(n);x&&cn(x,h,{maxBytes:5e5})}catch{const l=i(n);if(we.current.length===0&&l.length===0){const h=d(n);h&&ln(h)}}finally{G(!1)}},[d,n]);s.useEffect(()=>{const l=i(n);p(l),G(l.length===0)},[n,i]),s.useEffect(()=>{he()},[he,n]);const it=s.useRef(()=>{}),ve=s.useRef(!1);s.useEffect(()=>{ve.current=!1,B.current=null},[n]),s.useEffect(()=>{if(F||ve.current||ee.current)return;const l=dn(Kt,n);if(!l){ve.current=!0;return}const h=f.find(x=>x.id===l);if(h){ve.current=!0,it.current(l,h);return}ve.current=!0},[F,f,n]);const W=s.useCallback(async(l,h)=>{N(!0);try{const x=await un(l,{limit:50,...h},n),k=x.messages.map(Bt);h?.offset&&h.offset>0?v(Y=>[...k,...Y]):v(k),o(x.messages.length>=50)}catch{}finally{N(!1)}},[n]),He=s.useCallback(()=>{ye.current?.(),ye.current=null,me.current="",V(""),y(""),C(""),w([]),j(!1)},[]),ot=s.useCallback(()=>{me.current="",V("")},[]),ne=s.useCallback(()=>{const l=me.current.trim();l&&(me.current="",V(""),ze.current(l))},[]),ae=s.useCallback((l,h,x)=>{if(g.current||!l)return!0;ue.current=!1,h&&(y(h.streamingText),C(h.streamingThinking),w(h.toolCalls)),j(!0);const{handlers:k}=xs({sessionId:l,tempUserMessageId:"",setStreamingText:y,setStreamingThinking:C,setStreamingToolCalls:w,cancelStreamingFlushesRef:ye,addToast:x?.silent?void 0:r,onFallbackSession:(E,q)=>{const X=ks(E.fallbackModel);p(A=>A.map(P=>P.id===q?{...P,...X}:P)),S(A=>A&&A.id===q?{...A,...X}:A)},onDone:()=>{y(""),C(""),w([]),j(!1),O.current=!1,g.current=null,B.current=null,W(l),ne()},onError:E=>{y(""),C(""),w([]),j(!1),O.current=!1,g.current=null,B.current=null;const q=Ms(E);x?.silent||r?.(q.summary,"error"),W(l),ne()}}),Y=mn(l,k,n,{...typeof h?.replayFromEventId=="number"?{lastEventId:h.replayFromEventId}:{}});return g.current=Y,B.current={sessionId:l,replayFromEventId:typeof h?.replayFromEventId=="number"?h.replayFromEventId:null},!0},[r,W,n,ne]),Le=s.useCallback((l,h)=>{const x=ee.current?.id??null;if(l&&x===l&&!h)return;g.current&&(g.current.close(),g.current=null),B.current=null;const k=h??f.find(Y=>Y.id===l);S(k||null),l&&Ot(l,n).then(({session:Y})=>{!Y.isGenerating||!Y.inFlightGeneration||S(E=>!E||E.id!==l?E:{...E,...Y})}).catch(()=>{}),He(),o(!0),l?W(l):v([]),k?.isGenerating&&ae(k.id,k.inFlightGeneration),l?hn(Kt,l,n):fn(Kt,n)},[ae,f,W,n,He]);it.current=Le;const jt=s.useCallback(async l=>{const h=await gn(l,n);g.current&&(g.current.close(),g.current=null),B.current=null;const x={id:h.session.id,title:h.session.title,agentId:h.session.agentId,status:h.session.status,modelProvider:h.session.modelProvider,modelId:h.session.modelId,createdAt:h.session.createdAt,updatedAt:h.session.updatedAt};return p(k=>k.some(Y=>Y.id===x.id)?k:[x,...k]),He(),Le(x.id,x),v([]),x},[n,He,Le]),ct=s.useCallback(async l=>{await pn(l,{status:"archived"},n),p(h=>h.filter(x=>x.id!==l)),m?.id===l&&(B.current=null,S(null),v([]))},[m,n]),Re=s.useCallback(async l=>{m?.id===l&&g.current&&(g.current.close(),g.current=null),m?.id===l&&(B.current=null),await bn(l,n),p(h=>h.filter(x=>x.id!==l)),m?.id===l&&(S(null),v([]))},[m,n]),Ae=s.useCallback(async()=>{!m||!R||await W(m.id,{offset:Z.length})},[m,R,W,Z.length]),Ye=s.useCallback(()=>{m&&(ue.current=!0,ye.current?.(),ye.current=null,g.current?.close(),g.current=null,B.current=null,vn(m.id,n).catch(()=>{}),j(!1),O.current=!1,y(""),C(""),w([]),ne())},[m,n,ne]),ze=s.useRef(()=>{}),_e=xn(),Ee=s.useCallback(async l=>{try{await he();const h=await Ot(l,n);ee.current?.id===l&&S(x=>!x||x.id!==l?x:{...x,...h.session}),h.session.isGenerating?(y(""),C(""),w([]),j(!0),O.current=!0,ae(l,h.session.inFlightGeneration,{silent:!0})):(y(""),C(""),w([]),j(!1),O.current=!1,await W(l))}catch{}},[ae,W,n,he]),je=s.useCallback((l,h)=>{if(!m)return;if(O.current){me.current=l,V(l);return}ue.current=!1,g.current&&(g.current.close(),g.current=null),B.current=null;const x=`temp-${Date.now()}`,k={id:x,sessionId:m.id,role:"user",content:l,createdAt:new Date().toISOString()};v(E=>[...E,k]),y(""),C(""),w([]),j(!0);const{handlers:Y}=xs({sessionId:m.id,tempUserMessageId:x,setStreamingText:y,setStreamingThinking:C,setStreamingToolCalls:w,cancelStreamingFlushesRef:ye,addToast:r,onFallbackSession:(E,q)=>{const X=ks(E.fallbackModel);p(A=>A.map(P=>P.id===q?{...P,...X}:P)),S(A=>A&&A.id===q?{...A,...X}:A)},onDone:({messageId:E,message:q,accumulated:X})=>{const A=q?{...Bt(q),...X.text.length>0?{content:X.text}:{}}:{id:E||`msg-${Date.now()}`,sessionId:m.id,role:"assistant",content:X.text,thinkingOutput:X.thinking,toolCalls:X.toolCalls.length>0?X.toolCalls:void 0,fallbackInfo:X.fallbackInfo,createdAt:new Date().toISOString()};Me.current.add(A.id),v(P=>[...P,A]),y(""),C(""),w([]),j(!1),O.current=!1,g.current=null,B.current=null,setTimeout(()=>{Me.current.delete(A.id)},1e3),he(),ne()},onError:(E,q)=>{const X=Ms(E),A=typeof E=="string"?E:X.summary,P=Sn(A);v(J=>{const T=J.filter(Q=>Q.id!==q);return P?T:[...T,{id:`error-${Date.now()}`,sessionId:m.id,role:"assistant",content:X.summary,failureInfo:X,createdAt:new Date().toISOString()}]}),y(""),C(""),w([]),j(!1),O.current=!1,g.current=null,B.current=null,console.error("[useChat] Stream error:",E),P?(console.info("[useChat] Suppressed tab-suspension stream error:",E),m?.id&&(y(""),C(""),w([]),j(!0),O.current=!0,Ee(m.id))):(r?.(X.summary,"error"),he()),ue.current||ne()}});g.current=yn(m.id,l,Y,h,n)},[m,n,he,r,ae,Ee,ne]);ze.current=je;const Te=$?f.filter(l=>l.title?.toLowerCase().includes($.toLowerCase())||l.agentId.toLowerCase().includes($.toLowerCase())):f;return s.useEffect(()=>{if(!m?.id||m.isGenerating!==!0||g.current)return;const l=typeof m.inFlightGeneration?.replayFromEventId=="number"?m.inFlightGeneration.replayFromEventId:null,h=B.current;h?.sessionId===m.id&&h.replayFromEventId===l||ae(m.id,m.inFlightGeneration,{silent:!0})},[m?.id,m?.isGenerating,m?.inFlightGeneration,ae]),s.useEffect(()=>{if(!ee.current?.isGenerating||(g.current||ae(ee.current.id,ee.current.inFlightGeneration),!O.current||g.current||!ee.current))return;const l=setInterval(async()=>{if(!O.current||g.current||!ee.current){clearInterval(l);return}try{(await vs(n)).sessions.find(k=>k.id===ee.current?.id)?.isGenerating||(clearInterval(l),await W(ee.current.id),y(""),C(""),w([]),j(!1),O.current=!1,ne())}catch{}},3e3);return()=>clearInterval(l)},[ae,W,n,m,ne]),s.useEffect(()=>_e.onBecameVisible(()=>{const h=ee.current;if(!h||g.current)return;const x=ie.current;Ot(h.id,n).then(k=>{if(!(ie.current!==x||g.current)){if(k.session.isGenerating){y(""),C(""),w([]),j(!0),O.current=!0,ae(h.id,k.session.inFlightGeneration,{silent:!0});return}O.current&&(y(""),C(""),w([]),j(!1),O.current=!1,ne(),W(h.id))}}).catch(()=>{})}),[ae,W,n,_e,ne]),s.useEffect(()=>{const l=ie.current,h=n?`?projectId=${encodeURIComponent(n)}`:"",x=()=>ie.current!==l,k=P=>{if(x())return;const J=JSON.parse(P.data);p(T=>T.some(Q=>Q.id===J.id)?T:[J,...T])},Y=P=>{if(x())return;const J=JSON.parse(P.data);p(T=>[...T.map(oe=>oe.id===J.id?J:oe)]),ee.current?.id===J.id&&(S(J),J.isGenerating&&!g.current&&ae(J.id,J.inFlightGeneration))},E=P=>{if(x())return;const{id:J}=JSON.parse(P.data);p(T=>T.filter(Q=>Q.id!==J)),ee.current?.id===J&&(S(null),v([]))},q=P=>{if(x())return;const J=JSON.parse(P.data),T=Bt(J);if(!Me.current.has(T.id)){if(ee.current?.id===T.sessionId&&O.current&&!g.current&&T.role==="assistant"){v(Q=>Q.some(oe=>oe.id===T.id)?Q:[...Q,T]),y(""),C(""),w([]),j(!1),O.current=!1,ne();return}ee.current?.id===T.sessionId&&!O.current&&v(Q=>{if(Q.some(oe=>oe.id===T.id))return Q;if(T.role==="user"){const oe=Q.findIndex(ce=>ce.role==="user"&&ce.id.startsWith("temp-")&&ce.content.trim()===T.content.trim());if(oe>=0){const ce=[...Q];return ce[oe]=T,ce}}return[...Q,T]})}},X=P=>{if(x())return;const{id:J}=JSON.parse(P.data);v(T=>T.filter(Q=>Q.id!==J))};return wn(`/api/events${h}`,{events:{"chat:session:created":k,"chat:session:updated":Y,"chat:session:deleted":E,"chat:message:added":q,"chat:message:deleted":X}})},[ae,n,ne]),s.useEffect(()=>()=>{g.current&&(g.current.close(),g.current=null),B.current=null},[]),{sessions:f,activeSession:m,sessionsLoading:F,messages:Z,messagesLoading:U,isStreaming:te,streamingText:K,streamingThinking:I,streamingToolCalls:L,pendingMessage:se,selectSession:Le,createSession:jt,archiveSession:ct,deleteSession:Re,sendMessage:je,stopStreaming:Ye,clearPendingMessage:ot,loadMoreMessages:Ae,hasMoreMessages:R,searchQuery:$,setSearchQuery:u,filteredSessions:Te,refreshSessions:he,agentsMap:D}}function Xn(n,r=[]){const d=n.trim().replace(/^#/,"");if(!d)return{ok:!1,error:"Room name is required."};if(/[A-Z]/.test(d))return{ok:!1,error:"Use lowercase letters only."};const i=d.toLowerCase();return i.length>80?{ok:!1,error:"Room names can be at most 80 characters."}:/^[a-z0-9_-]+$/.test(i)?/^[-_]|[-_]$/.test(i)?{ok:!1,error:"Room names cannot start or end with a hyphen or underscore."}:r.some(f=>f.toLowerCase()===i)?{ok:!1,error:"A room with this name already exists."}:{ok:!0,name:i}:{ok:!1,error:"Use lowercase letters, numbers, hyphens, or underscores only."}}function Yn({isOpen:n,onClose:r,onCreate:d,projectId:i,existingRoomNames:f=[]}){const[p,m]=s.useState(""),[S,F]=s.useState([]),[G,Z]=s.useState(""),[v,U]=s.useState([]),[N,te]=s.useState(!1),[j,K]=s.useState(null),[y,I]=s.useState(!1),C=s.useRef(null),L=s.useRef(null);s.useEffect(()=>{n&&(L.current=document.activeElement instanceof HTMLElement?document.activeElement:null,te(!0),K(null),St(void 0,i).then(o=>F(o)).catch(()=>{F([]),K("Failed to load agents.")}).finally(()=>te(!1)))},[n,i]),s.useEffect(()=>{if(!n){m(""),Z(""),U([]),K(null),I(!1);return}const o=window.requestAnimationFrame(()=>C.current?.focus());return()=>window.cancelAnimationFrame(o)},[n]),s.useEffect(()=>{if(!n)return;const o=D=>{D.key==="Escape"&&r()};return document.addEventListener("keydown",o),()=>document.removeEventListener("keydown",o)},[n,r]),s.useEffect(()=>{n||L.current?.focus()},[n]);const w=s.useMemo(()=>Xn(p,f),[p,f]),se=s.useMemo(()=>{const o=G.trim().toLowerCase();return o?S.filter(D=>D.name.toLowerCase().includes(o)):S},[S,G]),V=s.useMemo(()=>S.filter(o=>v.includes(o.id)),[S,v]),$=w.ok&&v.length>0&&!y&&!N;if(!n)return null;const u=o=>{y||U(D=>D.includes(o)?D.filter(H=>H!==o):[...D,o])},R=async()=>{if(!w.ok){K(w.error);return}if(v.length===0){K("Select at least one member.");return}K(null),I(!0);try{await d({name:w.name,displayName:`#${w.name}`,memberAgentIds:v}),r()}catch(o){K(o instanceof Error?o.message:"Failed to create room.")}finally{I(!1)}};return sn.createPortal(t.jsx("div",{className:"modal-overlay open",onClick:o=>o.target===o.currentTarget&&r(),children:t.jsxs("div",{className:"modal modal-lg create-room-modal",role:"dialog","aria-modal":"true","aria-label":"Create room",onClick:o=>o.stopPropagation(),children:[t.jsxs("div",{className:"modal-header",children:[t.jsx("h3",{children:"Create room"}),t.jsx("button",{type:"button",className:"modal-close","aria-label":"Close",onClick:r,children:"×"})]}),t.jsxs("div",{className:"form-group create-room-modal-name-group",children:[t.jsx("label",{htmlFor:"create-room-name",children:"Room name"}),t.jsxs("div",{className:"create-room-modal-name-field",children:[t.jsx("span",{"aria-hidden":"true",className:"create-room-modal-name-hash",children:"#"}),t.jsx("input",{ref:C,id:"create-room-name",className:"input",value:p,disabled:y,onChange:o=>{const D=o.target.value.replace(/^#/,"").replace(/\s+/g,"-").toLowerCase();m(D)}})]}),!w.ok&&t.jsx("div",{className:"form-error",children:w.error})]}),t.jsxs("div",{className:"form-group",children:[t.jsx("label",{htmlFor:"create-room-member-search",children:"Members"}),t.jsx("input",{id:"create-room-member-search",className:"input",placeholder:"Search agents",value:G,disabled:y,onChange:o=>Z(o.target.value)})]}),V.length>0&&t.jsx("div",{className:"create-room-modal-selected","data-testid":"create-room-selected-chips",children:V.map(o=>t.jsxs("button",{type:"button",className:"btn btn-sm create-room-modal-chip",onClick:()=>u(o.id),disabled:y,children:[o.name," ×"]},o.id))}),t.jsx("div",{className:"create-room-modal-member-list","data-testid":"create-room-member-list",children:N?t.jsx("div",{className:"create-room-modal-empty",children:"Loading agents..."}):se.length===0?t.jsx("div",{className:"create-room-modal-empty",children:S.length===0?"No agents in this project yet.":"No agents match your search."}):se.map(o=>{const D=v.includes(o.id);return t.jsxs("button",{type:"button",className:`create-room-modal-member-row${D?" create-room-modal-member-row--selected":""}`,onClick:()=>u(o.id),disabled:y,children:[t.jsx($s,{agent:o,size:20}),t.jsx("span",{children:o.name}),t.jsx("span",{className:"create-room-modal-member-role",children:o.role})]},o.id)})}),j&&t.jsx("div",{className:"form-group",children:t.jsx("div",{className:"form-error",children:j})}),t.jsxs("div",{className:"modal-actions",children:[t.jsx("button",{type:"button",className:"btn",onClick:r,disabled:y,children:"Cancel"}),t.jsx("button",{type:"button",className:"btn btn-primary",onClick:()=>void R(),disabled:!$,children:y?"Creating...":"Create room"})]})]})}),document.body)}const Jn=640;function Qn(n){return Math.max(40,Math.min(n,Jn))}function zs(n){const r=new Date(n),i=new Date().getTime()-r.getTime(),f=Math.floor(i/1e3),p=Math.floor(f/60),m=Math.floor(p/60),S=Math.floor(m/24);return f<60?"just now":p<60?`${p}m ago`:m<24?`${m}h ago`:S<7?`${S}d ago`:r.toLocaleDateString()}function Rs(n,r){if(!n||!r)return null;const d=r.toLowerCase();if(d.includes("claude")){let f=r.replace(/^claude[- ]/i,"Claude ").replace(/sonnet[- ](\d+)[- ](\d+)/i,"Sonnet $1.$2").replace(/sonnet[- ](\d+)/i,"Sonnet $1").replace(/haiku[- ](\d+)/i,"Haiku $1").replace(/opus[- ](\d+)/i,"Opus $1").replace(/sonnet/i,"Sonnet").replace(/haiku/i,"Haiku").replace(/opus/i,"Opus").replace(/-/g," ").trim();return f=f.replace(/\s+/g," "),f.length>30?f.slice(0,30)+"…":f}if(d.includes("gpt")||d.includes("openai")){const f=r.replace(/^gpt-4-turbo$/i,"GPT-4 Turbo").replace(/^gpt-4o-mini$/i,"GPT-4o Mini").replace(/^gpt-4o$/i,"GPT-4o").replace(/^gpt-4$/i,"GPT-4").replace(/^gpt-o1-preview$/i,"GPT-o1 Preview").replace(/^gpt-o1-mini$/i,"GPT-o1 Mini").replace(/^gpt-o1$/i,"GPT-o1").replace(/^gpt/i,"GPT").trim();return f.length>30?f.slice(0,30)+"…":f}if(d.includes("gemini")){const f=r.replace(/^gemini[- ]/i,"Gemini ").replace(/pro[- ](\d+)[- ](\d+)/i,"Pro $1.$2").replace(/pro[- ](\d+)/i,"Pro $1").replace(/-/g," ").replace(/\s+/g," ").trim();return f.length>30?f.slice(0,30)+"…":f}const i=r.replace(/-/g," ").replace(/^\w/,f=>f.toUpperCase()).replace(/\s+/g," ").trim();return i.length>30?i.slice(0,30)+"…":i}function yt(n,r){return n.length<=r?n:`${n.slice(0,r)}…`}function Zn(n){if(!n)return null;const r=Object.entries(n);return r.length===0?null:r.map(([d,i])=>{const f=typeof i=="string"?i:(()=>{try{return JSON.stringify(i)}catch{return String(i)}})();return`${d}=${yt(f,50)}`}).join(", ")}function ea(n){if(n===void 0)return null;if(typeof n=="string")return yt(n,200);try{return yt(JSON.stringify(n),200)}catch{return yt(String(n),200)}}function ta(n){if(!n)return null;if(n.kind==="mailbox"||n.kind==="mailbox-message"){const r=typeof window>"u"?"/":window.location.pathname||"/",d=new URLSearchParams(typeof window>"u"?"":window.location.search);return d.set("view","mailbox"),d.set("mailbox-message",n.id),`${r}?${d.toString()}#message-${encodeURIComponent(n.id)}`}return null}function sa(n){if(!n)return null;const r=n.label??`${n.kind} ${n.id}`,d=ta(n),i=`chat-failure-reference-${n.kind}-${n.id}`.replace(/[^a-zA-Z0-9_-]+/g,"-").toLowerCase();return t.jsxs("div",{className:"chat-message-failure-reference",children:[t.jsx("span",{className:"chat-message-failure-reference-label",children:"Reference"}),t.jsx("span",{className:"chat-message-failure-reference-value",children:r}),d?t.jsx("a",{className:"btn btn-sm chat-message-failure-reference-link",href:d,children:"Open mailbox message"}):t.jsxs("details",{className:"chat-message-failure-reference-details",children:[t.jsx("summary",{className:"btn btn-sm chat-message-failure-reference-link",children:"View failure details"}),t.jsxs("dl",{className:"chat-message-failure-reference-meta",id:i,children:[t.jsxs("div",{children:[t.jsx("dt",{children:"Kind"}),t.jsx("dd",{children:n.kind})]}),t.jsxs("div",{children:[t.jsx("dt",{children:"ID"}),t.jsx("dd",{children:n.id})]}),n.label&&t.jsxs("div",{children:[t.jsx("dt",{children:"Label"}),t.jsx("dd",{children:n.label})]})]})]})]})}function _s(n){if(!n||n.length===0)return null;const r=(v,U)=>{const N=v.status==="running",te=v.status==="completed"&&v.isError,j=Zn(v.args),K=ea(v.result),y=N?j:K?`result: ${K}`:j?`args: ${j}`:null,I=N?"running":te?"error":"completed";return t.jsxs("details",{className:`chat-tool-call${N?" chat-tool-call--running":""}${te?" chat-tool-call--error":""}`,open:N,children:[t.jsxs("summary",{children:[t.jsx("span",{className:"chat-tool-call-status-dot","aria-hidden":"true"}),t.jsx("span",{className:"chat-tool-call-name",title:v.toolName,children:v.toolName}),y&&t.jsx("span",{className:"chat-tool-call-preview",title:y,children:y}),t.jsx("span",{className:"chat-tool-call-status-text",children:I})]}),t.jsxs("div",{className:"chat-tool-call-content",children:[j&&t.jsxs("div",{className:"chat-tool-call-row",children:[t.jsx("span",{className:"chat-tool-call-label",children:"args"}),t.jsx("span",{className:"chat-tool-call-value",children:j})]}),K&&t.jsxs("div",{className:`chat-tool-call-row${te?" chat-tool-call-row--error":""}`,children:[t.jsx("span",{className:"chat-tool-call-label",children:"result"}),t.jsx("span",{className:"chat-tool-call-value",children:K})]})]})]},`${v.toolName}-${U}`)},d="chat-tool-calls";if(n.length===1)return t.jsxs("div",{className:d,"data-testid":"chat-tool-calls",children:[t.jsxs("div",{className:"chat-tool-calls-header",children:[t.jsx(Cs,{size:12,"aria-hidden":"true"}),t.jsx("span",{children:"Tool calls"})]}),r(n[0],0)]});const i=n.filter(v=>v.status==="running").length,f=n.filter(v=>v.status==="completed"&&v.isError).length,p=i>0,m=Array.from(new Set(n.map(v=>v.toolName))),S=m.slice(0,5),F=Math.max(0,m.length-S.length),G=F>0?`${S.join(", ")}, +${F} more`:S.join(", "),Z=p?`(${i} running)`:f>0?`(${f} ${f===1?"error":"errors"})`:null;return t.jsx("div",{className:d,"data-testid":"chat-tool-calls",children:t.jsxs("details",{className:"chat-tool-calls-group","data-testid":"chat-tool-calls-group",open:p,children:[t.jsxs("summary",{className:"chat-tool-calls-group-summary",children:[t.jsx(Cs,{size:12,"aria-hidden":"true"}),t.jsxs("span",{className:"chat-tool-calls-count",children:[n.length," tool calls"]}),t.jsx("span",{className:"chat-tool-calls-names",title:G,children:G}),Z&&t.jsx("span",{className:"chat-tool-calls-group-status",children:Z})]}),n.map((v,U)=>r(v,U))]})})}const Us={p:({children:n,...r})=>t.jsx("p",{...r,children:js(n)}),li:({children:n,...r})=>t.jsx("li",{...r,children:js(n)}),pre:({children:n,...r})=>t.jsx("pre",{...r,className:"chat-markdown-pre",children:n}),code:({children:n,...r})=>{const d=typeof n=="string"?n:nn.Children.toArray(n).join(""),i=wt(d);return i.length===1&&typeof i[0]=="string"?t.jsx("code",{...r,children:n}):t.jsx("code",{...r,children:i})},table:({children:n,...r})=>t.jsx("table",{...r,className:"chat-markdown-table",children:n})},Xe="__fn_agent__",na=280,vt=180,xt=500,As="fusion:chat-sidebar-width",Wt="fusion:chat-scope",aa="fusion:chat-draft:";function Es(n,r){return r?`${aa}${n}:${r}`:null}function Ts(n){if(!n)return"";try{return localStorage.getItem(n)??""}catch{return""}}const ra=["image/png","image/jpeg","image/gif","image/webp","text/plain","application/json","text/yaml","text/markdown","text/csv","application/xml","text/x-log"];function Is(n){const r=/(^|[\s])\/([^\s]*)$/.exec(n);if(!r)return null;const d=r[1]??"",i=r[2]??"",f=r.index+d.length;return{filter:i,start:f,end:n.length}}function ia(n,r){const d=n.slice(0,r),i=/(^|[\s\n])@([\w-]*)$/.exec(d);if(!i)return null;const f=i[2]??"",p=d.length-f.length-1;return{filter:f,start:p,end:r}}function oa(n){const r=n?.runtimeConfig;if(!r||typeof r!="object")return null;const d=Reflect.get(r,"modelProvider"),i=Reflect.get(r,"modelId");return typeof d!="string"||d.trim().length===0||typeof i!="string"||i.trim().length===0?null:{provider:d,modelId:i}}function Ds(n,r,d){if(n?.modelProvider&&n?.modelId)return{provider:n.modelProvider,modelId:n.modelId};const i=oa(r??void 0);return i||(d.provider&&d.modelId?{provider:d.provider,modelId:d.modelId}:null)}function ca({projectId:n,onClose:r,onCreate:d}){const[i,f]=s.useState("agent"),[p,m]=s.useState([]),[S,F]=s.useState(!0),[G,Z]=s.useState(""),[v,U]=s.useState([]),[N,te]=s.useState(!0),[j,K]=s.useState(""),[y,I]=s.useState([]),[C,L]=s.useState([]);s.useEffect(()=>{let u=!1;return F(!0),St(void 0,n).then(R=>{u||m(R)}).catch(()=>{u||m([])}).finally(()=>{u||F(!1)}),()=>{u=!0}},[n]),s.useEffect(()=>{te(!0),Ps().then(u=>{U(u.models),I(u.favoriteProviders),L(u.favoriteModels)}).catch(()=>{U([]),I([]),L([])}).finally(()=>{te(!1)})},[]);const w=s.useCallback(async u=>{const R=y,D=R.includes(u)?R.filter(H=>H!==u):[u,...R];I(D);try{await Ns({favoriteProviders:D,favoriteModels:C})}catch{I(R)}},[y,C]),se=s.useCallback(async u=>{const R=C,D=R.includes(u)?R.filter(H=>H!==u):[u,...R];L(D);try{await Ns({favoriteProviders:y,favoriteModels:D})}catch{L(R)}},[C,y]),V=u=>{if(u.preventDefault(),i==="agent"){if(!G)return;d({agentId:G});return}if(!j)return;const R=j.indexOf("/");if(R<=0)return;const o=j.slice(0,R),D=j.slice(R+1);d({agentId:Xe,modelProvider:o,modelId:D})},$=i==="agent"?!G:!j;return t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",onClick:r,role:"dialog","aria-modal":"true",children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:u=>u.stopPropagation(),children:[t.jsx("h3",{children:"New Chat"}),t.jsxs("div",{className:"chat-new-dialog-mode-toggle","data-testid":"chat-new-dialog-mode-toggle",children:[t.jsx("button",{type:"button",className:`chat-new-dialog-mode-btn${i==="agent"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-agent",onClick:()=>{f("agent"),K("")},children:"Agent"}),t.jsx("button",{type:"button",className:`chat-new-dialog-mode-btn${i==="model"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-model",onClick:()=>{f("model"),Z("")},children:"Model"})]}),t.jsxs("form",{onSubmit:V,children:[i==="agent"&&t.jsxs("label",{className:"chat-new-dialog-model-label",children:["Agent",S?t.jsx("div",{className:"chat-new-dialog-loading",children:"Loading agents..."}):p.length===0?t.jsx("div",{className:"chat-new-dialog-empty",children:"No agents available"}):t.jsx("div",{className:"chat-new-dialog-agent-list",children:p.map(u=>t.jsxs("button",{type:"button",className:`chat-new-dialog-agent-item${G===u.id?" chat-new-dialog-agent-item--selected":""}`,onClick:()=>Z(u.id),"data-testid":`agent-option-${u.id}`,children:[t.jsx(rt,{size:16}),t.jsx("span",{className:"chat-new-dialog-agent-name",children:u.name}),t.jsx("span",{className:"chat-new-dialog-agent-role",children:u.role})]},u.id))})]}),i==="model"&&t.jsx("div",{className:"chat-new-dialog-model-dropdown","data-testid":"chat-new-dialog-model-section",children:N?t.jsx("div",{className:"chat-new-dialog-loading",children:"Loading models..."}):t.jsx(Kn,{models:v,value:j,onChange:K,label:"Model",placeholder:"Select a model",favoriteProviders:y,onToggleFavorite:w,favoriteModels:C,onToggleModelFavorite:se})}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{type:"button",className:"btn btn-sm",onClick:r,children:"Cancel"}),t.jsx("button",{type:"submit",className:"btn btn-sm btn-primary",disabled:$,children:"Create"})]})]})]})})}const Vt=s.memo(function({message:r,forcePlain:d,agentName:i,hideAssistantIdentity:f,showAssistantModelTag:p,activeModelTag:m,activeModelProvider:S,activeSessionId:F,mentionAgentsByName:G,roomContext:Z,copyAction:v}){const U=r.role==="assistant",N=U?r.failureInfo:void 0,te=U&&(!f||!!N),j=s.useMemo(()=>{if(U)return null;const I=r.content,C=/@([\w-]+)/g,L=[];let w=0,se=C.exec(I);for(;se;){const[V,$=""]=se,u=se.index;u>w&&L.push(I.slice(w,u));const R=$.replace(/_/g," ").toLowerCase(),o=G.get(R);if(o){const D=!!(Z&&!Z.memberIds.has(o.id)),H=D?`Not a member of ${Z?.roomName}`:void 0;L.push(t.jsxs("span",{className:`chat-mention-chip${D?" chat-mention-chip--non-member":""}`,title:H,"aria-label":H,children:["@",o.name.replace(/\s+/g,"_")]},`${o.id}-${u}`))}else L.push(V);w=u+V.length,se=C.exec(I)}return w<I.length&&L.push(I.slice(w)),L.length===0?I:L},[U,r.content,G,Z]),K=s.useMemo(()=>{const I=r.attachments;if(!I||I.length===0)return null;const C=r.roomId?`/api/chat/rooms/${encodeURIComponent(r.roomId)}/attachments/`:F?`/api/chat/sessions/${encodeURIComponent(F)}/attachments/`:null;return C?t.jsx("div",{className:"chat-message-attachments",children:I.map(L=>{const w=L.mimeType.startsWith("image/"),se=L.id||L.filename,V=`${C}${encodeURIComponent(L.filename)}`;return w?t.jsx("a",{className:"chat-message-attachment-link","data-testid":"chat-message-attachment",href:V,target:"_blank",rel:"noopener noreferrer",children:t.jsx("img",{className:"chat-message-attachment",src:V,alt:L.originalName})},se):t.jsxs("a",{className:"chat-message-attachment-file","data-testid":"chat-message-attachment",href:V,target:"_blank",rel:"noopener noreferrer",children:[t.jsx(Hn,{size:14}),t.jsx("span",{children:L.originalName})]},se)})}):null},[r.attachments,r.roomId,F]),y=s.useMemo(()=>U?N?t.jsxs("div",{className:"chat-message-content chat-message-content--failure",children:[t.jsxs("div",{className:"chat-message-failure-summary-row",children:[t.jsx("span",{className:"status-dot status-dot--error","aria-hidden":"true"}),t.jsx("span",{className:"chat-message-failure-label",children:"Response failed"})]}),t.jsx("div",{className:"chat-message-failure-summary",children:N.summary}),(N.errorClass||N.code)&&t.jsxs("div",{className:"chat-message-failure-badges",children:[N.errorClass&&t.jsx("span",{className:"chat-message-failure-badge",children:N.errorClass}),N.code&&t.jsx("span",{className:"chat-message-failure-badge",children:N.code})]}),(N.detail||N.reference)&&t.jsxs("details",{className:"chat-message-failure-details",children:[t.jsxs("summary",{children:[t.jsx(On,{size:14,"aria-hidden":"true"}),t.jsx("span",{children:"Failure details"})]}),N.detail&&t.jsx("pre",{className:"chat-message-failure-detail",children:wt(N.detail)}),sa(N.reference)]})]}):d?t.jsx("div",{className:"chat-message-content chat-message-content--plain",children:r.content}):t.jsx("div",{className:"chat-message-content chat-message-content--markdown",children:t.jsx(Fs,{remarkPlugins:[Ls],components:Us,children:r.content})}):null,[N,d,U,r.content]);return t.jsxs("div",{className:`chat-message chat-message--${r.role}${N?" chat-message--failure":""}`,"data-testid":`chat-message-${r.id}`,children:[te&&t.jsxs("div",{className:"chat-message-avatar",children:[S?t.jsx(at,{provider:S,size:"sm"}):t.jsx(rt,{size:14}),t.jsx("span",{children:i}),p&&m&&t.jsx("span",{className:"chat-model-tag",children:m})]}),U?y:t.jsx("div",{className:"chat-message-content",children:j}),!N&&v,_s(r.toolCalls),r.thinkingOutput&&t.jsxs("details",{className:"chat-message-thinking",children:[t.jsx("summary",{children:"Thinking"}),t.jsx("pre",{className:"chat-message-thinking-content",children:wt(r.thinkingOutput)})]}),K,t.jsx("div",{className:"chat-message-time",children:zs(r.createdAt)})]})});function ga({projectId:n,addToast:r,experimentalFeatures:d}){const{activeSession:i,sessionsLoading:f,messages:p,messagesLoading:m,isStreaming:S,streamingText:F,streamingThinking:G,streamingToolCalls:Z,selectSession:v,createSession:U,archiveSession:N,deleteSession:te,sendMessage:j,stopStreaming:K,pendingMessage:y,clearPendingMessage:I,searchQuery:C,setSearchQuery:L,filteredSessions:w}=qn(n,r),[se,V]=s.useState(!1),$=d?.chatRooms===!0,[u,R]=s.useState(()=>{try{if(localStorage.getItem(Wt)==="rooms"&&$)return"rooms"}catch{}return"direct"}),o=jn(n,r),{isUnread:D,markRead:H}=Cn(n),[g,B]=s.useState(()=>{const e=Es(u,u==="rooms"?o.activeRoom?.id:i?.id);return Ts(e)}),[ue,me]=s.useState(null),[ye,we]=s.useState(null),[ee,O]=s.useState(null),[Me,ie]=s.useState(!0),[Se,he]=s.useState(na),[it,ve]=s.useState(!1),[W,He]=s.useState(new Map),[ot,ne]=s.useState({provider:null,modelId:null}),[ae,Le]=s.useState([]),[jt,ct]=s.useState(!0),[Re,Ae]=s.useState(!1),[Ye,ze]=s.useState(""),[_e,Ee]=s.useState(0),[je,Te]=s.useState(""),[l,h]=s.useState(!1),[x,k]=s.useState(0),[Y,E]=s.useState(-1),[q,X]=s.useState(!1),[A,P]=s.useState([]),[J,T]=s.useState(!1),[Q,oe]=s.useState(!1),[ce,qt]=s.useState({}),[lt,Oe]=s.useState(!1),[dt,Je]=s.useState(!1),{pushNav:Xt}=Nn(),[,Qe]=s.useState(!1),[Hs,Os]=s.useState({top:0,left:0}),z=kn({projectId:n}),Ct=s.useCallback(e=>{if(!e||!z.mentionActive)return;const a=e.getBoundingClientRect();Os({top:a.top-260,left:a.left+8})},[z.mentionActive]),Yt=s.useRef(null),Jt=s.useRef(null),Qt=s.useRef(null),Ie=s.useRef(!1),Nt=s.useRef(null),Zt=s.useRef(null),De=s.useRef(null),$e=s.useRef(null),Ce=s.useRef(null),pe=s.useRef(null),fe=s.useRef(null),es=s.useRef(null),ts=s.useRef([]),Ze=s.useRef(0),et=s.useRef(new Map),M=Mn()==="mobile";s.useEffect(()=>{i?.id&&H("direct",i.id,i.lastMessageAt??i.updatedAt)},[i?.id,i?.lastMessageAt,i?.updatedAt,H]),s.useEffect(()=>{o.activeRoom?.id&&H("room",o.activeRoom.id,o.activeRoom.updatedAt)},[o.activeRoom?.id,o.activeRoom?.updatedAt,H]),s.useEffect(()=>{if(!i?.id||p.length===0)return;const e=p[p.length-1];H("direct",i.id,e?.createdAt??i.lastMessageAt??i.updatedAt)},[i?.id,i?.lastMessageAt,i?.updatedAt,H,p]),s.useEffect(()=>{if(!o.activeRoom?.id||o.messages.length===0)return;const e=o.messages[o.messages.length-1];H("room",o.activeRoom.id,e?.createdAt??o.activeRoom.updatedAt)},[H,o.activeRoom?.id,o.activeRoom?.updatedAt,o.messages]),s.useEffect(()=>{try{const e=localStorage.getItem(As);if(!e)return;const a=Number.parseInt(e,10);if(Number.isNaN(a))return;const c=Math.max(vt,Math.min(xt,a));he(c)}catch{}},[]),s.useEffect(()=>{try{const e=localStorage.getItem(Wt);if(e==="direct"){R("direct");return}e==="rooms"&&$&&R("rooms")}catch{}},[$]),s.useEffect(()=>{if(!$&&u==="rooms"){R("direct");return}try{localStorage.setItem(Wt,u)}catch{}},[$,u]);const le=Es(u,u==="rooms"?o.activeRoom?.id:i?.id),kt=s.useRef(le);s.useEffect(()=>{le!==kt.current&&(kt.current=le,B(Ts(le)))},[le]),s.useEffect(()=>{if(!(!le||kt.current!==le))try{if(g){localStorage.setItem(le,g);return}localStorage.removeItem(le)}catch{}},[le,g]);const de=$&&u==="rooms"&&!!o.activeRoom,{keyboardOverlap:ut,viewportHeight:ss,viewportOffsetTop:ns,keyboardOpen:tt}=Rn({enabled:M&&(!!i||de)}),as=ss!==null&&(ut>0||ns>0),rs=tt&&as?{"--keyboard-overlap":`${ut}px`,"--vv-offset-top":`${ns}px`,"--vv-height":`${ss}px`}:{},is=`chat-thread${tt&&as?" chat-thread--keyboard-active":""}`,be=s.useMemo(()=>{const e=Ye.trim().toLowerCase();return(e?ae.filter(c=>c.name.toLowerCase().includes(e)):ae).slice(0,10)},[ae,Ye]),Ge=s.useMemo(()=>Array.from(W.values()),[W]),Ne=s.useMemo(()=>!$||u!=="rooms"||!o.activeRoom?null:{roomId:o.activeRoom.id,roomName:o.activeRoom.name,memberIds:new Set(o.activeRoomMembers.map(e=>e.agentId))},[$,u,o.activeRoom,o.activeRoomMembers]),Ue=s.useMemo(()=>{const e=Ge.filter(b=>An(b.name,je));if(!Ne)return e;const a=e.filter(b=>Ne.memberIds.has(b.id));if(je.trim().length===0)return a;const c=e.filter(b=>!Ne.memberIds.has(b.id));return[...a,...c]},[Ge,je,Ne]),Mt=s.useMemo(()=>{const e=new Map;for(const a of Ge)e.set(a.name.toLowerCase(),a);return e},[Ge]);s.useEffect(()=>{Ee(0)},[be]),s.useEffect(()=>{k(0)},[je,l]),s.useEffect(()=>()=>{Ce.current!==null&&window.clearTimeout(Ce.current)},[]);const os=s.useCallback(()=>{const e=pe.current;if(!e)return;const c=e.scrollTop+e.clientHeight>=e.scrollHeight-50;oe(!c),Ie.current=!c},[]),ge=s.useCallback(e=>{if(!e.isConnected)return;let a=0,c=0,b=-1;const _=6,re=()=>{if(e.isConnected){if(e.scrollTop=e.scrollHeight,e.scrollHeight===b?c+=1:(c=0,b=e.scrollHeight),a+=1,a>=_||c>=2){oe(!1),Ie.current=!1;return}window.requestAnimationFrame(re)}};re()},[]),Ke=s.useCallback(()=>{const e=pe.current;e&&ge(e)},[ge]);s.useLayoutEffect(()=>{$e.current!==null&&(window.clearTimeout($e.current),$e.current=null);const e=de?o.activeRoom?.id??null:i?.id??null;if(!e){Nt.current=null;return}const a={threadId:e,loaded:de?!o.messagesLoading:!m,hasMessages:de?o.messages.length>0:p.length>0},c=Nt.current,b=c?.threadId!==e,_=c?.threadId===e&&!c.loaded&&a.loaded,re=c?.threadId===e&&!c.hasMessages&&a.hasMessages;if(!(c===null||b||_||re))return;const ke=pe.current;if(ke)return ge(ke),de||($e.current=window.setTimeout(()=>{if($e.current=null,Ie.current)return;const Ve=pe.current;Ve&&ge(Ve)},250)),Nt.current=a,()=>{$e.current!==null&&(window.clearTimeout($e.current),$e.current=null)}},[de,o.activeRoom?.id,o.messages.length,o.messagesLoading,i?.id,p.length,m,ge]);const Gs=de?o.messages:p;s.useEffect(()=>{Ie.current||Ke()},[Gs,F,G,S,Ke]),s.useEffect(()=>{ut<=0||!pe.current||Ke()},[ut,Ke]),En(M&&tt),s.useEffect(()=>{const e=()=>me(null);if(ue)return document.addEventListener("click",e),()=>document.removeEventListener("click",e)},[ue]),s.useEffect(()=>{if(!M||!tt)return;const e=a=>{a.target?.closest(".chat-messages")||a.preventDefault()};return document.addEventListener("touchmove",e,{passive:!1}),()=>{document.removeEventListener("touchmove",e)}},[M,tt]),s.useEffect(()=>{if(!M||!i)return;const e=()=>{const a=fe.current;a&&document.activeElement===a&&(a.blur(),window.setTimeout(()=>{a.focus({preventScroll:!0})},0))};return document.addEventListener("visibilitychange",e),window.addEventListener("pageshow",e),()=>{document.removeEventListener("visibilitychange",e),window.removeEventListener("pageshow",e)}},[M,i]),s.useEffect(()=>{const e=Zt.current;if(Zt.current=u,u!=="direct"||e!==null&&e!=="rooms")return;const a=pe.current;a&&(ge(a),Ie.current=!1,oe(!1))},[u,ge]),s.useEffect(()=>{if(!i&&!de||de&&!M)return;const e=()=>{const c=pe.current;c&&(ge(c),Ie.current=!1,oe(!1),De.current!==null&&(window.clearTimeout(De.current),De.current=null),De.current=window.setTimeout(()=>{if(De.current=null,Ie.current)return;const b=pe.current;b&&ge(b)},250))},a=()=>{document.visibilityState==="visible"&&e()};return document.addEventListener("visibilitychange",a),window.addEventListener("pageshow",e),()=>{document.removeEventListener("visibilitychange",a),window.removeEventListener("pageshow",e),De.current!==null&&(window.clearTimeout(De.current),De.current=null)}},[M,i,de,ge]),s.useEffect(()=>{if(de||typeof ResizeObserver>"u")return;const e=pe.current;if(!e)return;const a=new ResizeObserver(()=>{Ie.current||ge(e)});return a.observe(e),()=>{a.disconnect()}},[de,ge,i?.id,u]),s.useEffect(()=>{let e=!1;const a=n;return St(void 0,n).then(c=>{if(e||a!==n)return;const b=new Map;for(const _ of c)b.set(_.id,_);He(b)}).catch(()=>{}),()=>{e=!0}},[n]),s.useEffect(()=>{let e=!1;return Ps().then(a=>{e||ne({provider:a.defaultProvider??null,modelId:a.defaultModelId??null})}).catch(()=>{e||ne({provider:null,modelId:null})}),()=>{e=!0}},[]),s.useEffect(()=>{let e=!1;return ct(!0),Tn(n).then(a=>{e||Le(a)}).catch(()=>{e||Le([])}).finally(()=>{e||ct(!1)}),()=>{e=!0}},[n]),s.useEffect(()=>{ts.current=A},[A]),s.useEffect(()=>()=>{for(const e of ts.current)e.previewUrl&&URL.revokeObjectURL(e.previewUrl);for(const e of et.current.values())window.clearTimeout(e);et.current.clear()},[]);const mt=s.useCallback(e=>{if(!e||e.length===0)return;const a=[];for(const c of Array.from(e)){if(!ra.includes(c.type))continue;const b=c.type.startsWith("image/");a.push({file:c,previewUrl:b?URL.createObjectURL(c):""})}a.length>0&&P(c=>[...c,...a])},[]),Ks=s.useCallback(e=>{P(a=>{const c=a[e];return c?.previewUrl&&URL.revokeObjectURL(c.previewUrl),a.filter((b,_)=>_!==e)})},[]),Bs=s.useCallback(e=>{const a=e.clipboardData?.files;if(!a||a.length===0)return;const c=Array.from(a).filter(b=>b.type.startsWith("image/"));c.length!==0&&mt(c)},[mt]),Ws=s.useCallback(async e=>{try{await U(e),V(!1),M&&ie(!1)}catch{r("Failed to create chat session","error")}},[U,r,M]),xe=s.useCallback(e=>{const a=e??fe.current;a&&(a.style.height="auto",a.style.height=`${Qn(a.scrollHeight)}px`)},[]),cs=s.useCallback(e=>{fe.current=e,e&&xe(e)},[xe]);s.useLayoutEffect(()=>{xe()},[u,g,i?.id,o.activeRoom?.id,xe]);const Be=s.useCallback(()=>{if(B(""),le)try{localStorage.removeItem(le)}catch{}Ae(!1),ze(""),h(!1),Te(""),E(-1),P(e=>{for(const a of e)a.previewUrl&&URL.revokeObjectURL(a.previewUrl);return[]})},[le]),Rt=s.useCallback(()=>{const e=g.trim(),a=A.map(c=>c.file);if(!(!e&&a.length===0||!i)){if(e==="/clear"||e==="/new"){Be(),I(),K(),U({agentId:i.agentId,modelProvider:i.modelProvider??void 0,modelId:i.modelId??void 0}).catch(()=>{r("Failed to clear conversation","error")});return}Be(),j(e,a)}},[g,A,i,Be,K,I,U,r,j]),At=s.useCallback(async()=>{const e=g.trim();if(e){if($&&u==="rooms"){if(!o.activeRoom)return;if(e==="/clear"||e==="/new"){Be();try{await o.clearRoom(o.activeRoom.id)}catch{r("Failed to clear room conversation","error")}return}const a=g;Be();try{await o.sendRoomMessage(e,{files:A.map(c=>c.file)})}catch(c){B(a);const b=c instanceof Error&&c.message.trim()?c.message:"Failed to send room message";r(b,"error")}return}Rt()}},[g,A,$,u,o,o.clearRoom,Be,r,Rt]),Et=s.useCallback(e=>{B(a=>{const c=Is(a);if(!c)return a;const b=`/skill:${e.name} `,_=a.slice(0,c.start)+b+a.slice(c.end);return window.requestAnimationFrame(()=>{fe.current&&(xe(fe.current),fe.current.focus())}),_}),Ae(!1),ze(""),Ee(0)},[xe]),ht=s.useCallback(e=>{const a=fe.current;if(!a||Y<0)return;const c=a.selectionStart??Ze.current,b=a.selectionEnd??c,_=Math.max(c,b),re=Math.min(Y,_),ke=`${`@${e.name.replace(/\s+/g,"_")}`} `,Ve=g.slice(0,re)+ke+g.slice(_),qe=re+ke.length;B(Ve),h(!1),Te(""),k(0),E(-1),window.requestAnimationFrame(()=>{fe.current&&(xe(fe.current),fe.current.focus(),fe.current.setSelectionRange(qe,qe))})},[Y,g,xe]),ls=s.useCallback(e=>{if(Ze.current=e.currentTarget.selectionStart??Ze.current,z.mentionActive&&z.files.length>0){if(z.handleKeyDown(e,g),e.key==="Enter"||e.key==="Tab"){const a=z.files[z.selectedIndex];if(a){const c=z.selectFile(a,g);B(c),z.dismissMention(),Qe(!1)}}return}if(l&&e.key==="ArrowDown"){e.preventDefault(),Ue.length>0&&k(a=>(a+1)%Ue.length);return}if(l&&e.key==="ArrowUp"){e.preventDefault(),Ue.length>0&&k(a=>a===0?Ue.length-1:a-1);return}if(l&&e.key==="Enter"){e.preventDefault();const a=Ue[x]??Ue[0];a&&ht(a);return}if(l&&e.key==="Escape"){e.preventDefault(),h(!1),Te(""),E(-1);return}if(Re&&e.key==="ArrowDown"){e.preventDefault(),be.length>0&&Ee(a=>(a+1)%be.length);return}if(Re&&e.key==="ArrowUp"){e.preventDefault(),be.length>0&&Ee(a=>a===0?be.length-1:a-1);return}if(Re&&(e.key==="Enter"||e.key==="Tab")&&be.length>0){e.preventDefault();const a=be[_e]??be[0];a&&Et(a);return}if(Re&&e.key==="Escape"){e.preventDefault(),Ae(!1);return}e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),At())},[l,Ue,x,ht,Re,be,_e,Et,At,z,g]),ft=s.useCallback((e,a)=>{const c=ia(e,a);if(c){h(!0),Te(c.filter),E(c.start);return}h(!1),Te(""),E(-1)},[]),ds=s.useCallback(e=>{const a=e.target,c=a.value,b=a.selectionStart??c.length;xe(a),Ze.current=b,B(c);const _=Is(c);_?(Ae(!0),ze(_.filter)):(Ae(!1),ze("")),ft(c,b),z.detectMention(c,b),Qe(z.mentionActive),z.mentionActive&&Ct(a)},[ft,xe]),gt=s.useCallback(e=>{const a=e.currentTarget,c=a.selectionStart??a.value.length;Ze.current=c,ft(a.value,c),z.detectMention(a.value,c),Qe(z.mentionActive),z.mentionActive&&Ct(a)},[ft,z,Ct]),us=s.useCallback(e=>{e.key!=="Escape"&>(e)},[gt]),ms=s.useCallback(()=>{Ce.current!==null&&window.clearTimeout(Ce.current),Ce.current=window.setTimeout(()=>{Ae(!1),h(!1),Te(""),E(-1),Qe(!1),z.dismissMention(),Ce.current=null},120)},[z]),hs=s.useCallback(()=>{Ce.current!==null&&(window.clearTimeout(Ce.current),Ce.current=null),typeof window<"u"&&window.innerWidth<=768&&queueMicrotask(()=>{(window.scrollY!==0||window.scrollX!==0)&&window.scrollTo(0,0)})},[]),Vs=s.useCallback(async e=>{me(null);try{await N(e),r("Conversation archived","success")}catch{r("Failed to archive conversation","error")}},[N,r]),qs=s.useCallback(async e=>{we(null),me(null);try{await te(e),r("Conversation deleted","success")}catch{r("Failed to delete conversation","error")}},[te,r]),st=s.useCallback(e=>{try{localStorage.setItem(As,String(e))}catch{}},[]),Xs=s.useCallback(e=>{if(M)return;e.preventDefault(),e.stopPropagation();const a=e.currentTarget;typeof a.setPointerCapture=="function"&&a.setPointerCapture(e.pointerId);const c=e.clientX,b=Se;let _=b;document.body.style.userSelect="none";const re=ke=>{const Ve=ke.clientX-c,qe=Math.max(vt,Math.min(xt,b+Ve));_=qe,he(qe),st(qe)},We=ke=>{typeof a.releasePointerCapture=="function"&&a.releasePointerCapture(ke.pointerId),document.body.style.userSelect="",document.removeEventListener("pointermove",re),document.removeEventListener("pointerup",We),st(_)};document.addEventListener("pointermove",re),document.addEventListener("pointerup",We)},[M,st,Se]),Ys=s.useCallback(e=>{if(M||e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;e.preventDefault();const a=e.shiftKey?50:10,c=e.key==="ArrowLeft"?-a:a,b=Math.max(vt,Math.min(xt,Se+c));he(b),st(b)},[M,st,Se]),fs=s.useCallback(e=>{const a=w.find(c=>c.id===e);H("direct",e,a?.lastMessageAt??a?.updatedAt),v(e),Oe(!1),M&&ie(!1)},[w,M,H,v]),Tt=s.useCallback(()=>{v(""),ie(!0),Oe(!1)},[v]),It=s.useCallback(()=>{o.selectRoom(null),ie(!0),Oe(!1)},[o]),Js=()=>t.jsxs("div",{className:"chat-empty-state",children:[t.jsx(Gn,{size:48,strokeWidth:1.5}),t.jsx("h2",{children:"Start a new conversation"}),t.jsxs("button",{className:"btn btn-primary",onClick:()=>V(!0),children:[t.jsx(nt,{size:16}),"New Chat"]})]}),Dt=Ds(i,i?.agentId?W.get(i.agentId)??null:null,ot),Pe=Rs(Dt?.provider,Dt?.modelId),Fe=Dt?.provider??null,$t=!!(i||S||p.length>0),pt=u==="rooms"?de:!!i,gs=s.useRef(pt);s.useEffect(()=>{const e=gs.current;gs.current=pt,M&&(e||!pt||Xt({type:"view",revert:u==="rooms"?It:Tt}))},[u,Tt,It,pt,M,Xt]);const Pt=i?.agentId===Xe?Pe??"Fusion":i?.title||W.get(i?.agentId??"")?.name||i?.agentId||"Chat",ps=!!(Pe&&Pe!==Pt),Qs=M&&u==="direct"&&!!i,Ft=W.get(i?.agentId??"")?.name||(i?.agentId===Xe?Pe??"Fusion":i?.agentId?.slice(0,30)??"Fusion"),Lt=!1,zt=i?.agentId===Xe,Zs=y.length>50?`${y.slice(0,50)}…`:y,en=s.useCallback(()=>{X(e=>!e)},[]);s.useEffect(()=>{if(!lt)return;const e=a=>{Jt.current?.contains(a.target)||Oe(!1)};return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[lt]),s.useEffect(()=>{if(!dt)return;const e=c=>{Qt.current?.contains(c.target)||Je(!1)},a=c=>{c.key==="Escape"&&Je(!1)};return document.addEventListener("mousedown",e),document.addEventListener("keydown",a),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("keydown",a)}},[dt]),s.useEffect(()=>{(!M||u!=="direct"||Me)&&Oe(!1)},[M,u,Me]),s.useEffect(()=>{Je(!1)},[o.activeRoom?.id]);const _t=s.useCallback((e,a)=>{const c=et.current.get(e);c&&window.clearTimeout(c),qt(_=>({..._,[e]:a}));const b=window.setTimeout(()=>{qt(_=>{const{[e]:re,...We}=_;return We}),et.current.delete(e)},2e3);et.current.set(e,b)},[]),bs=s.useCallback(async(e,a)=>{try{if(!navigator.clipboard?.writeText)throw new Error("Clipboard API unavailable");await navigator.clipboard.writeText(a),_t(e,"success")}catch{_t(e,"error")}},[_t]),tn=s.useCallback((e,a=!1)=>a?t.jsx("div",{className:"chat-message-content chat-message-content--plain",children:e}):t.jsx("div",{className:"chat-message-content chat-message-content--markdown",children:t.jsx(Fs,{remarkPlugins:[Ls],components:Us,children:e})}),[]),Ut=i?.agentId===Xe,Ht=s.useCallback((e,a,c)=>t.jsx("button",{type:"button",className:`btn-icon chat-message-copy-action${ce[e]==="success"?" chat-message-copy-action--success":""}${ce[e]==="error"?" chat-message-copy-action--error":""}`,"data-testid":c??`chat-copy-response-${e}`,"aria-label":ce[e]==="success"?"Response copied":ce[e]==="error"?"Copy failed":"Copy response",onClick:()=>{bs(e,a)},children:ce[e]==="success"?t.jsx(In,{size:14}):t.jsx(Dn,{size:14})}),[ce,bs]);return t.jsxs("div",{className:"chat-view",children:[t.jsxs("div",{className:`chat-sidebar${Me?"":" chat-sidebar--hidden"}`,style:M?void 0:{width:`${Se}px`},children:[$&&t.jsxs("div",{className:"chat-sidebar-scope-toggle",role:"tablist","data-testid":"chat-sidebar-scope-toggle",children:[t.jsx("button",{type:"button",role:"tab",className:`chat-sidebar-scope-btn${u==="direct"?" chat-sidebar-scope-btn--active":""}`,"aria-selected":u==="direct","data-testid":"chat-sidebar-scope-direct",onClick:()=>R("direct"),children:"Direct"}),t.jsx("button",{type:"button",role:"tab",className:`chat-sidebar-scope-btn${u==="rooms"?" chat-sidebar-scope-btn--active":""}`,"aria-selected":u==="rooms","data-testid":"chat-sidebar-scope-rooms",onClick:()=>R("rooms"),children:"Rooms"})]}),!$||u==="direct"?t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"chat-sidebar-search-container",children:t.jsxs("div",{className:"chat-sidebar-search-wrapper",children:[t.jsx($n,{size:14,className:"chat-sidebar-search-icon"}),t.jsx("input",{type:"text",className:"chat-sidebar-search",placeholder:"Search conversations...",value:C,onChange:e=>L(e.target.value),"data-testid":"chat-search-input"})]})}),t.jsx("div",{className:"chat-session-list chat-sidebar-list",children:f?t.jsx("div",{className:"chat-empty-state chat-empty-state--padded",children:"Loading..."}):w.length===0?t.jsx("div",{className:"chat-empty-state chat-empty-state--padded",children:"No conversations yet"}):w.map(e=>{const a=i?.id===e.id,c=!a&&D("direct",e.id,e.lastMessageAt??e.updatedAt),b=Ds(e,W.get(e.agentId)??null,ot),_=Rs(b?.provider,b?.modelId)??"Fusion";return t.jsxs("div",{className:`chat-session-item${a?" chat-session-item--active":""}`,onClick:()=>fs(e.id),onContextMenu:re=>{re.preventDefault(),me({sessionId:e.id,x:re.clientX,y:re.clientY})},"data-testid":`chat-session-${e.id}`,children:[t.jsx("button",{className:"chat-session-delete-btn",onClick:re=>{re.stopPropagation(),we(e.id)},"data-testid":"chat-session-delete-btn","aria-label":"Delete conversation",children:t.jsx(Gt,{size:14})}),t.jsxs("div",{className:"chat-session-title",children:[e.title||"Untitled",c?t.jsx("span",{className:"chat-unread-dot","data-testid":`chat-unread-dot-${e.id}`,"aria-label":"Unread messages"}):null]}),t.jsx("div",{className:"chat-session-preview",children:e.lastMessagePreview||"No messages"}),t.jsxs("div",{className:"chat-session-meta",children:[t.jsxs("span",{className:"chat-session-meta-model",children:[b?.provider?t.jsx(at,{provider:b.provider,size:"sm"}):null,t.jsx("span",{children:W.get(e.agentId)?.name||(e.agentId===Xe?_:e.agentId.slice(0,30))})]}),t.jsx("span",{children:e.updatedAt?zs(e.updatedAt):""})]})]},e.id)})})]}):t.jsxs("div",{className:"chat-sidebar-rooms","data-testid":"chat-sidebar-rooms",children:[!M&&t.jsx("div",{className:"chat-sidebar-rooms-header","data-testid":"chat-sidebar-rooms-header",children:t.jsxs("button",{type:"button",className:"btn btn-sm btn-primary","data-testid":"chat-create-room-btn",onClick:()=>ve(!0),children:[t.jsx(nt,{size:14}),"Create room"]})}),o.rooms.length===0?t.jsx("div",{className:"chat-sidebar-rooms-empty","data-testid":"chat-sidebar-rooms-empty",children:"No rooms yet."}):t.jsx("div",{className:"chat-session-list chat-sidebar-list",children:o.rooms.map(e=>{const a=o.activeRoom?.id===e.id,c=!a&&D("room",e.id,e.updatedAt);return t.jsxs("div",{role:"button",tabIndex:0,className:`chat-room-item${a?" chat-room-item--active":""}`,"data-testid":`chat-room-item-${e.slug}`,onClick:()=>{H("room",e.id,e.updatedAt),o.selectRoom(e.id),M&&ie(!1)},onKeyDown:b=>{(b.key==="Enter"||b.key===" ")&&(b.preventDefault(),H("room",e.id,e.updatedAt),o.selectRoom(e.id),M&&ie(!1))},children:[t.jsxs("span",{className:"chat-room-item-details",children:[t.jsxs("span",{className:"chat-room-item-name-row",children:[t.jsxs("span",{className:"chat-room-item-name",children:["#",e.name]}),c?t.jsx("span",{className:"chat-unread-dot","data-testid":`chat-unread-dot-${e.id}`,"aria-label":"Unread messages"}):null]}),a?t.jsxs("span",{className:"chat-room-item-meta",children:[o.activeRoomMembers.length," ",o.activeRoomMembers.length===1?"member":"members"]}):null]}),t.jsx("button",{type:"button",className:"btn-icon chat-room-item-delete","data-testid":`chat-room-delete-${e.slug}`,"aria-label":`Delete room ${e.name}`,onClick:b=>{b.stopPropagation(),O(e.id)},children:t.jsx(Gt,{size:14})})]},e.id)})})]}),u==="rooms"?M?t.jsx("div",{className:"chat-sidebar-footer",children:t.jsxs("button",{type:"button",className:"btn btn-sm btn-primary chat-sidebar-footer-btn","data-testid":"chat-create-room-btn",onClick:()=>ve(!0),children:[t.jsx(nt,{size:14}),"Create room"]})}):null:t.jsx("div",{className:"chat-sidebar-footer",children:t.jsxs("button",{className:"btn btn-sm btn-primary chat-sidebar-footer-btn",onClick:()=>V(!0),"data-testid":"chat-new-btn",children:[t.jsx(nt,{size:14}),"New Chat"]})})]}),!M&&Me&&t.jsx("div",{className:"chat-sidebar-resize-handle",role:"separator","aria-orientation":"vertical","aria-valuemin":vt,"aria-valuemax":xt,"aria-valuenow":Se,"aria-label":"Resize chat sidebar",tabIndex:0,onPointerDown:Xs,onKeyDown:Ys}),ue&&t.jsxs("div",{className:"chat-session-context-menu",style:{top:ue.y,left:ue.x},onClick:e=>e.stopPropagation(),children:[t.jsxs("button",{onClick:()=>Vs(ue.sessionId),"data-testid":"chat-context-archive",children:[t.jsx(Pn,{size:14}),"Archive"]}),t.jsxs("button",{onClick:()=>{me(null),we(ue.sessionId)},"data-testid":"chat-context-delete",children:[t.jsx(Gt,{size:14}),"Delete"]})]}),ye&&t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",onClick:()=>we(null),children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{children:"Delete Conversation?"}),t.jsx("p",{className:"chat-view-delete-dialog-copy",children:"This action cannot be undone. All messages in this conversation will be permanently deleted."}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{className:"btn btn-sm",onClick:()=>we(null),children:"Cancel"}),t.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>void qs(ye),children:"Delete"})]})]})}),$&&ee&&t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",onClick:()=>O(null),children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{children:"Delete Room?"}),t.jsx("p",{className:"chat-view-delete-dialog-copy",children:"This action cannot be undone. This room and all its messages will be permanently deleted."}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{className:"btn btn-sm",onClick:()=>O(null),children:"Cancel"}),t.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>{(async()=>{try{await o.deleteRoom(ee),O(null)}catch{r("Failed to delete room","error")}})()},children:"Delete"})]})]})}),$&&u==="rooms"?t.jsxs("div",{className:is,style:rs,children:[o.activeRoom?t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"chat-room-thread-header",children:[M&&t.jsx("button",{className:"btn-icon",onClick:It,"data-testid":"chat-back-btn",children:t.jsx(ys,{size:16})}),t.jsxs("div",{className:"chat-room-switcher-menu",ref:Qt,children:[t.jsxs("button",{type:"button",className:"chat-room-switcher-trigger","data-testid":"chat-room-switcher-trigger","aria-haspopup":"menu","aria-expanded":dt,onClick:()=>Je(e=>!e),children:[t.jsxs("span",{className:"chat-thread-header-title",children:["#",o.activeRoom.name]}),t.jsx(bt,{size:16,"aria-hidden":"true"})]}),dt&&t.jsx("div",{role:"menu",className:"chat-room-switcher-dropdown","data-testid":"chat-room-switcher-dropdown",children:o.rooms.map(e=>t.jsxs("button",{type:"button",role:"menuitem",className:`chat-room-switcher-option${e.id===o.activeRoom?.id?" chat-room-switcher-option--active":""}`,"data-testid":`chat-room-switcher-option-${e.id}`,onClick:()=>{H("room",e.id,e.updatedAt),o.selectRoom(e.id),Je(!1)},children:["#",e.name]},e.id))})]}),t.jsx("div",{className:"chat-room-thread-members",children:o.activeRoomMembers.map(e=>t.jsx($s,{agent:W.get(e.agentId)??{id:e.agentId,name:e.agentId.slice(0,30)}},e.agentId))})]}),t.jsxs("div",{className:"chat-messages",ref:pe,onScroll:os,children:[o.messagesLoading?t.jsx("div",{className:"chat-empty-state",children:"Loading messages..."}):o.messages.length===0?t.jsx("div",{className:"chat-empty-state",children:"No messages yet. Start the conversation!"}):o.messages.map(e=>{const a=e.senderAgentId?W.get(e.senderAgentId)?.name??e.senderAgentId.slice(0,30):"You",c={id:e.id,sessionId:e.roomId,role:e.role,content:e.content,thinkingOutput:e.thinkingOutput??void 0,toolCalls:void 0,fallbackInfo:void 0,attachments:e.attachments,createdAt:e.createdAt};return t.jsx(Vt,{message:c,forcePlain:q,agentName:a,hideAssistantIdentity:!1,showAssistantModelTag:!1,activeModelTag:null,activeModelProvider:null,activeSessionId:o.activeRoom?.id??null,mentionAgentsByName:Mt,roomContext:Ne},e.id)}),t.jsx("div",{ref:Yt})]}),o.activeRoom&&Q&&t.jsxs("button",{type:"button",className:"btn btn-sm chat-jump-to-latest","data-testid":"chat-jump-to-latest",onClick:Ke,children:[t.jsx(bt,{size:14}),"Latest"]})]}):t.jsx("div",{className:"chat-room-empty-pane","data-testid":"chat-rooms-empty-pane",children:"Select a room or create one"}),o.activeRoom&&t.jsx("div",{className:"chat-input-area",children:t.jsxs("div",{className:"chat-input-row",children:[t.jsxs("div",{className:"chat-input-wrapper",children:[t.jsx("textarea",{ref:cs,className:"chat-input-textarea",placeholder:"Type a message...",value:g,onChange:ds,onKeyDown:ls,onKeyUp:us,onClick:gt,onBlur:ms,onFocus:hs,onTouchStart:e=>{typeof window>"u"||window.innerWidth>768||document.activeElement!==e.currentTarget&&(e.preventDefault(),e.currentTarget.focus({preventScroll:!0}))},rows:1,"data-testid":"chat-input"}),t.jsx(ws,{agents:Ge,filter:je,highlightedIndex:x,visible:l,onSelect:ht,position:"below",roomMemberIds:Ne?.memberIds,roomName:Ne?.roomName})]}),t.jsx("button",{type:"button",className:"chat-input-send",onPointerDown:e=>{e.pointerType&&e.pointerType!=="mouse"&&e.preventDefault()},onMouseDown:e=>{e.preventDefault()},onClick:()=>{At()},disabled:!g.trim(),"data-testid":"chat-send-btn",style:{touchAction:"manipulation"},children:t.jsx(Ss,{size:16})})]})})]}):t.jsxs("div",{className:is,style:rs,children:[($t||!M)&&t.jsxs("div",{className:"chat-thread-header",children:[M&&$t&&t.jsx("button",{className:"btn-icon",onClick:Tt,"data-testid":"chat-back-btn",children:t.jsx(ys,{size:16})}),t.jsx("div",{className:"chat-thread-header-identity","data-testid":"chat-thread-header-identity",children:Qs?t.jsxs("div",{className:"chat-mobile-session-menu",ref:Jt,children:[t.jsxs("button",{type:"button",className:"btn chat-mobile-session-trigger","data-testid":"chat-mobile-session-trigger","aria-haspopup":"menu","aria-expanded":lt,onClick:()=>Oe(e=>!e),children:[Fe?t.jsx(at,{provider:Fe,size:"md"}):t.jsx(rt,{size:16}),t.jsx("span",{className:"chat-thread-header-title",children:Pt}),ps&&t.jsx("span",{className:"chat-model-tag",children:Pe}),t.jsx(bt,{size:16,"aria-hidden":"true"})]}),lt&&t.jsx("div",{className:"chat-mobile-session-dropdown",role:"menu","data-testid":"chat-mobile-session-dropdown",children:w.map(e=>t.jsx("button",{type:"button",role:"menuitem",className:`chat-mobile-session-option${i?.id===e.id?" chat-mobile-session-option--active":""}`,"data-testid":`chat-mobile-session-option-${e.id}`,onClick:()=>fs(e.id),children:t.jsx("span",{className:"chat-mobile-session-option-title",children:e.title||"Untitled"})},e.id))})]}):t.jsxs(t.Fragment,{children:[Fe?t.jsx(at,{provider:Fe,size:"md"}):t.jsx(rt,{size:16}),t.jsx("span",{className:"chat-thread-header-title",children:Pt}),ps&&t.jsx("span",{className:"chat-model-tag",children:Pe})]})}),$t&&t.jsx("button",{type:"button",className:`chat-thread-header-render-toggle${q?" chat-thread-header-render-toggle--plain":""}`,"data-testid":"chat-thread-render-toggle","aria-label":q?"Show all messages as rendered Markdown":"Show all messages as plain text",onClick:en,children:q?t.jsx(Fn,{size:14}):t.jsx(Ln,{size:14})}),!M&&t.jsxs("button",{className:"btn btn-sm btn-primary chat-thread-header-new-chat",onClick:()=>V(!0),"data-testid":"chat-thread-new-chat-btn",children:[t.jsx(nt,{size:14}),"New Chat"]})]}),t.jsxs("div",{className:"chat-messages",ref:pe,onScroll:os,children:[S?t.jsxs(t.Fragment,{children:[p.map(e=>t.jsx(Vt,{message:e,forcePlain:q,agentName:Ft,hideAssistantIdentity:zt,showAssistantModelTag:Lt,activeModelTag:Pe,activeModelProvider:Fe,activeSessionId:i?.id??null,mentionAgentsByName:Mt,roomContext:null,copyAction:Ut&&e.role==="assistant"?Ht(e.id,e.content):void 0},e.id)),t.jsxs("div",{className:"chat-message chat-message--assistant chat-message--streaming",children:[!zt&&t.jsxs("div",{className:"chat-message-avatar",children:[Fe?t.jsx(at,{provider:Fe,size:"sm"}):t.jsx(rt,{size:14}),t.jsx("span",{children:Ft}),Lt]}),F?tn(F,q):t.jsx("div",{className:"chat-message-content chat-message-content--waiting",children:G?"Thinking…":"Connecting…"}),Ut&&F&&Ht("__streaming__",F,"chat-copy-response-streaming"),_s(Z),G&&t.jsxs("details",{className:"chat-message-thinking",children:[t.jsx("summary",{children:"Thinking"}),t.jsx("pre",{className:"chat-message-thinking-content",children:wt(G)})]}),t.jsxs("div",{className:"chat-typing-indicator",children:[t.jsx("span",{}),t.jsx("span",{}),t.jsx("span",{})]})]})]}):m?t.jsx("div",{className:"chat-empty-state",children:"Loading messages..."}):p.length===0&&!i?Js():p.length===0&&i?t.jsx("div",{className:"chat-empty-state",children:"No messages yet. Start the conversation!"}):t.jsx(t.Fragment,{children:p.map(e=>t.jsx(Vt,{message:e,forcePlain:q,agentName:Ft,hideAssistantIdentity:zt,showAssistantModelTag:Lt,activeModelTag:Pe,activeModelProvider:Fe,activeSessionId:i?.id??null,mentionAgentsByName:Mt,roomContext:null,copyAction:Ut&&e.role==="assistant"?Ht(e.id,e.content):void 0},e.id))}),t.jsx("div",{ref:Yt})]}),Q&&t.jsxs("button",{type:"button",className:"btn btn-sm chat-jump-to-latest","data-testid":"chat-jump-to-latest",onClick:Ke,children:[t.jsx(bt,{size:14}),"Latest"]}),i&&t.jsxs("div",{className:"chat-input-area",children:[t.jsx("input",{ref:es,type:"file",accept:"image/*,.txt,.json,.yaml,.yml,.log,.csv,.xml,.md",multiple:!0,style:{display:"none"},onChange:e=>{mt(e.target.files),e.target.value=""}}),Re&&t.jsx("div",{className:"chat-skill-menu","data-testid":"chat-skill-menu",role:"listbox","aria-label":"Skill suggestions",children:jt?t.jsx("div",{className:"chat-skill-menu-empty",children:"Loading skills…"}):be.length===0?t.jsx("div",{className:"chat-skill-menu-empty",children:Ye?"No skills found":"No skills available"}):be.map((e,a)=>t.jsxs("button",{type:"button",role:"option","aria-selected":a===_e,className:`chat-skill-menu-item${a===_e?" chat-skill-menu-item--highlighted":""}`,onMouseDown:c=>c.preventDefault(),onMouseEnter:()=>Ee(a),onClick:()=>Et(e),children:[t.jsx("span",{className:"chat-skill-menu-item-name",children:e.name}),t.jsx("span",{className:"chat-skill-menu-item-description",title:e.relativePath,children:e.relativePath})]},e.id))}),A.length>0&&t.jsx("div",{className:"chat-attachment-previews","data-testid":"chat-attachment-previews",children:A.map((e,a)=>t.jsxs("div",{className:"chat-attachment-preview","data-testid":`chat-attachment-preview-${a}`,children:[e.previewUrl?t.jsx("img",{src:e.previewUrl,alt:e.file.name}):t.jsx("span",{className:"chat-attachment-preview-name",children:e.file.name}),t.jsx("button",{type:"button",className:"chat-attachment-remove",onClick:()=>Ks(a),"data-testid":`chat-attachment-remove-${a}`,"aria-label":`Remove ${e.file.name}`,children:"×"})]},e.previewUrl||`${e.file.name}-${a}`))}),t.jsxs("div",{className:"chat-input-row",children:[t.jsx("button",{type:"button",className:"btn-icon chat-attach-btn","data-testid":"chat-attach-btn","aria-label":"Attach files",onClick:()=>es.current?.click(),children:t.jsx(zn,{size:16})}),t.jsxs("div",{className:`chat-input-wrapper${J?" chat-input-wrapper--dragover":""}`,onDragOver:e=>{e.preventDefault(),T(!0)},onDragLeave:()=>T(!1),onDrop:e=>{e.preventDefault(),T(!1),mt(e.dataTransfer.files)},children:[t.jsx("textarea",{ref:cs,className:"chat-input-textarea",placeholder:"Type a message...",value:g,onChange:ds,onKeyDown:ls,onKeyUp:us,onClick:gt,onBlur:ms,onFocus:hs,onPaste:Bs,onTouchStart:e=>{typeof window>"u"||window.innerWidth>768||document.activeElement!==e.currentTarget&&(e.preventDefault(),e.currentTarget.focus({preventScroll:!0}))},rows:1,"data-testid":"chat-input"}),t.jsx(ws,{agents:Ge,filter:je,highlightedIndex:x,visible:l,onSelect:ht,position:"below",roomMemberIds:Ne?.memberIds,roomName:Ne?.roomName}),t.jsx(_n,{visible:z.mentionActive&&!l,position:Hs,files:z.files,selectedIndex:z.selectedIndex,onSelect:e=>{const a=z.selectFile(e,g);B(a),z.dismissMention(),Qe(!1),fe.current?.focus()},loading:z.loading}),y&&t.jsxs("div",{className:"chat-pending-message","data-testid":"chat-pending-indicator",children:[t.jsx("span",{children:`Queued: ${Zs}`}),t.jsx("button",{type:"button",className:"chat-pending-message-dismiss","aria-label":"Dismiss queued message","data-testid":"chat-pending-dismiss",onClick:I,children:"×"})]})]}),S?t.jsx("button",{className:"chat-input-stop",onClick:K,"aria-label":"Stop generation","data-testid":"chat-stop-btn",children:t.jsx(Un,{size:14})}):t.jsx("button",{type:"button",className:"chat-input-send",onPointerDown:e=>{e.pointerType&&e.pointerType!=="mouse"&&e.preventDefault()},onMouseDown:e=>{e.preventDefault()},onClick:()=>{Rt()},disabled:!g.trim()&&A.length===0,"data-testid":"chat-send-btn",style:{touchAction:"manipulation"},children:t.jsx(Ss,{size:16})})]})]})]}),$&&t.jsx(Yn,{isOpen:it,onClose:()=>ve(!1),projectId:n,existingRoomNames:o.rooms.map(e=>e.name),onCreate:async e=>{await o.createRoom({name:e.name,memberAgentIds:e.memberAgentIds}),u!=="rooms"&&R("rooms"),ve(!1),M&&ie(!1)}}),se&&t.jsx(ca,{projectId:n,onClose:()=>V(!1),onCreate:Ws})]})}export{ga as ChatView,Qn as clampChatInputHeight,Ds as resolveSessionProvider};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r,j as t}from"./vendor-react-K0fH_qHe.js";import{bZ as De,b_ as de,b$ as Ke,c0 as ue,s as Ue,c1 as be,c2 as we,c3 as xe,c4 as ye,c5 as et,c6 as ae,c7 as tt,c8 as rt,c9 as st,ca as nt,cb as at,cc as ie,L as ee,S as it,M as lt,cd as ct,bD as ot,a as dt,ce as Me,T as Ae,cf as ut,V as vt,aY as mt,aZ as ft,ae as pt,az as ht,R as gt}from"./index-Ba-F8c1g.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const ve=500,bt=3e3;function B(e){return e instanceof Error?e.message:String(e)}function Pe(e){return e.length<=ve?e:e.slice(-ve)}function le(e,i){return Pe([...e,i])}function G(e){try{return JSON.parse(e)}catch{return null}}function Q(e){const i=e.text??"";return e.stream==="stderr"?`[stderr] ${i}`:i}function wt(e){return e?.previewUrl??null}async function Se(e){return tt(e)}async function Ne(e,i){return rt(e,i)}async function xt(e){return st(e)}async function yt(e){return nt(e)}async function je(e){return at(e)}function V(e){try{return e()}catch{return null}}function ce(){return typeof V(()=>de)=="function"&&typeof V(()=>De)=="function"}function q(e){return{config:{id:e.id??"default",name:e.name??"Dev Server",command:e.command??"",cwd:e.cwd??"."},status:e.status,runtime:e.pid?{pid:e.pid,startedAt:e.startedAt??new Date().toISOString(),exitCode:e.exitCode??void 0,previewUrl:e.previewUrl}:void 0,previewUrl:e.previewUrl??e.detectedUrl??e.manualUrl??void 0,logHistory:(e.logs??[]).map(i=>({timestamp:new Date().toISOString(),stream:i.startsWith("[stderr]")?"stderr":"stdout",text:i.replace(/^\[stderr\]\s*/,"")}))}}function St(e){const[i,o]=r.useState(null),[g,y]=r.useState([]),[w,f]=r.useState([]),[k,U]=r.useState([]),[C,P]=r.useState(!0),[S,u]=r.useState(null),n=r.useRef(0),[d,M]=r.useState(null),R=r.useCallback(a=>{if(o(a),a?.logHistory){const s=a.logHistory.slice(-ve).map(Q);f(s)}},[]),A=r.useCallback(async()=>{const a=n.current;try{if(ce())if(d){const s=await De(d,e);if(n.current!==a)return;R(s)}else{const s=await de(e);if(n.current!==a)return;y(s),s.length>0&&(M(s[0].config.id),R(s[0]))}else{const s=await Se(e);if(n.current!==a)return;const c=q(s);y([c]),R(c)}u(null)}catch(s){if(n.current!==a)return;u(B(s))}},[R,e,d]);r.useEffect(()=>{n.current+=1;const a=n.current;o(null),y([]),f([]),U([]),P(!0),u(null),M(null),(async()=>{try{const[c,l]=await Promise.allSettled([ce()?de(e):Se(e).then(N=>[q(N)]),typeof V(()=>ae)=="function"?ae(e):je(e).then(N=>N.map(b=>({name:b.name,command:b.command,cwd:b.cwd,scriptName:b.scriptName,packagePath:b.packagePath})))]);if(n.current!==a)return;let v=null;if(c.status==="fulfilled"){const N=c.value;if(y(N),N.length>0){const b=N[0];ce()&&M(b.config.id),R(b)}}else v=B(c.reason);l.status==="fulfilled"&&U(l.value),v&&u(v)}catch(c){if(n.current!==a)return;u(B(c))}finally{n.current===a&&P(!1)}})()},[R,e]),r.useEffect(()=>{const a=d?Ke(d,e):typeof V(()=>ue)=="function"?ue(e):null;if(!a)return;const s=n.current,c=Ue(a,{events:{history:l=>{if(n.current!==s)return;const v=G(l.data);if(v?.lines){const N=v.lines.map(Q);f(Pe(N))}},log:l=>{if(n.current!==s)return;const v=G(l.data);if(v){const N=typeof v.line=="string"?v.line:Q(v);f(b=>le(b,N))}},"dev-server:log":l=>{if(n.current!==s)return;const v=G(l.data);if(v){const N=typeof v.line=="string"?v.line:Q(v);f(b=>le(b,N))}},"dev-server:output":l=>{if(n.current!==s)return;const v=G(l.data);v?.line&&f(N=>le(N,v.line))},status:l=>{if(n.current!==s)return;const v=G(l.data),N=v?.status;N&&o(b=>b&&{...b,status:N,runtime:v.pid?{...b.runtime??{startedAt:new Date().toISOString()},pid:v.pid}:b.runtime})},"dev-server:status":l=>{if(n.current!==s)return;const v=G(l.data);if(v?.status){const N=q(v);o(N),y([N])}},stopped:()=>{n.current},failed:()=>{n.current}},onReconnect:()=>{n.current===s&&A()},onError:()=>{n.current===s&&u(l=>l??"Lost log stream connection.")}});return()=>{c()}},[e,A,d]),r.useEffect(()=>{if(i?.status!=="running"&&i?.status!=="starting")return;const a=setInterval(()=>{A()},bt);return()=>{clearInterval(a)}},[A,i?.status]);const _=r.useCallback(async(a,s)=>{n.current+=1;const c=n.current;try{let l;if(d&&typeof V(()=>be)=="function")l=await be(d,e);else{const v=await Ne({command:a,cwd:s},e);l=q(v)}if(n.current!==c)return;o(l),u(null)}catch(l){if(n.current!==c)return;throw u(B(l)),l}},[e,d]),D=r.useCallback(async()=>{n.current+=1;const a=n.current;try{let s;if(d&&typeof V(()=>we)=="function")s=await we(d,e);else{const c=await xt(e);s=q(c)}if(n.current!==a)return;o(s),u(null)}catch(s){if(n.current!==a)return;throw u(B(s)),s}},[e,d]),j=r.useCallback(async()=>{n.current+=1;const a=n.current;try{let s;if(d&&typeof V(()=>xe)=="function")s=await xe(d,e);else{const c=await yt(e);s=q(c)}if(n.current!==a)return;o(s),u(null)}catch(s){if(n.current!==a)return;throw u(B(s)),s}},[e,d]),T=r.useCallback(async a=>{n.current+=1;const s=n.current;try{let c;if(d&&typeof V(()=>ye)=="function")c=await ye(d,a,e);else{const l=await et({url:a},e);c={url:l.manualUrl??l.previewUrl??l.detectedUrl??null,source:l.manualUrl?"manual":"auto"}}if(n.current!==s)return;o(l=>l?{...l,previewUrl:c.url??void 0}:null),u(null)}catch(c){if(n.current!==s)return;throw u(B(c)),c}},[e,d]),h=r.useCallback(async()=>{n.current+=1;const a=n.current;try{let s;try{s=await ae(e)}catch{s=(await je(e)).map(l=>({name:l.name,command:l.command,cwd:l.cwd,scriptName:l.scriptName,packagePath:l.packagePath}))}if(n.current!==a)return;U(s),u(null)}catch(s){if(n.current!==a)return;throw u(B(s)),s}},[e]),p=r.useCallback(async(a,s)=>{if(typeof a!="string"&&!d)try{const v=a,N=await Ne({command:v.command,cwd:v.cwd,scriptName:v.scriptName,packagePath:v.packagePath??v.cwd},e),b=q(N);o(b),y([b]),u(null);return}catch(v){throw u(B(v)),v}const c=typeof a=="string"?a:a.command,l=typeof a=="string"?s:a.cwd;await _(c,l)},[e,_,d]),E=r.useCallback(async()=>{await D()},[D]),L=r.useCallback(async()=>{await j()},[j]),z=r.useCallback(async a=>{await T(a)},[T]),F=r.useCallback(async()=>{await h()},[h]),O=r.useCallback(async()=>{await A()},[A]),H=wt(i),x=i?{...i,pid:i.runtime?.pid}:null;return{session:i,sessions:g,logs:w,detectedCommands:k,previewUrl:H,isLoading:C,error:S,startServer:_,stopServer:D,restartServer:j,setPreviewUrl:T,detectCommands:h,refresh:A,candidates:k,serverState:x,loading:C,start:p,stop:E,restart:L,setManualUrl:z,detect:F,refreshStatus:O}}const ke=500,Ce=100;function Te(e){return e.length>ke?e.slice(-ke):e}function ze(e){return e==="stderr"?"stderr":"stdout"}function Z(e){try{return JSON.parse(e.data)}catch{return null}}function K(e,i){return{id:typeof e.id=="number"&&Number.isFinite(e.id)?e.id:i,text:typeof e.text=="string"?e.text:"",stream:ze(e.stream),timestamp:typeof e.timestamp=="string"?e.timestamp:""}}function Nt(e,i){return{id:i,text:e,stream:"stdout",timestamp:""}}function oe(e,i){if(i.length===0)return e;const o=[...e],g=new Set(e.map(y=>y.id));for(const y of i)g.has(y.id)||(g.add(y.id),o.push(y));return o.sort((y,w)=>y.id-w.id),Te(o)}function jt(e,i){const[o,g]=r.useState([]),[y,w]=r.useState(!1),[f,k]=r.useState(!1),[U,C]=r.useState(!1),[P,S]=r.useState(null),u=r.useRef(null),n=r.useRef(!1),d=r.useRef(0),M=r.useRef(0),R=r.useRef(e),A=r.useRef(i),_=r.useRef(0),D=r.useRef(1);(R.current!==e||A.current!==i)&&(R.current=e,A.current=i,d.current++,n.current=!0,_.current=0,D.current=1,g([]),w(!1),k(!1),C(!1),S(null),u.current&&(u.current(),u.current=null)),r.useEffect(()=>{if(!i){u.current&&(u.current(),u.current=null);return}const E=d.current,L=++M.current;n.current=!1,w(!0);const z=(x,a)=>{const s=Te(x);g(s),S(a),C(a!==null?a>s.length:!1);const c=s.length>0?s[s.length-1].id:0;_.current=c,D.current=c+1},F=x=>{if(n.current||d.current!==E||!x||typeof x!="object")return;const a=x.lines;if(!Array.isArray(a))return;if(a.length>0&&typeof a[0]=="string"){const c=a.filter(l=>typeof l=="string").map((l,v)=>Nt(l,v+1));z(c,c.length);return}const s=a.filter(c=>!!c&&typeof c=="object").map((c,l)=>K(c,l+1));z(s,s.length)},O=x=>{if(n.current||d.current!==E)return;const a=typeof x.text=="string"?x.text:typeof x.line=="string"?x.line:null;if(!a)return;const s=D.current,c=typeof x.id=="number"&&Number.isFinite(x.id)?x.id:s,l={id:c,text:a,stream:ze(x.stream),timestamp:typeof x.timestamp=="string"?x.timestamp:""};_.current=Math.max(_.current,c),D.current=Math.max(D.current,c+1),g(v=>oe(v,[l])),S(v=>v===null?v:Math.max(v+1,l.id))};async function H(){try{const a=await ie({maxLines:Ce},e);if(n.current||d.current!==E||M.current!==L)return;const s=a.lines.map((c,l)=>K(c,l+1));z(s,a.totalLines)}catch{if(n.current||d.current!==E||M.current!==L)return;z([],null)}finally{!n.current&&d.current===E&&M.current===L&&w(!1)}const x=ue(e);u.current=Ue(x,{events:{"dev-server:log":a=>{const s=Z(a);s&&O(s)},log:a=>{const s=Z(a);s&&O(s)},history:a=>{const s=Z(a);F(s)},"dev-server:history":a=>{const s=Z(a);F(s)}},onReconnect:()=>{n.current||d.current!==E||ie({lastEventId:_.current,maxLines:50},e).then(a=>{if(n.current||d.current!==E)return;const s=a.lines.map((c,l)=>K(c,D.current+l));if(s.length>0){const c=s[s.length-1].id;_.current=Math.max(_.current,c),D.current=Math.max(D.current,c+1)}g(c=>oe(c,s)),S(a.totalLines)}).catch(()=>{})}})}return H(),()=>{n.current=!0,u.current&&(u.current(),u.current=null)}},[i,e]);const T=r.useCallback(async()=>{if(!i||f)return;const E=d.current,L=o.length;k(!0);try{const z=await ie({maxLines:Ce,offset:L},e);if(n.current||d.current!==E)return;const F=z.lines.map((O,H)=>K(O,H+1));g(O=>oe(F,O)),C(z.totalLines>L+F.length),S(z.totalLines)}catch{}finally{k(!1)}},[i,o.length,f,e]),h=r.useCallback(()=>{g([])},[]),p=u.current!==null&&!y&&!n.current;return{entries:o,loading:y,loadingMore:f,hasMore:U,total:P,loadMore:T,clear:h,logs:o,isStreaming:p,clearLogs:h}}const kt="This preview appears to block iframe embedding. Open it in a new tab instead.",Ct="The preview URL could not be loaded. Verify the server is running and the URL is correct.",Et="Preview is taking longer than expected and may block iframe embedding.";function Lt(e){return e==="blocked"?kt:e==="error"?Ct:null}function Rt(e,i={}){const{loadTimeoutMs:o=1e4,detectionMethod:g=null}=i,y=r.useRef(null),w=r.useRef(null),[f,k]=r.useState("unknown"),[U,C]=r.useState(null),[P]=r.useState(g),S=r.useCallback(()=>{w.current!==null&&(window.clearTimeout(w.current),w.current=null)},[]),u=r.useCallback(j=>{k(j),C(Lt(j))},[]),n=r.useCallback(()=>{k("blocked"),C(Et)},[]);r.useEffect(()=>{if(S(),!e){k("unknown"),C(null);return}k("unknown"),C(null);let j=!1;return queueMicrotask(()=>{j||(k("loading"),C(null))}),()=>{j=!0,S()}},[S,e]),r.useEffect(()=>{if(f!=="loading"){S();return}const j=setTimeout(()=>{w.current=null,n()},o);return w.current=j,()=>{clearTimeout(j),w.current===j&&(w.current=null)}},[S,f,o,n]);const d=r.useCallback(()=>{const j=y.current;if(!j){u("embedded");return}try{if(j.contentWindow?.location?.href==="about:blank"&&j.src!=="about:blank"){u("blocked");return}}catch{}u("embedded")},[u]),M=r.useCallback(()=>{u("error")},[u]);r.useEffect(()=>{if(S(),!e){k("unknown"),C(null);return}k("unknown"),C(null)},[S]);const R=r.useCallback(()=>{S(),k("unknown"),C(null)},[S]),A=R,_=r.useMemo(()=>f==="embedded",[f]),D=r.useMemo(()=>f==="blocked"||f==="error",[f]);return{embedStatus:f,isEmbedded:_,isBlocked:D,blockReason:U,detectionMethod:P,iframeRef:y,resetEmbedStatus:R,setEmbedStatus:u,retry:A,embedContext:U,handleIframeLoad:d,handleIframeError:M}}const _t=/\x1b\[[0-9;]*m/g;function me(e){return e.replace(_t,"")}function Dt(e){if(!e)return"";const i=new Date(e);return Number.isNaN(i.getTime())?"":i.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1})}function Ut(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Mt(e){if(e.stream==="stderr")return"error";const i=me(e.text).toLowerCase();return/\b(warn|warning)\b/.test(i)?"warn":/\b(error|fatal)\b/.test(i)?"error":"info"}function At(e,i){if(!i)return e;const o=new RegExp(`(${Ut(i)})`,"ig"),g=e.split(o),y=i.toLowerCase();return t.jsx(t.Fragment,{children:g.map((w,f)=>w.toLowerCase()===y?t.jsx("mark",{children:w},`${w}-${f}`):t.jsx("span",{children:w},`${w}-${f}`))})}function Pt({entries:e,loading:i,loadingMore:o,hasMore:g,total:y,onLoadMore:w,isRunning:f}){const k=r.useRef(null),U=r.useRef(e.length),C=r.useRef(f),[P,S]=r.useState(!1),[u,n]=r.useState(!1),[d,M]=r.useState(""),[R,A]=r.useState("all"),_=r.useMemo(()=>R==="all"?e:e.filter(p=>Mt(p)===R),[e,R]),D=r.useMemo(()=>{const p=d.trim().toLowerCase();return p?_.filter(E=>me(E.text).toLowerCase().includes(p)):_},[_,d]),j=D.length,T=r.useCallback(()=>{const p=k.current;p&&(p.scrollTop=p.scrollHeight,n(!1))},[]);r.useEffect(()=>{const p=C.current,E=U.current,L=e.length>E;f&&(!p||!u&&L)&&T(),C.current=f,U.current=e.length},[e.length,f,u,T]);const h=r.useCallback(()=>{const p=k.current;if(!p)return;const L=p.scrollTop+p.clientHeight>=p.scrollHeight-50;n(!L)},[]);return r.useEffect(()=>{i||e.length===0||!u&&f&&T()},[e,f,u,i,T]),i&&e.length===0?t.jsx("section",{className:"devserver-log-viewer","data-testid":"devserver-log-viewer",children:t.jsxs("div",{className:"devserver-log-viewer__loading","data-testid":"devserver-log-loading",children:[t.jsx(ee,{size:16,className:"devserver-log-viewer__spinner"}),t.jsx("span",{children:"Loading logs…"})]})}):t.jsxs("section",{className:`devserver-log-viewer${P?" devserver-log-viewer--fullscreen":""}`,"data-testid":"devserver-log-viewer",children:[t.jsxs("header",{className:"devserver-log-viewer__toolbar",children:[t.jsxs("div",{className:"devserver-log-viewer__toolbar-meta",children:[t.jsx("span",{className:"devserver-log-viewer__title",children:"Logs"}),t.jsxs("span",{className:"devserver-log-viewer__count","data-testid":"devserver-log-count",children:[y!==null?`${e.length}/${y}`:`${e.length}`," lines"]})]}),t.jsxs("div",{className:"devserver-log-viewer__toolbar-actions",children:[t.jsxs("label",{className:"devserver-log-viewer__severity",htmlFor:"devserver-log-severity-filter",children:[t.jsx("span",{className:"visually-hidden",children:"Filter logs by severity"}),t.jsxs("select",{id:"devserver-log-severity-filter",className:"select devserver-log-viewer__severity-select",value:R,onChange:p=>A(p.target.value),"data-testid":"devserver-log-severity-filter","aria-label":"Filter logs by severity",children:[t.jsx("option",{value:"all",children:"All severities"}),t.jsx("option",{value:"info",children:"Info"}),t.jsx("option",{value:"warn",children:"Warn"}),t.jsx("option",{value:"error",children:"Error"})]})]}),t.jsxs("label",{className:"devserver-log-viewer__search",htmlFor:"devserver-log-search",children:[t.jsx("span",{className:"visually-hidden",children:"Search logs"}),t.jsx(it,{size:14}),t.jsx("input",{id:"devserver-log-search",className:"input devserver-log-viewer__search-input",type:"text",value:d,onChange:p=>M(p.target.value),placeholder:"Search logs","data-testid":"devserver-log-search-input","aria-label":"Search logs"})]}),d.trim().length>0&&t.jsxs("span",{className:"devserver-log-viewer__matches","data-testid":"devserver-log-match-count",children:[j," match",j===1?"":"es"]}),t.jsx("button",{type:"button",className:"btn btn-sm btn-icon",onClick:()=>S(p=>!p),"data-testid":"devserver-log-fullscreen-toggle","aria-label":P?"Exit fullscreen logs":"Enter fullscreen logs",children:P?t.jsx(lt,{size:14}):t.jsx(ct,{size:14})})]})]}),t.jsxs("div",{className:"devserver-log-viewer__body",children:[g&&t.jsx("div",{className:"devserver-log-viewer__load-more","data-testid":"devserver-log-load-more",children:t.jsx("button",{type:"button",className:"btn btn-sm touch-target",onClick:w,disabled:o,"data-testid":"devserver-log-load-more-button",children:o?t.jsxs(t.Fragment,{children:[t.jsx(ee,{size:14,className:"devserver-log-viewer__spinner"}),"Loading older logs…"]}):"Load older logs"})}),t.jsxs("div",{ref:k,className:"devserver-log-viewer__content",onScroll:h,"data-testid":"devserver-log-content",children:[!i&&D.length===0&&t.jsx("p",{className:"devserver-log-viewer__empty","data-testid":"devserver-log-empty",children:e.length===0?"No logs yet. Start the dev server to see output.":_.length===0?"No log lines match the selected severity.":"No log lines match your search."}),D.map(p=>{const E=me(p.text),L=Dt(p.timestamp);return t.jsxs("div",{className:"devserver-log-line",children:[L&&t.jsx("span",{className:"devserver-log-timestamp","data-testid":"devserver-log-timestamp",children:L}),p.stream==="stderr"&&t.jsx("span",{className:"devserver-log-stream-badge","data-testid":"devserver-log-stderr-badge",children:"ERR"}),t.jsx("span",{className:"devserver-log-text",children:ot(At(E,d.trim()))})]},p.id)})]}),u&&f&&t.jsxs("button",{type:"button",className:"btn btn-sm devserver-log-viewer__new-logs-button",onClick:T,"data-testid":"devserver-log-jump-button",children:[t.jsx(dt,{size:14}),"New logs"]})]})]})}const Tt="devserver-preview-iframe";function zt({url:e,embedStatus:i,onEmbedStatusChange:o,iframeRef:g,blockReason:y,onRetry:w,className:f=Tt,embedContext:k}){const U=y??k??null,[C,P]=r.useState(0);r.useEffect(()=>{!e||i!=="unknown"||(P(d=>d+1),o("loading"))},[i,o,e]);const S=r.useCallback(()=>{const d=g.current;if(!d){o("embedded");return}try{if(d.contentWindow?.location?.href==="about:blank"&&d.src!=="about:blank"){o("blocked");return}}catch{}o("embedded")},[g,o]),u=r.useCallback(d=>{d.stopPropagation(),o("error")},[o]),n=r.useCallback(()=>{e&&window.open(e,"_blank","noopener,noreferrer")},[e]);return e?t.jsxs("div",{className:"devserver-preview-iframe-shell",children:[t.jsx("iframe",{src:e,ref:g,sandbox:"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox",className:f,title:"Dev server preview",onLoad:S,onError:u,onErrorCapture:u,"data-testid":"devserver-preview-iframe"},`${e}-${C}`),i==="loading"&&t.jsxs("div",{className:"devserver-preview-overlay","data-testid":"devserver-preview-loading",children:[t.jsx(ee,{size:16,className:"dev-server-spin"}),t.jsx("span",{children:"Loading preview..."})]}),i==="blocked"&&t.jsxs("div",{className:"devserver-preview-blocked-panel",role:"alert","data-testid":"devserver-preview-blocked-panel",children:[t.jsx(Me,{className:"devserver-preview-blocked-icon","aria-hidden":"true"}),t.jsxs("div",{children:[t.jsx("p",{className:"devserver-preview-blocked-title",children:"Preview cannot be embedded"}),U&&t.jsx("p",{className:"devserver-preview-blocked-context",children:U})]}),t.jsx("p",{className:"devserver-preview-blocked-description",children:"You can view the preview in a separate browser tab."}),t.jsxs("div",{className:"devserver-preview-blocked-actions",children:[t.jsx("button",{type:"button",className:"btn btn-primary",onClick:n,children:"Open in new tab"}),w&&t.jsx("button",{type:"button",className:"btn btn-sm",onClick:w,children:"Retry"})]})]}),i==="error"&&t.jsxs("div",{className:"devserver-preview-error-panel",role:"alert","data-testid":"devserver-preview-error-panel",children:[t.jsx(Ae,{className:"devserver-preview-blocked-icon","aria-hidden":"true"}),t.jsxs("div",{children:[t.jsx("p",{className:"devserver-preview-blocked-title",children:"Unable to load preview"}),U&&t.jsx("p",{className:"devserver-preview-blocked-context",children:U})]}),t.jsx("p",{className:"devserver-preview-blocked-description",children:"You can view the preview in a separate browser tab."}),t.jsxs("div",{className:"devserver-preview-blocked-actions",children:[t.jsx("button",{type:"button",className:"btn btn-primary",onClick:n,children:"Open in new tab"}),w&&t.jsx("button",{type:"button",className:"btn btn-sm",onClick:w,children:"Retry"})]})]})]}):null}const Ee={stopped:{className:"dev-server-status-badge--stopped",label:"Stopped"},starting:{className:"dev-server-status-badge--starting",label:"Starting..."},running:{className:"dev-server-status-badge--running",label:"Running"},stopping:{className:"dev-server-status-badge--starting",label:"Stopping..."},failed:{className:"dev-server-status-badge--failed",label:"Failed"}};function Le(e){return e instanceof Error?e.message:String(e)}function $e(e){return e==="."?"root":e}function Re(e){return e?e==="root"?".":e:null}function _e(e,i,o){return!i||e.scriptName!==i?!1:o?$e(e.cwd)===o:!0}function $t(e){return e.cwd==="."?"root":e.cwd}function Ft(e){return e.length<=60?e:`${e.slice(0,60)}…`}function Wt({addToast:e,projectId:i}){const{session:o,detectedCommands:g,previewUrl:y,isLoading:w,error:f,startServer:k,stopServer:U,restartServer:C,setPreviewUrl:P,detectCommands:S,refresh:u}=St(i),n=o?.status??"stopped",d=n==="running"||n==="starting",M=Ee[n]??Ee.stopped,{entries:R,loading:A,loadingMore:_,hasMore:D,total:j,loadMore:T}=jt(i,!!i),h=y,p=o?.config?.cwd??null,[E,L]=r.useState(!0),[z,F]=r.useState(""),[O,H]=r.useState(""),[x,a]=r.useState(null),[s,c]=r.useState(null),[l,v]=r.useState("embedded"),N=l==="embedded"?h:null,{embedStatus:b,setEmbedStatus:Fe,resetEmbedStatus:I,iframeRef:X,isEmbedded:Oe,isBlocked:te,blockReason:re,retry:fe}=Rt(N),[pe,W]=r.useState(!1),he=r.useRef(b);r.useEffect(()=>{const m=he.current!==b;te&&m&&W(!0),b==="embedded"&&W(!1),he.current=b},[b,te]),r.useEffect(()=>{W(!1)},[h]);const J=r.useMemo(()=>{if(!x)return null;const m=Re(p);return g.find($=>!($.scriptName!==x||m&&$.cwd!==m||o?.config?.command&&$.command!==o.config.command))??g.find($=>_e($,x,p))??null},[g,o?.config?.command,x,p]);r.useEffect(()=>{typeof S=="function"&&S().catch(m=>{e(Le(m),"error")})},[e,S]),r.useEffect(()=>{if(x){L(!1);return}L(!0)},[x]),r.useEffect(()=>{if(o?.status==="running"||o?.status==="starting"){o.config?.command?.trim().length>0&&F(o.config.command);return}if(J){F(J.command);return}g.length>0&&F(m=>m.trim().length>0?m:g[0]?.command??"")},[g,J,o?.config?.command,o?.status]),r.useEffect(()=>{H(h??"")},[h]);const se=r.useCallback(()=>{h&&window.open(h,"_blank","noopener,noreferrer")},[h]),ge=r.useCallback(()=>{W(!1),fe()},[fe]),Be=r.useCallback(()=>{try{const m=X.current;if(m?.contentWindow){m.contentWindow.location.reload(),W(!1),I();return}}catch{}if(!(!h||!X.current))try{const m=new URL(h);m.searchParams.set("_t",Date.now().toString()),X.current.src=m.toString(),W(!1),I()}catch{X.current.src=h,W(!1),I()}},[h,X,I]),Y=r.useCallback(async(m,$,ne)=>{c(m);try{await $(),e(ne,"success")}catch(Ze){e(Le(Ze),"error")}finally{c(null)}},[e]),He=r.useCallback(m=>{a(m.scriptName),L(!1),F(m.command),e(`Selected ${m.scriptName} script.`,"success")},[e]),Ve=r.useCallback(()=>{a(null),L(!0),e("Cleared selected dev server script.","success")},[e]),We=()=>{const m=z.trim();if(m.length===0){e("Enter a command before starting the dev server.","warning");return}const $=Re(p)??".",ne=J?.cwd??$;Y("start",()=>k(m,ne),"Dev server started.")},qe=()=>{Y("stop",U,"Dev server stopped.")},Xe=()=>{Y("restart",C,"Dev server restarted.")},Ge=()=>{const m=O.trim(),$=m.length>0?m:null;Y("preview",()=>P($),$?"Preview URL updated.":"Preview URL override cleared.")},Ie=r.useCallback(()=>{f&&u()},[f,u]),Je=n==="starting"||n==="running"||s!==null,Ye=n==="stopped"||s!==null,Qe=n==="stopped"||n==="starting"||s!==null;return t.jsxs("div",{className:"dev-server-view","data-testid":"dev-server-view",children:[t.jsxs("section",{className:"dev-server-header","aria-label":"Dev server controls header",children:[t.jsxs("div",{className:"dev-server-header-title",children:[t.jsx(ut,{size:16}),t.jsx("h2",{children:"Dev Server"}),t.jsx("span",{className:`dev-server-status-badge ${M.className}`,"data-testid":"dev-server-status-badge",children:M.label})]}),t.jsxs("div",{className:"dev-server-header-actions",children:[t.jsxs("button",{type:"button",className:"btn btn-primary btn-sm",onClick:We,disabled:Je,"data-testid":"dev-server-start-button",children:[t.jsx(vt,{size:14}),t.jsx("span",{children:s==="start"?"Starting...":"Start"})]}),t.jsxs("button",{type:"button",className:"btn btn-danger btn-sm",onClick:qe,disabled:Ye,"data-testid":"dev-server-stop-button",children:[t.jsx(mt,{size:14}),t.jsx("span",{children:s==="stop"?"Stopping...":"Stop"})]}),t.jsxs("button",{type:"button",className:"btn btn-sm",onClick:Xe,disabled:Qe,"data-testid":"dev-server-restart-button",children:[t.jsx(ft,{size:14}),t.jsx("span",{children:s==="restart"?"Restarting...":"Restart"})]})]})]}),t.jsxs("section",{className:"dev-server-panel dev-server-config","aria-label":"Dev server configuration",children:[t.jsxs("div",{className:"dev-server-section-header",children:[t.jsx("h3",{children:"Configuration"}),w&&t.jsx("span",{className:"dev-server-muted",children:"Loading..."})]}),w&&!o&&g.length===0&&t.jsxs("div",{className:"dev-server-loading-state","data-testid":"dev-server-loading-state",children:[t.jsx(ee,{size:16,className:"dev-server-spin"}),t.jsx("span",{children:"Loading dev server configuration..."})]}),f&&t.jsxs("div",{className:"dev-server-error-box",role:"alert","data-testid":"dev-server-error-box",children:[t.jsx("p",{children:f}),t.jsx("button",{type:"button",className:"btn btn-sm",onClick:Ie,children:"Retry"})]}),t.jsxs("div",{className:"dev-server-section",children:[t.jsx("h3",{children:"Script Selection"}),x&&t.jsxs("div",{className:"dev-server-selected","data-testid":"dev-server-selected-summary",children:[t.jsx("span",{className:"dev-server-candidate-name",children:x}),t.jsx("span",{className:"dev-server-candidate-source",children:p??"root"}),t.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>L(!0),"data-testid":"dev-server-change-selection",children:"Change"}),t.jsx("button",{type:"button",className:"btn btn-danger btn-sm",onClick:Ve,"data-testid":"dev-server-clear-selection",children:"Clear"})]}),E&&g.length===0&&t.jsxs("p",{className:"dev-server-empty-state","data-testid":"dev-server-empty-candidates",children:["No dev server scripts detected. Check that your project has a ",t.jsx("code",{children:"package.json"})," with a ",t.jsx("code",{children:"dev"}),", ",t.jsx("code",{children:"start"}),", or similar script."]}),E&&g.length>0&&t.jsx("div",{className:"dev-server-candidates","data-testid":"dev-server-candidates",children:g.map(m=>{const $=_e(m,x,p);return t.jsxs("button",{type:"button",className:`dev-server-candidate ${$?"dev-server-candidate--selected":""}`,onClick:()=>He(m),"data-testid":`dev-server-candidate-${m.scriptName}-${$e(m.cwd)}`,children:[t.jsx("span",{className:"dev-server-candidate-name",children:m.scriptName}),t.jsx("span",{className:"dev-server-candidate-command",children:Ft(m.command)}),t.jsx("span",{className:"dev-server-candidate-source",children:$t(m)})]},`${m.cwd}::${m.scriptName}::${m.command}`)})})]}),t.jsxs("div",{className:"dev-server-field-group",children:[t.jsx("label",{htmlFor:"dev-server-command",className:"dev-server-label",children:"Command"}),t.jsx("input",{id:"dev-server-command",className:"input",value:z,onChange:m=>F(m.target.value),placeholder:"pnpm dev","data-testid":"dev-server-command-input",readOnly:n==="running"||n==="starting"})]}),(n==="running"||n==="starting")&&o&&t.jsxs("div",{className:"dev-server-current-command","data-testid":"dev-server-current-command",children:[t.jsx("span",{className:"dev-server-label",children:"Running command"}),t.jsx("code",{children:o.config?.command??z})]}),t.jsxs("div",{className:"dev-server-preview-override",children:[t.jsx("label",{htmlFor:"dev-server-preview-input",className:"dev-server-label",children:"Preview URL Override"}),t.jsx("input",{id:"dev-server-preview-input",className:"input",type:"url",value:O,onChange:m=>H(m.target.value),placeholder:"http://localhost:3000","data-testid":"dev-server-preview-input"}),t.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:Ge,disabled:s==="preview","data-testid":"dev-server-set-preview",children:"Save"})]}),h&&t.jsxs("p",{className:"dev-server-preview-hint",children:["Auto-detected: ",h]})]}),t.jsx("div",{className:"dev-server-content",children:t.jsxs("section",{className:"dev-server-panel dev-server-logs-panel","data-testid":"dev-server-logs-panel","aria-label":"Dev server logs",children:[t.jsxs("div",{className:"dev-server-section-header",children:[t.jsx("h3",{children:"Logs"}),t.jsxs("span",{className:"dev-server-muted",children:[j??R.length," lines"]})]}),t.jsx("div",{className:"dev-server-logs-viewer","data-testid":"dev-server-log-viewer",children:t.jsx(Pt,{entries:R,loading:A,loadingMore:_,hasMore:D,total:j,onLoadMore:T,isRunning:d})})]})}),t.jsxs("section",{className:"dev-server-panel devserver-preview-panel","data-testid":"devserver-preview-panel","aria-label":"Dev server preview",children:[t.jsxs("div",{className:"devserver-preview-header",children:[t.jsxs("div",{className:"devserver-preview-title",children:[t.jsx(pt,{size:14}),t.jsx("span",{children:"Preview"})]}),t.jsxs("span",{className:"devserver-preview-url-badge devserver-preview-url-badge--auto",title:h??"No preview URL","data-testid":"devserver-preview-url-badge",children:["Auto",h?` · ${h}`:" · Not available"]}),t.jsxs("div",{className:"devserver-preview-actions",children:[t.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>v(m=>m==="embedded"?"external":"embedded"),"data-testid":"devserver-preview-mode-toggle",children:l==="embedded"?"External only":"Embedded"}),t.jsx("button",{type:"button",className:"btn btn-sm btn-icon",title:"Open in new tab",onClick:se,disabled:!h,"data-testid":"devserver-preview-open-tab",children:t.jsx(ht,{})}),t.jsx("button",{type:"button",className:"btn btn-sm btn-icon",title:"Refresh preview",onClick:Be,disabled:!h,"data-testid":"devserver-preview-refresh",children:t.jsx(gt,{})})]})]}),t.jsxs("div",{className:"devserver-preview-container","data-embed-status":b,"data-embedded":Oe?"true":"false",children:[!h&&!d&&t.jsx("p",{className:"devserver-preview-empty",children:"Start a dev server to see a live preview here."}),!h&&d&&t.jsx("p",{className:"devserver-preview-empty",children:"No preview URL detected. Start the dev server or set a manual URL to preview your app."}),h&&l==="external"&&t.jsxs("div",{className:"devserver-preview-external-only","data-testid":"devserver-preview-external-only",children:[t.jsx("p",{children:"Embedded preview is disabled. Open your app in a separate browser tab."}),t.jsx("button",{type:"button",className:"btn btn-primary btn-sm touch-target",onClick:se,"data-testid":"devserver-preview-external-open-tab",children:"Open in new tab"})]}),h&&l==="embedded"&&pe&&te&&t.jsxs("div",{className:b==="error"?"devserver-preview-error-panel":"devserver-preview-blocked-panel","data-testid":"devserver-preview-fallback",role:"alert",children:[b==="error"?t.jsx(Ae,{className:"devserver-preview-blocked-icon","aria-hidden":"true"}):t.jsx(Me,{className:"devserver-preview-blocked-icon","aria-hidden":"true"}),t.jsxs("div",{children:[t.jsx("p",{className:"devserver-preview-blocked-title",children:b==="error"?"Preview failed":"Preview blocked"}),re&&t.jsx("p",{className:"devserver-preview-blocked-context",children:re})]}),t.jsx("p",{className:"devserver-preview-blocked-description",children:"Open the preview in a new tab, or retry embedded mode after checking your server settings."}),t.jsxs("div",{className:"devserver-preview-blocked-actions",children:[t.jsx("button",{type:"button",className:"btn btn-primary",onClick:se,"data-testid":"devserver-preview-fallback-open-tab",children:"Open preview in new tab"}),t.jsx("button",{type:"button",className:"btn btn-sm",onClick:ge,"data-testid":"devserver-preview-fallback-retry",children:"Retry embedded preview"})]})]}),h&&l==="embedded"&&!pe&&t.jsx(zt,{url:h,embedStatus:b,onEmbedStatusChange:Fe,iframeRef:X,blockReason:re,onRetry:ge})]})]})]})}export{Wt as DevServerView};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import{r as s,j as e}from"./vendor-react-K0fH_qHe.js";import{c as ze,aP as ls,aQ as os,aR as cs,aS as is,aT as Le,aU as ve,aV as Ve,aW as ye,aX as Fe,A as Oe,av as ds,V as Ke,aY as Ue,aZ as us,Y as _e,u as ms,R as Ne,a as we,J as he,a_ as Te,a$ as hs,b0 as fs,b1 as gs,b2 as $e,X as me,ad as xs,ae as ps,b3 as De,F as js,b4 as Ie,b5 as bs,b6 as vs,b7 as ys,b8 as _s,b9 as Ns,G as ks}from"./index-Ba-F8c1g.js";import{v as Cs}from"./projectDetection-G3XuxD2X.js";import{U as Be}from"./upload-j7JjaJzG.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";/**
|
|
2
|
-
* @license lucide-react v1.7.0 - ISC
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the ISC license.
|
|
5
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const Ss=[["path",{d:"M12 20h.01",key:"zekei9"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0",key:"1bycff"}],["path",{d:"M5 12.859a10 10 0 0 1 5.17-2.69",key:"1dl1wf"}],["path",{d:"M19 12.859a10 10 0 0 0-2.007-1.523",key:"4k23kn"}],["path",{d:"M2 8.82a15 15 0 0 1 4.177-2.643",key:"1grhjp"}],["path",{d:"M22 8.82a15 15 0 0 0-11.288-3.764",key:"z3jwby"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],ws=ze("wifi-off",Ss);/**
|
|
7
|
-
* @license lucide-react v1.7.0 - ISC
|
|
8
|
-
*
|
|
9
|
-
* This source code is licensed under the ISC license.
|
|
10
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
-
*/const Ms=[["path",{d:"M12 20h.01",key:"zekei9"}],["path",{d:"M2 8.82a15 15 0 0 1 20 0",key:"dnpr2z"}],["path",{d:"M5 12.859a10 10 0 0 1 14 0",key:"1x1e6c"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0",key:"1bycff"}]],Ps=ze("wifi",Ms);function pe(t){const{lastSyncAt:r,remoteReachable:a,diff:i}=t,u=i.global.length+i.project.length;return r===null?{syncState:"never-synced",lastSyncAt:r,diffCount:0}:a?u>0?{syncState:"diff",lastSyncAt:r,diffCount:u}:{syncState:"synced",lastSyncAt:r,diffCount:0}:{syncState:"error",lastSyncAt:r,diffCount:u}}function ke(t){if(t===null)return"Never synced";const r=new Date(t);if(Number.isNaN(r.getTime()))return"Never synced";const i=Date.now()-r.getTime(),u=Math.floor(i/1e3),m=Math.floor(u/60),o=Math.floor(m/60),j=Math.floor(o/24);return m<1?"Synced just now":m<60?`Synced ${m}m ago`:o<24?`Synced ${o}h ago`:`Synced ${j}d ago`}function Es(t){switch(t){case"synced":return"var(--color-success)";case"pending":return"var(--color-warning)";case"diff":return"var(--color-warning)";case"error":return"var(--color-error)";case"never-synced":return"var(--text-muted)"}}const Rs=3e4;function As(){const[t,r]=s.useState({}),[a,i]=s.useState(!1),[u,m]=s.useState({}),[o,j]=s.useState(null),g=s.useRef(new Set),c=s.useRef(!1),N=s.useRef(null),w=s.useRef(null),b=s.useCallback(async(p,x)=>{try{const S=await ls(p);r(Z=>({...Z,[p]:S})),j(null)}catch(S){console.error(`Failed to fetch sync status for node ${p}:`,S),j(S instanceof Error?S.message:"Failed to fetch sync status")}},[]),d=s.useCallback(async()=>{const p=Array.from(g.current);if(p.length===0)return;N.current&&N.current.abort(),N.current=new AbortController;const x=!c.current;x&&i(!0),j(null);try{const S=await Promise.allSettled(p.map(H=>b(H,x)));c.current=!0,S.filter(H=>H.status==="rejected").length>0&&j("Some sync status requests failed")}catch(S){if(S instanceof Error&&S.name==="AbortError")return;j(S instanceof Error?S.message:"Failed to fetch sync status"),c.current=!0}finally{i(!1)}},[b]),M=s.useCallback(()=>{w.current&&clearInterval(w.current),w.current=setInterval(()=>{d()},Rs)},[d]),_=s.useCallback(()=>{w.current&&(clearInterval(w.current),w.current=null)},[]);s.useEffect(()=>(d(),M(),()=>{_(),N.current&&N.current.abort()}),[d,M,_]);const l=s.useCallback(p=>{g.current.has(p)||(g.current.add(p),b(p,!c.current))},[b]),v=s.useCallback(p=>{g.current.delete(p),r(x=>{const S={...x};return delete S[p],S}),g.current.size===0&&_()},[_]),C=s.useCallback(async p=>{m(x=>({...x,[p]:!0})),j(null);try{const x=await os(p);return b(p,!1),!x.success&&x.error&&j(x.error),x}catch(x){const S=x instanceof Error?x.message:"Push settings failed";throw j(S),x}finally{m(x=>{const S={...x};return delete S[p],S})}},[b]),k=s.useCallback(async p=>{m(x=>({...x,[p]:!0})),j(null);try{const x=await cs(p);return b(p,!1),!x.success&&x.error&&j(x.error),x}catch(x){const S=x instanceof Error?x.message:"Pull settings failed";throw j(S),x}finally{m(x=>{const S={...x};return delete S[p],S})}},[b]),$=s.useCallback(async p=>{m(x=>({...x,[p]:!0})),j(null);try{return await is(p)}catch(x){const S=x instanceof Error?x.message:"Auth sync failed";throw j(S),x}finally{m(x=>{const S={...x};return delete S[p],S})}},[]),V=s.useCallback(p=>t[p]?.authMatch,[t]),A=s.useCallback(p=>t[p]?.authDiff,[t]);return{syncStatusMap:t,loading:a,actionLoading:u,error:o,refresh:d,trackNode:l,untrackNode:v,pushSettings:C,pullSettings:k,syncAuth:$,getAuthSyncState:V,getAuthProviders:A}}const Ls=1e4,$s=1e3;function Ds(){const[t,r]=s.useState([]),[a,i]=s.useState(!0),[u,m]=s.useState(null),o=s.useRef(null),j=s.useRef(0),g=s.useCallback(async()=>{try{m(null);const c=await Le();r(c.nodes)}catch(c){m(c instanceof Error?c.message:"Failed to fetch mesh state")}},[]);return s.useEffect(()=>{let c=!1;async function N(){i(!0);try{const b=await Le();c||(r(b.nodes),m(null))}catch(b){c||m(b instanceof Error?b.message:"Failed to fetch mesh state")}finally{c||i(!1)}}N();const w=()=>{if(document.visibilityState!=="visible")return;const b=Date.now();b-j.current<$s||(j.current=b,g())};return document.addEventListener("visibilitychange",w),()=>{c=!0,document.removeEventListener("visibilitychange",w)}},[g]),s.useEffect(()=>{if(!a)return o.current=setInterval(()=>{g()},Ls),()=>{o.current&&(clearInterval(o.current),o.current=null)}},[a,g]),{meshState:t,loading:a,error:u,refresh:g}}const de={online:{label:"Online",color:"var(--color-success)",className:"node-card__status--online"},offline:{label:"Offline",color:"var(--color-error)",className:"node-card__status--offline"},connecting:{label:"Connecting",color:"var(--color-warning)",className:"node-card__status--connecting"},error:{label:"Error",color:"var(--color-error)",className:"node-card__status--error"},creating:{label:"Creating",color:"var(--color-warning)",className:"node-card__status--creating"},recreating:{label:"Recreating",color:"var(--color-warning)",className:"node-card__status--recreating"},deleting:{label:"Deleting",color:"var(--color-error)",className:"node-card__status--deleting"},running:{label:"Running",color:"var(--color-success)",className:"node-card__status--online"},stopped:{label:"Stopped",color:"var(--color-error)",className:"node-card__status--offline"},exited:{label:"Exited",color:"var(--color-error)",className:"node-card__status--offline"}},Is={match:"var(--color-success)",differs:"var(--color-warning)","not-synced":"var(--text-muted)"};function zs(t,r){if(t==="match")return"Auth credentials match";if(t==="not-synced")return"Auth not synced";if(r&&Object.keys(r).length>0){const a=Object.entries(r).filter(([,i])=>i==="differs").map(([i])=>i);if(a.length>0)return`Auth credentials differ: ${a.join(", ")}`}return"Auth credentials differ"}function Vs(t,r=42){return t.length<=r?t:`${t.slice(0,r-3)}...`}function Fs(t,r){const a=t.node,i=r.node;if(a.id!==i.id||a.name!==i.name||a.type!==i.type||a.url!==i.url||a.status!==i.status||a.maxConcurrent!==i.maxConcurrent||a.updatedAt!==i.updatedAt||t.isLoading!==r.isLoading)return!1;const u=t.managedDockerNode,m=r.managedDockerNode;if(!!u!=!!m||u&&m&&(u.id!==m.id||u.status!==m.status||u.imageTag!==m.imageTag||u.updatedAt!==m.updatedAt))return!1;const o=t.syncStatus,j=r.syncStatus;if(!(!o&&!j)){if(!o||!j)return!1;if(o.syncState!==j.syncState||o.lastSyncAt!==j.lastSyncAt||o.diffCount!==j.diffCount)return!1}if(t.authSyncState!==r.authSyncState)return!1;const g=t.authSyncProviders,c=r.authSyncProviders;if(g!==c){if(!g||!c)return!1;{const b=Object.keys(g),d=Object.keys(c);if(b.length!==d.length||b.some(M=>g[M]!==c[M]))return!1}}const N=ve(t.projects,a),w=ve(r.projects,i);return N===w}function Os({node:t,projects:r,onHealthCheck:a,onEdit:i,onRemove:u,isLoading:m=!1,syncStatus:o,authSyncState:j,authSyncProviders:g,managedDockerNode:c}){const[N,w]=s.useState(!1),b=de[t.status]??de.offline,d=c?de[c.status]??de.error:null,M=c?.hostConfig.type==="remote"?`Remote: ${c.hostConfig.host??"unknown"}`:"Local Docker",_=s.useMemo(()=>ve(r,t),[r,t]),l=s.useCallback(()=>{i(t)},[i,t]),v=s.useCallback(V=>{V.stopPropagation(),a(t.id)},[a,t.id]),C=s.useCallback(V=>{V.stopPropagation(),i(t)},[i,t]),k=s.useCallback(V=>{if(V.stopPropagation(),!N){w(!0);return}u(t.id),w(!1)},[N,u,t.id]),$=s.useCallback(V=>{(V.key==="Enter"||V.key===" ")&&(V.preventDefault(),i(t))},[i,t]);return e.jsxs("article",{className:`node-card ${m?"node-card--loading":""}`,"data-node-id":t.id,role:"button",tabIndex:0,onClick:l,onKeyDown:$,children:[e.jsx("header",{className:"node-card__header",children:e.jsxs("div",{className:"node-card__title-wrap",children:[e.jsx("div",{className:"node-card__icon",children:e.jsx(Ve,{size:18})}),e.jsxs("div",{children:[e.jsx("h3",{className:"node-card__name",title:t.name,children:t.name}),e.jsxs("div",{className:"node-card__meta-row",children:[e.jsx("span",{className:"node-card__type-badge",children:t.type==="local"?"Local":"Remote"}),c&&e.jsxs("span",{className:"node-card__docker-badge",title:"Managed Docker node",children:[e.jsx(ye,{size:12,"aria-hidden":!0}),"Docker"]}),e.jsxs("span",{className:`node-card__status ${b.className}`,style:{color:b.color},"data-status":t.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:b.color},"aria-hidden":!0}),b.label]}),c&&d&&e.jsxs("span",{className:`node-card__status ${d.className}`,style:{color:d.color},"data-status":c.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:d.color},"aria-hidden":!0}),d.label]}),t.type==="remote"&&j&&e.jsx("span",{className:`node-card__auth-indicator node-card__auth-indicator--${j}`,title:zs(j,g),"aria-label":`Auth sync: ${j==="match"?"credentials match":j==="differs"?"credentials differ":"not synced"}`,style:{color:Is[j]},children:e.jsx(Fe,{size:14})})]})]})]})}),e.jsxs("div",{className:"node-card__body",children:[t.type==="remote"&&t.url&&e.jsx("div",{className:"node-card__url",title:t.url,children:Vs(t.url)}),c&&e.jsxs("div",{className:"node-card__docker-meta",children:[e.jsxs("span",{title:`${c.imageName}:${c.imageTag}`,children:[c.imageName,":",c.imageTag]}),e.jsx("span",{title:M,children:M})]}),e.jsxs("div",{className:"node-card__metrics",children:[e.jsxs("div",{className:"node-card__metric",children:[e.jsx("span",{className:"node-card__metric-label",children:"Projects"}),e.jsx("span",{className:"node-card__metric-value",children:_})]}),e.jsxs("div",{className:"node-card__metric",children:[e.jsx("span",{className:"node-card__metric-label",children:"Concurrency"}),e.jsx("span",{className:"node-card__metric-value",children:t.maxConcurrent})]})]}),t.type==="remote"&&o&&e.jsxs("div",{className:"node-card__sync","data-sync-state":o.syncState,"data-testid":"node-card-sync",children:[e.jsx("span",{className:"node-card__sync-dot",style:{backgroundColor:Es(o.syncState)},"aria-hidden":!0}),e.jsx("span",{className:"node-card__sync-time",children:ke(o.lastSyncAt)})]})]}),e.jsxs("footer",{className:"node-card__actions",children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:v,disabled:m,"aria-label":"Run node health check",title:"Health Check",children:[e.jsx(Oe,{size:14}),e.jsx("span",{children:"Health"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:C,disabled:m,"aria-label":"Edit node",title:"Edit",children:[e.jsx(ds,{size:14}),e.jsx("span",{children:"Edit"})]}),c&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",disabled:!0,"aria-label":"Start node container",title:"Available after FN-3113",children:[e.jsx(Ke,{size:14}),e.jsx("span",{children:"Start"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",disabled:!0,"aria-label":"Stop node container",title:"Available after FN-3113",children:[e.jsx(Ue,{size:14}),e.jsx("span",{children:"Stop"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",disabled:!0,"aria-label":"Restart node container",title:"Available after FN-3113",children:[e.jsx(us,{size:14}),e.jsx("span",{children:"Restart"})]})]}),e.jsxs("button",{className:`btn btn-sm node-card__action node-card__action--remove ${N?"btn-danger is-armed":""}`,type:"button",onClick:k,disabled:m,"aria-label":N?"Confirm remove node":"Remove node",title:N?"Confirm remove":"Remove",children:[e.jsx(_e,{size:14}),e.jsx("span",{children:N?"Confirm":"Remove"})]})]})]})}const Ks=s.memo(Os,Fs),ce={online:"var(--success, var(--color-success))",offline:"var(--text-dim)",connecting:"var(--color-warning)",error:"var(--color-error)"},ue=28,Us=12,Ts=300,Bs=120;function Hs({nodes:t,className:r}){const a=s.useMemo(()=>t.find(c=>c.nodeType==="local")??t[0],[t]),i=s.useMemo(()=>t.filter(c=>c.nodeId!==a?.nodeId),[t,a?.nodeId]),u=s.useMemo(()=>Ts+Math.max(0,i.length-4)*20,[i.length]),m=u/2,o=u/2,j=s.useMemo(()=>{const c=new Map;if(a&&c.set(a.nodeId,{x:m,y:o,node:a}),i.length>0){const N=Math.min(Bs,u/2-ue-10),w=2*Math.PI/i.length,b=-Math.PI/2;i.forEach((d,M)=>{const _=b+M*w;c.set(d.nodeId,{node:d,x:m+N*Math.cos(_),y:o+N*Math.sin(_)})})}return c},[m,o,a,i,u]),g=s.useMemo(()=>{const c=new Set,N=[];for(const w of t){const b=j.get(w.nodeId);if(b)for(const d of w.knownPeers){const M=j.get(d.peerNodeId);if(!M)continue;const _=[w.nodeId,d.peerNodeId].sort().join("::");c.has(_)||(c.add(_),N.push({key:_,from:b,to:M}))}}return N},[j,t]);return t.length===0?e.jsx("div",{className:`mesh-topology mesh-topology--empty ${r??""}`,children:e.jsx("div",{className:"mesh-topology__empty-state",children:e.jsx("p",{children:"No nodes to display"})})}):e.jsxs("div",{className:`mesh-topology ${r??""}`,children:[e.jsxs("svg",{className:"mesh-topology__svg",viewBox:`0 0 ${u} ${u}`,preserveAspectRatio:"xMidYMid meet","aria-label":"Node mesh topology visualization",children:[g.map(c=>e.jsx("line",{className:"mesh-topology__link mesh-topology__peer-line",x1:c.from.x,y1:c.from.y,x2:c.to.x,y2:c.to.y},c.key)),Array.from(j.values()).map(({node:c,x:N,y:w})=>e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${N}, ${w})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:ue,fill:ce[c.status],"aria-label":`${c.nodeName} (${c.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:ue+Us,textAnchor:"middle",children:c.nodeName.length>12?`${c.nodeName.slice(0,10)}…`:c.nodeName}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-ue-10})`,children:[e.jsx("circle",{className:"mesh-topology__node-type-badge",r:"8"}),e.jsx("text",{className:"mesh-topology__node-type-text",textAnchor:"middle",dominantBaseline:"middle",children:c.nodeType==="local"?"L":"R"})]})]},c.nodeId))]}),e.jsxs("div",{className:"mesh-topology__legend",children:[e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.online}}),e.jsx("span",{children:"Online"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.offline}}),e.jsx("span",{children:"Offline"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.connecting}}),e.jsx("span",{children:"Connecting"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.error}}),e.jsx("span",{children:"Error"})]})]}),g.length===0&&e.jsx("p",{className:"mesh-topology__notice",children:"Peer-to-peer discovery data unavailable."})]})}const qs=s.memo(Hs),Ce=1,Se=10;function Ys(t){const r={projectMappings:{}};t.name.trim()||(r.name="Name is required"),t.type==="remote"&&!t.url?.trim()&&(r.url="URL is required for remote nodes"),(!Number.isFinite(t.maxConcurrent)||t.maxConcurrent<Ce||t.maxConcurrent>Se)&&(r.maxConcurrent=`Concurrency must be between ${Ce} and ${Se}`);for(const a of t.projectMappings){const i=Cs(a.path);i.valid||(r.projectMappings[a.projectId]=i.error??"Path is invalid")}return r}function Xs({isOpen:t,onClose:r,onSubmit:a,onDiscoverRemoteProjects:i,addToast:u,projects:m}){ms(t);const[o,j]=s.useState(""),[g,c]=s.useState("local"),[N,w]=s.useState(""),[b,d]=s.useState(""),[M,_]=s.useState(2),[l,v]=s.useState("auto-generate"),[C,k]=s.useState({}),[$,V]=s.useState({projectMappings:{}}),[A,p]=s.useState(!1),[x,S]=s.useState("idle"),[Z,H]=s.useState(null),[Y,ee]=s.useState([]),U=s.useCallback(()=>{j(""),c("local"),w(""),d(""),_(2),v("auto-generate"),k({}),V({projectMappings:{}}),p(!1),S("idle"),H(null),ee([])},[]),X=s.useCallback(()=>{A||(U(),r())},[A,r,U]);s.useEffect(()=>{if(!t){U();return}const y=L=>{L.key==="Escape"&&(L.preventDefault(),X())};return document.addEventListener("keydown",y),()=>{document.removeEventListener("keydown",y)}},[X,t,U]);const G=s.useMemo(()=>({name:o.trim(),type:g,url:g==="remote"&&N.trim()||void 0,apiKey:g==="remote"&&l==="provide"&&b||void 0,maxConcurrent:M,apiKeyMode:l,projectMappings:Object.entries(C).map(([y,L])=>({projectId:y,path:L.trim()}))}),[b,l,M,o,C,g,N]),te=s.useCallback(async()=>{if(A||x==="loading")return;const y=N.trim();if(!y){V(L=>({...L,url:"URL is required for remote nodes"}));return}S("loading"),H(null);try{const L=await i({url:y,apiKey:l==="provide"&&b.trim().length>0?b:void 0});ee(L.projects),S("success"),k(D=>{if(Object.keys(D).length===0)return D;const K={...D};for(const ae of m){if(!(ae.id in K))continue;const ne=L.projects.filter(se=>se.name===ae.name);ne.length===1&&(K[ae.id]=ne[0].path)}return K})}catch(L){S("error"),ee([]),H(L instanceof Error?L.message:"Failed to discover remote projects")}},[b,l,x,A,i,m,N]);s.useEffect(()=>{if(g!=="remote"){S("idle"),H(null),ee([]);return}S("idle"),H(null),ee([])},[b,l,g,N]);const J=s.useCallback(async()=>{if(A)return;const y=Ys(G);if(V(y),!(y.name||y.url||y.maxConcurrent||Object.keys(y.projectMappings).length>0)){if(G.type==="remote"&&x!=="success"){H("Discover remote projects before adding this node.");return}p(!0);try{await a(G),u(`Node "${G.name}" registered`,"success"),X()}catch(L){const D=L instanceof Error?L.message:"Failed to register node";u(D,"error")}finally{p(!1)}}},[u,X,x,G,A,a]),T=y=>{k(L=>{if(y.id in L){const{[y.id]:D,...K}=L;return K}if(g==="remote"&&x==="success"){const D=Y.filter(K=>K.name===y.name);return D.length===1?{...L,[y.id]:D[0].path}:{...L,[y.id]:""}}return{...L,[y.id]:y.path}})},E=(y,L)=>{k(D=>({...D,[y]:L}))};return t?e.jsx("div",{className:"modal-overlay open",onClick:X,children:e.jsxs("div",{className:"modal modal-md add-node-modal",onClick:y=>y.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Add Node",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Add Node"}),e.jsx("button",{className:"modal-close",onClick:X,disabled:A,"aria-label":"Close add node modal",children:"×"})]}),e.jsxs("div",{className:"modal-body add-node-modal__body",children:[e.jsx("p",{className:"add-node-modal__description",children:"Register an existing Fusion node by providing its connection details and concurrency settings."}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Name"}),e.jsx("input",{className:"input",type:"text",value:o,onChange:y=>j(y.target.value),placeholder:"Build Machine",disabled:A,"aria-invalid":!!$.name,autoFocus:!0}),$.name&&e.jsx("span",{className:"form-error add-node-modal__error",children:$.name})]}),e.jsxs("div",{className:"add-node-modal__type-toggle",children:[e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${g==="local"?"active":""}`,"data-type":"local",onClick:()=>c("local"),disabled:A,"aria-pressed":g==="local",children:"Local"}),e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${g==="remote"?"active":""}`,"data-type":"remote",onClick:()=>c("remote"),disabled:A,"aria-pressed":g==="remote",children:"Remote"})]}),g==="remote"&&e.jsxs("div",{className:"add-node-modal__remote-fields","data-testid":"remote-fields-container","data-visible":!0,children:[e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Reachable URL / Hostname"}),e.jsx("input",{className:"input",type:"text",value:N,onChange:y=>w(y.target.value),placeholder:"https://node.example.com",disabled:A,"aria-invalid":!!$.url}),$.url&&e.jsx("span",{className:"form-error add-node-modal__error",children:$.url})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key Mode"}),e.jsxs("select",{className:"select",value:l,onChange:y=>v(y.target.value),disabled:A,children:[e.jsx("option",{value:"auto-generate",children:"Auto-generate"}),e.jsx("option",{value:"provide",children:"Provide key manually"})]})]}),l==="provide"&&e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:b,onChange:y=>d(y.target.value),placeholder:"Enter node API key",disabled:A})]}),e.jsxs("div",{className:"add-node-modal__discovery-actions",children:[e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void te(),disabled:A||x==="loading",children:x==="loading"?"Discovering...":"Discover Remote Projects"}),x==="success"&&e.jsx("span",{className:"add-node-modal__discovery-state","data-state":"success",children:Y.length>0?`Discovered ${Y.length} remote project${Y.length===1?"":"s"}.`:"No projects discovered on remote node."}),x==="error"&&Z&&e.jsx("span",{className:"form-error add-node-modal__error",children:Z}),x==="idle"&&e.jsx("span",{className:"add-node-modal__hint",children:"Discover remote projects before adding this node."})]}),x==="success"&&Y.length>0&&e.jsx("div",{className:"add-node-modal__discovered-list","aria-label":"Discovered remote projects",children:Y.map(y=>e.jsxs("div",{className:"card add-node-modal__discovered-card",children:[e.jsxs("div",{className:"add-node-modal__discovered-row",children:[e.jsx("strong",{children:y.name}),e.jsx("span",{className:"card-status-badge card-status-badge--in-review",children:y.status})]}),e.jsx("div",{className:"add-node-modal__hint",children:y.path})]},`${y.id}-${y.path}`))})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),e.jsx("input",{className:"input",type:"number",min:Ce,max:Se,value:M,onChange:y=>_(Number(y.target.value)),disabled:A,"aria-invalid":!!$.maxConcurrent}),e.jsx("span",{className:"add-node-modal__hint",children:"Max simultaneous task agents (1–10)"}),$.maxConcurrent&&e.jsx("span",{className:"form-error add-node-modal__error",children:$.maxConcurrent})]}),e.jsxs("section",{className:"add-node-modal__projects","aria-label":"Project path mappings",children:[e.jsx("h4",{className:"add-node-modal__projects-title",children:"Attach Existing Projects"}),e.jsx("p",{className:"add-node-modal__hint",children:"Select existing projects to run on this node and provide the node-specific absolute path for each one."}),m.length===0?e.jsx("p",{className:"add-node-modal__hint",children:"No projects are currently registered."}):e.jsx("div",{className:"add-node-modal__project-list",children:m.map(y=>{const L=y.id in C,D=$.projectMappings[y.id];return e.jsxs("div",{className:"card add-node-modal__project-card",children:[e.jsxs("label",{className:"checkbox-label add-node-modal__project-toggle",children:[e.jsx("input",{type:"checkbox",checked:L,onChange:()=>T(y),disabled:A}),e.jsx("span",{children:y.name})]}),L&&e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Path on this node"}),g==="remote"&&x==="success"&&e.jsx("span",{className:"add-node-modal__hint",children:(()=>{const K=Y.filter(ae=>ae.name===y.name);return K.length===1?`Remote-authoritative path discovered: ${K[0].path}`:K.length>1?"Multiple remote projects matched this name. Enter the correct path manually.":"No exact remote name match. Enter this path manually."})()}),e.jsx("input",{className:"input",type:"text",value:C[y.id]??"",onChange:K=>E(y.id,K.target.value),disabled:A,placeholder:"/absolute/path/to/project","aria-invalid":!!D}),D&&e.jsx("span",{className:"form-error add-node-modal__error",children:D})]})]},y.id)})})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:X,disabled:A,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm","data-testid":"add-node-submit",onClick:J,disabled:A,children:A?"Adding...":"Add Node"})]})]})}):null}function Js(){const[t,r]=s.useState([]),[a,i]=s.useState(!1),[u,m]=s.useState(null),[o,j]=s.useState(!1),[g,c]=s.useState(null),[N,w]=s.useState(!1),b=s.useCallback(async()=>{i(!0),m(null);try{const _=await fetch("/api/docker/contexts");if(!_.ok)throw new Error(`Failed to load Docker contexts (${_.status})`);const l=await _.json();return r(l),l}catch(_){const l=_ instanceof Error?_.message:String(_);throw m(l),_}finally{i(!1)}},[]),d=s.useCallback(async _=>{j(!0);try{const l=await fetch("/api/docker/test-connection",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({hostConfig:_})});if(!l.ok)throw new Error(`Failed to test Docker connection (${l.status})`);const v=await l.json();return c(v),v}finally{j(!1)}},[]),M=s.useCallback(async()=>{w(!0);try{const _=await fetch("/api/docker/local-available");if(!_.ok)throw new Error(`Failed to check local Docker availability (${_.status})`);return await _.json()}finally{w(!1)}},[]);return{contexts:t,isLoadingContexts:a,contextsError:u,loadContexts:b,isTestingConnection:o,lastTestResult:g,testConnection:d,isCheckingLocal:N,checkLocalDocker:M}}function Ws({value:t,onChange:r}){const[a,i]=s.useState(!!(t?.tlsCaPath||t?.tlsCertPath||t?.tlsKeyPath||t?.tlsVerify));s.useEffect(()=>{a||r({tlsVerify:void 0,tlsCaPath:void 0,tlsCertPath:void 0,tlsKeyPath:void 0})},[a,r]);const u=s.useMemo(()=>({tlsVerify:t?.tlsVerify??!0,tlsCaPath:t?.tlsCaPath??"",tlsCertPath:t?.tlsCertPath??"",tlsKeyPath:t?.tlsKeyPath??""}),[t]);return e.jsxs("div",{className:"docker-tls-config",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:a,onChange:m=>i(m.target.checked)}),"Use TLS"]}),a&&e.jsxs("div",{className:"docker-tls-config__fields",children:[e.jsxs("div",{className:"docker-tls-config__field",children:[e.jsx("label",{htmlFor:"docker-tls-ca-path",children:"CA Certificate Path"}),e.jsx("input",{id:"docker-tls-ca-path",className:"input",value:u.tlsCaPath,onChange:m=>r({...u,tlsCaPath:m.target.value}),placeholder:"/etc/docker/ca.pem"})]}),e.jsxs("div",{className:"docker-tls-config__field",children:[e.jsx("label",{htmlFor:"docker-tls-cert-path",children:"Client Certificate Path"}),e.jsx("input",{id:"docker-tls-cert-path",className:"input",value:u.tlsCertPath,onChange:m=>r({...u,tlsCertPath:m.target.value}),placeholder:"/etc/docker/cert.pem"})]}),e.jsxs("div",{className:"docker-tls-config__field",children:[e.jsx("label",{htmlFor:"docker-tls-key-path",children:"Client Key Path"}),e.jsx("input",{id:"docker-tls-key-path",className:"input",value:u.tlsKeyPath,onChange:m=>r({...u,tlsKeyPath:m.target.value}),placeholder:"/etc/docker/key.pem"})]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:u.tlsVerify,onChange:m=>r({...u,tlsVerify:m.target.checked})}),"Verify TLS Certificate"]})]})]})}function Gs({value:t,onChange:r,onError:a}){const i=t?.context?"context":t?.host?"host":"local",[u,m]=s.useState(i),[o,j]=s.useState(t?.context??""),[g,c]=s.useState(t?.host??""),[N,w]=s.useState(null),{contexts:b,isLoadingContexts:d,contextsError:M,loadContexts:_,testConnection:l,isTestingConnection:v,lastTestResult:C,checkLocalDocker:k,isCheckingLocal:$}=Js(),V=s.useMemo(()=>({tlsVerify:t?.tlsVerify,tlsCaPath:t?.tlsCaPath,tlsCertPath:t?.tlsCertPath,tlsKeyPath:t?.tlsKeyPath}),[t]);s.useEffect(()=>{if(u==="local"){r({});return}if(u==="context"){_().catch(p=>a?.(p instanceof Error?p.message:String(p))),r(o?{context:o}:{});return}r({host:g,...V})},[u]);const A=s.useCallback(p=>{u==="host"&&r({host:g,...p})},[g,u,r]);return e.jsxs("div",{className:"docker-target-selector",children:[e.jsxs("div",{className:"docker-target-selector__modes",role:"group","aria-label":"Docker target mode",children:[e.jsx("button",{type:"button",className:`btn btn-sm ${u==="local"?"docker-target-selector__mode-active":""}`,onClick:()=>{m("local"),k().then(p=>w(p.available?`Docker is available${p.version?` (${p.version})`:""}`:`Docker not found${p.error?`: ${p.error}`:""}`)).catch(p=>{const x=p instanceof Error?p.message:String(p);w(`Docker not found: ${x}`),a?.(x)})},children:"Local Docker"}),e.jsx("button",{type:"button",className:`btn btn-sm ${u==="context"?"docker-target-selector__mode-active":""}`,onClick:()=>m("context"),children:"Docker Context"}),e.jsx("button",{type:"button",className:`btn btn-sm ${u==="host"?"docker-target-selector__mode-active":""}`,onClick:()=>m("host"),children:"Remote Host"})]}),u==="local"&&N&&e.jsx("div",{className:"docker-target-selector__status",children:N}),u==="context"&&e.jsxs("div",{className:"docker-target-selector__panel",children:[e.jsxs("div",{className:"docker-target-selector__context-row",children:[e.jsxs("select",{className:"select",value:o,onChange:p=>{const x=p.target.value;j(x),r(x?{context:x}:{})},children:[e.jsx("option",{value:"",children:"Select context"}),b.map(p=>e.jsxs("option",{value:p.name,children:[p.name,p.isCurrentContext?" (current)":"",p.dockerHost?` — ${p.dockerHost}`:""]},p.name))]}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon",onClick:()=>void _(),disabled:d,"aria-label":"Refresh contexts",children:e.jsx(Ne,{size:14})})]}),M&&e.jsx("div",{className:"docker-target-selector__error",children:M})]}),u==="host"&&e.jsxs("div",{className:"docker-target-selector__panel",children:[e.jsxs("div",{className:"docker-target-selector__field",children:[e.jsx("label",{htmlFor:"docker-target-selector-host",children:"Docker Host"}),e.jsx("input",{id:"docker-target-selector-host",className:"input",placeholder:"tcp://host:2376",value:g,onChange:p=>{const x=p.target.value;c(x),r({host:x,...V})}})]}),e.jsx(Ws,{value:V,onChange:A})]}),e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void l(u==="local"?void 0:u==="context"?{context:o}:{host:g,...V}),disabled:v||$,children:v?"Testing...":"Test Connection"}),C&&e.jsx("div",{className:C.success?"docker-target-selector__success":"docker-target-selector__error",children:C.success?`Connected${C.dockerVersion?` (Docker ${C.dockerVersion})`:""}`:C.error??"Connection failed"})]})}const je="http://localhost:4040";function Zs({isOpen:t,onClose:r,onSubmit:a,addToast:i}){const[u,m]=s.useState(""),[o,j]=s.useState({}),[g,c]=s.useState(je),[N,w]=s.useState("auto"),[b,d]=s.useState(""),[M,_]=s.useState(!1),[l,v]=s.useState(!1),[C,k]=s.useState(!0),[$,V]=s.useState(4096),[A,p]=s.useState(2),[x,S]=s.useState(!1),[Z,H]=s.useState("runfusion/fusion"),[Y,ee]=s.useState("latest"),[U,X]=s.useState([]),[G,te]=s.useState([]),[J,T]=s.useState({}),[E,y]=s.useState(!1),L=s.useCallback(()=>{m(""),j({}),c(je),w("auto"),d(""),_(!1),v(!1),k(!0),V(4096),p(2),S(!1),H("runfusion/fusion"),ee("latest"),X([]),te([]),T({}),y(!1)},[]),D=s.useCallback(()=>{E||(L(),r())},[r,L,E]);s.useEffect(()=>{if(!t){L();return}const h=O=>{O.key==="Escape"&&(O.preventDefault(),D())};return document.addEventListener("keydown",h),()=>document.removeEventListener("keydown",h)},[D,t,L]);const K=s.useMemo(()=>({nodeId:null,name:u.trim(),imageName:Z.trim()||"runfusion/fusion",imageTag:Y.trim()||"latest",hostConfig:{context:o.context?.trim()||void 0,host:o.host?.trim()||void 0,tlsVerify:o.tlsVerify,tlsCaPath:o.tlsCaPath?.trim()||void 0,tlsCertPath:o.tlsCertPath?.trim()||void 0,tlsKeyPath:o.tlsKeyPath?.trim()||void 0},envVars:Object.fromEntries(U.map(h=>[h.key.trim(),h.value]).filter(([h])=>!!h)),volumeMounts:G.map(h=>({hostPath:h.hostPath.trim(),containerPath:h.containerPath.trim(),mode:h.mode})).filter(h=>h.hostPath&&h.containerPath),resourceSizing:{memoryMB:$,cpus:A},extraClis:[M?"claude-cli":null,l?"droid-cli":null].filter(Boolean),persistentStorage:C,reachableUrl:g.trim()||null,apiKey:N==="manual"&&b.trim()||null}),[b,N,A,o,U,Z,Y,M,l,$,G,u,C,g]),ae=s.useCallback(()=>{X(h=>[...h,{key:"",value:""}])},[]),ne=s.useCallback((h,O)=>{X(B=>B.map((q,oe)=>oe===h?O:q))},[]),se=s.useCallback(h=>{X(O=>O.filter((B,q)=>q!==h))},[]),le=s.useCallback(()=>{te(h=>[...h,{hostPath:"",containerPath:"",mode:"rw"}])},[]),R=s.useCallback((h,O)=>{te(B=>B.map((q,oe)=>oe===h?O:q))},[]),I=s.useCallback(h=>{te(O=>O.filter((B,q)=>q!==h))},[]),W=s.useCallback(async()=>{if(E)return;const h={};if((!K.name||K.name.length>64)&&(h.name="Name is required and must be 64 characters or fewer"),K.reachableUrl||(h.reachableUrl="URL is required"),$<512&&(h.memoryMB="Memory must be at least 512 MB"),A<.5&&(h.cpus="CPUs must be at least 0.5"),T(h),!(Object.keys(h).length>0)){y(!0);try{await a(K),D()}catch{}finally{y(!1)}}},[D,A,K,$,a,E]);return t?e.jsx("div",{className:"modal-overlay open",onClick:D,children:e.jsxs("div",{className:"modal docker-onboarding",role:"dialog","aria-modal":"true","aria-label":"Docker node onboarding",onClick:h=>h.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Provision Docker Node"}),e.jsx("button",{className:"modal-close",onClick:D,disabled:E,"aria-label":"Close onboarding modal",children:"×"})]}),e.jsxs("div",{className:"modal-body docker-onboarding__body",children:[e.jsxs("section",{className:"docker-onboarding__section",children:[e.jsx("h4",{className:"docker-onboarding__section-title",children:"Required Settings"}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Node Name"}),e.jsx("input",{className:"input",value:u,onChange:h=>m(h.target.value),disabled:E,placeholder:"my-docker-node",autoFocus:!0})]}),J.name&&e.jsx("div",{className:"form-error",children:J.name}),e.jsx(Gs,{value:o,onChange:j}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Reachable URL"}),e.jsx("input",{className:"input",value:g,onChange:h=>c(h.target.value),disabled:E,placeholder:je})]}),J.reachableUrl&&e.jsx("div",{className:"form-error",children:J.reachableUrl}),e.jsxs("div",{className:"docker-onboarding__radio-group",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"radio",checked:N==="auto",onChange:()=>w("auto"),disabled:E}),"Auto-generate"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"radio",checked:N==="manual",onChange:()=>w("manual"),disabled:E}),"Provide manually"]})]}),N==="manual"&&e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:b,onChange:h=>d(h.target.value),disabled:E,placeholder:"Enter API key"})]}),e.jsxs("div",{className:"docker-onboarding__checkbox-group",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:M,onChange:h=>_(h.target.checked),disabled:E}),"Claude CLI"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:l,onChange:h=>v(h.target.checked),disabled:E}),"Droid CLI"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:C,onChange:h=>k(h.target.checked),disabled:E}),"Keep data across container recreations"]})]}),e.jsxs("div",{className:"docker-onboarding__inline-fields",children:[e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Memory (MB)"}),e.jsx("input",{className:"input",type:"number",min:512,value:$,onChange:h=>V(Number(h.target.value)),disabled:E})]}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"CPUs"}),e.jsx("input",{className:"input",type:"number",min:.5,step:.5,value:A,onChange:h=>p(Number(h.target.value)),disabled:E})]})]}),J.memoryMB&&e.jsx("div",{className:"form-error",children:J.memoryMB}),J.cpus&&e.jsx("div",{className:"form-error",children:J.cpus})]}),e.jsxs("section",{className:"docker-onboarding__section",children:[e.jsxs("button",{type:"button",className:`docker-onboarding__advanced-toggle ${x?"is-expanded":""}`,onClick:()=>S(h=>!h),disabled:E,children:[e.jsx("span",{children:"Advanced"}),e.jsx(we,{})]}),e.jsx("div",{className:`docker-onboarding__advanced-content ${x?"is-expanded":""}`,children:e.jsxs("div",{children:[e.jsxs("div",{className:"docker-onboarding__inline-fields",children:[e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Image"}),e.jsx("input",{className:"input",value:Z,onChange:h=>H(h.target.value),disabled:E,placeholder:"runfusion/fusion"})]}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Tag"}),e.jsx("input",{className:"input",value:Y,onChange:h=>ee(h.target.value),disabled:E,placeholder:"latest"})]})]}),e.jsxs("div",{className:"docker-onboarding__kv-list",children:[e.jsx("h5",{children:"Environment Variables"}),U.map((h,O)=>e.jsxs("div",{className:"docker-onboarding__kv-row docker-onboarding__kv-row--env",children:[e.jsx("input",{className:"input",placeholder:"KEY",value:h.key,disabled:E,onChange:B=>ne(O,{key:B.target.value,value:h.value})}),e.jsx("input",{className:"input",placeholder:"Value",value:h.value,disabled:E,onChange:B=>ne(O,{key:h.key,value:B.target.value})}),e.jsx("button",{type:"button",className:"btn btn-icon","aria-label":"Remove environment variable",onClick:()=>se(O),disabled:E,children:e.jsx(_e,{size:14})})]},`env-${O}`)),e.jsxs("button",{type:"button",className:"btn btn-sm docker-onboarding__kv-add",onClick:ae,disabled:E,children:[e.jsx(he,{size:14}),"Add variable"]})]}),e.jsxs("div",{className:"docker-onboarding__kv-list",children:[e.jsx("h5",{children:"Volume Mounts"}),G.map((h,O)=>e.jsxs("div",{className:"docker-onboarding__kv-row docker-onboarding__kv-row--mount",children:[e.jsx("input",{className:"input",placeholder:"Host path",value:h.hostPath,disabled:E,onChange:B=>R(O,{hostPath:B.target.value,containerPath:h.containerPath,mode:h.mode})}),e.jsx("input",{className:"input",placeholder:"Container path",value:h.containerPath,disabled:E,onChange:B=>R(O,{hostPath:h.hostPath,containerPath:B.target.value,mode:h.mode})}),e.jsxs("select",{className:"select",value:h.mode,disabled:E,onChange:B=>R(O,{hostPath:h.hostPath,containerPath:h.containerPath,mode:B.target.value==="ro"?"ro":"rw"}),children:[e.jsx("option",{value:"rw",children:"rw"}),e.jsx("option",{value:"ro",children:"ro"})]}),e.jsx("button",{type:"button",className:"btn btn-icon","aria-label":"Remove volume mount",onClick:()=>I(O),disabled:E,children:e.jsx(_e,{size:14})})]},`mount-${O}`)),e.jsxs("button",{type:"button",className:"btn btn-sm docker-onboarding__kv-add",onClick:le,disabled:E,children:[e.jsx(he,{size:14}),"Add mount"]})]})]})})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn",onClick:D,disabled:E,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",onClick:()=>void W(),disabled:E,children:E?"Creating...":"Create Docker Node"})]})]})}):null}function Qs({nodeId:t,entries:r,loading:a=!1,singleNode:i=!1}){const[u,m]=s.useState(!1),[o,j]=s.useState("all"),[g,c]=s.useState("all"),N=s.useCallback(()=>{m(l=>!l)},[]),w=s.useMemo(()=>{const l=new Set;for(const v of r)l.add(v.nodeName);return Array.from(l).sort()},[r]),b=s.useMemo(()=>{let l=[...r];return o!=="all"&&(l=l.filter(v=>v.direction===o)),!i&&g!=="all"&&(l=l.filter(v=>v.nodeName===g)),l.sort((v,C)=>{const k=new Date(v.timestamp).getTime();return new Date(C.timestamp).getTime()-k}),l},[r,o,g,i]),d=s.useCallback(l=>new Date(l).toLocaleString(),[]),M=s.useCallback(l=>{switch(l){case"success":return"settings-sync-log__badge--success";case"conflict":return"settings-sync-log__badge--conflict";case"error":return"settings-sync-log__badge--error";default:return""}},[]),_=s.useCallback(l=>{switch(l){case"success":return"Success";case"conflict":return"Conflict";case"error":return"Error";default:return l}},[]);return e.jsxs("div",{className:"settings-sync-log",children:[e.jsxs("button",{className:"settings-sync-log__header",type:"button",onClick:N,"aria-expanded":u,"data-testid":"settings-sync-log-header",children:[e.jsx(we,{size:16,className:`settings-sync-log__chevron ${u?"settings-sync-log__chevron--expanded":""}`}),e.jsxs("span",{children:[r.length," ",r.length===1?"entry":"entries"]})]}),u&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"settings-sync-log__filters",children:[e.jsxs("label",{children:["Direction:",e.jsxs("select",{value:o,onChange:l=>j(l.target.value),children:[e.jsx("option",{value:"all",children:"All"}),e.jsx("option",{value:"push",children:"Push"}),e.jsx("option",{value:"pull",children:"Pull"})]})]}),!i&&e.jsxs("label",{children:["Node:",e.jsxs("select",{value:g,onChange:l=>c(l.target.value),children:[e.jsx("option",{value:"all",children:"All Nodes"}),w.map(l=>e.jsx("option",{value:l,children:l},l))]})]})]}),a&&r.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"Loading..."}):b.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"No sync history available"}):e.jsx("div",{className:"settings-sync-log__list",children:b.map(l=>e.jsxs("div",{className:"settings-sync-log__entry",children:[e.jsx("span",{className:"settings-sync-log__entry-timestamp",children:d(l.timestamp)}),e.jsx("span",{className:"settings-sync-log__entry-direction",children:l.direction==="push"?e.jsx(Be,{size:14,"data-testid":"upload-icon"}):e.jsx(Te,{size:14,"data-testid":"download-icon"})}),e.jsx("span",{className:`settings-sync-log__entry-result ${M(l.result)}`,children:_(l.result)}),!i&&e.jsx("span",{className:"settings-sync-log__entry-node",children:l.nodeName}),l.details&&e.jsx("span",{className:"settings-sync-log__entry-details",title:l.details,children:hs(l.details??"")})]},l.id))})]})]})}function et(t,r){const a=typeof t=="string"?t:JSON.stringify(t,null,2),i=typeof r=="string"?r:JSON.stringify(r,null,2);if(a===i)return a;const u=a.split(`
|
|
12
|
-
`),m=i.split(`
|
|
13
|
-
`),o=[],j=Math.max(u.length,m.length);for(let g=0;g<j;g++){const c=u[g],N=m[g];c!==void 0&&c!==N&&o.push(`- ${c}`),N!==void 0&&N!==c&&o.push(`+ ${N}`),c!==void 0&&c===N&&o.push(` ${c}`)}return o.join(`
|
|
14
|
-
`)}function st({isOpen:t,onClose:r,onResolve:a,conflicts:i,localNodeName:u,remoteNodeName:m,addToast:o}){const[j,g]=s.useState({}),[c,N]=s.useState(!1);s.useEffect(()=>{const l={};for(const v of i)j[v.key]||(l[v.key]={resolution:"local"});Object.keys(l).length>0&&g(v=>({...v,...l}))},[i,j]),s.useEffect(()=>{if(!t)return;const l=v=>{v.key==="Escape"&&(v.preventDefault(),r())};return document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l)},[t,r]);const w=s.useCallback((l,v)=>{g(C=>{const k=C[l]??{};return v==="manual"?{...C,[l]:{resolution:"manual",manualValue:k.manualValue??JSON.stringify(i.find($=>$.key===l)?.localValue??null,null,2)}}:{...C,[l]:{resolution:v}}})},[i]),b=s.useCallback((l,v)=>{g(C=>({...C,[l]:{...C[l],resolution:"manual",manualValue:v}}))},[]),d=s.useCallback(l=>{const v={};for(const C of i)v[C.key]={resolution:l};g(v)},[i]),M=s.useCallback(async()=>{N(!0);try{const l=i.map(v=>{const C=j[v.key]??{resolution:"local"};let k;switch(C.resolution){case"remote":k=v.remoteValue;break;case"manual":try{k=JSON.parse(C.manualValue??"null")}catch{k=C.manualValue??null}break;case"local":default:k=v.localValue;break}return{key:v.key,value:k}});await a(l),o("Settings conflicts resolved successfully","success"),r()}catch(l){const v=l instanceof Error?l.message:"Failed to resolve conflicts";o(v,"error")}finally{N(!1)}},[o,i,r,a,j]),_=s.useMemo(()=>{const l={};for(const v of i)l[v.key]=et(v.localValue,v.remoteValue);return l},[i]);return!t||i.length===0?null:e.jsx("div",{className:"modal-overlay open",onClick:r,children:e.jsxs("div",{className:"modal modal-lg settings-sync-conflict-modal",onClick:l=>l.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Resolve Settings Conflicts",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Resolve Settings Conflicts"}),e.jsx("button",{className:"modal-close",onClick:r,"aria-label":"Close conflict modal",children:"×"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("div",{className:"settings-sync-conflict-modal__conflict-list",children:i.map(l=>{const v=j[l.key]??{resolution:"local"},C=_[l.key];return e.jsxs("div",{className:"settings-sync-conflict-modal__conflict-item",children:[e.jsx("div",{className:"settings-sync-conflict-modal__key",children:l.key}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-panel",children:[e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:u}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:C})})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:m}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:C})})]})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__resolution",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:v.resolution==="local",onChange:()=>w(l.key,"local")}),"Keep Local"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:v.resolution==="remote",onChange:()=>w(l.key,"remote")}),"Keep Remote"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:v.resolution==="manual",onChange:()=>w(l.key,"manual")}),"Merge Manually"]})]}),v.resolution==="manual"&&e.jsx("textarea",{className:"settings-sync-conflict-modal__manual-input",value:v.manualValue??"",onChange:k=>b(l.key,k.target.value),placeholder:"Enter JSON value..."})]},l.key)})}),e.jsxs("div",{className:"settings-sync-conflict-modal__bulk-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:()=>d("local"),type:"button",children:"Resolve All: Keep Local"}),e.jsx("button",{className:"btn btn-sm",onClick:()=>d("remote"),type:"button",children:"Resolve All: Keep Remote"})]})]}),e.jsxs("div",{className:"modal-actions settings-sync-conflict-modal__footer",children:[e.jsx("button",{className:"btn btn-sm",onClick:r,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:M,disabled:c,children:c?"Resolving...":"Confirm"})]})]})})}const He=/(KEY|TOKEN|SECRET|PASSWORD)/i;function be(t){if(!t)return"—";const r=new Date(t);return Number.isNaN(r.getTime())?"—":r.toLocaleString()}function tt(t){if(!t)return"—";const r=new Date(t),a=Date.now();if(Number.isNaN(r.getTime())||r.getTime()>a)return"—";const i=Math.floor((a-r.getTime())/1e3);if(i<60)return`${i}s`;const u=Math.floor(i/60);if(u<60)return`${u}m`;const m=Math.floor(u/60);return m<24?`${m}h ${u%60}m`:`${Math.floor(m/24)}d ${m%24}h`}function at(t){switch(t){case"synced":return"node-detail-modal__sync-dot--synced";case"diff":return"node-detail-modal__sync-dot--diff";case"error":return"node-detail-modal__sync-dot--error";case"pending":return"node-detail-modal__sync-dot--pending";case"never-synced":default:return"node-detail-modal__sync-dot--never"}}function nt(t){return t==="running"?"success":t==="creating"||t==="recreating"||t==="restarting"?"warning":"error"}function rt(t){return t?`${t.charAt(0).toUpperCase()}${t.slice(1)}`:"Unknown"}function lt(t){if(!t)return"—";try{const r=new URL(t);return r.port?r.port:r.protocol==="https:"?"443":r.protocol==="http:"?"80":"—"}catch{return"—"}}function ot(t,r){return He.test(t)?"••••••••":r}function ct({isOpen:t,onClose:r,node:a,projects:i,onUpdate:u,onHealthCheck:m,addToast:o,syncStatus:j,onPushSettings:g,onPullSettings:c,onSyncAuth:N,syncHistory:w=[],onResolveConflicts:b,managedDockerNode:d,containerStatus:M,onFetchContainerStatus:_,onFetchLogs:l,onUpdateDockerConfig:v,onFetchDockerConfigDiff:C}){const k=s.useRef(!0),[$,V]=s.useState(!1),[A,p]=s.useState(""),[x,S]=s.useState(""),[Z,H]=s.useState(""),[Y,ee]=s.useState(2),[U,X]=s.useState(!1),[G,te]=s.useState(!1),[J,T]=s.useState(!1),[E,y]=s.useState(!1),[L,D]=s.useState(null),[K,ae]=s.useState(!1),[ne]=s.useState([]),[se,le]=s.useState(M),[R,I]=s.useState(!1),[W,h]=s.useState(!1),[O,B]=s.useState(""),[q,oe]=s.useState(!1),[fe,Me]=s.useState(!1),[f,F]=s.useState(a?.dockerConfig??null),[Pe,Ee]=s.useState({}),[ie,Re]=s.useState(!1),[qe,Ae]=s.useState(!1);s.useEffect(()=>(k.current=!0,()=>{k.current=!1}),[]),s.useEffect(()=>{le(M)},[M]),s.useEffect(()=>{if(!a||!t){V(!1),h(!1),B("");return}p(a.name),S(a.url??""),H(a.apiKey??""),ee(a.maxConcurrent),V(!1),F(a.dockerConfig??null),Me(!1),Ee({})},[t,a]),s.useEffect(()=>{if(!t)return;const n=P=>{P.key==="Escape"&&(P.preventDefault(),r())};return document.addEventListener("keydown",n),()=>document.removeEventListener("keydown",n)},[t,r]);const ge=s.useMemo(()=>a?fs(i,a):[],[a,i]),Ye=s.useMemo(()=>d?d.hostConfig.type==="remote"?d.hostConfig.host??"—":"Local Docker":"—",[d]),Xe=s.useMemo(()=>!d?.resourceSizing?.cpuLimit&&!d?.resourceSizing?.memoryLimit?"Default":`${d.resourceSizing?.cpuLimit??"Default CPU"} / ${d.resourceSizing?.memoryLimit??"Default memory"}`,[d]),Je=s.useCallback(async()=>{if(a)try{if(await m(a.id),!k.current)return;o(`Health check completed for ${a.name}`,"success")}catch(n){if(!k.current)return;const P=n instanceof Error?n.message:"Health check failed";o(P,"error")}},[o,a,m]),We=s.useCallback(async()=>{if(!(!a||!g)){D(null),te(!0);try{if(await g(a.id),!k.current)return;o("Settings pushed successfully","success")}catch(n){if(!k.current)return;const P=n instanceof Error?n.message:"Push settings failed";D(P),o(P,"error")}finally{k.current&&te(!1)}}},[o,a,g]),Ge=s.useCallback(async()=>{if(!(!a||!c)){D(null),T(!0);try{if(await c(a.id),!k.current)return;o("Settings pulled successfully","success")}catch(n){if(!k.current)return;const P=n instanceof Error?n.message:"Pull settings failed";D(P),o(P,"error")}finally{k.current&&T(!1)}}},[o,a,c]),Ze=s.useCallback(async()=>{if(!(!a||!N)){D(null),y(!0);try{if(await N(a.id),!k.current)return;o("Auth credentials synced successfully","success")}catch(n){if(!k.current)return;const P=n instanceof Error?n.message:"Auth sync failed";D(P),o(P,"error")}finally{k.current&&y(!1)}}},[o,a,N]),Qe=s.useCallback(()=>{D(null)},[]),es=s.useCallback(async()=>{if(!(!d||!_)){I(!0);try{const n=await _(d.id);if(!k.current)return;le(n)}catch(n){const P=n instanceof Error?n.message:"Failed to fetch container status";o(P,"error")}finally{k.current&&I(!1)}}},[o,d,_]),ss=s.useCallback(async()=>{if(!(!d||!l)){h(!0),oe(!0);try{const n=await l(d.id);if(!k.current)return;B(n)}catch(n){if(!k.current)return;B("");const P=n instanceof Error?n.message:"Failed to fetch container logs";o(P,"error")}finally{k.current&&oe(!1)}}},[o,d,l]),ts=s.useCallback(async()=>{if(!a||U)return;const n=A.trim();if(!n){o("Name is required","error");return}if(a.type==="remote"&&!x.trim()){o("URL is required for remote nodes","error");return}if(!Number.isFinite(Y)||Y<1){o("Concurrency must be at least 1","error");return}X(!0);try{await u(a.id,{name:n,url:a.type==="remote"&&x.trim()||void 0,apiKey:a.type==="remote"&&Z||void 0,maxConcurrent:Y}),o(`Updated ${n}`,"success"),V(!1)}catch(P){const Q=P instanceof Error?P.message:"Failed to update node";o(Q,"error")}finally{X(!1)}},[o,Z,U,Y,A,a,u,x]);s.useEffect(()=>{!a?.dockerConfig||!C||!t||C(a.id).then(n=>{k.current&&Ae(n.needsRecreate)}).catch(()=>{k.current&&Ae(!1)})},[t,a,C]);const as=s.useCallback(async()=>{if(!(!a||!f||!v||ie)){Re(!0);try{const n=await v(a.id,{image:f.image,volumeMounts:f.volumeMounts,environment:f.environment,resources:f.resources,host:f.host,extraClis:f.extraClis,persistence:f.persistence,containerName:f.containerName});if(!k.current)return;F(n),o("Docker config saved","success")}catch(n){if(!k.current)return;const P=n instanceof Error?n.message:"Failed to save Docker config";o(P,"error")}finally{k.current&&Re(!1)}}},[o,f,ie,a,v]),ns=s.useCallback(()=>{a&&(p(a.name),S(a.url??""),H(a.apiKey??""),ee(a.maxConcurrent),V(!1))},[a]);if(!t||!a)return null;const re=se?.status??d?.status,rs=nt(re);return e.jsxs("div",{className:"modal-overlay open",onClick:r,children:[e.jsxs("div",{className:"modal modal-lg node-detail-modal",onClick:n=>n.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":`Node details for ${a.name}`,children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Node Details"}),e.jsx("button",{className:"modal-close",onClick:r,"aria-label":"Close node detail modal",children:"×"})]}),e.jsxs("div",{className:"modal-body node-detail-modal__body",children:[e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("div",{className:"node-detail-modal__section-header",children:[e.jsx("h4",{children:"Overview"}),!$&&e.jsxs("button",{className:"btn btn-sm",onClick:()=>V(!0),children:[e.jsx(gs,{size:14}),"Edit"]})]}),e.jsxs("div",{className:"node-detail-modal__grid",children:[e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Name"}),$?e.jsx("input",{className:"input",value:A,onChange:n=>p(n.target.value),disabled:U}):e.jsx("strong",{children:a.name})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Type"}),e.jsx("strong",{children:a.type==="local"?"Local":"Remote"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Status"}),e.jsx("strong",{children:a.status})]}),e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),$?e.jsx("input",{className:"input",type:"number",min:1,max:10,value:Y,onChange:n=>ee(Number(n.target.value)),disabled:U}):e.jsx("strong",{children:a.maxConcurrent})]}),a.type==="remote"&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"URL"}),$?e.jsx("input",{className:"input",value:x,onChange:n=>S(n.target.value),disabled:U}):e.jsx("strong",{children:a.url??"—"})]}),e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"API Key"}),$?e.jsx("input",{className:"input",type:"password",value:Z,onChange:n=>H(n.target.value),placeholder:"Leave blank to keep unchanged",disabled:U}):e.jsx("strong",{children:a.apiKey?"••••••••":"Not configured"})]})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Created"}),e.jsx("strong",{children:be(a.createdAt)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Updated"}),e.jsx("strong",{children:be(a.updatedAt)})]})]}),$&&e.jsxs("div",{className:"node-detail-modal__edit-actions",children:[e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:ts,disabled:U,children:[e.jsx($e,{size:14}),U?"Saving...":"Save"]}),e.jsxs("button",{className:"btn btn-sm",onClick:ns,disabled:U,children:[e.jsx(me,{size:14}),"Cancel"]})]})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("h4",{children:[a.type==="local"?"Projects":"Assigned Projects"," (",ge.length,")"]}),ge.length===0?e.jsx("p",{className:"node-detail-modal__empty",children:a.type==="local"?"No projects are running on this node.":"No projects are assigned to this node."}):e.jsx("ul",{className:"node-detail-modal__project-list",children:ge.map(n=>e.jsxs("li",{className:"node-detail-modal__project-item",children:[e.jsx("span",{children:n.name}),e.jsx("code",{children:n.id})]},n.id))})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Health"}),e.jsxs("div",{className:"node-detail-modal__health-row",children:[e.jsxs("span",{children:["Status: ",e.jsx("strong",{children:a.status})]}),e.jsxs("span",{children:["Last check: ",e.jsx("strong",{children:be(a.updatedAt)})]})]})]}),f&&e.jsxs("section",{className:"node-detail-modal__section node-detail-modal__docker-config",children:[e.jsxs("button",{className:"btn btn-sm node-detail-modal__docker-toggle",onClick:()=>Me(n=>!n),"aria-expanded":fe,children:[e.jsx(we,{size:14,className:fe?"node-detail-modal__docker-toggle-icon--expanded":""}),"Docker Configuration"]}),fe&&e.jsxs("div",{className:"node-detail-modal__docker-config-content",children:[e.jsx("div",{className:"node-detail-modal__grid",children:e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"Image"}),e.jsx("input",{className:"input",value:f.image,onChange:n=>F({...f,image:n.target.value})})]})}),e.jsxs("details",{children:[e.jsx("summary",{children:"Volume Mounts"}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[f.volumeMounts.map((n,P)=>e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:n.hostPath,placeholder:"Host path",onChange:Q=>{const z=[...f.volumeMounts];z[P]={...z[P],hostPath:Q.target.value},F({...f,volumeMounts:z})}}),e.jsx("input",{className:"input",value:n.containerPath,placeholder:"Container path",onChange:Q=>{const z=[...f.volumeMounts];z[P]={...z[P],containerPath:Q.target.value},F({...f,volumeMounts:z})}}),e.jsxs("select",{className:"input",value:n.mode??"rw",onChange:Q=>{const z=[...f.volumeMounts];z[P]={...z[P],mode:Q.target.value},F({...f,volumeMounts:z})},children:[e.jsx("option",{value:"rw",children:"rw"}),e.jsx("option",{value:"ro",children:"ro"})]}),e.jsxs("select",{className:"input",value:n.type??"volume",onChange:Q=>{const z=[...f.volumeMounts];z[P]={...z[P],type:Q.target.value},F({...f,volumeMounts:z})},children:[e.jsx("option",{value:"volume",children:"volume"}),e.jsx("option",{value:"bind",children:"bind"})]}),e.jsx("button",{className:"btn btn-sm",onClick:()=>F({...f,volumeMounts:f.volumeMounts.filter((Q,z)=>z!==P)}),children:"Remove"})]},`${n.hostPath}-${n.containerPath}-${P}`)),e.jsx("button",{className:"btn btn-sm",onClick:()=>F({...f,volumeMounts:[...f.volumeMounts,{hostPath:"",containerPath:"",mode:"rw",type:"volume"}]}),children:"Add Mount"})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Environment Variables"}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[Object.entries(f.environment).map(([n,P])=>{const Q=He.test(n)&&!Pe[n];return e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:n,onChange:z=>{const xe={...f.environment};delete xe[n],xe[z.target.value]=P,F({...f,environment:xe})}}),e.jsx("input",{className:"input",value:Q?"***":String(P),onChange:z=>F({...f,environment:{...f.environment,[n]:z.target.value}})}),e.jsx("button",{className:"btn btn-sm",onClick:()=>Ee(z=>({...z,[n]:!z[n]})),children:Pe[n]?e.jsx(xs,{size:14}):e.jsx(ps,{size:14})}),e.jsx("button",{className:"btn btn-sm",onClick:()=>{const z={...f.environment};delete z[n],F({...f,environment:z})},children:"Remove"})]},n)}),e.jsx("button",{className:"btn btn-sm",onClick:()=>{const n=`NEW_VAR_${Object.keys(f.environment).length+1}`;F({...f,environment:{...f.environment,[n]:""}})},children:"Add Variable"})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Resources"}),e.jsxs("div",{className:"node-detail-modal__docker-stack",children:[e.jsx("input",{className:"input",type:"number",placeholder:"Memory bytes (2 GB = 2147483648)",value:f.resources?.memoryBytes??"",onChange:n=>F({...f,resources:{...f.resources,memoryBytes:n.target.value?Number(n.target.value):void 0}})}),e.jsx("input",{className:"input",type:"number",placeholder:"CPU count",value:f.resources?.cpuCount??"",onChange:n=>F({...f,resources:{...f.resources,cpuCount:n.target.value?Number(n.target.value):void 0}})}),e.jsx("input",{className:"input",type:"number",placeholder:"PIDs limit",value:f.resources?.pidsLimit??"",onChange:n=>F({...f,resources:{...f.resources,pidsLimit:n.target.value?Number(n.target.value):void 0}})})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Host Config"}),e.jsxs("div",{className:"node-detail-modal__docker-stack",children:[e.jsx("input",{className:"input",placeholder:"Context name",value:f.host?.contextName??"",onChange:n=>F({...f,host:{...f.host,contextName:n.target.value}})}),e.jsx("input",{className:"input",placeholder:"Docker host URL",value:f.host?.dockerHost??"",onChange:n=>F({...f,host:{...f.host,dockerHost:n.target.value}})}),e.jsx("input",{className:"input",placeholder:"TLS CA cert path",value:f.host?.tlsCaCert??"",onChange:n=>F({...f,host:{...f.host,tlsCaCert:n.target.value}})}),e.jsx("input",{className:"input",placeholder:"TLS cert path",value:f.host?.tlsCert??"",onChange:n=>F({...f,host:{...f.host,tlsCert:n.target.value}})}),e.jsx("input",{className:"input",placeholder:"TLS key path",value:f.host?.tlsKey??"",onChange:n=>F({...f,host:{...f.host,tlsKey:n.target.value}})}),e.jsxs("label",{className:"node-detail-modal__checkbox",children:[e.jsx("input",{type:"checkbox",checked:f.host?.tlsVerify??!0,onChange:n=>F({...f,host:{...f.host,tlsVerify:n.target.checked}})}),"TLS verify"]})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Extra CLIs"}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[(f.extraClis??[]).map((n,P)=>e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:n,onChange:Q=>{const z=[...f.extraClis??[]];z[P]=Q.target.value,F({...f,extraClis:z})}}),e.jsx("button",{className:"btn btn-sm",onClick:()=>F({...f,extraClis:(f.extraClis??[]).filter((Q,z)=>z!==P)}),children:"Remove"})]},`${n}-${P}`)),e.jsx("button",{className:"btn btn-sm",onClick:()=>F({...f,extraClis:[...f.extraClis??[],""]}),children:"Add CLI"})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Persistence"}),e.jsxs("div",{className:"node-detail-modal__docker-stack",children:[e.jsx("input",{className:"input",placeholder:"Volume name",value:f.persistence?.volumeName??"",onChange:n=>F({...f,persistence:{...f.persistence,volumeName:n.target.value}})}),e.jsxs("label",{className:"node-detail-modal__checkbox",children:[e.jsx("input",{type:"checkbox",checked:f.persistence?.retainOnDelete??!1,onChange:n=>F({...f,persistence:{...f.persistence,retainOnDelete:n.target.checked}})}),"Retain on delete"]})]})]}),e.jsxs("div",{className:"node-detail-modal__docker-meta",children:[e.jsxs("span",{children:["Config v",f.configVersion," • Updated ",ke(f.lastUpdated??a.updatedAt)]}),qe&&e.jsx("span",{className:"node-detail-modal__docker-recreate",children:"Needs Recreate"})]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>void as(),disabled:ie,children:[e.jsx($e,{size:14}),ie?"Saving...":"Save Docker Config"]})]})]}),d&&e.jsxs("section",{className:"node-detail-modal__section docker-management",children:[e.jsx("h4",{children:"Docker Management"}),e.jsxs("div",{className:"docker-management__status-card",children:[e.jsxs("div",{className:"docker-management__status-row",children:[e.jsx("span",{className:`docker-management__status-dot docker-management__status-dot--${rs}`,"aria-hidden":!0}),e.jsx("strong",{children:rt(re)}),(re==="creating"||re==="recreating"||re==="restarting")&&e.jsx(De,{size:14,className:"spin","aria-hidden":!0})]}),e.jsxs("div",{className:"docker-management__status-meta",children:[re==="running"&&e.jsxs("span",{children:["Uptime: ",tt(se?.startedAt)]}),re!=="running"&&se?.exitCode!==void 0&&e.jsxs("span",{children:["Exit code: ",se.exitCode]}),(se?.error||d.errorMessage)&&e.jsx("span",{children:se?.error??d.errorMessage})]}),e.jsx("button",{className:"btn btn-sm",onClick:()=>void es(),disabled:!_||R,children:R?"Refreshing...":"Refresh Status"})]}),e.jsxs("div",{className:"node-detail-modal__grid docker-management__info-grid",children:[e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Image"}),e.jsx("strong",{children:e.jsxs("code",{children:[d.imageName,":",d.imageTag]})})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Container ID"}),e.jsx("strong",{children:e.jsx("code",{children:d.containerId?d.containerId.slice(0,12):"—"})})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Host"}),e.jsx("strong",{children:Ye})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Persistent Storage"}),e.jsx("strong",{children:d.persistentStorage?"Yes":"No"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Port"}),e.jsx("strong",{children:lt(d.reachableUrl)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Resource Sizing"}),e.jsx("strong",{children:Xe})]})]}),e.jsxs("div",{className:"docker-management__actions",children:[e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:"Available after FN-3113",children:[e.jsx(Ke,{size:14}),"Start"]}),e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:"Available after FN-3113",children:[e.jsx(Ue,{size:14}),"Stop"]}),e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:"Available after FN-3113",children:[e.jsx(De,{size:14}),"Restart"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void ss(),disabled:!l,children:[e.jsx(js,{size:14}),"View Logs"]})]}),W&&e.jsxs("div",{className:"docker-management__log-viewer",children:[e.jsxs("div",{className:"docker-management__log-viewer-header",children:[e.jsx("strong",{children:"Container Logs"}),e.jsx("button",{className:"btn-icon",onClick:()=>h(!1),"aria-label":"Close logs",children:e.jsx(me,{size:14})})]}),q?e.jsx("p",{children:"Fetching logs..."}):e.jsx("pre",{children:O.trim()||"No logs available"})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Environment Variables"}),e.jsx("dl",{className:"docker-management__env-list",children:Object.entries(d.envVars).map(([n,P])=>e.jsxs("div",{children:[e.jsx("dt",{children:n}),e.jsx("dd",{children:ot(n,P)})]},n))})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Volume Mounts"}),e.jsx("ul",{className:"docker-management__mounts-list",children:d.volumeMounts.map(n=>e.jsxs("li",{children:[e.jsxs("span",{children:[n.hostPath," → ",n.containerPath]}),n.readOnly&&e.jsx("span",{className:"node-card__type-badge",children:"Read-only"})]},`${n.hostPath}:${n.containerPath}`))})]})]}),a.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Settings Sync"}),j&&e.jsxs("div",{className:"node-detail-modal__sync-status",children:[e.jsx("span",{className:`node-detail-modal__sync-dot ${at(j.syncState)}`,"aria-hidden":!0}),e.jsxs("span",{children:["Last sync: ",e.jsx("strong",{children:j.lastSyncAt?ke(j.lastSyncAt):"Never synced"})]}),j.diffCount>0&&e.jsxs("span",{className:"node-detail-modal__sync-diff",children:["Differences: ",e.jsx("strong",{children:j.diffCount})]})]}),e.jsxs("div",{className:"node-detail-modal__sync-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:We,disabled:G||!g,children:[e.jsx(Be,{size:14}),G?"Pushing...":"Push Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:Ge,disabled:J||!c,children:[e.jsx(Te,{size:14}),J?"Pulling...":"Pull Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:Ze,disabled:E||!N,children:[e.jsx(Fe,{size:14}),E?"Syncing...":"Sync Auth"]})]}),L&&e.jsxs("div",{className:"node-detail-modal__sync-error",children:[e.jsx("span",{children:L}),e.jsx("button",{className:"node-detail-modal__sync-error-dismiss",onClick:Qe,"aria-label":"Dismiss error",children:e.jsx(me,{size:14})})]})]}),a.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Sync History"}),e.jsx(Qs,{nodeId:a.id,entries:w,singleNode:!0})]})]}),e.jsxs("div",{className:"modal-actions node-detail-modal__actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:Je,children:[e.jsx(Oe,{size:14}),"Health Check"]}),e.jsx("button",{className:"btn btn-sm",onClick:r,children:"Close"})]})]}),a.type==="remote"&&e.jsx(st,{isOpen:K,onClose:()=>ae(!1),onResolve:b??(async()=>{}),conflicts:ne,localNodeName:"Local",remoteNodeName:a.name,addToast:o})]})}const it=15e3,dt=1e3;function ut(){const[t,r]=s.useState([]),[a,i]=s.useState(!0),[u,m]=s.useState(null),o=s.useRef(null),j=s.useRef(0),g=s.useCallback(async()=>{try{m(null);const b=await Ie();r(b)}catch(b){m(b instanceof Error?b.message:"Failed to fetch managed Docker nodes")}},[]);s.useEffect(()=>{let b=!1;async function d(){i(!0);try{const _=await Ie();b||(r(_),m(null))}catch(_){b||m(_ instanceof Error?_.message:"Failed to fetch managed Docker nodes")}finally{b||i(!1)}}d();const M=()=>{if(document.visibilityState!=="visible")return;const _=Date.now();_-j.current<dt||(j.current=_,g())};return document.addEventListener("visibilitychange",M),()=>{b=!0,document.removeEventListener("visibilitychange",M)}},[g]),s.useEffect(()=>{if(!a)return o.current=setInterval(()=>{g()},it),()=>{o.current&&(clearInterval(o.current),o.current=null)}},[a,g]);const c=s.useCallback(async b=>bs(b),[]),N=s.useCallback(async(b,d)=>(await vs(b,d)).logs,[]),w=s.useCallback(async b=>{const d=await ys(b),M={...d,nodeId:d.nodeId??void 0,containerId:d.containerId??void 0,status:d.status,hostConfig:{type:d.hostConfig.host||d.hostConfig.context?"remote":"local",host:d.hostConfig.host,context:d.hostConfig.context},reachableUrl:d.reachableUrl??void 0,volumeMounts:d.volumeMounts.map(_=>({hostPath:_.hostPath,containerPath:_.containerPath,readOnly:_.mode==="ro"?!0:void 0})),persistentStorage:d.persistentStorage,resourceSizing:{cpuLimit:d.resourceSizing.cpus!==void 0?String(d.resourceSizing.cpus):void 0,memoryLimit:d.resourceSizing.memoryMB!==void 0?`${d.resourceSizing.memoryMB}MB`:void 0},errorMessage:d.errorMessage??void 0};return r(_=>[..._,M]),M},[]);return{dockerNodes:t,loading:a,error:u,refresh:g,getContainerStatus:c,getLogs:N,create:w}}function jt({addToast:t,onClose:r}){const{nodes:a,loading:i,error:u,refresh:m,register:o,update:j,unregister:g,healthCheck:c,patchDockerConfig:N,fetchDockerDiff:w,discoverRemoteProjects:b}=_s(),{projects:d,refresh:M}=Ns(),{meshState:_,loading:l,error:v}=Ds(),{syncStatusMap:C,pushSettings:k,pullSettings:$,syncAuth:V,trackNode:A,getAuthSyncState:p,getAuthProviders:x}=As(),{dockerNodes:S,loading:Z,refresh:H,getContainerStatus:Y,getLogs:ee,create:U}=ut(),[X,G]=s.useState(!1),[te,J]=s.useState(!1),[T,E]=s.useState(null);s.useEffect(()=>{const R=a.filter(I=>I.type==="remote");for(const I of R)A(I.id)},[a,A]),s.useEffect(()=>{if(!T)return;const R=a.find(I=>I.id===T.id)??null;E(R)},[a,T]);const y=s.useMemo(()=>{const R=a.length,I=a.filter(q=>q.status==="online").length,W=a.filter(q=>q.status==="offline"||q.status==="error").length,h=a.filter(q=>q.type==="remote").length,O=a.filter(q=>q.type==="remote"&&C[q.id]&&pe(C[q.id]).syncState==="synced").length,B=S.length;return{total:R,online:I,offline:W,remote:h,synced:O,docker:B}},[S.length,a,C]),L=s.useCallback(async R=>{await o(R),await M()},[M,o]),D=s.useCallback(async R=>{try{await U(R),t(`Docker node "${R.name}" created`,"success"),J(!1)}catch(I){const W=I instanceof Error?I.message:"Failed to create Docker node";throw t(W,"error"),I}},[t,U]),K=s.useMemo(()=>{const R=new Map;for(const I of S)I.nodeId&&R.set(I.nodeId,I);return R},[S]),ae=s.useCallback(async()=>{try{await Promise.all([m(),H()])}catch{t("Failed to refresh nodes","error")}},[t,m,H]),ne=s.useCallback(async R=>{try{await c(R),t("Node health check complete","success")}catch(I){const W=I instanceof Error?I.message:"Health check failed";t(W,"error")}},[t,c]),se=s.useCallback(async R=>{try{await g(R),t("Node removed","success"),T?.id===R&&E(null)}catch(I){const W=I instanceof Error?I.message:"Failed to remove node";t(W,"error")}},[t,T?.id,g]),le=s.useCallback(async(R,I)=>{await j(R,I)},[j]);return e.jsxs("div",{className:"nodes-view","data-testid":"nodes-view",children:[e.jsxs("div",{className:"nodes-view-header",children:[e.jsxs("div",{className:"nodes-view-title",children:[e.jsxs("h2",{children:[e.jsx(Ve,{size:20}),"Nodes"]}),e.jsxs("span",{className:"nodes-view-count",children:[a.length," registered"]})]}),e.jsxs("div",{className:"nodes-view-actions",children:[e.jsx("button",{className:"btn-icon nodes-view-close",onClick:r,"aria-label":"Close nodes view",children:e.jsx(me,{size:16})}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void ae(),disabled:i||Z,children:[e.jsx(Ne,{size:14,className:i?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>G(!0),children:[e.jsx(he,{size:14}),"Add Node"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>J(!0),title:"Add a managed Docker node",children:[e.jsx(ye,{size:14}),"Add Docker Node"]})]})]}),e.jsxs("div",{className:"nodes-view-stats",children:[e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-total",children:[e.jsx("span",{children:"Total"}),e.jsx("strong",{children:y.total})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--online","data-testid":"nodes-stat-online",children:[e.jsxs("span",{children:[e.jsx(Ps,{size:14})," Online"]}),e.jsx("strong",{children:y.online})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--offline","data-testid":"nodes-stat-offline",children:[e.jsxs("span",{children:[e.jsx(ws,{size:14})," Offline"]}),e.jsx("strong",{children:y.offline})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-remote",children:[e.jsxs("span",{children:[e.jsx(ks,{size:14})," Remote"]}),e.jsx("strong",{children:y.remote})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--synced","data-testid":"nodes-stat-synced",children:[e.jsxs("span",{children:[e.jsx(Ne,{size:14})," Synced"]}),e.jsx("strong",{children:y.synced})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-docker",children:[e.jsxs("span",{children:[e.jsx(ye,{size:14})," Docker"]}),e.jsx("strong",{children:y.docker})]})]}),(u||v)&&e.jsx("div",{className:"nodes-view-error",children:u??v}),!l&&_.length>0&&e.jsxs("section",{className:"nodes-view-topology","aria-label":"Mesh Topology",children:[e.jsx("h3",{className:"nodes-view-section-title",children:"Mesh Topology"}),e.jsx(qs,{nodes:_})]}),i?e.jsx("div",{className:"nodes-view-grid",children:Array.from({length:4}).map((R,I)=>e.jsx("div",{className:"node-card node-card--loading","aria-hidden":!0},I))}):a.length===0?e.jsxs("div",{className:"nodes-view-empty",children:[e.jsx("p",{children:"No nodes are registered yet."}),e.jsxs("button",{className:"btn btn-primary",onClick:()=>G(!0),children:[e.jsx(he,{size:14}),"Add First Node"]})]}):e.jsx("div",{className:"nodes-view-grid",children:a.map(R=>{const I=R.type==="remote"&&C[R.id]?pe(C[R.id]):void 0;return e.jsx(Ks,{node:R,projects:d,onHealthCheck:W=>{ne(W)},onEdit:W=>E(W),onRemove:W=>{se(W)},isLoading:i,syncStatus:I,authSyncState:R.type==="remote"?p(R.id):void 0,authSyncProviders:R.type==="remote"?x(R.id):void 0,managedDockerNode:K.get(R.id)},R.id)})}),e.jsx(Xs,{isOpen:X,onClose:()=>G(!1),onSubmit:L,onDiscoverRemoteProjects:b,addToast:t,projects:d}),e.jsx(Zs,{isOpen:te,onClose:()=>J(!1),onSubmit:D,addToast:t}),e.jsx(ct,{isOpen:T!==null,onClose:()=>E(null),node:T,projects:d,onUpdate:le,onHealthCheck:ne,addToast:t,syncStatus:T?.type==="remote"&&T&&C[T.id]?pe(C[T.id]):void 0,onPushSettings:k,onPullSettings:$,onSyncAuth:V,managedDockerNode:T?K.get(T.id):void 0,onFetchContainerStatus:Y,onFetchLogs:ee,onUpdateDockerConfig:N,onFetchDockerConfigDiff:w})]})}export{jt as NodesView};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as n,j as e}from"./vendor-react-K0fH_qHe.js";import{a6 as K,a7 as ce,a8 as ie,aj as le,aC as he,ab as se,aD as me,s as be,aE as fe,aF as xe,aG as ve,aH as pe,aI as ye,aJ as Re,an as _e,u as ge,aK as je,x as Se,aL as we,L as Ne,S as ke}from"./index-Ba-F8c1g.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const Ee="builtin",z={pageFetch:!0,github:!1,localDocs:!0,llmSynthesis:!0};function te(r){const t=r?.researchGlobalDefaults,i=r?.researchSettings;return{enabled:i?.enabled??r?.researchEnabled??r?.researchGlobalEnabled??!0,searchProvider:i?.searchProvider??t?.searchProvider??r?.researchGlobalWebSearchProvider??Ee,synthesisProvider:i?.synthesisProvider??t?.synthesisProvider,synthesisModelId:i?.synthesisModelId??t?.synthesisModelId,enabledSources:{webSearch:!0,pageFetch:i?.enabledSources?.pageFetch??t?.enabledSources?.pageFetch??z.pageFetch,github:i?.enabledSources?.github??t?.enabledSources?.github??z.github,localDocs:i?.enabledSources?.localDocs??t?.enabledSources?.localDocs??z.localDocs,llmSynthesis:i?.enabledSources?.llmSynthesis??t?.enabledSources?.llmSynthesis??z.llmSynthesis},limits:{maxConcurrentRuns:i?.limits?.maxConcurrentRuns??r?.researchMaxConcurrentRuns??r?.researchGlobalMaxConcurrentRuns??3,maxSourcesPerRun:i?.limits?.maxSourcesPerRun??t?.maxSourcesPerRun??r?.researchMaxSourcesPerRun??r?.researchGlobalMaxSourcesPerRun??20,maxDurationMs:i?.limits?.maxDurationMs??r?.researchDefaultTimeout??r?.researchGlobalDefaultTimeout??3e5,requestTimeoutMs:i?.limits?.requestTimeoutMs??r?.researchGlobalFetchTimeoutMs??3e4},defaultExportFormat:t?.defaultExportFormat??"markdown"}}const Ce=300,Ae=4e3,Te=["queued","running","cancelling","retry_waiting"];function ae(r,t){if(r instanceof _e){const i=r;return{message:r.message,status:r.status,code:i.researchCode??"INTERNAL_ERROR",setupHint:i.setupHint,retryable:i.retryable}}return r instanceof Error?{message:r.message,code:"INTERNAL_ERROR"}:{message:t,code:"INTERNAL_ERROR"}}function Ie(r){if(!r)return{cancelable:!1,retryable:!1,isTransitioning:!1,blockingReason:"No run selected"};const t=Te.includes(r.status),i=r.status==="queued"||r.status==="running",f=r.lifecycle?.retryable,y=r.status==="failed"||r.status==="timed_out",a=!!(y&&f);let g;return!i&&t?g="Run is already transitioning":!i&&r.status==="completed"?g="Completed runs cannot be cancelled":!i&&r.status==="cancelled"?g="Run is already cancelled":!i&&r.status==="retry_exhausted"?g="Retry attempts exhausted":!i&&r.status==="failed"?g="Failed runs cannot be cancelled":!i&&r.status==="timed_out"&&(g="Timed out runs cannot be cancelled"),!a&&y&&f===!1&&(g=r.lifecycle?.errorCode==="RETRY_EXHAUSTED"?"Retry attempts exhausted":"Run is not retryable"),{cancelable:i,retryable:a,isTransitioning:t,blockingReason:g}}function Pe(r){const t=r?.projectId,i=t??"",f=`${ie.RESEARCH_RUNS_PREFIX}${i}`,y=`${ie.RESEARCH_SELECTED_ID_PREFIX}${i}`,a=K(f,{maxAgeMs:ce}),g=K(y,{maxAgeMs:le}),N=n.useRef(Array.isArray(a)&&a.length>0),[j,A]=n.useState(()=>Array.isArray(a)?a:[]),[v,I]=n.useState(g??null),[F,S]=n.useState(null),[D,P]=n.useState({available:!0}),[q,L]=n.useState(!(Array.isArray(a)&&a.length>0)),[H,M]=n.useState(null),[T,_]=n.useState(null),[R,k]=n.useState(""),o=n.useRef(0),x=n.useRef(0),$=n.useRef(t);n.useEffect(()=>{$.current!==t&&($.current=t,x.current++);const c=K(f,{maxAgeMs:ce}),l=K(y,{maxAgeMs:le}),h=Array.isArray(c)&&c.length>0;A(Array.isArray(c)?c:[]),I(l??null),S(null),L(!h),N.current=h},[t,f,y]);const E=n.useCallback(async(c=R)=>{const l=++o.current,h=t;N.current||L(!0),M(null),_(null);try{const m=await he({q:c||void 0,limit:100},h);if(l!==o.current||h!==t)return;A(m.runs),se(f,m.runs,{maxBytes:5e5}),N.current=!0,P(m.availability),v&&!m.runs.some(p=>p.id===v)&&(I(null),se(y,null,{maxBytes:5e5}),S(null))}catch(m){if(l!==o.current||h!==t)return;const p=ae(m,"Failed to load research runs");M(p.message),_(p)}finally{l===o.current&&L(!1)}},[t,f,R,y,v]),O=n.useCallback(async c=>{const l=await me(c,t);return S(l.run),P(l.availability),l.run},[t]);n.useEffect(()=>{N.current||L(!0);const c=window.setTimeout(()=>{E(R)},Ce);return()=>window.clearTimeout(c)},[E,R]),n.useEffect(()=>{if(!v){S(null);return}O(v)},[O,v]),n.useEffect(()=>{const c=x.current,l=()=>x.current!==c,h=t?`?projectId=${encodeURIComponent(t)}`:"";let m=!0;const p=()=>{!m||l()||(E(),v&&O(v))},w=be(`/api/events${h}`,{events:{"research:run:created":p,"research:run:updated":p,"research:run:completed":p,"research:run:failed":p,"research:run:cancelled":p},onReconnect:p}),U=window.setInterval(p,Ae);return()=>{m=!1,w(),window.clearInterval(U)}},[t,E,v,O]);const V=n.useCallback(c=>{I(c),se(y,c,{maxBytes:5e5})},[y]);return{runs:j,selectedRun:F,selectedRunId:v,setSelectedRunId:V,availability:D,loading:q,error:H,searchQuery:R,setSearchQuery:k,refresh:E,createRun:c=>Re(c,t),cancelRun:async c=>{try{_(null);const l=await ye(c,t);return v===c&&S(l.run),await E(),l}catch(l){const h=ae(l,"Failed to cancel run");throw _(h),h}},retryRun:async c=>{try{_(null);const l=await pe(c,t);return v===c&&S(l.run),await E(),l}catch(l){const h=ae(l,"Failed to retry run");throw _(h),h}},exportRun:(c,l)=>ve(c,l,t),createTaskFromRun:(c,l,h,m,p,w)=>xe(c,{title:l,findingId:h,description:m,priority:p,attachExport:w},t),attachRunToTask:(c,l,h,m)=>fe(c,{taskId:l,findingId:h,attachExport:m},t),uiError:T,runActionState:Ie(F),statusCounts:j.reduce((c,l)=>(c[l.status]+=1,c),{queued:0,running:0,cancelling:0,retry_waiting:0,completed:0,failed:0,cancelled:0,timed_out:0,retry_exhausted:0})}}function Le({open:r,mode:t,run:i,finding:f,projectId:y,onClose:a,onConfirm:g}){ge(r);const[N,j]=n.useState(!1),[A,v]=n.useState(""),[I,F]=n.useState(""),[S,D]=n.useState("normal"),[P,q]=n.useState(""),[L,H]=n.useState([]),[M,T]=n.useState(!1),[_,R]=n.useState(!1),k=n.useMemo(()=>{const o=(f.content??"").split(/(?<=[.!?])\s+/)[0]??"";return`${f.heading||"Research finding"} — ${o}`.trim()},[f.content,f.heading]);return n.useEffect(()=>{r&&(j(!1),v(`Research: ${f.heading||i.title}`),F(k),D("normal"),q(""),t==="enrich"&&(T(!0),je(50,0,y).then(o=>H(o.filter(x=>x.column!=="archived"))).finally(()=>T(!1))))},[r,t,y,f.heading,k,i.title]),r?e.jsx("div",{className:"modal-overlay open",role:"presentation",onClick:a,children:e.jsxs("div",{className:"modal modal-lg research-task-action-modal",role:"dialog","aria-modal":"true",onClick:o=>o.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:t==="create"?"Create task from finding":"Enrich existing task"}),e.jsx("button",{className:"modal-close",type:"button","aria-label":"Close",onClick:a,children:"×"})]}),e.jsxs("div",{className:"research-task-action-modal__body",children:[e.jsxs("div",{className:"card research-task-action-modal__preview",children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Run:"})," ",i.id]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Finding:"})," ",f.id,f.heading?` — ${f.heading}`:""]}),e.jsx("p",{children:k||"No preview available."})]}),t==="create"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"research-task-action-modal__field",children:["Title",e.jsx("input",{className:"input",value:A,onChange:o=>v(o.target.value)})]}),e.jsxs("label",{className:"research-task-action-modal__field",children:["Description",e.jsx("textarea",{className:"input research-task-action-modal__textarea",value:I,onChange:o=>F(o.target.value)})]}),e.jsxs("label",{className:"research-task-action-modal__field",children:["Priority",e.jsxs("select",{className:"select",value:S,onChange:o=>D(o.target.value),children:[e.jsx("option",{value:"low",children:"Low"}),e.jsx("option",{value:"normal",children:"Normal"}),e.jsx("option",{value:"high",children:"High"}),e.jsx("option",{value:"urgent",children:"Urgent"})]})]})]}):e.jsxs("label",{className:"research-task-action-modal__field",children:["Target task",e.jsx("input",{className:"input",list:"research-task-action-task-list",value:P,placeholder:M?"Loading tasks…":"Enter task ID",onChange:o=>q(o.target.value)}),e.jsx("datalist",{id:"research-task-action-task-list",children:L.map(o=>e.jsx("option",{value:o.id,children:o.title},o.id))})]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:N,onChange:o=>j(o.target.checked)}),e.jsx("span",{children:"Attach markdown export artifact"})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn",type:"button",onClick:a,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",type:"button",disabled:_||t==="enrich"&&!P,onClick:()=>{R(!0),g({taskId:t==="enrich"?P:void 0,title:t==="create"?A.trim():void 0,description:t==="create"?I.trim():void 0,priority:t==="create"?S:void 0,attachExport:N}).finally(()=>R(!1))},children:t==="create"?"Create Task":"Enrich Task"})]})]})}):null}const Me=["web-search","page-fetch","github","local-docs","llm-synthesis"],Fe={"web-search":"webSearch","page-fetch":"pageFetch",github:"github","local-docs":"localDocs","llm-synthesis":"llmSynthesis"},De={"web-search":"Web Search","page-fetch":"Page Fetch",github:"GitHub","local-docs":"Local Docs","llm-synthesis":"LLM Synthesis"};function Ge({projectId:r,addToast:t,onOpenSettings:i,readinessVersion:f=0}){const{runs:y,selectedRun:a,selectedRunId:g,setSelectedRunId:N,availability:j,loading:A,error:v,searchQuery:I,setSearchQuery:F,createRun:S,cancelRun:D,retryRun:P,exportRun:q,createTaskFromRun:L,attachRunToTask:H,statusCounts:M,refresh:T,uiError:_,runActionState:R}=Pe({projectId:r}),[k,o]=n.useState(""),[x,$]=n.useState(()=>te(void 0)),[E,O]=n.useState([]),[V,c]=n.useState(!1),[l,h]=n.useState([]),[m,p]=n.useState(null),[w,U]=n.useState(null),Q=j.supportedProviders??Me,W=x.searchProvider,X=s=>s==="web-search"?!0:x.enabledSources[Fe[s]];n.useEffect(()=>{const s=Q.filter(d=>X(d));h(d=>{const b=d.filter(u=>s.includes(u));return b.length>0?b:s})},[x.enabledSources,Q]),n.useEffect(()=>{let s=!1;return Promise.all([Se(r),we().catch(()=>({providers:[]}))]).then(([d,b])=>{s||($(te(d)),O(b.providers.filter(u=>u.type==="api_key").map(u=>({id:u.id,authenticated:u.authenticated}))))}).catch(()=>{s||$(te(void 0))}),()=>{s=!0}},[r,f]);const oe=n.useMemo(()=>a?a.status:"No run selected",[a]),de=n.useMemo(()=>a?a.status==="queued"||a.status==="retry_waiting"?"status-dot status-dot--pending":a.status==="running"?"status-dot status-dot--connecting":a.status==="completed"?"status-dot status-dot--online":a.status==="failed"||a.status==="cancelled"?"status-dot status-dot--error":"status-dot":"status-dot",[a]),Y=j.supportedExportFormats??["markdown","json","html"],J=n.useMemo(()=>new Map(E.map(s=>[s.id,s.authenticated])),[E]),Z=n.useMemo(()=>{const s=new Set;return x.enabledSources.webSearch&&W&&s.add(W),x.enabledSources.llmSynthesis&&x.synthesisProvider&&s.add(x.synthesisProvider),[...s].filter(d=>J.has(d))},[x.enabledSources.llmSynthesis,x.enabledSources.webSearch,x.synthesisProvider,W,J]).find(s=>J.get(s)!==!0),G=n.useMemo(()=>j.available?x.enabled?Z?{reason:`Missing API key for ${Z}.`,details:"Add provider credentials in Authentication settings.",settingsSection:"authentication"}:null:{reason:"Research is disabled for this project.",details:"Enable project research settings to create runs.",settingsSection:"research-project"}:{reason:j.reason??"Research is unavailable for this project.",details:j.setupInstructions,settingsSection:"research-project"},[j.available,j.reason,j.setupInstructions,x.enabled,Z]),B=async(s,d,b)=>{p(s);try{await d(),t?.(b,"success"),await T()}catch(u){t?.(u instanceof Error?u.message:"Action failed","error")}finally{p(null)}},ee=async s=>{if(a){p(`export-${s}`);try{const d=await q(a.id,s),b=new Blob([d.content],{type:"text/plain;charset=utf-8"}),u=URL.createObjectURL(b),C=document.createElement("a");C.href=u,C.download=d.filename,document.body.appendChild(C),C.click(),C.remove(),URL.revokeObjectURL(u),t?.(`Exported ${d.filename}`,"success")}catch(d){t?.(d instanceof Error?d.message:"Export failed","error")}finally{p(null)}}},ue=async()=>{if(k.trim()){c(!0);try{const s=l.filter(b=>X(b));if(s.length===0){c(!1),t?.("No enabled research sources are available for this project.","error");return}const d=await S({query:k.trim(),providers:s});N(d.run.id),o(""),t?.("Research run created","success"),await T()}catch(s){t?.(s instanceof Error?s.message:"Failed to create run","error")}finally{c(!1)}}};return e.jsxs("section",{className:"research-view","aria-label":"Research view",children:[e.jsxs("header",{className:"research-view__header",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"research-view__title",children:"Research"}),e.jsx("p",{className:"research-view__subtitle",children:"Cited search and synthesis runs: gather sources, fetch content, and synthesize findings."})]}),e.jsx("div",{className:"research-view__header-actions",children:e.jsx("button",{className:"btn",type:"button",onClick:()=>void T(),children:"Refresh"})})]}),G?e.jsxs("div",{className:"research-view__state research-view__state--error card","data-testid":"research-state-unavailable",children:[e.jsx("p",{children:G.reason}),G.details&&e.jsx("p",{children:G.details}),e.jsxs("p",{children:["Current defaults: provider ",x.searchProvider??"(not set)",", max sources ",x.limits.maxSourcesPerRun]}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",onClick:()=>void T(),children:"Refresh"}),e.jsx("button",{className:"btn btn-primary",type:"button",onClick:()=>i?.(G.settingsSection),children:"Open Settings"})]})]}):e.jsx(e.Fragment,{children:e.jsxs("div",{className:"research-view__layout",children:[e.jsx("aside",{className:"research-view__sidebar card",children:e.jsxs("div",{className:"research-view__sidebar-content",children:[e.jsxs("div",{className:"research-view__form",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"research-query",children:"Query"}),e.jsx("textarea",{id:"research-query",className:"input research-view__textarea",value:k,onChange:s=>o(s.target.value)})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Providers"}),e.jsx("div",{className:"research-view__providers",children:Q.map(s=>{const d=X(s),b=s==="web-search";return e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:b||l.includes(s),disabled:b||!d,onChange:()=>{b||!d||h(u=>u.includes(s)?u.filter(C=>C!==s):[...u,s])}}),e.jsxs("span",{children:[De[s]??s,b?e.jsx("span",{className:"research-view__provider-lock",children:"Always on"}):null]})]},s)})})]}),e.jsxs("button",{className:"btn btn-primary",type:"button",disabled:!k.trim()||V,onClick:()=>void ue(),children:[V?e.jsx(Ne,{className:"animate-spin",size:14}):null,"Create Run"]})]}),e.jsxs("div",{className:"research-view__history-header form-group",children:[e.jsx("label",{htmlFor:"research-run-search",children:"Search"}),e.jsxs("div",{className:"research-view__history-search-row",children:[e.jsx(ke,{size:14}),e.jsx("input",{id:"research-run-search",className:"input",placeholder:"Search runs",value:I,onChange:s=>F(s.target.value)})]})]}),e.jsx("div",{className:"research-view__history","data-testid":"research-state-running",children:y.map(s=>e.jsxs("button",{type:"button",className:`research-view__history-item card${g===s.id?" research-view__history-item--active":""}`,onClick:()=>N(s.id),children:[e.jsx("span",{className:"card-id",children:s.id}),e.jsx("span",{children:s.title})]},s.id))})]})}),e.jsxs("div",{className:"research-view__reader card",children:[A&&e.jsx("p",{"data-testid":"research-state-loading",children:"Loading research runs…"}),!A&&v&&e.jsx("p",{"data-testid":"research-state-error",children:v}),!A&&!v&&y.length===0&&e.jsx("p",{"data-testid":"research-state-empty",children:"No research runs yet"}),e.jsxs("div",{className:"research-view__reader-content",children:[a&&e.jsxs("div",{className:"research-view__run-detail",children:[e.jsxs("div",{className:"research-view__status-row",children:[e.jsx("span",{className:de}),e.jsx("strong",{children:oe})]}),e.jsx("h3",{className:"research-view__run-title",children:a.title}),e.jsx("p",{className:"research-view__run-query",children:a.query}),e.jsx("p",{className:"research-view__run-summary","data-testid":"research-state-results",children:a.results?.summary??"No summary yet."}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",title:R.cancelable?void 0:R.blockingReason,disabled:m==="cancel"||m==="retry"||!R.cancelable,onClick:()=>void B("cancel",()=>D(a.id),"Run cancelled"),children:"Cancel"}),e.jsx("button",{className:"btn",type:"button",title:R.retryable?void 0:R.blockingReason,disabled:m==="cancel"||m==="retry"||!R.retryable,onClick:()=>void B("retry",()=>P(a.id),"Run retried"),children:"Retry"}),Y.includes("markdown")&&e.jsx("button",{className:"btn",type:"button",disabled:m==="export-markdown",onClick:()=>void ee("markdown"),children:"Export MD"}),Y.includes("json")&&e.jsx("button",{className:"btn",type:"button",disabled:m==="export-json",onClick:()=>void ee("json"),children:"Export JSON"}),Y.includes("html")&&e.jsx("button",{className:"btn",type:"button",disabled:m==="export-html",onClick:()=>void ee("html"),children:"Export HTML"})]}),a.error&&e.jsx("p",{className:"research-view__error",children:a.error}),_&&e.jsxs("div",{className:"form-error",role:"alert",children:[e.jsx("p",{children:_.message}),_.setupHint&&e.jsx("p",{children:_.setupHint}),_.code==="MISSING_CREDENTIALS"&&e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>i?.("authentication"),children:"Open Authentication Settings"}),_.code==="FEATURE_DISABLED"&&e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>i?.("research-project"),children:"Open Research Settings"})]}),R.blockingReason&&e.jsx("p",{className:"research-view__run-query",children:R.blockingReason}),Array.isArray(a.results?.findings)&&a.results.findings.length>0&&e.jsx("div",{className:"research-view__findings",children:a.results.findings.map((s,d)=>{const u=s.id?.trim()||`finding-${d+1}`;return e.jsxs("article",{className:"research-view__finding card",children:[e.jsx("h4",{children:s.heading}),e.jsx("p",{children:s.content}),e.jsxs("div",{className:"research-view__actions research-view__finding-actions",children:[e.jsx("button",{className:"btn btn-primary btn-sm",type:"button",onClick:()=>U({mode:"create",findingId:u}),children:"Create Task"}),e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>U({mode:"enrich",findingId:u}),children:"Enrich Task"})]})]},u)})}),Array.isArray(a.results?.citations)&&a.results.citations.length>0&&e.jsx("ul",{className:"research-view__citations",children:a.results.citations.map(s=>e.jsx("li",{children:e.jsx("a",{href:s,target:"_blank",rel:"noreferrer",children:s})},s))}),a.events.length>0&&e.jsxs("details",{children:[e.jsx("summary",{children:"Run history"}),e.jsx("ul",{className:"research-view__events",children:a.events.map(s=>e.jsx("li",{children:s.message},s.id))})]})]}),!a&&y.length>0&&e.jsx("p",{children:"Select a run to view details."}),e.jsxs("div",{className:"research-view__stats",children:[e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Running"}),e.jsx("div",{className:"research-view__stat-value",children:M.running})]}),e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Completed"}),e.jsx("div",{className:"research-view__stat-value",children:M.completed})]}),e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Failed"}),e.jsx("div",{className:"research-view__stat-value",children:M.failed})]})]})]})]})]})}),a&&w&&(()=>{const s=a.results?.findings?.findIndex((b,u)=>(b.id?.trim()||`finding-${u+1}`)===w.findingId)??-1,d=s>=0?a.results.findings[s]:null;return d?e.jsx(Le,{open:!0,mode:w.mode,run:a,finding:{id:w.findingId,heading:d.heading,content:d.content},projectId:r,onClose:()=>U(null),onConfirm:async({taskId:b,title:u,description:C,priority:re,attachExport:ne})=>{w.mode==="create"?await B("create-task",()=>L(a.id,u,w.findingId,C,re,ne),"Task created from research"):b&&await B("attach-task",()=>H(a.id,b,w.findingId,ne),"Task enriched from research"),U(null)}}):null})()]})}export{Ge as ResearchView};
|