@runfusion/fusion 0.6.0 → 0.7.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 (64) hide show
  1. package/dist/bin.js +5183 -1528
  2. package/dist/client/assets/AgentDetailView-C1_lTTET.css +1 -0
  3. package/dist/client/assets/AgentDetailView-DyzuiJas.js +18 -0
  4. package/dist/client/assets/AgentsView-C2f7esMv.css +1 -0
  5. package/dist/client/assets/AgentsView-CgweOTe6.js +522 -0
  6. package/dist/client/assets/ChatView-DrY8FMIt.js +1 -0
  7. package/dist/client/assets/DevServerView-DlZpuAnj.css +1 -0
  8. package/dist/client/assets/DevServerView-fvjo36sF.js +6 -0
  9. package/dist/client/assets/{DirectoryPicker-Bcoh2_ft.js → DirectoryPicker-D5KQ-im_.js} +1 -1
  10. package/dist/client/assets/DocumentsView-BrhyOdeE.css +1 -0
  11. package/dist/client/assets/DocumentsView-D2wK7FYJ.js +1 -0
  12. package/dist/client/assets/{InsightsView-C4-vGe-H.js → InsightsView-DfY3sa1j.js} +1 -1
  13. package/dist/client/assets/{MemoryView-Ch7agzuP.js → MemoryView-CyAQgXwO.js} +1 -1
  14. package/dist/client/assets/{NodesView-D9rm5-_6.js → NodesView-g26-j7rg.js} +4 -4
  15. package/dist/client/assets/{PiExtensionsManager-hpV1-dOB.js → PiExtensionsManager-DfMr3Gls.js} +3 -3
  16. package/dist/client/assets/PluginManager-DiMOD-Kj.js +1 -0
  17. package/dist/client/assets/PluginManager-jyNkJZSz.css +1 -0
  18. package/dist/client/assets/RoadmapsView-DJC4F4CD.js +6 -0
  19. package/dist/client/assets/SettingsModal-BnekMOV2.css +1 -0
  20. package/dist/client/assets/{SettingsModal-DFitE2kE.js → SettingsModal-Cx3iMWDs.js} +1 -1
  21. package/dist/client/assets/SettingsModal-DjVE27r5.js +31 -0
  22. package/dist/client/assets/{SettingsModal-CDWvhvrd.css → SettingsModal-YjpwLH2V.css} +1 -1
  23. package/dist/client/assets/{SetupWizardModal-CjUbb4VZ.js → SetupWizardModal-Cow6woq6.js} +1 -1
  24. package/dist/client/assets/{SkillsView-CaQNaA67.js → SkillsView-DTB2cmXQ.js} +1 -1
  25. package/dist/client/assets/TodoView-C1g65hJo.css +1 -0
  26. package/dist/client/assets/TodoView-CyxdHUdz.js +6 -0
  27. package/dist/client/assets/{folder-open-DDanUhRq.js → folder-open-C3zB1vmh.js} +1 -1
  28. package/dist/client/assets/index-Belw0PQt.css +1 -0
  29. package/dist/client/assets/index-DJDWSrju.js +646 -0
  30. package/dist/client/assets/{list-checks-eKLuZO4Y.js → list-checks-CK3_6p5e.js} +1 -1
  31. package/dist/client/assets/star-BQhDgM9V.js +6 -0
  32. package/dist/client/assets/{upload-DDJr7Sat.js → upload-DDdZveEJ.js} +1 -1
  33. package/dist/client/assets/{users-zMb4VibZ.js → users-DWWgd19M.js} +1 -1
  34. package/dist/client/brands/hermes-logo.svg +1 -0
  35. package/dist/client/index.html +2 -2
  36. package/dist/client/version.json +1 -1
  37. package/dist/extension.js +2966 -742
  38. package/dist/pi-claude-cli/index.ts +12 -0
  39. package/dist/pi-claude-cli/package.json +1 -1
  40. package/dist/pi-claude-cli/src/__tests__/event-bridge.test.ts +40 -0
  41. package/dist/pi-claude-cli/src/__tests__/mcp-config.test.ts +17 -1
  42. package/dist/pi-claude-cli/src/__tests__/prompt-builder.test.ts +41 -0
  43. package/dist/pi-claude-cli/src/__tests__/tool-mapping.test.ts +1 -0
  44. package/dist/pi-claude-cli/src/prompt-builder.ts +8 -11
  45. package/dist/pi-claude-cli/src/provider.ts +17 -4
  46. package/package.json +7 -6
  47. package/dist/client/assets/AgentDetailView-C1b9PC5l.css +0 -1
  48. package/dist/client/assets/AgentDetailView-PYfYi6rl.js +0 -23
  49. package/dist/client/assets/AgentsView-CjqSko8c.js +0 -522
  50. package/dist/client/assets/AgentsView-DETxUmHS.css +0 -1
  51. package/dist/client/assets/ChatView-CY7Mdd3y.js +0 -1
  52. package/dist/client/assets/DevServerView-Jt4PTXWB.js +0 -11
  53. package/dist/client/assets/DevServerView-ZeBGQkLI.css +0 -1
  54. package/dist/client/assets/DocumentsView-B2YRSmIS.js +0 -1
  55. package/dist/client/assets/DocumentsView-DV2DrCZb.css +0 -1
  56. package/dist/client/assets/PluginManager-DHHM1Xeg.js +0 -1
  57. package/dist/client/assets/PluginManager-DRiIqol2.css +0 -1
  58. package/dist/client/assets/RoadmapsView-BpqARpKn.js +0 -6
  59. package/dist/client/assets/SettingsModal-B8Q5r_TT.js +0 -31
  60. package/dist/client/assets/SettingsModal-G0ESQXRD.css +0 -1
  61. package/dist/client/assets/TodoView-Bj0DcDdf.js +0 -1
  62. package/dist/client/assets/TodoView-DNi8blBB.css +0 -1
  63. package/dist/client/assets/index-BRTEq_-7.js +0 -631
  64. package/dist/client/assets/index-w9ci2GQ7.css +0 -1
