groove-dev 0.27.113 → 0.27.115
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/CENTRAL_COMMAND_REBUILD.md +689 -0
- package/EMBEDDING_DIAGNOSTIC.md +197 -0
- package/TRAINING_DATA_v4.md +3 -0
- package/node_modules/@groove-dev/cli/package.json +1 -1
- package/node_modules/@groove-dev/cli/src/commands/team.js +43 -1
- package/node_modules/@groove-dev/daemon/package.json +1 -1
- package/node_modules/@groove-dev/daemon/src/api.js +24 -0
- package/node_modules/@groove-dev/daemon/src/filewatcher.js +45 -0
- package/node_modules/@groove-dev/daemon/src/index.js +14 -2
- package/node_modules/@groove-dev/daemon/src/teams.js +100 -6
- package/node_modules/@groove-dev/daemon/src/tunnel-manager.js +75 -43
- package/node_modules/@groove-dev/gui/dist/assets/{index-BYh6iHqL.js → index-BKCiOUDb.js} +593 -593
- package/node_modules/@groove-dev/gui/dist/assets/index-D4Q72afD.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/node_modules/@groove-dev/gui/src/components/agents/workspace-mode.jsx +0 -22
- package/node_modules/@groove-dev/gui/src/components/layout/status-bar.jsx +43 -45
- package/node_modules/@groove-dev/gui/src/components/settings/quick-connect.jsx +2 -1
- package/node_modules/@groove-dev/gui/src/stores/groove.js +42 -8
- package/node_modules/@groove-dev/gui/src/views/agents.jsx +31 -3
- package/node_modules/@groove-dev/gui/src/views/editor.jsx +1 -20
- package/node_modules/@groove-dev/gui/src/views/teams.jsx +106 -3
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/commands/team.js +43 -1
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/api.js +24 -0
- package/packages/daemon/src/filewatcher.js +45 -0
- package/packages/daemon/src/index.js +14 -2
- package/packages/daemon/src/teams.js +100 -6
- package/packages/daemon/src/tunnel-manager.js +75 -43
- package/packages/gui/dist/assets/{index-BYh6iHqL.js → index-BKCiOUDb.js} +593 -593
- package/packages/gui/dist/assets/index-D4Q72afD.css +1 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/packages/gui/src/components/agents/workspace-mode.jsx +0 -22
- package/packages/gui/src/components/layout/status-bar.jsx +43 -45
- package/packages/gui/src/components/settings/quick-connect.jsx +2 -1
- package/packages/gui/src/stores/groove.js +42 -8
- package/packages/gui/src/views/agents.jsx +31 -3
- package/packages/gui/src/views/editor.jsx +1 -20
- package/packages/gui/src/views/teams.jsx +106 -3
- package/TRAINING_DATA_v3.md +0 -11
- package/codex-test/offroad-nitro-racer/dist/assets/index-CuvdKK6U.js +0 -44
- package/codex-test/offroad-nitro-racer/dist/assets/index-DvHn2Thu.css +0 -1
- package/codex-test/offroad-nitro-racer/dist/index.html +0 -23
- package/codex-test/offroad-nitro-racer/index.html +0 -21
- package/codex-test/offroad-nitro-racer/package-lock.json +0 -841
- package/codex-test/offroad-nitro-racer/package.json +0 -15
- package/codex-test/offroad-nitro-racer/src/game/AI.ts +0 -28
- package/codex-test/offroad-nitro-racer/src/game/Audio.ts +0 -63
- package/codex-test/offroad-nitro-racer/src/game/Car.ts +0 -247
- package/codex-test/offroad-nitro-racer/src/game/Effects.ts +0 -62
- package/codex-test/offroad-nitro-racer/src/game/Game.ts +0 -229
- package/codex-test/offroad-nitro-racer/src/game/Input.ts +0 -45
- package/codex-test/offroad-nitro-racer/src/game/Renderer.ts +0 -224
- package/codex-test/offroad-nitro-racer/src/game/Track.ts +0 -158
- package/codex-test/offroad-nitro-racer/src/game/UI.ts +0 -96
- package/codex-test/offroad-nitro-racer/src/game/math.ts +0 -42
- package/codex-test/offroad-nitro-racer/src/main.ts +0 -24
- package/codex-test/offroad-nitro-racer/src/style.css +0 -291
- package/codex-test/offroad-nitro-racer/src/vite-env.d.ts +0 -1
- package/codex-test/offroad-nitro-racer/tsconfig.json +0 -18
- package/codex-test/offroad-nitro-racer/vite.config.ts +0 -7
- package/node_modules/@groove-dev/gui/dist/assets/index-DAlSbVyK.css +0 -1
- package/packages/gui/dist/assets/index-DAlSbVyK.css +0 -1
|
@@ -10,7 +10,7 @@ import { RootNode } from '../components/agents/root-node';
|
|
|
10
10
|
import { cn } from '../lib/cn';
|
|
11
11
|
import { Button } from '../components/ui/button';
|
|
12
12
|
import { Badge } from '../components/ui/badge';
|
|
13
|
-
import { Plus, Users, UserPlus, Zap, X, Check, Rocket, Server, Monitor, Code2, TestTube, Shield, Pencil, Copy, Trash2, ChevronDown, ChevronLeft, ChevronRight, FolderOpen, Eye, Settings2, Search, GripVertical, Cloud, FileText, Database, Megaphone, Calculator, UserCheck, Headphones, BarChart3, Pen, Presentation, Globe, MessageCircle, Save, Layers } from 'lucide-react';
|
|
13
|
+
import { Plus, Users, UserPlus, Zap, X, Check, Rocket, Server, Monitor, Code2, TestTube, Shield, Pencil, Copy, Trash2, ChevronDown, ChevronLeft, ChevronRight, FolderOpen, Eye, Settings2, Search, GripVertical, Cloud, FileText, Database, Megaphone, Calculator, UserCheck, Headphones, BarChart3, Pen, Presentation, Globe, MessageCircle, Save, Layers, Archive } from 'lucide-react';
|
|
14
14
|
import { PreviewWorkspace } from '../components/preview/preview-workspace';
|
|
15
15
|
import { WorkspaceMode } from '../components/agents/workspace-mode';
|
|
16
16
|
import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuSeparator } from '../components/ui/context-menu';
|
|
@@ -88,11 +88,13 @@ export function TeamTabBar() {
|
|
|
88
88
|
const renameTeam = useGrooveStore((s) => s.renameTeam);
|
|
89
89
|
const cloneTeam = useGrooveStore((s) => s.cloneTeam);
|
|
90
90
|
const reorderTeams = useGrooveStore((s) => s.reorderTeams);
|
|
91
|
+
const addToast = useGrooveStore((s) => s.addToast);
|
|
91
92
|
|
|
92
93
|
const [creating, setCreating] = useState(false);
|
|
93
94
|
const [newName, setNewName] = useState('');
|
|
94
95
|
const [renamingId, setRenamingId] = useState(null);
|
|
95
96
|
const [renameValue, setRenameValue] = useState('');
|
|
97
|
+
const [archiveConfirm, setArchiveConfirm] = useState(null);
|
|
96
98
|
const submitting = useRef(false);
|
|
97
99
|
const [dragId, setDragId] = useState(null);
|
|
98
100
|
const [dragOverId, setDragOverId] = useState(null);
|
|
@@ -247,8 +249,15 @@ export function TeamTabBar() {
|
|
|
247
249
|
<Copy size={12} /> Clone
|
|
248
250
|
</ContextMenuItem>
|
|
249
251
|
<ContextMenuSeparator />
|
|
250
|
-
<ContextMenuItem danger onSelect={() =>
|
|
251
|
-
|
|
252
|
+
<ContextMenuItem danger onSelect={() => {
|
|
253
|
+
const teamAgents = agents.filter((a) => a.teamId === team.id);
|
|
254
|
+
if (teamAgents.some((a) => a.status === 'running' || a.status === 'starting')) {
|
|
255
|
+
addToast('error', 'Stop running agents first');
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
setArchiveConfirm(team);
|
|
259
|
+
}}>
|
|
260
|
+
<Trash2 size={12} /> {team.isDefault ? 'Wipe' : 'Archive'}
|
|
252
261
|
</ContextMenuItem>
|
|
253
262
|
</ContextMenuContent>
|
|
254
263
|
</ContextMenu>
|
|
@@ -295,6 +304,25 @@ export function TeamTabBar() {
|
|
|
295
304
|
<ChevronRight size={14} />
|
|
296
305
|
</button>
|
|
297
306
|
)}
|
|
307
|
+
|
|
308
|
+
<Dialog open={!!archiveConfirm} onOpenChange={(open) => !open && setArchiveConfirm(null)}>
|
|
309
|
+
<DialogContent title="Archive Team" description="Confirm team archival">
|
|
310
|
+
<div className="px-5 py-4 space-y-3">
|
|
311
|
+
<p className="text-sm text-text-1 font-sans">
|
|
312
|
+
This will archive <span className="font-semibold text-text-0">{archiveConfirm?.name}</span>.
|
|
313
|
+
</p>
|
|
314
|
+
<p className="text-xs text-text-2 font-sans">
|
|
315
|
+
All files will be preserved and can be restored later from the Archived Teams section.
|
|
316
|
+
</p>
|
|
317
|
+
</div>
|
|
318
|
+
<div className="px-5 py-4 border-t border-border-subtle flex justify-end gap-2">
|
|
319
|
+
<Button variant="ghost" size="sm" onClick={() => setArchiveConfirm(null)}>Cancel</Button>
|
|
320
|
+
<Button variant="danger" size="sm" onClick={() => { deleteTeam(archiveConfirm.id); setArchiveConfirm(null); }}>
|
|
321
|
+
<Archive size={12} /> Archive
|
|
322
|
+
</Button>
|
|
323
|
+
</div>
|
|
324
|
+
</DialogContent>
|
|
325
|
+
</Dialog>
|
|
298
326
|
</div>
|
|
299
327
|
);
|
|
300
328
|
}
|
|
@@ -8,8 +8,7 @@ import { MediaViewer, isMediaFile } from '../components/editor/media-viewer';
|
|
|
8
8
|
import { EditorStatusBar } from '../components/editor/editor-status-bar';
|
|
9
9
|
import { GotoLine } from '../components/editor/goto-line';
|
|
10
10
|
import { Breadcrumbs } from '../components/editor/breadcrumbs';
|
|
11
|
-
import { Code2,
|
|
12
|
-
import { Button } from '../components/ui/button';
|
|
11
|
+
import { Code2, Eye, FileCode, PanelLeftOpen } from 'lucide-react';
|
|
13
12
|
import { api } from '../lib/api';
|
|
14
13
|
import { cn } from '../lib/cn';
|
|
15
14
|
|
|
@@ -25,11 +24,8 @@ const SIDEBAR_MAX = 400;
|
|
|
25
24
|
export default function EditorView() {
|
|
26
25
|
const activeFile = useGrooveStore((s) => s.editorActiveFile);
|
|
27
26
|
const files = useGrooveStore((s) => s.editorFiles);
|
|
28
|
-
const changedFiles = useGrooveStore((s) => s.editorChangedFiles);
|
|
29
27
|
const updateFileContent = useGrooveStore((s) => s.updateFileContent);
|
|
30
28
|
const saveFile = useGrooveStore((s) => s.saveFile);
|
|
31
|
-
const reloadFile = useGrooveStore((s) => s.reloadFile);
|
|
32
|
-
const dismissFileChange = useGrooveStore((s) => s.dismissFileChange);
|
|
33
29
|
const sidebarWidth = useGrooveStore((s) => s.editorSidebarWidth);
|
|
34
30
|
const setSidebarWidth = useGrooveStore((s) => s.setEditorSidebarWidth);
|
|
35
31
|
|
|
@@ -104,7 +100,6 @@ export default function EditorView() {
|
|
|
104
100
|
const file = activeFile ? files[activeFile] : null;
|
|
105
101
|
const isMedia = activeFile && isMediaFile(activeFile);
|
|
106
102
|
const isHtml = activeFile && isHtmlFile(activeFile);
|
|
107
|
-
const hasExternalChange = activeFile && changedFiles[activeFile];
|
|
108
103
|
|
|
109
104
|
return (
|
|
110
105
|
<div className="flex h-full">
|
|
@@ -151,20 +146,6 @@ export default function EditorView() {
|
|
|
151
146
|
/>
|
|
152
147
|
)}
|
|
153
148
|
|
|
154
|
-
{/* External change banner */}
|
|
155
|
-
{hasExternalChange && (
|
|
156
|
-
<div className="absolute top-0 left-0 right-0 z-10 flex items-center gap-2 px-4 py-2 bg-warning/10 border-b border-warning/20">
|
|
157
|
-
<AlertTriangle size={14} className="text-warning" />
|
|
158
|
-
<span className="text-xs text-warning font-sans flex-1">File modified externally</span>
|
|
159
|
-
<Button variant="ghost" size="sm" onClick={() => reloadFile(activeFile)}>
|
|
160
|
-
<RefreshCw size={12} /> Reload
|
|
161
|
-
</Button>
|
|
162
|
-
<Button variant="ghost" size="sm" onClick={() => dismissFileChange(activeFile)}>
|
|
163
|
-
<X size={12} /> Dismiss
|
|
164
|
-
</Button>
|
|
165
|
-
</div>
|
|
166
|
-
)}
|
|
167
|
-
|
|
168
149
|
{/* Editor / Media / Empty */}
|
|
169
150
|
{!activeFile && (
|
|
170
151
|
<div className="w-full h-full flex items-center justify-center text-text-4 font-sans">
|
|
@@ -5,6 +5,7 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from '../components/ui/tabs'
|
|
|
5
5
|
import { Button } from '../components/ui/button';
|
|
6
6
|
import { Badge } from '../components/ui/badge';
|
|
7
7
|
import { StatusDot } from '../components/ui/status-dot';
|
|
8
|
+
import { Dialog, DialogContent } from '../components/ui/dialog';
|
|
8
9
|
import { api } from '../lib/api';
|
|
9
10
|
import { useToast } from '../lib/hooks/use-toast';
|
|
10
11
|
import { fmtNum, fmtDollar, timeAgo, fmtUptime } from '../lib/format';
|
|
@@ -12,6 +13,7 @@ import { cn } from '../lib/cn';
|
|
|
12
13
|
import {
|
|
13
14
|
Clock, CheckCircle, XCircle, AlertTriangle, ShieldCheck, ShieldX,
|
|
14
15
|
Users, Folder, Cpu, Trash2, Play, Pause, LayoutDashboard, ListChecks, Calendar,
|
|
16
|
+
Archive, RotateCcw, ChevronRight,
|
|
15
17
|
} from 'lucide-react';
|
|
16
18
|
|
|
17
19
|
// ── Team Dashboard ────────────────────────────────────────────
|
|
@@ -21,8 +23,18 @@ function TeamsDashboard() {
|
|
|
21
23
|
const activeTeamId = useGrooveStore((s) => s.activeTeamId);
|
|
22
24
|
const deleteTeam = useGrooveStore((s) => s.deleteTeam);
|
|
23
25
|
const addToast = useGrooveStore((s) => s.addToast);
|
|
26
|
+
const archivedTeams = useGrooveStore((s) => s.archivedTeams);
|
|
27
|
+
const fetchArchivedTeams = useGrooveStore((s) => s.fetchArchivedTeams);
|
|
28
|
+
const restoreTeam = useGrooveStore((s) => s.restoreTeam);
|
|
29
|
+
const purgeTeam = useGrooveStore((s) => s.purgeTeam);
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
const [archiveConfirm, setArchiveConfirm] = useState(null);
|
|
32
|
+
const [purgeConfirm, setPurgeConfirm] = useState(null);
|
|
33
|
+
const [archivedOpen, setArchivedOpen] = useState(false);
|
|
34
|
+
|
|
35
|
+
useEffect(() => { fetchArchivedTeams(); }, []);
|
|
36
|
+
|
|
37
|
+
if (teams.length === 0 && archivedTeams.length === 0) {
|
|
26
38
|
return (
|
|
27
39
|
<div className="flex-1 flex items-center justify-center">
|
|
28
40
|
<div className="text-center space-y-2">
|
|
@@ -74,10 +86,10 @@ function TeamsDashboard() {
|
|
|
74
86
|
addToast('error', 'Stop running agents first');
|
|
75
87
|
return;
|
|
76
88
|
}
|
|
77
|
-
|
|
89
|
+
setArchiveConfirm(team);
|
|
78
90
|
}}
|
|
79
91
|
className="p-1.5 text-text-4 hover:text-danger rounded transition-colors cursor-pointer"
|
|
80
|
-
title="
|
|
92
|
+
title="Archive team"
|
|
81
93
|
>
|
|
82
94
|
<Trash2 size={13} />
|
|
83
95
|
</button>
|
|
@@ -112,6 +124,97 @@ function TeamsDashboard() {
|
|
|
112
124
|
);
|
|
113
125
|
})}
|
|
114
126
|
</div>
|
|
127
|
+
|
|
128
|
+
{/* Archived Teams */}
|
|
129
|
+
{archivedTeams.length > 0 && (
|
|
130
|
+
<div className="border-t border-border-subtle">
|
|
131
|
+
<button
|
|
132
|
+
onClick={() => setArchivedOpen(!archivedOpen)}
|
|
133
|
+
className="w-full flex items-center gap-2 px-5 py-3 text-left cursor-pointer hover:bg-surface-5/30 transition-colors"
|
|
134
|
+
>
|
|
135
|
+
<ChevronRight
|
|
136
|
+
size={12}
|
|
137
|
+
className={cn('text-text-4 transition-transform duration-200', archivedOpen && 'rotate-90')}
|
|
138
|
+
/>
|
|
139
|
+
<Archive size={13} className="text-text-3" />
|
|
140
|
+
<span className="text-xs font-semibold text-text-2 font-sans uppercase tracking-wider flex-1">
|
|
141
|
+
Archived Teams
|
|
142
|
+
</span>
|
|
143
|
+
<span className="text-2xs font-mono text-text-4 bg-surface-4 px-1.5 py-0.5 rounded">
|
|
144
|
+
{archivedTeams.length}
|
|
145
|
+
</span>
|
|
146
|
+
</button>
|
|
147
|
+
{archivedOpen && (
|
|
148
|
+
<div className="px-4 pb-4 space-y-2">
|
|
149
|
+
{archivedTeams.map((at) => (
|
|
150
|
+
<div key={at.id} className="flex items-center gap-3 px-3 py-2.5 rounded-md bg-surface-0 border border-border-subtle">
|
|
151
|
+
<Archive size={13} className="text-text-4 flex-shrink-0" />
|
|
152
|
+
<div className="flex-1 min-w-0">
|
|
153
|
+
<span className="text-xs font-semibold text-text-1 font-sans">{at.originalName || at.name}</span>
|
|
154
|
+
{(at.deletedAt || at.archivedAt) && (
|
|
155
|
+
<div className="text-2xs text-text-4 font-mono mt-0.5">Archived {timeAgo(at.deletedAt || at.archivedAt)}</div>
|
|
156
|
+
)}
|
|
157
|
+
</div>
|
|
158
|
+
<button
|
|
159
|
+
onClick={() => restoreTeam(at.id)}
|
|
160
|
+
className="p-1.5 text-text-3 hover:text-accent rounded transition-colors cursor-pointer"
|
|
161
|
+
title="Restore team"
|
|
162
|
+
>
|
|
163
|
+
<RotateCcw size={13} />
|
|
164
|
+
</button>
|
|
165
|
+
<button
|
|
166
|
+
onClick={() => setPurgeConfirm(at)}
|
|
167
|
+
className="p-1.5 text-text-4 hover:text-danger rounded transition-colors cursor-pointer"
|
|
168
|
+
title="Permanently delete"
|
|
169
|
+
>
|
|
170
|
+
<Trash2 size={13} />
|
|
171
|
+
</button>
|
|
172
|
+
</div>
|
|
173
|
+
))}
|
|
174
|
+
</div>
|
|
175
|
+
)}
|
|
176
|
+
</div>
|
|
177
|
+
)}
|
|
178
|
+
|
|
179
|
+
{/* Archive confirmation dialog */}
|
|
180
|
+
<Dialog open={!!archiveConfirm} onOpenChange={(open) => !open && setArchiveConfirm(null)}>
|
|
181
|
+
<DialogContent title="Archive Team" description="Confirm team archival">
|
|
182
|
+
<div className="px-5 py-4 space-y-3">
|
|
183
|
+
<p className="text-sm text-text-1 font-sans">
|
|
184
|
+
This will archive <span className="font-semibold text-text-0">{archiveConfirm?.name}</span>.
|
|
185
|
+
</p>
|
|
186
|
+
<p className="text-xs text-text-2 font-sans">
|
|
187
|
+
All files will be preserved and can be restored later from the Archived Teams section.
|
|
188
|
+
</p>
|
|
189
|
+
</div>
|
|
190
|
+
<div className="px-5 py-4 border-t border-border-subtle flex justify-end gap-2">
|
|
191
|
+
<Button variant="ghost" size="sm" onClick={() => setArchiveConfirm(null)}>Cancel</Button>
|
|
192
|
+
<Button variant="danger" size="sm" onClick={() => { deleteTeam(archiveConfirm.id); setArchiveConfirm(null); }}>
|
|
193
|
+
<Archive size={12} /> Archive
|
|
194
|
+
</Button>
|
|
195
|
+
</div>
|
|
196
|
+
</DialogContent>
|
|
197
|
+
</Dialog>
|
|
198
|
+
|
|
199
|
+
{/* Purge confirmation dialog */}
|
|
200
|
+
<Dialog open={!!purgeConfirm} onOpenChange={(open) => !open && setPurgeConfirm(null)}>
|
|
201
|
+
<DialogContent title="Permanently Delete" description="Confirm permanent deletion">
|
|
202
|
+
<div className="px-5 py-4 space-y-3">
|
|
203
|
+
<p className="text-sm text-text-1 font-sans">
|
|
204
|
+
Permanently delete <span className="font-semibold text-text-0">{purgeConfirm?.originalName || purgeConfirm?.name}</span>?
|
|
205
|
+
</p>
|
|
206
|
+
<p className="text-xs text-danger font-sans">
|
|
207
|
+
This cannot be undone. All team files will be permanently removed.
|
|
208
|
+
</p>
|
|
209
|
+
</div>
|
|
210
|
+
<div className="px-5 py-4 border-t border-border-subtle flex justify-end gap-2">
|
|
211
|
+
<Button variant="ghost" size="sm" onClick={() => setPurgeConfirm(null)}>Cancel</Button>
|
|
212
|
+
<Button variant="danger" size="sm" onClick={() => { purgeTeam(purgeConfirm.id); setPurgeConfirm(null); }}>
|
|
213
|
+
<Trash2 size={12} /> Delete Forever
|
|
214
|
+
</Button>
|
|
215
|
+
</div>
|
|
216
|
+
</DialogContent>
|
|
217
|
+
</Dialog>
|
|
115
218
|
</div>
|
|
116
219
|
);
|
|
117
220
|
}
|