PageSourceSearch

https://www.hamienet.com/assets/SystemManager-jBvByZdL.js

js hamienet.com collected 2026-10-02 05:02:18 UTC 101,180 bytes, 1,457 lines download raw bytes

1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js";
2import { dZ as Server, cM as RefreshCw, ge as Github, b6 as LoaderCircle, cg as Activity, b1 as CircleAlert, bp as CirclePlay, c4 as RotateCcw, eu as Power, eC as Terminal, cl as HardDrive, cj as Cpu, dW as Thermometer, bD as FlaskConical, bs as Zap, ci as Database, a$ as Shield, b7 as Check, bR as ExternalLink, cB as ChevronUp, cC as ChevronDown, ck as Layers } from "./vendor-D0P4XgNj.js";
3import "./vendor-i18n-BC7ZMXWQ.js";
4const LogLine = ({ text }) => {
5  let colorClass = "text-zinc-300";
6  if (text.startsWith(">")) colorClass = "text-indigo-400 font-bold";
7  else if (text.startsWith("---")) colorClass = "text-zinc-500 italic py-2";
8  else if (text.toLowerCase().includes("error") || text.includes("FAIL") || text.includes("[ERROR]") || text.includes("fatal:")) colorClass = "text-red-400";
9  else if (text.toLowerCase().includes("success") || text.includes("code 0]") || text.includes("✔") || text.includes("DONE")) colorClass = "text-emerald-400";
10  else if (text.includes("warning") || text.includes("[Warning]")) colorClass = "text-amber-400";
11  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `break-all whitespace-pre-wrap hover:bg-white/5 px-2 py-0.5 rounded transition-colors font-mono text-xs ${colorClass}`, children: text });
12};
13const playAlertSound = (action, isError = false) => {
14  try {
15    const AudioContextClass = window.AudioContext || window.webkitAudioContext;
16    if (!AudioContextClass) return;
17    const audioCtx = new AudioContextClass();
18    if (audioCtx.state === "suspended") {
19      audioCtx.resume().catch(() => {
20      });
21    }
22    const playTone = (freq, type, start, duration, vol = 0.5) => {
23      const osc = audioCtx.createOscillator();
24      const gainNode = audioCtx.createGain();
25      osc.type = type;
26      osc.frequency.setValueAtTime(freq, audioCtx.currentTime + start);
27      gainNode.gain.setValueAtTime(0, audioCtx.currentTime + start);
28      gainNode.gain.linearRampToValueAtTime(vol, audioCtx.currentTime + start + 0.05);
29      gainNode.gain.linearRampToValueAtTime(0, audioCtx.currentTime + start + duration);
30      osc.connect(gainNode);
31      gainNode.connect(audioCtx.destination);
32      osc.start(audioCtx.currentTime + start);
33      osc.stop(audioCtx.currentTime + start + duration);
34    };
35    if (isError) {
36      playTone(440, "sawtooth", 0, 0.2, 0.3);
37      playTone(220, "sawtooth", 0.15, 0.4, 0.3);
38      return;
39    }
40    switch (action) {
41      case "git_pull":
42      case "git_push":
43      case "restart":
44        playTone(440, "sine", 0, 0.1);
45        playTone(554.37, "sine", 0.1, 0.1);
46        playTone(659.25, "sine", 0.2, 0.3);
47        break;
48      case "validate":
49        playTone(1046.5, "sine", 0, 0.15);
50        break;
51      case "build":
52        playTone(261.63, "sine", 0, 0.1);
53        playTone(329.63, "sine", 0.1, 0.1);
54        playTone(392, "sine", 0.2, 0.1);
55        playTone(523.25, "sine", 0.3, 0.5);
56        break;
57      case "offline_prep":
58        playTone(329.63, "sine", 0, 0.1);
59        playTone(440, "sine", 0.1, 0.1);
60        playTone(329.63, "sine", 0.2, 0.1);
61        playTone(440, "sine", 0.3, 0.3);
62        break;
63      case "prune":
64        playTone(110, "sine", 0, 0.5, 0.4);
65        break;
66      case "git_reset":
67      case "git_stash":
68      case "git_force_update":
69        playTone(220, "triangle", 0, 0.2);
70        playTone(220, "triangle", 0.3, 0.2);
71        break;
72      default:
73        playTone(660, "sine", 0, 0.1);
74        playTone(880, "sine", 0.1, 0.2);
75    }
76  } catch (e) {
77    console.error("Audio playback failed", e);
78  }
79};
80const SystemManager = () => {
81  const [logs, setLogs] = reactExports.useState(["System Manager Ready. Connect to stream..."]);
82  const [isRunning, setIsRunning] = reactExports.useState(false);
83  const [selectedServices, setSelectedServices] = reactExports.useState(() => {
84    const auto = localStorage.getItem("hamienet_auto_rebuild") === "true";
85    const includeSite = localStorage.getItem("hamienet_include_site_engine") === "true";
86    if (auto) {
87      const initial = ["web_test", "web_admin", "worker", "web_deployer", "db"];
88      if (includeSite) initial.push("web_site");
89      return new Set(initial);
90    }
91    return /* @__PURE__ */ new Set(["web_test"]);
92  });
93  const [secondaryLogs, setSecondaryLogs] = reactExports.useState(["Service Log Stream Ready. Select a service to view logs..."]);
94  const [isSecondaryRunning, setIsSecondaryRunning] = reactExports.useState(false);
95  const [activeServiceLogs, setActiveServiceLogs] = reactExports.useState(null);
96  const [statusData, setStatusData] = reactExports.useState(null);
97  const [showWorkerReplicas, setShowWorkerReplicas] = reactExports.useState(false);
98  const [lastChecked, setLastChecked] = reactExports.useState(null);
99  const [timeSinceLastChecked, setTimeSinceLastChecked] = reactExports.useState("");
100  const [autoPrep, setAutoPrep] = reactExports.useState(() => localStorage.getItem("hamienet_auto_prep") === "true");
101  const [autoRebuild, setAutoRebuild] = reactExports.useState(() => localStorage.getItem("hamienet_auto_rebuild") === "true");
102  const [includeSiteEngine, setIncludeSiteEngine] = reactExports.useState(() => localStorage.getItem("hamienet_include_site_engine") === "true");
103  const [isPrepEnabled, setIsPrepEnabled] = reactExports.useState(false);
104  const [isRefreshingStatus, setIsRefreshingStatus] = reactExports.useState(false);
105  const [validationStatus, setValidationStatus] = reactExports.useState("idle");
106  const [logService, setLogService] = reactExports.useState("web_site");
107  const [logNode, setLogNode] = reactExports.useState("all");
108  const [serviceLogs, setServiceLogs] = reactExports.useState([]);
109  const [serviceMetrics, setServiceMetrics] = reactExports.useState(null);
110  const [isLoadingLogs, setIsLoadingLogs] = reactExports.useState(false);
111  const fetchServiceLogsAndMetrics = async () => {
112    setIsLoadingLogs(true);
113    try {
114      const [logsRes, metricsRes] = await Promise.all([
115        fetch(`/api/admin/system/service-logs?service=${logService}&node=${logNode}&limit=50`),
116        fetch(`/api/admin/system/service-metrics?service=${logService}&node=${logNode}`)
117      ]);
118      if (logsRes.ok) setServiceLogs(await logsRes.json());
119      if (metricsRes.ok) setServiceMetrics(await metricsRes.json());
120    } catch (e) {
121      console.error("Failed to fetch service logs & metrics", e);
122    } finally {
123      setIsLoadingLogs(false);
124    }
125  };
126  reactExports.useEffect(() => {
127    fetchServiceLogsAndMetrics();
128  }, [logService, logNode]);
129  const smartPrepRef = reactExports.useRef(false);
130  const logContainerRef = reactExports.useRef(null);
131  const secondaryLogContainerRef = reactExports.useRef(null);
132  const prevScrollHeightRef = reactExports.useRef(0);
133  const prevSecondaryScrollHeightRef = reactExports.useRef(0);
134  const eventSourceRef = reactExports.useRef(null);
135  const secondaryEventSourceRef = reactExports.useRef(null);
136  reactExports.useEffect(() => {
137    localStorage.setItem("hamienet_auto_rebuild", String(autoRebuild));
138    localStorage.setItem("hamienet_auto_prep", String(autoPrep));
139    localStorage.setItem("hamienet_include_site_engine", String(includeSiteEngine));
140  }, [autoRebuild, autoPrep, includeSiteEngine]);
141  const fetchStatus = async (checkRemote = false) => {
142    try {
143      setIsRefreshingStatus(true);
144      const res = await fetch(`/api/admin/system/status${checkRemote ? "?refresh=true" : ""}`);
145      const data = await res.json();
146      setStatusData(data);
147      setLastChecked(/* @__PURE__ */ new Date());
148    } catch (e) {
149      console.error("Failed to fetch system status", e);
150      setLastChecked(/* @__PURE__ */ new Date());
151    } finally {
152      setIsRefreshingStatus(false);
153    }
154  };
155  reactExports.useEffect(() => {
156    fetchStatus(true);
157  }, []);
158  reactExports.useEffect(() => {
159    const updateRelativeTime = () => {
160      if (!lastChecked) {
161        setTimeSinceLastChecked("");
162        return;
163      }
164      const seconds = Math.floor((Date.now() - lastChecked.getTime()) / 1e3);
165      if (seconds < 5) {
166        setTimeSinceLastChecked("just now");
167      } else if (seconds < 60) {
168        setTimeSinceLastChecked(`${seconds}s ago`);
169      } else {
170        const minutes = Math.floor(seconds / 60);
171        const remainingSeconds = seconds % 60;
172        setTimeSinceLastChecked(`${minutes}m ${remainingSeconds}s ago`);
173      }
174    };
175    updateRelativeTime();
176    const interval = setInterval(updateRelativeTime, 1e3);
177    return () => clearInterval(interval);
178  }, [lastChecked]);
179  reactExports.useEffect(() => {
180    const timer = setInterval(() => {
181      if (document.visibilityState === "visible" && !isRunning && !isRefreshingStatus) {
182        fetchStatus(false);
183      }
184    }, 3e4);
185    return () => clearInterval(timer);
186  }, [isRunning, isRefreshingStatus]);
187  reactExports.useEffect(() => {
188    if (logContainerRef.current) {
189      const container = logContainerRef.current;
190      const wasAtBottom = prevScrollHeightRef.current - container.scrollTop <= container.clientHeight + 150;
191      if (wasAtBottom) {
192        const timer = setTimeout(() => {
193          container.scrollTop = container.scrollHeight;
194        }, 30);
195        prevScrollHeightRef.current = container.scrollHeight;
196        return () => clearTimeout(timer);
197      }
198      prevScrollHeightRef.current = container.scrollHeight;
199    }
200  }, [logs]);
201  reactExports.useEffect(() => {
202    if (secondaryLogContainerRef.current) {
203      const container = secondaryLogContainerRef.current;
204      const wasAtBottom = prevSecondaryScrollHeightRef.current - container.scrollTop <= container.clientHeight + 150;
205      if (wasAtBottom) {
206        const timer = setTimeout(() => {
207          container.scrollTop = container.scrollHeight;
208        }, 30);
209        prevSecondaryScrollHeightRef.current = container.scrollHeight;
210        return () => clearTimeout(timer);
211      }
212      prevSecondaryScrollHeightRef.current = container.scrollHeight;
213    }
214  }, [secondaryLogs]);
215  reactExports.useEffect(() => {
216    return () => {
217      stopStream();
218      stopSecondaryStream();
219    };
220  }, []);
221  const stopStream = () => {
222    if (eventSourceRef.current) {
223      eventSourceRef.current.close();
224      eventSourceRef.current = null;
225    }
226    setIsRunning(false);
227  };
228  const stopSecondaryStream = () => {
229    if (secondaryEventSourceRef.current) {
230      secondaryEventSourceRef.current.close();
231      secondaryEventSourceRef.current = null;
232    }
233    setIsSecondaryRunning(false);
234    setActiveServiceLogs(null);
235  };
236  const runCommand = (action, service, shouldAppend = false, forcePrep) => {
237    const isLogAction = action === "logs";
238    if (isLogAction) {
239      stopSecondaryStream();
240      setIsSecondaryRunning(true);
241      setActiveServiceLogs(service || null);
242      const header = `
243--- Streaming: ${service || ""} logs ---`;
244      setSecondaryLogs(shouldAppend ? (prev) => [...prev, header] : [header]);
245    } else {
246      stopStream();
247      setIsRunning(true);
248      const header = `
249--- Executing: ${action} ${service || ""} ${forcePrep || isPrepEnabled ? "(with prep)" : ""} ---`;
250      setLogs(shouldAppend ? (prev) => [...prev, header] : [header]);
251    }
252    const usePrep = forcePrep !== void 0 ? forcePrep : isPrepEnabled;
253    if (action === "git_pull") {
254      smartPrepRef.current = false;
255      setIsPrepEnabled(false);
256    }
257    let query = `action=${action}${service ? `&service=${service}` : ""}`;
258    if (action === "build" && usePrep) query += "&prep=true";
259    const sse = new EventSource(`/api/admin/system/execute?${query}`);
260    sse.onmessage = (e) => {
261      try {
262        const data = JSON.parse(e.data);
263        if (data.log) {
264          const logStr = data.log.trimEnd();
265          if (!isLogAction && (logStr.includes("[Process exited with code") || logStr.includes("[Execution Error]") || logStr.includes("[Exception]:"))) {
266            const isError = logStr.includes("[Execution Error]") || logStr.includes("[Exception]:") || logStr.includes("[Process exited with code") && !logStr.includes("code 0]");
267            playAlertSound(action, isError);
268          }
269          const targetSetter = isLogAction ? setSecondaryLogs : setLogs;
270          targetSetter((prev) => {
271            const newLogs = [...prev, logStr];
272            return newLogs.length > 2e3 ? newLogs.slice(newLogs.length - 2e3) : newLogs;
273          });
274          if (!isLogAction) {
275            if (logStr.includes("[AUTO_SELECT]:")) {
276              const match = logStr.match(/\[AUTO_SELECT\]:([^\s\n]+)/);
277              if (match) {
278                const items = match[1].split(",");
279                const services = items.filter((i) => i !== "prep");
280                if (services.includes("web_test") && includeSiteEngine) {
281                  if (!services.includes("web_site")) {
282                    services.push("web_site");
283                  }
284                }
285                const needsPrep = items.includes("prep");
286                setSelectedServices(new Set(services));
287                if (needsPrep && autoPrep) {
288                  smartPrepRef.current = true;
289                  setIsPrepEnabled(true);
290                  setLogs((prev) => [...prev, "[System] Dependency changes detected. Build prep will be included."]);
291                }
292              }
293            }
294            if (logStr.includes("[VALIDATION_RESULT]:")) {
295              setValidationStatus(logStr.includes(":PASS") ? "pass" : "fail");
296            }
297            if (logStr.includes("[Process exited with code 0]")) {
298              if (action === "git_pull") {
299                setTimeout(() => runCommand("validate", void 0, true), 500);
300              }
301              if (action === "validate") setValidationStatus("pass");
302              if (action === "git_pull" && autoRebuild) {
303                setTimeout(() => {
304                  setLogs((currentLogs) => {
305                    if (currentLogs.some((l) => l.includes("Already up to date."))) return currentLogs;
306                    setSelectedServices((prev) => {
307                      if (prev.size > 0) runCommand("build", Array.from(prev).join(" "), true, smartPrepRef.current);
308                      return prev;
309                    });
310                    return currentLogs;
311                  });
312                }, 1e3);
313              }
314            }
315          }
316        }
317      } catch (err) {
318      }
319    };
320    sse.onerror = () => {
321      if (isLogAction) {
322        stopSecondaryStream();
323        return;
324      }
325      const isDeployerRebuild = action === "build" && service && service.includes("deployer");
326      if (isDeployerRebuild) {
327        setLogs((prev) => [
328          ...prev,
329          "\n[System] Deployer container is restarting to swap to the new image...",
330          "[System] Reconnecting and polling status..."
331        ]);
332        let pollCount = 0;
333        const interval = setInterval(async () => {
334          pollCount++;
335          if (pollCount > 30) {
336            clearInterval(interval);
337            stopStream();
338            setLogs((prev) => [...prev, "[Error] Reconnection timeout. Please refresh the page manually."]);
339            return;
340          }
341          try {
342            const response = await fetch("/api/admin/system/status");
343            if (response.ok) {
344              clearInterval(interval);
345              setIsRunning(false);
346              if (eventSourceRef.current) {
347                eventSourceRef.current.close();
348                eventSourceRef.current = null;
349              }
350              setLogs((prev) => [
351                ...prev,
352                "\n[System] Reconnected successfully!",
353                "[System] Rebuild and deployer restart complete. Process exited 
353with code 0."
354              ]);
355              playAlertSound("build", false);
356              fetchStatus(true);
357            }
358          } catch (e) {
359          }
360        }, 5e3);
361      } else {
362        stopStream();
363      }
364    };
365    if (isLogAction) secondaryEventSourceRef.current = sse;
366    else eventSourceRef.current = sse;
367  };
368  const ResourceBar = ({ label, value, color, max }) => {
369    let barPercentage = 0;
370    let displayValue = value;
371    let secondaryDisplay = null;
372    if (label === "CPU Load") {
373      const rawPercentage = parseFloat(value) || 0;
374      if (max && rawPercentage > 0) {
375        const trueUsage = rawPercentage / max * 100;
376        displayValue = `${trueUsage.toFixed(1)}%`;
377        barPercentage = Math.min(trueUsage, 100);
378        secondaryDisplay = /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[8px] ml-1 opacity-60", children: [
379          "(",
380          value,
381          " raw)"
382        ] });
383      } else {
384        barPercentage = Math.min(rawPercentage, 100);
385      }
386    } else if (label === "Memory") {
387      const num = parseFloat(value) || 0;
388      let mb = num;
389      if (value.toUpperCase().includes("G")) {
390        mb = num * 1024;
391      } else if (value.toUpperCase().includes("K")) {
392        mb = num / 1024;
393      }
394      barPercentage = num > 0 ? Math.min(Math.max(mb / 8192 * 100, 5), 100) : 0;
395    }
396    const colorMap = {
397      "bg-indigo-500": "#6366f1",
398      "bg-purple-500": "#a855f7",
399      "bg-amber-500": "#f59e0b",
400      "bg-emerald-500": "#10b981",
401      "bg-blue-500": "#3b82f6",
402      "bg-blue-400": "#60a5fa",
403      "bg-zinc-500": "#71717a",
404      "bg-teal-500": "#14b8a6"
405    };
406    const bgStyleColor = colorMap[color] || "#6366f1";
407    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1 w-full", children: [
408      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-[10px] text-zinc-500 font-bold uppercase", children: [
409        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: label }),
410        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "truncate flex items-baseline", children: [
411          displayValue,
412          secondaryDisplay
413        ] })
414      ] }),
415      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1.5 w-full bg-zinc-800 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
416        "div",
417        {
418          className: "h-full transition-all duration-1000",
419          style: { width: `${barPercentage}%`, backgroundColor: bgStyleColor }
420        }
421      ) })
422    ] });
423  };
424  const HealthIndicator = ({ status, isRebuilding, timestamp }) => {
425    const isUp = status == null ? void 0 : status.startsWith("Up");
426    const isRestarting = status == null ? void 0 : status.includes("Restarting");
427    let color = "bg-zinc-700";
428    let text = "Disconnected";
429    let glow = "";
430    if (isRebuilding) {
431      color = "bg-amber-500";
432      text = "Rebuilding";
433      glow = "shadow-[0_0_8px_rgba(245,158,11,0.5)]";
434    } else if (isUp) {
435      color = "bg-emerald-500";
436      text = "Online";
437      glow = "shadow-[0_0_8px_rgba(16,185,129,0.5)]";
438    } else if (isRestarting) {
439      color = "bg-amber-500";
440      text = "Restarting";
441      glow = "shadow-[0_0_8px_rgba(245,158,11,0.5)]";
442    } else if (status) {
443      color = "bg-red-500";
444      text = "Offline";
445      glow = "shadow-[0_0_8px_rgba(239,68,68,0.5)]";
446    }
447    const timeStr = timestamp ? new Date(timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }) : "";
448    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
449      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `w-2 h-2 rounded-full ${color} ${glow} animate-pulse` }),
450      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-bold uppercase ${isRebuilding ? "text-amber-400" : isUp ? "text-emerald-400" : "text-zinc-500"}`, children: text }),
451      timeStr && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[9px] text-zinc-500 font-mono tracking-tight normal-case", children: [
452        "(Checked: ",
453        timeStr,
454        ")"
455      ] })
456    ] });
457  };
458  const renderDeploymentStatus = () => {
459    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K;
460    const servicesList = [
461      { id: "web_site", key: "hamienet_web", label: "Site Engine (3002)", icon: Server, color: "bg-indigo-500", url: ":3002", hostPort: "3002" },
462      { id: "web_test", key: "hamienet_web_test", label: "Test Engine (3005)", icon: FlaskConical, color: "bg-blue-500", url: ":3005", hostPort: "3005" },
463      { id: "web_admin", key: "hamienet_admin", label: "Admin Engine (3003)", icon: Server, color: "bg-purple-500", url: ":3003", hostPort: "3003" },
464      { id: "web_deployer", key: "hamienet_deployer", label: "System Deployer (3004)", icon: Zap, color: "bg-amber-500", url: ":3004", hostPort: "3004" },
465      { id: "worker", key: "hamienet-worker-1", label: "MIDI Processor", icon: Activity, color: "bg-emerald-500" },
466      { id: "db", key: "hamienet-db-1", label: "PostgreSQL DB", icon: Server, color: "bg-blue-500", hostPort: "5433" },
467      { id: "db-musicbrainz", key: "hamienet_db_musicbrainz", label: "MusicBrainz DB", icon: Database, color: "bg-blue-400", hostPort: "5434" },
468      { id: "nginx", key: "hamienet-nginx-1", label: "Nginx Proxy", icon: Shield, color: "bg-zinc-500", url: ":8181", hostPort: "8080/8443" },
469      { id: "beszel-hub", key: "hamienet_beszel_hub", label: "Beszel Hub (8090)", icon: Activity, color: "bg-indigo-500", url: ":8090", hostPort: "8090" },
470      { id: "beszel-agent", key: "hamienet_beszel_agent", label: "Beszel Agent", icon: Cpu, color: "bg-zinc-500" }
471    ];
472    const selectedList = Array.from(selectedServices);
473    const hasSelection = selectedList.length > 0;
474    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-xl overflow-hidden shadow-2xl", children: [
475      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-px bg-zinc-800 border-b border-zinc-800 overflow-hidden", children: [
476        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 bg-zinc-900 flex flex-col gap-1 col-span-1", children: [
477          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-zinc-500 font-bold uppercase flex items-center gap-1", children: [
478            /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { size: 10, className: "text-emerald-500" }),
479            " System Uptime"
480          ] }),
481          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-bold text-white truncate", children: (statusData == null ? void 0 : statusData.uptime) || "---" })
482        ] }),
483        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 bg-zinc-900 flex flex-col gap-1 col-span-1", children: [
484          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-zinc-500 font-bold uppercase flex items-center gap-1", children: [
485            /* @__PURE__ */ jsxRuntimeExports.jsx(Github, { size: 10, className: "text-indigo-400" }),
486            " Git Sync Status"
487          ] }),
488          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
489            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `text-xs font-bold ${(statusData == null ? void 0 : statusData.isUpToDate) ? "text-emerald-400" : "text-amber-400 underline underline-offset-4"}`, children: (statusData == null ? void 0 : statusData.isUpToDate) ? `Everything Up to Date (${(statusData == null ? void 0 : statusData.gitVersion) || "..."})` : `Update Available (${(statusData == null ? void 0 : statusData.gitVersion) || "..."} → ${(statusData == null ? void 0 : statusData.gitRemoteVersion) || "..."})` }),
490            (statusData == null ? void 0 : statusData.gitDate) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[9px] text-zinc-400 font-mono", children: [
491              (statusData == null ? void 0 : statusData.isUpToDate) ? "Commit:" : "Local:",
492              " ",
493              new Date(statusData.gitDate).toLocaleString()
494            ] }),
495            !(statusData == null ? void 0 : statusData.isUpToDate) && (statusData == null ? void 0 : statusData.gitRemoteDate) && /* @__P
495URE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[9px] text-amber-500 font-mono", children: [
496              "Remote: ",
497              new Date(statusData.gitRemoteDate).toLocaleString()
498            ] }),
499            (statusData == null ? void 0 : statusData.hasLocalChanges) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[9px] font-bold text-indigo-400 uppercase tracking-tight animate-pulse flex items-center gap-1", children: [
500              /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { size: 8 }),
501              " Local Changes Detected"
502            ] })
503          ] })
504        ] }),
505        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 bg-zinc-900 flex flex-col gap-3 col-span-1 lg:col-span-2", children: [
506          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-zinc-500 font-bold uppercase flex items-center gap-1 mb-0.5", children: [
507            /* @__PURE__ */ jsxRuntimeExports.jsx(HardDrive, { size: 10, className: "text-emerald-500" }),
508            " Storage Availability"
509          ] }),
510          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [
511            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col", children: [
512              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-[9px] font-black text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-1", children: [
513                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-center gap-1", children: "System" }),
514                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-bold text-zinc-700 dark:text-zinc-300", children: ((_b = (_a = statusData == null ? void 0 : statusData.diskSpace) == null ? void 0 : _a.systemDetails) == null ? void 0 : _b.percentage) !== void 0 ? `${statusData.diskSpace.systemDetails.percentage}%` : "---" })
515              ] }),
516              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full bg-zinc-200/60 dark:bg-zinc-800 h-2 rounded-full overflow-hidden shadow-inner", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
517                "div",
518                {
519                  className: "bg-emerald-500 h-full rounded-full transition-all duration-700 ease-out",
520                  style: { width: `${((_d = (_c = statusData == null ? void 0 : statusData.diskSpace) == null ? void 0 : _c.systemDetails) == null ? void 0 : _d.percentage) || 0}%` }
521                }
522              ) }),
523              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] font-mono text-zinc-400 font-bold mt-1 truncate", title: (_e = statusData == null ? void 0 : statusData.diskSpace) == null ? void 0 : _e.system, children: ((_f = statusData == null ? void 0 : statusData.diskSpace) == null ? void 0 : _f.system) || "---" })
524            ] }),
525            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col", children: [
526              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-[9px] font-black text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-1", children: [
527                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-center gap-1", children: "Files" }),
528                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-bold text-zinc-700 dark:text-zinc-300", children: ((_h = (_g = statusData == null ? void 0 : statusData.diskSpace) == null ? void 0 : _g.storageDetails) == null ? void 0 : _h.percentage) !== void 0 ? `${statusData.diskSpace.storageDetails.percentage}%` : "---" })
529              ] }),
530              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full bg-zinc-200/60 dark:bg-zinc-800 h-2 rounded-full overflow-hidden shadow-inner", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
531                "div",
532                {
533                  className: "bg-indigo-500 h-full rounded-full transition-all duration-700 ease-out",
534                  style: { width: `${((_j = (_i = statusData == null ? void 0 : statusData.diskSpace) == null ? void 0 : _i.storageDetails) == null ? void 0 : _j.percentage) || 0}%` }
535                }
536              ) }),
537              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] font-mono text-zinc-400 font-bold mt-1 truncate", title: (_k = statusData == null ? void 0 : statusData.diskSpace) == null ? void 0 : _k.storage, children: ((_l = statusData == null ? void 0 : statusData.diskSpace) == null ? void 0 : _l.storage) || "---" })
538            ] })
539          ] })
540        ] }),
541        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 bg-zinc-900 flex flex-col gap-3 col-span-1 lg:col-span-2", children: [
542          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-zinc-500 font-bold uppercase flex items-center gap-1 mb-0.5", children: [
543            /* @__PURE__ */ jsxRuntimeExports.jsx(Cpu, { size: 10, className: "text-amber-500" }),
544            " System Resources"
545          ] }),
546          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [
547            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col", children: [
548              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-[9px] font-black text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-1", children: [
549                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-center gap-1", children: "CPU Usage" }),
550                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-bold text-zinc-700 dark:text-zinc-300", children: ((_n = (_m = statusData == null ? void 0 : statusData.systemResources) == null ? void 0 : _m.cpu) == null ? void 0 : _n.percentage) !== void 0 ? `${statusData.systemResources.cpu.percentage}%` : "---" })
551              ] }),
552              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full bg-zinc-200/60 dark:bg-zinc-800 h-2 rounded-full overflow-hidden shadow-inner", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
553                "div",
554                {
555                  className: "bg-amber-500 h-full rounded-full transition-all duration-700 ease-out",
556                  style: { width: `${((_p = (_o = statusData == null ? void 0 : statusData.systemResources) == null ? void 0 : _o.cpu) == null ? void 0 : _p.percentage) || 0}%` }
557                }
558              ) }),
559              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] font-mono text-zinc-400 font-bold mt-1 truncate", children: "Host Processor Load" })
560            ] }),
561            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col", children: [
562              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-[9px] font-black text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-1", children: [
563                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-center gap-1", children: "RAM Usage" }),
564                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-bold text-zinc-700 dark:text-zinc-300", children: ((_r = (_q = statusData == null ? void 0 : statusData.systemResources) == null ? void 0 : _q.ram) == null ? void 0 : _r.percentage) !== void 0 ? `${statusData.systemResources.ram.percentage}%` : "---" })
565              ] }),
566              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full bg-zinc-200/60 dark:bg-zinc-800 h-2 rounded-full overflow-hidden shadow-inner", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
567                "div",
568                {
569                  className: "bg-blue-500 h-full rounded-full transition-all duration-700 ease-out",
570                  style: { width: `${((_t = (_s = statusData == null ? void 0 : statusData.systemResources) == null ? void 0 : _s.ram) == null ? void 0 : _t.percentage) || 0}%` }
571                }
572              ) }),
573              /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[9px] font-mono text-zinc-400 font-bold mt-1 truncate", title: `Used: ${((_v = (_u = statusData == null ? void 0 : statusData.systemResources) == null ? void 0 : _u.ram) == null ? void 0 : _v.used) || "---"} / Total: ${((_x = (_w = statusData == null ? void 0 : statusData.systemResources) == null ? void 0 : _w.ram) == null ? void 0 : _x.total) || "---"} (Free: ${((_z = (_y = statusData == null ? void 0 : statusData.systemResources) == null ? void 0 : _y.ram) == null ? void 0 : _z.available) || "---"})`, children: [
574                ((_B = (_A = statusData == null ? void 0 : statusData.systemResources) == null ? void 0 : _A.ram) == null ? void 0 : _B.used) || "---",
575                " used of ",
576                ((_D = (_C = statusData == null ? void 0 : statusData.systemResources) == null ? void 0 : _C.ram) == null ? void 0 : _D.total) || "---"
577              ] })
578            ] })
579          ] })
580        ] }),
581        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 bg-zinc-900 flex flex-col gap-1 col-span-1", children: [
582          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-amber-400 font-bold uppercase flex items-center gap-1", children: [
583            /* @__PURE__ */ jsxRuntimeExports.jsx(Thermometer, { size: 10, className: "text-amber-400" }),
584            " Temperature"
585          ] }),
586          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1 mt-1", children: [
587            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-baseline", children: [
588              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] text-zinc-500 font-bold uppercase", children: "System:" }),
589              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-bold text-amber-450 truncate", children: ((_E = statusData == null ? void 0 : statusData.temperature) == null ? void 0 : _E.system) || "---" })
590            ] }),
591            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-0.5 mt-0.5", children: [
592              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] text-zinc-500 font-bold uppercase", children: "CPUs:" }),
593              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-1 max-h-[34px] overflow-y-auto custom-scrollbar", children: ((_F = statusData == null ? void 0 : statusData.temperature) == null ? void 0 : _F.cpus) && statusData.temperature.cpus.length > 0 ? statusData.temperature.cpus.map((temp, idx) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] font-mono font-bold text-zinc-300 bg-zinc-800/40 px-1 py-0.2 rounded", children: temp }, idx)) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] text-zinc-500 italic", children: "---" }) })
594            ] })
595          ] })
596        ] }),
597        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 bg-zinc-900 flex flex-col gap-1 col-span-1", children: [
598          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] text-indigo-400 font-bold uppercase flex items-center gap-1", children: "Archive Scale" }),
599          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm font-bold text-white", children: [
600            ((_H = (_G = statusData == null ? void 0 : statusData.counts) == null ? void 0 : _G.tracks) == null ? void 0 : _H.toLocaleString()) || "---",
601            " ",
602            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 text-[10px]", children: "tracks" }),
603            " / ",
604            ((_J = (_I = statusData == null ? void 0 : statusData.counts) == null ? void 0 : _I.users) == null ? void 0 : _J.toLocaleString()) || "---",
605            " ",
606            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 text-[10px]", children: "users" })
607          ] })
608        ] }),
609        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 bg-zinc-900 flex flex-col gap-1 col-span-1", children: [
610          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-blue-400 font-bold uppercase flex items-center gap-1", children: [
611            /* @__PURE__ */ jsxRuntimeExports.jsx(Server, { size: 10, className: "text-blue-400" }),
612            " DB Connections"
613          ] }),
614          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-bold text-white", children: (statusData == null ? void 0 : statusData.dbConnections) ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
615            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400", children: statusData.dbConnections.active }),
616            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 mx-1", children: "/" }),
617            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: statusData.dbConnections.limit }),
618            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 text-[10px] ml-1.5", children: "active" })
619          ] }) : "---" })
620        ] }),
621        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `p-4 bg-zinc-900 flex flex-col gap-1 col-span-1 ${((_K = statusData == null ? void 0 : statusData.workerStats) == null ? void 0 : _K.active) > 0 ? "animate-pulse" : ""}`, children: [
622          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-purple-400 font-bold uppercase flex items-center gap-1", children: [
623            /* @__PURE__ */ jsxRuntimeExports.jsx(Cpu, { size: 10, className: "text-purple-400" }),
624            " Worker Instances"
625          ] }),
626          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-bold text-white", children: (statusData == null ? void 0 : statusData.workerStats) ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
627            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400", children: statusData.workerStats.running }),
628            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 mx-1", children: "/" }),
629            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-purple-400", children: statusData.workerStats.spawned }),
630            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 text-[10px] ml-1.5", children: "Up" }),
631            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 mx-1.5", children: "|" }),
632            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-amber-400", children: statusData.workerStats.active }),
633            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 text-[10px] ml-1.5", children: "active" })
634          ] }) : "---" })
635        ] })
636      ] }),
637      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6", children: [
638        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4 mb-6 pb-6 border-b border-zinc-800", children: [
639          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4", children: [
640            /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-sm font-bold uppercase text-zinc-400", children: "Services Status" }),
641            lastChecked && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-zinc-500 font-mono flex items-center gap-1 animate-in fade-in", children: [
642              "Checked: ",
643              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-450 font-bold", children: lastChecked.toLocaleTimeString() }),
644              " (",
645              timeSinceLastChecked,
646              ")"
647            ] }),
648            hasSelection && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 bg-indigo-500/10 border border-indigo-500/30 px-3 py-1 rounded-full animate-in fade-in slide-in-from-left-2", children: [
649              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-2 h-2 bg-indigo-500 rounded-full animate-pulse" }),
650              /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] font-bold text-indigo-400 uppercase", children: [
651                selectedList.length,
652                " Selected"
653              ] })
654            ] })
655          ] }),
656          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
657            /* @__PURE__ */ jsxRuntimeExports.jsx(
658              "button",
659              {
660                onClick: () => {
661                  if (selectedServices.size === servicesList.length) setSelectedServices(/* @__PURE__ */ new Set());
662                  else setSelectedServices(new Set(servicesList.map((s) => s.id)));
663                },
664                className: "text-[10px] font-bold uppercase text-zinc-500 hover:text-zinc-300 px-3 py-2 transition-colors",
665                children: selectedServices.size === servicesList.length ? "Deselect All" : "Select All"
666              }
667            ),
668            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-4 bg-zinc-800 mx-1" }),
669            /* @__PURE__ */ jsxRuntimeExports.jsxs(
670              "button",
671              {
672                onClick: () => runCommand("restart", selectedList.join(" ")),
673                disabled: !hasSelection || isRunning && activeServiceLogs === null || selectedList.some((id) => {
674                  var _a2;
675                  return (_a2 = statusData == null ? void 0 : statusData.activeBuilds) == null ? void 0 : _a2.includes(id);
676                }),
677                className: "flex items-center gap-2 bg-zinc-800 hover:bg-zinc-700 disabled:opacity-30 text-white text-[10px] font-bold uppercase px-4 py-2 rounded-lg transition-all border border-zinc-700",
678                children: [
679                  /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 12 }),
680                  " Restart Selected"
681                ]
682              }
683            ),
684            /* @__PURE__ */ jsxRuntimeExports.jsxs(
685              "button",
686              {
687                onClick: () => runCommand("build", selectedList.join(" ")),
688                disabled: !hasSelection || isRunning && activeServiceLogs === null || selectedList.some((id) => {
689                  var _a2;
690                  return (_a2 = statusData == null ? void 0 : statusData.activeBuilds) == null ? void 0 : _a2.includes(id);
691                }),
692                className: "flex items-center gap-2 bg-indigo-600 hover:bg-indigo-500 disabled:opacity-30 text-white text-[10px] font-bold uppercase px-4 py-2 rounded-lg transition-all shadow-lg shadow-indigo-600/20",
693                children: [
694                  /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { size: 12 }),
695                  " Rebuild Selected"
696                ]
697              }
698            )
699          ] })
700        ] }),
701        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6", children: servicesList.map((svc) => {
702          var _a2, _b2, _c2, _d2, _e2;
703          const containerHealth = (_a2 = statusData == null ? void 0 : statusData.health) == null ? void 0 : _a2[svc.key];
704          const containerStats = (_b2 = statusData == null ? void 0 : statusData.stats) == null ? void 0 : _b2[svc.key];
705          const isRebuilding = ((_c2 = statusData == null ? void 0 : statusData.activeBuilds) == null ? void 0 : _c2.includes(svc.id)) || false;
706          return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-800/30 border border-zinc-800 p-5 rounded-xl hover:border-zinc-700 transition-all group", children: [
707            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-start mb-4", children: [
708              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
709                /* @__PURE__ */ jsxRuntimeExports.jsx(
710                  "div",
711                  {
712                    onClick: () => {
713                      const next = new Set(selectedServices);
714                      if (next.has(svc.id)) next.delete(svc.id);
715                      else next.add(svc.id);
716                      setSelectedServices(next);
717                    },
718                    className: `w-8 h-8 rounded-lg flex items-center justify-center cursor-pointer transition-all border ${selectedServices.has(svc.id) ? "bg-indigo-500 border-indigo-400 text-white shadow-lg shadow-indigo-500/40" : "bg-zinc-800 border-zinc-700 text-zinc-400 hover:border-zinc-500"}`,
719                    children: selectedServices.has(svc.id) ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 18, strokeWidth: 3 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(svc.icon, { size: 18 })
720                  }
721                ),
722                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
723                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-bold text-white leading-none mb-1", children: svc.label }),
724                  /* @__PURE__ */ jsxRuntimeExports.jsx(HealthIndicator, { status: containerHealth, isRebuilding, timestamp: (statusData == null ? void 0 : statusData.timestamp) || (lastChecked == null ? void 0 : lastChecked.toISOString()) })
725                ] })
726              ] }),
727              svc.url && /* @__PURE__ */ jsxRuntimeExports.jsx(
728                "a",
729                {
730                  href: svc.url.startsWith(":") ? `${window.location.protocol}//${window.location.hostname}${svc.url}` : svc.url,
731                  target: "_blank",
732                  rel: "noopener noreferrer",
733                  className: "p-2 bg-zinc-800 hover:bg-zinc-700 rounded-lg text-zinc-400 hover:text-white transition-colors",
734                  children: /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { size: 14 })
735                }
736              )
737            ] }),
738            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3 mb-4", children: [
739              /* @__PURE__ */ jsxRuntimeExports.jsx(
740                ResourceBar,
741                {
742                  label: "CPU Load",
743                  value: (containerStats == null ? void 0 : containerStats.cpu) || "0%",
744                  color: svc.color,
745                  max: (statusData == null ? void 0 : statusData.hostCores) ? statusData.hostCores * 100 : void 0
746                }
747              ),
748              /* @__PURE__ */ jsxRuntimeExports.jsx(
749                ResourceBar,
750                {
751                  label: "Memory",
752                  value: (containerStats == null ? void 0 : containerStats.mem) || "0B",
753                  color: svc.color
754                }
755              ),
756              svc.id === "db" && (statusData == null ? void 0 : statusData.dbConnections) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1 w-full pt-2 border-t border-zinc-800/50", children: [
757                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-[10px] text-zinc-500 font-bold uppercase", children: [
758                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "DB Connections" }),
759                  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-400 font-mono font-bold", children: [
760                    statusData.dbConnections.active,
761                    " / ",
762                    statusData.dbConnections.limit || "---"
763                  ] })
764                ] }),
765                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1.5 w-full bg-zinc-800 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
766                  "div",
767                  {
768                    className: "h-full bg-blue-500 transition-all duration-1000",
769                    style: {
770                      width: `${statusData.dbConnections.limit ? Math.min(statusData.dbConnections.active / statusData.dbConnections.limit * 100, 100) : 0}%`
771                    }
772                  }
773                ) })
774              ] }),
775              svc.id === "worker" && (statusData == null ? void 0 : statusData.workerStats) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1 w-full pt-2 border-t border-zinc-800/50", children: [
776                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-[10px] text-zinc-500 font-bold uppercase", children: [
777                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Active Instances" }),
778                  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-emerald-400 font-mono font-bold", children: [
779                    statusData.workerStats.active,
780                    " / ",
781                    statusData.workerStats.running,
782                    " Up"
783                  ] })
784                ] }),
785                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1.5 w-full bg-zinc-800 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
786                  "div",
787                  {
788                    className: "h-full bg-emerald-500 transition-all duration-1000",
789                    style: {
790                      width: `${statusData.workerStats.running ? Math.min(statusData.workerStats.active / statusData.workerStats.running * 100, 100) : 0}%`
791                    }
792                  }
793                ) }),
794                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[9px] text-zinc-500 mt-0.5 font-bold uppercase flex justify-between", children: [
795                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Spawned Total:" }),
796                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-purple-400 font-mono", children: statusData.workerStats.spawned })
797                ] }),
798                /* @__PURE__ */ jsxRuntimeExports.jsxs(
799                  "button",
800                  {
801                    onClick: (e) => {
802                      e.stopPropagation();
803                      setShowWorkerReplicas(!showWorkerReplicas);
804                    },
805                    className: "mt-2 w-full flex items-center justify-between px-2 py-1 bg-zinc-900/60 border border-zinc-800 hover:border-zinc-700 hover:text-white rounded-md text-[9px] font-bold text-zinc-400 transition-colors",
806                    children: [
807                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "WORKER REPLICAS LIST" }),
808                      showWorkerReplicas ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { size: 10 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { size: 10 })
809                    ]
810                  }
811                ),
812                showWorkerReplicas && (statusData == null ? void 0 : statusData.allContainers) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 max-h-[140px] overflow-y-auto border border-zinc-800/80 rounded-lg p-1.5 space-y-1 bg-black/30 scrollbar-thin", children: statusData.allContainers.filter((c) => c.service === "worker").sort((a, b) => {
813                  var _a3, _b3;
814                  const numA = parseInt(((_a3 = a.name.match(/\d+$/)) == null ? void 0 : _a3[0]) || "0");
815                  const numB = parseInt(((_b3 = b.name.match(/\d+$/)) == null ? void 0 : _b3[0]) || "0");
816                  return numA - numB;
817                }).map((c) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-[9px] px-1.5 py-0.5 rounded hover:bg-zinc-800/40", children: [
818                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 truncate max-w-[100px]", title: c.name, children: c.name.replace("hamienet-", "") }),
819                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 font-mono", children: [
820                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-indigo-400 font-bold", children: c.cpu }),
821                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400", children: c.mem })
822                  ] })
823                ] }, c.name)) })
824              ] })
825            ] }),
826            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pt-3 border-t border-zinc-800/50 flex flex-col gap-3", children: [
827              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center", children: [
828                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
829                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-zinc-500 font-bold uppercase mb-1 flex flex-wrap items-center gap-2", children: [
830                    "Last Rebuild",
831                    ((_d2 = statusData == null ? void 0 : statusData.containerVersions) == null ? void 0 : _d2[svc.key]) && statusData.containerVersions[svc.key] !== "unknown" && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: `px-1.5 py-0.5 rounded text-[9px] font-mono lowercase normal-case tracking-normal ${statusData.containerVersions[svc.key] === statusData.gitVersion ? "bg-emerald-900/30 text-emerald-400" : "bg-amber-900/30 text-amber-400"}`, children: [
832                      "image: ",
833                      statusData.containerVersions[svc.key]
834                    ] }),
835                    (statusData == null ? void 0 : statusData.gitVersion) && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "bg-zinc-800 text-zinc-400 px-1.5 py-0.5 rounded text-[9px] font-mono lowercase normal-case tracking-normal", children: [
836                      "local: ",
837                      statusData.gitVersion
838                    ] }),
839                    (statusData == null ? void 0 : statusData.gitRemoteVersion) && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: `px-1.5 py-0.5 rounded text-[9px] font-mono lowercase normal-case tracking-normal ${statusData.gitVersion === statusData.gitRemoteVersion ? "bg-emerald-900/30 text-emerald-400" : "bg-amber-900/30 text-amber-400"}`, children: [
840                      "remote: ",
841                      statusData.gitRemoteVersion
842                    ] })
843                  ] }),
844                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] text-white/70 font-mono", children: ((_e2 = statusData == null ? void 0 : statusData.buildTimes) == null ? void 0 : _e2[svc.key]) && statusData.buildTimes[svc.key] !== "N/A" ? new Date(statusData.buildTimes[svc.key]).toLocaleString() : "---" })
845                ] }),
846                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-end gap-1", children: [
847                  /* @__PURE__ */ jsxRuntimeExports.jsx(
848                    "div",
849                    {
850                      className: "text-[9px] text-zinc-600 capitalize",
851                      title: "Process-level status from docker ps. A container can be Up but still initializing (e.g. running prisma generate) or blocked by nginx routing.",
852                      children: (containerHealth == null ? void 0 : containerHealth.toLowerCase()) || "Offline"
853                    }
854                  ),
855                  (statusData == null ? void 0 : statusData.hostIp) && statusData.hostIp !== "N/A" && svc.hostPort && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[9px] font-mono text-indigo-400/70 flex items-center gap-1", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
856                    statusData.hostIp,
857                    ":",
858                    svc.hostPort
859                  ] }) })
860                ] })
861              ] }),
862              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
863                /* @__PURE__ */ jsxRuntimeExports.jsxs(
864                  "button",
865                  {
866                    onClick: () => runCommand("logs", svc.id),
867                    className: `flex items-center justify-center gap-1.5 py-1.5 rounded-lg text-[10px] font-bold transition-all border ${activeServiceLogs === svc.id ? "bg-indigo-600 border-indigo-500 text-white shadow-lg shadow-indigo-500/20" : "bg-zinc-800 border-zinc-700 text-zinc-400 hover:text-white hover:bg-zinc-700"}`,
868                    title: "Stream Logs",
869                    children: [
870                      /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { size: 12 }),
871                      " LOG"
872                    ]
873                  }
874                ),
875                /* @__PURE__ */ jsxRuntimeExports.jsxs(
876                  "button",
877                  {
878                    onClick: () => runCommand("restart", svc.id),
879                    disabled: isRunning && activeServiceLogs === null || isRebuilding,
880                    className: "flex items-center justify-center gap-1.5 py-1.5 rounded-lg text-[10px] font-bold bg-zinc-800 border border-zinc-700 text-zinc-400 hover:text-white hover:bg-zinc-700 transition-all disabled:opacity-50",
881                    title: "Restart Service",
882                    children: [
883                      /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 12 }),
884                      " RST"
885                    ]
886                  }
887                ),
888                /* @__PURE__ */ jsxRuntimeExports.jsxs(
889                  "button",
890                  {
891                    onClick: () => runCommand("build", svc.id),
892                    disabled: isRunning && activeServiceLogs === null || isRebuilding,
893                    className: "flex items-center justify-center gap-1.5 py-1.5 rounded-lg text-[10px] font-bold bg-zinc-800 border border-zinc-700 text-zinc-400 hover:text-white hover:bg-zinc-700 transition-all disabled:opacity-50",
894                    title: "Rebuild Service",
895                    children: [
896                      isRebuilding ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { size: 12 }),
897                      " RBILD"
898                    ]
899                  }
900                )
901              ] })
902            ] })
903          ] }, svc.key);
904        }) }),
905        (() => {
906          var _a2;
907          const knownServices = /* @__PURE__ */ new Set(["web_site", "web_test", "web_admin", "web_deployer", "worker", "db", "db-musicbrainz", "syncthing", "nginx", "beszel-hub", "beszel-agent"]);
908          const extraContainers = ((_a2 = statusData == null ? void 0 : statusData.allContainers) == null ? void 0 : _a2.filter((c) => !knownServices.has(c.service))) || [];
909          if (extraContainers.length === 0) return null;
910          return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-t border-zinc-800/80 mt-8 pt-8", children: [
911            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mb-4", children: [
912              /* @__PURE__ */ jsxRuntimeExports.jsx(Layers, { className: "text-indigo-400", size: 16 }),
913              /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-xs font-bold uppercase tracking-wider text-white", children: "Dynamic Containers (Not Code-Mapped)" }),
914              /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-2 py-0.5 rounded-full text-[9px] font-bold bg-zinc-800 border border-zinc-700 text-zinc-400 font-mono", children: [
915                extraContainers.length,
916                " Detected"
917              ] })
918            ] }),
919            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6", children: extraContainers.map((c) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-800/10 border border-zinc-800/80 p-5 rounded-xl hover:border-zinc-700 transition-all flex flex-col justify-between", children: [
920              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
921                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-start mb-4", children: [
922                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 truncate max-w-[70%]", children: [
923                    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-8 h-8 rounded-lg bg-zinc-800 border border-zinc-700 flex items-center justify-center text-zinc-400", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Cpu, { size: 18 }) }),
924                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "truncate", children: [
925                      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-bold text-white truncate", title: c.name, children: c.name }),
926                      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] text-zinc-500 font-mono mt-0.5 truncate", children: c.status })
927                    ] })
928                  ] }),
929                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `px-2 py-0.5 rounded-md text-[9px] font-bold border ${c.status.startsWith("Up") ? "bg-emerald-500/10 border-emerald-500/20 text-emerald-400" : "bg-zinc-800/50 border-zinc-700 text-zinc-400"}`, children: c.status.startsWith("Up") ? "Online" : "Offline" })
930                ] }),
931                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4 mb-4 pt-2 border-t border-zinc-800/30", children: [
932                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
933                    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[9px] text-zinc-500 font-bold uppercase mb-1", children: "CPU Load" }),
934                    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-bold text-white font-mono", children: c.cpu || "0%" })
935                  ] }),
936                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
937                    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[9px] text-zinc-500 font-bold uppercase mb-1", children: "Memory" }),
938                    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-bold text-white font-mono", children: c.mem || "0B" })
939                  ] })
940                ] })
941              ] }),
942              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pt-3 border-t border-zinc-800/50 flex flex-col gap-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-between items-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
943                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] text-zinc-500 font-bold uppercase mb-1", children: "Created" }),
944                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] text-white/70 font-mono truncate max-w-[170px]", children: c.created && c.created !== "N/A" ? new Date(c.created).toLocaleString() : "---" })
945              ] }) }) })
946            ] }, c.name)) })
947          ] });
948        })()
949      ] }),
950      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-6 py-3 bg-black/40 border-t border-zinc-800 flex justify-between items-center text-[10px] text-zinc-500 font-mono", children: [
951        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-4", children: [
952          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
953            "Deployment Port: ",
954            /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "3002" })
955          ] }),
956          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
957            "Last GitHub Pull: ",
958            /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: (statusData == null ? void 0 : statusData.lastGitPull) ? new Date(statusData.lastGitPull).toLocaleString() : "---" })
959          ] })
960        ] }),
961        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
962          "Last offline prepare: ",
963          /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: (statusData == null ? void 0 : statusData.lastOfflinePrepare) ? new Date(statusData.lastOfflinePrepare).toLocaleDateString() : "Never" })
964        ] })
965      ] })
966    ] });
967  };
968  const renderNodeServiceLogsSection = () => {
969    var _a, _b, _c, _d, _e, _f;
970    const availableServices = [
971      { id: "web_site", label: "Site Engine (web_site)" },
972      { id: "web_test", label: "Test Engine (web_test)" },
973      { id: "web_admin", label: "Admin Engine (web_admin)" },
974      { id: "worker", label: "MIDI Processor (worker)" },
975      { id: "web_deployer", label: "System Deployer (web_deployer)" },
976      { id: "db", label: "PostgreSQL DB (db)" },
977      { id: "all_services", label: "All Services (all_services)" }
978    ];
979    const availableNodes = [
980      { id: "all", label: "All Nodes (HK & JP)" },
981      { id: "HK", label: "Hong Kong Node (HK)" },
982      { id: "JP", label: "Japan Node (JP)" }
983    ];
984    const builds = (serviceMetrics == null ? void 0 : serviceMetrics.builds) || {};
985    const downtime = (serviceMetrics == null ? void 0 : serviceMetrics.downtime) || {};
986    const uptime = (serviceMetrics == null ? void 0 : serviceMetrics.uptime) || {};
987    const formatDuration = (ms) => {
988      if (!ms || ms <= 0) return "0s";
989      const seconds = Math.floor(ms / 1e3);
990      if (seconds < 60) return `${seconds}s`;
991      const minutes = Math.floor(seconds / 60);
992      const remSec = seconds % 60;
993      if (minutes < 60) return `${minutes}m ${remSec}s`;
994      const hours = Math.floor(minutes / 60);
995      return `${hours}h ${minutes % 60}m`;
996    };
997    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-xl overflow-hidden shadow-2xl p-6 space-y-6", children: [
998      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 pb-4 border-b border-zinc-800", children: [
999        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
1000          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2.5 rounded-lg bg-indigo-500/10 border border-indigo-500/20 text-indigo-400", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { size: 20 }) }),
1001          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1002            /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-base font-bold text-white flex items-center gap-2", children: "Node & Service Performance Logs" }),
1003            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400", children: "Up time, Down time, and Build time logs categorized by service across HK & JP nodes" })
1004          ] })
1005        ] }),
1006        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-3 w-full sm:w-auto", children: [
1007          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [
1008            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-zinc-400 font-bold uppercase", children: "Service:" }),
1009            /* @__PURE__ */ jsxRuntimeExports.jsx(
1010              "select",
1011              {
1012                value: logService,
1013                onChange: (e) => setLogService(e.target.value),
1014                className: "bg-zinc-800 text-zinc-200 border border-zinc-700 rounded-lg px-3 py-1.5 text-xs font-bold focus:outline-none focus:ring-2 focus:ring-indigo-500 cursor-pointer",
1015                children: availableServices.map((s) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: s.id, className: "bg-zinc-850 text-zinc-200", children: s.label }, s.id))
1016              }
1017            )
1018          ] }),
1019          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [
1020            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-zinc-400 font-bold uppercase", children: "Node:" }),
1021            /* @__PURE__ */ jsxRuntimeExports.jsx(
1022              "select",
1023              {
1024                value: logNode,
1025                onChange: (e) => setLogNode(e.target.value),
1026                className: "bg-zinc-800 text-zinc-200 border border-zinc-700 rounded-lg px-3 py-1.5 text-xs font-bold focus:outline-none focus:ring-2 focus:ring-indigo-500 cursor-pointer",
1027                children: availableNodes.map((n) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: n.id, className: "bg-zinc-850 text-zinc-200", children: n.label }, n.id))
1028              }
1029            )
1030          ] }),
1031          /* @__PURE__ */ jsxRuntimeExports.jsx(
1032            "button",
1033            {
1034              onClick: fetchServiceLogsAndMetrics,
1035              disabled: isLoadingLogs,
1036              className: "p-2 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 rounded-lg transition-colors border border-zinc-700 disabled:opacity-50",
1037              title: "Refresh Logs & Metrics",
1038              children: /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { size: 14, className: isLoadingLogs ? "animate-spin" : "" })
1039            }
1040          )
1041        ] })
1042      ] }),
1043      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4", children: [
1044        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-950/60 border border-zinc-800/80 p-4 rounded-xl space-y-2", children: [
1045          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center", children: [
1046            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-bold uppercase text-zinc-400 flex items-center gap-1.5", children: [
1047              /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { size: 14, className: "text-emerald-400" }),
1048              " Service Availability"
1049            ] }),
1050            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `px-2 py-0.5 rounded text-[10px] font-bold uppercase border ${uptime.currentStatus === "ONLINE" ? "bg-emerald-500/10 border-emerald-500/30 text-emerald-400" : "bg-red-500/10 border-red-500/30 text-red-400"}`, children: uptime.currentStatus || "ONLINE" })
1051          ] }),
1052          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-baseline justify-between pt-1", children: [
1053            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-2xl font-black text-white font-mono", children: uptime.uptimePercentage !== void 0 ? `${uptime.uptimePercentage}%` : "100%" }),
1054            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-zinc-500 uppercase font-bold", children: "Uptime Rate" })
1055          ] }),
1056          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-zinc-500 font-mono pt-1 border-t border-zinc-800/50", children: [
1057            "Last Check: ",
1058            ((_a = uptime.latestCheck) == null ? void 0 : _a.timestamp) ? new Date(uptime.latestCheck.timestamp).toLocaleString() : "Active Heartbeat"
1059          ] })
1060        ] }),
1061        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-950/60 border border-zinc-800/80 p-4 rounded-xl space-y-2", children: [
1062          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center", children: [
1063            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-bold uppercase text-zinc-400 flex items-center gap-1.5", children: [
1064              /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { size: 14, className: "text-red-400" }),
1065              " Outages & Downtime"
1066            ] }),
1067            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-2 py-0.5 rounded text-[10px] font-bold uppercase bg-zinc-800 border border-zinc-700 text-zinc-300 font-mono", children: [
1068              downtime.totalOutages || 0,
1069              " Outages"
1070            ] })
1071          ] }),
1072          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-baseline justify-between pt-1", children: [
1073            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-2xl font-black text-white font-mono", children: formatDuration(downtime.totalDowntimeMs) }),
1074            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-zinc-500 uppercase font-bold", children: "Total Downtime" })
1075          ] }),
1076          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-zinc-500 font-mono pt-1 border-t border-zinc-800/50 truncate", children: [
1077            "Last Outage: ",
1078            ((_b = downtime.latest) == null ? void 0 : _b.timestamp) ? new Date(downtime.latest.timestamp).toLocaleString() : "No Outages Recorded"
1079          ] })
1080        ] }),
1081        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-950/60 border border-zinc-800/80 p-4 rounded-xl space-y-2", children: [
1082          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center", children: [
1083            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-bold uppercase text-zinc-400 flex items-center gap-1.5", children: [
1084              /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { size: 14, className: "text-amber-400" }),
1085              " Build Duration & Stats"
1086            ] }),
1087            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-2 py-0.5 rounded text-[10px] font-bold uppercase bg-zinc-800 border border-zinc-700 text-zinc-300 font-mono", children: [
1088              builds.total || 0,
1089              " Builds (",
1090              builds.successful || 0,
1091              " PASS / ",
1092              builds.failed || 0,
1093              " FAIL)"
1094            ] })
1095          ] }),
1096          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-baseline justify-between pt-1", children: [
1097            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-2xl font-black text-white font-mono", children: formatDuration(builds.avgDurationMs) }),
1098            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-zinc-500 uppercase font-bold", children: "Avg Build Time" })
1099          ] }),
1100          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-zinc-500 font-mono pt-1 border-t border-zinc-800/50 flex justify-between", children: [
1101            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
1102              "Latest Build: ",
1103              ((_c = builds.latest) == null ? void 0 : _c.durationMs) ? formatDuration(builds.latest.durationMs) : "---"
1104            ] }),
1105            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: ((_d = builds.latest) == null ? void 0 : _d.status) === "SUCCESS" ? "text-emerald-400 font-bold" : ((_e = builds.latest) == null ? void 0 : _e.status) === "FAILED" ? "text-red-400 font-bold" : "text-zinc-500", children: ((_f = builds.latest) == null ? void 0 : _f.status) || "---" })
1106          ] })
1107        ] })
1108      ] }),
1109      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-950/80 border border-zinc-800 rounded-xl overflow-hidden", children: [
1110        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3 bg-zinc-900/60 border-b border-zinc-800 flex justify-between items-center", children: [
1111          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-bold uppercase text-zinc-400 flex items-center gap-2", children: [
1112            /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { size: 14, className: "text-indigo-400" }),
1113            " Event Logs Feed (",
1114            serviceLogs.length,
1115            ")"
1116          ] }),
1117          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-zinc-500 font-mono", children: [
1118            "Filter: Service = ",
1119            logService,
1120            " | Node = ",
1121            logNode
1122          ] })
1123        ] }),
1124        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "max-h-[360px] overflow-y-auto custom-scrollbar", children: serviceLogs.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("table", { className: "w-full text-left text-xs", children: [
1125          /* @__PURE__ */ jsxRuntimeExports.jsx("thead", { className: "bg-zinc-900/40 text-zinc-500 font-mono text-[10px] uppercase border-b border-zinc-800/60 sticky top-0 bg-zinc-900", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { children: [
1126            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "py-2.5 px-4 font-bold", children: "Timestamp" }),
1127            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "py-2.5 px-4 font-bold", children: "Node" }),
1128            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "py-2.5 px-4 font-bold", children: "Service" }),
1129            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "py-2.5 px-4 font-bold", children: "Event Type" }),
1130            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "py-2.5 px-4 font-bold", children: "Status" }),
1131            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "py-2.5 px-4 font-bold", children: "Duration" }),
1132            /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "py-2.5 px-4 font-bold", children: "Details" })
1133          ] }) }),
1134          /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { className: "divide-y divide-zinc-800/40 font-mono text-[11px]", children: serviceLogs.map((log) => /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "hover:bg-zinc-800/30 transition-colors", children: [
1135            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-2 px-4 text-zinc-400 whitespace-nowrap", children: new Date(log.timestamp).toLocaleString() }),
1136            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-2 px-4 whitespace-nowrap", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: `px-2 py-0.5 rounded text-[9px] font-bold ${log.node === "HK" ? "bg-blue-500/10 text-blue-400 border border-blue-500/20" : "bg-purple-500/10 text-purple-400 border border-purple-500/20"}`, children: [
1137              log.node,
1138              " Node"
1139            ] }) }),
1140            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-2 px-4 font-bold text-zinc-200 whitespace-nowrap", children: log.service }),
1141            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-2 px-4 whitespace-nowrap", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `px-2 py-0.5 rounded text-[9px] font-bold ${log.eventType === "BUILD" ? "bg-amber-500/10 text-amber-400 border border-amber-500/20" : log.eventType === "DOWNTIME" ? "bg-red-500/10 text-red-400 border border-red-500/20" : "bg-emerald-500/10 text-emerald-400 border border-emerald-500/20"}`, children: log.eventType }) }),
1142            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-2 px-4 whitespace-nowrap", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `font-bold ${log.status === "SUCCESS" || log.status === "ONLINE" ? "text-emerald-400" : "text-red-400"}`, children: log.status }) }),
1143            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-2 px-4 text-zinc-400 whitespace-nowrap", children: log.durationMs ? formatDuration(log.durationMs) : "---" }),
1144            /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-2 px-4 text-zinc-300 truncate max-w-[320px]", title: log.message || "", children: log.message || "---" })
1145          ] }, log.id)) })
1146        ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-8 text-center text-zinc-500 text-xs italic", children: [
1147          'No log events recorded yet for service "',
1148          logService,
1149          '" on node filter "',
1150          logNode,
1151          '".'
1152        ] }) })
1153      ] })
1154    ] });
1155  };
1156  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full overflow-y-auto custom-scrollbar space-y-6 animate-in fade-in pb-20 px-6", children: [
1157    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6 rounded-xl border bg-zinc-900 border-zinc-800 flex flex-col md:flex-row items-start md:items-center justify-between gap-4", children: [
1158      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4", children: [
1159        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3 rounded-full bg-indigo-500/20 text-indigo-400", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Server, { size: 32 }) }),
1160        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1161          /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-2xl font-bold text-white", children: [
1162            "System Deployments (Standalone) ",
1163            (statusData == null ? void 0 : statusData.node) && statusData.node !== "Unknown" ? `(${statusData.node})` : (statusData == null ? void 0 : statusData.hostIp) === "192.168.1.115" ? "(HK)" : (statusData == null ? void 0 : statusData.hostIp) === "192.168.40.101" ? "(JP)" : ""
1164          ] }),
1165          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-zinc-400", children: "Manage code updates and Docker containers" })
1166        ] })
1167      ] }),
1168      /* @__PURE__ */ jsxRuntimeExports.jsxs(
1169        "button",
1170        {
1171          onClick: () => fetchStatus(true),
1172          disabled: isRefreshingStatus,
1173          className: "flex items-center gap-2 px-4 py-2 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 rounded-lg text-sm font-bold transition-all border border-zinc-700 disabled:opacity-50",
1174          children: [
1175            /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { size: 14, className: isRefreshingStatus ? "animate-spin" : "" }),
1176            "Refresh Metadata"
1177          ]
1178        }
1179      )
1180    ] }),
1181    renderDeploymentStatus(),
1182    renderNodeServiceLogsSection(),
1183    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-[300px_1fr] gap-6", children: [
1184      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
1185        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-xl p-5 shadow-sm", children: [
1186          /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "text-sm font-bold uppercase text-zinc-500 mb-4 flex items-center gap-2", children: [
1187            /* @__PURE__ */ jsxRuntimeExports.jsx(Github, { size: 16 }),
1188            " Source Control"
1189          ] }),
1190          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1191            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1192              "button",
1193              {
1194                onClick: () => runCommand("git_pull"),
1195                disabled: isRunning && activeServiceLogs === null,
1196                className: "w-full flex items-center justify-center gap-2 bg-white text-black hover:bg-zinc-200 py-3 rounded-lg font-bold transition-colors disabled:opacity-50",
1197                children: [
1198                  /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { size: 16 }),
1199                  " Pull Updates"
1200                ]
1201              }
1202            ),
1203            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1204              "button",
1205              {
1206                onClick: () => runCommand("git_push"),
1207                disabled: isRunning && activeServiceLogs === null || !(statusData == null ? void 0 : statusData.hasLocalChanges),
1208                className: `w-full flex items-center justify-center gap-2 py-3 rounded-lg font-bold transition-all ${(statusData == null ? void 0 : statusData.hasLocalChanges) ? "bg-indigo-600 text-white hover:bg-indigo-500 shadow-lg shadow-indigo-500/20" : "bg-zinc-800 text-zinc-500 cursor-not-allowed opacity-50"}`,
1209                children: [
1210                  /* @__PURE__ */ jsxRuntimeExports.jsx(Github, { size: 16 }),
1211                  " Push to Git"
1212                ]
1213              }
1214            ),
1215            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1216              "button",
1217              {
1218                onClick: () => {
1219                  setValidationStatus("validating");
1220                  runCommand("validate");
1221                },
1222                disabled: isRunning && activeServiceLogs === null,
1223                className: `w-full flex items-center justify-center gap-2 py-2 rounded-lg text-xs font-bold transition-all border ${validationStatus === "pass" ? "bg-emerald-500/10 border-emerald-500/50 text-emerald-400" : validationStatus === "fail" ? "bg-red-500/10 border-red-500/50 text-red-400" : "bg-zinc-800 border-zinc-700 text-zinc-300 hover:bg-zinc-700"} disabled:opacity-50`,
1224                children: [
1225                  validationStatus === "validating" ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { size: 14 }),
1226                  validationStatus === "pass" ? "Validation Passed" : validationStatus === "fail" ? "Validation Failed" : "Validate Syntax"
1227                ]
1228              }
1229            ),
1230            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1231              "div",
1232              {
1233                onClick: () => {
1234                  const next = !autoRebuild;
1235                  setAutoRebuild(next);
1236                  if (next) {
1237                    const initial = ["web_test", "web_admin", "worker", "db"];
1238                    if (includeSiteEngine) {
1239                      initial.push("web_site");
1240                    }
1241                    setSelectedServices(new Set(initial));
1242                  }
1243                },
1244                className: "flex items-center gap-2 px-1 py-1 cursor-pointer group",
1245                children: [
1246                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `w-3.5 h-3.5 rounded border flex items-center justify-center transition-colors ${autoRebuild ? "bg-emerald-500 border-emerald-500" : "bg-transparent border-zinc-600"}`, children: autoRebuild && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-1.5 h-1.5 bg-white rounded-full" }) }),
1247                  /* @__P
1247URE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-bold uppercase transition-colors ${autoRebuild ? "text-emerald-400" : "text-zinc-500 group-hover:text-zinc-400"}`, children: "Auto Rebuild Services" })
1248                ]
1249              }
1250            ),
1251            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1252              "div",
1253              {
1254                onClick: () => {
1255                  const next = !includeSiteEngine;
1256                  setIncludeSiteEngine(next);
1257                  setSelectedServices((prev) => {
1258                    const newSet = new Set(prev);
1259                    if (next) {
1260                      newSet.add("web_site");
1261                    } else {
1262                      newSet.delete("web_site");
1263                    }
1264                    return newSet;
1265                  });
1266                },
1267                className: "flex items-center gap-2 pl-4 py-1 cursor-pointer group",
1268                children: [
1269                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `w-3.5 h-3.5 rounded border flex items-center justify-center transition-colors ${includeSiteEngine ? "bg-emerald-500/80 border-emerald-500/80" : "bg-transparent border-zinc-600"}`, children: includeSiteEngine && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-1.5 h-1.5 bg-white rounded-full" }) }),
1270                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-bold uppercase transition-colors ${includeSiteEngine ? "text-emerald-400/80" : "text-zinc-500 group-hover:text-zinc-400"}`, children: "include Site Engine (3002)" })
1271                ]
1272              }
1273            ),
1274            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1275              "div",
1276              {
1277                onClick: () => {
1278                  const next = !autoPrep;
1279                  setAutoPrep(next);
1280                  if (next) setIsPrepEnabled(true);
1281                },
1282                className: "flex items-center gap-2 px-1 py-1 cursor-pointer group",
1283                children: [
1284                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `w-3.5 h-3.5 rounded border flex items-center justify-center transition-colors ${autoPrep ? "bg-indigo-500 border-indigo-500" : "bg-transparent border-zinc-600"}`, children: autoPrep && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-1.5 h-1.5 bg-white rounded-full" }) }),
1285                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-bold uppercase transition-colors ${autoPrep ? "text-indigo-400" : "text-zinc-500 group-hover:text-zinc-400"}`, children: "Auto Prepare Dependencies" })
1286                ]
1287              }
1288            ),
1289            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-2 mt-2", children: [
1290              /* @__PURE__ */ jsxRuntimeExports.jsx(
1291                "button",
1292                {
1293                  onClick: () => {
1294                    if (confirm("This will discard ALL local changes to tracked files. Continue?")) {
1295                      runCommand("git_reset");
1296                    }
1297                  },
1298                  disabled: isRunning && activeServiceLogs === null,
1299                  className: "flex items-center justify-center gap-2 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 py-2 rounded-lg text-xs font-bold transition-all border border-zinc-700 disabled:opacity-50",
1300                  title: "Discard local changes",
1301                  children: "Reset Local"
1302                }
1303              ),
1304              /* @__PURE__ */ jsxRuntimeExports.jsx(
1305                "button",
1306                {
1307                  onClick: () => runCommand("git_stash"),
1308                  disabled: isRunning && activeServiceLogs === null,
1309                  className: "flex items-center justify-center gap-2 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 py-2 rounded-lg text-xs font-bold transition-all border border-zinc-700 disabled:opacity-50",
1310                  title: "Move changes to stash",
1311                  children: "Stash Changes"
1312                }
1313              )
1314            ] }),
1315            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1316              "button",
1317              {
1318                onClick: () => {
1319                  if (confirm("CRITICAL: This will fetch the latest main branch and OVERWRITE ALL local changes. This is the 'Nuclear Option' to fix sync errors. Continue?")) {
1320                    runCommand("git_force_update");
1321                  }
1322                },
1323                disabled: isRunning && activeServiceLogs === null,
1324                className: "w-full flex items-center justify-center gap-2 bg-amber-500/10 hover:bg-amber-500/20 text-amber-500 py-2.5 rounded-lg text-xs font-bold transition-all border border-amber-500/20 disabled:opacity-50",
1325                children: [
1326                  /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { size: 14 }),
1327                  " Force Update (Overwrite)"
1328                ]
1329              }
1330            )
1331          ] }),
1332          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 pt-4 border-t border-zinc-800", children: [
1333            /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-[10px] font-bold uppercase text-zinc-600 mb-2", children: "Build Preparation" }),
1334            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1335              "button",
1336              {
1337                onClick: () => runCommand("offline_prep"),
1338                disabled: isRunning && activeServiceLogs === null,
1339                className: "w-full flex items-center justify-center gap-2 bg-zinc-800 hover:bg-zinc-700 text-white py-2.5 rounded-lg text-sm font-bold transition-all border border-zinc-700 disabled:opacity-50",
1340                children: [
1341                  /* @__PURE__ */ jsxRuntimeExports.jsx(CirclePlay, { size: 16, className: "text-emerald-500" }),
1342                  "Prepare Offline Capability"
1343                ]
1344              }
1345            ),
1346            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-zinc-500 mt-2 text-center", children: "Syncs dependencies & assets for zero-internet builds." })
1347          ] })
1348        ] }),
1349        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-xl p-5 shadow-sm", children: [
1350          /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "text-sm font-bold uppercase text-zinc-500 mb-4 flex items-center gap-2", children: [
1351            /* @__PURE__ */ jsxRuntimeExports.jsx(Server, { size: 16 }),
1352            " Maintenance"
1353          ] }),
1354          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1355            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1356              "button",
1357              {
1358                onClick: () => {
1359                  if (confirm("This will PERMANENTLY delete all unused Docker containers, networks, and images (preserving build cache). Continue?")) {
1360                    runCommand("prune");
1361                  }
1362                },
1363                disabled: isRunning && activeServiceLogs === null,
1364                className: "w-full flex items-center justify-center gap-2 bg-red-500/10 hover:bg-red-500/20 text-red-400 py-3 rounded-lg font-bold transition-colors border border-red-500/20 disabled:opacity-50",
1365                children: [
1366                  /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { size: 18 }),
1367                  "Prune Docker (Free Space)"
1368                ]
1369              }
1370            ),
1371            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1372              "button",
1373              {
1374                onClick: () => {
1375                  if (confirm("CRITICAL: This will immediately reboot the host server. All services will be temporarily offline. Proceed?")) {
1376                    if (confirm("Are you absolutely sure you want to REBOOT the entire server right now?")) {
1377                      runCommand("reboot_host");
1378                    }
1379                  }
1380                },
1381                disabled: isRunning && activeServiceLogs === null,
1382                className: "w-full flex items-center justify-center gap-2 bg-amber-500/10 hover:bg-amber-500/20 text-amber-500 py-3 rounded-lg font-bold transition-colors border border-amber-500/20 disabled:opacity-50",
1383                children: [
1384                  /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 18 }),
1385                  "Restart Host Server"
1386                ]
1387              }
1388            ),
1389            /* @__PURE__ */ jsxRuntimeExports.jsxs(
1390              "button",
1391              {
1392                onClick: () => {
1393                  if (confirm("CRITICAL: This will immediately shut down the host server. All services will go offline. Proceed?")) {
1394                    if (confirm("Are you absolutely sure you want to SHUT DOWN the entire server right now?")) {
1395                      runCommand("shutdown_host");
1396                    }
1397                  }
1398                },
1399                disabled: isRunning && activeServiceLogs === null,
1400                className: "w-full flex items-center justify-center gap-2 bg-red-500/10 hover:bg-red-500/20 text-red-500 py-3 rounded-lg font-bold transition-colors border border-red-500/20 disabled:opacity-50",
1401                children: [
1402                  /* @__PURE__ */ jsxRuntimeExports.jsx(Power, { size: 18 }),
1403                  "Shut Down Host Server"
1404                ]
1405              }
1406            )
1407          ] }),
1408          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-zinc-500 mt-2 text-center italic", children: "System diagnostics & physical system controls." })
1409        ] })
1410      ] }),
1411      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-6", children: [
1412        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-[#0a0a0a] rounded-xl border border-zinc-800 shadow-xl overflow-hidden flex flex-col h-[80vh] resize-y min-h-[300px]", children: [
1413          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-3 bg-zinc-900 border-b border-zinc-800 flex justify-between items-center shrink-0", children: [
1414            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-zinc-400 font-bold uppercase text-xs", children: [
1415              /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { size: 14 }),
1416              " Console Output"
1417            ] }),
1418            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
1419              isRunning && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1420                /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { size: 14, className: "animate-spin text-indigo-400" }),
1421                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-indigo-400 font-bold uppercase", children: "Running" })
1422              ] }),
1423              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: stopStream, disabled: !isRunning, className: "text-[10px] uppercase font-bold tracking-wider px-2 py-1 bg-red-500/10 text-red-500 hover:bg-red-500/20 rounded disabled:opacity-30 transition-colors", children: "Force Stop" }),
1424              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setLogs([]), className: "text-[10px] uppercase font-bold tracking-wider px-2 py-1 bg-zinc-800 text-zinc-400 hover:text-white rounded transition-colors", children: "Clear" })
1425            ] })
1426          ] }),
1427          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: logContainerRef, className: "p-4 overflow-y-auto text-zinc-300 space-y-1 flex-1 custom-scrollbar", children: logs.map((log, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(LogLine, { text: log }, i)) })
1428        ] }),
1429        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-[#0a0a0a] rounded-xl border border-zinc-800 shadow-xl overflow-hidden flex flex-col h-[80vh] resize-y min-h-[300px]", children: [
1430          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-3 bg-zinc-900 border-b border-zinc-800 flex justify-between items-center shrink-0", children: [
1431            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-zinc-400 font-bold uppercase text-xs", children: [
1432              /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { size: 14 }),
1433              " Service Logs ",
1434              activeServiceLogs && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-indigo-400", children: [
1435                "(",
1436                activeServiceLogs,
1437                ")"
1438              ] })
1439            ] }),
1440            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
1441              isSecondaryRunning && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1442                /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { size: 14, className: "animate-spin text-indigo-400" }),
1443                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-indigo-400 font-bold uppercase", children: "Streaming" })
1444              ] }),
1445              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: stopSecondaryStream, disabled: !isSecondaryRunning, className: "text-[10px] uppercase font-bold tracking-wider px-2 py-1 bg-red-500/10 text-red-500 hover:bg-red-500/20 rounded disabled:opacity-30 transition-colors", children: "Stop Stream" }),
1446              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setSecondaryLogs([]), className: "text-[10px] uppercase font-bold tracking-wider px-2 py-1 bg-zinc-800 text-zinc-400 hover:text-white rounded transition-colors", children: "Clear" })
1447            ] })
1448          ] }),
1449          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: secondaryLogContainerRef, className: "p-4 overflow-y-auto text-emerald-400/90 space-y-1 flex-1 custom-scrollbar font-mono text-xs", children: secondaryLogs.map((log, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(LogLine, { text: log }, i)) })
1450        ] })
1451      ] })
1452    ] })
1453  ] });
1454};
1455export {
1456  SystemManager as default
1457};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.