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