groove-dev 0.19.2 → 0.19.4
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/CHANGELOG.md +15 -0
- package/node_modules/@groove-dev/cli/bin/groove.js +1 -1
- package/node_modules/@groove-dev/daemon/src/api.js +68 -0
- package/node_modules/@groove-dev/daemon/src/providers/ollama.js +164 -26
- package/node_modules/@groove-dev/gui/.groove/codebase-index.json +3 -3
- package/node_modules/@groove-dev/gui/.groove/daemon.host +1 -0
- package/node_modules/@groove-dev/gui/.groove/daemon.pid +1 -0
- package/node_modules/@groove-dev/gui/.groove/state.json +1 -1
- package/node_modules/@groove-dev/gui/.groove/timeline.json +504 -0
- package/node_modules/@groove-dev/gui/AGENTS_REGISTRY.md +9 -0
- package/node_modules/@groove-dev/gui/dist/assets/{index-DCakRxDE.css → index-DgIS4D-j.css} +1 -1
- package/node_modules/@groove-dev/gui/dist/assets/{index-DbujgqhS.js → index-eysbqREF.js} +123 -123
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/src/components/agents/agent-config.jsx +9 -3
- package/node_modules/@groove-dev/gui/src/components/agents/ollama-setup.jsx +375 -0
- package/package.json +1 -1
- package/packages/cli/bin/groove.js +1 -1
- package/packages/daemon/src/api.js +68 -0
- package/packages/daemon/src/providers/ollama.js +164 -26
- package/packages/gui/dist/assets/{index-DCakRxDE.css → index-DgIS4D-j.css} +1 -1
- package/packages/gui/dist/assets/{index-DbujgqhS.js → index-eysbqREF.js} +123 -123
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/src/components/agents/agent-config.jsx +9 -3
- package/packages/gui/src/components/agents/ollama-setup.jsx +375 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.19.4 — Ollama server lifecycle, UI state fix (2026-04-08)
|
|
4
|
+
|
|
5
|
+
- **Server detection** — checks if Ollama server is running (not just binary installed), shows "Start Ollama Server" button with auto-start via brew services or ollama serve
|
|
6
|
+
- **Three-state install flow** — not installed → installed but server down → ready with models
|
|
7
|
+
- **UI state fix** — closing/reopening Ollama dropdown no longer reverts to install screen; provider list refreshes on state change
|
|
8
|
+
- **New API endpoints** — `POST /api/providers/ollama/serve` (auto-start server), `/check` now returns `serverRunning` flag
|
|
9
|
+
|
|
10
|
+
## v0.19.3 — Ollama setup experience: hardware detection, model catalog, one-click pull (2026-04-08)
|
|
11
|
+
|
|
12
|
+
- **Ollama model catalog** — 22 models across Code and General categories with RAM requirements and download sizes
|
|
13
|
+
- **Hardware detection** — auto-detects RAM, CPU, GPU (Apple Silicon unified memory, NVIDIA), recommends best models for your system
|
|
14
|
+
- **Model management** — pull models from GUI with progress via WebSocket, delete installed models, category tabs (Code/General)
|
|
15
|
+
- **Install flow** — platform-specific install command (brew on macOS, curl on Linux), copy button, hardware readiness check, "Recheck" button
|
|
16
|
+
- **5 new API endpoints** — `/api/providers/ollama/hardware`, `/models`, `/pull`, `/check`, `DELETE /models/:model`
|
|
17
|
+
|
|
3
18
|
## v0.19.2 — Config tab cleanup, remove restart, fix Ollama key prompt (2026-04-08)
|
|
4
19
|
|
|
5
20
|
- **Remove restart button** — sending a chat message resumes with context, restart was redundant
|
|
@@ -7,6 +7,7 @@ import { fileURLToPath } from 'url';
|
|
|
7
7
|
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync, mkdirSync, unlinkSync, renameSync, rmSync, createReadStream } from 'fs';
|
|
8
8
|
import { lookup as mimeLookup } from './mimetypes.js';
|
|
9
9
|
import { listProviders, getProvider } from './providers/index.js';
|
|
10
|
+
import { OllamaProvider } from './providers/ollama.js';
|
|
10
11
|
import { validateAgentConfig } from './validate.js';
|
|
11
12
|
|
|
12
13
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -126,6 +127,73 @@ export function createApi(app, daemon) {
|
|
|
126
127
|
res.json(providers);
|
|
127
128
|
});
|
|
128
129
|
|
|
130
|
+
// --- Ollama ---
|
|
131
|
+
|
|
132
|
+
app.get('/api/providers/ollama/hardware', (req, res) => {
|
|
133
|
+
res.json(OllamaProvider.getSystemHardware());
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
app.get('/api/providers/ollama/models', (req, res) => {
|
|
137
|
+
const installed = OllamaProvider.isInstalled() ? OllamaProvider.getInstalledModels() : [];
|
|
138
|
+
const catalog = OllamaProvider.catalog;
|
|
139
|
+
const hardware = OllamaProvider.getSystemHardware();
|
|
140
|
+
res.json({ installed, catalog, hardware });
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
app.post('/api/providers/ollama/pull', async (req, res) => {
|
|
144
|
+
const { model } = req.body;
|
|
145
|
+
if (!model) return res.status(400).json({ error: 'model is required' });
|
|
146
|
+
if (!OllamaProvider.isInstalled()) return res.status(400).json({ error: 'Ollama is not installed' });
|
|
147
|
+
const broadcast = daemon.broadcast || (() => {});
|
|
148
|
+
try {
|
|
149
|
+
broadcast({ type: 'ollama:pull:start', model });
|
|
150
|
+
await OllamaProvider.pullModel(model, (progress) => {
|
|
151
|
+
broadcast({ type: 'ollama:pull:progress', model, progress: progress.trim() });
|
|
152
|
+
});
|
|
153
|
+
broadcast({ type: 'ollama:pull:complete', model });
|
|
154
|
+
daemon.audit.log('ollama.pull', { model });
|
|
155
|
+
res.json({ ok: true, model });
|
|
156
|
+
} catch (err) {
|
|
157
|
+
broadcast({ type: 'ollama:pull:error', model, error: err.message });
|
|
158
|
+
res.status(500).json({ error: `Pull failed: ${err.message}` });
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
app.delete('/api/providers/ollama/models/:model', (req, res) => {
|
|
163
|
+
if (!OllamaProvider.isInstalled()) return res.status(400).json({ error: 'Ollama is not installed' });
|
|
164
|
+
const success = OllamaProvider.deleteModel(req.params.model);
|
|
165
|
+
if (success) {
|
|
166
|
+
daemon.audit.log('ollama.delete', { model: req.params.model });
|
|
167
|
+
res.json({ ok: true });
|
|
168
|
+
} else {
|
|
169
|
+
res.status(500).json({ error: 'Failed to delete model' });
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
app.post('/api/providers/ollama/check', async (req, res) => {
|
|
174
|
+
const installed = OllamaProvider.isInstalled();
|
|
175
|
+
const serverRunning = installed ? await OllamaProvider.isServerRunning() : false;
|
|
176
|
+
const install = OllamaProvider.installCommand();
|
|
177
|
+
const hardware = OllamaProvider.getSystemHardware();
|
|
178
|
+
const requirements = OllamaProvider.hardwareRequirements();
|
|
179
|
+
res.json({ installed, serverRunning, install, hardware, requirements });
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
app.post('/api/providers/ollama/serve', async (req, res) => {
|
|
183
|
+
if (!OllamaProvider.isInstalled()) return res.status(400).json({ error: 'Ollama is not installed' });
|
|
184
|
+
const already = await OllamaProvider.isServerRunning();
|
|
185
|
+
if (already) return res.json({ ok: true, alreadyRunning: true });
|
|
186
|
+
const result = OllamaProvider.startServer();
|
|
187
|
+
if (result.started) {
|
|
188
|
+
// Wait a moment for server to come up
|
|
189
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
190
|
+
const running = await OllamaProvider.isServerRunning();
|
|
191
|
+
res.json({ ok: running, method: result.method });
|
|
192
|
+
} else {
|
|
193
|
+
res.status(500).json({ error: 'Could not start server', command: result.command });
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
129
197
|
// --- Credentials ---
|
|
130
198
|
|
|
131
199
|
app.get('/api/credentials', (req, res) => {
|
|
@@ -2,19 +2,54 @@
|
|
|
2
2
|
// FSL-1.1-Apache-2.0 — see LICENSE
|
|
3
3
|
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
|
+
import { execFile } from 'child_process';
|
|
6
|
+
import os from 'os';
|
|
5
7
|
import { Provider } from './base.js';
|
|
6
8
|
|
|
9
|
+
// Comprehensive model catalog with RAM requirements
|
|
10
|
+
const MODEL_CATALOG = [
|
|
11
|
+
// ── Code-Focused ──────────────────────────────────────────
|
|
12
|
+
{ id: 'qwen2.5-coder:0.5b', name: 'Qwen 2.5 Coder 0.5B', category: 'code', tier: 'light', ramGb: 1, sizeGb: 0.4, description: 'Ultra-light code completion' },
|
|
13
|
+
{ id: 'qwen2.5-coder:1.5b', name: 'Qwen 2.5 Coder 1.5B', category: 'code', tier: 'light', ramGb: 2, sizeGb: 1.0, description: 'Fast code assistant' },
|
|
14
|
+
{ id: 'qwen2.5-coder:3b', name: 'Qwen 2.5 Coder 3B', category: 'code', tier: 'light', ramGb: 4, sizeGb: 1.9, description: 'Balanced speed and quality' },
|
|
15
|
+
{ id: 'qwen2.5-coder:7b', name: 'Qwen 2.5 Coder 7B', category: 'code', tier: 'medium', ramGb: 8, sizeGb: 4.7, description: 'Strong general coding' },
|
|
16
|
+
{ id: 'qwen2.5-coder:14b', name: 'Qwen 2.5 Coder 14B', category: 'code', tier: 'medium', ramGb: 16, sizeGb: 9.0, description: 'Advanced code reasoning' },
|
|
17
|
+
{ id: 'qwen2.5-coder:32b', name: 'Qwen 2.5 Coder 32B', category: 'code', tier: 'heavy', ramGb: 24, sizeGb: 20, description: 'Best-in-class code generation' },
|
|
18
|
+
{ id: 'codellama:7b', name: 'Code Llama 7B', category: 'code', tier: 'medium', ramGb: 8, sizeGb: 3.8, description: 'Meta code model, solid baseline' },
|
|
19
|
+
{ id: 'codellama:13b', name: 'Code Llama 13B', category: 'code', tier: 'medium', ramGb: 16, sizeGb: 7.4, description: 'Stronger code reasoning' },
|
|
20
|
+
{ id: 'codellama:34b', name: 'Code Llama 34B', category: 'code', tier: 'heavy', ramGb: 24, sizeGb: 19, description: 'Largest Code Llama' },
|
|
21
|
+
{ id: 'deepseek-coder-v2:16b', name: 'DeepSeek Coder V2 16B', category: 'code', tier: 'medium', ramGb: 16, sizeGb: 8.9, description: 'Strong multi-language coding' },
|
|
22
|
+
{ id: 'starcoder2:3b', name: 'StarCoder2 3B', category: 'code', tier: 'light', ramGb: 4, sizeGb: 1.7, description: 'Code completion specialist' },
|
|
23
|
+
{ id: 'starcoder2:7b', name: 'StarCoder2 7B', category: 'code', tier: 'medium', ramGb: 8, sizeGb: 4.0, description: 'Solid code generation' },
|
|
24
|
+
{ id: 'starcoder2:15b', name: 'StarCoder2 15B', category: 'code', tier: 'medium', ramGb: 16, sizeGb: 9.0, description: 'Best StarCoder variant' },
|
|
25
|
+
|
|
26
|
+
// ── General (Strong at Code) ──────────────────────────────
|
|
27
|
+
{ id: 'llama3.1:8b', name: 'Llama 3.1 8B', category: 'general', tier: 'medium', ramGb: 8, sizeGb: 4.7, description: 'Meta flagship, great all-rounder' },
|
|
28
|
+
{ id: 'llama3.1:70b', name: 'Llama 3.1 70B', category: 'general', tier: 'heavy', ramGb: 48, sizeGb: 40, description: 'Frontier-class open model' },
|
|
29
|
+
{ id: 'mistral:7b', name: 'Mistral 7B', category: 'general', tier: 'medium', ramGb: 8, sizeGb: 4.1, description: 'Fast and efficient' },
|
|
30
|
+
{ id: 'mixtral:8x7b', name: 'Mixtral 8x7B', category: 'general', tier: 'heavy', ramGb: 32, sizeGb: 26, description: 'MoE architecture, expert routing' },
|
|
31
|
+
{ id: 'gemma2:2b', name: 'Gemma 2 2B', category: 'general', tier: 'light', ramGb: 2, sizeGb: 1.6, description: 'Google lightweight model' },
|
|
32
|
+
{ id: 'gemma2:9b', name: 'Gemma 2 9B', category: 'general', tier: 'medium', ramGb: 8, sizeGb: 5.4, description: 'Google mid-range model' },
|
|
33
|
+
{ id: 'gemma2:27b', name: 'Gemma 2 27B', category: 'general', tier: 'heavy', ramGb: 20, sizeGb: 16, description: 'Google large model' },
|
|
34
|
+
{ id: 'phi3:mini', name: 'Phi-3 Mini 3.8B', category: 'general', tier: 'light', ramGb: 4, sizeGb: 2.3, description: 'Microsoft small but capable' },
|
|
35
|
+
{ id: 'phi3:medium', name: 'Phi-3 Medium 14B', category: 'general', tier: 'medium', ramGb: 16, sizeGb: 7.9, description: 'Microsoft mid-range' },
|
|
36
|
+
];
|
|
37
|
+
|
|
7
38
|
export class OllamaProvider extends Provider {
|
|
8
39
|
static name = 'ollama';
|
|
9
40
|
static displayName = 'Ollama (Local)';
|
|
10
41
|
static command = 'ollama';
|
|
11
42
|
static authType = 'local';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
{ id
|
|
16
|
-
|
|
17
|
-
|
|
43
|
+
|
|
44
|
+
// Models exposed to the spawn wizard / provider listing
|
|
45
|
+
static get models() {
|
|
46
|
+
return MODEL_CATALOG.map(({ id, name, tier }) => ({ id, name, tier }));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Full catalog with RAM/size/description for the setup UI
|
|
50
|
+
static get catalog() {
|
|
51
|
+
return MODEL_CATALOG;
|
|
52
|
+
}
|
|
18
53
|
|
|
19
54
|
static isInstalled() {
|
|
20
55
|
try {
|
|
@@ -26,53 +61,156 @@ export class OllamaProvider extends Provider {
|
|
|
26
61
|
}
|
|
27
62
|
|
|
28
63
|
static installCommand() {
|
|
29
|
-
|
|
64
|
+
const platform = process.platform;
|
|
65
|
+
if (platform === 'darwin') {
|
|
66
|
+
return { command: 'brew install ollama', alt: 'Or download from https://ollama.ai/download', platform: 'macOS' };
|
|
67
|
+
}
|
|
68
|
+
if (platform === 'linux') {
|
|
69
|
+
return { command: 'curl -fsSL https://ollama.ai/install.sh | sh', platform: 'Linux' };
|
|
70
|
+
}
|
|
71
|
+
return { command: 'Download from https://ollama.ai/download', platform: 'other' };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static async isServerRunning() {
|
|
75
|
+
try {
|
|
76
|
+
const controller = new AbortController();
|
|
77
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
78
|
+
const res = await fetch('http://localhost:11434/', { signal: controller.signal });
|
|
79
|
+
clearTimeout(timeout);
|
|
80
|
+
return res.ok;
|
|
81
|
+
} catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static startServer() {
|
|
87
|
+
const platform = process.platform;
|
|
88
|
+
if (platform === 'darwin') {
|
|
89
|
+
// Try brew services first, fall back to ollama serve
|
|
90
|
+
try {
|
|
91
|
+
execSync('brew services start ollama', { stdio: 'ignore', timeout: 10000 });
|
|
92
|
+
return { started: true, method: 'brew services' };
|
|
93
|
+
} catch {
|
|
94
|
+
try {
|
|
95
|
+
execFile('ollama', ['serve'], { stdio: 'ignore', detached: true }).unref();
|
|
96
|
+
return { started: true, method: 'ollama serve' };
|
|
97
|
+
} catch {
|
|
98
|
+
return { started: false, command: 'ollama serve' };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Linux / other
|
|
103
|
+
try {
|
|
104
|
+
execFile('ollama', ['serve'], { stdio: 'ignore', detached: true }).unref();
|
|
105
|
+
return { started: true, method: 'ollama serve' };
|
|
106
|
+
} catch {
|
|
107
|
+
return { started: false, command: 'ollama serve' };
|
|
108
|
+
}
|
|
30
109
|
}
|
|
31
110
|
|
|
32
111
|
static hardwareRequirements() {
|
|
33
112
|
return {
|
|
34
|
-
minRAM:
|
|
113
|
+
minRAM: 4,
|
|
35
114
|
recommendedRAM: 16,
|
|
36
115
|
gpuRecommended: true,
|
|
37
|
-
note: '
|
|
116
|
+
note: 'Apple Silicon Macs use unified memory — all RAM is GPU RAM. NVIDIA GPUs recommended on Linux.',
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static getSystemHardware() {
|
|
121
|
+
const totalRamGb = Math.round(os.totalmem() / (1024 ** 3));
|
|
122
|
+
const cpus = os.cpus();
|
|
123
|
+
const cpuModel = cpus[0]?.model || 'Unknown';
|
|
124
|
+
const cores = cpus.length;
|
|
125
|
+
const platform = process.platform;
|
|
126
|
+
const arch = os.arch();
|
|
127
|
+
const isAppleSilicon = platform === 'darwin' && arch === 'arm64';
|
|
128
|
+
|
|
129
|
+
let gpu = null;
|
|
130
|
+
if (isAppleSilicon) {
|
|
131
|
+
gpu = { type: 'apple-silicon', name: cpuModel.replace(/Apple /g, ''), vram: totalRamGb, note: 'Unified memory — all RAM available to GPU' };
|
|
132
|
+
} else if (platform === 'linux') {
|
|
133
|
+
try {
|
|
134
|
+
const out = execSync('nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits', { encoding: 'utf8', timeout: 5000 });
|
|
135
|
+
const [name, vram] = out.trim().split(', ');
|
|
136
|
+
gpu = { type: 'nvidia', name, vram: Math.round(parseInt(vram, 10) / 1024) };
|
|
137
|
+
} catch {
|
|
138
|
+
gpu = null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Recommend models based on available RAM
|
|
143
|
+
const recommended = MODEL_CATALOG
|
|
144
|
+
.filter((m) => m.ramGb <= totalRamGb)
|
|
145
|
+
.sort((a, b) => b.ramGb - a.ramGb);
|
|
146
|
+
|
|
147
|
+
const bestCodeModel = recommended.find((m) => m.category === 'code');
|
|
148
|
+
const bestGeneralModel = recommended.find((m) => m.category === 'general');
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
totalRamGb,
|
|
152
|
+
cpuModel,
|
|
153
|
+
cores,
|
|
154
|
+
platform,
|
|
155
|
+
arch,
|
|
156
|
+
isAppleSilicon,
|
|
157
|
+
gpu,
|
|
158
|
+
recommended: { code: bestCodeModel?.id || null, general: bestGeneralModel?.id || null },
|
|
159
|
+
maxModelRam: totalRamGb,
|
|
38
160
|
};
|
|
39
161
|
}
|
|
40
162
|
|
|
41
163
|
static getInstalledModels() {
|
|
42
164
|
try {
|
|
43
|
-
const output = execSync('ollama list', { encoding: 'utf8' });
|
|
165
|
+
const output = execSync('ollama list', { encoding: 'utf8', timeout: 10000 });
|
|
44
166
|
const lines = output.split('\n').slice(1).filter(Boolean);
|
|
45
167
|
return lines.map((line) => {
|
|
46
168
|
const parts = line.split(/\s+/);
|
|
47
|
-
|
|
169
|
+
const name = parts[0];
|
|
170
|
+
const size = parts[2] || parts[1] || '';
|
|
171
|
+
// Match against catalog for metadata
|
|
172
|
+
const catalogEntry = MODEL_CATALOG.find((m) => name.startsWith(m.id.split(':')[0]));
|
|
173
|
+
return { id: name, name, size, category: catalogEntry?.category || 'other', tier: catalogEntry?.tier || 'medium' };
|
|
48
174
|
});
|
|
49
175
|
} catch {
|
|
50
176
|
return [];
|
|
51
177
|
}
|
|
52
178
|
}
|
|
53
179
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
180
|
+
static pullModel(modelId, onProgress) {
|
|
181
|
+
return new Promise((resolve, reject) => {
|
|
182
|
+
const child = execFile('ollama', ['pull', modelId], { timeout: 600000 }, (err) => {
|
|
183
|
+
if (err) reject(err);
|
|
184
|
+
else resolve({ success: true, model: modelId });
|
|
185
|
+
});
|
|
186
|
+
if (child.stderr && onProgress) {
|
|
187
|
+
child.stderr.on('data', (data) => onProgress(data.toString()));
|
|
188
|
+
}
|
|
189
|
+
if (child.stdout && onProgress) {
|
|
190
|
+
child.stdout.on('data', (data) => onProgress(data.toString()));
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
57
194
|
|
|
58
|
-
|
|
59
|
-
|
|
195
|
+
static deleteModel(modelId) {
|
|
196
|
+
try {
|
|
197
|
+
execSync(`ollama rm ${modelId}`, { encoding: 'utf8', timeout: 30000 });
|
|
198
|
+
return true;
|
|
199
|
+
} catch {
|
|
200
|
+
return false;
|
|
60
201
|
}
|
|
202
|
+
}
|
|
61
203
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
};
|
|
204
|
+
buildSpawnCommand(agent) {
|
|
205
|
+
const model = agent.model || 'qwen2.5-coder:7b';
|
|
206
|
+
const args = ['run', model];
|
|
207
|
+
if (agent.prompt) args.push(agent.prompt);
|
|
208
|
+
return { command: 'ollama', args, env: { OLLAMA_API_BASE: 'http://localhost:11434' } };
|
|
67
209
|
}
|
|
68
210
|
|
|
69
211
|
buildHeadlessCommand(prompt, model) {
|
|
70
212
|
const m = model || 'qwen2.5-coder:7b';
|
|
71
|
-
return {
|
|
72
|
-
command: 'ollama',
|
|
73
|
-
args: ['run', m, prompt],
|
|
74
|
-
env: {},
|
|
75
|
-
};
|
|
213
|
+
return { command: 'ollama', args: ['run', m, prompt], env: {} };
|
|
76
214
|
}
|
|
77
215
|
|
|
78
216
|
switchModel(agent, newModel) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"projectName": "gui",
|
|
3
|
-
"scannedAt": "2026-04-09T05:
|
|
3
|
+
"scannedAt": "2026-04-09T05:52:27.246Z",
|
|
4
4
|
"stats": {
|
|
5
|
-
"totalFiles":
|
|
5
|
+
"totalFiles": 85,
|
|
6
6
|
"totalDirs": 14,
|
|
7
7
|
"treeDepth": 4
|
|
8
8
|
},
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"path": "src/components/agents",
|
|
67
67
|
"depth": 3,
|
|
68
68
|
"dirs": 0,
|
|
69
|
-
"files":
|
|
69
|
+
"files": 15,
|
|
70
70
|
"children": []
|
|
71
71
|
},
|
|
72
72
|
{
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
127.0.0.1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
55857
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"status": "stopped",
|
|
17
17
|
"pid": null,
|
|
18
18
|
"spawnedAt": "2026-04-09T02:46:11.349Z",
|
|
19
|
-
"lastActivity": "2026-04-09T05:
|
|
19
|
+
"lastActivity": "2026-04-09T05:32:30.003Z",
|
|
20
20
|
"tokensUsed": 41952,
|
|
21
21
|
"contextUsage": 0.020954,
|
|
22
22
|
"sessionId": "b870e8f8-84b1-4ad2-a0d3-fef8035466c0",
|