groove-dev 0.17.8 → 0.18.2
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 +4 -3
- package/node_modules/@groove-dev/daemon/google-oauth.json +5 -0
- package/node_modules/@groove-dev/daemon/integrations-registry.json +0 -40
- package/node_modules/@groove-dev/daemon/package.json +4 -3
- package/node_modules/@groove-dev/daemon/src/api.js +212 -21
- package/node_modules/@groove-dev/daemon/src/index.js +68 -1
- package/node_modules/@groove-dev/daemon/src/integrations.js +59 -20
- package/node_modules/@groove-dev/daemon/src/process.js +83 -11
- package/node_modules/@groove-dev/daemon/src/providers/claude-code.js +4 -0
- package/node_modules/@groove-dev/daemon/src/registry.js +1 -1
- package/node_modules/@groove-dev/gui/.groove/audit.log +1 -0
- package/node_modules/@groove-dev/gui/.groove/codebase-index.json +64 -0
- package/node_modules/@groove-dev/gui/.groove/config.json +10 -0
- package/node_modules/@groove-dev/gui/.groove/coordination.md +5 -0
- package/node_modules/@groove-dev/gui/.groove/credentials.json +6 -0
- package/node_modules/@groove-dev/gui/.groove/daemon.port +1 -0
- package/node_modules/@groove-dev/gui/.groove/federation/identity.key +3 -0
- package/node_modules/@groove-dev/gui/.groove/federation/identity.pub +3 -0
- package/node_modules/@groove-dev/gui/.groove/integrations/package.json +6 -0
- package/node_modules/@groove-dev/gui/.groove/state.json +3 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-x5suAiK7.js +182 -0
- package/node_modules/@groove-dev/gui/dist/index.html +1 -1
- package/node_modules/@groove-dev/gui/package.json +5 -4
- package/node_modules/@groove-dev/gui/src/App.jsx +149 -76
- package/node_modules/@groove-dev/gui/src/components/AgentActions.jsx +130 -1
- package/node_modules/@groove-dev/gui/src/components/AgentChat.jsx +47 -7
- package/node_modules/@groove-dev/gui/src/components/AgentNode.jsx +13 -83
- package/node_modules/@groove-dev/gui/src/components/SpawnPanel.jsx +918 -580
- package/node_modules/@groove-dev/gui/src/stores/groove.js +31 -2
- package/node_modules/@groove-dev/gui/src/views/AgentTree.jsx +133 -67
- package/node_modules/@groove-dev/gui/src/views/FileEditor.jsx +85 -1
- package/node_modules/@groove-dev/gui/src/views/IntegrationsStore.jsx +121 -44
- package/package.json +1 -2
- package/packages/cli/package.json +4 -3
- package/packages/daemon/integrations-registry.json +0 -40
- package/packages/daemon/package.json +4 -3
- package/packages/daemon/src/api.js +212 -21
- package/packages/daemon/src/index.js +68 -1
- package/packages/daemon/src/integrations.js +59 -20
- package/packages/daemon/src/process.js +83 -11
- package/packages/daemon/src/providers/claude-code.js +4 -0
- package/packages/daemon/src/registry.js +1 -1
- package/packages/gui/dist/assets/index-x5suAiK7.js +182 -0
- package/packages/gui/dist/index.html +1 -1
- package/packages/gui/node_modules/.vite/deps/@codemirror_autocomplete.js +68 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_autocomplete.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_commands.js +1420 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_commands.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-css.js +17 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-css.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-html.js +22 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-html.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-javascript.js +34 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-javascript.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-json.js +101 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-json.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-markdown.js +2534 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-markdown.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-python.js +789 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_lang-python.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_language.js +115 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_language.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_search.js +1136 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_search.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_state.js +63 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_state.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_theme-one-dark.js +179 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_theme-one-dark.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_view.js +104 -0
- package/packages/gui/node_modules/.vite/deps/@codemirror_view.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@xterm_addon-fit.js +46 -0
- package/packages/gui/node_modules/.vite/deps/@xterm_addon-fit.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@xterm_addon-web-links.js +121 -0
- package/packages/gui/node_modules/.vite/deps/@xterm_addon-web-links.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@xterm_xterm.js +9237 -0
- package/packages/gui/node_modules/.vite/deps/@xterm_xterm.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/@xyflow_react.js +9934 -0
- package/packages/gui/node_modules/.vite/deps/@xyflow_react.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/_metadata.json +184 -0
- package/packages/gui/node_modules/.vite/deps/chunk-3EE34IFC.js +5169 -0
- package/packages/gui/node_modules/.vite/deps/chunk-3EE34IFC.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-3IB5EUP7.js +2000 -0
- package/packages/gui/node_modules/.vite/deps/chunk-3IB5EUP7.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-3LBP22MX.js +1115 -0
- package/packages/gui/node_modules/.vite/deps/chunk-3LBP22MX.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-3Q7HT7ZF.js +701 -0
- package/packages/gui/node_modules/.vite/deps/chunk-3Q7HT7ZF.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-44CLUOQE.js +1776 -0
- package/packages/gui/node_modules/.vite/deps/chunk-44CLUOQE.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-5RZAEUNX.js +280 -0
- package/packages/gui/node_modules/.vite/deps/chunk-5RZAEUNX.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-5WRI5ZAA.js +30 -0
- package/packages/gui/node_modules/.vite/deps/chunk-5WRI5ZAA.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-7FYDPZIO.js +1004 -0
- package/packages/gui/node_modules/.vite/deps/chunk-7FYDPZIO.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-BX6POZPY.js +292 -0
- package/packages/gui/node_modules/.vite/deps/chunk-BX6POZPY.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-HVFOBSCQ.js +1062 -0
- package/packages/gui/node_modules/.vite/deps/chunk-HVFOBSCQ.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-RE2FU7ZU.js +10985 -0
- package/packages/gui/node_modules/.vite/deps/chunk-RE2FU7ZU.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/chunk-YYJMNVCJ.js +3459 -0
- package/packages/gui/node_modules/.vite/deps/chunk-YYJMNVCJ.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/package.json +3 -0
- package/packages/gui/node_modules/.vite/deps/react-dom.js +6 -0
- package/packages/gui/node_modules/.vite/deps/react-dom.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/react-dom_client.js +20217 -0
- package/packages/gui/node_modules/.vite/deps/react-dom_client.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/react.js +5 -0
- package/packages/gui/node_modules/.vite/deps/react.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/react_jsx-dev-runtime.js +278 -0
- package/packages/gui/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/react_jsx-runtime.js +6 -0
- package/packages/gui/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
- package/packages/gui/node_modules/.vite/deps/zustand.js +56 -0
- package/packages/gui/node_modules/.vite/deps/zustand.js.map +7 -0
- package/packages/gui/package.json +5 -4
- package/packages/gui/src/App.jsx +149 -76
- package/packages/gui/src/components/AgentActions.jsx +130 -1
- package/packages/gui/src/components/AgentChat.jsx +47 -7
- package/packages/gui/src/components/AgentNode.jsx +13 -83
- package/packages/gui/src/components/SpawnPanel.jsx +918 -580
- package/packages/gui/src/stores/groove.js +31 -2
- package/packages/gui/src/views/AgentTree.jsx +133 -67
- package/packages/gui/src/views/FileEditor.jsx +85 -1
- package/packages/gui/src/views/IntegrationsStore.jsx +121 -44
- package/docs/FILE-EDITOR-PLAN.md +0 -253
- package/docs/GUI_DESIGN_SPEC.md +0 -402
- package/docs/SKILLS-API-SPEC.md +0 -277
- package/node_modules/@groove-dev/gui/dist/assets/index-D5dtDQf0.js +0 -156
- package/packages/gui/dist/assets/index-D5dtDQf0.js +0 -156
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// FSL-1.1-Apache-2.0 — see LICENSE
|
|
3
3
|
|
|
4
4
|
import { spawn as cpSpawn } from 'child_process';
|
|
5
|
-
import { createWriteStream, mkdirSync, chmodSync } from 'fs';
|
|
5
|
+
import { createWriteStream, mkdirSync, chmodSync, existsSync, readFileSync, unlinkSync } from 'fs';
|
|
6
6
|
import { resolve } from 'path';
|
|
7
7
|
import { getProvider } from './providers/index.js';
|
|
8
|
+
import { validateAgentConfig } from './validate.js';
|
|
8
9
|
|
|
9
10
|
// Role-specific prompt prefixes — applied during spawn regardless of entry point
|
|
10
11
|
// (SpawnPanel, chat continue, CLI, API) for consistency
|
|
@@ -58,11 +59,15 @@ Do NOT write code unless explicitly asked. Use your MCP tools (database queries,
|
|
|
58
59
|
Do NOT write code unless explicitly asked. Use your MCP tools to interact with Home Assistant.
|
|
59
60
|
|
|
60
61
|
`,
|
|
61
|
-
planner: `You are a
|
|
62
|
+
planner: `You are a PLANNING ONLY agent. You create plans. You do NOT write code, edit files, or run commands.
|
|
63
|
+
|
|
64
|
+
ABSOLUTE RULE: Never use the Edit, Write, or Bash tools to modify source code. You ONLY use Read, Glob, and Grep to understand the codebase, then output a written plan. If the user says "build this" or "redesign this", create a PLAN for how other agents should build it — do NOT build it yourself.
|
|
65
|
+
|
|
66
|
+
Focus on:
|
|
62
67
|
- Understanding requirements
|
|
63
|
-
- Exploring the codebase
|
|
68
|
+
- Exploring the codebase to understand current architecture
|
|
64
69
|
- Identifying approaches and trade-offs
|
|
65
|
-
- Writing structured plans
|
|
70
|
+
- Writing structured plans with agent assignments
|
|
66
71
|
|
|
67
72
|
After completing your plan, you MUST do two things:
|
|
68
73
|
|
|
@@ -70,15 +75,25 @@ After completing your plan, you MUST do two things:
|
|
|
70
75
|
|
|
71
76
|
2. Save a machine-readable team config to .groove/recommended-team.json using this EXACT format:
|
|
72
77
|
[
|
|
73
|
-
{ "role": "
|
|
74
|
-
{ "role": "backend", "
|
|
75
|
-
{ "role": "
|
|
78
|
+
{ "role": "frontend", "phase": 1, "scope": ["src/components/**", "src/views/**"], "prompt": "Build the frontend: [specific tasks]" },
|
|
79
|
+
{ "role": "backend", "phase": 1, "scope": ["src/api/**", "src/server/**"], "prompt": "Build the backend: [specific tasks]" },
|
|
80
|
+
{ "role": "fullstack", "phase": 2, "scope": [], "prompt": "QC Senior Dev: Audit all changes from phase 1 agents. Verify correctness, fix issues, run tests, build the project, commit, and launch. Output the localhost URL." }
|
|
76
81
|
]
|
|
77
82
|
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
MANDATORY RULES — NEVER SKIP THESE:
|
|
84
|
+
|
|
85
|
+
1. The LAST entry in the array MUST be: { "role": "fullstack", "phase": 2, ... }
|
|
86
|
+
This is the QC Senior Dev. It auto-spawns after all other agents finish.
|
|
87
|
+
Its prompt: audit changes, fix issues, run tests, build, commit, launch.
|
|
88
|
+
NEVER omit this agent. Every team needs a QC.
|
|
89
|
+
|
|
90
|
+
2. ALL other agents are phase: 1 — they run in parallel.
|
|
91
|
+
|
|
92
|
+
3. Do NOT tell any agent to "wait for" another agent. Phase 2 handles sequencing automatically.
|
|
93
|
+
|
|
94
|
+
4. Set appropriate scopes. Write detailed prompts so each agent knows exactly what to build.
|
|
80
95
|
|
|
81
|
-
|
|
96
|
+
5. If the project is a monorepo, set "workingDir" for agents that need specific subdirectories.
|
|
82
97
|
|
|
83
98
|
IMPORTANT: Do not use markdown formatting like ** or ### in your output. Write in plain text with clean formatting. Use line breaks, dashes, and indentation for structure.
|
|
84
99
|
|
|
@@ -105,6 +120,17 @@ export class ProcessManager {
|
|
|
105
120
|
async spawn(config) {
|
|
106
121
|
const { registry, locks, introducer } = this.daemon;
|
|
107
122
|
|
|
123
|
+
// Clean stale recommended-team.json when spawning a new planner
|
|
124
|
+
if (config.role === 'planner') {
|
|
125
|
+
const dirs = [this.daemon.grooveDir];
|
|
126
|
+
if (config.workingDir) dirs.push(resolve(config.workingDir, '.groove'));
|
|
127
|
+
if (this.daemon.config?.defaultWorkingDir) dirs.push(resolve(this.daemon.config.defaultWorkingDir, '.groove'));
|
|
128
|
+
for (const dir of dirs) {
|
|
129
|
+
const p = resolve(dir, 'recommended-team.json');
|
|
130
|
+
if (existsSync(p)) try { unlinkSync(p); } catch { /* */ }
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
108
134
|
// Validate provider exists and is installed
|
|
109
135
|
const provider = getProvider(config.provider || 'claude-code');
|
|
110
136
|
if (!provider) {
|
|
@@ -325,6 +351,9 @@ For normal file edits within your scope, proceed without review.
|
|
|
325
351
|
if (finalStatus === 'completed' && this.daemon.journalist) {
|
|
326
352
|
this.daemon.journalist.cycle().catch(() => {});
|
|
327
353
|
}
|
|
354
|
+
|
|
355
|
+
// Phase 2 auto-spawn: check if all phase 1 agents for a team are done
|
|
356
|
+
this._checkPhase2(agent.id);
|
|
328
357
|
});
|
|
329
358
|
|
|
330
359
|
proc.on('error', (err) => {
|
|
@@ -338,6 +367,49 @@ For normal file edits within your scope, proceed without review.
|
|
|
338
367
|
return agent;
|
|
339
368
|
}
|
|
340
369
|
|
|
370
|
+
/**
|
|
371
|
+
* Check if a completed/crashed agent was the last phase 1 agent in a team.
|
|
372
|
+
* If so, auto-spawn the phase 2 (QC/finisher) agents.
|
|
373
|
+
*/
|
|
374
|
+
_checkPhase2(completedAgentId) {
|
|
375
|
+
const pending = this.daemon._pendingPhase2;
|
|
376
|
+
if (!pending || pending.length === 0) return;
|
|
377
|
+
|
|
378
|
+
const registry = this.daemon.registry;
|
|
379
|
+
|
|
380
|
+
for (let i = pending.length - 1; i >= 0; i--) {
|
|
381
|
+
const group = pending[i];
|
|
382
|
+
if (!group.waitFor.includes(completedAgentId)) continue;
|
|
383
|
+
|
|
384
|
+
// Check if ALL phase 1 agents in this group are done
|
|
385
|
+
const allDone = group.waitFor.every((id) => {
|
|
386
|
+
const a = registry.get(id);
|
|
387
|
+
return !a || a.status === 'completed' || a.status === 'crashed' || a.status === 'stopped' || a.status === 'killed';
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
if (allDone) {
|
|
391
|
+
// Remove from pending
|
|
392
|
+
pending.splice(i, 1);
|
|
393
|
+
|
|
394
|
+
// Auto-spawn phase 2 agents
|
|
395
|
+
for (const config of group.agents) {
|
|
396
|
+
try {
|
|
397
|
+
const validated = validateAgentConfig(config);
|
|
398
|
+
this.spawn(validated).then((agent) => {
|
|
399
|
+
this.daemon.broadcast({
|
|
400
|
+
type: 'phase2:spawned',
|
|
401
|
+
agentId: agent.id,
|
|
402
|
+
name: agent.name,
|
|
403
|
+
role: agent.role,
|
|
404
|
+
});
|
|
405
|
+
this.daemon.audit.log('phase2.autoSpawn', { id: agent.id, name: agent.name, role: agent.role });
|
|
406
|
+
}).catch(() => {});
|
|
407
|
+
} catch { /* skip invalid configs */ }
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
341
413
|
/**
|
|
342
414
|
* Resume a completed agent's session with a new message.
|
|
343
415
|
* Uses --resume SESSION_ID for zero cold-start continuation.
|
|
@@ -390,7 +462,7 @@ For normal file edits within your scope, proceed without review.
|
|
|
390
462
|
model: config.model,
|
|
391
463
|
prompt: config.prompt,
|
|
392
464
|
permission: config.permission,
|
|
393
|
-
workingDir: config.workingDir,
|
|
465
|
+
workingDir: config.workingDir || this.daemon.config?.defaultWorkingDir || undefined,
|
|
394
466
|
name: config.name,
|
|
395
467
|
});
|
|
396
468
|
|
|
@@ -48,6 +48,10 @@ export class ClaudeCodeProvider extends Provider {
|
|
|
48
48
|
args.push('--model', agent.model);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
if (agent.effort) {
|
|
52
|
+
args.push('--effort', agent.effort);
|
|
53
|
+
}
|
|
54
|
+
|
|
51
55
|
// Pass the initial prompt as positional arg (includes GROOVE context)
|
|
52
56
|
const fullPrompt = this.buildFullPrompt(agent);
|
|
53
57
|
if (fullPrompt) {
|
|
@@ -50,7 +50,7 @@ export class Registry extends EventEmitter {
|
|
|
50
50
|
if (!agent) return null;
|
|
51
51
|
|
|
52
52
|
// Only allow known fields to prevent prototype pollution
|
|
53
|
-
const SAFE_FIELDS = ['status', 'pid', 'tokensUsed', 'contextUsage', 'lastActivity', 'model', 'name', 'routingMode', 'routingReason', 'sessionId', 'skills', 'integrations'];
|
|
53
|
+
const SAFE_FIELDS = ['status', 'pid', 'tokensUsed', 'contextUsage', 'lastActivity', 'model', 'name', 'routingMode', 'routingReason', 'sessionId', 'skills', 'integrations', 'workingDir', 'effort'];
|
|
54
54
|
for (const key of Object.keys(updates)) {
|
|
55
55
|
if (SAFE_FIELDS.includes(key)) {
|
|
56
56
|
agent[key] = updates[key];
|