@runfusion/fusion 0.44.0 → 0.46.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.
- package/README.md +2 -1
- package/dist/bin.js +7431 -2240
- package/dist/client/.vite/manifest.json +1118 -331
- package/dist/client/assets/AgentDetailView-CgbB51Iw.css +1 -0
- package/dist/client/assets/AgentDetailView-D1cA9Bfj.js +18 -0
- package/dist/client/assets/{AgentPermissionPolicyEditor--YS4iMUY.js → AgentPermissionPolicyEditor-DE0wv8-L.js} +2 -2
- package/dist/client/assets/AgentsView-Bm_FA_1w.js +29 -0
- package/dist/client/assets/AgentsView-CzMa5Olf.css +1 -0
- package/dist/client/assets/ChatView-BtjkE0V7.css +1 -0
- package/dist/client/assets/ChatView-CHEkov6q.js +19 -0
- package/dist/client/assets/CommandCenter-Cfgek-dC.js +71 -0
- package/dist/client/assets/CommandCenter-DDjpYkPe.css +1 -0
- package/dist/client/assets/DevServerView-DgDksVH2.css +1 -0
- package/dist/client/assets/DevServerView-_or2KLVw.js +1 -0
- package/dist/client/assets/DirectoryPicker-etVwa-6X.js +1 -0
- package/dist/client/assets/DocumentsView-e8ZTdPIZ.js +1 -0
- package/dist/client/assets/EvalsView-CTbgPUne.css +1 -0
- package/dist/client/assets/EvalsView-CjDRQFMQ.js +1 -0
- package/dist/client/assets/ExperimentalAgentOnboardingModal-3ZEFv8sr.css +1 -0
- package/dist/client/assets/ExperimentalAgentOnboardingModal-DXR0OAsR.js +1 -0
- package/dist/client/assets/GoalsView-CUh8JBnJ.css +1 -0
- package/dist/client/assets/GoalsView-WWDKVslN.js +2 -0
- package/dist/client/assets/InsightsView-C7yRTMPn.css +1 -0
- package/dist/client/assets/InsightsView-DxIfxOzx.js +11 -0
- package/dist/client/assets/MemoryView-BVW2hkWf.js +2 -0
- package/dist/client/assets/MemoryView-CBDUr2Jy.css +1 -0
- package/dist/client/assets/PiExtensionsManager-CpSfMok2.js +11 -0
- package/dist/client/assets/PluginManager-CpBCy656.js +1 -0
- package/dist/client/assets/PullRequestView-BMspX1ga.js +6 -0
- package/dist/client/assets/PullRequestView-CpdE3Yo_.css +1 -0
- package/dist/client/assets/ResearchView--YEtcv_s.js +1 -0
- package/dist/client/assets/ResearchView-DIVNQF4_.css +1 -0
- package/dist/client/assets/SecretsView-CC6QDMWN.js +1 -0
- package/dist/client/assets/SecretsView-CvFioX7R.css +1 -0
- package/dist/client/assets/SessionTerminal-D4R3ScvQ.css +1 -0
- package/dist/client/assets/SessionTerminal-DJGtgIls.js +2 -0
- package/dist/client/assets/SettingsModal-4d_p8D7W.js +1 -0
- package/dist/client/assets/SettingsModal-BESN59Ao.css +1 -0
- package/dist/client/assets/SettingsModal-ino68pI2.css +1 -0
- package/dist/client/assets/SettingsModal-wABa7xmZ.js +21 -0
- package/dist/client/assets/SetupWizardModal-DHe2tXzx.js +2 -0
- package/dist/client/assets/ShadcnColorPicker-HX3j1v66.js +11 -0
- package/dist/client/assets/ShadcnColorPicker-pqVWCC5-.css +1 -0
- package/dist/client/assets/SkillsView-CJ8snrma.css +1 -0
- package/dist/client/assets/SkillsView-mdFVTX-r.js +1 -0
- package/dist/client/assets/TodoView-CIsL_uvQ.css +1 -0
- package/dist/client/assets/TodoView-DQVugDpW.js +6 -0
- package/dist/client/assets/WorkflowNodeEditor-CeERQHHu.js +8 -0
- package/dist/client/assets/WorkflowNodeEditor-f_XPV5Jd.css +1 -0
- package/dist/client/assets/{addon-fit-SnYDEvGm.js → addon-fit-C1WQXRvu.js} +1 -1
- package/dist/client/assets/{addon-unicode11-s5GoZCpi.js → addon-unicode11-BVmNDUBM.js} +1 -1
- package/dist/client/assets/{addon-web-links-jjt2f_oV.js → addon-web-links-CkVew5xs.js} +1 -1
- package/dist/client/assets/{addon-webgl-Icn-RnEx.js → addon-webgl-uLc0RKcC.js} +1 -1
- package/dist/client/assets/agentSkills-C2v1wbxh.js +1 -0
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-CZ_jbgep.css → agentSkills-bQJ4X1gH.css} +1 -1
- package/dist/client/assets/agentsOrgChartLayout-BMvyuaLA.js +1 -0
- package/dist/client/assets/app-BJGkp7Tt.js +13 -0
- package/dist/client/assets/app-BKLUvvm8.js +13 -0
- package/dist/client/assets/app-BaoNC9zg.js +13 -0
- package/dist/client/assets/app-CZQ_fFNf.js +13 -0
- package/dist/client/assets/app-DAu3AzsS.js +13 -0
- package/dist/client/assets/app-DgezOJub.js +13 -0
- package/dist/client/assets/arc-cxkkNsnK.js +1 -0
- package/dist/client/assets/architectureDiagram-3BPJPVTR-CGEhhgX_.js +36 -0
- package/dist/client/assets/band-CquvqAHh.js +1 -0
- package/dist/client/assets/blockDiagram-GPEHLZMM-D0DTo0HT.js +132 -0
- package/dist/client/assets/c4Diagram-AAUBKEIU-DNykNaRb.js +10 -0
- package/dist/client/assets/channel-Dwf1FoGU.js +1 -0
- package/dist/client/assets/chunk-2J33WTMH-5oQfAhmr.js +1 -0
- package/dist/client/assets/chunk-4BX2VUAB-BqLZXgFw.js +1 -0
- package/dist/client/assets/chunk-55IACEB6-C1oIjX3T.js +1 -0
- package/dist/client/assets/chunk-727SXJPM-BaovQTgk.js +206 -0
- package/dist/client/assets/chunk-AQP2D5EJ-B4ikBK42.js +231 -0
- package/dist/client/assets/chunk-FMBD7UC4-5zgtNnG2.js +15 -0
- package/dist/client/assets/chunk-ND2GUHAM-ByrypRna.js +1 -0
- package/dist/client/assets/chunk-QZHKN3VN-B7D1exsu.js +1 -0
- package/dist/client/assets/classDiagram-4FO5ZUOK-WqSUwcK_.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-WqSUwcK_.js +1 -0
- package/dist/client/assets/common-BDp2y6CF.js +1 -0
- package/dist/client/assets/common-BnEo5fLN.js +1 -0
- package/dist/client/assets/common-Bzr_Y8h4.js +1 -0
- package/dist/client/assets/common-CvwyFzfv.js +1 -0
- package/dist/client/assets/common-CztCXRkz.js +1 -0
- package/dist/client/assets/common-DPe2mbb7.js +1 -0
- package/dist/client/assets/cose-bilkent-S5V4N54A-CQmiNzGr.js +1 -0
- package/dist/client/assets/cytoscape.esm-OyMbaexL.js +331 -0
- package/dist/client/assets/dagre-BM42HDAG-BH8Uk0Up.js +4 -0
- package/dist/client/assets/{dashboard-view-B4LXCv5H.js → dashboard-view-CWJ-b59n.js} +1680 -1620
- package/dist/client/assets/dashboard-view-D3PWY2PH.js +1 -0
- package/dist/client/assets/dashboard-view-D_zsA-kz.css +1 -0
- package/dist/client/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/client/assets/diagram-2AECGRRQ-CDoHfkxY.js +43 -0
- package/dist/client/assets/diagram-5GNKFQAL-DARILCuD.js +10 -0
- package/dist/client/assets/diagram-KO2AKTUF-CNP-qi0y.js +3 -0
- package/dist/client/assets/diagram-LMA3HP47-SCiVmkcf.js +24 -0
- package/dist/client/assets/diagram-OG6HWLK6-iTJLXH61.js +24 -0
- package/dist/client/assets/erDiagram-TEJ5UH35-ByMpiPIa.js +85 -0
- package/dist/client/assets/flowDiagram-I6XJVG4X-DW3m3ZpM.js +162 -0
- package/dist/client/assets/{folder-open-33WGVnbp.js → folder-open-G-9vPAdv.js} +1 -1
- package/dist/client/assets/ganttDiagram-6RSMTGT7-BJeYH7Ol.js +292 -0
- package/dist/client/assets/gitGraphDiagram-PVQCEYII-CK_Chj4m.js +106 -0
- package/dist/client/assets/graph--OzhPTMs.js +1 -0
- package/dist/client/assets/index-BZBQ_KsL.css +1 -0
- package/dist/client/assets/index-ccFe_1av.js +1459 -0
- package/dist/client/assets/infoDiagram-5YYISTIA-D8Wg1IgN.js +2 -0
- package/dist/client/assets/init-Dmth1JHB.js +1 -0
- package/dist/client/assets/ishikawaDiagram-YF4QCWOH-DWROR2aX.js +70 -0
- package/dist/client/assets/journeyDiagram-JHISSGLW-Bns9774_.js +139 -0
- package/dist/client/assets/kanban-definition-UN3LZRKU-QtURfAoI.js +89 -0
- package/dist/client/assets/katex-HP8lGamR.js +257 -0
- package/dist/client/assets/layout-SsrduOYp.js +1 -0
- package/dist/client/assets/linear-dXivciGL.js +1 -0
- package/dist/client/assets/mermaid.core-DqgrgWWm.js +309 -0
- package/dist/client/assets/mindmap-definition-RKZ34NQL-jLaDb5_X.js +96 -0
- package/dist/client/assets/ordinal-DILIJJjt.js +1 -0
- package/dist/client/assets/pieDiagram-4H26LBE5-CjbHuIje.js +30 -0
- package/dist/client/assets/quadrantDiagram-W4KKPZXB-xgHbylQr.js +7 -0
- package/dist/client/assets/requirementDiagram-4Y6WPE33-CHdD7W41.js +84 -0
- package/dist/client/assets/sankeyDiagram-5OEKKPKP-C3me87g9.js +40 -0
- package/dist/client/assets/sequenceDiagram-3UESZ5HK-DSHfs1kU.js +162 -0
- package/dist/client/assets/{shield-alert-CqeGWBUK.js → shield-alert-DkGlhVjI.js} +1 -1
- package/dist/client/assets/stateDiagram-AJRCARHV-C08n7sMP.js +1 -0
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-BosoAbfO.js +1 -0
- package/dist/client/assets/step-yuy0qJer.js +1 -0
- package/dist/client/assets/time-DoDTxsna.js +1 -0
- package/dist/client/assets/timeline-definition-PNZ67QCA-C21h9Zqh.js +120 -0
- package/dist/client/assets/{upload-C11J2diI.js → upload-B9B-tYt9.js} +1 -1
- package/dist/client/assets/{users-a-ELbyyZ.js → users-C_BA3C7E.js} +1 -1
- package/dist/client/assets/{vendor-i18n-DYlSUfot.js → vendor-i18n-GF3RlKbq.js} +2 -2
- package/dist/client/assets/{vendor-react-BTgM5bbZ.js → vendor-react-SZ_qB27O.js} +1 -1
- package/dist/client/assets/vendor-reactflow-Bg-Qjzh8.js +15 -0
- package/dist/client/assets/{vendor-xterm-ea7-K05z.js → vendor-xterm-BNq00GSj.js} +1 -1
- package/dist/client/assets/vennDiagram-CIIHVFJN-Bv3G0dwI.js +34 -0
- package/dist/client/assets/wardley-L42UT6IY-WX0hHKcN.js +173 -0
- package/dist/client/assets/wardleyDiagram-YWT4CUSO-CMwIPWm7.js +78 -0
- package/dist/client/assets/xychartDiagram-2RQKCTM6-CZvFdt6j.js +7 -0
- package/dist/client/assets/zoom-out-NWbVkreR.js +41 -0
- package/dist/client/index.html +30 -10
- package/dist/client/sw.js +1 -1
- package/dist/client/theme-data.css +3082 -206
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/index.ts +56 -40
- package/dist/droid-cli/package.json +1 -1
- package/dist/droid-cli/src/__tests__/index.test.ts +47 -21
- package/dist/droid-cli/src/__tests__/process-manager.test.ts +50 -33
- package/dist/extension.js +5405 -919
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/pi-claude-cli/src/__tests__/process-manager.test.ts +25 -0
- package/dist/pi-claude-cli/src/process-manager.ts +11 -1
- package/dist/plugin-sdk/index.d.ts +137 -4
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +68 -44
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/bundled.js +5 -11
- package/dist/plugins/fusion-plugin-roadmap/manifest.json +1 -11
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +3 -3
- package/skill/fusion/SKILL.md +1 -1
- package/skill/fusion/references/cli-commands.md +2 -1
- package/skill/fusion/references/extension-tools.md +10 -0
- package/skill/fusion/references/fusion-capabilities.md +3 -1
- package/dist/client/assets/AgentDetailView-CanIeYHg.css +0 -1
- package/dist/client/assets/AgentDetailView-DxV8pFHX.js +0 -18
- package/dist/client/assets/AgentsView-BVILQjdS.css +0 -1
- package/dist/client/assets/AgentsView-CTzbcvhK.js +0 -29
- package/dist/client/assets/ChatView-COygcnyk.js +0 -6
- package/dist/client/assets/ChatView-DwJAd5G1.css +0 -1
- package/dist/client/assets/CommandCenter-CTaopaC0.css +0 -1
- package/dist/client/assets/CommandCenter-DoKX2HWm.js +0 -56
- package/dist/client/assets/DevServerView-Cyevyvqx.js +0 -1
- package/dist/client/assets/DevServerView-VTQY28P7.css +0 -1
- package/dist/client/assets/DirectoryPicker-DBdyXEhR.js +0 -1
- package/dist/client/assets/DocumentsView-BzSMyrns.js +0 -1
- package/dist/client/assets/DocumentsView-WfVoTZt8.css +0 -1
- package/dist/client/assets/EvalsView-CUNJ1TLc.css +0 -1
- package/dist/client/assets/EvalsView-ikz00o9g.js +0 -1
- package/dist/client/assets/ExperimentalAgentOnboardingModal-D-rzCCET.js +0 -499
- package/dist/client/assets/GoalsView-Bfu1Oy2-.js +0 -2
- package/dist/client/assets/GoalsView-rg9VSIza.css +0 -1
- package/dist/client/assets/InsightsView-Cgmf5nES.js +0 -11
- package/dist/client/assets/InsightsView-LMv1M1dU.css +0 -1
- package/dist/client/assets/MemoryView-DkEuDKQs.js +0 -2
- package/dist/client/assets/MemoryView-zaXewZzi.css +0 -1
- package/dist/client/assets/NodesView-7VInxyf_.css +0 -1
- package/dist/client/assets/NodesView-B_KYfS4o.js +0 -14
- package/dist/client/assets/PiExtensionsManager-Dz69kkKs.js +0 -11
- package/dist/client/assets/PluginManager-LHCVcduP.js +0 -1
- package/dist/client/assets/PullRequestView-3AdbS2a1.css +0 -1
- package/dist/client/assets/PullRequestView-DBJutLLl.js +0 -6
- package/dist/client/assets/ResearchView-DTh8FLUm.css +0 -1
- package/dist/client/assets/ResearchView-gpn1XcVy.js +0 -1
- package/dist/client/assets/SecretsView-B7YqIowt.js +0 -1
- package/dist/client/assets/SecretsView-Djo1rahi.css +0 -1
- package/dist/client/assets/SessionTerminal-9l4bdKcn.js +0 -2
- package/dist/client/assets/SessionTerminal-BNgtmXb3.css +0 -1
- package/dist/client/assets/SettingsModal-BGEK9_9A.js +0 -31
- package/dist/client/assets/SettingsModal-CKv0TJfM.css +0 -1
- package/dist/client/assets/SettingsModal-CXogw-Er.css +0 -1
- package/dist/client/assets/SettingsModal-DIIoHGUH.js +0 -1
- package/dist/client/assets/SetupWizardModal-BcVeMxeX.js +0 -1
- package/dist/client/assets/SetupWizardModal-CIqFbkrD.css +0 -1
- package/dist/client/assets/SkillsView-3bhGyWs1.css +0 -1
- package/dist/client/assets/SkillsView-BxSJ4PHL.js +0 -1
- package/dist/client/assets/StashRecoveryView-B_8WIQEo.css +0 -1
- package/dist/client/assets/StashRecoveryView-BhFQ2FsP.js +0 -1
- package/dist/client/assets/TodoView-7xIh-Fmi.css +0 -1
- package/dist/client/assets/TodoView-BZpewjy0.js +0 -6
- package/dist/client/assets/WorkflowNodeEditor-Yn1FRF2v.css +0 -1
- package/dist/client/assets/WorkflowNodeEditor-tWsgCdVt.js +0 -8
- package/dist/client/assets/app-BmGA0Hiz.js +0 -13
- package/dist/client/assets/app-CEVYlVuJ.js +0 -13
- package/dist/client/assets/app-CbBFax2C.js +0 -13
- package/dist/client/assets/app-DORKrGAz.js +0 -13
- package/dist/client/assets/app-DQibuQ9z.js +0 -13
- package/dist/client/assets/app-k76GrQP0.js +0 -13
- package/dist/client/assets/common-BRyX4VxB.js +0 -1
- package/dist/client/assets/common-CN9QPI2d.js +0 -1
- package/dist/client/assets/common-CNbjPELi.js +0 -1
- package/dist/client/assets/common-DFDqu_n0.js +0 -1
- package/dist/client/assets/common-DgWWKG8Z.js +0 -1
- package/dist/client/assets/common-X6PzBnVA.js +0 -1
- package/dist/client/assets/createLucideIcon-DmVITl5d.js +0 -21
- package/dist/client/assets/dashboard-view-BFoyhTYF.js +0 -3
- package/dist/client/assets/dashboard-view-Cxzm_eqc.js +0 -1
- package/dist/client/assets/dashboard-view-DdGlfuu-.css +0 -1
- package/dist/client/assets/dashboard-view-_8yfNwju.css +0 -1
- package/dist/client/assets/index-Bglw05rM.js +0 -791
- package/dist/client/assets/index-FYgnflWD.css +0 -1
- package/dist/client/assets/vendor-reactflow-ZasuEfF9.js +0 -15
- package/dist/client/assets/x-PItWc-wQ.js +0 -61
- package/dist/client/assets/zoom-out-CzlHv0Kj.js +0 -21
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import{r as c,j as e}from"./vendor-react-BTgM5bbZ.js";import{c as ze,a7 as ce,a8 as Se,a9 as ke,am as Ce,an as We,ac as je,ao as Ke,ap as Ye,aq as Ve,ar as Je,as as Qe,at as Ze,au as Me,av as es,i as ss,aw as Ae,ax as I,A as ts,X as Ie,ay as me,R as N,az as is,m as ns,C as _e,aA as le,aB as Ne,aC as as,J as Le,aD as rs,aE as De,aF as cs}from"./index-Bglw05rM.js";import{u as Pe}from"./vendor-i18n-DYlSUfot.js";import{U as Ee}from"./users-a-ELbyyZ.js";import"./vendor-reactflow-ZasuEfF9.js";import"./vendor-xterm-ea7-K05z.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 ls=[["path",{d:"M12 10h.01",key:"1nrarc"}],["path",{d:"M12 14h.01",key:"1etili"}],["path",{d:"M12 6h.01",key:"1vi96p"}],["path",{d:"M16 10h.01",key:"1m94wz"}],["path",{d:"M16 14h.01",key:"1gbofw"}],["path",{d:"M16 6h.01",key:"1x0f13"}],["path",{d:"M8 10h.01",key:"19clt8"}],["path",{d:"M8 14h.01",key:"6423bh"}],["path",{d:"M8 6h.01",key:"1dz90k"}],["path",{d:"M9 22v-3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v3",key:"cabbwy"}],["rect",{x:"4",y:"2",width:"16",height:"20",rx:"2",key:"1uxh74"}]],os=ze("building",ls);/**
|
|
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 hs=[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16",key:"c24i48"}],["path",{d:"m19 9-5 5-4-4-3 3",key:"2osh9i"}]],gs=ze("chart-line",hs),ue=["architecture","quality","workflow","performance","reliability","security","ux","testability","documentation","dependency","features","competitive_analysis","research","trends","other"],Fe={quality:"Quality",performance:"Performance",architecture:"Architecture",security:"Security",reliability:"Reliability",ux:"User Experience",testability:"Testability",documentation:"Documentation",dependency:"Dependencies",workflow:"Workflow",other:"Other",features:"Features",competitive_analysis:"Competitive Analysis",research:"Research",trends:"Trends"};function ds(g){const{t:h}=Pe("app"),$=g??"",w=`${ke.INSIGHTS_PREFIX}${$}`,S=`${ke.INSIGHT_LATEST_RUN_PREFIX}${$}`,s=ce(w,{maxAgeMs:Se}),K=ce(S,{maxAgeMs:Ce}),E=c.useRef(Array.isArray(s)&&s.length>0),U=c.useCallback(r=>h(`insights.category.${r}`,Fe[r]??r),[h]),[v,p]=c.useState(()=>Array.isArray(s)?s:[]),[T,Y]=c.useState(()=>ue.map(r=>({category:r,label:Fe[r]??r,items:[],isLoading:!1,error:null}))),[V,z]=c.useState(!(Array.isArray(s)&&s.length>0)),[J,G]=c.useState(null),[Q,_]=c.useState(K??null),[Z,H]=c.useState(!1),[ee,F]=c.useState(null),[se,L]=c.useState(new Map),[te,C]=c.useState(new Map),[u,k]=c.useState(new Map),[m,D]=c.useState(new Map),[B,j]=c.useState(!1),R=c.useCallback(async()=>{E.current||z(!0),G(null);try{const i=(await We({status:void 0,limit:1e3},g)).insights.filter(d=>d.status!=="dismissed");p(i),je(w,i.length>500?i.slice(0,500):i,{maxBytes:5e5});const t=await Ke(g);t.runs.length>0&&(_(t.runs[0]),je(S,t.runs[0],{maxBytes:5e5})),E.current=!0}catch(r){const i=r instanceof Error?r.message:"Failed to fetch insights";G(i)}finally{z(!1)}},[w,S,g]),y=c.useCallback(()=>{j(r=>!r)},[]),ie=c.useCallback(async(r,i)=>{H(!0),F(null);try{const t=await Ye("manual",void 0,g,r,i);_(t),t.status==="completed"?await R():t.status==="failed"&&t.error&&F(t.error)}catch(t){if(t instanceof Ve&&t.status===409&&t.details?.code==="ACTIVE_RUN_CONFLICT"){const f=typeof t.details.activeRunId=="string"?t.details.activeRunId:null;if(f)try{const ge=await Je(f,g);_(ge)}catch{}throw F("Insight generation is already running"),t}const d=t instanceof Error?t.message:"Failed to generate insights";throw F(d),t}finally{H(!1)}},[g,R]),oe=c.useCallback(async r=>{L(i=>{const t=new Map(i);return t.set(r,{running:!0,error:null}),t});try{await Qe(r,g),p(i=>i.filter(t=>t.id!==r)),L(i=>{const t=new Map(i);return t.set(r,{running:!1,error:null}),t})}catch(i){const t=i instanceof Error?i.message:"Failed to dismiss insight";throw L(d=>{const f=new Map(d);return f.set(r,{running:!1,error:t}),f}),i}},[g]),he=c.useCallback(async r=>{C(i=>{const t=new Map(i);return t.set(r,{running:!0,error:null}),t});try{const i=await Ze(r,g);return await Me(r,g),p(t=>t.map(d=>d.id===r?{...d,status:"archived",updatedAt:new Date().toISOString()}:d)),C(t=>{const d=new Map(t);return d.set(r,{running:!1,error:null}),d}),{title:i.suggestedTitle,description:i.suggestedDescription}}catch(i){const t=i instanceof Error?i.message:"Failed to create task";throw C(d=>{const f=new Map(d);return f.set(r,{running:!1,error:t}),f}),i}},[g]);c.useEffect(()=>{const r=new Map;for(const i of ue)r.set(i,[]);for(const i of v){if(!B&&i.status==="archived")continue;const t=r.get(i.category)??[];r.set(i.category,[...t,i])}Y(ue.map(i=>({category:i,label:U(i),items:r.get(i)??[],isLoading:!1,error:null})))},[v,B,U]);const x=c.useCallback(async r=>{k(i=>{const t=new Map(i);return t.set(r,{running:!0,error:null}),t});try{await Me(r,g),p(i=>i.map(t=>t.id===r?{...t,status:"archived",updatedAt:new Date().toISOString()}:t)),k(i=>{const t=new Map(i);return t.set(r,{running:!1,error:null}),t})}catch(i){const t=i instanceof Error?i.message:"Failed to archive insight";throw k(d=>{const f=new Map(d);return f.set(r,{running:!1,error:t}),f}),i}},[g]),O=c.useCallback(async r=>{D(i=>{const t=new Map(i);return t.set(r,{running:!0,error:null}),t});try{await es(r,g),p(i=>i.map(t=>t.id===r?{...t,status:"confirmed",updatedAt:new Date().toISOString()}:t)),D(i=>{const t=new Map(i);return t.set(r,{running:!1,error:null}),t})}catch(i){const t=i instanceof Error?i.message:"Failed to unarchive insight";throw D(d=>{const f=new Map(d);return f.set(r,{running:!1,error:t}),f}),i}},[g]),b=c.useMemo(()=>T.reduce((r,i)=>r+i.items.length,0),[T]),X=c.useMemo(()=>0,[]),q=c.useMemo(()=>v.filter(r=>r.status==="archived").length,[v]);return c.useEffect(()=>{const r=ce(w,{maxAgeMs:Se}),i=ce(S,{maxAgeMs:Ce}),t=Array.isArray(r)&&r.length>0;p(Array.isArray(r)?r:[]),_(i??null),z(!t),E.current=t},[w,S]),c.useEffect(()=>{R()},[R]),{sections:T,loading:V,error:J,latestRun:Q,isRunInFlight:Z,runError:ee,refresh:R,runInsights:ie,dismiss:oe,createTask:he,archive:x,unarchive:O,toggleShowArchived:y,dismissStates:se,createTaskStates:te,archiveStates:u,unarchiveStates:m,totalCount:b,dismissedCount:X,archivedCount:q,showArchived:B}}const $e=["Backlog health:","Backlog pressure detected","Stale paused todo","Backlog health: dependency-blocked todos"];function Re(g){return $e.some(h=>g.title.startsWith(h))}const Te={architecture:os,quality:_e,workflow:De,performance:Ne,reliability:N,security:le,ux:Ee,testability:me,documentation:rs,dependency:Le,features:as,competitive_analysis:Ee,research:gs,trends:Ne,other:I};function bs({projectId:g,addToast:h,onClose:$,onCreateTask:w,models:S}){const{t:s}=Pe("app"),{sections:K,loading:E,error:U,latestRun:v,isRunInFlight:p,runError:T,refresh:Y,runInsights:V,dismiss:z,createTask:J,archive:G=async()=>{},unarchive:Q=async()=>{},toggleShowArchived:_=()=>{},dismissStates:Z,createTaskStates:H,archiveStates:ee=new Map,unarchiveStates:F=new Map,totalCount:se,archivedCount:L=0,showArchived:te=!1}=ds(g),[C,u]=c.useState(null),[k,m]=c.useState("info"),[D,B]=c.useState(!1),[j,R]=c.useState(!1),[y,ie]=c.useState(()=>localStorage.getItem("fusion-insight-model")??""),[oe,he]=c.useState([]),[x,O]=c.useState([]),[b,X]=c.useState([]),[q,r]=c.useState();c.useEffect(()=>{S||ss().then(n=>{he(n.models),O(n.favoriteProviders),X(n.favoriteModels),r(n.resolvedPlanningProvider);const a=localStorage.getItem("fusion-insight-model");a&&(n.models.some(o=>`${o.provider}/${o.id}`===a)||(localStorage.removeItem("fusion-insight-model"),ie("")))}).catch(()=>{})},[S]);const i=S??oe,t=c.useMemo(()=>x.length>0?x:q?[q]:[],[x,q]),d=c.useCallback(async n=>{const l=x.includes(n)?x.filter(o=>o!==n):[n,...x];O(l);try{await Ae({favoriteProviders:l,favoriteModels:b})}catch{O(x)}},[x,b]),f=c.useCallback(async n=>{const l=b.includes(n)?b.filter(o=>o!==n):[n,...b];X(l);try{await Ae({favoriteProviders:x,favoriteModels:l})}catch{X(b)}},[b,x]),ge=c.useCallback(n=>{ie(n),n?localStorage.setItem("fusion-insight-model",n):localStorage.removeItem("fusion-insight-model")},[]),W=c.useMemo(()=>K.filter(n=>n.items.length>0),[K]),fe=c.useMemo(()=>W.reduce((n,a)=>n+a.items.filter(Re).length,0),[W]),M=c.useMemo(()=>j?W.map(n=>({...n,items:n.items.filter(Re)})).filter(n=>n.items.length>0):W,[W,j]),[P,de]=c.useState(null);c.useEffect(()=>{if(M.length===0){P!==null&&de(null);return}P&&M.some(a=>a.category===P&&a.items.length>0)||de(M[0].category)},[M,P]);const A=c.useMemo(()=>M.find(n=>n.category===P)??M[0],[M,P]);c.useEffect(()=>{if(C){const n=setTimeout(()=>u(null),5e3);return()=>clearTimeout(n)}},[C]);const ve=c.useCallback(async()=>{try{u(s("insights.generatingInsights","Generating insights...")),m("info");let n,a;if(y){const l=y.indexOf("/");if(l!==-1){const o=y.slice(0,l),ne=y.slice(l+1);o&&ne&&(n=o,a=ne)}}await V(n,a),u(s("insights.generationStarted","Insight generation started")),m("success"),h(s("insights.generationStarted","Insight generation started"),"success")}catch(n){const a=n instanceof Error?n.message:s("insights.failedToStart","Failed to start generation");if(a==="Insight generation is already running"){u(s("insights.alreadyRunning","Insight generation is already running. Showing the active run.")),m("info"),h(s("insights.alreadyRunningShort","Insight generation is already running"),"info");return}u(a),m("error"),h(a,"error")}},[V,h,y,s]),Ue=c.useCallback(async(n,a)=>{try{u(s("insights.dismissing",'Dismissing "{{title}}"...',{title:a})),m("info"),await z(n),u(s("insights.dismissed",'Dismissed "{{title}}"',{title:a})),m("success"),h(s("insights.dismissedMsg","Insight dismissed: {{title}}",{title:a}),"success")}catch(l){const o=l instanceof Error?l.message:s("insights.failedToDismiss","Failed to dismiss insight");u(o),m("error"),h(o,"error")}},[z,h,s]),Ge=c.useCallback(async(n,a)=>{try{u(s("insights.archiving",'Archiving "{{title}}"...',{title:a})),m("info"),await G(n),u(s("insights.archived",'Archived "{{title}}"',{title:a})),m("success"),h(s("insights.archivedMsg","Insight archived: {{title}}",{title:a}),"success")}catch(l){const o=l instanceof Error?l.message:s("insights.failedToArchive","Failed to archive insight");u(o),m("error"),h(o,"error")}},[G,h,s]),He=c.useCallback(async(n,a)=>{try{u(s("insights.unarchiving",'Unarchiving "{{title}}"...',{title:a})),m("info"),await Q(n),u(s("insights.unarchived",'Unarchived "{{title}}"',{title:a})),m("success"),h(s("insights.unarchivedMsg","Insight unarchived: {{title}}",{title:a}),"success")}catch(l){const o=l instanceof Error?l.message:s("insights.failedToUnarchive","Failed to unarchive insight");u(o),m("error"),h(o,"error")}},[Q,h,s]),Be=c.useCallback(async(n,a)=>{try{if(u(s("insights.creatingTask",'Creating task from "{{title}}"...',{title:a})),m("info"),!w)throw new Error(s("insights.taskCreationUnavailable","Task creation is unavailable in this view"));const l=await J(n);if(!l)throw new Error(s("insights.failedToPreparePayload","Failed to prepare task payload from insight"));await w({insightId:n,title:l.title,description:l.description}),u(s("insights.taskCreated",'Task created from "{{title}}"',{title:a})),m("success"),h(s("insights.taskCreatedMsg","Task created: {{title}}",{title:l.title}),"success")}catch(l){const o=l instanceof Error?l.message:s("insights.failedToCreateTask","Failed to create task");u(o),m("error"),h(o,"error")}},[J,w,h,s]),Oe=n=>{const a=Te[n.category]??I,l=A?.category===n.category;return e.jsx("li",{children:e.jsxs("button",{type:"button",className:`insights-category-item${l?" insights-category-item--active":""}`,onClick:()=>de(n.category),"aria-current":l?"true":void 0,"data-testid":`insights-category-${n.category}`,children:[e.jsx(a,{size:16,className:"insights-category-icon"}),e.jsx("span",{className:"insights-category-label",children:n.label}),e.jsx("span",{className:"insights-category-count",children:n.items.length})]})},n.category)},Xe=()=>{if(!A)return null;const n=Te[A.category]??I;return e.jsxs("section",{className:"insights-section","data-testid":`insights-section-${A.category}`,children:[e.jsx("div",{className:"insights-section-header",children:e.jsxs("div",{className:"insights-section-title",children:[e.jsx(n,{size:20,className:"insights-section-icon"}),e.jsx("h3",{children:A.label}),e.jsx("span",{className:"insights-section-count",children:A.items.length})]})}),e.jsx("div",{className:"insights-section-content",children:e.jsx("ul",{className:"insights-list",children:A.items.map(a=>{const l=Z.get(a.id),o=H.get(a.id),ne=ee.get(a.id),qe=F.get(a.id),xe=l?.running??!1,ye=o?.running??!1,pe=ne?.running??!1,be=qe?.running??!1,we=a.status==="archived",ae=A.items.some(re=>Z.get(re.id)?.running||H.get(re.id)?.running||ee.get(re.id)?.running||F.get(re.id)?.running);return e.jsxs("li",{className:`insight-item${we?" insight-item--archived":""}`,"data-insight-id":a.id,children:[e.jsxs("div",{className:"insight-item-header",children:[e.jsx("h4",{className:"insight-item-title",children:a.title}),e.jsxs("div",{className:"insight-item-actions",children:[we?e.jsx("button",{className:"insight-item-action-btn",onClick:()=>void He(a.id,a.title),disabled:be||ae,title:s("insights.unarchiveTitle","Unarchive this insight"),"aria-label":s("insights.unarchiveLabel","Unarchive this insight"),"data-testid":`unarchive-${a.id}`,children:be?e.jsx(N,{size:20,className:"spin"}):e.jsx(cs,{size:20})}):e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"insight-item-action-btn",onClick:()=>void Be(a.id,a.title),disabled:ye||ae,title:s("insights.createTaskTitle","Create task from this insight"),"aria-label":s("insights.createTaskLabel","Create task from this insight"),"data-testid":`create-task-${a.id}`,children:ye?e.jsx(N,{size:20,className:"spin"}):e.jsx(Le,{size:20})}),e.jsx("button",{className:"insight-item-action-btn",onClick:()=>void Ge(a.id,a.title),disabled:pe||ae,title:s("insights.archiveTitle","Archive this insight"),"aria-label":s("insights.archiveLabel","Archive this insight"),"data-testid":`archive-${a.id}`,children:pe?e.jsx(N,{size:20,className:"spin"}):e.jsx(me,{size:20})})]}),e.jsx("button",{className:"insight-item-action-btn",onClick:()=>void Ue(a.id,a.title),disabled:xe||ae,title:s("insights.dismissTitle","Dismiss this insight"),"aria-label":s("insights.dismissLabel","Dismiss this insight"),"data-testid":`dismiss-${a.id}`,children:xe?e.jsx(N,{size:20,className:"spin"}):e.jsx(Ie,{size:20})})]})]}),a.content&&e.jsx("p",{className:"insight-item-content",children:a.content}),e.jsxs("div",{className:"insight-item-meta",children:[e.jsx("span",{className:`insight-item-status insight-item-status--${a.status}`,children:a.status}),a.createdAt&&e.jsxs("span",{className:"insight-item-date",children:[e.jsx(De,{size:12}),new Date(a.createdAt).toLocaleDateString()]})]})]},a.id)})})})]})};return e.jsxs("div",{className:"insights-view","data-testid":"insights-view",children:[e.jsxs("div",{className:"insights-view-header",children:[e.jsxs("div",{className:"insights-view-title",children:[e.jsxs("h2",{children:[e.jsx(I,{size:20}),s("insights.title","Insights")]}),e.jsxs("span",{className:"insights-view-count",children:[se," ",s("common.total","total")]})]}),e.jsxs("div",{className:"insights-view-actions",children:[fe>0&&e.jsxs("button",{className:`btn btn-sm insights-backlog-health-toggle${j?" btn-icon--active":""}`,onClick:()=>R(n=>!n),"aria-pressed":j,"aria-label":j?s("insights.showAllInsights","Show all insights"):s("insights.showBacklogHealth","Show only backlog health insights"),"data-testid":"toggle-backlog-health",title:$e.join(", "),children:[e.jsx(ts,{size:14}),j?s("insights.allInsights","All Insights"):s("insights.backlogHealth","Backlog Health")," ",e.jsxs("span",{children:["(",fe,")"]})]}),$&&e.jsx("button",{className:"btn btn-sm insights-view-close",onClick:$,"aria-label":s("actions.closeInsightsView","Close insights view"),title:s("actions.close","Close"),children:e.jsx(Ie,{size:16})}),L>0&&e.jsxs("button",{className:"btn btn-sm insights-show-archived-toggle",onClick:_,"aria-label":te?s("insights.hideArchived","Hide archived insights"):s("insights.showArchived","Show archived insights"),"data-testid":"toggle-archived-insights",children:[e.jsx(me,{size:14}),te?s("insights.hideArchivedLabel","Hide Archived"):s("insights.showArchivedLabel","Show Archived ({{count}})",{count:L})]}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void Y(),disabled:E,"aria-label":s("actions.refreshInsights","Refresh insights"),"data-testid":"refresh-insights",children:[e.jsx(N,{size:14,className:E?"spin":""}),s("actions.refresh","Refresh")]}),e.jsxs("button",{className:"btn btn-sm insights-model-toggle",onClick:()=>B(n=>!n),"aria-label":s("insights.configureModel","Configure insight generation model"),"aria-expanded":D,"data-testid":"toggle-model-config",title:y?s("insights.modelConfigured","Model: {{model}}",{model:y}):s("insights.configureModelTitle","Configure model"),children:[e.jsx(is,{size:14}),y&&e.jsx("span",{className:"insights-model-indicator"})]}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:()=>void ve(),disabled:p,"aria-label":s("insights.generateInsights","Generate new insights"),"data-testid":"run-insights",children:p?e.jsxs(e.Fragment,{children:[e.jsx(N,{size:14,className:"spin"}),s("insights.generating","Generating...")]}):e.jsxs(e.Fragment,{children:[e.jsx(I,{size:14}),s("insights.generateInsightsBtn","Generate Insights")]})})]})]}),D&&e.jsxs("div",{className:"insights-model-config","data-testid":"model-config",children:[e.jsx("label",{htmlFor:"insight-model-select",className:"insights-model-label",children:s("insights.model","Model")}),e.jsx(ns,{models:i,value:y,onChange:ge,placeholder:s("insights.usePlanningDefault","Use planning default"),label:s("insights.generationModel","Insight generation model"),disabled:p,id:"insight-model-select",favoriteProviders:t,favoriteModels:b,onToggleFavorite:d,onToggleModelFavorite:f})]}),e.jsx("div",{className:"insights-status-region","aria-live":"polite","data-testid":"insights-status",children:C&&e.jsxs("div",{className:`insights-status-message insights-status-message--${k}`,role:k==="error"?"alert":void 0,children:[k==="success"&&e.jsx(_e,{size:16}),k==="error"&&e.jsx(le,{size:16}),k==="info"&&e.jsx(I,{size:16}),e.jsx("span",{children:C})]})}),T&&e.jsxs("div",{className:"insights-error-callout",role:"alert","data-testid":"run-error",children:[e.jsx(le,{size:16}),e.jsx("span",{children:T})]}),v&&e.jsx("div",{className:"insights-run-info","data-testid":"latest-run",children:e.jsxs("span",{className:"insights-run-status",children:[s("insights.latestRun","Latest run:")," ",v.status,v.status==="completed"&&e.jsxs(e.Fragment,{children:[" — ",s("insights.runCompleted","{{created}} created, {{updated}} updated",{created:v.insightsCreated,updated:v.insightsUpdated})]}),v.status==="failed"&&v.error&&e.jsxs(e.Fragment,{children:[" — ",v.error]})]})}),E?e.jsxs("div",{className:"insights-loading","data-testid":"insights-loading",children:[e.jsx(N,{size:24,className:"spin"}),e.jsx("p",{children:s("insights.loading","Loading insights...")})]}):U?e.jsxs("div",{className:"insights-error","data-testid":"insights-error",children:[e.jsx(le,{size:24}),e.jsx("p",{children:U}),e.jsx("button",{className:"btn btn-sm",onClick:()=>void Y(),children:s("actions.retry","Retry")})]}):se===0?e.jsxs("div",{className:"insights-empty","data-testid":"insights-empty",children:[e.jsx(I,{size:48}),e.jsx("h3",{children:s("insights.noInsightsYet","No insights yet")}),e.jsx("p",{children:s("insights.generateDescription","Generate insights to get AI-powered recommendations for your project.")}),e.jsxs("button",{className:"btn btn-primary",onClick:()=>void ve(),children:[e.jsx(I,{size:14}),s("insights.generateFirst","Generate First Insights")]})]}):e.jsxs("div",{className:"insights-body",children:[e.jsx("aside",{className:"insights-sidebar","aria-label":"Insight categories",children:e.jsx("ul",{className:"insights-category-list",children:M.map(Oe)})}),e.jsx("div",{className:"insights-detail",children:Xe()})]})]})}export{bs as InsightsView};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.insights-view{display:flex;flex-direction:column;height:100%;min-height:0;overflow:hidden}.insights-view-header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-lg);border-bottom:1px solid var(--border);background:var(--surface);flex-shrink:0}.insights-view-title{display:flex;align-items:center;gap:var(--space-sm)}.insights-view-title h2{margin:0;font-size:1.125rem;font-weight:600;display:flex;align-items:center;gap:var(--space-sm)}.insights-view-count{font-size:.8125rem;color:var(--text-muted);font-weight:400}.insights-view-actions{display:flex;align-items:center;gap:var(--space-sm)}.insights-model-config{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-lg);border-bottom:1px solid var(--border);background:var(--surface-subtle)}.insights-model-label{font-size:.8125rem;color:var(--text-muted);white-space:nowrap;flex-shrink:0}.insights-model-config .model-combobox{max-width:320px}.insights-model-toggle{position:relative}.insights-model-indicator{position:absolute;top:2px;right:2px;width:6px;height:6px;border-radius:50%;background:var(--todo, #f59e0b)}.insights-view-close{color:var(--text-muted)}.insights-view-close:hover{color:var(--text)}.insights-status-region{padding:var(--space-md) var(--space-lg);flex-shrink:0}.insights-status-region:empty{padding:0}.insights-status-message{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);border-radius:var(--radius-md);font-size:.8125rem}.insights-status-message--success{background:color-mix(in srgb,var(--color-success) 10%,transparent);color:var(--color-success)}.insights-status-message--error{background:color-mix(in srgb,var(--color-error) 10%,transparent);color:var(--color-error)}.insights-status-message--info{background:color-mix(in srgb,var(--accent) 10%,transparent);color:var(--accent)}.insights-error-callout{display:flex;align-items:center;gap:var(--space-sm);margin:0 var(--space-lg) var(--space-md);padding:var(--space-md);background:color-mix(in srgb,var(--color-error) 10%,transparent);border:1px solid color-mix(in srgb,var(--color-error) 30%,transparent);border-radius:var(--radius-md);color:var(--color-error);font-size:.8125rem;flex-shrink:0}.insights-run-info{padding:0 var(--space-lg) var(--space-md);flex-shrink:0}.insights-run-status{font-size:.75rem;color:var(--text-muted)}.insights-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-md);padding:var(--space-2xl);color:var(--text-muted)}.insights-error{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-md);padding:var(--space-2xl);text-align:center}.insights-error p{color:var(--text-muted);margin:0}.insights-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-md);padding:var(--space-2xl);text-align:center;flex:1}.insights-empty h3{margin:0;font-size:1.125rem;color:var(--text)}.insights-empty p{color:var(--text-muted);margin:0;max-width:calc(var(--space-2xl) * 12 + var(--space-lg))}.insights-body{flex:1;min-height:0;display:flex;overflow:hidden}.insights-sidebar{width:calc(var(--space-2xl) * 7 + var(--space-lg));flex-shrink:0;border-right:1px solid var(--border);background:var(--surface);overflow-y:auto;min-height:0}.insights-category-list{list-style:none;margin:0;padding:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-xs)}.insights-category-item{width:100%;display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);background:transparent;border:1px solid transparent;border-radius:var(--radius-md);color:var(--text);font:inherit;font-size:.8125rem;text-align:left;cursor:pointer;transition:background var(--transition-fast),border-color var(--transition-fast)}.insights-category-item:hover{background:var(--surface-1)}.insights-category-item--active{background:color-mix(in srgb,var(--accent) 12%,transparent);border-color:color-mix(in srgb,var(--accent) 35%,transparent);color:var(--accent)}.insights-category-icon{flex-shrink:0;color:var(--accent)}.insights-category-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}.insights-category-count{flex-shrink:0;font-size:.75rem;color:var(--text-muted);background:var(--surface-1);padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);border:1px solid var(--border)}.insights-category-item--active .insights-category-count{background:var(--surface);color:var(--accent);border-color:color-mix(in srgb,var(--accent) 30%,transparent)}.insights-detail{flex:1;min-width:0;min-height:0;overflow-y:auto;padding:var(--space-lg)}.insights-section{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden}.insights-section-header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-md) var(--space-lg);background:var(--surface);border-bottom:1px solid var(--border)}.insights-section-title{display:flex;align-items:center;gap:var(--space-sm)}.insights-section-title h3{margin:0;font-size:.9375rem;font-weight:600}.insights-section-icon{color:var(--accent)}.insights-section-count{font-size:.75rem;color:var(--text-muted);background:var(--surface-1);padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);border:1px solid var(--border)}.insights-section-content{padding:var(--space-md)}.insights-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-md)}.insight-item{padding:var(--space-md);background:var(--surface);border:1px solid var(--border);border-left:var(--space-xs) solid var(--accent);border-radius:var(--radius-md);transition:border-color var(--transition-fast)}.insight-item:hover{border-color:var(--accent)}.insight-item-header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-sm)}.insight-item-title{margin:0;font-size:.875rem;font-weight:600;color:var(--text);line-height:1.4}.insight-item-actions{display:flex;align-items:center;gap:var(--space-xs);flex-shrink:0}.insight-item-action-btn{display:inline-flex;align-items:center;justify-content:center;width:calc(var(--space-lg) * 2);height:calc(var(--space-lg) * 2);padding:0;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.insight-item-action-btn:hover:not(:disabled){background:var(--surface-1);color:var(--accent)}.insight-item-action-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.insight-item-action-btn:disabled{opacity:.5;cursor:not-allowed}.insight-item-content{margin:var(--space-sm) 0 0;font-size:.8125rem;color:var(--text-muted);line-height:1.5;white-space:pre-wrap;word-break:break-word}.insight-item-meta{display:flex;align-items:center;gap:var(--space-md);margin-top:var(--space-sm);font-size:.75rem;color:var(--text-muted)}.insight-item-status{padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-sm);text-transform:capitalize;font-weight:500}.insight-item-status--generated{background:color-mix(in srgb,var(--accent) 15%,transparent);color:var(--accent)}.insight-item-status--confirmed{background:color-mix(in srgb,var(--color-success) 15%,transparent);color:var(--color-success)}.insight-item-status--stale{background:color-mix(in srgb,var(--color-warning) 15%,transparent);color:var(--color-warning)}.insight-item-status--dismissed,.insight-item-status--archived{background:color-mix(in srgb,var(--text-dim) 15%,transparent);color:var(--text-dim)}.insight-item--archived{opacity:.6;border-left-color:var(--text-dim)}.insight-item--archived .insight-item-title{text-decoration:line-through;color:var(--text-muted)}.insight-item--archived .insight-item-content{text-decoration:line-through}.insight-item-date{display:flex;align-items:center;gap:var(--space-xs)}@media(max-width:768px){.insights-view-header{flex-wrap:nowrap;gap:var(--space-sm);padding:var(--space-md)}.insights-view-title{min-width:0;flex:1 1 auto}.insights-view-title h2{font-size:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.insights-view-actions{flex-shrink:0;justify-content:flex-end;flex-wrap:nowrap;gap:var(--space-xs)}.insights-body{flex-direction:column}.insights-sidebar{width:100%;border-right:none;border-bottom:1px solid var(--border);overflow-x:auto;overflow-y:hidden;flex-shrink:0}.insights-category-list{flex-direction:row;flex-wrap:nowrap;padding:var(--space-sm);gap:var(--space-xs)}.insights-category-list>li{flex-shrink:0}.insights-category-item{white-space:nowrap;padding:var(--space-xs) var(--space-sm)}.insights-category-label{overflow:visible;text-overflow:clip}.insights-detail{padding:var(--space-md)}.insights-section-header{padding:var(--space-sm) var(--space-md)}.insights-section-content,.insight-item{padding:var(--space-sm)}.insight-item-title{word-break:break-word}.insight-item-header{flex-direction:column;gap:var(--space-sm)}.insight-item-meta{flex-wrap:wrap;gap:var(--space-sm)}.insight-item-actions{align-self:flex-end}.insight-item-action-btn{width:calc(var(--space-2xl) + var(--space-sm));height:calc(var(--space-2xl) + var(--space-sm))}.insights-view-actions .btn{min-height:calc(var(--space-2xl) + var(--space-xs))}.insights-show-archived-toggle{max-width:calc(var(--space-2xl) * 5 + var(--space-md));white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.insights-view-close{min-height:calc(var(--space-2xl) + var(--space-xs));min-width:calc(var(--space-2xl) + var(--space-xs))}.insights-view-count{font-size:.75rem}.insights-model-config{padding:var(--space-xs) var(--space-md)}.insights-model-config .model-combobox{max-width:200px}}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r,j as e}from"./vendor-react-BTgM5bbZ.js";import{u as Re}from"./SettingsModal-DIIoHGUH.js";import{c1 as Me,c2 as we,c3 as qe,y as Te,c4 as Pe,c5 as We,c6 as He,c7 as Ae,c8 as Fe,c9 as _e,ca as Oe,cb as Ue,cc as De,cd as Qe,x as $e,ce as Be,L as F,cf as ze}from"./index-Bglw05rM.js";import{u as Ve}from"./vendor-i18n-DYlSUfot.js";import"./vendor-reactflow-ZasuEfF9.js";import"./vendor-xterm-ea7-K05z.js";import"./vendor-codemirror-jBKmHyH0.js";const B=".fusion/memory/MEMORY.md",Ye=5e4,Ge="0 3 * * *",Ze="0 4 * * *";function ge(i){return{memoryEnabled:i.memoryEnabled!==!1,memoryAutoSummarizeEnabled:i.memoryAutoSummarizeEnabled??!1,memoryAutoSummarizeThresholdChars:i.memoryAutoSummarizeThresholdChars??Ye,memoryAutoSummarizeSchedule:i.memoryAutoSummarizeSchedule??Ge,memoryDreamsEnabled:i.memoryDreamsEnabled??!1,memoryDreamsSchedule:i.memoryDreamsSchedule??Ze}}function Le(i,t){return i.some(h=>h.path===t)?t:i.find(h=>h.path===B)?.path??i[0]?.path??B}function Ke(i={}){const{projectId:t}=i,[h,s]=r.useState(""),[u,S]=r.useState(!0),[k,I]=r.useState(!1),[D,j]=r.useState(!1),[x,E]=r.useState(null),[n,M]=r.useState(!0),[V,_]=r.useState(!1),[re,O]=r.useState(()=>ge({})),[w,Y]=r.useState(!0),[z,me]=r.useState(!1),[be,U]=r.useState([]),[d,p]=r.useState(!0),[f,A]=r.useState(B),[o,v]=r.useState(""),[ne,R]=r.useState(!1),[c,N]=r.useState(!1),[xe,G]=r.useState(!1),[ie,Z]=r.useState(!1),[le,K]=r.useState(!1),[X,Q]=r.useState(null),[L,$]=r.useState(!0),[pe,q]=r.useState(!1),[fe,J]=r.useState(!1),[oe,ee]=r.useState(null),{status:ce,loading:de,refresh:se}=Re({projectId:t}),te=r.useCallback(m=>{v(m),N(!0)},[]),g=r.useCallback(async m=>{R(!0);try{const{content:l}=await Me(m,t);A(m),v(l),N(!1)}finally{R(!1)}},[t]),T=r.useCallback(async()=>{p(!0);try{const{files:m}=await we(t);if(U(m),m.length===0){A(B),v(""),N(!1);return}const l=Le(m,f);l!==f&&await g(l)}finally{p(!1)}},[t,f,g]);r.useEffect(()=>{let m=!1;async function l(){try{const y=await Qe(t);m||(s(y.content),S(!1))}catch{m||(s(""),S(!1))}}return l(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function l(){try{const y=await Fe(t);m||(E(y.content),_(y.exists),M(!1))}catch{m||(E(null),_(!1),M(!1))}}return l(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function l(){Y(!0);try{const y=await $e(t);m||O(ge(y))}catch{m||O(ge({}))}finally{m||Y(!1)}}return l(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function l(){p(!0);try{const{files:y}=await we(t);if(m)return;if(U(y),y.length===0){A(B),v(""),N(!1);return}const H=Le(y,f),{content:a}=await Me(H,t);if(m)return;A(H),v(a),N(!1)}catch{m||(U([]),A(B),v(""),N(!1))}finally{m||p(!1)}}return l(),()=>{m=!0}},[t,f]),r.useEffect(()=>{let m=!1;async function l(){try{const y=await Ae(t);m||(Q(y),$(!1))}catch{m||(Q(null),$(!1))}}return l(),()=>{m=!0}},[t]),r.useEffect(()=>{let m=!1;async function l(){try{const y=await Be(t);m||ee(y)}catch{m||ee(null)}}return l(),()=>{m=!0}},[t]);const P=r.useCallback(m=>{s(m),I(!0)},[]),Se=r.useCallback(async()=>{if(k){j(!0);try{await qe(h,t),I(!1)}finally{j(!1)}}},[h,k,t]),ye=r.useCallback(async m=>{me(!0);try{const l=await Te(m,t);O(ge(l))}finally{me(!1)}},[t]),he=r.useCallback(async m=>{await g(m)},[g]),je=r.useCallback(async()=>{if(c){G(!0);try{await Pe(f,o,t),N(!1),await T()}finally{G(!1)}}},[o,c,f,t,T]),ve=r.useCallback(async()=>{J(!0);try{const m=await We(t);return await se(),m}finally{J(!1)}},[t,se]),Ne=r.useCallback(async m=>He(m,t),[t]),ae=r.useCallback(async()=>{try{const m=await Ae(t);Q(m)}catch{Q(null)}},[t]),W=r.useCallback(async()=>{try{const m=await Fe(t);E(m.content),_(m.exists)}catch{E(null),_(!1)}},[t]),Ce=r.useCallback(async m=>{await _e(m,t),await W()},[t,W]),ke=r.useCallback(async()=>{Z(!0);try{const m=await Oe(t);return await Promise.all([W(),ae()]),{success:m.success,summary:m.summary}}finally{Z(!1)}},[t,W,ae]),ue=r.useCallback(async()=>{K(!0);try{return await Ue(t)}finally{K(!1)}},[t]),Ee=r.useCallback(async m=>{q(!0);try{const l=m?await De(m,t):await De(t);if(m){const y=l.path??m;A(y),v(l.content),N(!1),await T();return}s(l.content),I(!0)}finally{q(!1)}},[t,T]);return{workingMemory:h,workingMemoryLoading:u,workingMemoryDirty:k,setWorkingMemory:P,saveWorkingMemory:Se,savingWorkingMemory:D,insightsContent:x,insightsLoading:n,insightsExists:V,refreshInsights:W,saveInsights:Ce,memorySettings:re,settingsLoading:w,savingMemorySettings:z,saveMemorySettings:ye,memoryFiles:be,memoryFilesLoading:d,selectedFilePath:f,selectedFileContent:o,selectedFileLoading:ne,selectedFileDirty:c,setSelectedFileContent:te,selectFile:he,saveSelectedFile:je,savingSelectedFile:xe,reloadMemoryFiles:T,backendStatus:ce,backendLoading:de,extractInsights:ke,extracting:ie,triggerDreamNow:ue,dreamRunning:le,auditReport:X,auditLoading:L,refreshAudit:ae,compactMemory:Ee,compacting:pe,installQmdAction:ve,installingQmd:fe,testRetrieval:Ne,stats:oe}}const Xe={Patterns:"pattern",Principles:"principle",Conventions:"convention",Pitfalls:"pitfall",Context:"context"},Je=72;function es(i,t){if(i.length<=t)return i;const h=Math.max(1,t-1),s=Math.ceil(h/2),u=Math.floor(h/2);return`${i.slice(0,s)}…${i.slice(i.length-u)}`}function ss(i){const t=`${i.label} — ${i.path}`;return es(t,Je)}function ts(i){if(!i)return[];const t=[],h=i.split(/(?=^## )/m);for(const s of h){const u=s.trim();if(!u)continue;const S=u.match(/^##\s+(.+?)(\n|$)/);if(S){const k=S[1].trim(),I=Xe[k]??k.toLowerCase(),D=u.slice(S[0].length).trim(),j=D.split(`
|
|
2
|
-
`).map(x=>x.replace(/^-\s+/,"").trim()).filter(x=>x.length>0&&(x.startsWith("- ")||x.startsWith("* ")));(j.length>0||D.length>0)&&t.push({name:k,key:I,items:j.length>0?j:D.length>0?[D]:[],expanded:!0})}}return t}function as(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 rs(i){return i.reduce((t,h)=>t+h.items.length,0)}function ys({projectId:i,addToast:t,onSendSelectionToTask:h}){const{t:s}=Ve("app"),[u,S]=r.useState("working"),[k,I]=r.useState(new Set),[D,j]=r.useState(!1),[x,E]=r.useState(null),[n,M]=r.useState({memoryEnabled:!0,memoryAutoSummarizeEnabled:!1,memoryAutoSummarizeThresholdChars:5e4,memoryAutoSummarizeSchedule:"0 3 * * *",memoryDreamsEnabled:!1,memoryDreamsSchedule:"0 4 * * *"}),[V,_]=r.useState(""),[re,O]=r.useState(!1),[w,Y]=r.useState(null),{insightsContent:z,insightsLoading:me,insightsExists:be,saveInsights:U,memorySettings:d,settingsLoading:p,saveMemorySettings:f,savingMemorySettings:A,backendStatus:o,backendLoading:v,extractInsights:ne,extracting:R,auditReport:c,auditLoading:N,refreshAudit:xe,compactMemory:G,compacting:ie,installQmdAction:Z,installingQmd:le,testRetrieval:K,memoryFiles:X,memoryFilesLoading:Q,selectedFilePath:L,selectedFileContent:$,selectedFileLoading:pe,selectedFileDirty:q,setSelectedFileContent:fe,selectFile:J,saveSelectedFile:oe,savingSelectedFile:ee,reloadMemoryFiles:ce,triggerDreamNow:de,dreamRunning:se}=Ke({projectId:i});r.useEffect(()=>{M(d)},[d]);const te=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]),g=r.useMemo(()=>X.find(a=>a.path===L),[X,L]),T=g?g.layer==="long-term"?s("memory.layerDescLongTerm","Curated durable decisions, conventions, constraints, and pitfalls promoted from dreams."):g.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."),P=r.useMemo(()=>ts(z),[z]),Se=r.useMemo(()=>rs(P),[P]),ye=r.useMemo(()=>as(z),[z]),he=r.useCallback(a=>{I(b=>{const C=new Set(b);return C.has(a)?C.delete(a):C.add(a),C})},[]),je=r.useCallback(async a=>{try{await J(a)}catch{t(s("memory.loadFileFailed","Failed to load memory file"),"error")}},[J,t]),ve=r.useCallback(async()=>{try{await oe(),t(s("memory.memorySaved","Memory saved"),"success")}catch{t(s("memory.saveMemoryFailed","Failed to save memory"),"error")}},[oe,t]),Ne=r.useCallback(async()=>{if(!te)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 f(a),t(s("memory.settingsSaved","Memory settings saved"),"success")}catch{t(s("memory.saveSettingsFailed","Failed to save memory settings"),"error")}},[te,n,d,f,t]),ae=r.useCallback(async()=>{try{const a=await Z();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")}},[Z,t]),W=r.useCallback(async()=>{O(!0),Y(null);try{const a=await K(V);Y(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{O(!1)}},[V,K,t]),Ce=r.useCallback(async()=>{try{await de(),t(s("memory.dreamProcessingComplete","Dream processing completed"),"success"),await ce()}catch(a){t(a instanceof Error?a.message:s("memory.dreamProcessingFailed","Failed to run dream processing"),"error")}},[de,ce,t]),ke=r.useCallback(async()=>{try{await G(L),t(s("memory.fileCompacted","Memory file compacted"),"success")}catch{t(s("memory.compactFailed","Failed to compact memory"),"error")}},[G,L,t]),ue=r.useCallback(async()=>{try{const a=await ne();t(a.summary,"success")}catch(a){t(a instanceof Error?a.message:s("memory.extractInsightsFailed","Failed to extract insights"),"error")}},[ne,t]),Ee=r.useCallback(async()=>{if(x!==null)try{await U(x),j(!1),E(null),t(s("memory.insightsSaved","Insights saved"),"success")}catch{t(s("memory.saveInsightsFailed","Failed to save insights"),"error")}},[x,U,t]),m=r.useCallback(()=>{E(z??""),j(!0)},[z]),l=r.useCallback(()=>{j(!1),E(null)},[]),y=!v&&o!==null,H=o?.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":u==="working",className:`memory-view-tab${u==="working"?" memory-view-tab--active":""}`,onClick:()=>S("working"),"data-testid":"memory-tab-working",children:s("memory.tabWorking","Working Memory")}),e.jsx("button",{type:"button",role:"tab","aria-selected":u==="insights",className:`memory-view-tab${u==="insights"?" memory-view-tab--active":""}`,onClick:()=>S("insights"),"data-testid":"memory-tab-insights",children:s("memory.tabInsights","Insights")}),e.jsx("button",{type:"button",role:"tab","aria-selected":u==="engines",className:`memory-view-tab${u==="engines"?" memory-view-tab--active":""}`,onClick:()=>S("engines"),"data-testid":"memory-tab-engines",children:s("memory.tabEngines","Engines")})]}),e.jsxs("div",{className:"memory-view-content",children:[u==="working"&&e.jsxs("div",{className:"memory-working-tab",children:[y&&!H&&e.jsx("div",{className:"memory-readonly-banner",children:s("memory.readOnlyBanner","This memory backend is read-only. Changes cannot be saved.")}),Q||pe?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(F,{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:L,onChange:a=>{je(a.target.value)},disabled:q,children:X.map(a=>e.jsx("option",{value:a.path,title:`${a.label} — ${a.path}`,children:ss(a)},a.path))}),e.jsx("small",{children:q?s("memory.fileSwitchDirtyHint","Save or discard the current edits before switching files."):s("memory.fileSwitchHint","Choose any project memory file to view or edit.")})]}),g&&e.jsxs("div",{className:"memory-file-summary",children:[e.jsx("span",{children:g.layer==="long-term"?s("memory.layerLongTerm","Long-term"):g.layer==="daily"?s("memory.layerDaily","Daily"):s("memory.layerDreams","Dreams")}),e.jsx("strong",{children:g.path}),e.jsx("small",{children:s("memory.fileSummary","{{size}} bytes · updated {{updatedAt}}",{size:g.size.toLocaleString(),updatedAt:new Date(g.updatedAt).toLocaleString()})})]}),e.jsxs("div",{className:"form-group memory-editor-form-group",children:[e.jsx("label",{children:g?.label||s("memory.editorLabel","Memory Editor")}),e.jsx("small",{children:T}),e.jsx("div",{className:"memory-editor-container",children:e.jsx(ze,{content:$,onChange:fe,readOnly:!H,filePath:L,onSendSelectionToTask:h})})]})]}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsx("span",{className:"memory-char-count",children:s("memory.charCount","{{count}} characters",{count:$.length})}),e.jsx("div",{className:"memory-flex-spacer"}),H&&$.length>0&&e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:ke,disabled:ie||q,children:ie?e.jsxs(e.Fragment,{children:[e.jsx(F,{size:14,className:"animate-spin"}),s("memory.compacting","Compacting…")]}):s("memory.compactSelectedFile","Compact Selected File")}),q&&H&&e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:ve,disabled:ee,children:ee?e.jsxs(e.Fragment,{children:[e.jsx(F,{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=>{M(b=>({...b,memoryDreamsEnabled:a.target.checked}))},disabled:!n.memoryEnabled||p}),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=>{M(b=>({...b,memoryDreamsSchedule:a.target.value}))},placeholder:"0 4 * * *",disabled:p}),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:Ce,disabled:se||!n.memoryDreamsEnabled,children:se?e.jsxs(e.Fragment,{children:[e.jsx(F,{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=>{M(b=>({...b,memoryAutoSummarizeEnabled:a.target.checked}))},disabled:!n.memoryEnabled||p}),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=>{M(b=>({...b,memoryAutoSummarizeThresholdChars:parseInt(a.target.value,10)||5e4}))},min:1e3,disabled:p}),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=>{M(b=>({...b,memoryAutoSummarizeSchedule:a.target.value}))},placeholder:"0 3 * * *",disabled:p}),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.")}),te&&e.jsx("div",{className:"memory-action-bar",children:e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:Ne,disabled:A||p,children:A?e.jsxs(e.Fragment,{children:[e.jsx(F,{size:14,className:"animate-spin"}),s("memory.saving","Saving…")]}):s("memory.saveSettings","Save Settings")})})]})]})]}),u==="insights"&&e.jsx("div",{className:"memory-insights-tab",children:me?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(F,{size:20,className:"animate-spin"}),e.jsx("span",{children:s("memory.loadingInsights","Loading insights…")})]}):D?e.jsxs("div",{className:"memory-insights-editor-layout",children:[e.jsx("div",{className:"memory-editor-container",children:e.jsx(ze,{content:x??"",onChange:E,readOnly:!1,filePath:".fusion/memory/INSIGHTS.md",onSendSelectionToTask:h})}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:l,children:s("memory.cancel","Cancel")}),e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:Ee,children:s("memory.saveInsights","Save Insights")})]})]}):!be||P.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:ue,disabled:R,children:R?e.jsxs(e.Fragment,{children:[e.jsx(F,{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:Se}),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:P.length}),e.jsx("div",{className:"memory-stat-label",children:s("memory.categories","Categories")})]}),ye&&e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value memory-stat-value--updated",children:ye}),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:ue,disabled:R,children:R?e.jsxs(e.Fragment,{children:[e.jsx(F,{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:m,children:s("memory.editRaw","Edit Raw")})]}),e.jsx("div",{className:"memory-categories-list",children:P.map(a=>{const b=!k.has(a.key);return e.jsxs("div",{className:"memory-category-section",children:[e.jsxs("div",{className:"memory-category-header",onClick:()=>he(a.key),role:"button",tabIndex:0,onKeyDown:C=>{(C.key==="Enter"||C.key===" ")&&(C.preventDefault(),he(a.key))},children:[e.jsx("h4",{children:a.name}),e.jsx("span",{className:"memory-category-count",children:a.items.length})]}),b&&e.jsx("div",{className:"memory-category-items",children:a.items.map((C,Ie)=>e.jsx("div",{className:"memory-insight-item",children:C.replace(/^-\s+/,"").replace(/^\*\s+/,"")},Ie))})]},a.key)})})]})}),u==="engines"&&e.jsx("div",{className:"memory-engines-tab",children:v||N?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(F,{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")}),o?.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.")})]}):o?.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:o.qmdInstallCommand||"bun install -g @tobilu/qmd"})]}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:ae,disabled:le,children:le?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:[o?.capabilities?.readable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capReadable","Readable")}),o?.capabilities?.writable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capWritable","Writable")}),o?.capabilities?.supportsAtomicWrite&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capAtomicWrites","Atomic Writes")}),o?.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:V,onChange:a=>_(a.target.value),placeholder:s("memory.searchPlaceholder","Search memory with qmd")}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:W,disabled:re,children:re?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.")}),w&&e.jsxs("div",{className:"memory-test-result",children:[e.jsx("strong",{children:s("memory.testResultCount",'{{count}} result for "{{query}}"',{count:w.results.length,query:w.query,defaultValue_one:'{{count}} result for "{{query}}"',defaultValue_other:'{{count}} results for "{{query}}"'})}),e.jsx("small",{children:s("memory.testResultStatus","qmd {{qmdStatus}} · {{fallbackStatus}}",{qmdStatus:w.qmdAvailable?s("memory.qmdStatusAvailable","available"):s("memory.qmdStatusMissing","missing"),fallbackStatus:w.usedFallback?s("memory.localFallbackUsed","local fallback used"):s("memory.qmdPathUsed","qmd path used")})}),w.results.length>0?e.jsx("ul",{children:w.results.map((a,b)=>e.jsxs("li",{children:[e.jsxs("span",{children:[a.path,":",a.lineStart]}),e.jsx("p",{children:a.snippet})]},`${a.path}-${a.lineStart}-${b}`))}):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:o?.currentBackend==="file"?s("memory.backendFile","File (.fusion/memory/, agent/<agent-name>/memory/)"):o?.currentBackend==="readonly"?s("memory.backendReadonly","Read-Only"):o?.currentBackend==="qmd"?s("memory.backendQmd","QMD (Quantized Memory Distillation)"):o?.currentBackend??"unknown"})}),e.jsxs("div",{className:"memory-capability-row",children:[o?.capabilities?.readable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capReadable","Readable")}),o?.capabilities?.writable&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capWritable","Writable")}),o?.capabilities?.supportsAtomicWrite&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capAtomicWrites","Atomic Writes")}),o?.capabilities?.persistent&&e.jsx("span",{className:"memory-capability-badge",children:s("memory.capPersistent","Persistent")})]})]}),c&&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--${c.health}`,children:c.health==="healthy"?s("memory.healthHealthy","Healthy"):c.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:c.workingMemory.size})}),e.jsx("div",{className:"memory-health-detail",children:s("memory.sectionCount","{{count}} sections",{count:c.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:c.insightsMemory.size})}),e.jsx("div",{className:"memory-health-detail",children:s("memory.insightCount","{{count}} insights",{count:c.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:c.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:c.extraction.summary||s("memory.insightsExtracted","{{count}} insights extracted",{count:c.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:c.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")})}),c.pruning.applied&&e.jsx("div",{className:"memory-health-detail",children:c.pruning.reason})]})]}),c&&c.checks.length>0&&e.jsxs("div",{className:"memory-engine-card",children:[e.jsx("h3",{children:s("memory.auditChecksTitle","Audit Checks")}),e.jsx("div",{children:c.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:()=>xe(),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{ys as MemoryView};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.memory-view{display:flex;flex-direction:column;height:100%;padding:var(--space-lg);overflow:hidden}.memory-view-header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start;margin-bottom:var(--space-lg)}.memory-view-header h2{font-size:18px;color:var(--text);margin:0}.memory-view-description{color:var(--text-muted);font-size:13px;margin:var(--space-xs) 0 0 0}.memory-view-tabs{display:flex;flex-direction:row;gap:var(--space-xs);border-bottom:1px solid var(--border);margin-bottom:var(--space-lg)}.memory-view-tab{padding:var(--space-sm) var(--space-md);border-radius:var(--radius-sm) var(--radius-sm) 0 0;color:var(--text-muted);background:transparent;border:none;cursor:pointer;font-size:13px;transition:background var(--transition-fast),color var(--transition-fast)}.memory-view-tab:hover{background:var(--card-hover);color:var(--text)}.memory-view-tab:focus-visible{outline:none;box-shadow:var(--focus-ring)}.memory-view-tab--active{color:var(--text);border-bottom:2px solid var(--todo);font-weight:500}.memory-view-content{flex:1;min-height:0;display:flex;flex-direction:column}.memory-working-tab,.memory-insights-tab,.memory-engines-tab{flex:1;min-height:0;display:flex;flex-direction:column;overflow-y:auto}.memory-editor-section{display:flex;flex-direction:column;min-height:0;flex:1}.memory-editor-form-group{flex:1;min-height:0;display:flex;flex-direction:column}.memory-editor-container{border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;display:flex;flex-direction:column;flex:1 1 auto;min-height:calc(var(--space-xl) * 13 + var(--space-xs) * 2)}.memory-insights-editor-layout{display:flex;flex:1;min-height:0;flex-direction:column}.memory-category-section{margin-bottom:var(--space-lg)}.memory-category-header{display:flex;flex-direction:row;justify-content:space-between;align-items:center;cursor:pointer;padding:var(--space-sm) 0;border-bottom:1px solid var(--border);transition:opacity var(--transition-fast)}.memory-category-header:hover{opacity:.8}.memory-category-header h4{font-size:14px;font-weight:500;margin:0;color:var(--text)}.memory-category-count{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted);background:color-mix(in srgb,var(--text-muted) 15%,transparent);padding:2px 8px;border-radius:var(--radius-pill)}.memory-category-items{padding-top:var(--space-sm)}.memory-insight-item{padding:var(--space-xs) var(--space-sm);margin-bottom:var(--space-xs);border-left:3px solid var(--border);font-size:13px;color:var(--text);line-height:1.5}.memory-engine-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-xl);margin-bottom:var(--space-lg)}.memory-engine-card h3{font-size:14px;font-weight:500;margin:0 0 var(--space-md) 0;color:var(--text)}.memory-engine-status{display:flex;flex-direction:row;align-items:center;gap:var(--space-sm)}.memory-health-badge{display:inline-block;padding:2px 10px;border-radius:var(--radius-pill);font-size:12px}.memory-health-badge--healthy{background:color-mix(in srgb,var(--color-success) 15%,transparent);color:var(--color-success)}.memory-health-badge--warning{background:color-mix(in srgb,var(--color-warning) 15%,transparent);color:var(--color-warning)}.memory-health-badge--issues{background:color-mix(in srgb,var(--color-error) 15%,transparent);color:var(--color-error)}.memory-action-bar{display:flex;flex-direction:row;gap:var(--space-sm);margin-top:var(--space-md);align-items:center}.memory-empty-extract-button{margin-top:var(--space-md)}.memory-stat-value--updated{font-size:var(--space-lg)}.memory-capability-row{display:flex;gap:var(--space-xs);margin-top:var(--space-sm);flex-wrap:wrap}.memory-emphasis-text{font-weight:500}.memory-health-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--space-md)}.memory-health-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-md)}.memory-health-label{font-size:var(--space-md);color:var(--text-muted);text-transform:uppercase;margin-bottom:var(--space-xs)}.memory-health-detail{font-size:var(--space-md);color:var(--text-muted)}.memory-health-section{margin-top:var(--space-md);padding-top:var(--space-md);border-top:1px solid var(--border)}.memory-status-text--success{color:var(--color-success)}.memory-status-text--error{color:var(--color-error)}.memory-status-text--warning{color:var(--color-warning)}.memory-status-text--muted{color:var(--text-muted)}.memory-audit-check-content{flex:1}.memory-settings-note{margin-top:var(--space-lg);font-size:var(--space-md);color:var(--text-muted);display:flex;align-items:center;gap:var(--space-xs);flex-wrap:wrap}.memory-settings-note-button{background:none;border:none;color:inherit;cursor:pointer;font:inherit;padding:0;text-decoration:underline}.memory-settings-note-button:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:var(--focus-ring-strong)}.memory-empty-state{color:var(--text-muted);padding:var(--space-2xl);text-align:center;display:flex;flex-direction:column;align-items:center;gap:var(--space-sm)}.memory-stats-row{display:flex;flex-direction:row;gap:var(--space-lg);margin-bottom:var(--space-lg)}.memory-stat-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md) var(--space-lg);flex:1}.memory-stat-value{font-size:24px;font-weight:600;color:var(--text);margin-bottom:var(--space-xs)}.memory-stat-label{font-size:12px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.memory-audit-check{display:flex;flex-direction:row;padding:var(--space-sm) 0;border-bottom:1px solid var(--border);gap:var(--space-sm)}.memory-audit-check:last-child{border-bottom:none}.memory-audit-check-passed{color:var(--color-success);font-weight:600}.memory-audit-check-failed{color:var(--color-error);font-weight:600}.memory-capability-badge{font-size:11px;padding:2px 8px;border-radius:var(--radius-pill);background:color-mix(in srgb,var(--todo) 15%,transparent);color:var(--text-muted)}.memory-readonly-banner{background:color-mix(in srgb,var(--color-warning) 10%,transparent);border:1px solid color-mix(in srgb,var(--color-warning) 30%,transparent);border-radius:var(--radius-md);padding:var(--space-md);color:var(--color-warning);font-size:13px;margin-bottom:var(--space-md)}.memory-char-count{font-size:12px;color:var(--text-muted)}.memory-categories-list{margin-top:var(--space-lg)}.memory-config-section{margin-top:var(--space-lg);padding-top:var(--space-lg);border-top:1px solid var(--border);display:flex;flex-direction:column;gap:var(--space-md)}.memory-settings-group{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface);padding:var(--space-sm) 0}.memory-flex-spacer{flex:1}.memory-qmd-card{border-style:solid}.memory-retrieval-card{display:flex;flex-direction:column;gap:var(--space-sm)}.memory-retrieval-input-row{display:flex;align-items:center;gap:var(--space-sm)}.memory-retrieval-input-row .input{flex:1}.memory-retrieval-card .memory-test-result{margin-top:var(--space-sm)}@media(max-width:768px){.memory-view{padding:var(--space-md)}.memory-view-header{flex-direction:column;gap:var(--space-sm)}.memory-editor-container{min-height:calc(var(--space-xl) * 10)}.memory-stats-row{flex-wrap:wrap}.memory-stat-card{min-width:calc(50% - var(--space-sm))}.memory-view-tab{min-height:36px;padding:var(--space-sm)}.memory-engine-card{padding:var(--space-md)}.memory-retrieval-input-row{flex-direction:column;align-items:stretch}.memory-settings-group{padding:var(--space-xs) 0}.memory-health-grid{grid-template-columns:1fr}.memory-config-section{margin-top:var(--space-md);padding-top:var(--space-md)}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.nodes-management-overlay{display:flex;flex-direction:column;gap:var(--space-md);height:100%;overflow-y:auto;-webkit-overflow-scrolling:touch}.nodes-management-overlay__header{display:flex;justify-content:flex-end}.nodes-view{--nodes-view-spin-duration: calc(var(--duration-slow) * 4);--nodes-view-pulse-duration: calc(var(--duration-slow) * 5);display:flex;flex-direction:column;gap:var(--space-md);padding:var(--space-sm) var(--space-md) var(--space-xl)}.nodes-view-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--space-sm)}.nodes-view-title{display:flex;align-items:center;gap:var(--space-sm)}.nodes-view-title h2{margin:0;display:flex;align-items:center;gap:var(--space-sm)}.nodes-view-count{color:var(--text-muted);font-size:calc(var(--space-md) + var(--space-xs) / 4)}.nodes-view-actions{display:flex;gap:var(--space-sm)}.nodes-view-close{margin-left:auto}.nodes-view-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(calc(var(--space-xl) * 5.833),1fr));gap:var(--space-sm)}.nodes-view-stat{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-sm) var(--space-md);display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}.nodes-view-stat span{display:inline-flex;align-items:center;gap:var(--space-sm);color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs))}.nodes-view-stat strong{font-size:calc(var(--space-lg) + var(--space-xs) / 2)}.nodes-view-stat--online strong{color:var(--color-success)}.nodes-view-stat--offline strong{color:var(--color-error)}.nodes-view-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(calc(var(--space-lg) * 20),1fr));gap:var(--space-md)}.nodes-view-empty{padding:var(--space-xl);border:1px dashed var(--border);border-radius:var(--radius-md);text-align:center;color:var(--text-muted);display:flex;flex-direction:column;align-items:center;gap:var(--space-md)}.nodes-view-error{color:var(--color-error);font-size:calc(var(--space-md) + var(--space-xs) / 4)}.node-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md);display:flex;flex-direction:column;gap:var(--space-md);cursor:pointer;transition:border-color var(--transition-fast),transform var(--transition-fast)}.node-card:hover{border-color:var(--accent);transform:translateY(calc(var(--space-xs) * -.25))}.node-card:focus-visible{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.node-card--loading{min-height:calc(var(--space-xl) * 9.167);opacity:.55;pointer-events:none}.node-card__header{display:flex;align-items:center;justify-content:space-between}.node-card__title-wrap{display:flex;align-items:center;gap:var(--space-sm)}.node-card__icon{width:calc(var(--space-lg) * 2.125);height:calc(var(--space-lg) * 2.125);border-radius:var(--radius-sm);display:inline-flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent)}.node-card__name{margin:0;font-size:calc(var(--space-md) + var(--space-xs));line-height:1.25}.node-card__meta-row{margin-top:var(--space-xs);display:flex;align-items:center;gap:var(--space-xs)}.node-card__type-badge{border:1px solid var(--border);border-radius:var(--radius-pill);padding:var(--space-xs) var(--space-sm);font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted)}.node-card__status{display:inline-flex;align-items:center;gap:var(--space-xs);font-size:calc(var(--space-sm) + var(--space-xs) * .75);font-weight:600}.node-card__status-indicator{width:var(--space-sm);height:var(--space-sm);border-radius:50%}.node-card__status--online .node-card__status-indicator{background:var(--color-success)}.node-card__status--offline .node-card__status-indicator,.node-card__status--error .node-card__status-indicator{background:var(--color-error)}.node-card__status--connecting .node-card__status-indicator{background:var(--color-warning)}.node-card__auth-indicator{display:inline-flex;align-items:center;margin-left:var(--space-xs);vertical-align:middle}.node-card__url{font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted);word-break:break-all}.node-card__metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.node-card__metric{display:flex;flex-direction:column;gap:var(--space-xs)}.node-card__metric-label{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs) * .75);text-transform:uppercase;letter-spacing:.03em}.node-card__metric-value{font-size:calc(var(--space-md) + var(--space-xs));font-weight:600}.node-card__sync{display:flex;align-items:center;gap:var(--space-xs);margin-top:var(--space-sm);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.node-card__sync-dot{width:var(--space-sm);height:var(--space-sm);border-radius:50%;flex-shrink:0}.node-card__sync-time{color:var(--text-muted)}.nodes-view-stat--synced strong{color:var(--color-success)}.node-card__actions{display:flex;gap:var(--space-xs);flex-wrap:wrap}.node-card__action{display:inline-flex;align-items:center;gap:var(--space-xs)}.node-card__action--remove{margin-left:auto}.node-card__action--remove:not(.btn-danger){color:var(--color-error);border-color:color-mix(in srgb,var(--color-error) 45%,var(--border))}.node-card__action--remove.is-armed{background:color-mix(in srgb,var(--color-error) 14%,transparent)}.node-card__docker-badge{display:inline-flex;align-items:center;gap:var(--space-xs);border-radius:var(--radius-pill);padding:var(--space-xs) var(--space-sm);font-size:calc(var(--space-sm) + var(--space-xs) * .75);background:color-mix(in srgb,var(--color-info) 15%,transparent);color:var(--color-info)}.node-card__docker-meta{display:flex;gap:var(--space-sm);margin-top:var(--space-xs);font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.node-card__docker-meta span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mesh-topology{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-md);min-height:calc(var(--space-2xl) * 6.25);padding:var(--space-md);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md)}.mesh-topology__svg{width:100%;max-width:calc(var(--space-2xl) * 12.5);height:auto;aspect-ratio:1}.mesh-topology__node{transition:filter var(--transition-fast)}.mesh-topology__node:hover{filter:brightness(1.1)}.mesh-topology__node-circle{stroke:var(--border);stroke-width:calc(var(--space-xs) / 2);transition:fill var(--transition-fast)}.mesh-topology__node-label{font-size:calc(var(--space-sm) + var(--space-xs) * .75);fill:var(--text);font-weight:500}.mesh-topology__node-type-badge{fill:color-mix(in srgb,var(--surface) 75%,var(--bg));stroke:var(--border);stroke-width:calc(var(--space-xs) / 4)}.mesh-topology__node-type-text{font-size:calc(var(--space-sm) + var(--space-xs) / 2);font-weight:700;fill:var(--text-muted);text-transform:uppercase;letter-spacing:.03em}.mesh-topology__link{stroke:var(--border);stroke-width:calc((var(--space-xs) * 3) / 8);stroke-dasharray:var(--space-xs),var(--space-xs);opacity:.6}.mesh-topology__legend{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--space-md);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.mesh-topology__legend-item{display:flex;align-items:center;gap:var(--space-sm)}.mesh-topology__notice{margin:var(--space-md) 0 0;text-align:center;color:var(--text-dim);font-size:calc(var(--space-sm) + var(--space-xs))}.mesh-topology__legend-dot{width:calc(var(--space-sm) + var(--space-xs) / 2);height:calc(var(--space-sm) + var(--space-xs) / 2);border-radius:50%;border:1px solid var(--border)}.mesh-topology--empty{justify-content:center}.mesh-topology__empty-state{text-align:center;color:var(--text-muted);font-size:calc(var(--space-md) + var(--space-xs) / 2)}.connect-node-modal{width:min(calc(var(--space-lg) * 30),calc(100vw - (var(--space-lg) * 2)))}.connect-node-form{display:flex;flex-direction:column;gap:var(--space-md)}.connect-node-form .form-group{padding:0;margin-top:0}.connect-node-form .form-group:last-of-type{margin-bottom:0}.connect-node-field{display:flex;flex-direction:column;gap:var(--space-xs)}.connect-node-field__input{width:100%}.connect-node-field__input[aria-invalid=true]{border-color:var(--color-error);background:color-mix(in srgb,var(--color-error) 5%,var(--surface))}.connect-node-field__input[aria-invalid=true]:focus-visible{border-color:var(--color-error);box-shadow:var(--glow-danger)}.connect-node-url-preview{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);background:color-mix(in srgb,var(--surface) 50%,var(--bg));border-radius:var(--radius-sm);border-left:var(--space-xs) solid var(--accent);font-size:calc(var(--space-sm) + var(--space-xs))}.connect-node-url-preview-label{color:var(--text-muted)}.connect-node-url-preview code{font-family:var(--font-mono);color:var(--text);font-size:calc(var(--space-sm) + var(--space-xs))}.connect-node-actions{display:flex;justify-content:flex-end;gap:var(--space-sm);padding:var(--modal-padding);border-top:1px solid var(--border)}.nodes-view-topology{margin-bottom:var(--space-md)}.nodes-view-section-title{font-size:calc(var(--space-md) + var(--space-xs) * .5);font-weight:600;color:var(--text);margin:0 0 var(--space-sm)}.nodes-view .node-status-indicator{display:inline-flex;align-items:center;gap:var(--space-xs);font-size:calc(var(--space-sm) + var(--space-xs) * .625)}.nodes-view .node-status-indicator__label,.nodes-view .node-status-indicator--local{color:var(--text-muted)}.nodes-view .node-status-indicator--remote{color:var(--text)}.nodes-view .node-status-indicator__dot{width:var(--space-sm);height:var(--space-sm);border-radius:50%;position:relative;display:inline-block}.nodes-view .node-status-indicator__dot--online{background:var(--color-success);box-shadow:var(--glow-success)}.nodes-view .node-status-indicator__dot--offline,.nodes-view .node-status-indicator__dot--error{background:var(--color-error)}.nodes-view .node-status-indicator__dot--connecting{background:var(--color-warning);animation:pulse-warning var(--nodes-view-pulse-duration) ease-in-out infinite}.nodes-view .node-status-indicator__spinner{position:absolute;inset:0;border:calc(var(--space-xs) / 2) solid transparent;border-top-color:currentColor;border-radius:50%;animation:spin var(--nodes-view-spin-duration) linear infinite}.nodes-view .node-status-indicator__name{font-weight:500}.nodes-view .node-status-indicator__details{font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}@keyframes pulse-warning{0%,to{opacity:1;box-shadow:var(--glow-warning)}50%{opacity:.6;box-shadow:var(--glow-warning)}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.spin{animation:spin var(--nodes-view-spin-duration) linear infinite}@media(max-width:768px){.nodes-management-overlay{position:fixed;inset:0;z-index:50;background:var(--bg);padding-top:max(var(--space-sm),env(safe-area-inset-top,0px));padding-bottom:calc(var(--mobile-nav-height, 0px) + max(env(safe-area-inset-bottom,0px),12px));overflow-y:auto;-webkit-overflow-scrolling:touch}.nodes-view{padding-inline:var(--space-sm)}.nodes-view-grid,.node-card__metrics{grid-template-columns:1fr}.node-card__docker-badge,.node-card__docker-meta{gap:var(--space-xs)}.node-card__docker-meta span{max-width:calc(var(--space-2xl) * 4.5)}.connect-node-modal{width:calc(100vw - (var(--space-md) * 2))}.connect-node-field__input{min-height:calc(var(--space-2xl) + var(--space-md))}.nodes-view-header{flex-wrap:wrap;gap:var(--space-sm)}.nodes-view-title h2{font-size:calc(var(--space-md) + var(--space-xs))}.nodes-view-title h2 svg{flex-shrink:0}.nodes-view-count{font-size:calc(var(--space-sm) + var(--space-xs))}.nodes-view-actions{flex-wrap:wrap;gap:var(--space-sm);width:100%;justify-content:flex-end}.nodes-view-close{min-height:calc(var(--space-xl) + var(--space-md));min-width:calc(var(--space-xl) + var(--space-md))}.nodes-view-actions .btn{min-height:calc(var(--space-xl) + var(--space-md))}.nodes-view-stats{grid-template-columns:repeat(2,1fr);gap:var(--space-sm)}.nodes-view-stat{padding:var(--space-xs) var(--space-sm)}.nodes-view-stat span{font-size:calc(var(--space-sm) + var(--space-xs) * .75)}.nodes-view-stat strong{font-size:calc(var(--space-md) + var(--space-xs) / 2)}.nodes-view-empty{padding:var(--space-xl) var(--space-md);text-align:center}.nodes-view-error{padding:var(--space-md);margin:var(--space-md) 0}.nodes-view-topology{padding:var(--space-sm) 0}.nodes-view-section-title{font-size:calc(var(--space-md) + var(--space-xs) / 4)}}@media(min-width:769px)and (max-width:1024px){.nodes-management-overlay{position:fixed;inset:0;z-index:50;background:var(--bg);overflow-y:auto;-webkit-overflow-scrolling:touch}}.add-node-modal{width:min(calc(var(--space-lg) * 32.5),calc(100vw - (var(--space-lg) * 2)))}.add-node-modal__body{display:flex;flex-direction:column;gap:var(--space-md)}.add-node-modal__row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.add-node-modal__fieldset{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-sm)}.add-node-modal__fieldset legend{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs) * .625);padding:0 var(--space-xs)}.add-node-modal__storage-toggle{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-sm)}.add-node-modal__advanced-btn{align-self:flex-start}.add-node-modal__advanced{border:1px dashed var(--border);border-radius:var(--radius-sm);padding:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-sm)}.add-node-modal__textarea{min-height:calc(var(--space-2xl) * 2.25);resize:vertical;font-family:var(--font-mono)}.add-node-modal__description{font-size:calc(var(--space-sm) + var(--space-xs) * .625);color:var(--text-muted);margin-bottom:var(--space-sm);padding:0}.add-node-modal__field{display:flex;flex-direction:column;gap:var(--space-xs)}.add-node-modal__field>span{font-size:calc(var(--space-sm) + var(--space-xs) * .625);font-weight:600;color:var(--text-muted)}.add-node-modal__field .input{width:100%;padding:var(--space-sm) var(--space-md);font-size:calc(var(--space-md) + var(--space-xs) * .5)}.add-node-modal__field .input:focus-visible{border-color:var(--accent);box-shadow:var(--focus-ring-strong)}.add-node-modal__field .input[aria-invalid=true]{border-color:var(--color-error);background:color-mix(in srgb,var(--color-error) 5%,var(--surface))}.add-node-modal__field .input[aria-invalid=true]:focus{box-shadow:var(--glow-danger)}.add-node-modal__hint{font-size:calc(var(--space-sm) + var(--space-xs) * .375);color:var(--text-dim);margin-top:calc(var(--space-xs) / 2)}.add-node-modal__error{margin-top:calc(var(--space-xs) / 2)}.add-node-modal__type-toggle{display:flex;gap:0;border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;background:var(--surface)}.add-node-modal__type-btn{flex:1;padding:calc(var(--space-sm) + var(--space-xs) / 2) var(--space-lg);border:none;background:transparent;color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs) * .625);font-weight:500;cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.add-node-modal__type-btn:hover:not(:disabled){background:color-mix(in srgb,var(--bg) 50%,var(--surface))}.add-node-modal__type-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);z-index:1}.add-node-modal__type-btn.active{background:var(--accent);color:var(--bg)}.add-node-modal__type-btn:disabled{opacity:.6;cursor:not-allowed}.add-node-modal__remote-fields{display:grid;gap:var(--space-sm)}.add-node-modal__discovery-actions{display:flex;flex-direction:column;gap:var(--space-xs)}.add-node-modal__discovery-state{font-size:calc(var(--space-sm) + var(--space-xs) * .375);color:var(--color-success)}.add-node-modal__discovered-list{display:flex;flex-direction:column;gap:var(--space-xs)}.add-node-modal__discovered-card{padding:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-xs)}.add-node-modal__discovered-row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}.add-node-modal__projects{display:flex;flex-direction:column;gap:var(--space-sm)}.add-node-modal__projects-title{margin:0;font-size:calc(var(--space-md) + var(--space-xs) * .5)}.add-node-modal__project-list{display:flex;flex-direction:column;gap:var(--space-sm)}.add-node-modal__project-card{padding:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-sm)}.add-node-modal__project-toggle{margin:0}@media(max-width:768px){.add-node-modal{width:calc(100vw - (var(--space-md) * 2))}.add-node-modal__type-toggle{width:100%}.add-node-modal__type-btn{flex:1;padding:var(--space-md) var(--space-lg)}.add-node-modal__field input{min-height:calc(var(--space-2xl) + var(--space-md));font-size:calc(var(--space-md) + var(--space-xs) * .5)}.add-node-modal__row{grid-template-columns:1fr}.add-node-modal__project-card{padding:var(--space-md)}.add-node-modal__discovered-row{flex-direction:column;align-items:flex-start}}.docker-tls-config{display:flex;flex-direction:column;gap:var(--space-md)}.docker-tls-config__fields{display:grid;gap:var(--space-md)}.docker-tls-config__field{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-tls-config__field label{color:var(--text-muted)}@media(max-width:768px){.docker-tls-config .input{min-height:calc(var(--mobile-nav-height) - var(--space-sm))}}.docker-target-selector{display:flex;flex-direction:column;gap:var(--space-md)}.docker-target-selector__modes{display:flex;gap:var(--space-sm);flex-wrap:wrap}.docker-target-selector__mode-active{border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.docker-target-selector__panel{display:grid;gap:var(--space-md)}.docker-target-selector__field{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-target-selector__field label{color:var(--text-muted)}.docker-target-selector__context-row{display:grid;gap:var(--space-sm);grid-template-columns:minmax(0,1fr) auto;align-items:center}.docker-target-selector__status{color:var(--text-muted)}.docker-target-selector__success{color:var(--color-success)}.docker-target-selector__error{color:var(--color-error)}@media(max-width:768px){.docker-target-selector__modes .btn{min-height:calc(var(--mobile-nav-height) - var(--space-sm))}}.docker-onboarding{width:min(calc(var(--space-2xl) * 22.5),calc(100vw - (var(--space-lg) * 2)))}.docker-onboarding__body{display:flex;flex-direction:column;gap:var(--space-md)}.docker-onboarding__section{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md);display:flex;flex-direction:column;gap:var(--space-sm)}.docker-onboarding__section-title{margin:0;display:flex;align-items:center;gap:var(--space-sm);font-size:calc(var(--space-md) + var(--space-xs) / 2)}.docker-onboarding__field{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-onboarding__inline-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.docker-onboarding__radio-group{display:flex;align-items:center;gap:var(--space-md);flex-wrap:wrap}.docker-onboarding__type-toggle{display:flex;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}.docker-onboarding__type-btn{flex:1;border:none;background:var(--surface);color:var(--text);padding:var(--space-sm) var(--space-md);cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.docker-onboarding__type-btn+.docker-onboarding__type-btn{border-left:1px solid var(--border)}.docker-onboarding__type-btn.is-active{background:var(--todo);color:var(--bg)}.docker-onboarding__type-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);position:relative;z-index:1}.docker-onboarding__checkbox-group{display:flex;flex-direction:column;gap:var(--space-xs)}.docker-onboarding__kv-list{display:flex;flex-direction:column;gap:var(--space-sm)}.docker-onboarding__kv-list h5{margin:0;font-size:calc(var(--space-sm) + var(--space-xs))}.docker-onboarding__kv-row{display:grid;gap:var(--space-sm);align-items:center}.docker-onboarding__kv-row--env{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto}.docker-onboarding__kv-row--mount{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto auto}.docker-onboarding__kv-add{align-self:flex-start}.docker-onboarding__advanced-toggle{border:none;background:none;color:var(--text);padding:var(--space-xs);margin:calc(var(--space-xs) * -1);border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:space-between;width:100%;cursor:pointer;font-size:calc(var(--space-md) + var(--space-xs) / 2);font-weight:600}.docker-onboarding__advanced-toggle:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.docker-onboarding__advanced-toggle svg{transition:transform var(--transition-fast)}.docker-onboarding__advanced-toggle.is-expanded svg{transform:rotate(180deg)}.docker-onboarding__advanced-content{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--transition-fast)}.docker-onboarding__advanced-content>div{overflow:hidden;display:flex;flex-direction:column;gap:var(--space-sm)}.docker-onboarding__advanced-content.is-expanded{grid-template-rows:1fr}.docker-onboarding__tls-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.docker-onboarding__tls-fields .docker-onboarding__field:first-child{grid-column:1 / -1}@media(max-width:768px){.docker-onboarding{width:calc(100vw - (var(--space-md) * 2))}.docker-onboarding__inline-fields,.docker-onboarding__tls-fields,.docker-onboarding__kv-row{grid-template-columns:1fr}.docker-onboarding .input,.docker-onboarding .select,.docker-onboarding .btn{min-height:calc(var(--space-2xl) + var(--space-md))}.docker-onboarding__advanced-content{transition:none}}.settings-sync-log{display:flex;flex-direction:column;gap:var(--space-sm)}.settings-sync-log__header{display:flex;align-items:center;gap:var(--space-xs);cursor:pointer;padding:var(--space-xs) 0;border-radius:var(--radius-sm);border:none;background:transparent;color:var(--text);font:inherit;text-align:left;transition:background-color var(--transition-fast)}.settings-sync-log__header:hover{background:var(--surface-hover)}.settings-sync-log__header:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);background:var(--surface-hover)}.settings-sync-log__chevron{transform:rotate(0);transition:transform var(--transition-fast)}.settings-sync-log__chevron--expanded{transform:rotate(180deg)}.settings-sync-log__filters{display:flex;gap:var(--space-sm);align-items:center;flex-wrap:wrap}.settings-sync-log__filters label{display:flex;align-items:center;gap:var(--space-xs);font-size:12px;color:var(--text-muted)}.settings-sync-log__filters select{font-size:12px;padding:4px 8px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text)}.settings-sync-log__filters select:focus{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring)}.settings-sync-log__list{display:flex;flex-direction:column}.settings-sync-log__entry{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-xs) 0;border-bottom:1px solid var(--border)}.settings-sync-log__entry:last-child{border-bottom:none}.settings-sync-log__entry-timestamp{font-size:12px;color:var(--text-muted);min-width:140px}.settings-sync-log__entry-direction{display:flex;align-items:center;color:var(--text-muted)}.settings-sync-log__entry-result{display:inline-flex;padding:2px 8px;border-radius:999px;font-size:11px;font-weight:500}.settings-sync-log__badge--success{background:color-mix(in srgb,var(--color-success, #2da44e) 14%,transparent);color:var(--color-success, #2da44e)}.settings-sync-log__badge--conflict{background:color-mix(in srgb,var(--color-warning, #d29922) 14%,transparent);color:var(--color-warning, #d29922)}.settings-sync-log__badge--error{background:color-mix(in srgb,var(--color-error, #cf222e) 14%,transparent);color:var(--color-error, #cf222e)}.settings-sync-log__entry-node{font-weight:500;font-size:12px}.settings-sync-log__entry-details{font-size:12px;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.settings-sync-log__empty{text-align:center;color:var(--text-muted);padding:var(--space-md);font-size:13px}.node-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;background:color-mix(in srgb,var(--accent) 14%,transparent);border:1px solid color-mix(in srgb,var(--accent) 36%,transparent);color:var(--text-muted);font-size:11px;width:fit-content;margin-top:4px}@media(max-width:768px){.settings-sync-conflict-modal__diff-panel{grid-template-columns:1fr}}.settings-sync-conflict-modal{max-width:860px;width:min(860px,calc(100vw - 32px))}.settings-sync-conflict-modal__conflict-list{display:flex;flex-direction:column;gap:var(--space-md);max-height:min(50vh,400px);overflow-y:auto}.settings-sync-conflict-modal__conflict-item{border:1px solid var(--border);border-radius:var(--radius);padding:var(--space-md)}.settings-sync-conflict-modal__key{font-weight:600;font-family:monospace;margin-bottom:var(--space-sm)}.settings-sync-conflict-modal__diff-panel{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-sm);margin-bottom:var(--space-sm)}.settings-sync-conflict-modal__diff-side{border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}.settings-sync-conflict-modal__diff-label{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted);padding:4px 8px;border-bottom:1px solid var(--border);background:var(--surface)}.settings-sync-conflict-modal__diff-content{padding:var(--space-xs) var(--space-sm);white-space:pre;font-family:monospace;font-size:12px;line-height:1.5;overflow-x:auto}.settings-sync-conflict-modal__resolution{display:flex;gap:var(--space-md);align-items:center}.settings-sync-conflict-modal__resolution label{display:flex;align-items:center;gap:var(--space-xs);cursor:pointer}.settings-sync-conflict-modal__resolution input[type=radio]{cursor:pointer}.settings-sync-conflict-modal__manual-input{width:100%;font-family:monospace;font-size:12px;min-height:80px;margin-top:var(--space-xs);padding:var(--space-sm);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);resize:vertical}.settings-sync-conflict-modal__manual-input:focus{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring)}.settings-sync-conflict-modal__bulk-actions{display:flex;gap:var(--space-xs);padding-top:var(--space-sm);border-top:1px solid var(--border)}.settings-sync-conflict-modal__footer{display:flex;justify-content:flex-end;gap:var(--space-xs)}.node-detail-modal{max-width:calc(var(--space-lg) * 53.75);width:min(calc(var(--space-lg) * 53.75),calc(100vw - (var(--space-lg) * 2)))}.node-detail-modal__body{display:flex;flex-direction:column;gap:var(--space-md);max-height:min(72vh,calc(var(--space-lg) * 42.5));overflow-y:auto}.node-detail-modal__section{border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md)}.node-detail-modal__section h4{margin:0 0 var(--space-sm) 0}.node-detail-modal__section-header{display:flex;justify-content:space-between;align-items:center;gap:var(--space-sm);margin-bottom:var(--space-sm)}.node-detail-modal__grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.node-detail-modal__field{display:flex;flex-direction:column;gap:var(--space-xs)}.node-detail-modal__field--full{grid-column:span 2}.node-detail-modal__field span{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__edit-actions{margin-top:var(--space-sm);display:flex;gap:var(--space-xs)}.node-detail-modal__project-list{margin:0;padding-left:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-sm)}.node-detail-modal__project-item{display:flex;justify-content:space-between;align-items:center;gap:var(--space-sm)}.node-detail-modal__project-item code{color:var(--text-muted)}.node-detail-modal__empty{margin:0;color:var(--text-muted)}.node-detail-modal__health-row{display:flex;flex-wrap:wrap;gap:var(--space-md)}.node-detail-modal__actions{justify-content:space-between}.node-detail-modal__docker-config{display:flex;flex-direction:column;gap:var(--space-sm)}.node-detail-modal__docker-toggle{align-self:flex-start}.node-detail-modal__docker-toggle-icon--expanded{transform:rotate(180deg)}.node-detail-modal__docker-config-content{display:flex;flex-direction:column;gap:var(--space-sm)}.node-detail-modal__docker-list{display:flex;flex-direction:column;gap:var(--space-sm);margin-top:var(--space-sm)}.node-detail-modal__docker-row{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:var(--space-sm)}.node-detail-modal__docker-stack{display:flex;flex-direction:column;gap:var(--space-sm);margin-top:var(--space-sm)}.node-detail-modal__checkbox{display:flex;align-items:center;gap:var(--space-sm);color:var(--text-muted)}.node-detail-modal__docker-meta{display:flex;flex-wrap:wrap;gap:var(--space-sm);color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__docker-recreate{color:var(--color-warning)}.node-detail-modal__docker-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm);margin-top:var(--space-sm)}.node-detail-modal__textarea{min-height:calc(var(--space-2xl) * 2.25);resize:vertical;font-family:var(--font-mono)}.node-detail-modal__sync-status{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-sm);margin-bottom:var(--space-sm)}.node-detail-modal__sync-dot{width:calc(var(--space-sm) + var(--space-xs) / 2);height:calc(var(--space-sm) + var(--space-xs) / 2);border-radius:50%;flex-shrink:0}.node-detail-modal__sync-dot--synced{background:var(--color-success)}.node-detail-modal__sync-dot--diff,.node-detail-modal__sync-dot--pending{background:var(--color-warning)}.node-detail-modal__sync-dot--error{background:var(--color-error)}.node-detail-modal__sync-dot--never{background:var(--text-muted)}.node-detail-modal__sync-diff{color:var(--color-warning);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__sync-actions{display:flex;flex-wrap:wrap;gap:var(--space-sm);margin-top:var(--space-sm)}.node-detail-modal__sync-error{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm);margin-top:var(--space-sm);padding:var(--space-sm);background:color-mix(in srgb,var(--color-error) 10%,transparent);border:1px solid color-mix(in srgb,var(--color-error) 30%,transparent);border-radius:var(--radius-sm);color:var(--color-error);font-size:calc(var(--space-sm) + var(--space-xs))}.node-detail-modal__sync-error-dismiss{background:transparent;border:none;color:var(--color-error);cursor:pointer;padding:calc(var(--space-xs) / 2);display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm)}.node-detail-modal__sync-error-dismiss:hover{background:color-mix(in srgb,var(--color-error) 20%,transparent)}.node-detail-modal__sync-error-dismiss:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);background:color-mix(in srgb,var(--color-error) 20%,transparent)}.docker-management{display:flex;flex-direction:column;gap:var(--space-md)}.docker-management__status-card{display:flex;flex-direction:column;gap:var(--space-sm);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md)}.docker-management__status-row{display:inline-flex;align-items:center;gap:var(--space-sm)}.docker-management__status-dot{width:var(--space-sm);height:var(--space-sm);border-radius:50%}.docker-management__status-dot--success{background:var(--color-success)}.docker-management__status-dot--warning{background:var(--color-warning)}.docker-management__status-dot--error{background:var(--color-error)}.docker-management__status-meta{color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs));display:flex;gap:var(--space-md);flex-wrap:wrap}.docker-management__actions{display:flex;flex-wrap:wrap;gap:var(--space-sm)}.docker-management__info-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.docker-management__log-viewer{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md)}.docker-management__log-viewer-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-sm)}.docker-management__log-viewer pre{margin:0;max-height:calc(var(--space-2xl) * 9.375);overflow-y:auto;font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text);white-space:pre-wrap}.docker-management__env-list{margin:var(--space-sm) 0 0}.docker-management__env-list div{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr);gap:var(--space-sm);padding:var(--space-xs) 0}.docker-management__env-list dt{color:var(--text-muted);font-family:var(--font-mono)}.docker-management__env-list dd{margin:0;font-family:var(--font-mono);word-break:break-all}.docker-management__mounts-list{margin:var(--space-sm) 0 0;padding-left:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-sm)}.docker-management__mounts-list li{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}@media(max-width:768px){.node-detail-modal__grid,.node-detail-modal__docker-grid{grid-template-columns:1fr}.node-detail-modal__field--full{grid-column:span 1}.docker-management__actions{flex-direction:column}.docker-management__actions .btn{width:100%;justify-content:center}.docker-management__info-grid,.node-detail-modal__docker-row{grid-template-columns:1fr}.node-detail-modal__docker-toggle,.node-detail-modal__docker-config-content .btn{min-height:calc(var(--space-lg) * 2.25)}.docker-management__env-list div{grid-template-columns:1fr}.docker-management__mounts-list li{flex-direction:column;align-items:flex-start}.docker-management__log-viewer pre{max-height:calc(var(--space-2xl) * 6.25)}}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import{r as s,j as e}from"./vendor-react-BTgM5bbZ.js";import{c as ze,aU as ds,aV as us,aW as ms,aX as hs,aY as Ke,aZ as Ue,a_ as Ie,aI as fe,a$ as ke,b0 as Oe,b1 as _e,b2 as Be,A as Te,az as fs,Q as He,b3 as qe,b4 as gs,U as Ne,u as ps,R as Ce,a as we,J as ge,b5 as Ye,b6 as xs,b7 as vs,b8 as bs,b9 as Fe,X as he,ag as ys,ah as js,ba as Ve,F as ks,bb as $e,bc as _s,bd as Ns,be as Cs,bf as Ss,bg as Ms,G as Ps}from"./index-Bglw05rM.js";import{u as ne}from"./vendor-i18n-DYlSUfot.js";import{v as ws}from"./projectDetection-G3XuxD2X.js";import{U as Xe}from"./upload-C11J2diI.js";import"./vendor-reactflow-ZasuEfF9.js";import"./vendor-xterm-ea7-K05z.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 Ws({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 Gs=s.memo(Ws),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 W=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:W,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([]),[W,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))},[]),G=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})]}),W.name&&e.jsx("div",{className:"form-error",children:W.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})]}),W.reachableUrl&&e.jsx("div",{className:"form-error",children:W.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})]})]}),W.memoryMB&&e.jsx("div",{className:"form-error",children:W.memoryMB}),W.cpus&&e.jsx("div",{className:"form-error",children:W.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 G(),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),[W,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),[G,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),[We,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]),Ge=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)]}),We&&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:Ge})]}),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")]})]}),G&&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:W||!h,children:[e.jsx(Ye,{size:14}),W?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,W]=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,G=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:G,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"),W(!1)}catch(V){const G=V instanceof Error?V.message:a("nodes.failedCreateDocker","Failed to create Docker node");throw t(G,"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 G=V instanceof Error?V.message:a("nodes.healthCheckFailed","Health check failed");t(G,"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 G=V instanceof Error?V.message:a("nodes.failedRemove","Failed to remove node");t(G,"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:()=>W(!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(Gs,{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:G=>{re(G)},onEdit:G=>L(G),onRemove:G=>{te(G)},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:()=>W(!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};
|