@runfusion/fusion 0.17.2 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/bin.js +1035 -660
  2. package/dist/client/assets/ChatView-3Sqm6teN.js +1 -0
  3. package/dist/client/assets/{DevServerView-GFFVXHVP.js → DevServerView-r6V3FqkY.js} +1 -1
  4. package/dist/client/assets/DirectoryPicker-CTZE95Fk.js +1 -0
  5. package/dist/client/assets/DocumentsView-DSEf1Lmg.js +1 -0
  6. package/dist/client/assets/{InsightsView-Bxu0TJkt.js → InsightsView-F5PZsX5u.js} +2 -2
  7. package/dist/client/assets/MemoryView-DicXjec9.js +2 -0
  8. package/dist/client/assets/NodesView-DddCS7zB.js +14 -0
  9. package/dist/client/assets/NodesView-sJgPLTzz.css +1 -0
  10. package/dist/client/assets/{PiExtensionsManager-4e3MlD62.js → PiExtensionsManager-Ch7si-v8.js} +3 -3
  11. package/dist/client/assets/PluginManager-LcTh_fHP.js +1 -0
  12. package/dist/client/assets/ResearchView-D0TY1VcX.js +1 -0
  13. package/dist/client/assets/{RoadmapsView-jHTOK0RQ.js → RoadmapsView-DfEF3mql.js} +2 -2
  14. package/dist/client/assets/SettingsModal-BNSrO1M9.css +1 -0
  15. package/dist/client/assets/SettingsModal-SOADcCNJ.js +31 -0
  16. package/dist/client/assets/{SettingsModal-4Z8ZJMzD.js → SettingsModal-YcScdFiG.js} +1 -1
  17. package/dist/client/assets/SettingsModal-oOnIed5O.css +1 -0
  18. package/dist/client/assets/SetupWizardModal-EDYuf9Yc.js +1 -0
  19. package/dist/client/assets/SkillsView-Dkq2CQla.js +1 -0
  20. package/dist/client/assets/index-4hC8zoTD.css +1 -0
  21. package/dist/client/assets/index-DNzA4aZ7.js +1229 -0
  22. package/dist/client/assets/{users-D3u6f2Rz.js → users-Cp5TSxVm.js} +2 -2
  23. package/dist/client/index.html +2 -2
  24. package/dist/client/version.json +1 -1
  25. package/dist/droid-cli/index.ts +12 -7
  26. package/dist/droid-cli/package.json +4 -1
  27. package/dist/droid-cli/src/__tests__/provider.test.ts +42 -6
  28. package/dist/extension.js +505 -70
  29. package/dist/pi-claude-cli/package.json +1 -1
  30. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  31. package/package.json +2 -1
  32. package/skill/fusion/SKILL.md +2 -2
  33. package/skill/fusion/references/best-practices.md +33 -0
  34. package/skill/fusion/references/extension-tools.md +47 -2
  35. package/skill/fusion/references/fusion-capabilities.md +7 -2
  36. package/dist/client/assets/AgentDetailView-17J-F0Rl.js +0 -18
  37. package/dist/client/assets/AgentDetailView-yu8Xltqk.css +0 -1
  38. package/dist/client/assets/AgentsView-Bs03ptrd.css +0 -1
  39. package/dist/client/assets/AgentsView-sbBkb7Wd.js +0 -517
  40. package/dist/client/assets/ChatView-BR5cvK_B.js +0 -1
  41. package/dist/client/assets/DirectoryPicker-WPDSBdT6.js +0 -1
  42. package/dist/client/assets/DocumentsView-BHpDsIIt.js +0 -1
  43. package/dist/client/assets/MemoryView-CmnzZorw.js +0 -2
  44. package/dist/client/assets/NodesView-CO9_4hCr.js +0 -14
  45. package/dist/client/assets/NodesView-DuAXX_0j.css +0 -1
  46. package/dist/client/assets/PluginManager-DGN2rvOY.js +0 -1
  47. package/dist/client/assets/ResearchView-Dsa6Gykl.js +0 -1
  48. package/dist/client/assets/SettingsModal-D0kuJpBA.js +0 -31
  49. package/dist/client/assets/SettingsModal-D_AFkDJa.css +0 -1
  50. package/dist/client/assets/SettingsModal-Dq4a5KSX.css +0 -1
  51. package/dist/client/assets/SetupWizardModal-Bhumd4Rf.js +0 -1
  52. package/dist/client/assets/SkillsView-MHweJTz4.js +0 -1
  53. package/dist/client/assets/folder-open-BNQW9dE9.js +0 -6
  54. package/dist/client/assets/index-DEVBHvyW.css +0 -1
  55. package/dist/client/assets/index-k_85J1DS.js +0 -682
  56. package/dist/client/assets/star-7L86NZrT.js +0 -6
  57. package/dist/client/assets/upload-DsAS6tno.js +0 -6
