@runfusion/fusion 0.39.0 → 0.41.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 (193) hide show
  1. package/bin.mjs +20 -0
  2. package/dist/automation-store-EKXXEE2S.js +10 -0
  3. package/dist/automation-store-PLNG3X72.js +10 -0
  4. package/dist/automation-store-RDDYZFUJ.js +10 -0
  5. package/dist/bin.js +63127 -33419
  6. package/dist/chunk-2JI3F6MG.js +948 -0
  7. package/dist/chunk-4L6CLWJC.js +8345 -0
  8. package/dist/chunk-4VNS5WPM.js +42 -0
  9. package/dist/chunk-5RGECGQL.js +1139 -0
  10. package/dist/chunk-6JDLN7IL.js +409 -0
  11. package/dist/chunk-AICJATVW.js +948 -0
  12. package/dist/chunk-AWKNRUOR.js +1148 -0
  13. package/dist/chunk-BHM3UYWS.js +4651 -0
  14. package/dist/chunk-BMUXDSBF.js +4647 -0
  15. package/dist/chunk-GETECT6V.js +353 -0
  16. package/dist/chunk-GUV4QQT3.js +1143 -0
  17. package/dist/chunk-JKQO7YYZ.js +8369 -0
  18. package/dist/chunk-LYZVU6UV.js +409 -0
  19. package/dist/chunk-MAN4WYHO.js +353 -0
  20. package/dist/chunk-MCUG2Z7M.js +4651 -0
  21. package/dist/chunk-PSDYB45U.js +948 -0
  22. package/dist/chunk-RR2HM46R.js +8345 -0
  23. package/dist/chunk-RXMQ5OMY.js +9226 -0
  24. package/dist/chunk-S2EVJUY3.js +353 -0
  25. package/dist/chunk-UXR5XZFZ.js +409 -0
  26. package/dist/client/.vite/manifest.json +458 -156
  27. package/dist/client/assets/AgentDetailView-krC0B2O0.js +18 -0
  28. package/dist/client/assets/AgentPermissionPolicyEditor-VDXL4XQc.js +6 -0
  29. package/dist/client/assets/AgentsView-ChXccELt.js +29 -0
  30. package/dist/client/assets/{AgentsView-BI_CESkd.css → AgentsView-DfznJDek.css} +1 -1
  31. package/dist/client/assets/ChatView-Dz_xBKit.js +6 -0
  32. package/dist/client/assets/DevServerView-DGOahw1o.js +1 -0
  33. package/dist/client/assets/{DirectoryPicker-DzKVmxOf.css → DirectoryPicker-DTKtd8L2.css} +1 -1
  34. package/dist/client/assets/DirectoryPicker-DgqHlxyh.js +1 -0
  35. package/dist/client/assets/DocumentsView-CbbZwzbH.js +1 -0
  36. package/dist/client/assets/DocumentsView-WfVoTZt8.css +1 -0
  37. package/dist/client/assets/EvalsView-BL_ue7fJ.js +1 -0
  38. package/dist/client/assets/{ExperimentalAgentOnboardingModal-DoRPGkfN.js → ExperimentalAgentOnboardingModal-8H4XAu4O.js} +41 -41
  39. package/dist/client/assets/GoalsView-CO4FVL3E.js +2 -0
  40. package/dist/client/assets/GoalsView-DI66UsjT.css +1 -0
  41. package/dist/client/assets/InsightsView-C5vLvWVE.js +11 -0
  42. package/dist/client/assets/MemoryView-BL3W3yOv.js +2 -0
  43. package/dist/client/assets/NodesView-7VInxyf_.css +1 -0
  44. package/dist/client/assets/NodesView-DfBNNm9c.js +14 -0
  45. package/dist/client/assets/PiExtensionsManager-HvSiVeDN.js +11 -0
  46. package/dist/client/assets/PluginManager-DIjrlhnU.js +1 -0
  47. package/dist/client/assets/{PluginManager-BJQXdUmV.css → PluginManager-UHVLvWWl.css} +1 -1
  48. package/dist/client/assets/PullRequestView-C2jQX8xZ.js +6 -0
  49. package/dist/client/assets/PullRequestView-WQIS0zUC.css +1 -0
  50. package/dist/client/assets/ReliabilityView-DbqEwoRs.js +1 -0
  51. package/dist/client/assets/ReliabilityView-eoKBhBc4.css +1 -0
  52. package/dist/client/assets/ResearchView-C1QghmLI.js +1 -0
  53. package/dist/client/assets/SecretsView-Y2MQ-9n5.js +1 -0
  54. package/dist/client/assets/SessionTerminal-BiigPP2l.css +1 -0
  55. package/dist/client/assets/SessionTerminal-DaTXNT3A.js +2 -0
  56. package/dist/client/assets/SettingsModal-BAzm2kYd.js +31 -0
  57. package/dist/client/assets/{SettingsModal-Dmz2aH3c.js → SettingsModal-DabcZZ6S.js} +1 -1
  58. package/dist/client/assets/SettingsModal-bJvc9aHl.css +1 -0
  59. package/dist/client/assets/SettingsModal-nF_GaeeK.css +1 -0
  60. package/dist/client/assets/SetupWizardModal-CIqFbkrD.css +1 -0
  61. package/dist/client/assets/SetupWizardModal-Db-Rxinm.js +1 -0
  62. package/dist/client/assets/SkillsView-3bhGyWs1.css +1 -0
  63. package/dist/client/assets/SkillsView-CIEY1-DE.js +1 -0
  64. package/dist/client/assets/StashRecoveryView-B6iDu5tI.js +1 -0
  65. package/dist/client/assets/{TodoView-Cx9cVhq7.css → TodoView-7xIh-Fmi.css} +1 -1
  66. package/dist/client/assets/TodoView-B8IK_BPM.js +6 -0
  67. package/dist/client/assets/WorkflowNodeEditor-DaPyvD_R.js +8 -0
  68. package/dist/client/assets/WorkflowNodeEditor-Po5uv_dN.css +1 -0
  69. package/dist/client/assets/{addon-fit-C7jRorKK.js → addon-fit-B4jkcKk4.js} +1 -1
  70. package/dist/client/assets/addon-unicode11-Cdne2Sj4.js +1 -0
  71. package/dist/client/assets/{addon-web-links-CkJwd4cQ.js → addon-web-links-CRNLzj7m.js} +1 -1
  72. package/dist/client/assets/{addon-webgl-BjvOw43o.js → addon-webgl-CeCSULF1.js} +1 -1
  73. package/dist/client/assets/app-CTRT_hQh.js +13 -0
  74. package/dist/client/assets/app-CVg6W-HU.js +13 -0
  75. package/dist/client/assets/app-CY3pQXOr.js +13 -0
  76. package/dist/client/assets/app-DNh04p5I.js +13 -0
  77. package/dist/client/assets/app-DhHgtB9j.js +13 -0
  78. package/dist/client/assets/app-NL_hPGDS.js +13 -0
  79. package/dist/client/assets/common-BRyX4VxB.js +1 -0
  80. package/dist/client/assets/common-CN9QPI2d.js +1 -0
  81. package/dist/client/assets/common-CNbjPELi.js +1 -0
  82. package/dist/client/assets/common-DFDqu_n0.js +1 -0
  83. package/dist/client/assets/common-DgWWKG8Z.js +1 -0
  84. package/dist/client/assets/common-X6PzBnVA.js +1 -0
  85. package/dist/client/assets/{createLucideIcon-BazL2hk5.js → createLucideIcon-BYvOGRiO.js} +2 -2
  86. package/dist/client/assets/dashboard-view-BgiLoG1G.css +1 -0
  87. package/dist/client/assets/{dashboard-view-DqWnXEbq.css → dashboard-view-CuUPQZzi.css} +1 -1
  88. package/dist/client/assets/dashboard-view-DlKsVySD.js +3 -0
  89. package/dist/client/assets/dashboard-view-Dn4CztR6.js +1 -0
  90. package/dist/client/assets/dashboard-view-O5j3PSGY.js +8101 -0
  91. package/dist/client/assets/errors-07IrmOYM.js +1 -0
  92. package/dist/client/assets/errors-BPsCufin.js +1 -0
  93. package/dist/client/assets/errors-CcVDgqlA.js +1 -0
  94. package/dist/client/assets/errors-D-i_Bxc6.js +1 -0
  95. package/dist/client/assets/errors-DDdWAK-U.js +1 -0
  96. package/dist/client/assets/errors-DOF5Td3F.js +1 -0
  97. package/dist/client/assets/{folder-open-CJgBSqdA.js → folder-open-C9XAaduE.js} +1 -1
  98. package/dist/client/assets/index-BHGM5W8a.css +1 -0
  99. package/dist/client/assets/index-CgfrecpF.js +793 -0
  100. package/dist/client/assets/{upload-hsiV4Ixv.js → upload-BRAEugYV.js} +1 -1
  101. package/dist/client/assets/{users-D63HpHlZ.js → users-BlflbMZ3.js} +1 -1
  102. package/dist/client/assets/vendor-i18n-CV0mwX_-.js +9 -0
  103. package/dist/client/assets/{vendor-react-K0fH_qHe.js → vendor-react-D37HfzIf.js} +1 -1
  104. package/dist/client/assets/vendor-reactflow-C5ap-Sga.css +1 -0
  105. package/dist/client/assets/vendor-reactflow-CRZcPCXF.js +15 -0
  106. package/dist/client/assets/{vendor-xterm-DzcZoU0P.js → vendor-xterm-tcedd2Jt.js} +1 -1
  107. package/dist/client/assets/x-CqNX_9E2.js +61 -0
  108. package/dist/client/assets/zoom-out-CSTHbJgD.js +21 -0
  109. package/dist/client/index.html +7 -4
  110. package/dist/client/sw.js +36 -1
  111. package/dist/client/version.json +1 -1
  112. package/dist/droid-cli/package.json +2 -2
  113. package/dist/extension.js +53678 -32499
  114. package/dist/extract-zip-WL55Z3AU.js +2497 -0
  115. package/dist/index.min-CHQ3ABYJ.js +2926 -0
  116. package/dist/memory-dreams-7USISKVE.js +32 -0
  117. package/dist/memory-dreams-PBPISUDD.js +32 -0
  118. package/dist/memory-dreams-XNO2B2QF.js +32 -0
  119. package/dist/migration-EH2YOCYQ.js +15 -0
  120. package/dist/migration-PLGTTKL5.js +15 -0
  121. package/dist/migration-WZEZK22R.js +15 -0
  122. package/dist/pi-claude-cli/package.json +2 -2
  123. package/dist/plugin-sdk/index.d.ts +97 -0
  124. package/dist/plugin-sdk/index.js +55 -0
  125. package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +17286 -0
  126. package/dist/plugins/fusion-plugin-acp-runtime/manifest.json +13 -0
  127. package/dist/plugins/fusion-plugin-acp-runtime/package.json +11 -0
  128. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +2 -3
  129. package/dist/plugins/fusion-plugin-cli-printing-press/src/dashboard-interop.d.ts +19 -0
  130. package/dist/plugins/fusion-plugin-cli-printing-press/src/index.ts +0 -3
  131. package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +1984 -0
  132. package/dist/plugins/fusion-plugin-compound-engineering/manifest.json +56 -0
  133. package/dist/plugins/fusion-plugin-compound-engineering/package.json +11 -0
  134. package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +5 -0
  135. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  136. package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +5 -0
  137. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  138. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +5 -0
  139. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  140. package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +5 -0
  141. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  142. package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +5 -0
  143. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  144. package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +5 -0
  145. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  146. package/dist/plugins/fusion-plugin-reports/package.json +2 -2
  147. package/dist/plugins/fusion-plugin-reports/src/__tests__/review-panel.test.ts +3 -3
  148. package/dist/plugins/fusion-plugin-reports/src/index.ts +0 -1
  149. package/dist/plugins/fusion-plugin-roadmap/bundled.js +5 -0
  150. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  151. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +2 -2
  152. package/dist/routine-store-GIJ6MXWY.js +10 -0
  153. package/dist/routine-store-HTVC2PUQ.js +10 -0
  154. package/dist/routine-store-KGHZBPDF.js +10 -0
  155. package/package.json +24 -10
  156. package/skill/fusion/SKILL.md +1 -1
  157. package/skill/fusion/references/engine-tools.md +79 -3
  158. package/skill/fusion/references/extension-tools.md +32 -3
  159. package/skill/fusion/references/fusion-capabilities.md +6 -3
  160. package/dist/client/assets/AgentDetailView-nS4sABBv.js +0 -18
  161. package/dist/client/assets/AgentPermissionPolicyEditor-DiYAo51R.js +0 -6
  162. package/dist/client/assets/AgentsView-VbUsJLma.js +0 -29
  163. package/dist/client/assets/ChatView-B1AMky9x.js +0 -6
  164. package/dist/client/assets/DevServerView-CyFdAcCd.js +0 -1
  165. package/dist/client/assets/DirectoryPicker-C7v2Esic.js +0 -1
  166. package/dist/client/assets/DocumentsView-P_YIsnO0.js +0 -1
  167. package/dist/client/assets/DocumentsView-gv4zG3aT.css +0 -1
  168. package/dist/client/assets/EvalsView-2zyH0dWG.js +0 -1
  169. package/dist/client/assets/GoalsView-Dky8vDoG.css +0 -1
  170. package/dist/client/assets/GoalsView-l0PVSxK4.js +0 -2
  171. package/dist/client/assets/InsightsView-BZKu5-C3.js +0 -11
  172. package/dist/client/assets/MemoryView-CYBNC_h8.js +0 -2
  173. package/dist/client/assets/NodesView-CQ63uWC8.js +0 -14
  174. package/dist/client/assets/NodesView-DT4pXowv.css +0 -1
  175. package/dist/client/assets/PiExtensionsManager-BNXxlpb6.js +0 -6
  176. package/dist/client/assets/PluginManager-DejpEyl7.js +0 -1
  177. package/dist/client/assets/ReliabilityView-C1C1j1SD.js +0 -1
  178. package/dist/client/assets/ReliabilityView-D9AsVv5l.css +0 -1
  179. package/dist/client/assets/ResearchView-B4u2YieX.js +0 -1
  180. package/dist/client/assets/SecretsView-DvMMG_rf.js +0 -1
  181. package/dist/client/assets/SettingsModal-986SEzVN.css +0 -1
  182. package/dist/client/assets/SettingsModal-C2mfeKp1.js +0 -31
  183. package/dist/client/assets/SettingsModal-DZrJ5PFH.css +0 -1
  184. package/dist/client/assets/SetupWizardModal-BiIFP3De.js +0 -1
  185. package/dist/client/assets/SetupWizardModal-CGYGKurR.css +0 -1
  186. package/dist/client/assets/SkillsView-CRARYL_G.js +0 -1
  187. package/dist/client/assets/SkillsView-CUbSBeZ2.css +0 -1
  188. package/dist/client/assets/StashRecoveryView-DHj0O6sE.js +0 -1
  189. package/dist/client/assets/TodoView-CjyU1h-B.js +0 -6
  190. package/dist/client/assets/dashboard-view-BVckVLAO.js +0 -21
  191. package/dist/client/assets/dashboard-view-BWGH_fAq.js +0 -63
  192. package/dist/client/assets/index-BonLYFW-.js +0 -742
  193. package/dist/client/assets/index-nzIVQsA_.css +0 -1
