@runfusion/fusion 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/dist/bin.js +26610 -20597
  2. package/dist/client/assets/AgentDetailView-BwJaLqZh.css +1 -0
  3. package/dist/client/assets/AgentDetailView-gy_5SUj2.js +18 -0
  4. package/dist/client/assets/AgentsView-BkB9FiMT.js +29 -0
  5. package/dist/client/assets/{AgentsView-DSGQWObq.css → AgentsView-CV3vm7Qk.css} +1 -1
  6. package/dist/client/assets/ChatView-B_-B8fqu.js +1 -0
  7. package/dist/client/assets/ChatView-DwJAd5G1.css +1 -0
  8. package/dist/client/assets/{DevServerView-C9lzHrcT.js → DevServerView-BkvtjZBa.js} +1 -1
  9. package/dist/client/assets/{DirectoryPicker-aVdFaV37.js → DirectoryPicker-BK-KbnhP.js} +1 -1
  10. package/dist/client/assets/{DocumentsView-DIpg3NSP.js → DocumentsView-BEg1CQAk.js} +1 -1
  11. package/dist/client/assets/{DocumentsView-BrhyOdeE.css → DocumentsView-gv4zG3aT.css} +1 -1
  12. package/dist/client/assets/EvalsView-Berf9bQm.js +1 -0
  13. package/dist/client/assets/EvalsView-CUNJ1TLc.css +1 -0
  14. package/dist/client/assets/{agentSkills-DDHJnrkn.css → ExperimentalAgentOnboardingModal-B-APN_lM.css} +1 -1
  15. package/dist/client/assets/ExperimentalAgentOnboardingModal-jcInE50G.js +499 -0
  16. package/dist/client/assets/InsightsView-B0J4mhzV.css +1 -0
  17. package/dist/client/assets/InsightsView-BX5bSF1J.js +11 -0
  18. package/dist/client/assets/{MemoryView-nXlTqebk.js → MemoryView-CKElJY_3.js} +2 -2
  19. package/dist/client/assets/NodesView-DLUOBLf6.js +14 -0
  20. package/dist/client/assets/NodesView-DT4pXowv.css +1 -0
  21. package/dist/client/assets/{PiExtensionsManager-Buopv-jb.js → PiExtensionsManager-COlJf0Kx.js} +2 -2
  22. package/dist/client/assets/PluginManager-CfW55BF4.js +1 -0
  23. package/dist/client/assets/PluginManager-DtRQXia5.css +1 -0
  24. package/dist/client/assets/{ResearchView-_BHXUv2j.js → ResearchView-B256Lr8I.js} +1 -1
  25. package/dist/client/assets/SettingsModal-BeA_nQtW.js +31 -0
  26. package/dist/client/assets/SettingsModal-DzsLquBu.css +1 -0
  27. package/dist/client/assets/{SettingsModal-C89Ikhfm.js → SettingsModal-yRqM4DV8.js} +1 -1
  28. package/dist/client/assets/SetupWizardModal-uUZk3TKT.js +1 -0
  29. package/dist/client/assets/{SkillsView-hDpTBdFT.js → SkillsView-CP8JX0P_.js} +1 -1
  30. package/dist/client/assets/TodoView-Cx9cVhq7.css +1 -0
  31. package/dist/client/assets/TodoView-DCRIkDZ-.js +6 -0
  32. package/dist/client/assets/createLucideIcon-BazL2hk5.js +21 -0
  33. package/dist/client/assets/dashboard-view-BkTMSZYn.css +1 -0
  34. package/dist/client/assets/dashboard-view-CyWN-d02.js +63 -0
  35. package/dist/client/assets/dashboard-view-lR7YYmSC.js +21 -0
  36. package/dist/client/assets/{folder-open-usZkXdq2.js → folder-open-DHjELt8-.js} +1 -1
  37. package/dist/client/assets/index-CQyVRLOb.js +692 -0
  38. package/dist/client/assets/index-CxA2Nn0_.css +1 -0
  39. package/dist/client/assets/projectDetection-G3XuxD2X.js +1 -0
  40. package/dist/client/assets/{star-BAT_ObKE.js → star-DYesq1AV.js} +1 -1
  41. package/dist/client/assets/{upload-BC2YKNEV.js → upload-DTWF3Db5.js} +1 -1
  42. package/dist/client/assets/{users-Dkd4rtrN.js → users--syrel4l.js} +1 -1
  43. package/dist/client/index.html +12 -20
  44. package/dist/client/theme-data.css +106 -0
  45. package/dist/client/version.json +1 -1
  46. package/dist/droid-cli/package.json +1 -1
  47. package/dist/extension.js +14287 -9568
  48. package/dist/pi-claude-cli/package.json +1 -1
  49. package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +218 -0
  50. package/dist/plugins/fusion-plugin-cursor-runtime/manifest.json +6 -0
  51. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +11 -0
  52. package/dist/plugins/fusion-plugin-dependency-graph/manifest.json +1 -1
  53. package/dist/plugins/fusion-plugin-dependency-graph/package.json +6 -4
  54. package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraph.css +58 -0
  55. package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraph.tsx +301 -0
  56. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphHighlight.css +27 -0
  57. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.css +157 -0
  58. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.tsx +126 -0
  59. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphToolbar.css +35 -0
  60. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphToolbar.tsx +36 -0
  61. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.highlighting.test.tsx +112 -0
  62. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.persistence.test.tsx +115 -0
  63. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.test.tsx +128 -0
  64. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphTaskNode.drag.test.tsx +82 -0
  65. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphTaskNode.test.tsx +307 -0
  66. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphToolbar.test.tsx +60 -0
  67. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/edges.test.tsx +75 -0
  68. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/filtering.test.tsx +62 -0
  69. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/filters.test.ts +78 -0
  70. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/graphPositionStorage.test.ts +95 -0
  71. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/host-integration.test.ts +74 -0
  72. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/index.test.ts +58 -0
  73. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/interactions.test.tsx +121 -0
  74. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/layout.test.ts +70 -0
  75. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/persistence.test.tsx +89 -0
  76. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphData.test.ts +86 -0
  77. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphInteraction.test.ts +167 -0
  78. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphPositions.test.ts +66 -0
  79. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useNodeDrag.test.ts +81 -0
  80. package/dist/plugins/fusion-plugin-dependency-graph/src/dashboard-interop.d.ts +35 -0
  81. package/dist/plugins/fusion-plugin-dependency-graph/src/dashboard-view.tsx +19 -0
  82. package/dist/plugins/fusion-plugin-dependency-graph/src/edges.tsx +70 -0
  83. package/dist/plugins/fusion-plugin-dependency-graph/src/filters.ts +8 -0
  84. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/__tests__/useDependencyChain.test.ts +53 -0
  85. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useDependencyChain.ts +60 -0
  86. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useGraphPositions.ts +45 -0
  87. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useNodeDrag.ts +114 -0
  88. package/dist/plugins/fusion-plugin-dependency-graph/src/index.ts +1 -2
  89. package/dist/plugins/fusion-plugin-dependency-graph/src/layout.ts +91 -0
  90. package/dist/plugins/fusion-plugin-dependency-graph/src/styles/drag.css +15 -0
  91. package/dist/plugins/fusion-plugin-dependency-graph/src/types.ts +21 -0
  92. package/dist/plugins/fusion-plugin-dependency-graph/src/useGraphData.ts +17 -0
  93. package/dist/plugins/fusion-plugin-dependency-graph/src/useGraphInteraction.ts +292 -0
  94. package/dist/plugins/fusion-plugin-dependency-graph/src/utils/graphPositionStorage.ts +65 -0
  95. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +136680 -0
  96. package/dist/plugins/fusion-plugin-droid-runtime/manifest.json +13 -0
  97. package/dist/plugins/fusion-plugin-droid-runtime/mcp-schema-server.cjs +49 -0
  98. package/dist/plugins/fusion-plugin-droid-runtime/package.json +11 -0
  99. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  100. package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +93 -6
  101. package/dist/plugins/fusion-plugin-openclaw-runtime/mcp-schema-server.cjs +59 -0
  102. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  103. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  104. package/dist/plugins/fusion-plugin-reports/manifest.json +33 -0
  105. package/dist/plugins/fusion-plugin-reports/package.json +26 -0
  106. package/dist/plugins/fusion-plugin-reports/src/__tests__/manifest.test.ts +51 -0
  107. package/dist/plugins/fusion-plugin-reports/src/__tests__/review-panel.test.ts +166 -0
  108. package/dist/plugins/fusion-plugin-reports/src/__tests__/settings.test.ts +157 -0
  109. package/dist/plugins/fusion-plugin-reports/src/index.ts +41 -0
  110. package/dist/plugins/fusion-plugin-reports/src/review-panel.ts +294 -0
  111. package/dist/plugins/fusion-plugin-reports/src/review-types.ts +75 -0
  112. package/dist/plugins/fusion-plugin-reports/src/settings.ts +105 -0
  113. package/dist/plugins/fusion-plugin-roadmap/manifest.json +16 -0
  114. package/dist/plugins/fusion-plugin-roadmap/package.json +48 -0
  115. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/api-client.test.ts +101 -0
  116. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/index.test.ts +92 -0
  117. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/roadmap-routes.test.ts +48 -0
  118. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/roadmap-suggestions.test.ts +31 -0
  119. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/RoadmapsView.css +1299 -0
  120. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/RoadmapsView.tsx +2559 -0
  121. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/__tests__/RoadmapsView.test.tsx +1144 -0
  122. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/__tests__/useRoadmaps.test.ts +1756 -0
  123. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/api.ts +70 -0
  124. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/test-setup.ts +7 -0
  125. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/types.ts +1 -0
  126. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useConfirm.ts +8 -0
  127. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useRoadmaps.ts +1188 -0
  128. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useViewportMode.ts +20 -0
  129. package/dist/plugins/fusion-plugin-roadmap/src/dashboard-view.tsx +6 -0
  130. package/dist/plugins/fusion-plugin-roadmap/src/index.ts +74 -0
  131. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-routes.ts +1 -0
  132. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-schema.ts +41 -0
  133. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-suggestions.d.ts +15 -0
  134. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-suggestions.ts +15 -0
  135. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.d.ts +283 -0
  136. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.d.ts.map +1 -0
  137. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.js +21 -0
  138. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.js.map +1 -0
  139. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.ts +310 -0
  140. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.d.ts +5 -0
  141. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.d.ts.map +1 -0
  142. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.js +361 -0
  143. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.js.map +1 -0
  144. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.ts +408 -0
  145. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.d.ts +68 -0
  146. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.d.ts.map +1 -0
  147. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.js +300 -0
  148. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.js.map +1 -0
  149. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.ts +381 -0
  150. package/dist/plugins/fusion-plugin-roadmap/src/server/index.d.ts +3 -0
  151. package/dist/plugins/fusion-plugin-roadmap/src/server/index.ts +1 -0
  152. package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-handoff.test.ts +445 -0
  153. package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-ordering.test.ts +334 -0
  154. package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-store.test.ts +1318 -0
  155. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-handoff.ts +163 -0
  156. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.d.ts +37 -0
  157. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.d.ts.map +1 -0
  158. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.js +188 -0
  159. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.js.map +1 -0
  160. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.ts +311 -0
  161. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.d.ts +299 -0
  162. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.d.ts.map +1 -0
  163. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.js +765 -0
  164. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.js.map +1 -0
  165. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.ts +1001 -0
  166. package/dist/plugins/fusion-plugin-whatsapp-chat/manifest.json +8 -0
  167. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +34 -0
  168. package/dist/plugins/fusion-plugin-whatsapp-chat/src/__tests__/auth-state.test.ts +99 -0
  169. package/dist/plugins/fusion-plugin-whatsapp-chat/src/__tests__/connection.test.ts +145 -0
  170. package/dist/plugins/fusion-plugin-whatsapp-chat/src/__tests__/index.test.ts +216 -0
  171. package/dist/plugins/fusion-plugin-whatsapp-chat/src/__tests__/reply.test.ts +52 -0
  172. package/dist/plugins/fusion-plugin-whatsapp-chat/src/auth-state.ts +89 -0
  173. package/dist/plugins/fusion-plugin-whatsapp-chat/src/connection.ts +253 -0
  174. package/dist/plugins/fusion-plugin-whatsapp-chat/src/index.ts +262 -0
  175. package/dist/plugins/fusion-plugin-whatsapp-chat/src/qrcode.d.ts +1 -0
  176. package/dist/plugins/fusion-plugin-whatsapp-chat/src/reply.ts +37 -0
  177. package/package.json +2 -2
  178. package/skill/fusion/SKILL.md +2 -2
  179. package/skill/fusion/references/engine-tools.md +3 -0
  180. package/skill/fusion/references/extension-tools.md +39 -0
  181. package/skill/fusion/references/fusion-capabilities.md +3 -0
  182. package/dist/client/assets/AgentDetailView-C1XceMgi.js +0 -18
  183. package/dist/client/assets/AgentDetailView-CeO_1MK7.css +0 -1
  184. package/dist/client/assets/AgentsView-Deh125ss.js +0 -527
  185. package/dist/client/assets/ChatView-7D_RQDqT.js +0 -1
  186. package/dist/client/assets/InsightsView-AWo5o_81.css +0 -1
  187. package/dist/client/assets/InsightsView-jKjEFAx_.js +0 -11
  188. package/dist/client/assets/NodesView-Di2SvOhg.js +0 -14
  189. package/dist/client/assets/NodesView-fXqDk9ur.css +0 -1
  190. package/dist/client/assets/PluginManager-B9-NbQ8f.js +0 -1
  191. package/dist/client/assets/PluginManager-C1DbPaar.css +0 -1
  192. package/dist/client/assets/RoadmapsView-DHWjUoc8.js +0 -6
  193. package/dist/client/assets/SettingsModal-DHitIpsa.css +0 -1
  194. package/dist/client/assets/SettingsModal-DR_yirvK.js +0 -31
  195. package/dist/client/assets/SetupWizardModal-BtDMY9pa.js +0 -1
  196. package/dist/client/assets/agentSkills-B-w5wFHh.js +0 -1
  197. package/dist/client/assets/index-Bc6ZdGMz.css +0 -1
  198. package/dist/client/assets/index-D__RMku8.js +0 -694
  199. package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraphView.css +0 -141
  200. package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraphView.tsx +0 -428
  201. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraphView.test.tsx +0 -261
  202. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/storage.test.ts +0 -41
  203. package/dist/plugins/fusion-plugin-dependency-graph/src/storage.ts +0 -22
  204. /package/dist/client/assets/{RoadmapsView-DdGlfuu-.css → dashboard-view-DdGlfuu-.css} +0 -0
