@runfusion/fusion 0.41.0 → 0.43.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 (86) hide show
  1. package/dist/bin.js +45728 -42714
  2. package/dist/client/.vite/manifest.json +76 -76
  3. package/dist/client/assets/AgentDetailView-DiWELtb1.css +1 -0
  4. package/dist/client/assets/AgentDetailView-FUKwQxBP.js +18 -0
  5. package/dist/client/assets/{AgentPermissionPolicyEditor-VDXL4XQc.js → AgentPermissionPolicyEditor-DMDUhF1n.js} +2 -2
  6. package/dist/client/assets/{AgentsView-ChXccELt.js → AgentsView-BrQLd-yI.js} +3 -3
  7. package/dist/client/assets/ChatView-Wz_0goif.js +6 -0
  8. package/dist/client/assets/{DevServerView-DGOahw1o.js → DevServerView-DRqQpHsc.js} +1 -1
  9. package/dist/client/assets/{DirectoryPicker-DgqHlxyh.js → DirectoryPicker-BFot4CVM.js} +1 -1
  10. package/dist/client/assets/{DocumentsView-CbbZwzbH.js → DocumentsView-hamhUcvL.js} +1 -1
  11. package/dist/client/assets/{EvalsView-BL_ue7fJ.js → EvalsView-DAXqDqn2.js} +1 -1
  12. package/dist/client/assets/{ExperimentalAgentOnboardingModal-8H4XAu4O.js → ExperimentalAgentOnboardingModal-B4aZ1y0n.js} +1 -1
  13. package/dist/client/assets/{GoalsView-CO4FVL3E.js → GoalsView-2QOp9DA0.js} +1 -1
  14. package/dist/client/assets/{InsightsView-C5vLvWVE.js → InsightsView-D5fzFy-F.js} +1 -1
  15. package/dist/client/assets/{MemoryView-BL3W3yOv.js → MemoryView-B082KoR-.js} +2 -2
  16. package/dist/client/assets/NodesView-BA3pKMZu.js +14 -0
  17. package/dist/client/assets/{PiExtensionsManager-HvSiVeDN.js → PiExtensionsManager-C4I11iKm.js} +2 -2
  18. package/dist/client/assets/{PluginManager-DIjrlhnU.js → PluginManager-BzTzTMXZ.js} +1 -1
  19. package/dist/client/assets/{PullRequestView-C2jQX8xZ.js → PullRequestView-11xJ565q.js} +2 -2
  20. package/dist/client/assets/{ReliabilityView-DbqEwoRs.js → ReliabilityView-CpELpGqw.js} +1 -1
  21. package/dist/client/assets/{ResearchView-C1QghmLI.js → ResearchView-BHiXfjzE.js} +1 -1
  22. package/dist/client/assets/{SecretsView-Y2MQ-9n5.js → SecretsView-CC5OYoCn.js} +1 -1
  23. package/dist/client/assets/SessionTerminal-G70Jwkzs.js +2 -0
  24. package/dist/client/assets/{SettingsModal-DabcZZ6S.js → SettingsModal-BKEbtdqR.js} +1 -1
  25. package/dist/client/assets/SettingsModal-C0M1CqOu.js +31 -0
  26. package/dist/client/assets/SettingsModal-DpAxDq6M.css +1 -0
  27. package/dist/client/assets/{SetupWizardModal-Db-Rxinm.js → SetupWizardModal-CBfItlP6.js} +1 -1
  28. package/dist/client/assets/{SkillsView-CIEY1-DE.js → SkillsView-DbcW87-E.js} +1 -1
  29. package/dist/client/assets/{StashRecoveryView-B6iDu5tI.js → StashRecoveryView-CH9RPtzX.js} +1 -1
  30. package/dist/client/assets/{TodoView-B8IK_BPM.js → TodoView-ToviJ0SV.js} +2 -2
  31. package/dist/client/assets/WorkflowNodeEditor-BTu0D9c5.js +8 -0
  32. package/dist/client/assets/WorkflowNodeEditor-BokhW3de.css +1 -0
  33. package/dist/client/assets/app-B2ZxMfJT.js +13 -0
  34. package/dist/client/assets/app-BffGU_HQ.js +13 -0
  35. package/dist/client/assets/app-C8AHhs5N.js +13 -0
  36. package/dist/client/assets/app-CUu1sm3x.js +13 -0
  37. package/dist/client/assets/app-Ri9Te2Dv.js +13 -0
  38. package/dist/client/assets/app-sEkTyT-w.js +13 -0
  39. package/dist/client/assets/{dashboard-view-O5j3PSGY.js → dashboard-view-C3SsjXo1.js} +1621 -1621
  40. package/dist/client/assets/{dashboard-view-Dn4CztR6.js → dashboard-view-DtgLZ_LM.js} +1 -1
  41. package/dist/client/assets/dashboard-view-Du53JbmQ.css +1 -0
  42. package/dist/client/assets/{folder-open-C9XAaduE.js → folder-open-BlPyIWyf.js} +1 -1
  43. package/dist/client/assets/index-DqhCiU35.css +1 -0
  44. package/dist/client/assets/index-bZCpHtGq.js +793 -0
  45. package/dist/client/assets/{upload-BRAEugYV.js → upload-B-qmm1NH.js} +1 -1
  46. package/dist/client/assets/{users-BlflbMZ3.js → users-D6C5TXf2.js} +1 -1
  47. package/dist/client/index.html +2 -2
  48. package/dist/client/version.json +1 -1
  49. package/dist/droid-cli/package.json +1 -1
  50. package/dist/extension.js +44655 -41906
  51. package/dist/pi-claude-cli/package.json +1 -1
  52. package/dist/plugin-sdk/index.d.ts +6258 -86
  53. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  54. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  55. package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +236 -26
  56. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  57. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  58. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  59. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  60. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  61. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  62. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  63. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  64. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  65. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  66. package/package.json +2 -9
  67. package/skill/fusion/references/extension-tools.md +3 -3
  68. package/skill/fusion/references/fusion-capabilities.md +2 -2
  69. package/dist/client/assets/AgentDetailView-CY-O6VkV.css +0 -1
  70. package/dist/client/assets/AgentDetailView-krC0B2O0.js +0 -18
  71. package/dist/client/assets/ChatView-Dz_xBKit.js +0 -6
  72. package/dist/client/assets/NodesView-DfBNNm9c.js +0 -14
  73. package/dist/client/assets/SessionTerminal-DaTXNT3A.js +0 -2
  74. package/dist/client/assets/SettingsModal-BAzm2kYd.js +0 -31
  75. package/dist/client/assets/SettingsModal-bJvc9aHl.css +0 -1
  76. package/dist/client/assets/WorkflowNodeEditor-DaPyvD_R.js +0 -8
  77. package/dist/client/assets/WorkflowNodeEditor-Po5uv_dN.css +0 -1
  78. package/dist/client/assets/app-CTRT_hQh.js +0 -13
  79. package/dist/client/assets/app-CVg6W-HU.js +0 -13
  80. package/dist/client/assets/app-CY3pQXOr.js +0 -13
  81. package/dist/client/assets/app-DNh04p5I.js +0 -13
  82. package/dist/client/assets/app-DhHgtB9j.js +0 -13
  83. package/dist/client/assets/app-NL_hPGDS.js +0 -13
  84. package/dist/client/assets/dashboard-view-BgiLoG1G.css +0 -1
  85. package/dist/client/assets/index-BHGM5W8a.css +0 -1
  86. package/dist/client/assets/index-CgfrecpF.js +0 -793
