groove-dev 0.27.92 → 0.27.93

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.
@@ -6,10 +6,10 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <link rel="icon" type="image/png" href="/favicon.png" />
8
8
  <title>Groove GUI</title>
9
- <script type="module" crossorigin src="/assets/index-DWv32qyJ.js"></script>
9
+ <script type="module" crossorigin src="/assets/index-VB4_k5Pz.js"></script>
10
10
  <link rel="modulepreload" crossorigin href="/assets/vendor-C0HXlhrU.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/reactflow-BQPfi37R.js">
12
- <link rel="modulepreload" crossorigin href="/assets/codemirror-BBL3i_JW.js">
12
+ <link rel="modulepreload" crossorigin href="/assets/codemirror-CFF1Lrnz.js">
13
13
  <link rel="modulepreload" crossorigin href="/assets/xterm--7_ns2zW.js">
14
14
  <link rel="stylesheet" crossorigin href="/assets/index-Bo6AeNmM.css">
15
15
  </head>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/gui",
3
- "version": "0.27.92",
3
+ "version": "0.27.93",
4
4
  "description": "GROOVE GUI — visual agent control plane",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -3,10 +3,10 @@ import { useRef, useEffect } from 'react';
3
3
  import { EditorView, keymap, lineNumbers, highlightActiveLine, highlightActiveLineGutter } from '@codemirror/view';
4
4
  import { EditorState, Compartment } from '@codemirror/state';
5
5
  import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
6
- import { bracketMatching } from '@codemirror/language';
6
+ import { bracketMatching, syntaxHighlighting } from '@codemirror/language';
7
7
  import { searchKeymap, highlightSelectionMatches } from '@codemirror/search';
8
8
  import { autocompletion } from '@codemirror/autocomplete';
9
- import { oneDark } from '@codemirror/theme-one-dark';
9
+ import { oneDarkHighlightStyle } from '@codemirror/theme-one-dark';
10
10
  import { javascript } from '@codemirror/lang-javascript';
11
11
  import { css } from '@codemirror/lang-css';
12
12
  import { html } from '@codemirror/lang-html';