@@ -1,14 +1,14 @@
1
- import{r as n,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Y,ak as xe,al as ge,am as pe,an as je,ao as Z,ap as Q,A as T,aq as _e,I as Ne,K as be,ar as ee,as as ve,at as Ce,X as B,au as ke,av as Se,R as J,w as G,G as we}from"./index-BRTEq_-7.js";import{U as se}from"./upload-DDJr7Sat.js";import"./vendor-xterm-DzcZoU0P.js";/**
1
+ import{r as n,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Y,am as xe,an as ge,ao as pe,ap as je,aq as Z,ar as Q,A as T,as as _e,M as Ne,N as be,at as ee,au as ve,av as Ce,X as B,aw as ke,ax as Se,R as J,y as G,G as we}from"./index-DJDWSrju.js";import{U as se}from"./upload-DDdZveEJ.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 Ae=[["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"}]],Me=Y("wifi-off",Ae);/**
6
+ */const Me=[["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"}]],Ae=Y("wifi-off",Me);/**
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 Ee=[["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"}]],Re=Y("wifi",Ee);function U(t){const{lastSyncAt:l,remoteReachable:s,diff:r}=t,f=r.global.length+r.project.length;return l===null?{syncState:"never-synced",lastSyncAt:l,diffCount:0}:s?f>0?{syncState:"diff",lastSyncAt:l,diffCount:f}:{syncState:"synced",lastSyncAt:l,diffCount:0}:{syncState:"error",lastSyncAt:l,diffCount:f}}function te(t){if(t===null)return"Never synced";const l=new Date(t);if(Number.isNaN(l.getTime()))return"Never synced";const r=Date.now()-l.getTime(),f=Math.floor(r/1e3),m=Math.floor(f/60),c=Math.floor(m/60),u=Math.floor(c/24);return m<1?"Synced just now":m<60?`Synced ${m}m ago`:c<24?`Synced ${c}h ago`:`Synced ${u}d ago`}function ae(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 Pe=3e4;function $e(){const[t,l]=n.useState({}),[s,r]=n.useState(!1),[f,m]=n.useState({}),[c,u]=n.useState(null),o=n.useRef(new Set),y=n.useRef(!1),g=n.useRef(null),j=n.useRef(null),C=n.useCallback(async(h,d)=>{try{const p=await xe(h);l(z=>({...z,[h]:p})),u(null)}catch(p){console.error(`Failed to fetch sync status for node ${h}:`,p),u(p instanceof Error?p.message:"Failed to fetch sync status")}},[]),_=n.useCallback(async()=>{const h=Array.from(o.current);if(h.length===0)return;g.current&&g.current.abort(),g.current=new AbortController;const d=!y.current;d&&r(!0),u(null);try{const p=await Promise.allSettled(h.map(L=>C(L,d)));y.current=!0,p.filter(L=>L.status==="rejected").length>0&&u("Some sync status requests failed")}catch(p){if(p instanceof Error&&p.name==="AbortError")return;u(p instanceof Error?p.message:"Failed to fetch sync status"),y.current=!0}finally{r(!1)}},[C]),S=n.useCallback(()=>{j.current&&clearInterval(j.current),j.current=setInterval(()=>{_()},Pe)},[_]),A=n.useCallback(()=>{j.current&&(clearInterval(j.current),j.current=null)},[]);n.useEffect(()=>(_(),S(),()=>{A(),g.current&&g.current.abort()}),[_,S,A]);const a=n.useCallback(h=>{o.current.has(h)||(o.current.add(h),C(h,!y.current))},[C]),i=n.useCallback(h=>{o.current.delete(h),l(d=>{const p={...d};return delete p[h],p}),o.current.size===0&&A()},[A]),x=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{const d=await ge(h);return C(h,!1),!d.success&&d.error&&u(d.error),d}catch(d){const p=d instanceof Error?d.message:"Push settings failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[C]),b=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{const d=await pe(h);return C(h,!1),!d.success&&d.error&&u(d.error),d}catch(d){const p=d instanceof Error?d.message:"Pull settings failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[C]),w=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{return await je(h)}catch(d){const p=d instanceof Error?d.message:"Auth sync failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[]),$=n.useCallback(h=>t[h]?.authMatch,[t]),v=n.useCallback(h=>t[h]?.authDiff,[t]);return{syncStatusMap:t,loading:s,actionLoading:f,error:c,refresh:_,trackNode:a,untrackNode:i,pushSettings:x,pullSettings:b,syncAuth:w,getAuthSyncState:$,getAuthProviders:v}}function Le(t,l){return l.type==="remote"?t.nodeId===l.id:t.nodeId===l.id||t.nodeId===void 0||t.nodeId===null}function ne(t,l){return t.filter(s=>Le(s,l))}function H(t,l){return ne(t,l).length}const ze={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"}},De={match:"var(--color-success)",differs:"var(--color-warning)","not-synced":"var(--text-muted)"};function Oe(t,l){if(t==="match")return"Auth credentials match";if(t==="not-synced")return"Auth not synced";if(l&&Object.keys(l).length>0){const s=Object.entries(l).filter(([,r])=>r==="differs").map(([r])=>r);if(s.length>0)return`Auth credentials differ: ${s.join(", ")}`}return"Auth credentials differ"}function Fe(t,l=42){return t.length<=l?t:`${t.slice(0,l-3)}...`}function Ie(t,l){const s=t.node,r=l.node;if(s.id!==r.id||s.name!==r.name||s.type!==r.type||s.url!==r.url||s.status!==r.status||s.maxConcurrent!==r.maxConcurrent||s.updatedAt!==r.updatedAt||t.isLoading!==l.isLoading)return!1;const f=t.syncStatus,m=l.syncStatus;if(!(!f&&!m)){if(!f||!m)return!1;if(f.syncState!==m.syncState||f.lastSyncAt!==m.lastSyncAt||f.diffCount!==m.diffCount)return!1}if(t.authSyncState!==l.authSyncState)return!1;const c=t.authSyncProviders,u=l.authSyncProviders;if(c!==u){if(!c||!u)return!1;{const g=Object.keys(c),j=Object.keys(u);if(g.length!==j.length||g.some(C=>c[C]!==u[C]))return!1}}const o=H(t.projects,s),y=H(l.projects,r);return o===y}function Ke({node:t,projects:l,onHealthCheck:s,onEdit:r,onRemove:f,isLoading:m=!1,syncStatus:c,authSyncState:u,authSyncProviders:o}){const[y,g]=n.useState(!1),j=ze[t.status],C=n.useMemo(()=>H(l,t),[l,t]),_=n.useCallback(()=>{r(t)},[r,t]),S=n.useCallback(x=>{x.stopPropagation(),s(t.id)},[s,t.id]),A=n.useCallback(x=>{x.stopPropagation(),r(t)},[r,t]),a=n.useCallback(x=>{if(x.stopPropagation(),!y){g(!0);return}f(t.id),g(!1)},[y,f,t.id]),i=n.useCallback(x=>{(x.key==="Enter"||x.key===" ")&&(x.preventDefault(),r(t))},[r,t]);return e.jsxs("article",{className:`node-card ${m?"node-card--loading":""}`,"data-node-id":t.id,role:"button",tabIndex:0,onClick:_,onKeyDown:i,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(Z,{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"}),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]}),t.type==="remote"&&u&&e.jsx("span",{className:`node-card__auth-indicator node-card__auth-indicator--${u}`,title:Oe(u,o),"aria-label":`Auth sync: ${u==="match"?"credentials match":u==="differs"?"credentials differ":"not synced"}`,style:{color:De[u]},children:e.jsx(Q,{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:Fe(t.url)}),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:C})]}),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"&&c&&e.jsxs("div",{className:"node-card__sync","data-sync-state":c.syncState,"data-testid":"node-card-sync",children:[e.jsx("span",{className:"node-card__sync-dot",style:{backgroundColor:ae(c.syncState)},"aria-hidden":!0}),e.jsx("span",{className:"node-card__sync-time",children:te(c.lastSyncAt)})]})]}),e.jsxs("footer",{className:"node-card__actions",children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:S,disabled:m,"aria-label":"Run node health check",title:"Health Check",children:[e.jsx(T,{size:14}),e.jsx("span",{children:"Health"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:A,disabled:m,"aria-label":"Edit node",title:"Edit",children:[e.jsx(_e,{size:14}),e.jsx("span",{children:"Edit"})]}),e.jsxs("button",{className:`btn btn-sm node-card__action node-card__action--remove ${y?"btn-danger is-armed":""}`,type:"button",onClick:a,disabled:m,"aria-label":y?"Confirm remove node":"Remove node",title:y?"Confirm remove":"Remove",children:[e.jsx(Ne,{size:14}),e.jsx("span",{children:y?"Confirm":"Remove"})]})]})]})}const Ue=n.memo(Ke,Ie),O={online:"var(--success, var(--color-success))",offline:"var(--text-dim)",connecting:"var(--triage)",error:"var(--color-error)"},D=28,W=12,Ve=300,Be=120;function He({nodes:t,className:l}){const s=n.useMemo(()=>t.find(o=>o.type==="local")??t[0],[t]),r=n.useMemo(()=>t.filter(o=>o.type==="remote"),[t]),f=n.useMemo(()=>{const o=Ve,y=Math.max(0,r.length-4)*20;return o+y},[r.length]),m=f/2,c=f/2,u=n.useMemo(()=>{if(r.length===0)return[];const o=Math.min(Be,f/2-D-10),y=2*Math.PI/r.length,g=-Math.PI/2;return r.map((j,C)=>{const _=g+C*y;return{node:j,x:m+o*Math.cos(_),y:c+o*Math.sin(_)}})},[r,f,m,c]);return t.length===0?e.jsx("div",{className:`mesh-topology mesh-topology--empty ${l??""}`,children:e.jsx("div",{className:"mesh-topology__empty-state",children:e.jsx("p",{children:"No nodes to display"})})}):e.jsxs("div",{className:`mesh-topology ${l??""}`,children:[e.jsxs("svg",{className:"mesh-topology__svg",viewBox:`0 0 ${f} ${f}`,preserveAspectRatio:"xMidYMid meet","aria-label":"Node mesh topology visualization",children:[u.map(o=>e.jsx("line",{className:"mesh-topology__link",x1:m,y1:c,x2:o.x,y2:o.y},`link-${o.node.id}`)),s&&e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${m}, ${c})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:D,fill:O[s.status],"aria-label":`${s.name} (${s.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:D+W,textAnchor:"middle",children:s.name.length>12?`${s.name.slice(0,10)}…`:s.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-D-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:s.type==="local"?"L":"R"})]})]}),u.map(o=>e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${o.x}, ${o.y})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:D,fill:O[o.node.status],"aria-label":`${o.node.name} (${o.node.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:D+W,textAnchor:"middle",children:o.node.name.length>12?`${o.node.name.slice(0,10)}…`:o.node.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-D-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:o.node.type==="local"?"L":"R"})]})]},o.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:O.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:O.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:O.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:O.error}}),e.jsx("span",{children:"Error"})]})]}),e.jsx("p",{className:"mesh-topology__notice",children:"Peer-to-peer discovery data unavailable."})]})}const qe=n.memo(He),q=1,X=10;function Xe(t){const l={};return t.name.trim()||(l.name="Name is required"),t.type==="remote"&&!t.url?.trim()&&(l.url="URL is required for remote nodes"),(!Number.isFinite(t.maxConcurrent)||t.maxConcurrent<q||t.maxConcurrent>X)&&(l.maxConcurrent=`Concurrency must be between ${q} and ${X}`),l}function Je({isOpen:t,onClose:l,onSubmit:s,addToast:r}){const[f,m]=n.useState(""),[c,u]=n.useState("local"),[o,y]=n.useState(""),[g,j]=n.useState(""),[C,_]=n.useState(2),[S,A]=n.useState({}),[a,i]=n.useState(!1),x=n.useCallback(()=>{m(""),u("local"),y(""),j(""),_(2),A({}),i(!1)},[]),b=n.useCallback(()=>{a||(x(),l())},[a,l,x]);n.useEffect(()=>{if(!t){x();return}const v=h=>{h.key==="Escape"&&(h.preventDefault(),b())};return document.addEventListener("keydown",v),()=>{document.removeEventListener("keydown",v)}},[b,t,x]);const w=n.useMemo(()=>({name:f.trim(),type:c,url:c==="remote"&&o.trim()||void 0,apiKey:c==="remote"&&g||void 0,maxConcurrent:C}),[g,C,f,c,o]),$=n.useCallback(async()=>{if(a)return;const v=Xe(w);if(A(v),!(Object.keys(v).length>0)){i(!0);try{await s(w),r(`Node "${w.name}" registered`,"success"),b()}catch(h){const d=h instanceof Error?h.message:"Failed to register node";r(d,"error")}finally{i(!1)}}},[r,b,w,a,s]);return t?e.jsx("div",{className:"modal-overlay open",onClick:b,children:e.jsxs("div",{className:"modal modal-md add-node-modal",onClick:v=>v.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:b,disabled:a,"aria-label":"Close add node modal",children:"×"})]}),e.jsxs("div",{className:"modal-body add-node-modal__body",children:[e.jsx("p",{className:"add-node-modal__description",children:"Register a node to distribute task execution across machines."}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Name"}),e.jsx("input",{className:"input",type:"text",value:f,onChange:v=>m(v.target.value),placeholder:"Build Machine",disabled:a,"aria-invalid":!!S.name,autoFocus:!0}),S.name&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.name})]}),e.jsxs("div",{className:"add-node-modal__type-toggle",children:[e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${c==="local"?"active":""}`,"data-type":"local",onClick:()=>u("local"),disabled:a,"aria-pressed":c==="local",children:"Local"}),e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${c==="remote"?"active":""}`,"data-type":"remote",onClick:()=>u("remote"),disabled:a,"aria-pressed":c==="remote",children:"Remote"})]}),e.jsxs("div",{className:"add-node-modal__remote-fields","data-testid":"remote-fields-container","data-visible":c==="remote",children:[e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"URL"}),e.jsx("input",{className:"input",type:"text",value:o,onChange:v=>y(v.target.value),placeholder:"https://node.example.com",disabled:a,"aria-invalid":!!S.url}),S.url&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.url})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:g,onChange:v=>j(v.target.value),placeholder:"Optional",disabled:a})]})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),e.jsx("input",{className:"input",type:"number",min:q,max:X,value:C,onChange:v=>_(Number(v.target.value)),disabled:a,"aria-invalid":!!S.maxConcurrent}),e.jsx("span",{className:"add-node-modal__hint",children:"Max simultaneous task agents (1–10)"}),S.maxConcurrent&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.maxConcurrent})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:b,disabled:a,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm","data-testid":"add-node-submit",onClick:$,disabled:a,children:a?"Adding...":"Add Node"})]})]})}):null}function Ge({nodeId:t,entries:l,loading:s=!1,singleNode:r=!1}){const[f,m]=n.useState(!1),[c,u]=n.useState("all"),[o,y]=n.useState("all"),g=n.useCallback(()=>{m(a=>!a)},[]),j=n.useMemo(()=>{const a=new Set;for(const i of l)a.add(i.nodeName);return Array.from(a).sort()},[l]),C=n.useMemo(()=>{let a=[...l];return c!=="all"&&(a=a.filter(i=>i.direction===c)),!r&&o!=="all"&&(a=a.filter(i=>i.nodeName===o)),a.sort((i,x)=>{const b=new Date(i.timestamp).getTime();return new Date(x.timestamp).getTime()-b}),a},[l,c,o,r]),_=n.useCallback(a=>new Date(a).toLocaleString(),[]),S=n.useCallback(a=>{switch(a){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""}},[]),A=n.useCallback(a=>{switch(a){case"success":return"Success";case"conflict":return"Conflict";case"error":return"Error";default:return a}},[]);return e.jsxs("div",{className:"settings-sync-log",children:[e.jsxs("button",{className:"settings-sync-log__header",type:"button",onClick:g,"aria-expanded":f,"data-testid":"settings-sync-log-header",children:[e.jsx(be,{size:16,className:`settings-sync-log__chevron ${f?"settings-sync-log__chevron--expanded":""}`}),e.jsxs("span",{children:[l.length," ",l.length===1?"entry":"entries"]})]}),f&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"settings-sync-log__filters",children:[e.jsxs("label",{children:["Direction:",e.jsxs("select",{value:c,onChange:a=>u(a.target.value),children:[e.jsx("option",{value:"all",children:"All"}),e.jsx("option",{value:"push",children:"Push"}),e.jsx("option",{value:"pull",children:"Pull"})]})]}),!r&&e.jsxs("label",{children:["Node:",e.jsxs("select",{value:o,onChange:a=>y(a.target.value),children:[e.jsx("option",{value:"all",children:"All Nodes"}),j.map(a=>e.jsx("option",{value:a,children:a},a))]})]})]}),s&&l.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"Loading..."}):C.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"No sync history available"}):e.jsx("div",{className:"settings-sync-log__list",children:C.map(a=>e.jsxs("div",{className:"settings-sync-log__entry",children:[e.jsx("span",{className:"settings-sync-log__entry-timestamp",children:_(a.timestamp)}),e.jsx("span",{className:"settings-sync-log__entry-direction",children:a.direction==="push"?e.jsx(se,{size:14,"data-testid":"upload-icon"}):e.jsx(ee,{size:14,"data-testid":"download-icon"})}),e.jsx("span",{className:`settings-sync-log__entry-result ${S(a.result)}`,children:A(a.result)}),!r&&e.jsx("span",{className:"settings-sync-log__entry-node",children:a.nodeName}),a.details&&e.jsx("span",{className:"settings-sync-log__entry-details",title:a.details,children:a.details})]},a.id))})]})]})}function We(t,l){const s=typeof t=="string"?t:JSON.stringify(t,null,2),r=typeof l=="string"?l:JSON.stringify(l,null,2);if(s===r)return s;const f=s.split(`
11
+ */const Ee=[["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"}]],Re=Y("wifi",Ee);function U(t){const{lastSyncAt:l,remoteReachable:s,diff:r}=t,f=r.global.length+r.project.length;return l===null?{syncState:"never-synced",lastSyncAt:l,diffCount:0}:s?f>0?{syncState:"diff",lastSyncAt:l,diffCount:f}:{syncState:"synced",lastSyncAt:l,diffCount:0}:{syncState:"error",lastSyncAt:l,diffCount:f}}function te(t){if(t===null)return"Never synced";const l=new Date(t);if(Number.isNaN(l.getTime()))return"Never synced";const r=Date.now()-l.getTime(),f=Math.floor(r/1e3),m=Math.floor(f/60),c=Math.floor(m/60),u=Math.floor(c/24);return m<1?"Synced just now":m<60?`Synced ${m}m ago`:c<24?`Synced ${c}h ago`:`Synced ${u}d ago`}function ae(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 Pe=3e4;function $e(){const[t,l]=n.useState({}),[s,r]=n.useState(!1),[f,m]=n.useState({}),[c,u]=n.useState(null),o=n.useRef(new Set),y=n.useRef(!1),g=n.useRef(null),j=n.useRef(null),C=n.useCallback(async(h,d)=>{try{const p=await xe(h);l(z=>({...z,[h]:p})),u(null)}catch(p){console.error(`Failed to fetch sync status for node ${h}:`,p),u(p instanceof Error?p.message:"Failed to fetch sync status")}},[]),_=n.useCallback(async()=>{const h=Array.from(o.current);if(h.length===0)return;g.current&&g.current.abort(),g.current=new AbortController;const d=!y.current;d&&r(!0),u(null);try{const p=await Promise.allSettled(h.map(L=>C(L,d)));y.current=!0,p.filter(L=>L.status==="rejected").length>0&&u("Some sync status requests failed")}catch(p){if(p instanceof Error&&p.name==="AbortError")return;u(p instanceof Error?p.message:"Failed to fetch sync status"),y.current=!0}finally{r(!1)}},[C]),S=n.useCallback(()=>{j.current&&clearInterval(j.current),j.current=setInterval(()=>{_()},Pe)},[_]),M=n.useCallback(()=>{j.current&&(clearInterval(j.current),j.current=null)},[]);n.useEffect(()=>(_(),S(),()=>{M(),g.current&&g.current.abort()}),[_,S,M]);const a=n.useCallback(h=>{o.current.has(h)||(o.current.add(h),C(h,!y.current))},[C]),i=n.useCallback(h=>{o.current.delete(h),l(d=>{const p={...d};return delete p[h],p}),o.current.size===0&&M()},[M]),x=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{const d=await ge(h);return C(h,!1),!d.success&&d.error&&u(d.error),d}catch(d){const p=d instanceof Error?d.message:"Push settings failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[C]),b=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{const d=await pe(h);return C(h,!1),!d.success&&d.error&&u(d.error),d}catch(d){const p=d instanceof Error?d.message:"Pull settings failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[C]),w=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{return await je(h)}catch(d){const p=d instanceof Error?d.message:"Auth sync failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[]),$=n.useCallback(h=>t[h]?.authMatch,[t]),v=n.useCallback(h=>t[h]?.authDiff,[t]);return{syncStatusMap:t,loading:s,actionLoading:f,error:c,refresh:_,trackNode:a,untrackNode:i,pushSettings:x,pullSettings:b,syncAuth:w,getAuthSyncState:$,getAuthProviders:v}}function Le(t,l){return l.type==="remote"?t.nodeId===l.id:t.nodeId===l.id||t.nodeId===void 0||t.nodeId===null}function ne(t,l){return t.filter(s=>Le(s,l))}function H(t,l){return ne(t,l).length}const ze={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"}},De={match:"var(--color-success)",differs:"var(--color-warning)","not-synced":"var(--text-muted)"};function Oe(t,l){if(t==="match")return"Auth credentials match";if(t==="not-synced")return"Auth not synced";if(l&&Object.keys(l).length>0){const s=Object.entries(l).filter(([,r])=>r==="differs").map(([r])=>r);if(s.length>0)return`Auth credentials differ: ${s.join(", ")}`}return"Auth credentials differ"}function Fe(t,l=42){return t.length<=l?t:`${t.slice(0,l-3)}...`}function Ie(t,l){const s=t.node,r=l.node;if(s.id!==r.id||s.name!==r.name||s.type!==r.type||s.url!==r.url||s.status!==r.status||s.maxConcurrent!==r.maxConcurrent||s.updatedAt!==r.updatedAt||t.isLoading!==l.isLoading)return!1;const f=t.syncStatus,m=l.syncStatus;if(!(!f&&!m)){if(!f||!m)return!1;if(f.syncState!==m.syncState||f.lastSyncAt!==m.lastSyncAt||f.diffCount!==m.diffCount)return!1}if(t.authSyncState!==l.authSyncState)return!1;const c=t.authSyncProviders,u=l.authSyncProviders;if(c!==u){if(!c||!u)return!1;{const g=Object.keys(c),j=Object.keys(u);if(g.length!==j.length||g.some(C=>c[C]!==u[C]))return!1}}const o=H(t.projects,s),y=H(l.projects,r);return o===y}function Ke({node:t,projects:l,onHealthCheck:s,onEdit:r,onRemove:f,isLoading:m=!1,syncStatus:c,authSyncState:u,authSyncProviders:o}){const[y,g]=n.useState(!1),j=ze[t.status],C=n.useMemo(()=>H(l,t),[l,t]),_=n.useCallback(()=>{r(t)},[r,t]),S=n.useCallback(x=>{x.stopPropagation(),s(t.id)},[s,t.id]),M=n.useCallback(x=>{x.stopPropagation(),r(t)},[r,t]),a=n.useCallback(x=>{if(x.stopPropagation(),!y){g(!0);return}f(t.id),g(!1)},[y,f,t.id]),i=n.useCallback(x=>{(x.key==="Enter"||x.key===" ")&&(x.preventDefault(),r(t))},[r,t]);return e.jsxs("article",{className:`node-card ${m?"node-card--loading":""}`,"data-node-id":t.id,role:"button",tabIndex:0,onClick:_,onKeyDown:i,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(Z,{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"}),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]}),t.type==="remote"&&u&&e.jsx("span",{className:`node-card__auth-indicator node-card__auth-indicator--${u}`,title:Oe(u,o),"aria-label":`Auth sync: ${u==="match"?"credentials match":u==="differs"?"credentials differ":"not synced"}`,style:{color:De[u]},children:e.jsx(Q,{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:Fe(t.url)}),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:C})]}),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"&&c&&e.jsxs("div",{className:"node-card__sync","data-sync-state":c.syncState,"data-testid":"node-card-sync",children:[e.jsx("span",{className:"node-card__sync-dot",style:{backgroundColor:ae(c.syncState)},"aria-hidden":!0}),e.jsx("span",{className:"node-card__sync-time",children:te(c.lastSyncAt)})]})]}),e.jsxs("footer",{className:"node-card__actions",children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:S,disabled:m,"aria-label":"Run node health check",title:"Health Check",children:[e.jsx(T,{size:14}),e.jsx("span",{children:"Health"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:M,disabled:m,"aria-label":"Edit node",title:"Edit",children:[e.jsx(_e,{size:14}),e.jsx("span",{children:"Edit"})]}),e.jsxs("button",{className:`btn btn-sm node-card__action node-card__action--remove ${y?"btn-danger is-armed":""}`,type:"button",onClick:a,disabled:m,"aria-label":y?"Confirm remove node":"Remove node",title:y?"Confirm remove":"Remove",children:[e.jsx(Ne,{size:14}),e.jsx("span",{children:y?"Confirm":"Remove"})]})]})]})}const Ue=n.memo(Ke,Ie),O={online:"var(--success, var(--color-success))",offline:"var(--text-dim)",connecting:"var(--triage)",error:"var(--color-error)"},D=28,W=12,Ve=300,Be=120;function He({nodes:t,className:l}){const s=n.useMemo(()=>t.find(o=>o.type==="local")??t[0],[t]),r=n.useMemo(()=>t.filter(o=>o.type==="remote"),[t]),f=n.useMemo(()=>{const o=Ve,y=Math.max(0,r.length-4)*20;return o+y},[r.length]),m=f/2,c=f/2,u=n.useMemo(()=>{if(r.length===0)return[];const o=Math.min(Be,f/2-D-10),y=2*Math.PI/r.length,g=-Math.PI/2;return r.map((j,C)=>{const _=g+C*y;return{node:j,x:m+o*Math.cos(_),y:c+o*Math.sin(_)}})},[r,f,m,c]);return t.length===0?e.jsx("div",{className:`mesh-topology mesh-topology--empty ${l??""}`,children:e.jsx("div",{className:"mesh-topology__empty-state",children:e.jsx("p",{children:"No nodes to display"})})}):e.jsxs("div",{className:`mesh-topology ${l??""}`,children:[e.jsxs("svg",{className:"mesh-topology__svg",viewBox:`0 0 ${f} ${f}`,preserveAspectRatio:"xMidYMid meet","aria-label":"Node mesh topology visualization",children:[u.map(o=>e.jsx("line",{className:"mesh-topology__link",x1:m,y1:c,x2:o.x,y2:o.y},`link-${o.node.id}`)),s&&e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${m}, ${c})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:D,fill:O[s.status],"aria-label":`${s.name} (${s.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:D+W,textAnchor:"middle",children:s.name.length>12?`${s.name.slice(0,10)}…`:s.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-D-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:s.type==="local"?"L":"R"})]})]}),u.map(o=>e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${o.x}, ${o.y})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:D,fill:O[o.node.status],"aria-label":`${o.node.name} (${o.node.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:D+W,textAnchor:"middle",children:o.node.name.length>12?`${o.node.name.slice(0,10)}…`:o.node.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-D-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:o.node.type==="local"?"L":"R"})]})]},o.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:O.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:O.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:O.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:O.error}}),e.jsx("span",{children:"Error"})]})]}),e.jsx("p",{className:"mesh-topology__notice",children:"Peer-to-peer discovery data unavailable."})]})}const qe=n.memo(He),q=1,X=10;function Xe(t){const l={};return t.name.trim()||(l.name="Name is required"),t.type==="remote"&&!t.url?.trim()&&(l.url="URL is required for remote nodes"),(!Number.isFinite(t.maxConcurrent)||t.maxConcurrent<q||t.maxConcurrent>X)&&(l.maxConcurrent=`Concurrency must be between ${q} and ${X}`),l}function Je({isOpen:t,onClose:l,onSubmit:s,addToast:r}){const[f,m]=n.useState(""),[c,u]=n.useState("local"),[o,y]=n.useState(""),[g,j]=n.useState(""),[C,_]=n.useState(2),[S,M]=n.useState({}),[a,i]=n.useState(!1),x=n.useCallback(()=>{m(""),u("local"),y(""),j(""),_(2),M({}),i(!1)},[]),b=n.useCallback(()=>{a||(x(),l())},[a,l,x]);n.useEffect(()=>{if(!t){x();return}const v=h=>{h.key==="Escape"&&(h.preventDefault(),b())};return document.addEventListener("keydown",v),()=>{document.removeEventListener("keydown",v)}},[b,t,x]);const w=n.useMemo(()=>({name:f.trim(),type:c,url:c==="remote"&&o.trim()||void 0,apiKey:c==="remote"&&g||void 0,maxConcurrent:C}),[g,C,f,c,o]),$=n.useCallback(async()=>{if(a)return;const v=Xe(w);if(M(v),!(Object.keys(v).length>0)){i(!0);try{await s(w),r(`Node "${w.name}" registered`,"success"),b()}catch(h){const d=h instanceof Error?h.message:"Failed to register node";r(d,"error")}finally{i(!1)}}},[r,b,w,a,s]);return t?e.jsx("div",{className:"modal-overlay open",onClick:b,children:e.jsxs("div",{className:"modal modal-md add-node-modal",onClick:v=>v.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:b,disabled:a,"aria-label":"Close add node modal",children:"×"})]}),e.jsxs("div",{className:"modal-body add-node-modal__body",children:[e.jsx("p",{className:"add-node-modal__description",children:"Register a node to distribute task execution across machines."}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Name"}),e.jsx("input",{className:"input",type:"text",value:f,onChange:v=>m(v.target.value),placeholder:"Build Machine",disabled:a,"aria-invalid":!!S.name,autoFocus:!0}),S.name&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.name})]}),e.jsxs("div",{className:"add-node-modal__type-toggle",children:[e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${c==="local"?"active":""}`,"data-type":"local",onClick:()=>u("local"),disabled:a,"aria-pressed":c==="local",children:"Local"}),e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${c==="remote"?"active":""}`,"data-type":"remote",onClick:()=>u("remote"),disabled:a,"aria-pressed":c==="remote",children:"Remote"})]}),e.jsxs("div",{className:"add-node-modal__remote-fields","data-testid":"remote-fields-container","data-visible":c==="remote",children:[e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"URL"}),e.jsx("input",{className:"input",type:"text",value:o,onChange:v=>y(v.target.value),placeholder:"https://node.example.com",disabled:a,"aria-invalid":!!S.url}),S.url&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.url})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:g,onChange:v=>j(v.target.value),placeholder:"Optional",disabled:a})]})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),e.jsx("input",{className:"input",type:"number",min:q,max:X,value:C,onChange:v=>_(Number(v.target.value)),disabled:a,"aria-invalid":!!S.maxConcurrent}),e.jsx("span",{className:"add-node-modal__hint",children:"Max simultaneous task agents (1–10)"}),S.maxConcurrent&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.maxConcurrent})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:b,disabled:a,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm","data-testid":"add-node-submit",onClick:$,disabled:a,children:a?"Adding...":"Add Node"})]})]})}):null}function Ge({nodeId:t,entries:l,loading:s=!1,singleNode:r=!1}){const[f,m]=n.useState(!1),[c,u]=n.useState("all"),[o,y]=n.useState("all"),g=n.useCallback(()=>{m(a=>!a)},[]),j=n.useMemo(()=>{const a=new Set;for(const i of l)a.add(i.nodeName);return Array.from(a).sort()},[l]),C=n.useMemo(()=>{let a=[...l];return c!=="all"&&(a=a.filter(i=>i.direction===c)),!r&&o!=="all"&&(a=a.filter(i=>i.nodeName===o)),a.sort((i,x)=>{const b=new Date(i.timestamp).getTime();return new Date(x.timestamp).getTime()-b}),a},[l,c,o,r]),_=n.useCallback(a=>new Date(a).toLocaleString(),[]),S=n.useCallback(a=>{switch(a){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""}},[]),M=n.useCallback(a=>{switch(a){case"success":return"Success";case"conflict":return"Conflict";case"error":return"Error";default:return a}},[]);return e.jsxs("div",{className:"settings-sync-log",children:[e.jsxs("button",{className:"settings-sync-log__header",type:"button",onClick:g,"aria-expanded":f,"data-testid":"settings-sync-log-header",children:[e.jsx(be,{size:16,className:`settings-sync-log__chevron ${f?"settings-sync-log__chevron--expanded":""}`}),e.jsxs("span",{children:[l.length," ",l.length===1?"entry":"entries"]})]}),f&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"settings-sync-log__filters",children:[e.jsxs("label",{children:["Direction:",e.jsxs("select",{value:c,onChange:a=>u(a.target.value),children:[e.jsx("option",{value:"all",children:"All"}),e.jsx("option",{value:"push",children:"Push"}),e.jsx("option",{value:"pull",children:"Pull"})]})]}),!r&&e.jsxs("label",{children:["Node:",e.jsxs("select",{value:o,onChange:a=>y(a.target.value),children:[e.jsx("option",{value:"all",children:"All Nodes"}),j.map(a=>e.jsx("option",{value:a,children:a},a))]})]})]}),s&&l.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"Loading..."}):C.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"No sync history available"}):e.jsx("div",{className:"settings-sync-log__list",children:C.map(a=>e.jsxs("div",{className:"settings-sync-log__entry",children:[e.jsx("span",{className:"settings-sync-log__entry-timestamp",children:_(a.timestamp)}),e.jsx("span",{className:"settings-sync-log__entry-direction",children:a.direction==="push"?e.jsx(se,{size:14,"data-testid":"upload-icon"}):e.jsx(ee,{size:14,"data-testid":"download-icon"})}),e.jsx("span",{className:`settings-sync-log__entry-result ${S(a.result)}`,children:M(a.result)}),!r&&e.jsx("span",{className:"settings-sync-log__entry-node",children:a.nodeName}),a.details&&e.jsx("span",{className:"settings-sync-log__entry-details",title:a.details,children:a.details})]},a.id))})]})]})}function We(t,l){const s=typeof t=="string"?t:JSON.stringify(t,null,2),r=typeof l=="string"?l:JSON.stringify(l,null,2);if(s===r)return s;const f=s.split(`
12
12
  `),m=r.split(`
13
13
  `),c=[],u=Math.max(f.length,m.length);for(let o=0;o<u;o++){const y=f[o],g=m[o];y!==void 0&&y!==g&&c.push(`- ${y}`),g!==void 0&&g!==y&&c.push(`+ ${g}`),y!==void 0&&y===g&&c.push(` ${y}`)}return c.join(`
14
- `)}function Ye({isOpen:t,onClose:l,onResolve:s,conflicts:r,localNodeName:f,remoteNodeName:m,addToast:c}){const[u,o]=n.useState({}),[y,g]=n.useState(!1);n.useEffect(()=>{const a={};for(const i of r)u[i.key]||(a[i.key]={resolution:"local"});Object.keys(a).length>0&&o(i=>({...i,...a}))},[r,u]),n.useEffect(()=>{if(!t)return;const a=i=>{i.key==="Escape"&&(i.preventDefault(),l())};return document.addEventListener("keydown",a),()=>document.removeEventListener("keydown",a)},[t,l]);const j=n.useCallback((a,i)=>{o(x=>{const b=x[a]??{};return i==="manual"?{...x,[a]:{resolution:"manual",manualValue:b.manualValue??JSON.stringify(r.find(w=>w.key===a)?.localValue??null,null,2)}}:{...x,[a]:{resolution:i}}})},[r]),C=n.useCallback((a,i)=>{o(x=>({...x,[a]:{...x[a],resolution:"manual",manualValue:i}}))},[]),_=n.useCallback(a=>{const i={};for(const x of r)i[x.key]={resolution:a};o(i)},[r]),S=n.useCallback(async()=>{g(!0);try{const a=r.map(i=>{const x=u[i.key]??{resolution:"local"};let b;switch(x.resolution){case"remote":b=i.remoteValue;break;case"manual":try{b=JSON.parse(x.manualValue??"null")}catch{b=x.manualValue??null}break;case"local":default:b=i.localValue;break}return{key:i.key,value:b}});await s(a),c("Settings conflicts resolved successfully","success"),l()}catch(a){const i=a instanceof Error?a.message:"Failed to resolve conflicts";c(i,"error")}finally{g(!1)}},[c,r,l,s,u]),A=n.useMemo(()=>{const a={};for(const i of r)a[i.key]=We(i.localValue,i.remoteValue);return a},[r]);return!t||r.length===0?null:e.jsx("div",{className:"modal-overlay open",onClick:l,children:e.jsxs("div",{className:"modal modal-lg settings-sync-conflict-modal",onClick:a=>a.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:l,"aria-label":"Close conflict modal",children:"×"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("div",{className:"settings-sync-conflict-modal__conflict-list",children:r.map(a=>{const i=u[a.key]??{resolution:"local"},x=A[a.key];return e.jsxs("div",{className:"settings-sync-conflict-modal__conflict-item",children:[e.jsx("div",{className:"settings-sync-conflict-modal__key",children:a.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:f}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:x})})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:m}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:x})})]})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__resolution",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="local",onChange:()=>j(a.key,"local")}),"Keep Local"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="remote",onChange:()=>j(a.key,"remote")}),"Keep Remote"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="manual",onChange:()=>j(a.key,"manual")}),"Merge Manually"]})]}),i.resolution==="manual"&&e.jsx("textarea",{className:"settings-sync-conflict-modal__manual-input",value:i.manualValue??"",onChange:b=>C(a.key,b.target.value),placeholder:"Enter JSON value..."})]},a.key)})}),e.jsxs("div",{className:"settings-sync-conflict-modal__bulk-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:()=>_("local"),type:"button",children:"Resolve All: Keep Local"}),e.jsx("button",{className:"btn btn-sm",onClick:()=>_("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:l,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:S,disabled:y,children:y?"Resolving...":"Confirm"})]})]})})}function V(t){if(!t)return"—";const l=new Date(t);return Number.isNaN(l.getTime())?"—":l.toLocaleString()}function Ze({isOpen:t,onClose:l,node:s,projects:r,onUpdate:f,onHealthCheck:m,addToast:c,syncStatus:u,onPushSettings:o,onPullSettings:y,onSyncAuth:g,syncHistory:j=[],onResolveConflicts:C}){const _=n.useRef(!0),[S,A]=n.useState(!1),[a,i]=n.useState(""),[x,b]=n.useState(""),[w,$]=n.useState(""),[v,h]=n.useState(2),[d,p]=n.useState(!1),[z,L]=n.useState(!1),[k,M]=n.useState(!1),[P,F]=n.useState(!1),[I,E]=n.useState(null),[le,re]=n.useState(!1),[ce]=n.useState([]);n.useEffect(()=>(_.current=!0,()=>{_.current=!1}),[]),n.useEffect(()=>{if(!s||!t){A(!1);return}i(s.name),b(s.url??""),$(s.apiKey??""),h(s.maxConcurrent),A(!1)},[t,s]),n.useEffect(()=>{if(!t)return;const N=R=>{R.key==="Escape"&&(R.preventDefault(),l())};return document.addEventListener("keydown",N),()=>document.removeEventListener("keydown",N)},[t,l]);const K=n.useMemo(()=>s?ne(r,s):[],[s,r]),oe=n.useCallback(async()=>{if(s)try{if(await m(s.id),!_.current)return;c(`Health check completed for ${s.name}`,"success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Health check failed";c(R,"error")}},[c,s,m]),ie=n.useCallback(async()=>{if(!(!s||!o)){E(null),L(!0);try{if(await o(s.id),!_.current)return;c("Settings pushed successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Push settings failed";E(R),c(R,"error")}finally{_.current&&L(!1)}}},[c,s,o]),de=n.useCallback(async()=>{if(!(!s||!y)){E(null),M(!0);try{if(await y(s.id),!_.current)return;c("Settings pulled successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Pull settings failed";E(R),c(R,"error")}finally{_.current&&M(!1)}}},[c,s,y]),ue=n.useCallback(async()=>{if(!(!s||!g)){E(null),F(!0);try{if(await g(s.id),!_.current)return;c("Auth credentials synced successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Auth sync failed";E(R),c(R,"error")}finally{_.current&&F(!1)}}},[c,s,g]),me=n.useCallback(()=>{E(null)},[]),he=n.useCallback(async()=>{if(!s||d)return;const N=a.trim();if(!N){c("Name is required","error");return}if(s.type==="remote"&&!x.trim()){c("URL is required for remote nodes","error");return}if(!Number.isFinite(v)||v<1){c("Concurrency must be at least 1","error");return}p(!0);try{await f(s.id,{name:N,url:s.type==="remote"&&x.trim()||void 0,apiKey:s.type==="remote"&&w||void 0,maxConcurrent:v}),c(`Updated ${N}`,"success"),A(!1)}catch(R){const ye=R instanceof Error?R.message:"Failed to update node";c(ye,"error")}finally{p(!1)}},[c,w,d,v,a,s,f,x]),fe=n.useCallback(()=>{s&&(i(s.name),b(s.url??""),$(s.apiKey??""),h(s.maxConcurrent),A(!1))},[s]);return!t||!s?null:e.jsxs("div",{className:"modal-overlay open",onClick:l,children:[e.jsxs("div",{className:"modal modal-lg node-detail-modal",onClick:N=>N.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":`Node details for ${s.name}`,children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Node Details"}),e.jsx("button",{className:"modal-close",onClick:l,"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"}),!S&&e.jsxs("button",{className:"btn btn-sm",onClick:()=>A(!0),children:[e.jsx(ve,{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"}),S?e.jsx("input",{className:"input",value:a,onChange:N=>i(N.target.value),disabled:d}):e.jsx("strong",{children:s.name})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Type"}),e.jsx("strong",{children:s.type==="local"?"Local":"Remote"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Status"}),e.jsx("strong",{children:s.status})]}),e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),S?e.jsx("input",{className:"input",type:"number",min:1,max:10,value:v,onChange:N=>h(Number(N.target.value)),disabled:d}):e.jsx("strong",{children:s.maxConcurrent})]}),s.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"}),S?e.jsx("input",{className:"input",value:x,onChange:N=>b(N.target.value),disabled:d}):e.jsx("strong",{children:s.url??"—"})]}),e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"API Key"}),S?e.jsx("input",{className:"input",type:"password",value:w,onChange:N=>$(N.target.value),placeholder:"Leave blank to keep unchanged",disabled:d}):e.jsx("strong",{children:s.apiKey?"••••••••":"Not configured"})]})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Created"}),e.jsx("strong",{children:V(s.createdAt)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Updated"}),e.jsx("strong",{children:V(s.updatedAt)})]})]}),S&&e.jsxs("div",{className:"node-detail-modal__edit-actions",children:[e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:he,disabled:d,children:[e.jsx(Ce,{size:14}),d?"Saving...":"Save"]}),e.jsxs("button",{className:"btn btn-sm",onClick:fe,disabled:d,children:[e.jsx(B,{size:14}),"Cancel"]})]})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("h4",{children:[s.type==="local"?"Projects":"Assigned Projects"," (",K.length,")"]}),K.length===0?e.jsx("p",{className:"node-detail-modal__empty",children:s.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:K.map(N=>e.jsxs("li",{className:"node-detail-modal__project-item",children:[e.jsx("span",{children:N.name}),e.jsx("code",{children:N.id})]},N.id))})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Health"}),e.jsxs("div",{className:"node-detail-modal__health-row",children:[e.jsxs("span",{children:["Status: ",e.jsx("strong",{children:s.status})]}),e.jsxs("span",{children:["Last check: ",e.jsx("strong",{children:V(s.updatedAt)})]})]})]}),s.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Settings Sync"}),u&&e.jsxs("div",{className:"node-detail-modal__sync-status",children:[e.jsx("span",{className:"node-detail-modal__sync-dot",style:{backgroundColor:ae(u.syncState)},"aria-hidden":!0}),e.jsxs("span",{children:["Last sync:"," ",e.jsx("strong",{children:u.lastSyncAt?te(u.lastSyncAt):"Never synced"})]}),u.diffCount>0&&e.jsxs("span",{className:"node-detail-modal__sync-diff",children:["Differences: ",e.jsx("strong",{children:u.diffCount})]})]}),e.jsxs("div",{className:"node-detail-modal__sync-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:ie,disabled:z||!o,children:[e.jsx(se,{size:14}),z?"Pushing...":"Push Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:de,disabled:k||!y,children:[e.jsx(ee,{size:14}),k?"Pulling...":"Pull Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:ue,disabled:P||!g,children:[e.jsx(Q,{size:14}),P?"Syncing...":"Sync Auth"]})]}),I&&e.jsxs("div",{className:"node-detail-modal__sync-error",children:[e.jsx("span",{children:I}),e.jsx("button",{className:"node-detail-modal__sync-error-dismiss",onClick:me,"aria-label":"Dismiss error",children:e.jsx(B,{size:14})})]})]}),s.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Sync History"}),e.jsx(Ge,{nodeId:s.id,entries:j,singleNode:!0})]})]}),e.jsxs("div",{className:"modal-actions node-detail-modal__actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:oe,children:[e.jsx(T,{size:14}),"Health Check"]}),e.jsx("button",{className:"btn btn-sm",onClick:l,children:"Close"})]})]}),s.type==="remote"&&e.jsx(Ye,{isOpen:le,onClose:()=>re(!1),onResolve:C??(async()=>{}),conflicts:ce,localNodeName:"Local",remoteNodeName:s.name,addToast:c})]})}function ts({addToast:t,onClose:l}){const{nodes:s,loading:r,error:f,refresh:m,register:c,update:u,unregister:o,healthCheck:y}=ke(),{projects:g}=Se(),{syncStatusMap:j,pushSettings:C,pullSettings:_,syncAuth:S,trackNode:A,getAuthSyncState:a,getAuthProviders:i}=$e(),[x,b]=n.useState(!1),[w,$]=n.useState(null);n.useEffect(()=>{const k=s.filter(M=>M.type==="remote");for(const M of k)A(M.id)},[s,A]),n.useEffect(()=>{if(!w)return;const k=s.find(M=>M.id===w.id)??null;$(k)},[s,w]);const v=n.useMemo(()=>{const k=s.length,M=s.filter(E=>E.status==="online").length,P=s.filter(E=>E.status==="offline"||E.status==="error").length,F=s.filter(E=>E.type==="remote").length,I=s.filter(E=>E.type==="remote"&&j[E.id]&&U(j[E.id]).syncState==="synced").length;return{total:k,online:M,offline:P,remote:F,synced:I}},[s,j]),h=n.useCallback(async k=>{await c(k)},[c]),d=n.useCallback(async()=>{try{await m()}catch{t("Failed to refresh nodes","error")}},[t,m]),p=n.useCallback(async k=>{try{await y(k),t("Node health check complete","success")}catch(M){const P=M instanceof Error?M.message:"Health check failed";t(P,"error")}},[t,y]),z=n.useCallback(async k=>{try{await o(k),t("Node removed","success"),w?.id===k&&$(null)}catch(M){const P=M instanceof Error?M.message:"Failed to remove node";t(P,"error")}},[t,w?.id,o]),L=n.useCallback(async(k,M)=>{await u(k,M)},[u]);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(Z,{size:20}),"Nodes"]}),e.jsxs("span",{className:"nodes-view-count",children:[s.length," registered"]})]}),e.jsxs("div",{className:"nodes-view-actions",children:[e.jsx("button",{className:"btn-icon nodes-view-close",onClick:l,"aria-label":"Close nodes view",children:e.jsx(B,{size:16})}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void d(),disabled:r,children:[e.jsx(J,{size:14,className:r?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>b(!0),children:[e.jsx(G,{size:14}),"Add 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(Re,{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(Me,{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(we,{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(J,{size:14})," Synced"]}),e.jsx("strong",{children:v.synced})]})]}),f&&e.jsx("div",{className:"nodes-view-error",children:f}),!r&&s.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(qe,{nodes:s})]}),r?e.jsx("div",{className:"nodes-view-grid",children:Array.from({length:4}).map((k,M)=>e.jsx("div",{className:"node-card node-card--loading","aria-hidden":!0},M))}):s.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:()=>b(!0),children:[e.jsx(G,{size:14}),"Add First Node"]})]}):e.jsx("div",{className:"nodes-view-grid",children:s.map(k=>{const M=k.type==="remote"&&j[k.id]?U(j[k.id]):void 0;return e.jsx(Ue,{node:k,projects:g,onHealthCheck:P=>{p(P)},onEdit:P=>$(P),onRemove:P=>{z(P)},isLoading:r,syncStatus:M,authSyncState:k.type==="remote"?a(k.id):void 0,authSyncProviders:k.type==="remote"?i(k.id):void 0},k.id)})}),e.jsx(Je,{isOpen:x,onClose:()=>b(!1),onSubmit:h,addToast:t}),e.jsx(Ze,{isOpen:w!==null,onClose:()=>$(null),node:w,projects:g,onUpdate:L,onHealthCheck:p,addToast:t,syncStatus:w?.type==="remote"&&w&&j[w.id]?U(j[w.id]):void 0,onPushSettings:C,onPullSettings:_,onSyncAuth:S})]})}export{ts as NodesView};
14
+ `)}function Ye({isOpen:t,onClose:l,onResolve:s,conflicts:r,localNodeName:f,remoteNodeName:m,addToast:c}){const[u,o]=n.useState({}),[y,g]=n.useState(!1);n.useEffect(()=>{const a={};for(const i of r)u[i.key]||(a[i.key]={resolution:"local"});Object.keys(a).length>0&&o(i=>({...i,...a}))},[r,u]),n.useEffect(()=>{if(!t)return;const a=i=>{i.key==="Escape"&&(i.preventDefault(),l())};return document.addEventListener("keydown",a),()=>document.removeEventListener("keydown",a)},[t,l]);const j=n.useCallback((a,i)=>{o(x=>{const b=x[a]??{};return i==="manual"?{...x,[a]:{resolution:"manual",manualValue:b.manualValue??JSON.stringify(r.find(w=>w.key===a)?.localValue??null,null,2)}}:{...x,[a]:{resolution:i}}})},[r]),C=n.useCallback((a,i)=>{o(x=>({...x,[a]:{...x[a],resolution:"manual",manualValue:i}}))},[]),_=n.useCallback(a=>{const i={};for(const x of r)i[x.key]={resolution:a};o(i)},[r]),S=n.useCallback(async()=>{g(!0);try{const a=r.map(i=>{const x=u[i.key]??{resolution:"local"};let b;switch(x.resolution){case"remote":b=i.remoteValue;break;case"manual":try{b=JSON.parse(x.manualValue??"null")}catch{b=x.manualValue??null}break;case"local":default:b=i.localValue;break}return{key:i.key,value:b}});await s(a),c("Settings conflicts resolved successfully","success"),l()}catch(a){const i=a instanceof Error?a.message:"Failed to resolve conflicts";c(i,"error")}finally{g(!1)}},[c,r,l,s,u]),M=n.useMemo(()=>{const a={};for(const i of r)a[i.key]=We(i.localValue,i.remoteValue);return a},[r]);return!t||r.length===0?null:e.jsx("div",{className:"modal-overlay open",onClick:l,children:e.jsxs("div",{className:"modal modal-lg settings-sync-conflict-modal",onClick:a=>a.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:l,"aria-label":"Close conflict modal",children:"×"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("div",{className:"settings-sync-conflict-modal__conflict-list",children:r.map(a=>{const i=u[a.key]??{resolution:"local"},x=M[a.key];return e.jsxs("div",{className:"settings-sync-conflict-modal__conflict-item",children:[e.jsx("div",{className:"settings-sync-conflict-modal__key",children:a.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:f}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:x})})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:m}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:x})})]})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__resolution",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="local",onChange:()=>j(a.key,"local")}),"Keep Local"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="remote",onChange:()=>j(a.key,"remote")}),"Keep Remote"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="manual",onChange:()=>j(a.key,"manual")}),"Merge Manually"]})]}),i.resolution==="manual"&&e.jsx("textarea",{className:"settings-sync-conflict-modal__manual-input",value:i.manualValue??"",onChange:b=>C(a.key,b.target.value),placeholder:"Enter JSON value..."})]},a.key)})}),e.jsxs("div",{className:"settings-sync-conflict-modal__bulk-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:()=>_("local"),type:"button",children:"Resolve All: Keep Local"}),e.jsx("button",{className:"btn btn-sm",onClick:()=>_("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:l,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:S,disabled:y,children:y?"Resolving...":"Confirm"})]})]})})}function V(t){if(!t)return"—";const l=new Date(t);return Number.isNaN(l.getTime())?"—":l.toLocaleString()}function Ze({isOpen:t,onClose:l,node:s,projects:r,onUpdate:f,onHealthCheck:m,addToast:c,syncStatus:u,onPushSettings:o,onPullSettings:y,onSyncAuth:g,syncHistory:j=[],onResolveConflicts:C}){const _=n.useRef(!0),[S,M]=n.useState(!1),[a,i]=n.useState(""),[x,b]=n.useState(""),[w,$]=n.useState(""),[v,h]=n.useState(2),[d,p]=n.useState(!1),[z,L]=n.useState(!1),[k,A]=n.useState(!1),[P,F]=n.useState(!1),[I,E]=n.useState(null),[le,re]=n.useState(!1),[ce]=n.useState([]);n.useEffect(()=>(_.current=!0,()=>{_.current=!1}),[]),n.useEffect(()=>{if(!s||!t){M(!1);return}i(s.name),b(s.url??""),$(s.apiKey??""),h(s.maxConcurrent),M(!1)},[t,s]),n.useEffect(()=>{if(!t)return;const N=R=>{R.key==="Escape"&&(R.preventDefault(),l())};return document.addEventListener("keydown",N),()=>document.removeEventListener("keydown",N)},[t,l]);const K=n.useMemo(()=>s?ne(r,s):[],[s,r]),oe=n.useCallback(async()=>{if(s)try{if(await m(s.id),!_.current)return;c(`Health check completed for ${s.name}`,"success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Health check failed";c(R,"error")}},[c,s,m]),ie=n.useCallback(async()=>{if(!(!s||!o)){E(null),L(!0);try{if(await o(s.id),!_.current)return;c("Settings pushed successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Push settings failed";E(R),c(R,"error")}finally{_.current&&L(!1)}}},[c,s,o]),de=n.useCallback(async()=>{if(!(!s||!y)){E(null),A(!0);try{if(await y(s.id),!_.current)return;c("Settings pulled successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Pull settings failed";E(R),c(R,"error")}finally{_.current&&A(!1)}}},[c,s,y]),ue=n.useCallback(async()=>{if(!(!s||!g)){E(null),F(!0);try{if(await g(s.id),!_.current)return;c("Auth credentials synced successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Auth sync failed";E(R),c(R,"error")}finally{_.current&&F(!1)}}},[c,s,g]),me=n.useCallback(()=>{E(null)},[]),he=n.useCallback(async()=>{if(!s||d)return;const N=a.trim();if(!N){c("Name is required","error");return}if(s.type==="remote"&&!x.trim()){c("URL is required for remote nodes","error");return}if(!Number.isFinite(v)||v<1){c("Concurrency must be at least 1","error");return}p(!0);try{await f(s.id,{name:N,url:s.type==="remote"&&x.trim()||void 0,apiKey:s.type==="remote"&&w||void 0,maxConcurrent:v}),c(`Updated ${N}`,"success"),M(!1)}catch(R){const ye=R instanceof Error?R.message:"Failed to update node";c(ye,"error")}finally{p(!1)}},[c,w,d,v,a,s,f,x]),fe=n.useCallback(()=>{s&&(i(s.name),b(s.url??""),$(s.apiKey??""),h(s.maxConcurrent),M(!1))},[s]);return!t||!s?null:e.jsxs("div",{className:"modal-overlay open",onClick:l,children:[e.jsxs("div",{className:"modal modal-lg node-detail-modal",onClick:N=>N.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":`Node details for ${s.name}`,children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Node Details"}),e.jsx("button",{className:"modal-close",onClick:l,"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"}),!S&&e.jsxs("button",{className:"btn btn-sm",onClick:()=>M(!0),children:[e.jsx(ve,{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"}),S?e.jsx("input",{className:"input",value:a,onChange:N=>i(N.target.value),disabled:d}):e.jsx("strong",{children:s.name})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Type"}),e.jsx("strong",{children:s.type==="local"?"Local":"Remote"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Status"}),e.jsx("strong",{children:s.status})]}),e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),S?e.jsx("input",{className:"input",type:"number",min:1,max:10,value:v,onChange:N=>h(Number(N.target.value)),disabled:d}):e.jsx("strong",{children:s.maxConcurrent})]}),s.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"}),S?e.jsx("input",{className:"input",value:x,onChange:N=>b(N.target.value),disabled:d}):e.jsx("strong",{children:s.url??"—"})]}),e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"API Key"}),S?e.jsx("input",{className:"input",type:"password",value:w,onChange:N=>$(N.target.value),placeholder:"Leave blank to keep unchanged",disabled:d}):e.jsx("strong",{children:s.apiKey?"••••••••":"Not configured"})]})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Created"}),e.jsx("strong",{children:V(s.createdAt)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Updated"}),e.jsx("strong",{children:V(s.updatedAt)})]})]}),S&&e.jsxs("div",{className:"node-detail-modal__edit-actions",children:[e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:he,disabled:d,children:[e.jsx(Ce,{size:14}),d?"Saving...":"Save"]}),e.jsxs("button",{className:"btn btn-sm",onClick:fe,disabled:d,children:[e.jsx(B,{size:14}),"Cancel"]})]})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("h4",{children:[s.type==="local"?"Projects":"Assigned Projects"," (",K.length,")"]}),K.length===0?e.jsx("p",{className:"node-detail-modal__empty",children:s.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:K.map(N=>e.jsxs("li",{className:"node-detail-modal__project-item",children:[e.jsx("span",{children:N.name}),e.jsx("code",{children:N.id})]},N.id))})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Health"}),e.jsxs("div",{className:"node-detail-modal__health-row",children:[e.jsxs("span",{children:["Status: ",e.jsx("strong",{children:s.status})]}),e.jsxs("span",{children:["Last check: ",e.jsx("strong",{children:V(s.updatedAt)})]})]})]}),s.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Settings Sync"}),u&&e.jsxs("div",{className:"node-detail-modal__sync-status",children:[e.jsx("span",{className:"node-detail-modal__sync-dot",style:{backgroundColor:ae(u.syncState)},"aria-hidden":!0}),e.jsxs("span",{children:["Last sync:"," ",e.jsx("strong",{children:u.lastSyncAt?te(u.lastSyncAt):"Never synced"})]}),u.diffCount>0&&e.jsxs("span",{className:"node-detail-modal__sync-diff",children:["Differences: ",e.jsx("strong",{children:u.diffCount})]})]}),e.jsxs("div",{className:"node-detail-modal__sync-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:ie,disabled:z||!o,children:[e.jsx(se,{size:14}),z?"Pushing...":"Push Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:de,disabled:k||!y,children:[e.jsx(ee,{size:14}),k?"Pulling...":"Pull Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:ue,disabled:P||!g,children:[e.jsx(Q,{size:14}),P?"Syncing...":"Sync Auth"]})]}),I&&e.jsxs("div",{className:"node-detail-modal__sync-error",children:[e.jsx("span",{children:I}),e.jsx("button",{className:"node-detail-modal__sync-error-dismiss",onClick:me,"aria-label":"Dismiss error",children:e.jsx(B,{size:14})})]})]}),s.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Sync History"}),e.jsx(Ge,{nodeId:s.id,entries:j,singleNode:!0})]})]}),e.jsxs("div",{className:"modal-actions node-detail-modal__actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:oe,children:[e.jsx(T,{size:14}),"Health Check"]}),e.jsx("button",{className:"btn btn-sm",onClick:l,children:"Close"})]})]}),s.type==="remote"&&e.jsx(Ye,{isOpen:le,onClose:()=>re(!1),onResolve:C??(async()=>{}),conflicts:ce,localNodeName:"Local",remoteNodeName:s.name,addToast:c})]})}function ts({addToast:t,onClose:l}){const{nodes:s,loading:r,error:f,refresh:m,register:c,update:u,unregister:o,healthCheck:y}=ke(),{projects:g}=Se(),{syncStatusMap:j,pushSettings:C,pullSettings:_,syncAuth:S,trackNode:M,getAuthSyncState:a,getAuthProviders:i}=$e(),[x,b]=n.useState(!1),[w,$]=n.useState(null);n.useEffect(()=>{const k=s.filter(A=>A.type==="remote");for(const A of k)M(A.id)},[s,M]),n.useEffect(()=>{if(!w)return;const k=s.find(A=>A.id===w.id)??null;$(k)},[s,w]);const v=n.useMemo(()=>{const k=s.length,A=s.filter(E=>E.status==="online").length,P=s.filter(E=>E.status==="offline"||E.status==="error").length,F=s.filter(E=>E.type==="remote").length,I=s.filter(E=>E.type==="remote"&&j[E.id]&&U(j[E.id]).syncState==="synced").length;return{total:k,online:A,offline:P,remote:F,synced:I}},[s,j]),h=n.useCallback(async k=>{await c(k)},[c]),d=n.useCallback(async()=>{try{await m()}catch{t("Failed to refresh nodes","error")}},[t,m]),p=n.useCallback(async k=>{try{await y(k),t("Node health check complete","success")}catch(A){const P=A instanceof Error?A.message:"Health check failed";t(P,"error")}},[t,y]),z=n.useCallback(async k=>{try{await o(k),t("Node removed","success"),w?.id===k&&$(null)}catch(A){const P=A instanceof Error?A.message:"Failed to remove node";t(P,"error")}},[t,w?.id,o]),L=n.useCallback(async(k,A)=>{await u(k,A)},[u]);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(Z,{size:20}),"Nodes"]}),e.jsxs("span",{className:"nodes-view-count",children:[s.length," registered"]})]}),e.jsxs("div",{className:"nodes-view-actions",children:[e.jsx("button",{className:"btn-icon nodes-view-close",onClick:l,"aria-label":"Close nodes view",children:e.jsx(B,{size:16})}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void d(),disabled:r,children:[e.jsx(J,{size:14,className:r?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>b(!0),children:[e.jsx(G,{size:14}),"Add 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(Re,{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(Ae,{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(we,{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(J,{size:14})," Synced"]}),e.jsx("strong",{children:v.synced})]})]}),f&&e.jsx("div",{className:"nodes-view-error",children:f}),!r&&s.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(qe,{nodes:s})]}),r?e.jsx("div",{className:"nodes-view-grid",children:Array.from({length:4}).map((k,A)=>e.jsx("div",{className:"node-card node-card--loading","aria-hidden":!0},A))}):s.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:()=>b(!0),children:[e.jsx(G,{size:14}),"Add First Node"]})]}):e.jsx("div",{className:"nodes-view-grid",children:s.map(k=>{const A=k.type==="remote"&&j[k.id]?U(j[k.id]):void 0;return e.jsx(Ue,{node:k,projects:g,onHealthCheck:P=>{p(P)},onEdit:P=>$(P),onRemove:P=>{z(P)},isLoading:r,syncStatus:A,authSyncState:k.type==="remote"?a(k.id):void 0,authSyncProviders:k.type==="remote"?i(k.id):void 0},k.id)})}),e.jsx(Je,{isOpen:x,onClose:()=>b(!1),onSubmit:h,addToast:t}),e.jsx(Ze,{isOpen:w!==null,onClose:()=>$(null),node:w,projects:g,onUpdate:L,onHealthCheck:p,addToast:t,syncStatus:w?.type==="remote"&&w&&j[w.id]?U(j[w.id]):void 0,onPushSettings:C,onPullSettings:_,onSyncAuth:S})]})}export{ts as NodesView};
@@ -1,11 +1,11 @@
1
- import{r as l,j as e}from"./vendor-react-K0fH_qHe.js";import{c as A,d5 as J,d6 as Q,d7 as V,R as $,cY as y,w as Z,K as T,D as ee,I as se,bR as L,F as D,d8 as ae,d9 as te,da as _,X as ie}from"./index-BRTEq_-7.js";import"./vendor-xterm-DzcZoU0P.js";/**
1
+ import{r as l,j as e}from"./vendor-react-K0fH_qHe.js";import{c as A,dq as Q,dr as V,ds as Y,R as $,di as y,y as Z,N as T,H as ee,M as se,c7 as L,F as D,dt as ae,du as te,dv as M,X as ie}from"./index-DJDWSrju.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"}]],I=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"}]],_=A("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"}]],M=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(""),[K,O]=l.useState(new Set),[p,W]=l.useState([]),[b,z]=l.useState(!0),[q,C]=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{z(!0);const s=await Q(x);W(s.extensions)}catch(s){t(`Failed to load extensions: ${s instanceof Error?s.message:String(s)}`,"error")}finally{z(!1)}},[t,x]),B=l.useCallback(async s=>{try{C(!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{C(!1)}},[p,x,m,t]);l.useEffect(()=>{r()},[r]),l.useEffect(()=>{m()},[m]);const U=s=>{O(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)}},Y=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,{size:12})})]},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(Z,{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=K.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:()=>Y(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(M,{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(I,{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",M,"extensions"),u("Skills",L,"skills"),u("Prompts",D,"prompts"),u("Themes",I,"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($,{size:14,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};
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"}]],q=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,O]=l.useState(new Set),[p,W]=l.useState([]),[b,z]=l.useState(!0),[B,C]=l.useState(!1),r=l.useCallback(async()=>{try{P(!0);const s=await Q();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{z(!0);const s=await V(x);W(s.extensions)}catch(s){t(`Failed to load extensions: ${s instanceof Error?s.message:String(s)}`,"error")}finally{z(!1)}},[t,x]),H=l.useCallback(async s=>{try{C(!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 Y(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{C(!1)}},[p,x,m,t]);l.useEffect(()=>{r()},[r]),l.useEffect(()=>{m()},[m]);const K=s=>{O(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 M({packages:i}),t("Package removed","success"),await r()}catch(a){t(`Failed to remove package: ${a instanceof Error?a.message:String(a)}`,"error")}},J=async(s,i)=>{if(!c)return;const a=c[s].filter(n=>n!==i);try{await M({[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:()=>J(a,n),title:`Remove ${n}`,"aria-label":`Remove ${n}`,children:e.jsx(ie,{size:12})})]},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(Z,{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=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:()=>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(q,{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(_,{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",q,"extensions"),u("Skills",L,"skills"),u("Prompts",D,"prompts"),u("Themes",_,"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($,{size:14,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 H(s),disabled:B,"aria-label":`Toggle ${s.name}`}),e.jsx("span",{className:"toggle-slider"})]})})]},s.id))})]})]})}export{he as PiExtensionsManager};
@@ -0,0 +1 @@
1
+ import{r as u,j as s}from"./vendor-react-K0fH_qHe.js";import{o as ee,dg as se,s as ne,X as D,aj as te,y as O,dh as A,M as _,R as ie,di as ae,as as le,bZ as re,dj as ce,dk as de,dl as ue,dm as oe,dn as M,bW as ge}from"./index-DJDWSrju.js";import{D as me}from"./DirectoryPicker-D5KQ-im_.js";import"./vendor-xterm-DzcZoU0P.js";import"./folder-open-C3zB1vmh.js";const V=[{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}],j={started:"var(--color-success)",loaded:"var(--color-warning)",error:"var(--color-error)",stopped:"var(--color-muted)",installed:"var(--color-info)"};function fe({addToast:l,projectId:c}){const[N,b]=u.useState([]),[S,w]=u.useState(!0),[H,f]=u.useState(!1),[x,v]=u.useState(""),[C,P]=u.useState(!1),[h,I]=u.useState(null),[i,y]=u.useState(null),[a,p]=u.useState({}),[G,$]=u.useState(!1),[R,E]=u.useState(null),{confirm:J}=ee(),o=u.useCallback(async()=>{try{w(!0);const e=await se(c);b(e)}catch(e){l(`Failed to load plugins: ${e instanceof Error?e.message:String(e)}`,"error")}finally{w(!1)}},[c,l]);u.useEffect(()=>{o()},[o]);const K=u.useRef([]);K.current=N,u.useEffect(()=>{const e=c?`?projectId=${encodeURIComponent(c)}`:"",n=g=>{try{const t=JSON.parse(g.data);if(c&&t.projectId&&t.projectId!==c)return;switch(t.transition){case"installing":case"enabled":case"disabled":case"settings-updated":b(d=>{const m=d.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...d];return r[m]={...r[m],enabled:t.enabled,state:t.state,settings:t.settings,error:t.error},r}else return o(),d});break;case"uninstalled":b(d=>d.filter(m=>m.id!==t.pluginId));break;case"error":b(d=>{const m=d.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...d];return r[m]={...r[m],state:t.state,error:t.error},r}return d});break}}catch{}};return ne(`/api/events${e}`,{events:{"plugin:lifecycle":n},onReconnect:()=>{o()}})},[c,o]);const z=async()=>{if(!x.trim()){l("Please enter a plugin path","error");return}try{P(!0),await M({path:x},c),l("Plugin installed successfully","success"),f(!1),v(""),await o()}catch(e){l(`Failed to install plugin: ${e instanceof Error?e.message:String(e)}`,"error")}finally{P(!1)}},W=async e=>{try{E(e.id),await M({path:e.path},c),l(`${e.name} installed successfully`,"success"),await o()}catch(n){l(`Failed to install ${e.name}: ${n instanceof Error?n.message:String(n)}`,"error")}finally{E(null)}},F=async e=>{try{await ue(e.id,c),l(`${e.name} enabled`,"success"),await o()}catch(n){l(`Failed to enable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},B=async e=>{try{await de(e.id,c),l(`${e.name} disabled`,"success"),await o()}catch(n){l(`Failed to disable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},L=async e=>{try{I(e.id),await ce(e.id,c),l(`${e.name} reloaded`,"success"),await o()}catch(n){l(`Failed to reload plugin: ${n instanceof Error?n.message:String(n)}`,"error")}finally{I(null)}},U=async e=>{if(await J({title:"Uninstall Plugin",message:`Are you sure you want to uninstall "${e.name}"?`,danger:!0}))try{await oe(e.id,c),l(`${e.name} uninstalled`,"success"),await o(),y(null)}catch(g){l(`Failed to uninstall plugin: ${g instanceof Error?g.message:String(g)}`,"error")}},X=async e=>{y(e);try{$(!0);const n=await ge(e.id,c);p(n)}catch{p({})}finally{$(!1)}},Z=async()=>{if(i)try{await re(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(D,{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:j[i.state]||j.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(te,{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"}),G?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 g=`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",{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?g:void 0}),n.type==="string"&&n.multiline&&s.jsx("textarea",{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?g:void 0}),n.type==="password"&&s.jsx("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?g:void 0}),n.type==="number"&&s.jsx("input",{type:"number",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:Number(t.target.value)}),"aria-describedby":n.description&&!n.required?g: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",{id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),"aria-describedby":n.description&&!n.required?g: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,d)=>s.jsxs("div",{className:"plugin-settings-array-item",children:[s.jsx("input",{type:n.itemType==="number"?"number":"text",value:t??"",onChange:m=>{const r=m.target.value,q=[...a[e]||[]];q[d]=n.itemType==="number"?Number(r):r,p({...a,[e]:q})}}),s.jsx("button",{className:"btn-icon",onClick:()=>{const r=[...a[e]||[]];r.splice(d,1),p({...a,[e]:r})},"aria-label":"Remove item",children:s.jsx(D,{size:14})})]},d)),s.jsxs("button",{className:"btn btn-secondary",onClick:()=>{const t=a[e]||[],d=n.itemType==="number"?0:"";p({...a,[e]:[...t,d]})},children:[s.jsx(O,{size:14})," Add Item"]})]}),n.description&&!n.required&&!n.multiline&&s.jsx("span",{id:g,className:"form-help",children:n.description})]},e)}),s.jsx("button",{className:"btn btn-primary",onClick:Z,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(A,{size:14,className:h===i.id?"spin":""}),h===i.id?"Reloading...":"Reload"]}),i.enabled?s.jsx("button",{className:"btn btn-secondary",onClick:()=>B(i),children:"Disable"}):s.jsx("button",{className:"btn btn-primary",onClick:()=>F(i),children:"Enable"}),s.jsxs("button",{className:"btn btn-danger",onClick:()=>U(i),children:[s.jsx(_,{size:14})," Uninstall"]})]})]})]});const Q=new Set(N.map(e=>e.id)),Y=new Set(V.map(e=>e.id)),k=N.filter(e=>!Y.has(e.id)),T=()=>s.jsxs("section",{className:"plugin-bundled-runtime-section","aria-label":"Bundled Runtime Plugins",children:[s.jsxs("div",{className:"plugin-bundled-runtime-header",children:[s.jsx("h4",{className:"plugin-bundled-runtime-heading",children:"Bundled Runtime Plugins"}),s.jsx("p",{className:"plugin-bundled-runtime-description",children:"Install Fusion's bundled runtimes directly from this screen."})]}),s.jsx("div",{className:"plugin-bundled-runtime-list","aria-label":"Bundled runtime plugin recommendations",children:V.map(e=>{const n=Q.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:()=>W(e),disabled:n||R===e.id,children:n?"Installed":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 btn-ghost",onClick:o,title:"Refresh","aria-label":"Refresh plugin list",children:[s.jsx(ie,{size:14,className:S?"spin":""}),"Refresh"]}),s.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>f(!0),children:[s.jsx(O,{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(me,{value:x,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||!x.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:[k.length===0?s.jsxs("div",{className:"settings-empty-state",children:[s.jsx(ae,{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 runtime below."})]}):s.jsx("div",{className:"plugin-list",children:k.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:j[e.state]||j.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(A,{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?B(e):F(e)}),s.jsx("span",{className:"toggle-slider"})]}),s.jsx("button",{className:"btn-icon",onClick:()=>X(e),title:"Settings",children:s.jsx(le,{size:14})}),s.jsx("button",{className:"btn-icon",onClick:()=>U(e),title:"Uninstall",children:s.jsx(_,{size:14})})]})]},e.id))}),T()]})]})}export{fe as PluginManager,j as STATE_COLORS};
@@ -0,0 +1 @@
1
+ .plugin-manager,.plugin-manager-detail{display:flex;flex-direction:column;gap:var(--space-lg);padding-inline:var(--space-xl);padding-block:var(--space-md)}.plugin-manager-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--space-sm);border-bottom:var(--btn-border-width) solid var(--border);gap:var(--space-sm)}.plugin-manager-header-title{font-size:13px;font-weight:600;color:var(--text);flex:1}.plugin-manager-actions{display:flex;gap:var(--space-sm);align-items:center}.plugin-install-form{display:flex;flex-direction:column;gap:var(--space-sm);padding:var(--space-lg);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--surface)}.plugin-install-hint{margin:0;font-size:.85rem;color:var(--text-secondary, var(--text-muted));line-height:1.45}.plugin-install-hint code{padding:var(--btn-border-width) var(--space-xs);border-radius:var(--radius-sm);background:color-mix(in srgb,var(--text-muted) 12%,transparent);font-size:.85em}.plugin-install-actions{display:flex;gap:var(--space-sm);justify-content:flex-end}.plugin-list{display:flex;flex-direction:column;gap:var(--space-sm)}.plugin-item{display:flex;align-items:center;justify-content:space-between;padding:var(--space-md) var(--space-lg);background:var(--surface);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);transition:border-color var(--transition-fast)}.plugin-item:hover{border-color:var(--text-dim)}.plugin-info{display:flex;align-items:center;gap:var(--space-sm);min-width:0}.plugin-name{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.plugin-version{font-size:.85rem}.plugin-state-badge{display:inline-flex;align-items:center;padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;background:color-mix(in srgb,currentColor 12%,transparent)}.plugin-actions{display:flex;align-items:center;gap:var(--space-xs);flex-shrink:0}.plugin-manager-detail-header,.plugin-detail-title{display:flex;align-items:center;gap:var(--space-md);flex-wrap:wrap}.plugin-detail-name{margin:0}.plugin-detail-content{display:flex;flex-direction:column;gap:var(--space-lg)}.plugin-detail-card{background:var(--surface);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);padding:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-md)}.plugin-description{font-size:.95rem;color:var(--text-secondary, var(--text-muted));line-height:1.5}.plugin-detail-meta-row{display:flex;align-items:center;gap:var(--space-xs);font-size:.9rem;color:var(--text-muted)}.plugin-homepage a{display:inline-flex;align-items:center;gap:var(--space-xs);color:var(--color-info);font-size:.85rem}.plugin-detail-section-heading{margin:0;padding:0;border:0;font-size:.95rem}.plugin-settings-form{display:flex;flex-direction:column;gap:var(--space-lg);margin-top:var(--space-xs)}.plugin-settings-form .form-group{padding:0;margin:0}.plugin-settings-array{display:flex;flex-direction:column;gap:var(--space-sm)}.plugin-settings-array-item{display:flex;align-items:center;gap:var(--space-sm)}.plugin-settings-array-item input{flex:1}.plugin-detail-actions{display:flex;gap:var(--space-sm);padding-top:var(--space-md);border-top:var(--btn-border-width) solid var(--border);justify-content:flex-end}.plugin-manager .empty-state,.plugin-manager .loading-state,.plugin-manager .settings-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-sm);padding:var(--space-2xl);text-align:center;color:var(--text-muted)}.plugin-bundled-runtime-list{width:100%;display:flex;flex-direction:column;gap:var(--space-sm);margin-top:var(--space-sm)}.plugin-bundled-runtime-item{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--surface)}.plugin-bundled-runtime-meta{display:flex;align-items:center;gap:var(--space-sm);min-width:0}.plugin-bundled-runtime-name{color:var(--text);font-size:.9rem;font-weight:500}.plugin-bundled-runtime-badge{display:inline-flex;align-items:center;padding:var(--btn-border-width) var(--space-xs);border-radius:var(--radius-pill);background:var(--status-in-review-bg);color:var(--in-review);font-size:.75rem;font-weight:600;text-transform:uppercase}.plugin-bundled-runtime-section{display:flex;flex-direction:column;gap:var(--space-sm)}.plugin-bundled-runtime-header{display:flex;flex-direction:column;gap:var(--space-xs)}.plugin-bundled-runtime-heading{margin:0;font-size:.95rem}.plugin-bundled-runtime-description{margin:0;font-size:.85rem;color:var(--text-muted)}.plugin-bundled-runtime-status{display:inline-flex;align-items:center;padding:var(--btn-border-width) var(--space-xs);border-radius:var(--radius-pill);font-size:.75rem;font-weight:600;text-transform:uppercase}.plugin-bundled-runtime-status--installed{background:var(--status-done-bg);color:var(--done)}.plugin-bundled-runtime-status--available{background:var(--status-todo-bg);color:var(--todo)}@media(max-width:768px){.plugin-manager-detail-header{gap:var(--space-sm)}.plugin-detail-title{gap:var(--space-xs)}.plugin-detail-card{padding:var(--space-md);gap:var(--space-sm)}.plugin-list{gap:var(--space-xs)}.plugin-item{padding:var(--space-md);flex-direction:column;align-items:stretch;gap:var(--space-sm)}.plugin-info{width:100%;flex-wrap:wrap;row-gap:var(--space-xs)}.plugin-name{flex:1 1 100%;white-space:normal}.plugin-actions{width:100%;justify-content:flex-end;flex-wrap:wrap;gap:var(--space-sm)}.plugin-actions .btn-icon,.plugin-actions .toggle-switch{min-width:36px;min-height:36px}.plugin-actions .toggle-switch{display:inline-flex;align-items:center;justify-content:center}.plugin-detail-actions{flex-wrap:wrap;justify-content:flex-start}.plugin-detail-actions button{flex:1 1 auto;min-height:36px}.plugin-bundled-runtime-item{flex-direction:column;align-items:stretch}.plugin-bundled-runtime-item .btn{min-height:36px}}
@@ -0,0 +1,6 @@
1
+ import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Et,aQ as kt,aR as Ft,aS as Dt,aT as Mt,aU as Rt,aV as tt,aW as It,aX as $t,aY as at,aZ as zt,a_ as At,a$ as Bt,b0 as Ht,b1 as Ot,b2 as Tt,b3 as Gt,b4 as Pt,o as Lt,aH as Vt,y as Ae,b5 as he,X as re,au as Fe,M as Pe,a9 as Ut,af as pt,at as rt,a6 as Kt,b6 as Ye,b7 as Wt}from"./index-DJDWSrju.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 Yt=[["path",{d:"M12 2v4",key:"3427ic"}],["path",{d:"m16.2 7.8 2.9-2.9",key:"r700ao"}],["path",{d:"M18 12h4",key:"wj9ykh"}],["path",{d:"m16.2 16.2 2.9 2.9",key:"1bxg5t"}],["path",{d:"M12 18v4",key:"jadmvz"}],["path",{d:"m4.9 19.1 2.9-2.9",key:"bwix9q"}],["path",{d:"M2 12h4",key:"j09sii"}],["path",{d:"m4.9 4.9 2.9 2.9",key:"giyufr"}]],qt=Et("loader",Yt);function Jt(l){const n=l?.projectId,[v,f]=a.useState([]),[_,j]=a.useState(null),[S,m]=a.useState(null),[F,E]=a.useState([]),[C,y]=a.useState({}),[se,V]=a.useState(!1),[A,$]=a.useState(null),[De,ne]=a.useState(null),[fe,ie]=a.useState(!1),[Be,oe]=a.useState(null),[be,G]=a.useState([]),[B,P]=a.useState(!1),[X,H]=a.useState({}),[Me,le]=a.useState({}),Y=a.useRef(X),ce=a.useRef(Me),Q=a.useRef(be);Y.current=X,ce.current=Me,Q.current=be;const Re=a.useRef(n),D=a.useRef(0),Z=a.useRef(0),He=a.useRef(v),x=a.useRef(_),de=a.useRef(F),ve=a.useRef(C),R=a.useRef(n),xe=a.useRef(De);He.current=v,x.current=_,de.current=F,ve.current=C,R.current=n,xe.current=De,a.useEffect(()=>{Re.current!==n&&(Re.current=n,D.current++,j(null),m(null),E([]),y({}),ne(null),oe(null),G([]),P(!1),H({}),le({}))},[n]);const q=a.useCallback(async()=>{V(!0),$(null);try{const r=await kt(n);f(r)}catch(r){$(r instanceof Error?r:new Error("Failed to fetch roadmaps"))}finally{V(!1)}},[n]),N=a.useCallback(async r=>{try{const c=await Ft(r,n);m(c),E(c.milestones||[]);const i={};for(const s of c.milestones||[])i[s.id]=s.features||[];y(i)}catch(c){$(c instanceof Error?c:new Error("Failed to fetch roadmap"))}},[n]);a.useEffect(()=>{q()},[q]),a.useEffect(()=>{_?N(_):(m(null),E([]),y({}))},[_,N]);const Oe=a.useCallback(async(r,c)=>{try{const i=await Dt(r,R.current);f(s=>[...s,i]),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to create roadmap");throw c?.onError?.(s),s}},[]),we=a.useCallback(async(r,c,i)=>{try{const s=await Mt(r,c,R.current);f(d=>d.map(o=>o.id===r?s:o)),x.current===r&&m(d=>d?{...d,...s}:null),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update roadmap");throw i?.onError?.(d),d}},[]),h=a.useCallback(async(r,c)=>{try{await Rt(r,R.current),f(i=>i.filter(s=>s.id!==r)),x.current===r&&(j(null),m(null),E([]),y({})),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete roadmap");throw c?.onError?.(s),s}},[]),I=a.useCallback(r=>{j(r)},[]),je=a.useCallback(async(r,c)=>{const i=x.current;if(!i){const s=new Error("No roadmap selected");throw c?.onError?.(s),s}try{const s=await tt(i,r,R.current);E(d=>[...d,s]),y(d=>({...d,[s.id]:[]})),x.current&&N(x.current),c?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to create milestone");throw c?.onError?.(d),d}},[N]),J=a.useCallback(async(r,c,i)=>{try{const s=await It(r,c,R.current);E(d=>d.map(o=>o.id===r?s:o)),x.current&&N(x.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update milestone");throw i?.onError?.(d),d}},[N]),_e=a.useCallback(async(r,c)=>{try{await $t(r,R.current),E(i=>i.filter(s=>s.id!==r)),y(i=>{const s={...i};return delete s[r],s}),x.current&&N(x.current),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete milestone");throw c?.onError?.(s),s}},[N]),Le=a.useCallback(async(r,c,i)=>{try{const s=await at(r,c,R.current);y(d=>({...d,[r]:[...d[r]||[],s]})),x.current&&N(x.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to create feature");throw i?.onError?.(d),d}},[N]),M=a.useCallback(async(r,c,i)=>{try{const s=await zt(r,c,R.current);y(d=>{const o={};for(const[g,p]of Object.entries(d))o[g]=p.map(w=>w.id===r?s:w);return o}),x.current&&N(x.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update feature");throw i?.onError?.(d),d}},[N]),ue=a.useCallback(async(r,c)=>{try{await At(r,R.current),y(i=>{const s={};for(const[d,o]of Object.entries(i))s[d]=o.filter(g=>g.id!==r);return s}),x.current&&N(x.current),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete feature");throw c?.onError?.(s),s}},[N]),O=a.useCallback(async(r,c,i)=>{const s=de.current,d=c.map(o=>s.find(g=>g.id===o)).filter(o=>o!==void 0).map((o,g)=>({...o,orderIndex:g}));E(d);try{await Bt(r,c,R.current),x.current&&N(x.current),i?.onSuccess?.()}catch(o){E(s);const g=o instanceof Error?o:new Error("Failed to reorder milestones");throw i?.onError?.(g),g}},[N]),ee=a.useCallback(async(r,c,i)=>{const s=ve.current[r]||[],d=s.map(p=>p.id);if(JSON.stringify(d)===JSON.stringify(c)){i?.onSuccess?.();return}const o=ve.current,g=c.map(p=>s.find(w=>w.id===p)).filter(p=>p!==void 0).map((p,w)=>({...p,orderIndex:w}));y(p=>({...p,[r]:g}));try{await Ht(r,c,R.current),x.current&&N(x.current),i?.onSuccess?.()}catch(p){y(o);const w=p instanceof Error?p:new Error("Failed to reorder features");throw i?.onError?.(w),w}},[N]),te=a.useCallback(async(r,c,i,s)=>{const d=ve.current;let o=null;for(const[k,K]of Object.entries(d))if(K.some(Ke=>Ke.id===r)){o=k;break}if(!o){const k=new Error("Feature not found");throw s?.onError?.(k),k}if(o===c){const k=d[o]||[],K=Math.max(0,Math.min(i,k.length-1));if(k.findIndex(We=>We.id===r)===K){s?.onSuccess?.();return}}const g=d[o]||[],p=d[c]||[],w=g.find(k=>k.id===r);if(!w){const k=new Error("Feature not found");throw s?.onError?.(k),k}const T=g.filter(k=>k.id!==r).map((k,K)=>({...k,orderIndex:K})),Ne={...w,milestoneId:c,orderIndex:i},ae=[...p];ae.splice(i,0,Ne);const Ve=ae.map((k,K)=>({...k,orderIndex:K}));y(o===c?k=>({...k,[o]:Ve}):k=>({...k,[o]:T,[c]:Ve}));try{await Ot(r,c,i,n),x.current&&N(x.current),s?.onSuccess?.()}catch(k){y(d);const K=k instanceof Error?k:new Error("Failed to move feature");throw s?.onError?.(K),K}},[N,n]);function Ie(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`draft-${Date.now()}-${Math.random().toString(36).slice(2,11)}`}const pe=a.useCallback(async(r,c=5,i)=>{const s=x.current;if(!s){const g=new Error("No roadmap selected");throw i?.onError?.(g),g}const d=D.current,o=R.current;P(!0);try{const g=await Tt(s,r,c,o);if(D.current!==d)return;const p=g.suggestions.map(w=>({id:Ie(),title:w.title,description:w.description}));G(p),i?.onSuccess?.()}catch(g){if(D.current!==d)return;const p=g instanceof Error?g:new Error("Failed to generate suggestions");throw i?.onError?.(p),p}finally{D.current===d&&P(!1)}},[]),Ue=a.useCallback((r,c)=>{const s=Q.current.map(d=>d.id===r?{...d,...c}:d);Q.current=s,G(d=>d.map(o=>o.id===r?{...o,...c}:o))},[]),me=a.useCallback(async(r,c)=>{const i=x.current;if(!i){const p=new Error("No roadmap selected");throw c?.onError?.(p),p}const s=D.current,d=Q.current,o=d.findIndex(p=>p.id===r);if(o===-1){const p=new Error("Suggestion draft not found");throw c?.onError?.(p),p}const g=d[o];if(!g.title.trim()){const p=new Error("Title cannot be empty");throw c?.onError?.(p),p}G(p=>p.filter(w=>w.id!==r));try{if(await tt(i,{title:g.title,description:g.description},R.current),D.current!==s){G(p=>{const w=[...p];return w.splice(o,0,g),w});return}x.current&&N(x.current),c?.onSuccess?.()}catch(p){G(T=>{const Ne=[...T];return Ne.splice(o,0,g),Ne});const w=p instanceof Error?p:new Error("Failed to accept suggestion");throw c?.onError?.(w),w}},[N]),U=a.useCallback(async r=>{const c=x.current;if(!c){const o=new Error("No roadmap selected");throw r?.onError?.(o),o}const i=[...Q.current];if(i.length===0)return;const s=i.findIndex(o=>!o.title.trim());if(s!==-1){const o=new Error(`Title cannot be empty at position ${s+1}`);throw r?.onError?.(o),o}G([]);const d=D.current;for(let o=0;o<i.length&&D.current===d;o++){const g=i[o];try{await tt(c,{title:g.title,description:g.description},R.current)}catch(p){const w=p instanceof Error?p:new Error("Failed to accept all suggestions");throw r?.onError?.(w),w}}D.current===d&&(x.current&&N(x.current),r?.onSuccess?.())},[N]),qe=a.useCallback(r=>ce.current[r]??!1,[]),Te=a.useCallback(async(r,c,i)=>{const s=D.current,d=R.current;le(o=>({...o,[r]:!0}));try{const o=await Gt(r,c,d);if(D.current!==s)return;const g=o.suggestions.map(p=>({id:Ie(),title:p.title,description:p.description}));H(p=>({...p,[r]:g})),i?.onSuccess?.()}catch(o){if(D.current!==s)return;const g=o instanceof Error?o:new Error("Failed to generate feature suggestions");throw i?.onError?.(g),g}finally{D.current===s&&le(o=>({...o,[r]:!1}))}},[]),Ce=a.useCallback((r,c,i)=>{const d=(Y.current[r]||[]).map(o=>o.id===c?{...o,...i}:o);Y.current={...Y.current,[r]:d},H(o=>({...o,[r]:o[r]?.map(g=>g.id===c?{...g,...i}:g)||[]}))},[]),Ge=a.useCallback(async(r,c,i)=>{const s=D.current,d=Y.current[r]||[],o=d.findIndex(p=>p.id===c);if(o===-1){const p=new Error("Suggestion draft not found");throw i?.onError?.(p),p}const g=d[o];if(!g.title.trim()){const p=new Error("Title cannot be empty");throw i?.onError?.(p),p}H(p=>({...p,[r]:p[r]?.filter(w=>w.id!==c)||[]}));try{if(await at(r,{title:g.title,description:g.description},R.current),D.current!==s){H(p=>{const T=[...p[r]||[]];return T.splice(o,0,g),{...p,[r]:T}});return}x.current&&N(x.current),i?.onSuccess?.()}catch(p){H(T=>{const ae=[...T[r]||[]];return ae.splice(o,0,g),{...T,[r]:ae}});const w=p instanceof Error?p:new Error("Failed to accept suggestion");throw i?.onError?.(w),w}},[N]),Je=a.useCallback(async(r,c)=>{const i=[...Y.current[r]||[]];if(i.length===0)return;const s=i.findIndex(o=>!o.title.trim());if(s!==-1){const o=new Error(`Title cannot be empty at position ${s+1}`);throw c?.onError?.(o),o}H(o=>({...o,[r]:[]}));const d=D.current;for(let o=0;o<i.length&&D.current===d;o++){const g=i[o];try{await at(r,{title:g.title,description:g.description},R.current)}catch(p){const w=p instanceof Error?p:new Error("Failed to accept all suggestions");throw c?.onError?.(w),w}}D.current===d&&(x.current&&N(x.current),c?.onSuccess?.())},[N]),ye=a.useCallback(()=>{G([]),P(!1)},[]),Xe=a.useCallback(r=>{H(c=>{const i={...c};return delete i[r],i}),le(c=>{const i={...c};return delete i[r],i})},[]),ge=a.useCallback(async(r,c)=>{const i=++Z.current,s=n;ie(!0),oe(null);try{const d=await Pt(r,s);if(Z.current!==i||n!==s)return;ne(d),c?.onSuccess?.()}catch(d){if(Z.current!==i||n!==s)return;const o=d instanceof Error?d:new Error(String(d));oe(o),ne(null),c?.onError?.(o)}finally{Z.current===i&&ie(!1)}},[n]),$e=a.useCallback(()=>{ne(null),oe(null),ie(!1)},[]),Qe=a.useCallback(async()=>{await q(),x.current&&await N(x.current)},[q,N]);return{roadmaps:v,selectedRoadmapId:_,selectedRoadmap:S,milestones:F,featuresByMilestoneId:C,loading:se,error:A,createRoadmap:Oe,updateRoadmap:we,deleteRoadmap:h,selectRoadmap:I,createMilestone:je,updateMilestone:J,deleteMilestone:_e,reorderMilestones:O,createFeature:Le,updateFeature:M,deleteFeature:ue,reorderFeatures:ee,moveFeature:te,milestoneSuggestions:be,isGeneratingSuggestions:B,generateMilestoneSuggestions:pe,updateMilestoneSuggestionDraft:Ue,acceptMilestoneSuggestion:me,acceptAllMilestoneSuggestions:U,clearMilestoneSuggestions:ye,featureSuggestionsByMilestoneId:X,isGeneratingFeatureSuggestions:qe,generateFeatureSuggestions:Te,updateFeatureSuggestionDraft:Ce,acceptFeatureSuggestion:Ge,acceptAllFeatureSuggestions:Je,clearFeatureSuggestions:Xe,handoffPayload:De,isFetchingHandoff:fe,handoffError:Be,fetchHandoff:ge,clearHandoff:$e,refresh:Qe}}function Xt({isOpen:l,onClose:n,roadmapTitle:v,handoffPayload:f,isLoading:_,error:j,onFetchHandoff:S,onCopyToClipboard:m}){return l?e.jsx("div",{className:"modal-overlay open",onClick:n,role:"presentation",children:e.jsxs("div",{className:"modal modal-lg",onClick:F=>F.stopPropagation(),role:"dialog","aria-modal":"true","aria-labelledby":"handoff-modal-title",children:[e.jsxs("div",{className:"modal-header",children:[e.jsxs("h2",{id:"handoff-modal-title",children:["Export Roadmap: ",v]}),e.jsx("button",{className:"modal-close",onClick:n,"aria-label":"Close modal",children:e.jsx(re,{size:18})})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("p",{className:"text-muted",style:{marginBottom:"var(--space-lg)"},children:"Export roadmap data for use in mission and task planning flows. This is a read-only export — no missions or tasks will be created."}),j&&e.jsxs("div",{className:"form-error",style:{marginBottom:"var(--space-lg)"},children:["Error loading handoff data: ",j.message]}),!f&&!_&&e.jsx("div",{style:{textAlign:"center",padding:"var(--space-xl)"},children:e.jsxs("button",{className:"btn btn-primary",onClick:S,children:[e.jsx(rt,{size:16,style:{marginRight:"var(--space-sm)"}}),"Load Handoff Data"]})}),_&&e.jsxs("div",{style:{textAlign:"center",padding:"var(--space-xl)"},children:[e.jsx(qt,{size:24,className:"spin"}),e.jsx("p",{style:{marginTop:"var(--space-md)"},children:"Loading handoff data..."})]}),f&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{marginBottom:"var(--space-lg)"},children:[e.jsx("h3",{style:{marginBottom:"var(--space-sm)"},children:"Mission Planning Handoff"}),e.jsx("div",{className:"card",style:{padding:"var(--space-md)"},children:e.jsx("pre",{style:{whiteSpace:"pre-wrap",fontSize:"12px",maxHeight:"200px",overflow:"auto"},children:JSON.stringify(f.mission,null,2)})})]}),e.jsxs("div",{style:{marginBottom:"var(--space-lg)"},children:[e.jsxs("h3",{style:{marginBottom:"var(--space-sm)"},children:["Feature Task Planning Handoffs (",f.features.length,")"]}),e.jsx("div",{className:"card",style:{padding:"var(--space-md)"},children:e.jsx("pre",{style:{whiteSpace:"pre-wrap",fontSize:"12px",maxHeight:"300px",overflow:"auto"},children:JSON.stringify(f.features,null,2)})})]})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("div",{className:"modal-actions-left",children:f&&e.jsxs("button",{className:"btn btn-sm",onClick:m,children:[e.jsx(Wt,{size:14,style:{marginRight:"var(--space-xs)"}}),"Copy to Clipboard"]})}),e.jsx("div",{className:"modal-actions-right",children:e.jsx("button",{className:"btn",onClick:n,children:"Close"})})]})]})}):null}function Qt({roadmap:l,isSelected:n,onSelect:v,onEdit:f,onDelete:_,onExport:j}){const S=C=>{C.key==="Enter"&&v()},m=C=>{C.stopPropagation(),f()},F=C=>{C.stopPropagation(),_()},E=C=>{C.stopPropagation(),j()};return e.jsxs("div",{className:`roadmaps-view__sidebar-item${n?" roadmaps-view__sidebar-item--active":""}`,onClick:v,onKeyDown:S,role:"button",tabIndex:0,"aria-selected":n,"data-testid":`roadmap-item-${l.id}`,children:[e.jsxs("div",{className:"roadmaps-view__sidebar-item-content",children:[e.jsx("div",{className:"roadmaps-view__sidebar-item-title",children:l.title}),l.description&&e.jsx("div",{className:"roadmaps-view__sidebar-item-desc",children:l.description})]}),e.jsxs("div",{className:"roadmaps-view__sidebar-item-actions",onClick:m,role:"presentation",children:[e.jsx("span",{className:"roadmaps-view__icon-btn",onClick:E,role:"button",title:"Export roadmap","aria-label":"Export roadmap","data-testid":`roadmap-export-${l.id}`,tabIndex:0,children:e.jsx(rt,{size:14})}),e.jsx("span",{className:"roadmaps-view__icon-btn",onClick:m,role:"button",title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":`roadmap-edit-${l.id}`,tabIndex:0,children:e.jsx(Fe,{size:14})}),e.jsx("span",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:F,role:"button",title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":`roadmap-delete-${l.id}`,tabIndex:0,children:e.jsx(Pe,{size:14})})]})]})}function Zt({roadmaps:l,selectedRoadmapId:n,onSelect:v,onCreate:f,onEdit:_,onDelete:j,onExport:S,showCreateForm:m,onCancelCreate:F,onSaveCreate:E}){return e.jsxs("div",{className:"roadmaps-view__mobile-list","data-testid":"roadmaps-view__mobile-list",children:[e.jsxs("div",{className:"roadmaps-view__mobile-list-header",children:[e.jsx("h2",{className:"roadmaps-view__mobile-list-title",children:"Roadmaps"}),!m&&e.jsx("button",{className:"roadmaps-view__mobile-add-btn",onClick:f,title:"Create roadmap","aria-label":"Create roadmap","data-testid":"mobile-create-roadmap-btn",children:e.jsx(Ae,{size:18})})]}),m&&e.jsx("div",{className:"roadmaps-view__mobile-create-form",children:e.jsx(mt,{onSave:E,onCancel:F})}),l.length===0&&!m?e.jsxs("div",{className:"roadmaps-view__mobile-empty",children:[e.jsx("p",{children:"No roadmaps yet."}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:f,children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Create Roadmap"})]})]}):e.jsx("div",{className:"roadmaps-view__mobile-list-items",children:l.map(C=>e.jsxs("div",{className:`roadmaps-view__mobile-item${C.id===n?" roadmaps-view__mobile-item--active":""}`,onClick:()=>v(C.id),role:"button",tabIndex:0,onKeyDown:y=>{y.key==="Enter"&&v(C.id)},"data-testid":`mobile-roadmap-item-${C.id}`,children:[e.jsxs("div",{className:"roadmaps-view__mobile-item-content",children:[e.jsx("span",{className:"roadmaps-view__mobile-item-title",children:C.title}),C.description&&e.jsx("span",{className:"roadmaps-view__mobile-item-desc",children:C.description})]}),e.jsxs("div",{className:"roadmaps-view__mobile-item-actions",children:[e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:y=>{y.stopPropagation(),S(C)},title:"Export roadmap","aria-label":"Export roadmap","data-testid":`mobile-roadmap-export-${C.id}`,children:e.jsx(rt,{size:16})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:y=>{y.stopPropagation(),_(C)},title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":`mobile-roadmap-edit-${C.id}`,children:e.jsx(Fe,{size:16})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn roadmaps-view__mobile-action-btn--danger",onClick:y=>{y.stopPropagation(),j(C.id)},title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":`mobile-roadmap-delete-${C.id}`,children:e.jsx(Pe,{size:16})})]})]},C.id))})]})}function ea({roadmapTitle:l,onBack:n,onEdit:v,onDelete:f,onCreate:_}){return e.jsxs("div",{className:"roadmaps-view__mobile-header","data-testid":"roadmaps-view__mobile-header",children:[e.jsx("button",{className:"roadmaps-view__mobile-back-btn",onClick:n,title:"Back to roadmap list","aria-label":"Back to roadmap list","data-testid":"mobile-back-btn",children:e.jsx(Kt,{size:20})}),e.jsx("h2",{className:"roadmaps-view__mobile-header-title",children:l}),e.jsxs("div",{className:"roadmaps-view__mobile-header-actions",children:[e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:_,title:"Create roadmap","aria-label":"Create roadmap","data-testid":"mobile-header-create-btn",children:e.jsx(Ae,{size:18})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:v,title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":"mobile-header-edit-btn",children:e.jsx(Fe,{size:18})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn roadmaps-view__mobile-action-btn--danger",onClick:f,title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":"mobile-header-delete-btn",children:e.jsx(Pe,{size:18})})]})]})}function ta({milestone:l,features:n,onEditMilestone:v,onDeleteMilestone:f,onAddFeature:_,onEditFeature:j,onDeleteFeature:S,milestoneEdit:m,onStartMilestoneEdit:F,onCancelMilestoneEdit:E,onSaveMilestoneEdit:C,featureEdit:y,onStartFeatureEdit:se,onCancelFeatureEdit:V,onSaveFeatureEdit:A,projectId:$,addToast:De,isMilestoneDragging:ne,isMilestoneDropTarget:fe,milestoneDropPosition:ie,onMilestoneDragStart:Be,onMilestoneDragEnd:oe,onMilestoneDragOver:be,onMilestoneDrop:G,onMilestoneDragLeave:B,isFeatureDragging:P,isFeatureDropTarget:X,featureDropIndex:H,onFeatureDragStart:Me,onFeatureDragEnd:le,onFeatureDragOver:Y,onFeatureDrop:ce,onFeatureDragLeave:Q,onFeatureDropOnMilestone:Re,featureSuggestions:D,isGeneratingFeatureSuggestions:Z,onGenerateFeatureSuggestions:He,onAcceptFeatureSuggestion:x,onAcceptAllFeatureSuggestions:de,onUpdateFeatureSuggestionDraft:ve,onClearFeatureSuggestions:R}){const xe=m?.milestoneId===l.id,q=h=>{h.key==="Enter"?(h.preventDefault(),m&&C({title:m.value})):h.key==="Escape"&&E()},N=h=>{h.key==="Escape"&&E()},Oe=["roadmaps-view__milestone",ne?"roadmaps-view__milestone--dragging":"",fe?"roadmaps-view__milestone--drop-target":"",fe&&ie==="before"?"roadmaps-view__milestone--drop-before":"",fe&&ie==="after"?"roadmaps-view__milestone--drop-after":""].filter(Boolean).join(" "),we=["roadmaps-view__feature-list",X?"roadmaps-view__feature-list--drop-target":""].filter(Boolean).join(" ");return e.jsxs("div",{className:Oe,draggable:!xe,onDragStart:h=>{xe||(Be(l.id),h.dataTransfer.setData("text/plain",`milestone:${l.id}`),h.dataTransfer.effectAllowed="move")},onDragEnd:oe,onDragOver:h=>{h.dataTransfer.types.includes("text/plain")&&h.dataTransfer.types.includes("text/plain")&&(h.preventDefault(),h.dataTransfer.dropEffect="move",be(l.id))},onDrop:h=>{h.preventDefault(),h.dataTransfer.getData("text/plain")?.startsWith("feature:")||G(l.id)},onDragLeave:B,"data-testid":`milestone-card-${l.id}`,children:[e.jsx("div",{className:"roadmaps-view__milestone-header",children:xe?e.jsxs("div",{className:"roadmaps-view__inline-edit",children:[e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`milestone-drag-handle-${l.id}`,children:e.jsx(Ye,{size:14})}),e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:m.value,onChange:()=>F(),onKeyDown:q,placeholder:"Milestone title",autoFocus:!0,"data-testid":`milestone-title-input-${l.id}`}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>C({title:m.value}),"aria-label":"Save milestone title",title:"Save",children:e.jsx(he,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:E,"aria-label":"Cancel editing",title:"Cancel",children:e.jsx(re,{size:14})})]}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:m.field==="description"?m.value:l.description||"",onChange:()=>{},onKeyDown:N,placeholder:"Milestone description (optional)",rows:2,"data-testid":`milestone-desc-input-${l.id}`})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"roadmaps-view__milestone-title-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`milestone-drag-handle-${l.id}`,children:e.jsx(Ye,{size:14})}),e.jsx("h3",{className:"roadmaps-view__milestone-title",children:l.title}),e.jsxs("div",{className:"roadmaps-view__milestone-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:v,title:"Edit milestone","aria-label":"Edit milestone","data-testid":`milestone-edit-${l.id}`,children:e.jsx(Fe,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:f,title:"Delete milestone","aria-label":"Delete milestone","data-testid":`milestone-delete-${l.id}`,children:e.jsx(Pe,{size:14})})]})]}),l.description&&e.jsx("p",{className:"roadmaps-view__milestone-desc",children:l.description})]})}),e.jsxs("div",{className:"roadmaps-view__milestone-actions-bar",children:[e.jsxs("button",{className:"roadmaps-view__add-feature-btn",onClick:_,title:"Add feature","aria-label":"Add feature","data-testid":`add-feature-${l.id}`,children:[e.jsx(Ae,{size:12}),e.jsx("span",{children:"Add Feature"})]}),e.jsxs("button",{className:"roadmaps-view__suggest-btn",onClick:()=>{He?.()},disabled:Z??!1,title:"Generate feature suggestions with AI","aria-label":"Generate feature suggestions","data-testid":`generate-features-${l.id}`,children:[e.jsx(pt,{size:12}),e.jsx("span",{children:Z?"Generating...":"AI Suggestions"})]})]}),e.jsxs("div",{className:we,onDragOver:h=>{h.preventDefault(),h.dataTransfer.dropEffect="move",h.dataTransfer.getData("text/plain")?.startsWith("feature:")&&Re()},onDrop:h=>{h.preventDefault();const I=h.dataTransfer.getData("text/plain");I?.startsWith("feature:")&&ce(I.split(":")[1],n.length)},onDragLeave:Q,children:[n.length===0?e.jsx("p",{className:"roadmaps-view__empty-features",children:"No features yet."}):n.map((h,I)=>{const je=y?.featureId===h.id,J=P(h.id),_e=M=>{M.key==="Enter"?(M.preventDefault(),y&&A({title:y.value})):M.key==="Escape"&&V()},Le=["roadmaps-view__feature-item",J?"roadmaps-view__feature-item--dragging":"",X&&H===I?"roadmaps-view__feature-item--drop-before":"",X&&H===I+1?"roadmaps-view__feature-item--drop-after":""].filter(Boolean).join(" ");return e.jsx("div",{className:Le,draggable:!je,onDragStart:M=>{je||(Me(h.id,l.id),M.dataTransfer.setData("text/plain",`feature:${h.id}`),M.dataTransfer.effectAllowed="move")},onDragEnd:le,onDragOver:M=>{if(M.preventDefault(),M.stopPropagation(),M.dataTransfer.dropEffect="move",M.dataTransfer.getData("text/plain")?.startsWith("feature:")){const O=M.currentTarget.getBoundingClientRect(),ee=O.top+O.height/2,te=M.clientY<ee?"before":"after";Y(h.id,te)}},onDrop:M=>{M.preventDefault(),M.stopPropagation();const ue=M.dataTransfer.getData("text/plain");if(ue?.startsWith("feature:")){const O=ue.split(":")[1],ee=M.currentTarget.getBoundingClientRect(),te=ee.top+ee.height/2,Ie=M.clientY<te?"before":"after";let pe=I;Ie==="after"&&(pe=I+1),ce(O,pe)}},onDragLeave:Q,"data-testid":`feature-item-${h.id}`,children:je?e.jsx("div",{className:"roadmaps-view__inline-edit roadmaps-view__inline-edit--compact",children:e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle roadmaps-view__drag-handle--feature",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`feature-drag-handle-${h.id}`,children:e.jsx(Ye,{size:12})}),e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:y.value,onChange:()=>{},onKeyDown:_e,placeholder:"Feature title",autoFocus:!0,"data-testid":`feature-title-input-${h.id}`}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>A({title:y.value}),"aria-label":"Save feature title",title:"Save",children:e.jsx(he,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:V,"aria-label":"Cancel editing",title:"Cancel",children:e.jsx(re,{size:14})})]})}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"roadmaps-view__drag-handle roadmaps-view__drag-handle--feature",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`feature-drag-handle-${h.id}`,children:e.jsx(Ye,{size:12})}),e.jsxs("div",{className:"roadmaps-view__feature-content",children:[e.jsx("span",{className:"roadmaps-view__feature-title",children:h.title}),h.description&&e.jsx("p",{className:"roadmaps-view__feature-desc",children:h.description})]}),e.jsxs("div",{className:"roadmaps-view__feature-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:()=>j(h.id),title:"Edit feature","aria-label":"Edit feature","data-testid":`feature-edit-${h.id}`,children:e.jsx(Fe,{size:12})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:()=>S(h.id),title:"Delete feature","aria-label":"Delete feature","data-testid":`feature-delete-${h.id}`,children:e.jsx(Pe,{size:12})})]})]})},h.id)}),D&&D.length>0&&e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsxs("div",{className:"roadmap-suggestion-header",children:[e.jsx("h4",{className:"roadmap-suggestion-title",children:"AI Feature Suggestions"}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-accept-all-btn",onClick:()=>de?.(),title:"Accept all suggestions","aria-label":"Accept all","data-testid":`accept-all-features-${l.id}`,children:"Accept All"}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:()=>R?.(),title:"Clear suggestions","aria-label":"Clear","data-testid":`clear-features-${l.id}`,children:"Clear"})]})]}),e.jsx("div",{className:"roadmap-suggestion-list",children:D.map(h=>e.jsx(aa,{suggestion:h,onUpdateDraft:I=>ve?.(l.id,h.id,I),onAccept:()=>{x?.(l.id,h.id)},testIdPrefix:`feature-suggestion-${l.id}`},h.id))})]})]})]})}function aa({suggestion:l,onUpdateDraft:n,onAccept:v,testIdPrefix:f}){const[_,j]=a.useState(!1),[S,m]=a.useState(l.title),[F,E]=a.useState(l.description||""),C=()=>{m(l.title),E(l.description||""),j(!0)},y=()=>{n({title:S.trim(),description:F.trim()||void 0}),j(!1)},se=()=>{m(l.title),E(l.description||""),j(!1)},V=()=>{l.title.trim()&&v()},A=l.title.trim().length>0;return _?e.jsx("div",{className:"roadmap-suggestion-card roadmap-suggestion-card--editing",children:e.jsxs("div",{className:"roadmap-suggestion-edit-form",children:[e.jsx("input",{type:"text",className:"roadmap-suggestion-input",value:S,onChange:$=>m($.target.value),placeholder:"Feature title",autoFocus:!0,"data-testid":`${f}-${l.id}-title-input`}),e.jsx("textarea",{className:"roadmap-suggestion-textarea",value:F,onChange:$=>E($.target.value),placeholder:"Description (optional)",rows:2,"data-testid":`${f}-${l.id}-desc-input`}),e.jsxs("div",{className:"roadmap-suggestion-edit-actions",children:[e.jsx("button",{className:"roadmap-suggestion-save-btn",onClick:y,disabled:!S.trim(),title:"Save","data-testid":`${f}-${l.id}-save`,children:e.jsx(he,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-cancel-btn",onClick:se,title:"Cancel","data-testid":`${f}-${l.id}-cancel`,children:e.jsx(re,{size:12})})]})]})}):e.jsxs("div",{className:"roadmap-suggestion-card","data-testid":`${f}-${l.id}`,children:[e.jsxs("div",{className:"roadmap-suggestion-content",children:[e.jsx("span",{className:"roadmap-suggestion-card-title",children:l.title}),l.description&&e.jsx("p",{className:"roadmap-suggestion-card-desc",children:l.description})]}),e.jsxs("div",{className:"roadmap-suggestion-card-actions",children:[e.jsx("button",{className:"roadmap-suggestion-edit-btn",onClick:C,title:"Edit suggestion","aria-label":"Edit","data-testid":`${f}-${l.id}-edit`,children:e.jsx(Fe,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-accept-btn",onClick:V,disabled:!A,title:"Accept this suggestion","aria-label":"Accept","data-testid":`${f}-${l.id}-accept`,children:e.jsx(he,{size:12})})]})]})}function ut({suggestion:l,onUpdateDraft:n,onAccept:v,testIdPrefix:f}){const[_,j]=a.useState(!1),[S,m]=a.useState(l.title),[F,E]=a.useState(l.description||""),C=()=>{m(l.title),E(l.description||""),j(!0)},y=()=>{n({title:S.trim(),description:F.trim()||void 0}),j(!1)},se=()=>{m(l.title),E(l.description||""),j(!1)},V=()=>{l.title.trim()&&v()},A=l.title.trim().length>0;return _?e.jsx("div",{className:"roadmap-suggestion-card roadmap-suggestion-card--editing",children:e.jsxs("div",{className:"roadmap-suggestion-edit-form",children:[e.jsx("input",{type:"text",className:"roadmap-suggestion-input",value:S,onChange:$=>m($.target.value),placeholder:"Milestone title",autoFocus:!0,"data-testid":`${f}-${l.id}-title-input`}),e.jsx("textarea",{className:"roadmap-suggestion-textarea",value:F,onChange:$=>E($.target.value),placeholder:"Description (optional)",rows:2,"data-testid":`${f}-${l.id}-desc-input`}),e.jsxs("div",{className:"roadmap-suggestion-edit-actions",children:[e.jsx("button",{className:"roadmap-suggestion-save-btn",onClick:y,disabled:!S.trim(),title:"Save","data-testid":`${f}-${l.id}-save`,children:e.jsx(he,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-cancel-btn",onClick:se,title:"Cancel","data-testid":`${f}-${l.id}-cancel`,children:e.jsx(re,{size:12})})]})]})}):e.jsxs("div",{className:"roadmap-suggestion-card","data-testid":`${f}-${l.id}`,children:[e.jsxs("div",{className:"roadmap-suggestion-content",children:[e.jsx("span",{className:"roadmap-suggestion-card-title",children:l.title}),l.description&&e.jsx("p",{className:"roadmap-suggestion-card-desc",children:l.description})]}),e.jsxs("div",{className:"roadmap-suggestion-card-actions",children:[e.jsx("button",{className:"roadmap-suggestion-edit-btn",onClick:C,title:"Edit suggestion","aria-label":"Edit","data-testid":`${f}-${l.id}-edit`,children:e.jsx(Fe,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-accept-btn",onClick:V,disabled:!A,title:"Accept this suggestion","aria-label":"Accept","data-testid":`${f}-${l.id}-accept`,children:e.jsx(he,{size:12})})]})]})}function mt({onSave:l,onCancel:n}){const[v,f]=a.useState(""),[_,j]=a.useState(""),S=m=>{m.preventDefault(),v.trim()&&l({title:v.trim(),description:_.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form","data-testid":"create-roadmap-form",children:e.jsxs("form",{onSubmit:S,children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:v,onChange:m=>f(m.target.value),placeholder:"Roadmap title",autoFocus:!0,"data-testid":"create-roadmap-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:_,onChange:m=>j(m.target.value),placeholder:"Roadmap description (optional)",rows:2,"data-testid":"create-roadmap-description"}),e.jsxs("div",{className:"roadmaps-view__create-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__btn roadmaps-view__btn--primary",disabled:!v.trim(),"data-testid":"create-roadmap-submit",children:"Create"}),e.jsx("button",{type:"button",className:"roadmaps-view__btn",onClick:n,"data-testid":"create-roadmap-cancel",children:"Cancel"})]})]})})}function ra({onSave:l,onCancel:n}){const[v,f]=a.useState(""),[_,j]=a.useState(""),S=m=>{m.preventDefault(),v.trim()&&l({title:v.trim(),description:_.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form roadmaps-view__create-form--inline","data-testid":"create-milestone-form",children:e.jsxs("form",{onSubmit:S,className:"roadmaps-view__inline-form",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:v,onChange:m=>f(m.target.value),placeholder:"Milestone title",autoFocus:!0,"data-testid":"create-milestone-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:_,onChange:m=>j(m.target.value),placeholder:"Description (optional)",rows:1,"data-testid":"create-milestone-description"}),e.jsxs("div",{className:"roadmaps-view__inline-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",disabled:!v.trim(),"aria-label":"Save milestone",title:"Save","data-testid":"create-milestone-submit",children:e.jsx(he,{size:14})}),e.jsx("button",{type:"button",className:"roadmaps-view__icon-btn",onClick:n,"aria-label":"Cancel",title:"Cancel","data-testid":"create-milestone-cancel",children:e.jsx(re,{size:14})})]})]})})}function sa({onSave:l,onCancel:n}){const[v,f]=a.useState(""),[_,j]=a.useState(""),S=m=>{m.preventDefault(),v.trim()&&l({title:v.trim(),description:_.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form roadmaps-view__create-form--inline","data-testid":"create-feature-form",children:e.jsxs("form",{onSubmit:S,className:"roadmaps-view__inline-form",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:v,onChange:m=>f(m.target.value),placeholder:"Feature title",autoFocus:!0,"data-testid":"create-feature-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:_,onChange:m=>j(m.target.value),placeholder:"Description (optional)",rows:1,"data-testid":"create-feature-description"}),e.jsxs("div",{className:"roadmaps-view__inline-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",disabled:!v.trim(),"aria-label":"Save feature",title:"Save","data-testid":"create-feature-submit",children:e.jsx(he,{size:14})}),e.jsx("button",{type:"button",className:"roadmaps-view__icon-btn",onClick:n,"aria-label":"Cancel",title:"Cancel","data-testid":"create-feature-cancel",children:e.jsx(re,{size:14})})]})]})})}function ca({projectId:l,addToast:n}){const{confirm:v}=Lt(),f=Vt()==="mobile",{roadmaps:_,selectedRoadmapId:j,selectedRoadmap:S,milestones:m,featuresByMilestoneId:F,loading:E,error:C,createRoadmap:y,updateRoadmap:se,deleteRoadmap:V,selectRoadmap:A,createMilestone:$,updateMilestone:De,deleteMilestone:ne,createFeature:fe,updateFeature:ie,deleteFeature:Be,reorderMilestones:oe,reorderFeatures:be,moveFeature:G,milestoneSuggestions:B,isGeneratingSuggestions:P,generateMilestoneSuggestions:X,updateMilestoneSuggestionDraft:H,acceptMilestoneSuggestion:Me,acceptAllMilestoneSuggestions:le,clearMilestoneSuggestions:Y,featureSuggestionsByMilestoneId:ce,isGeneratingFeatureSuggestions:Q,generateFeatureSuggestions:Re,updateFeatureSuggestionDraft:D,acceptFeatureSuggestion:Z,acceptAllFeatureSuggestions:He,clearFeatureSuggestions:x,handoffPayload:de,isFetchingHandoff:ve,handoffError:R,fetchHandoff:xe,clearHandoff:q}=Jt({projectId:l}),[N,Oe]=a.useState(!1),[we,h]=a.useState(null),[I,je]=a.useState(""),[J,_e]=a.useState(""),[Le,M]=a.useState(!1),ue=a.useRef(null);a.useEffect(()=>{ue.current!==null&&ue.current!==j&&M(!1),ue.current=j},[j]);const[O,ee]=a.useState({roadmapId:null,field:null,value:""}),[te,Ie]=a.useState({milestoneId:null,field:null,value:""}),[pe,Ue]=a.useState({featureId:null,field:null,value:""}),[me,U]=a.useState({type:null,parentId:void 0,title:"",description:""}),[qe,Te]=a.useState(!1),[Ce,Ge]=a.useState({draggingId:null,dropTargetId:null,dropPosition:null}),Je=a.useCallback(t=>{Ge(u=>({...u,draggingId:t}))},[]),ye=a.useCallback(()=>{Ge({draggingId:null,dropTargetId:null,dropPosition:null})},[]),Xe=a.useCallback(t=>{Ge(u=>u.draggingId===t?u:{...u,dropTargetId:t,dropPosition:null})},[]),[ge,$e]=a.useState({draggingId:null,draggingMilestoneId:null,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null}),Qe=a.useCallback((t,u)=>{$e(b=>({...b,draggingId:t,draggingMilestoneId:u}))},[]),r=a.useCallback(()=>{$e({draggingId:null,draggingMilestoneId:null,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null})},[]),c=a.useCallback((t,u)=>{$e(b=>{if(b.draggingId===t)return b;const L=(F[b.draggingMilestoneId||""]||[]).findIndex(Ee=>Ee.id===t);let W;return u==="before"?W=L:W=L+1,{...b,dropTargetMilestoneId:b.draggingMilestoneId,dropTargetIndex:W,dropPosition:u}})},[F]),i=a.useCallback(()=>{$e(t=>({...t,dropTargetMilestoneId:t.draggingMilestoneId,dropTargetIndex:(F[t.draggingMilestoneId||""]||[]).length}))},[F]),s=a.useCallback(async(t,u)=>{const{draggingMilestoneId:b,dropTargetMilestoneId:z}=ge;if(!b){r();return}const L=z||b,W=F[b]||[],Ee=W.find(ke=>ke.id===t);if(!Ee){r();return}if(b!==L){if(b===L){r();return}try{await G(t,L,u,{onError:ke=>{n(`Failed to move feature: ${ke.message}`,"error")}})}catch{}}else{const ke=[...W],Nt=ke.findIndex(ze=>ze.id===t);ke.splice(Nt,1),ke.splice(u,0,Ee);const dt=ke.map(ze=>ze.id),St=W.map(ze=>ze.id);if(dt.join(",")===St.join(",")){r();return}try{await be(b,dt,{onError:ze=>{n(`Failed to reorder features: ${ze.message}`,"error")}})}catch{}}r()},[ge,F,be,G,n,r]),d=a.useCallback(t=>{const u=t.currentTarget.getBoundingClientRect(),b=t.clientX,z=t.clientY;(b<u.left||b>u.right||z<u.top||z>u.bottom)&&$e(L=>({...L,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null}))},[]),o=a.useCallback(t=>ge.draggingId===t,[ge.draggingId]),g=a.useCallback(async t=>{const{draggingId:u}=Ce;if(!u||u===t){ye();return}const b=m.map(Ee=>Ee.id),z=b.indexOf(u),L=b.indexOf(t);if(z===-1||L===-1){ye();return}const W=[...b];if(W.splice(z,1),W.splice(L,0,u),W.join(",")===b.join(",")){ye();return}try{await oe(j,W,{onError:Ee=>{n(`Failed to reorder milestones: ${Ee.message}`,"error")}})}catch{}ye()},[Ce,m,j,oe,n,ye]),p=a.useCallback(t=>{const u=t.currentTarget.getBoundingClientRect(),b=t.clientX,z=t.clientY;(b<u.left||b>u.right||z<u.top||z>u.bottom)&&Ge(L=>({...L,dropTargetId:null,dropPosition:null}))},[]),w=a.useCallback(t=>{A(t.id),ee({roadmapId:t.id,field:"title",value:t.title})},[A]),T=a.useCallback(()=>{ee({roadmapId:null,field:null,value:""})},[]),Ne=a.useCallback(async t=>{if(O.roadmapId)try{await se(O.roadmapId,t,{onError:u=>n(u.message,"error")}),T()}catch{}},[O.roadmapId,se,T,n]),ae=a.useCallback(async t=>{if(await v({title:"Delete Roadmap",message:"Delete this roadmap? This cannot be undone.",danger:!0}))try{await V(t,{onError:b=>n(b.message,"error")}),n("Roadmap deleted","success")}catch{}},[V,n,v]),Ve=a.useCallback((t,u)=>{h(t),je(u),Oe(!0),q()},[q]),k=a.useCallback(()=>{Oe(!1),h(null),je(""),q()},[q]),K=a.useCallback(()=>{we&&xe(we,{onError:t=>n(`Failed to load handoff: ${t.message}`,"error")})},[we,xe,n]),Ke=a.useCallback(()=>{if(de){const t=JSON.stringify(de,null,2);navigator.clipboard.writeText(t).then(()=>{n("Handoff data copied to clipboard","success")}).catch(()=>{n("Failed to copy to clipboard","error")})}},[de,n]),We=a.useCallback(async t=>{try{await y(t,{onError:u=>n(u.message,"error")}),U({type:null,parentId:void 0,title:"",description:""}),n("Roadmap created","success")}catch{}},[y,n]),st=a.useCallback(t=>{Ie({milestoneId:t.id,field:"title",value:t.title})},[]),Ze=a.useCallback(()=>{Ie({milestoneId:null,field:null,value:""})},[]),gt=a.useCallback(async t=>{if(te.milestoneId)try{await De(te.milestoneId,t,{onError:u=>n(u.message,"error")}),Ze()}catch{}},[te.milestoneId,De,Ze,n]),ht=a.useCallback(async t=>{if(await v({title:"Delete Milestone",message:"Delete this milestone and all its features?",danger:!0}))try{await ne(t,{onError:b=>n(b.message,"error")}),n("Milestone deleted","success")}catch{}},[ne,n,v]),ft=a.useCallback(async t=>{try{await $(t,{onError:u=>n(u.message,"error")}),U({type:null,parentId:void 0,title:"",description:""}),n("Milestone created","success")}catch{}},[$,n]),nt=a.useCallback((t,u,b)=>{Ue({featureId:t,field:"title",value:u})},[]),et=a.useCallback(()=>{Ue({featureId:null,field:null,value:""})},[]),bt=a.useCallback(async t=>{if(pe.featureId)try{await ie(pe.featureId,t,{onError:u=>n(u.message,"error")}),et()}catch{}},[pe.featureId,ie,et,n]),vt=a.useCallback(async t=>{if(await v({title:"Delete Feature",message:"Delete this feature?",danger:!0}))try{await Be(t,{onError:b=>n(b.message,"error")}),n("Feature deleted","success")}catch{}},[Be,n,v]),it=a.useCallback(async()=>{if(J.trim())try{await X(J,5,{onError:t=>n(t.message,"error")})}catch{}},[J,X,n]),ot=a.useCallback(async t=>{try{await Me(t,{onError:u=>n(u.message,"error")}),n("Milestone added","success")}catch{}},[Me,n]),lt=a.useCallback(async()=>{try{await le({onError:t=>n(t.message,"error")}),n(`${B.length} milestones added`,"success"),_e("")}catch{}},[le,B.length,n]),ct=a.useCallback(()=>{Y(),_e("")},[Y]),xt=a.useCallback(async t=>{try{await Re(t,{count:5},{onError:u=>n(u.message,"error")})}catch{}},[Re,n]),wt=a.useCallback(async(t,u)=>{try{await Z(t,u,{onError:b=>n(b.message,"error")}),n("Feature added","success")}catch{}},[Z,n]),jt=a.useCallback((t,u,b)=>{D(t,u,b)},[D]),_t=a.useCallback(async t=>{const u=ce[t]||[];try{await He(t,{onError:b=>n(b.message,"error")}),n(`${u.length} features added`,"success")}catch{}},[He,ce,n]),Ct=a.useCallback(t=>{x(t)},[x]),yt=a.useCallback(async(t,u)=>{try{await fe(t,u,{onError:b=>n(b.message,"error")}),U({type:null,parentId:void 0,title:"",description:""}),n("Feature created","success")}catch{}},[fe,n]),Se=j;return E&&_.length===0?e.jsx("div",{className:"roadmaps-view roadmaps-view--loading",children:e.jsx("div",{className:"roadmaps-view__loading-state",children:"Loading roadmaps..."})}):C&&_.length===0?e.jsx("div",{className:"roadmaps-view roadmaps-view--error",children:e.jsxs("div",{className:"roadmaps-view__error-state",children:[e.jsx("p",{children:"Failed to load roadmaps"}),e.jsx("p",{className:"roadmaps-view__error-msg",children:C.message})]})}):e.jsxs("div",{className:"roadmaps-view",children:[f&&!Se&&e.jsx(Zt,{roadmaps:_,selectedRoadmapId:Se,onSelect:t=>A(t),onCreate:()=>Te(!0),onEdit:w,onDelete:ae,onExport:t=>Ve(t.id,t.title),showCreateForm:qe,onCancelCreate:()=>Te(!1),onSaveCreate:async t=>{await We(t),Te(!1)}}),!f&&e.jsxs("aside",{className:"roadmaps-view__sidebar","aria-label":"Roadmaps",children:[e.jsxs("div",{className:"roadmaps-view__sidebar-header",children:[e.jsx("h2",{className:"roadmaps-view__sidebar-title",children:"Roadmaps"}),e.jsx("button",{className:"roadmaps-view__add-btn",onClick:()=>U({type:"roadmap",title:"",description:""}),title:"Create roadmap","aria-label":"Create roadmap","data-testid":"create-roadmap-btn",children:e.jsx(Ae,{size:16})})]}),me.type==="roadmap"&&e.jsx(mt,{onSave:We,onCancel:()=>U({type:null,parentId:void 0,title:"",description:""})}),e.jsx("div",{className:"roadmaps-view__sidebar-list",children:_.length===0?e.jsx("p",{className:"roadmaps-view__empty-sidebar",children:"No roadmaps yet. Click + to create one."}):_.map(t=>e.jsx(Qt,{roadmap:t,isSelected:t.id===Se,onSelect:()=>A(t.id),onEdit:()=>w(t),onDelete:()=>ae(t.id),onExport:()=>Ve(t.id,t.title)},t.id))})]}),e.jsxs("main",{className:"roadmaps-view__main","aria-label":"Roadmap content",children:[f&&Se&&e.jsx(ea,{roadmapTitle:S?.title||"Untitled Roadmap",onBack:()=>A(null),onEdit:()=>{S&&w(S)},onDelete:()=>ae(Se),onCreate:()=>Te(!0)}),Se?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"roadmaps-view__roadmap-header",children:O.roadmapId===Se?e.jsx("div",{className:"roadmaps-view__inline-edit",children:e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input roadmaps-view__inline-input--large",value:O.value,onChange:t=>ee(u=>({...u,value:t.target.value})),onKeyDown:t=>{t.key==="Enter"?Ne({title:O.value}):t.key==="Escape"&&T()},placeholder:"Roadmap title",autoFocus:!0,"data-testid":"roadmap-title-input"}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>Ne({title:O.value}),"aria-label":"Save",title:"Save",children:e.jsx(he,{size:16})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:T,"aria-label":"Cancel",title:"Cancel",children:e.jsx(re,{size:16})})]})}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"roadmaps-view__roadmap-title-row",children:[e.jsx("h1",{className:"roadmaps-view__roadmap-title",children:S?.title||"Untitled Roadmap"}),e.jsxs("div",{className:"roadmaps-view__roadmap-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:()=>{S&&w(S)},title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":"edit-roadmap-btn",children:e.jsx(Fe,{size:16})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:()=>ae(Se),title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":"delete-roadmap-btn",children:e.jsx(Pe,{size:16})})]})]}),S?.description&&e.jsx("p",{className:"roadmaps-view__roadmap-desc",children:S.description})]})}),f?Le?e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsxs("div",{className:"roadmap-suggestion-header",children:[e.jsx("h3",{className:"roadmap-suggestion-title",children:"Generate Milestone Ideas"}),e.jsx("button",{className:"roadmap-suggestion-collapse-btn",onClick:()=>M(!1),"aria-label":"Collapse suggestion panel","data-testid":"collapse-suggestion-panel-btn",children:e.jsx(Ut,{size:16})})]}),e.jsxs("div",{className:"roadmap-suggestion-form",children:[e.jsx("textarea",{className:"roadmap-suggestion-input",value:J,onChange:t=>_e(t.target.value),placeholder:"Describe your roadmap goal (e.g., 'Build a user authentication system with OAuth, profiles, and admin dashboard')",rows:2,disabled:P||!j,"data-testid":"goal-prompt-input",autoFocus:!0}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-generate-btn",onClick:it,disabled:!J.trim()||P||!j,"data-testid":"generate-suggestions-btn",children:P?"Generating...":"Generate Milestones"}),B.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"roadmap-suggestion-accept-all-btn",onClick:lt,"data-testid":"accept-all-suggestions-btn",children:["Accept All (",B.length,")"]}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:ct,title:"Clear suggestions","aria-label":"Clear suggestions","data-testid":"clear-suggestions-btn",children:e.jsx(re,{size:14})})]})]})]}),B.length>0&&e.jsx("div",{className:"roadmap-suggestion-list",children:B.map(t=>e.jsx(ut,{suggestion:t,onUpdateDraft:u=>H(t.id,u),onAccept:()=>ot(t.id),testIdPrefix:"suggestion"},t.id))})]}):e.jsx("div",{className:"roadmap-suggestion-section",children:e.jsxs("button",{className:"roadmap-suggestion-expand-btn",onClick:()=>M(!0),disabled:!j,"data-testid":"expand-suggestion-panel-btn",children:[e.jsx(pt,{size:16}),"Generate Milestone Ideas"]})}):e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsx("div",{className:"roadmap-suggestion-header",children:e.jsx("h3",{className:"roadmap-suggestion-title",children:"Generate Milestone Ideas"})}),e.jsxs("div",{className:"roadmap-suggestion-form",children:[e.jsx("textarea",{className:"roadmap-suggestion-input",value:J,onChange:t=>_e(t.target.value),placeholder:"Describe your roadmap goal (e.g., 'Build a user authentication system with OAuth, profiles, and admin dashboard')",rows:2,disabled:P||!j,"data-testid":"goal-prompt-input"}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-generate-btn",onClick:it,disabled:!J.trim()||P||!j,"data-testid":"generate-suggestions-btn",children:P?"Generating...":"Generate Milestones"}),B.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"roadmap-suggestion-accept-all-btn",onClick:lt,"data-testid":"accept-all-suggestions-btn",children:["Accept All (",B.length,")"]}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:ct,title:"Clear suggestions","aria-label":"Clear suggestions","data-testid":"clear-suggestions-btn",children:e.jsx(re,{size:14})})]})]})]}),B.length>0&&e.jsx("div",{className:"roadmap-suggestion-list",children:B.map(t=>e.jsx(ut,{suggestion:t,onUpdateDraft:u=>H(t.id,u),onAccept:()=>ot(t.id),testIdPrefix:"suggestion"},t.id))})]}),e.jsxs("div",{className:"roadmaps-view__milestone-lanes",children:[me.type==="milestone"&&e.jsx(ra,{onSave:ft,onCancel:()=>U({type:null,parentId:void 0,title:"",description:""})}),m.length===0&&me.type!=="milestone"?e.jsxs("div",{className:"roadmaps-view__empty-milestones",children:[e.jsx("p",{children:"This roadmap has no milestones."}),e.jsxs("button",{className:"roadmaps-view__add-milestone-btn",onClick:()=>U({type:"milestone",title:"",description:""}),"data-testid":"add-milestone-btn-empty",children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Add Milestone"})]})]}):e.jsxs(e.Fragment,{children:[me.type!=="milestone"&&e.jsxs("button",{className:"roadmaps-view__add-milestone-fab",onClick:()=>U({type:"milestone",title:"",description:""}),"data-testid":"add-milestone-btn",children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Add Milestone"})]}),m.map(t=>e.jsx(ta,{milestone:t,features:F[t.id]||[],onEditMilestone:()=>st(t),onDeleteMilestone:()=>ht(t.id),onAddFeature:()=>U({type:"feature",parentId:t.id,title:"",description:""}),onEditFeature:u=>{const b=F[t.id]?.find(z=>z.id===u);b&&nt(u,b.title,b.description)},onDeleteFeature:vt,milestoneEdit:te,onStartMilestoneEdit:()=>st(t),onCancelMilestoneEdit:Ze,onSaveMilestoneEdit:gt,featureEdit:pe,onStartFeatureEdit:nt,onCancelFeatureEdit:et,onSaveFeatureEdit:bt,projectId:l,addToast:n,isMilestoneDragging:Ce.draggingId===t.id,isMilestoneDropTarget:Ce.dropTargetId===t.id,milestoneDropPosition:Ce.dropTargetId===t.id?Ce.dropPosition:null,onMilestoneDragStart:Je,onMilestoneDragEnd:ye,onMilestoneDragOver:Xe,onMilestoneDrop:g,onMilestoneDragLeave:p,isFeatureDragging:o,isFeatureDropTarget:ge.dropTargetMilestoneId===t.id,featureDropIndex:ge.dropTargetMilestoneId===t.id?ge.dropTargetIndex:null,onFeatureDragStart:Qe,onFeatureDragEnd:r,onFeatureDragOver:c,onFeatureDrop:s,onFeatureDragLeave:d,onFeatureDropOnMilestone:i,featureSuggestions:ce[t.id],isGeneratingFeatureSuggestions:Q(t.id),onGenerateFeatureSuggestions:()=>xt(t.id),onAcceptFeatureSuggestion:u=>wt(t.id,u),onAcceptAllFeatureSuggestions:()=>_t(t.id),onUpdateFeatureSuggestionDraft:(u,b,z)=>jt(u,b,z),onClearFeatureSuggestions:()=>Ct(t.id)},t.id))]})]})]}):e.jsx("div",{className:"roadmaps-view__empty-main",children:e.jsx("p",{children:"Select a roadmap from the sidebar to view its milestones."})})]}),me.type==="feature"&&me.parentId&&e.jsx("div",{className:"roadmaps-view__feature-create-overlay",children:e.jsx(sa,{onSave:t=>yt(me.parentId,t),onCancel:()=>U({type:null,parentId:void 0,title:"",description:""})})}),e.jsx(Xt,{isOpen:N,onClose:k,roadmapId:we||"",roadmapTitle:I,handoffPayload:de,isLoading:ve,error:R,onFetchHandoff:K,onCopyToClipboard:Ke})]})}export{ca as RoadmapsView};
@@ -0,0 +1 @@
1
+ .settings-header-actions{display:flex;align-items:stretch;gap:var(--space-xs);margin-left:auto;margin-right:var(--space-sm)}.settings-header-actions>.settings-github-star-btn,.settings-header-actions>.btn{height:26px;box-sizing:border-box}.settings-github-star-btn{display:inline-flex;align-items:stretch;border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-pill);background:var(--card);color:var(--text);font-size:12px;font-weight:500;text-decoration:none;overflow:hidden;transition:border-color var(--transition-fast),background var(--transition-fast)}.settings-github-star-btn:hover{border-color:var(--text-muted);background:var(--card-hover)}.settings-github-star-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);border-color:var(--todo)}.settings-github-star-btn__action{display:inline-flex;align-items:center;gap:5px;padding:4px 10px}.settings-github-star-btn__count{display:inline-flex;align-items:center;padding:4px 9px;border-left:var(--btn-border-width) solid var(--border);background:color-mix(in srgb,var(--surface) 60%,var(--card));color:var(--text-muted);font-variant-numeric:tabular-nums}.settings-modal{width:min(95vw,1100px);max-width:95vw;min-width:520px;height:80vh;min-height:480px;max-height:calc(100dvh - var(--overlay-padding-top, 10vh) - 16px);overflow:hidden;resize:both}@media(max-width:768px){.modal-overlay:has(.settings-modal){padding-top:0;align-items:stretch;justify-content:stretch}.modal.settings-modal{width:100vw;min-width:0;max-width:100vw;height:100dvh;min-height:0;max-height:100dvh;margin:0;border:none;border-radius:0;resize:none}}.settings-modal-heading{display:flex;flex-direction:column;gap:var(--space-xs)}.settings-modal-heading h3{margin:0}.settings-modal-version{margin:0;font-size:.85rem;color:var(--text-muted);font-weight:500}.settings-update-check{display:flex;align-items:center;gap:var(--space-sm)}.settings-update-btn{border-radius:var(--radius-sm)}.settings-update-btn svg.spinning{animation:settings-update-spin 1s linear infinite}.settings-update-result{font-size:.85rem;font-weight:500}.settings-update-result--up-to-date{color:var(--color-success)}.settings-update-result--available{color:var(--color-info)}.settings-update-result--error{color:var(--text-muted)}@keyframes settings-update-spin{to{transform:rotate(360deg)}}.settings-layout{display:flex;flex:1;flex-direction:row;min-height:0;overflow:hidden}.settings-mobile-section-picker{display:none}.settings-sidebar{width:170px;min-width:170px;border-right:1px solid var(--border);display:flex;flex-direction:column;overflow-y:auto;padding:10px 8px;gap:2px;background:#0000001a;scrollbar-color:var(--border) transparent;scrollbar-width:thin}.settings-sidebar::-webkit-scrollbar{width:6px}.settings-sidebar::-webkit-scrollbar-track{background:transparent}.settings-sidebar::-webkit-scrollbar-thumb{background:var(--border);border-radius:var(--radius-sm)}.settings-sidebar::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.settings-nav-item{display:block;width:100%;padding:var(--space-sm) var(--space-md);font-size:13px;font-weight:500;color:var(--text-muted);background:none;border:none;border-left:3px solid transparent;border-radius:0 var(--radius) var(--radius) 0;cursor:pointer;text-align:left;transition:background var(--transition-fast),color var(--transition-fast),border-color var(--transition-fast)}.settings-nav-item:hover{background:var(--bg);color:var(--text);border-left-color:var(--border)}.settings-nav-item:focus-visible{box-shadow:var(--focus-ring-strong);outline:none}.settings-nav-item.active{background:var(--bg);color:var(--todo);font-weight:600;border-left-color:var(--todo)}.settings-group-header{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);padding:var(--space-md) var(--space-md) var(--space-xs);margin-top:var(--space-sm);user-select:none}.settings-group-header:first-child{margin-top:0}.settings-content{flex:1;overflow-x:hidden;overflow-y:auto;padding:4px 0 12px;scrollbar-color:var(--border) transparent;scrollbar-width:thin}.settings-content::-webkit-scrollbar{width:6px}.settings-content::-webkit-scrollbar-track{background:transparent}.settings-content::-webkit-scrollbar-thumb{background:var(--border);border-radius:var(--radius-sm)}.settings-content::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.settings-content>*{animation:settingsFadeIn var(--transition-normal)}@keyframes settingsFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.settings-section-heading{font-size:14px;font-weight:600;padding:var(--space-lg) var(--space-xl) var(--space-md);margin:0 var(--space-xl) 0;color:var(--text);border-bottom:1px solid var(--border);margin-bottom:var(--space-xs)}.settings-section-heading--spaced{margin-top:var(--space-xl)}.settings-plugins-subsection-toggle{display:inline-flex;gap:var(--space-xs);padding:0 var(--space-xl);margin:var(--space-md) 0}.settings-plugins-subsection-btn{display:inline-flex;align-items:center;justify-content:center;border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-pill);background:var(--surface);color:var(--text-muted);font-size:.85rem;font-weight:600;padding:var(--space-xs) var(--space-md);cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast),border-color var(--transition-fast),box-shadow var(--transition-fast)}.settings-plugins-subsection-btn:hover{background:var(--surface-hover);color:var(--text)}.settings-plugins-subsection-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.settings-plugins-subsection-btn.active{background:color-mix(in srgb,var(--todo) 14%,transparent);border-color:color-mix(in srgb,var(--todo) 45%,var(--border));color:var(--todo)}.settings-plugins-subsection-panel{padding-bottom:var(--space-md)}.settings-scope-icon{margin-right:6px;display:inline-flex;vertical-align:middle;color:var(--text-muted)}.settings-scope-banner{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-xl);margin:0 var(--space-xl) var(--space-xs);font-size:12px;border-radius:var(--radius);color:var(--text-muted)}.settings-scope-global{background:color-mix(in srgb,var(--color-info) 8%,transparent);border-left:3px solid color-mix(in srgb,var(--color-info) 40%,transparent)}.settings-scope-project{background:color-mix(in srgb,var(--color-success) 8%,transparent);border-left:3px solid color-mix(in srgb,var(--color-success) 40%,transparent)}.settings-scope-mixed{background:color-mix(in srgb,var(--triage) 8%,transparent);border-left:3px solid color-mix(in srgb,var(--triage) 40%,transparent)}.settings-note{display:block;padding:0 var(--space-xl);margin-top:var(--space-xs);font-size:12px;color:var(--text-muted)}.settings-overlap-ignore-group code{font-family:var(--font-mono);font-size:.9em}.settings-button-row{display:flex;flex-wrap:wrap;gap:var(--space-sm);margin-top:var(--space-sm)}.settings-raw-output{margin:var(--space-sm) 0 0;padding:var(--space-sm);border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);color:var(--text-muted);max-height:calc(var(--space-2xl) * 7);overflow:auto;font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs))}.settings-url-output{display:block;margin-top:var(--space-xs);padding:var(--space-sm);border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);color:var(--text-muted);font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));overflow-wrap:anywhere;word-break:break-word;overflow-x:auto;max-width:100%}.settings-qr-preview{margin-top:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-sm)}.settings-qr-preview-label{margin:0;font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.settings-qr-preview-image-wrap{width:fit-content;max-width:100%;padding:var(--space-sm);border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--card)}.settings-qr-preview-image{display:block;width:min(calc(var(--space-2xl) * 6),100%);height:auto;aspect-ratio:1 / 1}.settings-overlap-ignore-list{display:flex;flex-direction:column;gap:var(--space-sm);margin:var(--space-sm) 0}.settings-overlap-ignore-row,.settings-overlap-ignore-path-controls{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--space-sm);align-items:center}.settings-overlap-path-picker-modal{max-width:min(960px,calc(100vw - var(--space-2xl)))}.settings-overlap-path-picker-body{display:flex;flex-direction:column;gap:var(--space-sm);max-height:min(70vh,720px)}.settings-overlap-path-picker-note{margin:0;font-size:12px;color:var(--text-muted)}.settings-section-divider{border-top:1px solid var(--border);margin:var(--space-lg) var(--space-xl)}@media(max-width:768px){.settings-note{padding:0 var(--space-lg)}.settings-overlap-ignore-row,.settings-overlap-ignore-path-controls{grid-template-columns:minmax(0,1fr)}.settings-overlap-ignore-row>.btn{justify-self:start}.settings-overlap-path-picker-modal{max-width:calc(100vw - var(--space-md))}}.ntfy-advanced-disclosure{margin-top:var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--surface)}.ntfy-advanced-disclosure>summary{cursor:pointer;list-style:none;padding:var(--space-sm) var(--space-md);font-size:12px;font-weight:600;color:var(--text)}.ntfy-advanced-disclosure>summary::-webkit-details-marker{display:none}.ntfy-advanced-content{padding:0 var(--space-md) var(--space-md);display:flex;flex-direction:column;gap:var(--space-sm)}.settings-inline-link{color:var(--todo);text-decoration:none;transition:text-decoration var(--transition-fast)}.settings-inline-link:hover{text-decoration:underline}.settings-inline-link:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);border-radius:var(--radius-sm)}.memory-status-message{display:flex;gap:var(--space-md);align-items:center;justify-content:space-between;margin-bottom:var(--space-md)}.memory-status-message span{min-width:0}.memory-retrieval-test{margin-top:var(--space-lg)}.memory-test-result{margin:0 var(--space-xl) var(--space-lg);padding:var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--card)}.memory-test-result strong,.memory-test-result span{color:var(--text);font-size:12px}.memory-test-result small{display:block;margin-top:var(--space-xs);color:var(--text-muted);font-size:12px}.memory-test-result ul{margin:var(--space-md) 0 0;padding:0;list-style:none}.memory-test-result li{padding-top:var(--space-sm);border-top:var(--btn-border-width) solid var(--border)}.memory-test-result li+li{margin-top:var(--space-sm)}.memory-test-result p{margin:var(--space-xs) 0 0;color:var(--text-muted);font-size:12px;line-height:1.5;overflow-wrap:anywhere}.memory-editor-section{margin-top:var(--space-lg)}.memory-file-summary{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--space-xs) var(--space-md);align-items:center;margin:0 var(--space-xl) var(--space-md);padding:var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--card)}.memory-file-summary span{display:inline-flex;align-items:center;justify-content:center;padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);color:var(--color-info);background:color-mix(in srgb,var(--color-info) 12%,transparent);font-size:11px;font-weight:600}.memory-file-summary strong{min-width:0;overflow-wrap:anywhere;color:var(--text);font-family:var(--font-mono);font-size:12px}.memory-file-summary small{grid-column:2;color:var(--text-muted);font-size:12px}.memory-editor-frame{min-height:50vh;border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);overflow:hidden;display:flex;flex-direction:column}.auth-panel-body{padding-inline:var(--space-md)}.auth-section-hint{padding:12px 16px;margin-bottom:12px;background:var(--bg-tertiary);border-radius:var(--radius);font-size:13px;color:var(--text-muted);border-left:3px solid var(--text-muted)}.auth-provider-group{margin-bottom:10px}.auth-group-label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--text-muted);margin-bottom:4px;padding:0 4px}.auth-provider-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);margin-bottom:4px;overflow:hidden;transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.auth-provider-card:hover{border-color:var(--text-dim)}.auth-provider-card--authenticated{border-color:color-mix(in srgb,var(--color-success) 40%,var(--border));background:color-mix(in srgb,var(--color-success) 5%,var(--surface))}.auth-provider-card--authenticated:hover{border-color:color-mix(in srgb,var(--color-success) 60%,var(--border))}.auth-provider-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;gap:12px}.auth-provider-info{display:flex;align-items:center;gap:10px;flex-wrap:wrap;flex:1;min-width:0}.auth-provider-info strong{font-weight:500;color:var(--text)}.auth-provider-icon-slot{display:inline-flex;align-items:center;justify-content:center;inline-size:calc(var(--space-md) + var(--space-xs) * 2);block-size:calc(var(--space-md) + var(--space-xs) * 2);flex-shrink:0}.auth-provider-icon-slot .provider-icon{display:inline-flex}.auth-hint{display:block;padding:12px 4px 0;font-size:12px;color:var(--text-muted);border-top:1px solid var(--border);margin-top:8px}.auth-apikey-section{display:flex;flex-direction:column;gap:4px;align-items:flex-end;flex-shrink:0}.auth-apikey-input-row{display:flex;gap:6px;align-items:center}.auth-apikey-input{background:var(--bg-input);border:1px solid var(--border);border-radius:6px;color:var(--text);padding:6px 10px;font-size:13px;width:180px;font-family:monospace}.auth-apikey-input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px #6366f133}.auth-apikey-input:disabled{opacity:.6}.auth-apikey-progress{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted);padding-right:4px}.auth-apikey-error{font-size:11px;color:var(--color-error);padding-right:4px}.auth-key-hint{font-family:var(--font-mono);font-size:12px;color:var(--text-muted);display:inline-block;margin-top:var(--space-xs);user-select:none}.settings-lane-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:500;white-space:nowrap}.settings-lane-badge--override{background-color:color-mix(in srgb,var(--color-accent) 20%,transparent);color:var(--color-accent)}.settings-lane-badge--inherited{background-color:color-mix(in srgb,var(--color-text-muted) 15%,transparent);color:var(--text-muted)}.settings-description{font-size:13px;color:var(--text-secondary);padding-inline:var(--space-xl);margin-block:0 var(--space-md);line-height:1.5}.settings-model-presets{display:flex;flex-direction:column;gap:var(--space-md)}.settings-preset-list{display:flex;flex-direction:column;gap:var(--space-sm)}.settings-preset-item{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-md);padding:var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--card)}.settings-preset-item-meta{display:flex;flex-direction:column;gap:var(--space-xs);min-width:0}.settings-preset-item-meta strong{color:var(--text);overflow-wrap:anywhere}.settings-preset-summary{font-size:12px;overflow-wrap:anywhere}.settings-preset-item-actions{display:flex;gap:var(--space-xs);flex-wrap:wrap;justify-content:flex-end}.settings-preset-actions{display:flex;justify-content:flex-start}.settings-preset-editor{display:flex;flex-direction:column;gap:var(--space-md);padding:var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:color-mix(in srgb,var(--surface) 85%,var(--card))}.settings-preset-editor-fields{display:flex;flex-direction:column;gap:var(--space-sm)}.settings-preset-editor .form-group{padding:0}.settings-preset-editor-actions{justify-content:flex-start;margin-top:0;padding:0}.settings-preset-auto-select{margin-top:var(--space-sm)}.settings-preset-size-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-sm)}.settings-preset-size-row{padding:0}@media(max-width:768px){.settings-update-check{flex-wrap:wrap;row-gap:var(--space-xs)}.settings-layout{flex-direction:column;min-height:0}.settings-mobile-section-picker{display:flex;flex-direction:column;gap:var(--space-xs);padding:var(--space-md) var(--space-lg);border-bottom:var(--btn-border-width) solid var(--border);background:var(--surface)}.settings-mobile-section-picker label{color:var(--text-muted);font-weight:600;text-transform:uppercase}.settings-mobile-section-picker select{width:100%}.settings-mobile-section-picker select:focus-visible{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.settings-sidebar{display:none}.settings-nav-item{display:flex;align-items:center;justify-content:center;gap:4px;border-left:none;border-bottom:2px solid transparent;border-radius:var(--radius) var(--radius) 0 0;padding:6px 12px;white-space:nowrap}.settings-nav-item:hover{border-left-color:transparent;border-bottom-color:var(--border)}.settings-nav-item.active{border-left-color:transparent;border-bottom-color:var(--todo)}.settings-group-header{display:none}.settings-scope-icon{margin-right:0}.settings-content{flex:1;min-height:0;overflow-x:hidden;overflow-y:auto}.settings-content .form-group small{overflow-wrap:break-word;word-break:break-all}.settings-content input,.settings-content select,.settings-content textarea{font-size:16px}.settings-section-heading{padding:var(--space-lg) var(--space-lg) var(--space-md);margin:0 var(--space-lg) 0}.settings-plugins-subsection-toggle{display:flex;width:100%;padding:0 var(--space-lg)}.settings-plugins-subsection-btn{flex:1;min-height:36px}.settings-plugins-subsection-panel{padding-left:var(--space-lg);padding-right:var(--space-lg)}.form-group{padding:0 14px}.settings-scope-banner{padding:var(--space-sm) var(--space-lg)}.memory-editor-frame{min-height:45vh}.memory-file-summary{grid-template-columns:1fr;margin:0 var(--space-lg) var(--space-md)}.memory-status-message{align-items:stretch;flex-direction:column}.memory-file-summary span{justify-content:flex-start}.memory-file-summary small{grid-column:auto}.settings-description{padding:0 var(--space-lg)}.settings-content .btn,.settings-preset-item-actions .btn{min-height:36px}.auth-provider-row{flex-wrap:wrap;padding:12px 14px;gap:var(--space-sm)}.auth-section-hint{margin:0 14px 12px;padding:10px 14px}.auth-provider-group{margin-bottom:12px}.auth-group-label{padding:0 14px}.auth-provider-card{margin:0 14px 8px}.auth-provider-header{flex-wrap:wrap;padding:10px 14px;gap:10px}.auth-provider-header>div:not(.auth-provider-info):not(.auth-apikey-section){margin-left:auto}.auth-provider-info{width:100%;flex-basis:100%}.auth-apikey-section{width:100%;flex-basis:100%;align-items:flex-end}.auth-apikey-input-row{width:100%;flex-wrap:wrap;justify-content:flex-end}.auth-apikey-input{flex:1;min-width:120px;width:auto}.auth-apikey-input-row .btn{flex-shrink:0;margin-left:auto}.auth-hint{padding:12px 14px 0}.settings-model-presets{gap:var(--space-sm)}.settings-preset-item{flex-direction:column;align-items:stretch;padding:var(--space-sm) var(--space-md)}.settings-preset-item-actions{justify-content:flex-start}.settings-preset-editor{padding:var(--space-sm) var(--space-md)}.settings-preset-editor-actions{flex-wrap:wrap}.settings-preset-size-grid{grid-template-columns:1fr;gap:var(--space-xs)}}
@@ -1 +1 @@
1
- import{r as e}from"./vendor-react-K0fH_qHe.js";import{cr as C}from"./index-BRTEq_-7.js";function L(k={}){const{projectId:d,pollInterval:b=6e4,autoRefresh:p=!1,enabled:t=!0}=k,[S,o]=e.useState(null),[m,l]=e.useState(t),[E,c]=e.useState(null),[R,v]=e.useState(null),r=e.useRef(null),n=e.useRef(null),a=e.useRef(!0),s=e.useCallback(async()=>{if(!t){l(!1),c(null),o(null);return}r.current&&r.current.abort(),r.current=new AbortController,l(!0),c(null),o(null);try{const u=await C(d);if(!a.current)return;o(u),c(null),v(new Date),l(!1)}catch(u){if(u instanceof Error&&u.name==="AbortError"||!a.current)return;const A=u instanceof Error?u.message:"Failed to fetch memory backend status";c(A),l(!1)}},[t,d]);e.useEffect(()=>(a.current=!0,t?(s(),()=>{a.current=!1}):(r.current&&r.current.abort(),o(null),c(null),l(!1),()=>{a.current=!1})),[t,s]),e.useEffect(()=>{if(!(!t||!p))return n.current=setInterval(()=>{s()},b),()=>{n.current&&(clearInterval(n.current),n.current=null)}},[t,p,b,s]),e.useEffect(()=>()=>{a.current=!1,r.current&&r.current.abort(),n.current&&(clearInterval(n.current),n.current=null)},[]);const h=e.useCallback(()=>s(),[s]),f=m?null:S,B=f?.currentBackend??null,i=f?.capabilities??null,y=f?.availableBackends??[],I=i?.readable??!1,g=i?.writable??!1,w=i?.supportsAtomicWrite??!1;return{status:f,currentBackend:B,capabilities:i,availableBackends:y,isReadable:I,isWritable:g,supportsAtomicWrite:w,loading:m,error:E,lastUpdated:R,refresh:h}}export{L as u};
1
+ import{r as e}from"./vendor-react-K0fH_qHe.js";import{cN as C}from"./index-DJDWSrju.js";function L(k={}){const{projectId:d,pollInterval:b=6e4,autoRefresh:p=!1,enabled:t=!0}=k,[S,o]=e.useState(null),[m,l]=e.useState(t),[E,c]=e.useState(null),[R,v]=e.useState(null),r=e.useRef(null),n=e.useRef(null),a=e.useRef(!0),s=e.useCallback(async()=>{if(!t){l(!1),c(null),o(null);return}r.current&&r.current.abort(),r.current=new AbortController,l(!0),c(null),o(null);try{const u=await C(d);if(!a.current)return;o(u),c(null),v(new Date),l(!1)}catch(u){if(u instanceof Error&&u.name==="AbortError"||!a.current)return;const A=u instanceof Error?u.message:"Failed to fetch memory backend status";c(A),l(!1)}},[t,d]);e.useEffect(()=>(a.current=!0,t?(s(),()=>{a.current=!1}):(r.current&&r.current.abort(),o(null),c(null),l(!1),()=>{a.current=!1})),[t,s]),e.useEffect(()=>{if(!(!t||!p))return n.current=setInterval(()=>{s()},b),()=>{n.current&&(clearInterval(n.current),n.current=null)}},[t,p,b,s]),e.useEffect(()=>()=>{a.current=!1,r.current&&r.current.abort(),n.current&&(clearInterval(n.current),n.current=null)},[]);const h=e.useCallback(()=>s(),[s]),f=m?null:S,B=f?.currentBackend??null,i=f?.capabilities??null,y=f?.availableBackends??[],I=i?.readable??!1,g=i?.writable??!1,w=i?.supportsAtomicWrite??!1;return{status:f,currentBackend:B,capabilities:i,availableBackends:y,isReadable:I,isWritable:g,supportsAtomicWrite:w,loading:m,error:E,lastUpdated:R,refresh:h}}export{L as u};