@@ -1 +0,0 @@
1
- import{r as i,j as r}from"./vendor-react-K0fH_qHe.js";import{eX as N,eY as g,dC as b,b as y,aj as P,ae as C,af as H,L as O,ay as v}from"./index-BonLYFW-.js";import{F as z}from"./folder-open-CJgBSqdA.js";function D({value:o,onChange:d,placeholder:m,onInputKeyDown:x,nodeId:l,localNodeId:h}){const[e,n]=i.useState({isOpen:!1,loading:!1,error:null,currentPath:"",parentPath:null,entries:[],showHidden:!1}),a=i.useCallback(async(s,c=!1)=>{n(t=>({...t,loading:!0,error:null}));try{const t=await N(s,c,l,h);n(u=>({...u,loading:!1,currentPath:t.currentPath,parentPath:t.parentPath,entries:t.entries}))}catch(t){n(u=>({...u,loading:!1,error:t instanceof Error?t.message:"Failed to browse directory"}))}},[l,h]),j=i.useCallback(()=>{n(s=>s.isOpen?{...s,isOpen:!1}:{...s,isOpen:!0})},[]);i.useEffect(()=>{e.isOpen&&!e.loading&&e.entries.length===0&&!e.error&&a(o||void 0,e.showHidden)},[e.isOpen,e.loading,e.entries.length,e.error,o,e.showHidden,a,l,h]);const p=i.useCallback(s=>{a(s,e.showHidden)},[a,e.showHidden]),k=i.useCallback(()=>{d(e.currentPath),n(s=>({...s,isOpen:!1}))},[e.currentPath,d]),w=i.useCallback(()=>{n(s=>{const c=!s.showHidden;return{...s,showHidden:c}})},[]);i.useEffect(()=>{e.isOpen&&e.currentPath&&a(e.currentPath,e.showHidden)},[e.showHidden]);const f=e.currentPath?g(e.currentPath):[];return r.jsxs("div",{className:"directory-picker",children:[r.jsxs("div",{className:"directory-picker-input-row",children:[r.jsx("input",{type:"text",className:"input directory-picker-input",value:o,onChange:s=>d(s.target.value),onKeyDown:x,placeholder:m||"/path/to/your/project"}),r.jsxs("button",{type:"button",className:"btn btn-secondary btn-sm directory-picker-browse-btn",onClick:j,"aria-label":e.isOpen?"Close directory browser":"Browse directories",children:[e.isOpen?r.jsx(z,{size:16}):r.jsx(b,{size:16}),r.jsx("span",{children:"Browse"})]})]}),e.isOpen&&r.jsxs("div",{className:"directory-picker-browser",role:"tree","aria-label":"Directory browser",children:[r.jsx("div",{className:"directory-picker-breadcrumbs",children:f.map((s,c)=>r.jsxs("span",{className:"directory-picker-breadcrumb-item",children:[c>0&&r.jsx(y,{size:12,className:"directory-picker-breadcrumb-sep"}),r.jsx("button",{type:"button",className:"directory-picker-breadcrumb",onClick:()=>p(s.path),title:s.path,children:s.label})]},s.path))}),r.jsxs("div",{className:"directory-picker-toolbar",children:[e.parentPath&&r.jsxs("button",{type:"button",className:"btn btn-sm btn-secondary directory-picker-up-btn",onClick:()=>p(e.parentPath),"aria-label":"Go to parent directory",title:"Parent directory",children:[r.jsx(P,{size:14}),r.jsx("span",{children:"Up"})]}),r.jsxs("button",{type:"button",className:"btn btn-sm btn-secondary directory-picker-hidden-toggle",onClick:w,"aria-label":e.showHidden?"Hide hidden directories":"Show hidden directories",title:e.showHidden?"Hide hidden":"Show hidden",children:[e.showHidden?r.jsx(C,{size:14}):r.jsx(H,{size:14}),r.jsx("span",{children:e.showHidden?"Hide hidden":"Show hidden"})]})]}),e.loading?r.jsxs("div",{className:"directory-picker-loading",children:[r.jsx(O,{size:20,className:"animate-spin"}),r.jsx("span",{children:"Loading…"})]}):e.error?r.jsxs("div",{className:"directory-picker-error",children:[r.jsx(v,{size:16}),r.jsx("span",{children:e.error})]}):r.jsx("div",{className:"directory-picker-entries",children:e.entries.length===0?r.jsx("div",{className:"directory-picker-empty",children:"No subdirectories"}):e.entries.map(s=>r.jsxs("button",{type:"button",className:"directory-picker-entry",onClick:()=>p(s.path),role:"treeitem",title:s.path,children:[r.jsx(b,{size:16,className:"directory-picker-entry-icon"}),r.jsx("span",{className:"directory-picker-entry-name",children:s.name}),s.hasChildren&&r.jsx(y,{size:14,className:"directory-picker-entry-arrow"})]},s.path))}),r.jsxs("div",{className:"directory-picker-actions",children:[r.jsx("span",{className:"directory-picker-selected-path",title:e.currentPath,children:e.currentPath}),r.jsx("button",{type:"button",className:"btn btn-primary directory-picker-select-btn",onClick:k,children:"Select"})]})]})]})}export{D};
@@ -1 +0,0 @@
1
- import{r as s,j as e}from"./vendor-react-K0fH_qHe.js";import{a7 as K,a8 as W,a9 as ie,aa as de,ab as G,ac as ue,f as me,ad as he,F as T,ae as fe,af as pe,S as je,X as xe,R as we,ag as ke,ah as X,ai as V,a as Y,b as ge,aj as be}from"./index-BonLYFW-.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";function ve(n){const{projectId:c,searchQuery:h,includeProjectFiles:a=!0}=n??{},l=c?`${ie.DOCUMENTS_PREFIX}${c}`:null,[o,m]=s.useState(()=>{if(!l)return[];const w=K(l,{maxAgeMs:W});return Array.isArray(w)?w:[]}),[d,i]=s.useState([]),[k,x]=s.useState(()=>o.length===0),[C,b]=s.useState(null),g=s.useRef(null),f=s.useRef(o.length>0),p=s.useRef(null),v=s.useCallback(async()=>{g.current&&g.current.abort();const w=new AbortController;g.current=w;const z=!f.current;z&&x(!0),b(null);const E=de(h?{q:h}:void 0,c),R=a?G(c):Promise.resolve({files:[]}),[j,M]=await Promise.allSettled([E,R]);if(w.signal.aborted)return;let A=null;if(j.status==="fulfilled"){if(m(j.value),l){const y=j.value.length>500?j.value.slice(0,500):j.value;ue(l,y,{maxBytes:5e5})}f.current=!0}else A=j.reason instanceof Error?j.reason.message:String(j.reason);if(M.status==="fulfilled"){const y=M.value.files,L=h?.trim().toLowerCase(),F=L?y.filter(P=>P.name.toLowerCase().includes(L)||P.path.toLowerCase().includes(L)):y;i(F)}b(A),z&&x(!1)},[l,a,c,h]);return s.useEffect(()=>{if(!l){f.current=!1,m([]),x(!0);return}const w=K(l,{maxAgeMs:W});Array.isArray(w)?(m(w),f.current=!0,x(!1)):(f.current=!1,m([]),x(!0))},[l]),s.useEffect(()=>(p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{v()},300),()=>{p.current&&clearTimeout(p.current)}),[v]),s.useEffect(()=>(v(),()=>{g.current&&g.current.abort()}),[]),{documents:o,projectFiles:d,loading:k,error:C,refresh:v}}function Ne(n,c){const[h,a]=s.useState([]),[l,o]=s.useState(!0),[m,d]=s.useState(null),i=s.useRef(null),k=s.useRef(!1),x=c?.showHidden??!1,C=s.useCallback(async b=>{i.current&&i.current.abort();const g=new AbortController;i.current=g;const f=!k.current;f&&o(!0),d(null);try{const p=await G(n,{showHidden:b?.showHidden??x});if(g.signal.aborted)return;a(p.files),k.current=!0}catch(p){if(g.signal.aborted)return;d(p instanceof Error?p.message:String(p))}finally{!g.signal.aborted&&f&&o(!1)}},[n,x]);return s.useEffect(()=>(k.current=!1,C({showHidden:x}),()=>{i.current&&i.current.abort()}),[C,x]),{files:h,loading:l,error:m,refresh:C}}const Se=768;function J(n){return n?new Date(n).toLocaleString():""}function Ce(n){return n<1024?`${n} B`:n<1024*1024?`${(n/1024).toFixed(n>=10*1024?0:1)} KB`:`${(n/(1024*1024)).toFixed(1)} MB`}function Fe(n,c=200){return n.length<=c?n:`${n.substring(0,c)}…`}function Ee({document:n,renderMarkdown:c,onToggleMarkdown:h}){const[a,l]=s.useState(!1),o=Fe(n.content),m=n.content.length>200;return e.jsxs("div",{className:"document-card",children:[e.jsxs("div",{className:"document-card-header",children:[e.jsxs("div",{className:"document-card-key",children:[e.jsx(T,{size:14}),e.jsx("span",{className:"document-card-key-text",children:n.key}),e.jsxs("span",{className:"document-card-revision-badge",children:["v",n.revision]})]}),e.jsx("div",{className:"document-card-actions",children:e.jsx("button",{className:"btn btn-sm document-card-expand-btn",onClick:()=>l(d=>!d),title:a?"Collapse":"Expand","aria-label":a?"Collapse content":"Expand content",children:a?e.jsx(be,{size:14}):e.jsx(Y,{size:14})})})]}),e.jsxs("div",{className:"document-card-meta",children:[e.jsx("span",{className:"document-card-author",children:n.author}),e.jsx("span",{className:"document-card-separator",children:"·"}),e.jsx("span",{className:"document-card-date",children:J(n.updatedAt)})]}),e.jsxs("div",{className:`document-card-content${a?" document-card-content--expanded":""}`,children:[a?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"document-card-content-header",children:e.jsx("button",{className:"btn btn-sm document-mode-toggle",onClick:h,"aria-label":c?"Switch to plain text":"Switch to markdown","aria-pressed":c,title:c?"Switch to plain text":"Switch to markdown",children:c?"Markdown":"Plain"})}),c?e.jsx("div",{className:"document-card-content-markdown",children:e.jsx("div",{className:"markdown-body",children:e.jsx(X,{remarkPlugins:[V],children:n.content})})}):e.jsx("pre",{className:"document-card-content-text",children:n.content})]}):e.jsx("p",{className:"document-card-preview",children:o}),m&&!a&&e.jsx("p",{className:"document-card-preview-truncated",children:"…"})]})]})}function ye({taskId:n,taskTitle:c,documents:h,onOpenTask:a,renderMarkdownStates:l,onToggleMarkdown:o}){const[m,d]=s.useState(!1);return e.jsxs("div",{className:"documents-group",children:[e.jsxs("div",{className:"documents-group-header",children:[e.jsxs("button",{className:"documents-group-toggle-btn",onClick:()=>d(i=>!i),"aria-expanded":m,"aria-label":`${m?"Collapse":"Expand"} documents for task ${n}`,children:[e.jsx("span",{className:"documents-group-toggle","aria-hidden":"true",children:m?e.jsx(Y,{size:16}):e.jsx(ge,{size:16})}),e.jsx("span",{className:"documents-group-task-id",children:n}),e.jsx("span",{className:"documents-group-task-title",children:c||"Untitled"})]}),e.jsxs("span",{className:"documents-group-count",children:[h.length," doc",h.length!==1?"s":""]}),e.jsx("button",{className:"documents-group-task-link",onClick:()=>a(n),"aria-label":`Open task ${n}: ${c||"Untitled"}`,children:"Open task"})]}),m&&e.jsx("div",{className:"documents-group-content",children:h.map(i=>e.jsx(Ee,{document:i,renderMarkdown:l.get(i.id)??!1,onToggleMarkdown:()=>o(i.id)},i.id))})]})}function ze({projectId:n,addToast:c,onOpenDetail:h}){const[a,l]=s.useState("project"),[o,m]=s.useState(""),[d,i]=s.useState(null),[k,x]=s.useState(!1),[C,b]=s.useState(null),[g,f]=s.useState(!1),[p,v]=s.useState(null),[w,z]=s.useState(!1),E=s.useRef(0),R=s.useRef(!1),[j,M]=s.useState(!1),[A,y]=s.useState(new Map),L=a==="tasks"?o.trim():"",{documents:F,loading:P,error:Z,refresh:B}=ve({projectId:n,searchQuery:L||void 0,includeProjectFiles:!1}),{files:S,loading:D,error:I,refresh:O}=Ne(n,{showHidden:k});s.useEffect(()=>{const t=()=>{z(window.innerWidth<=Se)};return t(),window.addEventListener("resize",t),()=>{window.removeEventListener("resize",t)}},[]),s.useEffect(()=>{R.current=!1,l("project"),i(null),x(!1),b(null),v(null),f(!1),M(!1),y(new Map)},[n]),s.useEffect(()=>{R.current||P||D||(S.length>0?l("project"):F.length>0&&l("tasks"),R.current=!0)},[F.length,P,S.length,D]);const $=s.useMemo(()=>{const t=new Map;for(const r of F){const u=t.get(r.taskId)||[];t.set(r.taskId,[...u,r])}return Array.from(t.entries()).map(([r,u])=>{const N=[...u].sort((oe,le)=>le.updatedAt.localeCompare(oe.updatedAt));return{taskId:r,taskTitle:N[0]?.taskTitle,documents:N,latestUpdated:N[0]?.updatedAt??""}}).sort((r,u)=>u.latestUpdated.localeCompare(r.latestUpdated))},[F]),H=s.useMemo(()=>{const t=o.trim().toLowerCase();return t?S.filter(r=>{const u=r.path.toLowerCase(),N=r.name.toLowerCase();return u.includes(t)||N.includes(t)}):S},[S,o]);s.useEffect(()=>{if(!d)return;S.some(r=>r.path===d.path)||(i(null),b(null),v(null),f(!1))},[S,d]);const ee=s.useCallback(t=>{m(t.target.value)},[]),se=s.useCallback(()=>{m("")},[]),U=s.useCallback(t=>{l(t)},[]),te=s.useCallback(async t=>{try{const r=await me(t,n);h(r)}catch{c(`Failed to open task ${t}`,"error")}},[n,h,c]),ne=s.useCallback(async t=>{i(t),f(!0),v(null),b(null);const r=E.current+1;E.current=r;try{const u=await he("project",t.path,n);if(E.current!==r)return;b(u.content)}catch(u){if(E.current!==r)return;const N=u instanceof Error?u.message:`Failed to open ${t.path}`;v(N),c(N,"error")}finally{E.current===r&&f(!1)}},[n,c]),ae=s.useCallback(()=>{i(null),b(null),v(null),f(!1)},[]),re=s.useCallback(t=>{y(r=>{const u=new Map(r),N=u.get(t)??!1;return u.set(t,!N),u})},[]),_=a==="project"?I:Z,ce=s.useCallback(async()=>{if(a==="project"){await O();return}await B()},[a,O,B]),Q=a==="project"?H.length:F.length,q=a==="project"?"Search project markdown files…":"Search task documents…";return e.jsxs("div",{className:"documents-view",children:[e.jsxs("div",{className:"documents-view-header",children:[e.jsxs("div",{className:"documents-view-title-row",children:[e.jsxs("h2",{className:"documents-view-title",children:[e.jsx(T,{size:20}),"Documents"]}),e.jsxs("span",{className:"documents-view-count",children:[Q," result",Q!==1?"s":""]})]}),e.jsxs("div",{className:"documents-controls-row",children:[e.jsxs("div",{className:"documents-tab-bar",role:"tablist","aria-label":"Documents sections",children:[e.jsxs("button",{className:`btn documents-tab${a==="project"?" active":""}`,role:"tab","aria-selected":a==="project","aria-label":"Show project markdown files",onClick:()=>U("project"),children:["Project Files",e.jsx("span",{className:"documents-tab-count",children:S.length})]}),e.jsxs("button",{className:`btn documents-tab${a==="tasks"?" active":""}`,role:"tab","aria-selected":a==="tasks","aria-label":"Show task documents",onClick:()=>U("tasks"),children:["Task Documents",e.jsx("span",{className:"documents-tab-count",children:$.length})]})]}),a==="project"&&e.jsxs("button",{className:"btn btn-sm documents-hidden-toggle",onClick:()=>x(t=>!t),"aria-pressed":k,"aria-label":k?"Hide hidden project files":"Show hidden project files",title:k?"Hide hidden files":"Show hidden files",children:[k?e.jsx(fe,{size:14}):e.jsx(pe,{size:14}),k?"Hide Hidden":"Show Hidden"]}),e.jsxs("div",{className:"documents-search",children:[e.jsx(je,{size:16,className:"documents-search-icon"}),e.jsx("input",{type:"text",className:"documents-search-input",placeholder:q,value:o,onChange:ee,"aria-label":q}),o&&e.jsx("button",{className:"documents-search-clear",onClick:se,"aria-label":"Clear search",children:e.jsx(xe,{size:16})})]})]})]}),e.jsx("div",{className:"documents-view-content",children:_?e.jsxs("div",{className:"documents-view-error",children:[e.jsxs("p",{children:["Failed to load ",a==="project"?"project files":"task documents",": ",_]}),e.jsxs("button",{className:"btn btn-primary",onClick:()=>void ce(),"aria-label":"Retry loading documents",children:[e.jsx(we,{size:16}),"Retry"]})]}):a==="project"?D&&S.length===0?e.jsx("div",{className:"documents-view-loading",children:e.jsx("p",{children:"Loading project markdown files…"})}):H.length===0?e.jsx("div",{className:"documents-view-empty",children:o.trim()?e.jsxs("p",{children:['No project markdown files match "',o.trim(),'".']}):e.jsxs(e.Fragment,{children:[e.jsx(T,{size:48,className:"documents-view-empty-icon"}),e.jsx("p",{children:"No Markdown files found in this project."})]})}):e.jsxs("div",{className:`documents-project-layout${w?" documents-project-layout--mobile":""}`,children:[(!w||!d)&&e.jsx("aside",{className:"documents-view-sidebar","aria-label":"Project markdown files",children:e.jsx("ul",{className:"markdown-file-list",children:H.map(t=>{const r=d?.path===t.path;return e.jsx("li",{className:"markdown-file-list-item",children:e.jsxs("button",{className:`markdown-file-item${r?" markdown-file-item--selected":""}`,onClick:()=>void ne(t),"aria-label":`Open ${t.path}`,"aria-current":r?"true":void 0,children:[e.jsx("span",{className:"markdown-file-item-name",children:t.name}),e.jsx("span",{className:"markdown-file-item-path",children:t.path}),e.jsxs("span",{className:"markdown-file-item-meta",children:[Ce(t.size)," · ",J(t.mtime)]})]})},t.path)})})}),(!w||d)&&e.jsxs("section",{className:"documents-view-main","aria-label":"Project file content preview",children:[w&&d&&e.jsxs("button",{className:"btn btn-sm documents-mobile-back",onClick:ae,"aria-label":"Back to project files list",children:[e.jsx(ke,{size:14}),"Back to files"]}),d?e.jsxs("div",{className:"documents-content-viewer",children:[e.jsxs("div",{className:"documents-content-header",children:[e.jsx("p",{className:"documents-file-path-header",children:d.path}),e.jsx("button",{className:"btn btn-sm document-mode-toggle",onClick:()=>M(t=>!t),"aria-label":j?"Switch to plain text":"Switch to markdown","aria-pressed":j,title:j?"Switch to plain text":"Switch to markdown",children:j?"Markdown":"Plain"})]}),g?e.jsx("p",{className:"documents-content-state",children:"Loading file content…"}):p?e.jsx("p",{className:"documents-content-state documents-content-state--error",children:p}):j?e.jsx("div",{className:"documents-content-markdown",children:e.jsx("div",{className:"markdown-body",children:e.jsx(X,{remarkPlugins:[V],children:C??""})})}):e.jsx("pre",{className:"document-card-content-text documents-content-viewer-text",children:C??""})]}):e.jsx("div",{className:"documents-view-empty",children:e.jsx("p",{children:"Select a Markdown file to view its content."})})]})]}):P&&F.length===0?e.jsx("div",{className:"documents-view-loading",children:e.jsx("p",{children:"Loading task documents…"})}):$.length===0?e.jsx("div",{className:"documents-view-empty",children:o.trim()?e.jsxs("p",{children:['No task documents match "',o.trim(),'".']}):e.jsxs(e.Fragment,{children:[e.jsx(T,{size:48,className:"documents-view-empty-icon"}),e.jsx("p",{children:"No task documents yet."}),e.jsx("p",{className:"documents-view-empty-hint",children:"Documents are created in task detail tabs."})]})}):e.jsx("div",{className:"documents-task-list-wrap",children:e.jsx("div",{className:"documents-view-list",children:$.map(({taskId:t,taskTitle:r,documents:u})=>e.jsx(ye,{taskId:t,taskTitle:r,documents:u,onOpenTask:te,renderMarkdownStates:A,onToggleMarkdown:re},t))})})})]})}export{ze as DocumentsView};
@@ -1 +0,0 @@
1
- .documents-view{display:flex;flex-direction:column;height:100%;min-height:0}.documents-view-header{padding:var(--space-lg);border-bottom:1px solid var(--border);background:var(--surface)}.documents-view-title-row{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-md)}.documents-view-title{display:flex;align-items:center;gap:var(--space-sm);font-size:18px;font-weight:600;margin:0;color:var(--text)}.documents-view-title svg{color:var(--todo)}.documents-view-count{font-size:14px;color:var(--text-muted)}.documents-controls-row{display:flex;align-items:center;gap:var(--space-md);flex-wrap:nowrap}.documents-tab-bar{display:flex;align-items:center;gap:var(--space-sm);flex-shrink:0}.documents-tab{display:inline-flex;align-items:center;gap:var(--space-sm);border:1px solid var(--border);background:var(--surface);color:var(--text-muted)}.documents-tab:hover{background:var(--card-hover);color:var(--text)}.documents-tab.active{color:var(--todo);border-color:var(--todo);background:color-mix(in srgb,var(--todo) 12%,transparent)}.documents-tab:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.documents-tab-count{display:inline-flex;align-items:center;justify-content:center;min-width:20px;padding:0 var(--space-xs);border-radius:var(--radius-pill);background:color-mix(in srgb,var(--text) 10%,transparent);color:inherit;font-size:11px;font-family:var(--font-mono)}.documents-hidden-toggle{flex-shrink:0;white-space:nowrap}.documents-hidden-toggle[aria-pressed=true]{color:var(--todo);border-color:var(--todo);background:color-mix(in srgb,var(--todo) 12%,transparent)}.documents-search{position:relative;display:flex;align-items:center;flex:1 1 auto;min-width:0}.documents-search-icon{position:absolute;left:var(--space-sm);color:var(--text-muted);pointer-events:none}.documents-search-input{width:100%;min-width:120px;padding:var(--space-sm) var(--space-sm) var(--space-sm) calc(var(--space-sm) + 24px);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg);color:var(--text);font-size:14px;transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.documents-search-input:focus-visible{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.documents-search-input::placeholder{color:var(--text-dim)}.documents-search-clear{position:absolute;right:var(--space-sm);display:flex;align-items:center;justify-content:center;background:none;border:none;color:var(--text-muted);cursor:pointer;padding:var(--space-xs);border-radius:var(--radius-sm);transition:color var(--transition-fast),background var(--transition-fast)}.documents-search-clear:hover{color:var(--text);background:var(--card-hover)}.documents-search-clear:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.documents-view-content{flex:1;min-height:0;overflow:auto;padding:var(--space-lg)}.documents-view-loading,.documents-view-empty,.documents-view-error{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:var(--space-2xl);color:var(--text-muted);min-height:200px}.documents-view-empty-icon{margin-bottom:var(--space-md);color:var(--text-dim)}.documents-view-empty-hint{font-size:13px;color:var(--text-dim);margin-top:var(--space-xs)}.documents-view-error{color:var(--color-error)}.documents-view-error .btn{margin-top:var(--space-md)}.documents-project-layout{display:grid;grid-template-columns:minmax(280px,320px) minmax(0,1fr);min-height:0;height:100%;border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;background:var(--card)}.documents-project-layout--mobile{grid-template-columns:1fr}.documents-view-sidebar{width:100%;min-width:0;overflow-y:auto;border-right:1px solid var(--border);background:var(--surface)}.markdown-file-list{margin:0;padding:0;list-style:none}.markdown-file-list-item{margin:0}.markdown-file-item{width:100%;display:flex;flex-direction:column;align-items:flex-start;gap:var(--space-xs);border:none;border-left:3px solid transparent;border-bottom:1px solid var(--border);padding:var(--space-md);background:transparent;color:var(--text);text-align:left;cursor:pointer;transition:background var(--transition-fast),border-color var(--transition-fast)}.markdown-file-list-item:last-child .markdown-file-item{border-bottom:none}.markdown-file-item:hover{background:var(--card-hover)}.markdown-file-item:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.markdown-file-item--selected{border-left-color:var(--todo);background:color-mix(in srgb,var(--todo) 12%,transparent)}.markdown-file-item-name{font-size:13px;font-weight:600;color:var(--text)}.markdown-file-item-path{font-size:12px;color:var(--text-muted);font-family:var(--font-mono);word-break:break-word}.markdown-file-item-meta{font-size:12px;color:var(--text-dim)}.documents-view-main{min-width:0;overflow-y:auto;background:var(--card);padding:var(--space-lg)}.documents-mobile-back{margin-bottom:var(--space-md)}.documents-content-viewer{display:flex;flex-direction:column;gap:var(--space-md);margin:0 auto;width:min(100%,880px)}.documents-content-header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}.documents-file-path-header{margin:0;padding:var(--space-sm) var(--space-md);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface);color:var(--text-muted);font-family:var(--font-mono);font-size:12px;word-break:break-word;flex:1}.documents-content-viewer-text,.documents-content-markdown{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface);padding:var(--space-md);min-height:220px}.documents-content-state{margin:0;color:var(--text-muted)}.documents-content-state--error{color:var(--color-error)}.documents-task-list-wrap{width:min(100%,960px);margin:0 auto}.documents-view-list{display:flex;flex-direction:column;gap:var(--space-md)}.documents-group{border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;background:var(--card)}.documents-group-header{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);background:var(--surface);border-bottom:1px solid var(--border)}.documents-group-toggle-btn{display:flex;align-items:center;gap:var(--space-sm);min-width:0;border:none;background:none;color:var(--text);text-align:left;padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-md);cursor:pointer;transition:background var(--transition-fast);min-height:36px}.documents-group-toggle-btn:hover{background:var(--card-hover)}.documents-group-toggle-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.documents-group-toggle{display:flex;align-items:center;justify-content:center;color:var(--text-muted);flex-shrink:0}.documents-group-task-id{font-family:var(--font-mono);font-size:12px;color:var(--text-muted);flex-shrink:0}.documents-group-task-title{font-size:14px;font-weight:500;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.documents-group-count{font-size:12px;color:var(--text-dim);justify-self:end}.documents-group-task-link{border:1px solid var(--border);background:var(--card);color:var(--text-muted);padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-md);cursor:pointer;transition:border-color var(--transition-fast),color var(--transition-fast),background var(--transition-fast);min-height:36px}.documents-group-task-link:hover{border-color:var(--todo);color:var(--todo);background:color-mix(in srgb,var(--todo) 10%,transparent)}.documents-group-task-link:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.documents-group-content{padding:var(--space-md);display:flex;flex-direction:column;gap:var(--space-sm)}.document-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;transition:border-color var(--transition-fast)}.document-card:hover{border-color:var(--text-dim)}.document-card-header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-sm) var(--space-md);background:var(--surface);border-bottom:1px solid var(--border)}.document-card-key{display:flex;align-items:center;gap:var(--space-xs);color:var(--text)}.document-card-key svg{color:var(--text-muted);flex-shrink:0}.document-card-key-text{font-family:var(--font-mono);font-size:13px;font-weight:500}.document-card-revision-badge{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted);background:var(--surface);padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);border:1px solid var(--border)}.document-card-expand-btn{padding:var(--space-xs);color:var(--text-muted)}.document-card-expand-btn:hover{color:var(--text)}.document-card-actions{display:flex;align-items:center;gap:var(--space-xs)}.document-mode-toggle{padding:var(--space-xs) var(--space-sm);font-size:11px;font-weight:500;color:var(--text-muted);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-sm);cursor:pointer;transition:var(--transition-fast);line-height:1}.document-mode-toggle:hover{background:var(--card-hover);color:var(--text)}.document-mode-toggle:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.document-mode-toggle[aria-pressed=true]{background:var(--accent);color:var(--accent-text);border-color:var(--accent)}.document-card-content-header{display:flex;justify-content:flex-end;margin-bottom:var(--space-sm)}.document-card-meta{display:flex;align-items:center;gap:var(--space-xs);padding:var(--space-xs) var(--space-md);font-size:12px;color:var(--text-dim);border-bottom:1px solid var(--border)}.document-card-separator{color:var(--border)}.document-card-content{padding:var(--space-md)}.document-card-preview{margin:0;font-size:13px;color:var(--text-muted);line-height:1.5;word-break:break-word}.document-card-preview-truncated{margin:0;font-size:13px;color:var(--text-dim)}.document-card-content--expanded .document-card-preview,.document-card-content--expanded .document-card-preview-truncated{display:none}.document-card-content-text{margin:0;font-size:13px;color:var(--text);line-height:1.5;white-space:pre-wrap;word-break:break-word;font-family:var(--font-primary)}@media(max-width:768px){.documents-view-header{padding:var(--space-md)}.documents-view-title-row{flex-direction:column;align-items:flex-start;gap:var(--space-sm)}.documents-view-title{font-size:16px}.documents-controls-row{flex-direction:column;align-items:stretch;gap:var(--space-sm)}.documents-tab-bar{width:100%}.documents-tab{flex:1;justify-content:center;min-height:44px}.documents-hidden-toggle{width:100%;justify-content:center;min-height:44px}.documents-search-input{max-width:none;width:100%}.documents-view-content{padding:var(--space-md)}.documents-project-layout,.documents-project-layout--mobile{display:flex;flex-direction:column;min-height:0}.documents-view-sidebar{border-right:none;border-bottom:1px solid var(--border);max-height:none}.markdown-file-item{min-height:44px;padding:var(--space-sm) var(--space-md)}.documents-view-main{padding:var(--space-md)}.documents-content-viewer{width:100%}.documents-content-viewer-text{min-height:160px}.documents-group-header{grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"toggle count" "link link";row-gap:var(--space-xs)}.documents-group-toggle-btn{grid-area:toggle}.documents-group-count{grid-area:count;justify-self:end}.documents-group-task-link{grid-area:link;width:100%;justify-self:stretch;min-height:44px}.documents-group-task-title{max-width:180px}.document-card-key-text{font-size:12px}.document-mode-toggle{min-width:36px;min-height:36px}}
@@ -1 +0,0 @@
1
- import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{a7 as C,a8 as _,a9 as D,aP as W,aQ as G,ac as V,aR as Q,x as Y,ax as J,R as Z,aB as ee}from"./index-BonLYFW-.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const se=300,te=15e3;function B(r){if(!r.trim())return;const t=Number(r);return Number.isFinite(t)?t:void 0}function N(...r){for(const t of r)if(Array.isArray(t))return t;return[]}function p(r){return typeof r=="object"&&r!==null?r:{}}function K(r){const t=p(r),h=p(t.taskSnapshot);return{id:String(t.id??t.evalId??""),runId:String(t.runId??t.batchId??""),taskId:String(t.taskId??h.taskId??""),taskTitle:String(h.title??t.taskTitle??t.title??"Untitled task"),createdAt:String(t.createdAt??t.timestamp??t.updatedAt??new Date(0).toISOString()),overallScore:typeof t.overallScore=="number"?t.overallScore:null,maxScore:typeof t.maxScore=="number"?t.maxScore:null,categoryScores:N(t.categoryScores,p(t.scores).categories)}}function ae(r){const t=p(r);return{...K(t),rationale:String(t.rationale??t.summary??""),evidence:N(t.evidence,p(t.details).evidence),followUps:N(t.followUps,p(t.recommendations).followUps)}}function re(r){const t=r?.projectId,h=t??"",f=`${D.EVALS_RUNS_PREFIX}${h}`,u=`${D.EVALS_RESULTS_PREFIX}${h}`,v=C(f,{maxAgeMs:_}),S=C(u,{maxAgeMs:_}),m=a.useRef(Array.isArray(v)&&v.length>0||Array.isArray(S)&&S.length>0),[c,E]=a.useState({q:"",runId:"",scoreMin:"",scoreMax:""}),[T,i]=a.useState(()=>Array.isArray(v)?v:[]),[L,R]=a.useState(()=>Array.isArray(S)?S:[]),[d,I]=a.useState(null),[F,s]=a.useState(null),[o,g]=a.useState(0),[b,U]=a.useState(!m.current),[X,z]=a.useState(null),k=a.useRef(0),$=a.useRef(t),w=a.useRef(d);w.current=d;const A=a.useCallback(async()=>{const l=++k.current;m.current||U(!0),z(null);try{const[n,x]=await Promise.all([W({q:c.q||void 0,runId:c.runId||void 0,scoreMin:B(c.scoreMin),scoreMax:B(c.scoreMax),limit:100,offset:0},t),G(t)]);if(l!==k.current)return;const y=N(n.results,n.evals,n.items).map(K);R(y),V(u,y.length>500?y.slice(0,500):y,{maxBytes:5e5}),g(typeof n.count=="number"?n.count:y.length);const O=N(x.runs,x.items).map(q=>{const j=p(q),P=p(j.counts);return{id:String(j.id??""),createdAt:String(j.createdAt??""),completedAt:typeof j.completedAt=="string"?j.completedAt:void 0,status:String(j.status??"pending"),evaluatedTaskCount:typeof P.totalTasks=="number"?P.totalTasks:0}});i(O),V(f,O,{maxBytes:5e5}),m.current=!0,w.current&&!y.some(q=>q.id===w.current)&&(I(null),s(null))}catch(n){if(l!==k.current)return;z(n instanceof Error?n.message:"Failed to load evals")}finally{l===k.current&&U(!1)}},[c.q,c.runId,c.scoreMax,c.scoreMin,t,u,f]),M=a.useCallback(async l=>{const n=await Q(l,t),x=n.result??n;s(ae(x))},[t]);a.useEffect(()=>{if($.current===t)return;$.current=t;const l=C(f,{maxAgeMs:_}),n=C(u,{maxAgeMs:_}),x=Array.isArray(l)&&l.length>0||Array.isArray(n)&&n.length>0;i(Array.isArray(l)?l:[]),R(Array.isArray(n)?n:[]),U(!x),m.current=x},[t,u,f]),a.useEffect(()=>{const l=window.setTimeout(()=>{A()},se);return()=>window.clearTimeout(l)},[A]),a.useEffect(()=>{if(!d){s(null);return}M(d)},[M,d]),a.useEffect(()=>{const l=window.setInterval(()=>{A(),d&&M(d)},te);return()=>window.clearInterval(l)},[M,A,d]);const H=a.useCallback(l=>{w.current=l,I(l)},[]);return{loading:b,error:X,results:L,count:o,runs:T,filters:c,setFilters:E,refresh:A,selectedEvalId:d,setSelectedEvalId:H,selectedEval:F}}function ue({projectId:r,onOpenSettings:t,onOpenTaskDetail:h}){const{loading:f,error:u,results:v,runs:S,filters:m,setFilters:c,selectedEvalId:E,setSelectedEvalId:T,selectedEval:i,refresh:L}=re({projectId:r}),[R,d]=a.useState(!0);a.useEffect(()=>{let s=!1;return Y(r).then(o=>{if(s)return;const g=o.evalSettings?.enabled;d(g??!1)}).catch(()=>{s||d(!1)}),()=>{s=!0}},[r]);const I=v.length>0,F=a.useMemo(()=>v.find(s=>s.id===E)??null,[v,E]);return R?e.jsxs("section",{className:"evals-view","data-testid":"evals-view",children:[e.jsxs("div",{className:"evals-list card",children:[e.jsxs("div",{className:"evals-toolbar",children:[e.jsx("input",{className:"input",placeholder:"Search task or rationale",value:m.q,onChange:s=>c(o=>({...o,q:s.target.value}))}),e.jsxs("select",{className:"select",value:m.runId,onChange:s=>c(o=>({...o,runId:s.target.value})),children:[e.jsx("option",{value:"",children:"All runs"}),S.map(s=>e.jsx("option",{value:s.id,children:s.id},s.id))]}),e.jsx("input",{className:"input",placeholder:"Min score",value:m.scoreMin,onChange:s=>c(o=>({...o,scoreMin:s.target.value}))}),e.jsx("input",{className:"input",placeholder:"Max score",value:m.scoreMax,onChange:s=>c(o=>({...o,scoreMax:s.target.value}))}),e.jsx("button",{className:"btn btn-icon",type:"button",onClick:()=>void L(),"aria-label":"Refresh evals",children:e.jsx(Z,{size:16})})]}),f&&e.jsx("p",{className:"evals-state","data-testid":"evals-loading",children:"Loading evals…"}),u&&e.jsx("p",{className:"evals-state evals-state--error",children:u}),!f&&!u&&!I&&e.jsx("p",{className:"evals-state",children:"No evals yet. Scheduled evals review tasks completed since the last run."}),e.jsx("ul",{className:"evals-results","data-testid":"evals-results",children:v.map(s=>e.jsx("li",{children:e.jsxs("button",{className:`evals-result ${s.id===E?"evals-result--active":""}`,type:"button",onClick:()=>T(s.id),children:[e.jsx("span",{className:"evals-result-title",children:s.taskTitle}),e.jsxs("span",{className:"evals-result-meta",children:[s.taskId," · ",s.runId," · ",s.overallScore??"n/a"]})]})},s.id))})]}),e.jsxs("div",{className:"evals-detail card","data-testid":"evals-detail",children:[!i&&e.jsx("p",{className:"evals-state",children:"Select an evaluation to inspect scores, rationale, and evidence."}),i&&e.jsxs(e.Fragment,{children:[e.jsx("h3",{className:"evals-detail-title",children:F?.taskTitle??i.taskTitle}),e.jsxs("p",{className:"evals-result-meta",children:[i.taskId," · ",i.runId]}),e.jsxs("p",{className:"evals-score",children:["Overall score: ",i.overallScore??"n/a"]}),e.jsx("ul",{className:"evals-categories",children:i.categoryScores.map(s=>e.jsxs("li",{children:[s.category,": ",s.finalScore]},s.category))}),e.jsx("p",{className:"evals-rationale",children:i.rationale||"No rationale recorded."}),e.jsxs("div",{children:[e.jsx("h4",{children:"Evidence"}),e.jsx("ul",{className:"evals-links",children:i.evidence.map((s,o)=>{const g=typeof s.metadata?.taskId=="string"?s.metadata.taskId:void 0,b=typeof s.metadata?.url=="string"?s.metadata.url:void 0;return e.jsx("li",{children:g?e.jsx("button",{type:"button",className:"btn",onClick:()=>h?.(g),children:s.ref}):b?e.jsxs("a",{href:b,target:"_blank",rel:"noreferrer",className:"evals-external-link",children:[s.ref,e.jsx(ee,{size:14})]}):e.jsx("span",{children:s.ref})},`${s.ref}-${o}`)})})]}),e.jsxs("div",{children:[e.jsx("h4",{children:"Suggested follow-up tasks"}),e.jsxs("ul",{className:"evals-follow-ups",children:[i.followUps.length===0&&e.jsx("li",{children:"None"}),i.followUps.map(s=>e.jsxs("li",{children:[e.jsx("strong",{children:s.title}),e.jsx("p",{children:s.rationale})]},s.suggestionId))]})]})]})]})]}):e.jsxs("section",{className:"evals-view card","data-testid":"evals-disabled",children:[e.jsx("h2",{className:"evals-title",children:"Scheduled evals are disabled"}),e.jsx("p",{className:"evals-empty-copy",children:"Enable Scheduled Evals to review scored tasks, evidence, and follow-up recommendations."}),e.jsxs("button",{className:"btn btn-primary",type:"button",onClick:()=>t?.("scheduled-evals"),children:[e.jsx(J,{size:16}),"Open Scheduled Evals Settings"]})]})}export{ue as EvalsView};
@@ -1 +0,0 @@
1
- .goals-view{display:flex;flex-direction:column;gap:var(--space-lg);height:100%;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:var(--space-lg)}.goals-header{display:flex;justify-content:space-between;align-items:center;gap:var(--space-md)}.goals-title{margin:0;color:var(--text);font-size:calc(var(--space-lg) + var(--space-xs))}.goals-count{margin:0;color:var(--text-muted)}.goals-add-button{display:inline-flex;align-items:center;gap:var(--space-sm)}.goals-add-button:focus-visible,.goals-card:focus-visible,.goals-activate-button:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.goals-warning{margin:0;padding:var(--space-md);border-radius:var(--radius-md);border:calc(var(--space-xs) / 4) solid var(--color-warning);background:color-mix(in srgb,var(--color-warning) 10%,transparent);color:var(--color-warning)}.goals-error{margin:0}.goals-form{display:flex;flex-direction:column;gap:var(--space-sm)}.goals-form-label{color:var(--text-muted)}.goals-form textarea.input{min-height:calc(var(--space-2xl) * 2);resize:vertical}.goals-form-actions{display:flex;gap:var(--space-sm)}.goals-list{display:flex;flex-direction:column;gap:var(--space-md)}.goals-card{display:flex;align-items:center;justify-content:space-between;gap:var(--space-md)}.goals-card-archived{border-color:color-mix(in srgb,var(--text-muted) 25%,transparent)}.goals-card-main{min-width:0}.goals-card-edit{display:flex;flex:1;flex-direction:column;gap:var(--space-sm)}.goals-card-title{margin:0;color:var(--text);font-size:calc(var(--space-md) + var(--space-xs))}.goals-card-description{margin:var(--space-xs) 0 0;color:var(--text-muted)}.goals-card-description>:first-child{margin-top:0}.goals-card-description>:last-child{margin-bottom:0}.goals-card-description-collapsed{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4;overflow:hidden;max-height:calc(var(--space-md) * 6)}.goals-card-description-toggle{margin-top:var(--space-xs);align-self:flex-start;color:var(--text-muted)}.goals-card-status{margin:var(--space-xs) 0 0;color:var(--text-muted)}.goals-card-actions{display:flex;gap:var(--space-sm)}.goals-activate-button{min-width:calc(var(--space-2xl) * 2)}.goals-empty{color:var(--text-muted)}@media(max-width:768px){.goals-header,.goals-card{flex-direction:column;align-items:stretch}.goals-form-actions,.goals-card-actions{flex-direction:column}.goals-card-description-collapsed{-webkit-line-clamp:3;max-height:calc(var(--space-md) * 5)}}
@@ -1,2 +0,0 @@
1
- import{r as i,j as e}from"./vendor-react-K0fH_qHe.js";import{J as Q,ah as Y,ai as Z}from"./index-BonLYFW-.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const tt=5,et=3,I="Cannot activate more than 5 goals. Resolve an active goal before activating another.",at=280;function R(l){return!!(l&&typeof l=="object"&&"code"in l&&l.code==="ACTIVE_GOAL_LIMIT_EXCEEDED")}function ot({initialGoals:l}){const[c,g]=i.useState(()=>l??[]),[m,x]=i.useState(l===void 0),[v,o]=i.useState(null),[M,j]=i.useState(!1),[y,N]=i.useState(""),[E,S]=i.useState(""),[w,d]=i.useState(null),[C,A]=i.useState(!1),[h,G]=i.useState(null),[T,p]=i.useState(""),[$,f]=i.useState(""),[k,u]=i.useState(null),[D,L]=i.useState(!1),[U,H]=i.useState(()=>new Set);i.useEffect(()=>{if(l!==void 0)return;let t=!0;return(async()=>{try{x(!0),o(null);const a=await fetch("/api/goals");if(!a.ok)throw new Error(`Failed to load goals (${a.status})`);const n=await a.json();if(!t)return;g(Array.isArray(n.goals)?n.goals:[])}catch{if(!t)return;o("Unable to load goals right now. Please try again.")}finally{t&&x(!1)}})(),()=>{t=!1}},[l]);const b=i.useMemo(()=>c.filter(t=>t.status==="active").length,[c]),V=b>=et&&b<=tt;function J(){o(null),d(null),j(!0)}function q(t){G(t.id),p(t.title),f(t.description??""),u(null)}function O(){G(null),p(""),f(""),u(null)}function P(){j(!1),N(""),S(""),d(null)}async function W(){const t=y.trim();if(!t){d("Title is required.");return}try{A(!0),d(null),o(null);const s=await fetch("/api/goals",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({title:t,description:E})});if(s.ok){const n=await s.json();g(r=>[...r,n]),P();return}let a=null;try{a=await s.json()}catch{a=null}if(s.status===409&&R(a)){o(I);return}d("Unable to create goal right now. Please try again.")}catch{d("Unable to create goal right now. Please try again.")}finally{A(!1)}}async function X(){if(!h)return;const t=T.trim();if(!t){u("Title is required.");return}try{L(!0),u(null);const s=await fetch(`/api/goals/${h}`,{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({title:t,description:$})});if(!s.ok)throw new Error(`Failed to update goal (${s.status})`);const a=await s.json();g(n=>n.map(r=>r.id===a.id?a:r)),O()}catch{u("Unable to save goal right now. Please try again.")}finally{L(!1)}}function B(t){return t.length>at||t.includes(`
2
- `)}function K(t){H(s=>{const a=new Set(s);return a.has(t)?a.delete(t):a.add(t),a})}async function F(t){const s=t.status==="active"?`/api/goals/${t.id}/archive`:`/api/goals/${t.id}/unarchive`;try{o(null);const a=await fetch(s,{method:"POST"});if(a.ok){const r=await a.json();g(z=>z.map(_=>_.id===r.id?r:_));return}let n=null;try{n=await a.json()}catch{n=null}if(a.status===409&&R(n)){o(I);return}o("Unable to update goal status right now. Please try again.")}catch{o("Unable to update goal status right now. Please try again.")}}return e.jsxs("section",{className:"goals-view","data-testid":"goals-view",children:[e.jsxs("header",{className:"goals-header",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"goals-title",children:"Goals"}),e.jsxs("p",{className:"goals-count","data-testid":"goals-active-count",children:[b," active goals"]})]}),e.jsxs("button",{type:"button",className:"btn btn-primary goals-add-button",onClick:J,"data-testid":"goals-add-button",children:[e.jsx(Q,{"aria-hidden":"true"}),"Add Goal"]})]}),M?e.jsxs("div",{className:"card goals-form","data-testid":"goals-form",children:[e.jsx("label",{className:"goals-form-label",htmlFor:"goals-form-title",children:"Title"}),e.jsx("input",{id:"goals-form-title",className:"input",type:"text",value:y,maxLength:200,onChange:t=>N(t.target.value),"data-testid":"goals-form-title"}),e.jsx("label",{className:"goals-form-label",htmlFor:"goals-form-description",children:"Description"}),e.jsx("textarea",{id:"goals-form-description",className:"input",value:E,maxLength:5e3,onChange:t=>S(t.target.value),"data-testid":"goals-form-description"}),w?e.jsx("p",{className:"form-error goals-error",role:"alert",children:w}):null,e.jsxs("div",{className:"goals-form-actions",children:[e.jsx("button",{type:"button",className:"btn btn-primary",onClick:()=>void W(),disabled:C,"data-testid":"goals-form-submit",children:"Save"}),e.jsx("button",{type:"button",className:"btn",onClick:P,disabled:C,"data-testid":"goals-form-cancel",children:"Cancel"})]})]}):null,V?e.jsx("p",{className:"goals-warning",role:"status",children:"Approaching the 5-active goal cap. Keep active goals focused."}):null,v?e.jsx("p",{className:"form-error goals-error",role:"alert","data-testid":"goals-error",children:v}):null,m?e.jsx("p",{className:"goals-loading",role:"status","data-testid":"goals-loading",children:"Loading goals…"}):null,!m&&c.length===0?e.jsx("div",{className:"goals-empty card","data-testid":"goals-empty-state",children:"No goals yet. Add one to begin tracking strategic outcomes."}):null,!m&&c.length>0?e.jsx("div",{className:"goals-list","data-testid":"goals-list",children:c.map(t=>e.jsx("article",{className:`card goals-card ${t.status==="archived"?"goals-card-archived":""}`.trim(),"data-testid":`goal-card-${t.id}`,children:h===t.id?e.jsxs("div",{className:"goals-card-main goals-card-edit",children:[e.jsx("label",{className:"goals-form-label",htmlFor:`goal-edit-title-${t.id}`,children:"Title"}),e.jsx("input",{id:`goal-edit-title-${t.id}`,className:"input",type:"text",value:T,maxLength:200,onChange:s=>p(s.target.value),"data-testid":`goal-edit-title-${t.id}`}),e.jsx("label",{className:"goals-form-label",htmlFor:`goal-edit-description-${t.id}`,children:"Description"}),e.jsx("textarea",{id:`goal-edit-description-${t.id}`,className:"input",value:$,maxLength:5e3,onChange:s=>f(s.target.value),"data-testid":`goal-edit-description-${t.id}`}),k?e.jsx("p",{className:"form-error goals-error",role:"alert",children:k}):null,e.jsxs("div",{className:"goals-card-actions",children:[e.jsx("button",{type:"button",className:"btn btn-primary",onClick:()=>void X(),disabled:D,"data-testid":`goal-edit-save-${t.id}`,children:"Save"}),e.jsx("button",{type:"button",className:"btn",onClick:O,disabled:D,"data-testid":`goal-edit-cancel-${t.id}`,children:"Cancel"})]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"goals-card-main",children:[e.jsx("h3",{className:"goals-card-title",children:t.title}),t.description?(()=>{const s=B(t.description),a=U.has(t.id);return e.jsxs(e.Fragment,{children:[e.jsx("div",{className:`markdown-body goals-card-description ${s&&!a?"goals-card-description-collapsed":""}`.trim(),children:e.jsx(Y,{remarkPlugins:[Z],children:t.description})}),s?e.jsx("button",{type:"button",className:"btn goals-card-description-toggle","aria-expanded":a,"data-testid":`goal-description-toggle-${t.id}`,onClick:()=>K(t.id),children:a?"Show less":"Show more"}):null]})})():null,e.jsxs("p",{className:"goals-card-status",children:["Status: ",t.status]})]}),e.jsxs("div",{className:"goals-card-actions",children:[e.jsx("button",{type:"button",className:"btn",onClick:()=>q(t),"data-testid":`goal-edit-${t.id}`,children:"Edit"}),t.status==="active"?e.jsx("button",{type:"button",className:"btn goals-activate-button",onClick:()=>void F(t),"data-testid":`goal-archive-${t.id}`,children:"Archive"}):e.jsx("button",{type:"button",className:"btn goals-activate-button",onClick:()=>void F(t),"data-testid":`goal-unarchive-${t.id}`,children:"Unarchive"})]})]})},t.id))}):null]})}export{ot as GoalsView};
@@ -1,11 +0,0 @@
1
- import{r,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Re,a7 as te,a8 as be,a9 as we,ak as Se,al as Xe,ac as je,am as qe,an as We,ao as Ke,ap as Ye,aq as Ve,ar as Je,as as ke,at as Qe,i as Ze,au as Ce,av as C,A as es,X as Ne,aw as ge,R as N,ax as ss,m as ts,C as $e,ay as ie,az as Me,aA as is,J as ze,aB as as,aC as _e,aD as ns}from"./index-BonLYFW-.js";import{U as Ae}from"./users-D63HpHlZ.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";/**
2
- * @license lucide-react v1.7.0 - ISC
3
- *
4
- * This source code is licensed under the ISC license.
5
- * See the LICENSE file in the root directory of this source tree.
6
- */const rs=[["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"}]],cs=Re("building",rs);/**
7
- * @license lucide-react v1.7.0 - ISC
8
- *
9
- * This source code is licensed under the ISC license.
10
- * See the LICENSE file in the root directory of this source tree.
11
- */const ls=[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16",key:"c24i48"}],["path",{d:"m19 9-5 5-4-4-3 3",key:"2osh9i"}]],os=Re("chart-line",ls),de=["architecture","quality","workflow","performance","reliability","security","ux","testability","documentation","dependency","features","competitive_analysis","research","trends","other"],Ie={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 hs(d){const o=d??"",S=`${we.INSIGHTS_PREFIX}${o}`,w=`${we.INSIGHT_LATEST_RUN_PREFIX}${o}`,p=te(S,{maxAgeMs:be}),B=te(w,{maxAgeMs:Se}),M=r.useRef(Array.isArray(p)&&p.length>0),[A,f]=r.useState(()=>Array.isArray(p)?p:[]),[I,X]=r.useState(()=>de.map(n=>({category:n,label:Ie[n]??n,items:[],isLoading:!1,error:null}))),[q,$]=r.useState(!(Array.isArray(p)&&p.length>0)),[W,G]=r.useState(null),[K,E]=r.useState(B??null),[ae,P]=r.useState(!1),[Y,F]=r.useState(null),[V,z]=r.useState(new Map),[J,_]=r.useState(new Map),[L,h]=r.useState(new Map),[R,g]=r.useState(new Map),[D,ne]=r.useState(!1),v=r.useCallback(async()=>{M.current||$(!0),G(null);try{const t=(await Xe({status:void 0,limit:1e3},d)).insights.filter(u=>u.status!=="dismissed");f(t),je(S,t.length>500?t.slice(0,500):t,{maxBytes:5e5});const s=await qe(d);s.runs.length>0&&(E(s.runs[0]),je(w,s.runs[0],{maxBytes:5e5})),M.current=!0}catch(n){const t=n instanceof Error?n.message:"Failed to fetch insights";G(t)}finally{$(!1)}},[S,w,d]),re=r.useCallback(()=>{ne(n=>!n)},[]),y=r.useCallback(async(n,t)=>{P(!0),F(null);try{const s=await We("manual",void 0,d,n,t);E(s),s.status==="completed"?await v():s.status==="failed"&&s.error&&F(s.error)}catch(s){if(s instanceof Ke&&s.status===409&&s.details?.code==="ACTIVE_RUN_CONFLICT"){const m=typeof s.details.activeRunId=="string"?s.details.activeRunId:null;if(m)try{const oe=await Ye(m,d);E(oe)}catch{}throw F("Insight generation is already running"),s}const u=s instanceof Error?s.message:"Failed to generate insights";throw F(u),s}finally{P(!1)}},[d,v]),Q=r.useCallback(async n=>{z(t=>{const s=new Map(t);return s.set(n,{running:!0,error:null}),s});try{await Ve(n,d),f(t=>t.filter(s=>s.id!==n)),z(t=>{const s=new Map(t);return s.set(n,{running:!1,error:null}),s})}catch(t){const s=t instanceof Error?t.message:"Failed to dismiss insight";throw z(u=>{const m=new Map(u);return m.set(n,{running:!1,error:s}),m}),t}},[d]),ce=r.useCallback(async n=>{_(t=>{const s=new Map(t);return s.set(n,{running:!0,error:null}),s});try{const t=await Je(n,d);return await ke(n,d),f(s=>s.map(u=>u.id===n?{...u,status:"archived",updatedAt:new Date().toISOString()}:u)),_(s=>{const u=new Map(s);return u.set(n,{running:!1,error:null}),u}),{title:t.suggestedTitle,description:t.suggestedDescription}}catch(t){const s=t instanceof Error?t.message:"Failed to create task";throw _(u=>{const m=new Map(u);return m.set(n,{running:!1,error:s}),m}),t}},[d]);r.useEffect(()=>{const n=new Map;for(const t of de)n.set(t,[]);for(const t of A){if(!D&&t.status==="archived")continue;const s=n.get(t.category)??[];n.set(t.category,[...s,t])}X(de.map(t=>({category:t,label:Ie[t]??t,items:n.get(t)??[],isLoading:!1,error:null})))},[A,D]);const le=r.useCallback(async n=>{h(t=>{const s=new Map(t);return s.set(n,{running:!0,error:null}),s});try{await ke(n,d),f(t=>t.map(s=>s.id===n?{...s,status:"archived",updatedAt:new Date().toISOString()}:s)),h(t=>{const s=new Map(t);return s.set(n,{running:!1,error:null}),s})}catch(t){const s=t instanceof Error?t.message:"Failed to archive insight";throw h(u=>{const m=new Map(u);return m.set(n,{running:!1,error:s}),m}),t}},[d]),x=r.useCallback(async n=>{g(t=>{const s=new Map(t);return s.set(n,{running:!0,error:null}),s});try{await Qe(n,d),f(t=>t.map(s=>s.id===n?{...s,status:"confirmed",updatedAt:new Date().toISOString()}:s)),g(t=>{const s=new Map(t);return s.set(n,{running:!1,error:null}),s})}catch(t){const s=t instanceof Error?t.message:"Failed to unarchive insight";throw g(u=>{const m=new Map(u);return m.set(n,{running:!1,error:s}),m}),t}},[d]),U=r.useMemo(()=>I.reduce((n,t)=>n+t.items.length,0),[I]),b=r.useMemo(()=>0,[]),H=r.useMemo(()=>A.filter(n=>n.status==="archived").length,[A]);return r.useEffect(()=>{const n=te(S,{maxAgeMs:be}),t=te(w,{maxAgeMs:Se}),s=Array.isArray(n)&&n.length>0;f(Array.isArray(n)?n:[]),E(t??null),$(!s),M.current=s},[S,w]),r.useEffect(()=>{v()},[v]),{sections:I,loading:q,error:W,latestRun:K,isRunInFlight:ae,runError:Y,refresh:v,runInsights:y,dismiss:Q,createTask:ce,archive:le,unarchive:x,toggleShowArchived:re,dismissStates:V,createTaskStates:J,archiveStates:L,unarchiveStates:R,totalCount:U,dismissedCount:b,archivedCount:H,showArchived:D}}const Le=["Backlog health:","Backlog pressure detected","Stale paused todo","Backlog health: dependency-blocked todos"];function Ee(d){return Le.some(o=>d.title.startsWith(o))}const Fe={architecture:cs,quality:$e,workflow:_e,performance:Me,reliability:N,security:ie,ux:Ae,testability:ge,documentation:as,dependency:ze,features:is,competitive_analysis:Ae,research:os,trends:Me,other:C};function vs({projectId:d,addToast:o,onClose:S,onCreateTask:w,models:p}){const{sections:B,loading:M,error:A,latestRun:f,isRunInFlight:I,runError:X,refresh:q,runInsights:$,dismiss:W,createTask:G,archive:K=async()=>{},unarchive:E=async()=>{},toggleShowArchived:ae=()=>{},dismissStates:P,createTaskStates:Y,archiveStates:F=new Map,unarchiveStates:V=new Map,totalCount:z,archivedCount:J=0,showArchived:_=!1}=hs(d),[L,h]=r.useState(null),[R,g]=r.useState("info"),[D,ne]=r.useState(!1),[v,re]=r.useState(!1),[y,Q]=r.useState(()=>localStorage.getItem("fusion-insight-model")??""),[ce,le]=r.useState([]),[x,U]=r.useState([]),[b,H]=r.useState([]),[n,t]=r.useState();r.useEffect(()=>{p||Ze().then(i=>{le(i.models),U(i.favoriteProviders),H(i.favoriteModels),t(i.resolvedPlanningProvider);const a=localStorage.getItem("fusion-insight-model");a&&(i.models.some(l=>`${l.provider}/${l.id}`===a)||(localStorage.removeItem("fusion-insight-model"),Q("")))}).catch(()=>{})},[p]);const s=p??ce,u=r.useMemo(()=>x.length>0?x:n?[n]:[],[x,n]),m=r.useCallback(async i=>{const c=x.includes(i)?x.filter(l=>l!==i):[i,...x];U(c);try{await Ce({favoriteProviders:c,favoriteModels:b})}catch{U(x)}},[x,b]),oe=r.useCallback(async i=>{const c=b.includes(i)?b.filter(l=>l!==i):[i,...b];H(c);try{await Ce({favoriteProviders:x,favoriteModels:c})}catch{H(b)}},[b,x]),De=r.useCallback(i=>{Q(i),i?localStorage.setItem("fusion-insight-model",i):localStorage.removeItem("fusion-insight-model")},[]),O=r.useMemo(()=>B.filter(i=>i.items.length>0),[B]),ue=r.useMemo(()=>O.reduce((i,a)=>i+a.items.filter(Ee).length,0),[O]),j=r.useMemo(()=>v?O.map(i=>({...i,items:i.items.filter(Ee)})).filter(i=>i.items.length>0):O,[O,v]),[T,he]=r.useState(null);r.useEffect(()=>{if(j.length===0){T!==null&&he(null);return}T&&j.some(a=>a.category===T&&a.items.length>0)||he(j[0].category)},[j,T]);const k=r.useMemo(()=>j.find(i=>i.category===T)??j[0],[j,T]);r.useEffect(()=>{if(L){const i=setTimeout(()=>h(null),5e3);return()=>clearTimeout(i)}},[L]);const me=r.useCallback(async()=>{try{h("Generating insights..."),g("info");let i,a;if(y){const c=y.indexOf("/");if(c!==-1){const l=y.slice(0,c),Z=y.slice(c+1);l&&Z&&(i=l,a=Z)}}await $(i,a),h("Insight generation started"),g("success"),o("Insight generation started","success")}catch(i){const a=i instanceof Error?i.message:"Failed to start generation";if(a==="Insight generation is already running"){h("Insight generation is already running. Showing the active run."),g("info"),o("Insight generation is already running","info");return}h(a),g("error"),o(a,"error")}},[$,o,y]),Te=r.useCallback(async(i,a)=>{try{h(`Dismissing "${a}"...`),g("info"),await W(i),h(`Dismissed "${a}"`),g("success"),o(`Insight dismissed: ${a}`,"success")}catch(c){const l=c instanceof Error?c.message:"Failed to dismiss insight";h(l),g("error"),o(l,"error")}},[W,o]),Ge=r.useCallback(async(i,a)=>{try{h(`Archiving "${a}"...`),g("info"),await K(i),h(`Archived "${a}"`),g("success"),o(`Insight archived: ${a}`,"success")}catch(c){const l=c instanceof Error?c.message:"Failed to archive insight";h(l),g("error"),o(l,"error")}},[K,o]),Pe=r.useCallback(async(i,a)=>{try{h(`Unarchiving "${a}"...`),g("info"),await E(i),h(`Unarchived "${a}"`),g("success"),o(`Insight unarchived: ${a}`,"success")}catch(c){const l=c instanceof Error?c.message:"Failed to unarchive insight";h(l),g("error"),o(l,"error")}},[E,o]),Ue=r.useCallback(async(i,a)=>{try{if(h(`Creating task from "${a}"...`),g("info"),!w)throw new Error("Task creation is unavailable in this view");const c=await G(i);if(!c)throw new Error("Failed to prepare task payload from insight");await w({insightId:i,title:c.title,description:c.description}),h(`Task created from "${a}"`),g("success"),o(`Task created: ${c.title}`,"success")}catch(c){const l=c instanceof Error?c.message:"Failed to create task";h(l),g("error"),o(l,"error")}},[G,w,o]),He=i=>{const a=Fe[i.category]??C,c=k?.category===i.category;return e.jsx("li",{children:e.jsxs("button",{type:"button",className:`insights-category-item${c?" insights-category-item--active":""}`,onClick:()=>he(i.category),"aria-current":c?"true":void 0,"data-testid":`insights-category-${i.category}`,children:[e.jsx(a,{size:16,className:"insights-category-icon"}),e.jsx("span",{className:"insights-category-label",children:i.label}),e.jsx("span",{className:"insights-category-count",children:i.items.length})]})},i.category)},Oe=()=>{if(!k)return null;const i=Fe[k.category]??C;return e.jsxs("section",{className:"insights-section","data-testid":`insights-section-${k.category}`,children:[e.jsx("div",{className:"insights-section-header",children:e.jsxs("div",{className:"insights-section-title",children:[e.jsx(i,{size:20,className:"insights-section-icon"}),e.jsx("h3",{children:k.label}),e.jsx("span",{className:"insights-section-count",children:k.items.length})]})}),e.jsx("div",{className:"insights-section-content",children:e.jsx("ul",{className:"insights-list",children:k.items.map(a=>{const c=P.get(a.id),l=Y.get(a.id),Z=F.get(a.id),Be=V.get(a.id),fe=c?.running??!1,ve=l?.running??!1,xe=Z?.running??!1,ye=Be?.running??!1,pe=a.status==="archived",ee=k.items.some(se=>P.get(se.id)?.running||Y.get(se.id)?.running||F.get(se.id)?.running||V.get(se.id)?.running);return e.jsxs("li",{className:`insight-item${pe?" insight-item--archived":""}`,"data-insight-id":a.id,children:[e.jsxs("div",{className:"insight-item-header",children:[e.jsx("h4",{className:"insight-item-title",children:a.title}),e.jsxs("div",{className:"insight-item-actions",children:[pe?e.jsx("button",{className:"insight-item-action-btn",onClick:()=>void Pe(a.id,a.title),disabled:ye||ee,title:"Unarchive this insight","aria-label":"Unarchive this insight","data-testid":`unarchive-${a.id}`,children:ye?e.jsx(N,{size:20,className:"spin"}):e.jsx(ns,{size:20})}):e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"insight-item-action-btn",onClick:()=>void Ue(a.id,a.title),disabled:ve||ee,title:"Create task from this insight","aria-label":"Create task from this insight","data-testid":`create-task-${a.id}`,children:ve?e.jsx(N,{size:20,className:"spin"}):e.jsx(ze,{size:20})}),e.jsx("button",{className:"insight-item-action-btn",onClick:()=>void Ge(a.id,a.title),disabled:xe||ee,title:"Archive this insight","aria-label":"Archive this insight","data-testid":`archive-${a.id}`,children:xe?e.jsx(N,{size:20,className:"spin"}):e.jsx(ge,{size:20})})]}),e.jsx("button",{className:"insight-item-action-btn",onClick:()=>void Te(a.id,a.title),disabled:fe||ee,title:"Dismiss this insight","aria-label":"Dismiss this insight","data-testid":`dismiss-${a.id}`,children:fe?e.jsx(N,{size:20,className:"spin"}):e.jsx(Ne,{size:20})})]})]}),a.content&&e.jsx("p",{className:"insight-item-content",children:a.content}),e.jsxs("div",{className:"insight-item-meta",children:[e.jsx("span",{className:`insight-item-status insight-item-status--${a.status}`,children:a.status}),a.createdAt&&e.jsxs("span",{className:"insight-item-date",children:[e.jsx(_e,{size:12}),new Date(a.createdAt).toLocaleDateString()]})]})]},a.id)})})})]})};return e.jsxs("div",{className:"insights-view","data-testid":"insights-view",children:[e.jsxs("div",{className:"insights-view-header",children:[e.jsxs("div",{className:"insights-view-title",children:[e.jsxs("h2",{children:[e.jsx(C,{size:20}),"Insights"]}),e.jsxs("span",{className:"insights-view-count",children:[z," total"]})]}),e.jsxs("div",{className:"insights-view-actions",children:[ue>0&&e.jsxs("button",{className:`btn btn-sm insights-backlog-health-toggle${v?" btn-icon--active":""}`,onClick:()=>re(i=>!i),"aria-pressed":v,"aria-label":v?"Show all insights":"Show only backlog health insights","data-testid":"toggle-backlog-health",title:Le.join(", "),children:[e.jsx(es,{size:14}),v?"All Insights":"Backlog Health"," ",e.jsxs("span",{children:["(",ue,")"]})]}),S&&e.jsx("button",{className:"btn btn-sm insights-view-close",onClick:S,"aria-label":"Close insights view",title:"Close",children:e.jsx(Ne,{size:16})}),J>0&&e.jsxs("button",{className:"btn btn-sm insights-show-archived-toggle",onClick:ae,"aria-label":_?"Hide archived insights":"Show archived insights","data-testid":"toggle-archived-insights",children:[e.jsx(ge,{size:14}),_?"Hide Archived":`Show Archived (${J})`]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void q(),disabled:M,"aria-label":"Refresh insights","data-testid":"refresh-insights",children:[e.jsx(N,{size:14,className:M?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-sm insights-model-toggle",onClick:()=>ne(i=>!i),"aria-label":"Configure insight generation model","aria-expanded":D,"data-testid":"toggle-model-config",title:y?`Model: ${y}`:"Configure model",children:[e.jsx(ss,{size:14}),y&&e.jsx("span",{className:"insights-model-indicator"})]}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:()=>void me(),disabled:I,"aria-label":"Generate new insights","data-testid":"run-insights",children:I?e.jsxs(e.Fragment,{children:[e.jsx(N,{size:14,className:"spin"}),"Generating..."]}):e.jsxs(e.Fragment,{children:[e.jsx(C,{size:14}),"Generate Insights"]})})]})]}),D&&e.jsxs("div",{className:"insights-model-config","data-testid":"model-config",children:[e.jsx("label",{htmlFor:"insight-model-select",className:"insights-model-label",children:"Model"}),e.jsx(ts,{models:s,value:y,onChange:De,placeholder:"Use planning default",label:"Insight generation model",disabled:I,id:"insight-model-select",favoriteProviders:u,favoriteModels:b,onToggleFavorite:m,onToggleModelFavorite:oe})]}),e.jsx("div",{className:"insights-status-region","aria-live":"polite","data-testid":"insights-status",children:L&&e.jsxs("div",{className:`insights-status-message insights-status-message--${R}`,role:R==="error"?"alert":void 0,children:[R==="success"&&e.jsx($e,{size:16}),R==="error"&&e.jsx(ie,{size:16}),R==="info"&&e.jsx(C,{size:16}),e.jsx("span",{children:L})]})}),X&&e.jsxs("div",{className:"insights-error-callout",role:"alert","data-testid":"run-error",children:[e.jsx(ie,{size:16}),e.jsx("span",{children:X})]}),f&&e.jsx("div",{className:"insights-run-info","data-testid":"latest-run",children:e.jsxs("span",{className:"insights-run-status",children:["Latest run: ",f.status,f.status==="completed"&&e.jsxs(e.Fragment,{children:[" — ",f.insightsCreated," created, ",f.insightsUpdated," updated"]}),f.status==="failed"&&f.error&&e.jsxs(e.Fragment,{children:[" — ",f.error]})]})}),M?e.jsxs("div",{className:"insights-loading","data-testid":"insights-loading",children:[e.jsx(N,{size:24,className:"spin"}),e.jsx("p",{children:"Loading insights..."})]}):A?e.jsxs("div",{className:"insights-error","data-testid":"insights-error",children:[e.jsx(ie,{size:24}),e.jsx("p",{children:A}),e.jsx("button",{className:"btn btn-sm",onClick:()=>void q(),children:"Retry"})]}):z===0?e.jsxs("div",{className:"insights-empty","data-testid":"insights-empty",children:[e.jsx(C,{size:48}),e.jsx("h3",{children:"No insights yet"}),e.jsx("p",{children:"Generate insights to get AI-powered recommendations for your project."}),e.jsxs("button",{className:"btn btn-primary",onClick:()=>void me(),children:[e.jsx(C,{size:14}),"Generate First Insights"]})]}):e.jsxs("div",{className:"insights-body",children:[e.jsx("aside",{className:"insights-sidebar","aria-label":"Insight categories",children:e.jsx("ul",{className:"insights-category-list",children:j.map(He)})}),e.jsx("div",{className:"insights-detail",children:Oe()})]})]})}export{vs as InsightsView};
@@ -1,2 +0,0 @@
1
- import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{u as Le}from"./SettingsModal-Dmz2aH3c.js";import{bS as Ee,bT as ke,bU as Ie,y as Re,bV as qe,bW as _e,bX as Pe,bY as Me,bZ as we,b_ as We,b$ as Te,c0 as Oe,c1 as Ae,c2 as $e,x as Ue,c3 as He,L as w,c4 as Fe}from"./index-BonLYFW-.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const T=".fusion/memory/MEMORY.md",Qe=5e4,Ye="0 3 * * *",Be="0 4 * * *";function he(i){return{memoryEnabled:i.memoryEnabled!==!1,memoryAutoSummarizeEnabled:i.memoryAutoSummarizeEnabled??!1,memoryAutoSummarizeThresholdChars:i.memoryAutoSummarizeThresholdChars??Qe,memoryAutoSummarizeSchedule:i.memoryAutoSummarizeSchedule??Ye,memoryDreamsEnabled:i.memoryDreamsEnabled??!1,memoryDreamsSchedule:i.memoryDreamsSchedule??Be}}function De(i,t){return i.some(m=>m.path===t)?t:i.find(m=>m.path===T)?.path??i[0]?.path??T}function Ve(i={}){const{projectId:t}=i,[m,u]=a.useState(""),[C,A]=a.useState(!0),[E,k]=a.useState(!1),[b,x]=a.useState(!1),[r,p]=a.useState(null),[O,K]=a.useState(!0),[J,L]=a.useState(!1),[S,P]=a.useState(()=>he({})),[F,ee]=a.useState(!0),[ue,$]=a.useState(!1),[o,v]=a.useState([]),[se,I]=a.useState(!0),[c,M]=a.useState(T),[W,y]=a.useState(""),[d,te]=a.useState(!1),[U,f]=a.useState(!1),[ae,H]=a.useState(!1),[ne,Q]=a.useState(!1),[Y,re]=a.useState(!1),[D,z]=a.useState(null),[ye,R]=a.useState(!0),[ge,B]=a.useState(!1),[ie,V]=a.useState(!1),[le,G]=a.useState(null),{status:me,loading:Z,refresh:j}=Le({projectId:t}),be=a.useCallback(n=>{y(n),f(!0)},[]),N=a.useCallback(async n=>{te(!0);try{const{content:l}=await Ee(n,t);M(n),y(l),f(!1)}finally{te(!1)}},[t]),q=a.useCallback(async()=>{I(!0);try{const{files:n}=await ke(t);if(v(n),n.length===0){M(T),y(""),f(!1);return}const l=De(n,c);l!==c&&await N(l)}finally{I(!1)}},[t,c,N]);a.useEffect(()=>{let n=!1;async function l(){try{const s=await $e(t);n||(u(s.content),A(!1))}catch{n||(u(""),A(!1))}}return l(),()=>{n=!0}},[t]),a.useEffect(()=>{let n=!1;async function l(){try{const s=await we(t);n||(p(s.content),L(s.exists),K(!1))}catch{n||(p(null),L(!1),K(!1))}}return l(),()=>{n=!0}},[t]),a.useEffect(()=>{let n=!1;async function l(){ee(!0);try{const s=await Ue(t);n||P(he(s))}catch{n||P(he({}))}finally{n||ee(!1)}}return l(),()=>{n=!0}},[t]),a.useEffect(()=>{let n=!1;async function l(){I(!0);try{const{files:s}=await ke(t);if(n)return;if(v(s),s.length===0){M(T),y(""),f(!1);return}const h=De(s,c),{content:g}=await Ee(h,t);if(n)return;M(h),y(g),f(!1)}catch{n||(v([]),M(T),y(""),f(!1))}finally{n||I(!1)}}return l(),()=>{n=!0}},[t,c]),a.useEffect(()=>{let n=!1;async function l(){try{const s=await Me(t);n||(z(s),R(!1))}catch{n||(z(null),R(!1))}}return l(),()=>{n=!0}},[t]),a.useEffect(()=>{let n=!1;async function l(){try{const s=await He(t);n||G(s)}catch{n||G(null)}}return l(),()=>{n=!0}},[t]);const ce=a.useCallback(n=>{u(n),k(!0)},[]),oe=a.useCallback(async()=>{if(E){x(!0);try{await Ie(m,t),k(!1)}finally{x(!1)}}},[m,E,t]),xe=a.useCallback(async n=>{$(!0);try{const l=await Re(n,t);P(he(l))}finally{$(!1)}},[t]),pe=a.useCallback(async n=>{await N(n)},[N]),fe=a.useCallback(async()=>{if(U){H(!0);try{await qe(c,W,t),f(!1),await q()}finally{H(!1)}}},[W,U,c,t,q]),je=a.useCallback(async()=>{V(!0);try{const n=await _e(t);return await j(),n}finally{V(!1)}},[t,j]),Se=a.useCallback(async n=>Pe(n,t),[t]),X=a.useCallback(async()=>{try{const n=await Me(t);z(n)}catch{z(null)}},[t]),_=a.useCallback(async()=>{try{const n=await we(t);p(n.content),L(n.exists)}catch{p(null),L(!1)}},[t]),de=a.useCallback(async n=>{await We(n,t),await _()},[t,_]),ve=a.useCallback(async()=>{Q(!0);try{const n=await Te(t);return await Promise.all([_(),X()]),{success:n.success,summary:n.summary}}finally{Q(!1)}},[t,_,X]),Ne=a.useCallback(async()=>{re(!0);try{return await Oe(t)}finally{re(!1)}},[t]),Ce=a.useCallback(async n=>{B(!0);try{const l=n?await Ae(n,t):await Ae(t);if(n){const s=l.path??n;M(s),y(l.content),f(!1),await q();return}u(l.content),k(!0)}finally{B(!1)}},[t,q]);return{workingMemory:m,workingMemoryLoading:C,workingMemoryDirty:E,setWorkingMemory:ce,saveWorkingMemory:oe,savingWorkingMemory:b,insightsContent:r,insightsLoading:O,insightsExists:J,refreshInsights:_,saveInsights:de,memorySettings:S,settingsLoading:F,savingMemorySettings:ue,saveMemorySettings:xe,memoryFiles:o,memoryFilesLoading:se,selectedFilePath:c,selectedFileContent:W,selectedFileLoading:d,selectedFileDirty:U,setSelectedFileContent:be,selectFile:pe,saveSelectedFile:fe,savingSelectedFile:ae,reloadMemoryFiles:q,backendStatus:me,backendLoading:Z,extractInsights:ve,extracting:ne,triggerDreamNow:Ne,dreamRunning:Y,auditReport:D,auditLoading:ye,refreshAudit:X,compactMemory:Ce,compacting:ge,installQmdAction:je,installingQmd:ie,testRetrieval:Se,stats:le}}const Ge={Patterns:"pattern",Principles:"principle",Conventions:"convention",Pitfalls:"pitfall",Context:"context"},Ze={"long-term":"Long-term",daily:"Daily",dreams:"Dreams"},Xe={"long-term":"Curated durable decisions, conventions, constraints, and pitfalls promoted from dreams.",daily:"Raw daily observations, open loops, and running context for dream processing.",dreams:"Synthesized patterns and open loops promoted from daily memory."},Ke=72;function Je(i,t){if(i.length<=t)return i;const m=Math.max(1,t-1),u=Math.ceil(m/2),C=Math.floor(m/2);return`${i.slice(0,u)}…${i.slice(i.length-C)}`}function es(i){const t=`${i.label} — ${i.path}`;return Je(t,Ke)}function ss(i){if(!i)return[];const t=[],m=i.split(/(?=^## )/m);for(const u of m){const C=u.trim();if(!C)continue;const A=C.match(/^##\s+(.+?)(\n|$)/);if(A){const E=A[1].trim(),k=Ge[E]??E.toLowerCase(),b=C.slice(A[0].length).trim(),x=b.split(`
2
- `).map(r=>r.replace(/^-\s+/,"").trim()).filter(r=>r.length>0&&(r.startsWith("- ")||r.startsWith("* ")));(x.length>0||b.length>0)&&t.push({name:E,key:k,items:x.length>0?x:b.length>0?[b]:[],expanded:!0})}}return t}function ts(i){if(!i)return null;const t=i.match(/##\s+Last\s+Updated:\s*(\d{4}-\d{2}-\d{2})/i);return t?t[1]:null}function as(i){return i.reduce((t,m)=>t+m.items.length,0)}function ns(i){switch(i){case"file":return"File (.fusion/memory/, agent/<agent-name>/memory/)";case"readonly":return"Read-Only";case"qmd":return"QMD (Quantized Memory Distillation)";default:return i}}function rs(i){switch(i){case"healthy":return"Healthy";case"warning":return"Warning";case"issues":return"Issues Found"}}function ds({projectId:i,addToast:t}){const[m,u]=a.useState("working"),[C,A]=a.useState(new Set),[E,k]=a.useState(!1),[b,x]=a.useState(null),[r,p]=a.useState({memoryEnabled:!0,memoryAutoSummarizeEnabled:!1,memoryAutoSummarizeThresholdChars:5e4,memoryAutoSummarizeSchedule:"0 3 * * *",memoryDreamsEnabled:!1,memoryDreamsSchedule:"0 4 * * *"}),[O,K]=a.useState(""),[J,L]=a.useState(!1),[S,P]=a.useState(null),{insightsContent:F,insightsLoading:ee,insightsExists:ue,saveInsights:$,memorySettings:o,settingsLoading:v,saveMemorySettings:se,savingMemorySettings:I,backendStatus:c,backendLoading:M,extractInsights:W,extracting:y,auditReport:d,auditLoading:te,refreshAudit:U,compactMemory:f,compacting:ae,installQmdAction:H,installingQmd:ne,testRetrieval:Q,memoryFiles:Y,memoryFilesLoading:re,selectedFilePath:D,selectedFileContent:z,selectedFileLoading:ye,selectedFileDirty:R,setSelectedFileContent:ge,selectFile:B,saveSelectedFile:ie,savingSelectedFile:V,reloadMemoryFiles:le,triggerDreamNow:G,dreamRunning:me}=Ve({projectId:i});a.useEffect(()=>{p(o)},[o]);const Z=a.useMemo(()=>r.memoryEnabled!==o.memoryEnabled||r.memoryAutoSummarizeEnabled!==o.memoryAutoSummarizeEnabled||r.memoryAutoSummarizeThresholdChars!==o.memoryAutoSummarizeThresholdChars||r.memoryAutoSummarizeSchedule!==o.memoryAutoSummarizeSchedule||r.memoryDreamsEnabled!==o.memoryDreamsEnabled||r.memoryDreamsSchedule!==o.memoryDreamsSchedule,[r,o]),j=a.useMemo(()=>Y.find(s=>s.path===D),[Y,D]),be=j?Xe[j.layer]:"Edits the selected memory file.",N=a.useMemo(()=>ss(F),[F]),q=a.useMemo(()=>as(N),[N]),ce=a.useMemo(()=>ts(F),[F]),oe=a.useCallback(s=>{A(h=>{const g=new Set(h);return g.has(s)?g.delete(s):g.add(s),g})},[]),xe=a.useCallback(async s=>{try{await B(s)}catch{t("Failed to load memory file","error")}},[B,t]),pe=a.useCallback(async()=>{try{await ie(),t("Memory saved","success")}catch{t("Failed to save memory","error")}},[ie,t]),fe=a.useCallback(async()=>{if(!Z)return;const s={};r.memoryEnabled!==o.memoryEnabled&&(s.memoryEnabled=r.memoryEnabled),r.memoryAutoSummarizeEnabled!==o.memoryAutoSummarizeEnabled&&(s.memoryAutoSummarizeEnabled=r.memoryAutoSummarizeEnabled),r.memoryAutoSummarizeThresholdChars!==o.memoryAutoSummarizeThresholdChars&&(s.memoryAutoSummarizeThresholdChars=r.memoryAutoSummarizeThresholdChars),r.memoryAutoSummarizeSchedule!==o.memoryAutoSummarizeSchedule&&(s.memoryAutoSummarizeSchedule=r.memoryAutoSummarizeSchedule),r.memoryDreamsEnabled!==o.memoryDreamsEnabled&&(s.memoryDreamsEnabled=r.memoryDreamsEnabled),r.memoryDreamsSchedule!==o.memoryDreamsSchedule&&(s.memoryDreamsSchedule=r.memoryDreamsSchedule);try{await se(s),t("Memory settings saved","success")}catch{t("Failed to save memory settings","error")}},[Z,r,o,se,t]),je=a.useCallback(async()=>{try{const s=await H();t(s.qmdAvailable?"qmd installed successfully":"qmd install finished, but qmd is still unavailable",s.qmdAvailable?"success":"info")}catch{t("Failed to install qmd","error")}},[H,t]),Se=a.useCallback(async()=>{L(!0),P(null);try{const s=await Q(O);P(s),t(s.qmdAvailable?"Memory retrieval test complete":"qmd is not installed; local fallback was used",s.qmdAvailable?"success":"info")}catch{t("Failed to test memory retrieval","error")}finally{L(!1)}},[O,Q,t]),X=a.useCallback(async()=>{try{await G(),t("Dream processing completed","success"),await le()}catch(s){t(s instanceof Error?s.message:"Failed to run dream processing","error")}},[G,le,t]),_=a.useCallback(async()=>{try{await f(D),t("Memory file compacted","success")}catch{t("Failed to compact memory","error")}},[f,D,t]),de=a.useCallback(async()=>{try{const s=await W();t(s.summary,"success")}catch(s){t(s instanceof Error?s.message:"Failed to extract insights","error")}},[W,t]),ve=a.useCallback(async()=>{if(b!==null)try{await $(b),k(!1),x(null),t("Insights saved","success")}catch{t("Failed to save insights","error")}},[b,$,t]),Ne=a.useCallback(()=>{x(F??""),k(!0)},[F]),Ce=a.useCallback(()=>{k(!1),x(null)},[]),n=!M&&c!==null,l=c?.capabilities?.writable??!1;return e.jsxs("div",{className:"memory-view",children:[e.jsx("div",{className:"memory-view-header",children:e.jsxs("div",{children:[e.jsx("h2",{children:"Memory"}),e.jsx("p",{className:"memory-view-description",children:"Working memory, long-term insights, and engine status"})]})}),e.jsxs("div",{className:"memory-view-tabs",role:"tablist",children:[e.jsx("button",{type:"button",role:"tab","aria-selected":m==="working",className:`memory-view-tab${m==="working"?" memory-view-tab--active":""}`,onClick:()=>u("working"),"data-testid":"memory-tab-working",children:"Working Memory"}),e.jsx("button",{type:"button",role:"tab","aria-selected":m==="insights",className:`memory-view-tab${m==="insights"?" memory-view-tab--active":""}`,onClick:()=>u("insights"),"data-testid":"memory-tab-insights",children:"Insights"}),e.jsx("button",{type:"button",role:"tab","aria-selected":m==="engines",className:`memory-view-tab${m==="engines"?" memory-view-tab--active":""}`,onClick:()=>u("engines"),"data-testid":"memory-tab-engines",children:"Engines"})]}),e.jsxs("div",{className:"memory-view-content",children:[m==="working"&&e.jsxs("div",{className:"memory-working-tab",children:[n&&!l&&e.jsx("div",{className:"memory-readonly-banner",children:"This memory backend is read-only. Changes cannot be saved."}),re||ye?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(w,{size:20,className:"animate-spin"}),e.jsx("span",{children:"Loading memory file…"})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"memory-editor-section",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryViewFilePath",children:"Memory File"}),e.jsx("select",{id:"memoryViewFilePath",className:"select",value:D,onChange:s=>{xe(s.target.value)},disabled:R,children:Y.map(s=>e.jsx("option",{value:s.path,title:`${s.label} — ${s.path}`,children:es(s)},s.path))}),e.jsx("small",{children:R?"Save or discard the current edits before switching files.":"Choose any project memory file to view or edit."})]}),j&&e.jsxs("div",{className:"memory-file-summary",children:[e.jsx("span",{children:Ze[j.layer]}),e.jsx("strong",{children:j.path}),e.jsxs("small",{children:[j.size.toLocaleString()," bytes · updated ",new Date(j.updatedAt).toLocaleString()]})]}),e.jsxs("div",{className:"form-group memory-editor-form-group",children:[e.jsx("label",{children:j?.label||"Memory Editor"}),e.jsx("small",{children:be}),e.jsx("div",{className:"memory-editor-container",children:e.jsx(Fe,{content:z,onChange:ge,readOnly:!l,filePath:D})})]})]}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsxs("span",{className:"memory-char-count",children:[z.length," characters"]}),e.jsx("div",{className:"memory-flex-spacer"}),l&&z.length>0&&e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:_,disabled:ae||R,children:ae?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Compacting…"]}):"Compact Selected File"}),R&&l&&e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:pe,disabled:V,children:V?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Saving…"]}):"Save"})]}),e.jsxs("div",{className:"memory-config-section",children:[e.jsxs("div",{className:"memory-settings-group",children:[e.jsxs("div",{className:"form-group",children:[e.jsxs("label",{htmlFor:"memoryDreamsEnabled",className:"checkbox-label",children:[e.jsx("input",{id:"memoryDreamsEnabled",type:"checkbox",checked:r.memoryDreamsEnabled,onChange:s=>{p(h=>({...h,memoryDreamsEnabled:s.target.checked}))},disabled:!r.memoryEnabled||v}),"Process dreams from daily memory"]}),e.jsx("small",{children:"Turns daily notes into DREAMS.md and promotes reusable lessons into MEMORY.md."})]}),r.memoryEnabled&&r.memoryDreamsEnabled&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryDreamsSchedule",children:"Dream Schedule"}),e.jsx("input",{id:"memoryDreamsSchedule",type:"text",className:"input",value:r.memoryDreamsSchedule,onChange:s=>{p(h=>({...h,memoryDreamsSchedule:s.target.value}))},placeholder:"0 4 * * *",disabled:v}),e.jsx("small",{children:"Cron expression for dream processing."})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("button",{type:"button",className:"btn btn-sm",onClick:X,disabled:me||!r.memoryDreamsEnabled,children:me?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Dreaming…"]}):"Dream Now"}),e.jsx("small",{children:"Manually trigger dream processing now."})]})]})]}),e.jsxs("div",{className:"memory-settings-group",children:[e.jsxs("div",{className:"form-group",children:[e.jsxs("label",{htmlFor:"memoryAutoSummarizeEnabled",className:"checkbox-label",children:[e.jsx("input",{id:"memoryAutoSummarizeEnabled",type:"checkbox",checked:r.memoryAutoSummarizeEnabled,onChange:s=>{p(h=>({...h,memoryAutoSummarizeEnabled:s.target.checked}))},disabled:!r.memoryEnabled||v}),"Auto-Summarize Memory"]}),e.jsx("small",{children:"Automatically compact memory when it exceeds the threshold on a schedule"})]}),r.memoryEnabled&&r.memoryAutoSummarizeEnabled&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryAutoSummarizeThresholdChars",children:"Compaction Threshold (chars)"}),e.jsx("input",{id:"memoryAutoSummarizeThresholdChars",type:"number",className:"input",value:r.memoryAutoSummarizeThresholdChars,onChange:s=>{p(h=>({...h,memoryAutoSummarizeThresholdChars:parseInt(s.target.value,10)||5e4}))},min:1e3,disabled:v}),e.jsx("small",{children:"Memory will be compacted when it exceeds this character count"})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryAutoSummarizeSchedule",children:"Schedule (cron)"}),e.jsx("input",{id:"memoryAutoSummarizeSchedule",type:"text",className:"input",value:r.memoryAutoSummarizeSchedule,onChange:s=>{p(h=>({...h,memoryAutoSummarizeSchedule:s.target.value}))},placeholder:"0 3 * * *",disabled:v}),e.jsx("small",{children:"Cron expression for auto-summarize schedule (default: daily at 3 AM)"})]})]})]}),!r.memoryEnabled&&e.jsx("div",{className:"settings-empty-state memory-status-message",children:"Memory is currently disabled. Enable memory tools in Settings to edit these automations."}),Z&&e.jsx("div",{className:"memory-action-bar",children:e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:fe,disabled:I||v,children:I?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Saving…"]}):"Save Settings"})})]})]})]}),m==="insights"&&e.jsx("div",{className:"memory-insights-tab",children:ee?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(w,{size:20,className:"animate-spin"}),e.jsx("span",{children:"Loading insights…"})]}):E?e.jsxs("div",{className:"memory-insights-editor-layout",children:[e.jsx("div",{className:"memory-editor-container",children:e.jsx(Fe,{content:b??"",onChange:x,readOnly:!1,filePath:".fusion/memory/INSIGHTS.md"})}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:Ce,children:"Cancel"}),e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:ve,children:"Save Insights"})]})]}):!ue||N.length===0?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx("p",{children:"No insights extracted yet."}),e.jsx("p",{children:'Insights are automatically extracted from working memory. Click "Extract Now" to trigger extraction manually.'}),e.jsx("button",{type:"button",className:"btn btn-primary btn-sm memory-empty-extract-button",onClick:de,disabled:y,children:y?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Extracting…"]}):"Extract Now"})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"memory-stats-row",children:[e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value",children:q}),e.jsx("div",{className:"memory-stat-label",children:"Total Insights"})]}),e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value",children:N.length}),e.jsx("div",{className:"memory-stat-label",children:"Categories"})]}),ce&&e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value memory-stat-value--updated",children:ce}),e.jsx("div",{className:"memory-stat-label",children:"Last Updated"})]})]}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:de,disabled:y,children:y?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Extracting…"]}):"Extract Now"}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:Ne,children:"Edit Raw"})]}),e.jsx("div",{className:"memory-categories-list",children:N.map(s=>{const h=!C.has(s.key);return e.jsxs("div",{className:"memory-category-section",children:[e.jsxs("div",{className:"memory-category-header",onClick:()=>oe(s.key),role:"button",tabIndex:0,onKeyDown:g=>{(g.key==="Enter"||g.key===" ")&&(g.preventDefault(),oe(s.key))},children:[e.jsx("h4",{children:s.name}),e.jsx("span",{className:"memory-category-count",children:s.items.length})]}),h&&e.jsx("div",{className:"memory-category-items",children:s.items.map((g,ze)=>e.jsx("div",{className:"memory-insight-item",children:g.replace(/^-\s+/,"").replace(/^\*\s+/,"")},ze))})]},s.key)})})]})}),m==="engines"&&e.jsx("div",{className:"memory-engines-tab",children:M||te?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(w,{size:20,className:"animate-spin"}),e.jsx("span",{children:"Loading engine status…"})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"memory-engine-card memory-qmd-card",children:[e.jsx("h3",{children:"QMD Integration"}),c?.qmdAvailable===!0?e.jsxs("div",{className:"memory-engine-status",children:[e.jsx("span",{className:"memory-health-badge memory-health-badge--healthy",children:"Installed"}),e.jsx("span",{className:"memory-char-count",children:"qmd is available on PATH."})]}):c?.qmdAvailable===!1?e.jsxs("div",{className:"settings-empty-state memory-status-message",children:[e.jsxs("span",{children:["qmd is not installed. Search will use local files. Install indexed retrieval: ",e.jsx("code",{children:c.qmdInstallCommand||"bun install -g @tobilu/qmd"})]}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:je,disabled:ne,children:ne?"Installing…":"Install qmd"})]}):e.jsxs("div",{className:"memory-engine-status",children:[e.jsx("span",{className:"memory-health-badge",children:"Checking"}),e.jsx("span",{className:"memory-char-count",children:"Checking qmd availability…"})]}),e.jsxs("div",{className:"memory-capability-row",children:[c?.capabilities?.readable&&e.jsx("span",{className:"memory-capability-badge",children:"Readable"}),c?.capabilities?.writable&&e.jsx("span",{className:"memory-capability-badge",children:"Writable"}),c?.capabilities?.supportsAtomicWrite&&e.jsx("span",{className:"memory-capability-badge",children:"Atomic Writes"}),c?.capabilities?.persistent&&e.jsx("span",{className:"memory-capability-badge",children:"Persistent"})]})]}),e.jsxs("div",{className:"memory-engine-card memory-retrieval-card",children:[e.jsx("h3",{children:"Test Memory Search"}),e.jsxs("div",{className:"memory-retrieval-input-row",children:[e.jsx("input",{type:"text",className:"input",value:O,onChange:s=>K(s.target.value),placeholder:"Search memory with qmd"}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:Se,disabled:J,children:J?"Testing…":"Test Retrieval"})]}),e.jsx("small",{className:"settings-muted",children:"Runs the same qmd-backed memory_search path agents use."}),S&&e.jsxs("div",{className:"memory-test-result",children:[e.jsxs("strong",{children:[S.results.length," result",S.results.length===1?"":"s"," ",'for "',S.query,'"']}),e.jsxs("small",{children:["qmd ",S.qmdAvailable?"available":"missing"," · ",S.usedFallback?"local fallback used":"qmd path used"]}),S.results.length>0?e.jsx("ul",{children:S.results.map((s,h)=>e.jsxs("li",{children:[e.jsxs("span",{children:[s.path,":",s.lineStart]}),e.jsx("p",{children:s.snippet})]},`${s.path}-${s.lineStart}-${h}`))}):e.jsx("small",{children:"No matching memory found."})]})]}),e.jsxs("div",{className:"memory-engine-card",children:[e.jsx("h3",{children:"Current Backend"}),e.jsx("div",{className:"memory-engine-status",children:e.jsx("span",{className:"memory-emphasis-text",children:ns(c?.currentBackend??"unknown")})}),e.jsxs("div",{className:"memory-capability-row",children:[c?.capabilities?.readable&&e.jsx("span",{className:"memory-capability-badge",children:"Readable"}),c?.capabilities?.writable&&e.jsx("span",{className:"memory-capability-badge",children:"Writable"}),c?.capabilities?.supportsAtomicWrite&&e.jsx("span",{className:"memory-capability-badge",children:"Atomic Writes"}),c?.capabilities?.persistent&&e.jsx("span",{className:"memory-capability-badge",children:"Persistent"})]})]}),d&&e.jsxs("div",{className:"memory-engine-card",children:[e.jsxs("div",{className:"memory-health-header",children:[e.jsx("h3",{children:"Health Status"}),e.jsx("span",{className:`memory-health-badge memory-health-badge--${d.health}`,children:rs(d.health)})]}),e.jsxs("div",{className:"memory-health-grid",children:[e.jsxs("div",{children:[e.jsx("div",{className:"memory-health-label",children:"Working Memory"}),e.jsxs("div",{className:"memory-emphasis-text",children:[d.workingMemory.size," chars"]}),e.jsxs("div",{className:"memory-health-detail",children:[d.workingMemory.sectionCount," sections"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"memory-health-label",children:"Insights Memory"}),e.jsxs("div",{className:"memory-emphasis-text",children:[d.insightsMemory.size," chars"]}),e.jsxs("div",{className:"memory-health-detail",children:[d.insightsMemory.insightCount," insights"]})]})]}),e.jsxs("div",{className:"memory-health-section",children:[e.jsx("div",{className:"memory-health-label",children:"Last Extraction"}),e.jsx("div",{className:"memory-emphasis-text",children:d.extraction.success?e.jsx("span",{className:"memory-status-text memory-status-text--success",children:"Success"}):e.jsx("span",{className:"memory-status-text memory-status-text--error",children:"Failed"})}),e.jsx("div",{className:"memory-health-detail",children:d.extraction.summary||`${d.extraction.insightCount} insights extracted`})]}),e.jsxs("div",{className:"memory-health-section",children:[e.jsx("div",{className:"memory-health-label",children:"Pruning"}),e.jsx("div",{className:"memory-emphasis-text",children:d.pruning.applied?e.jsx("span",{className:"memory-status-text memory-status-text--warning",children:"Applied"}):e.jsx("span",{className:"memory-status-text memory-status-text--muted",children:"Not needed"})}),d.pruning.applied&&e.jsx("div",{className:"memory-health-detail",children:d.pruning.reason})]})]}),d&&d.checks.length>0&&e.jsxs("div",{className:"memory-engine-card",children:[e.jsx("h3",{children:"Audit Checks"}),e.jsx("div",{children:d.checks.map(s=>e.jsxs("div",{className:"memory-audit-check",children:[e.jsx("span",{className:s.passed?"memory-audit-check-passed":"memory-audit-check-failed",children:s.passed?"✓":"✗"}),e.jsxs("div",{className:"memory-audit-check-content",children:[e.jsx("div",{className:"memory-emphasis-text",children:s.name}),e.jsx("div",{className:"memory-health-detail",children:s.details})]})]},s.id))})]}),e.jsx("div",{className:"memory-action-bar",children:e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:()=>U(),children:"Run Audit"})}),e.jsxs("div",{className:"memory-settings-note",children:[e.jsx("span",{children:"Note: Change backend type in"}),e.jsx("button",{type:"button",className:"memory-settings-note-button",onClick:()=>{t("Open Settings → Memory to change backend type","info")},children:"Settings → Memory"})]})]})})]})]})}export{ds as MemoryView};
@@ -1,14 +0,0 @@
1
- import{r as s,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Ve,aS as os,aT as cs,aU as is,aV as ds,aW as De,aG as he,aX as ye,aY as Fe,aZ as _e,a_ as Oe,A as Ke,ax as us,Q as Ue,a$ as Te,b0 as ms,_ as Ne,u as hs,R as ke,a as Me,J as fe,b1 as Be,b2 as fs,b3 as gs,b4 as ps,b5 as $e,X as me,ae as xs,af as js,b6 as Ie,F as bs,b7 as ze,b8 as vs,b9 as ys,ba as _s,bb as Ns,bc as ks,G as Cs}from"./index-BonLYFW-.js";import{v as Ss}from"./projectDetection-G3XuxD2X.js";import{U as He}from"./upload-hsiV4Ixv.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";/**
2
- * @license lucide-react v1.7.0 - ISC
3
- *
4
- * This source code is licensed under the ISC license.
5
- * See the LICENSE file in the root directory of this source tree.
6
- */const ws=[["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"}]],Ms=Ve("wifi-off",ws);/**
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 Ps=[["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"}]],Es=Ve("wifi",Ps);function je(t){const{lastSyncAt:l,remoteReachable:a,diff:d}=t,u=d.global.length+d.project.length;return l===null?{syncState:"never-synced",lastSyncAt:l,diffCount:0}:a?u>0?{syncState:"diff",lastSyncAt:l,diffCount:u}:{syncState:"synced",lastSyncAt:l,diffCount:0}:{syncState:"error",lastSyncAt:l,diffCount:u}}function Ce(t){if(t===null)return"Never synced";const l=new Date(t);if(Number.isNaN(l.getTime()))return"Never synced";const d=Date.now()-l.getTime(),u=Math.floor(d/1e3),m=Math.floor(u/60),o=Math.floor(m/60),j=Math.floor(o/24);return m<1?"Synced just now":m<60?`Synced ${m}m ago`:o<24?`Synced ${o}h ago`:`Synced ${j}d ago`}function Rs(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 As=3e4;function Ls(){const[t,l]=s.useState({}),[a,d]=s.useState(!1),[u,m]=s.useState({}),[o,j]=s.useState(null),g=s.useRef(new Set),c=s.useRef(!1),N=s.useRef(null),w=s.useRef(null),b=s.useCallback(async(x,p)=>{try{const S=await os(x);l(Z=>({...Z,[x]:S})),j(null)}catch(S){console.error(`Failed to fetch sync status for node ${x}:`,S),j(S instanceof Error?S.message:"Failed to fetch sync status")}},[]),i=s.useCallback(async()=>{const x=Array.from(g.current);if(x.length===0)return;N.current&&N.current.abort(),N.current=new AbortController;const p=!c.current;p&&d(!0),j(null);try{const S=await Promise.allSettled(x.map(H=>b(H,p)));c.current=!0,S.filter(H=>H.status==="rejected").length>0&&j("Some sync status requests failed")}catch(S){if(S instanceof Error&&S.name==="AbortError")return;j(S instanceof Error?S.message:"Failed to fetch sync status"),c.current=!0}finally{d(!1)}},[b]),M=s.useCallback(()=>{w.current&&clearInterval(w.current),w.current=setInterval(()=>{i()},As)},[i]),_=s.useCallback(()=>{w.current&&(clearInterval(w.current),w.current=null)},[]);s.useEffect(()=>(i(),M(),()=>{_(),N.current&&N.current.abort()}),[i,M,_]);const n=s.useCallback(x=>{g.current.has(x)||(g.current.add(x),b(x,!c.current))},[b]),v=s.useCallback(x=>{g.current.delete(x),l(p=>{const S={...p};return delete S[x],S}),g.current.size===0&&_()},[_]),C=s.useCallback(async x=>{m(p=>({...p,[x]:!0})),j(null);try{const p=await cs(x);return b(x,!1),!p.success&&p.error&&j(p.error),p}catch(p){const S=p instanceof Error?p.message:"Push settings failed";throw j(S),p}finally{m(p=>{const S={...p};return delete S[x],S})}},[b]),k=s.useCallback(async x=>{m(p=>({...p,[x]:!0})),j(null);try{const p=await is(x);return b(x,!1),!p.success&&p.error&&j(p.error),p}catch(p){const S=p instanceof Error?p.message:"Pull settings failed";throw j(S),p}finally{m(p=>{const S={...p};return delete S[x],S})}},[b]),D=s.useCallback(async x=>{m(p=>({...p,[x]:!0})),j(null);try{return await ds(x)}catch(p){const S=p instanceof Error?p.message:"Auth sync failed";throw j(S),p}finally{m(p=>{const S={...p};return delete S[x],S})}},[]),V=s.useCallback(x=>t[x]?.authMatch,[t]),A=s.useCallback(x=>t[x]?.authDiff,[t]);return{syncStatusMap:t,loading:a,actionLoading:u,error:o,refresh:i,trackNode:n,untrackNode:v,pushSettings:C,pullSettings:k,syncAuth:D,getAuthSyncState:V,getAuthProviders:A}}const Ds=1e4,$s=1e3;function Is(){const[t,l]=s.useState([]),[a,d]=s.useState(!0),[u,m]=s.useState(null),o=s.useRef(null),j=s.useRef(0),g=s.useCallback(async()=>{try{m(null);const c=await De();l(c.nodes)}catch(c){m(c instanceof Error?c.message:"Failed to fetch mesh state")}},[]);return s.useEffect(()=>{let c=!1;async function N(){d(!0);try{const b=await De();c||(l(b.nodes),m(null))}catch(b){c||m(b instanceof Error?b.message:"Failed to fetch mesh state")}finally{c||d(!1)}}N();const w=()=>{if(document.visibilityState!=="visible")return;const b=Date.now(),i=b-j.current;if(i<$s){he({view:"useMeshState",trigger:"visibility",projectId:void 0,replayAttempted:!1,reason:"debounce-skipped",detail:{timeSinceLastRefreshMs:i}});return}j.current=b,he({view:"useMeshState",trigger:"visibility",projectId:void 0,replayAttempted:!1,reason:"debounced-refresh"}),g()};return document.addEventListener("visibilitychange",w),()=>{c=!0,document.removeEventListener("visibilitychange",w)}},[g]),s.useEffect(()=>{if(!a)return o.current=setInterval(()=>{g()},Ds),()=>{o.current&&(clearInterval(o.current),o.current=null)}},[a,g]),{meshState:t,loading:a,error:u,refresh:g}}const de={online:{label:"Online",color:"var(--color-success)",className:"node-card__status--online"},offline:{label:"Offline",color:"var(--color-error)",className:"node-card__status--offline"},connecting:{label:"Connecting",color:"var(--color-warning)",className:"node-card__status--connecting"},error:{label:"Error",color:"var(--color-error)",className:"node-card__status--error"},creating:{label:"Creating",color:"var(--color-warning)",className:"node-card__status--creating"},recreating:{label:"Recreating",color:"var(--color-warning)",className:"node-card__status--recreating"},deleting:{label:"Deleting",color:"var(--color-error)",className:"node-card__status--deleting"},running:{label:"Running",color:"var(--color-success)",className:"node-card__status--online"},stopped:{label:"Stopped",color:"var(--color-error)",className:"node-card__status--offline"},exited:{label:"Exited",color:"var(--color-error)",className:"node-card__status--offline"}},zs={match:"var(--color-success)",differs:"var(--color-warning)","not-synced":"var(--text-muted)"};function Vs(t,l){if(t==="match")return"Auth credentials match";if(t==="not-synced")return"Auth not synced";if(l&&Object.keys(l).length>0){const a=Object.entries(l).filter(([,d])=>d==="differs").map(([d])=>d);if(a.length>0)return`Auth credentials differ: ${a.join(", ")}`}return"Auth credentials differ"}function Fs(t,l=42){return t.length<=l?t:`${t.slice(0,l-3)}...`}function Os(t,l){const a=t.node,d=l.node;if(a.id!==d.id||a.name!==d.name||a.type!==d.type||a.url!==d.url||a.status!==d.status||a.maxConcurrent!==d.maxConcurrent||a.updatedAt!==d.updatedAt||t.isLoading!==l.isLoading)return!1;const u=t.managedDockerNode,m=l.managedDockerNode;if(!!u!=!!m||u&&m&&(u.id!==m.id||u.status!==m.status||u.imageTag!==m.imageTag||u.updatedAt!==m.updatedAt))return!1;const o=t.syncStatus,j=l.syncStatus;if(!(!o&&!j)){if(!o||!j)return!1;if(o.syncState!==j.syncState||o.lastSyncAt!==j.lastSyncAt||o.diffCount!==j.diffCount)return!1}if(t.authSyncState!==l.authSyncState)return!1;const g=t.authSyncProviders,c=l.authSyncProviders;if(g!==c){if(!g||!c)return!1;{const b=Object.keys(g),i=Object.keys(c);if(b.length!==i.length||b.some(M=>g[M]!==c[M]))return!1}}const N=ye(t.projects,a),w=ye(l.projects,d);return N===w}function Ks({node:t,projects:l,onHealthCheck:a,onEdit:d,onRemove:u,isLoading:m=!1,syncStatus:o,authSyncState:j,authSyncProviders:g,managedDockerNode:c}){const[N,w]=s.useState(!1),b=de[t.status]??de.offline,i=c?de[c.status]??de.error:null,M=c?.hostConfig.type==="remote"?`Remote: ${c.hostConfig.host??"unknown"}`:"Local Docker",_=s.useMemo(()=>ye(l,t),[l,t]),n=s.useCallback(()=>{d(t)},[d,t]),v=s.useCallback(V=>{V.stopPropagation(),a(t.id)},[a,t.id]),C=s.useCallback(V=>{V.stopPropagation(),d(t)},[d,t]),k=s.useCallback(V=>{if(V.stopPropagation(),!N){w(!0);return}u(t.id),w(!1)},[N,u,t.id]),D=s.useCallback(V=>{(V.key==="Enter"||V.key===" ")&&(V.preventDefault(),d(t))},[d,t]);return e.jsxs("article",{className:`node-card ${m?"node-card--loading":""}`,"data-node-id":t.id,role:"button",tabIndex:0,onClick:n,onKeyDown:D,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(Fe,{size:18})}),e.jsxs("div",{children:[e.jsx("h3",{className:"node-card__name",title:t.name,children:t.name}),e.jsxs("div",{className:"node-card__meta-row",children:[e.jsx("span",{className:"node-card__type-badge",children:t.type==="local"?"Local":"Remote"}),c&&e.jsxs("span",{className:"node-card__docker-badge",title:"Managed Docker node",children:[e.jsx(_e,{size:12,"aria-hidden":!0}),"Docker"]}),e.jsxs("span",{className:`node-card__status ${b.className}`,style:{color:b.color},"data-status":t.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:b.color},"aria-hidden":!0}),b.label]}),c&&i&&e.jsxs("span",{className:`node-card__status ${i.className}`,style:{color:i.color},"data-status":c.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:i.color},"aria-hidden":!0}),i.label]}),t.type==="remote"&&j&&e.jsx("span",{className:`node-card__auth-indicator node-card__auth-indicator--${j}`,title:Vs(j,g),"aria-label":`Auth sync: ${j==="match"?"credentials match":j==="differs"?"credentials differ":"not synced"}`,style:{color:zs[j]},children:e.jsx(Oe,{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:Fs(t.url)}),c&&e.jsxs("div",{className:"node-card__docker-meta",children:[e.jsxs("span",{title:`${c.imageName}:${c.imageTag}`,children:[c.imageName,":",c.imageTag]}),e.jsx("span",{title:M,children:M})]}),e.jsxs("div",{className:"node-card__metrics",children:[e.jsxs("div",{className:"node-card__metric",children:[e.jsx("span",{className:"node-card__metric-label",children:"Projects"}),e.jsx("span",{className:"node-card__metric-value",children:_})]}),e.jsxs("div",{className:"node-card__metric",children:[e.jsx("span",{className:"node-card__metric-label",children:"Concurrency"}),e.jsx("span",{className:"node-card__metric-value",children:t.maxConcurrent})]})]}),t.type==="remote"&&o&&e.jsxs("div",{className:"node-card__sync","data-sync-state":o.syncState,"data-testid":"node-card-sync",children:[e.jsx("span",{className:"node-card__sync-dot",style:{backgroundColor:Rs(o.syncState)},"aria-hidden":!0}),e.jsx("span",{className:"node-card__sync-time",children:Ce(o.lastSyncAt)})]})]}),e.jsxs("footer",{className:"node-card__actions",children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:v,disabled:m,"aria-label":"Run node health check",title:"Health Check",children:[e.jsx(Ke,{size:14}),e.jsx("span",{children:"Health"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:C,disabled:m,"aria-label":"Edit node",title:"Edit",children:[e.jsx(us,{size:14}),e.jsx("span",{children:"Edit"})]}),c&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",disabled:!0,"aria-label":"Start node container",title:"Available after FN-3113",children:[e.jsx(Ue,{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(Te,{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:m,"aria-label":N?"Confirm remove node":"Remove node",title:N?"Confirm remove":"Remove",children:[e.jsx(Ne,{size:14}),e.jsx("span",{children:N?"Confirm":"Remove"})]})]})]})}const Us=s.memo(Ks,Os),ce={online:"var(--success, var(--color-success))",offline:"var(--text-dim)",connecting:"var(--color-warning)",error:"var(--color-error)"},ue=28,Ts=12,Bs=300,Hs=120;function qs({nodes:t,className:l}){const a=s.useMemo(()=>t.find(c=>c.nodeType==="local")??t[0],[t]),d=s.useMemo(()=>t.filter(c=>c.nodeId!==a?.nodeId),[t,a?.nodeId]),u=s.useMemo(()=>Bs+Math.max(0,d.length-4)*20,[d.length]),m=u/2,o=u/2,j=s.useMemo(()=>{const c=new Map;if(a&&c.set(a.nodeId,{x:m,y:o,node:a}),d.length>0){const N=Math.min(Hs,u/2-ue-10),w=2*Math.PI/d.length,b=-Math.PI/2;d.forEach((i,M)=>{const _=b+M*w;c.set(i.nodeId,{node:i,x:m+N*Math.cos(_),y:o+N*Math.sin(_)})})}return c},[m,o,a,d,u]),g=s.useMemo(()=>{const c=new Set,N=[];for(const w of t){const b=j.get(w.nodeId);if(b)for(const i of w.knownPeers){const M=j.get(i.peerNodeId);if(!M)continue;const _=[w.nodeId,i.peerNodeId].sort().join("::");c.has(_)||(c.add(_),N.push({key:_,from:b,to:M}))}}return N},[j,t]);return t.length===0?e.jsx("div",{className:`mesh-topology mesh-topology--empty ${l??""}`,children:e.jsx("div",{className:"mesh-topology__empty-state",children:e.jsx("p",{children:"No nodes to display"})})}):e.jsxs("div",{className:`mesh-topology ${l??""}`,children:[e.jsxs("svg",{className:"mesh-topology__svg",viewBox:`0 0 ${u} ${u}`,preserveAspectRatio:"xMidYMid meet","aria-label":"Node mesh topology visualization",children:[g.map(c=>e.jsx("line",{className:"mesh-topology__link mesh-topology__peer-line",x1:c.from.x,y1:c.from.y,x2:c.to.x,y2:c.to.y},c.key)),Array.from(j.values()).map(({node:c,x:N,y:w})=>e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${N}, ${w})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:ue,fill:ce[c.status],"aria-label":`${c.nodeName} (${c.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:ue+Ts,textAnchor:"middle",children:c.nodeName.length>12?`${c.nodeName.slice(0,10)}…`:c.nodeName}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-ue-10})`,children:[e.jsx("circle",{className:"mesh-topology__node-type-badge",r:"8"}),e.jsx("text",{className:"mesh-topology__node-type-text",textAnchor:"middle",dominantBaseline:"middle",children:c.nodeType==="local"?"L":"R"})]})]},c.nodeId))]}),e.jsxs("div",{className:"mesh-topology__legend",children:[e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.online}}),e.jsx("span",{children:"Online"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.offline}}),e.jsx("span",{children:"Offline"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.connecting}}),e.jsx("span",{children:"Connecting"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:ce.error}}),e.jsx("span",{children:"Error"})]})]}),g.length===0&&e.jsx("p",{className:"mesh-topology__notice",children:"Peer-to-peer discovery data unavailable."})]})}const Ys=s.memo(qs),Se=1,we=10;function Xs(t){const l={projectMappings:{}};t.name.trim()||(l.name="Name is required"),t.type==="remote"&&!t.url?.trim()&&(l.url="URL is required for remote nodes"),(!Number.isFinite(t.maxConcurrent)||t.maxConcurrent<Se||t.maxConcurrent>we)&&(l.maxConcurrent=`Concurrency must be between ${Se} and ${we}`);for(const a of t.projectMappings){const d=Ss(a.path);d.valid||(l.projectMappings[a.projectId]=d.error??"Path is invalid")}return l}function Js({isOpen:t,onClose:l,onSubmit:a,onDiscoverRemoteProjects:d,addToast:u,projects:m}){hs(t);const[o,j]=s.useState(""),[g,c]=s.useState("local"),[N,w]=s.useState(""),[b,i]=s.useState(""),[M,_]=s.useState(2),[n,v]=s.useState("auto-generate"),[C,k]=s.useState({}),[D,V]=s.useState({projectMappings:{}}),[A,x]=s.useState(!1),[p,S]=s.useState("idle"),[Z,H]=s.useState(null),[Y,ee]=s.useState([]),U=s.useCallback(()=>{j(""),c("local"),w(""),i(""),_(2),v("auto-generate"),k({}),V({projectMappings:{}}),x(!1),S("idle"),H(null),ee([])},[]),X=s.useCallback(()=>{A||(U(),l())},[A,l,U]);s.useEffect(()=>{if(!t){U();return}const y=L=>{L.key==="Escape"&&(L.preventDefault(),X())};return document.addEventListener("keydown",y),()=>{document.removeEventListener("keydown",y)}},[X,t,U]);const G=s.useMemo(()=>({name:o.trim(),type:g,url:g==="remote"&&N.trim()||void 0,apiKey:g==="remote"&&n==="provide"&&b||void 0,maxConcurrent:M,apiKeyMode:n,projectMappings:Object.entries(C).map(([y,L])=>({projectId:y,path:L.trim()}))}),[b,n,M,o,C,g,N]),te=s.useCallback(async()=>{if(A||p==="loading")return;const y=N.trim();if(!y){V(L=>({...L,url:"URL is required for remote nodes"}));return}S("loading"),H(null);try{const L=await d({url:y,apiKey:n==="provide"&&b.trim().length>0?b:void 0});ee(L.projects),S("success"),k($=>{if(Object.keys($).length===0)return $;const K={...$};for(const ae of m){if(!(ae.id in K))continue;const ne=L.projects.filter(se=>se.name===ae.name);ne.length===1&&(K[ae.id]=ne[0].path)}return K})}catch(L){S("error"),ee([]),H(L instanceof Error?L.message:"Failed to discover remote projects")}},[b,n,p,A,d,m,N]);s.useEffect(()=>{if(g!=="remote"){S("idle"),H(null),ee([]);return}S("idle"),H(null),ee([])},[b,n,g,N]);const J=s.useCallback(async()=>{if(A)return;const y=Xs(G);if(V(y),!(y.name||y.url||y.maxConcurrent||Object.keys(y.projectMappings).length>0)){if(G.type==="remote"&&p!=="success"){H("Discover remote projects before adding this node.");return}x(!0);try{await a(G),u(`Node "${G.name}" registered`,"success"),X()}catch(L){const $=L instanceof Error?L.message:"Failed to register node";u($,"error")}finally{x(!1)}}},[u,X,p,G,A,a]),T=y=>{k(L=>{if(y.id in L){const{[y.id]:$,...K}=L;return K}if(g==="remote"&&p==="success"){const $=Y.filter(K=>K.name===y.name);return $.length===1?{...L,[y.id]:$[0].path}:{...L,[y.id]:""}}return{...L,[y.id]:y.path}})},E=(y,L)=>{k($=>({...$,[y]:L}))};return t?e.jsx("div",{className:"modal-overlay open",onClick:X,children:e.jsxs("div",{className:"modal modal-md add-node-modal",onClick:y=>y.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Add Node",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Add Node"}),e.jsx("button",{className:"modal-close",onClick:X,disabled:A,"aria-label":"Close add node modal",children:"×"})]}),e.jsxs("div",{className:"modal-body add-node-modal__body",children:[e.jsx("p",{className:"add-node-modal__description",children:"Register an existing Fusion node by providing its connection details and concurrency settings."}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Name"}),e.jsx("input",{className:"input",type:"text",value:o,onChange:y=>j(y.target.value),placeholder:"Build Machine",disabled:A,"aria-invalid":!!D.name,autoFocus:!0}),D.name&&e.jsx("span",{className:"form-error add-node-modal__error",children:D.name})]}),e.jsxs("div",{className:"add-node-modal__type-toggle",children:[e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${g==="local"?"active":""}`,"data-type":"local",onClick:()=>c("local"),disabled:A,"aria-pressed":g==="local",children:"Local"}),e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${g==="remote"?"active":""}`,"data-type":"remote",onClick:()=>c("remote"),disabled:A,"aria-pressed":g==="remote",children:"Remote"})]}),g==="remote"&&e.jsxs("div",{className:"add-node-modal__remote-fields","data-testid":"remote-fields-container","data-visible":!0,children:[e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Reachable URL / Hostname"}),e.jsx("input",{className:"input",type:"text",value:N,onChange:y=>w(y.target.value),placeholder:"https://node.example.com",disabled:A,"aria-invalid":!!D.url}),D.url&&e.jsx("span",{className:"form-error add-node-modal__error",children:D.url})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key Mode"}),e.jsxs("select",{className:"select",value:n,onChange:y=>v(y.target.value),disabled:A,children:[e.jsx("option",{value:"auto-generate",children:"Auto-generate"}),e.jsx("option",{value:"provide",children:"Provide key manually"})]})]}),n==="provide"&&e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:b,onChange:y=>i(y.target.value),placeholder:"Enter node API key",disabled:A})]}),e.jsxs("div",{className:"add-node-modal__discovery-actions",children:[e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void te(),disabled:A||p==="loading",children:p==="loading"?"Discovering...":"Discover Remote Projects"}),p==="success"&&e.jsx("span",{className:"add-node-modal__discovery-state","data-state":"success",children:Y.length>0?`Discovered ${Y.length} remote project${Y.length===1?"":"s"}.`:"No projects discovered on remote node."}),p==="error"&&Z&&e.jsx("span",{className:"form-error add-node-modal__error",children:Z}),p==="idle"&&e.jsx("span",{className:"add-node-modal__hint",children:"Discover remote projects before adding this node."})]}),p==="success"&&Y.length>0&&e.jsx("div",{className:"add-node-modal__discovered-list","aria-label":"Discovered remote projects",children:Y.map(y=>e.jsxs("div",{className:"card add-node-modal__discovered-card",children:[e.jsxs("div",{className:"add-node-modal__discovered-row",children:[e.jsx("strong",{children:y.name}),e.jsx("span",{className:"card-status-badge card-status-badge--in-review",children:y.status})]}),e.jsx("div",{className:"add-node-modal__hint",children:y.path})]},`${y.id}-${y.path}`))})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),e.jsx("input",{className:"input",type:"number",min:Se,max:we,value:M,onChange:y=>_(Number(y.target.value)),disabled:A,"aria-invalid":!!D.maxConcurrent}),e.jsx("span",{className:"add-node-modal__hint",children:"Max simultaneous task agents (1–10)"}),D.maxConcurrent&&e.jsx("span",{className:"form-error add-node-modal__error",children:D.maxConcurrent})]}),e.jsxs("section",{className:"add-node-modal__projects","aria-label":"Project path mappings",children:[e.jsx("h4",{className:"add-node-modal__projects-title",children:"Attach Existing Projects"}),e.jsx("p",{className:"add-node-modal__hint",children:"Select existing projects to run on this node and provide the node-specific absolute path for each one."}),m.length===0?e.jsx("p",{className:"add-node-modal__hint",children:"No projects are currently registered."}):e.jsx("div",{className:"add-node-modal__project-list",children:m.map(y=>{const L=y.id in C,$=D.projectMappings[y.id];return e.jsxs("div",{className:"card add-node-modal__project-card",children:[e.jsxs("label",{className:"checkbox-label add-node-modal__project-toggle",children:[e.jsx("input",{type:"checkbox",checked:L,onChange:()=>T(y),disabled:A}),e.jsx("span",{children:y.name})]}),L&&e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Path on this node"}),g==="remote"&&p==="success"&&e.jsx("span",{className:"add-node-modal__hint",children:(()=>{const K=Y.filter(ae=>ae.name===y.name);return K.length===1?`Remote-authoritative path discovered: ${K[0].path}`:K.length>1?"Multiple remote projects matched this name. Enter the correct path manually.":"No exact remote name match. Enter this path manually."})()}),e.jsx("input",{className:"input",type:"text",value:C[y.id]??"",onChange:K=>E(y.id,K.target.value),disabled:A,placeholder:"/absolute/path/to/project","aria-invalid":!!$}),$&&e.jsx("span",{className:"form-error add-node-modal__error",children:$})]})]},y.id)})})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:X,disabled:A,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm","data-testid":"add-node-submit",onClick:J,disabled:A,children:A?"Adding...":"Add Node"})]})]})}):null}function Ws(){const[t,l]=s.useState([]),[a,d]=s.useState(!1),[u,m]=s.useState(null),[o,j]=s.useState(!1),[g,c]=s.useState(null),[N,w]=s.useState(!1),b=s.useCallback(async()=>{d(!0),m(null);try{const _=await fetch("/api/docker/contexts");if(!_.ok)throw new Error(`Failed to load Docker contexts (${_.status})`);const n=await _.json();return l(n),n}catch(_){const n=_ instanceof Error?_.message:String(_);throw m(n),_}finally{d(!1)}},[]),i=s.useCallback(async _=>{j(!0);try{const n=await fetch("/api/docker/test-connection",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({hostConfig:_})});if(!n.ok)throw new Error(`Failed to test Docker connection (${n.status})`);const v=await n.json();return c(v),v}finally{j(!1)}},[]),M=s.useCallback(async()=>{w(!0);try{const _=await fetch("/api/docker/local-available");if(!_.ok)throw new Error(`Failed to check local Docker availability (${_.status})`);return await _.json()}finally{w(!1)}},[]);return{contexts:t,isLoadingContexts:a,contextsError:u,loadContexts:b,isTestingConnection:o,lastTestResult:g,testConnection:i,isCheckingLocal:N,checkLocalDocker:M}}function Gs({value:t,onChange:l}){const[a,d]=s.useState(!!(t?.tlsCaPath||t?.tlsCertPath||t?.tlsKeyPath||t?.tlsVerify));s.useEffect(()=>{a||l({tlsVerify:void 0,tlsCaPath:void 0,tlsCertPath:void 0,tlsKeyPath:void 0})},[a,l]);const u=s.useMemo(()=>({tlsVerify:t?.tlsVerify??!0,tlsCaPath:t?.tlsCaPath??"",tlsCertPath:t?.tlsCertPath??"",tlsKeyPath:t?.tlsKeyPath??""}),[t]);return e.jsxs("div",{className:"docker-tls-config",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:a,onChange:m=>d(m.target.checked)}),"Use TLS"]}),a&&e.jsxs("div",{className:"docker-tls-config__fields",children:[e.jsxs("div",{className:"docker-tls-config__field",children:[e.jsx("label",{htmlFor:"docker-tls-ca-path",children:"CA Certificate Path"}),e.jsx("input",{id:"docker-tls-ca-path",className:"input",value:u.tlsCaPath,onChange:m=>l({...u,tlsCaPath:m.target.value}),placeholder:"/etc/docker/ca.pem"})]}),e.jsxs("div",{className:"docker-tls-config__field",children:[e.jsx("label",{htmlFor:"docker-tls-cert-path",children:"Client Certificate Path"}),e.jsx("input",{id:"docker-tls-cert-path",className:"input",value:u.tlsCertPath,onChange:m=>l({...u,tlsCertPath:m.target.value}),placeholder:"/etc/docker/cert.pem"})]}),e.jsxs("div",{className:"docker-tls-config__field",children:[e.jsx("label",{htmlFor:"docker-tls-key-path",children:"Client Key Path"}),e.jsx("input",{id:"docker-tls-key-path",className:"input",value:u.tlsKeyPath,onChange:m=>l({...u,tlsKeyPath:m.target.value}),placeholder:"/etc/docker/key.pem"})]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:u.tlsVerify,onChange:m=>l({...u,tlsVerify:m.target.checked})}),"Verify TLS Certificate"]})]})]})}function Zs({value:t,onChange:l,onError:a}){const d=t?.context?"context":t?.host?"host":"local",[u,m]=s.useState(d),[o,j]=s.useState(t?.context??""),[g,c]=s.useState(t?.host??""),[N,w]=s.useState(null),{contexts:b,isLoadingContexts:i,contextsError:M,loadContexts:_,testConnection:n,isTestingConnection:v,lastTestResult:C,checkLocalDocker:k,isCheckingLocal:D}=Ws(),V=s.useMemo(()=>({tlsVerify:t?.tlsVerify,tlsCaPath:t?.tlsCaPath,tlsCertPath:t?.tlsCertPath,tlsKeyPath:t?.tlsKeyPath}),[t]);s.useEffect(()=>{if(u==="local"){l({});return}if(u==="context"){_().catch(x=>a?.(x instanceof Error?x.message:String(x))),l(o?{context:o}:{});return}l({host:g,...V})},[u]);const A=s.useCallback(x=>{u==="host"&&l({host:g,...x})},[g,u,l]);return e.jsxs("div",{className:"docker-target-selector",children:[e.jsxs("div",{className:"docker-target-selector__modes",role:"group","aria-label":"Docker target mode",children:[e.jsx("button",{type:"button",className:`btn btn-sm ${u==="local"?"docker-target-selector__mode-active":""}`,onClick:()=>{m("local"),k().then(x=>w(x.available?`Docker is available${x.version?` (${x.version})`:""}`:`Docker not found${x.error?`: ${x.error}`:""}`)).catch(x=>{const p=x instanceof Error?x.message:String(x);w(`Docker not found: ${p}`),a?.(p)})},children:"Local Docker"}),e.jsx("button",{type:"button",className:`btn btn-sm ${u==="context"?"docker-target-selector__mode-active":""}`,onClick:()=>m("context"),children:"Docker Context"}),e.jsx("button",{type:"button",className:`btn btn-sm ${u==="host"?"docker-target-selector__mode-active":""}`,onClick:()=>m("host"),children:"Remote Host"})]}),u==="local"&&N&&e.jsx("div",{className:"docker-target-selector__status",children:N}),u==="context"&&e.jsxs("div",{className:"docker-target-selector__panel",children:[e.jsxs("div",{className:"docker-target-selector__context-row",children:[e.jsxs("select",{className:"select",value:o,onChange:x=>{const p=x.target.value;j(p),l(p?{context:p}:{})},children:[e.jsx("option",{value:"",children:"Select context"}),b.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 _(),disabled:i,"aria-label":"Refresh contexts",children:e.jsx(ke,{size:14})})]}),M&&e.jsx("div",{className:"docker-target-selector__error",children:M})]}),u==="host"&&e.jsxs("div",{className:"docker-target-selector__panel",children:[e.jsxs("div",{className:"docker-target-selector__field",children:[e.jsx("label",{htmlFor:"docker-target-selector-host",children:"Docker Host"}),e.jsx("input",{id:"docker-target-selector-host",className:"input",placeholder:"tcp://host:2376",value:g,onChange:x=>{const p=x.target.value;c(p),l({host:p,...V})}})]}),e.jsx(Gs,{value:V,onChange:A})]}),e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void n(u==="local"?void 0:u==="context"?{context:o}:{host:g,...V}),disabled:v||D,children:v?"Testing...":"Test Connection"}),C&&e.jsx("div",{className:C.success?"docker-target-selector__success":"docker-target-selector__error",children:C.success?`Connected${C.dockerVersion?` (Docker ${C.dockerVersion})`:""}`:C.error??"Connection failed"})]})}const be="http://localhost:4040";function Qs({isOpen:t,onClose:l,onSubmit:a,addToast:d}){const[u,m]=s.useState(""),[o,j]=s.useState({}),[g,c]=s.useState(be),[N,w]=s.useState("auto"),[b,i]=s.useState(""),[M,_]=s.useState(!1),[n,v]=s.useState(!1),[C,k]=s.useState(!0),[D,V]=s.useState(4096),[A,x]=s.useState(2),[p,S]=s.useState(!1),[Z,H]=s.useState("runfusion/fusion"),[Y,ee]=s.useState("latest"),[U,X]=s.useState([]),[G,te]=s.useState([]),[J,T]=s.useState({}),[E,y]=s.useState(!1),L=s.useCallback(()=>{m(""),j({}),c(be),w("auto"),i(""),_(!1),v(!1),k(!0),V(4096),x(2),S(!1),H("runfusion/fusion"),ee("latest"),X([]),te([]),T({}),y(!1)},[]),$=s.useCallback(()=>{E||(L(),l())},[l,L,E]);s.useEffect(()=>{if(!t){L();return}const h=O=>{O.key==="Escape"&&(O.preventDefault(),$())};return document.addEventListener("keydown",h),()=>document.removeEventListener("keydown",h)},[$,t,L]);const K=s.useMemo(()=>({nodeId:null,name:u.trim(),imageName:Z.trim()||"runfusion/fusion",imageTag:Y.trim()||"latest",hostConfig:{context:o.context?.trim()||void 0,host:o.host?.trim()||void 0,tlsVerify:o.tlsVerify,tlsCaPath:o.tlsCaPath?.trim()||void 0,tlsCertPath:o.tlsCertPath?.trim()||void 0,tlsKeyPath:o.tlsKeyPath?.trim()||void 0},envVars:Object.fromEntries(U.map(h=>[h.key.trim(),h.value]).filter(([h])=>!!h)),volumeMounts:G.map(h=>({hostPath:h.hostPath.trim(),containerPath:h.containerPath.trim(),mode:h.mode})).filter(h=>h.hostPath&&h.containerPath),resourceSizing:{memoryMB:D,cpus:A},extraClis:[M?"claude-cli":null,n?"droid-cli":null].filter(Boolean),persistentStorage:C,reachableUrl:g.trim()||null,apiKey:N==="manual"&&b.trim()||null}),[b,N,A,o,U,Z,Y,M,n,D,G,u,C,g]),ae=s.useCallback(()=>{X(h=>[...h,{key:"",value:""}])},[]),ne=s.useCallback((h,O)=>{X(B=>B.map((q,oe)=>oe===h?O:q))},[]),se=s.useCallback(h=>{X(O=>O.filter((B,q)=>q!==h))},[]),le=s.useCallback(()=>{te(h=>[...h,{hostPath:"",containerPath:"",mode:"rw"}])},[]),R=s.useCallback((h,O)=>{te(B=>B.map((q,oe)=>oe===h?O:q))},[]),I=s.useCallback(h=>{te(O=>O.filter((B,q)=>q!==h))},[]),W=s.useCallback(async()=>{if(E)return;const h={};if((!K.name||K.name.length>64)&&(h.name="Name is required and must be 64 characters or fewer"),K.reachableUrl||(h.reachableUrl="URL is required"),D<512&&(h.memoryMB="Memory must be at least 512 MB"),A<.5&&(h.cpus="CPUs must be at least 0.5"),T(h),!(Object.keys(h).length>0)){y(!0);try{await a(K),$()}catch{}finally{y(!1)}}},[$,A,K,D,a,E]);return t?e.jsx("div",{className:"modal-overlay open",onClick:$,children:e.jsxs("div",{className:"modal docker-onboarding",role:"dialog","aria-modal":"true","aria-label":"Docker node onboarding",onClick:h=>h.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Provision Docker Node"}),e.jsx("button",{className:"modal-close",onClick:$,disabled:E,"aria-label":"Close onboarding modal",children:"×"})]}),e.jsxs("div",{className:"modal-body docker-onboarding__body",children:[e.jsxs("section",{className:"docker-onboarding__section",children:[e.jsx("h4",{className:"docker-onboarding__section-title",children:"Required Settings"}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Node Name"}),e.jsx("input",{className:"input",value:u,onChange:h=>m(h.target.value),disabled:E,placeholder:"my-docker-node",autoFocus:!0})]}),J.name&&e.jsx("div",{className:"form-error",children:J.name}),e.jsx(Zs,{value:o,onChange:j}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Reachable URL"}),e.jsx("input",{className:"input",value:g,onChange:h=>c(h.target.value),disabled:E,placeholder:be})]}),J.reachableUrl&&e.jsx("div",{className:"form-error",children:J.reachableUrl}),e.jsxs("div",{className:"docker-onboarding__radio-group",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"radio",checked:N==="auto",onChange:()=>w("auto"),disabled:E}),"Auto-generate"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"radio",checked:N==="manual",onChange:()=>w("manual"),disabled:E}),"Provide manually"]})]}),N==="manual"&&e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:b,onChange:h=>i(h.target.value),disabled:E,placeholder:"Enter API key"})]}),e.jsxs("div",{className:"docker-onboarding__checkbox-group",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:M,onChange:h=>_(h.target.checked),disabled:E}),"Claude CLI"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:n,onChange:h=>v(h.target.checked),disabled:E}),"Droid CLI"]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:C,onChange:h=>k(h.target.checked),disabled:E}),"Keep data across container recreations"]})]}),e.jsxs("div",{className:"docker-onboarding__inline-fields",children:[e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Memory (MB)"}),e.jsx("input",{className:"input",type:"number",min:512,value:D,onChange:h=>V(Number(h.target.value)),disabled:E})]}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"CPUs"}),e.jsx("input",{className:"input",type:"number",min:.5,step:.5,value:A,onChange:h=>x(Number(h.target.value)),disabled:E})]})]}),J.memoryMB&&e.jsx("div",{className:"form-error",children:J.memoryMB}),J.cpus&&e.jsx("div",{className:"form-error",children:J.cpus})]}),e.jsxs("section",{className:"docker-onboarding__section",children:[e.jsxs("button",{type:"button",className:`docker-onboarding__advanced-toggle ${p?"is-expanded":""}`,onClick:()=>S(h=>!h),disabled:E,children:[e.jsx("span",{children:"Advanced"}),e.jsx(Me,{})]}),e.jsx("div",{className:`docker-onboarding__advanced-content ${p?"is-expanded":""}`,children:e.jsxs("div",{children:[e.jsxs("div",{className:"docker-onboarding__inline-fields",children:[e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Image"}),e.jsx("input",{className:"input",value:Z,onChange:h=>H(h.target.value),disabled:E,placeholder:"runfusion/fusion"})]}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:"Tag"}),e.jsx("input",{className:"input",value:Y,onChange:h=>ee(h.target.value),disabled:E,placeholder:"latest"})]})]}),e.jsxs("div",{className:"docker-onboarding__kv-list",children:[e.jsx("h5",{children:"Environment Variables"}),U.map((h,O)=>e.jsxs("div",{className:"docker-onboarding__kv-row docker-onboarding__kv-row--env",children:[e.jsx("input",{className:"input",placeholder:"KEY",value:h.key,disabled:E,onChange:B=>ne(O,{key:B.target.value,value:h.value})}),e.jsx("input",{className:"input",placeholder:"Value",value:h.value,disabled:E,onChange:B=>ne(O,{key:h.key,value:B.target.value})}),e.jsx("button",{type:"button",className:"btn btn-icon","aria-label":"Remove environment variable",onClick:()=>se(O),disabled:E,children:e.jsx(Ne,{size:14})})]},`env-${O}`)),e.jsxs("button",{type:"button",className:"btn btn-sm docker-onboarding__kv-add",onClick:ae,disabled:E,children:[e.jsx(fe,{size:14}),"Add variable"]})]}),e.jsxs("div",{className:"docker-onboarding__kv-list",children:[e.jsx("h5",{children:"Volume Mounts"}),G.map((h,O)=>e.jsxs("div",{className:"docker-onboarding__kv-row docker-onboarding__kv-row--mount",children:[e.jsx("input",{className:"input",placeholder:"Host path",value:h.hostPath,disabled:E,onChange:B=>R(O,{hostPath:B.target.value,containerPath:h.containerPath,mode:h.mode})}),e.jsx("input",{className:"input",placeholder:"Container path",value:h.containerPath,disabled:E,onChange:B=>R(O,{hostPath:h.hostPath,containerPath:B.target.value,mode:h.mode})}),e.jsxs("select",{className:"select",value:h.mode,disabled:E,onChange:B=>R(O,{hostPath:h.hostPath,containerPath:h.containerPath,mode:B.target.value==="ro"?"ro":"rw"}),children:[e.jsx("option",{value:"rw",children:"rw"}),e.jsx("option",{value:"ro",children:"ro"})]}),e.jsx("button",{type:"button",className:"btn btn-icon","aria-label":"Remove volume mount",onClick:()=>I(O),disabled:E,children:e.jsx(Ne,{size:14})})]},`mount-${O}`)),e.jsxs("button",{type:"button",className:"btn btn-sm docker-onboarding__kv-add",onClick:le,disabled:E,children:[e.jsx(fe,{size:14}),"Add mount"]})]})]})})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn",onClick:$,disabled:E,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",onClick:()=>void W(),disabled:E,children:E?"Creating...":"Create Docker Node"})]})]})}):null}function et({nodeId:t,entries:l,loading:a=!1,singleNode:d=!1}){const[u,m]=s.useState(!1),[o,j]=s.useState("all"),[g,c]=s.useState("all"),N=s.useCallback(()=>{m(n=>!n)},[]),w=s.useMemo(()=>{const n=new Set;for(const v of l)n.add(v.nodeName);return Array.from(n).sort()},[l]),b=s.useMemo(()=>{let n=[...l];return o!=="all"&&(n=n.filter(v=>v.direction===o)),!d&&g!=="all"&&(n=n.filter(v=>v.nodeName===g)),n.sort((v,C)=>{const k=new Date(v.timestamp).getTime();return new Date(C.timestamp).getTime()-k}),n},[l,o,g,d]),i=s.useCallback(n=>new Date(n).toLocaleString(),[]),M=s.useCallback(n=>{switch(n){case"success":return"settings-sync-log__badge--success";case"conflict":return"settings-sync-log__badge--conflict";case"error":return"settings-sync-log__badge--error";default:return""}},[]),_=s.useCallback(n=>{switch(n){case"success":return"Success";case"conflict":return"Conflict";case"error":return"Error";default:return n}},[]);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(Me,{size:16,className:`settings-sync-log__chevron ${u?"settings-sync-log__chevron--expanded":""}`}),e.jsxs("span",{children:[l.length," ",l.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:n=>j(n.target.value),children:[e.jsx("option",{value:"all",children:"All"}),e.jsx("option",{value:"push",children:"Push"}),e.jsx("option",{value:"pull",children:"Pull"})]})]}),!d&&e.jsxs("label",{children:["Node:",e.jsxs("select",{value:g,onChange:n=>c(n.target.value),children:[e.jsx("option",{value:"all",children:"All Nodes"}),w.map(n=>e.jsx("option",{value:n,children:n},n))]})]})]}),a&&l.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"Loading..."}):b.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"No sync history available"}):e.jsx("div",{className:"settings-sync-log__list",children:b.map(n=>e.jsxs("div",{className:"settings-sync-log__entry",children:[e.jsx("span",{className:"settings-sync-log__entry-timestamp",children:i(n.timestamp)}),e.jsx("span",{className:"settings-sync-log__entry-direction",children:n.direction==="push"?e.jsx(He,{size:14,"data-testid":"upload-icon"}):e.jsx(Be,{size:14,"data-testid":"download-icon"})}),e.jsx("span",{className:`settings-sync-log__entry-result ${M(n.result)}`,children:_(n.result)}),!d&&e.jsx("span",{className:"settings-sync-log__entry-node",children:n.nodeName}),n.details&&e.jsx("span",{className:"settings-sync-log__entry-details",title:n.details,children:fs(n.details??"")})]},n.id))})]})]})}function st(t,l){const a=typeof t=="string"?t:JSON.stringify(t,null,2),d=typeof l=="string"?l:JSON.stringify(l,null,2);if(a===d)return a;const u=a.split(`
12
- `),m=d.split(`
13
- `),o=[],j=Math.max(u.length,m.length);for(let g=0;g<j;g++){const c=u[g],N=m[g];c!==void 0&&c!==N&&o.push(`- ${c}`),N!==void 0&&N!==c&&o.push(`+ ${N}`),c!==void 0&&c===N&&o.push(` ${c}`)}return o.join(`
14
- `)}function tt({isOpen:t,onClose:l,onResolve:a,conflicts:d,localNodeName:u,remoteNodeName:m,addToast:o}){const[j,g]=s.useState({}),[c,N]=s.useState(!1);s.useEffect(()=>{const n={};for(const v of d)j[v.key]||(n[v.key]={resolution:"local"});Object.keys(n).length>0&&g(v=>({...v,...n}))},[d,j]),s.useEffect(()=>{if(!t)return;const n=v=>{v.key==="Escape"&&(v.preventDefault(),l())};return document.addEventListener("keydown",n),()=>document.removeEventListener("keydown",n)},[t,l]);const w=s.useCallback((n,v)=>{g(C=>{const k=C[n]??{};return v==="manual"?{...C,[n]:{resolution:"manual",manualValue:k.manualValue??JSON.stringify(d.find(D=>D.key===n)?.localValue??null,null,2)}}:{...C,[n]:{resolution:v}}})},[d]),b=s.useCallback((n,v)=>{g(C=>({...C,[n]:{...C[n],resolution:"manual",manualValue:v}}))},[]),i=s.useCallback(n=>{const v={};for(const C of d)v[C.key]={resolution:n};g(v)},[d]),M=s.useCallback(async()=>{N(!0);try{const n=d.map(v=>{const C=j[v.key]??{resolution:"local"};let k;switch(C.resolution){case"remote":k=v.remoteValue;break;case"manual":try{k=JSON.parse(C.manualValue??"null")}catch{k=C.manualValue??null}break;case"local":default:k=v.localValue;break}return{key:v.key,value:k}});await a(n),o("Settings conflicts resolved successfully","success"),l()}catch(n){const v=n instanceof Error?n.message:"Failed to resolve conflicts";o(v,"error")}finally{N(!1)}},[o,d,l,a,j]),_=s.useMemo(()=>{const n={};for(const v of d)n[v.key]=st(v.localValue,v.remoteValue);return n},[d]);return!t||d.length===0?null:e.jsx("div",{className:"modal-overlay open",onClick:l,children:e.jsxs("div",{className:"modal modal-lg settings-sync-conflict-modal",onClick:n=>n.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Resolve Settings Conflicts",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Resolve Settings Conflicts"}),e.jsx("button",{className:"modal-close",onClick:l,"aria-label":"Close conflict modal",children:"×"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("div",{className:"settings-sync-conflict-modal__conflict-list",children:d.map(n=>{const v=j[n.key]??{resolution:"local"},C=_[n.key];return e.jsxs("div",{className:"settings-sync-conflict-modal__conflict-item",children:[e.jsx("div",{className:"settings-sync-conflict-modal__key",children:n.key}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-panel",children:[e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:u}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:C})})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:m}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:C})})]})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__resolution",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${n.key}`,checked:v.resolution==="local",onChange:()=>w(n.key,"local")}),"Keep Local"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${n.key}`,checked:v.resolution==="remote",onChange:()=>w(n.key,"remote")}),"Keep Remote"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${n.key}`,checked:v.resolution==="manual",onChange:()=>w(n.key,"manual")}),"Merge Manually"]})]}),v.resolution==="manual"&&e.jsx("textarea",{className:"settings-sync-conflict-modal__manual-input",value:v.manualValue??"",onChange:k=>b(n.key,k.target.value),placeholder:"Enter JSON value..."})]},n.key)})}),e.jsxs("div",{className:"settings-sync-conflict-modal__bulk-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:()=>i("local"),type:"button",children:"Resolve All: Keep Local"}),e.jsx("button",{className:"btn btn-sm",onClick:()=>i("remote"),type:"button",children:"Resolve All: Keep Remote"})]})]}),e.jsxs("div",{className:"modal-actions settings-sync-conflict-modal__footer",children:[e.jsx("button",{className:"btn btn-sm",onClick:l,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:M,disabled:c,children:c?"Resolving...":"Confirm"})]})]})})}const qe=/(KEY|TOKEN|SECRET|PASSWORD)/i;function ve(t){if(!t)return"—";const l=new Date(t);return Number.isNaN(l.getTime())?"—":l.toLocaleString()}function at(t){if(!t)return"—";const l=new Date(t),a=Date.now();if(Number.isNaN(l.getTime())||l.getTime()>a)return"—";const d=Math.floor((a-l.getTime())/1e3);if(d<60)return`${d}s`;const u=Math.floor(d/60);if(u<60)return`${u}m`;const m=Math.floor(u/60);return m<24?`${m}h ${u%60}m`:`${Math.floor(m/24)}d ${m%24}h`}function nt(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 rt(t){return t==="running"?"success":t==="creating"||t==="recreating"||t==="restarting"?"warning":"error"}function lt(t){return t?`${t.charAt(0).toUpperCase()}${t.slice(1)}`:"Unknown"}function ot(t){if(!t)return"—";try{const l=new URL(t);return l.port?l.port:l.protocol==="https:"?"443":l.protocol==="http:"?"80":"—"}catch{return"—"}}function ct(t,l){return qe.test(t)?"••••••••":l}function it({isOpen:t,onClose:l,node:a,projects:d,onUpdate:u,onHealthCheck:m,addToast:o,syncStatus:j,onPushSettings:g,onPullSettings:c,onSyncAuth:N,syncHistory:w=[],onResolveConflicts:b,managedDockerNode:i,containerStatus:M,onFetchContainerStatus:_,onFetchLogs:n,onUpdateDockerConfig:v,onFetchDockerConfigDiff:C}){const k=s.useRef(!0),[D,V]=s.useState(!1),[A,x]=s.useState(""),[p,S]=s.useState(""),[Z,H]=s.useState(""),[Y,ee]=s.useState(2),[U,X]=s.useState(!1),[G,te]=s.useState(!1),[J,T]=s.useState(!1),[E,y]=s.useState(!1),[L,$]=s.useState(null),[K,ae]=s.useState(!1),[ne]=s.useState([]),[se,le]=s.useState(M),[R,I]=s.useState(!1),[W,h]=s.useState(!1),[O,B]=s.useState(""),[q,oe]=s.useState(!1),[ge,Pe]=s.useState(!1),[f,F]=s.useState(a?.dockerConfig??null),[Ee,Re]=s.useState({}),[ie,Ae]=s.useState(!1),[Ye,Le]=s.useState(!1);s.useEffect(()=>(k.current=!0,()=>{k.current=!1}),[]),s.useEffect(()=>{le(M)},[M]),s.useEffect(()=>{if(!a||!t){V(!1),h(!1),B("");return}x(a.name),S(a.url??""),H(a.apiKey??""),ee(a.maxConcurrent),V(!1),F(a.dockerConfig??null),Pe(!1),Re({})},[t,a]),s.useEffect(()=>{if(!t)return;const r=P=>{P.key==="Escape"&&(P.preventDefault(),l())};return document.addEventListener("keydown",r),()=>document.removeEventListener("keydown",r)},[t,l]);const pe=s.useMemo(()=>a?gs(d,a):[],[a,d]),Xe=s.useMemo(()=>i?i.hostConfig.type==="remote"?i.hostConfig.host??"—":"Local Docker":"—",[i]),Je=s.useMemo(()=>!i?.resourceSizing?.cpuLimit&&!i?.resourceSizing?.memoryLimit?"Default":`${i.resourceSizing?.cpuLimit??"Default CPU"} / ${i.resourceSizing?.memoryLimit??"Default memory"}`,[i]),We=s.useCallback(async()=>{if(a)try{if(await m(a.id),!k.current)return;o(`Health check completed for ${a.name}`,"success")}catch(r){if(!k.current)return;const P=r instanceof Error?r.message:"Health check failed";o(P,"error")}},[o,a,m]),Ge=s.useCallback(async()=>{if(!(!a||!g)){$(null),te(!0);try{if(await g(a.id),!k.current)return;o("Settings pushed successfully","success")}catch(r){if(!k.current)return;const P=r instanceof Error?r.message:"Push settings failed";$(P),o(P,"error")}finally{k.current&&te(!1)}}},[o,a,g]),Ze=s.useCallback(async()=>{if(!(!a||!c)){$(null),T(!0);try{if(await c(a.id),!k.current)return;o("Settings pulled successfully","success")}catch(r){if(!k.current)return;const P=r instanceof Error?r.message:"Pull settings failed";$(P),o(P,"error")}finally{k.current&&T(!1)}}},[o,a,c]),Qe=s.useCallback(async()=>{if(!(!a||!N)){$(null),y(!0);try{if(await N(a.id),!k.current)return;o("Auth credentials synced successfully","success")}catch(r){if(!k.current)return;const P=r instanceof Error?r.message:"Auth sync failed";$(P),o(P,"error")}finally{k.current&&y(!1)}}},[o,a,N]),es=s.useCallback(()=>{$(null)},[]),ss=s.useCallback(async()=>{if(!(!i||!_)){I(!0);try{const r=await _(i.id);if(!k.current)return;le(r)}catch(r){const P=r instanceof Error?r.message:"Failed to fetch container status";o(P,"error")}finally{k.current&&I(!1)}}},[o,i,_]),ts=s.useCallback(async()=>{if(!(!i||!n)){h(!0),oe(!0);try{const r=await n(i.id);if(!k.current)return;B(r)}catch(r){if(!k.current)return;B("");const P=r instanceof Error?r.message:"Failed to fetch container logs";o(P,"error")}finally{k.current&&oe(!1)}}},[o,i,n]),as=s.useCallback(async()=>{if(!a||U)return;const r=A.trim();if(!r){o("Name is required","error");return}if(a.type==="remote"&&!p.trim()){o("URL is required for remote nodes","error");return}if(!Number.isFinite(Y)||Y<1){o("Concurrency must be at least 1","error");return}X(!0);try{await u(a.id,{name:r,url:a.type==="remote"&&p.trim()||void 0,apiKey:a.type==="remote"&&Z||void 0,maxConcurrent:Y}),o(`Updated ${r}`,"success"),V(!1)}catch(P){const Q=P instanceof Error?P.message:"Failed to update node";o(Q,"error")}finally{X(!1)}},[o,Z,U,Y,A,a,u,p]);s.useEffect(()=>{!a?.dockerConfig||!C||!t||C(a.id).then(r=>{k.current&&Le(r.needsRecreate)}).catch(()=>{k.current&&Le(!1)})},[t,a,C]);const ns=s.useCallback(async()=>{if(!(!a||!f||!v||ie)){Ae(!0);try{const r=await v(a.id,{image:f.image,volumeMounts:f.volumeMounts,environment:f.environment,resources:f.resources,host:f.host,extraClis:f.extraClis,persistence:f.persistence,containerName:f.containerName});if(!k.current)return;F(r),o("Docker config saved","success")}catch(r){if(!k.current)return;const P=r instanceof Error?r.message:"Failed to save Docker config";o(P,"error")}finally{k.current&&Ae(!1)}}},[o,f,ie,a,v]),rs=s.useCallback(()=>{a&&(x(a.name),S(a.url??""),H(a.apiKey??""),ee(a.maxConcurrent),V(!1))},[a]);if(!t||!a)return null;const re=se?.status??i?.status,ls=rt(re);return e.jsxs("div",{className:"modal-overlay open",onClick:l,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:l,"aria-label":"Close node detail modal",children:"×"})]}),e.jsxs("div",{className:"modal-body node-detail-modal__body",children:[e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("div",{className:"node-detail-modal__section-header",children:[e.jsx("h4",{children:"Overview"}),!D&&e.jsxs("button",{className:"btn btn-sm",onClick:()=>V(!0),children:[e.jsx(ps,{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"}),D?e.jsx("input",{className:"input",value:A,onChange:r=>x(r.target.value),disabled:U}):e.jsx("strong",{children:a.name})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Type"}),e.jsx("strong",{children:a.type==="local"?"Local":"Remote"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Status"}),e.jsx("strong",{children:a.status})]}),e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),D?e.jsx("input",{className:"input",type:"number",min:1,max:10,value:Y,onChange:r=>ee(Number(r.target.value)),disabled:U}):e.jsx("strong",{children:a.maxConcurrent})]}),a.type==="remote"&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"URL"}),D?e.jsx("input",{className:"input",value:p,onChange:r=>S(r.target.value),disabled:U}):e.jsx("strong",{children:a.url??"—"})]}),e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"API Key"}),D?e.jsx("input",{className:"input",type:"password",value:Z,onChange:r=>H(r.target.value),placeholder:"Leave blank to keep unchanged",disabled:U}):e.jsx("strong",{children:a.apiKey?"••••••••":"Not configured"})]})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Created"}),e.jsx("strong",{children:ve(a.createdAt)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Updated"}),e.jsx("strong",{children:ve(a.updatedAt)})]})]}),D&&e.jsxs("div",{className:"node-detail-modal__edit-actions",children:[e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:as,disabled:U,children:[e.jsx($e,{size:14}),U?"Saving...":"Save"]}),e.jsxs("button",{className:"btn btn-sm",onClick:rs,disabled:U,children:[e.jsx(me,{size:14}),"Cancel"]})]})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("h4",{children:[a.type==="local"?"Projects":"Assigned Projects"," (",pe.length,")"]}),pe.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:pe.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:ve(a.updatedAt)})]})]})]}),f&&e.jsxs("section",{className:"node-detail-modal__section node-detail-modal__docker-config",children:[e.jsxs("button",{className:"btn btn-sm node-detail-modal__docker-toggle",onClick:()=>Pe(r=>!r),"aria-expanded":ge,children:[e.jsx(Me,{size:14,className:ge?"node-detail-modal__docker-toggle-icon--expanded":""}),"Docker Configuration"]}),ge&&e.jsxs("div",{className:"node-detail-modal__docker-config-content",children:[e.jsx("div",{className:"node-detail-modal__grid",children:e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"Image"}),e.jsx("input",{className:"input",value:f.image,onChange:r=>F({...f,image:r.target.value})})]})}),e.jsxs("details",{children:[e.jsx("summary",{children:"Volume Mounts"}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[f.volumeMounts.map((r,P)=>e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:r.hostPath,placeholder:"Host path",onChange:Q=>{const z=[...f.volumeMounts];z[P]={...z[P],hostPath:Q.target.value},F({...f,volumeMounts:z})}}),e.jsx("input",{className:"input",value:r.containerPath,placeholder:"Container path",onChange:Q=>{const z=[...f.volumeMounts];z[P]={...z[P],containerPath:Q.target.value},F({...f,volumeMounts:z})}}),e.jsxs("select",{className:"input",value:r.mode??"rw",onChange:Q=>{const z=[...f.volumeMounts];z[P]={...z[P],mode:Q.target.value},F({...f,volumeMounts:z})},children:[e.jsx("option",{value:"rw",children:"rw"}),e.jsx("option",{value:"ro",children:"ro"})]}),e.jsxs("select",{className:"input",value:r.type??"volume",onChange:Q=>{const z=[...f.volumeMounts];z[P]={...z[P],type:Q.target.value},F({...f,volumeMounts:z})},children:[e.jsx("option",{value:"volume",children:"volume"}),e.jsx("option",{value:"bind",children:"bind"})]}),e.jsx("button",{className:"btn btn-sm",onClick:()=>F({...f,volumeMounts:f.volumeMounts.filter((Q,z)=>z!==P)}),children:"Remove"})]},`${r.hostPath}-${r.containerPath}-${P}`)),e.jsx("button",{className:"btn btn-sm",onClick:()=>F({...f,volumeMounts:[...f.volumeMounts,{hostPath:"",containerPath:"",mode:"rw",type:"volume"}]}),children:"Add Mount"})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Environment Variables"}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[Object.entries(f.environment).map(([r,P])=>{const Q=qe.test(r)&&!Ee[r];return e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:r,onChange:z=>{const xe={...f.environment};delete xe[r],xe[z.target.value]=P,F({...f,environment:xe})}}),e.jsx("input",{className:"input",value:Q?"***":String(P),onChange:z=>F({...f,environment:{...f.environment,[r]:z.target.value}})}),e.jsx("button",{className:"btn btn-sm",onClick:()=>Re(z=>({...z,[r]:!z[r]})),children:Ee[r]?e.jsx(xs,{size:14}):e.jsx(js,{size:14})}),e.jsx("button",{className:"btn btn-sm",onClick:()=>{const z={...f.environment};delete z[r],F({...f,environment:z})},children:"Remove"})]},r)}),e.jsx("button",{className:"btn btn-sm",onClick:()=>{const r=`NEW_VAR_${Object.keys(f.environment).length+1}`;F({...f,environment:{...f.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:f.resources?.memoryBytes??"",onChange:r=>F({...f,resources:{...f.resources,memoryBytes:r.target.value?Number(r.target.value):void 0}})}),e.jsx("input",{className:"input",type:"number",placeholder:"CPU count",value:f.resources?.cpuCount??"",onChange:r=>F({...f,resources:{...f.resources,cpuCount:r.target.value?Number(r.target.value):void 0}})}),e.jsx("input",{className:"input",type:"number",placeholder:"PIDs limit",value:f.resources?.pidsLimit??"",onChange:r=>F({...f,resources:{...f.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:f.host?.contextName??"",onChange:r=>F({...f,host:{...f.host,contextName:r.target.value}})}),e.jsx("input",{className:"input",placeholder:"Docker host URL",value:f.host?.dockerHost??"",onChange:r=>F({...f,host:{...f.host,dockerHost:r.target.value}})}),e.jsx("input",{className:"input",placeholder:"TLS CA cert path",value:f.host?.tlsCaCert??"",onChange:r=>F({...f,host:{...f.host,tlsCaCert:r.target.value}})}),e.jsx("input",{className:"input",placeholder:"TLS cert path",value:f.host?.tlsCert??"",onChange:r=>F({...f,host:{...f.host,tlsCert:r.target.value}})}),e.jsx("input",{className:"input",placeholder:"TLS key path",value:f.host?.tlsKey??"",onChange:r=>F({...f,host:{...f.host,tlsKey:r.target.value}})}),e.jsxs("label",{className:"node-detail-modal__checkbox",children:[e.jsx("input",{type:"checkbox",checked:f.host?.tlsVerify??!0,onChange:r=>F({...f,host:{...f.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:[(f.extraClis??[]).map((r,P)=>e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:r,onChange:Q=>{const z=[...f.extraClis??[]];z[P]=Q.target.value,F({...f,extraClis:z})}}),e.jsx("button",{className:"btn btn-sm",onClick:()=>F({...f,extraClis:(f.extraClis??[]).filter((Q,z)=>z!==P)}),children:"Remove"})]},`${r}-${P}`)),e.jsx("button",{className:"btn btn-sm",onClick:()=>F({...f,extraClis:[...f.extraClis??[],""]}),children:"Add CLI"})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Persistence"}),e.jsxs("div",{className:"node-detail-modal__docker-stack",children:[e.jsx("input",{className:"input",placeholder:"Volume name",value:f.persistence?.volumeName??"",onChange:r=>F({...f,persistence:{...f.persistence,volumeName:r.target.value}})}),e.jsxs("label",{className:"node-detail-modal__checkbox",children:[e.jsx("input",{type:"checkbox",checked:f.persistence?.retainOnDelete??!1,onChange:r=>F({...f,persistence:{...f.persistence,retainOnDelete:r.target.checked}})}),"Retain on delete"]})]})]}),e.jsxs("div",{className:"node-detail-modal__docker-meta",children:[e.jsxs("span",{children:["Config v",f.configVersion," • Updated ",Ce(f.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($e,{size:14}),ie?"Saving...":"Save Docker Config"]})]})]}),i&&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--${ls}`,"aria-hidden":!0}),e.jsx("strong",{children:lt(re)}),(re==="creating"||re==="recreating"||re==="restarting")&&e.jsx(Ie,{size:14,className:"spin","aria-hidden":!0})]}),e.jsxs("div",{className:"docker-management__status-meta",children:[re==="running"&&e.jsxs("span",{children:["Uptime: ",at(se?.startedAt)]}),re!=="running"&&se?.exitCode!==void 0&&e.jsxs("span",{children:["Exit code: ",se.exitCode]}),(se?.error||i.errorMessage)&&e.jsx("span",{children:se?.error??i.errorMessage})]}),e.jsx("button",{className:"btn btn-sm",onClick:()=>void ss(),disabled:!_||R,children:R?"Refreshing...":"Refresh Status"})]}),e.jsxs("div",{className:"node-detail-modal__grid docker-management__info-grid",children:[e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Image"}),e.jsx("strong",{children:e.jsxs("code",{children:[i.imageName,":",i.imageTag]})})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Container ID"}),e.jsx("strong",{children:e.jsx("code",{children:i.containerId?i.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:i.persistentStorage?"Yes":"No"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Port"}),e.jsx("strong",{children:ot(i.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(Ue,{size:14}),"Start"]}),e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:"Available after FN-3113",children:[e.jsx(Te,{size:14}),"Stop"]}),e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:"Available after FN-3113",children:[e.jsx(Ie,{size:14}),"Restart"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void ts(),disabled:!n,children:[e.jsx(bs,{size:14}),"View Logs"]})]}),W&&e.jsxs("div",{className:"docker-management__log-viewer",children:[e.jsxs("div",{className:"docker-management__log-viewer-header",children:[e.jsx("strong",{children:"Container Logs"}),e.jsx("button",{className:"btn-icon",onClick:()=>h(!1),"aria-label":"Close logs",children:e.jsx(me,{size:14})})]}),q?e.jsx("p",{children:"Fetching logs..."}):e.jsx("pre",{children:O.trim()||"No logs available"})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Environment Variables"}),e.jsx("dl",{className:"docker-management__env-list",children:Object.entries(i.envVars).map(([r,P])=>e.jsxs("div",{children:[e.jsx("dt",{children:r}),e.jsx("dd",{children:ct(r,P)})]},r))})]}),e.jsxs("details",{children:[e.jsx("summary",{children:"Volume Mounts"}),e.jsx("ul",{className:"docker-management__mounts-list",children:i.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"}),j&&e.jsxs("div",{className:"node-detail-modal__sync-status",children:[e.jsx("span",{className:`node-detail-modal__sync-dot ${nt(j.syncState)}`,"aria-hidden":!0}),e.jsxs("span",{children:["Last sync: ",e.jsx("strong",{children:j.lastSyncAt?Ce(j.lastSyncAt):"Never synced"})]}),j.diffCount>0&&e.jsxs("span",{className:"node-detail-modal__sync-diff",children:["Differences: ",e.jsx("strong",{children:j.diffCount})]})]}),e.jsxs("div",{className:"node-detail-modal__sync-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:Ge,disabled:G||!g,children:[e.jsx(He,{size:14}),G?"Pushing...":"Push Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:Ze,disabled:J||!c,children:[e.jsx(Be,{size:14}),J?"Pulling...":"Pull Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:Qe,disabled:E||!N,children:[e.jsx(Oe,{size:14}),E?"Syncing...":"Sync Auth"]})]}),L&&e.jsxs("div",{className:"node-detail-modal__sync-error",children:[e.jsx("span",{children:L}),e.jsx("button",{className:"node-detail-modal__sync-error-dismiss",onClick:es,"aria-label":"Dismiss error",children:e.jsx(me,{size:14})})]})]}),a.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Sync History"}),e.jsx(et,{nodeId:a.id,entries:w,singleNode:!0})]})]}),e.jsxs("div",{className:"modal-actions node-detail-modal__actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:We,children:[e.jsx(Ke,{size:14}),"Health Check"]}),e.jsx("button",{className:"btn btn-sm",onClick:l,children:"Close"})]})]}),a.type==="remote"&&e.jsx(tt,{isOpen:K,onClose:()=>ae(!1),onResolve:b??(async()=>{}),conflicts:ne,localNodeName:"Local",remoteNodeName:a.name,addToast:o})]})}const dt=15e3,ut=1e3;function mt(){const[t,l]=s.useState([]),[a,d]=s.useState(!0),[u,m]=s.useState(null),o=s.useRef(null),j=s.useRef(0),g=s.useCallback(async()=>{try{m(null);const b=await ze();l(b)}catch(b){m(b instanceof Error?b.message:"Failed to fetch managed Docker nodes")}},[]);s.useEffect(()=>{let b=!1;async function i(){d(!0);try{const _=await ze();b||(l(_),m(null))}catch(_){b||m(_ instanceof Error?_.message:"Failed to fetch managed Docker nodes")}finally{b||d(!1)}}i();const M=()=>{if(document.visibilityState!=="visible")return;const _=Date.now(),n=_-j.current;if(n<ut){he({view:"useManagedDockerNodes",trigger:"visibility",projectId:void 0,replayAttempted:!1,reason:"debounce-skipped",detail:{timeSinceLastRefreshMs:n}});return}j.current=_,he({view:"useManagedDockerNodes",trigger:"visibility",projectId:void 0,replayAttempted:!1,reason:"debounced-refresh"}),g()};return document.addEventListener("visibilitychange",M),()=>{b=!0,document.removeEventListener("visibilitychange",M)}},[g]),s.useEffect(()=>{if(!a)return o.current=setInterval(()=>{g()},dt),()=>{o.current&&(clearInterval(o.current),o.current=null)}},[a,g]);const c=s.useCallback(async b=>vs(b),[]),N=s.useCallback(async(b,i)=>(await ys(b,i)).logs,[]),w=s.useCallback(async b=>{const i=await _s(b),M={...i,nodeId:i.nodeId??void 0,containerId:i.containerId??void 0,status:i.status,hostConfig:{type:i.hostConfig.host||i.hostConfig.context?"remote":"local",host:i.hostConfig.host,context:i.hostConfig.context},reachableUrl:i.reachableUrl??void 0,volumeMounts:i.volumeMounts.map(_=>({hostPath:_.hostPath,containerPath:_.containerPath,readOnly:_.mode==="ro"?!0:void 0})),persistentStorage:i.persistentStorage,resourceSizing:{cpuLimit:i.resourceSizing.cpus!==void 0?String(i.resourceSizing.cpus):void 0,memoryLimit:i.resourceSizing.memoryMB!==void 0?`${i.resourceSizing.memoryMB}MB`:void 0},errorMessage:i.errorMessage??void 0};return l(_=>[..._,M]),M},[]);return{dockerNodes:t,loading:a,error:u,refresh:g,getContainerStatus:c,getLogs:N,create:w}}function bt({addToast:t,onClose:l}){const{nodes:a,loading:d,error:u,refresh:m,register:o,update:j,unregister:g,healthCheck:c,patchDockerConfig:N,fetchDockerDiff:w,discoverRemoteProjects:b}=Ns(),{projects:i,refresh:M}=ks(),{meshState:_,loading:n,error:v}=Is(),{syncStatusMap:C,pushSettings:k,pullSettings:D,syncAuth:V,trackNode:A,getAuthSyncState:x,getAuthProviders:p}=Ls(),{dockerNodes:S,loading:Z,refresh:H,getContainerStatus:Y,getLogs:ee,create:U}=mt(),[X,G]=s.useState(!1),[te,J]=s.useState(!1),[T,E]=s.useState(null);s.useEffect(()=>{const R=a.filter(I=>I.type==="remote");for(const I of R)A(I.id)},[a,A]),s.useEffect(()=>{if(!T)return;const R=a.find(I=>I.id===T.id)??null;E(R)},[a,T]);const y=s.useMemo(()=>{const R=a.length,I=a.filter(q=>q.status==="online").length,W=a.filter(q=>q.status==="offline"||q.status==="error").length,h=a.filter(q=>q.type==="remote").length,O=a.filter(q=>q.type==="remote"&&C[q.id]&&je(C[q.id]).syncState==="synced").length,B=S.length;return{total:R,online:I,offline:W,remote:h,synced:O,docker:B}},[S.length,a,C]),L=s.useCallback(async R=>{await o(R),await M()},[M,o]),$=s.useCallback(async R=>{try{await U(R),t(`Docker node "${R.name}" created`,"success"),J(!1)}catch(I){const W=I instanceof Error?I.message:"Failed to create Docker node";throw t(W,"error"),I}},[t,U]),K=s.useMemo(()=>{const R=new Map;for(const I of S)I.nodeId&&R.set(I.nodeId,I);return R},[S]),ae=s.useCallback(async()=>{try{await Promise.all([m(),H()])}catch{t("Failed to refresh nodes","error")}},[t,m,H]),ne=s.useCallback(async R=>{try{await c(R),t("Node health check complete","success")}catch(I){const W=I instanceof Error?I.message:"Health check failed";t(W,"error")}},[t,c]),se=s.useCallback(async R=>{try{await g(R),t("Node removed","success"),T?.id===R&&E(null)}catch(I){const W=I instanceof Error?I.message:"Failed to remove node";t(W,"error")}},[t,T?.id,g]),le=s.useCallback(async(R,I)=>{await j(R,I)},[j]);return e.jsxs("div",{className:"nodes-view","data-testid":"nodes-view",children:[e.jsxs("div",{className:"nodes-view-header",children:[e.jsxs("div",{className:"nodes-view-title",children:[e.jsxs("h2",{children:[e.jsx(Fe,{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:l,"aria-label":"Close nodes view",children:e.jsx(me,{size:16})}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void ae(),disabled:d||Z,children:[e.jsx(ke,{size:14,className:d?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>G(!0),children:[e.jsx(fe,{size:14}),"Add Node"]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>J(!0),title:"Add a managed Docker node",children:[e.jsx(_e,{size:14}),"Add Docker Node"]})]})]}),e.jsxs("div",{className:"nodes-view-stats",children:[e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-total",children:[e.jsx("span",{children:"Total"}),e.jsx("strong",{children:y.total})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--online","data-testid":"nodes-stat-online",children:[e.jsxs("span",{children:[e.jsx(Es,{size:14})," Online"]}),e.jsx("strong",{children:y.online})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--offline","data-testid":"nodes-stat-offline",children:[e.jsxs("span",{children:[e.jsx(Ms,{size:14})," Offline"]}),e.jsx("strong",{children:y.offline})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-remote",children:[e.jsxs("span",{children:[e.jsx(Cs,{size:14})," Remote"]}),e.jsx("strong",{children:y.remote})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--synced","data-testid":"nodes-stat-synced",children:[e.jsxs("span",{children:[e.jsx(ke,{size:14})," Synced"]}),e.jsx("strong",{children:y.synced})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-docker",children:[e.jsxs("span",{children:[e.jsx(_e,{size:14})," Docker"]}),e.jsx("strong",{children:y.docker})]})]}),(u||v)&&e.jsx("div",{className:"nodes-view-error",children:u??v}),!n&&_.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(Ys,{nodes:_})]}),d?e.jsx("div",{className:"nodes-view-grid",children:Array.from({length:4}).map((R,I)=>e.jsx("div",{className:"node-card node-card--loading","aria-hidden":!0},I))}):a.length===0?e.jsxs("div",{className:"nodes-view-empty",children:[e.jsx("p",{children:"No nodes are registered yet."}),e.jsxs("button",{className:"btn btn-primary",onClick:()=>G(!0),children:[e.jsx(fe,{size:14}),"Add First Node"]})]}):e.jsx("div",{className:"nodes-view-grid",children:a.map(R=>{const I=R.type==="remote"&&C[R.id]?je(C[R.id]):void 0;return e.jsx(Us,{node:R,projects:i,onHealthCheck:W=>{ne(W)},onEdit:W=>E(W),onRemove:W=>{se(W)},isLoading:d,syncStatus:I,authSyncState:R.type==="remote"?x(R.id):void 0,authSyncProviders:R.type==="remote"?p(R.id):void 0,managedDockerNode:K.get(R.id)},R.id)})}),e.jsx(Js,{isOpen:X,onClose:()=>G(!1),onSubmit:L,onDiscoverRemoteProjects:b,addToast:t,projects:i}),e.jsx(Qs,{isOpen:te,onClose:()=>J(!1),onSubmit:$,addToast:t}),e.jsx(it,{isOpen:T!==null,onClose:()=>E(null),node:T,projects:i,onUpdate:le,onHealthCheck:ne,addToast:t,syncStatus:T?.type==="remote"&&T&&C[T.id]?je(C[T.id]):void 0,onPushSettings:k,onPullSettings:D,onSyncAuth:V,managedDockerNode:T?K.get(T.id):void 0,onFetchContainerStatus:Y,onFetchLogs:ee,onUpdateDockerConfig:N,onFetchDockerConfigDiff:w})]})}export{bt as NodesView};