groove-dev 0.27.120 → 0.27.122

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.
Files changed (35) hide show
  1. package/node_modules/@groove-dev/cli/package.json +1 -1
  2. package/node_modules/@groove-dev/daemon/package.json +1 -1
  3. package/node_modules/@groove-dev/daemon/src/api.js +3 -3
  4. package/node_modules/@groove-dev/daemon/src/index.js +1 -2
  5. package/node_modules/@groove-dev/daemon/src/teams.js +11 -5
  6. package/node_modules/@groove-dev/daemon/src/tunnel-manager.js +15 -12
  7. package/node_modules/@groove-dev/gui/dist/assets/{index-oKbzuMnX.js → index-BcmoHTm0.js} +1745 -1745
  8. package/node_modules/@groove-dev/gui/dist/assets/index-DWI-g_Sm.css +1 -0
  9. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  10. package/node_modules/@groove-dev/gui/package.json +1 -1
  11. package/node_modules/@groove-dev/gui/src/components/layout/status-bar.jsx +8 -10
  12. package/node_modules/@groove-dev/gui/src/components/settings/quick-connect.jsx +9 -1
  13. package/node_modules/@groove-dev/gui/src/components/teams/team-removal-dialog.jsx +36 -2
  14. package/node_modules/@groove-dev/gui/src/stores/groove.js +21 -10
  15. package/node_modules/@groove-dev/gui/src/views/agents.jsx +62 -9
  16. package/node_modules/@groove-dev/gui/src/views/teams.jsx +2 -1
  17. package/package.json +1 -1
  18. package/packages/cli/package.json +1 -1
  19. package/packages/daemon/package.json +1 -1
  20. package/packages/daemon/src/api.js +3 -3
  21. package/packages/daemon/src/index.js +1 -2
  22. package/packages/daemon/src/teams.js +11 -5
  23. package/packages/daemon/src/tunnel-manager.js +15 -12
  24. package/packages/gui/dist/assets/{index-oKbzuMnX.js → index-BcmoHTm0.js} +1745 -1745
  25. package/packages/gui/dist/assets/index-DWI-g_Sm.css +1 -0
  26. package/packages/gui/dist/index.html +2 -2
  27. package/packages/gui/package.json +1 -1
  28. package/packages/gui/src/components/layout/status-bar.jsx +8 -10
  29. package/packages/gui/src/components/settings/quick-connect.jsx +9 -1
  30. package/packages/gui/src/components/teams/team-removal-dialog.jsx +36 -2
  31. package/packages/gui/src/stores/groove.js +21 -10
  32. package/packages/gui/src/views/agents.jsx +62 -9
  33. package/packages/gui/src/views/teams.jsx +2 -1
  34. package/node_modules/@groove-dev/gui/dist/assets/index-BLd3MON8.css +0 -1
  35. package/packages/gui/dist/assets/index-BLd3MON8.css +0 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/cli",