@@ -98,7 +98,7 @@ export function CodeEditor({ content, language, onChange, onSave, onCursorChange
98
98
  autocompletion(),
99
99
  keymap.of([...defaultKeymap, ...historyKeymap, ...searchKeymap]),
100
100
  saveKeymap,
101
- oneDark,
101
+ syntaxHighlighting(oneDarkHighlightStyle),
102
102
  grooveTheme,
103
103
  langCompartment.current.of(langExt()),
104
104
  EditorView.updateListener.of((update) => {
@@ -2497,13 +2497,16 @@ export const useGrooveStore = create((set, get) => ({
2497
2497
  setWorkspaceMode(on) {
2498
2498
  set({ workspaceMode: on });
2499
2499
  localStorage.setItem('groove:workspaceMode', String(on));
2500
- if (on && !get().workspaceAgentId) {
2501
- const teamAgents = get().agents.filter((a) => a.teamId === get().activeTeamId);
2502
- const selected = get().detailPanel?.type === 'agent' ? get().detailPanel.agentId : null;
2503
- const running = teamAgents.find((a) => a.status === 'running');
2504
- set({ workspaceAgentId: selected || running?.id || teamAgents[0]?.id || null });
2505
- }
2506
2500
  if (on) {
2501
+ const teamAgents = get().agents.filter((a) => a.teamId === get().activeTeamId);
2502
+ const current = get().workspaceAgentId;
2503
+ const belongsToTeam = current && teamAgents.some((a) => a.id === current);
2504
+ if (!belongsToTeam) {
2505
+ const selected = get().detailPanel?.type === 'agent' ? get().detailPanel.agentId : null;
2506
+ const selectedInTeam = selected && teamAgents.some((a) => a.id === selected);
2507
+ const running = teamAgents.find((a) => a.status === 'running');
2508
+ set({ workspaceAgentId: (selectedInTeam ? selected : null) || running?.id || teamAgents[0]?.id || null });
2509
+ }
2507
2510
  const agentId = get().workspaceAgentId;
2508
2511
  if (agentId) get().selectAgent(agentId);
2509
2512
  }
@@ -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, Radio, Eye, Settings2, Search, GripVertical, Cloud, FileText, Database, Megaphone, Calculator, UserCheck, Headphones, BarChart3, Pen, Presentation, Globe, MessageCircle, Save, Play, Clock, ListChecks, 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, Play, Clock, ListChecks, Layers } 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';
@@ -974,15 +974,15 @@ function TeamBuilder() {
974
974
  <div className="flex gap-2">
975
975
  <div className="flex-1 space-y-1">
976
976
  <label className="text-2xs text-text-3 font-sans">Provider</label>
977
- <Select value={r.provider || ''} onValueChange={(v) => {
978
- updateRole(i, { provider: v || null });
979
- const p = providers.find((x) => x.id === v);
977
+ <Select value={r.provider || '__default__'} onValueChange={(v) => {
978
+ const pv = v === '__default__' ? null : v;
979
+ const p = providers.find((x) => x.id === pv);
980
980
  const pModels = (p?.models || []).filter((m) => m.type !== 'image' && !m.disabled);
981
- updateRole(i, { provider: v || null, model: pModels[0]?.id || null });
981
+ updateRole(i, { provider: pv, model: pModels[0]?.id || null });
982
982
  }}>
983
983
  <SelectTrigger placeholder="Team Default" className="bg-surface-3 h-7 text-xs" />
984
984
  <SelectContent>
985
- <SelectItem value="">Team Default</SelectItem>
985
+ <SelectItem value="__default__">Team Default</SelectItem>
986
986
  {providers.map((p) => (
987
987
  <SelectItem key={p.id} value={p.id}>{p.displayName || p.name || p.id}</SelectItem>
988
988
  ))}
@@ -991,10 +991,10 @@ function TeamBuilder() {
991
991
  </div>
992
992
  <div className="flex-1 space-y-1">
993
993
  <label className="text-2xs text-text-3 font-sans">Model</label>
994
- <Select value={r.model || ''} onValueChange={(v) => updateRole(i, { model: v || null })}>
994
+ <Select value={r.model || '__default__'} onValueChange={(v) => updateRole(i, { model: v === '__default__' ? null : v })}>
995
995
  <SelectTrigger placeholder="Default" className="bg-surface-3 h-7 text-xs" />
996
996
  <SelectContent>
997
- <SelectItem value="">Default</SelectItem>
997
+ <SelectItem value="__default__">Default</SelectItem>
998
998
  {roleModels.map((m) => (
999
999
  <SelectItem key={m.id} value={m.id}>{m.name || m.id}</SelectItem>
1000
1000
  ))}
@@ -1079,10 +1079,10 @@ function TeamBuilder() {
1079
1079
  <div className="flex gap-2">
1080
1080
  <div className="flex-1 space-y-0.5">
1081
1081
  <label className="text-2xs text-text-3 font-sans">Provider</label>
1082
- <Select value={settings.provider || ''} onValueChange={handleSettingsProviderChange}>
1082
+ <Select value={settings.provider || '__default__'} onValueChange={(v) => handleSettingsProviderChange(v === '__default__' ? '' : v)}>
1083
1083
  <SelectTrigger placeholder="Default" className="bg-surface-3 h-7 text-xs" />
1084
1084
  <SelectContent>
1085
- <SelectItem value="">Default</SelectItem>
1085
+ <SelectItem value="__default__">Default</SelectItem>
1086
1086
  {providers.map((p) => (
1087
1087
  <SelectItem key={p.id} value={p.id}>{p.displayName || p.name || p.id}</SelectItem>
1088
1088
  ))}
@@ -1091,10 +1091,10 @@ function TeamBuilder() {
1091
1091
  </div>
1092
1092
  <div className="flex-1 space-y-0.5">
1093
1093
  <label className="text-2xs text-text-3 font-sans">Model</label>
1094
- <Select value={settings.model || ''} onValueChange={(v) => setSettings({ model: v })}>
1094
+ <Select value={settings.model || '__default__'} onValueChange={(v) => setSettings({ model: v === '__default__' ? '' : v })}>
1095
1095
  <SelectTrigger placeholder="Auto" className="bg-surface-3 h-7 text-xs" />
1096
1096
  <SelectContent>
1097
- <SelectItem value="">Auto</SelectItem>
1097
+ <SelectItem value="__default__">Auto</SelectItem>
1098
1098
  {settingsModels.map((m) => (
1099
1099
  <SelectItem key={m.id} value={m.id}>{m.name || m.id}</SelectItem>
1100
1100
  ))}
@@ -1194,44 +1194,33 @@ function EmptyState({ onPlanner, onSpawn, onTeamBuilder }) {
1194
1194
  </div>
1195
1195
  </button>
1196
1196
 
1197
- <button
1198
- onClick={onTeamBuilder}
1199
- className="w-full flex items-center gap-3 p-4 rounded-lg border border-purple/25 bg-gradient-to-r from-purple/6 to-purple/2 hover:from-purple/12 hover:to-purple/5 hover:border-purple/35 transition-all cursor-pointer group text-left"
1200
- >
1201
- <div className="w-10 h-10 rounded-lg bg-purple/15 flex items-center justify-center group-hover:scale-110 transition-transform flex-shrink-0">
1202
- <UserPlus size={20} className="text-purple" />
1203
- </div>
1204
- <div className="min-w-0">
1205
- <div className="text-sm font-semibold text-text-0 font-sans">Build a Team</div>
1206
- <div className="text-xs text-text-3 font-sans mt-0.5">Pick your roles, configure settings, and launch</div>
1207
- </div>
1208
- </button>
1209
-
1210
- <button
1211
- onClick={onSpawn}
1212
- className="w-full flex items-center gap-3 p-4 rounded-lg border border-border bg-surface-1 hover:bg-surface-2 hover:border-border transition-all cursor-pointer group text-left"
1213
- >
1214
- <div className="w-10 h-10 rounded-lg bg-surface-4 flex items-center justify-center group-hover:scale-110 transition-transform flex-shrink-0">
1215
- <Plus size={20} className="text-text-1" />
1216
- </div>
1217
- <div className="min-w-0">
1218
- <div className="text-sm font-semibold text-text-0 font-sans">Spawn Agent</div>
1219
- <div className="text-xs text-text-3 font-sans mt-0.5">Choose a role and configure</div>
1220
- </div>
1221
- </button>
1197
+ <div className="grid grid-cols-2 gap-3">
1198
+ <button
1199
+ onClick={onTeamBuilder}
1200
+ className="flex items-center gap-3 p-4 rounded-lg border border-purple/25 bg-gradient-to-r from-purple/6 to-purple/2 hover:from-purple/12 hover:to-purple/5 hover:border-purple/35 transition-all cursor-pointer group text-left"
1201
+ >
1202
+ <div className="w-10 h-10 rounded-lg bg-purple/15 flex items-center justify-center group-hover:scale-110 transition-transform flex-shrink-0">
1203
+ <UserPlus size={20} className="text-purple" />
1204
+ </div>
1205
+ <div className="min-w-0">
1206
+ <div className="text-sm font-semibold text-text-0 font-sans">Build a Team</div>
1207
+ <div className="text-xs text-text-3 font-sans mt-0.5">Pick roles and configure</div>
1208
+ </div>
1209
+ </button>
1222
1210
 
1223
- <button
1224
- onClick={() => useGrooveStore.getState().toggleQuickConnect()}
1225
- className="w-full flex items-center gap-3 p-4 rounded-lg border border-border bg-surface-1 hover:bg-surface-2 hover:border-border transition-all cursor-pointer group text-left"
1226
- >
1227
- <div className="w-10 h-10 rounded-lg bg-surface-4 flex items-center justify-center group-hover:scale-110 transition-transform flex-shrink-0">
1228
- <Radio size={20} className="text-text-1" />
1229
- </div>
1230
- <div className="min-w-0">
1231
- <div className="text-sm font-semibold text-text-0 font-sans">Connect to Remote Server</div>
1232
- <div className="text-xs text-text-3 font-sans mt-0.5">SSH tunnel to a remote machine</div>
1233
- </div>
1234
- </button>
1211
+ <button
1212
+ onClick={onSpawn}
1213
+ className="flex items-center gap-3 p-4 rounded-lg border border-border bg-surface-1 hover:bg-surface-2 hover:border-border transition-all cursor-pointer group text-left"
1214
+ >
1215
+ <div className="w-10 h-10 rounded-lg bg-surface-4 flex items-center justify-center group-hover:scale-110 transition-transform flex-shrink-0">
1216
+ <Plus size={20} className="text-text-1" />
1217
+ </div>
1218
+ <div className="min-w-0">
1219
+ <div className="text-sm font-semibold text-text-0 font-sans">Spawn Agent</div>
1220
+ <div className="text-xs text-text-3 font-sans mt-0.5">Choose a role and configure</div>
1221
+ </div>
1222
+ </button>
1223
+ </div>
1235
1224
  </div>
1236
1225
 
1237
1226
  {window.groove?.openFolder && (