groove-dev 0.27.146 → 0.27.148

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 CHANGED
@@ -295,10 +295,3 @@ Audit-driven release. Multi-agent orchestration system with 7 coordination layer
295
295
  - Dashboard: routing donut, cache panel, context health gauges
296
296
  - Monitor/QC agent mode (stay active, loop)
297
297
  - Distribution: demo video, HN launch, Twitter content
298
-
299
- <!-- GROOVE:START -->
300
- ## GROOVE Orchestration (auto-injected)
301
- Active agents: 0
302
- See AGENTS_REGISTRY.md for full agent state.
303
- **Memory policy:** GROOVE manages project memory automatically. Do not read or write MEMORY.md or .groove/memory/ files directly.
304
- <!-- GROOVE:END -->
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/cli",
3
- "version": "0.27.146",
3
+ "version": "0.27.148",
4
4
  "description": "GROOVE CLI — manage AI coding agents from your terminal",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/daemon",
3
- "version": "0.27.146",
3
+ "version": "0.27.148",
4
4
  "description": "GROOVE daemon — agent orchestration engine",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -175,6 +175,12 @@ export class ModelLab {
175
175
  const rt = this.runtimes.get(id);
176
176
  if (!rt) throw new Error('Runtime not found');
177
177
 
178
+ // Clear disconnected flag on start/reconnect
179
+ if (rt._disconnected) {
180
+ delete rt._disconnected;
181
+ this._saveRuntimes();
182
+ }
183
+
178
184
  // MLX runtimes — use built-in MLXServerManager
179
185
  if (rt.type === 'mlx' && !rt.launchConfig) {
180
186
  const modelId = rt._mlxModelId || this._deriveModelId(rt, 'MLX - ');
@@ -208,7 +214,16 @@ export class ModelLab {
208
214
  }
209
215
 
210
216
  // Generic launchConfig runtimes (vLLM, TGI, etc.)
211
- if (!rt.launchConfig) throw new Error('No launch config — use the assistant to set up this runtime first');
217
+ if (!rt.launchConfig) {
218
+ // Remote runtime — "start" means reconnect; verify it's reachable
219
+ const status = await this.getRuntimeStatus(rt);
220
+ if (status.online) {
221
+ this.daemon.broadcast({ type: 'lab:runtime:started', data: { id } });
222
+ this.daemon.audit.log('lab.runtime.start', { id, name: rt.name });
223
+ return rt;
224
+ }
225
+ throw new Error('Remote server is not reachable — start the server manually and try again');
226
+ }
212
227
  if (this._processes.has(id)) throw new Error('Server already running');
213
228
 
214
229
  const lc = rt.launchConfig;
@@ -268,12 +283,14 @@ export class ModelLab {
268
283
  const rt = this.runtimes.get(id);
269
284
  if (!rt) throw new Error('Runtime not found');
270
285
 
286
+ let killed = false;
287
+
271
288
  if (rt._localModelId) {
272
289
  const mm = this.daemon.modelManager;
273
290
  const ls = this.daemon.llamaServer;
274
291
  if (mm && ls) {
275
292
  const modelPath = mm.getModelPath(rt._localModelId);
276
- if (modelPath) await ls.stopServer(modelPath);
293
+ if (modelPath) { await ls.stopServer(modelPath); killed = true; }
277
294
  }
278
295
  }
279
296
 
@@ -281,7 +298,7 @@ export class ModelLab {
281
298
  const ms = this.daemon.mlxServer;
282
299
  if (ms) {
283
300
  const hfId = rt._mlxModelId.startsWith('mlx:') ? rt._mlxModelId.slice(4) : rt._mlxModelId;
284
- await ms.stopServer(hfId);
301
+ await ms.stopServer(hfId); killed = true;
285
302
  }
286
303
  }
287
304
 
@@ -293,6 +310,13 @@ export class ModelLab {
293
310
  try { proc.kill('SIGTERM'); } catch { clearTimeout(timeout); resolve(); }
294
311
  });
295
312
  this._processes.delete(id);
313
+ killed = true;
314
+ }
315
+
316
+ // Remote/external runtimes: mark as disconnected so status checks treat it as offline
317
+ if (!killed) {
318
+ rt._disconnected = true;
319
+ this._saveRuntimes();
296
320
  }
297
321
 
298
322
  this.daemon.broadcast({ type: 'lab:runtime:stopped', data: { id } });
@@ -370,6 +394,7 @@ export class ModelLab {
370
394
  }
371
395
 
372
396
  async getRuntimeStatus(rt) {
397
+ if (rt._disconnected) return { online: false, latency: null };
373
398
  try {
374
399
  const start = Date.now();
375
400
  const ep = localURL(rt.endpoint);
@@ -1128,7 +1128,7 @@ For normal file edits within your scope, proceed without review.
1128
1128
 
1129
1129
  const loop = new AgentLoop({ daemon: this.daemon, agent, loopConfig, logStream });
1130
1130
  this.handles.set(agent.id, { loop, logStream });
1131
- registry.update(agent.id, { status: 'running' });
1131
+ registry.update(agent.id, { status: 'running', model: loopConfig.model, apiBase: loopConfig.apiBase });
1132
1132
 
1133
1133
  // Record spawn lifecycle event
1134
1134
  if (this.daemon.timeline) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/gui",
3
- "version": "0.27.146",
3
+ "version": "0.27.148",
4
4
  "description": "GROOVE GUI — visual agent control plane",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groove-dev",
3
- "version": "0.27.146",
3
+ "version": "0.27.148",
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)",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/cli",
3
- "version": "0.27.146",
3
+ "version": "0.27.148",
4
4
  "description": "GROOVE CLI — manage AI coding agents from your terminal",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/daemon",
3
- "version": "0.27.146",
3
+ "version": "0.27.148",
4
4
  "description": "GROOVE daemon — agent orchestration engine",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -175,6 +175,12 @@ export class ModelLab {
175
175
  const rt = this.runtimes.get(id);
176
176
  if (!rt) throw new Error('Runtime not found');
177
177
 
178
+ // Clear disconnected flag on start/reconnect
179
+ if (rt._disconnected) {
180
+ delete rt._disconnected;
181
+ this._saveRuntimes();
182
+ }
183
+
178
184
  // MLX runtimes — use built-in MLXServerManager
179
185
  if (rt.type === 'mlx' && !rt.launchConfig) {
180
186
  const modelId = rt._mlxModelId || this._deriveModelId(rt, 'MLX - ');
@@ -208,7 +214,16 @@ export class ModelLab {
208
214
  }
209
215
 
210
216
  // Generic launchConfig runtimes (vLLM, TGI, etc.)
211
- if (!rt.launchConfig) throw new Error('No launch config — use the assistant to set up this runtime first');
217
+ if (!rt.launchConfig) {
218
+ // Remote runtime — "start" means reconnect; verify it's reachable
219
+ const status = await this.getRuntimeStatus(rt);
220
+ if (status.online) {
221
+ this.daemon.broadcast({ type: 'lab:runtime:started', data: { id } });
222
+ this.daemon.audit.log('lab.runtime.start', { id, name: rt.name });
223
+ return rt;
224
+ }
225
+ throw new Error('Remote server is not reachable — start the server manually and try again');
226
+ }
212
227
  if (this._processes.has(id)) throw new Error('Server already running');
213
228
 
214
229
  const lc = rt.launchConfig;
@@ -268,12 +283,14 @@ export class ModelLab {
268
283
  const rt = this.runtimes.get(id);
269
284
  if (!rt) throw new Error('Runtime not found');
270
285
 
286
+ let killed = false;
287
+
271
288
  if (rt._localModelId) {
272
289
  const mm = this.daemon.modelManager;
273
290
  const ls = this.daemon.llamaServer;
274
291
  if (mm && ls) {
275
292
  const modelPath = mm.getModelPath(rt._localModelId);
276
- if (modelPath) await ls.stopServer(modelPath);
293
+ if (modelPath) { await ls.stopServer(modelPath); killed = true; }
277
294
  }
278
295
  }
279
296
 
@@ -281,7 +298,7 @@ export class ModelLab {
281
298
  const ms = this.daemon.mlxServer;
282
299
  if (ms) {
283
300
  const hfId = rt._mlxModelId.startsWith('mlx:') ? rt._mlxModelId.slice(4) : rt._mlxModelId;
284
- await ms.stopServer(hfId);
301
+ await ms.stopServer(hfId); killed = true;
285
302
  }
286
303
  }
287
304
 
@@ -293,6 +310,13 @@ export class ModelLab {
293
310
  try { proc.kill('SIGTERM'); } catch { clearTimeout(timeout); resolve(); }
294
311
  });
295
312
  this._processes.delete(id);
313
+ killed = true;
314
+ }
315
+
316
+ // Remote/external runtimes: mark as disconnected so status checks treat it as offline
317
+ if (!killed) {
318
+ rt._disconnected = true;
319
+ this._saveRuntimes();
296
320
  }
297
321
 
298
322
  this.daemon.broadcast({ type: 'lab:runtime:stopped', data: { id } });
@@ -370,6 +394,7 @@ export class ModelLab {
370
394
  }
371
395
 
372
396
  async getRuntimeStatus(rt) {
397
+ if (rt._disconnected) return { online: false, latency: null };
373
398
  try {
374
399
  const start = Date.now();
375
400
  const ep = localURL(rt.endpoint);
@@ -1128,7 +1128,7 @@ For normal file edits within your scope, proceed without review.
1128
1128
 
1129
1129
  const loop = new AgentLoop({ daemon: this.daemon, agent, loopConfig, logStream });
1130
1130
  this.handles.set(agent.id, { loop, logStream });
1131
- registry.update(agent.id, { status: 'running' });
1131
+ registry.update(agent.id, { status: 'running', model: loopConfig.model, apiBase: loopConfig.apiBase });
1132
1132
 
1133
1133
  // Record spawn lifecycle event
1134
1134
  if (this.daemon.timeline) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/gui",
3
- "version": "0.27.146",
3
+ "version": "0.27.148",
4
4
  "description": "GROOVE GUI — visual agent control plane",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",