groove-dev 0.27.29 → 0.27.32
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/CLAUDE.md +0 -7
- 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 +4 -1
- package/node_modules/@groove-dev/daemon/src/providers/local.js +4 -2
- package/node_modules/@groove-dev/daemon/src/providers/ollama.js +35 -3
- package/node_modules/@groove-dev/gui/dist/assets/{index-CjjmUhoW.css → index-BwNjgBny.css} +1 -1
- package/node_modules/@groove-dev/gui/dist/assets/{index-CNsQ3n1t.js → index-PxWmJjcJ.js} +9 -9
- 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/app.css +10 -0
- package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +4 -4
- package/node_modules/@groove-dev/gui/src/components/editor/terminal.jsx +21 -13
- package/node_modules/@groove-dev/gui/src/components/layout/terminal-panel.jsx +1 -1
- package/node_modules/@groove-dev/gui/src/views/settings.jsx +2 -2
- 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 +4 -1
- package/packages/daemon/src/providers/local.js +4 -2
- package/packages/daemon/src/providers/ollama.js +35 -3
- package/packages/gui/dist/assets/{index-CjjmUhoW.css → index-BwNjgBny.css} +1 -1
- package/packages/gui/dist/assets/{index-CNsQ3n1t.js → index-PxWmJjcJ.js} +9 -9
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/packages/gui/src/app.css +10 -0
- package/packages/gui/src/components/agents/spawn-wizard.jsx +4 -4
- package/packages/gui/src/components/editor/terminal.jsx +21 -13
- package/packages/gui/src/components/layout/terminal-panel.jsx +1 -1
- package/packages/gui/src/views/settings.jsx +2 -2
|
@@ -6,12 +6,12 @@
|
|
|
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-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-PxWmJjcJ.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
12
|
<link rel="modulepreload" crossorigin href="/assets/codemirror-BBL3i_JW.js">
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/xterm--7_ns2zW.js">
|
|
14
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BwNjgBny.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
|
@@ -80,6 +80,16 @@ html {
|
|
|
80
80
|
::-webkit-scrollbar-thumb:hover { background: var(--color-surface-6); }
|
|
81
81
|
::selection { background: rgba(51, 175, 188, 0.25); }
|
|
82
82
|
|
|
83
|
+
/* ── Terminal (xterm) ────────────────────────────────────── */
|
|
84
|
+
|
|
85
|
+
.xterm-viewport::-webkit-scrollbar { width: 6px; }
|
|
86
|
+
.xterm-viewport::-webkit-scrollbar-track { background: transparent; }
|
|
87
|
+
.xterm-viewport::-webkit-scrollbar-thumb { background: var(--color-surface-5); border-radius: 3px; }
|
|
88
|
+
.xterm-viewport::-webkit-scrollbar-thumb:hover { background: var(--color-surface-6); }
|
|
89
|
+
.xterm-viewport { scrollbar-width: thin; scrollbar-color: var(--color-surface-5) transparent; }
|
|
90
|
+
.xterm { padding: 0; }
|
|
91
|
+
.xterm-screen { width: 100% !important; }
|
|
92
|
+
|
|
83
93
|
/* ── Animations ───────────────────────────────────────────── */
|
|
84
94
|
|
|
85
95
|
@keyframes pulse {
|
|
@@ -90,14 +90,14 @@ export function SpawnWizard() {
|
|
|
90
90
|
const selectedRole = role || customRole;
|
|
91
91
|
const selectedProvider = providers.find((p) => p.id === provider);
|
|
92
92
|
const availableModels = selectedProvider?.models || [];
|
|
93
|
-
const installedProviders = providers.filter((p) => p.installed);
|
|
93
|
+
const installedProviders = providers.filter((p) => p.authType === 'api-key' ? (p.installed && p.hasKey) : p.installed);
|
|
94
94
|
|
|
95
95
|
useEffect(() => {
|
|
96
96
|
if (open) {
|
|
97
97
|
fetchProviders().then((data) => {
|
|
98
98
|
const list = Array.isArray(data) ? data : data.providers || [];
|
|
99
99
|
setProviders(list);
|
|
100
|
-
const installed = list.filter((p) => p.installed);
|
|
100
|
+
const installed = list.filter((p) => p.authType === 'api-key' ? (p.installed && p.hasKey) : p.installed);
|
|
101
101
|
if (installed.length > 0 && !provider) {
|
|
102
102
|
const priority = ['claude-code', 'gemini', 'codex', 'ollama'];
|
|
103
103
|
const best = priority.find((pid) => installed.some((p) => p.id === pid)) || installed[0].id;
|
|
@@ -408,8 +408,8 @@ export function SpawnWizard() {
|
|
|
408
408
|
>
|
|
409
409
|
<option value="">Auto</option>
|
|
410
410
|
{providers.map((p) => (
|
|
411
|
-
<option key={p.id} value={p.id} disabled={!p.installed}>
|
|
412
|
-
{p.name}{!p.installed ? ' (
|
|
411
|
+
<option key={p.id} value={p.id} disabled={p.authType === 'api-key' ? !(p.installed && p.hasKey) : !p.installed}>
|
|
412
|
+
{p.name}{!p.installed ? ' (Not installed)' : (p.authType === 'api-key' && !p.hasKey) ? ' (No API key)' : ''}
|
|
413
413
|
</option>
|
|
414
414
|
))}
|
|
415
415
|
</select>
|
|
@@ -8,14 +8,15 @@ import { TerminalPanel } from '../layout/terminal-panel';
|
|
|
8
8
|
|
|
9
9
|
const THEME = {
|
|
10
10
|
background: '#1a1e25',
|
|
11
|
-
foreground: '#
|
|
11
|
+
foreground: '#c8ccd4',
|
|
12
12
|
cursor: '#33afbc',
|
|
13
13
|
cursorAccent: '#1a1e25',
|
|
14
|
-
selectionBackground: 'rgba(51, 175, 188, 0.
|
|
14
|
+
selectionBackground: 'rgba(51, 175, 188, 0.3)',
|
|
15
|
+
selectionForeground: '#ffffff',
|
|
15
16
|
black: '#1a1e25', red: '#e06c75', green: '#4ae168', yellow: '#e5c07b',
|
|
16
|
-
blue: '#61afef', magenta: '#c678dd', cyan: '#33afbc', white: '#
|
|
17
|
-
brightBlack: '#
|
|
18
|
-
brightBlue: '#61afef', brightMagenta: '#c678dd', brightCyan: '#
|
|
17
|
+
blue: '#61afef', magenta: '#c678dd', cyan: '#33afbc', white: '#abb2bf',
|
|
18
|
+
brightBlack: '#5c6370', brightRed: '#f07178', brightGreen: '#4ae168', brightYellow: '#e5c07b',
|
|
19
|
+
brightBlue: '#61afef', brightMagenta: '#c678dd', brightCyan: '#56b6c2', brightWhite: '#ffffff',
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
let tabCounter = 0;
|
|
@@ -35,12 +36,19 @@ function TerminalInstance({ tabId, visible }) {
|
|
|
35
36
|
const term = new XTerm({
|
|
36
37
|
theme: THEME,
|
|
37
38
|
fontFamily: "'JetBrains Mono Variable', 'SF Mono', monospace",
|
|
38
|
-
fontSize:
|
|
39
|
-
lineHeight: 1.
|
|
39
|
+
fontSize: 12,
|
|
40
|
+
lineHeight: 1.1,
|
|
41
|
+
letterSpacing: 0,
|
|
40
42
|
cursorBlink: true,
|
|
41
43
|
cursorStyle: 'bar',
|
|
42
|
-
|
|
44
|
+
cursorWidth: 1,
|
|
45
|
+
scrollback: 10000,
|
|
43
46
|
allowProposedApi: true,
|
|
47
|
+
minimumContrastRatio: 1,
|
|
48
|
+
drawBoldTextInBrightColors: true,
|
|
49
|
+
fontWeight: '400',
|
|
50
|
+
fontWeightBold: '600',
|
|
51
|
+
overviewRulerWidth: 0,
|
|
44
52
|
});
|
|
45
53
|
|
|
46
54
|
const fitAddon = new FitAddon();
|
|
@@ -50,10 +58,6 @@ function TerminalInstance({ tabId, visible }) {
|
|
|
50
58
|
termRef.current = term;
|
|
51
59
|
fitRef.current = fitAddon;
|
|
52
60
|
|
|
53
|
-
requestAnimationFrame(() => {
|
|
54
|
-
try { fitAddon.fit(); } catch {}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
61
|
let spawnAttempts = 0;
|
|
58
62
|
function trySpawn() {
|
|
59
63
|
spawnAttempts++;
|
|
@@ -97,7 +101,11 @@ function TerminalInstance({ tabId, visible }) {
|
|
|
97
101
|
});
|
|
98
102
|
}
|
|
99
103
|
|
|
100
|
-
|
|
104
|
+
// Fit first, then spawn — ensures PTY gets correct column count
|
|
105
|
+
requestAnimationFrame(() => {
|
|
106
|
+
try { fitAddon.fit(); } catch {}
|
|
107
|
+
trySpawn();
|
|
108
|
+
});
|
|
101
109
|
|
|
102
110
|
const observer = new ResizeObserver(() => {
|
|
103
111
|
requestAnimationFrame(() => { try { fitAddon.fit(); } catch {} });
|
|
@@ -999,7 +999,7 @@ export default function SettingsView() {
|
|
|
999
999
|
const connectedCount = providers.filter((p) => {
|
|
1000
1000
|
if (p.authType === 'local') return p.installed;
|
|
1001
1001
|
if (p.authType === 'subscription') return p.installed;
|
|
1002
|
-
return p.hasKey;
|
|
1002
|
+
return p.installed && p.hasKey;
|
|
1003
1003
|
}).length;
|
|
1004
1004
|
|
|
1005
1005
|
// Rotation threshold display: 0 = auto, otherwise show as percentage
|
|
@@ -1074,7 +1074,7 @@ export default function SettingsView() {
|
|
|
1074
1074
|
onChange={(e) => updateConfig('defaultProvider', e.target.value)}
|
|
1075
1075
|
className="w-full h-8 px-2.5 text-xs bg-surface-0 border border-border-subtle rounded-md text-text-0 font-mono focus:outline-none focus:ring-1 focus:ring-accent cursor-pointer"
|
|
1076
1076
|
>
|
|
1077
|
-
{providers.filter((p) => p.installed || p.hasKey).map((p) => (
|
|
1077
|
+
{providers.filter((p) => p.installed && (p.authType === 'local' || p.authType === 'subscription' || p.hasKey)).map((p) => (
|
|
1078
1078
|
<option key={p.id} value={p.id}>{p.name}</option>
|
|
1079
1079
|
))}
|
|
1080
1080
|
</select>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groove-dev",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.32",
|
|
4
4
|
"description": "Open-source agent orchestration layer — the AI company OS. Local model agent engine (GGUF/Ollama/llama-server), HuggingFace model browser, MCP integrations (Slack, Gmail, Stripe, 15+), agent scheduling (cron), business roles (CMO, CFO, EA). GUI dashboard, multi-agent coordination, zero cold-start, infinite sessions. Works with Claude Code, Codex, Gemini CLI, Ollama, any local model.",
|
|
5
5
|
"license": "FSL-1.1-Apache-2.0",
|
|
6
6
|
"author": "Groove Dev <hello@groovedev.ai> (https://groovedev.ai)",
|
|
@@ -426,7 +426,10 @@ export function createApi(app, daemon) {
|
|
|
426
426
|
app.post('/api/providers/ollama/pull', async (req, res) => {
|
|
427
427
|
const { model } = req.body;
|
|
428
428
|
if (!model) return res.status(400).json({ error: 'model is required' });
|
|
429
|
-
if (!OllamaProvider.isInstalled())
|
|
429
|
+
if (!OllamaProvider.isInstalled()) {
|
|
430
|
+
const install = OllamaProvider.installCommand();
|
|
431
|
+
return res.status(400).json({ error: `Ollama is not installed. Install with: ${install.command}` });
|
|
432
|
+
}
|
|
430
433
|
const broadcast = daemon.broadcast.bind(daemon);
|
|
431
434
|
try {
|
|
432
435
|
// Auto-start Ollama server if not running
|
|
@@ -93,14 +93,16 @@ export class LocalProvider extends Provider {
|
|
|
93
93
|
|
|
94
94
|
static _hasOllama() {
|
|
95
95
|
try {
|
|
96
|
-
|
|
96
|
+
const cmd = process.platform === 'win32' ? 'where ollama' : 'which ollama';
|
|
97
|
+
execSync(cmd, { stdio: 'ignore' });
|
|
97
98
|
return true;
|
|
98
99
|
} catch { return false; }
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
static _hasLlamaServer() {
|
|
102
103
|
try {
|
|
103
|
-
|
|
104
|
+
const cmd = process.platform === 'win32' ? 'where llama-server' : 'which llama-server';
|
|
105
|
+
execSync(cmd, { stdio: 'ignore' });
|
|
104
106
|
return true;
|
|
105
107
|
} catch { return false; }
|
|
106
108
|
}
|
|
@@ -52,7 +52,8 @@ export class OllamaProvider extends Provider {
|
|
|
52
52
|
|
|
53
53
|
static isInstalled() {
|
|
54
54
|
try {
|
|
55
|
-
|
|
55
|
+
const cmd = process.platform === 'win32' ? 'where ollama' : 'which ollama';
|
|
56
|
+
execSync(cmd, { stdio: 'ignore' });
|
|
56
57
|
return true;
|
|
57
58
|
} catch {
|
|
58
59
|
return false;
|
|
@@ -67,6 +68,9 @@ export class OllamaProvider extends Provider {
|
|
|
67
68
|
if (platform === 'linux') {
|
|
68
69
|
return { command: 'curl -fsSL https://ollama.ai/install.sh | sh', platform: 'Linux' };
|
|
69
70
|
}
|
|
71
|
+
if (platform === 'win32') {
|
|
72
|
+
return { command: 'winget install Ollama.Ollama', alt: 'Or download from https://ollama.ai/download', platform: 'Windows' };
|
|
73
|
+
}
|
|
70
74
|
return { command: 'Download from https://ollama.ai/download', platform: 'other' };
|
|
71
75
|
}
|
|
72
76
|
|
|
@@ -98,6 +102,22 @@ export class OllamaProvider extends Provider {
|
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
104
|
}
|
|
105
|
+
if (platform === 'win32') {
|
|
106
|
+
try {
|
|
107
|
+
let cmd = 'ollama';
|
|
108
|
+
try {
|
|
109
|
+
execSync('where ollama', { stdio: 'ignore' });
|
|
110
|
+
} catch {
|
|
111
|
+
const localAppData = process.env.LOCALAPPDATA || '';
|
|
112
|
+
const fallback = localAppData + '\\Programs\\Ollama\\ollama.exe';
|
|
113
|
+
cmd = fallback;
|
|
114
|
+
}
|
|
115
|
+
execFile(cmd, ['serve'], { stdio: 'ignore', detached: true, shell: true }).unref();
|
|
116
|
+
return { started: true, method: 'ollama serve' };
|
|
117
|
+
} catch {
|
|
118
|
+
return { started: false, command: 'ollama serve' };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
101
121
|
// Linux / other
|
|
102
122
|
try {
|
|
103
123
|
execFile('ollama', ['serve'], { stdio: 'ignore', detached: true }).unref();
|
|
@@ -109,6 +129,14 @@ export class OllamaProvider extends Provider {
|
|
|
109
129
|
|
|
110
130
|
static stopServer() {
|
|
111
131
|
const platform = process.platform;
|
|
132
|
+
if (platform === 'win32') {
|
|
133
|
+
try {
|
|
134
|
+
execSync('taskkill /IM ollama.exe /F', { stdio: 'ignore', timeout: 5000 });
|
|
135
|
+
return { stopped: true, method: 'taskkill' };
|
|
136
|
+
} catch {
|
|
137
|
+
return { stopped: false };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
112
140
|
if (platform === 'darwin') {
|
|
113
141
|
try {
|
|
114
142
|
execSync('brew services stop ollama', { stdio: 'ignore', timeout: 10000 });
|
|
@@ -135,7 +163,11 @@ export class OllamaProvider extends Provider {
|
|
|
135
163
|
minRAM: 4,
|
|
136
164
|
recommendedRAM: 16,
|
|
137
165
|
gpuRecommended: true,
|
|
138
|
-
note:
|
|
166
|
+
note: process.platform === 'win32'
|
|
167
|
+
? 'NVIDIA or AMD GPUs recommended. Ensure GPU drivers are up to date.'
|
|
168
|
+
: process.platform === 'darwin'
|
|
169
|
+
? 'Apple Silicon Macs use unified memory — all RAM is GPU RAM.'
|
|
170
|
+
: 'NVIDIA GPUs recommended on Linux.',
|
|
139
171
|
};
|
|
140
172
|
}
|
|
141
173
|
|
|
@@ -151,7 +183,7 @@ export class OllamaProvider extends Provider {
|
|
|
151
183
|
let gpu = null;
|
|
152
184
|
if (isAppleSilicon) {
|
|
153
185
|
gpu = { type: 'apple-silicon', name: cpuModel.replace(/Apple /g, ''), vram: totalRamGb, note: 'Unified memory — all RAM available to GPU' };
|
|
154
|
-
} else if (platform === 'linux') {
|
|
186
|
+
} else if (platform === 'linux' || platform === 'win32') {
|
|
155
187
|
try {
|
|
156
188
|
const out = execSync('nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits', { encoding: 'utf8', timeout: 5000 });
|
|
157
189
|
const [name, vram] = out.trim().split(', ');
|