groove-dev 0.27.121 → 0.27.123
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/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 +3 -3
- package/node_modules/@groove-dev/daemon/src/index.js +12 -4
- package/node_modules/@groove-dev/daemon/src/introducer.js +3 -4
- package/node_modules/@groove-dev/daemon/src/teams.js +11 -5
- package/node_modules/@groove-dev/daemon/src/tunnel-manager.js +20 -13
- package/node_modules/@groove-dev/gui/dist/assets/{index-bmkBX18f.js → index-BcmoHTm0.js} +1745 -1745
- package/node_modules/@groove-dev/gui/dist/assets/index-DWI-g_Sm.css +1 -0
- 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/components/settings/quick-connect.jsx +9 -1
- package/node_modules/@groove-dev/gui/src/components/teams/team-removal-dialog.jsx +36 -2
- package/node_modules/@groove-dev/gui/src/stores/groove.js +21 -10
- package/node_modules/@groove-dev/gui/src/views/agents.jsx +62 -9
- package/node_modules/@groove-dev/gui/src/views/teams.jsx +2 -1
- 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 +3 -3
- package/packages/daemon/src/index.js +12 -4
- package/packages/daemon/src/introducer.js +3 -4
- package/packages/daemon/src/teams.js +11 -5
- package/packages/daemon/src/tunnel-manager.js +20 -13
- package/packages/gui/dist/assets/{index-bmkBX18f.js → index-BcmoHTm0.js} +1745 -1745
- package/packages/gui/dist/assets/index-DWI-g_Sm.css +1 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/packages/gui/src/components/settings/quick-connect.jsx +9 -1
- package/packages/gui/src/components/teams/team-removal-dialog.jsx +36 -2
- package/packages/gui/src/stores/groove.js +21 -10
- package/packages/gui/src/views/agents.jsx +62 -9
- package/packages/gui/src/views/teams.jsx +2 -1
- package/node_modules/@groove-dev/gui/dist/assets/index-BLd3MON8.css +0 -1
- package/packages/gui/dist/assets/index-BLd3MON8.css +0 -1
|
@@ -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
|
|
1153
|
-
daemon.audit.log('team.promote', { id:
|
|
1154
|
-
res.json(
|
|
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
|
}
|
|
@@ -295,8 +295,12 @@ export class Daemon {
|
|
|
295
295
|
if (this._registryIoTimer) return;
|
|
296
296
|
this._registryIoTimer = setTimeout(() => {
|
|
297
297
|
this._registryIoTimer = null;
|
|
298
|
-
|
|
299
|
-
|
|
298
|
+
try {
|
|
299
|
+
this.introducer.writeRegistryFile(this.projectDir);
|
|
300
|
+
this.introducer.injectGrooveSection(this.projectDir);
|
|
301
|
+
} catch (err) {
|
|
302
|
+
console.error('[registry-io] Failed to update registry files:', err.message);
|
|
303
|
+
}
|
|
300
304
|
}, 2000);
|
|
301
305
|
};
|
|
302
306
|
|
|
@@ -765,8 +769,12 @@ export class Daemon {
|
|
|
765
769
|
// 5. Refresh journalist context — regenerate project map and registry
|
|
766
770
|
// so stale agent references don't persist in GROOVE_PROJECT_MAP.md
|
|
767
771
|
if (cleaned > 0) {
|
|
768
|
-
|
|
769
|
-
|
|
772
|
+
try {
|
|
773
|
+
this.introducer.writeRegistryFile(this.projectDir);
|
|
774
|
+
this.introducer.injectGrooveSection(this.projectDir);
|
|
775
|
+
} catch (err) {
|
|
776
|
+
console.error('[registry-io] Failed to refresh registry during GC:', err.message);
|
|
777
|
+
}
|
|
770
778
|
// Clear journalist's stale in-memory state for removed agents
|
|
771
779
|
this.journalist.lastLogSizes = Object.fromEntries(
|
|
772
780
|
Object.entries(this.journalist.lastLogSizes).filter(([id]) => {
|
|
@@ -477,7 +477,7 @@ export class Introducer {
|
|
|
477
477
|
if (agents.length === 0) {
|
|
478
478
|
const regPath = resolve(projectDir, 'AGENTS_REGISTRY.md');
|
|
479
479
|
if (existsSync(regPath)) {
|
|
480
|
-
writeFileSync(regPath, '');
|
|
480
|
+
try { writeFileSync(regPath, ''); } catch { /* dir may be gone */ }
|
|
481
481
|
}
|
|
482
482
|
return;
|
|
483
483
|
}
|
|
@@ -494,6 +494,7 @@ export class Introducer {
|
|
|
494
494
|
for (const [teamId, teamAgents] of teamGroups) {
|
|
495
495
|
const team = teamId !== '_default' ? this.daemon.teams?.get(teamId) : null;
|
|
496
496
|
const dir = team?.workingDir || projectDir;
|
|
497
|
+
if (!existsSync(dir)) continue;
|
|
497
498
|
|
|
498
499
|
const lines = [
|
|
499
500
|
`# AGENTS REGISTRY`,
|
|
@@ -518,9 +519,7 @@ export class Introducer {
|
|
|
518
519
|
}
|
|
519
520
|
|
|
520
521
|
injectGrooveSection(projectDir) {
|
|
521
|
-
|
|
522
|
-
// This section is delimited by markers so we can update it without
|
|
523
|
-
// clobbering the user's content.
|
|
522
|
+
if (!existsSync(projectDir)) return;
|
|
524
523
|
const claudeMdPath = resolve(projectDir, 'CLAUDE.md');
|
|
525
524
|
const agents = this.daemon.registry.getAll();
|
|
526
525
|
|
|
@@ -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:
|
|
391
|
-
|
|
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=
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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
|
|
|
@@ -446,7 +449,11 @@ export class TunnelManager {
|
|
|
446
449
|
this.daemon.broadcast({ type: 'tunnel.version-mismatch', data: { id, localVersion: localVer, remoteVersion: installedVer, message: 'Pinned version not available on npm, installed latest' } });
|
|
447
450
|
}
|
|
448
451
|
|
|
449
|
-
const
|
|
452
|
+
const cdPrefix = config.projectDir ? `cd "${config.projectDir}" && ` : '';
|
|
453
|
+
const setProjectDir = config.projectDir
|
|
454
|
+
? `curl -sf -X POST -H 'Content-Type: application/json' --data '{"path":"${config.projectDir}"}' http://localhost:${REMOTE_PORT}/api/project-dir > /dev/null 2>&1 || true; `
|
|
455
|
+
: '';
|
|
456
|
+
const restartCmd = `kill $(lsof -t -i:${REMOTE_PORT}) 2>/dev/null || true; sleep 2; ${cdPrefix}GROOVE_BIN=$(which groove) && nohup "$GROOVE_BIN" start > /tmp/groove-daemon.log 2>&1 < /dev/null & disown; sleep 4; curl -sf http://localhost:${REMOTE_PORT}/api/status && (${setProjectDir}true) || true`;
|
|
450
457
|
const restartResult = execFileSync('ssh', [...sshBase, sshCmd(restartCmd)], {
|
|
451
458
|
encoding: 'utf8',
|
|
452
459
|
timeout: 60000,
|