@@ -0,0 +1,14 @@
1
+ import{r as s,j as e}from"./vendor-react-K0fH_qHe.js";import{h as _e,Q as Be,U as He,V as qe,W as Ye,Y as ve,Z as me,_ as Ne,$ as ke,a0 as Xe,a1 as Ce,a2 as Se,a3 as Je,a4 as he,I as We,R as fe,C as we,P as oe,a5 as Me,a6 as Pe,a7 as Ge,a8 as Ze,X as re,a9 as ye,F as Qe,aa as be,ab as es,ac as ss,ad as ts,ae as as,af as ns,ag as ls}from"./index-DNzA4aZ7.js";import"./vendor-xterm-DzcZoU0P.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 rs=[["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"}]],os=_e("wifi-off",rs);/**
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 cs=[["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"}]],is=_e("wifi",cs);function ie(t){const{lastSyncAt:n,remoteReachable:a,diff:o}=t,d=o.global.length+o.project.length;return n===null?{syncState:"never-synced",lastSyncAt:n,diffCount:0}:a?d>0?{syncState:"diff",lastSyncAt:n,diffCount:d}:{syncState:"synced",lastSyncAt:n,diffCount:0}:{syncState:"error",lastSyncAt:n,diffCount:d}}function Ee(t){if(t===null)return"Never synced";const n=new Date(t);if(Number.isNaN(n.getTime()))return"Never synced";const o=Date.now()-n.getTime(),d=Math.floor(o/1e3),f=Math.floor(d/60),r=Math.floor(f/60),x=Math.floor(r/24);return f<1?"Synced just now":f<60?`Synced ${f}m ago`:r<24?`Synced ${r}h ago`:`Synced ${x}d ago`}function ds(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 us=3e4;function ms(){const[t,n]=s.useState({}),[a,o]=s.useState(!1),[d,f]=s.useState({}),[r,x]=s.useState(null),i=s.useRef(new Set),p=s.useRef(!1),_=s.useRef(null),k=s.useRef(null),j=s.useCallback(async(g,m)=>{try{const N=await Be(g);n(F=>({...F,[g]:N})),x(null)}catch(N){console.error(`Failed to fetch sync status for node ${g}:`,N),x(N instanceof Error?N.message:"Failed to fetch sync status")}},[]),c=s.useCallback(async()=>{const g=Array.from(i.current);if(g.length===0)return;_.current&&_.current.abort(),_.current=new AbortController;const m=!p.current;m&&o(!0),x(null);try{const N=await Promise.allSettled(g.map(O=>j(O,m)));p.current=!0,N.filter(O=>O.status==="rejected").length>0&&x("Some sync status requests failed")}catch(N){if(N instanceof Error&&N.name==="AbortError")return;x(N instanceof Error?N.message:"Failed to fetch sync status"),p.current=!0}finally{o(!1)}},[j]),C=s.useCallback(()=>{k.current&&clearInterval(k.current),k.current=setInterval(()=>{c()},us)},[c]),b=s.useCallback(()=>{k.current&&(clearInterval(k.current),k.current=null)},[]);s.useEffect(()=>(c(),C(),()=>{b(),_.current&&_.current.abort()}),[c,C,b]);const l=s.useCallback(g=>{i.current.has(g)||(i.current.add(g),j(g,!p.current))},[j]),u=s.useCallback(g=>{i.current.delete(g),n(m=>{const N={...m};return delete N[g],N}),i.current.size===0&&b()},[b]),y=s.useCallback(async g=>{f(m=>({...m,[g]:!0})),x(null);try{const m=await He(g);return j(g,!1),!m.success&&m.error&&x(m.error),m}catch(m){const N=m instanceof Error?m.message:"Push settings failed";throw x(N),m}finally{f(m=>{const N={...m};return delete N[g],N})}},[j]),E=s.useCallback(async g=>{f(m=>({...m,[g]:!0})),x(null);try{const m=await qe(g);return j(g,!1),!m.success&&m.error&&x(m.error),m}catch(m){const N=m instanceof Error?m.message:"Pull settings failed";throw x(N),m}finally{f(m=>{const N={...m};return delete N[g],N})}},[j]),A=s.useCallback(async g=>{f(m=>({...m,[g]:!0})),x(null);try{return await Ye(g)}catch(m){const N=m instanceof Error?m.message:"Auth sync failed";throw x(N),m}finally{f(m=>{const N={...m};return delete N[g],N})}},[]),P=s.useCallback(g=>t[g]?.authMatch,[t]),z=s.useCallback(g=>t[g]?.authDiff,[t]);return{syncStatusMap:t,loading:a,actionLoading:d,error:r,refresh:c,trackNode:l,untrackNode:u,pushSettings:y,pullSettings:E,syncAuth:A,getAuthSyncState:P,getAuthProviders:z}}function hs(t,n){return n.type==="remote"?t.nodeId===n.id:t.nodeId===n.id||t.nodeId===void 0||t.nodeId===null}function Re(t,n){return t.filter(a=>hs(a,n))}function ge(t,n){return Re(t,n).length}const le={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"}},fs={match:"var(--color-success)",differs:"var(--color-warning)","not-synced":"var(--text-muted)"};function gs(t,n){if(t==="match")return"Auth credentials match";if(t==="not-synced")return"Auth not synced";if(n&&Object.keys(n).length>0){const a=Object.entries(n).filter(([,o])=>o==="differs").map(([o])=>o);if(a.length>0)return`Auth credentials differ: ${a.join(", ")}`}return"Auth credentials differ"}function xs(t,n=42){return t.length<=n?t:`${t.slice(0,n-3)}...`}function ps(t,n){const a=t.node,o=n.node;if(a.id!==o.id||a.name!==o.name||a.type!==o.type||a.url!==o.url||a.status!==o.status||a.maxConcurrent!==o.maxConcurrent||a.updatedAt!==o.updatedAt||t.isLoading!==n.isLoading)return!1;const d=t.managedDockerNode,f=n.managedDockerNode;if(!!d!=!!f||d&&f&&(d.id!==f.id||d.status!==f.status||d.imageTag!==f.imageTag||d.updatedAt!==f.updatedAt))return!1;const r=t.syncStatus,x=n.syncStatus;if(!(!r&&!x)){if(!r||!x)return!1;if(r.syncState!==x.syncState||r.lastSyncAt!==x.lastSyncAt||r.diffCount!==x.diffCount)return!1}if(t.authSyncState!==n.authSyncState)return!1;const i=t.authSyncProviders,p=n.authSyncProviders;if(i!==p){if(!i||!p)return!1;{const j=Object.keys(i),c=Object.keys(p);if(j.length!==c.length||j.some(C=>i[C]!==p[C]))return!1}}const _=ge(t.projects,a),k=ge(n.projects,o);return _===k}function ys({node:t,projects:n,onHealthCheck:a,onEdit:o,onRemove:d,isLoading:f=!1,syncStatus:r,authSyncState:x,authSyncProviders:i,managedDockerNode:p}){const[_,k]=s.useState(!1),j=le[t.status]??le.offline,c=p?le[p.status]??le.error:null,C=p?.hostConfig.type==="remote"?`Remote: ${p.hostConfig.host??"unknown"}`:"Local Docker",b=s.useMemo(()=>ge(n,t),[n,t]),l=s.useCallback(()=>{o(t)},[o,t]),u=s.useCallback(P=>{P.stopPropagation(),a(t.id)},[a,t.id]),y=s.useCallback(P=>{P.stopPropagation(),o(t)},[o,t]),E=s.useCallback(P=>{if(P.stopPropagation(),!_){k(!0);return}d(t.id),k(!1)},[_,d,t.id]),A=s.useCallback(P=>{(P.key==="Enter"||P.key===" ")&&(P.preventDefault(),o(t))},[o,t]);return e.jsxs("article",{className:`node-card ${f?"node-card--loading":""}`,"data-node-id":t.id,role:"button",tabIndex:0,onClick:l,onKeyDown:A,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"}),p&&e.jsxs("span",{className:"node-card__docker-badge",title:"Managed Docker node",children:[e.jsx(me,{size:12,"aria-hidden":!0}),"Docker"]}),e.jsxs("span",{className:`node-card__status ${j.className}`,style:{color:j.color},"data-status":t.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:j.color},"aria-hidden":!0}),j.label]}),p&&c&&e.jsxs("span",{className:`node-card__status ${c.className}`,style:{color:c.color},"data-status":p.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:c.color},"aria-hidden":!0}),c.label]}),t.type==="remote"&&x&&e.jsx("span",{className:`node-card__auth-indicator node-card__auth-indicator--${x}`,title:gs(x,i),"aria-label":`Auth sync: ${x==="match"?"credentials match":x==="differs"?"credentials differ":"not synced"}`,style:{color:fs[x]},children:e.jsx(Ne,{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:xs(t.url)}),p&&e.jsxs("div",{className:"node-card__docker-meta",children:[e.jsxs("span",{title:`${p.imageName}:${p.imageTag}`,children:[p.imageName,":",p.imageTag]}),e.jsx("span",{title:C,children:C})]}),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:b})]}),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"&&r&&e.jsxs("div",{className:"node-card__sync","data-sync-state":r.syncState,"data-testid":"node-card-sync",children:[e.jsx("span",{className:"node-card__sync-dot",style:{backgroundColor:ds(r.syncState)},"aria-hidden":!0}),e.jsx("span",{className:"node-card__sync-time",children:Ee(r.lastSyncAt)})]})]}),e.jsxs("footer",{className:"node-card__actions",children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:u,disabled:f,"aria-label":"Run node health check",title:"Health Check",children:[e.jsx(ke,{size:14}),e.jsx("span",{children:"Health"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:y,disabled:f,"aria-label":"Edit node",title:"Edit",children:[e.jsx(Xe,{size:14}),e.jsx("span",{children:"Edit"})]}),p&&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(Ce,{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(Se,{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(Je,{size:14}),e.jsx("span",{children:"Restart"})]})]}),e.jsxs("button",{className:`btn btn-sm node-card__action node-card__action--remove ${_?"btn-danger is-armed":""}`,type:"button",onClick:E,disabled:f,"aria-label":_?"Confirm remove node":"Remove node",title:_?"Confirm remove":"Remove",children:[e.jsx(he,{size:14}),e.jsx("span",{children:_?"Confirm":"Remove"})]})]})]})}const bs=s.memo(ys,ps),se={online:"var(--success, var(--color-success))",offline:"var(--text-dim)",connecting:"var(--triage)",error:"var(--color-error)"},Q=28,je=12,js=300,_s=120;function vs({nodes:t,className:n}){const a=s.useMemo(()=>t.find(i=>i.type==="local")??t[0],[t]),o=s.useMemo(()=>t.filter(i=>i.type==="remote"),[t]),d=s.useMemo(()=>{const i=js,p=Math.max(0,o.length-4)*20;return i+p},[o.length]),f=d/2,r=d/2,x=s.useMemo(()=>{if(o.length===0)return[];const i=Math.min(_s,d/2-Q-10),p=2*Math.PI/o.length,_=-Math.PI/2;return o.map((k,j)=>{const c=_+j*p;return{node:k,x:f+i*Math.cos(c),y:r+i*Math.sin(c)}})},[o,d,f,r]);return t.length===0?e.jsx("div",{className:`mesh-topology mesh-topology--empty ${n??""}`,children:e.jsx("div",{className:"mesh-topology__empty-state",children:e.jsx("p",{children:"No nodes to display"})})}):e.jsxs("div",{className:`mesh-topology ${n??""}`,children:[e.jsxs("svg",{className:"mesh-topology__svg",viewBox:`0 0 ${d} ${d}`,preserveAspectRatio:"xMidYMid meet","aria-label":"Node mesh topology visualization",children:[x.map(i=>e.jsx("line",{className:"mesh-topology__link",x1:f,y1:r,x2:i.x,y2:i.y},`link-${i.node.id}`)),a&&e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${f}, ${r})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:Q,fill:se[a.status],"aria-label":`${a.name} (${a.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:Q+je,textAnchor:"middle",children:a.name.length>12?`${a.name.slice(0,10)}…`:a.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-Q-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:a.type==="local"?"L":"R"})]})]}),x.map(i=>e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${i.x}, ${i.y})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:Q,fill:se[i.node.status],"aria-label":`${i.node.name} (${i.node.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:Q+je,textAnchor:"middle",children:i.node.name.length>12?`${i.node.name.slice(0,10)}…`:i.node.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-Q-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:i.node.type==="local"?"L":"R"})]})]},i.node.id))]}),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:se.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:se.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:se.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:se.error}}),e.jsx("span",{children:"Error"})]})]}),e.jsx("p",{className:"mesh-topology__notice",children:"Peer-to-peer discovery data unavailable."})]})}const Ns=s.memo(vs),xe=1,pe=10;function ks(t){const n={};return t.name.trim()||(n.name="Name is required"),t.type==="remote"&&!t.url?.trim()&&(n.url="URL is required for remote nodes"),(!Number.isFinite(t.maxConcurrent)||t.maxConcurrent<xe||t.maxConcurrent>pe)&&(n.maxConcurrent=`Concurrency must be between ${xe} and ${pe}`),n}function Cs({isOpen:t,onClose:n,onSubmit:a,addToast:o}){We(t);const[d,f]=s.useState(""),[r,x]=s.useState("local"),[i,p]=s.useState(""),[_,k]=s.useState(""),[j,c]=s.useState(2),[C,b]=s.useState("auto-generate"),[l,u]=s.useState({}),[y,E]=s.useState(!1),A=s.useCallback(()=>{f(""),x("local"),p(""),k(""),c(2),b("auto-generate"),u({}),E(!1)},[]),P=s.useCallback(()=>{y||(A(),n())},[y,n,A]);s.useEffect(()=>{if(!t){A();return}const m=N=>{N.key==="Escape"&&(N.preventDefault(),P())};return document.addEventListener("keydown",m),()=>{document.removeEventListener("keydown",m)}},[P,t,A]);const z=s.useMemo(()=>({name:d.trim(),type:r,url:r==="remote"&&i.trim()||void 0,apiKey:r==="remote"&&C==="provide"&&_||void 0,maxConcurrent:j,apiKeyMode:C}),[_,C,j,d,r,i]),g=s.useCallback(async()=>{if(y)return;const m=ks(z);if(u(m),!(Object.keys(m).length>0)){E(!0);try{await a(z),o(`Node "${z.name}" registered`,"success"),P()}catch(N){const F=N instanceof Error?N.message:"Failed to register node";o(F,"error")}finally{E(!1)}}},[o,P,z,y,a]);return t?e.jsx("div",{className:"modal-overlay open",onClick:P,children:e.jsxs("div",{className:"modal modal-md add-node-modal",onClick:m=>m.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:P,disabled:y,"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:d,onChange:m=>f(m.target.value),placeholder:"Build Machine",disabled:y,"aria-invalid":!!l.name,autoFocus:!0}),l.name&&e.jsx("span",{className:"form-error add-node-modal__error",children:l.name})]}),e.jsxs("div",{className:"add-node-modal__type-toggle",children:[e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${r==="local"?"active":""}`,"data-type":"local",onClick:()=>x("local"),disabled:y,"aria-pressed":r==="local",children:"Local"}),e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${r==="remote"?"active":""}`,"data-type":"remote",onClick:()=>x("remote"),disabled:y,"aria-pressed":r==="remote",children:"Remote"})]}),r==="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:i,onChange:m=>p(m.target.value),placeholder:"https://node.example.com",disabled:y,"aria-invalid":!!l.url}),l.url&&e.jsx("span",{className:"form-error add-node-modal__error",children:l.url})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key Mode"}),e.jsxs("select",{className:"select",value:C,onChange:m=>b(m.target.value),disabled:y,children:[e.jsx("option",{value:"auto-generate",children:"Auto-generate"}),e.jsx("option",{value:"provide",children:"Provide key manually"})]})]}),C==="provide"&&e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:_,onChange:m=>k(m.target.value),placeholder:"Enter node API key",disabled:y})]})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),e.jsx("input",{className:"input",type:"number",min:xe,max:pe,value:j,onChange:m=>c(Number(m.target.value)),disabled:y,"aria-invalid":!!l.maxConcurrent}),e.jsx("span",{className:"add-node-modal__hint",children:"Max simultaneous task agents (1–10)"}),l.maxConcurrent&&e.jsx("span",{className:"form-error add-node-modal__error",children:l.maxConcurrent})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:P,disabled:y,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm","data-testid":"add-node-submit",onClick:g,disabled:y,children:y?"Adding...":"Add Node"})]})]})}):null}function Ss(){const[t,n]=s.useState([]),[a,o]=s.useState(!1),[d,f]=s.useState(null),[r,x]=s.useState(!1),[i,p]=s.useState(null),[_,k]=s.useState(!1),j=s.useCallback(async()=>{o(!0),f(null);try{const b=await fetch("/api/docker/contexts");if(!b.ok)throw new Error(`Failed to load Docker contexts (${b.status})`);const l=await b.json();return n(l),l}catch(b){const l=b instanceof Error?b.message:String(b);throw f(l),b}finally{o(!1)}},[]),c=s.useCallback(async b=>{x(!0);try{const l=await fetch("/api/docker/test-connection",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({hostConfig:b})});if(!l.ok)throw new Error(`Failed to test Docker connection (${l.status})`);const u=await l.json();return p(u),u}finally{x(!1)}},[]),C=s.useCallback(async()=>{k(!0);try{const b=await fetch("/api/docker/local-available");if(!b.ok)throw new Error(`Failed to check local Docker availability (${b.status})`);return await b.json()}finally{k(!1)}},[]);return{contexts:t,isLoadingContexts:a,contextsError:d,loadContexts:j,isTestingConnection:r,lastTestResult:i,testConnection:c,isCheckingLocal:_,checkLocalDocker:C}}function ws({value:t,onChange:n}){const[a,o]=s.useState(!!(t?.tlsCaPath||t?.tlsCertPath||t?.tlsKeyPath||t?.tlsVerify));s.useEffect(()=>{a||n({tlsVerify:void 0,tlsCaPath:void 0,tlsCertPath:void 0,tlsKeyPath:void 0})},[a,n]);const d=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:f=>o(f.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:d.tlsCaPath,onChange:f=>n({...d,tlsCaPath:f.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:d.tlsCertPath,onChange:f=>n({...d,tlsCertPath:f.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:d.tlsKeyPath,onChange:f=>n({...d,tlsKeyPath:f.target.value}),placeholder:"/etc/docker/key.pem"})]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:d.tlsVerify,onChange:f=>n({...d,tlsVerify:f.target.checked})}),"Verify TLS Certificate"]})]})]})}function Ms({value:t,onChange:n,onError:a}){const o=t?.context?"context":t?.host?"host":"local",[d,f]=s.useState(o),[r,x]=s.useState(t?.context??""),[i,p]=s.useState(t?.host??""),[_,k]=s.useState(null),{contexts:j,isLoadingContexts:c,contextsError:C,loadContexts:b,testConnection:l,isTestingConnection:u,lastTestResult:y,checkLocalDocker:E,isCheckingLocal:A}=Ss(),P=s.useMemo(()=>({tlsVerify:t?.tlsVerify,tlsCaPath:t?.tlsCaPath,tlsCertPath:t?.tlsCertPath,tlsKeyPath:t?.tlsKeyPath}),[t]);s.useEffect(()=>{if(d==="local"){n({});return}if(d==="context"){b().catch(g=>a?.(g instanceof Error?g.message:String(g))),n(r?{context:r}:{});return}n({host:i,...P})},[d]);const z=s.useCallback(g=>{d==="host"&&n({host:i,...g})},[i,d,n]);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 ${d==="local"?"docker-target-selector__mode-active":""}`,onClick:()=>{f("local"),E().then(g=>k(g.available?`Docker is available${g.version?` (${g.version})`:""}`:`Docker not found${g.error?`: ${g.error}`:""}`)).catch(g=>{const m=g instanceof Error?g.message:String(g);k(`Docker not found: ${m}`),a?.(m)})},children:"Local Docker"}),e.jsx("button",{type:"button",className:`btn btn-sm ${d==="context"?"docker-target-selector__mode-active":""}`,onClick:()=>f("context"),children:"Docker Context"}),e.jsx("button",{type:"button",className:`btn btn-sm ${d==="host"?"docker-target-selector__mode-active":""}`,onClick:()=>f("host"),children:"Remote Host"})]}),d==="local"&&_&&e.jsx("div",{className:"docker-target-selector__status",children:_}),d==="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:r,onChange:g=>{const m=g.target.value;x(m),n(m?{context:m}:{})},children:[e.jsx("option",{value:"",children:"Select context"}),j.map(g=>e.jsxs("option",{value:g.name,children:[g.name,g.isCurrentContext?" (current)":"",g.dockerHost?` — ${g.dockerHost}`:""]},g.name))]}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon",onClick:()=>void b(),disabled:c,"aria-label":"Refresh contexts",children:e.jsx(fe,{size:14})})]}),C&&e.jsx("div",{className:"docker-target-selector__error",children:C})]}),d==="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:i,onChange:g=>{const m=g.target.value;p(m),n({host:m,...P})}})]}),e.jsx(ws,{value:P,onChange:z})]}),e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void l(d==="local"?void 0:d==="context"?{context:r}:{host:i,...P}),disabled:u||A,children:u?"Testing...":"Test Connection"}),y&&e.jsx("div",{className:y.success?"docker-target-selector__success":"docker-target-selector__error",children:y.success?`Connected${y.dockerVersion?` (Docker ${y.dockerVersion})`:""}`:y.error??"Connection failed"})]})}const de="http://localhost:4040";function Ps({isOpen:t,onClose:n,onSubmit:a,addToast:o}){const[d,f]=s.useState(""),[r,x]=s.useState({}),[i,p]=s.useState(de),[_,k]=s.useState("auto"),[j,c]=s.useState(""),[C,b]=s.useState(!1),[l,u]=s.useState(!1),[y,E]=s.useState(!0),[A,P]=s.useState(4096),[z,g]=s.useState(2),[m,N]=s.useState(!1),[F,O]=s.useState("runfusion/fusion"),[R,H]=s.useState("latest"),[V,X]=s.useState([]),[J,q]=s.useState([]),[U,W]=s.useState({}),[M,T]=s.useState(!1),S=s.useCallback(()=>{f(""),x({}),p(de),k("auto"),c(""),b(!1),u(!1),E(!0),P(4096),g(2),N(!1),O("runfusion/fusion"),H("latest"),X([]),q([]),W({}),T(!1)},[]),w=s.useCallback(()=>{M||(S(),n())},[n,S,M]);s.useEffect(()=>{if(!t){S();return}const h=L=>{L.key==="Escape"&&(L.preventDefault(),w())};return document.addEventListener("keydown",h),()=>document.removeEventListener("keydown",h)},[w,t,S]);const D=s.useMemo(()=>({nodeId:null,name:d.trim(),imageName:F.trim()||"runfusion/fusion",imageTag:R.trim()||"latest",hostConfig:{context:r.context?.trim()||void 0,host:r.host?.trim()||void 0,tlsVerify:r.tlsVerify,tlsCaPath:r.tlsCaPath?.trim()||void 0,tlsCertPath:r.tlsCertPath?.trim()||void 0,tlsKeyPath:r.tlsKeyPath?.trim()||void 0},envVars:Object.fromEntries(V.map(h=>[h.key.trim(),h.value]).filter(([h])=>!!h)),volumeMounts:J.map(h=>({hostPath:h.hostPath.trim(),containerPath:h.containerPath.trim(),mode:h.mode})).filter(h=>h.hostPath&&h.containerPath),resourceSizing:{memoryMB:A,cpus:z},extraClis:[C?"claude-cli":null,l?"droid-cli":null].filter(Boolean),persistentStorage:y,reachableUrl:i.trim()||null,apiKey:_==="manual"&&j.trim()||null}),[j,_,z,r,V,F,R,C,l,A,J,d,y,i]),Y=s.useCallback(()=>{X(h=>[...h,{key:"",value:""}])},[]),G=s.useCallback((h,L)=>{X(I=>I.map((B,ne)=>ne===h?L:B))},[]),ee=s.useCallback(h=>{X(L=>L.filter((I,B)=>B!==h))},[]),K=s.useCallback(()=>{q(h=>[...h,{hostPath:"",containerPath:"",mode:"rw"}])},[]),te=s.useCallback((h,L)=>{q(I=>I.map((B,ne)=>ne===h?L:B))},[]),ae=s.useCallback(h=>{q(L=>L.filter((I,B)=>B!==h))},[]),ce=s.useCallback(async()=>{if(M)return;const h={};if((!D.name||D.name.length>64)&&(h.name="Name is required and must be 64 characters or fewer"),D.reachableUrl||(h.reachableUrl="URL is required"),A<512&&(h.memoryMB="Memory must be at least 512 MB"),z<.5&&(h.cpus="CPUs must be at least 0.5"),W(h),!(Object.keys(h).length>0)){T(!0);try{await a(D),w()}catch{}finally{T(!1)}}},[w,z,D,A,a,M]);return t?e.jsx("div",{className:"modal-overlay open",onClick:w,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:w,disabled:M,"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:d,onChange:h=>f(h.target.value),disabled:M,placeholder:"my-docker-node",autoFocus:!0})]}),U.name&&e.jsx("div",{className:"form-error",children:U.name}),e.jsx(Ms,{value:r,onChange:x}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Reachable URL"}),e.jsx("input",{className:"input",value:i,onChange:h=>p(h.target.value),disabled:M,placeholder:de})]}),U.reachableUrl&&e.jsx("div",{className:"form-error",children:U.reachableUrl}),e.jsxs("div",{className:"docker-onboarding__radio-group",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"radio",checked:_==="auto",onChange:()=>k("auto"),disabled:M}),"Auto-generate"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"radio",checked:_==="manual",onChange:()=>k("manual"),disabled:M}),"Provide manually"]})]}),_==="manual"&&e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:j,onChange:h=>c(h.target.value),disabled:M,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:C,onChange:h=>b(h.target.checked),disabled:M}),"Claude CLI"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:l,onChange:h=>u(h.target.checked),disabled:M}),"Droid CLI"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:y,onChange:h=>E(h.target.checked),disabled:M}),"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:A,onChange:h=>P(Number(h.target.value)),disabled:M})]}),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:z,onChange:h=>g(Number(h.target.value)),disabled:M})]})]}),U.memoryMB&&e.jsx("div",{className:"form-error",children:U.memoryMB}),U.cpus&&e.jsx("div",{className:"form-error",children:U.cpus})]}),e.jsxs("section",{className:"docker-onboarding__section",children:[e.jsxs("button",{type:"button",className:`docker-onboarding__advanced-toggle ${m?"is-expanded":""}`,onClick:()=>N(h=>!h),disabled:M,children:[e.jsx("span",{children:"Advanced"}),e.jsx(we,{})]}),e.jsx("div",{className:`docker-onboarding__advanced-content ${m?"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:F,onChange:h=>O(h.target.value),disabled:M,placeholder:"runfusion/fusion"})]}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Tag"}),e.jsx("input",{className:"input",value:R,onChange:h=>H(h.target.value),disabled:M,placeholder:"latest"})]})]}),e.jsxs("div",{className:"docker-onboarding__kv-list",children:[e.jsx("h5",{children:"Environment Variables"}),V.map((h,L)=>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:M,onChange:I=>G(L,{key:I.target.value,value:h.value})}),e.jsx("input",{className:"input",placeholder:"Value",value:h.value,disabled:M,onChange:I=>G(L,{key:h.key,value:I.target.value})}),e.jsx("button",{type:"button",className:"btn btn-icon","aria-label":"Remove environment variable",onClick:()=>ee(L),disabled:M,children:e.jsx(he,{size:14})})]},`env-${L}`)),e.jsxs("button",{type:"button",className:"btn btn-sm docker-onboarding__kv-add",onClick:Y,disabled:M,children:[e.jsx(oe,{size:14}),"Add variable"]})]}),e.jsxs("div",{className:"docker-onboarding__kv-list",children:[e.jsx("h5",{children:"Volume Mounts"}),J.map((h,L)=>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:M,onChange:I=>te(L,{hostPath:I.target.value,containerPath:h.containerPath,mode:h.mode})}),e.jsx("input",{className:"input",placeholder:"Container path",value:h.containerPath,disabled:M,onChange:I=>te(L,{hostPath:h.hostPath,containerPath:I.target.value,mode:h.mode})}),e.jsxs("select",{className:"select",value:h.mode,disabled:M,onChange:I=>te(L,{hostPath:h.hostPath,containerPath:h.containerPath,mode:I.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:()=>ae(L),disabled:M,children:e.jsx(he,{size:14})})]},`mount-${L}`)),e.jsxs("button",{type:"button",className:"btn btn-sm docker-onboarding__kv-add",onClick:K,disabled:M,children:[e.jsx(oe,{size:14}),"Add mount"]})]})]})})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn",onClick:w,disabled:M,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",onClick:()=>void ce(),disabled:M,children:M?"Creating...":"Create Docker Node"})]})]})}):null}function Es({nodeId:t,entries:n,loading:a=!1,singleNode:o=!1}){const[d,f]=s.useState(!1),[r,x]=s.useState("all"),[i,p]=s.useState("all"),_=s.useCallback(()=>{f(l=>!l)},[]),k=s.useMemo(()=>{const l=new Set;for(const u of n)l.add(u.nodeName);return Array.from(l).sort()},[n]),j=s.useMemo(()=>{let l=[...n];return r!=="all"&&(l=l.filter(u=>u.direction===r)),!o&&i!=="all"&&(l=l.filter(u=>u.nodeName===i)),l.sort((u,y)=>{const E=new Date(u.timestamp).getTime();return new Date(y.timestamp).getTime()-E}),l},[n,r,i,o]),c=s.useCallback(l=>new Date(l).toLocaleString(),[]),C=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""}},[]),b=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:_,"aria-expanded":d,"data-testid":"settings-sync-log-header",children:[e.jsx(we,{size:16,className:`settings-sync-log__chevron ${d?"settings-sync-log__chevron--expanded":""}`}),e.jsxs("span",{children:[n.length," ",n.length===1?"entry":"entries"]})]}),d&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"settings-sync-log__filters",children:[e.jsxs("label",{children:["Direction:",e.jsxs("select",{value:r,onChange:l=>x(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"})]})]}),!o&&e.jsxs("label",{children:["Node:",e.jsxs("select",{value:i,onChange:l=>p(l.target.value),children:[e.jsx("option",{value:"all",children:"All Nodes"}),k.map(l=>e.jsx("option",{value:l,children:l},l))]})]})]}),a&&n.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"Loading..."}):j.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"No sync history available"}):e.jsx("div",{className:"settings-sync-log__list",children:j.map(l=>e.jsxs("div",{className:"settings-sync-log__entry",children:[e.jsx("span",{className:"settings-sync-log__entry-timestamp",children:c(l.timestamp)}),e.jsx("span",{className:"settings-sync-log__entry-direction",children:l.direction==="push"?e.jsx(Me,{size:14,"data-testid":"upload-icon"}):e.jsx(Pe,{size:14,"data-testid":"download-icon"})}),e.jsx("span",{className:`settings-sync-log__entry-result ${C(l.result)}`,children:b(l.result)}),!o&&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:l.details})]},l.id))})]})]})}function Rs(t,n){const a=typeof t=="string"?t:JSON.stringify(t,null,2),o=typeof n=="string"?n:JSON.stringify(n,null,2);if(a===o)return a;const d=a.split(`
12
+ `),f=o.split(`
13
+ `),r=[],x=Math.max(d.length,f.length);for(let i=0;i<x;i++){const p=d[i],_=f[i];p!==void 0&&p!==_&&r.push(`- ${p}`),_!==void 0&&_!==p&&r.push(`+ ${_}`),p!==void 0&&p===_&&r.push(` ${p}`)}return r.join(`
14
+ `)}function As({isOpen:t,onClose:n,onResolve:a,conflicts:o,localNodeName:d,remoteNodeName:f,addToast:r}){const[x,i]=s.useState({}),[p,_]=s.useState(!1);s.useEffect(()=>{const l={};for(const u of o)x[u.key]||(l[u.key]={resolution:"local"});Object.keys(l).length>0&&i(u=>({...u,...l}))},[o,x]),s.useEffect(()=>{if(!t)return;const l=u=>{u.key==="Escape"&&(u.preventDefault(),n())};return document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l)},[t,n]);const k=s.useCallback((l,u)=>{i(y=>{const E=y[l]??{};return u==="manual"?{...y,[l]:{resolution:"manual",manualValue:E.manualValue??JSON.stringify(o.find(A=>A.key===l)?.localValue??null,null,2)}}:{...y,[l]:{resolution:u}}})},[o]),j=s.useCallback((l,u)=>{i(y=>({...y,[l]:{...y[l],resolution:"manual",manualValue:u}}))},[]),c=s.useCallback(l=>{const u={};for(const y of o)u[y.key]={resolution:l};i(u)},[o]),C=s.useCallback(async()=>{_(!0);try{const l=o.map(u=>{const y=x[u.key]??{resolution:"local"};let E;switch(y.resolution){case"remote":E=u.remoteValue;break;case"manual":try{E=JSON.parse(y.manualValue??"null")}catch{E=y.manualValue??null}break;case"local":default:E=u.localValue;break}return{key:u.key,value:E}});await a(l),r("Settings conflicts resolved successfully","success"),n()}catch(l){const u=l instanceof Error?l.message:"Failed to resolve conflicts";r(u,"error")}finally{_(!1)}},[r,o,n,a,x]),b=s.useMemo(()=>{const l={};for(const u of o)l[u.key]=Rs(u.localValue,u.remoteValue);return l},[o]);return!t||o.length===0?null:e.jsx("div",{className:"modal-overlay open",onClick:n,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:n,"aria-label":"Close conflict modal",children:"×"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("div",{className:"settings-sync-conflict-modal__conflict-list",children:o.map(l=>{const u=x[l.key]??{resolution:"local"},y=b[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:d}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:y})})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:f}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:y})})]})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__resolution",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:u.resolution==="local",onChange:()=>k(l.key,"local")}),"Keep Local"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:u.resolution==="remote",onChange:()=>k(l.key,"remote")}),"Keep Remote"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:u.resolution==="manual",onChange:()=>k(l.key,"manual")}),"Merge Manually"]})]}),u.resolution==="manual"&&e.jsx("textarea",{className:"settings-sync-conflict-modal__manual-input",value:u.manualValue??"",onChange:E=>j(l.key,E.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:()=>c("local"),type:"button",children:"Resolve All: Keep Local"}),e.jsx("button",{className:"btn btn-sm",onClick:()=>c("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:n,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:C,disabled:p,children:p?"Resolving...":"Confirm"})]})]})})}const Ls=/(KEY|TOKEN|SECRET|PASSWORD)/i;function ue(t){if(!t)return"—";const n=new Date(t);return Number.isNaN(n.getTime())?"—":n.toLocaleString()}function $s(t){if(!t)return"—";const n=new Date(t),a=Date.now();if(Number.isNaN(n.getTime())||n.getTime()>a)return"—";const o=Math.floor((a-n.getTime())/1e3);if(o<60)return`${o}s`;const d=Math.floor(o/60);if(d<60)return`${d}m`;const f=Math.floor(d/60);return f<24?`${f}h ${d%60}m`:`${Math.floor(f/24)}d ${f%24}h`}function zs(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 Ds(t){return t==="running"?"success":t==="creating"||t==="recreating"||t==="restarting"?"warning":"error"}function Is(t){return t?`${t.charAt(0).toUpperCase()}${t.slice(1)}`:"Unknown"}function Fs(t){if(!t)return"—";try{const n=new URL(t);return n.port?n.port:n.protocol==="https:"?"443":n.protocol==="http:"?"80":"—"}catch{return"—"}}function Ks(t,n){return Ls.test(t)?"••••••••":n}function Os({isOpen:t,onClose:n,node:a,projects:o,onUpdate:d,onHealthCheck:f,addToast:r,syncStatus:x,onPushSettings:i,onPullSettings:p,onSyncAuth:_,syncHistory:k=[],onResolveConflicts:j,managedDockerNode:c,containerStatus:C,onFetchContainerStatus:b,onFetchLogs:l}){const u=s.useRef(!0),[y,E]=s.useState(!1),[A,P]=s.useState(""),[z,g]=s.useState(""),[m,N]=s.useState(""),[F,O]=s.useState(2),[R,H]=s.useState(!1),[V,X]=s.useState(!1),[J,q]=s.useState(!1),[U,W]=s.useState(!1),[M,T]=s.useState(null),[S,w]=s.useState(!1),[D]=s.useState([]),[Y,G]=s.useState(C),[ee,K]=s.useState(!1),[te,ae]=s.useState(!1),[ce,h]=s.useState(""),[L,I]=s.useState(!1);s.useEffect(()=>(u.current=!0,()=>{u.current=!1}),[]),s.useEffect(()=>{G(C)},[C]),s.useEffect(()=>{if(!a||!t){E(!1),ae(!1),h("");return}P(a.name),g(a.url??""),N(a.apiKey??""),O(a.maxConcurrent),E(!1)},[t,a]),s.useEffect(()=>{if(!t)return;const v=$=>{$.key==="Escape"&&($.preventDefault(),n())};return document.addEventListener("keydown",v),()=>document.removeEventListener("keydown",v)},[t,n]);const B=s.useMemo(()=>a?Re(o,a):[],[a,o]),ne=s.useMemo(()=>c?c.hostConfig.type==="remote"?c.hostConfig.host??"—":"Local Docker":"—",[c]),Ae=s.useMemo(()=>!c?.resourceSizing?.cpuLimit&&!c?.resourceSizing?.memoryLimit?"Default":`${c.resourceSizing?.cpuLimit??"Default CPU"} / ${c.resourceSizing?.memoryLimit??"Default memory"}`,[c]),Le=s.useCallback(async()=>{if(a)try{if(await f(a.id),!u.current)return;r(`Health check completed for ${a.name}`,"success")}catch(v){if(!u.current)return;const $=v instanceof Error?v.message:"Health check failed";r($,"error")}},[r,a,f]),$e=s.useCallback(async()=>{if(!(!a||!i)){T(null),X(!0);try{if(await i(a.id),!u.current)return;r("Settings pushed successfully","success")}catch(v){if(!u.current)return;const $=v instanceof Error?v.message:"Push settings failed";T($),r($,"error")}finally{u.current&&X(!1)}}},[r,a,i]),ze=s.useCallback(async()=>{if(!(!a||!p)){T(null),q(!0);try{if(await p(a.id),!u.current)return;r("Settings pulled successfully","success")}catch(v){if(!u.current)return;const $=v instanceof Error?v.message:"Pull settings failed";T($),r($,"error")}finally{u.current&&q(!1)}}},[r,a,p]),De=s.useCallback(async()=>{if(!(!a||!_)){T(null),W(!0);try{if(await _(a.id),!u.current)return;r("Auth credentials synced successfully","success")}catch(v){if(!u.current)return;const $=v instanceof Error?v.message:"Auth sync failed";T($),r($,"error")}finally{u.current&&W(!1)}}},[r,a,_]),Ie=s.useCallback(()=>{T(null)},[]),Fe=s.useCallback(async()=>{if(!(!c||!b)){K(!0);try{const v=await b(c.id);if(!u.current)return;G(v)}catch(v){const $=v instanceof Error?v.message:"Failed to fetch container status";r($,"error")}finally{u.current&&K(!1)}}},[r,c,b]),Ke=s.useCallback(async()=>{if(!(!c||!l)){ae(!0),I(!0);try{const v=await l(c.id);if(!u.current)return;h(v)}catch(v){if(!u.current)return;h("");const $=v instanceof Error?v.message:"Failed to fetch container logs";r($,"error")}finally{u.current&&I(!1)}}},[r,c,l]),Oe=s.useCallback(async()=>{if(!a||R)return;const v=A.trim();if(!v){r("Name is required","error");return}if(a.type==="remote"&&!z.trim()){r("URL is required for remote nodes","error");return}if(!Number.isFinite(F)||F<1){r("Concurrency must be at least 1","error");return}H(!0);try{await d(a.id,{name:v,url:a.type==="remote"&&z.trim()||void 0,apiKey:a.type==="remote"&&m||void 0,maxConcurrent:F}),r(`Updated ${v}`,"success"),E(!1)}catch($){const Te=$ instanceof Error?$.message:"Failed to update node";r(Te,"error")}finally{H(!1)}},[r,m,R,F,A,a,d,z]),Ve=s.useCallback(()=>{a&&(P(a.name),g(a.url??""),N(a.apiKey??""),O(a.maxConcurrent),E(!1))},[a]);if(!t||!a)return null;const Z=Y?.status??c?.status,Ue=Ds(Z);return e.jsxs("div",{className:"modal-overlay open",onClick:n,children:[e.jsxs("div",{className:"modal modal-lg node-detail-modal",onClick:v=>v.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:n,"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"}),!y&&e.jsxs("button",{className:"btn btn-sm",onClick:()=>E(!0),children:[e.jsx(Ge,{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"}),y?e.jsx("input",{className:"input",value:A,onChange:v=>P(v.target.value),disabled:R}):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"}),y?e.jsx("input",{className:"input",type:"number",min:1,max:10,value:F,onChange:v=>O(Number(v.target.value)),disabled:R}):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"}),y?e.jsx("input",{className:"input",value:z,onChange:v=>g(v.target.value),disabled:R}):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"}),y?e.jsx("input",{className:"input",type:"password",value:m,onChange:v=>N(v.target.value),placeholder:"Leave blank to keep unchanged",disabled:R}):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:ue(a.createdAt)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Updated"}),e.jsx("strong",{children:ue(a.updatedAt)})]})]}),y&&e.jsxs("div",{className:"node-detail-modal__edit-actions",children:[e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:Oe,disabled:R,children:[e.jsx(Ze,{size:14}),R?"Saving...":"Save"]}),e.jsxs("button",{className:"btn btn-sm",onClick:Ve,disabled:R,children:[e.jsx(re,{size:14}),"Cancel"]})]})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("h4",{children:[a.type==="local"?"Projects":"Assigned Projects"," (",B.length,")"]}),B.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:B.map(v=>e.jsxs("li",{className:"node-detail-modal__project-item",children:[e.jsx("span",{children:v.name}),e.jsx("code",{children:v.id})]},v.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:ue(a.updatedAt)})]})]})]}),c&&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--${Ue}`,"aria-hidden":!0}),e.jsx("strong",{children:Is(Z)}),(Z==="creating"||Z==="recreating"||Z==="restarting")&&e.jsx(ye,{size:14,className:"spin","aria-hidden":!0})]}),e.jsxs("div",{className:"docker-management__status-meta",children:[Z==="running"&&e.jsxs("span",{children:["Uptime: ",$s(Y?.startedAt)]}),Z!=="running"&&Y?.exitCode!==void 0&&e.jsxs("span",{children:["Exit code: ",Y.exitCode]}),(Y?.error||c.errorMessage)&&e.jsx("span",{children:Y?.error??c.errorMessage})]}),e.jsx("button",{className:"btn btn-sm",onClick:()=>void Fe(),disabled:!b||ee,children:ee?"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:[c.imageName,":",c.imageTag]})})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Container ID"}),e.jsx("strong",{children:e.jsx("code",{children:c.containerId?c.containerId.slice(0,12):"—"})})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Host"}),e.jsx("strong",{children:ne})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Persistent Storage"}),e.jsx("strong",{children:c.persistentStorage?"Yes":"No"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Port"}),e.jsx("strong",{children:Fs(c.reachableUrl)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Resource Sizing"}),e.jsx("strong",{children:Ae})]})]}),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(Ce,{size:14}),"Start"]}),e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:"Available after FN-3113",children:[e.jsx(Se,{size:14}),"Stop"]}),e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:"Available after FN-3113",children:[e.jsx(ye,{size:14}),"Restart"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void Ke(),disabled:!l,children:[e.jsx(Qe,{size:14}),"View Logs"]})]}),te&&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:()=>ae(!1),"aria-label":"Close logs",children:e.jsx(re,{size:14})})]}),L?e.jsx("p",{children:"Fetching logs..."}):e.jsx("pre",{children:ce.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(c.envVars).map(([v,$])=>e.jsxs("div",{children:[e.jsx("dt",{children:v}),e.jsx("dd",{children:Ks(v,$)})]},v))})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Volume Mounts"}),e.jsx("ul",{className:"docker-management__mounts-list",children:c.volumeMounts.map(v=>e.jsxs("li",{children:[e.jsxs("span",{children:[v.hostPath," → ",v.containerPath]}),v.readOnly&&e.jsx("span",{className:"node-card__type-badge",children:"Read-only"})]},`${v.hostPath}:${v.containerPath}`))})]})]}),a.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Settings Sync"}),x&&e.jsxs("div",{className:"node-detail-modal__sync-status",children:[e.jsx("span",{className:`node-detail-modal__sync-dot ${zs(x.syncState)}`,"aria-hidden":!0}),e.jsxs("span",{children:["Last sync: ",e.jsx("strong",{children:x.lastSyncAt?Ee(x.lastSyncAt):"Never synced"})]}),x.diffCount>0&&e.jsxs("span",{className:"node-detail-modal__sync-diff",children:["Differences: ",e.jsx("strong",{children:x.diffCount})]})]}),e.jsxs("div",{className:"node-detail-modal__sync-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:$e,disabled:V||!i,children:[e.jsx(Me,{size:14}),V?"Pushing...":"Push Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:ze,disabled:J||!p,children:[e.jsx(Pe,{size:14}),J?"Pulling...":"Pull Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:De,disabled:U||!_,children:[e.jsx(Ne,{size:14}),U?"Syncing...":"Sync Auth"]})]}),M&&e.jsxs("div",{className:"node-detail-modal__sync-error",children:[e.jsx("span",{children:M}),e.jsx("button",{className:"node-detail-modal__sync-error-dismiss",onClick:Ie,"aria-label":"Dismiss error",children:e.jsx(re,{size:14})})]})]}),a.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Sync History"}),e.jsx(Es,{nodeId:a.id,entries:k,singleNode:!0})]})]}),e.jsxs("div",{className:"modal-actions node-detail-modal__actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:Le,children:[e.jsx(ke,{size:14}),"Health Check"]}),e.jsx("button",{className:"btn btn-sm",onClick:n,children:"Close"})]})]}),a.type==="remote"&&e.jsx(As,{isOpen:S,onClose:()=>w(!1),onResolve:j??(async()=>{}),conflicts:D,localNodeName:"Local",remoteNodeName:a.name,addToast:r})]})}const Vs=15e3,Us=1e3;function Ts(){const[t,n]=s.useState([]),[a,o]=s.useState(!0),[d,f]=s.useState(null),r=s.useRef(null),x=s.useRef(0),i=s.useCallback(async()=>{try{f(null);const j=await be();n(j)}catch(j){f(j instanceof Error?j.message:"Failed to fetch managed Docker nodes")}},[]);s.useEffect(()=>{let j=!1;async function c(){o(!0);try{const b=await be();j||(n(b),f(null))}catch(b){j||f(b instanceof Error?b.message:"Failed to fetch managed Docker nodes")}finally{j||o(!1)}}c();const C=()=>{if(document.visibilityState!=="visible")return;const b=Date.now();b-x.current<Us||(x.current=b,i())};return document.addEventListener("visibilitychange",C),()=>{j=!0,document.removeEventListener("visibilitychange",C)}},[i]),s.useEffect(()=>{if(!a)return r.current=setInterval(()=>{i()},Vs),()=>{r.current&&(clearInterval(r.current),r.current=null)}},[a,i]);const p=s.useCallback(async j=>es(j),[]),_=s.useCallback(async(j,c)=>(await ss(j,c)).logs,[]),k=s.useCallback(async j=>{const c=await ts(j),C={...c,nodeId:c.nodeId??void 0,containerId:c.containerId??void 0,status:c.status,hostConfig:{type:c.hostConfig.host||c.hostConfig.context?"remote":"local",host:c.hostConfig.host,context:c.hostConfig.context},reachableUrl:c.reachableUrl??void 0,volumeMounts:c.volumeMounts.map(b=>({hostPath:b.hostPath,containerPath:b.containerPath,readOnly:b.mode==="ro"?!0:void 0})),persistentStorage:c.persistentStorage,resourceSizing:{cpuLimit:c.resourceSizing.cpus!==void 0?String(c.resourceSizing.cpus):void 0,memoryLimit:c.resourceSizing.memoryMB!==void 0?`${c.resourceSizing.memoryMB}MB`:void 0},errorMessage:c.errorMessage??void 0};return n(b=>[...b,C]),C},[]);return{dockerNodes:t,loading:a,error:d,refresh:i,getContainerStatus:p,getLogs:_,create:k}}function Ys({addToast:t,onClose:n}){const{nodes:a,loading:o,error:d,refresh:f,register:r,update:x,unregister:i,healthCheck:p}=as(),{projects:_}=ns(),{syncStatusMap:k,pushSettings:j,pullSettings:c,syncAuth:C,trackNode:b,getAuthSyncState:l,getAuthProviders:u}=ms(),{dockerNodes:y,loading:E,refresh:A,getContainerStatus:P,getLogs:z,create:g}=Ts(),[m,N]=s.useState(!1),[F,O]=s.useState(!1),[R,H]=s.useState(null);s.useEffect(()=>{const S=a.filter(w=>w.type==="remote");for(const w of S)b(w.id)},[a,b]),s.useEffect(()=>{if(!R)return;const S=a.find(w=>w.id===R.id)??null;H(S)},[a,R]);const V=s.useMemo(()=>{const S=a.length,w=a.filter(K=>K.status==="online").length,D=a.filter(K=>K.status==="offline"||K.status==="error").length,Y=a.filter(K=>K.type==="remote").length,G=a.filter(K=>K.type==="remote"&&k[K.id]&&ie(k[K.id]).syncState==="synced").length,ee=y.length;return{total:S,online:w,offline:D,remote:Y,synced:G,docker:ee}},[y.length,a,k]),X=s.useCallback(async S=>{await r(S)},[r]),J=s.useCallback(async S=>{try{await g(S),t(`Docker node "${S.name}" created`,"success"),O(!1)}catch(w){const D=w instanceof Error?w.message:"Failed to create Docker node";throw t(D,"error"),w}},[t,g]),q=s.useMemo(()=>{const S=new Map;for(const w of y)w.nodeId&&S.set(w.nodeId,w);return S},[y]),U=s.useCallback(async()=>{try{await Promise.all([f(),A()])}catch{t("Failed to refresh nodes","error")}},[t,f,A]),W=s.useCallback(async S=>{try{await p(S),t("Node health check complete","success")}catch(w){const D=w instanceof Error?w.message:"Health check failed";t(D,"error")}},[t,p]),M=s.useCallback(async S=>{try{await i(S),t("Node removed","success"),R?.id===S&&H(null)}catch(w){const D=w instanceof Error?w.message:"Failed to remove node";t(D,"error")}},[t,R?.id,i]),T=s.useCallback(async(S,w)=>{await x(S,w)},[x]);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:n,"aria-label":"Close nodes view",children:e.jsx(re,{size:16})}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void U(),disabled:o||E,children:[e.jsx(fe,{size:14,className:o?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>N(!0),children:[e.jsx(oe,{size:14}),"Add Node"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>O(!0),title:"Add a managed Docker node",children:[e.jsx(me,{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:V.total})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--online","data-testid":"nodes-stat-online",children:[e.jsxs("span",{children:[e.jsx(is,{size:14})," Online"]}),e.jsx("strong",{children:V.online})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--offline","data-testid":"nodes-stat-offline",children:[e.jsxs("span",{children:[e.jsx(os,{size:14})," Offline"]}),e.jsx("strong",{children:V.offline})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-remote",children:[e.jsxs("span",{children:[e.jsx(ls,{size:14})," Remote"]}),e.jsx("strong",{children:V.remote})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--synced","data-testid":"nodes-stat-synced",children:[e.jsxs("span",{children:[e.jsx(fe,{size:14})," Synced"]}),e.jsx("strong",{children:V.synced})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-docker",children:[e.jsxs("span",{children:[e.jsx(me,{size:14})," Docker"]}),e.jsx("strong",{children:V.docker})]})]}),d&&e.jsx("div",{className:"nodes-view-error",children:d}),!o&&a.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(Ns,{nodes:a})]}),o?e.jsx("div",{className:"nodes-view-grid",children:Array.from({length:4}).map((S,w)=>e.jsx("div",{className:"node-card node-card--loading","aria-hidden":!0},w))}):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:()=>N(!0),children:[e.jsx(oe,{size:14}),"Add First Node"]})]}):e.jsx("div",{className:"nodes-view-grid",children:a.map(S=>{const w=S.type==="remote"&&k[S.id]?ie(k[S.id]):void 0;return e.jsx(bs,{node:S,projects:_,onHealthCheck:D=>{W(D)},onEdit:D=>H(D),onRemove:D=>{M(D)},isLoading:o,syncStatus:w,authSyncState:S.type==="remote"?l(S.id):void 0,authSyncProviders:S.type==="remote"?u(S.id):void 0,managedDockerNode:q.get(S.id)},S.id)})}),e.jsx(Cs,{isOpen:m,onClose:()=>N(!1),onSubmit:X,addToast:t}),e.jsx(Ps,{isOpen:F,onClose:()=>O(!1),onSubmit:J,addToast:t}),e.jsx(Os,{isOpen:R!==null,onClose:()=>H(null),node:R,projects:_,onUpdate:T,onHealthCheck:W,addToast:t,syncStatus:R?.type==="remote"&&R&&k[R.id]?ie(k[R.id]):void 0,onPushSettings:j,onPullSettings:c,onSyncAuth:C,managedDockerNode:R?q.get(R.id):void 0,onFetchContainerStatus:P,onFetchLogs:z})]})}export{Ys as NodesView};
@@ -0,0 +1 @@
1
+ .nodes-management-overlay{display:flex;flex-direction:column;gap:var(--space-md);height:100%;overflow-y:auto;-webkit-overflow-scrolling:touch}.nodes-management-overlay__header{display:flex;justify-content:flex-end}.nodes-view{--nodes-view-spin-duration: calc(var(--transition-slow) * 4);--nodes-view-pulse-duration: calc(var(--transition-slow) * 5);display:flex;flex-direction:column;gap:var(--space-md);padding:var(--space-sm) var(--space-md) var(--space-xl)}.nodes-view-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--space-sm)}.nodes-view-title{display:flex;align-items:center;gap:var(--space-sm)}.nodes-view-title h2{margin:0;display:flex;align-items:center;gap:var(--space-sm)}.nodes-view-count{color:var(--text-muted);font-size:calc(var(--space-md) + var(--space-xs) / 4)}.nodes-view-actions{display:flex;gap:var(--space-sm)}.nodes-view-close{margin-left:auto}.nodes-view-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(calc(var(--space-xl) * 5.833),1fr));gap:var(--space-sm)}.nodes-view-stat{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-sm) var(--space-md);display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}.nodes-view-stat span{display:inline-flex;align-items:center;gap:var(--space-sm);color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs))}.nodes-view-stat strong{font-size:calc(var(--space-lg) + var(--space-xs) / 2)}.nodes-view-stat--online strong{color:var(--color-success)}.nodes-view-stat--offline strong{color:var(--color-error)}.nodes-view-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(calc(var(--space-lg) * 20),1fr));gap:var(--space-md)}.nodes-view-empty{padding:var(--space-xl);border:1px dashed var(--border);border-radius:var(--radius-md);text-align:center;color:var(--text-muted);display:flex;flex-direction:column;align-items:center;gap:var(--space-md)}.nodes-view-error{color:var(--color-error);font-size:calc(var(--space-md) + var(--space-xs) / 4)}.node-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md);display:flex;flex-direction:column;gap:var(--space-md);cursor:pointer;transition:border-color var(--transition-fast),transform var(--transition-fast)}.node-card:hover{border-color:var(--accent);transform:translateY(calc(var(--space-xs) * -.25))}.node-card:focus-visible{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.node-card--loading{min-height:calc(var(--space-xl) * 9.167);opacity:.55;pointer-events:none}.node-card__header{display:flex;align-items:center;justify-content:space-between}.node-card__title-wrap{display:flex;align-items:center;gap:var(--space-sm)}.node-card__icon{width:calc(var(--space-lg) * 2.125);height:calc(var(--space-lg) * 2.125);border-radius:var(--radius-sm);display:inline-flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent)}.node-card__name{margin:0;font-size:calc(var(--space-md) + var(--space-xs));line-height:1.25}.node-card__meta-row{margin-top:var(--space-xs);display:flex;align-items:center;gap:var(--space-xs)}.node-card__type-badge{border:1px solid var(--border);border-radius:var(--radius-pill);padding:var(--space-xs) var(--space-sm);font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted)}.node-card__status{display:inline-flex;align-items:center;gap:var(--space-xs);font-size:calc(var(--space-sm) + var(--space-xs) * .75);font-weight:600}.node-card__status-indicator{width:var(--space-sm);height:var(--space-sm);border-radius:50%}.node-card__status--online .node-card__status-indicator{background:var(--color-success)}.node-card__status--offline .node-card__status-indicator,.node-card__status--error .node-card__status-indicator{background:var(--color-error)}.node-card__status--connecting .node-card__status-indicator{background:var(--color-warning)}.node-card__auth-indicator{display:inline-flex;align-items:center;margin-left:var(--space-xs);vertical-align:middle}.node-card__url{font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted);word-break:break-all}.node-card__metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.node-card__metric{display:flex;flex-direction:column;gap:var(--space-xs)}.node-card__metric-label{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs) * .75);text-transform:uppercase;letter-spacing:.03em}.node-card__metric-value{font-size:calc(var(--space-md) + var(--space-xs));font-weight:600}.node-card__sync{display:flex;align-items:center;gap:var(--space-xs);margin-top:var(--space-sm);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.node-card__sync-dot{width:var(--space-sm);height:var(--space-sm);border-radius:50%;flex-shrink:0}.node-card__sync-time{color:var(--text-muted)}.nodes-view-stat--synced strong{color:var(--color-success)}.node-card__actions{display:flex;gap:var(--space-xs);flex-wrap:wrap}.node-card__action{display:inline-flex;align-items:center;gap:var(--space-xs)}.node-card__action--remove{margin-left:auto}.node-card__action--remove:not(.btn-danger){color:var(--color-error);border-color:color-mix(in srgb,var(--color-error) 45%,var(--border))}.node-card__action--remove.is-armed{background:color-mix(in srgb,var(--color-error) 14%,transparent)}.node-card__docker-badge{display:inline-flex;align-items:center;gap:var(--space-xs);border-radius:var(--radius-pill);padding:var(--space-xs) var(--space-sm);font-size:calc(var(--space-sm) + var(--space-xs) * .75);background:color-mix(in srgb,var(--color-info) 15%,transparent);color:var(--color-info)}.node-card__docker-meta{display:flex;gap:var(--space-sm);margin-top:var(--space-xs);font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.node-card__docker-meta span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mesh-topology{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-md);min-height:calc(var(--space-2xl) * 6.25);padding:var(--space-md);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md)}.mesh-topology__svg{width:100%;max-width:calc(var(--space-2xl) * 12.5);height:auto;aspect-ratio:1}.mesh-topology__node{transition:filter var(--transition-fast)}.mesh-topology__node:hover{filter:brightness(1.1)}.mesh-topology__node-circle{stroke:var(--border);stroke-width:calc(var(--space-xs) / 2);transition:fill var(--transition-fast)}.mesh-topology__node-label{font-size:calc(var(--space-sm) + var(--space-xs) * .75);fill:var(--text);font-weight:500}.mesh-topology__node-type-badge{fill:color-mix(in srgb,var(--surface) 75%,var(--bg));stroke:var(--border);stroke-width:calc(var(--space-xs) / 4)}.mesh-topology__node-type-text{font-size:calc(var(--space-sm) + var(--space-xs) / 2);font-weight:700;fill:var(--text-muted);text-transform:uppercase;letter-spacing:.03em}.mesh-topology__link{stroke:var(--border);stroke-width:calc((var(--space-xs) * 3) / 8);stroke-dasharray:var(--space-xs),var(--space-xs);opacity:.6}.mesh-topology__legend{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--space-md);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.mesh-topology__legend-item{display:flex;align-items:center;gap:var(--space-sm)}.mesh-topology__notice{margin:var(--space-md) 0 0;text-align:center;color:var(--text-dim);font-size:calc(var(--space-sm) + var(--space-xs))}.mesh-topology__legend-dot{width:calc(var(--space-sm) + var(--space-xs) / 2);height:calc(var(--space-sm) + var(--space-xs) / 2);border-radius:50%;border:1px solid var(--border)}.mesh-topology--empty{justify-content:center}.mesh-topology__empty-state{text-align:center;color:var(--text-muted);font-size:calc(var(--space-md) + var(--space-xs) / 2)}.connect-node-modal{width:min(calc(var(--space-lg) * 30),calc(100vw - (var(--space-lg) * 2)))}.connect-node-form{display:flex;flex-direction:column;gap:var(--space-md)}.connect-node-form .form-group{padding:0;margin-top:0}.connect-node-form .form-group:last-of-type{margin-bottom:0}.connect-node-field{display:flex;flex-direction:column;gap:var(--space-xs)}.connect-node-field__input{width:100%}.connect-node-field__input[aria-invalid=true]{border-color:var(--color-error);background:color-mix(in srgb,var(--color-error) 5%,var(--surface))}.connect-node-field__input[aria-invalid=true]:focus-visible{border-color:var(--color-error);box-shadow:var(--glow-danger)}.connect-node-url-preview{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);background:color-mix(in srgb,var(--surface) 50%,var(--bg));border-radius:var(--radius-sm);border-left:var(--space-xs) solid var(--accent);font-size:calc(var(--space-sm) + var(--space-xs))}.connect-node-url-preview-label{color:var(--text-muted)}.connect-node-url-preview code{font-family:var(--font-mono);color:var(--text);font-size:calc(var(--space-sm) + var(--space-xs))}.connect-node-actions{display:flex;justify-content:flex-end;gap:var(--space-sm);padding:var(--modal-padding);border-top:1px solid var(--border)}.nodes-view-topology{margin-bottom:var(--space-md)}.nodes-view-section-title{font-size:calc(var(--space-md) + var(--space-xs) * .5);font-weight:600;color:var(--text);margin:0 0 var(--space-sm)}.nodes-view .node-status-indicator{display:inline-flex;align-items:center;gap:var(--space-xs);font-size:calc(var(--space-sm) + var(--space-xs) * .625)}.nodes-view .node-status-indicator__label,.nodes-view .node-status-indicator--local{color:var(--text-muted)}.nodes-view .node-status-indicator--remote{color:var(--text)}.nodes-view .node-status-indicator__dot{width:var(--space-sm);height:var(--space-sm);border-radius:50%;position:relative;display:inline-block}.nodes-view .node-status-indicator__dot--online{background:var(--color-success);box-shadow:var(--glow-success)}.nodes-view .node-status-indicator__dot--offline,.nodes-view .node-status-indicator__dot--error{background:var(--color-error)}.nodes-view .node-status-indicator__dot--connecting{background:var(--color-warning);animation:pulse-warning var(--nodes-view-pulse-duration) ease-in-out infinite}.nodes-view .node-status-indicator__spinner{position:absolute;inset:0;border:calc(var(--space-xs) / 2) solid transparent;border-top-color:currentColor;border-radius:50%;animation:spin var(--nodes-view-spin-duration) linear infinite}.nodes-view .node-status-indicator__name{font-weight:500}.nodes-view .node-status-indicator__details{font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}@keyframes pulse-warning{0%,to{opacity:1;box-shadow:var(--glow-warning)}50%{opacity:.6;box-shadow:var(--glow-warning)}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.spin{animation:spin var(--nodes-view-spin-duration) linear infinite}@media(max-width:768px){.nodes-view{padding-inline:var(--space-sm)}.nodes-view-grid,.node-card__metrics{grid-template-columns:1fr}.node-card__docker-badge,.node-card__docker-meta{gap:var(--space-xs)}.node-card__docker-meta span{max-width:calc(var(--space-2xl) * 4.5)}.connect-node-modal{width:calc(100vw - (var(--space-md) * 2))}.connect-node-field__input{min-height:calc(var(--space-2xl) + var(--space-md))}.nodes-view-header{flex-wrap:wrap;gap:var(--space-sm)}.nodes-view-title h2{font-size:calc(var(--space-md) + var(--space-xs))}.nodes-view-title h2 svg{flex-shrink:0}.nodes-view-count{font-size:calc(var(--space-sm) + var(--space-xs))}.nodes-view-actions{flex-wrap:wrap;gap:var(--space-sm);width:100%;justify-content:flex-end}.nodes-view-close{min-height:calc(var(--space-xl) + var(--space-md));min-width:calc(var(--space-xl) + var(--space-md))}.nodes-view-actions .btn{min-height:calc(var(--space-xl) + var(--space-md))}.nodes-view-stats{grid-template-columns:repeat(2,1fr);gap:var(--space-sm)}.nodes-view-stat{padding:var(--space-xs) var(--space-sm)}.nodes-view-stat span{font-size:calc(var(--space-sm) + var(--space-xs) * .75)}.nodes-view-stat strong{font-size:calc(var(--space-md) + var(--space-xs) / 2)}.nodes-view-empty{padding:var(--space-xl) var(--space-md);text-align:center}.nodes-view-error{padding:var(--space-md);margin:var(--space-md) 0}.nodes-view-topology{padding:var(--space-sm) 0}.nodes-view-section-title{font-size:calc(var(--space-md) + var(--space-xs) / 4)}}.add-node-modal{width:min(calc(var(--space-lg) * 32.5),calc(100vw - (var(--space-lg) * 2)))}.add-node-modal__body{display:flex;flex-direction:column;gap:var(--space-md)}.add-node-modal__row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.add-node-modal__fieldset{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-sm)}.add-node-modal__fieldset legend{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs) * .625);padding:0 var(--space-xs)}.add-node-modal__storage-toggle{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-sm)}.add-node-modal__advanced-btn{align-self:flex-start}.add-node-modal__advanced{border:1px dashed var(--border);border-radius:var(--radius-sm);padding:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-sm)}.add-node-modal__textarea{min-height:calc(var(--space-2xl) * 2.25);resize:vertical;font-family:var(--font-mono)}.add-node-modal__description{font-size:calc(var(--space-sm) + var(--space-xs) * .625);color:var(--text-muted);margin-bottom:var(--space-sm);padding:0}.add-node-modal__field{display:flex;flex-direction:column;gap:var(--space-xs)}.add-node-modal__field>span{font-size:calc(var(--space-sm) + var(--space-xs) * .625);font-weight:600;color:var(--text-muted)}.add-node-modal__field .input{width:100%;padding:var(--space-sm) var(--space-md);font-size:calc(var(--space-md) + var(--space-xs) * .5)}.add-node-modal__field .input:focus-visible{border-color:var(--accent);box-shadow:var(--focus-ring-strong)}.add-node-modal__field .input[aria-invalid=true]{border-color:var(--color-error);background:color-mix(in srgb,var(--color-error) 5%,var(--surface))}.add-node-modal__field .input[aria-invalid=true]:focus{box-shadow:var(--glow-danger)}.add-node-modal__hint{font-size:calc(var(--space-sm) + var(--space-xs) * .375);color:var(--text-dim);margin-top:calc(var(--space-xs) / 2)}.add-node-modal__error{margin-top:calc(var(--space-xs) / 2)}.add-node-modal__type-toggle{display:flex;gap:0;border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;background:var(--surface)}.add-node-modal__type-btn{flex:1;padding:calc(var(--space-sm) + var(--space-xs) / 2) var(--space-lg);border:none;background:transparent;color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs) * .625);font-weight:500;cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.add-node-modal__type-btn:hover:not(:disabled){background:color-mix(in srgb,var(--bg) 50%,var(--surface))}.add-node-modal__type-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);z-index:1}.add-node-modal__type-btn.active{background:var(--accent);color:var(--bg)}.add-node-modal__type-btn:disabled{opacity:.6;cursor:not-allowed}.add-node-modal__remote-fields{display:grid;gap:var(--space-sm)}@media(max-width:768px){.add-node-modal{width:calc(100vw - (var(--space-md) * 2))}.add-node-modal__type-toggle{width:100%}.add-node-modal__type-btn{flex:1;padding:var(--space-md) var(--space-lg)}.add-node-modal__field input{min-height:calc(var(--space-2xl) + var(--space-md));font-size:calc(var(--space-md) + var(--space-xs) * .5)}.add-node-modal__row{grid-template-columns:1fr}}.docker-tls-config{display:flex;flex-direction:column;gap:var(--space-md)}.docker-tls-config__fields{display:grid;gap:var(--space-md)}.docker-tls-config__field{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-tls-config__field label{color:var(--text-muted)}@media(max-width:768px){.docker-tls-config .input{min-height:calc(var(--mobile-nav-height) - var(--space-sm))}}.docker-target-selector{display:flex;flex-direction:column;gap:var(--space-md)}.docker-target-selector__modes{display:flex;gap:var(--space-sm);flex-wrap:wrap}.docker-target-selector__mode-active{border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.docker-target-selector__panel{display:grid;gap:var(--space-md)}.docker-target-selector__field{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-target-selector__field label{color:var(--text-muted)}.docker-target-selector__context-row{display:grid;gap:var(--space-sm);grid-template-columns:minmax(0,1fr) auto;align-items:center}.docker-target-selector__status{color:var(--text-muted)}.docker-target-selector__success{color:var(--color-success)}.docker-target-selector__error{color:var(--color-error)}@media(max-width:768px){.docker-target-selector__modes .btn{min-height:calc(var(--mobile-nav-height) - var(--space-sm))}}.docker-onboarding{width:min(calc(var(--space-2xl) * 22.5),calc(100vw - (var(--space-lg) * 2)))}.docker-onboarding__body{display:flex;flex-direction:column;gap:var(--space-md)}.docker-onboarding__section{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md);display:flex;flex-direction:column;gap:var(--space-sm)}.docker-onboarding__section-title{margin:0;display:flex;align-items:center;gap:var(--space-sm);font-size:calc(var(--space-md) + var(--space-xs) / 2)}.docker-onboarding__field{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-onboarding__inline-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.docker-onboarding__radio-group{display:flex;align-items:center;gap:var(--space-md);flex-wrap:wrap}.docker-onboarding__type-toggle{display:flex;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}.docker-onboarding__type-btn{flex:1;border:none;background:var(--surface);color:var(--text);padding:var(--space-sm) var(--space-md);cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.docker-onboarding__type-btn+.docker-onboarding__type-btn{border-left:1px solid var(--border)}.docker-onboarding__type-btn.is-active{background:var(--todo);color:var(--bg)}.docker-onboarding__type-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);position:relative;z-index:1}.docker-onboarding__checkbox-group{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-onboarding__kv-list{display:flex;flex-direction:column;gap:var(--space-sm)}.docker-onboarding__kv-list h5{margin:0;font-size:calc(var(--space-sm) + var(--space-xs))}.docker-onboarding__kv-row{display:grid;gap:var(--space-sm);align-items:center}.docker-onboarding__kv-row--env{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto}.docker-onboarding__kv-row--mount{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto auto}.docker-onboarding__kv-add{align-self:flex-start}.docker-onboarding__advanced-toggle{border:none;background:none;color:var(--text);padding:var(--space-xs);margin:calc(var(--space-xs) * -1);border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:space-between;width:100%;cursor:pointer;font-size:calc(var(--space-md) + var(--space-xs) / 2);font-weight:600}.docker-onboarding__advanced-toggle:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.docker-onboarding__advanced-toggle svg{transition:transform var(--transition-fast)}.docker-onboarding__advanced-toggle.is-expanded svg{transform:rotate(180deg)}.docker-onboarding__advanced-content{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--transition-fast)}.docker-onboarding__advanced-content>div{overflow:hidden;display:flex;flex-direction:column;gap:var(--space-sm)}.docker-onboarding__advanced-content.is-expanded{grid-template-rows:1fr}.docker-onboarding__tls-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.docker-onboarding__tls-fields .docker-onboarding__field:first-child{grid-column:1 / -1}@media(max-width:768px){.docker-onboarding{width:calc(100vw - (var(--space-md) * 2))}.docker-onboarding__inline-fields,.docker-onboarding__tls-fields,.docker-onboarding__kv-row{grid-template-columns:1fr}.docker-onboarding .input,.docker-onboarding .select,.docker-onboarding .btn{min-height:calc(var(--space-2xl) + var(--space-md))}.docker-onboarding__advanced-content{transition:none}}.settings-sync-log{display:flex;flex-direction:column;gap:var(--space-sm)}.settings-sync-log__header{display:flex;align-items:center;gap:var(--space-xs);cursor:pointer;padding:var(--space-xs) 0;border-radius:var(--radius-sm);border:none;background:transparent;color:var(--text);font:inherit;text-align:left;transition:background-color var(--transition-fast)}.settings-sync-log__header:hover{background:var(--surface-hover)}.settings-sync-log__header:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);background:var(--surface-hover)}.settings-sync-log__chevron{transform:rotate(0);transition:transform var(--transition-fast)}.settings-sync-log__chevron--expanded{transform:rotate(180deg)}.settings-sync-log__filters{display:flex;gap:var(--space-sm);align-items:center;flex-wrap:wrap}.settings-sync-log__filters label{display:flex;align-items:center;gap:var(--space-xs);font-size:12px;color:var(--text-muted)}.settings-sync-log__filters select{font-size:12px;padding:4px 8px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text)}.settings-sync-log__filters select:focus{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring)}.settings-sync-log__list{display:flex;flex-direction:column}.settings-sync-log__entry{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-xs) 0;border-bottom:1px solid var(--border)}.settings-sync-log__entry:last-child{border-bottom:none}.settings-sync-log__entry-timestamp{font-size:12px;color:var(--text-muted);min-width:140px}.settings-sync-log__entry-direction{display:flex;align-items:center;color:var(--text-muted)}.settings-sync-log__entry-result{display:inline-flex;padding:2px 8px;border-radius:999px;font-size:11px;font-weight:500}.settings-sync-log__badge--success{background:color-mix(in srgb,var(--color-success, #2da44e) 14%,transparent);color:var(--color-success, #2da44e)}.settings-sync-log__badge--conflict{background:color-mix(in srgb,#d29922 14%,transparent);color:#d29922}.settings-sync-log__badge--error{background:color-mix(in srgb,var(--color-error, #cf222e) 14%,transparent);color:var(--color-error, #cf222e)}.settings-sync-log__entry-node{font-weight:500;font-size:12px}.settings-sync-log__entry-details{font-size:12px;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.settings-sync-log__empty{text-align:center;color:var(--text-muted);padding:var(--space-md);font-size:13px}.node-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;background:color-mix(in srgb,var(--accent) 14%,transparent);border:1px solid color-mix(in srgb,var(--accent) 36%,transparent);color:var(--text-muted);font-size:11px;width:fit-content;margin-top:4px}@media(max-width:768px){.settings-sync-conflict-modal__diff-panel{grid-template-columns:1fr}}.settings-sync-conflict-modal{max-width:860px;width:min(860px,calc(100vw - 32px))}.settings-sync-conflict-modal__conflict-list{display:flex;flex-direction:column;gap:var(--space-md);max-height:min(50vh,400px);overflow-y:auto}.settings-sync-conflict-modal__conflict-item{border:1px solid var(--border);border-radius:var(--radius);padding:var(--space-md)}.settings-sync-conflict-modal__key{font-weight:600;font-family:monospace;margin-bottom:var(--space-sm)}.settings-sync-conflict-modal__diff-panel{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-sm);margin-bottom:var(--space-sm)}.settings-sync-conflict-modal__diff-side{border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}.settings-sync-conflict-modal__diff-label{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted);padding:4px 8px;border-bottom:1px solid var(--border);background:var(--surface)}.settings-sync-conflict-modal__diff-content{padding:var(--space-xs) var(--space-sm);white-space:pre;font-family:monospace;font-size:12px;line-height:1.5;overflow-x:auto}.settings-sync-conflict-modal__resolution{display:flex;gap:var(--space-md);align-items:center}.settings-sync-conflict-modal__resolution label{display:flex;align-items:center;gap:var(--space-xs);cursor:pointer}.settings-sync-conflict-modal__resolution input[type=radio]{cursor:pointer}.settings-sync-conflict-modal__manual-input{width:100%;font-family:monospace;font-size:12px;min-height:80px;margin-top:var(--space-xs);padding:var(--space-sm);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);resize:vertical}.settings-sync-conflict-modal__manual-input:focus{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring)}.settings-sync-conflict-modal__bulk-actions{display:flex;gap:var(--space-xs);padding-top:var(--space-sm);border-top:1px solid var(--border)}.settings-sync-conflict-modal__footer{display:flex;justify-content:flex-end;gap:var(--space-xs)}.node-detail-modal{max-width:calc(var(--space-lg) * 53.75);width:min(calc(var(--space-lg) * 53.75),calc(100vw - (var(--space-lg) * 2)))}.node-detail-modal__body{display:flex;flex-direction:column;gap:var(--space-md);max-height:min(72vh,calc(var(--space-lg) * 42.5));overflow-y:auto}.node-detail-modal__section{border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md)}.node-detail-modal__section h4{margin:0 0 var(--space-sm) 0}.node-detail-modal__section-header{display:flex;justify-content:space-between;align-items:center;gap:var(--space-sm);margin-bottom:var(--space-sm)}.node-detail-modal__grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.node-detail-modal__field{display:flex;flex-direction:column;gap:var(--space-xs)}.node-detail-modal__field--full{grid-column:span 2}.node-detail-modal__field span{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__edit-actions{margin-top:var(--space-sm);display:flex;gap:var(--space-xs)}.node-detail-modal__project-list{margin:0;padding-left:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-sm)}.node-detail-modal__project-item{display:flex;justify-content:space-between;align-items:center;gap:var(--space-sm)}.node-detail-modal__project-item code{color:var(--text-muted)}.node-detail-modal__empty{margin:0;color:var(--text-muted)}.node-detail-modal__health-row{display:flex;flex-wrap:wrap;gap:var(--space-md)}.node-detail-modal__actions{justify-content:space-between}.node-detail-modal__docker-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm);margin-top:var(--space-sm)}.node-detail-modal__textarea{min-height:calc(var(--space-2xl) * 2.25);resize:vertical;font-family:var(--font-mono)}.node-detail-modal__sync-status{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-sm);margin-bottom:var(--space-sm)}.node-detail-modal__sync-dot{width:calc(var(--space-sm) + var(--space-xs) / 2);height:calc(var(--space-sm) + var(--space-xs) / 2);border-radius:50%;flex-shrink:0}.node-detail-modal__sync-dot--synced{background:var(--color-success)}.node-detail-modal__sync-dot--diff,.node-detail-modal__sync-dot--pending{background:var(--color-warning)}.node-detail-modal__sync-dot--error{background:var(--color-error)}.node-detail-modal__sync-dot--never{background:var(--text-muted)}.node-detail-modal__sync-diff{color:var(--color-warning);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__sync-actions{display:flex;flex-wrap:wrap;gap:var(--space-sm);margin-top:var(--space-sm)}.node-detail-modal__sync-error{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm);margin-top:var(--space-sm);padding:var(--space-sm);background:color-mix(in srgb,var(--color-error) 10%,transparent);border:1px solid color-mix(in srgb,var(--color-error) 30%,transparent);border-radius:var(--radius-sm);color:var(--color-error);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__sync-error-dismiss{background:transparent;border:none;color:var(--color-error);cursor:pointer;padding:calc(var(--space-xs) / 2);display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm)}.node-detail-modal__sync-error-dismiss:hover{background:color-mix(in srgb,var(--color-error) 20%,transparent)}.node-detail-modal__sync-error-dismiss:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);background:color-mix(in srgb,var(--color-error) 20%,transparent)}.docker-management{display:flex;flex-direction:column;gap:var(--space-md)}.docker-management__status-card{display:flex;flex-direction:column;gap:var(--space-sm);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md)}.docker-management__status-row{display:inline-flex;align-items:center;gap:var(--space-sm)}.docker-management__status-dot{width:var(--space-sm);height:var(--space-sm);border-radius:50%}.docker-management__status-dot--success{background:var(--color-success)}.docker-management__status-dot--warning{background:var(--color-warning)}.docker-management__status-dot--error{background:var(--color-error)}.docker-management__status-meta{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs));display:flex;gap:var(--space-md);flex-wrap:wrap}.docker-management__actions{display:flex;flex-wrap:wrap;gap:var(--space-sm)}.docker-management__info-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.docker-management__log-viewer{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md)}.docker-management__log-viewer-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-sm)}.docker-management__log-viewer pre{margin:0;max-height:calc(var(--space-2xl) * 9.375);overflow-y:auto;font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text);white-space:pre-wrap}.docker-management__env-list{margin:var(--space-sm) 0 0}.docker-management__env-list div{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr);gap:var(--space-sm);padding:var(--space-xs) 0}.docker-management__env-list dt{color:var(--text-muted);font-family:var(--font-mono)}.docker-management__env-list dd{margin:0;font-family:var(--font-mono);word-break:break-all}.docker-management__mounts-list{margin:var(--space-sm) 0 0;padding-left:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-sm)}.docker-management__mounts-list li{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}@media(max-width:768px){.node-detail-modal__grid,.node-detail-modal__docker-grid{grid-template-columns:1fr}.node-detail-modal__field--full{grid-column:span 1}.docker-management__actions{flex-direction:column}.docker-management__actions .btn{width:100%;justify-content:center}.docker-management__info-grid,.docker-management__env-list div{grid-template-columns:1fr}.docker-management__mounts-list li{flex-direction:column;align-items:flex-start}.docker-management__log-viewer pre{max-height:calc(var(--space-2xl) * 6.25)}}
@@ -1,11 +1,11 @@
1
- import{r as l,j as e}from"./vendor-react-K0fH_qHe.js";import{c as A,dZ as J,d_ as Q,d$ as V,R as $,dR as y,O as Y,a as T,b as ee,_ as se,cm as L,F as _,e0 as ae,e1 as te,e2 as D,X as ie}from"./index-k_85J1DS.js";import"./vendor-xterm-DzcZoU0P.js";/**
1
+ import{r as l,j as e}from"./vendor-react-K0fH_qHe.js";import{h as G,d6 as J,d7 as Q,d8 as V,R as $,cZ as y,P as Y,C as T,e as ee,a4 as se,bZ as L,F as D,d9 as ae,da as te,db as _,X as ie}from"./index-DNzA4aZ7.js";import"./vendor-xterm-DzcZoU0P.js";/**
2
2
  * @license lucide-react v1.7.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
- */const ne=[["path",{d:"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z",key:"e79jfc"}],["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor",key:"1okk4w"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor",key:"f64h9f"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor",key:"qy21gx"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor",key:"fotxhn"}]],M=A("palette",ne);/**
6
+ */const ne=[["path",{d:"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z",key:"e79jfc"}],["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor",key:"1okk4w"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor",key:"f64h9f"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor",key:"qy21gx"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor",key:"fotxhn"}]],M=G("palette",ne);/**
7
7
  * @license lucide-react v1.7.0 - ISC
8
8
  *
9
9
  * This source code is licensed under the ISC license.
10
10
  * See the LICENSE file in the root directory of this source tree.
11
- */const le=[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]],O=A("puzzle",le);function ce(t){return t.replace(/-/g,"-")}function re(t){return{"fusion-global":"Fusion Global","pi-global":"Pi Global","fusion-project":"Fusion Project","pi-project":"Pi Project",package:"Package"}[t]??t}function oe(t){return t.startsWith("npm:")?"npm":t.startsWith("git:")?"git":"local"}function de(t){return t.replace(/^(npm:|git:)/,"")}function he({addToast:t,projectId:x}){const[c,G]=l.useState(null),[f,P]=l.useState(!0),[N,S]=l.useState(!1),[E,w]=l.useState(!1),[h,F]=l.useState(""),[I,W]=l.useState(new Set),[p,q]=l.useState([]),[b,C]=l.useState(!0),[B,z]=l.useState(!1),r=l.useCallback(async()=>{try{P(!0);const s=await J();G(s)}catch(s){t(`Failed to load Pi settings: ${s instanceof Error?s.message:String(s)}`,"error")}finally{P(!1)}},[t]),m=l.useCallback(async()=>{try{C(!0);const s=await Q(x);q(s.extensions)}catch(s){t(`Failed to load extensions: ${s instanceof Error?s.message:String(s)}`,"error")}finally{C(!1)}},[t,x]),K=l.useCallback(async s=>{try{z(!0);const i=s.enabled?[...p.filter(a=>a.enabled&&a.id!==s.id).map(a=>a.id),s.id]:p.filter(a=>a.enabled&&a.id!==s.id).map(a=>a.id);await V(i,x),await m(),t(s.enabled?"Extension disabled":"Extension enabled","success")}catch(i){t(`Failed to update extension: ${i instanceof Error?i.message:String(i)}`,"error")}finally{z(!1)}},[p,x,m,t]);l.useEffect(()=>{r()},[r]),l.useEffect(()=>{m()},[m]);const U=s=>{W(i=>{const a=new Set(i);return a.has(s)?a.delete(s):a.add(s),a})},R=async()=>{if(!h.trim()){t("Please enter a package source","error");return}try{S(!0),await ae(h.trim()),t("Package installed successfully","success"),F(""),await r()}catch(s){t(`Failed to install package: ${s instanceof Error?s.message:String(s)}`,"error")}finally{S(!1)}},X=async()=>{try{w(!0),await te(x),await Promise.all([r(),m()]),t("Fusion skill reinstalled successfully","success")}catch(s){t(`Failed to reinstall Fusion skill: ${s instanceof Error?s.message:String(s)}`,"error")}finally{w(!1)}},Z=async s=>{if(!c)return;const i=c.packages.filter(a=>(typeof a=="string"?a:a.source)!==s);try{await D({packages:i}),t("Package removed","success"),await r()}catch(a){t(`Failed to remove package: ${a instanceof Error?a.message:String(a)}`,"error")}},H=async(s,i)=>{if(!c)return;const a=c[s].filter(n=>n!==i);try{await D({[s]:a}),t(`${s.slice(0,-1)} removed`,"success"),await r()}catch(n){t(`Failed to update settings: ${n instanceof Error?n.message:String(n)}`,"error")}},u=(s,i,a)=>!c||c[a].length===0?null:e.jsxs("div",{className:"pi-ext-section",children:[e.jsxs("div",{className:"pi-ext-section-header",children:[e.jsx(i,{size:14}),e.jsx("span",{children:s}),e.jsx("span",{className:"pi-ext-count",children:c[a].length})]}),e.jsx("div",{className:"pi-ext-resource-list",children:c[a].map((n,g)=>e.jsxs("span",{className:"pi-ext-resource-tag",children:[e.jsx("span",{className:"pi-ext-resource-path",children:n}),e.jsx("button",{className:"btn-icon touch-target pi-ext-resource-remove",onClick:()=>H(a,n),title:`Remove ${n}`,"aria-label":`Remove ${n}`,children:e.jsx(ie,{})})]},g))})]});return e.jsxs("div",{className:"pi-ext-manager",children:[e.jsxs("div",{className:"pi-ext-manager-header",children:[e.jsx("h4",{className:"pi-ext-manager-title",children:"Pi Extensions"}),e.jsx("div",{className:"pi-ext-manager-actions",children:e.jsx("button",{className:"btn-icon",onClick:r,title:"Refresh",disabled:f,children:e.jsx($,{size:16,className:f?"spin":""})})})]}),f?e.jsx("div",{className:"loading-state",children:"Loading Pi settings…"}):c?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"pi-ext-add-form",children:[e.jsxs("div",{className:"pi-ext-add-form-row",children:[e.jsx("input",{type:"text",className:"input",placeholder:"npm:pi-extension-name or git:https://github.com/...",value:h,onChange:s=>F(s.target.value),onKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),R())},disabled:N}),e.jsxs("button",{className:"btn btn-primary",onClick:R,disabled:N||!h.trim(),children:[e.jsx(Y,{size:14}),N?"Installing…":"Add"]})]}),e.jsx("div",{className:"pi-ext-add-form-row",children:e.jsx("button",{className:"btn",onClick:X,disabled:E,children:E?"Reinstalling Fusion…":"Reinstall Fusion skill"})})]}),c.packages.length>0?e.jsx("div",{className:"pi-ext-package-list",children:c.packages.map((s,i)=>{const a=typeof s=="string"?s:s.source,n=oe(a),g=de(a),j=typeof s=="object"&&s!==null,v=j&&(s.extensions?.length??0)>0||(s.skills?.length??0)>0||(s.prompts?.length??0)>0||(s.themes?.length??0)>0,k=I.has(i);return e.jsxs("div",{className:"pi-ext-package-card",children:[e.jsxs("div",{className:"pi-ext-package-header",children:[j&&v?e.jsx("button",{className:"pi-ext-expand-btn",onClick:()=>U(i),"aria-expanded":k,children:k?e.jsx(T,{size:14}):e.jsx(ee,{size:14})}):e.jsx("span",{className:"pi-ext-expand-placeholder"}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${n}`,children:n}),e.jsx("span",{className:"pi-ext-package-source",children:g}),e.jsxs("div",{className:"pi-ext-package-actions",children:[j&&v&&e.jsxs("span",{className:"pi-ext-filter-hint",children:[s.extensions?.length??0," ext,"," ",s.skills?.length??0," skill,"," ",s.prompts?.length??0," prompt,"," ",s.themes?.length??0," theme"]}),e.jsx("button",{className:"btn-icon touch-target pi-ext-remove-btn",onClick:()=>Z(a),title:"Remove package","aria-label":`Remove package ${g}`,children:e.jsx(se,{size:14})})]})]}),j&&v&&k&&e.jsxs("div",{className:"pi-ext-filter-list",children:[s.extensions?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(O,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Extensions:"}),s.extensions.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.skills?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(L,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Skills:"}),s.skills.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.prompts?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(_,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Prompts:"}),s.prompts.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.themes?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(M,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Themes:"}),s.themes.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null]})]},i)})}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"No packages configured."}),e.jsx("p",{className:"text-muted",children:"Add a package source above to get started."})]}),e.jsxs("div",{className:"pi-ext-top-level",children:[u("Extensions",O,"extensions"),u("Skills",L,"skills"),u("Prompts",_,"prompts"),u("Themes",M,"themes")]})]}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"Failed to load Pi settings."})]}),e.jsxs("div",{className:"pi-ext-discovered-section",children:[e.jsxs("div",{className:"pi-ext-discovered-header",children:[e.jsx("h4",{children:"Discovered Extensions"}),e.jsx("button",{className:"btn-icon",onClick:m,disabled:b,title:"Refresh extensions",children:e.jsx($,{className:b?"spin":""})})]}),e.jsx("p",{className:"pi-ext-description",children:"Installed extensions resolved from packages and configured paths."}),b?e.jsx("div",{className:"loading-state",children:"Loading extensions…"}):p.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"No extensions discovered."})]}):e.jsx("div",{className:"pi-ext-list",children:p.map(s=>e.jsxs("div",{className:"pi-ext-item",children:[e.jsxs("div",{className:"pi-ext-item-content",children:[e.jsxs("div",{className:"pi-ext-info",children:[e.jsx("span",{className:"pi-ext-name",children:s.name}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${ce(s.source)}`,children:re(s.source)})]}),e.jsx("span",{className:"pi-ext-path",children:s.path})]}),e.jsx("div",{className:"pi-ext-actions",children:e.jsxs("label",{className:"toggle-switch",children:[e.jsx("input",{type:"checkbox",checked:s.enabled,onChange:()=>void K(s),disabled:B,"aria-label":`Toggle ${s.name}`}),e.jsx("span",{className:"toggle-slider"})]})})]},s.id))})]})]})}export{he as PiExtensionsManager};
11
+ */const le=[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]],A=G("puzzle",le);function ce(t){return t.replace(/-/g,"-")}function re(t){return{"fusion-global":"Fusion Global","pi-global":"Pi Global","fusion-project":"Fusion Project","pi-project":"Pi Project",package:"Package"}[t]??t}function oe(t){return t.startsWith("npm:")?"npm":t.startsWith("git:")?"git":"local"}function de(t){return t.replace(/^(npm:|git:)/,"")}function he({addToast:t,projectId:x}){const[c,I]=l.useState(null),[f,P]=l.useState(!0),[N,S]=l.useState(!1),[E,w]=l.useState(!1),[h,F]=l.useState(""),[O,W]=l.useState(new Set),[p,Z]=l.useState([]),[b,C]=l.useState(!0),[q,z]=l.useState(!1),r=l.useCallback(async()=>{try{P(!0);const s=await J();I(s)}catch(s){t(`Failed to load Pi settings: ${s instanceof Error?s.message:String(s)}`,"error")}finally{P(!1)}},[t]),m=l.useCallback(async()=>{try{C(!0);const s=await Q(x);Z(s.extensions)}catch(s){t(`Failed to load extensions: ${s instanceof Error?s.message:String(s)}`,"error")}finally{C(!1)}},[t,x]),B=l.useCallback(async s=>{try{z(!0);const i=s.enabled?[...p.filter(a=>a.enabled&&a.id!==s.id).map(a=>a.id),s.id]:p.filter(a=>a.enabled&&a.id!==s.id).map(a=>a.id);await V(i,x),await m(),t(s.enabled?"Extension disabled":"Extension enabled","success")}catch(i){t(`Failed to update extension: ${i instanceof Error?i.message:String(i)}`,"error")}finally{z(!1)}},[p,x,m,t]);l.useEffect(()=>{r()},[r]),l.useEffect(()=>{m()},[m]);const K=s=>{W(i=>{const a=new Set(i);return a.has(s)?a.delete(s):a.add(s),a})},R=async()=>{if(!h.trim()){t("Please enter a package source","error");return}try{S(!0),await ae(h.trim()),t("Package installed successfully","success"),F(""),await r()}catch(s){t(`Failed to install package: ${s instanceof Error?s.message:String(s)}`,"error")}finally{S(!1)}},U=async()=>{try{w(!0),await te(x),await Promise.all([r(),m()]),t("Fusion skill reinstalled successfully","success")}catch(s){t(`Failed to reinstall Fusion skill: ${s instanceof Error?s.message:String(s)}`,"error")}finally{w(!1)}},X=async s=>{if(!c)return;const i=c.packages.filter(a=>(typeof a=="string"?a:a.source)!==s);try{await _({packages:i}),t("Package removed","success"),await r()}catch(a){t(`Failed to remove package: ${a instanceof Error?a.message:String(a)}`,"error")}},H=async(s,i)=>{if(!c)return;const a=c[s].filter(n=>n!==i);try{await _({[s]:a}),t(`${s.slice(0,-1)} removed`,"success"),await r()}catch(n){t(`Failed to update settings: ${n instanceof Error?n.message:String(n)}`,"error")}},u=(s,i,a)=>!c||c[a].length===0?null:e.jsxs("div",{className:"pi-ext-section",children:[e.jsxs("div",{className:"pi-ext-section-header",children:[e.jsx(i,{size:14}),e.jsx("span",{children:s}),e.jsx("span",{className:"pi-ext-count",children:c[a].length})]}),e.jsx("div",{className:"pi-ext-resource-list",children:c[a].map((n,g)=>e.jsxs("span",{className:"pi-ext-resource-tag",children:[e.jsx("span",{className:"pi-ext-resource-path",children:n}),e.jsx("button",{className:"btn-icon touch-target pi-ext-resource-remove",onClick:()=>H(a,n),title:`Remove ${n}`,"aria-label":`Remove ${n}`,children:e.jsx(ie,{})})]},g))})]});return e.jsxs("div",{className:"pi-ext-manager",children:[e.jsxs("div",{className:"pi-ext-manager-header",children:[e.jsx("h4",{className:"pi-ext-manager-title",children:"Pi Extensions"}),e.jsx("div",{className:"pi-ext-manager-actions",children:e.jsx("button",{className:"btn-icon",onClick:r,title:"Refresh",disabled:f,children:e.jsx($,{size:16,className:f?"spin":""})})})]}),f?e.jsx("div",{className:"loading-state",children:"Loading Pi settings…"}):c?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"pi-ext-add-form",children:[e.jsxs("div",{className:"pi-ext-add-form-row",children:[e.jsx("input",{type:"text",className:"input",placeholder:"npm:pi-extension-name or git:https://github.com/...",value:h,onChange:s=>F(s.target.value),onKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),R())},disabled:N}),e.jsxs("button",{className:"btn btn-primary",onClick:R,disabled:N||!h.trim(),children:[e.jsx(Y,{size:14}),N?"Installing…":"Add"]})]}),e.jsx("div",{className:"pi-ext-add-form-row",children:e.jsx("button",{className:"btn",onClick:U,disabled:E,children:E?"Reinstalling Fusion…":"Reinstall Fusion skill"})})]}),c.packages.length>0?e.jsx("div",{className:"pi-ext-package-list",children:c.packages.map((s,i)=>{const a=typeof s=="string"?s:s.source,n=oe(a),g=de(a),j=typeof s=="object"&&s!==null,v=j&&(s.extensions?.length??0)>0||(s.skills?.length??0)>0||(s.prompts?.length??0)>0||(s.themes?.length??0)>0,k=O.has(i);return e.jsxs("div",{className:"pi-ext-package-card",children:[e.jsxs("div",{className:"pi-ext-package-header",children:[j&&v?e.jsx("button",{className:"pi-ext-expand-btn",onClick:()=>K(i),"aria-expanded":k,children:k?e.jsx(T,{size:14}):e.jsx(ee,{size:14})}):e.jsx("span",{className:"pi-ext-expand-placeholder"}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${n}`,children:n}),e.jsx("span",{className:"pi-ext-package-source",children:g}),e.jsxs("div",{className:"pi-ext-package-actions",children:[j&&v&&e.jsxs("span",{className:"pi-ext-filter-hint",children:[s.extensions?.length??0," ext,"," ",s.skills?.length??0," skill,"," ",s.prompts?.length??0," prompt,"," ",s.themes?.length??0," theme"]}),e.jsx("button",{className:"btn-icon touch-target pi-ext-remove-btn",onClick:()=>X(a),title:"Remove package","aria-label":`Remove package ${g}`,children:e.jsx(se,{size:14})})]})]}),j&&v&&k&&e.jsxs("div",{className:"pi-ext-filter-list",children:[s.extensions?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(A,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Extensions:"}),s.extensions.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.skills?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(L,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Skills:"}),s.skills.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.prompts?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(D,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Prompts:"}),s.prompts.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.themes?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(M,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Themes:"}),s.themes.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null]})]},i)})}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"No packages configured."}),e.jsx("p",{className:"text-muted",children:"Add a package source above to get started."})]}),e.jsxs("div",{className:"pi-ext-top-level",children:[u("Extensions",A,"extensions"),u("Skills",L,"skills"),u("Prompts",D,"prompts"),u("Themes",M,"themes")]})]}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"Failed to load Pi settings."})]}),e.jsxs("div",{className:"pi-ext-discovered-section",children:[e.jsxs("div",{className:"pi-ext-discovered-header",children:[e.jsx("h4",{children:"Discovered Extensions"}),e.jsx("button",{className:"btn-icon",onClick:m,disabled:b,title:"Refresh extensions",children:e.jsx($,{className:b?"spin":""})})]}),e.jsx("p",{className:"pi-ext-description",children:"Installed extensions resolved from packages and configured paths."}),b?e.jsx("div",{className:"loading-state",children:"Loading extensions…"}):p.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"No extensions discovered."})]}):e.jsx("div",{className:"pi-ext-list",children:p.map(s=>e.jsxs("div",{className:"pi-ext-item",children:[e.jsxs("div",{className:"pi-ext-item-content",children:[e.jsxs("div",{className:"pi-ext-info",children:[e.jsx("span",{className:"pi-ext-name",children:s.name}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${ce(s.source)}`,children:re(s.source)})]}),e.jsx("span",{className:"pi-ext-path",children:s.path})]}),e.jsx("div",{className:"pi-ext-actions",children:e.jsxs("label",{className:"toggle-switch",children:[e.jsx("input",{type:"checkbox",checked:s.enabled,onChange:()=>void B(s),disabled:q,"aria-label":`Toggle ${s.name}`}),e.jsx("span",{className:"toggle-slider"})]})})]},s.id))})]})]})}export{he as PiExtensionsManager};
@@ -0,0 +1 @@
1
+ import{r as o,j as s}from"./vendor-react-K0fH_qHe.js";import{aZ as T,cY as ee,w as se,X as O,p as ne,P as A,a9 as _,a4 as M,R as te,cZ as ie,a0 as ae,bO as le,c_ as re,c$ as ce,d0 as de,d1 as ue,d2 as V,bL as oe}from"./index-DNzA4aZ7.js";import{D as ge}from"./DirectoryPicker-CTZE95Fk.js";import"./vendor-xterm-DzcZoU0P.js";const me=[{id:"fusion-plugin-agent-browser-runtime",name:"Agent Browser Runtime",path:"./plugins/fusion-plugin-agent-browser-runtime",experimental:!0},{id:"fusion-plugin-hermes-runtime",name:"Hermes Runtime",path:"./plugins/fusion-plugin-hermes-runtime",experimental:!0},{id:"fusion-plugin-paperclip-runtime",name:"Paperclip Runtime",path:"./plugins/fusion-plugin-paperclip-runtime"},{id:"fusion-plugin-openclaw-runtime",name:"OpenClaw Runtime",path:"./plugins/fusion-plugin-openclaw-runtime",experimental:!0},{id:"fusion-plugin-droid-runtime",name:"Droid Runtime",path:"./plugins/fusion-plugin-droid-runtime",experimental:!0}],N={started:"var(--color-success)",loaded:"var(--color-warning)",error:"var(--color-error)",stopped:"var(--color-muted)",installed:"var(--color-info)"};function Ne({addToast:l,projectId:c}){const[x,b]=o.useState([]),[S,w]=o.useState(!0),[H,f]=o.useState(!1),[j,v]=o.useState(""),[C,P]=o.useState(!1),[h,$]=o.useState(null),[i,y]=o.useState(null),[a,p]=o.useState({}),[Z,I]=o.useState(!1),[R,E]=o.useState(null),{confirm:G}=T(),g=o.useCallback(async()=>{try{w(!0);const e=await ee(c);b(e)}catch(e){l(`Failed to load plugins: ${e instanceof Error?e.message:String(e)}`,"error")}finally{w(!1)}},[c,l]);o.useEffect(()=>{g()},[g]);const J=o.useRef([]);J.current=x,o.useEffect(()=>{const e=c?`?projectId=${encodeURIComponent(c)}`:"",n=d=>{try{const t=JSON.parse(d.data);if(c&&t.projectId&&t.projectId!==c)return;switch(t.transition){case"installing":case"enabled":case"disabled":case"settings-updated":b(u=>{const m=u.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...u];return r[m]={...r[m],enabled:t.enabled,state:t.state,settings:t.settings,error:t.error},r}else return g(),u});break;case"uninstalled":b(u=>u.filter(m=>m.id!==t.pluginId));break;case"error":b(u=>{const m=u.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...u];return r[m]={...r[m],state:t.state,error:t.error},r}return u});break}}catch{}};return se(`/api/events${e}`,{events:{"plugin:lifecycle":n},onReconnect:()=>{g()}})},[c,g]);const z=async()=>{if(!j.trim()){l("Please enter a plugin path","error");return}try{P(!0),await V({path:j},c),l("Plugin installed successfully","success"),f(!1),v(""),await g()}catch(e){l(`Failed to install plugin: ${e instanceof Error?e.message:String(e)}`,"error")}finally{P(!1)}},K=async e=>{try{E(e.id),await V({path:e.path},c),l(`${e.name} installed successfully`,"success"),await g()}catch(n){l(`Failed to install ${e.name}: ${n instanceof Error?n.message:String(n)}`,"error")}finally{E(null)}},B=async e=>{try{await de(e.id,c),l(`${e.name} enabled`,"success"),await g()}catch(n){l(`Failed to enable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},F=async e=>{try{await ce(e.id,c),l(`${e.name} disabled`,"success"),await g()}catch(n){l(`Failed to disable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},L=async e=>{try{$(e.id),await re(e.id,c),l(`${e.name} reloaded`,"success"),await g()}catch(n){l(`Failed to reload plugin: ${n instanceof Error?n.message:String(n)}`,"error")}finally{$(null)}},D=async e=>{if(await G({title:"Uninstall Plugin",message:`Are you sure you want to uninstall "${e.name}"?`,danger:!0}))try{await ue(e.id,c),l(`${e.name} uninstalled`,"success"),await g(),y(null)}catch(d){l(`Failed to uninstall plugin: ${d instanceof Error?d.message:String(d)}`,"error")}},U=async e=>{y(e);try{I(!0);const n=await oe(e.id,c);p(n)}catch{p({})}finally{I(!1)}},X=async()=>{if(i)try{await le(i.id,a,c),l("Settings saved","success")}catch(e){l(`Failed to save settings: ${e instanceof Error?e.message:String(e)}`,"error")}};if(i)return s.jsxs("div",{className:"plugin-manager-detail","data-testid":"plugin-manager-detail",children:[s.jsxs("div",{className:"plugin-manager-detail-header",children:[s.jsx("button",{className:"btn-icon",onClick:()=>y(null),"aria-label":"Back to plugin list",children:s.jsx(O,{size:16})}),s.jsxs("div",{className:"plugin-detail-title",children:[s.jsx("h4",{className:"plugin-detail-name",children:i.name}),s.jsx("span",{className:"plugin-state-badge",style:{color:N[i.state]||N.installed},children:i.state})]})]}),s.jsxs("div",{className:"plugin-detail-content",children:[s.jsxs("div",{className:"plugin-detail-card",children:[i.description&&s.jsx("p",{className:"plugin-description",children:i.description}),i.author&&s.jsxs("p",{className:"plugin-detail-meta-row",children:[s.jsx("span",{className:"text-muted",children:"Author:"}),i.author]}),i.homepage&&s.jsxs("p",{className:"plugin-detail-meta-row plugin-homepage",children:[s.jsx("span",{className:"text-muted",children:"Homepage:"}),s.jsxs("a",{href:i.homepage,target:"_blank",rel:"noopener noreferrer",children:[i.homepage,s.jsx(ne,{size:12})]})]}),s.jsxs("p",{className:"plugin-detail-meta-row",children:[s.jsx("span",{className:"text-muted",children:"Version:"}),i.version]})]}),s.jsxs("div",{className:"plugin-detail-card",children:[s.jsx("h5",{className:"plugin-detail-section-heading",children:"Settings"}),Z?s.jsx("p",{className:"text-muted",children:"Loading..."}):i.settingsSchema&&Object.keys(i.settingsSchema).length>0?s.jsxs("div",{className:"plugin-settings-form",children:[Object.entries(i.settingsSchema).map(([e,n])=>{const d=`setting-${e}-help`;return s.jsxs("div",{className:"form-group",children:[s.jsxs("label",{htmlFor:`setting-${e}`,children:[n.label||e,n.required&&" *"]}),n.type==="string"&&!n.multiline&&s.jsx("input",{className:"input",type:"text",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?d:void 0}),n.type==="string"&&n.multiline&&s.jsx("textarea",{className:"input",id:`setting-${e}`,rows:4,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?d:void 0}),n.type==="password"&&s.jsx("input",{className:"input",type:"password",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?d:void 0}),n.type==="number"&&s.jsx("input",{className:"input",type:"number",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:Number(t.target.value)}),"aria-describedby":n.description&&!n.required?d:void 0}),n.type==="boolean"&&s.jsxs("label",{className:"checkbox-label",children:[s.jsx("input",{type:"checkbox",checked:a[e]??!1,onChange:t=>p({...a,[e]:t.target.checked})}),n.description]}),n.type==="enum"&&s.jsxs("select",{className:"select",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),"aria-describedby":n.description&&!n.required?d:void 0,children:[s.jsx("option",{value:"",children:"Select..."}),n.enumValues?.map(t=>s.jsx("option",{value:t,children:t},t))]}),n.type==="array"&&s.jsxs("div",{className:"plugin-settings-array",children:[a[e]?.map((t,u)=>s.jsxs("div",{className:"plugin-settings-array-item",children:[s.jsx("input",{className:"input",type:n.itemType==="number"?"number":"text",value:t??"",onChange:m=>{const r=m.target.value,k=[...a[e]||[]];k[u]=n.itemType==="number"?Number(r):r,p({...a,[e]:k})}}),s.jsx("button",{className:"btn-icon",onClick:()=>{const r=[...a[e]||[]];r.splice(u,1),p({...a,[e]:r})},"aria-label":"Remove item",children:s.jsx(O,{size:14})})]},u)),s.jsxs("button",{className:"btn btn-secondary",onClick:()=>{const t=a[e]||[],u=n.itemType==="number"?0:"";p({...a,[e]:[...t,u]})},children:[s.jsx(A,{size:14})," Add Item"]})]}),n.description&&!n.required&&!n.multiline&&s.jsx("span",{id:d,className:"form-help",children:n.description})]},e)}),s.jsx("button",{className:"btn btn-primary",onClick:X,children:"Save Settings"})]}):s.jsx("p",{className:"text-muted",children:"No configurable settings."})]}),s.jsxs("div",{className:"plugin-detail-actions",children:[i.state==="started"&&s.jsxs("button",{className:"btn btn-secondary",onClick:()=>L(i),disabled:h===i.id,children:[s.jsx(_,{size:14,className:h===i.id?"spin":""}),h===i.id?"Reloading...":"Reload"]}),i.enabled?s.jsx("button",{className:"btn btn-secondary",onClick:()=>F(i),children:"Disable"}):s.jsx("button",{className:"btn btn-primary",onClick:()=>B(i),children:"Enable"}),s.jsxs("button",{className:"btn btn-danger",onClick:()=>D(i),children:[s.jsx(M,{size:14})," Uninstall"]})]})]})]});const Y=new Set(x.map(e=>e.id)),Q=new Map(x.map(e=>[e.id,e])),q=x,W=()=>s.jsxs("section",{className:"plugin-bundled-runtime-section","aria-label":"Bundled Plugins",children:[s.jsxs("div",{className:"plugin-bundled-runtime-header",children:[s.jsx("h4",{className:"plugin-bundled-runtime-heading",children:"Bundled Plugins"}),s.jsx("p",{className:"plugin-bundled-runtime-description",children:"Install Fusion's bundled plugins directly from this screen."})]}),s.jsx("div",{className:"plugin-bundled-runtime-list","aria-label":"Bundled plugin recommendations",children:me.map(e=>{const n=Y.has(e.id);return s.jsxs("div",{className:"plugin-bundled-runtime-item",children:[s.jsxs("div",{className:"plugin-bundled-runtime-meta",children:[s.jsx("span",{className:"plugin-bundled-runtime-name",children:e.name}),e.experimental&&s.jsx("span",{className:"plugin-bundled-runtime-badge",children:"Experimental"}),s.jsx("span",{className:`plugin-bundled-runtime-status ${n?"plugin-bundled-runtime-status--installed":"plugin-bundled-runtime-status--available"}`,children:n?"Installed":"Not installed"})]}),s.jsx("button",{className:`btn ${n?"btn-secondary":"btn-primary"} btn-sm`,onClick:()=>{if(n){const d=Q.get(e.id);d&&U(d);return}K(e)},disabled:R===e.id,children:n?"Manage":R===e.id?"Installing...":`Install ${e.name}`})]},e.id)})})]});return s.jsxs("div",{className:"plugin-manager","data-testid":"plugin-manager",children:[s.jsxs("div",{className:"plugin-manager-header",children:[s.jsx("span",{className:"plugin-manager-header-title",children:"Installed Plugins"}),s.jsxs("div",{className:"plugin-manager-actions",children:[s.jsxs("button",{className:"btn btn-sm",onClick:g,title:"Refresh","aria-label":"Refresh plugin list",children:[s.jsx(te,{size:14,className:S?"spin":""}),"Refresh"]}),s.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>f(!0),children:[s.jsx(A,{size:14})," Install"]})]})]}),H&&s.jsxs("div",{className:"plugin-install-form",children:[s.jsxs("p",{className:"plugin-install-hint",children:["Browse to a plugin package root (contains ",s.jsx("code",{children:"manifest.json"}),") or a built ",s.jsx("code",{children:"dist"})," directory."]}),s.jsx(ge,{value:j,onChange:v,placeholder:"Absolute path to plugin directory or dist folder",onInputKeyDown:e=>{e.key==="Enter"&&(e.preventDefault(),z())}}),s.jsxs("div",{className:"plugin-install-actions",children:[s.jsx("button",{className:"btn btn-primary",onClick:z,disabled:C||!j.trim(),children:C?"Installing...":"Install Plugin"}),s.jsx("button",{className:"btn btn-secondary",onClick:()=>{f(!1),v("")},children:"Cancel"})]})]}),S?s.jsx("div",{className:"settings-empty-state",children:"Loading plugins..."}):s.jsxs(s.Fragment,{children:[q.length===0?s.jsxs("div",{className:"settings-empty-state",children:[s.jsx(ie,{size:32,className:"text-muted"}),s.jsx("p",{children:"No plugins installed."}),s.jsx("p",{className:"text-muted",children:"Install a plugin to get started, or use a bundled plugin below."})]}):s.jsx("div",{className:"plugin-list",children:q.map(e=>s.jsxs("div",{className:"plugin-item",children:[s.jsxs("div",{className:"plugin-info",children:[s.jsx("span",{className:"plugin-name",children:e.name}),s.jsxs("span",{className:"plugin-version text-muted",children:["v",e.version]}),s.jsx("span",{className:"plugin-state-badge",style:{color:N[e.state]||N.installed},children:e.state})]}),s.jsxs("div",{className:"plugin-actions",children:[e.state==="started"&&s.jsx("button",{className:"btn-icon",onClick:()=>L(e),disabled:h===e.id,title:"Reload",children:s.jsx(_,{size:14,className:h===e.id?"spin":""})}),s.jsxs("label",{className:"toggle-switch",children:[s.jsx("input",{type:"checkbox",checked:e.enabled,onChange:()=>e.enabled?F(e):B(e)}),s.jsx("span",{className:"toggle-slider"})]}),s.jsx("button",{className:"btn-icon",onClick:()=>U(e),title:"Settings",children:s.jsx(ae,{size:14})}),s.jsx("button",{className:"btn-icon",onClick:()=>D(e),title:"Uninstall",children:s.jsx(M,{size:14})})]})]},e.id))}),W()]})]})}export{Ne as PluginManager,N as STATE_COLORS};
@@ -0,0 +1 @@
1
+ import{r as i,j as e}from"./vendor-react-K0fH_qHe.js";import{u as oe,v as de,w as ue,x as he,y as me,z as be,B as fe,D as ve,G as pe,H as xe,I as ye,J as ge,K as je,N as Re,O as Se,S as _e}from"./index-DNzA4aZ7.js";import"./vendor-xterm-DzcZoU0P.js";const O={webSearch:!0,pageFetch:!0,github:!1,localDocs:!0,llmSynthesis:!0};function X(n){const t=n?.researchGlobalDefaults,c=n?.researchSettings;return{enabled:c?.enabled??n?.researchEnabled??n?.researchGlobalEnabled??!0,searchProvider:c?.searchProvider??t?.searchProvider,synthesisProvider:c?.synthesisProvider??t?.synthesisProvider,synthesisModelId:c?.synthesisModelId??t?.synthesisModelId,enabledSources:{webSearch:c?.enabledSources?.webSearch??t?.enabledSources?.webSearch??O.webSearch,pageFetch:c?.enabledSources?.pageFetch??t?.enabledSources?.pageFetch??O.pageFetch,github:c?.enabledSources?.github??t?.enabledSources?.github??O.github,localDocs:c?.enabledSources?.localDocs??t?.enabledSources?.localDocs??O.localDocs,llmSynthesis:c?.enabledSources?.llmSynthesis??t?.enabledSources?.llmSynthesis??O.llmSynthesis},limits:{maxConcurrentRuns:c?.limits?.maxConcurrentRuns??n?.researchMaxConcurrentRuns??n?.researchGlobalMaxConcurrentRuns??3,maxSourcesPerRun:c?.limits?.maxSourcesPerRun??t?.maxSourcesPerRun??n?.researchMaxSourcesPerRun??n?.researchGlobalMaxSourcesPerRun??20,maxDurationMs:c?.limits?.maxDurationMs??n?.researchDefaultTimeout??n?.researchGlobalDefaultTimeout??3e5,requestTimeoutMs:c?.limits?.requestTimeoutMs??n?.researchFetchTimeoutMs??3e4},defaultExportFormat:t?.defaultExportFormat??"markdown"}}const we=300,Ne=4e3,ke=["queued","running","cancelling","retry_waiting"];function Z(n,t){if(n instanceof xe){const c=n;return{message:n.message,status:n.status,code:c.researchCode??"INTERNAL_ERROR",setupHint:c.setupHint,retryable:c.retryable}}return n instanceof Error?{message:n.message,code:"INTERNAL_ERROR"}:{message:t,code:"INTERNAL_ERROR"}}function Ee(n){if(!n)return{cancelable:!1,retryable:!1,isTransitioning:!1,blockingReason:"No run selected"};const t=ke.includes(n.status),c=n.status==="queued"||n.status==="running",f=n.lifecycle?.retryable,u=n.status==="failed"||n.status==="timed_out",a=!!(u&&f);let x;return!c&&t?x="Run is already transitioning":!c&&n.status==="completed"?x="Completed runs cannot be cancelled":!c&&n.status==="cancelled"?x="Run is already cancelled":!c&&n.status==="retry_exhausted"?x="Retry attempts exhausted":!c&&n.status==="failed"?x="Failed runs cannot be cancelled":!c&&n.status==="timed_out"&&(x="Timed out runs cannot be cancelled"),!a&&u&&f===!1&&(x=n.lifecycle?.errorCode==="RETRY_EXHAUSTED"?"Retry attempts exhausted":"Run is not retryable"),{cancelable:c,retryable:a,isTransitioning:t,blockingReason:x}}function Ce(n){const t=n?.projectId,[c,f]=i.useState([]),[u,a]=i.useState(null),[x,R]=i.useState(null),[g,w]=i.useState({available:!0}),[k,P]=i.useState(!0),[L,T]=i.useState(null),[M,j]=i.useState(null),[S,F]=i.useState(""),E=i.useRef(0),N=i.useRef(0),_=i.useRef(t);i.useEffect(()=>{_.current!==t&&(_.current=t,N.current++)},[t]);const v=i.useCallback(async(o=S)=>{const r=++E.current,l=t;T(null),j(null);try{const y=await oe({q:o||void 0,limit:100},l);if(r!==E.current||l!==t)return;f(y.runs),w(y.availability),u&&!y.runs.some(b=>b.id===u)&&(a(null),R(null))}catch(y){if(r!==E.current||l!==t)return;const b=Z(y,"Failed to load research runs");T(b.message),j(b)}finally{r===E.current&&P(!1)}},[t,S,u]),p=i.useCallback(async o=>{const r=await de(o,t);return R(r.run),w(r.availability),r.run},[t]);return i.useEffect(()=>{P(!0);const o=window.setTimeout(()=>{v(S)},we);return()=>window.clearTimeout(o)},[v,S]),i.useEffect(()=>{if(!u){R(null);return}p(u)},[p,u]),i.useEffect(()=>{const o=N.current,r=()=>N.current!==o,l=t?`?projectId=${encodeURIComponent(t)}`:"";let y=!0;const b=()=>{!y||r()||(v(),u&&p(u))},D=ue(`/api/events${l}`,{events:{"research:run:created":b,"research:run:updated":b,"research:run:completed":b,"research:run:failed":b,"research:run:cancelled":b},onReconnect:b}),U=window.setInterval(b,Ne);return()=>{y=!1,D(),window.clearInterval(U)}},[t,v,u,p]),{runs:c,selectedRun:x,selectedRunId:u,setSelectedRunId:a,availability:g,loading:k,error:L,searchQuery:S,setSearchQuery:F,refresh:v,createRun:o=>pe(o,t),cancelRun:async o=>{try{j(null);const r=await ve(o,t);return u===o&&R(r.run),await v(),r}catch(r){const l=Z(r,"Failed to cancel run");throw j(l),l}},retryRun:async o=>{try{j(null);const r=await fe(o,t);return u===o&&R(r.run),await v(),r}catch(r){const l=Z(r,"Failed to retry run");throw j(l),l}},exportRun:(o,r)=>be(o,r,t),createTaskFromRun:(o,r,l,y,b,D)=>me(o,{title:r,findingId:l,description:y,priority:b,attachExport:D},t),attachRunToTask:(o,r,l,y)=>he(o,{taskId:r,findingId:l,attachExport:y},t),uiError:M,runActionState:Ee(x),statusCounts:c.reduce((o,r)=>(o[r.status]+=1,o),{queued:0,running:0,cancelling:0,retry_waiting:0,completed:0,failed:0,cancelled:0,timed_out:0,retry_exhausted:0})}}function Pe({open:n,mode:t,run:c,finding:f,projectId:u,onClose:a,onConfirm:x}){ye(n);const[R,g]=i.useState(!1),[w,k]=i.useState(""),[P,L]=i.useState(""),[T,M]=i.useState("normal"),[j,S]=i.useState(""),[F,E]=i.useState([]),[N,_]=i.useState(!1),[v,p]=i.useState(!1),o=i.useMemo(()=>{const r=(f.content??"").split(/(?<=[.!?])\s+/)[0]??"";return`${f.heading||"Research finding"} — ${r}`.trim()},[f.content,f.heading]);return i.useEffect(()=>{n&&(g(!1),k(`Research: ${f.heading||c.title}`),L(o),M("normal"),S(""),t==="enrich"&&(_(!0),ge(50,0,u).then(r=>E(r.filter(l=>l.column!=="archived"))).finally(()=>_(!1))))},[n,t,u,f.heading,o,c.title]),n?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:r=>r.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:"})," ",c.id]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Finding:"})," ",f.id,f.heading?` — ${f.heading}`:""]}),e.jsx("p",{children:o||"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:w,onChange:r=>k(r.target.value)})]}),e.jsxs("label",{className:"research-task-action-modal__field",children:["Description",e.jsx("textarea",{className:"input research-task-action-modal__textarea",value:P,onChange:r=>L(r.target.value)})]}),e.jsxs("label",{className:"research-task-action-modal__field",children:["Priority",e.jsxs("select",{className:"select",value:T,onChange:r=>M(r.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:j,placeholder:N?"Loading tasks…":"Enter task ID",onChange:r=>S(r.target.value)}),e.jsx("datalist",{id:"research-task-action-task-list",children:F.map(r=>e.jsx("option",{value:r.id,children:r.title},r.id))})]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:R,onChange:r=>g(r.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:v||t==="enrich"&&!j,onClick:()=>{p(!0),x({taskId:t==="enrich"?j:void 0,title:t==="create"?w.trim():void 0,description:t==="create"?P.trim():void 0,priority:t==="create"?T:void 0,attachExport:R}).finally(()=>p(!1))},children:t==="create"?"Create Task":"Enrich Task"})]})]})}):null}const Te=["web-search","page-fetch","github","local-docs","llm-synthesis"],Ae={"web-search":"webSearch","page-fetch":"pageFetch",github:"github","local-docs":"localDocs","llm-synthesis":"llmSynthesis"},Ie={"web-search":"Web Search","page-fetch":"Page Fetch",github:"GitHub","local-docs":"Local Docs","llm-synthesis":"LLM Synthesis"};function qe({projectId:n,addToast:t,onOpenSettings:c,readinessVersion:f=0}){const{runs:u,selectedRun:a,selectedRunId:x,setSelectedRunId:R,availability:g,loading:w,error:k,searchQuery:P,setSearchQuery:L,createRun:T,cancelRun:M,retryRun:j,exportRun:S,createTaskFromRun:F,attachRunToTask:E,statusCounts:N,refresh:_,uiError:v,runActionState:p}=Ce({projectId:n}),[o,r]=i.useState(""),[l,y]=i.useState(()=>X(void 0)),[b,D]=i.useState([]),[U,z]=i.useState(!1),[ee,se]=i.useState([]),[A,$]=i.useState(null),[I,H]=i.useState(null),Q=g.supportedProviders??Te,G=s=>l.enabledSources[Ae[s]];i.useEffect(()=>{const s=Q.filter(d=>G(d));se(d=>{const m=d.filter(h=>s.includes(h));return m.length>0?m:s})},[l.enabledSources,Q]),i.useEffect(()=>{let s=!1;return Promise.all([je(n),Re().catch(()=>({providers:[]}))]).then(([d,m])=>{s||(y(X(d)),D(m.providers.filter(h=>h.type==="api_key").map(h=>({id:h.id,authenticated:h.authenticated}))))}).catch(()=>{s||y(X(void 0))}),()=>{s=!0}},[n,f]);const ie=i.useMemo(()=>a?a.status:"No run selected",[a]),ce=i.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]),K=g.supportedExportFormats??["markdown","json","html"],V=l.searchProvider,te=l.enabledSources.webSearch&&!V,re=l.enabledSources.llmSynthesis&&(!l.synthesisProvider||!l.synthesisModelId),J=i.useMemo(()=>new Map(b.map(s=>[s.id,s.authenticated])),[b]),Y=i.useMemo(()=>{const s=new Set;return l.enabledSources.webSearch&&V&&s.add(V),l.enabledSources.llmSynthesis&&l.synthesisProvider&&s.add(l.synthesisProvider),[...s].filter(d=>J.has(d))},[l.enabledSources.llmSynthesis,l.enabledSources.webSearch,l.synthesisProvider,V,J]).find(s=>J.get(s)!==!0),q=i.useMemo(()=>g.available?l.enabled?te||re?{reason:"Research defaults are incomplete.",details:"Select the required provider/model defaults in Research settings.",settingsSection:"research-global"}:Y?{reason:`Missing API key for ${Y}.`,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:g.reason??"Research is unavailable for this project.",details:g.setupInstructions,settingsSection:"research-project"},[g.available,g.reason,g.setupInstructions,l.enabled,Y,te,re]),B=async(s,d,m)=>{$(s);try{await d(),t?.(m,"success"),await _()}catch(h){t?.(h instanceof Error?h.message:"Action failed","error")}finally{$(null)}},W=async s=>{if(a){$(`export-${s}`);try{const d=await S(a.id,s),m=new Blob([d.content],{type:"text/plain;charset=utf-8"}),h=URL.createObjectURL(m),C=document.createElement("a");C.href=h,C.download=d.filename,document.body.appendChild(C),C.click(),C.remove(),URL.revokeObjectURL(h),t?.(`Exported ${d.filename}`,"success")}catch(d){t?.(d instanceof Error?d.message:"Export failed","error")}finally{$(null)}}},le=async()=>{if(o.trim()){z(!0);try{const s=ee.filter(m=>G(m));if(s.length===0){z(!1),t?.("No enabled research sources are available for this project.","error");return}const d=await T({query:o.trim(),providers:s});R(d.run.id),r(""),t?.("Research run created","success"),await _()}catch(s){t?.(s instanceof Error?s.message:"Failed to create run","error")}finally{z(!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:"Create and track research runs with cited findings."})]}),e.jsx("button",{className:"btn",type:"button",onClick:()=>void _(),children:"Refresh"})]}),q?e.jsxs("div",{className:"research-view__state research-view__state--error card","data-testid":"research-state-unavailable",children:[e.jsx("p",{children:q.reason}),q.details&&e.jsx("p",{children:q.details}),e.jsxs("p",{children:["Current defaults: provider ",l.searchProvider??"(not set)",", max sources ",l.limits.maxSourcesPerRun]}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",onClick:()=>void _(),children:"Refresh"}),e.jsx("button",{className:"btn btn-primary",type:"button",onClick:()=>c?.(q.settingsSection),children:"Open Settings"})]})]}):e.jsxs("div",{className:"research-view__layout",children:[e.jsxs("aside",{className:"research-view__sidebar card",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:o,onChange:s=>r(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=>e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:ee.includes(s),disabled:!G(s),onChange:()=>{G(s)&&se(d=>d.includes(s)?d.filter(m=>m!==s):[...d,s])}}),e.jsx("span",{children:Ie[s]??s})]},s))})]}),e.jsxs("button",{className:"btn btn-primary",type:"button",disabled:!o.trim()||U,onClick:()=>void le(),children:[U?e.jsx(Se,{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(_e,{size:14}),e.jsx("input",{id:"research-run-search",className:"input",placeholder:"Search runs",value:P,onChange:s=>L(s.target.value)})]})]}),e.jsx("div",{className:"research-view__history","data-testid":"research-state-running",children:u.map(s=>e.jsxs("button",{type:"button",className:`research-view__history-item card${x===s.id?" research-view__history-item--active":""}`,onClick:()=>R(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:[w&&e.jsx("p",{"data-testid":"research-state-loading",children:"Loading research runs…"}),!w&&k&&e.jsx("p",{"data-testid":"research-state-error",children:k}),!w&&!k&&u.length===0&&e.jsx("p",{"data-testid":"research-state-empty",children:"No research runs yet"}),a&&e.jsxs("div",{children:[e.jsxs("div",{className:"research-view__status-row",children:[e.jsx("span",{className:ce}),e.jsx("strong",{children:ie})]}),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:p.cancelable?void 0:p.blockingReason,disabled:A==="cancel"||A==="retry"||!p.cancelable,onClick:()=>void B("cancel",()=>M(a.id),"Run cancelled"),children:"Cancel"}),e.jsx("button",{className:"btn",type:"button",title:p.retryable?void 0:p.blockingReason,disabled:A==="cancel"||A==="retry"||!p.retryable,onClick:()=>void B("retry",()=>j(a.id),"Run retried"),children:"Retry"}),K.includes("markdown")&&e.jsx("button",{className:"btn",type:"button",disabled:A==="export-markdown",onClick:()=>void W("markdown"),children:"Export MD"}),K.includes("json")&&e.jsx("button",{className:"btn",type:"button",disabled:A==="export-json",onClick:()=>void W("json"),children:"Export JSON"}),K.includes("html")&&e.jsx("button",{className:"btn",type:"button",disabled:A==="export-html",onClick:()=>void W("html"),children:"Export HTML"})]}),a.error&&e.jsx("p",{className:"research-view__error",children:a.error}),v&&e.jsxs("div",{className:"form-error",role:"alert",children:[e.jsx("p",{children:v.message}),v.setupHint&&e.jsx("p",{children:v.setupHint}),v.code==="MISSING_CREDENTIALS"&&e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>c?.("authentication"),children:"Open Authentication Settings"}),v.code==="FEATURE_DISABLED"&&e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>c?.("research-project"),children:"Open Research Settings"})]}),p.blockingReason&&e.jsx("p",{className:"research-view__run-query",children:p.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 h=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:()=>H({mode:"create",findingId:h}),children:"Create Task"}),e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>H({mode:"enrich",findingId:h}),children:"Enrich Task"})]})]},h)})}),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&&u.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:N.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:N.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:N.failed})]})]})]})]}),a&&I&&(()=>{const s=a.results?.findings?.findIndex((m,h)=>(m.id?.trim()||`finding-${h+1}`)===I.findingId)??-1,d=s>=0?a.results.findings[s]:null;return d?e.jsx(Pe,{open:!0,mode:I.mode,run:a,finding:{id:I.findingId,heading:d.heading,content:d.content},projectId:n,onClose:()=>H(null),onConfirm:async({taskId:m,title:h,description:C,priority:ae,attachExport:ne})=>{I.mode==="create"?await B("create-task",()=>F(a.id,h,I.findingId,C,ae,ne),"Task created from research"):m&&await B("attach-task",()=>E(a.id,m,I.findingId,ne),"Task enriched from research"),H(null)}}):null})()]})}export{qe as ResearchView};