groove-dev 0.27.142 → 0.27.144
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@groove-dev/cli/package.json +1 -1
- package/node_modules/@groove-dev/daemon/package.json +1 -1
- package/node_modules/@groove-dev/daemon/src/api.js +1086 -6532
- package/node_modules/@groove-dev/daemon/src/gateways/manager.js +35 -1
- package/node_modules/@groove-dev/daemon/src/index.js +3 -0
- package/node_modules/@groove-dev/daemon/src/journalist.js +23 -13
- package/node_modules/@groove-dev/daemon/src/mlx-server.js +365 -0
- package/node_modules/@groove-dev/daemon/src/model-lab.js +308 -12
- package/node_modules/@groove-dev/daemon/src/pm.js +1 -1
- package/node_modules/@groove-dev/daemon/src/process.js +2 -2
- package/node_modules/@groove-dev/daemon/src/providers/local.js +36 -8
- package/node_modules/@groove-dev/daemon/src/registry.js +21 -5
- package/node_modules/@groove-dev/daemon/src/routes/agents.js +889 -0
- package/node_modules/@groove-dev/daemon/src/routes/coordination.js +318 -0
- package/node_modules/@groove-dev/daemon/src/routes/files.js +751 -0
- package/node_modules/@groove-dev/daemon/src/routes/integrations.js +485 -0
- package/node_modules/@groove-dev/daemon/src/routes/network.js +1784 -0
- package/node_modules/@groove-dev/daemon/src/routes/providers.js +755 -0
- package/node_modules/@groove-dev/daemon/src/routes/schedules.js +110 -0
- package/node_modules/@groove-dev/daemon/src/routes/teams.js +650 -0
- package/node_modules/@groove-dev/daemon/src/scheduler.js +456 -24
- package/node_modules/@groove-dev/daemon/src/teams.js +1 -1
- package/node_modules/@groove-dev/daemon/src/validate.js +38 -1
- package/node_modules/@groove-dev/daemon/templates/mlx-setup.json +12 -0
- package/node_modules/@groove-dev/daemon/templates/tgi-setup.json +1 -1
- package/node_modules/@groove-dev/daemon/templates/vllm-setup.json +1 -1
- package/node_modules/@groove-dev/daemon/test/introducer.test.js +3 -3
- package/node_modules/@groove-dev/daemon/test/journalist.test.js +7 -10
- package/node_modules/@groove-dev/daemon/test/registry.test.js +38 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-BcoF6_eF.js +1012 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-Dd7qhiEd.css +1 -0
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/package.json +1 -1
- package/{packages/gui/src/app.jsx → node_modules/@groove-dev/gui/src/App.jsx} +0 -2
- package/node_modules/@groove-dev/gui/src/app.css +35 -0
- package/node_modules/@groove-dev/gui/src/components/agents/agent-config.jsx +1 -128
- package/node_modules/@groove-dev/gui/src/components/agents/agent-feed.jsx +144 -31
- package/node_modules/@groove-dev/gui/src/components/agents/agent-node.jsx +8 -13
- package/node_modules/@groove-dev/gui/src/components/agents/code-review.jsx +159 -122
- package/node_modules/@groove-dev/gui/src/components/agents/diff-viewer.jsx +23 -23
- package/node_modules/@groove-dev/gui/src/components/agents/journalist-panel.jsx +1 -1
- package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +2 -135
- package/node_modules/@groove-dev/gui/src/components/automations/automation-card.jsx +274 -0
- package/node_modules/@groove-dev/gui/src/components/automations/automation-wizard.jsx +1136 -0
- package/node_modules/@groove-dev/gui/src/components/dashboard/activity-feed.jsx +3 -3
- package/node_modules/@groove-dev/gui/src/components/dashboard/cache-ring.jsx +5 -5
- package/node_modules/@groove-dev/gui/src/components/dashboard/context-gauges.jsx +6 -8
- package/node_modules/@groove-dev/gui/src/components/dashboard/fleet-panel.jsx +8 -14
- package/node_modules/@groove-dev/gui/src/components/dashboard/intel-panel.jsx +238 -656
- package/node_modules/@groove-dev/gui/src/components/dashboard/kpi-card.jsx +3 -3
- package/node_modules/@groove-dev/gui/src/components/dashboard/routing-chart.jsx +3 -3
- package/node_modules/@groove-dev/gui/src/components/dashboard/team-burn-panel.jsx +1 -1
- package/node_modules/@groove-dev/gui/src/components/dashboard/token-chart.jsx +4 -4
- package/node_modules/@groove-dev/gui/src/components/editor/selection-menu.jsx +2 -0
- package/node_modules/@groove-dev/gui/src/components/lab/lab-assistant.jsx +316 -82
- package/node_modules/@groove-dev/gui/src/components/lab/metrics-panel.jsx +187 -32
- package/node_modules/@groove-dev/gui/src/components/lab/parameter-panel.jsx +195 -14
- package/node_modules/@groove-dev/gui/src/components/lab/runtime-config.jsx +286 -102
- package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +2 -4
- package/node_modules/@groove-dev/gui/src/components/layout/terminal-panel.jsx +4 -2
- package/node_modules/@groove-dev/gui/src/components/layout/welcome-splash.jsx +137 -108
- package/node_modules/@groove-dev/gui/src/components/network/network-health.jsx +2 -2
- package/node_modules/@groove-dev/gui/src/components/network/performance-dashboard.jsx +4 -4
- package/node_modules/@groove-dev/gui/src/components/settings/ssh-wizard.jsx +81 -99
- package/node_modules/@groove-dev/gui/src/components/ui/sheet.jsx +5 -2
- package/node_modules/@groove-dev/gui/src/lib/cron.js +64 -0
- package/node_modules/@groove-dev/gui/src/lib/status.js +24 -24
- package/node_modules/@groove-dev/gui/src/lib/theme-hex.js +1 -0
- package/node_modules/@groove-dev/gui/src/stores/groove.js +34 -3144
- package/node_modules/@groove-dev/gui/src/stores/helpers.js +10 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +452 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/automations-slice.js +96 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/chat-slice.js +227 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/editor-slice.js +285 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/marketplace-slice.js +461 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/network-slice.js +361 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/preview-slice.js +109 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/providers-slice.js +897 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/teams-slice.js +413 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/ui-slice.js +98 -0
- package/node_modules/@groove-dev/gui/src/views/agents.jsx +5 -5
- package/node_modules/@groove-dev/gui/src/views/dashboard.jsx +12 -13
- package/node_modules/@groove-dev/gui/src/views/marketplace.jsx +191 -3
- package/node_modules/@groove-dev/gui/src/views/model-lab.jsx +17 -6
- package/node_modules/@groove-dev/gui/src/views/models.jsx +410 -509
- package/node_modules/@groove-dev/gui/src/views/network.jsx +3 -3
- package/node_modules/@groove-dev/gui/src/views/settings.jsx +81 -94
- package/node_modules/@groove-dev/gui/src/views/teams.jsx +40 -483
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/api.js +1086 -6532
- package/packages/daemon/src/gateways/manager.js +35 -1
- package/packages/daemon/src/index.js +3 -0
- package/packages/daemon/src/journalist.js +23 -13
- package/packages/daemon/src/mlx-server.js +365 -0
- package/packages/daemon/src/model-lab.js +308 -12
- package/packages/daemon/src/pm.js +1 -1
- package/packages/daemon/src/process.js +2 -2
- package/packages/daemon/src/providers/local.js +36 -8
- package/packages/daemon/src/registry.js +21 -5
- package/packages/daemon/src/routes/agents.js +889 -0
- package/packages/daemon/src/routes/coordination.js +318 -0
- package/packages/daemon/src/routes/files.js +751 -0
- package/packages/daemon/src/routes/integrations.js +485 -0
- package/packages/daemon/src/routes/network.js +1784 -0
- package/packages/daemon/src/routes/providers.js +755 -0
- package/packages/daemon/src/routes/schedules.js +110 -0
- package/packages/daemon/src/routes/teams.js +650 -0
- package/packages/daemon/src/scheduler.js +456 -24
- package/packages/daemon/src/teams.js +1 -1
- package/packages/daemon/src/validate.js +38 -1
- package/packages/daemon/templates/mlx-setup.json +12 -0
- package/packages/daemon/templates/tgi-setup.json +1 -1
- package/packages/daemon/templates/vllm-setup.json +1 -1
- package/packages/gui/dist/assets/index-BcoF6_eF.js +1012 -0
- package/packages/gui/dist/assets/index-Dd7qhiEd.css +1 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/{node_modules/@groove-dev/gui/src/app.jsx → packages/gui/src/App.jsx} +0 -2
- package/packages/gui/src/app.css +35 -0
- package/packages/gui/src/components/agents/agent-config.jsx +1 -128
- package/packages/gui/src/components/agents/agent-feed.jsx +144 -31
- package/packages/gui/src/components/agents/agent-node.jsx +8 -13
- package/packages/gui/src/components/agents/code-review.jsx +159 -122
- package/packages/gui/src/components/agents/diff-viewer.jsx +23 -23
- package/packages/gui/src/components/agents/journalist-panel.jsx +1 -1
- package/packages/gui/src/components/agents/spawn-wizard.jsx +2 -135
- package/packages/gui/src/components/automations/automation-card.jsx +274 -0
- package/packages/gui/src/components/automations/automation-wizard.jsx +1136 -0
- package/packages/gui/src/components/dashboard/activity-feed.jsx +3 -3
- package/packages/gui/src/components/dashboard/cache-ring.jsx +5 -5
- package/packages/gui/src/components/dashboard/context-gauges.jsx +6 -8
- package/packages/gui/src/components/dashboard/fleet-panel.jsx +8 -14
- package/packages/gui/src/components/dashboard/intel-panel.jsx +238 -656
- package/packages/gui/src/components/dashboard/kpi-card.jsx +3 -3
- package/packages/gui/src/components/dashboard/routing-chart.jsx +3 -3
- package/packages/gui/src/components/dashboard/team-burn-panel.jsx +1 -1
- package/packages/gui/src/components/dashboard/token-chart.jsx +4 -4
- package/packages/gui/src/components/editor/selection-menu.jsx +2 -0
- package/packages/gui/src/components/lab/lab-assistant.jsx +316 -82
- package/packages/gui/src/components/lab/metrics-panel.jsx +187 -32
- package/packages/gui/src/components/lab/parameter-panel.jsx +195 -14
- package/packages/gui/src/components/lab/runtime-config.jsx +286 -102
- package/packages/gui/src/components/layout/activity-bar.jsx +2 -4
- package/packages/gui/src/components/layout/terminal-panel.jsx +4 -2
- package/packages/gui/src/components/layout/welcome-splash.jsx +137 -108
- package/packages/gui/src/components/network/network-health.jsx +2 -2
- package/packages/gui/src/components/network/performance-dashboard.jsx +4 -4
- package/packages/gui/src/components/settings/ssh-wizard.jsx +81 -99
- package/packages/gui/src/components/ui/sheet.jsx +5 -2
- package/packages/gui/src/lib/cron.js +64 -0
- package/packages/gui/src/lib/status.js +24 -24
- package/packages/gui/src/lib/theme-hex.js +1 -0
- package/packages/gui/src/stores/groove.js +34 -3144
- package/packages/gui/src/stores/helpers.js +10 -0
- package/packages/gui/src/stores/slices/agents-slice.js +452 -0
- package/packages/gui/src/stores/slices/automations-slice.js +96 -0
- package/packages/gui/src/stores/slices/chat-slice.js +227 -0
- package/packages/gui/src/stores/slices/editor-slice.js +285 -0
- package/packages/gui/src/stores/slices/marketplace-slice.js +461 -0
- package/packages/gui/src/stores/slices/network-slice.js +361 -0
- package/packages/gui/src/stores/slices/preview-slice.js +109 -0
- package/packages/gui/src/stores/slices/providers-slice.js +897 -0
- package/packages/gui/src/stores/slices/teams-slice.js +413 -0
- package/packages/gui/src/stores/slices/ui-slice.js +98 -0
- package/packages/gui/src/views/agents.jsx +5 -5
- package/packages/gui/src/views/dashboard.jsx +12 -13
- package/packages/gui/src/views/marketplace.jsx +191 -3
- package/packages/gui/src/views/model-lab.jsx +17 -6
- package/packages/gui/src/views/models.jsx +410 -509
- package/packages/gui/src/views/network.jsx +3 -3
- package/packages/gui/src/views/settings.jsx +81 -94
- package/packages/gui/src/views/teams.jsx +40 -483
- package/SECURITY_SWEEP.md +0 -228
- package/TRAINING_DATA_v4.md +0 -6
- package/node_modules/@groove-dev/gui/dist/assets/index-Bjd91ufV.js +0 -984
- package/node_modules/@groove-dev/gui/dist/assets/index-BqdwIFn4.css +0 -1
- package/node_modules/@groove-dev/gui/src/components/agents/agent-chat.jsx +0 -322
- package/node_modules/@groove-dev/gui/src/views/preview.jsx +0 -6
- package/node_modules/@groove-dev/gui/src/views/subscription-panel.jsx +0 -327
- package/packages/gui/dist/assets/index-Bjd91ufV.js +0 -984
- package/packages/gui/dist/assets/index-BqdwIFn4.css +0 -1
- package/packages/gui/src/components/agents/agent-chat.jsx +0 -322
- package/packages/gui/src/views/preview.jsx +0 -6
- package/packages/gui/src/views/subscription-panel.jsx +0 -327
- package/test.py +0 -571
|
@@ -11,15 +11,15 @@ import {
|
|
|
11
11
|
} from 'lucide-react';
|
|
12
12
|
|
|
13
13
|
const STEPS = [
|
|
14
|
-
{ id: 'details', label: 'Server
|
|
15
|
-
{ id: 'auth', label: '
|
|
14
|
+
{ id: 'details', label: 'Server', icon: Server },
|
|
15
|
+
{ id: 'auth', label: 'Auth', icon: KeyRound },
|
|
16
16
|
{ id: 'setup', label: 'Setup', icon: Settings },
|
|
17
17
|
{ id: 'connected', label: 'Connected', icon: Plug },
|
|
18
18
|
];
|
|
19
19
|
|
|
20
20
|
function StepIndicator({ steps, currentStep, completedSteps, onStepClick }) {
|
|
21
21
|
return (
|
|
22
|
-
<div className="flex items-center
|
|
22
|
+
<div className="flex items-center mb-6">
|
|
23
23
|
{steps.map((step, i) => {
|
|
24
24
|
const isActive = currentStep === i;
|
|
25
25
|
const isCompleted = completedSteps.includes(i);
|
|
@@ -27,35 +27,31 @@ function StepIndicator({ steps, currentStep, completedSteps, onStepClick }) {
|
|
|
27
27
|
const Icon = step.icon;
|
|
28
28
|
|
|
29
29
|
return (
|
|
30
|
-
<div key={step.id} className="flex items-center
|
|
30
|
+
<div key={step.id} className="flex items-center flex-1 last:flex-initial">
|
|
31
31
|
<button
|
|
32
32
|
onClick={() => isClickable && onStepClick(i)}
|
|
33
33
|
disabled={!isClickable}
|
|
34
34
|
className={cn(
|
|
35
|
-
'flex items-center gap-
|
|
36
|
-
isActive
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
? 'text-success cursor-pointer hover:bg-surface-3'
|
|
40
|
-
: 'text-text-4',
|
|
35
|
+
'flex items-center gap-2 px-2.5 py-1.5 rounded-lg transition-all text-xs font-sans font-medium',
|
|
36
|
+
isActive && 'bg-accent/10 text-accent',
|
|
37
|
+
isCompleted && 'text-success cursor-pointer hover:bg-surface-3',
|
|
38
|
+
!isActive && !isCompleted && 'text-text-4',
|
|
41
39
|
isClickable && !isActive && 'cursor-pointer',
|
|
42
40
|
)}
|
|
43
41
|
>
|
|
44
42
|
<div className={cn(
|
|
45
|
-
'w-
|
|
46
|
-
isActive
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
? 'border-success/40 bg-success/10 text-success'
|
|
50
|
-
: 'border-border-subtle bg-surface-3 text-text-4',
|
|
43
|
+
'w-7 h-7 rounded-full flex items-center justify-center text-2xs font-bold border-2 transition-all',
|
|
44
|
+
isActive && 'border-accent bg-accent/15 text-accent',
|
|
45
|
+
isCompleted && 'border-success/40 bg-success/10 text-success',
|
|
46
|
+
!isActive && !isCompleted && 'border-border-subtle bg-surface-3 text-text-4',
|
|
51
47
|
)}>
|
|
52
|
-
{isCompleted ? <Check size={
|
|
48
|
+
{isCompleted ? <Check size={11} /> : <Icon size={11} />}
|
|
53
49
|
</div>
|
|
54
50
|
<span className="hidden sm:inline">{step.label}</span>
|
|
55
51
|
</button>
|
|
56
52
|
{i < steps.length - 1 && (
|
|
57
53
|
<div className={cn(
|
|
58
|
-
'flex-1 h-px mx-1',
|
|
54
|
+
'flex-1 h-px mx-1.5',
|
|
59
55
|
isCompleted ? 'bg-success/30' : 'bg-border-subtle',
|
|
60
56
|
)} />
|
|
61
57
|
)}
|
|
@@ -85,14 +81,31 @@ function ToggleSwitch({ value, onChange }) {
|
|
|
85
81
|
|
|
86
82
|
function FieldCard({ icon: Icon, title, children }) {
|
|
87
83
|
return (
|
|
88
|
-
<div className="rounded-
|
|
89
|
-
<div className="flex items-center gap-2">
|
|
90
|
-
<div className="w-
|
|
91
|
-
<Icon size={
|
|
84
|
+
<div className="rounded-xl border border-border-subtle bg-surface-1/80 px-5 py-4 flex flex-col gap-2.5">
|
|
85
|
+
<div className="flex items-center gap-2.5">
|
|
86
|
+
<div className="w-7 h-7 rounded-lg bg-accent/10 border border-accent/10 flex items-center justify-center flex-shrink-0">
|
|
87
|
+
<Icon size={13} className="text-accent" />
|
|
92
88
|
</div>
|
|
93
|
-
<span className="text-
|
|
89
|
+
<span className="text-sm font-semibold text-text-0 font-sans">{title}</span>
|
|
94
90
|
</div>
|
|
95
|
-
<div className="mt-
|
|
91
|
+
<div className="mt-0.5">{children}</div>
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function InfoCard({ icon: Icon, title, iconColor, children }) {
|
|
97
|
+
return (
|
|
98
|
+
<div className="rounded-xl border border-border-subtle bg-surface-1/80 px-5 py-4">
|
|
99
|
+
<div className="flex items-center gap-2.5 mb-3">
|
|
100
|
+
<div className={cn(
|
|
101
|
+
'w-7 h-7 rounded-lg flex items-center justify-center flex-shrink-0',
|
|
102
|
+
iconColor || 'bg-accent/10',
|
|
103
|
+
)}>
|
|
104
|
+
<Icon size={13} className={iconColor ? undefined : 'text-accent'} />
|
|
105
|
+
</div>
|
|
106
|
+
<span className="text-sm font-semibold text-text-0 font-sans">{title}</span>
|
|
107
|
+
</div>
|
|
108
|
+
{children}
|
|
96
109
|
</div>
|
|
97
110
|
);
|
|
98
111
|
}
|
|
@@ -216,11 +229,11 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
216
229
|
setConnecting(false);
|
|
217
230
|
}
|
|
218
231
|
|
|
219
|
-
const inputCls = 'h-
|
|
220
|
-
const monoInputCls = 'h-
|
|
232
|
+
const inputCls = 'h-9 px-3 text-xs bg-surface-0 border border-border-subtle rounded-lg text-text-0 font-sans placeholder:text-text-4 focus:outline-none focus:ring-1 focus:ring-accent/50 focus:border-accent/30 transition-colors';
|
|
233
|
+
const monoInputCls = 'h-9 px-3 text-xs bg-surface-0 border border-border-subtle rounded-lg text-text-0 font-mono placeholder:text-text-4 focus:outline-none focus:ring-1 focus:ring-accent/50 focus:border-accent/30 transition-colors';
|
|
221
234
|
|
|
222
235
|
return (
|
|
223
|
-
<div className="p-
|
|
236
|
+
<div className="p-5">
|
|
224
237
|
<StepIndicator
|
|
225
238
|
steps={STEPS}
|
|
226
239
|
currentStep={step}
|
|
@@ -228,13 +241,12 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
228
241
|
onStepClick={setStep}
|
|
229
242
|
/>
|
|
230
243
|
|
|
231
|
-
{/* Step 0: Server Details */}
|
|
232
244
|
{step === 0 && (
|
|
233
|
-
<div className="grid grid-cols-2 gap-
|
|
245
|
+
<div className="grid grid-cols-2 gap-4">
|
|
234
246
|
<FieldCard icon={Server} title="Server Info">
|
|
235
|
-
<div className="space-y-
|
|
247
|
+
<div className="space-y-3">
|
|
236
248
|
<div>
|
|
237
|
-
<label className="text-2xs font-semibold text-text-2 font-sans mb-1 block">Name</label>
|
|
249
|
+
<label className="text-2xs font-semibold text-text-2 font-sans mb-1.5 block">Name</label>
|
|
238
250
|
<input
|
|
239
251
|
value={name}
|
|
240
252
|
onChange={(e) => setName(e.target.value)}
|
|
@@ -244,7 +256,7 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
244
256
|
/>
|
|
245
257
|
</div>
|
|
246
258
|
<div>
|
|
247
|
-
<label className="text-2xs font-semibold text-text-2 font-sans mb-1 block">Host</label>
|
|
259
|
+
<label className="text-2xs font-semibold text-text-2 font-sans mb-1.5 block">Host</label>
|
|
248
260
|
<input
|
|
249
261
|
value={host}
|
|
250
262
|
onChange={(e) => setHost(e.target.value)}
|
|
@@ -256,9 +268,9 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
256
268
|
</FieldCard>
|
|
257
269
|
|
|
258
270
|
<FieldCard icon={Settings} title="Connection">
|
|
259
|
-
<div className="space-y-
|
|
271
|
+
<div className="space-y-3">
|
|
260
272
|
<div>
|
|
261
|
-
<label className="text-2xs font-semibold text-text-2 font-sans mb-1 block">User</label>
|
|
273
|
+
<label className="text-2xs font-semibold text-text-2 font-sans mb-1.5 block">User</label>
|
|
262
274
|
<input
|
|
263
275
|
value={user}
|
|
264
276
|
onChange={(e) => setUser(e.target.value)}
|
|
@@ -267,7 +279,7 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
267
279
|
/>
|
|
268
280
|
</div>
|
|
269
281
|
<div>
|
|
270
|
-
<label className="text-2xs font-semibold text-text-2 font-sans mb-1 block">SSH Port</label>
|
|
282
|
+
<label className="text-2xs font-semibold text-text-2 font-sans mb-1.5 block">SSH Port</label>
|
|
271
283
|
<input
|
|
272
284
|
value={sshPort}
|
|
273
285
|
onChange={(e) => setSshPort(Number(e.target.value) || 22)}
|
|
@@ -280,13 +292,12 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
280
292
|
</div>
|
|
281
293
|
)}
|
|
282
294
|
|
|
283
|
-
{/* Step 1: Authentication */}
|
|
284
295
|
{step === 1 && (
|
|
285
|
-
<div className="grid grid-cols-2 gap-
|
|
296
|
+
<div className="grid grid-cols-2 gap-4">
|
|
286
297
|
<FieldCard icon={KeyRound} title="SSH Key">
|
|
287
|
-
<div className="space-y-
|
|
298
|
+
<div className="space-y-3">
|
|
288
299
|
<div>
|
|
289
|
-
<label className="text-2xs font-semibold text-text-2 font-sans mb-1 block">Key Path</label>
|
|
300
|
+
<label className="text-2xs font-semibold text-text-2 font-sans mb-1.5 block">Key Path</label>
|
|
290
301
|
<div className="flex items-center gap-1.5">
|
|
291
302
|
<input
|
|
292
303
|
value={sshKeyPath}
|
|
@@ -299,12 +310,12 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
299
310
|
variant="secondary"
|
|
300
311
|
size="sm"
|
|
301
312
|
onClick={() => setKeyBrowserOpen(true)}
|
|
302
|
-
className="h-
|
|
313
|
+
className="h-9 px-2.5 flex-shrink-0"
|
|
303
314
|
>
|
|
304
|
-
<FolderSearch size={
|
|
315
|
+
<FolderSearch size={13} />
|
|
305
316
|
</Button>
|
|
306
317
|
</div>
|
|
307
|
-
<p className="text-2xs text-text-4 font-sans mt-1">
|
|
318
|
+
<p className="text-2xs text-text-4 font-sans mt-1.5">
|
|
308
319
|
Leave blank to use default SSH agent.
|
|
309
320
|
</p>
|
|
310
321
|
</div>
|
|
@@ -313,7 +324,7 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
313
324
|
size="sm"
|
|
314
325
|
onClick={handleTest}
|
|
315
326
|
disabled={testLoading}
|
|
316
|
-
className="h-
|
|
327
|
+
className="h-8 text-2xs gap-1.5"
|
|
317
328
|
>
|
|
318
329
|
{testLoading ? <Loader2 size={11} className="animate-spin" /> : <Plug size={11} />}
|
|
319
330
|
Test Connection
|
|
@@ -321,15 +332,9 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
321
332
|
</div>
|
|
322
333
|
</FieldCard>
|
|
323
334
|
|
|
324
|
-
<div className="space-y-
|
|
325
|
-
<
|
|
326
|
-
<div className="
|
|
327
|
-
<div className="w-6 h-6 rounded bg-accent/8 flex items-center justify-center flex-shrink-0">
|
|
328
|
-
<Server size={12} className="text-accent" />
|
|
329
|
-
</div>
|
|
330
|
-
<span className="text-[13px] font-medium text-text-0 font-sans">Target</span>
|
|
331
|
-
</div>
|
|
332
|
-
<div className="space-y-1.5 text-2xs font-sans">
|
|
335
|
+
<div className="space-y-4">
|
|
336
|
+
<InfoCard icon={Server} title="Target">
|
|
337
|
+
<div className="space-y-2 text-2xs font-sans">
|
|
333
338
|
<div className="flex items-center justify-between">
|
|
334
339
|
<span className="text-text-3">Host</span>
|
|
335
340
|
<span className="text-text-1 font-mono">{host || '—'}</span>
|
|
@@ -343,11 +348,11 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
343
348
|
<span className="text-text-1 font-mono">{sshPort}</span>
|
|
344
349
|
</div>
|
|
345
350
|
</div>
|
|
346
|
-
</
|
|
351
|
+
</InfoCard>
|
|
347
352
|
|
|
348
353
|
{testResult && (
|
|
349
354
|
<div className={cn(
|
|
350
|
-
'px-
|
|
355
|
+
'px-4 py-3 rounded-xl text-2xs font-sans flex items-start gap-2',
|
|
351
356
|
testResult.error
|
|
352
357
|
? 'bg-danger/8 border border-danger/20 text-danger'
|
|
353
358
|
: testResult.reachable
|
|
@@ -375,11 +380,10 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
375
380
|
</div>
|
|
376
381
|
)}
|
|
377
382
|
|
|
378
|
-
{/* Step 2: Setup */}
|
|
379
383
|
{step === 2 && (
|
|
380
|
-
<div className="grid grid-cols-2 gap-
|
|
384
|
+
<div className="grid grid-cols-2 gap-4">
|
|
381
385
|
<FieldCard icon={Settings} title="Behavior">
|
|
382
|
-
<div className="space-y-
|
|
386
|
+
<div className="space-y-4">
|
|
383
387
|
<label className="flex items-center justify-between cursor-pointer">
|
|
384
388
|
<div>
|
|
385
389
|
<span className="text-xs text-text-1 font-sans block">Auto-start daemon</span>
|
|
@@ -397,15 +401,9 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
397
401
|
</div>
|
|
398
402
|
</FieldCard>
|
|
399
403
|
|
|
400
|
-
{testResult && !testResult.error
|
|
401
|
-
<
|
|
402
|
-
<div className="
|
|
403
|
-
<div className="w-6 h-6 rounded bg-success/10 flex items-center justify-center flex-shrink-0">
|
|
404
|
-
<Check size={12} className="text-success" />
|
|
405
|
-
</div>
|
|
406
|
-
<span className="text-[13px] font-medium text-text-0 font-sans">Test Results</span>
|
|
407
|
-
</div>
|
|
408
|
-
<div className="space-y-2">
|
|
404
|
+
{testResult && !testResult.error ? (
|
|
405
|
+
<InfoCard icon={Check} title="Test Results" iconColor="bg-success/10 text-success">
|
|
406
|
+
<div className="space-y-2.5">
|
|
409
407
|
<div className="flex items-center gap-2 text-2xs font-sans">
|
|
410
408
|
<StatusDot status={testResult.reachable ? 'running' : 'crashed'} size="sm" />
|
|
411
409
|
<span className="text-text-1">Reachable</span>
|
|
@@ -419,18 +417,10 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
419
417
|
<span className="text-text-1">Daemon Running</span>
|
|
420
418
|
</div>
|
|
421
419
|
</div>
|
|
422
|
-
</
|
|
423
|
-
)
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
<div className="rounded-lg border border-border-subtle bg-surface-1 px-4 py-3.5">
|
|
427
|
-
<div className="flex items-center gap-2 mb-2">
|
|
428
|
-
<div className="w-6 h-6 rounded bg-accent/8 flex items-center justify-center flex-shrink-0">
|
|
429
|
-
<Server size={12} className="text-accent" />
|
|
430
|
-
</div>
|
|
431
|
-
<span className="text-[13px] font-medium text-text-0 font-sans">{name || 'Server'}</span>
|
|
432
|
-
</div>
|
|
433
|
-
<div className="space-y-1.5 text-2xs font-sans">
|
|
420
|
+
</InfoCard>
|
|
421
|
+
) : (
|
|
422
|
+
<InfoCard icon={Server} title={name || 'Server'}>
|
|
423
|
+
<div className="space-y-2 text-2xs font-sans">
|
|
434
424
|
<div className="flex items-center justify-between">
|
|
435
425
|
<span className="text-text-3">Connection</span>
|
|
436
426
|
<span className="text-text-1 font-mono">{user}@{host}:{sshPort}</span>
|
|
@@ -442,21 +432,20 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
442
432
|
</div>
|
|
443
433
|
)}
|
|
444
434
|
</div>
|
|
445
|
-
</
|
|
435
|
+
</InfoCard>
|
|
446
436
|
)}
|
|
447
437
|
</div>
|
|
448
438
|
)}
|
|
449
439
|
|
|
450
|
-
{/* Step 3: Connected */}
|
|
451
440
|
{step === 3 && (
|
|
452
|
-
<div className="grid grid-cols-2 gap-
|
|
453
|
-
<div className="rounded-
|
|
454
|
-
<div className="w-
|
|
455
|
-
<Check size={
|
|
441
|
+
<div className="grid grid-cols-2 gap-4">
|
|
442
|
+
<div className="rounded-xl border border-success/25 bg-gradient-to-br from-success/[0.06] to-transparent px-5 py-6 text-center">
|
|
443
|
+
<div className="w-12 h-12 rounded-full bg-success/15 border border-success/20 flex items-center justify-center mx-auto mb-3">
|
|
444
|
+
<Check size={22} className="text-success" />
|
|
456
445
|
</div>
|
|
457
|
-
<h3 className="text-
|
|
458
|
-
<p className="text-
|
|
459
|
-
Successfully connected to <span className="font-mono text-text-1">{name}</span>
|
|
446
|
+
<h3 className="text-base font-semibold text-text-0 font-sans mb-1">Connected</h3>
|
|
447
|
+
<p className="text-xs text-text-3 font-sans mb-4">
|
|
448
|
+
Successfully connected to <span className="font-mono text-text-1 font-medium">{name}</span>
|
|
460
449
|
</p>
|
|
461
450
|
<Button
|
|
462
451
|
variant="primary"
|
|
@@ -466,21 +455,15 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
466
455
|
const n = encodeURIComponent(name);
|
|
467
456
|
window.open(`http://localhost:${port}?instance=${n}`, '_blank');
|
|
468
457
|
}}
|
|
469
|
-
className="h-8 text-xs gap-1.5
|
|
458
|
+
className="h-8 text-xs gap-1.5"
|
|
470
459
|
>
|
|
471
460
|
<ExternalLink size={12} />
|
|
472
461
|
Open Remote GUI
|
|
473
462
|
</Button>
|
|
474
463
|
</div>
|
|
475
464
|
|
|
476
|
-
<
|
|
477
|
-
<div className="
|
|
478
|
-
<div className="w-6 h-6 rounded bg-accent/8 flex items-center justify-center flex-shrink-0">
|
|
479
|
-
<Server size={12} className="text-accent" />
|
|
480
|
-
</div>
|
|
481
|
-
<span className="text-[13px] font-medium text-text-0 font-sans">Connection Info</span>
|
|
482
|
-
</div>
|
|
483
|
-
<div className="space-y-1.5 text-2xs font-sans">
|
|
465
|
+
<InfoCard icon={Server} title="Connection Info">
|
|
466
|
+
<div className="space-y-2 text-2xs font-sans">
|
|
484
467
|
<div className="flex items-center justify-between">
|
|
485
468
|
<span className="text-text-3">Connection</span>
|
|
486
469
|
<span className="text-text-1 font-mono">{user}@{host}:{sshPort}</span>
|
|
@@ -509,12 +492,11 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
509
492
|
</div>
|
|
510
493
|
)}
|
|
511
494
|
</div>
|
|
512
|
-
</
|
|
495
|
+
</InfoCard>
|
|
513
496
|
</div>
|
|
514
497
|
)}
|
|
515
498
|
|
|
516
|
-
|
|
517
|
-
<div className="flex items-center justify-between mt-4">
|
|
499
|
+
<div className="flex items-center justify-between mt-5">
|
|
518
500
|
<Button
|
|
519
501
|
variant="ghost"
|
|
520
502
|
size="sm"
|
|
@@ -9,7 +9,7 @@ export function Sheet({ children, ...props }) {
|
|
|
9
9
|
|
|
10
10
|
export const SheetTrigger = DialogPrimitive.Trigger;
|
|
11
11
|
|
|
12
|
-
export function SheetContent({ children, className, title, side = 'right', width = 400, ...props }) {
|
|
12
|
+
export function SheetContent({ children, className, title, side = 'right', width = 400, onClose, ...props }) {
|
|
13
13
|
return (
|
|
14
14
|
<DialogPrimitive.Portal>
|
|
15
15
|
<DialogPrimitive.Overlay className="fixed inset-0 z-40 bg-black/30" />
|
|
@@ -30,7 +30,10 @@ export function SheetContent({ children, className, title, side = 'right', width
|
|
|
30
30
|
<DialogPrimitive.Title className="text-base font-semibold text-text-0 font-sans">
|
|
31
31
|
{title}
|
|
32
32
|
</DialogPrimitive.Title>
|
|
33
|
-
<DialogPrimitive.Close
|
|
33
|
+
<DialogPrimitive.Close
|
|
34
|
+
onClick={onClose}
|
|
35
|
+
className="p-1 rounded-md text-text-3 hover:text-text-0 hover:bg-surface-5 transition-colors cursor-pointer"
|
|
36
|
+
>
|
|
34
37
|
<X size={16} />
|
|
35
38
|
</DialogPrimitive.Close>
|
|
36
39
|
</div>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// FSL-1.1-Apache-2.0 — see LICENSE
|
|
2
|
+
|
|
3
|
+
export const CRON_PRESETS = [
|
|
4
|
+
{ label: 'Every hour', cron: '0 * * * *', description: 'Runs at the start of every hour' },
|
|
5
|
+
{ label: 'Every morning', cron: '0 9 * * *', description: 'Daily at 9:00 AM' },
|
|
6
|
+
{ label: 'Twice daily', cron: '0 9,17 * * *', description: '9:00 AM and 5:00 PM' },
|
|
7
|
+
{ label: 'Every weekday', cron: '0 9 * * 1-5', description: 'Monday-Friday at 9:00 AM' },
|
|
8
|
+
{ label: 'Mon & Thu', cron: '0 9 * * 1,4', description: 'Monday and Thursday at 9:00 AM' },
|
|
9
|
+
{ label: 'Weekly', cron: '0 9 * * 1', description: 'Every Monday at 9:00 AM' },
|
|
10
|
+
{ label: 'Monthly', cron: '0 9 1 * *', description: '1st of each month at 9:00 AM' },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const presetMap = new Map(CRON_PRESETS.map((p) => [p.cron, p.description]));
|
|
14
|
+
|
|
15
|
+
export function cronToHuman(expr) {
|
|
16
|
+
if (!expr) return '';
|
|
17
|
+
const trimmed = expr.trim();
|
|
18
|
+
const match = presetMap.get(trimmed);
|
|
19
|
+
if (match) return match;
|
|
20
|
+
return trimmed;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const FIELD_RANGES = [
|
|
24
|
+
{ name: 'minute', min: 0, max: 59 },
|
|
25
|
+
{ name: 'hour', min: 0, max: 23 },
|
|
26
|
+
{ name: 'day of month', min: 1, max: 31 },
|
|
27
|
+
{ name: 'month', min: 1, max: 12 },
|
|
28
|
+
{ name: 'day of week', min: 0, max: 7 },
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
function validateField(value, range) {
|
|
32
|
+
if (value === '*') return null;
|
|
33
|
+
if (/^\*\/\d+$/.test(value)) {
|
|
34
|
+
const step = parseInt(value.slice(2), 10);
|
|
35
|
+
if (step < 1 || step > range.max) return `Invalid step ${step} for ${range.name}`;
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const parts = value.split(',');
|
|
39
|
+
for (const part of parts) {
|
|
40
|
+
if (part.includes('-')) {
|
|
41
|
+
const [lo, hi] = part.split('-').map(Number);
|
|
42
|
+
if (isNaN(lo) || isNaN(hi) || lo < range.min || hi > range.max || lo > hi) {
|
|
43
|
+
return `Invalid range ${part} for ${range.name} (${range.min}-${range.max})`;
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
const n = Number(part);
|
|
47
|
+
if (isNaN(n) || n < range.min || n > range.max) {
|
|
48
|
+
return `Invalid value ${part} for ${range.name} (${range.min}-${range.max})`;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function validateCron(expr) {
|
|
56
|
+
if (!expr || typeof expr !== 'string') return { valid: false, error: 'Expression is required' };
|
|
57
|
+
const fields = expr.trim().split(/\s+/);
|
|
58
|
+
if (fields.length !== 5) return { valid: false, error: `Expected 5 fields, got ${fields.length}` };
|
|
59
|
+
for (let i = 0; i < 5; i++) {
|
|
60
|
+
const err = validateField(fields[i], FIELD_RANGES[i]);
|
|
61
|
+
if (err) return { valid: false, error: err };
|
|
62
|
+
}
|
|
63
|
+
return { valid: true };
|
|
64
|
+
}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// Single source of truth for agent status colors + role colors
|
|
3
3
|
|
|
4
4
|
export const STATUS_COLORS = {
|
|
5
|
-
running: 'var(--color-
|
|
6
|
-
starting: 'var(--color-
|
|
5
|
+
running: 'var(--color-accent)',
|
|
6
|
+
starting: 'var(--color-text-3)',
|
|
7
7
|
stopped: 'var(--color-text-3)',
|
|
8
8
|
crashed: 'var(--color-danger)',
|
|
9
9
|
completed: 'var(--color-accent)',
|
|
10
10
|
killed: 'var(--color-text-3)',
|
|
11
|
-
rotating: 'var(--color-
|
|
11
|
+
rotating: 'var(--color-accent)',
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export const STATUS_LABELS = {
|
|
@@ -25,24 +25,26 @@ export function statusColor(status) {
|
|
|
25
25
|
return STATUS_COLORS[status] || 'var(--color-text-3)';
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
const NEUTRAL_ROLE = { bg: 'rgba(139,146,158,0.08)', text: '#8b929e', border: '#8b929e' };
|
|
29
|
+
|
|
28
30
|
export const ROLE_COLORS = {
|
|
29
|
-
planner:
|
|
30
|
-
backend:
|
|
31
|
-
frontend:
|
|
32
|
-
fullstack:
|
|
33
|
-
testing:
|
|
34
|
-
devops:
|
|
35
|
-
docs:
|
|
36
|
-
security:
|
|
37
|
-
database:
|
|
38
|
-
cmo:
|
|
39
|
-
cfo:
|
|
40
|
-
ea:
|
|
41
|
-
support:
|
|
42
|
-
analyst:
|
|
43
|
-
creative:
|
|
44
|
-
slides:
|
|
45
|
-
chat:
|
|
31
|
+
planner: NEUTRAL_ROLE,
|
|
32
|
+
backend: NEUTRAL_ROLE,
|
|
33
|
+
frontend: NEUTRAL_ROLE,
|
|
34
|
+
fullstack: NEUTRAL_ROLE,
|
|
35
|
+
testing: NEUTRAL_ROLE,
|
|
36
|
+
devops: NEUTRAL_ROLE,
|
|
37
|
+
docs: NEUTRAL_ROLE,
|
|
38
|
+
security: NEUTRAL_ROLE,
|
|
39
|
+
database: NEUTRAL_ROLE,
|
|
40
|
+
cmo: NEUTRAL_ROLE,
|
|
41
|
+
cfo: NEUTRAL_ROLE,
|
|
42
|
+
ea: NEUTRAL_ROLE,
|
|
43
|
+
support: NEUTRAL_ROLE,
|
|
44
|
+
analyst: NEUTRAL_ROLE,
|
|
45
|
+
creative: NEUTRAL_ROLE,
|
|
46
|
+
slides: NEUTRAL_ROLE,
|
|
47
|
+
chat: NEUTRAL_ROLE,
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
export function roleColor(role) {
|
|
@@ -50,8 +52,6 @@ export function roleColor(role) {
|
|
|
50
52
|
return ROLE_COLORS[lower] || { bg: 'rgba(139, 146, 158, 0.12)', text: '#8b929e', border: '#8b929e' };
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
export function contextColor(
|
|
54
|
-
|
|
55
|
-
if (pct >= 60) return 'var(--color-warning)';
|
|
56
|
-
return 'var(--color-success)';
|
|
55
|
+
export function contextColor() {
|
|
56
|
+
return 'var(--color-accent)';
|
|
57
57
|
}
|