3
- "version": "0.27.120",
3
+ "version": "0.27.122",
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.120",
3
+ "version": "0.27.122",
4
4
  "description": "GROOVE daemon — agent orchestration engine",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -1149,9 +1149,9 @@ export function createApi(app, daemon) {
1149
1149
 
1150
1150
  app.post('/api/teams/:id/promote', (req, res) => {
1151
1151
  try {
1152
- const team = daemon.teams.promote(req.params.id);
1153
- daemon.audit.log('team.promote', { id: team.id, name: team.name });
1154
- res.json(team);
1152
+ const result = daemon.teams.promote(req.params.id);
1153
+ daemon.audit.log('team.promote', { id: req.params.id, destination: result.destination });
1154
+ res.json(result);
1155
1155
  } catch (err) {
1156
1156
  res.status(400).json({ error: err.message });
1157
1157
  }
@@ -5,7 +5,6 @@ import { createServer as createHttpServer, request as httpProxyRequest } from 'h
5
5
  import { createServer as createNetServer } from 'net';
6
6
  import { execFileSync } from 'child_process';
7
7
  import { resolve } from 'path';
8
- import { homedir } from 'os';
9
8
  import { readFileSync, writeFileSync, unlinkSync, existsSync, mkdirSync, readdirSync, rmdirSync, rmSync, statSync } from 'fs';
10
9
  import express from 'express';
11
10
  import { WebSocketServer } from 'ws';
@@ -95,7 +94,7 @@ export class Daemon {
95
94
  this.port = options.port !== undefined ? options.port : (parseInt(process.env.GROOVE_PORT, 10) || DEFAULT_PORT);
96
95
  this.host = resolveHost(options.host);
97
96
  this.projectDir = options.projectDir || process.cwd();
98
- this.grooveDir = options.grooveDir || resolve(homedir(), '.groove');
97
+ this.grooveDir = options.grooveDir || resolve(this.projectDir, '.groove');
99
98
  this.pidFile = resolve(this.grooveDir, 'daemon.pid');
100
99
 
101
100
  // Ensure .groove directories exist
@@ -376,9 +376,6 @@ export class Teams {
376
376
 
377
377
  rmSync(oldDir, { recursive: true, force: true });
378
378
 
379
- team.workingDir = targetDir;
380
- team.mode = 'production';
381
-
382
379
  const agents = this.daemon.registry.getAll().filter((a) => a.teamId === id);
383
380
  for (const agent of agents) {
384
381
  if (agent.workingDir === oldDir) {
@@ -386,9 +383,18 @@ export class Teams {
386
383
  }
387
384
  }
388
385
 
386
+ const wasDefault = team.isDefault;
387
+ this.teams.delete(id);
389
388
  this._save();
390
- this.daemon.broadcast({ type: 'team:updated', team });
391
- return team;
389
+ this.daemon.broadcast({ type: 'team:deleted', teamId: id });
390
+
391
+ if (wasDefault) {
392
+ this._ensureDefault();
393
+ const fresh = this.getDefault();
394
+ if (fresh) this.daemon.broadcast({ type: 'team:created', team: fresh });
395
+ }
396
+
397
+ return { promoted: true, destination: targetDir };
392
398
  }
393
399
 
394
400
  // Backward compat stubs
@@ -216,14 +216,14 @@ export class TunnelManager {
216
216
  const result = execFileSync('ssh', [
217
217
  ...keyArgs,
218
218
  '-p', String(config.port || 22),
219
- '-o', 'ConnectTimeout=10',
219
+ '-o', 'ConnectTimeout=5',
220
220
  '-o', 'StrictHostKeyChecking=accept-new',
221
221
  '-o', 'BatchMode=yes',
222
222
  target,
223
223
  sshCmd(`S=$(curl -sf http://localhost:${REMOTE_PORT}/api/status 2>/dev/null); if [ -n "$S" ]; then echo "__GROOVE_RUNNING__$S__GROOVE_END__"; else which groove >/dev/null 2>&1 && echo __GROOVE_VER__$(groove --version 2>/dev/null || echo unknown)__GROOVE_STOPPED__ || echo __GROOVE_NOT_INSTALLED__; fi`),
224
224
  ], {
225
225
  encoding: 'utf8',
226
- timeout: 20000,
226
+ timeout: 15000,
227
227
  stdio: ['pipe', 'pipe', 'pipe'],
228
228
  });
229
229
 
@@ -267,6 +267,8 @@ export class TunnelManager {
267
267
  let testResult;
268
268
  if (opts.skipTest && opts.testResult) {
269
269
  testResult = opts.testResult;
270
+ } else if (config.lastConnected && opts.skipTest !== false) {
271
+ testResult = { reachable: true, daemonRunning: true, grooveInstalled: true, remoteVersion: null };
270
272
  } else {
271
273
  testResult = await this.test(id);
272
274
  }
@@ -345,19 +347,20 @@ export class TunnelManager {
345
347
  failCount: 0,
346
348
  });
347
349
 
348
- if (!preConnectHandled) {
350
+ const skipUpgrade = testResult.daemonRunning && testResult.remoteVersion && testResult.remoteVersion === getLocalVersion();
351
+ if (!preConnectHandled && !skipUpgrade) {
349
352
  await this._checkAndUpgradeRunning(id, config, localPort);
350
353
  }
351
354
 
352
- try {
353
- const statusResp = await fetch(`http://localhost:${localPort}/api/status`, { signal: AbortSignal.timeout(5000) });
354
- if (statusResp.ok) {
355
- const statusData = await statusResp.json();
356
- const remoteVer = statusData.version;
357
- const localVer = getLocalVersion();
358
- this.daemon.broadcast({ type: 'tunnel.version-info', data: { id, localVersion: localVer, remoteVersion: remoteVer, match: remoteVer === localVer } });
359
- }
360
- } catch { /* non-fatal */ }
355
+ const remoteVer = testResult?.remoteVersion || null;
356
+ const localVer = getLocalVersion();
357
+ if (remoteVer) {
358
+ this.daemon.broadcast({ type: 'tunnel.version-info', data: { id, localVersion: localVer, remoteVersion: remoteVer, match: remoteVer === localVer } });
359
+ }
360
+
361
+ config.lastConnected = new Date().toISOString();
362
+ this.saved.set(id, config);
363
+ this._save();
361
364
 
362
365
  const url = `http://localhost:${localPort}?instance=${encodeURIComponent(config.name)}`;
363
366