@@ -1 +0,0 @@
1
- import{r as s,j as t}from"./vendor-react-K0fH_qHe.js";import{n as it,b1 as ft,z as qt,b2 as Jt,E as Xt,b3 as Qt,b4 as Yt,b5 as Zt,b6 as es,b7 as ts,b8 as ss,b9 as ns,s as as,ba as rs,x as is,bb as cs,u as ls,bc as os,ag as yt,ah as kt,S as ds,a1 as gt,P as He,Q as nt,ar as us,bd as hs,B as Be,ad as ms,ae as fs,a as gs,be as ps,bf as xs,bg as vs,aR as bs,bh as ws,bi as Ss,bj as pt,bk as ys,m as ks,o as xt,t as js}from"./index-D__RMku8.js";import"./vendor-xterm-DzcZoU0P.js";const at="kb-chat-active-session";function Ns(a){const r=typeof a=="string"?a.trim():"",i=r.indexOf("/");return!r||i<=0||i>=r.length-1?{}:{modelProvider:r.slice(0,i),modelId:r.slice(i+1)}}function Cs(a){const r=a?.toolCalls;if(!Array.isArray(r))return;const i=r.map(d=>{if(!d||typeof d!="object")return null;const c=d,v=typeof c.toolName=="string"?c.toolName:"";if(!v)return null;const k=c.args;return{toolName:v,...k&&typeof k=="object"?{args:k}:{},isError:!!c.isError,result:c.result,status:"completed"}}).filter(d=>d!==null);return i.length>0?i:void 0}function Ms(a){const r=a?.fallback;if(!r||typeof r!="object")return;const i=r,d=typeof i.primaryModel=="string"?i.primaryModel:"",c=typeof i.fallbackModel=="string"?i.fallbackModel:"",v=i.triggerPoint;if(!(!d||!c||v!=="session-creation"&&v!=="prompt-time"))return{primaryModel:d,fallbackModel:c,triggerPoint:v}}function rt(a){return{id:a.id,sessionId:a.sessionId,role:a.role,content:a.content,thinkingOutput:a.thinkingOutput,toolCalls:Cs(a.metadata),fallbackInfo:Ms(a.metadata),attachments:a.attachments,createdAt:a.createdAt}}function As(a,r){const[i,d]=s.useState([]),[c,v]=s.useState(null),[k,I]=s.useState(!0),[L,y]=s.useState([]),[D,b]=s.useState(!1),[E,P]=s.useState(!1),[M,p]=s.useState(""),[w,x]=s.useState(""),[F,j]=s.useState([]),[K,B]=s.useState(""),[G,R]=s.useState(""),[Q,h]=s.useState(!0),[N,oe]=s.useState(new Map),f=s.useRef(null),se=s.useRef(!1),Y=s.useRef(""),Z=s.useRef(null),Ce=s.useRef(i),U=s.useRef(c),we=s.useRef(E);Ce.current=i,U.current=c,we.current=E,s.useEffect(()=>{Y.current=K},[K]);const pe=s.useRef(new Set),de=s.useRef(0),Ie=s.useRef(a);Ie.current!==a&&(Ie.current=a,de.current++),s.useEffect(()=>{const o=de.current;it(void 0,a).then(m=>{if(de.current!==o)return;const g=new Map;for(const S of m)g.set(S.id,S);oe(g)}).catch(()=>{})},[a]);const ue=s.useCallback(async()=>{I(!0);try{const m=[...(await ft(a)).sessions].sort((g,S)=>new Date(S.updatedAt).getTime()-new Date(g.updatedAt).getTime());d(m)}catch{}finally{I(!1)}},[a]);s.useEffect(()=>{ue()},[ue]);const re=s.useRef(()=>{}),ee=s.useRef(!1);s.useEffect(()=>{ee.current=!1},[a]),s.useEffect(()=>{if(k||ee.current||U.current)return;const o=qt(at,a);if(!o){ee.current=!0;return}const m=i.find(g=>g.id===o);if(m){ee.current=!0,re.current(o,m);return}ee.current=!0},[k,i,a]);const ne=s.useCallback(async(o,m)=>{b(!0);try{const g=await Jt(o,{limit:50,...m},a),S=g.messages.map(rt);m?.offset&&m.offset>0?y(q=>[...S,...q]):y(S),h(g.messages.length>=50)}catch{}finally{b(!1)}},[a]),ie=s.useCallback(()=>{Z.current?.(),Z.current=null,Y.current="",B(""),p(""),x(""),j([]),P(!1)},[]),ce=s.useCallback((o,m)=>{const g=U.current?.id??null;if(o&&g===o&&!m)return;f.current&&(f.current.close(),f.current=null);const S=m??i.find(q=>q.id===o);v(S||null),ie(),h(!0),o?ne(o):y([]),S?.isGenerating&&(P(!0),p("")),o?Xt(at,o,a):Qt(at,a)},[i,ne,a,ie]);re.current=ce;const xe=s.useCallback(async o=>{const m=await Yt(o,a);f.current&&(f.current.close(),f.current=null);const g={id:m.session.id,title:m.session.title,agentId:m.session.agentId,status:m.session.status,modelProvider:m.session.modelProvider,modelId:m.session.modelId,createdAt:m.session.createdAt,updatedAt:m.session.updatedAt};return d(S=>S.some(q=>q.id===g.id)?S:[g,...S]),ie(),ce(g.id,g),y([]),g},[a,ie,ce]),Se=s.useCallback(async o=>{await Zt(o,{status:"archived"},a),d(m=>m.filter(g=>g.id!==o)),c?.id===o&&(v(null),y([]))},[c,a]),he=s.useCallback(async o=>{c?.id===o&&f.current&&(f.current.close(),f.current=null),await es(o,a),d(m=>m.filter(g=>g.id!==o)),c?.id===o&&(v(null),y([]))},[c,a]),ae=s.useCallback(async()=>{!c||!Q||await ne(c.id,{offset:L.length})},[c,Q,ne,L.length]),me=s.useCallback(()=>{c&&(se.current=!0,Z.current?.(),Z.current=null,f.current?.close(),f.current=null,ts(c.id,a).catch(()=>{}),P(!1),p(""),x(""),j([]))},[c,a]),Me=s.useCallback(()=>{Y.current="",B("")},[]),fe=s.useCallback((o,m)=>{if(!c)return;if(E){Y.current=o,B(o),r?.("Still waiting for previous response — message queued","warning");return}se.current=!1,f.current&&(f.current.close(),f.current=null);const g=`temp-${Date.now()}`,S={id:g,sessionId:c.id,role:"user",content:o,createdAt:new Date().toISOString()};y(V=>[...V,S]),p(""),x(""),j([]),P(!0);const{handlers:q}=ss({sessionId:c.id,tempUserMessageId:g,setStreamingText:p,setStreamingThinking:x,setStreamingToolCalls:j,cancelStreamingFlushesRef:Z,addToast:r,onFallbackSession:(V,J)=>{const O=Ns(V.fallbackModel);d(_=>_.map(A=>A.id===J?{...A,...O}:A)),v(_=>_&&_.id===J?{..._,...O}:_)},onDone:({messageId:V,message:J,accumulated:O})=>{const _=J?rt(J):{id:V||`msg-${Date.now()}`,sessionId:c.id,role:"assistant",content:O.text,thinkingOutput:O.thinking,toolCalls:O.toolCalls.length>0?O.toolCalls:void 0,fallbackInfo:O.fallbackInfo,createdAt:new Date().toISOString()};pe.current.add(_.id),y(z=>[...z,_]),p(""),x(""),j([]),P(!1),f.current=null,setTimeout(()=>{pe.current.delete(_.id)},1e3),ue();const A=Y.current.trim();A&&(Y.current="",B(""),fe(A))},onError:(V,J)=>{if(y(O=>O.filter(_=>_.id!==J)),p(""),x(""),j([]),P(!1),f.current=null,console.error("[useChat] Stream error:",V),r?.(typeof V=="string"&&V.trim()?V:"Failed to get response","error"),!se.current){const O=Y.current.trim();O&&(Y.current="",B(""),fe(O))}}});f.current=ns(c.id,o,q,m,a)},[c,E,a,ue,r]),Ae=G?i.filter(o=>o.title?.toLowerCase().includes(G.toLowerCase())||o.agentId.toLowerCase().includes(G.toLowerCase())):i;return s.useEffect(()=>{if(!E||f.current||!U.current)return;const o=setInterval(async()=>{if(!we.current||f.current||!U.current){clearInterval(o);return}try{(await ft(a)).sessions.find(S=>S.id===U.current?.id)?.isGenerating||(clearInterval(o),await ne(U.current.id),p(""),x(""),j([]),P(!1))}catch{}},3e3);return()=>clearInterval(o)},[E,ne,a]),s.useEffect(()=>{const o=de.current,m=a?`?projectId=${encodeURIComponent(a)}`:"",g=()=>de.current!==o,S=A=>{if(g())return;const z=JSON.parse(A.data);d(C=>C.some(u=>u.id===z.id)?C:[z,...C])},q=A=>{if(g())return;const z=JSON.parse(A.data);d(C=>[...C.map(X=>X.id===z.id?z:X)]),U.current?.id===z.id&&v(z)},V=A=>{if(g())return;const{id:z}=JSON.parse(A.data);d(C=>C.filter(u=>u.id!==z)),U.current?.id===z&&(v(null),y([]))},J=A=>{if(g())return;const z=JSON.parse(A.data),C=rt(z);if(!pe.current.has(C.id)){if(U.current?.id===C.sessionId&&we.current&&!f.current&&C.role==="assistant"){y(u=>u.some(X=>X.id===C.id)?u:[...u,C]),p(""),x(""),j([]),P(!1);return}U.current?.id===C.sessionId&&!we.current&&y(u=>{if(u.some(X=>X.id===C.id))return u;if(C.role==="user"){const X=u.findIndex(ge=>ge.role==="user"&&ge.id.startsWith("temp-")&&ge.content.trim()===C.content.trim());if(X>=0){const ge=[...u];return ge[X]=C,ge}}return[...u,C]})}},O=A=>{if(g())return;const{id:z}=JSON.parse(A.data);y(C=>C.filter(u=>u.id!==z))};return as(`/api/events${m}`,{events:{"chat:session:created":S,"chat:session:updated":q,"chat:session:deleted":V,"chat:message:added":J,"chat:message:deleted":O}})},[a]),s.useEffect(()=>()=>{f.current&&(f.current.close(),f.current=null)},[]),{sessions:i,activeSession:c,sessionsLoading:k,messages:L,messagesLoading:D,isStreaming:E,streamingText:M,streamingThinking:w,streamingToolCalls:F,pendingMessage:K,selectSession:ce,createSession:xe,archiveSession:Se,deleteSession:he,sendMessage:fe,stopStreaming:me,clearPendingMessage:Me,loadMoreMessages:ae,hasMoreMessages:Q,searchQuery:G,setSearchQuery:R,filteredSessions:Ae,refreshSessions:ue,agentsMap:N}}function jt(a){const r=new Date(a),d=new Date().getTime()-r.getTime(),c=Math.floor(d/1e3),v=Math.floor(c/60),k=Math.floor(v/60),I=Math.floor(k/24);return c<60?"just now":v<60?`${v}m ago`:k<24?`${k}h ago`:I<7?`${I}d ago`:r.toLocaleDateString()}function vt(a,r){if(!a||!r)return null;const i=r.toLowerCase();if(i.includes("claude")){let c=r.replace(/^claude[- ]/i,"Claude ").replace(/sonnet[- ](\d+)[- ](\d+)/i,"Sonnet $1.$2").replace(/sonnet[- ](\d+)/i,"Sonnet $1").replace(/haiku[- ](\d+)/i,"Haiku $1").replace(/opus[- ](\d+)/i,"Opus $1").replace(/sonnet/i,"Sonnet").replace(/haiku/i,"Haiku").replace(/opus/i,"Opus").replace(/-/g," ").trim();return c=c.replace(/\s+/g," "),c.length>30?c.slice(0,30)+"…":c}if(i.includes("gpt")||i.includes("openai")){const c=r.replace(/^gpt-4-turbo$/i,"GPT-4 Turbo").replace(/^gpt-4o-mini$/i,"GPT-4o Mini").replace(/^gpt-4o$/i,"GPT-4o").replace(/^gpt-4$/i,"GPT-4").replace(/^gpt-o1-preview$/i,"GPT-o1 Preview").replace(/^gpt-o1-mini$/i,"GPT-o1 Mini").replace(/^gpt-o1$/i,"GPT-o1").replace(/^gpt/i,"GPT").trim();return c.length>30?c.slice(0,30)+"…":c}if(i.includes("gemini")){const c=r.replace(/^gemini[- ]/i,"Gemini ").replace(/pro[- ](\d+)[- ](\d+)/i,"Pro $1.$2").replace(/pro[- ](\d+)/i,"Pro $1").replace(/-/g," ").replace(/\s+/g," ").trim();return c.length>30?c.slice(0,30)+"…":c}const d=r.replace(/-/g," ").replace(/^\w/,c=>c.toUpperCase()).replace(/\s+/g," ").trim();return d.length>30?d.slice(0,30)+"…":d}function We(a,r){return a.length<=r?a:`${a.slice(0,r)}…`}function Ts(a){if(!a)return null;const r=Object.entries(a);return r.length===0?null:r.map(([i,d])=>{const c=typeof d=="string"?d:(()=>{try{return JSON.stringify(d)}catch{return String(d)}})();return`${i}=${We(c,50)}`}).join(", ")}function Ps(a){if(a===void 0)return null;if(typeof a=="string")return We(a,200);try{return We(JSON.stringify(a),200)}catch{return We(String(a),200)}}function Nt(a){if(!a||a.length===0)return null;const r=(b,E)=>{const P=b.status==="running",M=b.status==="completed"&&b.isError,p=Ts(b.args),w=Ps(b.result),x=P?p:w?`result: ${w}`:p?`args: ${p}`:null,F=P?"running":M?"error":"completed";return t.jsxs("details",{className:`chat-tool-call${P?" chat-tool-call--running":""}${M?" chat-tool-call--error":""}`,open:P,children:[t.jsxs("summary",{children:[t.jsx("span",{className:"chat-tool-call-status-dot","aria-hidden":"true"}),t.jsx("span",{className:"chat-tool-call-name",title:b.toolName,children:b.toolName}),x&&t.jsx("span",{className:"chat-tool-call-preview",title:x,children:x}),t.jsx("span",{className:"chat-tool-call-status-text",children:F})]}),t.jsxs("div",{className:"chat-tool-call-content",children:[p&&t.jsxs("div",{className:"chat-tool-call-row",children:[t.jsx("span",{className:"chat-tool-call-label",children:"args"}),t.jsx("span",{className:"chat-tool-call-value",children:p})]}),w&&t.jsxs("div",{className:`chat-tool-call-row${M?" chat-tool-call-row--error":""}`,children:[t.jsx("span",{className:"chat-tool-call-label",children:"result"}),t.jsx("span",{className:"chat-tool-call-value",children:w})]})]})]},`${b.toolName}-${E}`)},i="chat-tool-calls";if(a.length===1)return t.jsxs("div",{className:i,"data-testid":"chat-tool-calls",children:[t.jsxs("div",{className:"chat-tool-calls-header",children:[t.jsx(pt,{size:12,"aria-hidden":"true"}),t.jsx("span",{children:"Tool calls"})]}),r(a[0],0)]});const d=a.filter(b=>b.status==="running").length,c=a.filter(b=>b.status==="completed"&&b.isError).length,v=d>0,k=Array.from(new Set(a.map(b=>b.toolName))),I=k.slice(0,5),L=Math.max(0,k.length-I.length),y=L>0?`${I.join(", ")}, +${L} more`:I.join(", "),D=v?`(${d} running)`:c>0?`(${c} ${c===1?"error":"errors"})`:null;return t.jsx("div",{className:i,"data-testid":"chat-tool-calls",children:t.jsxs("details",{className:"chat-tool-calls-group","data-testid":"chat-tool-calls-group",open:v,children:[t.jsxs("summary",{className:"chat-tool-calls-group-summary",children:[t.jsx(pt,{size:12,"aria-hidden":"true"}),t.jsxs("span",{className:"chat-tool-calls-count",children:[a.length," tool calls"]}),t.jsx("span",{className:"chat-tool-calls-names",title:y,children:y}),D&&t.jsx("span",{className:"chat-tool-calls-group-status",children:D})]}),a.map((b,E)=>r(b,E))]})})}const Ct={pre:({children:a,...r})=>t.jsx("pre",{...r,className:"chat-markdown-pre",children:a}),table:({children:a,...r})=>t.jsx("table",{...r,className:"chat-markdown-table",children:a})},$e="__fn_agent__",Ds=280,Oe=180,_e=500,bt="fusion:chat-sidebar-width",Es=["image/png","image/jpeg","image/gif","image/webp","text/plain","application/json","text/yaml","text/markdown","text/csv","application/xml","text/x-log"];function wt(a){const r=/(^|[\s])\/([^\s]*)$/.exec(a);if(!r)return null;const i=r[1]??"",d=r[2]??"",c=r.index+i.length;return{filter:d,start:c,end:a.length}}function Rs(a,r){const i=a.slice(0,r),d=/(^|[\s\n])@([\w-]*)$/.exec(i);if(!d)return null;const c=d[2]??"",v=i.length-c.length-1;return{filter:c,start:v,end:r}}function $s({projectId:a,onClose:r,onCreate:i}){const[d,c]=s.useState("agent"),[v,k]=s.useState([]),[I,L]=s.useState(!0),[y,D]=s.useState(""),[b,E]=s.useState([]),[P,M]=s.useState(!0),[p,w]=s.useState(""),[x,F]=s.useState([]),[j,K]=s.useState([]);s.useEffect(()=>{let h=!1;return L(!0),it(void 0,a).then(N=>{h||k(N)}).catch(()=>{h||k([])}).finally(()=>{h||L(!1)}),()=>{h=!0}},[a]),s.useEffect(()=>{M(!0),ks().then(h=>{E(h.models),F(h.favoriteProviders),K(h.favoriteModels)}).catch(()=>{E([]),F([]),K([])}).finally(()=>{M(!1)})},[]);const B=s.useCallback(async h=>{const N=x,f=N.includes(h)?N.filter(se=>se!==h):[h,...N];F(f);try{await xt({favoriteProviders:f,favoriteModels:j})}catch{F(N)}},[x,j]),G=s.useCallback(async h=>{const N=j,f=N.includes(h)?N.filter(se=>se!==h):[h,...N];K(f);try{await xt({favoriteProviders:x,favoriteModels:f})}catch{K(N)}},[j,x]),R=h=>{if(h.preventDefault(),d==="agent"){if(!y)return;i({agentId:y});return}if(!p)return;const N=p.indexOf("/");if(N<=0)return;const oe=p.slice(0,N),f=p.slice(N+1);i({agentId:$e,modelProvider:oe,modelId:f})},Q=d==="agent"?!y:!p;return t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",onClick:r,role:"dialog","aria-modal":"true",children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:h=>h.stopPropagation(),children:[t.jsx("h3",{children:"New Chat"}),t.jsxs("div",{className:"chat-new-dialog-mode-toggle","data-testid":"chat-new-dialog-mode-toggle",children:[t.jsx("button",{type:"button",className:`chat-new-dialog-mode-btn${d==="agent"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-agent",onClick:()=>{c("agent"),w("")},children:"Agent"}),t.jsx("button",{type:"button",className:`chat-new-dialog-mode-btn${d==="model"?" chat-new-dialog-mode-btn--active":""}`,"data-testid":"chat-new-dialog-mode-model",onClick:()=>{c("model"),D("")},children:"Model"})]}),t.jsxs("form",{onSubmit:R,children:[d==="agent"&&t.jsxs("label",{className:"chat-new-dialog-model-label",children:["Agent",I?t.jsx("div",{className:"chat-new-dialog-loading",children:"Loading agents..."}):v.length===0?t.jsx("div",{className:"chat-new-dialog-empty",children:"No agents available"}):t.jsx("div",{className:"chat-new-dialog-agent-list",children:v.map(h=>t.jsxs("button",{type:"button",className:`chat-new-dialog-agent-item${y===h.id?" chat-new-dialog-agent-item--selected":""}`,onClick:()=>D(h.id),"data-testid":`agent-option-${h.id}`,children:[t.jsx(Be,{size:16}),t.jsx("span",{className:"chat-new-dialog-agent-name",children:h.name}),t.jsx("span",{className:"chat-new-dialog-agent-role",children:h.role})]},h.id))})]}),d==="model"&&t.jsx("div",{className:"chat-new-dialog-model-dropdown","data-testid":"chat-new-dialog-model-section",children:P?t.jsx("div",{className:"chat-new-dialog-loading",children:"Loading models..."}):t.jsx(js,{models:b,value:p,onChange:w,label:"Model",placeholder:"Select a model",favoriteProviders:x,onToggleFavorite:B,favoriteModels:j,onToggleModelFavorite:G})}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{type:"button",className:"btn btn-sm",onClick:r,children:"Cancel"}),t.jsx("button",{type:"submit",className:"btn btn-sm btn-primary",disabled:Q,children:"Create"})]})]})]})})}const St=s.memo(function({message:r,forcePlain:i,agentName:d,hideAssistantIdentity:c,showAssistantModelTag:v,activeModelTag:k,activeModelProvider:I,activeSessionId:L,mentionAgentsByName:y}){const D=r.role==="assistant",b=s.useMemo(()=>{if(D)return null;const M=r.content,p=/@([\w-]+)/g,w=[];let x=0,F=p.exec(M);for(;F;){const[j,K=""]=F,B=F.index;B>x&&w.push(M.slice(x,B));const G=K.replace(/_/g," ").toLowerCase(),R=y.get(G);R?w.push(t.jsxs("span",{className:"chat-mention-chip",children:["@",R.name.replace(/\s+/g,"_")]},`${R.id}-${B}`)):w.push(j),x=B+j.length,F=p.exec(M)}return x<M.length&&w.push(M.slice(x)),w.length===0?M:w},[D,r.content,y]),E=s.useMemo(()=>{const M=r.attachments;if(!M||M.length===0||!L)return null;const p=`/api/chat/sessions/${encodeURIComponent(L)}/attachments/`;return t.jsx("div",{className:"chat-message-attachments",children:M.map(w=>{const x=w.mimeType.startsWith("image/"),F=w.id||w.filename,j=`${p}${encodeURIComponent(w.filename)}`;return x?t.jsx("a",{className:"chat-message-attachment-link","data-testid":"chat-message-attachment",href:j,target:"_blank",rel:"noopener noreferrer",children:t.jsx("img",{className:"chat-message-attachment",src:j,alt:w.originalName})},F):t.jsxs("a",{className:"chat-message-attachment-file","data-testid":"chat-message-attachment",href:j,target:"_blank",rel:"noopener noreferrer",children:[t.jsx(Ss,{size:14}),t.jsx("span",{children:w.originalName})]},F)})})},[r.attachments,L]),P=s.useMemo(()=>D?i?t.jsx("div",{className:"chat-message-content chat-message-content--plain",children:r.content}):t.jsx("div",{className:"chat-message-content chat-message-content--markdown",children:t.jsx(yt,{remarkPlugins:[kt],components:Ct,children:r.content})}):null,[D,i,r.content]);return t.jsxs("div",{className:`chat-message chat-message--${r.role}`,"data-testid":`chat-message-${r.id}`,children:[D&&!c&&t.jsxs("div",{className:"chat-message-avatar",children:[I?t.jsx(He,{provider:I,size:"sm"}):t.jsx(Be,{size:14}),t.jsx("span",{children:d}),v&&k&&t.jsx("span",{className:"chat-model-tag",children:k})]}),D?P:t.jsx("div",{className:"chat-message-content",children:b}),Nt(r.toolCalls),r.thinkingOutput&&t.jsxs("details",{className:"chat-message-thinking",children:[t.jsx("summary",{children:"Thinking"}),t.jsx("pre",{className:"chat-message-thinking-content",children:r.thinkingOutput})]}),E,t.jsx("div",{className:"chat-message-time",children:jt(r.createdAt)})]})});function Us({projectId:a,addToast:r}){const{activeSession:i,sessionsLoading:d,messages:c,messagesLoading:v,isStreaming:k,streamingText:I,streamingThinking:L,streamingToolCalls:y,selectSession:D,createSession:b,archiveSession:E,deleteSession:P,sendMessage:M,stopStreaming:p,pendingMessage:w,clearPendingMessage:x,searchQuery:F,setSearchQuery:j,filteredSessions:K}=As(a,r),[B,G]=s.useState(!1),[R,Q]=s.useState(""),[h,N]=s.useState(null),[oe,f]=s.useState(null),[se,Y]=s.useState(!0),[Z,Ce]=s.useState(Ds),[U,we]=s.useState(new Map),[pe,de]=s.useState([]),[Ie,ue]=s.useState(!0),[re,ee]=s.useState(!1),[ne,ie]=s.useState(""),[ce,xe]=s.useState(0),[Se,he]=s.useState(""),[ae,me]=s.useState(!1),[Me,fe]=s.useState(0),[Ae,o]=s.useState(-1),[m,g]=s.useState(!1),[S,q]=s.useState([]),[V,J]=s.useState(!1),[O,_]=s.useState(!1),[,A]=s.useState(!1),[z,C]=s.useState({top:0,left:0}),u=rs({projectId:a}),X=s.useCallback(e=>{if(!e||!u.mentionActive)return;const n=e.getBoundingClientRect();C({top:n.top-260,left:n.left+8})},[u.mentionActive]),ge=s.useRef(null),Ge=s.useRef(!1),le=s.useRef(null),Le=s.useRef(null),H=s.useRef(null),ct=s.useRef(null),lt=s.useRef([]),Te=s.useRef(0),$=is()==="mobile";s.useEffect(()=>{try{const e=localStorage.getItem(bt);if(!e)return;const n=Number.parseInt(e,10);if(Number.isNaN(n))return;const l=Math.max(Oe,Math.min(_e,n));Ce(l)}catch{}},[]);const{keyboardOverlap:Fe,viewportHeight:ot,viewportOffsetTop:dt,keyboardOpen:Pe}=cs({enabled:$&&!!i}),ut=Fe>0||dt>0,Mt=Pe&&ut?{"--keyboard-overlap":`${Fe}px`,"--vv-offset-top":`${dt}px`,...ot!==null?{"--vv-height":`${ot}px`}:{}}:{},te=s.useMemo(()=>{const e=ne.trim().toLowerCase();return(e?pe.filter(l=>l.name.toLowerCase().includes(e)):pe).slice(0,10)},[pe,ne]),ye=s.useMemo(()=>Array.from(U.values()),[U]),ve=s.useMemo(()=>{const e=Se.trim().toLowerCase();return e?ye.filter(n=>n.name.toLowerCase().includes(e)):ye},[ye,Se]),ht=s.useMemo(()=>{const e=new Map;for(const n of ye)e.set(n.name.toLowerCase(),n);return e},[ye]);s.useEffect(()=>{xe(0)},[te]),s.useEffect(()=>{fe(0)},[Se,ae]),s.useEffect(()=>()=>{le.current!==null&&window.clearTimeout(le.current)},[]);const At=s.useCallback(()=>{const e=Le.current;if(!e)return;const l=e.scrollTop+e.clientHeight>=e.scrollHeight-50;_(!l),Ge.current=!l},[]),De=s.useCallback(()=>{const e=Le.current;e&&(e.scrollTop=e.scrollHeight,_(!1),Ge.current=!1)},[]);s.useEffect(()=>{Ge.current||De()},[c,I,L,k,De]),s.useEffect(()=>{Fe<=0||!Le.current||De()},[Fe,De]),ls($&&Pe),s.useEffect(()=>{const e=()=>N(null);if(h)return document.addEventListener("click",e),()=>document.removeEventListener("click",e)},[h]),s.useEffect(()=>{if(!$||!Pe)return;const e=n=>{n.target?.closest(".chat-messages")||n.preventDefault()};return document.addEventListener("touchmove",e,{passive:!1}),()=>{document.removeEventListener("touchmove",e)}},[$,Pe]),s.useEffect(()=>{if(!$||!i)return;const e=()=>{const n=H.current;n&&document.activeElement===n&&(n.blur(),window.setTimeout(()=>{n.focus({preventScroll:!0})},0))};return document.addEventListener("visibilitychange",e),window.addEventListener("pageshow",e),()=>{document.removeEventListener("visibilitychange",e),window.removeEventListener("pageshow",e)}},[$,i]),s.useEffect(()=>{let e=!1;const n=a;return it(void 0,a).then(l=>{if(e||n!==a)return;const T=new Map;for(const W of l)T.set(W.id,W);we(T)}).catch(()=>{}),()=>{e=!0}},[a]),s.useEffect(()=>{let e=!1;return ue(!0),os(a).then(n=>{e||de(n)}).catch(()=>{e||de([])}).finally(()=>{e||ue(!1)}),()=>{e=!0}},[a]),s.useEffect(()=>{lt.current=S},[S]),s.useEffect(()=>()=>{for(const e of lt.current)e.previewUrl&&URL.revokeObjectURL(e.previewUrl)},[]);const ze=s.useCallback(e=>{if(!e||e.length===0)return;const n=[];for(const l of Array.from(e)){if(!Es.includes(l.type))continue;const T=l.type.startsWith("image/");n.push({file:l,previewUrl:T?URL.createObjectURL(l):""})}n.length>0&&q(l=>[...l,...n])},[]),Tt=s.useCallback(e=>{q(n=>{const l=n[e];return l?.previewUrl&&URL.revokeObjectURL(l.previewUrl),n.filter((T,W)=>W!==e)})},[]),Pt=s.useCallback(e=>{const n=e.clipboardData?.files;if(!n||n.length===0)return;const l=Array.from(n).filter(T=>T.type.startsWith("image/"));l.length!==0&&ze(l)},[ze]),Dt=s.useCallback(async e=>{try{await b(e),G(!1),$&&Y(!1)}catch{r("Failed to create chat session","error")}},[b,r,$]),Ve=s.useCallback(()=>{Q(""),ee(!1),ie(""),me(!1),he(""),o(-1),q(e=>{for(const n of e)n.previewUrl&&URL.revokeObjectURL(n.previewUrl);return[]})},[]),Ke=s.useCallback(()=>{const e=R.trim(),n=S.map(l=>l.file);if(!(!e&&n.length===0||!i)){if(e==="/clear"){Ve(),p(),x(),b({agentId:i.agentId,modelProvider:i.modelProvider??void 0,modelId:i.modelId??void 0}).catch(()=>{r("Failed to clear conversation","error")});return}Ve(),M(e,n)}},[R,S,i,Ve,p,x,b,r,M]),qe=s.useCallback(e=>{Q(n=>{const l=wt(n);if(!l)return n;const T=`/skill:${e.name} `,W=n.slice(0,l.start)+T+n.slice(l.end);return window.requestAnimationFrame(()=>{H.current&&(H.current.style.height="auto",H.current.style.height=`${Math.min(H.current.scrollHeight,120)}px`,H.current.focus())}),W}),ee(!1),ie(""),xe(0)},[]),Je=s.useCallback(e=>{const n=H.current;if(!n||Ae<0)return;const l=n.selectionStart??Te.current,T=n.selectionEnd??l,W=Math.max(l,T),Re=Math.min(Ae,W),je=`${`@${e.name.replace(/\s+/g,"_")}`} `,st=R.slice(0,Re)+je+R.slice(W),Ne=Re+je.length;Q(st),me(!1),he(""),fe(0),o(-1),window.requestAnimationFrame(()=>{H.current&&(H.current.style.height="auto",H.current.style.height=`${Math.min(H.current.scrollHeight,120)}px`,H.current.focus(),H.current.setSelectionRange(Ne,Ne))})},[Ae,R]),Et=s.useCallback(e=>{if(Te.current=e.currentTarget.selectionStart??Te.current,u.mentionActive&&u.files.length>0){if(u.handleKeyDown(e,R),e.key==="Enter"||e.key==="Tab"){const n=u.files[u.selectedIndex];if(n){const l=u.selectFile(n,R);Q(l),u.dismissMention(),A(!1)}}return}if(ae&&e.key==="ArrowDown"){e.preventDefault(),ve.length>0&&fe(n=>(n+1)%ve.length);return}if(ae&&e.key==="ArrowUp"){e.preventDefault(),ve.length>0&&fe(n=>n===0?ve.length-1:n-1);return}if(ae&&e.key==="Enter"){e.preventDefault();const n=ve[Me]??ve[0];n&&Je(n);return}if(ae&&e.key==="Escape"){e.preventDefault(),me(!1),he(""),o(-1);return}if(re&&e.key==="ArrowDown"){e.preventDefault(),te.length>0&&xe(n=>(n+1)%te.length);return}if(re&&e.key==="ArrowUp"){e.preventDefault(),te.length>0&&xe(n=>n===0?te.length-1:n-1);return}if(re&&(e.key==="Enter"||e.key==="Tab")&&te.length>0){e.preventDefault();const n=te[ce]??te[0];n&&qe(n);return}if(re&&e.key==="Escape"){e.preventDefault(),ee(!1);return}e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),Ke())},[ae,ve,Me,Je,re,te,ce,qe,Ke,u,R]),Ue=s.useCallback((e,n)=>{const l=Rs(e,n);if(l){me(!0),he(l.filter),o(l.start);return}me(!1),he(""),o(-1)},[]),Rt=s.useCallback(e=>{const n=e.target,l=n.value,T=n.selectionStart??l.length;Te.current=T,Q(l);const W=wt(l);W?(ee(!0),ie(W.filter)):(ee(!1),ie("")),Ue(l,T),u.detectMention(l,T),A(u.mentionActive),u.mentionActive&&X(n),n.style.height="auto",n.style.height=`${Math.min(n.scrollHeight,120)}px`},[Ue]),Xe=s.useCallback(e=>{const n=e.currentTarget,l=n.selectionStart??n.value.length;Te.current=l,Ue(n.value,l),u.detectMention(n.value,l),A(u.mentionActive),u.mentionActive&&X(n)},[Ue,u,X]),$t=s.useCallback(e=>{e.key!=="Escape"&&Xe(e)},[Xe]),It=s.useCallback(()=>{le.current!==null&&window.clearTimeout(le.current),le.current=window.setTimeout(()=>{ee(!1),me(!1),he(""),o(-1),A(!1),u.dismissMention(),le.current=null},120)},[u]),Lt=s.useCallback(()=>{le.current!==null&&(window.clearTimeout(le.current),le.current=null),typeof window<"u"&&window.innerWidth<=768&&window.setTimeout(()=>{(window.scrollY!==0||window.scrollX!==0)&&window.scrollTo(0,0)},0)},[]),Ft=s.useCallback(async e=>{N(null);try{await E(e),r("Conversation archived","success")}catch{r("Failed to archive conversation","error")}},[E,r]),zt=s.useCallback(async e=>{f(null),N(null);try{await P(e),r("Conversation deleted","success")}catch{r("Failed to delete conversation","error")}},[P,r]),Ee=s.useCallback(e=>{try{localStorage.setItem(bt,String(e))}catch{}},[]),Ut=s.useCallback(e=>{if($)return;e.preventDefault(),e.stopPropagation();const n=e.currentTarget;typeof n.setPointerCapture=="function"&&n.setPointerCapture(e.pointerId);const l=e.clientX,T=Z;let W=T;document.body.style.userSelect="none";const Re=je=>{const st=je.clientX-l,Ne=Math.max(Oe,Math.min(_e,T+st));W=Ne,Ce(Ne),Ee(Ne)},tt=je=>{typeof n.releasePointerCapture=="function"&&n.releasePointerCapture(je.pointerId),document.body.style.userSelect="",document.removeEventListener("pointermove",Re),document.removeEventListener("pointerup",tt),Ee(W)};document.addEventListener("pointermove",Re),document.addEventListener("pointerup",tt)},[$,Ee,Z]),Ot=s.useCallback(e=>{if($||e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;e.preventDefault();const n=e.shiftKey?50:10,l=e.key==="ArrowLeft"?-n:n,T=Math.max(Oe,Math.min(_e,Z+l));Ce(T),Ee(T)},[$,Ee,Z]),_t=s.useCallback(e=>{D(e),$&&Y(!1)},[D,$]),Ht=s.useCallback(()=>{D(""),Y(!0)},[D]),Wt=()=>t.jsxs("div",{className:"chat-empty-state",children:[t.jsx(ys,{size:48,strokeWidth:1.5}),t.jsx("h2",{children:"Start a new conversation"}),t.jsxs("button",{className:"btn btn-primary",onClick:()=>G(!0),children:[t.jsx(nt,{size:16}),"New Chat"]})]}),be=vt(i?.modelProvider,i?.modelId),ke=i?.modelProvider??null,Qe=!!(i||k||c.length>0),mt=i?.agentId===$e?be??"Fusion":i?.title||U.get(i?.agentId??"")?.name||i?.agentId||"Chat",Bt=!!(be&&be!==mt),Ye=U.get(i?.agentId??"")?.name||(i?.agentId===$e?be??"Fusion":i?.agentId?.slice(0,30)??"Fusion"),Ze=!1,et=i?.agentId===$e,Gt=w.length>50?`${w.slice(0,50)}…`:w,Vt=s.useCallback(()=>{g(e=>!e)},[]),Kt=s.useCallback((e,n=!1)=>n?t.jsx("div",{className:"chat-message-content chat-message-content--plain",children:e}):t.jsx("div",{className:"chat-message-content chat-message-content--markdown",children:t.jsx(yt,{remarkPlugins:[kt],components:Ct,children:e})}),[]);return t.jsxs("div",{className:"chat-view",children:[t.jsxs("div",{className:`chat-sidebar${se?"":" chat-sidebar--hidden"}`,style:$?void 0:{width:`${Z}px`},children:[t.jsx("div",{className:"chat-sidebar-search",children:t.jsxs("div",{className:"chat-sidebar-search-wrapper",children:[t.jsx(ds,{size:14,className:"chat-sidebar-search-icon"}),t.jsx("input",{type:"text",className:"chat-sidebar-search",placeholder:"Search conversations...",value:F,onChange:e=>j(e.target.value),"data-testid":"chat-search-input"})]})}),t.jsx("div",{className:"chat-session-list chat-sidebar-list",children:d?t.jsx("div",{style:{padding:"12px",color:"var(--text-secondary)",fontSize:"13px"},children:"Loading..."}):K.length===0?t.jsx("div",{style:{padding:"12px",color:"var(--text-secondary)",fontSize:"13px"},children:"No conversations yet"}):K.map(e=>t.jsxs("div",{className:`chat-session-item${i?.id===e.id?" chat-session-item--active":""}`,onClick:()=>_t(e.id),onContextMenu:n=>{n.preventDefault(),N({sessionId:e.id,x:n.clientX,y:n.clientY})},"data-testid":`chat-session-${e.id}`,children:[t.jsx("button",{className:"chat-session-delete-btn",onClick:n=>{n.stopPropagation(),f(e.id)},"data-testid":"chat-session-delete-btn","aria-label":"Delete conversation",children:t.jsx(gt,{size:14})}),t.jsx("div",{className:"chat-session-title",children:e.title||"Untitled"}),t.jsx("div",{className:"chat-session-preview",children:e.lastMessagePreview||"No messages"}),t.jsxs("div",{className:"chat-session-meta",children:[t.jsxs("span",{className:"chat-session-meta-model",children:[e.modelProvider&&t.jsx(He,{provider:e.modelProvider,size:"sm"}),t.jsx("span",{children:U.get(e.agentId)?.name||(e.agentId===$e?vt(e.modelProvider,e.modelId)??"Fusion":e.agentId.slice(0,30))})]}),t.jsx("span",{children:e.updatedAt?jt(e.updatedAt):""})]})]},e.id))}),t.jsx("div",{className:"chat-sidebar-footer",children:t.jsxs("button",{className:"btn btn-sm btn-primary chat-sidebar-footer-btn",onClick:()=>G(!0),"data-testid":"chat-new-btn",children:[t.jsx(nt,{size:14}),"New Chat"]})})]}),!$&&se&&t.jsx("div",{className:"chat-sidebar-resize-handle",role:"separator","aria-orientation":"vertical","aria-valuemin":Oe,"aria-valuemax":_e,"aria-valuenow":Z,"aria-label":"Resize chat sidebar",tabIndex:0,onPointerDown:Ut,onKeyDown:Ot}),h&&t.jsxs("div",{className:"chat-session-context-menu",style:{top:h.y,left:h.x},onClick:e=>e.stopPropagation(),children:[t.jsxs("button",{onClick:()=>Ft(h.sessionId),"data-testid":"chat-context-archive",children:[t.jsx(us,{size:14}),"Archive"]}),t.jsxs("button",{onClick:()=>{N(null),f(h.sessionId)},"data-testid":"chat-context-delete",children:[t.jsx(gt,{size:14}),"Delete"]})]}),oe&&t.jsx("div",{className:"chat-new-dialog-backdrop chat-view-dialog-backdrop",onClick:()=>f(null),children:t.jsxs("div",{className:"chat-new-dialog chat-view-dialog",onClick:e=>e.stopPropagation(),children:[t.jsx("h3",{children:"Delete Conversation?"}),t.jsx("p",{className:"chat-view-delete-dialog-copy",children:"This action cannot be undone. All messages in this conversation will be permanently deleted."}),t.jsxs("div",{className:"chat-new-dialog-actions",children:[t.jsx("button",{className:"btn btn-sm",onClick:()=>f(null),children:"Cancel"}),t.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>void zt(oe),children:"Delete"})]})]})}),t.jsxs("div",{className:`chat-thread${Pe&&ut?" chat-thread--keyboard-active":""}`,style:Mt,children:[(Qe||!$)&&t.jsxs("div",{className:"chat-thread-header",children:[$&&Qe&&t.jsx("button",{className:"btn-icon",onClick:Ht,"data-testid":"chat-back-btn",children:t.jsx(hs,{size:16})}),t.jsxs("div",{className:"chat-thread-header-identity","data-testid":"chat-thread-header-identity",children:[ke?t.jsx(He,{provider:ke,size:"md"}):t.jsx(Be,{size:16}),t.jsx("span",{className:"chat-thread-header-title",children:mt}),Bt&&t.jsx("span",{className:"chat-model-tag",children:be})]}),Qe&&t.jsx("button",{type:"button",className:`chat-thread-header-render-toggle${m?" chat-thread-header-render-toggle--plain":""}`,"data-testid":"chat-thread-render-toggle","aria-label":m?"Show all messages as rendered Markdown":"Show all messages as plain text",onClick:Vt,children:m?t.jsx(ms,{size:14}):t.jsx(fs,{size:14})}),!$&&t.jsxs("button",{className:"btn btn-sm btn-primary chat-thread-header-new-chat",onClick:()=>G(!0),"data-testid":"chat-thread-new-chat-btn",children:[t.jsx(nt,{size:14}),"New Chat"]})]}),t.jsxs("div",{className:"chat-messages",ref:Le,onScroll:At,children:[k?t.jsxs(t.Fragment,{children:[c.map(e=>t.jsx(St,{message:e,forcePlain:m,agentName:Ye,hideAssistantIdentity:et,showAssistantModelTag:Ze,activeModelTag:be,activeModelProvider:ke,activeSessionId:i?.id??null,mentionAgentsByName:ht},e.id)),t.jsxs("div",{className:"chat-message chat-message--assistant chat-message--streaming",children:[!et&&t.jsxs("div",{className:"chat-message-avatar",children:[ke?t.jsx(He,{provider:ke,size:"sm"}):t.jsx(Be,{size:14}),t.jsx("span",{children:Ye}),Ze]}),I?Kt(I,m):t.jsx("div",{className:"chat-message-content chat-message-content--waiting",children:L?"Thinking…":"Connecting…"}),Nt(y),L&&t.jsxs("details",{className:"chat-message-thinking",children:[t.jsx("summary",{children:"Thinking"}),t.jsx("pre",{className:"chat-message-thinking-content",children:L})]}),t.jsxs("div",{className:"chat-typing-indicator",children:[t.jsx("span",{}),t.jsx("span",{}),t.jsx("span",{})]})]})]}):v?t.jsx("div",{style:{color:"var(--text-secondary)",fontSize:"13px"},children:"Loading messages..."}):c.length===0&&!i?Wt():c.length===0&&i?t.jsx("div",{style:{color:"var(--text-secondary)",fontSize:"13px"},children:"No messages yet. Start the conversation!"}):t.jsx(t.Fragment,{children:c.map(e=>t.jsx(St,{message:e,forcePlain:m,agentName:Ye,hideAssistantIdentity:et,showAssistantModelTag:Ze,activeModelTag:be,activeModelProvider:ke,activeSessionId:i?.id??null,mentionAgentsByName:ht},e.id))}),t.jsx("div",{ref:ge})]}),O&&t.jsxs("button",{type:"button",className:"btn btn-sm chat-jump-to-latest","data-testid":"chat-jump-to-latest",onClick:De,children:[t.jsx(gs,{size:14}),"Latest"]}),i&&t.jsxs("div",{className:"chat-input-area",children:[t.jsx("input",{ref:ct,type:"file",accept:"image/*,.txt,.json,.yaml,.yml,.log,.csv,.xml,.md",multiple:!0,style:{display:"none"},onChange:e=>{ze(e.target.files),e.target.value=""}}),re&&t.jsx("div",{className:"chat-skill-menu","data-testid":"chat-skill-menu",role:"listbox","aria-label":"Skill suggestions",children:Ie?t.jsx("div",{className:"chat-skill-menu-empty",children:"Loading skills…"}):te.length===0?t.jsx("div",{className:"chat-skill-menu-empty",children:ne?"No skills found":"No skills available"}):te.map((e,n)=>t.jsxs("button",{type:"button",role:"option","aria-selected":n===ce,className:`chat-skill-menu-item${n===ce?" chat-skill-menu-item--highlighted":""}`,onMouseDown:l=>l.preventDefault(),onMouseEnter:()=>xe(n),onClick:()=>qe(e),children:[t.jsx("span",{className:"chat-skill-menu-item-name",children:e.name}),t.jsx("span",{className:"chat-skill-menu-item-description",title:e.relativePath,children:e.relativePath})]},e.id))}),S.length>0&&t.jsx("div",{className:"chat-attachment-previews","data-testid":"chat-attachment-previews",children:S.map((e,n)=>t.jsxs("div",{className:"chat-attachment-preview","data-testid":`chat-attachment-preview-${n}`,children:[e.previewUrl?t.jsx("img",{src:e.previewUrl,alt:e.file.name}):t.jsx("span",{className:"chat-attachment-preview-name",children:e.file.name}),t.jsx("button",{type:"button",className:"chat-attachment-remove",onClick:()=>Tt(n),"data-testid":`chat-attachment-remove-${n}`,"aria-label":`Remove ${e.file.name}`,children:"×"})]},e.previewUrl||`${e.file.name}-${n}`))}),t.jsxs("div",{className:"chat-input-row",children:[t.jsx("button",{type:"button",className:"btn-icon chat-attach-btn","data-testid":"chat-attach-btn","aria-label":"Attach files",onClick:()=>ct.current?.click(),children:t.jsx(ps,{size:16})}),t.jsxs("div",{className:`chat-input-wrapper${V?" chat-input-wrapper--dragover":""}`,onDragOver:e=>{e.preventDefault(),J(!0)},onDragLeave:()=>J(!1),onDrop:e=>{e.preventDefault(),J(!1),ze(e.dataTransfer.files)},children:[t.jsx("textarea",{ref:H,className:"chat-input-textarea",placeholder:"Type a message...",value:R,onChange:Rt,onKeyDown:Et,onKeyUp:$t,onClick:Xe,onBlur:It,onFocus:Lt,onPaste:Pt,onTouchStart:e=>{typeof window>"u"||window.innerWidth>768||document.activeElement!==e.currentTarget&&(e.preventDefault(),e.currentTarget.focus({preventScroll:!0}))},rows:1,"data-testid":"chat-input"}),t.jsx(xs,{agents:ye,filter:Se,highlightedIndex:Me,visible:ae,onSelect:Je,position:"below"}),t.jsx(vs,{visible:u.mentionActive&&!ae,position:z,files:u.files,selectedIndex:u.selectedIndex,onSelect:e=>{const n=u.selectFile(e,R);Q(n),u.dismissMention(),A(!1),H.current?.focus()},loading:u.loading}),w&&t.jsxs("div",{className:"chat-pending-message","data-testid":"chat-pending-indicator",children:[t.jsx("span",{children:`Queued: ${Gt}`}),t.jsx("button",{type:"button",className:"chat-pending-message-dismiss","aria-label":"Dismiss queued message","data-testid":"chat-pending-dismiss",onClick:x,children:"×"})]})]}),k?t.jsx("button",{className:"chat-input-stop",onClick:p,"aria-label":"Stop generation","data-testid":"chat-stop-btn",children:t.jsx(bs,{size:14})}):t.jsx("button",{type:"button",className:"chat-input-send",onPointerDown:e=>{e.pointerType&&e.pointerType!=="mouse"&&e.preventDefault()},onMouseDown:e=>{e.preventDefault()},onClick:()=>{Ke()},disabled:!R.trim()&&S.length===0,"data-testid":"chat-send-btn",style:{touchAction:"manipulation"},children:t.jsx(ws,{size:16})})]})]})]}),B&&t.jsx($s,{projectId:a,onClose:()=>G(!1),onCreate:Dt})]})}export{Us as ChatView};
@@ -1 +0,0 @@
1
- .insights-view{display:flex;flex-direction:column;height:100%;min-height:0;overflow:hidden}.insights-view-header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-lg);border-bottom:1px solid var(--border);background:var(--surface);flex-shrink:0}.insights-view-title{display:flex;align-items:center;gap:var(--space-sm)}.insights-view-title h2{margin:0;font-size:1.125rem;font-weight:600;display:flex;align-items:center;gap:var(--space-sm)}.insights-view-count{font-size:.8125rem;color:var(--text-muted);font-weight:400}.insights-view-actions{display:flex;align-items:center;gap:var(--space-sm)}.insights-view-close{color:var(--text-muted)}.insights-view-close:hover{color:var(--text)}.insights-status-region{padding:var(--space-md) var(--space-lg);flex-shrink:0}.insights-status-region:empty{padding:0}.insights-status-message{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);border-radius:var(--radius-md);font-size:.8125rem}.insights-status-message--success{background:color-mix(in srgb,var(--color-success) 10%,transparent);color:var(--color-success)}.insights-status-message--error{background:color-mix(in srgb,var(--color-error) 10%,transparent);color:var(--color-error)}.insights-status-message--info{background:color-mix(in srgb,var(--accent) 10%,transparent);color:var(--accent)}.insights-error-callout{display:flex;align-items:center;gap:var(--space-sm);margin:0 var(--space-lg) var(--space-md);padding:var(--space-md);background:color-mix(in srgb,var(--color-error) 10%,transparent);border:1px solid color-mix(in srgb,var(--color-error) 30%,transparent);border-radius:var(--radius-md);color:var(--color-error);font-size:.8125rem;flex-shrink:0}.insights-run-info{padding:0 var(--space-lg) var(--space-md);flex-shrink:0}.insights-run-status{font-size:.75rem;color:var(--text-muted)}.insights-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-md);padding:var(--space-2xl);color:var(--text-muted)}.insights-error{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-md);padding:var(--space-2xl);text-align:center}.insights-error p{color:var(--text-muted);margin:0}.insights-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-md);padding:var(--space-2xl);text-align:center;flex:1}.insights-empty h3{margin:0;font-size:1.125rem;color:var(--text)}.insights-empty p{color:var(--text-muted);margin:0;max-width:calc(var(--space-2xl) * 12 + var(--space-lg))}.insights-body{flex:1;min-height:0;display:flex;overflow:hidden}.insights-sidebar{width:calc(var(--space-2xl) * 7 + var(--space-lg));flex-shrink:0;border-right:1px solid var(--border);background:var(--surface);overflow-y:auto;min-height:0}.insights-category-list{list-style:none;margin:0;padding:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-xs)}.insights-category-item{width:100%;display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);background:transparent;border:1px solid transparent;border-radius:var(--radius-md);color:var(--text);font:inherit;font-size:.8125rem;text-align:left;cursor:pointer;transition:background var(--transition-fast),border-color var(--transition-fast)}.insights-category-item:hover{background:var(--surface-elevated)}.insights-category-item--active{background:color-mix(in srgb,var(--accent) 12%,transparent);border-color:color-mix(in srgb,var(--accent) 35%,transparent);color:var(--accent)}.insights-category-icon{flex-shrink:0;color:var(--accent)}.insights-category-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}.insights-category-count{flex-shrink:0;font-size:.75rem;color:var(--text-muted);background:var(--surface-elevated);padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);border:1px solid var(--border)}.insights-category-item--active .insights-category-count{background:var(--surface);color:var(--accent);border-color:color-mix(in srgb,var(--accent) 30%,transparent)}.insights-detail{flex:1;min-width:0;min-height:0;overflow-y:auto;padding:var(--space-lg)}.insights-section{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden}.insights-section-header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-md) var(--space-lg);background:var(--surface);border-bottom:1px solid var(--border)}.insights-section-title{display:flex;align-items:center;gap:var(--space-sm)}.insights-section-title h3{margin:0;font-size:.9375rem;font-weight:600}.insights-section-icon{color:var(--accent)}.insights-section-count{font-size:.75rem;color:var(--text-muted);background:var(--surface-elevated);padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);border:1px solid var(--border)}.insights-section-content{padding:var(--space-md)}.insights-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-md)}.insight-item{padding:var(--space-md);background:var(--surface);border:1px solid var(--border);border-left:var(--space-xs) solid var(--accent);border-radius:var(--radius-md);transition:border-color var(--transition-fast)}.insight-item:hover{border-color:var(--accent)}.insight-item-header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-sm)}.insight-item-title{margin:0;font-size:.875rem;font-weight:600;color:var(--text);line-height:1.4}.insight-item-actions{display:flex;align-items:center;gap:var(--space-xs);flex-shrink:0}.insight-item-action-btn{display:inline-flex;align-items:center;justify-content:center;width:calc(var(--space-lg) * 2);height:calc(var(--space-lg) * 2);padding:0;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.insight-item-action-btn:hover:not(:disabled){background:var(--surface-elevated);color:var(--accent)}.insight-item-action-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.insight-item-action-btn:disabled{opacity:.5;cursor:not-allowed}.insight-item-content{margin:var(--space-sm) 0 0;font-size:.8125rem;color:var(--text-muted);line-height:1.5;white-space:pre-wrap;word-break:break-word}.insight-item-meta{display:flex;align-items:center;gap:var(--space-md);margin-top:var(--space-sm);font-size:.75rem;color:var(--text-muted)}.insight-item-status{padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-sm);text-transform:capitalize;font-weight:500}.insight-item-status--generated{background:color-mix(in srgb,var(--accent) 15%,transparent);color:var(--accent)}.insight-item-status--confirmed{background:color-mix(in srgb,var(--color-success) 15%,transparent);color:var(--color-success)}.insight-item-status--stale{background:color-mix(in srgb,var(--color-warning) 15%,transparent);color:var(--color-warning)}.insight-item-status--dismissed,.insight-item-status--archived{background:color-mix(in srgb,var(--text-dim) 15%,transparent);color:var(--text-dim)}.insight-item--archived{opacity:.6;border-left-color:var(--text-dim)}.insight-item--archived .insight-item-title{text-decoration:line-through;color:var(--text-muted)}.insight-item--archived .insight-item-content{text-decoration:line-through}.insight-item-date{display:flex;align-items:center;gap:var(--space-xs)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.spin{animation:spin 1s linear infinite}@media(max-width:768px){.insights-view-header{flex-wrap:nowrap;gap:var(--space-sm);padding:var(--space-md)}.insights-view-title{min-width:0;flex:1 1 auto}.insights-view-title h2{font-size:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.insights-view-actions{flex-shrink:0;justify-content:flex-end;flex-wrap:nowrap;gap:var(--space-xs)}.insights-body{flex-direction:column}.insights-sidebar{width:100%;border-right:none;border-bottom:1px solid var(--border);overflow-x:auto;overflow-y:hidden;flex-shrink:0}.insights-category-list{flex-direction:row;flex-wrap:nowrap;padding:var(--space-sm);gap:var(--space-xs)}.insights-category-list>li{flex-shrink:0}.insights-category-item{white-space:nowrap;padding:var(--space-xs) var(--space-sm)}.insights-category-label{overflow:visible;text-overflow:clip}.insights-detail{padding:var(--space-md)}.insights-section-header{padding:var(--space-sm) var(--space-md)}.insights-section-content,.insight-item{padding:var(--space-sm)}.insight-item-title{word-break:break-word}.insight-item-header{flex-direction:column;gap:var(--space-sm)}.insight-item-meta{flex-wrap:wrap;gap:var(--space-sm)}.insight-item-actions{align-self:flex-end}.insight-item-action-btn{width:calc(var(--space-2xl) + var(--space-sm));height:calc(var(--space-2xl) + var(--space-sm))}.insights-view-actions .btn{min-height:calc(var(--space-2xl) + var(--space-xs))}.insights-show-archived-toggle{max-width:calc(var(--space-2xl) * 5 + var(--space-md));white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.insights-view-close{min-height:calc(var(--space-2xl) + var(--space-xs));min-width:calc(var(--space-2xl) + var(--space-xs))}.insights-view-count{font-size:.75rem}}
@@ -1,11 +0,0 @@
1
- import{r,j as s}from"./vendor-react-K0fH_qHe.js";import{c as os,aj as vs,ak as xs,al as fs,am as ps,an as ys,ao as is,ap as ws,aq as y,X as as,ar as J,R as w,C as hs,as as Y,at as ns,au as bs,Q as us,av as js,aw as ds,ax as ks}from"./index-D__RMku8.js";import{U as rs}from"./users-Dkd4rtrN.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 Ns=[["path",{d:"M12 10h.01",key:"1nrarc"}],["path",{d:"M12 14h.01",key:"1etili"}],["path",{d:"M12 6h.01",key:"1vi96p"}],["path",{d:"M16 10h.01",key:"1m94wz"}],["path",{d:"M16 14h.01",key:"1gbofw"}],["path",{d:"M16 6h.01",key:"1x0f13"}],["path",{d:"M8 10h.01",key:"19clt8"}],["path",{d:"M8 14h.01",key:"6423bh"}],["path",{d:"M8 6h.01",key:"1dz90k"}],["path",{d:"M9 22v-3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v3",key:"cabbwy"}],["rect",{x:"4",y:"2",width:"16",height:"20",rx:"2",key:"1uxh74"}]],Ss=os("building",Ns);/**
7
- * @license lucide-react v1.7.0 - ISC
8
- *
9
- * This source code is licensed under the ISC license.
10
- * See the LICENSE file in the root directory of this source tree.
11
- */const Cs=[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16",key:"c24i48"}],["path",{d:"m19 9-5 5-4-4-3 3",key:"2osh9i"}]],Ms=os("chart-line",Cs),X=["architecture","quality","workflow","performance","reliability","security","ux","testability","documentation","dependency","features","competitive_analysis","research","trends","other"],cs={quality:"Quality",performance:"Performance",architecture:"Architecture",security:"Security",reliability:"Reliability",ux:"User Experience",testability:"Testability",documentation:"Documentation",dependency:"Dependencies",workflow:"Workflow",other:"Other",features:"Features",competitive_analysis:"Competitive Analysis",research:"Research",trends:"Trends"};function As(u){const[o,f]=r.useState([]),[b,L]=r.useState(()=>X.map(t=>({category:t,label:cs[t]??t,items:[],isLoading:!1,error:null}))),[I,E]=r.useState(!0),[m,F]=r.useState(null),[U,z]=r.useState(null),[G,$]=r.useState(!1),[_,k]=r.useState(null),[O,R]=r.useState(new Map),[T,N]=r.useState(new Map),[q,S]=r.useState(new Map),[B,C]=r.useState(new Map),[M,A]=r.useState(!1),c=r.useCallback(async()=>{E(!0),F(null);try{const t=await vs({status:void 0,limit:1e3},u);f(t.insights.filter(i=>i.status!=="dismissed"));const e=await xs(u);e.runs.length>0&&z(e.runs[0])}catch(t){const e=t instanceof Error?t.message:"Failed to fetch insights";F(e)}finally{E(!1)}},[u]),j=r.useCallback(()=>{A(t=>!t)},[]),h=r.useCallback(async()=>{$(!0),k(null);try{const t=await fs("manual",void 0,u);z(t),t.status==="completed"?await c():t.status==="failed"&&t.error&&k(t.error)}catch(t){const e=t instanceof Error?t.message:"Failed to generate insights";throw k(e),t}finally{$(!1)}},[u,c]),v=r.useCallback(async t=>{R(e=>{const i=new Map(e);return i.set(t,{running:!0,error:null}),i});try{await ps(t,u),f(e=>e.filter(i=>i.id!==t)),R(e=>{const i=new Map(e);return i.set(t,{running:!1,error:null}),i})}catch(e){const i=e instanceof Error?e.message:"Failed to dismiss insight";throw R(d=>{const n=new Map(d);return n.set(t,{running:!1,error:i}),n}),e}},[u]),p=r.useCallback(async t=>{N(e=>{const i=new Map(e);return i.set(t,{running:!0,error:null}),i});try{const e=await ys(t,u);return await is(t,u),f(i=>i.map(d=>d.id===t?{...d,status:"archived",updatedAt:new Date().toISOString()}:d)),N(i=>{const d=new Map(i);return d.set(t,{running:!1,error:null}),d}),{title:e.suggestedTitle,description:e.suggestedDescription}}catch(e){const i=e instanceof Error?e.message:"Failed to create task";throw N(d=>{const n=new Map(d);return n.set(t,{running:!1,error:i}),n}),e}},[u]);r.useEffect(()=>{const t=new Map;for(const e of X)t.set(e,[]);for(const e of o){if(!M&&e.status==="archived")continue;const i=t.get(e.category)??[];t.set(e.category,[...i,e])}L(X.map(e=>({category:e,label:cs[e]??e,items:t.get(e)??[],isLoading:!1,error:null})))},[o,M]);const D=r.useCallback(async t=>{S(e=>{const i=new Map(e);return i.set(t,{running:!0,error:null}),i});try{await is(t,u),f(e=>e.map(i=>i.id===t?{...i,status:"archived",updatedAt:new Date().toISOString()}:i)),S(e=>{const i=new Map(e);return i.set(t,{running:!1,error:null}),i})}catch(e){const i=e instanceof Error?e.message:"Failed to archive insight";throw S(d=>{const n=new Map(d);return n.set(t,{running:!1,error:i}),n}),e}},[u]),x=r.useCallback(async t=>{C(e=>{const i=new Map(e);return i.set(t,{running:!0,error:null}),i});try{await ws(t,u),f(e=>e.map(i=>i.id===t?{...i,status:"confirmed",updatedAt:new Date().toISOString()}:i)),C(e=>{const i=new Map(e);return i.set(t,{running:!1,error:null}),i})}catch(e){const i=e instanceof Error?e.message:"Failed to unarchive insight";throw C(d=>{const n=new Map(d);return n.set(t,{running:!1,error:i}),n}),e}},[u]),H=r.useMemo(()=>b.reduce((t,e)=>t+e.items.length,0),[b]),V=r.useMemo(()=>0,[]),W=r.useMemo(()=>o.filter(t=>t.status==="archived").length,[o]);return r.useEffect(()=>{c()},[c]),{sections:b,loading:I,error:m,latestRun:U,isRunInFlight:G,runError:_,refresh:c,runInsights:h,dismiss:v,createTask:p,archive:D,unarchive:x,toggleShowArchived:j,dismissStates:O,createTaskStates:T,archiveStates:q,unarchiveStates:B,totalCount:H,dismissedCount:V,archivedCount:W,showArchived:M}}const ls={architecture:Ss,quality:hs,workflow:ds,performance:ns,reliability:w,security:Y,ux:rs,testability:J,documentation:js,dependency:us,features:bs,competitive_analysis:rs,research:Ms,trends:ns,other:y};function $s({projectId:u,addToast:o,onClose:f,onCreateTask:b}){const{sections:L,loading:I,error:E,latestRun:m,isRunInFlight:F,runError:U,refresh:z,runInsights:G,dismiss:$,createTask:_,archive:k=async()=>{},unarchive:O=async()=>{},toggleShowArchived:R=()=>{},dismissStates:T,createTaskStates:N,archiveStates:q=new Map,unarchiveStates:S=new Map,totalCount:B,archivedCount:C=0,showArchived:M=!1}=As(u),[A,c]=r.useState(null),[j,h]=r.useState("info"),v=r.useMemo(()=>L.filter(n=>n.items.length>0),[L]),[p,D]=r.useState(null);r.useEffect(()=>{if(v.length===0){p!==null&&D(null);return}p&&v.some(a=>a.category===p)||D(v[0].category)},[v,p]);const x=r.useMemo(()=>v.find(n=>n.category===p)??v[0],[v,p]);r.useEffect(()=>{if(A){const n=setTimeout(()=>c(null),5e3);return()=>clearTimeout(n)}},[A]);const H=r.useCallback(async()=>{try{c("Generating insights..."),h("info"),await G(),c("Insight generation started"),h("success"),o("Insight generation started","success")}catch(n){const a=n instanceof Error?n.message:"Failed to start generation";c(a),h("error"),o(a,"error")}},[G,o]),V=r.useCallback(async(n,a)=>{try{c(`Dismissing "${a}"...`),h("info"),await $(n),c(`Dismissed "${a}"`),h("success"),o(`Insight dismissed: ${a}`,"success")}catch(l){const g=l instanceof Error?l.message:"Failed to dismiss insight";c(g),h("error"),o(g,"error")}},[$,o]),W=r.useCallback(async(n,a)=>{try{c(`Archiving "${a}"...`),h("info"),await k(n),c(`Archived "${a}"`),h("success"),o(`Insight archived: ${a}`,"success")}catch(l){const g=l instanceof Error?l.message:"Failed to archive insight";c(g),h("error"),o(g,"error")}},[k,o]),t=r.useCallback(async(n,a)=>{try{c(`Unarchiving "${a}"...`),h("info"),await O(n),c(`Unarchived "${a}"`),h("success"),o(`Insight unarchived: ${a}`,"success")}catch(l){const g=l instanceof Error?l.message:"Failed to unarchive insight";c(g),h("error"),o(g,"error")}},[O,o]),e=r.useCallback(async(n,a)=>{try{if(c(`Creating task from "${a}"...`),h("info"),!b)throw new Error("Task creation is unavailable in this view");const l=await _(n);if(!l)throw new Error("Failed to prepare task payload from insight");await b({insightId:n,title:l.title,description:l.description}),c(`Task created from "${a}"`),h("success"),o(`Task created: ${l.title}`,"success")}catch(l){const g=l instanceof Error?l.message:"Failed to create task";c(g),h("error"),o(g,"error")}},[_,b,o]),i=n=>{const a=ls[n.category]??y,l=x?.category===n.category;return s.jsx("li",{children:s.jsxs("button",{type:"button",className:`insights-category-item${l?" insights-category-item--active":""}`,onClick:()=>D(n.category),"aria-current":l?"true":void 0,"data-testid":`insights-category-${n.category}`,children:[s.jsx(a,{size:16,className:"insights-category-icon"}),s.jsx("span",{className:"insights-category-label",children:n.label}),s.jsx("span",{className:"insights-category-count",children:n.items.length})]})},n.category)},d=()=>{if(!x)return null;const n=ls[x.category]??y;return s.jsxs("section",{className:"insights-section","data-testid":`insights-section-${x.category}`,children:[s.jsx("div",{className:"insights-section-header",children:s.jsxs("div",{className:"insights-section-title",children:[s.jsx(n,{size:20,className:"insights-section-icon"}),s.jsx("h3",{children:x.label}),s.jsx("span",{className:"insights-section-count",children:x.items.length})]})}),s.jsx("div",{className:"insights-section-content",children:s.jsx("ul",{className:"insights-list",children:x.items.map(a=>{const l=T.get(a.id),g=N.get(a.id),gs=q.get(a.id),ms=S.get(a.id),K=l?.running??!1,Z=g?.running??!1,ss=gs?.running??!1,es=ms?.running??!1,ts=a.status==="archived",P=x.items.some(Q=>T.get(Q.id)?.running||N.get(Q.id)?.running||q.get(Q.id)?.running||S.get(Q.id)?.running);return s.jsxs("li",{className:`insight-item${ts?" insight-item--archived":""}`,"data-insight-id":a.id,children:[s.jsxs("div",{className:"insight-item-header",children:[s.jsx("h4",{className:"insight-item-title",children:a.title}),s.jsxs("div",{className:"insight-item-actions",children:[ts?s.jsx("button",{className:"insight-item-action-btn",onClick:()=>void t(a.id,a.title),disabled:es||P,title:"Unarchive this insight","aria-label":"Unarchive this insight","data-testid":`unarchive-${a.id}`,children:es?s.jsx(w,{size:20,className:"spin"}):s.jsx(ks,{size:20})}):s.jsxs(s.Fragment,{children:[s.jsx("button",{className:"insight-item-action-btn",onClick:()=>void e(a.id,a.title),disabled:Z||P,title:"Create task from this insight","aria-label":"Create task from this insight","data-testid":`create-task-${a.id}`,children:Z?s.jsx(w,{size:20,className:"spin"}):s.jsx(us,{size:20})}),s.jsx("button",{className:"insight-item-action-btn",onClick:()=>void W(a.id,a.title),disabled:ss||P,title:"Archive this insight","aria-label":"Archive this insight","data-testid":`archive-${a.id}`,children:ss?s.jsx(w,{size:20,className:"spin"}):s.jsx(J,{size:20})})]}),s.jsx("button",{className:"insight-item-action-btn",onClick:()=>void V(a.id,a.title),disabled:K||P,title:"Dismiss this insight","aria-label":"Dismiss this insight","data-testid":`dismiss-${a.id}`,children:K?s.jsx(w,{size:20,className:"spin"}):s.jsx(as,{size:20})})]})]}),a.content&&s.jsx("p",{className:"insight-item-content",children:a.content}),s.jsxs("div",{className:"insight-item-meta",children:[s.jsx("span",{className:`insight-item-status insight-item-status--${a.status}`,children:a.status}),a.createdAt&&s.jsxs("span",{className:"insight-item-date",children:[s.jsx(ds,{size:12}),new Date(a.createdAt).toLocaleDateString()]})]})]},a.id)})})})]})};return s.jsxs("div",{className:"insights-view","data-testid":"insights-view",children:[s.jsxs("div",{className:"insights-view-header",children:[s.jsxs("div",{className:"insights-view-title",children:[s.jsxs("h2",{children:[s.jsx(y,{size:20}),"Insights"]}),s.jsxs("span",{className:"insights-view-count",children:[B," total"]})]}),s.jsxs("div",{className:"insights-view-actions",children:[f&&s.jsx("button",{className:"btn btn-sm insights-view-close",onClick:f,"aria-label":"Close insights view",title:"Close",children:s.jsx(as,{size:16})}),C>0&&s.jsxs("button",{className:"btn btn-sm insights-show-archived-toggle",onClick:R,"aria-label":M?"Hide archived insights":"Show archived insights","data-testid":"toggle-archived-insights",children:[s.jsx(J,{size:14}),M?"Hide Archived":`Show Archived (${C})`]}),s.jsxs("button",{className:"btn btn-sm",onClick:()=>void z(),disabled:I,"aria-label":"Refresh insights","data-testid":"refresh-insights",children:[s.jsx(w,{size:14,className:I?"spin":""}),"Refresh"]}),s.jsx("button",{className:"btn btn-primary btn-sm",onClick:()=>void H(),disabled:F,"aria-label":"Generate new insights","data-testid":"run-insights",children:F?s.jsxs(s.Fragment,{children:[s.jsx(w,{size:14,className:"spin"}),"Generating..."]}):s.jsxs(s.Fragment,{children:[s.jsx(y,{size:14}),"Generate Insights"]})})]})]}),s.jsx("div",{className:"insights-status-region","aria-live":"polite","data-testid":"insights-status",children:A&&s.jsxs("div",{className:`insights-status-message insights-status-message--${j}`,role:j==="error"?"alert":void 0,children:[j==="success"&&s.jsx(hs,{size:16}),j==="error"&&s.jsx(Y,{size:16}),j==="info"&&s.jsx(y,{size:16}),s.jsx("span",{children:A})]})}),U&&s.jsxs("div",{className:"insights-error-callout",role:"alert","data-testid":"run-error",children:[s.jsx(Y,{size:16}),s.jsx("span",{children:U})]}),m&&s.jsx("div",{className:"insights-run-info","data-testid":"latest-run",children:s.jsxs("span",{className:"insights-run-status",children:["Latest run: ",m.status,m.status==="completed"&&s.jsxs(s.Fragment,{children:[" — ",m.insightsCreated," created, ",m.insightsUpdated," updated"]}),m.status==="failed"&&m.error&&s.jsxs(s.Fragment,{children:[" — ",m.error]})]})}),I?s.jsxs("div",{className:"insights-loading","data-testid":"insights-loading",children:[s.jsx(w,{size:24,className:"spin"}),s.jsx("p",{children:"Loading insights..."})]}):E?s.jsxs("div",{className:"insights-error","data-testid":"insights-error",children:[s.jsx(Y,{size:24}),s.jsx("p",{children:E}),s.jsx("button",{className:"btn btn-sm",onClick:()=>void z(),children:"Retry"})]}):B===0?s.jsxs("div",{className:"insights-empty","data-testid":"insights-empty",children:[s.jsx(y,{size:48}),s.jsx("h3",{children:"No insights yet"}),s.jsx("p",{children:"Generate insights to get AI-powered recommendations for your project."}),s.jsxs("button",{className:"btn btn-primary",onClick:()=>void H(),children:[s.jsx(y,{size:14}),"Generate First Insights"]})]}):s.jsxs("div",{className:"insights-body",children:[s.jsx("aside",{className:"insights-sidebar","aria-label":"Insight categories",children:s.jsx("ul",{className:"insights-category-list",children:v.map(i)})}),s.jsx("div",{className:"insights-detail",children:d()})]})]})}export{$s as InsightsView};
@@ -1,14 +0,0 @@
1
- import{r as s,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Ie,aJ as os,aK as cs,aL as is,aM as ds,aN as Ve,aO as ye,aP as Ke,A as Fe,aQ as us,$ as Oe,aR as Ue,aS as ms,a1 as ve,u as hs,R as _e,a as we,Q as me,aT as Te,aU as fs,aV as Le,X as ue,ad as gs,ae as xs,aW as $e,F as ps,aX as De,aY as js,aZ as bs,a_ as ys,a$ as vs,b0 as _s,G as Ns}from"./index-D__RMku8.js";import{U as Be}from"./upload-BC2YKNEV.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 ks=[["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"}]],Cs=Ie("wifi-off",ks);/**
7
- * @license lucide-react v1.7.0 - ISC
8
- *
9
- * This source code is licensed under the ISC license.
10
- * See the LICENSE file in the root directory of this source tree.
11
- */const Ss=[["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"}]],ws=Ie("wifi",Ss);function pe(t){const{lastSyncAt:n,remoteReachable:a,diff:i}=t,u=i.global.length+i.project.length;return n===null?{syncState:"never-synced",lastSyncAt:n,diffCount:0}:a?u>0?{syncState:"diff",lastSyncAt:n,diffCount:u}:{syncState:"synced",lastSyncAt:n,diffCount:0}:{syncState:"error",lastSyncAt:n,diffCount:u}}function Ne(t){if(t===null)return"Never synced";const n=new Date(t);if(Number.isNaN(n.getTime()))return"Never synced";const i=Date.now()-n.getTime(),u=Math.floor(i/1e3),g=Math.floor(u/60),o=Math.floor(g/60),p=Math.floor(o/24);return g<1?"Synced just now":g<60?`Synced ${g}m ago`:o<24?`Synced ${o}h ago`:`Synced ${p}d ago`}function Ms(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 Ps=3e4;function Es(){const[t,n]=s.useState({}),[a,i]=s.useState(!1),[u,g]=s.useState({}),[o,p]=s.useState(null),d=s.useRef(new Set),b=s.useRef(!1),N=s.useRef(null),P=s.useRef(null),y=s.useCallback(async(x,m)=>{try{const C=await os(x);n(B=>({...B,[x]:C})),p(null)}catch(C){console.error(`Failed to fetch sync status for node ${x}:`,C),p(C instanceof Error?C.message:"Failed to fetch sync status")}},[]),c=s.useCallback(async()=>{const x=Array.from(d.current);if(x.length===0)return;N.current&&N.current.abort(),N.current=new AbortController;const m=!b.current;m&&i(!0),p(null);try{const C=await Promise.allSettled(x.map(H=>y(H,m)));b.current=!0,C.filter(H=>H.status==="rejected").length>0&&p("Some sync status requests failed")}catch(C){if(C instanceof Error&&C.name==="AbortError")return;p(C instanceof Error?C.message:"Failed to fetch sync status"),b.current=!0}finally{i(!1)}},[y]),w=s.useCallback(()=>{P.current&&clearInterval(P.current),P.current=setInterval(()=>{c()},Ps)},[c]),v=s.useCallback(()=>{P.current&&(clearInterval(P.current),P.current=null)},[]);s.useEffect(()=>(c(),w(),()=>{v(),N.current&&N.current.abort()}),[c,w,v]);const l=s.useCallback(x=>{d.current.has(x)||(d.current.add(x),y(x,!b.current))},[y]),j=s.useCallback(x=>{d.current.delete(x),n(m=>{const C={...m};return delete C[x],C}),d.current.size===0&&v()},[v]),_=s.useCallback(async x=>{g(m=>({...m,[x]:!0})),p(null);try{const m=await cs(x);return y(x,!1),!m.success&&m.error&&p(m.error),m}catch(m){const C=m instanceof Error?m.message:"Push settings failed";throw p(C),m}finally{g(m=>{const C={...m};return delete C[x],C})}},[y]),k=s.useCallback(async x=>{g(m=>({...m,[x]:!0})),p(null);try{const m=await is(x);return y(x,!1),!m.success&&m.error&&p(m.error),m}catch(m){const C=m instanceof Error?m.message:"Pull settings failed";throw p(C),m}finally{g(m=>{const C={...m};return delete C[x],C})}},[y]),L=s.useCallback(async x=>{g(m=>({...m,[x]:!0})),p(null);try{return await ds(x)}catch(m){const C=m instanceof Error?m.message:"Auth sync failed";throw p(C),m}finally{g(m=>{const C={...m};return delete C[x],C})}},[]),E=s.useCallback(x=>t[x]?.authMatch,[t]),V=s.useCallback(x=>t[x]?.authDiff,[t]);return{syncStatusMap:t,loading:a,actionLoading:u,error:o,refresh:c,trackNode:l,untrackNode:j,pushSettings:_,pullSettings:k,syncAuth:L,getAuthSyncState:E,getAuthProviders:V}}function Rs(t,n){return n.type==="remote"?t.nodeId===n.id:t.nodeId===n.id||t.nodeId===void 0||t.nodeId===null}function He(t,n){return t.filter(a=>Rs(a,n))}function ke(t,n){return He(t,n).length}const de={online:{label:"Online",color:"var(--color-success)",className:"node-card__status--online"},offline:{label:"Offline",color:"var(--color-error)",className:"node-card__status--offline"},connecting:{label:"Connecting",color:"var(--color-warning)",className:"node-card__status--connecting"},error:{label:"Error",color:"var(--color-error)",className:"node-card__status--error"},creating:{label:"Creating",color:"var(--color-warning)",className:"node-card__status--creating"},recreating:{label:"Recreating",color:"var(--color-warning)",className:"node-card__status--recreating"},deleting:{label:"Deleting",color:"var(--color-error)",className:"node-card__status--deleting"},running:{label:"Running",color:"var(--color-success)",className:"node-card__status--online"},stopped:{label:"Stopped",color:"var(--color-error)",className:"node-card__status--offline"},exited:{label:"Exited",color:"var(--color-error)",className:"node-card__status--offline"}},As={match:"var(--color-success)",differs:"var(--color-warning)","not-synced":"var(--text-muted)"};function Ls(t,n){if(t==="match")return"Auth credentials match";if(t==="not-synced")return"Auth not synced";if(n&&Object.keys(n).length>0){const a=Object.entries(n).filter(([,i])=>i==="differs").map(([i])=>i);if(a.length>0)return`Auth credentials differ: ${a.join(", ")}`}return"Auth credentials differ"}function $s(t,n=42){return t.length<=n?t:`${t.slice(0,n-3)}...`}function Ds(t,n){const a=t.node,i=n.node;if(a.id!==i.id||a.name!==i.name||a.type!==i.type||a.url!==i.url||a.status!==i.status||a.maxConcurrent!==i.maxConcurrent||a.updatedAt!==i.updatedAt||t.isLoading!==n.isLoading)return!1;const u=t.managedDockerNode,g=n.managedDockerNode;if(!!u!=!!g||u&&g&&(u.id!==g.id||u.status!==g.status||u.imageTag!==g.imageTag||u.updatedAt!==g.updatedAt))return!1;const o=t.syncStatus,p=n.syncStatus;if(!(!o&&!p)){if(!o||!p)return!1;if(o.syncState!==p.syncState||o.lastSyncAt!==p.lastSyncAt||o.diffCount!==p.diffCount)return!1}if(t.authSyncState!==n.authSyncState)return!1;const d=t.authSyncProviders,b=n.authSyncProviders;if(d!==b){if(!d||!b)return!1;{const y=Object.keys(d),c=Object.keys(b);if(y.length!==c.length||y.some(w=>d[w]!==b[w]))return!1}}const N=ke(t.projects,a),P=ke(n.projects,i);return N===P}function zs({node:t,projects:n,onHealthCheck:a,onEdit:i,onRemove:u,isLoading:g=!1,syncStatus:o,authSyncState:p,authSyncProviders:d,managedDockerNode:b}){const[N,P]=s.useState(!1),y=de[t.status]??de.offline,c=b?de[b.status]??de.error:null,w=b?.hostConfig.type==="remote"?`Remote: ${b.hostConfig.host??"unknown"}`:"Local Docker",v=s.useMemo(()=>ke(n,t),[n,t]),l=s.useCallback(()=>{i(t)},[i,t]),j=s.useCallback(E=>{E.stopPropagation(),a(t.id)},[a,t.id]),_=s.useCallback(E=>{E.stopPropagation(),i(t)},[i,t]),k=s.useCallback(E=>{if(E.stopPropagation(),!N){P(!0);return}u(t.id),P(!1)},[N,u,t.id]),L=s.useCallback(E=>{(E.key==="Enter"||E.key===" ")&&(E.preventDefault(),i(t))},[i,t]);return e.jsxs("article",{className:`node-card ${g?"node-card--loading":""}`,"data-node-id":t.id,role:"button",tabIndex:0,onClick:l,onKeyDown:L,children:[e.jsx("header",{className:"node-card__header",children:e.jsxs("div",{className:"node-card__title-wrap",children:[e.jsx("div",{className:"node-card__icon",children:e.jsx(Ve,{size:18})}),e.jsxs("div",{children:[e.jsx("h3",{className:"node-card__name",title:t.name,children:t.name}),e.jsxs("div",{className:"node-card__meta-row",children:[e.jsx("span",{className:"node-card__type-badge",children:t.type==="local"?"Local":"Remote"}),b&&e.jsxs("span",{className:"node-card__docker-badge",title:"Managed Docker node",children:[e.jsx(ye,{size:12,"aria-hidden":!0}),"Docker"]}),e.jsxs("span",{className:`node-card__status ${y.className}`,style:{color:y.color},"data-status":t.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:y.color},"aria-hidden":!0}),y.label]}),b&&c&&e.jsxs("span",{className:`node-card__status ${c.className}`,style:{color:c.color},"data-status":b.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:c.color},"aria-hidden":!0}),c.label]}),t.type==="remote"&&p&&e.jsx("span",{className:`node-card__auth-indicator node-card__auth-indicator--${p}`,title:Ls(p,d),"aria-label":`Auth sync: ${p==="match"?"credentials match":p==="differs"?"credentials differ":"not synced"}`,style:{color:As[p]},children:e.jsx(Ke,{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:$s(t.url)}),b&&e.jsxs("div",{className:"node-card__docker-meta",children:[e.jsxs("span",{title:`${b.imageName}:${b.imageTag}`,children:[b.imageName,":",b.imageTag]}),e.jsx("span",{title:w,children:w})]}),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:v})]}),e.jsxs("div",{className:"node-card__metric",children:[e.jsx("span",{className:"node-card__metric-label",children:"Concurrency"}),e.jsx("span",{className:"node-card__metric-value",children:t.maxConcurrent})]})]}),t.type==="remote"&&o&&e.jsxs("div",{className:"node-card__sync","data-sync-state":o.syncState,"data-testid":"node-card-sync",children:[e.jsx("span",{className:"node-card__sync-dot",style:{backgroundColor:Ms(o.syncState)},"aria-hidden":!0}),e.jsx("span",{className:"node-card__sync-time",children:Ne(o.lastSyncAt)})]})]}),e.jsxs("footer",{className:"node-card__actions",children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:j,disabled:g,"aria-label":"Run node health check",title:"Health Check",children:[e.jsx(Fe,{size:14}),e.jsx("span",{children:"Health"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:_,disabled:g,"aria-label":"Edit node",title:"Edit",children:[e.jsx(us,{size:14}),e.jsx("span",{children:"Edit"})]}),b&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",disabled:!0,"aria-label":"Start node container",title:"Available after FN-3113",children:[e.jsx(Oe,{size:14}),e.jsx("span",{children:"Start"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",disabled:!0,"aria-label":"Stop node container",title:"Available after FN-3113",children:[e.jsx(Ue,{size:14}),e.jsx("span",{children:"Stop"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",disabled:!0,"aria-label":"Restart node container",title:"Available after FN-3113",children:[e.jsx(ms,{size:14}),e.jsx("span",{children:"Restart"})]})]}),e.jsxs("button",{className:`btn btn-sm node-card__action node-card__action--remove ${N?"btn-danger is-armed":""}`,type:"button",onClick:k,disabled:g,"aria-label":N?"Confirm remove node":"Remove node",title:N?"Confirm remove":"Remove",children:[e.jsx(ve,{size:14}),e.jsx("span",{children:N?"Confirm":"Remove"})]})]})]})}const Is=s.memo(zs,Ds),ce={online:"var(--success, var(--color-success))",offline:"var(--text-dim)",connecting:"var(--triage)",error:"var(--color-error)"},le=28,ze=12,Vs=300,Ks=120;function Fs({nodes:t,className:n}){const a=s.useMemo(()=>t.find(d=>d.type==="local")??t[0],[t]),i=s.useMemo(()=>t.filter(d=>d.type==="remote"),[t]),u=s.useMemo(()=>{const d=Vs,b=Math.max(0,i.length-4)*20;return d+b},[i.length]),g=u/2,o=u/2,p=s.useMemo(()=>{if(i.length===0)return[];const d=Math.min(Ks,u/2-le-10),b=2*Math.PI/i.length,N=-Math.PI/2;return i.map((P,y)=>{const c=N+y*b;return{node:P,x:g+d*Math.cos(c),y:o+d*Math.sin(c)}})},[i,u,g,o]);return t.length===0?e.jsx("div",{className:`mesh-topology mesh-topology--empty ${n??""}`,children:e.jsx("div",{className:"mesh-topology__empty-state",children:e.jsx("p",{children:"No nodes to display"})})}):e.jsxs("div",{className:`mesh-topology ${n??""}`,children:[e.jsxs("svg",{className:"mesh-topology__svg",viewBox:`0 0 ${u} ${u}`,preserveAspectRatio:"xMidYMid meet","aria-label":"Node mesh topology visualization",children:[p.map(d=>e.jsx("line",{className:"mesh-topology__link",x1:g,y1:o,x2:d.x,y2:d.y},`link-${d.node.id}`)),a&&e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${g}, ${o})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:le,fill:ce[a.status],"aria-label":`${a.name} (${a.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:le+ze,textAnchor:"middle",children:a.name.length>12?`${a.name.slice(0,10)}…`:a.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-le-10})`,children:[e.jsx("circle",{className:"mesh-topology__node-type-badge",r:"8"}),e.jsx("text",{className:"mesh-topology__node-type-text",textAnchor:"middle",dominantBaseline:"middle",children:a.type==="local"?"L":"R"})]})]}),p.map(d=>e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${d.x}, ${d.y})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:le,fill:ce[d.node.status],"aria-label":`${d.node.name} (${d.node.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:le+ze,textAnchor:"middle",children:d.node.name.length>12?`${d.node.name.slice(0,10)}…`:d.node.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-le-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:d.node.type==="local"?"L":"R"})]})]},d.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:ce.online}}),e.jsx("span",{children:"Online"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.offline}}),e.jsx("span",{children:"Offline"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.connecting}}),e.jsx("span",{children:"Connecting"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.error}}),e.jsx("span",{children:"Error"})]})]}),e.jsx("p",{className:"mesh-topology__notice",children:"Peer-to-peer discovery data unavailable."})]})}const Os=s.memo(Fs),Ce=1,Se=10;function Us(t){const n={};return t.name.trim()||(n.name="Name is required"),t.type==="remote"&&!t.url?.trim()&&(n.url="URL is required for remote nodes"),(!Number.isFinite(t.maxConcurrent)||t.maxConcurrent<Ce||t.maxConcurrent>Se)&&(n.maxConcurrent=`Concurrency must be between ${Ce} and ${Se}`),n}function Ts({isOpen:t,onClose:n,onSubmit:a,addToast:i}){hs(t);const[u,g]=s.useState(""),[o,p]=s.useState("local"),[d,b]=s.useState(""),[N,P]=s.useState(""),[y,c]=s.useState(2),[w,v]=s.useState("auto-generate"),[l,j]=s.useState({}),[_,k]=s.useState(!1),L=s.useCallback(()=>{g(""),p("local"),b(""),P(""),c(2),v("auto-generate"),j({}),k(!1)},[]),E=s.useCallback(()=>{_||(L(),n())},[_,n,L]);s.useEffect(()=>{if(!t){L();return}const m=C=>{C.key==="Escape"&&(C.preventDefault(),E())};return document.addEventListener("keydown",m),()=>{document.removeEventListener("keydown",m)}},[E,t,L]);const V=s.useMemo(()=>({name:u.trim(),type:o,url:o==="remote"&&d.trim()||void 0,apiKey:o==="remote"&&w==="provide"&&N||void 0,maxConcurrent:y,apiKeyMode:w}),[N,w,y,u,o,d]),x=s.useCallback(async()=>{if(_)return;const m=Us(V);if(j(m),!(Object.keys(m).length>0)){k(!0);try{await a(V),i(`Node "${V.name}" registered`,"success"),E()}catch(C){const B=C instanceof Error?C.message:"Failed to register node";i(B,"error")}finally{k(!1)}}},[i,E,V,_,a]);return t?e.jsx("div",{className:"modal-overlay open",onClick:E,children:e.jsxs("div",{className:"modal modal-md add-node-modal",onClick:m=>m.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Add Node",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Add Node"}),e.jsx("button",{className:"modal-close",onClick:E,disabled:_,"aria-label":"Close add node modal",children:"×"})]}),e.jsxs("div",{className:"modal-body add-node-modal__body",children:[e.jsx("p",{className:"add-node-modal__description",children:"Register an existing Fusion node by providing its connection details and concurrency settings."}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Name"}),e.jsx("input",{className:"input",type:"text",value:u,onChange:m=>g(m.target.value),placeholder:"Build Machine",disabled:_,"aria-invalid":!!l.name,autoFocus:!0}),l.name&&e.jsx("span",{className:"form-error add-node-modal__error",children:l.name})]}),e.jsxs("div",{className:"add-node-modal__type-toggle",children:[e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${o==="local"?"active":""}`,"data-type":"local",onClick:()=>p("local"),disabled:_,"aria-pressed":o==="local",children:"Local"}),e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${o==="remote"?"active":""}`,"data-type":"remote",onClick:()=>p("remote"),disabled:_,"aria-pressed":o==="remote",children:"Remote"})]}),o==="remote"&&e.jsxs("div",{className:"add-node-modal__remote-fields","data-testid":"remote-fields-container","data-visible":!0,children:[e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Reachable URL / Hostname"}),e.jsx("input",{className:"input",type:"text",value:d,onChange:m=>b(m.target.value),placeholder:"https://node.example.com",disabled:_,"aria-invalid":!!l.url}),l.url&&e.jsx("span",{className:"form-error add-node-modal__error",children:l.url})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key Mode"}),e.jsxs("select",{className:"select",value:w,onChange:m=>v(m.target.value),disabled:_,children:[e.jsx("option",{value:"auto-generate",children:"Auto-generate"}),e.jsx("option",{value:"provide",children:"Provide key manually"})]})]}),w==="provide"&&e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:N,onChange:m=>P(m.target.value),placeholder:"Enter node API key",disabled:_})]})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),e.jsx("input",{className:"input",type:"number",min:Ce,max:Se,value:y,onChange:m=>c(Number(m.target.value)),disabled:_,"aria-invalid":!!l.maxConcurrent}),e.jsx("span",{className:"add-node-modal__hint",children:"Max simultaneous task agents (1–10)"}),l.maxConcurrent&&e.jsx("span",{className:"form-error add-node-modal__error",children:l.maxConcurrent})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:E,disabled:_,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm","data-testid":"add-node-submit",onClick:x,disabled:_,children:_?"Adding...":"Add Node"})]})]})}):null}function Bs(){const[t,n]=s.useState([]),[a,i]=s.useState(!1),[u,g]=s.useState(null),[o,p]=s.useState(!1),[d,b]=s.useState(null),[N,P]=s.useState(!1),y=s.useCallback(async()=>{i(!0),g(null);try{const v=await fetch("/api/docker/contexts");if(!v.ok)throw new Error(`Failed to load Docker contexts (${v.status})`);const l=await v.json();return n(l),l}catch(v){const l=v instanceof Error?v.message:String(v);throw g(l),v}finally{i(!1)}},[]),c=s.useCallback(async v=>{p(!0);try{const l=await fetch("/api/docker/test-connection",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({hostConfig:v})});if(!l.ok)throw new Error(`Failed to test Docker connection (${l.status})`);const j=await l.json();return b(j),j}finally{p(!1)}},[]),w=s.useCallback(async()=>{P(!0);try{const v=await fetch("/api/docker/local-available");if(!v.ok)throw new Error(`Failed to check local Docker availability (${v.status})`);return await v.json()}finally{P(!1)}},[]);return{contexts:t,isLoadingContexts:a,contextsError:u,loadContexts:y,isTestingConnection:o,lastTestResult:d,testConnection:c,isCheckingLocal:N,checkLocalDocker:w}}function Hs({value:t,onChange:n}){const[a,i]=s.useState(!!(t?.tlsCaPath||t?.tlsCertPath||t?.tlsKeyPath||t?.tlsVerify));s.useEffect(()=>{a||n({tlsVerify:void 0,tlsCaPath:void 0,tlsCertPath:void 0,tlsKeyPath:void 0})},[a,n]);const u=s.useMemo(()=>({tlsVerify:t?.tlsVerify??!0,tlsCaPath:t?.tlsCaPath??"",tlsCertPath:t?.tlsCertPath??"",tlsKeyPath:t?.tlsKeyPath??""}),[t]);return e.jsxs("div",{className:"docker-tls-config",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:a,onChange:g=>i(g.target.checked)}),"Use TLS"]}),a&&e.jsxs("div",{className:"docker-tls-config__fields",children:[e.jsxs("div",{className:"docker-tls-config__field",children:[e.jsx("label",{htmlFor:"docker-tls-ca-path",children:"CA Certificate Path"}),e.jsx("input",{id:"docker-tls-ca-path",className:"input",value:u.tlsCaPath,onChange:g=>n({...u,tlsCaPath:g.target.value}),placeholder:"/etc/docker/ca.pem"})]}),e.jsxs("div",{className:"docker-tls-config__field",children:[e.jsx("label",{htmlFor:"docker-tls-cert-path",children:"Client Certificate Path"}),e.jsx("input",{id:"docker-tls-cert-path",className:"input",value:u.tlsCertPath,onChange:g=>n({...u,tlsCertPath:g.target.value}),placeholder:"/etc/docker/cert.pem"})]}),e.jsxs("div",{className:"docker-tls-config__field",children:[e.jsx("label",{htmlFor:"docker-tls-key-path",children:"Client Key Path"}),e.jsx("input",{id:"docker-tls-key-path",className:"input",value:u.tlsKeyPath,onChange:g=>n({...u,tlsKeyPath:g.target.value}),placeholder:"/etc/docker/key.pem"})]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:u.tlsVerify,onChange:g=>n({...u,tlsVerify:g.target.checked})}),"Verify TLS Certificate"]})]})]})}function qs({value:t,onChange:n,onError:a}){const i=t?.context?"context":t?.host?"host":"local",[u,g]=s.useState(i),[o,p]=s.useState(t?.context??""),[d,b]=s.useState(t?.host??""),[N,P]=s.useState(null),{contexts:y,isLoadingContexts:c,contextsError:w,loadContexts:v,testConnection:l,isTestingConnection:j,lastTestResult:_,checkLocalDocker:k,isCheckingLocal:L}=Bs(),E=s.useMemo(()=>({tlsVerify:t?.tlsVerify,tlsCaPath:t?.tlsCaPath,tlsCertPath:t?.tlsCertPath,tlsKeyPath:t?.tlsKeyPath}),[t]);s.useEffect(()=>{if(u==="local"){n({});return}if(u==="context"){v().catch(x=>a?.(x instanceof Error?x.message:String(x))),n(o?{context:o}:{});return}n({host:d,...E})},[u]);const V=s.useCallback(x=>{u==="host"&&n({host:d,...x})},[d,u,n]);return e.jsxs("div",{className:"docker-target-selector",children:[e.jsxs("div",{className:"docker-target-selector__modes",role:"group","aria-label":"Docker target mode",children:[e.jsx("button",{type:"button",className:`btn btn-sm ${u==="local"?"docker-target-selector__mode-active":""}`,onClick:()=>{g("local"),k().then(x=>P(x.available?`Docker is available${x.version?` (${x.version})`:""}`:`Docker not found${x.error?`: ${x.error}`:""}`)).catch(x=>{const m=x instanceof Error?x.message:String(x);P(`Docker not found: ${m}`),a?.(m)})},children:"Local Docker"}),e.jsx("button",{type:"button",className:`btn btn-sm ${u==="context"?"docker-target-selector__mode-active":""}`,onClick:()=>g("context"),children:"Docker Context"}),e.jsx("button",{type:"button",className:`btn btn-sm ${u==="host"?"docker-target-selector__mode-active":""}`,onClick:()=>g("host"),children:"Remote Host"})]}),u==="local"&&N&&e.jsx("div",{className:"docker-target-selector__status",children:N}),u==="context"&&e.jsxs("div",{className:"docker-target-selector__panel",children:[e.jsxs("div",{className:"docker-target-selector__context-row",children:[e.jsxs("select",{className:"select",value:o,onChange:x=>{const m=x.target.value;p(m),n(m?{context:m}:{})},children:[e.jsx("option",{value:"",children:"Select context"}),y.map(x=>e.jsxs("option",{value:x.name,children:[x.name,x.isCurrentContext?" (current)":"",x.dockerHost?` — ${x.dockerHost}`:""]},x.name))]}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon",onClick:()=>void v(),disabled:c,"aria-label":"Refresh contexts",children:e.jsx(_e,{size:14})})]}),w&&e.jsx("div",{className:"docker-target-selector__error",children:w})]}),u==="host"&&e.jsxs("div",{className:"docker-target-selector__panel",children:[e.jsxs("div",{className:"docker-target-selector__field",children:[e.jsx("label",{htmlFor:"docker-target-selector-host",children:"Docker Host"}),e.jsx("input",{id:"docker-target-selector-host",className:"input",placeholder:"tcp://host:2376",value:d,onChange:x=>{const m=x.target.value;b(m),n({host:m,...E})}})]}),e.jsx(Hs,{value:E,onChange:V})]}),e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void l(u==="local"?void 0:u==="context"?{context:o}:{host:d,...E}),disabled:j||L,children:j?"Testing...":"Test Connection"}),_&&e.jsx("div",{className:_.success?"docker-target-selector__success":"docker-target-selector__error",children:_.success?`Connected${_.dockerVersion?` (Docker ${_.dockerVersion})`:""}`:_.error??"Connection failed"})]})}const je="http://localhost:4040";function Ys({isOpen:t,onClose:n,onSubmit:a,addToast:i}){const[u,g]=s.useState(""),[o,p]=s.useState({}),[d,b]=s.useState(je),[N,P]=s.useState("auto"),[y,c]=s.useState(""),[w,v]=s.useState(!1),[l,j]=s.useState(!1),[_,k]=s.useState(!0),[L,E]=s.useState(4096),[V,x]=s.useState(2),[m,C]=s.useState(!1),[B,H]=s.useState("runfusion/fusion"),[J,W]=s.useState("latest"),[D,X]=s.useState([]),[q,Q]=s.useState([]),[Y,te]=s.useState({}),[R,Z]=s.useState(!1),ee=s.useCallback(()=>{g(""),p({}),b(je),P("auto"),c(""),v(!1),j(!1),k(!0),E(4096),x(2),C(!1),H("runfusion/fusion"),W("latest"),X([]),Q([]),te({}),Z(!1)},[]),O=s.useCallback(()=>{R||(ee(),n())},[n,ee,R]);s.useEffect(()=>{if(!t){ee();return}const f=I=>{I.key==="Escape"&&(I.preventDefault(),O())};return document.addEventListener("keydown",f),()=>document.removeEventListener("keydown",f)},[O,t,ee]);const M=s.useMemo(()=>({nodeId:null,name:u.trim(),imageName:B.trim()||"runfusion/fusion",imageTag:J.trim()||"latest",hostConfig:{context:o.context?.trim()||void 0,host:o.host?.trim()||void 0,tlsVerify:o.tlsVerify,tlsCaPath:o.tlsCaPath?.trim()||void 0,tlsCertPath:o.tlsCertPath?.trim()||void 0,tlsKeyPath:o.tlsKeyPath?.trim()||void 0},envVars:Object.fromEntries(D.map(f=>[f.key.trim(),f.value]).filter(([f])=>!!f)),volumeMounts:q.map(f=>({hostPath:f.hostPath.trim(),containerPath:f.containerPath.trim(),mode:f.mode})).filter(f=>f.hostPath&&f.containerPath),resourceSizing:{memoryMB:L,cpus:V},extraClis:[w?"claude-cli":null,l?"droid-cli":null].filter(Boolean),persistentStorage:_,reachableUrl:d.trim()||null,apiKey:N==="manual"&&y.trim()||null}),[y,N,V,o,D,B,J,w,l,L,q,u,_,d]),$=s.useCallback(()=>{X(f=>[...f,{key:"",value:""}])},[]),F=s.useCallback((f,I)=>{X(K=>K.map((se,oe)=>oe===f?I:se))},[]),G=s.useCallback(f=>{X(I=>I.filter((K,se)=>se!==f))},[]),re=s.useCallback(()=>{Q(f=>[...f,{hostPath:"",containerPath:"",mode:"rw"}])},[]),ae=s.useCallback((f,I)=>{Q(K=>K.map((se,oe)=>oe===f?I:se))},[]),U=s.useCallback(f=>{Q(I=>I.filter((K,se)=>se!==f))},[]),he=s.useCallback(async()=>{if(R)return;const f={};if((!M.name||M.name.length>64)&&(f.name="Name is required and must be 64 characters or fewer"),M.reachableUrl||(f.reachableUrl="URL is required"),L<512&&(f.memoryMB="Memory must be at least 512 MB"),V<.5&&(f.cpus="CPUs must be at least 0.5"),te(f),!(Object.keys(f).length>0)){Z(!0);try{await a(M),O()}catch{}finally{Z(!1)}}},[O,V,M,L,a,R]);return t?e.jsx("div",{className:"modal-overlay open",onClick:O,children:e.jsxs("div",{className:"modal docker-onboarding",role:"dialog","aria-modal":"true","aria-label":"Docker node onboarding",onClick:f=>f.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Provision Docker Node"}),e.jsx("button",{className:"modal-close",onClick:O,disabled:R,"aria-label":"Close onboarding modal",children:"×"})]}),e.jsxs("div",{className:"modal-body docker-onboarding__body",children:[e.jsxs("section",{className:"docker-onboarding__section",children:[e.jsx("h4",{className:"docker-onboarding__section-title",children:"Required Settings"}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Node Name"}),e.jsx("input",{className:"input",value:u,onChange:f=>g(f.target.value),disabled:R,placeholder:"my-docker-node",autoFocus:!0})]}),Y.name&&e.jsx("div",{className:"form-error",children:Y.name}),e.jsx(qs,{value:o,onChange:p}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Reachable URL"}),e.jsx("input",{className:"input",value:d,onChange:f=>b(f.target.value),disabled:R,placeholder:je})]}),Y.reachableUrl&&e.jsx("div",{className:"form-error",children:Y.reachableUrl}),e.jsxs("div",{className:"docker-onboarding__radio-group",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"radio",checked:N==="auto",onChange:()=>P("auto"),disabled:R}),"Auto-generate"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"radio",checked:N==="manual",onChange:()=>P("manual"),disabled:R}),"Provide manually"]})]}),N==="manual"&&e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:y,onChange:f=>c(f.target.value),disabled:R,placeholder:"Enter API key"})]}),e.jsxs("div",{className:"docker-onboarding__checkbox-group",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:w,onChange:f=>v(f.target.checked),disabled:R}),"Claude CLI"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:l,onChange:f=>j(f.target.checked),disabled:R}),"Droid CLI"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:_,onChange:f=>k(f.target.checked),disabled:R}),"Keep data across container recreations"]})]}),e.jsxs("div",{className:"docker-onboarding__inline-fields",children:[e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Memory (MB)"}),e.jsx("input",{className:"input",type:"number",min:512,value:L,onChange:f=>E(Number(f.target.value)),disabled:R})]}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"CPUs"}),e.jsx("input",{className:"input",type:"number",min:.5,step:.5,value:V,onChange:f=>x(Number(f.target.value)),disabled:R})]})]}),Y.memoryMB&&e.jsx("div",{className:"form-error",children:Y.memoryMB}),Y.cpus&&e.jsx("div",{className:"form-error",children:Y.cpus})]}),e.jsxs("section",{className:"docker-onboarding__section",children:[e.jsxs("button",{type:"button",className:`docker-onboarding__advanced-toggle ${m?"is-expanded":""}`,onClick:()=>C(f=>!f),disabled:R,children:[e.jsx("span",{children:"Advanced"}),e.jsx(we,{})]}),e.jsx("div",{className:`docker-onboarding__advanced-content ${m?"is-expanded":""}`,children:e.jsxs("div",{children:[e.jsxs("div",{className:"docker-onboarding__inline-fields",children:[e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Image"}),e.jsx("input",{className:"input",value:B,onChange:f=>H(f.target.value),disabled:R,placeholder:"runfusion/fusion"})]}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Tag"}),e.jsx("input",{className:"input",value:J,onChange:f=>W(f.target.value),disabled:R,placeholder:"latest"})]})]}),e.jsxs("div",{className:"docker-onboarding__kv-list",children:[e.jsx("h5",{children:"Environment Variables"}),D.map((f,I)=>e.jsxs("div",{className:"docker-onboarding__kv-row docker-onboarding__kv-row--env",children:[e.jsx("input",{className:"input",placeholder:"KEY",value:f.key,disabled:R,onChange:K=>F(I,{key:K.target.value,value:f.value})}),e.jsx("input",{className:"input",placeholder:"Value",value:f.value,disabled:R,onChange:K=>F(I,{key:f.key,value:K.target.value})}),e.jsx("button",{type:"button",className:"btn btn-icon","aria-label":"Remove environment variable",onClick:()=>G(I),disabled:R,children:e.jsx(ve,{size:14})})]},`env-${I}`)),e.jsxs("button",{type:"button",className:"btn btn-sm docker-onboarding__kv-add",onClick:$,disabled:R,children:[e.jsx(me,{size:14}),"Add variable"]})]}),e.jsxs("div",{className:"docker-onboarding__kv-list",children:[e.jsx("h5",{children:"Volume Mounts"}),q.map((f,I)=>e.jsxs("div",{className:"docker-onboarding__kv-row docker-onboarding__kv-row--mount",children:[e.jsx("input",{className:"input",placeholder:"Host path",value:f.hostPath,disabled:R,onChange:K=>ae(I,{hostPath:K.target.value,containerPath:f.containerPath,mode:f.mode})}),e.jsx("input",{className:"input",placeholder:"Container path",value:f.containerPath,disabled:R,onChange:K=>ae(I,{hostPath:f.hostPath,containerPath:K.target.value,mode:f.mode})}),e.jsxs("select",{className:"select",value:f.mode,disabled:R,onChange:K=>ae(I,{hostPath:f.hostPath,containerPath:f.containerPath,mode:K.target.value==="ro"?"ro":"rw"}),children:[e.jsx("option",{value:"rw",children:"rw"}),e.jsx("option",{value:"ro",children:"ro"})]}),e.jsx("button",{type:"button",className:"btn btn-icon","aria-label":"Remove volume mount",onClick:()=>U(I),disabled:R,children:e.jsx(ve,{size:14})})]},`mount-${I}`)),e.jsxs("button",{type:"button",className:"btn btn-sm docker-onboarding__kv-add",onClick:re,disabled:R,children:[e.jsx(me,{size:14}),"Add mount"]})]})]})})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn",onClick:O,disabled:R,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",onClick:()=>void he(),disabled:R,children:R?"Creating...":"Create Docker Node"})]})]})}):null}function Xs({nodeId:t,entries:n,loading:a=!1,singleNode:i=!1}){const[u,g]=s.useState(!1),[o,p]=s.useState("all"),[d,b]=s.useState("all"),N=s.useCallback(()=>{g(l=>!l)},[]),P=s.useMemo(()=>{const l=new Set;for(const j of n)l.add(j.nodeName);return Array.from(l).sort()},[n]),y=s.useMemo(()=>{let l=[...n];return o!=="all"&&(l=l.filter(j=>j.direction===o)),!i&&d!=="all"&&(l=l.filter(j=>j.nodeName===d)),l.sort((j,_)=>{const k=new Date(j.timestamp).getTime();return new Date(_.timestamp).getTime()-k}),l},[n,o,d,i]),c=s.useCallback(l=>new Date(l).toLocaleString(),[]),w=s.useCallback(l=>{switch(l){case"success":return"settings-sync-log__badge--success";case"conflict":return"settings-sync-log__badge--conflict";case"error":return"settings-sync-log__badge--error";default:return""}},[]),v=s.useCallback(l=>{switch(l){case"success":return"Success";case"conflict":return"Conflict";case"error":return"Error";default:return l}},[]);return e.jsxs("div",{className:"settings-sync-log",children:[e.jsxs("button",{className:"settings-sync-log__header",type:"button",onClick:N,"aria-expanded":u,"data-testid":"settings-sync-log-header",children:[e.jsx(we,{size:16,className:`settings-sync-log__chevron ${u?"settings-sync-log__chevron--expanded":""}`}),e.jsxs("span",{children:[n.length," ",n.length===1?"entry":"entries"]})]}),u&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"settings-sync-log__filters",children:[e.jsxs("label",{children:["Direction:",e.jsxs("select",{value:o,onChange:l=>p(l.target.value),children:[e.jsx("option",{value:"all",children:"All"}),e.jsx("option",{value:"push",children:"Push"}),e.jsx("option",{value:"pull",children:"Pull"})]})]}),!i&&e.jsxs("label",{children:["Node:",e.jsxs("select",{value:d,onChange:l=>b(l.target.value),children:[e.jsx("option",{value:"all",children:"All Nodes"}),P.map(l=>e.jsx("option",{value:l,children:l},l))]})]})]}),a&&n.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"Loading..."}):y.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"No sync history available"}):e.jsx("div",{className:"settings-sync-log__list",children:y.map(l=>e.jsxs("div",{className:"settings-sync-log__entry",children:[e.jsx("span",{className:"settings-sync-log__entry-timestamp",children:c(l.timestamp)}),e.jsx("span",{className:"settings-sync-log__entry-direction",children:l.direction==="push"?e.jsx(Be,{size:14,"data-testid":"upload-icon"}):e.jsx(Te,{size:14,"data-testid":"download-icon"})}),e.jsx("span",{className:`settings-sync-log__entry-result ${w(l.result)}`,children:v(l.result)}),!i&&e.jsx("span",{className:"settings-sync-log__entry-node",children:l.nodeName}),l.details&&e.jsx("span",{className:"settings-sync-log__entry-details",title:l.details,children:l.details})]},l.id))})]})]})}function Js(t,n){const a=typeof t=="string"?t:JSON.stringify(t,null,2),i=typeof n=="string"?n:JSON.stringify(n,null,2);if(a===i)return a;const u=a.split(`
12
- `),g=i.split(`
13
- `),o=[],p=Math.max(u.length,g.length);for(let d=0;d<p;d++){const b=u[d],N=g[d];b!==void 0&&b!==N&&o.push(`- ${b}`),N!==void 0&&N!==b&&o.push(`+ ${N}`),b!==void 0&&b===N&&o.push(` ${b}`)}return o.join(`
14
- `)}function Ws({isOpen:t,onClose:n,onResolve:a,conflicts:i,localNodeName:u,remoteNodeName:g,addToast:o}){const[p,d]=s.useState({}),[b,N]=s.useState(!1);s.useEffect(()=>{const l={};for(const j of i)p[j.key]||(l[j.key]={resolution:"local"});Object.keys(l).length>0&&d(j=>({...j,...l}))},[i,p]),s.useEffect(()=>{if(!t)return;const l=j=>{j.key==="Escape"&&(j.preventDefault(),n())};return document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l)},[t,n]);const P=s.useCallback((l,j)=>{d(_=>{const k=_[l]??{};return j==="manual"?{..._,[l]:{resolution:"manual",manualValue:k.manualValue??JSON.stringify(i.find(L=>L.key===l)?.localValue??null,null,2)}}:{..._,[l]:{resolution:j}}})},[i]),y=s.useCallback((l,j)=>{d(_=>({..._,[l]:{..._[l],resolution:"manual",manualValue:j}}))},[]),c=s.useCallback(l=>{const j={};for(const _ of i)j[_.key]={resolution:l};d(j)},[i]),w=s.useCallback(async()=>{N(!0);try{const l=i.map(j=>{const _=p[j.key]??{resolution:"local"};let k;switch(_.resolution){case"remote":k=j.remoteValue;break;case"manual":try{k=JSON.parse(_.manualValue??"null")}catch{k=_.manualValue??null}break;case"local":default:k=j.localValue;break}return{key:j.key,value:k}});await a(l),o("Settings conflicts resolved successfully","success"),n()}catch(l){const j=l instanceof Error?l.message:"Failed to resolve conflicts";o(j,"error")}finally{N(!1)}},[o,i,n,a,p]),v=s.useMemo(()=>{const l={};for(const j of i)l[j.key]=Js(j.localValue,j.remoteValue);return l},[i]);return!t||i.length===0?null:e.jsx("div",{className:"modal-overlay open",onClick:n,children:e.jsxs("div",{className:"modal modal-lg settings-sync-conflict-modal",onClick:l=>l.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Resolve Settings Conflicts",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Resolve Settings Conflicts"}),e.jsx("button",{className:"modal-close",onClick:n,"aria-label":"Close conflict modal",children:"×"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("div",{className:"settings-sync-conflict-modal__conflict-list",children:i.map(l=>{const j=p[l.key]??{resolution:"local"},_=v[l.key];return e.jsxs("div",{className:"settings-sync-conflict-modal__conflict-item",children:[e.jsx("div",{className:"settings-sync-conflict-modal__key",children:l.key}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-panel",children:[e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:u}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:_})})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:g}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:_})})]})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__resolution",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:j.resolution==="local",onChange:()=>P(l.key,"local")}),"Keep Local"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:j.resolution==="remote",onChange:()=>P(l.key,"remote")}),"Keep Remote"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:j.resolution==="manual",onChange:()=>P(l.key,"manual")}),"Merge Manually"]})]}),j.resolution==="manual"&&e.jsx("textarea",{className:"settings-sync-conflict-modal__manual-input",value:j.manualValue??"",onChange:k=>y(l.key,k.target.value),placeholder:"Enter JSON value..."})]},l.key)})}),e.jsxs("div",{className:"settings-sync-conflict-modal__bulk-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:()=>c("local"),type:"button",children:"Resolve All: Keep Local"}),e.jsx("button",{className:"btn btn-sm",onClick:()=>c("remote"),type:"button",children:"Resolve All: Keep Remote"})]})]}),e.jsxs("div",{className:"modal-actions settings-sync-conflict-modal__footer",children:[e.jsx("button",{className:"btn btn-sm",onClick:n,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:w,disabled:b,children:b?"Resolving...":"Confirm"})]})]})})}const qe=/(KEY|TOKEN|SECRET|PASSWORD)/i;function be(t){if(!t)return"—";const n=new Date(t);return Number.isNaN(n.getTime())?"—":n.toLocaleString()}function Gs(t){if(!t)return"—";const n=new Date(t),a=Date.now();if(Number.isNaN(n.getTime())||n.getTime()>a)return"—";const i=Math.floor((a-n.getTime())/1e3);if(i<60)return`${i}s`;const u=Math.floor(i/60);if(u<60)return`${u}m`;const g=Math.floor(u/60);return g<24?`${g}h ${u%60}m`:`${Math.floor(g/24)}d ${g%24}h`}function Qs(t){switch(t){case"synced":return"node-detail-modal__sync-dot--synced";case"diff":return"node-detail-modal__sync-dot--diff";case"error":return"node-detail-modal__sync-dot--error";case"pending":return"node-detail-modal__sync-dot--pending";case"never-synced":default:return"node-detail-modal__sync-dot--never"}}function Zs(t){return t==="running"?"success":t==="creating"||t==="recreating"||t==="restarting"?"warning":"error"}function et(t){return t?`${t.charAt(0).toUpperCase()}${t.slice(1)}`:"Unknown"}function st(t){if(!t)return"—";try{const n=new URL(t);return n.port?n.port:n.protocol==="https:"?"443":n.protocol==="http:"?"80":"—"}catch{return"—"}}function tt(t,n){return qe.test(t)?"••••••••":n}function at({isOpen:t,onClose:n,node:a,projects:i,onUpdate:u,onHealthCheck:g,addToast:o,syncStatus:p,onPushSettings:d,onPullSettings:b,onSyncAuth:N,syncHistory:P=[],onResolveConflicts:y,managedDockerNode:c,containerStatus:w,onFetchContainerStatus:v,onFetchLogs:l,onUpdateDockerConfig:j,onFetchDockerConfigDiff:_}){const k=s.useRef(!0),[L,E]=s.useState(!1),[V,x]=s.useState(""),[m,C]=s.useState(""),[B,H]=s.useState(""),[J,W]=s.useState(2),[D,X]=s.useState(!1),[q,Q]=s.useState(!1),[Y,te]=s.useState(!1),[R,Z]=s.useState(!1),[ee,O]=s.useState(null),[M,$]=s.useState(!1),[F]=s.useState([]),[G,re]=s.useState(w),[ae,U]=s.useState(!1),[he,f]=s.useState(!1),[I,K]=s.useState(""),[se,oe]=s.useState(!1),[fe,Me]=s.useState(!1),[h,z]=s.useState(a?.dockerConfig??null),[Pe,Ee]=s.useState({}),[ie,Re]=s.useState(!1),[Ye,Ae]=s.useState(!1);s.useEffect(()=>(k.current=!0,()=>{k.current=!1}),[]),s.useEffect(()=>{re(w)},[w]),s.useEffect(()=>{if(!a||!t){E(!1),f(!1),K("");return}x(a.name),C(a.url??""),H(a.apiKey??""),W(a.maxConcurrent),E(!1),z(a.dockerConfig??null),Me(!1),Ee({})},[t,a]),s.useEffect(()=>{if(!t)return;const r=S=>{S.key==="Escape"&&(S.preventDefault(),n())};return document.addEventListener("keydown",r),()=>document.removeEventListener("keydown",r)},[t,n]);const ge=s.useMemo(()=>a?He(i,a):[],[a,i]),Xe=s.useMemo(()=>c?c.hostConfig.type==="remote"?c.hostConfig.host??"—":"Local Docker":"—",[c]),Je=s.useMemo(()=>!c?.resourceSizing?.cpuLimit&&!c?.resourceSizing?.memoryLimit?"Default":`${c.resourceSizing?.cpuLimit??"Default CPU"} / ${c.resourceSizing?.memoryLimit??"Default memory"}`,[c]),We=s.useCallback(async()=>{if(a)try{if(await g(a.id),!k.current)return;o(`Health check completed for ${a.name}`,"success")}catch(r){if(!k.current)return;const S=r instanceof Error?r.message:"Health check failed";o(S,"error")}},[o,a,g]),Ge=s.useCallback(async()=>{if(!(!a||!d)){O(null),Q(!0);try{if(await d(a.id),!k.current)return;o("Settings pushed successfully","success")}catch(r){if(!k.current)return;const S=r instanceof Error?r.message:"Push settings failed";O(S),o(S,"error")}finally{k.current&&Q(!1)}}},[o,a,d]),Qe=s.useCallback(async()=>{if(!(!a||!b)){O(null),te(!0);try{if(await b(a.id),!k.current)return;o("Settings pulled successfully","success")}catch(r){if(!k.current)return;const S=r instanceof Error?r.message:"Pull settings failed";O(S),o(S,"error")}finally{k.current&&te(!1)}}},[o,a,b]),Ze=s.useCallback(async()=>{if(!(!a||!N)){O(null),Z(!0);try{if(await N(a.id),!k.current)return;o("Auth credentials synced successfully","success")}catch(r){if(!k.current)return;const S=r instanceof Error?r.message:"Auth sync failed";O(S),o(S,"error")}finally{k.current&&Z(!1)}}},[o,a,N]),es=s.useCallback(()=>{O(null)},[]),ss=s.useCallback(async()=>{if(!(!c||!v)){U(!0);try{const r=await v(c.id);if(!k.current)return;re(r)}catch(r){const S=r instanceof Error?r.message:"Failed to fetch container status";o(S,"error")}finally{k.current&&U(!1)}}},[o,c,v]),ts=s.useCallback(async()=>{if(!(!c||!l)){f(!0),oe(!0);try{const r=await l(c.id);if(!k.current)return;K(r)}catch(r){if(!k.current)return;K("");const S=r instanceof Error?r.message:"Failed to fetch container logs";o(S,"error")}finally{k.current&&oe(!1)}}},[o,c,l]),as=s.useCallback(async()=>{if(!a||D)return;const r=V.trim();if(!r){o("Name is required","error");return}if(a.type==="remote"&&!m.trim()){o("URL is required for remote nodes","error");return}if(!Number.isFinite(J)||J<1){o("Concurrency must be at least 1","error");return}X(!0);try{await u(a.id,{name:r,url:a.type==="remote"&&m.trim()||void 0,apiKey:a.type==="remote"&&B||void 0,maxConcurrent:J}),o(`Updated ${r}`,"success"),E(!1)}catch(S){const T=S instanceof Error?S.message:"Failed to update node";o(T,"error")}finally{X(!1)}},[o,B,D,J,V,a,u,m]);s.useEffect(()=>{!a?.dockerConfig||!_||!t||_(a.id).then(r=>{k.current&&Ae(r.needsRecreate)}).catch(()=>{k.current&&Ae(!1)})},[t,a,_]);const ns=s.useCallback(async()=>{if(!(!a||!h||!j||ie)){Re(!0);try{const r=await j(a.id,{image:h.image,volumeMounts:h.volumeMounts,environment:h.environment,resources:h.resources,host:h.host,extraClis:h.extraClis,persistence:h.persistence,containerName:h.containerName});if(!k.current)return;z(r),o("Docker config saved","success")}catch(r){if(!k.current)return;const S=r instanceof Error?r.message:"Failed to save Docker config";o(S,"error")}finally{k.current&&Re(!1)}}},[o,h,ie,a,j]),ls=s.useCallback(()=>{a&&(x(a.name),C(a.url??""),H(a.apiKey??""),W(a.maxConcurrent),E(!1))},[a]);if(!t||!a)return null;const ne=G?.status??c?.status,rs=Zs(ne);return e.jsxs("div",{className:"modal-overlay open",onClick:n,children:[e.jsxs("div",{className:"modal modal-lg node-detail-modal",onClick:r=>r.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":`Node details for ${a.name}`,children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Node Details"}),e.jsx("button",{className:"modal-close",onClick:n,"aria-label":"Close node detail modal",children:"×"})]}),e.jsxs("div",{className:"modal-body node-detail-modal__body",children:[e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("div",{className:"node-detail-modal__section-header",children:[e.jsx("h4",{children:"Overview"}),!L&&e.jsxs("button",{className:"btn btn-sm",onClick:()=>E(!0),children:[e.jsx(fs,{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"}),L?e.jsx("input",{className:"input",value:V,onChange:r=>x(r.target.value),disabled:D}):e.jsx("strong",{children:a.name})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Type"}),e.jsx("strong",{children:a.type==="local"?"Local":"Remote"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Status"}),e.jsx("strong",{children:a.status})]}),e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),L?e.jsx("input",{className:"input",type:"number",min:1,max:10,value:J,onChange:r=>W(Number(r.target.value)),disabled:D}):e.jsx("strong",{children:a.maxConcurrent})]}),a.type==="remote"&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"URL"}),L?e.jsx("input",{className:"input",value:m,onChange:r=>C(r.target.value),disabled:D}):e.jsx("strong",{children:a.url??"—"})]}),e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"API Key"}),L?e.jsx("input",{className:"input",type:"password",value:B,onChange:r=>H(r.target.value),placeholder:"Leave blank to keep unchanged",disabled:D}):e.jsx("strong",{children:a.apiKey?"••••••••":"Not configured"})]})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Created"}),e.jsx("strong",{children:be(a.createdAt)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Updated"}),e.jsx("strong",{children:be(a.updatedAt)})]})]}),L&&e.jsxs("div",{className:"node-detail-modal__edit-actions",children:[e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:as,disabled:D,children:[e.jsx(Le,{size:14}),D?"Saving...":"Save"]}),e.jsxs("button",{className:"btn btn-sm",onClick:ls,disabled:D,children:[e.jsx(ue,{size:14}),"Cancel"]})]})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("h4",{children:[a.type==="local"?"Projects":"Assigned Projects"," (",ge.length,")"]}),ge.length===0?e.jsx("p",{className:"node-detail-modal__empty",children:a.type==="local"?"No projects are running on this node.":"No projects are assigned to this node."}):e.jsx("ul",{className:"node-detail-modal__project-list",children:ge.map(r=>e.jsxs("li",{className:"node-detail-modal__project-item",children:[e.jsx("span",{children:r.name}),e.jsx("code",{children:r.id})]},r.id))})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Health"}),e.jsxs("div",{className:"node-detail-modal__health-row",children:[e.jsxs("span",{children:["Status: ",e.jsx("strong",{children:a.status})]}),e.jsxs("span",{children:["Last check: ",e.jsx("strong",{children:be(a.updatedAt)})]})]})]}),h&&e.jsxs("section",{className:"node-detail-modal__section node-detail-modal__docker-config",children:[e.jsxs("button",{className:"btn btn-sm node-detail-modal__docker-toggle",onClick:()=>Me(r=>!r),"aria-expanded":fe,children:[e.jsx(we,{size:14,className:fe?"node-detail-modal__docker-toggle-icon--expanded":""}),"Docker Configuration"]}),fe&&e.jsxs("div",{className:"node-detail-modal__docker-config-content",children:[e.jsx("div",{className:"node-detail-modal__grid",children:e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"Image"}),e.jsx("input",{className:"input",value:h.image,onChange:r=>z({...h,image:r.target.value})})]})}),e.jsxs("details",{children:[e.jsx("summary",{children:"Volume Mounts"}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[h.volumeMounts.map((r,S)=>e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:r.hostPath,placeholder:"Host path",onChange:T=>{const A=[...h.volumeMounts];A[S]={...A[S],hostPath:T.target.value},z({...h,volumeMounts:A})}}),e.jsx("input",{className:"input",value:r.containerPath,placeholder:"Container path",onChange:T=>{const A=[...h.volumeMounts];A[S]={...A[S],containerPath:T.target.value},z({...h,volumeMounts:A})}}),e.jsxs("select",{className:"input",value:r.mode??"rw",onChange:T=>{const A=[...h.volumeMounts];A[S]={...A[S],mode:T.target.value},z({...h,volumeMounts:A})},children:[e.jsx("option",{value:"rw",children:"rw"}),e.jsx("option",{value:"ro",children:"ro"})]}),e.jsxs("select",{className:"input",value:r.type??"volume",onChange:T=>{const A=[...h.volumeMounts];A[S]={...A[S],type:T.target.value},z({...h,volumeMounts:A})},children:[e.jsx("option",{value:"volume",children:"volume"}),e.jsx("option",{value:"bind",children:"bind"})]}),e.jsx("button",{className:"btn btn-sm",onClick:()=>z({...h,volumeMounts:h.volumeMounts.filter((T,A)=>A!==S)}),children:"Remove"})]},`${r.hostPath}-${r.containerPath}-${S}`)),e.jsx("button",{className:"btn btn-sm",onClick:()=>z({...h,volumeMounts:[...h.volumeMounts,{hostPath:"",containerPath:"",mode:"rw",type:"volume"}]}),children:"Add Mount"})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Environment Variables"}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[Object.entries(h.environment).map(([r,S])=>{const T=qe.test(r)&&!Pe[r];return e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:r,onChange:A=>{const xe={...h.environment};delete xe[r],xe[A.target.value]=S,z({...h,environment:xe})}}),e.jsx("input",{className:"input",value:T?"***":String(S),onChange:A=>z({...h,environment:{...h.environment,[r]:A.target.value}})}),e.jsx("button",{className:"btn btn-sm",onClick:()=>Ee(A=>({...A,[r]:!A[r]})),children:Pe[r]?e.jsx(gs,{size:14}):e.jsx(xs,{size:14})}),e.jsx("button",{className:"btn btn-sm",onClick:()=>{const A={...h.environment};delete A[r],z({...h,environment:A})},children:"Remove"})]},r)}),e.jsx("button",{className:"btn btn-sm",onClick:()=>{const r=`NEW_VAR_${Object.keys(h.environment).length+1}`;z({...h,environment:{...h.environment,[r]:""}})},children:"Add Variable"})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Resources"}),e.jsxs("div",{className:"node-detail-modal__docker-stack",children:[e.jsx("input",{className:"input",type:"number",placeholder:"Memory bytes (2 GB = 2147483648)",value:h.resources?.memoryBytes??"",onChange:r=>z({...h,resources:{...h.resources,memoryBytes:r.target.value?Number(r.target.value):void 0}})}),e.jsx("input",{className:"input",type:"number",placeholder:"CPU count",value:h.resources?.cpuCount??"",onChange:r=>z({...h,resources:{...h.resources,cpuCount:r.target.value?Number(r.target.value):void 0}})}),e.jsx("input",{className:"input",type:"number",placeholder:"PIDs limit",value:h.resources?.pidsLimit??"",onChange:r=>z({...h,resources:{...h.resources,pidsLimit:r.target.value?Number(r.target.value):void 0}})})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Host Config"}),e.jsxs("div",{className:"node-detail-modal__docker-stack",children:[e.jsx("input",{className:"input",placeholder:"Context name",value:h.host?.contextName??"",onChange:r=>z({...h,host:{...h.host,contextName:r.target.value}})}),e.jsx("input",{className:"input",placeholder:"Docker host URL",value:h.host?.dockerHost??"",onChange:r=>z({...h,host:{...h.host,dockerHost:r.target.value}})}),e.jsx("input",{className:"input",placeholder:"TLS CA cert path",value:h.host?.tlsCaCert??"",onChange:r=>z({...h,host:{...h.host,tlsCaCert:r.target.value}})}),e.jsx("input",{className:"input",placeholder:"TLS cert path",value:h.host?.tlsCert??"",onChange:r=>z({...h,host:{...h.host,tlsCert:r.target.value}})}),e.jsx("input",{className:"input",placeholder:"TLS key path",value:h.host?.tlsKey??"",onChange:r=>z({...h,host:{...h.host,tlsKey:r.target.value}})}),e.jsxs("label",{className:"node-detail-modal__checkbox",children:[e.jsx("input",{type:"checkbox",checked:h.host?.tlsVerify??!0,onChange:r=>z({...h,host:{...h.host,tlsVerify:r.target.checked}})}),"TLS verify"]})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Extra CLIs"}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[(h.extraClis??[]).map((r,S)=>e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:r,onChange:T=>{const A=[...h.extraClis??[]];A[S]=T.target.value,z({...h,extraClis:A})}}),e.jsx("button",{className:"btn btn-sm",onClick:()=>z({...h,extraClis:(h.extraClis??[]).filter((T,A)=>A!==S)}),children:"Remove"})]},`${r}-${S}`)),e.jsx("button",{className:"btn btn-sm",onClick:()=>z({...h,extraClis:[...h.extraClis??[],""]}),children:"Add CLI"})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Persistence"}),e.jsxs("div",{className:"node-detail-modal__docker-stack",children:[e.jsx("input",{className:"input",placeholder:"Volume name",value:h.persistence?.volumeName??"",onChange:r=>z({...h,persistence:{...h.persistence,volumeName:r.target.value}})}),e.jsxs("label",{className:"node-detail-modal__checkbox",children:[e.jsx("input",{type:"checkbox",checked:h.persistence?.retainOnDelete??!1,onChange:r=>z({...h,persistence:{...h.persistence,retainOnDelete:r.target.checked}})}),"Retain on delete"]})]})]}),e.jsxs("div",{className:"node-detail-modal__docker-meta",children:[e.jsxs("span",{children:["Config v",h.configVersion," • Updated ",Ne(h.lastUpdated??a.updatedAt)]}),Ye&&e.jsx("span",{className:"node-detail-modal__docker-recreate",children:"Needs Recreate"})]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>void ns(),disabled:ie,children:[e.jsx(Le,{size:14}),ie?"Saving...":"Save Docker Config"]})]})]}),c&&e.jsxs("section",{className:"node-detail-modal__section docker-management",children:[e.jsx("h4",{children:"Docker Management"}),e.jsxs("div",{className:"docker-management__status-card",children:[e.jsxs("div",{className:"docker-management__status-row",children:[e.jsx("span",{className:`docker-management__status-dot docker-management__status-dot--${rs}`,"aria-hidden":!0}),e.jsx("strong",{children:et(ne)}),(ne==="creating"||ne==="recreating"||ne==="restarting")&&e.jsx($e,{size:14,className:"spin","aria-hidden":!0})]}),e.jsxs("div",{className:"docker-management__status-meta",children:[ne==="running"&&e.jsxs("span",{children:["Uptime: ",Gs(G?.startedAt)]}),ne!=="running"&&G?.exitCode!==void 0&&e.jsxs("span",{children:["Exit code: ",G.exitCode]}),(G?.error||c.errorMessage)&&e.jsx("span",{children:G?.error??c.errorMessage})]}),e.jsx("button",{className:"btn btn-sm",onClick:()=>void ss(),disabled:!v||ae,children:ae?"Refreshing...":"Refresh Status"})]}),e.jsxs("div",{className:"node-detail-modal__grid docker-management__info-grid",children:[e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Image"}),e.jsx("strong",{children:e.jsxs("code",{children:[c.imageName,":",c.imageTag]})})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Container ID"}),e.jsx("strong",{children:e.jsx("code",{children:c.containerId?c.containerId.slice(0,12):"—"})})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Host"}),e.jsx("strong",{children:Xe})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Persistent Storage"}),e.jsx("strong",{children:c.persistentStorage?"Yes":"No"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Port"}),e.jsx("strong",{children:st(c.reachableUrl)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Resource Sizing"}),e.jsx("strong",{children:Je})]})]}),e.jsxs("div",{className:"docker-management__actions",children:[e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:"Available after FN-3113",children:[e.jsx(Oe,{size:14}),"Start"]}),e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:"Available after FN-3113",children:[e.jsx(Ue,{size:14}),"Stop"]}),e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:"Available after FN-3113",children:[e.jsx($e,{size:14}),"Restart"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void ts(),disabled:!l,children:[e.jsx(ps,{size:14}),"View Logs"]})]}),he&&e.jsxs("div",{className:"docker-management__log-viewer",children:[e.jsxs("div",{className:"docker-management__log-viewer-header",children:[e.jsx("strong",{children:"Container Logs"}),e.jsx("button",{className:"btn-icon",onClick:()=>f(!1),"aria-label":"Close logs",children:e.jsx(ue,{size:14})})]}),se?e.jsx("p",{children:"Fetching logs..."}):e.jsx("pre",{children:I.trim()||"No logs available"})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Environment Variables"}),e.jsx("dl",{className:"docker-management__env-list",children:Object.entries(c.envVars).map(([r,S])=>e.jsxs("div",{children:[e.jsx("dt",{children:r}),e.jsx("dd",{children:tt(r,S)})]},r))})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Volume Mounts"}),e.jsx("ul",{className:"docker-management__mounts-list",children:c.volumeMounts.map(r=>e.jsxs("li",{children:[e.jsxs("span",{children:[r.hostPath," → ",r.containerPath]}),r.readOnly&&e.jsx("span",{className:"node-card__type-badge",children:"Read-only"})]},`${r.hostPath}:${r.containerPath}`))})]})]}),a.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Settings Sync"}),p&&e.jsxs("div",{className:"node-detail-modal__sync-status",children:[e.jsx("span",{className:`node-detail-modal__sync-dot ${Qs(p.syncState)}`,"aria-hidden":!0}),e.jsxs("span",{children:["Last sync: ",e.jsx("strong",{children:p.lastSyncAt?Ne(p.lastSyncAt):"Never synced"})]}),p.diffCount>0&&e.jsxs("span",{className:"node-detail-modal__sync-diff",children:["Differences: ",e.jsx("strong",{children:p.diffCount})]})]}),e.jsxs("div",{className:"node-detail-modal__sync-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:Ge,disabled:q||!d,children:[e.jsx(Be,{size:14}),q?"Pushing...":"Push Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:Qe,disabled:Y||!b,children:[e.jsx(Te,{size:14}),Y?"Pulling...":"Pull Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:Ze,disabled:R||!N,children:[e.jsx(Ke,{size:14}),R?"Syncing...":"Sync Auth"]})]}),ee&&e.jsxs("div",{className:"node-detail-modal__sync-error",children:[e.jsx("span",{children:ee}),e.jsx("button",{className:"node-detail-modal__sync-error-dismiss",onClick:es,"aria-label":"Dismiss error",children:e.jsx(ue,{size:14})})]})]}),a.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Sync History"}),e.jsx(Xs,{nodeId:a.id,entries:P,singleNode:!0})]})]}),e.jsxs("div",{className:"modal-actions node-detail-modal__actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:We,children:[e.jsx(Fe,{size:14}),"Health Check"]}),e.jsx("button",{className:"btn btn-sm",onClick:n,children:"Close"})]})]}),a.type==="remote"&&e.jsx(Ws,{isOpen:M,onClose:()=>$(!1),onResolve:y??(async()=>{}),conflicts:F,localNodeName:"Local",remoteNodeName:a.name,addToast:o})]})}const nt=15e3,lt=1e3;function rt(){const[t,n]=s.useState([]),[a,i]=s.useState(!0),[u,g]=s.useState(null),o=s.useRef(null),p=s.useRef(0),d=s.useCallback(async()=>{try{g(null);const y=await De();n(y)}catch(y){g(y instanceof Error?y.message:"Failed to fetch managed Docker nodes")}},[]);s.useEffect(()=>{let y=!1;async function c(){i(!0);try{const v=await De();y||(n(v),g(null))}catch(v){y||g(v instanceof Error?v.message:"Failed to fetch managed Docker nodes")}finally{y||i(!1)}}c();const w=()=>{if(document.visibilityState!=="visible")return;const v=Date.now();v-p.current<lt||(p.current=v,d())};return document.addEventListener("visibilitychange",w),()=>{y=!0,document.removeEventListener("visibilitychange",w)}},[d]),s.useEffect(()=>{if(!a)return o.current=setInterval(()=>{d()},nt),()=>{o.current&&(clearInterval(o.current),o.current=null)}},[a,d]);const b=s.useCallback(async y=>js(y),[]),N=s.useCallback(async(y,c)=>(await bs(y,c)).logs,[]),P=s.useCallback(async y=>{const c=await ys(y),w={...c,nodeId:c.nodeId??void 0,containerId:c.containerId??void 0,status:c.status,hostConfig:{type:c.hostConfig.host||c.hostConfig.context?"remote":"local",host:c.hostConfig.host,context:c.hostConfig.context},reachableUrl:c.reachableUrl??void 0,volumeMounts:c.volumeMounts.map(v=>({hostPath:v.hostPath,containerPath:v.containerPath,readOnly:v.mode==="ro"?!0:void 0})),persistentStorage:c.persistentStorage,resourceSizing:{cpuLimit:c.resourceSizing.cpus!==void 0?String(c.resourceSizing.cpus):void 0,memoryLimit:c.resourceSizing.memoryMB!==void 0?`${c.resourceSizing.memoryMB}MB`:void 0},errorMessage:c.errorMessage??void 0};return n(v=>[...v,w]),w},[]);return{dockerNodes:t,loading:a,error:u,refresh:d,getContainerStatus:b,getLogs:N,create:P}}function ut({addToast:t,onClose:n}){const{nodes:a,loading:i,error:u,refresh:g,register:o,update:p,unregister:d,healthCheck:b,patchDockerConfig:N,fetchDockerDiff:P}=vs(),{projects:y}=_s(),{syncStatusMap:c,pushSettings:w,pullSettings:v,syncAuth:l,trackNode:j,getAuthSyncState:_,getAuthProviders:k}=Es(),{dockerNodes:L,loading:E,refresh:V,getContainerStatus:x,getLogs:m,create:C}=rt(),[B,H]=s.useState(!1),[J,W]=s.useState(!1),[D,X]=s.useState(null);s.useEffect(()=>{const M=a.filter($=>$.type==="remote");for(const $ of M)j($.id)},[a,j]),s.useEffect(()=>{if(!D)return;const M=a.find($=>$.id===D.id)??null;X(M)},[a,D]);const q=s.useMemo(()=>{const M=a.length,$=a.filter(U=>U.status==="online").length,F=a.filter(U=>U.status==="offline"||U.status==="error").length,G=a.filter(U=>U.type==="remote").length,re=a.filter(U=>U.type==="remote"&&c[U.id]&&pe(c[U.id]).syncState==="synced").length,ae=L.length;return{total:M,online:$,offline:F,remote:G,synced:re,docker:ae}},[L.length,a,c]),Q=s.useCallback(async M=>{await o(M)},[o]),Y=s.useCallback(async M=>{try{await C(M),t(`Docker node "${M.name}" created`,"success"),W(!1)}catch($){const F=$ instanceof Error?$.message:"Failed to create Docker node";throw t(F,"error"),$}},[t,C]),te=s.useMemo(()=>{const M=new Map;for(const $ of L)$.nodeId&&M.set($.nodeId,$);return M},[L]),R=s.useCallback(async()=>{try{await Promise.all([g(),V()])}catch{t("Failed to refresh nodes","error")}},[t,g,V]),Z=s.useCallback(async M=>{try{await b(M),t("Node health check complete","success")}catch($){const F=$ instanceof Error?$.message:"Health check failed";t(F,"error")}},[t,b]),ee=s.useCallback(async M=>{try{await d(M),t("Node removed","success"),D?.id===M&&X(null)}catch($){const F=$ instanceof Error?$.message:"Failed to remove node";t(F,"error")}},[t,D?.id,d]),O=s.useCallback(async(M,$)=>{await p(M,$)},[p]);return e.jsxs("div",{className:"nodes-view","data-testid":"nodes-view",children:[e.jsxs("div",{className:"nodes-view-header",children:[e.jsxs("div",{className:"nodes-view-title",children:[e.jsxs("h2",{children:[e.jsx(Ve,{size:20}),"Nodes"]}),e.jsxs("span",{className:"nodes-view-count",children:[a.length," registered"]})]}),e.jsxs("div",{className:"nodes-view-actions",children:[e.jsx("button",{className:"btn-icon nodes-view-close",onClick:n,"aria-label":"Close nodes view",children:e.jsx(ue,{size:16})}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void R(),disabled:i||E,children:[e.jsx(_e,{size:14,className:i?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>H(!0),children:[e.jsx(me,{size:14}),"Add Node"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>W(!0),title:"Add a managed Docker node",children:[e.jsx(ye,{size:14}),"Add Docker Node"]})]})]}),e.jsxs("div",{className:"nodes-view-stats",children:[e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-total",children:[e.jsx("span",{children:"Total"}),e.jsx("strong",{children:q.total})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--online","data-testid":"nodes-stat-online",children:[e.jsxs("span",{children:[e.jsx(ws,{size:14})," Online"]}),e.jsx("strong",{children:q.online})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--offline","data-testid":"nodes-stat-offline",children:[e.jsxs("span",{children:[e.jsx(Cs,{size:14})," Offline"]}),e.jsx("strong",{children:q.offline})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-remote",children:[e.jsxs("span",{children:[e.jsx(Ns,{size:14})," Remote"]}),e.jsx("strong",{children:q.remote})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--synced","data-testid":"nodes-stat-synced",children:[e.jsxs("span",{children:[e.jsx(_e,{size:14})," Synced"]}),e.jsx("strong",{children:q.synced})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-docker",children:[e.jsxs("span",{children:[e.jsx(ye,{size:14})," Docker"]}),e.jsx("strong",{children:q.docker})]})]}),u&&e.jsx("div",{className:"nodes-view-error",children:u}),!i&&a.length>0&&e.jsxs("section",{className:"nodes-view-topology","aria-label":"Mesh Topology",children:[e.jsx("h3",{className:"nodes-view-section-title",children:"Mesh Topology"}),e.jsx(Os,{nodes:a})]}),i?e.jsx("div",{className:"nodes-view-grid",children:Array.from({length:4}).map((M,$)=>e.jsx("div",{className:"node-card node-card--loading","aria-hidden":!0},$))}):a.length===0?e.jsxs("div",{className:"nodes-view-empty",children:[e.jsx("p",{children:"No nodes are registered yet."}),e.jsxs("button",{className:"btn btn-primary",onClick:()=>H(!0),children:[e.jsx(me,{size:14}),"Add First Node"]})]}):e.jsx("div",{className:"nodes-view-grid",children:a.map(M=>{const $=M.type==="remote"&&c[M.id]?pe(c[M.id]):void 0;return e.jsx(Is,{node:M,projects:y,onHealthCheck:F=>{Z(F)},onEdit:F=>X(F),onRemove:F=>{ee(F)},isLoading:i,syncStatus:$,authSyncState:M.type==="remote"?_(M.id):void 0,authSyncProviders:M.type==="remote"?k(M.id):void 0,managedDockerNode:te.get(M.id)},M.id)})}),e.jsx(Ts,{isOpen:B,onClose:()=>H(!1),onSubmit:Q,addToast:t}),e.jsx(Ys,{isOpen:J,onClose:()=>W(!1),onSubmit:Y,addToast:t}),e.jsx(at,{isOpen:D!==null,onClose:()=>X(null),node:D,projects:y,onUpdate:O,onHealthCheck:Z,addToast:t,syncStatus:D?.type==="remote"&&D&&c[D.id]?pe(c[D.id]):void 0,onPushSettings:w,onPullSettings:v,onSyncAuth:l,managedDockerNode:D?te.get(D.id):void 0,onFetchContainerStatus:x,onFetchLogs:m,onUpdateDockerConfig:N,onFetchDockerConfigDiff:P})]})}export{ut as NodesView};
@@ -1 +0,0 @@
1
- .nodes-management-overlay{display:flex;flex-direction:column;gap:var(--space-md);height:100%;overflow-y:auto;-webkit-overflow-scrolling:touch}.nodes-management-overlay__header{display:flex;justify-content:flex-end}.nodes-view{--nodes-view-spin-duration: calc(var(--transition-slow) * 4);--nodes-view-pulse-duration: calc(var(--transition-slow) * 5);display:flex;flex-direction:column;gap:var(--space-md);padding:var(--space-sm) var(--space-md) var(--space-xl)}.nodes-view-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--space-sm)}.nodes-view-title{display:flex;align-items:center;gap:var(--space-sm)}.nodes-view-title h2{margin:0;display:flex;align-items:center;gap:var(--space-sm)}.nodes-view-count{color:var(--text-muted);font-size:calc(var(--space-md) + var(--space-xs) / 4)}.nodes-view-actions{display:flex;gap:var(--space-sm)}.nodes-view-close{margin-left:auto}.nodes-view-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(calc(var(--space-xl) * 5.833),1fr));gap:var(--space-sm)}.nodes-view-stat{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-sm) var(--space-md);display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}.nodes-view-stat span{display:inline-flex;align-items:center;gap:var(--space-sm);color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs))}.nodes-view-stat strong{font-size:calc(var(--space-lg) + var(--space-xs) / 2)}.nodes-view-stat--online strong{color:var(--color-success)}.nodes-view-stat--offline strong{color:var(--color-error)}.nodes-view-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(calc(var(--space-lg) * 20),1fr));gap:var(--space-md)}.nodes-view-empty{padding:var(--space-xl);border:1px dashed var(--border);border-radius:var(--radius-md);text-align:center;color:var(--text-muted);display:flex;flex-direction:column;align-items:center;gap:var(--space-md)}.nodes-view-error{color:var(--color-error);font-size:calc(var(--space-md) + var(--space-xs) / 4)}.node-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md);display:flex;flex-direction:column;gap:var(--space-md);cursor:pointer;transition:border-color var(--transition-fast),transform var(--transition-fast)}.node-card:hover{border-color:var(--accent);transform:translateY(calc(var(--space-xs) * -.25))}.node-card:focus-visible{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.node-card--loading{min-height:calc(var(--space-xl) * 9.167);opacity:.55;pointer-events:none}.node-card__header{display:flex;align-items:center;justify-content:space-between}.node-card__title-wrap{display:flex;align-items:center;gap:var(--space-sm)}.node-card__icon{width:calc(var(--space-lg) * 2.125);height:calc(var(--space-lg) * 2.125);border-radius:var(--radius-sm);display:inline-flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent)}.node-card__name{margin:0;font-size:calc(var(--space-md) + var(--space-xs));line-height:1.25}.node-card__meta-row{margin-top:var(--space-xs);display:flex;align-items:center;gap:var(--space-xs)}.node-card__type-badge{border:1px solid var(--border);border-radius:var(--radius-pill);padding:var(--space-xs) var(--space-sm);font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted)}.node-card__status{display:inline-flex;align-items:center;gap:var(--space-xs);font-size:calc(var(--space-sm) + var(--space-xs) * .75);font-weight:600}.node-card__status-indicator{width:var(--space-sm);height:var(--space-sm);border-radius:50%}.node-card__status--online .node-card__status-indicator{background:var(--color-success)}.node-card__status--offline .node-card__status-indicator,.node-card__status--error .node-card__status-indicator{background:var(--color-error)}.node-card__status--connecting .node-card__status-indicator{background:var(--color-warning)}.node-card__auth-indicator{display:inline-flex;align-items:center;margin-left:var(--space-xs);vertical-align:middle}.node-card__url{font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted);word-break:break-all}.node-card__metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.node-card__metric{display:flex;flex-direction:column;gap:var(--space-xs)}.node-card__metric-label{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs) * .75);text-transform:uppercase;letter-spacing:.03em}.node-card__metric-value{font-size:calc(var(--space-md) + var(--space-xs));font-weight:600}.node-card__sync{display:flex;align-items:center;gap:var(--space-xs);margin-top:var(--space-sm);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.node-card__sync-dot{width:var(--space-sm);height:var(--space-sm);border-radius:50%;flex-shrink:0}.node-card__sync-time{color:var(--text-muted)}.nodes-view-stat--synced strong{color:var(--color-success)}.node-card__actions{display:flex;gap:var(--space-xs);flex-wrap:wrap}.node-card__action{display:inline-flex;align-items:center;gap:var(--space-xs)}.node-card__action--remove{margin-left:auto}.node-card__action--remove:not(.btn-danger){color:var(--color-error);border-color:color-mix(in srgb,var(--color-error) 45%,var(--border))}.node-card__action--remove.is-armed{background:color-mix(in srgb,var(--color-error) 14%,transparent)}.node-card__docker-badge{display:inline-flex;align-items:center;gap:var(--space-xs);border-radius:var(--radius-pill);padding:var(--space-xs) var(--space-sm);font-size:calc(var(--space-sm) + var(--space-xs) * .75);background:color-mix(in srgb,var(--color-info) 15%,transparent);color:var(--color-info)}.node-card__docker-meta{display:flex;gap:var(--space-sm);margin-top:var(--space-xs);font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.node-card__docker-meta span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mesh-topology{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-md);min-height:calc(var(--space-2xl) * 6.25);padding:var(--space-md);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md)}.mesh-topology__svg{width:100%;max-width:calc(var(--space-2xl) * 12.5);height:auto;aspect-ratio:1}.mesh-topology__node{transition:filter var(--transition-fast)}.mesh-topology__node:hover{filter:brightness(1.1)}.mesh-topology__node-circle{stroke:var(--border);stroke-width:calc(var(--space-xs) / 2);transition:fill var(--transition-fast)}.mesh-topology__node-label{font-size:calc(var(--space-sm) + var(--space-xs) * .75);fill:var(--text);font-weight:500}.mesh-topology__node-type-badge{fill:color-mix(in srgb,var(--surface) 75%,var(--bg));stroke:var(--border);stroke-width:calc(var(--space-xs) / 4)}.mesh-topology__node-type-text{font-size:calc(var(--space-sm) + var(--space-xs) / 2);font-weight:700;fill:var(--text-muted);text-transform:uppercase;letter-spacing:.03em}.mesh-topology__link{stroke:var(--border);stroke-width:calc((var(--space-xs) * 3) / 8);stroke-dasharray:var(--space-xs),var(--space-xs);opacity:.6}.mesh-topology__legend{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--space-md);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.mesh-topology__legend-item{display:flex;align-items:center;gap:var(--space-sm)}.mesh-topology__notice{margin:var(--space-md) 0 0;text-align:center;color:var(--text-dim);font-size:calc(var(--space-sm) + var(--space-xs))}.mesh-topology__legend-dot{width:calc(var(--space-sm) + var(--space-xs) / 2);height:calc(var(--space-sm) + var(--space-xs) / 2);border-radius:50%;border:1px solid var(--border)}.mesh-topology--empty{justify-content:center}.mesh-topology__empty-state{text-align:center;color:var(--text-muted);font-size:calc(var(--space-md) + var(--space-xs) / 2)}.connect-node-modal{width:min(calc(var(--space-lg) * 30),calc(100vw - (var(--space-lg) * 2)))}.connect-node-form{display:flex;flex-direction:column;gap:var(--space-md)}.connect-node-form .form-group{padding:0;margin-top:0}.connect-node-form .form-group:last-of-type{margin-bottom:0}.connect-node-field{display:flex;flex-direction:column;gap:var(--space-xs)}.connect-node-field__input{width:100%}.connect-node-field__input[aria-invalid=true]{border-color:var(--color-error);background:color-mix(in srgb,var(--color-error) 5%,var(--surface))}.connect-node-field__input[aria-invalid=true]:focus-visible{border-color:var(--color-error);box-shadow:var(--glow-danger)}.connect-node-url-preview{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);background:color-mix(in srgb,var(--surface) 50%,var(--bg));border-radius:var(--radius-sm);border-left:var(--space-xs) solid var(--accent);font-size:calc(var(--space-sm) + var(--space-xs))}.connect-node-url-preview-label{color:var(--text-muted)}.connect-node-url-preview code{font-family:var(--font-mono);color:var(--text);font-size:calc(var(--space-sm) + var(--space-xs))}.connect-node-actions{display:flex;justify-content:flex-end;gap:var(--space-sm);padding:var(--modal-padding);border-top:1px solid var(--border)}.nodes-view-topology{margin-bottom:var(--space-md)}.nodes-view-section-title{font-size:calc(var(--space-md) + var(--space-xs) * .5);font-weight:600;color:var(--text);margin:0 0 var(--space-sm)}.nodes-view .node-status-indicator{display:inline-flex;align-items:center;gap:var(--space-xs);font-size:calc(var(--space-sm) + var(--space-xs) * .625)}.nodes-view .node-status-indicator__label,.nodes-view .node-status-indicator--local{color:var(--text-muted)}.nodes-view .node-status-indicator--remote{color:var(--text)}.nodes-view .node-status-indicator__dot{width:var(--space-sm);height:var(--space-sm);border-radius:50%;position:relative;display:inline-block}.nodes-view .node-status-indicator__dot--online{background:var(--color-success);box-shadow:var(--glow-success)}.nodes-view .node-status-indicator__dot--offline,.nodes-view .node-status-indicator__dot--error{background:var(--color-error)}.nodes-view .node-status-indicator__dot--connecting{background:var(--color-warning);animation:pulse-warning var(--nodes-view-pulse-duration) ease-in-out infinite}.nodes-view .node-status-indicator__spinner{position:absolute;inset:0;border:calc(var(--space-xs) / 2) solid transparent;border-top-color:currentColor;border-radius:50%;animation:spin var(--nodes-view-spin-duration) linear infinite}.nodes-view .node-status-indicator__name{font-weight:500}.nodes-view .node-status-indicator__details{font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}@keyframes pulse-warning{0%,to{opacity:1;box-shadow:var(--glow-warning)}50%{opacity:.6;box-shadow:var(--glow-warning)}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.spin{animation:spin var(--nodes-view-spin-duration) linear infinite}@media(max-width:768px){.nodes-view{padding-inline:var(--space-sm)}.nodes-view-grid,.node-card__metrics{grid-template-columns:1fr}.node-card__docker-badge,.node-card__docker-meta{gap:var(--space-xs)}.node-card__docker-meta span{max-width:calc(var(--space-2xl) * 4.5)}.connect-node-modal{width:calc(100vw - (var(--space-md) * 2))}.connect-node-field__input{min-height:calc(var(--space-2xl) + var(--space-md))}.nodes-view-header{flex-wrap:wrap;gap:var(--space-sm)}.nodes-view-title h2{font-size:calc(var(--space-md) + var(--space-xs))}.nodes-view-title h2 svg{flex-shrink:0}.nodes-view-count{font-size:calc(var(--space-sm) + var(--space-xs))}.nodes-view-actions{flex-wrap:wrap;gap:var(--space-sm);width:100%;justify-content:flex-end}.nodes-view-close{min-height:calc(var(--space-xl) + var(--space-md));min-width:calc(var(--space-xl) + var(--space-md))}.nodes-view-actions .btn{min-height:calc(var(--space-xl) + var(--space-md))}.nodes-view-stats{grid-template-columns:repeat(2,1fr);gap:var(--space-sm)}.nodes-view-stat{padding:var(--space-xs) var(--space-sm)}.nodes-view-stat span{font-size:calc(var(--space-sm) + var(--space-xs) * .75)}.nodes-view-stat strong{font-size:calc(var(--space-md) + var(--space-xs) / 2)}.nodes-view-empty{padding:var(--space-xl) var(--space-md);text-align:center}.nodes-view-error{padding:var(--space-md);margin:var(--space-md) 0}.nodes-view-topology{padding:var(--space-sm) 0}.nodes-view-section-title{font-size:calc(var(--space-md) + var(--space-xs) / 4)}}.add-node-modal{width:min(calc(var(--space-lg) * 32.5),calc(100vw - (var(--space-lg) * 2)))}.add-node-modal__body{display:flex;flex-direction:column;gap:var(--space-md)}.add-node-modal__row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.add-node-modal__fieldset{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-sm)}.add-node-modal__fieldset legend{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs) * .625);padding:0 var(--space-xs)}.add-node-modal__storage-toggle{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-sm)}.add-node-modal__advanced-btn{align-self:flex-start}.add-node-modal__advanced{border:1px dashed var(--border);border-radius:var(--radius-sm);padding:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-sm)}.add-node-modal__textarea{min-height:calc(var(--space-2xl) * 2.25);resize:vertical;font-family:var(--font-mono)}.add-node-modal__description{font-size:calc(var(--space-sm) + var(--space-xs) * .625);color:var(--text-muted);margin-bottom:var(--space-sm);padding:0}.add-node-modal__field{display:flex;flex-direction:column;gap:var(--space-xs)}.add-node-modal__field>span{font-size:calc(var(--space-sm) + var(--space-xs) * .625);font-weight:600;color:var(--text-muted)}.add-node-modal__field .input{width:100%;padding:var(--space-sm) var(--space-md);font-size:calc(var(--space-md) + var(--space-xs) * .5)}.add-node-modal__field .input:focus-visible{border-color:var(--accent);box-shadow:var(--focus-ring-strong)}.add-node-modal__field .input[aria-invalid=true]{border-color:var(--color-error);background:color-mix(in srgb,var(--color-error) 5%,var(--surface))}.add-node-modal__field .input[aria-invalid=true]:focus{box-shadow:var(--glow-danger)}.add-node-modal__hint{font-size:calc(var(--space-sm) + var(--space-xs) * .375);color:var(--text-dim);margin-top:calc(var(--space-xs) / 2)}.add-node-modal__error{margin-top:calc(var(--space-xs) / 2)}.add-node-modal__type-toggle{display:flex;gap:0;border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;background:var(--surface)}.add-node-modal__type-btn{flex:1;padding:calc(var(--space-sm) + var(--space-xs) / 2) var(--space-lg);border:none;background:transparent;color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs) * .625);font-weight:500;cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.add-node-modal__type-btn:hover:not(:disabled){background:color-mix(in srgb,var(--bg) 50%,var(--surface))}.add-node-modal__type-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);z-index:1}.add-node-modal__type-btn.active{background:var(--accent);color:var(--bg)}.add-node-modal__type-btn:disabled{opacity:.6;cursor:not-allowed}.add-node-modal__remote-fields{display:grid;gap:var(--space-sm)}@media(max-width:768px){.add-node-modal{width:calc(100vw - (var(--space-md) * 2))}.add-node-modal__type-toggle{width:100%}.add-node-modal__type-btn{flex:1;padding:var(--space-md) var(--space-lg)}.add-node-modal__field input{min-height:calc(var(--space-2xl) + var(--space-md));font-size:calc(var(--space-md) + var(--space-xs) * .5)}.add-node-modal__row{grid-template-columns:1fr}}.docker-tls-config{display:flex;flex-direction:column;gap:var(--space-md)}.docker-tls-config__fields{display:grid;gap:var(--space-md)}.docker-tls-config__field{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-tls-config__field label{color:var(--text-muted)}@media(max-width:768px){.docker-tls-config .input{min-height:calc(var(--mobile-nav-height) - var(--space-sm))}}.docker-target-selector{display:flex;flex-direction:column;gap:var(--space-md)}.docker-target-selector__modes{display:flex;gap:var(--space-sm);flex-wrap:wrap}.docker-target-selector__mode-active{border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.docker-target-selector__panel{display:grid;gap:var(--space-md)}.docker-target-selector__field{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-target-selector__field label{color:var(--text-muted)}.docker-target-selector__context-row{display:grid;gap:var(--space-sm);grid-template-columns:minmax(0,1fr) auto;align-items:center}.docker-target-selector__status{color:var(--text-muted)}.docker-target-selector__success{color:var(--color-success)}.docker-target-selector__error{color:var(--color-error)}@media(max-width:768px){.docker-target-selector__modes .btn{min-height:calc(var(--mobile-nav-height) - var(--space-sm))}}.docker-onboarding{width:min(calc(var(--space-2xl) * 22.5),calc(100vw - (var(--space-lg) * 2)))}.docker-onboarding__body{display:flex;flex-direction:column;gap:var(--space-md)}.docker-onboarding__section{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md);display:flex;flex-direction:column;gap:var(--space-sm)}.docker-onboarding__section-title{margin:0;display:flex;align-items:center;gap:var(--space-sm);font-size:calc(var(--space-md) + var(--space-xs) / 2)}.docker-onboarding__field{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-onboarding__inline-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.docker-onboarding__radio-group{display:flex;align-items:center;gap:var(--space-md);flex-wrap:wrap}.docker-onboarding__type-toggle{display:flex;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}.docker-onboarding__type-btn{flex:1;border:none;background:var(--surface);color:var(--text);padding:var(--space-sm) var(--space-md);cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.docker-onboarding__type-btn+.docker-onboarding__type-btn{border-left:1px solid var(--border)}.docker-onboarding__type-btn.is-active{background:var(--todo);color:var(--bg)}.docker-onboarding__type-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);position:relative;z-index:1}.docker-onboarding__checkbox-group{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-onboarding__kv-list{display:flex;flex-direction:column;gap:var(--space-sm)}.docker-onboarding__kv-list h5{margin:0;font-size:calc(var(--space-sm) + var(--space-xs))}.docker-onboarding__kv-row{display:grid;gap:var(--space-sm);align-items:center}.docker-onboarding__kv-row--env{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto}.docker-onboarding__kv-row--mount{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto auto}.docker-onboarding__kv-add{align-self:flex-start}.docker-onboarding__advanced-toggle{border:none;background:none;color:var(--text);padding:var(--space-xs);margin:calc(var(--space-xs) * -1);border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:space-between;width:100%;cursor:pointer;font-size:calc(var(--space-md) + var(--space-xs) / 2);font-weight:600}.docker-onboarding__advanced-toggle:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.docker-onboarding__advanced-toggle svg{transition:transform var(--transition-fast)}.docker-onboarding__advanced-toggle.is-expanded svg{transform:rotate(180deg)}.docker-onboarding__advanced-content{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--transition-fast)}.docker-onboarding__advanced-content>div{overflow:hidden;display:flex;flex-direction:column;gap:var(--space-sm)}.docker-onboarding__advanced-content.is-expanded{grid-template-rows:1fr}.docker-onboarding__tls-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.docker-onboarding__tls-fields .docker-onboarding__field:first-child{grid-column:1 / -1}@media(max-width:768px){.docker-onboarding{width:calc(100vw - (var(--space-md) * 2))}.docker-onboarding__inline-fields,.docker-onboarding__tls-fields,.docker-onboarding__kv-row{grid-template-columns:1fr}.docker-onboarding .input,.docker-onboarding .select,.docker-onboarding .btn{min-height:calc(var(--space-2xl) + var(--space-md))}.docker-onboarding__advanced-content{transition:none}}.settings-sync-log{display:flex;flex-direction:column;gap:var(--space-sm)}.settings-sync-log__header{display:flex;align-items:center;gap:var(--space-xs);cursor:pointer;padding:var(--space-xs) 0;border-radius:var(--radius-sm);border:none;background:transparent;color:var(--text);font:inherit;text-align:left;transition:background-color var(--transition-fast)}.settings-sync-log__header:hover{background:var(--surface-hover)}.settings-sync-log__header:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);background:var(--surface-hover)}.settings-sync-log__chevron{transform:rotate(0);transition:transform var(--transition-fast)}.settings-sync-log__chevron--expanded{transform:rotate(180deg)}.settings-sync-log__filters{display:flex;gap:var(--space-sm);align-items:center;flex-wrap:wrap}.settings-sync-log__filters label{display:flex;align-items:center;gap:var(--space-xs);font-size:12px;color:var(--text-muted)}.settings-sync-log__filters select{font-size:12px;padding:4px 8px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text)}.settings-sync-log__filters select:focus{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring)}.settings-sync-log__list{display:flex;flex-direction:column}.settings-sync-log__entry{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-xs) 0;border-bottom:1px solid var(--border)}.settings-sync-log__entry:last-child{border-bottom:none}.settings-sync-log__entry-timestamp{font-size:12px;color:var(--text-muted);min-width:140px}.settings-sync-log__entry-direction{display:flex;align-items:center;color:var(--text-muted)}.settings-sync-log__entry-result{display:inline-flex;padding:2px 8px;border-radius:999px;font-size:11px;font-weight:500}.settings-sync-log__badge--success{background:color-mix(in srgb,var(--color-success, #2da44e) 14%,transparent);color:var(--color-success, #2da44e)}.settings-sync-log__badge--conflict{background:color-mix(in srgb,#d29922 14%,transparent);color:#d29922}.settings-sync-log__badge--error{background:color-mix(in srgb,var(--color-error, #cf222e) 14%,transparent);color:var(--color-error, #cf222e)}.settings-sync-log__entry-node{font-weight:500;font-size:12px}.settings-sync-log__entry-details{font-size:12px;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.settings-sync-log__empty{text-align:center;color:var(--text-muted);padding:var(--space-md);font-size:13px}.node-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;background:color-mix(in srgb,var(--accent) 14%,transparent);border:1px solid color-mix(in srgb,var(--accent) 36%,transparent);color:var(--text-muted);font-size:11px;width:fit-content;margin-top:4px}@media(max-width:768px){.settings-sync-conflict-modal__diff-panel{grid-template-columns:1fr}}.settings-sync-conflict-modal{max-width:860px;width:min(860px,calc(100vw - 32px))}.settings-sync-conflict-modal__conflict-list{display:flex;flex-direction:column;gap:var(--space-md);max-height:min(50vh,400px);overflow-y:auto}.settings-sync-conflict-modal__conflict-item{border:1px solid var(--border);border-radius:var(--radius);padding:var(--space-md)}.settings-sync-conflict-modal__key{font-weight:600;font-family:monospace;margin-bottom:var(--space-sm)}.settings-sync-conflict-modal__diff-panel{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-sm);margin-bottom:var(--space-sm)}.settings-sync-conflict-modal__diff-side{border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}.settings-sync-conflict-modal__diff-label{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted);padding:4px 8px;border-bottom:1px solid var(--border);background:var(--surface)}.settings-sync-conflict-modal__diff-content{padding:var(--space-xs) var(--space-sm);white-space:pre;font-family:monospace;font-size:12px;line-height:1.5;overflow-x:auto}.settings-sync-conflict-modal__resolution{display:flex;gap:var(--space-md);align-items:center}.settings-sync-conflict-modal__resolution label{display:flex;align-items:center;gap:var(--space-xs);cursor:pointer}.settings-sync-conflict-modal__resolution input[type=radio]{cursor:pointer}.settings-sync-conflict-modal__manual-input{width:100%;font-family:monospace;font-size:12px;min-height:80px;margin-top:var(--space-xs);padding:var(--space-sm);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);resize:vertical}.settings-sync-conflict-modal__manual-input:focus{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring)}.settings-sync-conflict-modal__bulk-actions{display:flex;gap:var(--space-xs);padding-top:var(--space-sm);border-top:1px solid var(--border)}.settings-sync-conflict-modal__footer{display:flex;justify-content:flex-end;gap:var(--space-xs)}.node-detail-modal{max-width:calc(var(--space-lg) * 53.75);width:min(calc(var(--space-lg) * 53.75),calc(100vw - (var(--space-lg) * 2)))}.node-detail-modal__body{display:flex;flex-direction:column;gap:var(--space-md);max-height:min(72vh,calc(var(--space-lg) * 42.5));overflow-y:auto}.node-detail-modal__section{border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md)}.node-detail-modal__section h4{margin:0 0 var(--space-sm) 0}.node-detail-modal__section-header{display:flex;justify-content:space-between;align-items:center;gap:var(--space-sm);margin-bottom:var(--space-sm)}.node-detail-modal__grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.node-detail-modal__field{display:flex;flex-direction:column;gap:var(--space-xs)}.node-detail-modal__field--full{grid-column:span 2}.node-detail-modal__field span{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__edit-actions{margin-top:var(--space-sm);display:flex;gap:var(--space-xs)}.node-detail-modal__project-list{margin:0;padding-left:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-sm)}.node-detail-modal__project-item{display:flex;justify-content:space-between;align-items:center;gap:var(--space-sm)}.node-detail-modal__project-item code{color:var(--text-muted)}.node-detail-modal__empty{margin:0;color:var(--text-muted)}.node-detail-modal__health-row{display:flex;flex-wrap:wrap;gap:var(--space-md)}.node-detail-modal__actions{justify-content:space-between}.node-detail-modal__docker-config{display:flex;flex-direction:column;gap:var(--space-sm)}.node-detail-modal__docker-toggle{align-self:flex-start}.node-detail-modal__docker-toggle-icon--expanded{transform:rotate(180deg)}.node-detail-modal__docker-config-content{display:flex;flex-direction:column;gap:var(--space-sm)}.node-detail-modal__docker-list{display:flex;flex-direction:column;gap:var(--space-sm);margin-top:var(--space-sm)}.node-detail-modal__docker-row{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:var(--space-sm)}.node-detail-modal__docker-stack{display:flex;flex-direction:column;gap:var(--space-sm);margin-top:var(--space-sm)}.node-detail-modal__checkbox{display:flex;align-items:center;gap:var(--space-sm);color:var(--text-muted)}.node-detail-modal__docker-meta{display:flex;flex-wrap:wrap;gap:var(--space-sm);color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__docker-recreate{color:var(--color-warning)}.node-detail-modal__docker-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm);margin-top:var(--space-sm)}.node-detail-modal__textarea{min-height:calc(var(--space-2xl) * 2.25);resize:vertical;font-family:var(--font-mono)}.node-detail-modal__sync-status{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-sm);margin-bottom:var(--space-sm)}.node-detail-modal__sync-dot{width:calc(var(--space-sm) + var(--space-xs) / 2);height:calc(var(--space-sm) + var(--space-xs) / 2);border-radius:50%;flex-shrink:0}.node-detail-modal__sync-dot--synced{background:var(--color-success)}.node-detail-modal__sync-dot--diff,.node-detail-modal__sync-dot--pending{background:var(--color-warning)}.node-detail-modal__sync-dot--error{background:var(--color-error)}.node-detail-modal__sync-dot--never{background:var(--text-muted)}.node-detail-modal__sync-diff{color:var(--color-warning);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__sync-actions{display:flex;flex-wrap:wrap;gap:var(--space-sm);margin-top:var(--space-sm)}.node-detail-modal__sync-error{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm);margin-top:var(--space-sm);padding:var(--space-sm);background:color-mix(in srgb,var(--color-error) 10%,transparent);border:1px solid color-mix(in srgb,var(--color-error) 30%,transparent);border-radius:var(--radius-sm);color:var(--color-error);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__sync-error-dismiss{background:transparent;border:none;color:var(--color-error);cursor:pointer;padding:calc(var(--space-xs) / 2);display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm)}.node-detail-modal__sync-error-dismiss:hover{background:color-mix(in srgb,var(--color-error) 20%,transparent)}.node-detail-modal__sync-error-dismiss:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);background:color-mix(in srgb,var(--color-error) 20%,transparent)}.docker-management{display:flex;flex-direction:column;gap:var(--space-md)}.docker-management__status-card{display:flex;flex-direction:column;gap:var(--space-sm);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md)}.docker-management__status-row{display:inline-flex;align-items:center;gap:var(--space-sm)}.docker-management__status-dot{width:var(--space-sm);height:var(--space-sm);border-radius:50%}.docker-management__status-dot--success{background:var(--color-success)}.docker-management__status-dot--warning{background:var(--color-warning)}.docker-management__status-dot--error{background:var(--color-error)}.docker-management__status-meta{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs));display:flex;gap:var(--space-md);flex-wrap:wrap}.docker-management__actions{display:flex;flex-wrap:wrap;gap:var(--space-sm)}.docker-management__info-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.docker-management__log-viewer{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md)}.docker-management__log-viewer-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-sm)}.docker-management__log-viewer pre{margin:0;max-height:calc(var(--space-2xl) * 9.375);overflow-y:auto;font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text);white-space:pre-wrap}.docker-management__env-list{margin:var(--space-sm) 0 0}.docker-management__env-list div{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr);gap:var(--space-sm);padding:var(--space-xs) 0}.docker-management__env-list dt{color:var(--text-muted);font-family:var(--font-mono)}.docker-management__env-list dd{margin:0;font-family:var(--font-mono);word-break:break-all}.docker-management__mounts-list{margin:var(--space-sm) 0 0;padding-left:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-sm)}.docker-management__mounts-list li{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}@media(max-width:768px){.node-detail-modal__grid,.node-detail-modal__docker-grid{grid-template-columns:1fr}.node-detail-modal__field--full{grid-column:span 1}.docker-management__actions{flex-direction:column}.docker-management__actions .btn{width:100%;justify-content:center}.docker-management__info-grid,.node-detail-modal__docker-row{grid-template-columns:1fr}.node-detail-modal__docker-toggle,.node-detail-modal__docker-config-content .btn{min-height:calc(var(--space-lg) * 2.25)}.docker-management__env-list div{grid-template-columns:1fr}.docker-management__mounts-list li{flex-direction:column;align-items:flex-start}.docker-management__log-viewer pre{max-height:calc(var(--space-2xl) * 6.25)}}
@@ -1 +0,0 @@
1
- import{r as g,j as e}from"./vendor-react-K0fH_qHe.js";import{D as me,e0 as he,e1 as K,s as be,X,av as xe,Q as Y,aW as Z,a1 as T,R as fe,e2 as Ne,aQ as je,cn as ye,e3 as Se,e4 as ve,e5 as we,e6 as Ce,e7 as ee,ck as Ie,e8 as Pe}from"./index-D__RMku8.js";import{D as Ee}from"./DirectoryPicker-aVdFaV37.js";import"./vendor-xterm-DzcZoU0P.js";import"./folder-open-usZkXdq2.js";const ne="fusion-plugin-agent-browser",te={enabled:{type:"boolean",label:"Enable Agent Browser",group:"General"},installChannel:{type:"enum",label:"Install Channel",enumValues:["stable","beta","nightly"],defaultValue:"stable",group:"General"},commandTimeoutMs:{type:"number",label:"Command Timeout (ms)",defaultValue:12e4,group:"General"},headlessMode:{type:"boolean",label:"Headless Mode",defaultValue:!0,group:"Browser"},allowedDomains:{type:"array",label:"Allowed Domains",itemType:"string",group:"Browser"},promptExecutorSystem:{type:"string",label:"Executor System Prompt",multiline:!0,group:"Prompt Contributions"},promptExecutorTask:{type:"string",label:"Executor Task Prompt",multiline:!0,group:"Prompt Contributions"},promptTriage:{type:"string",label:"Triage Prompt",multiline:!0,group:"Prompt Contributions"},promptReviewer:{type:"string",label:"Reviewer Prompt",multiline:!0,group:"Prompt Contributions"},promptHeartbeat:{type:"string",label:"Heartbeat Prompt",multiline:!0,group:"Prompt Contributions"},skillExposure:{type:"enum",label:"Skill Exposure",enumValues:["none","selected","all"],defaultValue:"selected",group:"Skills"}},se=[{id:"fusion-plugin-hermes-runtime",name:"Hermes Runtime",description:"Runtime provider for Hermes CLI-backed execution.",category:"runtime",path:"./plugins/fusion-plugin-hermes-runtime",experimental:!0},{id:"fusion-plugin-paperclip-runtime",name:"Paperclip Runtime",description:"Runtime provider for Paperclip agent connections.",category:"runtime",path:"./plugins/fusion-plugin-paperclip-runtime"},{id:"fusion-plugin-openclaw-runtime",name:"OpenClaw Runtime",description:"Runtime provider for OpenClaw execution.",category:"runtime",path:"./plugins/fusion-plugin-openclaw-runtime",experimental:!0},{id:"fusion-plugin-droid-runtime",name:"Droid Runtime",description:"Runtime provider for Droid CLI execution.",category:"runtime",path:"./plugins/fusion-plugin-droid-runtime",experimental:!0},{id:"fusion-plugin-dependency-graph",name:"Dependency Graph",description:"Dashboard plugin for task dependency graph visualization.",category:"integration",path:"./plugins/fusion-plugin-dependency-graph"},{id:ne,name:"Agent Browser",description:"Built-in integration metadata. Package install support lands in FN-3101.",category:"integration",hasSetup:!0}],I={started:"var(--color-success)",loaded:"var(--color-warning)",error:"var(--color-error)",stopped:"var(--color-muted)",installed:"var(--color-info)"};function Re(c){const l=c.settingsSchema,h=l&&Object.keys(l).length>0;return c.id!==ne?h?l:void 0:h?{...te,...l}:te}function $e(c){const l=new Map,h=[];for(const[N,f]of Object.entries(c))if(f.group){const j=l.get(f.group)??[];j.push([N,f]),l.set(f.group,j)}else h.push([N,f]);return{grouped:l,ungrouped:h}}function Ae({addToast:c,projectId:l}){const[h,N]=g.useState([]),[f,j]=g.useState(!0),[ie,P]=g.useState(!1),[w,E]=g.useState(""),[k,F]=g.useState(!1),[y,L]=g.useState(null),[u,R]=g.useState(null),[d,b]=g.useState({}),[ae,D]=g.useState(!1),[z,A]=g.useState(null),[le,$]=g.useState({}),[re,O]=g.useState(null),[C,U]=g.useState(null),{confirm:ce}=me(),m=g.useCallback(async()=>{try{j(!0);const t=await he(l);N(t)}catch(t){c(`Failed to load plugins: ${t instanceof Error?t.message:String(t)}`,"error")}finally{j(!1)}},[l,c]);g.useEffect(()=>{m()},[m]),g.useEffect(()=>{const t=se.filter(r=>r.hasSetup&&h.some(a=>a.id===r.id));if(t.length===0)return;let i=!1;return Promise.all(t.map(async r=>{try{const a=await K(r.id,l);if(i)return;$(o=>({...o,[r.id]:a}))}catch{if(i)return;$(a=>({...a,[r.id]:{hasSetup:!0,status:"error",error:"Failed to check setup status"}}))}})),()=>{i=!0}},[h,l]);const oe=g.useRef([]);oe.current=h,g.useEffect(()=>{const t=l?`?projectId=${encodeURIComponent(l)}`:"",i=r=>{try{const a=JSON.parse(r.data);if(l&&a.projectId&&a.projectId!==l)return;switch(a.transition){case"installing":case"enabled":case"disabled":case"settings-updated":N(o=>{const n=o.findIndex(s=>s.id===a.pluginId);if(n>=0){const s=[...o];return s[n]={...s[n],enabled:a.enabled,state:a.state,settings:a.settings,error:a.error},s}else return m(),o});break;case"uninstalled":N(o=>o.filter(n=>n.id!==a.pluginId));break;case"error":N(o=>{const n=o.findIndex(s=>s.id===a.pluginId);if(n>=0){const s=[...o];return s[n]={...s[n],state:a.state,error:a.error},s}return o});break}}catch{}};return be(`/api/events${t}`,{events:{"plugin:lifecycle":i},onReconnect:()=>{m()}})},[l,m]);const q=async()=>{if(!w.trim()){c("Please enter a plugin path","error");return}try{F(!0),await ee({path:w},l),c("Plugin installed successfully","success"),P(!1),E(""),await m()}catch(t){c(`Failed to install plugin: ${t instanceof Error?t.message:String(t)}`,"error")}finally{F(!1)}},ue=async t=>{if(!t.path){c(`${t.name} is built in and does not have an installable package yet`,"warning");return}try{A(t.id),await ee({path:t.path},l),c(`${t.name} installed successfully`,"success"),await m()}catch(i){c(`Failed to install ${t.name}: ${i instanceof Error?i.message:String(i)}`,"error")}finally{A(null)}},_=async t=>{try{U(t.id);const i=await Pe(t.id,l);if(!i.success){c(`Failed to install ${t.name} setup: ${i.error??"unknown error"}`,"error");return}c(`${t.name} setup installed`,"success"),O(t.id);const r=await K(t.id,l);$(a=>({...a,[t.id]:r}))}catch(i){c(`Failed to install ${t.name} setup: ${i instanceof Error?i.message:String(i)}`,"error")}finally{U(null),O(null)}},G=async t=>{try{await we(t.id,l),c(`${t.name} enabled`,"success"),await m()}catch(i){c(`Failed to enable plugin: ${i instanceof Error?i.message:String(i)}`,"error")}},M=async t=>{try{await ve(t.id,l),c(`${t.name} disabled`,"success"),await m()}catch(i){c(`Failed to disable plugin: ${i instanceof Error?i.message:String(i)}`,"error")}},V=async t=>{try{L(t.id),await Se(t.id,l),c(`${t.name} reloaded`,"success"),await m()}catch(i){c(`Failed to reload plugin: ${i instanceof Error?i.message:String(i)}`,"error")}finally{L(null)}},H=async t=>{if(await ce({title:"Uninstall Plugin",message:`Are you sure you want to uninstall "${t.name}"?`,danger:!0}))try{await Ce(t.id,l),c(`${t.name} uninstalled`,"success"),await m(),R(null)}catch(r){c(`Failed to uninstall plugin: ${r instanceof Error?r.message:String(r)}`,"error")}},B=async t=>{R(t);try{D(!0);const i=await Ie(t.id,l);b(i)}catch{b({})}finally{D(!1)}},de=async()=>{if(u)try{await ye(u.id,d,l),c("Settings saved","success")}catch(t){c(`Failed to save settings: ${t instanceof Error?t.message:String(t)}`,"error")}};if(u)return e.jsxs("div",{className:"plugin-manager-detail","data-testid":"plugin-manager-detail",children:[e.jsxs("div",{className:"plugin-manager-detail-header",children:[e.jsx("button",{className:"btn-icon",onClick:()=>R(null),"aria-label":"Back to plugin list",children:e.jsx(X,{size:16})}),e.jsxs("div",{className:"plugin-detail-title",children:[e.jsx("h4",{className:"plugin-detail-name",children:u.name}),e.jsx("span",{className:"plugin-state-badge",style:{color:I[u.state]||I.installed},children:u.state})]})]}),e.jsxs("div",{className:"plugin-detail-content",children:[e.jsxs("div",{className:"plugin-detail-card",children:[u.description&&e.jsx("p",{className:"plugin-description",children:u.description}),u.author&&e.jsxs("p",{className:"plugin-detail-meta-row",children:[e.jsx("span",{className:"text-muted",children:"Author:"}),u.author]}),u.homepage&&e.jsxs("p",{className:"plugin-detail-meta-row plugin-homepage",children:[e.jsx("span",{className:"text-muted",children:"Homepage:"}),e.jsxs("a",{href:u.homepage,target:"_blank",rel:"noopener noreferrer",children:[u.homepage,e.jsx(xe,{size:12})]})]}),e.jsxs("p",{className:"plugin-detail-meta-row",children:[e.jsx("span",{className:"text-muted",children:"Version:"}),u.version]})]}),e.jsxs("div",{className:"plugin-detail-card",children:[e.jsx("h5",{className:"plugin-detail-section-heading",children:"Settings"}),ae?e.jsx("p",{className:"text-muted",children:"Loading..."}):(()=>{const t=Re(u);return t&&Object.keys(t).length>0?e.jsxs("div",{className:"plugin-settings-form",children:[(()=>{const{grouped:i,ungrouped:r}=$e(t),a=[];r.length>0&&a.push({title:null,entries:r});for(const[o,n]of i.entries())a.push({title:o,entries:n});return a.map(o=>e.jsxs("div",{className:o.title?"plugin-settings-group":void 0,children:[o.title&&e.jsx("h6",{className:"plugin-settings-group-heading",children:o.title}),o.entries.map(([n,s])=>{const x=`setting-${n}-help`;return e.jsxs("div",{className:"form-group",children:[e.jsxs("label",{htmlFor:`setting-${n}`,children:[s.label||n,s.required&&" *"]}),s.type==="string"&&!s.multiline&&e.jsx("input",{className:"input",type:"text",id:`setting-${n}`,value:d[n]??"",onChange:p=>b({...d,[n]:p.target.value}),placeholder:s.description,"aria-describedby":s.description&&!s.required?x:void 0}),s.type==="string"&&s.multiline&&e.jsx("textarea",{className:"input",id:`setting-${n}`,rows:4,value:d[n]??"",onChange:p=>b({...d,[n]:p.target.value}),placeholder:s.description,"aria-describedby":s.description&&!s.required?x:void 0}),s.type==="password"&&e.jsx("input",{className:"input",type:"password",id:`setting-${n}`,value:d[n]??"",onChange:p=>b({...d,[n]:p.target.value}),placeholder:s.description,"aria-describedby":s.description&&!s.required?x:void 0}),s.type==="number"&&e.jsx("input",{className:"input",type:"number",id:`setting-${n}`,value:d[n]??"",onChange:p=>b({...d,[n]:Number(p.target.value)}),"aria-describedby":s.description&&!s.required?x:void 0}),s.type==="boolean"&&e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:d[n]??!1,onChange:p=>b({...d,[n]:p.target.checked})}),s.description]}),s.type==="enum"&&e.jsxs("select",{className:"select",id:`setting-${n}`,value:d[n]??"",onChange:p=>b({...d,[n]:p.target.value}),"aria-describedby":s.description&&!s.required?x:void 0,children:[e.jsx("option",{value:"",children:"Select..."}),s.enumValues?.map(p=>e.jsx("option",{value:p,children:p},p))]}),s.type==="array"&&e.jsxs("div",{className:"plugin-settings-array",children:[d[n]?.map((p,S)=>e.jsxs("div",{className:"plugin-settings-array-item",children:[e.jsx("input",{className:"input",type:s.itemType==="number"?"number":"text",value:p??"",onChange:Q=>{const v=Q.target.value,J=[...d[n]||[]];J[S]=s.itemType==="number"?Number(v):v,b({...d,[n]:J})}}),e.jsx("button",{className:"btn-icon",onClick:()=>{const v=[...d[n]||[]];v.splice(S,1),b({...d,[n]:v})},"aria-label":"Remove item",children:e.jsx(X,{size:14})})]},S)),e.jsxs("button",{className:"btn btn-secondary",onClick:()=>{const p=d[n]||[],S=s.itemType==="number"?0:"";b({...d,[n]:[...p,S]})},children:[e.jsx(Y,{size:14})," Add Item"]})]}),s.description&&!s.required&&!s.multiline&&e.jsx("span",{id:x,className:"form-help",children:s.description})]},n)})]},o.title??"ungrouped"))})(),e.jsx("button",{className:"btn btn-primary",onClick:de,children:"Save Settings"})]}):e.jsx("p",{className:"text-muted",children:"No configurable settings."})})()]}),e.jsxs("div",{className:"plugin-detail-actions",children:[u.state==="started"&&e.jsxs("button",{className:"btn btn-secondary",onClick:()=>V(u),disabled:y===u.id,children:[e.jsx(Z,{size:14,className:y===u.id?"spin":""}),y===u.id?"Reloading...":"Reload"]}),u.enabled?e.jsx("button",{className:"btn btn-secondary",onClick:()=>M(u),children:"Disable"}):e.jsx("button",{className:"btn btn-primary",onClick:()=>G(u),children:"Enable"}),e.jsxs("button",{className:"btn btn-danger",onClick:()=>H(u),children:[e.jsx(T,{size:14})," Uninstall"]})]})]})]});const pe=new Map(h.map(t=>[t.id,t])),W=h,ge=()=>e.jsxs("section",{className:"plugin-builtins-section","aria-label":"Built-in Plugins",children:[e.jsxs("div",{className:"plugin-builtins-header",children:[e.jsx("h4",{className:"plugin-builtins-heading",children:"Built-in Plugins"}),e.jsx("p",{className:"plugin-builtins-description",children:"Built-in plugin catalog for runtimes and integrations."})]}),e.jsx("div",{className:"plugin-builtins-list","aria-label":"Built-in plugin recommendations",children:se.map(t=>{const i=pe.get(t.id),r=!!i,a=le[t.id],o=r&&t.hasSetup&&a?.hasSetup&&(a.status==="not-installed"||a.status==="error"),n=r&&a?.hasSetup&&a.status==="installed",s=re===t.id,x=!t.path;return e.jsxs("div",{className:"plugin-builtins-item",children:[e.jsxs("div",{className:"plugin-builtins-meta",children:[e.jsx("span",{className:"plugin-builtins-name",children:t.name}),t.experimental&&e.jsx("span",{className:"plugin-builtins-runtime-badge",children:"Experimental"}),e.jsx("span",{className:"plugin-builtins-runtime-badge",children:t.category}),e.jsx("span",{className:`plugin-builtins-status ${r?"plugin-builtins-status--installed":"plugin-builtins-status--available"}`,children:r?"Installed":x?"Built in":"Not installed"}),o&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--warning",children:"Setup required"}),n&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--ready",children:"Setup ready"}),s&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--pending",children:"Checking setup..."}),e.jsx("span",{className:"plugin-builtins-description-text",children:t.description})]}),x?r&&o?e.jsx("button",{className:"btn btn-primary btn-sm",onClick:()=>void _(t),disabled:C===t.id||s,children:C===t.id?"Setting up...":"Install Setup"}):r&&i?e.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>void B(i),children:"Manage"}):e.jsx("span",{className:"plugin-builtins-metadata-only",children:"Built-in metadata only"}):e.jsx("button",{className:`btn ${r&&!o?"btn-secondary":"btn-primary"} btn-sm`,onClick:()=>{if(!r){ue(t);return}if(o){_(t);return}i&&B(i)},disabled:z===t.id||C===t.id||s,children:r?o?C===t.id?"Setting up...":"Install Setup":"Manage":z===t.id?"Installing...":`Install ${t.name}`})]},t.id)})})]});return e.jsxs("div",{className:"plugin-manager","data-testid":"plugin-manager",children:[e.jsxs("div",{className:"plugin-manager-header",children:[e.jsx("span",{className:"plugin-manager-header-title",children:"Installed Plugins"}),e.jsxs("div",{className:"plugin-manager-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:m,title:"Refresh","aria-label":"Refresh plugin list",children:[e.jsx(fe,{size:14,className:f?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>P(!0),children:[e.jsx(Y,{size:14})," Install"]})]})]}),ie&&e.jsxs("div",{className:"plugin-install-form",children:[e.jsxs("p",{className:"plugin-install-hint",children:["Browse to a plugin package root (contains ",e.jsx("code",{children:"manifest.json"}),") or a built ",e.jsx("code",{children:"dist"})," directory."]}),e.jsx(Ee,{value:w,onChange:E,placeholder:"Absolute path to plugin directory or dist folder",onInputKeyDown:t=>{t.key==="Enter"&&(t.preventDefault(),q())}}),e.jsxs("div",{className:"plugin-install-actions",children:[e.jsx("button",{className:"btn btn-primary",onClick:q,disabled:k||!w.trim(),children:k?"Installing...":"Install Plugin"}),e.jsx("button",{className:"btn btn-secondary",onClick:()=>{P(!1),E("")},children:"Cancel"})]})]}),f?e.jsx("div",{className:"settings-empty-state",children:"Loading plugins..."}):e.jsxs(e.Fragment,{children:[W.length===0?e.jsxs("div",{className:"settings-empty-state",children:[e.jsx(Ne,{size:32,className:"text-muted"}),e.jsx("p",{children:"No plugins installed."}),e.jsx("p",{className:"text-muted",children:"Install a plugin to get started, or use the built-in catalog below."})]}):e.jsx("div",{className:"plugin-list",children:W.map(t=>e.jsxs("div",{className:"plugin-item",children:[e.jsxs("div",{className:"plugin-info",children:[e.jsx("span",{className:"plugin-name",children:t.name}),e.jsxs("span",{className:"plugin-version text-muted",children:["v",t.version]}),e.jsx("span",{className:"plugin-state-badge",style:{color:I[t.state]||I.installed},children:t.state})]}),e.jsxs("div",{className:"plugin-actions",children:[t.state==="started"&&e.jsx("button",{className:"btn-icon",onClick:()=>V(t),disabled:y===t.id,title:"Reload",children:e.jsx(Z,{size:14,className:y===t.id?"spin":""})}),e.jsxs("label",{className:"toggle-switch",children:[e.jsx("input",{type:"checkbox",checked:t.enabled,onChange:()=>t.enabled?M(t):G(t)}),e.jsx("span",{className:"toggle-slider"})]}),e.jsx("button",{className:"btn-icon",onClick:()=>B(t),title:"Settings",children:e.jsx(je,{size:14})}),e.jsx("button",{className:"btn-icon",onClick:()=>H(t),title:"Uninstall",children:e.jsx(T,{size:14})})]})]},t.id))}),ge()]})]})}export{te as AGENT_BROWSER_SETTINGS_SCHEMA,ne as BUILTIN_AGENT_BROWSER_PLUGIN_ID,Ae as PluginManager,I as STATE_COLORS};
@@ -1 +0,0 @@
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{flex-wrap:wrap;align-items:flex-start}.plugin-homepage a{display:inline-flex;align-items:center;gap:var(--space-xs);color:var(--color-info);font-size:.85rem;flex-wrap:wrap;overflow-wrap:anywhere}.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-group{display:flex;flex-direction:column;gap:var(--space-md)}.plugin-settings-group-heading{margin:0;font-size:.8rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--text-muted)}.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-builtins-section{display:flex;flex-direction:column;gap:var(--space-sm)}.plugin-builtins-header{display:flex;flex-direction:column;gap:var(--space-xs)}.plugin-builtins-heading{margin:0;font-size:.95rem}.plugin-builtins-description{margin:0;font-size:.85rem;color:var(--text-muted)}.plugin-builtins-list{width:100%;display:flex;flex-direction:column;gap:var(--space-sm);margin-top:var(--space-sm)}.plugin-builtins-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-builtins-meta{display:flex;align-items:center;gap:var(--space-sm);row-gap:var(--space-xs);flex-wrap:wrap;min-width:0}.plugin-builtins-name{color:var(--text);font-size:.9rem;font-weight:500}.plugin-builtins-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-builtins-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-builtins-status--installed{background:var(--status-done-bg);color:var(--done)}.plugin-builtins-status--available{background:var(--status-todo-bg);color:var(--todo)}.plugin-builtins-setup-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-builtins-setup-status--warning{background:var(--status-in-review-bg);color:var(--color-warning)}.plugin-builtins-setup-status--ready{background:var(--status-done-bg);color:var(--color-success)}.plugin-builtins-setup-status--pending{background:var(--status-todo-bg);color:var(--color-warning)}.plugin-builtins-description-text{flex:1 1 100%;color:var(--text-muted);font-size:.85rem}.plugin-builtins-metadata-only{color:var(--text-muted);font-size:.8rem;font-weight:600;text-transform:uppercase}.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);row-gap:var(--space-xs);flex-wrap:wrap;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}@media(min-width:769px){.plugin-builtins-status,.plugin-bundled-runtime-status{margin-left:auto}}.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,.plugin-manager-detail{padding-inline:var(--space-sm)}.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-builtins-item,.plugin-bundled-runtime-item{flex-direction:column;align-items:stretch}.plugin-builtins-item .btn,.plugin-bundled-runtime-item .btn{min-height:36px}}