@gravito/zenith 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +77 -22
  3. package/README.zh-TW.md +88 -0
  4. package/dist/bin.js +64681 -15842
  5. package/dist/client/assets/index-C80c1frR.css +1 -0
  6. package/dist/client/assets/index-CrWem9u3.js +434 -0
  7. package/dist/server/index.js +64681 -15842
  8. package/package.json +9 -7
  9. package/postcss.config.js +4 -4
  10. package/src/client/Layout.tsx +36 -39
  11. package/src/client/Sidebar.tsx +7 -7
  12. package/src/client/ThroughputChart.tsx +31 -17
  13. package/src/client/WorkerStatus.tsx +56 -80
  14. package/src/client/components/ConfirmDialog.tsx +22 -14
  15. package/src/client/components/JobInspector.tsx +95 -162
  16. package/src/client/index.css +29 -31
  17. package/src/client/pages/LoginPage.tsx +33 -31
  18. package/src/client/pages/MetricsPage.tsx +65 -37
  19. package/src/client/pages/OverviewPage.tsx +30 -28
  20. package/src/client/pages/PulsePage.tsx +111 -190
  21. package/src/client/pages/QueuesPage.tsx +82 -83
  22. package/src/client/pages/SchedulesPage.tsx +56 -61
  23. package/src/client/pages/SettingsPage.tsx +118 -137
  24. package/src/client/pages/WorkersPage.tsx +101 -115
  25. package/src/server/services/CommandService.ts +8 -9
  26. package/src/server/services/PulseService.ts +61 -4
  27. package/src/server/services/QueueService.ts +293 -0
  28. package/src/shared/types.ts +38 -13
  29. package/tailwind.config.js +75 -68
  30. package/tsconfig.json +28 -37
  31. package/tsconfig.node.json +9 -11
  32. package/dist/client/assets/index-BSMp8oq_.js +0 -436
  33. package/dist/client/assets/index-BwxlHx-_.css +0 -1
  34. package/dist/client/index.html +0 -13
  35. package/src/client/index.html +0 -12
  36. /package/{ECOSYSTEM_EXPANSION_RFC.md → doc/ECOSYSTEM_EXPANSION_RFC.md} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravito/zenith",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "Gravito Zenith: Zero-config control plane for Gravito Flux & Stream",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,13 +17,15 @@
17
17
  "test": "bun test",
18
18
  "typecheck": "bun tsc -p tsconfig.json --noEmit --skipLibCheck",
19
19
  "seed": "bun scripts/seed.ts",
20
- "worker": "bun scripts/worker.ts"
20
+ "worker": "bun scripts/worker.ts",
21
+ "test:unit": "bun test",
22
+ "test:integration": "test $(find tests -name '*.integration.test.ts' 2>/dev/null | wc -l) -gt 0 && find tests -name '*.integration.test.ts' -print0 | xargs -0 bun test --timeout=10000 || echo 'No integration tests found'"
21
23
  },
22
24
  "dependencies": {
23
- "@gravito/atlas": "workspace:*",
24
- "@gravito/photon": "workspace:*",
25
- "@gravito/quasar": "workspace:*",
26
- "@gravito/stream": "workspace:*",
25
+ "@gravito/atlas": "^1.6.0",
26
+ "@gravito/photon": "^1.0.1",
27
+ "@gravito/quasar": "^1.3.0",
28
+ "@gravito/stream": "^2.0.2",
27
29
  "@tanstack/react-query": "^5.0.0",
28
30
  "clsx": "^2.1.1",
29
31
  "date-fns": "^4.1.0",
@@ -51,4 +53,4 @@
51
53
  "publishConfig": {
52
54
  "access": "public"
53
55
  }
54
- }
56
+ }
package/postcss.config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
- plugins: {
3
- tailwindcss: {},
4
- autoprefixer: {},
5
- },
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
6
  }
