groove-dev 0.27.168 → 0.27.169
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/index.js +15 -2
- package/node_modules/@groove-dev/daemon/src/process.js +1 -1
- package/node_modules/@groove-dev/daemon/src/providers/claude-code.js +7 -1
- package/node_modules/@groove-dev/daemon/src/registry.js +3 -0
- package/node_modules/@groove-dev/daemon/src/state.js +7 -2
- package/node_modules/@groove-dev/daemon/src/validate.js +1 -0
- package/node_modules/@groove-dev/gui/dist/assets/{index-CSMIQsrG.js → index-BcWo4sq-.js} +140 -140
- package/node_modules/@groove-dev/gui/dist/assets/index-BvXojcnr.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/agents/agent-feed.jsx +6 -0
- package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +30 -1
- package/node_modules/@groove-dev/gui/src/components/editor/terminal.jsx +64 -42
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/index.js +15 -2
- package/packages/daemon/src/process.js +1 -1
- package/packages/daemon/src/providers/claude-code.js +7 -1
- package/packages/daemon/src/registry.js +3 -0
- package/packages/daemon/src/state.js +7 -2
- package/packages/daemon/src/validate.js +1 -0
- package/packages/gui/dist/assets/{index-CSMIQsrG.js → index-BcWo4sq-.js} +140 -140
- package/packages/gui/dist/assets/index-BvXojcnr.css +1 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/packages/gui/src/components/agents/agent-feed.jsx +6 -0
- package/packages/gui/src/components/agents/spawn-wizard.jsx +30 -1
- package/packages/gui/src/components/editor/terminal.jsx +64 -42
- package/node_modules/@groove-dev/gui/dist/assets/index-BJVNpGIp.css +0 -1
- package/packages/gui/dist/assets/index-BJVNpGIp.css +0 -1
- package/ssh/error.png +0 -0
- package/terminal/Screenshot_2026-05-19_at_12.20.15_PM.png +0 -0
|
@@ -717,9 +717,22 @@ export class Daemon {
|
|
|
717
717
|
this._gc();
|
|
718
718
|
this._gcInterval = setInterval(() => this._gc(), 24 * 60 * 60 * 1000);
|
|
719
719
|
|
|
720
|
-
// Periodic state save — crash protection (every
|
|
720
|
+
// Periodic state save — crash protection (every 5s)
|
|
721
|
+
this._lastSavedAgentCount = this.registry.getAll().length;
|
|
721
722
|
this._stateSaveInterval = setInterval(async () => {
|
|
722
|
-
try {
|
|
723
|
+
try {
|
|
724
|
+
const agents = this.registry.getAll();
|
|
725
|
+
// Safety: never overwrite a populated state with an empty one.
|
|
726
|
+
// An empty registry while agents existed before signals a bug, not
|
|
727
|
+
// legitimate cleanup — skip the save so .bak stays valid.
|
|
728
|
+
if (agents.length === 0 && this._lastSavedAgentCount > 0) {
|
|
729
|
+
console.warn(`[Groove:State] Skipping save — registry unexpectedly empty (was ${this._lastSavedAgentCount} agents). This prevents silent data loss.`);
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
this._lastSavedAgentCount = agents.length;
|
|
733
|
+
this.state.set('agents', agents);
|
|
734
|
+
await this.state.save();
|
|
735
|
+
} catch {}
|
|
723
736
|
}, 5000);
|
|
724
737
|
}
|
|
725
738
|
|
|
@@ -2526,7 +2526,7 @@ After fixing all issues, run tests (npm test) and build (npm run build) to verif
|
|
|
2526
2526
|
locks.release(agentId);
|
|
2527
2527
|
|
|
2528
2528
|
// Build resume command
|
|
2529
|
-
const { command: rawCommand, args, env } = provider.buildResumeCommand(sessionId, message, config.model);
|
|
2529
|
+
const { command: rawCommand, args, env } = provider.buildResumeCommand(sessionId, message, config.model, { fast: config.fast });
|
|
2530
2530
|
const command = resolveProviderCommand(config.provider || 'claude-code') || rawCommand;
|
|
2531
2531
|
|
|
2532
2532
|
// Set up log capture
|
|
@@ -39,6 +39,7 @@ export class ClaudeCodeProvider extends Provider {
|
|
|
39
39
|
static authType = 'subscription';
|
|
40
40
|
static managesOwnContext = true; // Claude Code compacts context internally (~25-37% → 2-8%)
|
|
41
41
|
static models = [
|
|
42
|
+
{ id: 'claude-opus-4-8', name: 'Claude Opus 4.8', tier: 'heavy', contextWindow: 1_000_000 },
|
|
42
43
|
{ id: 'claude-opus-4-6', name: 'Claude Opus 4.6', tier: 'heavy', contextWindow: 1_000_000 },
|
|
43
44
|
{ id: 'claude-sonnet-4-6', name: 'Claude Sonnet 4.6', tier: 'medium', contextWindow: 200_000 },
|
|
44
45
|
{ id: 'claude-haiku-4-5-20251001', name: 'Claude Haiku 4.5', tier: 'light', contextWindow: 200_000 },
|
|
@@ -104,6 +105,10 @@ export class ClaudeCodeProvider extends Provider {
|
|
|
104
105
|
args.push('--effort', agent.effort);
|
|
105
106
|
}
|
|
106
107
|
|
|
108
|
+
if (agent.fast) {
|
|
109
|
+
args.push('--fast');
|
|
110
|
+
}
|
|
111
|
+
|
|
107
112
|
// Pass the initial prompt as positional arg (includes GROOVE context)
|
|
108
113
|
const fullPrompt = this.buildFullPrompt(agent);
|
|
109
114
|
if (fullPrompt) {
|
|
@@ -117,13 +122,14 @@ export class ClaudeCodeProvider extends Provider {
|
|
|
117
122
|
};
|
|
118
123
|
}
|
|
119
124
|
|
|
120
|
-
buildResumeCommand(sessionId, prompt, model) {
|
|
125
|
+
buildResumeCommand(sessionId, prompt, model, options = {}) {
|
|
121
126
|
// Resume a previous session — preserves full conversation history
|
|
122
127
|
// No cold start, no handoff brief needed
|
|
123
128
|
const args = ['--resume', sessionId, '--output-format', 'stream-json', '--verbose', '--dangerously-skip-permissions'];
|
|
124
129
|
const knockSettings = ClaudeCodeProvider._buildKnockSettings();
|
|
125
130
|
if (knockSettings) args.push('--settings', knockSettings);
|
|
126
131
|
if (model) args.push('--model', model);
|
|
132
|
+
if (options.fast) args.push('--fast');
|
|
127
133
|
if (prompt) args.push(prompt);
|
|
128
134
|
return { command: 'claude', args, env: {} };
|
|
129
135
|
}
|
|
@@ -97,6 +97,9 @@ export class Registry extends EventEmitter {
|
|
|
97
97
|
const agent = this.agents.get(id);
|
|
98
98
|
if (!agent) return false;
|
|
99
99
|
|
|
100
|
+
const caller = new Error().stack.split('\n').slice(1, 4).map(l => l.trim()).join(' <- ');
|
|
101
|
+
console.log(`[Groove:Registry] REMOVE agent ${agent.name} (${id}) role=${agent.role} status=${agent.status} team=${agent.teamId} silent=${silent} | ${caller}`);
|
|
102
|
+
|
|
100
103
|
this.agents.delete(id);
|
|
101
104
|
if (silent) {
|
|
102
105
|
this._pendingRemovals.push(id);
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
import { readFileSync, writeFileSync, existsSync, readdirSync, unlinkSync, renameSync, copyFileSync } from 'fs';
|
|
5
5
|
import { writeFile } from 'node:fs/promises';
|
|
6
|
-
import { resolve } from 'path';
|
|
6
|
+
import { resolve, dirname } from 'path';
|
|
7
|
+
import { randomUUID } from 'crypto';
|
|
7
8
|
|
|
8
9
|
export class StateManager {
|
|
9
10
|
constructor(grooveDir) {
|
|
@@ -39,7 +40,11 @@ export class StateManager {
|
|
|
39
40
|
if (existsSync(this.path)) {
|
|
40
41
|
try { copyFileSync(this.path, this.backupPath); } catch { /* non-fatal */ }
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
+
// Atomic write: write to temp file, then rename (rename is atomic on POSIX).
|
|
44
|
+
// Prevents SIGKILL during write from leaving state.json truncated/empty.
|
|
45
|
+
const tmpPath = resolve(dirname(this.path), `state.${randomUUID().slice(0, 8)}.tmp`);
|
|
46
|
+
await writeFile(tmpPath, JSON.stringify(this.data, null, 2));
|
|
47
|
+
renameSync(tmpPath, this.path);
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
get(key) {
|
|
@@ -139,6 +139,7 @@ export function validateAgentConfig(config) {
|
|
|
139
139
|
verbosity,
|
|
140
140
|
effort,
|
|
141
141
|
routingMode,
|
|
142
|
+
fast: config.fast === true ? true : undefined,
|
|
142
143
|
labPresetId: (typeof config.labPresetId === 'string' && config.labPresetId.length <= 64) ? config.labPresetId : undefined,
|
|
143
144
|
keeperTags: Array.isArray(config.keeperTags) ? config.keeperTags.filter(t => typeof t === 'string').slice(0, 20) : undefined,
|
|
144
145
|
};
|