@@ -1,2 +1,2 @@
1
- import{r,j as e}from"./vendor-react-D37HfzIf.js";import{u as Ie}from"./SettingsModal-DabcZZ6S.js";import{bY as Ee,bZ as Me,b_ as Re,y as qe,b$ as Te,c0 as Pe,c1 as We,c2 as we,c3 as Ae,c4 as He,c5 as _e,c6 as Oe,c7 as Fe,c8 as Ue,x as Qe,c9 as $e,L as A,ca as De}from"./index-CgfrecpF.js";import{u as Be}from"./vendor-i18n-CV0mwX_-.js";import"./vendor-reactflow-CRZcPCXF.js";import"./vendor-xterm-tcedd2Jt.js";import"./vendor-codemirror-jBKmHyH0.js";const Q=".fusion/memory/MEMORY.md",Ye=5e4,Ve="0 3 * * *",Ge="0 4 * * *";function ue(i){return{memoryEnabled:i.memoryEnabled!==!1,memoryAutoSummarizeEnabled:i.memoryAutoSummarizeEnabled??!1,memoryAutoSummarizeThresholdChars:i.memoryAutoSummarizeThresholdChars??Ye,memoryAutoSummarizeSchedule:i.memoryAutoSummarizeSchedule??Ve,memoryDreamsEnabled:i.memoryDreamsEnabled??!1,memoryDreamsSchedule:i.memoryDreamsSchedule??Ge}}function ze(i,t){return i.some(s=>s.path===t)?t:i.find(s=>s.path===Q)?.path??i[0]?.path??Q}function Ze(i={}){const{projectId:t}=i,[s,h]=r.useState(""),[x,F]=r.useState(!0),[M,L]=r.useState(!1),[N,p]=r.useState(!1),[g,n]=r.useState(null),[D,T]=r.useState(!0),[ge,I]=r.useState(!1),[X,f]=r.useState(()=>ue({})),[J,w]=r.useState(!0),[be,ee]=r.useState(!1),[se,d]=r.useState([]),[z,R]=r.useState(!0),[S,l]=r.useState(Q),[P,C]=r.useState(""),[W,y]=r.useState(!1),[$,k]=r.useState(!1),[te,B]=r.useState(!1),[ae,Y]=r.useState(!1),[re,H]=r.useState(!1),[xe,j]=r.useState(null),[V,me]=r.useState(!0),[_,ne]=r.useState(!1),[ie,G]=r.useState(!1),[le,Z]=r.useState(null),{status:oe,loading:ce,refresh:O}=Ie({projectId:t}),b=r.useCallback(m=>{C(m),k(!0)},[]),U=r.useCallback(async m=>{y(!0);try{const{content:o}=await Ee(m,t);l(m),C(o),k(!1)}finally{y(!1)}},[t]),v=r.useCallback(async()=>{R(!0);try{const{files:m}=await Me(t);if(d(m),m.length===0){l(Q),C(""),k(!1);return}const o=ze(m,S);o!==S&&await U(o)}finally{R(!1)}},[t,S,U]);r.useEffect(()=>{let m=!1;async function o(){try{const c=await Ue(t);m||(h(c.content),F(!1))}catch{m||(h(""),F(!1))}}return o(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function o(){try{const c=await Ae(t);m||(n(c.content),I(c.exists),T(!1))}catch{m||(n(null),I(!1),T(!1))}}return o(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function o(){w(!0);try{const c=await Qe(t);m||f(ue(c))}catch{m||f(ue({}))}finally{m||w(!1)}}return o(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function o(){R(!0);try{const{files:c}=await Me(t);if(m)return;if(d(c),c.length===0){l(Q),C(""),k(!1);return}const a=ze(c,S),{content:u}=await Ee(a,t);if(m)return;l(a),C(u),k(!1)}catch{m||(d([]),l(Q),C(""),k(!1))}finally{m||R(!1)}}return o(),()=>{m=!0}},[t,S]),r.useEffect(()=>{let m=!1;async function o(){try{const c=await we(t);m||(j(c),me(!1))}catch{m||(j(null),me(!1))}}return o(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function o(){try{const c=await $e(t);m||Z(c)}catch{m||Z(null)}}return o(),()=>{m=!0}},[t]);const pe=r.useCallback(m=>{h(m),L(!0)},[]),de=r.useCallback(async()=>{if(M){p(!0);try{await Re(s,t),L(!1)}finally{p(!1)}}},[s,M,t]),ye=r.useCallback(async m=>{ee(!0);try{const o=await qe(m,t);f(ue(o))}finally{ee(!1)}},[t]),fe=r.useCallback(async m=>{await U(m)},[U]),Se=r.useCallback(async()=>{if($){B(!0);try{await Te(S,P,t),k(!1),await v()}finally{B(!1)}}},[P,$,S,t,v]),je=r.useCallback(async()=>{G(!0);try{const m=await Pe(t);return await O(),m}finally{G(!1)}},[t,O]),ve=r.useCallback(async m=>We(m,t),[t]),K=r.useCallback(async()=>{try{const m=await we(t);j(m)}catch{j(null)}},[t]),q=r.useCallback(async()=>{try{const m=await Ae(t);n(m.content),I(m.exists)}catch{n(null),I(!1)}},[t]),Ne=r.useCallback(async m=>{await He(m,t),await q()},[t,q]),he=r.useCallback(async()=>{Y(!0);try{const m=await _e(t);return await Promise.all([q(),K()]),{success:m.success,summary:m.summary}}finally{Y(!1)}},[t,q,K]),Ce=r.useCallback(async()=>{H(!0);try{return await Oe(t)}finally{H(!1)}},[t]),ke=r.useCallback(async m=>{ne(!0);try{const o=m?await Fe(m,t):await Fe(t);if(m){const c=o.path??m;l(c),C(o.content),k(!1),await v();return}h(o.content),L(!0)}finally{ne(!1)}},[t,v]);return{workingMemory:s,workingMemoryLoading:x,workingMemoryDirty:M,setWorkingMemory:pe,saveWorkingMemory:de,savingWorkingMemory:N,insightsContent:g,insightsLoading:D,insightsExists:ge,refreshInsights:q,saveInsights:Ne,memorySettings:X,settingsLoading:J,savingMemorySettings:be,saveMemorySettings:ye,memoryFiles:se,memoryFilesLoading:z,selectedFilePath:S,selectedFileContent:P,selectedFileLoading:W,selectedFileDirty:$,setSelectedFileContent:b,selectFile:fe,saveSelectedFile:Se,savingSelectedFile:te,reloadMemoryFiles:v,backendStatus:oe,backendLoading:ce,extractInsights:he,extracting:ae,triggerDreamNow:Ce,dreamRunning:re,auditReport:xe,auditLoading:V,refreshAudit:K,compactMemory:ke,compacting:_,installQmdAction:je,installingQmd:ie,testRetrieval:ve,stats:le}}const Ke={Patterns:"pattern",Principles:"principle",Conventions:"convention",Pitfalls:"pitfall",Context:"context"},Xe=72;function Je(i,t){if(i.length<=t)return i;const s=Math.max(1,t-1),h=Math.ceil(s/2),x=Math.floor(s/2);return`${i.slice(0,h)}…${i.slice(i.length-x)}`}function es(i){const t=`${i.label} — ${i.path}`;return Je(t,Xe)}function ss(i){if(!i)return[];const t=[],s=i.split(/(?=^## )/m);for(const h of s){const x=h.trim();if(!x)continue;const F=x.match(/^##\s+(.+?)(\n|$)/);if(F){const M=F[1].trim(),L=Ke[M]??M.toLowerCase(),N=x.slice(F[0].length).trim(),p=N.split(`
2
- `).map(g=>g.replace(/^-\s+/,"").trim()).filter(g=>g.length>0&&(g.startsWith("- ")||g.startsWith("* ")));(p.length>0||N.length>0)&&t.push({name:M,key:L,items:p.length>0?p:N.length>0?[N]:[],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,s)=>t+s.items.length,0)}function ds({projectId:i,addToast:t}){const{t:s}=Be("app"),[h,x]=r.useState("working"),[F,M]=r.useState(new Set),[L,N]=r.useState(!1),[p,g]=r.useState(null),[n,D]=r.useState({memoryEnabled:!0,memoryAutoSummarizeEnabled:!1,memoryAutoSummarizeThresholdChars:5e4,memoryAutoSummarizeSchedule:"0 3 * * *",memoryDreamsEnabled:!1,memoryDreamsSchedule:"0 4 * * *"}),[T,ge]=r.useState(""),[I,X]=r.useState(!1),[f,J]=r.useState(null),{insightsContent:w,insightsLoading:be,insightsExists:ee,saveInsights:se,memorySettings:d,settingsLoading:z,saveMemorySettings:R,savingMemorySettings:S,backendStatus:l,backendLoading:P,extractInsights:C,extracting:W,auditReport:y,auditLoading:$,refreshAudit:k,compactMemory:te,compacting:B,installQmdAction:ae,installingQmd:Y,testRetrieval:re,memoryFiles:H,memoryFilesLoading:xe,selectedFilePath:j,selectedFileContent:V,selectedFileLoading:me,selectedFileDirty:_,setSelectedFileContent:ne,selectFile:ie,saveSelectedFile:G,savingSelectedFile:le,reloadMemoryFiles:Z,triggerDreamNow:oe,dreamRunning:ce}=Ze({projectId:i});r.useEffect(()=>{D(d)},[d]);const O=r.useMemo(()=>n.memoryEnabled!==d.memoryEnabled||n.memoryAutoSummarizeEnabled!==d.memoryAutoSummarizeEnabled||n.memoryAutoSummarizeThresholdChars!==d.memoryAutoSummarizeThresholdChars||n.memoryAutoSummarizeSchedule!==d.memoryAutoSummarizeSchedule||n.memoryDreamsEnabled!==d.memoryDreamsEnabled||n.memoryDreamsSchedule!==d.memoryDreamsSchedule,[n,d]),b=r.useMemo(()=>H.find(a=>a.path===j),[H,j]),U=b?b.layer==="long-term"?s("memory.layerDescLongTerm","Curated durable decisions, conventions, constraints, and pitfalls promoted from dreams."):b.layer==="daily"?s("memory.layerDescDaily","Raw daily observations, open loops, and running context for dream processing."):s("memory.layerDescDreams","Synthesized patterns and open loops promoted from daily memory."):s("memory.editorDefaultDescription","Edits the selected memory file."),v=r.useMemo(()=>ss(w),[w]),pe=r.useMemo(()=>as(v),[v]),de=r.useMemo(()=>ts(w),[w]),ye=r.useCallback(a=>{M(u=>{const E=new Set(u);return E.has(a)?E.delete(a):E.add(a),E})},[]),fe=r.useCallback(async a=>{try{await ie(a)}catch{t(s("memory.loadFileFailed","Failed to load memory file"),"error")}},[ie,t]),Se=r.useCallback(async()=>{try{await G(),t(s("memory.memorySaved","Memory saved"),"success")}catch{t(s("memory.saveMemoryFailed","Failed to save memory"),"error")}},[G,t]),je=r.useCallback(async()=>{if(!O)return;const a={};n.memoryEnabled!==d.memoryEnabled&&(a.memoryEnabled=n.memoryEnabled),n.memoryAutoSummarizeEnabled!==d.memoryAutoSummarizeEnabled&&(a.memoryAutoSummarizeEnabled=n.memoryAutoSummarizeEnabled),n.memoryAutoSummarizeThresholdChars!==d.memoryAutoSummarizeThresholdChars&&(a.memoryAutoSummarizeThresholdChars=n.memoryAutoSummarizeThresholdChars),n.memoryAutoSummarizeSchedule!==d.memoryAutoSummarizeSchedule&&(a.memoryAutoSummarizeSchedule=n.memoryAutoSummarizeSchedule),n.memoryDreamsEnabled!==d.memoryDreamsEnabled&&(a.memoryDreamsEnabled=n.memoryDreamsEnabled),n.memoryDreamsSchedule!==d.memoryDreamsSchedule&&(a.memoryDreamsSchedule=n.memoryDreamsSchedule);try{await R(a),t(s("memory.settingsSaved","Memory settings saved"),"success")}catch{t(s("memory.saveSettingsFailed","Failed to save memory settings"),"error")}},[O,n,d,R,t]),ve=r.useCallback(async()=>{try{const a=await ae();t(a.qmdAvailable?s("memory.qmdInstallSuccess","qmd installed successfully"):s("memory.qmdInstallUnavailable","qmd install finished, but qmd is still unavailable"),a.qmdAvailable?"success":"info")}catch{t(s("memory.installQmdFailed","Failed to install qmd"),"error")}},[ae,t]),K=r.useCallback(async()=>{X(!0),J(null);try{const a=await re(T);J(a),t(a.qmdAvailable?s("memory.retrievalTestComplete","Memory retrieval test complete"):s("memory.retrievalTestFallback","qmd is not installed; local fallback was used"),a.qmdAvailable?"success":"info")}catch{t(s("memory.retrievalTestFailed","Failed to test memory retrieval"),"error")}finally{X(!1)}},[T,re,t]),q=r.useCallback(async()=>{try{await oe(),t(s("memory.dreamProcessingComplete","Dream processing completed"),"success"),await Z()}catch(a){t(a instanceof Error?a.message:s("memory.dreamProcessingFailed","Failed to run dream processing"),"error")}},[oe,Z,t]),Ne=r.useCallback(async()=>{try{await te(j),t(s("memory.fileCompacted","Memory file compacted"),"success")}catch{t(s("memory.compactFailed","Failed to compact memory"),"error")}},[te,j,t]),he=r.useCallback(async()=>{try{const a=await C();t(a.summary,"success")}catch(a){t(a instanceof Error?a.message:s("memory.extractInsightsFailed","Failed to extract insights"),"error")}},[C,t]),Ce=r.useCallback(async()=>{if(p!==null)try{await se(p),N(!1),g(null),t(s("memory.insightsSaved","Insights saved"),"success")}catch{t(s("memory.saveInsightsFailed","Failed to save insights"),"error")}},[p,se,t]),ke=r.useCallback(()=>{g(w??""),N(!0)},[w]),m=r.useCallback(()=>{N(!1),g(null)},[]),o=!P&&l!==null,c=l?.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:s("memory.title","Memory")}),e.jsx("p",{className:"memory-view-description",children:s("memory.description","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":h==="working",className:`memory-view-tab${h==="working"?" memory-view-tab--active":""}`,onClick:()=>x("working"),"data-testid":"memory-tab-working",children:s("memory.tabWorking","Working Memory")}),e.jsx("button",{type:"button",role:"tab","aria-selected":h==="insights",className:`memory-view-tab${h==="insights"?" memory-view-tab--active":""}`,onClick:()=>x("insights"),"data-testid":"memory-tab-insights",children:s("memory.tabInsights","Insights")}),e.jsx("button",{type:"button",role:"tab","aria-selected":h==="engines",className:`memory-view-tab${h==="engines"?" memory-view-tab--active":""}`,onClick:()=>x("engines"),"data-testid":"memory-tab-engines",children:s("memory.tabEngines","Engines")})]}),e.jsxs("div",{className:"memory-view-content",children:[h==="working"&&e.jsxs("div",{className:"memory-working-tab",children:[o&&!c&&e.jsx("div",{className:"memory-readonly-banner",children:s("memory.readOnlyBanner","This memory backend is read-only. Changes cannot be saved.")}),xe||me?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(A,{size:20,className:"animate-spin"}),e.jsx("span",{children:s("memory.loadingFile","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:s("memory.fileLabel","Memory File")}),e.jsx("select",{id:"memoryViewFilePath",className:"select",value:j,onChange:a=>{fe(a.target.value)},disabled:_,children:H.map(a=>e.jsx("option",{value:a.path,title:`${a.label} — ${a.path}`,children:es(a)},a.path))}),e.jsx("small",{children:_?s("memory.fileSwitchDirtyHint","Save or discard the current edits before switching files."):s("memory.fileSwitchHint","Choose any project memory file to view or edit.")})]}),b&&e.jsxs("div",{className:"memory-file-summary",children:[e.jsx("span",{children:b.layer==="long-term"?s("memory.layerLongTerm","Long-term"):b.layer==="daily"?s("memory.layerDaily","Daily"):s("memory.layerDreams","Dreams")}),e.jsx("strong",{children:b.path}),e.jsx("small",{children:s("memory.fileSummary","{{size}} bytes · updated {{updatedAt}}",{size:b.size.toLocaleString(),updatedAt:new Date(b.updatedAt).toLocaleString()})})]}),e.jsxs("div",{className:"form-group memory-editor-form-group",children:[e.jsx("label",{children:b?.label||s("memory.editorLabel","Memory Editor")}),e.jsx("small",{children:U}),e.jsx("div",{className:"memory-editor-container",children:e.jsx(De,{content:V,onChange:ne,readOnly:!c,filePath:j})})]})]}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsx("span",{className:"memory-char-count",children:s("memory.charCount","{{count}} characters",{count:V.length})}),e.jsx("div",{className:"memory-flex-spacer"}),c&&V.length>0&&e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:Ne,disabled:B||_,children:B?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.compacting","Compacting…")]}):s("memory.compactSelectedFile","Compact Selected File")}),_&&c&&e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:Se,disabled:le,children:le?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.saving","Saving…")]}):s("memory.save","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:n.memoryDreamsEnabled,onChange:a=>{D(u=>({...u,memoryDreamsEnabled:a.target.checked}))},disabled:!n.memoryEnabled||z}),s("memory.dreamsEnabledLabel","Process dreams from daily memory")]}),e.jsx("small",{children:s("memory.dreamsEnabledHint","Turns daily notes into DREAMS.md and promotes reusable lessons into MEMORY.md.")})]}),n.memoryEnabled&&n.memoryDreamsEnabled&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryDreamsSchedule",children:s("memory.dreamsScheduleLabel","Dream Schedule")}),e.jsx("input",{id:"memoryDreamsSchedule",type:"text",className:"input",value:n.memoryDreamsSchedule,onChange:a=>{D(u=>({...u,memoryDreamsSchedule:a.target.value}))},placeholder:"0 4 * * *",disabled:z}),e.jsx("small",{children:s("memory.dreamsScheduleHint","Cron expression for dream processing.")})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("button",{type:"button",className:"btn btn-sm",onClick:q,disabled:ce||!n.memoryDreamsEnabled,children:ce?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.dreaming","Dreaming…")]}):s("memory.dreamNow","Dream Now")}),e.jsx("small",{children:s("memory.dreamNowHint","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:n.memoryAutoSummarizeEnabled,onChange:a=>{D(u=>({...u,memoryAutoSummarizeEnabled:a.target.checked}))},disabled:!n.memoryEnabled||z}),s("memory.autoSummarizeLabel","Auto-Summarize Memory")]}),e.jsx("small",{children:s("memory.autoSummarizeHint","Automatically compact memory when it exceeds the threshold on a schedule")})]}),n.memoryEnabled&&n.memoryAutoSummarizeEnabled&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryAutoSummarizeThresholdChars",children:s("memory.compactionThresholdLabel","Compaction Threshold (chars)")}),e.jsx("input",{id:"memoryAutoSummarizeThresholdChars",type:"number",className:"input",value:n.memoryAutoSummarizeThresholdChars,onChange:a=>{D(u=>({...u,memoryAutoSummarizeThresholdChars:parseInt(a.target.value,10)||5e4}))},min:1e3,disabled:z}),e.jsx("small",{children:s("memory.compactionThresholdHint","Memory will be compacted when it exceeds this character count")})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryAutoSummarizeSchedule",children:s("memory.autoSummarizeScheduleLabel","Schedule (cron)")}),e.jsx("input",{id:"memoryAutoSummarizeSchedule",type:"text",className:"input",value:n.memoryAutoSummarizeSchedule,onChange:a=>{D(u=>({...u,memoryAutoSummarizeSchedule:a.target.value}))},placeholder:"0 3 * * *",disabled:z}),e.jsx("small",{children:s("memory.autoSummarizeScheduleHint","Cron expression for auto-summarize schedule (default: daily at 3 AM)")})]})]})]}),!n.memoryEnabled&&e.jsx("div",{className:"settings-empty-state memory-status-message",children:s("memory.disabledMessage","Memory is currently disabled. Enable memory tools in Settings to edit these automations.")}),O&&e.jsx("div",{className:"memory-action-bar",children:e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:je,disabled:S||z,children:S?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.saving","Saving…")]}):s("memory.saveSettings","Save Settings")})})]})]})]}),h==="insights"&&e.jsx("div",{className:"memory-insights-tab",children:be?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(A,{size:20,className:"animate-spin"}),e.jsx("span",{children:s("memory.loadingInsights","Loading insights…")})]}):L?e.jsxs("div",{className:"memory-insights-editor-layout",children:[e.jsx("div",{className:"memory-editor-container",children:e.jsx(De,{content:p??"",onChange:g,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:m,children:s("memory.cancel","Cancel")}),e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:Ce,children:s("memory.saveInsights","Save Insights")})]})]}):!ee||v.length===0?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx("p",{children:s("memory.noInsights","No insights extracted yet.")}),e.jsx("p",{children:s("memory.noInsightsHint",'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:he,disabled:W,children:W?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.extracting","Extracting…")]}):s("memory.extractNow","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:pe}),e.jsx("div",{className:"memory-stat-label",children:s("memory.totalInsights","Total Insights")})]}),e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value",children:v.length}),e.jsx("div",{className:"memory-stat-label",children:s("memory.categories","Categories")})]}),de&&e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value memory-stat-value--updated",children:de}),e.jsx("div",{className:"memory-stat-label",children:s("memory.lastUpdated","Last Updated")})]})]}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:he,disabled:W,children:W?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.extracting","Extracting…")]}):s("memory.extractNow","Extract Now")}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:ke,children:s("memory.editRaw","Edit Raw")})]}),e.jsx("div",{className:"memory-categories-list",children:v.map(a=>{const u=!F.has(a.key);return e.jsxs("div",{className:"memory-category-section",children:[e.jsxs("div",{className:"memory-category-header",onClick:()=>ye(a.key),role:"button",tabIndex:0,onKeyDown:E=>{(E.key==="Enter"||E.key===" ")&&(E.preventDefault(),ye(a.key))},children:[e.jsx("h4",{children:a.name}),e.jsx("span",{className:"memory-category-count",children:a.items.length})]}),u&&e.jsx("div",{className:"memory-category-items",children:a.items.map((E,Le)=>e.jsx("div",{className:"memory-insight-item",children:E.replace(/^-\s+/,"").replace(/^\*\s+/,"")},Le))})]},a.key)})})]})}),h==="engines"&&e.jsx("div",{className:"memory-engines-tab",children:P||$?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(A,{size:20,className:"animate-spin"}),e.jsx("span",{children:s("memory.loadingEngineStatus","Loading engine status…")})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"memory-engine-card memory-qmd-card",children:[e.jsx("h3",{children:s("memory.qmdIntegrationTitle","QMD Integration")}),l?.qmdAvailable===!0?e.jsxs("div",{className:"memory-engine-status",children:[e.jsx("span",{className:"memory-health-badge memory-health-badge--healthy",children:s("memory.qmdInstalled","Installed")}),e.jsx("span",{className:"memory-char-count",children:s("memory.qmdAvailableOnPath","qmd is available on PATH.")})]}):l?.qmdAvailable===!1?e.jsxs("div",{className:"settings-empty-state memory-status-message",children:[e.jsxs("span",{children:[s("memory.qmdNotInstalled","qmd is not installed. Search will use local files. Install indexed retrieval:")," ",e.jsx("code",{children:l.qmdInstallCommand||"bun install -g @tobilu/qmd"})]}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:ve,disabled:Y,children:Y?s("memory.installing","Installing…"):s("memory.installQmd","Install qmd")})]}):e.jsxs("div",{className:"memory-engine-status",children:[e.jsx("span",{className:"memory-health-badge",children:s("memory.qmdChecking","Checking")}),e.jsx("span",{className:"memory-char-count",children:s("memory.qmdCheckingAvailability","Checking qmd availability…")})]}),e.jsxs("div",{className:"memory-capability-row",children:[l?.capabilities?.readable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capReadable","Readable")}),l?.capabilities?.writable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capWritable","Writable")}),l?.capabilities?.supportsAtomicWrite&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capAtomicWrites","Atomic Writes")}),l?.capabilities?.persistent&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capPersistent","Persistent")})]})]}),e.jsxs("div",{className:"memory-engine-card memory-retrieval-card",children:[e.jsx("h3",{children:s("memory.testMemorySearchTitle","Test Memory Search")}),e.jsxs("div",{className:"memory-retrieval-input-row",children:[e.jsx("input",{type:"text",className:"input",value:T,onChange:a=>ge(a.target.value),placeholder:s("memory.searchPlaceholder","Search memory with qmd")}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:K,disabled:I,children:I?s("memory.testing","Testing…"):s("memory.testRetrieval","Test Retrieval")})]}),e.jsx("small",{className:"settings-muted",children:s("memory.testSearchHint","Runs the same qmd-backed memory_search path agents use.")}),f&&e.jsxs("div",{className:"memory-test-result",children:[e.jsx("strong",{children:s("memory.testResultCount",'{{count}} result for "{{query}}"',{count:f.results.length,query:f.query,defaultValue_one:'{{count}} result for "{{query}}"',defaultValue_other:'{{count}} results for "{{query}}"'})}),e.jsx("small",{children:s("memory.testResultStatus","qmd {{qmdStatus}} · {{fallbackStatus}}",{qmdStatus:f.qmdAvailable?s("memory.qmdStatusAvailable","available"):s("memory.qmdStatusMissing","missing"),fallbackStatus:f.usedFallback?s("memory.localFallbackUsed","local fallback used"):s("memory.qmdPathUsed","qmd path used")})}),f.results.length>0?e.jsx("ul",{children:f.results.map((a,u)=>e.jsxs("li",{children:[e.jsxs("span",{children:[a.path,":",a.lineStart]}),e.jsx("p",{children:a.snippet})]},`${a.path}-${a.lineStart}-${u}`))}):e.jsx("small",{children:s("memory.noMatchingMemory","No matching memory found.")})]})]}),e.jsxs("div",{className:"memory-engine-card",children:[e.jsx("h3",{children:s("memory.currentBackendTitle","Current Backend")}),e.jsx("div",{className:"memory-engine-status",children:e.jsx("span",{className:"memory-emphasis-text",children:l?.currentBackend==="file"?s("memory.backendFile","File (.fusion/memory/, agent/<agent-name>/memory/)"):l?.currentBackend==="readonly"?s("memory.backendReadonly","Read-Only"):l?.currentBackend==="qmd"?s("memory.backendQmd","QMD (Quantized Memory Distillation)"):l?.currentBackend??"unknown"})}),e.jsxs("div",{className:"memory-capability-row",children:[l?.capabilities?.readable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capReadable","Readable")}),l?.capabilities?.writable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capWritable","Writable")}),l?.capabilities?.supportsAtomicWrite&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capAtomicWrites","Atomic Writes")}),l?.capabilities?.persistent&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capPersistent","Persistent")})]})]}),y&&e.jsxs("div",{className:"memory-engine-card",children:[e.jsxs("div",{className:"memory-health-header",children:[e.jsx("h3",{children:s("memory.healthStatusTitle","Health Status")}),e.jsx("span",{className:`memory-health-badge memory-health-badge--${y.health}`,children:y.health==="healthy"?s("memory.healthHealthy","Healthy"):y.health==="warning"?s("memory.healthWarning","Warning"):s("memory.healthIssues","Issues Found")})]}),e.jsxs("div",{className:"memory-health-grid",children:[e.jsxs("div",{children:[e.jsx("div",{className:"memory-health-label",children:s("memory.workingMemoryLabel","Working Memory")}),e.jsx("div",{className:"memory-emphasis-text",children:s("memory.sizeChars","{{size}} chars",{size:y.workingMemory.size})}),e.jsx("div",{className:"memory-health-detail",children:s("memory.sectionCount","{{count}} sections",{count:y.workingMemory.sectionCount})})]}),e.jsxs("div",{children:[e.jsx("div",{className:"memory-health-label",children:s("memory.insightsMemoryLabel","Insights Memory")}),e.jsx("div",{className:"memory-emphasis-text",children:s("memory.sizeChars","{{size}} chars",{size:y.insightsMemory.size})}),e.jsx("div",{className:"memory-health-detail",children:s("memory.insightCount","{{count}} insights",{count:y.insightsMemory.insightCount})})]})]}),e.jsxs("div",{className:"memory-health-section",children:[e.jsx("div",{className:"memory-health-label",children:s("memory.lastExtractionLabel","Last Extraction")}),e.jsx("div",{className:"memory-emphasis-text",children:y.extraction.success?e.jsx("span",{className:"memory-status-text memory-status-text--success",children:s("memory.extractionSuccess","Success")}):e.jsx("span",{className:"memory-status-text memory-status-text--error",children:s("memory.extractionFailed","Failed")})}),e.jsx("div",{className:"memory-health-detail",children:y.extraction.summary||s("memory.insightsExtracted","{{count}} insights extracted",{count:y.extraction.insightCount})})]}),e.jsxs("div",{className:"memory-health-section",children:[e.jsx("div",{className:"memory-health-label",children:s("memory.pruningLabel","Pruning")}),e.jsx("div",{className:"memory-emphasis-text",children:y.pruning.applied?e.jsx("span",{className:"memory-status-text memory-status-text--warning",children:s("memory.pruningApplied","Applied")}):e.jsx("span",{className:"memory-status-text memory-status-text--muted",children:s("memory.pruningNotNeeded","Not needed")})}),y.pruning.applied&&e.jsx("div",{className:"memory-health-detail",children:y.pruning.reason})]})]}),y&&y.checks.length>0&&e.jsxs("div",{className:"memory-engine-card",children:[e.jsx("h3",{children:s("memory.auditChecksTitle","Audit Checks")}),e.jsx("div",{children:y.checks.map(a=>e.jsxs("div",{className:"memory-audit-check",children:[e.jsx("span",{className:a.passed?"memory-audit-check-passed":"memory-audit-check-failed",children:a.passed?"✓":"✗"}),e.jsxs("div",{className:"memory-audit-check-content",children:[e.jsx("div",{className:"memory-emphasis-text",children:a.name}),e.jsx("div",{className:"memory-health-detail",children:a.details})]})]},a.id))})]}),e.jsx("div",{className:"memory-action-bar",children:e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:()=>k(),children:s("memory.runAudit","Run Audit")})}),e.jsxs("div",{className:"memory-settings-note",children:[e.jsx("span",{children:s("memory.settingsNote","Note: Change backend type in")}),e.jsx("button",{type:"button",className:"memory-settings-note-button",onClick:()=>{t(s("memory.settingsNoteToast","Open Settings → Memory to change backend type"),"info")},children:s("memory.settingsNoteLink","Settings → Memory")})]})]})})]})]})}export{ds as MemoryView};
1
+ import{r,j as e}from"./vendor-react-D37HfzIf.js";import{u as Ie}from"./SettingsModal-BKEbtdqR.js";import{bZ as Ee,b_ as Me,b$ as Re,y as qe,c0 as Te,c1 as Pe,c2 as We,c3 as we,c4 as Ae,c5 as He,c6 as _e,c7 as Oe,c8 as Fe,c9 as Ue,x as Qe,ca as $e,L as A,cb as De}from"./index-bZCpHtGq.js";import{u as Be}from"./vendor-i18n-CV0mwX_-.js";import"./vendor-reactflow-CRZcPCXF.js";import"./vendor-xterm-tcedd2Jt.js";import"./vendor-codemirror-jBKmHyH0.js";const Q=".fusion/memory/MEMORY.md",Ve=5e4,Ye="0 3 * * *",Ge="0 4 * * *";function ue(i){return{memoryEnabled:i.memoryEnabled!==!1,memoryAutoSummarizeEnabled:i.memoryAutoSummarizeEnabled??!1,memoryAutoSummarizeThresholdChars:i.memoryAutoSummarizeThresholdChars??Ve,memoryAutoSummarizeSchedule:i.memoryAutoSummarizeSchedule??Ye,memoryDreamsEnabled:i.memoryDreamsEnabled??!1,memoryDreamsSchedule:i.memoryDreamsSchedule??Ge}}function ze(i,t){return i.some(s=>s.path===t)?t:i.find(s=>s.path===Q)?.path??i[0]?.path??Q}function Ze(i={}){const{projectId:t}=i,[s,h]=r.useState(""),[x,F]=r.useState(!0),[M,L]=r.useState(!1),[N,p]=r.useState(!1),[g,n]=r.useState(null),[D,T]=r.useState(!0),[ge,I]=r.useState(!1),[X,f]=r.useState(()=>ue({})),[J,w]=r.useState(!0),[be,ee]=r.useState(!1),[se,d]=r.useState([]),[z,R]=r.useState(!0),[S,l]=r.useState(Q),[P,C]=r.useState(""),[W,y]=r.useState(!1),[$,k]=r.useState(!1),[te,B]=r.useState(!1),[ae,V]=r.useState(!1),[re,H]=r.useState(!1),[xe,j]=r.useState(null),[Y,me]=r.useState(!0),[_,ne]=r.useState(!1),[ie,G]=r.useState(!1),[le,Z]=r.useState(null),{status:oe,loading:ce,refresh:O}=Ie({projectId:t}),b=r.useCallback(m=>{C(m),k(!0)},[]),U=r.useCallback(async m=>{y(!0);try{const{content:o}=await Ee(m,t);l(m),C(o),k(!1)}finally{y(!1)}},[t]),v=r.useCallback(async()=>{R(!0);try{const{files:m}=await Me(t);if(d(m),m.length===0){l(Q),C(""),k(!1);return}const o=ze(m,S);o!==S&&await U(o)}finally{R(!1)}},[t,S,U]);r.useEffect(()=>{let m=!1;async function o(){try{const c=await Ue(t);m||(h(c.content),F(!1))}catch{m||(h(""),F(!1))}}return o(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function o(){try{const c=await Ae(t);m||(n(c.content),I(c.exists),T(!1))}catch{m||(n(null),I(!1),T(!1))}}return o(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function o(){w(!0);try{const c=await Qe(t);m||f(ue(c))}catch{m||f(ue({}))}finally{m||w(!1)}}return o(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function o(){R(!0);try{const{files:c}=await Me(t);if(m)return;if(d(c),c.length===0){l(Q),C(""),k(!1);return}const a=ze(c,S),{content:u}=await Ee(a,t);if(m)return;l(a),C(u),k(!1)}catch{m||(d([]),l(Q),C(""),k(!1))}finally{m||R(!1)}}return o(),()=>{m=!0}},[t,S]),r.useEffect(()=>{let m=!1;async function o(){try{const c=await we(t);m||(j(c),me(!1))}catch{m||(j(null),me(!1))}}return o(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function o(){try{const c=await $e(t);m||Z(c)}catch{m||Z(null)}}return o(),()=>{m=!0}},[t]);const pe=r.useCallback(m=>{h(m),L(!0)},[]),de=r.useCallback(async()=>{if(M){p(!0);try{await Re(s,t),L(!1)}finally{p(!1)}}},[s,M,t]),ye=r.useCallback(async m=>{ee(!0);try{const o=await qe(m,t);f(ue(o))}finally{ee(!1)}},[t]),fe=r.useCallback(async m=>{await U(m)},[U]),Se=r.useCallback(async()=>{if($){B(!0);try{await Te(S,P,t),k(!1),await v()}finally{B(!1)}}},[P,$,S,t,v]),je=r.useCallback(async()=>{G(!0);try{const m=await Pe(t);return await O(),m}finally{G(!1)}},[t,O]),ve=r.useCallback(async m=>We(m,t),[t]),K=r.useCallback(async()=>{try{const m=await we(t);j(m)}catch{j(null)}},[t]),q=r.useCallback(async()=>{try{const m=await Ae(t);n(m.content),I(m.exists)}catch{n(null),I(!1)}},[t]),Ne=r.useCallback(async m=>{await He(m,t),await q()},[t,q]),he=r.useCallback(async()=>{V(!0);try{const m=await _e(t);return await Promise.all([q(),K()]),{success:m.success,summary:m.summary}}finally{V(!1)}},[t,q,K]),Ce=r.useCallback(async()=>{H(!0);try{return await Oe(t)}finally{H(!1)}},[t]),ke=r.useCallback(async m=>{ne(!0);try{const o=m?await Fe(m,t):await Fe(t);if(m){const c=o.path??m;l(c),C(o.content),k(!1),await v();return}h(o.content),L(!0)}finally{ne(!1)}},[t,v]);return{workingMemory:s,workingMemoryLoading:x,workingMemoryDirty:M,setWorkingMemory:pe,saveWorkingMemory:de,savingWorkingMemory:N,insightsContent:g,insightsLoading:D,insightsExists:ge,refreshInsights:q,saveInsights:Ne,memorySettings:X,settingsLoading:J,savingMemorySettings:be,saveMemorySettings:ye,memoryFiles:se,memoryFilesLoading:z,selectedFilePath:S,selectedFileContent:P,selectedFileLoading:W,selectedFileDirty:$,setSelectedFileContent:b,selectFile:fe,saveSelectedFile:Se,savingSelectedFile:te,reloadMemoryFiles:v,backendStatus:oe,backendLoading:ce,extractInsights:he,extracting:ae,triggerDreamNow:Ce,dreamRunning:re,auditReport:xe,auditLoading:Y,refreshAudit:K,compactMemory:ke,compacting:_,installQmdAction:je,installingQmd:ie,testRetrieval:ve,stats:le}}const Ke={Patterns:"pattern",Principles:"principle",Conventions:"convention",Pitfalls:"pitfall",Context:"context"},Xe=72;function Je(i,t){if(i.length<=t)return i;const s=Math.max(1,t-1),h=Math.ceil(s/2),x=Math.floor(s/2);return`${i.slice(0,h)}…${i.slice(i.length-x)}`}function es(i){const t=`${i.label} — ${i.path}`;return Je(t,Xe)}function ss(i){if(!i)return[];const t=[],s=i.split(/(?=^## )/m);for(const h of s){const x=h.trim();if(!x)continue;const F=x.match(/^##\s+(.+?)(\n|$)/);if(F){const M=F[1].trim(),L=Ke[M]??M.toLowerCase(),N=x.slice(F[0].length).trim(),p=N.split(`
2
+ `).map(g=>g.replace(/^-\s+/,"").trim()).filter(g=>g.length>0&&(g.startsWith("- ")||g.startsWith("* ")));(p.length>0||N.length>0)&&t.push({name:M,key:L,items:p.length>0?p:N.length>0?[N]:[],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,s)=>t+s.items.length,0)}function ds({projectId:i,addToast:t}){const{t:s}=Be("app"),[h,x]=r.useState("working"),[F,M]=r.useState(new Set),[L,N]=r.useState(!1),[p,g]=r.useState(null),[n,D]=r.useState({memoryEnabled:!0,memoryAutoSummarizeEnabled:!1,memoryAutoSummarizeThresholdChars:5e4,memoryAutoSummarizeSchedule:"0 3 * * *",memoryDreamsEnabled:!1,memoryDreamsSchedule:"0 4 * * *"}),[T,ge]=r.useState(""),[I,X]=r.useState(!1),[f,J]=r.useState(null),{insightsContent:w,insightsLoading:be,insightsExists:ee,saveInsights:se,memorySettings:d,settingsLoading:z,saveMemorySettings:R,savingMemorySettings:S,backendStatus:l,backendLoading:P,extractInsights:C,extracting:W,auditReport:y,auditLoading:$,refreshAudit:k,compactMemory:te,compacting:B,installQmdAction:ae,installingQmd:V,testRetrieval:re,memoryFiles:H,memoryFilesLoading:xe,selectedFilePath:j,selectedFileContent:Y,selectedFileLoading:me,selectedFileDirty:_,setSelectedFileContent:ne,selectFile:ie,saveSelectedFile:G,savingSelectedFile:le,reloadMemoryFiles:Z,triggerDreamNow:oe,dreamRunning:ce}=Ze({projectId:i});r.useEffect(()=>{D(d)},[d]);const O=r.useMemo(()=>n.memoryEnabled!==d.memoryEnabled||n.memoryAutoSummarizeEnabled!==d.memoryAutoSummarizeEnabled||n.memoryAutoSummarizeThresholdChars!==d.memoryAutoSummarizeThresholdChars||n.memoryAutoSummarizeSchedule!==d.memoryAutoSummarizeSchedule||n.memoryDreamsEnabled!==d.memoryDreamsEnabled||n.memoryDreamsSchedule!==d.memoryDreamsSchedule,[n,d]),b=r.useMemo(()=>H.find(a=>a.path===j),[H,j]),U=b?b.layer==="long-term"?s("memory.layerDescLongTerm","Curated durable decisions, conventions, constraints, and pitfalls promoted from dreams."):b.layer==="daily"?s("memory.layerDescDaily","Raw daily observations, open loops, and running context for dream processing."):s("memory.layerDescDreams","Synthesized patterns and open loops promoted from daily memory."):s("memory.editorDefaultDescription","Edits the selected memory file."),v=r.useMemo(()=>ss(w),[w]),pe=r.useMemo(()=>as(v),[v]),de=r.useMemo(()=>ts(w),[w]),ye=r.useCallback(a=>{M(u=>{const E=new Set(u);return E.has(a)?E.delete(a):E.add(a),E})},[]),fe=r.useCallback(async a=>{try{await ie(a)}catch{t(s("memory.loadFileFailed","Failed to load memory file"),"error")}},[ie,t]),Se=r.useCallback(async()=>{try{await G(),t(s("memory.memorySaved","Memory saved"),"success")}catch{t(s("memory.saveMemoryFailed","Failed to save memory"),"error")}},[G,t]),je=r.useCallback(async()=>{if(!O)return;const a={};n.memoryEnabled!==d.memoryEnabled&&(a.memoryEnabled=n.memoryEnabled),n.memoryAutoSummarizeEnabled!==d.memoryAutoSummarizeEnabled&&(a.memoryAutoSummarizeEnabled=n.memoryAutoSummarizeEnabled),n.memoryAutoSummarizeThresholdChars!==d.memoryAutoSummarizeThresholdChars&&(a.memoryAutoSummarizeThresholdChars=n.memoryAutoSummarizeThresholdChars),n.memoryAutoSummarizeSchedule!==d.memoryAutoSummarizeSchedule&&(a.memoryAutoSummarizeSchedule=n.memoryAutoSummarizeSchedule),n.memoryDreamsEnabled!==d.memoryDreamsEnabled&&(a.memoryDreamsEnabled=n.memoryDreamsEnabled),n.memoryDreamsSchedule!==d.memoryDreamsSchedule&&(a.memoryDreamsSchedule=n.memoryDreamsSchedule);try{await R(a),t(s("memory.settingsSaved","Memory settings saved"),"success")}catch{t(s("memory.saveSettingsFailed","Failed to save memory settings"),"error")}},[O,n,d,R,t]),ve=r.useCallback(async()=>{try{const a=await ae();t(a.qmdAvailable?s("memory.qmdInstallSuccess","qmd installed successfully"):s("memory.qmdInstallUnavailable","qmd install finished, but qmd is still unavailable"),a.qmdAvailable?"success":"info")}catch{t(s("memory.installQmdFailed","Failed to install qmd"),"error")}},[ae,t]),K=r.useCallback(async()=>{X(!0),J(null);try{const a=await re(T);J(a),t(a.qmdAvailable?s("memory.retrievalTestComplete","Memory retrieval test complete"):s("memory.retrievalTestFallback","qmd is not installed; local fallback was used"),a.qmdAvailable?"success":"info")}catch{t(s("memory.retrievalTestFailed","Failed to test memory retrieval"),"error")}finally{X(!1)}},[T,re,t]),q=r.useCallback(async()=>{try{await oe(),t(s("memory.dreamProcessingComplete","Dream processing completed"),"success"),await Z()}catch(a){t(a instanceof Error?a.message:s("memory.dreamProcessingFailed","Failed to run dream processing"),"error")}},[oe,Z,t]),Ne=r.useCallback(async()=>{try{await te(j),t(s("memory.fileCompacted","Memory file compacted"),"success")}catch{t(s("memory.compactFailed","Failed to compact memory"),"error")}},[te,j,t]),he=r.useCallback(async()=>{try{const a=await C();t(a.summary,"success")}catch(a){t(a instanceof Error?a.message:s("memory.extractInsightsFailed","Failed to extract insights"),"error")}},[C,t]),Ce=r.useCallback(async()=>{if(p!==null)try{await se(p),N(!1),g(null),t(s("memory.insightsSaved","Insights saved"),"success")}catch{t(s("memory.saveInsightsFailed","Failed to save insights"),"error")}},[p,se,t]),ke=r.useCallback(()=>{g(w??""),N(!0)},[w]),m=r.useCallback(()=>{N(!1),g(null)},[]),o=!P&&l!==null,c=l?.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:s("memory.title","Memory")}),e.jsx("p",{className:"memory-view-description",children:s("memory.description","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":h==="working",className:`memory-view-tab${h==="working"?" memory-view-tab--active":""}`,onClick:()=>x("working"),"data-testid":"memory-tab-working",children:s("memory.tabWorking","Working Memory")}),e.jsx("button",{type:"button",role:"tab","aria-selected":h==="insights",className:`memory-view-tab${h==="insights"?" memory-view-tab--active":""}`,onClick:()=>x("insights"),"data-testid":"memory-tab-insights",children:s("memory.tabInsights","Insights")}),e.jsx("button",{type:"button",role:"tab","aria-selected":h==="engines",className:`memory-view-tab${h==="engines"?" memory-view-tab--active":""}`,onClick:()=>x("engines"),"data-testid":"memory-tab-engines",children:s("memory.tabEngines","Engines")})]}),e.jsxs("div",{className:"memory-view-content",children:[h==="working"&&e.jsxs("div",{className:"memory-working-tab",children:[o&&!c&&e.jsx("div",{className:"memory-readonly-banner",children:s("memory.readOnlyBanner","This memory backend is read-only. Changes cannot be saved.")}),xe||me?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(A,{size:20,className:"animate-spin"}),e.jsx("span",{children:s("memory.loadingFile","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:s("memory.fileLabel","Memory File")}),e.jsx("select",{id:"memoryViewFilePath",className:"select",value:j,onChange:a=>{fe(a.target.value)},disabled:_,children:H.map(a=>e.jsx("option",{value:a.path,title:`${a.label} — ${a.path}`,children:es(a)},a.path))}),e.jsx("small",{children:_?s("memory.fileSwitchDirtyHint","Save or discard the current edits before switching files."):s("memory.fileSwitchHint","Choose any project memory file to view or edit.")})]}),b&&e.jsxs("div",{className:"memory-file-summary",children:[e.jsx("span",{children:b.layer==="long-term"?s("memory.layerLongTerm","Long-term"):b.layer==="daily"?s("memory.layerDaily","Daily"):s("memory.layerDreams","Dreams")}),e.jsx("strong",{children:b.path}),e.jsx("small",{children:s("memory.fileSummary","{{size}} bytes · updated {{updatedAt}}",{size:b.size.toLocaleString(),updatedAt:new Date(b.updatedAt).toLocaleString()})})]}),e.jsxs("div",{className:"form-group memory-editor-form-group",children:[e.jsx("label",{children:b?.label||s("memory.editorLabel","Memory Editor")}),e.jsx("small",{children:U}),e.jsx("div",{className:"memory-editor-container",children:e.jsx(De,{content:Y,onChange:ne,readOnly:!c,filePath:j})})]})]}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsx("span",{className:"memory-char-count",children:s("memory.charCount","{{count}} characters",{count:Y.length})}),e.jsx("div",{className:"memory-flex-spacer"}),c&&Y.length>0&&e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:Ne,disabled:B||_,children:B?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.compacting","Compacting…")]}):s("memory.compactSelectedFile","Compact Selected File")}),_&&c&&e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:Se,disabled:le,children:le?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.saving","Saving…")]}):s("memory.save","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:n.memoryDreamsEnabled,onChange:a=>{D(u=>({...u,memoryDreamsEnabled:a.target.checked}))},disabled:!n.memoryEnabled||z}),s("memory.dreamsEnabledLabel","Process dreams from daily memory")]}),e.jsx("small",{children:s("memory.dreamsEnabledHint","Turns daily notes into DREAMS.md and promotes reusable lessons into MEMORY.md.")})]}),n.memoryEnabled&&n.memoryDreamsEnabled&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryDreamsSchedule",children:s("memory.dreamsScheduleLabel","Dream Schedule")}),e.jsx("input",{id:"memoryDreamsSchedule",type:"text",className:"input",value:n.memoryDreamsSchedule,onChange:a=>{D(u=>({...u,memoryDreamsSchedule:a.target.value}))},placeholder:"0 4 * * *",disabled:z}),e.jsx("small",{children:s("memory.dreamsScheduleHint","Cron expression for dream processing.")})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("button",{type:"button",className:"btn btn-sm",onClick:q,disabled:ce||!n.memoryDreamsEnabled,children:ce?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.dreaming","Dreaming…")]}):s("memory.dreamNow","Dream Now")}),e.jsx("small",{children:s("memory.dreamNowHint","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:n.memoryAutoSummarizeEnabled,onChange:a=>{D(u=>({...u,memoryAutoSummarizeEnabled:a.target.checked}))},disabled:!n.memoryEnabled||z}),s("memory.autoSummarizeLabel","Auto-Summarize Memory")]}),e.jsx("small",{children:s("memory.autoSummarizeHint","Automatically compact memory when it exceeds the threshold on a schedule")})]}),n.memoryEnabled&&n.memoryAutoSummarizeEnabled&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryAutoSummarizeThresholdChars",children:s("memory.compactionThresholdLabel","Compaction Threshold (chars)")}),e.jsx("input",{id:"memoryAutoSummarizeThresholdChars",type:"number",className:"input",value:n.memoryAutoSummarizeThresholdChars,onChange:a=>{D(u=>({...u,memoryAutoSummarizeThresholdChars:parseInt(a.target.value,10)||5e4}))},min:1e3,disabled:z}),e.jsx("small",{children:s("memory.compactionThresholdHint","Memory will be compacted when it exceeds this character count")})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryAutoSummarizeSchedule",children:s("memory.autoSummarizeScheduleLabel","Schedule (cron)")}),e.jsx("input",{id:"memoryAutoSummarizeSchedule",type:"text",className:"input",value:n.memoryAutoSummarizeSchedule,onChange:a=>{D(u=>({...u,memoryAutoSummarizeSchedule:a.target.value}))},placeholder:"0 3 * * *",disabled:z}),e.jsx("small",{children:s("memory.autoSummarizeScheduleHint","Cron expression for auto-summarize schedule (default: daily at 3 AM)")})]})]})]}),!n.memoryEnabled&&e.jsx("div",{className:"settings-empty-state memory-status-message",children:s("memory.disabledMessage","Memory is currently disabled. Enable memory tools in Settings to edit these automations.")}),O&&e.jsx("div",{className:"memory-action-bar",children:e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:je,disabled:S||z,children:S?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.saving","Saving…")]}):s("memory.saveSettings","Save Settings")})})]})]})]}),h==="insights"&&e.jsx("div",{className:"memory-insights-tab",children:be?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(A,{size:20,className:"animate-spin"}),e.jsx("span",{children:s("memory.loadingInsights","Loading insights…")})]}):L?e.jsxs("div",{className:"memory-insights-editor-layout",children:[e.jsx("div",{className:"memory-editor-container",children:e.jsx(De,{content:p??"",onChange:g,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:m,children:s("memory.cancel","Cancel")}),e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:Ce,children:s("memory.saveInsights","Save Insights")})]})]}):!ee||v.length===0?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx("p",{children:s("memory.noInsights","No insights extracted yet.")}),e.jsx("p",{children:s("memory.noInsightsHint",'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:he,disabled:W,children:W?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.extracting","Extracting…")]}):s("memory.extractNow","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:pe}),e.jsx("div",{className:"memory-stat-label",children:s("memory.totalInsights","Total Insights")})]}),e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value",children:v.length}),e.jsx("div",{className:"memory-stat-label",children:s("memory.categories","Categories")})]}),de&&e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value memory-stat-value--updated",children:de}),e.jsx("div",{className:"memory-stat-label",children:s("memory.lastUpdated","Last Updated")})]})]}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:he,disabled:W,children:W?e.jsxs(e.Fragment,{children:[e.jsx(A,{size:14,className:"animate-spin"}),s("memory.extracting","Extracting…")]}):s("memory.extractNow","Extract Now")}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:ke,children:s("memory.editRaw","Edit Raw")})]}),e.jsx("div",{className:"memory-categories-list",children:v.map(a=>{const u=!F.has(a.key);return e.jsxs("div",{className:"memory-category-section",children:[e.jsxs("div",{className:"memory-category-header",onClick:()=>ye(a.key),role:"button",tabIndex:0,onKeyDown:E=>{(E.key==="Enter"||E.key===" ")&&(E.preventDefault(),ye(a.key))},children:[e.jsx("h4",{children:a.name}),e.jsx("span",{className:"memory-category-count",children:a.items.length})]}),u&&e.jsx("div",{className:"memory-category-items",children:a.items.map((E,Le)=>e.jsx("div",{className:"memory-insight-item",children:E.replace(/^-\s+/,"").replace(/^\*\s+/,"")},Le))})]},a.key)})})]})}),h==="engines"&&e.jsx("div",{className:"memory-engines-tab",children:P||$?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(A,{size:20,className:"animate-spin"}),e.jsx("span",{children:s("memory.loadingEngineStatus","Loading engine status…")})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"memory-engine-card memory-qmd-card",children:[e.jsx("h3",{children:s("memory.qmdIntegrationTitle","QMD Integration")}),l?.qmdAvailable===!0?e.jsxs("div",{className:"memory-engine-status",children:[e.jsx("span",{className:"memory-health-badge memory-health-badge--healthy",children:s("memory.qmdInstalled","Installed")}),e.jsx("span",{className:"memory-char-count",children:s("memory.qmdAvailableOnPath","qmd is available on PATH.")})]}):l?.qmdAvailable===!1?e.jsxs("div",{className:"settings-empty-state memory-status-message",children:[e.jsxs("span",{children:[s("memory.qmdNotInstalled","qmd is not installed. Search will use local files. Install indexed retrieval:")," ",e.jsx("code",{children:l.qmdInstallCommand||"bun install -g @tobilu/qmd"})]}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:ve,disabled:V,children:V?s("memory.installing","Installing…"):s("memory.installQmd","Install qmd")})]}):e.jsxs("div",{className:"memory-engine-status",children:[e.jsx("span",{className:"memory-health-badge",children:s("memory.qmdChecking","Checking")}),e.jsx("span",{className:"memory-char-count",children:s("memory.qmdCheckingAvailability","Checking qmd availability…")})]}),e.jsxs("div",{className:"memory-capability-row",children:[l?.capabilities?.readable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capReadable","Readable")}),l?.capabilities?.writable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capWritable","Writable")}),l?.capabilities?.supportsAtomicWrite&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capAtomicWrites","Atomic Writes")}),l?.capabilities?.persistent&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capPersistent","Persistent")})]})]}),e.jsxs("div",{className:"memory-engine-card memory-retrieval-card",children:[e.jsx("h3",{children:s("memory.testMemorySearchTitle","Test Memory Search")}),e.jsxs("div",{className:"memory-retrieval-input-row",children:[e.jsx("input",{type:"text",className:"input",value:T,onChange:a=>ge(a.target.value),placeholder:s("memory.searchPlaceholder","Search memory with qmd")}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:K,disabled:I,children:I?s("memory.testing","Testing…"):s("memory.testRetrieval","Test Retrieval")})]}),e.jsx("small",{className:"settings-muted",children:s("memory.testSearchHint","Runs the same qmd-backed memory_search path agents use.")}),f&&e.jsxs("div",{className:"memory-test-result",children:[e.jsx("strong",{children:s("memory.testResultCount",'{{count}} result for "{{query}}"',{count:f.results.length,query:f.query,defaultValue_one:'{{count}} result for "{{query}}"',defaultValue_other:'{{count}} results for "{{query}}"'})}),e.jsx("small",{children:s("memory.testResultStatus","qmd {{qmdStatus}} · {{fallbackStatus}}",{qmdStatus:f.qmdAvailable?s("memory.qmdStatusAvailable","available"):s("memory.qmdStatusMissing","missing"),fallbackStatus:f.usedFallback?s("memory.localFallbackUsed","local fallback used"):s("memory.qmdPathUsed","qmd path used")})}),f.results.length>0?e.jsx("ul",{children:f.results.map((a,u)=>e.jsxs("li",{children:[e.jsxs("span",{children:[a.path,":",a.lineStart]}),e.jsx("p",{children:a.snippet})]},`${a.path}-${a.lineStart}-${u}`))}):e.jsx("small",{children:s("memory.noMatchingMemory","No matching memory found.")})]})]}),e.jsxs("div",{className:"memory-engine-card",children:[e.jsx("h3",{children:s("memory.currentBackendTitle","Current Backend")}),e.jsx("div",{className:"memory-engine-status",children:e.jsx("span",{className:"memory-emphasis-text",children:l?.currentBackend==="file"?s("memory.backendFile","File (.fusion/memory/, agent/<agent-name>/memory/)"):l?.currentBackend==="readonly"?s("memory.backendReadonly","Read-Only"):l?.currentBackend==="qmd"?s("memory.backendQmd","QMD (Quantized Memory Distillation)"):l?.currentBackend??"unknown"})}),e.jsxs("div",{className:"memory-capability-row",children:[l?.capabilities?.readable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capReadable","Readable")}),l?.capabilities?.writable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capWritable","Writable")}),l?.capabilities?.supportsAtomicWrite&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capAtomicWrites","Atomic Writes")}),l?.capabilities?.persistent&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capPersistent","Persistent")})]})]}),y&&e.jsxs("div",{className:"memory-engine-card",children:[e.jsxs("div",{className:"memory-health-header",children:[e.jsx("h3",{children:s("memory.healthStatusTitle","Health Status")}),e.jsx("span",{className:`memory-health-badge memory-health-badge--${y.health}`,children:y.health==="healthy"?s("memory.healthHealthy","Healthy"):y.health==="warning"?s("memory.healthWarning","Warning"):s("memory.healthIssues","Issues Found")})]}),e.jsxs("div",{className:"memory-health-grid",children:[e.jsxs("div",{children:[e.jsx("div",{className:"memory-health-label",children:s("memory.workingMemoryLabel","Working Memory")}),e.jsx("div",{className:"memory-emphasis-text",children:s("memory.sizeChars","{{size}} chars",{size:y.workingMemory.size})}),e.jsx("div",{className:"memory-health-detail",children:s("memory.sectionCount","{{count}} sections",{count:y.workingMemory.sectionCount})})]}),e.jsxs("div",{children:[e.jsx("div",{className:"memory-health-label",children:s("memory.insightsMemoryLabel","Insights Memory")}),e.jsx("div",{className:"memory-emphasis-text",children:s("memory.sizeChars","{{size}} chars",{size:y.insightsMemory.size})}),e.jsx("div",{className:"memory-health-detail",children:s("memory.insightCount","{{count}} insights",{count:y.insightsMemory.insightCount})})]})]}),e.jsxs("div",{className:"memory-health-section",children:[e.jsx("div",{className:"memory-health-label",children:s("memory.lastExtractionLabel","Last Extraction")}),e.jsx("div",{className:"memory-emphasis-text",children:y.extraction.success?e.jsx("span",{className:"memory-status-text memory-status-text--success",children:s("memory.extractionSuccess","Success")}):e.jsx("span",{className:"memory-status-text memory-status-text--error",children:s("memory.extractionFailed","Failed")})}),e.jsx("div",{className:"memory-health-detail",children:y.extraction.summary||s("memory.insightsExtracted","{{count}} insights extracted",{count:y.extraction.insightCount})})]}),e.jsxs("div",{className:"memory-health-section",children:[e.jsx("div",{className:"memory-health-label",children:s("memory.pruningLabel","Pruning")}),e.jsx("div",{className:"memory-emphasis-text",children:y.pruning.applied?e.jsx("span",{className:"memory-status-text memory-status-text--warning",children:s("memory.pruningApplied","Applied")}):e.jsx("span",{className:"memory-status-text memory-status-text--muted",children:s("memory.pruningNotNeeded","Not needed")})}),y.pruning.applied&&e.jsx("div",{className:"memory-health-detail",children:y.pruning.reason})]})]}),y&&y.checks.length>0&&e.jsxs("div",{className:"memory-engine-card",children:[e.jsx("h3",{children:s("memory.auditChecksTitle","Audit Checks")}),e.jsx("div",{children:y.checks.map(a=>e.jsxs("div",{className:"memory-audit-check",children:[e.jsx("span",{className:a.passed?"memory-audit-check-passed":"memory-audit-check-failed",children:a.passed?"✓":"✗"}),e.jsxs("div",{className:"memory-audit-check-content",children:[e.jsx("div",{className:"memory-emphasis-text",children:a.name}),e.jsx("div",{className:"memory-health-detail",children:a.details})]})]},a.id))})]}),e.jsx("div",{className:"memory-action-bar",children:e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:()=>k(),children:s("memory.runAudit","Run Audit")})}),e.jsxs("div",{className:"memory-settings-note",children:[e.jsx("span",{children:s("memory.settingsNote","Note: Change backend type in")}),e.jsx("button",{type:"button",className:"memory-settings-note-button",onClick:()=>{t(s("memory.settingsNoteToast","Open Settings → Memory to change backend type"),"info")},children:s("memory.settingsNoteLink","Settings → Memory")})]})]})})]})]})}export{ds as MemoryView};
@@ -0,0 +1,14 @@
1
+ import{r as s,j as e}from"./vendor-react-D37HfzIf.js";import{c as ze,aS as ds,aT as us,aU as ms,aV as hs,aW as Ke,aX as Ue,aY as Ie,aG as fe,aZ as ke,a_ as Oe,a$ as _e,b0 as Be,A as Te,ax as fs,Q as He,b1 as qe,b2 as gs,U as Ne,u as ps,R as Ce,a as we,J as ge,b3 as Ye,b4 as xs,b5 as vs,b6 as bs,b7 as Fe,X as he,ae as ys,af as js,b8 as Ve,F as ks,b9 as $e,ba as _s,bb as Ns,bc as Cs,bd as Ss,be as Ms,G as Ps}from"./index-bZCpHtGq.js";import{u as ne}from"./vendor-i18n-CV0mwX_-.js";import{v as ws}from"./projectDetection-G3XuxD2X.js";import{U as Xe}from"./upload-B-qmm1NH.js";import"./vendor-reactflow-CRZcPCXF.js";import"./vendor-xterm-tcedd2Jt.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 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"}]],Es=ze("wifi-off",Rs);/**
7
+ * @license lucide-react v1.7.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const Ls=[["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"}]],As=ze("wifi",Ls);function be(t){const{lastSyncAt:i,remoteReachable:a,diff:c}=t,r=Object.values(c.workflowSettings??{}).reduce((o,g)=>o+g.length,0),m=c.global.length+c.project.length+r;return i===null?{syncState:"never-synced",lastSyncAt:i,diffCount:0}:a?m>0?{syncState:"diff",lastSyncAt:i,diffCount:m}:{syncState:"synced",lastSyncAt:i,diffCount:0}:{syncState:"error",lastSyncAt:i,diffCount:m}}function Se(t){if(t===null)return"Never synced";const i=new Date(t);if(Number.isNaN(i.getTime()))return"Never synced";const c=Date.now()-i.getTime(),r=Math.floor(c/1e3),m=Math.floor(r/60),o=Math.floor(m/60),g=Math.floor(o/24);return m<1?"Synced just now":m<60?`Synced ${m}m ago`:o<24?`Synced ${o}h ago`:`Synced ${g}d ago`}function Ds(t){switch(t){case"synced":return"var(--color-success)";case"pending":return"var(--color-warning)";case"diff":return"var(--color-warning)";case"error":return"var(--color-error)";case"never-synced":return"var(--text-muted)"}}const Is=3e4;function Fs(){const{t}=ne("app"),[i,a]=s.useState({}),[c,r]=s.useState(!1),[m,o]=s.useState({}),[g,N]=s.useState(null),h=s.useRef(new Set),u=s.useRef(!1),C=s.useRef(null),S=s.useRef(null),f=s.useCallback(async(k,p)=>{try{const w=await ds(k);a(Q=>({...Q,[k]:w})),N(null)}catch(w){console.error(`Failed to fetch sync status for node ${k}:`,w),N(w instanceof Error?w.message:t("nodeSync.error.failedToFetchStatus","Failed to fetch sync status"))}},[t]),P=s.useCallback(async()=>{const k=Array.from(h.current);if(k.length===0)return;C.current&&C.current.abort(),C.current=new AbortController;const p=!u.current;p&&r(!0),N(null);try{const w=await Promise.allSettled(k.map(q=>f(q,p)));u.current=!0,w.filter(q=>q.status==="rejected").length>0&&N(t("nodeSync.error.someRequestsFailed","Some sync status requests failed"))}catch(w){if(w instanceof Error&&w.name==="AbortError")return;N(w instanceof Error?w.message:t("nodeSync.error.failedToFetchStatus","Failed to fetch sync status")),u.current=!0}finally{r(!1)}},[f,t]),j=s.useCallback(()=>{S.current&&clearInterval(S.current),S.current=setInterval(()=>{P()},Is)},[P]),b=s.useCallback(()=>{S.current&&(clearInterval(S.current),S.current=null)},[]);s.useEffect(()=>(P(),j(),()=>{b(),C.current&&C.current.abort()}),[P,j,b]);const l=s.useCallback(k=>{h.current.has(k)||(h.current.add(k),f(k,!u.current))},[f]),y=s.useCallback(k=>{h.current.delete(k),a(p=>{const w={...p};return delete w[k],w}),h.current.size===0&&b()},[b]),n=s.useCallback(async k=>{o(p=>({...p,[k]:!0})),N(null);try{const p=await us(k);return f(k,!1),!p.success&&p.error&&N(p.error),p}catch(p){const w=p instanceof Error?p.message:t("nodeSync.error.pushFailed","Push settings failed");throw N(w),p}finally{o(p=>{const w={...p};return delete w[k],w})}},[f,t]),M=s.useCallback(async k=>{o(p=>({...p,[k]:!0})),N(null);try{const p=await ms(k);return f(k,!1),!p.success&&p.error&&N(p.error),p}catch(p){const w=p instanceof Error?p.message:t("nodeSync.error.pullFailed","Pull settings failed");throw N(w),p}finally{o(p=>{const w={...p};return delete w[k],w})}},[f,t]),I=s.useCallback(async k=>{o(p=>({...p,[k]:!0})),N(null);try{return await hs(k)}catch(p){const w=p instanceof Error?p.message:t("nodeSync.error.authSyncFailed","Auth sync failed");throw N(w),p}finally{o(p=>{const w={...p};return delete w[k],w})}},[t]),O=s.useCallback(k=>i[k]?.authMatch,[i]),R=s.useCallback(k=>i[k]?.authDiff,[i]);return{syncStatusMap:i,loading:c,actionLoading:m,error:g,refresh:P,trackNode:l,untrackNode:y,pushSettings:n,pullSettings:M,syncAuth:I,getAuthSyncState:O,getAuthProviders:R}}const Vs=1e4,$s=1e3;function zs(){const{t}=ne("app"),[i,a]=s.useState([]),[c,r]=s.useState(!0),[m,o]=s.useState(null),g=s.useRef(null),N=s.useRef(0),h=s.useRef(i),u=Ke();s.useEffect(()=>{h.current=i},[i]);const C=s.useCallback(f=>h.current.length>0&&Ue(f,u.wasRecentlyHidden()),[u]),S=s.useCallback(async()=>{try{o(null);const f=await Ie();a(f.nodes)}catch(f){const P=f instanceof Error?f.message:t("mesh.failedToFetchMeshState","Failed to fetch mesh state");C(P)||o(P)}},[C,t]);return s.useEffect(()=>{let f=!1;async function P(){r(!0);try{const b=await Ie();f||(a(b.nodes),o(null))}catch(b){const l=b instanceof Error?b.message:t("mesh.failedToFetchMeshState","Failed to fetch mesh state");!f&&!C(l)&&o(l)}finally{f||r(!1)}}P();const j=()=>{if(document.visibilityState!=="visible")return;const b=Date.now(),l=b-N.current;if(l<$s){fe({view:"useMeshState",trigger:"visibility",projectId:void 0,replayAttempted:!1,reason:"debounce-skipped",detail:{timeSinceLastRefreshMs:l}});return}N.current=b,fe({view:"useMeshState",trigger:"visibility",projectId:void 0,replayAttempted:!1,reason:"debounced-refresh"}),S()};return document.addEventListener("visibilitychange",j),()=>{f=!0,document.removeEventListener("visibilitychange",j)}},[S,C,t]),s.useEffect(()=>{if(!c)return g.current=setInterval(()=>{S()},Vs),()=>{g.current&&(clearInterval(g.current),g.current=null)}},[c,S]),{meshState:i,loading:c,error:m,refresh:S}}function Ks(t){return{online:{label:t("nodes.status.online","Online"),color:"var(--color-success)",className:"node-card__status--online"},offline:{label:t("nodes.status.offline","Offline"),color:"var(--color-error)",className:"node-card__status--offline"},connecting:{label:t("nodes.status.connecting","Connecting"),color:"var(--color-warning)",className:"node-card__status--connecting"},error:{label:t("nodes.status.error","Error"),color:"var(--color-error)",className:"node-card__status--error"},creating:{label:t("nodes.status.creating","Creating"),color:"var(--color-warning)",className:"node-card__status--creating"},recreating:{label:t("nodes.status.recreating","Recreating"),color:"var(--color-warning)",className:"node-card__status--recreating"},deleting:{label:t("nodes.status.deleting","Deleting"),color:"var(--color-error)",className:"node-card__status--deleting"},running:{label:t("nodes.status.running","Running"),color:"var(--color-success)",className:"node-card__status--online"},stopped:{label:t("nodes.status.stopped","Stopped"),color:"var(--color-error)",className:"node-card__status--offline"},exited:{label:t("nodes.status.exited","Exited"),color:"var(--color-error)",className:"node-card__status--offline"}}}const Us={match:"var(--color-success)",differs:"var(--color-warning)","not-synced":"var(--text-muted)"};function Os(t,i,a){if(t==="match")return a?a("nodes.auth.match","Auth credentials match"):"Auth credentials match";if(t==="not-synced")return a?a("nodes.auth.notSynced","Auth not synced"):"Auth not synced";if(i&&Object.keys(i).length>0){const c=Object.entries(i).filter(([,r])=>r==="differs").map(([r])=>r);if(c.length>0)return a?a("nodes.auth.differProviders","Auth credentials differ: {{providers}}",{providers:c.join(", ")}):`Auth credentials differ: ${c.join(", ")}`}return a?a("nodes.auth.differ","Auth credentials differ"):"Auth credentials differ"}function Bs(t,i=42){return t.length<=i?t:`${t.slice(0,i-3)}...`}function Ts(t,i){const a=t.node,c=i.node;if(a.id!==c.id||a.name!==c.name||a.type!==c.type||a.url!==c.url||a.status!==c.status||a.maxConcurrent!==c.maxConcurrent||a.updatedAt!==c.updatedAt||t.isLoading!==i.isLoading)return!1;const r=t.managedDockerNode,m=i.managedDockerNode;if(!!r!=!!m||r&&m&&(r.id!==m.id||r.status!==m.status||r.imageTag!==m.imageTag||r.updatedAt!==m.updatedAt))return!1;const o=t.syncStatus,g=i.syncStatus;if(!(!o&&!g)){if(!o||!g)return!1;if(o.syncState!==g.syncState||o.lastSyncAt!==g.lastSyncAt||o.diffCount!==g.diffCount)return!1}if(t.authSyncState!==i.authSyncState)return!1;const N=t.authSyncProviders,h=i.authSyncProviders;if(N!==h){if(!N||!h)return!1;{const S=Object.keys(N),f=Object.keys(h);if(S.length!==f.length||S.some(P=>N[P]!==h[P]))return!1}}const u=ke(t.projects,a),C=ke(i.projects,c);return u===C}function Hs({node:t,projects:i,onHealthCheck:a,onEdit:c,onRemove:r,isLoading:m=!1,syncStatus:o,authSyncState:g,authSyncProviders:N,managedDockerNode:h}){const{t:u}=ne("app"),[C,S]=s.useState(!1),f=Ks(u),P=f[t.status]??f.offline,j=h?f[h.status]??f.error:null,b=h?.hostConfig.type==="remote"?u("nodes.dockerHost.remote","Remote: {{host}}",{host:h.hostConfig.host??"unknown"}):u("nodes.dockerHost.local","Local Docker"),l=s.useMemo(()=>ke(i,t),[i,t]),y=s.useCallback(()=>{c(t)},[c,t]),n=s.useCallback(R=>{R.stopPropagation(),a(t.id)},[a,t.id]),M=s.useCallback(R=>{R.stopPropagation(),c(t)},[c,t]),I=s.useCallback(R=>{if(R.stopPropagation(),!C){S(!0);return}r(t.id),S(!1)},[C,r,t.id]),O=s.useCallback(R=>{(R.key==="Enter"||R.key===" ")&&(R.preventDefault(),c(t))},[c,t]);return e.jsxs("article",{className:`node-card ${m?"node-card--loading":""}`,"data-node-id":t.id,role:"button",tabIndex:0,onClick:y,onKeyDown:O,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(Oe,{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"?u("nodes.type.local","Local"):u("nodes.type.remote","Remote")}),h&&e.jsxs("span",{className:"node-card__docker-badge",title:u("nodes.dockerBadge","Managed Docker node"),children:[e.jsx(_e,{size:12,"aria-hidden":!0}),u("nodes.dockerLabel","Docker")]}),e.jsxs("span",{className:`node-card__status ${P.className}`,style:{color:P.color},"data-status":t.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:P.color},"aria-hidden":!0}),P.label]}),h&&j&&e.jsxs("span",{className:`node-card__status ${j.className}`,style:{color:j.color},"data-status":h.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:j.color},"aria-hidden":!0}),j.label]}),t.type==="remote"&&g&&e.jsx("span",{className:`node-card__auth-indicator node-card__auth-indicator--${g}`,title:Os(g,N,u),"aria-label":u("nodes.authSync.label","Auth sync: {{status}}",{status:g==="match"?u("nodes.authSync.match","credentials match"):g==="differs"?u("nodes.authSync.differ","credentials differ"):u("nodes.authSync.notSynced","not synced")}),style:{color:Us[g]},children:e.jsx(Be,{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:Bs(t.url)}),h&&e.jsxs("div",{className:"node-card__docker-meta",children:[e.jsxs("span",{title:`${h.imageName}:${h.imageTag}`,children:[h.imageName,":",h.imageTag]}),e.jsx("span",{title:b,children:b})]}),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:u("nodes.metrics.projects","Projects")}),e.jsx("span",{className:"node-card__metric-value",children:l})]}),e.jsxs("div",{className:"node-card__metric",children:[e.jsx("span",{className:"node-card__metric-label",children:u("nodes.metrics.concurrency","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:Ds(o.syncState)},"aria-hidden":!0}),e.jsx("span",{className:"node-card__sync-time",children:Se(o.lastSyncAt)})]})]}),e.jsxs("footer",{className:"node-card__actions",children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:n,disabled:m,"aria-label":u("nodes.actions.health.ariaLabel","Run node health check"),title:u("nodes.actions.health.title","Health Check"),children:[e.jsx(Te,{size:14}),e.jsx("span",{children:u("nodes.actions.health.label","Health")})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:M,disabled:m,"aria-label":u("nodes.actions.edit.ariaLabel","Edit node"),title:u("nodes.actions.edit.title","Edit"),children:[e.jsx(fs,{size:14}),e.jsx("span",{children:u("nodes.actions.edit.label","Edit")})]}),h&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",disabled:!0,"aria-label":u("nodes.actions.start.ariaLabel","Start node container"),title:u("nodes.actions.start.title","Available after FN-3113"),children:[e.jsx(He,{size:14}),e.jsx("span",{children:u("nodes.actions.start.label","Start")})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",disabled:!0,"aria-label":u("nodes.actions.stop.ariaLabel","Stop node container"),title:u("nodes.actions.stop.title","Available after FN-3113"),children:[e.jsx(qe,{size:14}),e.jsx("span",{children:u("nodes.actions.stop.label","Stop")})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",disabled:!0,"aria-label":u("nodes.actions.restart.ariaLabel","Restart node container"),title:u("nodes.actions.restart.title","Available after FN-3113"),children:[e.jsx(gs,{size:14}),e.jsx("span",{children:u("nodes.actions.restart.label","Restart")})]})]}),e.jsxs("button",{className:`btn btn-sm node-card__action node-card__action--remove ${C?"btn-danger is-armed":""}`,type:"button",onClick:I,disabled:m,"aria-label":C?u("nodes.actions.remove.ariaLabelConfirm","Confirm remove node"):u("nodes.actions.remove.ariaLabel","Remove node"),title:C?u("nodes.actions.remove.titleConfirm","Confirm remove"):u("nodes.actions.remove.title","Remove"),children:[e.jsx(Ne,{size:14}),e.jsx("span",{children:C?u("nodes.actions.remove.labelConfirm","Confirm"):u("nodes.actions.remove.label","Remove")})]})]})]})}const qs=s.memo(Hs,Ts),de={online:"var(--success, var(--color-success))",offline:"var(--text-dim)",connecting:"var(--color-warning)",error:"var(--color-error)"},me=28,Ys=12,Xs=300,Js=120;function Gs({nodes:t,className:i}){const{t:a}=ne("app"),c=s.useMemo(()=>t.find(u=>u.nodeType==="local")??t[0],[t]),r=s.useMemo(()=>t.filter(u=>u.nodeId!==c?.nodeId),[t,c?.nodeId]),m=s.useMemo(()=>Xs+Math.max(0,r.length-4)*20,[r.length]),o=m/2,g=m/2,N=s.useMemo(()=>{const u=new Map;if(c&&u.set(c.nodeId,{x:o,y:g,node:c}),r.length>0){const C=Math.min(Js,m/2-me-10),S=2*Math.PI/r.length,f=-Math.PI/2;r.forEach((P,j)=>{const b=f+j*S;u.set(P.nodeId,{node:P,x:o+C*Math.cos(b),y:g+C*Math.sin(b)})})}return u},[o,g,c,r,m]),h=s.useMemo(()=>{const u=new Set,C=[];for(const S of t){const f=N.get(S.nodeId);if(f)for(const P of S.knownPeers){const j=N.get(P.peerNodeId);if(!j)continue;const b=[S.nodeId,P.peerNodeId].sort().join("::");u.has(b)||(u.add(b),C.push({key:b,from:f,to:j}))}}return C},[N,t]);return t.length===0?e.jsx("div",{className:`mesh-topology mesh-topology--empty ${i??""}`,children:e.jsx("div",{className:"mesh-topology__empty-state",children:e.jsx("p",{children:a("mesh.noNodes","No nodes to display")})})}):e.jsxs("div",{className:`mesh-topology ${i??""}`,children:[e.jsxs("svg",{className:"mesh-topology__svg",viewBox:`0 0 ${m} ${m}`,preserveAspectRatio:"xMidYMid meet","aria-label":a("mesh.ariaLabel","Node mesh topology visualization"),children:[h.map(u=>e.jsx("line",{className:"mesh-topology__link mesh-topology__peer-line",x1:u.from.x,y1:u.from.y,x2:u.to.x,y2:u.to.y},u.key)),Array.from(N.values()).map(({node:u,x:C,y:S})=>e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${C}, ${S})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:me,fill:de[u.status],"aria-label":`${u.nodeName} (${u.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:me+Ys,textAnchor:"middle",children:u.nodeName.length>12?`${u.nodeName.slice(0,10)}…`:u.nodeName}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-me-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:u.nodeType==="local"?"L":"R"})]})]},u.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:de.online}}),e.jsx("span",{children:a("mesh.online","Online")})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:de.offline}}),e.jsx("span",{children:a("mesh.offline","Offline")})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:de.connecting}}),e.jsx("span",{children:a("mesh.connecting","Connecting")})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:de.error}}),e.jsx("span",{children:a("mesh.error","Error")})]})]}),h.length===0&&e.jsx("p",{className:"mesh-topology__notice",children:a("mesh.noPeers","Peer-to-peer discovery data unavailable.")})]})}const Ws=s.memo(Gs),Me=1,Pe=10;function Zs(t,i){const a={projectMappings:{}};t.name.trim()||(a.name=i("nodes.nameRequired","Name is required")),t.type==="remote"&&!t.url?.trim()&&(a.url=i("nodes.urlRequired","URL is required for remote nodes")),(!Number.isFinite(t.maxConcurrent)||t.maxConcurrent<Me||t.maxConcurrent>Pe)&&(a.maxConcurrent=i("nodes.concurrencyRange","Concurrency must be between {{min}} and {{max}}",{min:Me,max:Pe}));for(const c of t.projectMappings){const r=ws(c.path);r.valid||(a.projectMappings[c.projectId]=r.error??i("nodes.pathInvalid","Path is invalid"))}return a}function Qs({isOpen:t,onClose:i,onSubmit:a,onDiscoverRemoteProjects:c,addToast:r,projects:m}){const{t:o}=ne("app");ps(t);const[g,N]=s.useState(""),[h,u]=s.useState("local"),[C,S]=s.useState(""),[f,P]=s.useState(""),[j,b]=s.useState(2),[l,y]=s.useState("auto-generate"),[n,M]=s.useState({}),[I,O]=s.useState({projectMappings:{}}),[R,k]=s.useState(!1),[p,w]=s.useState("idle"),[Q,q]=s.useState(null),[X,se]=s.useState([]),B=s.useCallback(()=>{N(""),u("local"),S(""),P(""),b(2),y("auto-generate"),M({}),O({projectMappings:{}}),k(!1),w("idle"),q(null),se([])},[]),J=s.useCallback(()=>{R||(B(),i())},[R,i,B]);s.useEffect(()=>{if(!t){B();return}const _=D=>{D.key==="Escape"&&(D.preventDefault(),J())};return document.addEventListener("keydown",_),()=>{document.removeEventListener("keydown",_)}},[J,t,B]);const Z=s.useMemo(()=>({name:g.trim(),type:h,url:h==="remote"&&C.trim()||void 0,apiKey:h==="remote"&&l==="provide"&&f||void 0,maxConcurrent:j,apiKeyMode:l,projectMappings:Object.entries(n).map(([_,D])=>({projectId:_,path:D.trim()}))}),[f,l,j,g,n,h,C]),ae=s.useCallback(async()=>{if(R||p==="loading")return;const _=C.trim();if(!_){O(D=>({...D,url:o("nodes.urlRequired","URL is required for remote nodes")}));return}w("loading"),q(null);try{const D=await c({url:_,apiKey:l==="provide"&&f.trim().length>0?f:void 0});se(D.projects),w("success"),M(F=>{if(Object.keys(F).length===0)return F;const U={...F};for(const oe of m){if(!(oe.id in U))continue;const re=D.projects.filter(te=>te.name===oe.name);re.length===1&&(U[oe.id]=re[0].path)}return U})}catch(D){w("error"),se([]),q(D instanceof Error?D.message:o("nodes.discoveryFailed","Failed to discover remote projects"))}},[f,l,p,R,c,m,o,C]);s.useEffect(()=>{if(h!=="remote"){w("idle"),q(null),se([]);return}w("idle"),q(null),se([])},[f,l,h,C]);const G=s.useCallback(async()=>{if(R)return;const _=Zs(Z,o);if(O(_),!(_.name||_.url||_.maxConcurrent||Object.keys(_.projectMappings).length>0)){if(Z.type==="remote"&&p!=="success"){q(o("nodes.discoverBeforeAdding","Discover remote projects before adding this node."));return}k(!0);try{await a(Z),r(o("nodes.registered",'Node "{{name}}" registered',{name:Z.name}),"success"),J()}catch(D){const F=D instanceof Error?D.message:o("nodes.registerFailed","Failed to register node");r(F,"error")}finally{k(!1)}}},[r,J,p,Z,R,a,o]),T=_=>{M(D=>{if(_.id in D){const{[_.id]:F,...U}=D;return U}if(h==="remote"&&p==="success"){const F=X.filter(U=>U.name===_.name);return F.length===1?{...D,[_.id]:F[0].path}:{...D,[_.id]:""}}return{...D,[_.id]:_.path}})},L=(_,D)=>{M(F=>({...F,[_]:D}))};return t?e.jsx("div",{className:"modal-overlay open",onClick:J,children:e.jsxs("div",{className:"modal modal-md add-node-modal",onClick:_=>_.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":o("nodes.addNode","Add Node"),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:o("nodes.addNode","Add Node")}),e.jsx("button",{className:"modal-close",onClick:J,disabled:R,"aria-label":o("nodes.closeNodeModal","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:o("nodes.description","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:o("nodes.name","Name")}),e.jsx("input",{className:"input",type:"text",value:g,onChange:_=>N(_.target.value),placeholder:o("nodes.namePlaceholder","Build Machine"),disabled:R,"aria-invalid":!!I.name,autoFocus:!0}),I.name&&e.jsx("span",{className:"form-error add-node-modal__error",children:I.name})]}),e.jsxs("div",{className:"add-node-modal__type-toggle",children:[e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${h==="local"?"active":""}`,"data-type":"local",onClick:()=>u("local"),disabled:R,"aria-pressed":h==="local",children:o("nodes.local","Local")}),e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${h==="remote"?"active":""}`,"data-type":"remote",onClick:()=>u("remote"),disabled:R,"aria-pressed":h==="remote",children:o("nodes.remote","Remote")})]}),h==="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:o("nodes.reachableUrl","Reachable URL / Hostname")}),e.jsx("input",{className:"input",type:"text",value:C,onChange:_=>S(_.target.value),placeholder:"https://node.example.com",disabled:R,"aria-invalid":!!I.url}),I.url&&e.jsx("span",{className:"form-error add-node-modal__error",children:I.url})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:o("nodes.apiKeyMode","API Key Mode")}),e.jsxs("select",{className:"select",value:l,onChange:_=>y(_.target.value),disabled:R,children:[e.jsx("option",{value:"auto-generate",children:o("nodes.autoGenerate","Auto-generate")}),e.jsx("option",{value:"provide",children:o("nodes.provideManually","Provide key manually")})]})]}),l==="provide"&&e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:o("nodes.apiKey","API Key")}),e.jsx("input",{className:"input",type:"password",value:f,onChange:_=>P(_.target.value),placeholder:o("nodes.apiKeyPlaceholder","Enter node API key"),disabled:R})]}),e.jsxs("div",{className:"add-node-modal__discovery-actions",children:[e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void ae(),disabled:R||p==="loading",children:p==="loading"?o("nodes.discovering","Discovering..."):o("nodes.discoverRemoteProjects","Discover Remote Projects")}),p==="success"&&e.jsx("span",{className:"add-node-modal__discovery-state","data-state":"success",children:X.length>0?o("nodes.discoveredCount","Discovered {{count}} remote project{{plural}}",{count:X.length,plural:X.length===1?"":"s"}):o("nodes.noProjectsDiscovered","No projects discovered on remote node.")}),p==="error"&&Q&&e.jsx("span",{className:"form-error add-node-modal__error",children:Q}),p==="idle"&&e.jsx("span",{className:"add-node-modal__hint",children:o("nodes.discoverBeforeAdding","Discover remote projects before adding this node.")})]}),p==="success"&&X.length>0&&e.jsx("div",{className:"add-node-modal__discovered-list","aria-label":"Discovered remote projects",children:X.map(_=>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:_.name}),e.jsx("span",{className:"card-status-badge card-status-badge--in-review",children:_.status})]}),e.jsx("div",{className:"add-node-modal__hint",children:_.path})]},`${_.id}-${_.path}`))})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:o("nodes.maxConcurrent","Max Concurrent")}),e.jsx("input",{className:"input",type:"number",min:Me,max:Pe,value:j,onChange:_=>b(Number(_.target.value)),disabled:R,"aria-invalid":!!I.maxConcurrent}),e.jsx("span",{className:"add-node-modal__hint",children:o("nodes.maxConcurrentHint","Max simultaneous task agents (1–10)")}),I.maxConcurrent&&e.jsx("span",{className:"form-error add-node-modal__error",children:I.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:o("nodes.attachProjects","Attach Existing Projects")}),e.jsx("p",{className:"add-node-modal__hint",children:o("nodes.attachProjectsHint","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:o("nodes.noProjects","No projects are currently registered.")}):e.jsx("div",{className:"add-node-modal__project-list",children:m.map(_=>{const D=_.id in n,F=I.projectMappings[_.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:D,onChange:()=>T(_),disabled:R}),e.jsx("span",{children:_.name})]}),D&&e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:o("nodes.pathOnNode","Path on this node")}),h==="remote"&&p==="success"&&e.jsx("span",{className:"add-node-modal__hint",children:(()=>{const U=X.filter(oe=>oe.name===_.name);return U.length===1?o("nodes.pathDiscovered","Remote-authoritative path discovered: {{path}}",{path:U[0].path}):U.length>1?o("nodes.multipleMatches","Multiple remote projects matched this name. Enter the correct path manually."):o("nodes.noMatch","No exact remote name match. Enter this path manually.")})()}),e.jsx("input",{className:"input",type:"text",value:n[_.id]??"",onChange:U=>L(_.id,U.target.value),disabled:R,placeholder:"/absolute/path/to/project","aria-invalid":!!F}),F&&e.jsx("span",{className:"form-error add-node-modal__error",children:F})]})]},_.id)})})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:J,disabled:R,children:o("common.cancel","Cancel")}),e.jsx("button",{className:"btn btn-primary btn-sm","data-testid":"add-node-submit",onClick:G,disabled:R,children:R?o("nodes.adding","Adding..."):o("nodes.addNode","Add Node")})]})]})}):null}function et(){const[t,i]=s.useState([]),[a,c]=s.useState(!1),[r,m]=s.useState(null),[o,g]=s.useState(!1),[N,h]=s.useState(null),[u,C]=s.useState(!1),S=s.useCallback(async()=>{c(!0),m(null);try{const j=await fetch("/api/docker/contexts");if(!j.ok)throw new Error(`Failed to load Docker contexts (${j.status})`);const b=await j.json();return i(b),b}catch(j){const b=j instanceof Error?j.message:String(j);throw m(b),j}finally{c(!1)}},[]),f=s.useCallback(async j=>{g(!0);try{const b=await fetch("/api/docker/test-connection",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({hostConfig:j})});if(!b.ok)throw new Error(`Failed to test Docker connection (${b.status})`);const l=await b.json();return h(l),l}finally{g(!1)}},[]),P=s.useCallback(async()=>{C(!0);try{const j=await fetch("/api/docker/local-available");if(!j.ok)throw new Error(`Failed to check local Docker availability (${j.status})`);return await j.json()}finally{C(!1)}},[]);return{contexts:t,isLoadingContexts:a,contextsError:r,loadContexts:S,isTestingConnection:o,lastTestResult:N,testConnection:f,isCheckingLocal:u,checkLocalDocker:P}}function st({value:t,onChange:i}){const{t:a}=ne("app"),[c,r]=s.useState(!!(t?.tlsCaPath||t?.tlsCertPath||t?.tlsKeyPath||t?.tlsVerify));s.useEffect(()=>{c||i({tlsVerify:void 0,tlsCaPath:void 0,tlsCertPath:void 0,tlsKeyPath:void 0})},[c,i]);const m=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:c,onChange:o=>r(o.target.checked)}),a("docker.useTls","Use TLS")]}),c&&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:a("docker.caPath","CA Certificate Path")}),e.jsx("input",{id:"docker-tls-ca-path",className:"input",value:m.tlsCaPath,onChange:o=>i({...m,tlsCaPath:o.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:a("docker.certPath","Client Certificate Path")}),e.jsx("input",{id:"docker-tls-cert-path",className:"input",value:m.tlsCertPath,onChange:o=>i({...m,tlsCertPath:o.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:a("docker.keyPath","Client Key Path")}),e.jsx("input",{id:"docker-tls-key-path",className:"input",value:m.tlsKeyPath,onChange:o=>i({...m,tlsKeyPath:o.target.value}),placeholder:"/etc/docker/key.pem"})]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:m.tlsVerify,onChange:o=>i({...m,tlsVerify:o.target.checked})}),a("docker.verifyTls","Verify TLS Certificate")]})]})]})}function tt({value:t,onChange:i,onError:a}){const{t:c}=ne("app"),r=t?.context?"context":t?.host?"host":"local",[m,o]=s.useState(r),[g,N]=s.useState(t?.context??""),[h,u]=s.useState(t?.host??""),[C,S]=s.useState(null),{contexts:f,isLoadingContexts:P,contextsError:j,loadContexts:b,testConnection:l,isTestingConnection:y,lastTestResult:n,checkLocalDocker:M,isCheckingLocal:I}=et(),O=s.useMemo(()=>({tlsVerify:t?.tlsVerify,tlsCaPath:t?.tlsCaPath,tlsCertPath:t?.tlsCertPath,tlsKeyPath:t?.tlsKeyPath}),[t]);s.useEffect(()=>{if(m==="local"){i({});return}if(m==="context"){b().catch(k=>a?.(k instanceof Error?k.message:String(k))),i(g?{context:g}:{});return}i({host:h,...O})},[m]);const R=s.useCallback(k=>{m==="host"&&i({host:h,...k})},[h,m,i]);return e.jsxs("div",{className:"docker-target-selector",children:[e.jsxs("div",{className:"docker-target-selector__modes",role:"group","aria-label":c("docker.targetMode","Docker target mode"),children:[e.jsx("button",{type:"button",className:`btn btn-sm ${m==="local"?"docker-target-selector__mode-active":""}`,onClick:()=>{o("local"),M().then(k=>{if(k.available){const p=k.version?` (${k.version})`:"";S(c("docker.available","Docker is available{{version}}",{version:p}))}else{const p=k.error?`: ${k.error}`:"";S(c("docker.notFound","Docker not found{{error}}",{error:p}))}}).catch(k=>{const p=k instanceof Error?k.message:String(k);S(c("docker.notFoundError","Docker not found: {{message}}",{message:p})),a?.(p)})},children:c("docker.local","Local Docker")}),e.jsx("button",{type:"button",className:`btn btn-sm ${m==="context"?"docker-target-selector__mode-active":""}`,onClick:()=>o("context"),children:c("docker.context","Docker Context")}),e.jsx("button",{type:"button",className:`btn btn-sm ${m==="host"?"docker-target-selector__mode-active":""}`,onClick:()=>o("host"),children:c("docker.remote","Remote Host")})]}),m==="local"&&C&&e.jsx("div",{className:"docker-target-selector__status",children:C}),m==="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:g,onChange:k=>{const p=k.target.value;N(p),i(p?{context:p}:{})},children:[e.jsx("option",{value:"",children:c("docker.selectContext","Select context")}),f.map(k=>e.jsxs("option",{value:k.name,children:[k.name,k.isCurrentContext?" (current)":"",k.dockerHost?` — ${k.dockerHost}`:""]},k.name))]}),e.jsx("button",{type:"button",className:"btn btn-sm btn-icon",onClick:()=>void b(),disabled:P,"aria-label":c("docker.refreshContexts","Refresh contexts"),children:e.jsx(Ce,{size:14})})]}),j&&e.jsx("div",{className:"docker-target-selector__error",children:j})]}),m==="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:c("docker.host","Docker Host")}),e.jsx("input",{id:"docker-target-selector-host",className:"input",placeholder:c("docker.hostPlaceholder","tcp://host:2376"),value:h,onChange:k=>{const p=k.target.value;u(p),i({host:p,...O})}})]}),e.jsx(st,{value:O,onChange:R})]}),e.jsx("button",{type:"button",className:"btn btn-sm",onClick:()=>void l(m==="local"?void 0:m==="context"?{context:g}:{host:h,...O}),disabled:y||I,children:y?c("docker.testing","Testing..."):c("docker.testConnection","Test Connection")}),n&&e.jsx("div",{className:n.success?"docker-target-selector__success":"docker-target-selector__error",children:n.success?c("docker.connected","Connected{{version}}",{version:n.dockerVersion?` (Docker ${n.dockerVersion})`:""}):n.error??c("docker.connectionFailed","Connection failed")})]})}const ye="http://localhost:4040";function nt({isOpen:t,onClose:i,onSubmit:a,addToast:c}){const{t:r}=ne("app"),[m,o]=s.useState(""),[g,N]=s.useState({}),[h,u]=s.useState(ye),[C,S]=s.useState("auto"),[f,P]=s.useState(""),[j,b]=s.useState(!1),[l,y]=s.useState(!1),[n,M]=s.useState(!0),[I,O]=s.useState(4096),[R,k]=s.useState(2),[p,w]=s.useState(!1),[Q,q]=s.useState("runfusion/fusion"),[X,se]=s.useState("latest"),[B,J]=s.useState([]),[Z,ae]=s.useState([]),[G,T]=s.useState({}),[L,_]=s.useState(!1),D=s.useCallback(()=>{o(""),N({}),u(ye),S("auto"),P(""),b(!1),y(!1),M(!0),O(4096),k(2),w(!1),q("runfusion/fusion"),se("latest"),J([]),ae([]),T({}),_(!1)},[]),F=s.useCallback(()=>{L||(D(),i())},[i,D,L]);s.useEffect(()=>{if(!t){D();return}const x=K=>{K.key==="Escape"&&(K.preventDefault(),F())};return document.addEventListener("keydown",x),()=>document.removeEventListener("keydown",x)},[F,t,D]);const U=s.useMemo(()=>({nodeId:null,name:m.trim(),imageName:Q.trim()||"runfusion/fusion",imageTag:X.trim()||"latest",hostConfig:{context:g.context?.trim()||void 0,host:g.host?.trim()||void 0,tlsVerify:g.tlsVerify,tlsCaPath:g.tlsCaPath?.trim()||void 0,tlsCertPath:g.tlsCertPath?.trim()||void 0,tlsKeyPath:g.tlsKeyPath?.trim()||void 0},envVars:Object.fromEntries(B.map(x=>[x.key.trim(),x.value]).filter(([x])=>!!x)),volumeMounts:Z.map(x=>({hostPath:x.hostPath.trim(),containerPath:x.containerPath.trim(),mode:x.mode})).filter(x=>x.hostPath&&x.containerPath),resourceSizing:{memoryMB:I,cpus:R},extraClis:[j?"claude-cli":null,l?"droid-cli":null].filter(Boolean),persistentStorage:n,reachableUrl:h.trim()||null,apiKey:C==="manual"&&f.trim()||null}),[f,C,R,g,B,Q,X,j,l,I,Z,m,n,h]),oe=s.useCallback(()=>{J(x=>[...x,{key:"",value:""}])},[]),re=s.useCallback((x,K)=>{J(H=>H.map((Y,ie)=>ie===x?K:Y))},[]),te=s.useCallback(x=>{J(K=>K.filter((H,Y)=>Y!==x))},[]),ce=s.useCallback(()=>{ae(x=>[...x,{hostPath:"",containerPath:"",mode:"rw"}])},[]),A=s.useCallback((x,K)=>{ae(H=>H.map((Y,ie)=>ie===x?K:Y))},[]),V=s.useCallback(x=>{ae(K=>K.filter((H,Y)=>Y!==x))},[]),W=s.useCallback(async()=>{if(L)return;const x={};if((!U.name||U.name.length>64)&&(x.name=r("docker.errors.nameRequired","Name is required and must be 64 characters or fewer")),U.reachableUrl||(x.reachableUrl=r("docker.errors.urlRequired","URL is required")),I<512&&(x.memoryMB=r("docker.errors.memoryMinimum","Memory must be at least 512 MB")),R<.5&&(x.cpus=r("docker.errors.cpusMinimum","CPUs must be at least 0.5")),T(x),!(Object.keys(x).length>0)){_(!0);try{await a(U),F()}catch{}finally{_(!1)}}},[F,R,U,I,a,L,r]);return t?e.jsx("div",{className:"modal-overlay open",onClick:F,children:e.jsxs("div",{className:"modal docker-onboarding",role:"dialog","aria-modal":"true","aria-label":r("docker.ariaLabels.modal","Docker node onboarding"),onClick:x=>x.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:r("docker.titles.provisionNode","Provision Docker Node")}),e.jsx("button",{className:"modal-close",onClick:F,disabled:L,"aria-label":r("docker.ariaLabels.closeModal","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:r("docker.sections.requiredSettings","Required Settings")}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:r("docker.labels.nodeName","Node Name")}),e.jsx("input",{className:"input",value:m,onChange:x=>o(x.target.value),disabled:L,placeholder:r("docker.placeholders.nodeName","my-docker-node"),autoFocus:!0})]}),G.name&&e.jsx("div",{className:"form-error",children:G.name}),e.jsx(tt,{value:g,onChange:N}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:r("docker.labels.reachableUrl","Reachable URL")}),e.jsx("input",{className:"input",value:h,onChange:x=>u(x.target.value),disabled:L,placeholder:ye})]}),G.reachableUrl&&e.jsx("div",{className:"form-error",children:G.reachableUrl}),e.jsxs("div",{className:"docker-onboarding__radio-group",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"radio",checked:C==="auto",onChange:()=>S("auto"),disabled:L}),r("docker.options.autoGenerate","Auto-generate")]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"radio",checked:C==="manual",onChange:()=>S("manual"),disabled:L}),r("docker.options.provideManually","Provide manually")]})]}),C==="manual"&&e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:r("docker.labels.apiKey","API Key")}),e.jsx("input",{className:"input",type:"password",value:f,onChange:x=>P(x.target.value),disabled:L,placeholder:r("docker.placeholders.apiKey","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:j,onChange:x=>b(x.target.checked),disabled:L}),r("docker.options.claudeCli","Claude CLI")]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:l,onChange:x=>y(x.target.checked),disabled:L}),r("docker.options.droidCli","Droid CLI")]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:n,onChange:x=>M(x.target.checked),disabled:L}),r("docker.options.persistentStorage","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:r("docker.labels.memory","Memory (MB)")}),e.jsx("input",{className:"input",type:"number",min:512,value:I,onChange:x=>O(Number(x.target.value)),disabled:L})]}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:r("docker.labels.cpus","CPUs")}),e.jsx("input",{className:"input",type:"number",min:.5,step:.5,value:R,onChange:x=>k(Number(x.target.value)),disabled:L})]})]}),G.memoryMB&&e.jsx("div",{className:"form-error",children:G.memoryMB}),G.cpus&&e.jsx("div",{className:"form-error",children:G.cpus})]}),e.jsxs("section",{className:"docker-onboarding__section",children:[e.jsxs("button",{type:"button",className:`docker-onboarding__advanced-toggle ${p?"is-expanded":""}`,onClick:()=>w(x=>!x),disabled:L,children:[e.jsx("span",{children:r("docker.sections.advanced","Advanced")}),e.jsx(we,{})]}),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:r("docker.labels.image","Image")}),e.jsx("input",{className:"input",value:Q,onChange:x=>q(x.target.value),disabled:L,placeholder:r("docker.placeholders.image","runfusion/fusion")})]}),e.jsxs("label",{className:"docker-onboarding__field",children:[e.jsx("span",{children:r("docker.labels.tag","Tag")}),e.jsx("input",{className:"input",value:X,onChange:x=>se(x.target.value),disabled:L,placeholder:r("docker.placeholders.tag","latest")})]})]}),e.jsxs("div",{className:"docker-onboarding__kv-list",children:[e.jsx("h5",{children:r("docker.sections.environmentVariables","Environment Variables")}),B.map((x,K)=>e.jsxs("div",{className:"docker-onboarding__kv-row docker-onboarding__kv-row--env",children:[e.jsx("input",{className:"input",placeholder:r("docker.placeholders.envVarKey","KEY"),value:x.key,disabled:L,onChange:H=>re(K,{key:H.target.value,value:x.value})}),e.jsx("input",{className:"input",placeholder:r("docker.placeholders.envVarValue","Value"),value:x.value,disabled:L,onChange:H=>re(K,{key:x.key,value:H.target.value})}),e.jsx("button",{type:"button",className:"btn btn-icon","aria-label":r("docker.ariaLabels.removeVariable","Remove environment variable"),onClick:()=>te(K),disabled:L,children:e.jsx(Ne,{size:14})})]},`env-${K}`)),e.jsxs("button",{type:"button",className:"btn btn-sm docker-onboarding__kv-add",onClick:oe,disabled:L,children:[e.jsx(ge,{size:14}),r("docker.actions.addVariable","Add variable")]})]}),e.jsxs("div",{className:"docker-onboarding__kv-list",children:[e.jsx("h5",{children:r("docker.sections.volumeMounts","Volume Mounts")}),Z.map((x,K)=>e.jsxs("div",{className:"docker-onboarding__kv-row docker-onboarding__kv-row--mount",children:[e.jsx("input",{className:"input",placeholder:r("docker.placeholders.hostPath","Host path"),value:x.hostPath,disabled:L,onChange:H=>A(K,{hostPath:H.target.value,containerPath:x.containerPath,mode:x.mode})}),e.jsx("input",{className:"input",placeholder:r("docker.placeholders.containerPath","Container path"),value:x.containerPath,disabled:L,onChange:H=>A(K,{hostPath:x.hostPath,containerPath:H.target.value,mode:x.mode})}),e.jsxs("select",{className:"select",value:x.mode,disabled:L,onChange:H=>A(K,{hostPath:x.hostPath,containerPath:x.containerPath,mode:H.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":r("docker.ariaLabels.removeMount","Remove volume mount"),onClick:()=>V(K),disabled:L,children:e.jsx(Ne,{size:14})})]},`mount-${K}`)),e.jsxs("button",{type:"button",className:"btn btn-sm docker-onboarding__kv-add",onClick:ce,disabled:L,children:[e.jsx(ge,{size:14}),r("docker.actions.addMount","Add mount")]})]})]})})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn",onClick:F,disabled:L,children:r("docker.actions.cancel","Cancel")}),e.jsx("button",{className:"btn btn-primary",onClick:()=>void W(),disabled:L,children:L?r("docker.states.creating","Creating..."):r("docker.actions.createNode","Create Docker Node")})]})]})}):null}function at({nodeId:t,entries:i,loading:a=!1,singleNode:c=!1}){const{t:r}=ne("app"),[m,o]=s.useState(!1),[g,N]=s.useState("all"),[h,u]=s.useState("all"),C=s.useCallback(()=>{o(l=>!l)},[]),S=s.useMemo(()=>{const l=new Set;for(const y of i)l.add(y.nodeName);return Array.from(l).sort()},[i]),f=s.useMemo(()=>{let l=[...i];return g!=="all"&&(l=l.filter(y=>y.direction===g)),!c&&h!=="all"&&(l=l.filter(y=>y.nodeName===h)),l.sort((y,n)=>{const M=new Date(y.timestamp).getTime();return new Date(n.timestamp).getTime()-M}),l},[i,g,h,c]),P=s.useCallback(l=>new Date(l).toLocaleString(),[]),j=s.useCallback(l=>{switch(l){case"success":return"settings-sync-log__badge--success";case"conflict":return"settings-sync-log__badge--conflict";case"error":return"settings-sync-log__badge--error";default:return""}},[]),b=s.useCallback(l=>{switch(l){case"success":return r("syncLog.resultSuccess","Success");case"conflict":return r("syncLog.resultConflict","Conflict");case"error":return r("syncLog.resultError","Error");default:return l}},[r]);return e.jsxs("div",{className:"settings-sync-log",children:[e.jsxs("button",{className:"settings-sync-log__header",type:"button",onClick:C,"aria-expanded":m,"data-testid":"settings-sync-log-header",children:[e.jsx(we,{size:16,className:`settings-sync-log__chevron ${m?"settings-sync-log__chevron--expanded":""}`}),e.jsx("span",{children:r("syncLog.entryCount",{count:i.length,defaultValue_one:"{{count}} entry",defaultValue_other:"{{count}} entries"})})]}),m&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"settings-sync-log__filters",children:[e.jsxs("label",{children:[r("syncLog.filterDirection","Direction:"),e.jsxs("select",{value:g,onChange:l=>N(l.target.value),children:[e.jsx("option",{value:"all",children:r("syncLog.filterAll","All")}),e.jsx("option",{value:"push",children:r("syncLog.filterPush","Push")}),e.jsx("option",{value:"pull",children:r("syncLog.filterPull","Pull")})]})]}),!c&&e.jsxs("label",{children:[r("syncLog.filterNode","Node:"),e.jsxs("select",{value:h,onChange:l=>u(l.target.value),children:[e.jsx("option",{value:"all",children:r("syncLog.filterAllNodes","All Nodes")}),S.map(l=>e.jsx("option",{value:l,children:l},l))]})]})]}),a&&i.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:r("syncLog.loading","Loading...")}):f.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:r("syncLog.noHistory","No sync history available")}):e.jsx("div",{className:"settings-sync-log__list",children:f.map(l=>e.jsxs("div",{className:"settings-sync-log__entry",children:[e.jsx("span",{className:"settings-sync-log__entry-timestamp",children:P(l.timestamp)}),e.jsx("span",{className:"settings-sync-log__entry-direction",children:l.direction==="push"?e.jsx(Xe,{size:14,"data-testid":"upload-icon"}):e.jsx(Ye,{size:14,"data-testid":"download-icon"})}),e.jsx("span",{className:`settings-sync-log__entry-result ${j(l.result)}`,children:b(l.result)}),!c&&e.jsx("span",{className:"settings-sync-log__entry-node",children:l.nodeName}),l.details&&e.jsx("span",{className:"settings-sync-log__entry-details",title:l.details,children:xs(l.details??"")})]},l.id))})]})]})}function ot(t,i){const a=typeof t=="string"?t:JSON.stringify(t,null,2),c=typeof i=="string"?i:JSON.stringify(i,null,2);if(a===c)return a;const r=a.split(`
12
+ `),m=c.split(`
13
+ `),o=[],g=Math.max(r.length,m.length);for(let N=0;N<g;N++){const h=r[N],u=m[N];h!==void 0&&h!==u&&o.push(`- ${h}`),u!==void 0&&u!==h&&o.push(`+ ${u}`),h!==void 0&&h===u&&o.push(` ${h}`)}return o.join(`
14
+ `)}function rt({isOpen:t,onClose:i,onResolve:a,conflicts:c,localNodeName:r,remoteNodeName:m,addToast:o}){const{t:g}=ne("app"),[N,h]=s.useState({}),[u,C]=s.useState(!1);s.useEffect(()=>{const l={};for(const y of c)N[y.key]||(l[y.key]={resolution:"local"});Object.keys(l).length>0&&h(y=>({...y,...l}))},[c,N]),s.useEffect(()=>{if(!t)return;const l=y=>{y.key==="Escape"&&(y.preventDefault(),i())};return document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l)},[t,i]);const S=s.useCallback((l,y)=>{h(n=>{const M=n[l]??{};return y==="manual"?{...n,[l]:{resolution:"manual",manualValue:M.manualValue??JSON.stringify(c.find(I=>I.key===l)?.localValue??null,null,2)}}:{...n,[l]:{resolution:y}}})},[c]),f=s.useCallback((l,y)=>{h(n=>({...n,[l]:{...n[l],resolution:"manual",manualValue:y}}))},[]),P=s.useCallback(l=>{const y={};for(const n of c)y[n.key]={resolution:l};h(y)},[c]),j=s.useCallback(async()=>{C(!0);try{const l=c.map(y=>{const n=N[y.key]??{resolution:"local"};let M;switch(n.resolution){case"remote":M=y.remoteValue;break;case"manual":try{M=JSON.parse(n.manualValue??"null")}catch{M=n.manualValue??null}break;case"local":default:M=y.localValue;break}return{key:y.key,value:M}});await a(l),o(g("settings.resolvedSuccess","Settings conflicts resolved successfully"),"success"),i()}catch(l){const y=l instanceof Error?l.message:g("settings.resolveFailed","Failed to resolve conflicts");o(y,"error")}finally{C(!1)}},[o,c,i,a,N]),b=s.useMemo(()=>{const l={};for(const y of c)l[y.key]=ot(y.localValue,y.remoteValue);return l},[c]);return!t||c.length===0?null:e.jsx("div",{className:"modal-overlay open",onClick:i,children:e.jsxs("div",{className:"modal modal-lg settings-sync-conflict-modal",onClick:l=>l.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":g("settings.conflictModalTitle","Resolve Settings Conflicts"),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:g("settings.conflictModalTitle","Resolve Settings Conflicts")}),e.jsx("button",{className:"modal-close",onClick:i,"aria-label":g("settings.closeModal","Close conflict modal"),children:"×"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("div",{className:"settings-sync-conflict-modal__conflict-list",children:c.map(l=>{const y=N[l.key]??{resolution:"local"},n=b[l.key];return e.jsxs("div",{className:"settings-sync-conflict-modal__conflict-item",children:[e.jsx("div",{className:"settings-sync-conflict-modal__key",children:l.key}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-panel",children:[e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:r}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:n})})]}),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:n})})]})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__resolution",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:y.resolution==="local",onChange:()=>S(l.key,"local")}),g("settings.keepLocal","Keep Local")]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:y.resolution==="remote",onChange:()=>S(l.key,"remote")}),g("settings.keepRemote","Keep Remote")]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${l.key}`,checked:y.resolution==="manual",onChange:()=>S(l.key,"manual")}),g("settings.mergeManually","Merge Manually")]})]}),y.resolution==="manual"&&e.jsx("textarea",{className:"settings-sync-conflict-modal__manual-input",value:y.manualValue??"",onChange:M=>f(l.key,M.target.value),placeholder:g("settings.jsonPlaceholder","Enter JSON value...")})]},l.key)})}),e.jsxs("div",{className:"settings-sync-conflict-modal__bulk-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:()=>P("local"),type:"button",children:g("settings.resolveAllLocal","Resolve All: Keep Local")}),e.jsx("button",{className:"btn btn-sm",onClick:()=>P("remote"),type:"button",children:g("settings.resolveAllRemote","Resolve All: Keep Remote")})]})]}),e.jsxs("div",{className:"modal-actions settings-sync-conflict-modal__footer",children:[e.jsx("button",{className:"btn btn-sm",onClick:i,children:g("actions.cancel","Cancel")}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:j,disabled:u,children:u?g("settings.resolving","Resolving..."):g("actions.confirm","Confirm")})]})]})})}const Je=/(KEY|TOKEN|SECRET|PASSWORD)/i;function je(t){if(!t)return"—";const i=new Date(t);return Number.isNaN(i.getTime())?"—":i.toLocaleString()}function lt(t){if(!t)return"—";const i=new Date(t),a=Date.now();if(Number.isNaN(i.getTime())||i.getTime()>a)return"—";const c=Math.floor((a-i.getTime())/1e3);if(c<60)return`${c}s`;const r=Math.floor(c/60);if(r<60)return`${r}m`;const m=Math.floor(r/60);return m<24?`${m}h ${r%60}m`:`${Math.floor(m/24)}d ${m%24}h`}function ct(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 it(t){return t==="running"?"success":t==="creating"||t==="recreating"||t==="restarting"?"warning":"error"}function dt(t){return t?`${t.charAt(0).toUpperCase()}${t.slice(1)}`:"Unknown"}function ut(t){if(!t)return"—";try{const i=new URL(t);return i.port?i.port:i.protocol==="https:"?"443":i.protocol==="http:"?"80":"—"}catch{return"—"}}function mt(t,i){return Je.test(t)?"••••••••":i}function ht({isOpen:t,onClose:i,node:a,projects:c,onUpdate:r,onHealthCheck:m,addToast:o,syncStatus:g,onPushSettings:N,onPullSettings:h,onSyncAuth:u,syncHistory:C=[],onResolveConflicts:S,managedDockerNode:f,containerStatus:P,onFetchContainerStatus:j,onFetchLogs:b,onUpdateDockerConfig:l,onFetchDockerConfigDiff:y}){const{t:n}=ne("app"),M=s.useRef(!0),[I,O]=s.useState(!1),[R,k]=s.useState(""),[p,w]=s.useState(""),[Q,q]=s.useState(""),[X,se]=s.useState(2),[B,J]=s.useState(!1),[Z,ae]=s.useState(!1),[G,T]=s.useState(!1),[L,_]=s.useState(!1),[D,F]=s.useState(null),[U,oe]=s.useState(!1),[re]=s.useState([]),[te,ce]=s.useState(P),[A,V]=s.useState(!1),[W,x]=s.useState(!1),[K,H]=s.useState(""),[Y,ie]=s.useState(!1),[pe,Re]=s.useState(!1),[v,z]=s.useState(a?.dockerConfig??null),[Ee,Le]=s.useState({}),[ue,Ae]=s.useState(!1),[Ge,De]=s.useState(!1);s.useEffect(()=>(M.current=!0,()=>{M.current=!1}),[]),s.useEffect(()=>{ce(P)},[P]),s.useEffect(()=>{if(!a||!t){O(!1),x(!1),H("");return}k(a.name),w(a.url??""),q(a.apiKey??""),se(a.maxConcurrent),O(!1),z(a.dockerConfig??null),Re(!1),Le({})},[t,a]),s.useEffect(()=>{if(!t)return;const d=E=>{E.key==="Escape"&&(E.preventDefault(),i())};return document.addEventListener("keydown",d),()=>document.removeEventListener("keydown",d)},[t,i]);const xe=s.useMemo(()=>a?vs(c,a):[],[a,c]),We=s.useMemo(()=>f?f.hostConfig.type==="remote"?f.hostConfig.host??"—":n("nodes.localDocker","Local Docker"):"—",[f,n]),Ze=s.useMemo(()=>!f?.resourceSizing?.cpuLimit&&!f?.resourceSizing?.memoryLimit?n("nodes.dockerResourceDefault","Default"):`${f.resourceSizing?.cpuLimit??n("nodes.dockerDefaultCpu","Default CPU")} / ${f.resourceSizing?.memoryLimit??n("nodes.dockerDefaultMemory","Default memory")}`,[f,n]),Qe=s.useCallback(async()=>{if(a)try{if(await m(a.id),!M.current)return;o(n("nodes.healthCheckSuccess","Health check completed for {{name}}",{name:a.name}),"success")}catch(d){if(!M.current)return;const E=d instanceof Error?d.message:n("nodes.healthCheckFailed","Health check failed");o(E,"error")}},[o,a,m]),es=s.useCallback(async()=>{if(!(!a||!N)){F(null),ae(!0);try{if(await N(a.id),!M.current)return;o(n("nodes.pushSettingsSuccess","Settings pushed successfully"),"success")}catch(d){if(!M.current)return;const E=d instanceof Error?d.message:n("nodes.pushSettingsFailed","Push settings failed");F(E),o(E,"error")}finally{M.current&&ae(!1)}}},[o,a,N]),ss=s.useCallback(async()=>{if(!(!a||!h)){F(null),T(!0);try{if(await h(a.id),!M.current)return;o(n("nodes.pullSettingsSuccess","Settings pulled successfully"),"success")}catch(d){if(!M.current)return;const E=d instanceof Error?d.message:n("nodes.pullSettingsFailed","Pull settings failed");F(E),o(E,"error")}finally{M.current&&T(!1)}}},[o,a,h]),ts=s.useCallback(async()=>{if(!(!a||!u)){F(null),_(!0);try{if(await u(a.id),!M.current)return;o(n("nodes.syncAuthSuccess","Auth credentials synced successfully"),"success")}catch(d){if(!M.current)return;const E=d instanceof Error?d.message:n("nodes.syncAuthFailed","Auth sync failed");F(E),o(E,"error")}finally{M.current&&_(!1)}}},[o,a,u]),ns=s.useCallback(()=>{F(null)},[]),as=s.useCallback(async()=>{if(!(!f||!j)){V(!0);try{const d=await j(f.id);if(!M.current)return;ce(d)}catch(d){const E=d instanceof Error?d.message:n("nodes.fetchContainerStatusFailed","Failed to fetch container status");o(E,"error")}finally{M.current&&V(!1)}}},[o,f,j]),os=s.useCallback(async()=>{if(!(!f||!b)){x(!0),ie(!0);try{const d=await b(f.id);if(!M.current)return;H(d)}catch(d){if(!M.current)return;H("");const E=d instanceof Error?d.message:n("nodes.fetchContainerLogsFailed","Failed to fetch container logs");o(E,"error")}finally{M.current&&ie(!1)}}},[o,f,b]),rs=s.useCallback(async()=>{if(!a||B)return;const d=R.trim();if(!d){o(n("nodes.nameRequired","Name is required"),"error");return}if(a.type==="remote"&&!p.trim()){o(n("nodes.urlRequired","URL is required for remote nodes"),"error");return}if(!Number.isFinite(X)||X<1){o(n("nodes.concurrencyMin","Concurrency must be at least 1"),"error");return}J(!0);try{await r(a.id,{name:d,url:a.type==="remote"&&p.trim()||void 0,apiKey:a.type==="remote"&&Q||void 0,maxConcurrent:X}),o(n("nodes.updateSuccess","Updated {{name}}",{name:d}),"success"),O(!1)}catch(E){const ee=E instanceof Error?E.message:n("nodes.updateFailed","Failed to update node");o(ee,"error")}finally{J(!1)}},[o,Q,B,X,R,a,r,p]);s.useEffect(()=>{!a?.dockerConfig||!y||!t||y(a.id).then(d=>{M.current&&De(d.needsRecreate)}).catch(()=>{M.current&&De(!1)})},[t,a,y]);const ls=s.useCallback(async()=>{if(!(!a||!v||!l||ue)){Ae(!0);try{const d=await l(a.id,{image:v.image,volumeMounts:v.volumeMounts,environment:v.environment,resources:v.resources,host:v.host,extraClis:v.extraClis,persistence:v.persistence,containerName:v.containerName});if(!M.current)return;z(d),o(n("nodes.dockerConfigSaveSuccess","Docker config saved"),"success")}catch(d){if(!M.current)return;const E=d instanceof Error?d.message:n("nodes.dockerConfigSaveFailed","Failed to save Docker config");o(E,"error")}finally{M.current&&Ae(!1)}}},[o,v,ue,a,l]),cs=s.useCallback(()=>{a&&(k(a.name),w(a.url??""),q(a.apiKey??""),se(a.maxConcurrent),O(!1))},[a]);if(!t||!a)return null;const le=te?.status??f?.status,is=it(le);return e.jsxs("div",{className:"modal-overlay open",onClick:i,children:[e.jsxs("div",{className:"modal modal-lg node-detail-modal",onClick:d=>d.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":n("nodes.modalAriaLabel","Node details for {{name}}",{name:a.name}),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:n("nodes.modalTitle","Node Details")}),e.jsx("button",{className:"modal-close",onClick:i,"aria-label":n("nodes.closeModalAriaLabel","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:n("nodes.sectionOverview","Overview")}),!I&&e.jsxs("button",{className:"btn btn-sm",onClick:()=>O(!0),children:[e.jsx(bs,{size:14}),n("nodes.editButton","Edit")]})]}),e.jsxs("div",{className:"node-detail-modal__grid",children:[e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.fieldName","Name")}),I?e.jsx("input",{className:"input",value:R,onChange:d=>k(d.target.value),disabled:B}):e.jsx("strong",{children:a.name})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.fieldType","Type")}),e.jsx("strong",{children:a.type==="local"?n("nodes.typeLocal","Local"):n("nodes.typeRemote","Remote")})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.fieldStatus","Status")}),e.jsx("strong",{children:a.status})]}),e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.fieldMaxConcurrent","Max Concurrent")}),I?e.jsx("input",{className:"input",type:"number",min:1,max:10,value:X,onChange:d=>se(Number(d.target.value)),disabled:B}):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:n("nodes.fieldUrl","URL")}),I?e.jsx("input",{className:"input",value:p,onChange:d=>w(d.target.value),disabled:B}):e.jsx("strong",{children:a.url??"—"})]}),e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:n("nodes.fieldApiKey","API Key")}),I?e.jsx("input",{className:"input",type:"password",value:Q,onChange:d=>q(d.target.value),placeholder:n("nodes.apiKeyPlaceholder","Leave blank to keep unchanged"),disabled:B}):e.jsx("strong",{children:a.apiKey?"••••••••":n("nodes.apiKeyNotConfigured","Not configured")})]})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.fieldCreated","Created")}),e.jsx("strong",{children:je(a.createdAt)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.fieldUpdated","Updated")}),e.jsx("strong",{children:je(a.updatedAt)})]})]}),I&&e.jsxs("div",{className:"node-detail-modal__edit-actions",children:[e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:rs,disabled:B,children:[e.jsx(Fe,{size:14}),B?n("nodes.saving","Saving..."):n("nodes.saveButton","Save")]}),e.jsxs("button",{className:"btn btn-sm",onClick:cs,disabled:B,children:[e.jsx(he,{size:14}),n("nodes.cancelButton","Cancel")]})]})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("h4",{children:[a.type==="local"?n("nodes.sectionProjects","Projects"):n("nodes.sectionAssignedProjects","Assigned Projects")," (",xe.length,")"]}),xe.length===0?e.jsx("p",{className:"node-detail-modal__empty",children:a.type==="local"?n("nodes.noProjectsRunning","No projects are running on this node."):n("nodes.noProjectsAssigned","No projects are assigned to this node.")}):e.jsx("ul",{className:"node-detail-modal__project-list",children:xe.map(d=>e.jsxs("li",{className:"node-detail-modal__project-item",children:[e.jsx("span",{children:d.name}),e.jsx("code",{children:d.id})]},d.id))})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:n("nodes.sectionHealth","Health")}),e.jsxs("div",{className:"node-detail-modal__health-row",children:[e.jsxs("span",{children:[n("nodes.healthStatus","Status:")," ",e.jsx("strong",{children:a.status})]}),e.jsxs("span",{children:[n("nodes.healthLastCheck","Last check:")," ",e.jsx("strong",{children:je(a.updatedAt)})]})]})]}),v&&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:()=>Re(d=>!d),"aria-expanded":pe,children:[e.jsx(we,{size:14,className:pe?"node-detail-modal__docker-toggle-icon--expanded":""}),n("nodes.dockerConfiguration","Docker Configuration")]}),pe&&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:n("nodes.dockerFieldImage","Image")}),e.jsx("input",{className:"input",value:v.image,onChange:d=>z({...v,image:d.target.value})})]})}),e.jsxs("details",{children:[e.jsx("summary",{children:n("nodes.dockerVolumeMounts","Volume Mounts")}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[v.volumeMounts.map((d,E)=>e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:d.hostPath,placeholder:n("nodes.dockerHostPath","Host path"),onChange:ee=>{const $=[...v.volumeMounts];$[E]={...$[E],hostPath:ee.target.value},z({...v,volumeMounts:$})}}),e.jsx("input",{className:"input",value:d.containerPath,placeholder:n("nodes.dockerContainerPath","Container path"),onChange:ee=>{const $=[...v.volumeMounts];$[E]={...$[E],containerPath:ee.target.value},z({...v,volumeMounts:$})}}),e.jsxs("select",{className:"input",value:d.mode??"rw",onChange:ee=>{const $=[...v.volumeMounts];$[E]={...$[E],mode:ee.target.value},z({...v,volumeMounts:$})},children:[e.jsx("option",{value:"rw",children:"rw"}),e.jsx("option",{value:"ro",children:"ro"})]}),e.jsxs("select",{className:"input",value:d.type??"volume",onChange:ee=>{const $=[...v.volumeMounts];$[E]={...$[E],type:ee.target.value},z({...v,volumeMounts:$})},children:[e.jsx("option",{value:"volume",children:"volume"}),e.jsx("option",{value:"bind",children:"bind"})]}),e.jsx("button",{className:"btn btn-sm",onClick:()=>z({...v,volumeMounts:v.volumeMounts.filter((ee,$)=>$!==E)}),children:n("nodes.removeButton","Remove")})]},`${d.hostPath}-${d.containerPath}-${E}`)),e.jsx("button",{className:"btn btn-sm",onClick:()=>z({...v,volumeMounts:[...v.volumeMounts,{hostPath:"",containerPath:"",mode:"rw",type:"volume"}]}),children:n("nodes.addMountButton","Add Mount")})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:n("nodes.dockerEnvVars","Environment Variables")}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[Object.entries(v.environment).map(([d,E])=>{const ee=Je.test(d)&&!Ee[d];return e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:d,onChange:$=>{const ve={...v.environment};delete ve[d],ve[$.target.value]=E,z({...v,environment:ve})}}),e.jsx("input",{className:"input",value:ee?"***":String(E),onChange:$=>z({...v,environment:{...v.environment,[d]:$.target.value}})}),e.jsx("button",{className:"btn btn-sm",onClick:()=>Le($=>({...$,[d]:!$[d]})),children:Ee[d]?e.jsx(ys,{size:14}):e.jsx(js,{size:14})}),e.jsx("button",{className:"btn btn-sm",onClick:()=>{const $={...v.environment};delete $[d],z({...v,environment:$})},children:n("nodes.removeButton","Remove")})]},d)}),e.jsx("button",{className:"btn btn-sm",onClick:()=>{const d=`NEW_VAR_${Object.keys(v.environment).length+1}`;z({...v,environment:{...v.environment,[d]:""}})},children:n("nodes.addVariableButton","Add Variable")})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:n("nodes.dockerResources","Resources")}),e.jsxs("div",{className:"node-detail-modal__docker-stack",children:[e.jsx("input",{className:"input",type:"number",placeholder:n("nodes.dockerMemoryBytes","Memory bytes (2 GB = 2147483648)"),value:v.resources?.memoryBytes??"",onChange:d=>z({...v,resources:{...v.resources,memoryBytes:d.target.value?Number(d.target.value):void 0}})}),e.jsx("input",{className:"input",type:"number",placeholder:n("nodes.dockerCpuCount","CPU count"),value:v.resources?.cpuCount??"",onChange:d=>z({...v,resources:{...v.resources,cpuCount:d.target.value?Number(d.target.value):void 0}})}),e.jsx("input",{className:"input",type:"number",placeholder:n("nodes.dockerPidsLimit","PIDs limit"),value:v.resources?.pidsLimit??"",onChange:d=>z({...v,resources:{...v.resources,pidsLimit:d.target.value?Number(d.target.value):void 0}})})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:n("nodes.dockerHostConfig","Host Config")}),e.jsxs("div",{className:"node-detail-modal__docker-stack",children:[e.jsx("input",{className:"input",placeholder:n("nodes.dockerContextName","Context name"),value:v.host?.contextName??"",onChange:d=>z({...v,host:{...v.host,contextName:d.target.value}})}),e.jsx("input",{className:"input",placeholder:n("nodes.dockerHostUrl","Docker host URL"),value:v.host?.dockerHost??"",onChange:d=>z({...v,host:{...v.host,dockerHost:d.target.value}})}),e.jsx("input",{className:"input",placeholder:n("nodes.dockerTlsCaCert","TLS CA cert path"),value:v.host?.tlsCaCert??"",onChange:d=>z({...v,host:{...v.host,tlsCaCert:d.target.value}})}),e.jsx("input",{className:"input",placeholder:n("nodes.dockerTlsCert","TLS cert path"),value:v.host?.tlsCert??"",onChange:d=>z({...v,host:{...v.host,tlsCert:d.target.value}})}),e.jsx("input",{className:"input",placeholder:n("nodes.dockerTlsKey","TLS key path"),value:v.host?.tlsKey??"",onChange:d=>z({...v,host:{...v.host,tlsKey:d.target.value}})}),e.jsxs("label",{className:"node-detail-modal__checkbox",children:[e.jsx("input",{type:"checkbox",checked:v.host?.tlsVerify??!0,onChange:d=>z({...v,host:{...v.host,tlsVerify:d.target.checked}})}),n("nodes.dockerTlsVerify","TLS verify")]})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:n("nodes.dockerExtraClis","Extra CLIs")}),e.jsxs("div",{className:"node-detail-modal__docker-list",children:[(v.extraClis??[]).map((d,E)=>e.jsxs("div",{className:"node-detail-modal__docker-row",children:[e.jsx("input",{className:"input",value:d,onChange:ee=>{const $=[...v.extraClis??[]];$[E]=ee.target.value,z({...v,extraClis:$})}}),e.jsx("button",{className:"btn btn-sm",onClick:()=>z({...v,extraClis:(v.extraClis??[]).filter((ee,$)=>$!==E)}),children:n("nodes.removeButton","Remove")})]},`${d}-${E}`)),e.jsx("button",{className:"btn btn-sm",onClick:()=>z({...v,extraClis:[...v.extraClis??[],""]}),children:n("nodes.addCliButton","Add CLI")})]})]}),e.jsxs("details",{children:[e.jsx("summary",{children:n("nodes.dockerPersistence","Persistence")}),e.jsxs("div",{className:"node-detail-modal__docker-stack",children:[e.jsx("input",{className:"input",placeholder:n("nodes.dockerVolumeName","Volume name"),value:v.persistence?.volumeName??"",onChange:d=>z({...v,persistence:{...v.persistence,volumeName:d.target.value}})}),e.jsxs("label",{className:"node-detail-modal__checkbox",children:[e.jsx("input",{type:"checkbox",checked:v.persistence?.retainOnDelete??!1,onChange:d=>z({...v,persistence:{...v.persistence,retainOnDelete:d.target.checked}})}),n("nodes.dockerRetainOnDelete","Retain on delete")]})]})]}),e.jsxs("div",{className:"node-detail-modal__docker-meta",children:[e.jsxs("span",{children:["Config v",v.configVersion," • Updated ",Se(v.lastUpdated??a.updatedAt)]}),Ge&&e.jsx("span",{className:"node-detail-modal__docker-recreate",children:n("nodes.dockerNeedsRecreate","Needs Recreate")})]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>void ls(),disabled:ue,children:[e.jsx(Fe,{size:14}),ue?n("nodes.saving","Saving..."):n("nodes.saveDockerConfig","Save Docker Config")]})]})]}),f&&e.jsxs("section",{className:"node-detail-modal__section docker-management",children:[e.jsx("h4",{children:n("nodes.sectionDockerManagement","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--${is}`,"aria-hidden":!0}),e.jsx("strong",{children:le?dt(le):n("nodes.dockerStatusUnknown","Unknown")}),(le==="creating"||le==="recreating"||le==="restarting")&&e.jsx(Ve,{size:14,className:"spin","aria-hidden":!0})]}),e.jsxs("div",{className:"docker-management__status-meta",children:[le==="running"&&e.jsxs("span",{children:[n("nodes.dockerUptime","Uptime:")," ",lt(te?.startedAt)]}),le!=="running"&&te?.exitCode!==void 0&&e.jsxs("span",{children:[n("nodes.dockerExitCode","Exit code:")," ",te.exitCode]}),(te?.error||f.errorMessage)&&e.jsx("span",{children:te?.error??f.errorMessage})]}),e.jsx("button",{className:"btn btn-sm",onClick:()=>void as(),disabled:!j||A,children:A?n("nodes.refreshing","Refreshing..."):n("nodes.refreshStatus","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:n("nodes.dockerFieldImage","Image")}),e.jsx("strong",{children:e.jsxs("code",{children:[f.imageName,":",f.imageTag]})})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.dockerContainerId","Container ID")}),e.jsx("strong",{children:e.jsx("code",{children:f.containerId?f.containerId.slice(0,12):"—"})})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.dockerHost","Host")}),e.jsx("strong",{children:We})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.dockerPersistentStorage","Persistent Storage")}),e.jsx("strong",{children:f.persistentStorage?n("nodes.yes","Yes"):n("nodes.no","No")})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.dockerPort","Port")}),e.jsx("strong",{children:ut(f.reachableUrl)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:n("nodes.dockerResourceSizing","Resource Sizing")}),e.jsx("strong",{children:Ze})]})]}),e.jsxs("div",{className:"docker-management__actions",children:[e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:n("nodes.availableSoon","Available after FN-3113"),children:[e.jsx(He,{size:14}),n("nodes.startButton","Start")]}),e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:n("nodes.availableSoon","Available after FN-3113"),children:[e.jsx(qe,{size:14}),n("nodes.stopButton","Stop")]}),e.jsxs("button",{className:"btn btn-sm",disabled:!0,title:n("nodes.availableSoon","Available after FN-3113"),children:[e.jsx(Ve,{size:14}),n("nodes.restartButton","Restart")]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void os(),disabled:!b,children:[e.jsx(ks,{size:14}),n("nodes.viewLogsButton","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:n("nodes.containerLogs","Container Logs")}),e.jsx("button",{className:"btn-icon",onClick:()=>x(!1),"aria-label":n("nodes.closeLogsAriaLabel","Close logs"),children:e.jsx(he,{size:14})})]}),Y?e.jsx("p",{children:n("nodes.fetchingLogs","Fetching logs...")}):e.jsx("pre",{children:K.trim()||n("nodes.noLogsAvailable","No logs available")})]}),e.jsxs("details",{children:[e.jsx("summary",{children:n("nodes.dockerEnvVars","Environment Variables")}),e.jsx("dl",{className:"docker-management__env-list",children:Object.entries(f.envVars).map(([d,E])=>e.jsxs("div",{children:[e.jsx("dt",{children:d}),e.jsx("dd",{children:mt(d,E)})]},d))})]}),e.jsxs("details",{children:[e.jsx("summary",{children:n("nodes.dockerVolumeMounts","Volume Mounts")}),e.jsx("ul",{className:"docker-management__mounts-list",children:f.volumeMounts.map(d=>e.jsxs("li",{children:[e.jsxs("span",{children:[d.hostPath," → ",d.containerPath]}),d.readOnly&&e.jsx("span",{className:"node-card__type-badge",children:n("nodes.readOnly","Read-only")})]},`${d.hostPath}:${d.containerPath}`))})]})]}),a.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:n("nodes.sectionSettingsSync","Settings Sync")}),g&&e.jsxs("div",{className:"node-detail-modal__sync-status",children:[e.jsx("span",{className:`node-detail-modal__sync-dot ${ct(g.syncState)}`,"aria-hidden":!0}),e.jsxs("span",{children:[n("nodes.syncLastSync","Last sync:")," ",e.jsx("strong",{children:g.lastSyncAt?Se(g.lastSyncAt):n("nodes.syncNeverSynced","Never synced")})]}),g.diffCount>0&&e.jsxs("span",{className:"node-detail-modal__sync-diff",children:[n("nodes.syncDifferences","Differences:")," ",e.jsx("strong",{children:g.diffCount})]})]}),e.jsxs("div",{className:"node-detail-modal__sync-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:es,disabled:Z||!N,children:[e.jsx(Xe,{size:14}),Z?n("nodes.pushing","Pushing..."):n("nodes.pushSettings","Push Settings")]}),e.jsxs("button",{className:"btn btn-sm",onClick:ss,disabled:G||!h,children:[e.jsx(Ye,{size:14}),G?n("nodes.pulling","Pulling..."):n("nodes.pullSettings","Pull Settings")]}),e.jsxs("button",{className:"btn btn-sm",onClick:ts,disabled:L||!u,children:[e.jsx(Be,{size:14}),L?n("nodes.syncing","Syncing..."):n("nodes.syncAuth","Sync Auth")]})]}),D&&e.jsxs("div",{className:"node-detail-modal__sync-error",children:[e.jsx("span",{children:D}),e.jsx("button",{className:"node-detail-modal__sync-error-dismiss",onClick:ns,"aria-label":n("nodes.dismissError","Dismiss error"),children:e.jsx(he,{size:14})})]})]}),a.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:n("nodes.sectionSyncHistory","Sync History")}),e.jsx(at,{nodeId:a.id,entries:C,singleNode:!0})]})]}),e.jsxs("div",{className:"modal-actions node-detail-modal__actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:Qe,children:[e.jsx(Te,{size:14}),n("nodes.healthCheckButton","Health Check")]}),e.jsx("button",{className:"btn btn-sm",onClick:i,children:n("nodes.closeButton","Close")})]})]}),a.type==="remote"&&e.jsx(rt,{isOpen:U,onClose:()=>oe(!1),onResolve:S??(async()=>{}),conflicts:re,localNodeName:n("nodes.localNodeName","Local"),remoteNodeName:a.name,addToast:o})]})}const ft=15e3,gt=1e3;function pt(){const[t,i]=s.useState([]),[a,c]=s.useState(!0),[r,m]=s.useState(null),o=s.useRef(null),g=s.useRef(0),N=s.useRef(t),h=Ke();s.useEffect(()=>{N.current=t},[t]);const u=s.useCallback(j=>N.current.length>0&&Ue(j,h.wasRecentlyHidden()),[h]),C=s.useCallback(async()=>{try{m(null);const j=await $e();i(j)}catch(j){const b=j instanceof Error?j.message:"Failed to fetch managed Docker nodes";u(b)||m(b)}},[u]);s.useEffect(()=>{let j=!1;async function b(){c(!0);try{const y=await $e();j||(i(y),m(null))}catch(y){const n=y instanceof Error?y.message:"Failed to fetch managed Docker nodes";!j&&!u(n)&&m(n)}finally{j||c(!1)}}b();const l=()=>{if(document.visibilityState!=="visible")return;const y=Date.now(),n=y-g.current;if(n<gt){fe({view:"useManagedDockerNodes",trigger:"visibility",projectId:void 0,replayAttempted:!1,reason:"debounce-skipped",detail:{timeSinceLastRefreshMs:n}});return}g.current=y,fe({view:"useManagedDockerNodes",trigger:"visibility",projectId:void 0,replayAttempted:!1,reason:"debounced-refresh"}),C()};return document.addEventListener("visibilitychange",l),()=>{j=!0,document.removeEventListener("visibilitychange",l)}},[C,u]),s.useEffect(()=>{if(!a)return o.current=setInterval(()=>{C()},ft),()=>{o.current&&(clearInterval(o.current),o.current=null)}},[a,C]);const S=s.useCallback(async j=>_s(j),[]),f=s.useCallback(async(j,b)=>(await Ns(j,b)).logs,[]),P=s.useCallback(async j=>{const b=await Cs(j),l={...b,nodeId:b.nodeId??void 0,containerId:b.containerId??void 0,status:b.status,hostConfig:{type:b.hostConfig.host||b.hostConfig.context?"remote":"local",host:b.hostConfig.host,context:b.hostConfig.context},reachableUrl:b.reachableUrl??void 0,volumeMounts:b.volumeMounts.map(y=>({hostPath:y.hostPath,containerPath:y.containerPath,readOnly:y.mode==="ro"?!0:void 0})),persistentStorage:b.persistentStorage,resourceSizing:{cpuLimit:b.resourceSizing.cpus!==void 0?String(b.resourceSizing.cpus):void 0,memoryLimit:b.resourceSizing.memoryMB!==void 0?`${b.resourceSizing.memoryMB}MB`:void 0},errorMessage:b.errorMessage??void 0};return i(y=>[...y,l]),l},[]);return{dockerNodes:t,loading:a,error:r,refresh:C,getContainerStatus:S,getLogs:f,create:P}}function Ct({addToast:t,onClose:i}){const{t:a}=ne("app"),{nodes:c,loading:r,error:m,refresh:o,register:g,update:N,unregister:h,healthCheck:u,patchDockerConfig:C,fetchDockerDiff:S,discoverRemoteProjects:f}=Ss(),{projects:P,refresh:j}=Ms(),{meshState:b,loading:l,error:y}=zs(),{syncStatusMap:n,pushSettings:M,pullSettings:I,syncAuth:O,trackNode:R,getAuthSyncState:k,getAuthProviders:p}=Fs(),{dockerNodes:w,loading:Q,refresh:q,getContainerStatus:X,getLogs:se,create:B}=pt(),[J,Z]=s.useState(!1),[ae,G]=s.useState(!1),[T,L]=s.useState(null);s.useEffect(()=>{const A=c.filter(V=>V.type==="remote");for(const V of A)R(V.id)},[c,R]),s.useEffect(()=>{if(!T)return;const A=c.find(V=>V.id===T.id)??null;L(A)},[c,T]);const _=s.useMemo(()=>{const A=c.length,V=c.filter(Y=>Y.status==="online").length,W=c.filter(Y=>Y.status==="offline"||Y.status==="error").length,x=c.filter(Y=>Y.type==="remote").length,K=c.filter(Y=>Y.type==="remote"&&n[Y.id]&&be(n[Y.id]).syncState==="synced").length,H=w.length;return{total:A,online:V,offline:W,remote:x,synced:K,docker:H}},[w.length,c,n]),D=s.useCallback(async A=>{await g(A),await j()},[j,g]),F=s.useCallback(async A=>{try{await B(A),t(a("nodes.dockerNodeCreated",'Docker node "{{name}}" created',{name:A.name}),"success"),G(!1)}catch(V){const W=V instanceof Error?V.message:a("nodes.failedCreateDocker","Failed to create Docker node");throw t(W,"error"),V}},[t,B,a]),U=s.useMemo(()=>{const A=new Map;for(const V of w)V.nodeId&&A.set(V.nodeId,V);return A},[w]),oe=s.useCallback(async()=>{try{await Promise.all([o(),q()])}catch{t(a("nodes.failedRefresh","Failed to refresh nodes"),"error")}},[t,o,q,a]),re=s.useCallback(async A=>{try{await u(A),t(a("nodes.healthCheckComplete","Node health check complete"),"success")}catch(V){const W=V instanceof Error?V.message:a("nodes.healthCheckFailed","Health check failed");t(W,"error")}},[t,u,a]),te=s.useCallback(async A=>{try{await h(A),t(a("nodes.removed","Node removed"),"success"),T?.id===A&&L(null)}catch(V){const W=V instanceof Error?V.message:a("nodes.failedRemove","Failed to remove node");t(W,"error")}},[t,T?.id,h,a]),ce=s.useCallback(async(A,V)=>{await N(A,V)},[N]);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(Oe,{size:20}),a("nodes.heading","Nodes")]}),e.jsx("span",{className:"nodes-view-count",children:a("nodes.registeredCount","{{count}} registered",{count:c.length})})]}),e.jsxs("div",{className:"nodes-view-actions",children:[e.jsx("button",{className:"btn-icon nodes-view-close",onClick:i,"aria-label":a("nodes.closeAriaLabel","Close nodes view"),children:e.jsx(he,{size:16})}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void oe(),disabled:r||Q,children:[e.jsx(Ce,{size:14,className:r?"spin":""}),a("nodes.refresh","Refresh")]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>Z(!0),children:[e.jsx(ge,{size:14}),a("nodes.addNode","Add Node")]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>G(!0),title:a("nodes.addDockerNodeTitle","Add a managed Docker node"),children:[e.jsx(_e,{size:14}),a("nodes.addDockerNode","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:a("nodes.total","Total")}),e.jsx("strong",{children:_.total})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--online","data-testid":"nodes-stat-online",children:[e.jsxs("span",{children:[e.jsx(As,{size:14})," ",a("nodes.online","Online")]}),e.jsx("strong",{children:_.online})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--offline","data-testid":"nodes-stat-offline",children:[e.jsxs("span",{children:[e.jsx(Es,{size:14})," ",a("nodes.offline","Offline")]}),e.jsx("strong",{children:_.offline})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-remote",children:[e.jsxs("span",{children:[e.jsx(Ps,{size:14})," ",a("nodes.remote","Remote")]}),e.jsx("strong",{children:_.remote})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--synced","data-testid":"nodes-stat-synced",children:[e.jsxs("span",{children:[e.jsx(Ce,{size:14})," ",a("nodes.synced","Synced")]}),e.jsx("strong",{children:_.synced})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-docker",children:[e.jsxs("span",{children:[e.jsx(_e,{size:14})," ",a("nodes.docker","Docker")]}),e.jsx("strong",{children:_.docker})]})]}),(m||y)&&e.jsx("div",{className:"nodes-view-error",children:m??y}),!l&&b.length>0&&e.jsxs("section",{className:"nodes-view-topology","aria-label":a("nodes.meshTopologyAriaLabel","Mesh Topology"),children:[e.jsx("h3",{className:"nodes-view-section-title",children:a("nodes.meshTopology","Mesh Topology")}),e.jsx(Ws,{nodes:b})]}),r?e.jsx("div",{className:"nodes-view-grid",children:Array.from({length:4}).map((A,V)=>e.jsx("div",{className:"node-card node-card--loading","aria-hidden":!0},V))}):c.length===0?e.jsxs("div",{className:"nodes-view-empty",children:[e.jsx("p",{children:a("nodes.noRegistered","No nodes are registered yet.")}),e.jsxs("button",{className:"btn btn-primary",onClick:()=>Z(!0),children:[e.jsx(ge,{size:14}),a("nodes.addFirstNode","Add First Node")]})]}):e.jsx("div",{className:"nodes-view-grid",children:c.map(A=>{const V=A.type==="remote"&&n[A.id]?be(n[A.id]):void 0;return e.jsx(qs,{node:A,projects:P,onHealthCheck:W=>{re(W)},onEdit:W=>L(W),onRemove:W=>{te(W)},isLoading:r,syncStatus:V,authSyncState:A.type==="remote"?k(A.id):void 0,authSyncProviders:A.type==="remote"?p(A.id):void 0,managedDockerNode:U.get(A.id)},A.id)})}),e.jsx(Qs,{isOpen:J,onClose:()=>Z(!1),onSubmit:D,onDiscoverRemoteProjects:f,addToast:t,projects:P}),e.jsx(nt,{isOpen:ae,onClose:()=>G(!1),onSubmit:F,addToast:t}),e.jsx(ht,{isOpen:T!==null,onClose:()=>L(null),node:T,projects:P,onUpdate:ce,onHealthCheck:re,addToast:t,syncStatus:T?.type==="remote"&&T&&n[T.id]?be(n[T.id]):void 0,onPushSettings:M,onPullSettings:I,onSyncAuth:O,managedDockerNode:T?U.get(T.id):void 0,onFetchContainerStatus:X,onFetchLogs:se,onUpdateDockerConfig:C,onFetchDockerConfigDiff:S})]})}export{Ct as NodesView};
@@ -1,4 +1,4 @@
1
- import{r as l,j as e}from"./vendor-react-D37HfzIf.js";import{c as G,ga as V,gb as Y,gc as Z,R as L,g1 as y,J as T,a as ee,b as se,U as ae,F as D,gd as ie,ge as ne,gf as B,X as te}from"./index-CgfrecpF.js";import{u as re}from"./vendor-i18n-CV0mwX_-.js";import{B as _}from"./AgentPermissionPolicyEditor-VDXL4XQc.js";import"./vendor-reactflow-CRZcPCXF.js";import"./vendor-xterm-tcedd2Jt.js";import"./vendor-codemirror-jBKmHyH0.js";/**
1
+ import{r as l,j as e}from"./vendor-react-D37HfzIf.js";import{c as G,gd as V,ge as Y,gf as Z,R as L,g4 as y,J as T,a as ee,b as se,U as ae,F as D,gg as ie,gh as ne,gi as B,X as te}from"./index-bZCpHtGq.js";import{u as re}from"./vendor-i18n-CV0mwX_-.js";import{B as _}from"./AgentPermissionPolicyEditor-DMDUhF1n.js";import"./vendor-reactflow-CRZcPCXF.js";import"./vendor-xterm-tcedd2Jt.js";import"./vendor-codemirror-jBKmHyH0.js";/**
2
2
  * @license lucide-react v1.7.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -8,4 +8,4 @@ import{r as l,j as e}from"./vendor-react-D37HfzIf.js";import{c as G,ga as V,gb a
8
8
  *
9
9
  * This source code is licensed under the ISC license.
10
10
  * See the LICENSE file in the root directory of this source tree.
11
- */const ce=[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]],A=G("puzzle",ce);function oe(n){return n.replace(/-/g,"-")}function de(n){return{"fusion-global":"Fusion Global","pi-global":"Pi Global","fusion-project":"Fusion Project","pi-project":"Pi Project",package:"Package"}[n]??n}function pe(n){return n.startsWith("npm:")?"npm":n.startsWith("git:")?"git":"local"}function xe(n){return n.replace(/^(npm:|git:)/,"")}function ve({addToast:n,projectId:x}){const{t:a}=re("app"),[c,I]=l.useState(null),[N,P]=l.useState(!0),[v,E]=l.useState(!1),[S,F]=l.useState(!1),[u,w]=l.useState(""),[O,U]=l.useState(new Set),[m,W]=l.useState([]),[b,R]=l.useState(!0),[q,C]=l.useState(!1),o=l.useCallback(async()=>{try{P(!0);const s=await V();I(s)}catch(s){n(a("piManager.loadSettingsFailed","Failed to load Pi settings: {{error}}",{error:s instanceof Error?s.message:String(s)}),"error")}finally{P(!1)}},[n,a]),g=l.useCallback(async()=>{try{R(!0);const s=await Y(x);W(s.extensions)}catch(s){n(a("piManager.loadExtensionsFailed","Failed to load extensions: {{error}}",{error:s instanceof Error?s.message:String(s)}),"error")}finally{R(!1)}},[n,x,a]),H=l.useCallback(async s=>{try{C(!0);const t=s.enabled?[...m.filter(i=>i.enabled&&i.id!==s.id).map(i=>i.id),s.id]:m.filter(i=>i.enabled&&i.id!==s.id).map(i=>i.id);await Z(t,x),await g(),n(s.enabled?a("piManager.extensionDisabled","Extension disabled"):a("piManager.extensionEnabled","Extension enabled"),"success")}catch(t){n(a("piManager.updateFailed","Failed to update extension: {{error}}",{error:t instanceof Error?t.message:String(t)}),"error")}finally{C(!1)}},[m,x,g,n,a]);l.useEffect(()=>{o()},[o]),l.useEffect(()=>{g()},[g]);const J=s=>{U(t=>{const i=new Set(t);return i.has(s)?i.delete(s):i.add(s),i})},z=async()=>{if(!u.trim()){n(a("piManager.enterSource","Please enter a package source"),"error");return}try{E(!0),await ie(u.trim()),n(a("piManager.installSuccess","Package installed successfully"),"success"),w(""),await o()}catch(s){n(a("piManager.installFailed","Failed to install package: {{error}}",{error:s instanceof Error?s.message:String(s)}),"error")}finally{E(!1)}},K=async()=>{try{F(!0),await ne(x),await Promise.all([o(),g()]),n(a("piManager.reinstallSuccess","Fusion skill reinstalled successfully"),"success")}catch(s){n(a("piManager.reinstallFailed","Failed to reinstall Fusion skill: {{error}}",{error:s instanceof Error?s.message:String(s)}),"error")}finally{F(!1)}},X=async s=>{if(!c)return;const t=c.packages.filter(i=>(typeof i=="string"?i:i.source)!==s);try{await B({packages:t}),n(a("piManager.packageRemoved","Package removed"),"success"),await o()}catch(i){n(a("piManager.removeFailed","Failed to remove package: {{error}}",{error:i instanceof Error?i.message:String(i)}),"error")}},Q=async(s,t)=>{if(!c)return;const i=c[s].filter(r=>r!==t);try{await B({[s]:i});const r=a(`piManager.resourceType.${s.slice(0,-1)}`,s.slice(0,-1));n(a("piManager.resourceRemoved","{{resource}} removed",{resource:r}),"success"),await o()}catch(r){n(a("piManager.updateSettingsFailed","Failed to update settings: {{error}}",{error:r instanceof Error?r.message:String(r)}),"error")}},h=(s,t,i)=>!c||c[i].length===0?null:e.jsxs("div",{className:"pi-ext-section",children:[e.jsxs("div",{className:"pi-ext-section-header",children:[e.jsx(t,{size:14}),e.jsx("span",{children:s}),e.jsx("span",{className:"pi-ext-count",children:c[i].length})]}),e.jsx("div",{className:"pi-ext-resource-list",children:c[i].map((r,f)=>e.jsxs("span",{className:"pi-ext-resource-tag",children:[e.jsx("span",{className:"pi-ext-resource-path",children:r}),e.jsx("button",{className:"btn-icon touch-target pi-ext-resource-remove",onClick:()=>Q(i,r),title:a("piManager.removeResource","Remove {{path}}",{path:r}),"aria-label":a("piManager.removeResource","Remove {{path}}",{path:r}),children:e.jsx(te,{})})]},f))})]});return e.jsxs("div",{className:"pi-ext-manager",children:[e.jsxs("div",{className:"pi-ext-manager-header",children:[e.jsx("h4",{className:"pi-ext-manager-title",children:a("piManager.title","Pi Extensions")}),e.jsx("div",{className:"pi-ext-manager-actions",children:e.jsx("button",{className:"btn-icon",onClick:o,title:a("piManager.refreshButton","Refresh"),disabled:N,children:e.jsx(L,{size:16,className:N?"spin":""})})})]}),N?e.jsx("div",{className:"loading-state",children:a("piManager.loading","Loading Pi settings…")}):c?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"pi-ext-add-form",children:[e.jsxs("div",{className:"pi-ext-add-form-row",children:[e.jsx("input",{type:"text",className:"input",placeholder:a("piManager.packagePlaceholder","npm:pi-extension-name or git:https://github.com/..."),value:u,onChange:s=>w(s.target.value),onKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),z())},disabled:v}),e.jsxs("button",{className:"btn btn-primary",onClick:z,disabled:v||!u.trim(),children:[e.jsx(T,{size:14}),v?a("piManager.installing","Installing…"):a("piManager.addButton","Add")]})]}),e.jsx("div",{className:"pi-ext-add-form-row",children:e.jsx("button",{className:"btn",onClick:K,disabled:S,children:S?a("piManager.reinstalling","Reinstalling Fusion…"):a("piManager.reinstallButton","Reinstall Fusion skill")})})]}),c.packages.length>0?e.jsx("div",{className:"pi-ext-package-list",children:c.packages.map((s,t)=>{const i=typeof s=="string"?s:s.source,r=pe(i),f=xe(i),j=typeof s=="object"&&s!==null,k=j&&(s.extensions?.length??0)>0||(s.skills?.length??0)>0||(s.prompts?.length??0)>0||(s.themes?.length??0)>0,M=O.has(t);return e.jsxs("div",{className:"pi-ext-package-card",children:[e.jsxs("div",{className:"pi-ext-package-header",children:[j&&k?e.jsx("button",{className:"pi-ext-expand-btn",onClick:()=>J(t),"aria-expanded":M,children:M?e.jsx(ee,{size:14}):e.jsx(se,{size:14})}):e.jsx("span",{className:"pi-ext-expand-placeholder"}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${r}`,children:r}),e.jsx("span",{className:"pi-ext-package-source",children:f}),e.jsxs("div",{className:"pi-ext-package-actions",children:[j&&k&&e.jsxs("span",{className:"pi-ext-filter-hint",children:[s.extensions?.length??0," ext,"," ",s.skills?.length??0," skill,"," ",s.prompts?.length??0," prompt,"," ",s.themes?.length??0," theme"]}),e.jsx("button",{className:"btn-icon touch-target pi-ext-remove-btn",onClick:()=>X(i),title:a("piManager.removePackage","Remove package"),"aria-label":a("piManager.removePackageLabel","Remove package {{label}}",{label:f}),children:e.jsx(ae,{size:14})})]})]}),j&&k&&M&&e.jsxs("div",{className:"pi-ext-filter-list",children:[s.extensions?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(A,{size:12}),e.jsxs("span",{className:"pi-ext-filter-label",children:[a("piManager.filterExtensions","Extensions:")," "]}),s.extensions.map((d,p)=>e.jsx("span",{className:"pi-ext-filter-tag",children:d},p))]}):null,s.skills?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(_,{size:12}),e.jsxs("span",{className:"pi-ext-filter-label",children:[a("piManager.filterSkills","Skills:")," "]}),s.skills.map((d,p)=>e.jsx("span",{className:"pi-ext-filter-tag",children:d},p))]}):null,s.prompts?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(D,{size:12}),e.jsxs("span",{className:"pi-ext-filter-label",children:[a("piManager.filterPrompts","Prompts:")," "]}),s.prompts.map((d,p)=>e.jsx("span",{className:"pi-ext-filter-tag",children:d},p))]}):null,s.themes?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx($,{size:12}),e.jsxs("span",{className:"pi-ext-filter-label",children:[a("piManager.filterThemes","Themes:")," "]}),s.themes.map((d,p)=>e.jsx("span",{className:"pi-ext-filter-tag",children:d},p))]}):null]})]},t)})}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:a("piManager.noPackages","No packages configured.")}),e.jsx("p",{className:"text-muted",children:a("piManager.noPackagesHelp","Add a package source above to get started.")})]}),e.jsxs("div",{className:"pi-ext-top-level",children:[h(a("piManager.sectionExtensions","Extensions"),A,"extensions"),h(a("piManager.sectionSkills","Skills"),_,"skills"),h(a("piManager.sectionPrompts","Prompts"),D,"prompts"),h(a("piManager.sectionThemes","Themes"),$,"themes")]})]}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:a("piManager.loadingFailed","Failed to load Pi settings.")})]}),e.jsxs("div",{className:"pi-ext-discovered-section",children:[e.jsxs("div",{className:"pi-ext-discovered-header",children:[e.jsx("h4",{children:a("piManager.discoveredTitle","Discovered Extensions")}),e.jsx("button",{className:"btn-icon",onClick:g,disabled:b,title:a("piManager.refreshExtensions","Refresh extensions"),children:e.jsx(L,{className:b?"spin":""})})]}),e.jsx("p",{className:"pi-ext-description",children:a("piManager.discoveredDescription","Installed extensions resolved from packages and configured paths.")}),b?e.jsx("div",{className:"loading-state",children:a("piManager.loadingExtensions","Loading extensions…")}):m.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:a("piManager.noExtensions","No extensions discovered.")})]}):e.jsx("div",{className:"pi-ext-list",children:m.map(s=>e.jsxs("div",{className:"pi-ext-item",children:[e.jsxs("div",{className:"pi-ext-item-content",children:[e.jsxs("div",{className:"pi-ext-info",children:[e.jsx("span",{className:"pi-ext-name",children:s.name}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${oe(s.source)}`,children:de(s.source)})]}),e.jsx("span",{className:"pi-ext-path",children:s.path})]}),e.jsx("div",{className:"pi-ext-actions",children:e.jsxs("label",{className:"toggle-switch",children:[e.jsx("input",{type:"checkbox",checked:s.enabled,onChange:()=>void H(s),disabled:q,"aria-label":a("piManager.toggleExtension","Toggle {{name}}",{name:s.name})}),e.jsx("span",{className:"toggle-slider"})]})})]},s.id))})]})]})}export{ve as PiExtensionsManager};
11
+ */const ce=[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]],A=G("puzzle",ce);function oe(n){return n.replace(/-/g,"-")}function de(n){return{"fusion-global":"Fusion Global","pi-global":"Pi Global","fusion-project":"Fusion Project","pi-project":"Pi Project",package:"Package"}[n]??n}function pe(n){return n.startsWith("npm:")?"npm":n.startsWith("git:")?"git":"local"}function xe(n){return n.replace(/^(npm:|git:)/,"")}function ve({addToast:n,projectId:x}){const{t:a}=re("app"),[c,I]=l.useState(null),[N,P]=l.useState(!0),[v,E]=l.useState(!1),[S,F]=l.useState(!1),[h,w]=l.useState(""),[O,U]=l.useState(new Set),[m,W]=l.useState([]),[b,R]=l.useState(!0),[q,C]=l.useState(!1),o=l.useCallback(async()=>{try{P(!0);const s=await V();I(s)}catch(s){n(a("piManager.loadSettingsFailed","Failed to load Pi settings: {{error}}",{error:s instanceof Error?s.message:String(s)}),"error")}finally{P(!1)}},[n,a]),g=l.useCallback(async()=>{try{R(!0);const s=await Y(x);W(s.extensions)}catch(s){n(a("piManager.loadExtensionsFailed","Failed to load extensions: {{error}}",{error:s instanceof Error?s.message:String(s)}),"error")}finally{R(!1)}},[n,x,a]),H=l.useCallback(async s=>{try{C(!0);const t=s.enabled?[...m.filter(i=>i.enabled&&i.id!==s.id).map(i=>i.id),s.id]:m.filter(i=>i.enabled&&i.id!==s.id).map(i=>i.id);await Z(t,x),await g(),n(s.enabled?a("piManager.extensionDisabled","Extension disabled"):a("piManager.extensionEnabled","Extension enabled"),"success")}catch(t){n(a("piManager.updateFailed","Failed to update extension: {{error}}",{error:t instanceof Error?t.message:String(t)}),"error")}finally{C(!1)}},[m,x,g,n,a]);l.useEffect(()=>{o()},[o]),l.useEffect(()=>{g()},[g]);const J=s=>{U(t=>{const i=new Set(t);return i.has(s)?i.delete(s):i.add(s),i})},z=async()=>{if(!h.trim()){n(a("piManager.enterSource","Please enter a package source"),"error");return}try{E(!0),await ie(h.trim()),n(a("piManager.installSuccess","Package installed successfully"),"success"),w(""),await o()}catch(s){n(a("piManager.installFailed","Failed to install package: {{error}}",{error:s instanceof Error?s.message:String(s)}),"error")}finally{E(!1)}},K=async()=>{try{F(!0),await ne(x),await Promise.all([o(),g()]),n(a("piManager.reinstallSuccess","Fusion skill reinstalled successfully"),"success")}catch(s){n(a("piManager.reinstallFailed","Failed to reinstall Fusion skill: {{error}}",{error:s instanceof Error?s.message:String(s)}),"error")}finally{F(!1)}},X=async s=>{if(!c)return;const t=c.packages.filter(i=>(typeof i=="string"?i:i.source)!==s);try{await B({packages:t}),n(a("piManager.packageRemoved","Package removed"),"success"),await o()}catch(i){n(a("piManager.removeFailed","Failed to remove package: {{error}}",{error:i instanceof Error?i.message:String(i)}),"error")}},Q=async(s,t)=>{if(!c)return;const i=c[s].filter(r=>r!==t);try{await B({[s]:i});const r=a(`piManager.resourceType.${s.slice(0,-1)}`,s.slice(0,-1));n(a("piManager.resourceRemoved","{{resource}} removed",{resource:r}),"success"),await o()}catch(r){n(a("piManager.updateSettingsFailed","Failed to update settings: {{error}}",{error:r instanceof Error?r.message:String(r)}),"error")}},u=(s,t,i)=>!c||c[i].length===0?null:e.jsxs("div",{className:"pi-ext-section",children:[e.jsxs("div",{className:"pi-ext-section-header",children:[e.jsx(t,{size:14}),e.jsx("span",{children:s}),e.jsx("span",{className:"pi-ext-count",children:c[i].length})]}),e.jsx("div",{className:"pi-ext-resource-list",children:c[i].map((r,f)=>e.jsxs("span",{className:"pi-ext-resource-tag",children:[e.jsx("span",{className:"pi-ext-resource-path",children:r}),e.jsx("button",{className:"btn-icon touch-target pi-ext-resource-remove",onClick:()=>Q(i,r),title:a("piManager.removeResource","Remove {{path}}",{path:r}),"aria-label":a("piManager.removeResource","Remove {{path}}",{path:r}),children:e.jsx(te,{})})]},f))})]});return e.jsxs("div",{className:"pi-ext-manager",children:[e.jsxs("div",{className:"pi-ext-manager-header",children:[e.jsx("h4",{className:"pi-ext-manager-title",children:a("piManager.title","Pi Extensions")}),e.jsx("div",{className:"pi-ext-manager-actions",children:e.jsx("button",{className:"btn-icon",onClick:o,title:a("piManager.refreshButton","Refresh"),disabled:N,children:e.jsx(L,{size:16,className:N?"spin":""})})})]}),N?e.jsx("div",{className:"loading-state",children:a("piManager.loading","Loading Pi settings…")}):c?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"pi-ext-add-form",children:[e.jsxs("div",{className:"pi-ext-add-form-row",children:[e.jsx("input",{type:"text",className:"input",placeholder:a("piManager.packagePlaceholder","npm:pi-extension-name or git:https://github.com/..."),value:h,onChange:s=>w(s.target.value),onKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),z())},disabled:v}),e.jsxs("button",{className:"btn btn-primary",onClick:z,disabled:v||!h.trim(),children:[e.jsx(T,{size:14}),v?a("piManager.installing","Installing…"):a("piManager.addButton","Add")]})]}),e.jsx("div",{className:"pi-ext-add-form-row",children:e.jsx("button",{className:"btn",onClick:K,disabled:S,children:S?a("piManager.reinstalling","Reinstalling Fusion…"):a("piManager.reinstallButton","Reinstall Fusion skill")})})]}),c.packages.length>0?e.jsx("div",{className:"pi-ext-package-list",children:c.packages.map((s,t)=>{const i=typeof s=="string"?s:s.source,r=pe(i),f=xe(i),j=typeof s=="object"&&s!==null,k=j&&(s.extensions?.length??0)>0||(s.skills?.length??0)>0||(s.prompts?.length??0)>0||(s.themes?.length??0)>0,M=O.has(t);return e.jsxs("div",{className:"pi-ext-package-card",children:[e.jsxs("div",{className:"pi-ext-package-header",children:[j&&k?e.jsx("button",{className:"pi-ext-expand-btn",onClick:()=>J(t),"aria-expanded":M,children:M?e.jsx(ee,{size:14}):e.jsx(se,{size:14})}):e.jsx("span",{className:"pi-ext-expand-placeholder"}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${r}`,children:r}),e.jsx("span",{className:"pi-ext-package-source",children:f}),e.jsxs("div",{className:"pi-ext-package-actions",children:[j&&k&&e.jsxs("span",{className:"pi-ext-filter-hint",children:[s.extensions?.length??0," ext,"," ",s.skills?.length??0," skill,"," ",s.prompts?.length??0," prompt,"," ",s.themes?.length??0," theme"]}),e.jsx("button",{className:"btn-icon touch-target pi-ext-remove-btn",onClick:()=>X(i),title:a("piManager.removePackage","Remove package"),"aria-label":a("piManager.removePackageLabel","Remove package {{label}}",{label:f}),children:e.jsx(ae,{size:14})})]})]}),j&&k&&M&&e.jsxs("div",{className:"pi-ext-filter-list",children:[s.extensions?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(A,{size:12}),e.jsxs("span",{className:"pi-ext-filter-label",children:[a("piManager.filterExtensions","Extensions:")," "]}),s.extensions.map((d,p)=>e.jsx("span",{className:"pi-ext-filter-tag",children:d},p))]}):null,s.skills?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(_,{size:12}),e.jsxs("span",{className:"pi-ext-filter-label",children:[a("piManager.filterSkills","Skills:")," "]}),s.skills.map((d,p)=>e.jsx("span",{className:"pi-ext-filter-tag",children:d},p))]}):null,s.prompts?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(D,{size:12}),e.jsxs("span",{className:"pi-ext-filter-label",children:[a("piManager.filterPrompts","Prompts:")," "]}),s.prompts.map((d,p)=>e.jsx("span",{className:"pi-ext-filter-tag",children:d},p))]}):null,s.themes?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx($,{size:12}),e.jsxs("span",{className:"pi-ext-filter-label",children:[a("piManager.filterThemes","Themes:")," "]}),s.themes.map((d,p)=>e.jsx("span",{className:"pi-ext-filter-tag",children:d},p))]}):null]})]},t)})}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:a("piManager.noPackages","No packages configured.")}),e.jsx("p",{className:"text-muted",children:a("piManager.noPackagesHelp","Add a package source above to get started.")})]}),e.jsxs("div",{className:"pi-ext-top-level",children:[u(a("piManager.sectionExtensions","Extensions"),A,"extensions"),u(a("piManager.sectionSkills","Skills"),_,"skills"),u(a("piManager.sectionPrompts","Prompts"),D,"prompts"),u(a("piManager.sectionThemes","Themes"),$,"themes")]})]}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:a("piManager.loadingFailed","Failed to load Pi settings.")})]}),e.jsxs("div",{className:"pi-ext-discovered-section",children:[e.jsxs("div",{className:"pi-ext-discovered-header",children:[e.jsx("h4",{children:a("piManager.discoveredTitle","Discovered Extensions")}),e.jsx("button",{className:"btn-icon",onClick:g,disabled:b,title:a("piManager.refreshExtensions","Refresh extensions"),children:e.jsx(L,{className:b?"spin":""})})]}),e.jsx("p",{className:"pi-ext-description",children:a("piManager.discoveredDescription","Installed extensions resolved from packages and configured paths.")}),b?e.jsx("div",{className:"loading-state",children:a("piManager.loadingExtensions","Loading extensions…")}):m.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:a("piManager.noExtensions","No extensions discovered.")})]}):e.jsx("div",{className:"pi-ext-list",children:m.map(s=>e.jsxs("div",{className:"pi-ext-item",children:[e.jsxs("div",{className:"pi-ext-item-content",children:[e.jsxs("div",{className:"pi-ext-info",children:[e.jsx("span",{className:"pi-ext-name",children:s.name}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${oe(s.source)}`,children:de(s.source)})]}),e.jsx("span",{className:"pi-ext-path",children:s.path})]}),e.jsx("div",{className:"pi-ext-actions",children:e.jsxs("label",{className:"toggle-switch",children:[e.jsx("input",{type:"checkbox",checked:s.enabled,onChange:()=>void H(s),disabled:q,"aria-label":a("piManager.toggleExtension","Toggle {{name}}",{name:s.name})}),e.jsx("span",{className:"toggle-slider"})]})})]},s.id))})]})]})}export{ve as PiExtensionsManager};