@@ -379,20 +379,20 @@ export function Layout({ children }: LayoutProps) {
379
379
  animate={{ width: isSidebarOpen ? 260 : 80 }}
380
380
  className="border-r border-border/40 bg-card/50 backdrop-blur-xl flex flex-col z-50 transition-all duration-300 ease-[0.22, 1, 0.36, 1]"
381
381
  >
382
- <div className="h-16 flex items-center px-6 border-b border-border/40 bg-card/80">
382
+ <div className="h-16 flex items-center px-6 border-b border-white/5 bg-black/40">
383
383
  <div className="flex items-center gap-3 overflow-hidden">
384
- <div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center shrink-0 shadow-lg shadow-primary/20">
385
- <Zap className="text-primary-foreground fill-current" size={18} />
384
+ <div className="w-9 h-9 rounded-xl bg-primary flex items-center justify-center shrink-0 shadow-[0_0_20px_rgba(0,240,255,0.3)]">
385
+ <Zap className="text-black fill-current" size={20} />
386
386
  </div>
387
387
  <motion.div
388
388
  animate={{ opacity: isSidebarOpen ? 1 : 0 }}
389
389
  className="flex flex-col min-w-[140px]"
390
390
  >
391
- <span className="font-extrabold text-lg tracking-tight leading-none bg-clip-text text-transparent bg-gradient-to-r from-primary to-primary/60">
391
+ <span className="font-black text-xl tracking-tighter leading-none text-white font-heading italic uppercase">
392
392
  Zenith
393
393
  </span>
394
- <span className="text-[9px] font-bold text-muted-foreground uppercase tracking-[0.2em]">
395
- Control Plane
394
+ <span className="text-[8px] font-black text-primary uppercase tracking-[0.3em] mt-0.5">
395
+ Quantum Control
396
396
  </span>
397
397
  </motion.div>
398
398
  </div>
@@ -430,17 +430,17 @@ export function Layout({ children }: LayoutProps) {
430
430
  </button>
431
431
 
432
432
  {/* System Integrity Indicator */}
433
- <div className="hidden lg:flex items-center gap-3 px-4 py-1.5 rounded-full bg-primary/5 border border-primary/10 transition-all hover:bg-primary/10 hover:border-primary/20 cursor-default group">
433
+ <div className="hidden lg:flex items-center gap-3 px-4 py-2 rounded-xl bg-primary/5 border border-primary/20 transition-all hover:bg-primary/10 cursor-default group shadow-[inset_0_0_20px_rgba(0,240,255,0.02)]">
434
434
  <div className="relative flex items-center justify-center">
435
- <ShieldCheck size={14} className="text-primary z-10" />
436
- <div className="absolute w-3 h-3 bg-primary rounded-full glow-pulse"></div>
435
+ <ShieldCheck size={16} className="text-primary z-10" />
436
+ <div className="absolute w-4 h-4 bg-primary/20 rounded-full glow-pulse"></div>
437
437
  </div>
438
438
  <div className="flex flex-col">
439
- <span className="text-[9px] font-black uppercase tracking-[0.1em] text-primary/60 leading-none">
440
- System Integrity
439
+ <span className="text-[8px] font-black uppercase tracking-[0.2em] text-primary/60 leading-none">
440
+ Quantum Core
441
441
  </span>
442
- <span className="text-[11px] font-black tracking-tight leading-none">
443
- {health.toFixed(1)}% Nominal
442
+ <span className="text-[11px] font-black tracking-tight leading-none text-white mt-0.5 font-mono">
443
+ {health.toFixed(2)}% NOMINAL
444
444
  </span>
445
445
  </div>
446
446
  </div>
@@ -452,6 +452,7 @@ export function Layout({ children }: LayoutProps) {
452
452
  onClick={toggleTheme}
453
453
  className="p-2.5 hover:bg-muted rounded-xl text-muted-foreground hover:text-primary transition-all duration-300 active:scale-95 group relative"
454
454
  title={theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'}
455
+ aria-label={theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'}
455
456
  >
456
457
  {theme === 'light' ? (
457
458
  <Moon size={20} className="group-hover:rotate-[15deg] transition-transform" />
@@ -483,45 +484,41 @@ export function Layout({ children }: LayoutProps) {
483
484
  </div>
484
485
 
485
486
  {/* Dynamic Status Bar (Ambient) */}
486
- <footer className="h-7 border-t bg-card/80 backdrop-blur-md flex items-center justify-between px-6 z-10 transition-colors">
487
+ <footer className="h-8 border-t border-white/5 bg-black/60 backdrop-blur-xl flex items-center justify-between px-6 z-10 transition-colors">
487
488
  <div className="flex items-center gap-6 overflow-hidden">
488
- <div className="flex items-center gap-2 border-r border-border/50 pr-4">
489
- <span className="w-1.5 h-1.5 rounded-full bg-green-500 shadow-[0_0_8px_rgba(34,197,94,0.4)]"></span>
490
- <span className="text-[10px] font-black text-muted-foreground/60 uppercase tracking-widest whitespace-nowrap">
491
- Node: {systemStatus?.env || 'production-east-1'}
489
+ <div className="flex items-center gap-2 border-r border-white/10 pr-4">
490
+ <span className="w-1.5 h-1.5 rounded-full bg-emerald-500 shadow-[0_0_8px_#10B981]"></span>
491
+ <span className="text-[9px] font-black text-white/40 uppercase tracking-[0.2em] whitespace-nowrap font-mono">
492
+ {systemStatus?.env || 'QUANTUM-1'}
492
493
  </span>
493
494
  </div>
494
- <div className="flex items-center gap-4 text-[9px] font-black text-muted-foreground/40 uppercase tracking-[0.2em] animate-in fade-in slide-in-from-left duration-1000">
495
- <span className="flex items-center gap-1.5">
496
- <Activity size={10} className="text-primary/40" /> Latency: 4ms
495
+ <div className="flex items-center gap-4 text-[9px] font-black text-white/20 uppercase tracking-[0.3em] animate-in fade-in slide-in-from-left duration-1000">
496
+ <span className="flex items-center gap-1.5 text-primary/60">
497
+ <Activity size={10} className="text-primary" /> 4MS
497
498
  </span>
498
- <span className="hidden sm:inline border-l border-border/30 pl-4 text-primary">
499
- RAM: {systemStatus?.memory?.rss || '...'} /{' '}
500
- {systemStatus?.memory?.total || '4.00 GB'}
499
+ <span className="hidden sm:inline border-l border-white/5 pl-4 text-white/40">
500
+ MEM: {systemStatus?.memory?.rss || '...'}
501
501
  </span>
502
- <span className="hidden md:inline border-l border-border/30 pl-4 uppercase">
503
- Engine: {systemStatus?.engine || 'v2.4.1-beta'}
504
- </span>
505
- <span className="hidden lg:inline border-l border-border/30 pl-4 lowercase">
506
- v: {systemStatus?.node || '...'}
502
+ <span className="hidden md:inline border-l border-white/5 pl-4 text-white/40">
503
+ ENGINE: {systemStatus?.engine || 'V2.4.1'}
507
504
  </span>
508
505
  </div>
509
506
  </div>
510
- <div className="flex items-center gap-4 pl-4 bg-gradient-to-l from-card via-card to-transparent text-right">
511
- <div className="flex items-center gap-2">
512
- <div className="w-8 h-1 bg-muted rounded-full overflow-hidden">
507
+ <div className="flex items-center gap-4 pl-4 bg-gradient-to-l from-black via-black to-transparent text-right">
508
+ <div className="flex items-center gap-3">
509
+ <div className="w-12 h-1 bg-white/5 rounded-full overflow-hidden">
513
510
  <motion.div
514
- animate={{ x: [-20, 20] }}
515
- transition={{ duration: 2, repeat: Infinity, ease: 'linear' }}
516
- className="w-4 h-full bg-primary/40"
511
+ animate={{ x: [-48, 48] }}
512
+ transition={{ duration: 3, repeat: Infinity, ease: 'linear' }}
513
+ className="w-6 h-full bg-primary/40 shadow-[0_0_10px_#00F0FF]"
517
514
  />
518
515
  </div>
519
- <span className="text-[9px] font-black text-primary/60 uppercase tracking-widest">
520
- Bus Traffic
516
+ <span className="text-[8px] font-black text-primary uppercase tracking-[0.3em]">
517
+ SYNCING
521
518
  </span>
522
519
  </div>
523
- <span className="font-mono text-[10px] text-muted-foreground/60 tabular-nums lowercase">
524
- {new Date().toISOString().split('T')[1]?.split('.')[0] || ''} utc
520
+ <span className="font-mono text-[9px] text-white/30 tabular-nums uppercase">
521
+ {new Date().toISOString().split('T')[1]?.split('.')[0] || ''} Z
525
522
  </span>
526
523
  </div>
527
524
  </footer>
@@ -56,17 +56,17 @@ export function Sidebar({ className, collapsed, toggleCollapse }: SidebarProps)
56
56
  key={i}
57
57
  to={item.path}
58
58
  className={cn(
59
- 'w-full flex items-center gap-4 px-4 py-3 rounded-xl transition-all text-muted-foreground group/item relative overflow-hidden',
59
+ 'w-full flex items-center gap-4 px-4 py-3 rounded-xl transition-all text-muted-foreground/60 group/item relative overflow-hidden font-heading',
60
60
  isActive
61
- ? 'bg-primary text-primary-foreground shadow-lg shadow-primary/20 hover:scale-[1.02]'
62
- : 'hover:bg-muted font-medium hover:text-foreground active:scale-95'
61
+ ? 'bg-primary/10 text-primary shadow-[0_0_20px_rgba(0,240,255,0.1)] border border-primary/20'
62
+ : 'hover:bg-white/[0.03] font-medium hover:text-foreground active:scale-95'
63
63
  )}
64
64
  >
65
65
  <item.icon
66
- size={22}
66
+ size={20}
67
67
  className={cn(
68
68
  'transition-all shrink-0',
69
- isActive ? 'scale-110' : 'group-hover/item:scale-110'
69
+ isActive ? 'scale-110 text-primary' : 'group-hover/item:scale-110'
70
70
  )}
71
71
  />
72
72
  <motion.span
@@ -75,14 +75,14 @@ export function Sidebar({ className, collapsed, toggleCollapse }: SidebarProps)
75
75
  opacity: collapsed ? 0 : 1,
76
76
  display: collapsed ? 'none' : 'block',
77
77
  }}
78
- className="font-semibold whitespace-nowrap tracking-tight"
78
+ className="font-black whitespace-nowrap tracking-tight uppercase text-[11px]"
79
79
  >
80
80
  {item.label}
81
81
  </motion.span>
82
82
  {isActive && (
83
83
  <motion.div
84
84
  layoutId="active-pill"
85
- className="absolute left-0 w-1 h-6 bg-primary-foreground rounded-r-full"
85
+ className="absolute left-0 w-1 h-5 bg-primary rounded-r-full shadow-[0_0_10px_#00F0FF]"
86
86
  />
87
87
  )}
88
88
  </NavLink>
@@ -70,21 +70,23 @@ export function ThroughputChart() {
70
70
  <div className="flex justify-between items-start mb-6 z-10">
71
71
  <div>
72
72
  <div className="flex items-center gap-2">
73
- <h3 className="text-xl font-bold tracking-tight">System Throughput</h3>
74
- <div className="flex items-center gap-1.5 px-2 py-0.5 bg-green-500/10 text-green-500 text-[8px] font-black uppercase tracking-widest rounded-full border border-green-500/20">
75
- <span className="w-1 h-1 bg-green-500 rounded-full animate-ping"></span>
73
+ <h3 className="text-xl font-black tracking-tight font-heading">System Throughput</h3>
74
+ <div className="flex items-center gap-1.5 px-2 py-0.5 bg-primary/10 text-primary text-[8px] font-black uppercase tracking-widest rounded-full border border-primary/20">
75
+ <span className="w-1 h-1 bg-primary rounded-full animate-ping"></span>
76
76
  Live
77
77
  </div>
78
78
  </div>
79
- <p className="text-[10px] text-muted-foreground uppercase tracking-[0.2em] font-bold mt-1">
79
+ <p className="text-[10px] text-muted-foreground uppercase tracking-[0.2em] font-black mt-1">
80
80
  Jobs processed per minute
81
81
  </p>
82
82
  </div>
83
83
  <div className="text-right">
84
- <p className="text-2xl font-black text-foreground">
84
+ <p className="text-3xl font-black text-foreground font-mono">
85
85
  {chartData[chartData.length - 1]?.value || 0}
86
86
  </p>
87
- <p className="text-[8px] text-muted-foreground uppercase font-bold">Current Rate</p>
87
+ <p className="text-[8px] text-muted-foreground uppercase font-black tracking-tighter">
88
+ Current Rate
89
+ </p>
88
90
  </div>
89
91
  </div>
90
92
 
@@ -93,7 +95,7 @@ export function ThroughputChart() {
93
95
  <AreaChart data={chartData} margin={{ top: 10, right: 10, left: -20, bottom: 0 }}>
94
96
  <defs>
95
97
  <linearGradient id="colorValue" x1="0" y1="0" x2="0" y2="1">
96
- <stop offset="5%" stopColor="hsl(var(--primary))" stopOpacity={0.4} />
98
+ <stop offset="5%" stopColor="hsl(var(--primary))" stopOpacity={0.5} />
97
99
  <stop offset="50%" stopColor="hsl(var(--primary))" stopOpacity={0.1} />
98
100
  <stop offset="95%" stopColor="hsl(var(--primary))" stopOpacity={0} />
99
101
  </linearGradient>
@@ -102,38 +104,50 @@ export function ThroughputChart() {
102
104
  strokeDasharray="3 3"
103
105
  vertical={false}
104
106
  stroke="hsl(var(--border))"
105
- opacity={0.5}
107
+ opacity={0.3}
106
108
  />
107
109
  <XAxis
108
110
  dataKey="time"
109
111
  axisLine={false}
110
112
  tickLine={false}
111
- tick={{ fontSize: 9, fill: 'hsl(var(--muted-foreground))', fontWeight: 600 }}
113
+ tick={{
114
+ fontSize: 9,
115
+ fill: 'hsl(var(--muted-foreground))',
116
+ fontWeight: 700,
117
+ fontFamily: 'Fira Code',
118
+ }}
112
119
  dy={10}
113
120
  />
114
121
  <YAxis
115
122
  axisLine={false}
116
123
  tickLine={false}
117
- tick={{ fontSize: 9, fill: 'hsl(var(--muted-foreground))', fontWeight: 600 }}
124
+ tick={{
125
+ fontSize: 9,
126
+ fill: 'hsl(var(--muted-foreground))',
127
+ fontWeight: 700,
128
+ fontFamily: 'Fira Code',
129
+ }}
118
130
  />
119
131
  <Tooltip
120
132
  cursor={{ stroke: 'hsl(var(--primary))', strokeWidth: 1, strokeDasharray: '4 4' }}
121
133
  contentStyle={{
122
- backgroundColor: 'hsl(var(--card))',
123
- border: '1px solid hsl(var(--border))',
124
- borderRadius: '16px',
125
- fontSize: '12px',
126
- boxShadow: '0 10px 15px -3px rgb(0 0 0 / 0.1)',
134
+ backgroundColor: 'rgba(9, 9, 11, 0.9)',
135
+ border: '1px solid rgba(255, 255, 255, 0.1)',
136
+ borderRadius: '12px',
137
+ fontSize: '11px',
138
+ fontFamily: 'Fira Code',
139
+ boxShadow: '0 10px 15px -3px rgb(0 0 0 / 0.5)',
140
+ backdropFilter: 'blur(8px)',
127
141
  }}
128
142
  itemStyle={{ fontWeight: 'bold', color: 'hsl(var(--primary))' }}
129
143
  />
130
144
  <Area
131
- type="stepAfter"
145
+ type="monotone"
132
146
  dataKey="value"
133
147
  stroke="hsl(var(--primary))"
134
148
  fillOpacity={1}
135
149
  fill="url(#colorValue)"
136
- strokeWidth={2.5}
150
+ strokeWidth={3}
137
151
  animationDuration={1500}
138
152
  />
139
153
  </AreaChart>
@@ -1,5 +1,5 @@
1
1
  import { type ClassValue, clsx } from 'clsx'
2
- import { Activity, Cpu, Terminal } from 'lucide-react'
2
+ import { Activity, Cpu } from 'lucide-react'
3
3
  import { twMerge } from 'tailwind-merge'
4
4
 
5
5
  function cn(...inputs: ClassValue[]) {
@@ -73,28 +73,28 @@ export function WorkerStatus({
73
73
 
74
74
  return (
75
75
  <div className="card-premium h-full flex flex-col overflow-hidden">
76
- <div className="p-6 pb-0 flex-none">
77
- <div className="flex justify-between items-center mb-6">
76
+ <div className="p-5 pb-0 flex-none">
77
+ <div className="flex justify-between items-center mb-5">
78
78
  <div>
79
- <h3 className="text-lg font-black flex items-center gap-2 tracking-tight">
80
- <Cpu size={20} className="text-primary" />
79
+ <h3 className="text-base font-black flex items-center gap-2 tracking-tight font-heading">
80
+ <Cpu size={18} className="text-primary" />
81
81
  Cluster Nodes
82
82
  </h3>
83
- <p className="text-[10px] text-muted-foreground uppercase font-black tracking-widest opacity-60">
84
- Real-time load
83
+ <p className="text-[9px] text-muted-foreground uppercase font-black tracking-[0.2em] opacity-50 mt-0.5">
84
+ Live Infrastructure
85
85
  </p>
86
86
  </div>
87
- <span className="text-[10px] font-black text-green-500 bg-green-500/10 px-3 py-1 rounded-full uppercase tracking-widest border border-green-500/20">
87
+ <span className="text-[9px] font-black text-emerald-500 bg-emerald-500/10 px-2 py-1 rounded-md uppercase tracking-widest border border-emerald-500/20">
88
88
  {onlineCount} ACTIVE
89
89
  </span>
90
90
  </div>
91
91
  </div>
92
92
 
93
- <div className="flex-1 overflow-y-auto min-h-0 px-6 space-y-3 scrollbar-thin pb-6">
93
+ <div className="flex-1 overflow-y-auto min-h-0 px-5 space-y-2 scrollbar-thin pb-5">
94
94
  {workers.length === 0 && (
95
- <div className="py-12 text-center text-muted-foreground/30 flex flex-col items-center gap-2">
96
- <Activity size={24} className="opacity-20 animate-pulse" />
97
- <p className="text-[10px] font-black uppercase tracking-widest">No nodes connected</p>
95
+ <div className="py-12 text-center text-muted-foreground/20 flex flex-col items-center gap-2">
96
+ <Activity size={24} className="opacity-30 animate-pulse" />
97
+ <p className="text-[9px] font-black uppercase tracking-[0.3em]">Awaiting signals...</p>
98
98
  </div>
99
99
  )}
100
100
 
@@ -102,52 +102,41 @@ export function WorkerStatus({
102
102
  <div
103
103
  key={worker.id}
104
104
  className={cn(
105
- 'relative flex items-center gap-4 p-4 rounded-2xl border transition-all group overflow-hidden shrink-0',
105
+ 'relative flex items-center gap-3 p-3 rounded-xl border transition-all group overflow-hidden shrink-0',
106
106
  worker.id === highlightedWorkerId
107
- ? 'bg-primary/5 border-primary/50 shadow-[0_0_20px_rgba(var(--primary-rgb),0.1)] -translate-y-1 scale-[1.02] z-10'
108
- : 'bg-card hover:bg-muted/10 border-border/50 hover:border-primary/20'
107
+ ? 'bg-primary/10 border-primary/40 shadow-[0_0_20px_rgba(0,240,255,0.1)] -translate-x-1 z-10'
108
+ : 'bg-black/20 hover:bg-white/[0.03] border-white/5 hover:border-primary/20'
109
109
  )}
110
110
  >
111
111
  {/* Status bar */}
112
112
  <div
113
113
  className={cn(
114
114
  'absolute left-0 top-0 bottom-0 w-1 transition-all',
115
- worker.status === 'online' ? 'bg-green-500' : 'bg-muted-foreground/30'
115
+ worker.status === 'online'
116
+ ? 'bg-emerald-500 shadow-[0_0_10px_#10B981]'
117
+ : 'bg-muted-foreground/20'
116
118
  )}
117
119
  />
118
120
 
119
- {/* Icon/Dot */}
120
- <div className="relative shrink-0 ml-1">
121
- <div
122
- className={cn(
123
- 'w-3 h-3 rounded-full',
124
- worker.status === 'online'
125
- ? 'bg-green-500 animate-pulse shadow-[0_0_12px_rgba(34,197,94,0.6)]'
126
- : 'bg-muted-foreground/40'
127
- )}
128
- />
129
- </div>
130
-
131
121
  {/* Main Info */}
132
- <div className="flex-1 min-w-0 flex flex-col justify-center mr-2">
122
+ <div className="flex-1 min-w-0 flex flex-col justify-center">
133
123
  {worker.service && (
134
- <span className="text-[10px] font-black text-primary/80 uppercase tracking-widest mb-0.5 whitespace-nowrap">
124
+ <span className="text-[8px] font-black text-primary uppercase tracking-widest mb-0.5 whitespace-nowrap opacity-80">
135
125
  {worker.service}
136
126
  </span>
137
127
  )}
138
128
  <h4
139
- className="text-sm font-black tracking-tight text-foreground truncate"
129
+ className="text-xs font-black tracking-tight text-foreground/90 truncate font-heading"
140
130
  title={worker.id}
141
131
  >
142
132
  {getWorkerName(worker.id, worker.pid) || worker.id}
143
133
  </h4>
144
- <div className="flex items-center gap-2 mt-1">
145
- <span className="text-[9px] font-bold text-muted-foreground uppercase tracking-wider whitespace-nowrap">
146
- PID {worker.pid}
134
+ <div className="flex items-center gap-2 mt-0.5">
135
+ <span className="text-[8px] font-bold text-muted-foreground/40 uppercase font-mono">
136
+ PID:{worker.pid}
147
137
  </span>
148
138
  {worker.meta?.laravel && worker.meta.laravel.workerCount > 0 && (
149
- <span className="inline-flex items-center gap-1 text-[9px] font-black text-white bg-red-500 px-1.5 py-0.5 rounded shadow-sm uppercase tracking-widest leading-none whitespace-nowrap">
150
- <Terminal size={8} />
139
+ <span className="inline-flex items-center gap-1 text-[8px] font-black text-white bg-red-500/80 px-1 rounded shadow-sm uppercase tracking-tighter leading-none whitespace-nowrap">
151
140
  {worker.meta.laravel.workerCount} PHP
152
141
  </span>
153
142
  )}
@@ -155,57 +144,44 @@ export function WorkerStatus({
155
144
  </div>
156
145
 
157
146
  {/* Metrics (Right Side) */}
158
- <div className="flex items-center gap-3 text-right shrink-0">
147
+ <div className="flex items-center gap-4 text-right shrink-0">
159
148
  {worker.metrics && (
160
149
  <>
161
- <div className="hidden sm:block space-y-1 w-12">
162
- <div className="flex justify-between text-[8px] font-black text-muted-foreground uppercase tracking-tighter">
163
- <span>CPU</span>
164
- <span
165
- className={cn(
166
- worker.metrics.cpu > (worker.metrics.cores || 1) * 100 && 'text-red-500'
167
- )}
168
- >
169
- {worker.metrics.cpu.toFixed(0)}%
170
- </span>
171
- </div>
172
- <div className="h-1 w-full bg-muted rounded-full overflow-hidden">
173
- <div
174
- className="h-full bg-foreground transition-all duration-700"
175
- style={{ width: `${Math.min(100, worker.metrics.cpu)}%` }}
176
- ></div>
177
- </div>
150
+ <div className="hidden sm:flex flex-col items-end gap-1 w-10">
151
+ <span className="text-[8px] font-black text-muted-foreground/40 uppercase font-mono">
152
+ CPU
153
+ </span>
154
+ <span
155
+ className={cn(
156
+ 'text-[10px] font-black font-mono tracking-tighter',
157
+ worker.metrics.cpu > 80 ? 'text-red-500' : 'text-primary'
158
+ )}
159
+ >
160
+ {worker.metrics.cpu.toFixed(0)}%
161
+ </span>
178
162
  </div>
179
163
 
180
- <div className="hidden sm:block space-y-1 w-12">
181
- <div className="flex justify-between text-[8px] font-black text-muted-foreground uppercase tracking-tighter">
182
- <span>RAM</span>
183
- <span className="truncate ml-1">
184
- {formatBytes(worker.metrics.ram.rss).split(' ')[0]}
185
- </span>
186
- </div>
187
- <div className="h-1 w-full bg-muted rounded-full overflow-hidden">
188
- <div
189
- className="h-full bg-indigo-500 transition-all duration-700"
190
- style={{
191
- width: `${Math.min(100, (worker.metrics.ram.rss / 2000000000) * 100)}%`,
192
- }}
193
- ></div>
194
- </div>
164
+ <div className="hidden sm:flex flex-col items-end gap-1 w-12">
165
+ <span className="text-[8px] font-black text-muted-foreground/40 uppercase font-mono">
166
+ RAM
167
+ </span>
168
+ <span className="text-[10px] font-black font-mono tracking-tighter text-white/80">
169
+ {formatBytes(worker.metrics.ram.rss).split(' ')[0]}
170
+ </span>
195
171
  </div>
196
172
  </>
197
173
  )}
198
174
 
199
- <div className="w-12">
200
- <p className="text-xs font-black tracking-tighter tabular-nums text-foreground">
175
+ <div className="flex flex-col items-end gap-1 w-10">
176
+ <span className="text-[8px] font-black text-muted-foreground/40 uppercase font-mono">
177
+ UP
178
+ </span>
179
+ <p className="text-[10px] font-black tracking-tighter font-mono text-foreground/60 tabular-nums">
201
180
  {worker.uptime > 3600
202
- ? `${(worker.uptime / 3600).toFixed(1)}h`
181
+ ? `${(worker.uptime / 3600).toFixed(1)}H`
203
182
  : worker.uptime > 60
204
- ? `${(worker.uptime / 60).toFixed(0)}m`
205
- : `${worker.uptime.toFixed(0)}s`}
206
- </p>
207
- <p className="text-[8px] text-muted-foreground uppercase font-black tracking-widest opacity-50">
208
- UP
183
+ ? `${(worker.uptime / 60).toFixed(0)}M`
184
+ : `${worker.uptime.toFixed(0)}S`}
209
185
  </p>
210
186
  </div>
211
187
  </div>
@@ -213,12 +189,12 @@ export function WorkerStatus({
213
189
  ))}
214
190
  </div>
215
191
 
216
- <div className="p-6 pt-0 flex-none">
192
+ <div className="p-5 pt-0 flex-none">
217
193
  <button
218
194
  type="button"
219
- className="w-full py-3 bg-muted text-[10px] font-black rounded-xl hover:bg-primary hover:text-primary-foreground transition-all uppercase tracking-[0.2em] opacity-60 hover:opacity-100 active:scale-95 shadow-lg shadow-transparent hover:shadow-primary/20"
195
+ className="w-full py-2.5 bg-muted/50 text-[9px] font-black rounded-lg hover:bg-primary hover:text-primary-foreground transition-all uppercase tracking-[0.2em] border border-white/5 hover:border-primary/50 active:scale-95 shadow-lg shadow-transparent hover:shadow-primary/10 font-heading"
220
196
  >
221
- Manage Nodes
197
+ Node Orchestration
222
198
  </button>
223
199
  </div>
224
200
  </div>
@@ -60,16 +60,21 @@ export function ConfirmDialog({
60
60
  onKeyDown={(e) => e.stopPropagation()}
61
61
  >
62
62
  <motion.div
63
- initial={{ scale: 0.9, opacity: 0 }}
64
- animate={{ scale: 1, opacity: 1 }}
65
- exit={{ scale: 0.9, opacity: 0 }}
66
- transition={{ type: 'spring', damping: 25, stiffness: 200 }}
67
- className="bg-card border rounded-2xl p-6 max-w-md shadow-2xl"
63
+ initial={{ scale: 0.95, opacity: 0, y: 20 }}
64
+ animate={{ scale: 1, opacity: 1, y: 0 }}
65
+ exit={{ scale: 0.95, opacity: 0, y: 20 }}
66
+ transition={{ type: 'spring', damping: 25, stiffness: 300 }}
67
+ className="bg-zinc-900 border border-white/10 rounded-3xl p-8 max-w-md shadow-[0_0_50px_rgba(0,0,0,0.8)] scanline overflow-hidden"
68
68
  onClick={(e) => e.stopPropagation()}
69
69
  >
70
- <h3 className="text-xl font-black mb-2">{title}</h3>
71
- <p className="text-sm text-muted-foreground mb-6 whitespace-pre-line">{message}</p>
72
- <div className="flex gap-3 justify-end">
70
+ <h3 className="text-2xl font-black mb-3 font-heading tracking-tight text-white uppercase italic italic">
71
+ {title}
72
+ </h3>
73
+ <div className="h-px w-full bg-white/5 mb-6" />
74
+ <p className="text-[13px] font-bold text-muted-foreground mb-8 leading-relaxed uppercase tracking-wide opacity-80">
75
+ {message}
76
+ </p>
77
+ <div className="flex gap-4 justify-end">
73
78
  <button
74
79
  type="button"
75
80
  onClick={(e) => {
@@ -77,7 +82,7 @@ export function ConfirmDialog({
77
82
  onCancel()
78
83
  }}
79
84
  disabled={isProcessing}
80
- className="px-4 py-2 bg-muted text-foreground rounded-lg hover:bg-muted/80 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
85
+ className="px-6 py-3 bg-zinc-800 text-white/60 rounded-xl hover:bg-zinc-700 transition-all disabled:opacity-20 disabled:cursor-not-allowed text-[10px] font-black uppercase tracking-[0.2em] font-heading border border-white/5"
81
86
  >
82
87
  {cancelText}
83
88
  </button>
@@ -89,10 +94,13 @@ export function ConfirmDialog({
89
94
  }}
90
95
  disabled={isProcessing}
91
96
  className={cn(
92
- 'px-4 py-2 rounded-lg text-white transition-all disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2',
93
- variant === 'danger' && 'bg-red-500 hover:bg-red-600',
94
- variant === 'warning' && 'bg-amber-500 hover:bg-amber-600',
95
- variant === 'info' && 'bg-blue-500 hover:bg-blue-600'
97
+ 'px-6 py-3 rounded-xl text-black transition-all disabled:opacity-20 disabled:cursor-not-allowed flex items-center gap-2 text-[10px] font-black uppercase tracking-[0.2em] font-heading shadow-lg',
98
+ variant === 'danger' &&
99
+ 'bg-red-500 shadow-[0_0_20px_rgba(239,68,68,0.3)] hover:bg-red-400',
100
+ variant === 'warning' &&
101
+ 'bg-amber-500 shadow-[0_0_20px_rgba(245,158,11,0.3)] hover:bg-amber-400',
102
+ variant === 'info' &&
103
+ 'bg-primary shadow-[0_0_20px_rgba(0,240,255,0.3)] hover:bg-primary/80'
96
104
  )}
97
105
  >
98
106
  {isProcessing && (
@@ -114,7 +122,7 @@ export function ConfirmDialog({
114
122
  />
115
123
  </svg>
116
124
  )}
117
- {isProcessing ? 'Processing...' : confirmText}
125
+ {isProcessing ? 'Executing...' : confirmText}
118
126
  </button>
119
127
  </div>
120
128
  </motion.div>