groove-dev 0.26.20 → 0.26.22
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/daemon/src/introducer.js +8 -2
- package/node_modules/@groove-dev/daemon/src/process.js +94 -32
- package/node_modules/@groove-dev/gui/dist/assets/{index-CBgUozrt.js → index-DOejqkiH.js} +23 -23
- package/node_modules/@groove-dev/gui/dist/assets/{index-CHRPn_ls.css → index-DomJ4Dgb.css} +1 -1
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/src/components/agents/agent-feed.jsx +5 -5
- package/node_modules/@groove-dev/gui/src/components/ui/thinking-indicator.jsx +35 -73
- package/node_modules/@groove-dev/gui/src/stores/groove.js +39 -14
- package/node_modules/@groove-dev/gui/src/views/agents.jsx +49 -18
- package/package.json +1 -1
- package/packages/daemon/src/introducer.js +8 -2
- package/packages/daemon/src/process.js +94 -32
- package/packages/gui/dist/assets/{index-CBgUozrt.js → index-DOejqkiH.js} +23 -23
- package/packages/gui/dist/assets/{index-CHRPn_ls.css → index-DomJ4Dgb.css} +1 -1
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/src/components/agents/agent-feed.jsx +5 -5
- package/packages/gui/src/components/ui/thinking-indicator.jsx +35 -73
- package/packages/gui/src/stores/groove.js +39 -14
- package/packages/gui/src/views/agents.jsx +49 -18
|
@@ -75,8 +75,14 @@ export class Introducer {
|
|
|
75
75
|
lines.push('');
|
|
76
76
|
lines.push(`## Coordination Rules`);
|
|
77
77
|
lines.push('');
|
|
78
|
-
lines.push(`- Stay within your file scope
|
|
79
|
-
lines.push(`- If you
|
|
78
|
+
lines.push(`- Stay within your file scope when other agents are actively running.`);
|
|
79
|
+
lines.push(`- If you are the ONLY active agent, you may edit files outside your scope if needed to complete your task.`);
|
|
80
|
+
lines.push(`- If you need another agent to make changes (e.g., you're a frontend agent and need backend API changes):`);
|
|
81
|
+
lines.push(` Write a handoff file to .groove/handoffs/<role>.md (e.g., .groove/handoffs/backend.md) with:`);
|
|
82
|
+
lines.push(` - What needs to change and why`);
|
|
83
|
+
lines.push(` - Which files to modify`);
|
|
84
|
+
lines.push(` - Expected behavior after the change`);
|
|
85
|
+
lines.push(` GROOVE will automatically wake the target agent and deliver your request.`);
|
|
80
86
|
lines.push(`- Check AGENTS_REGISTRY.md for the latest team state.`);
|
|
81
87
|
|
|
82
88
|
// Project files section — tell the new agent what exists and what to read
|
|
@@ -2,7 +2,7 @@
|
|
|
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, existsSync, readFileSync, unlinkSync } from 'fs';
|
|
5
|
+
import { createWriteStream, mkdirSync, chmodSync, existsSync, readFileSync, unlinkSync, readdirSync } from 'fs';
|
|
6
6
|
import { resolve } from 'path';
|
|
7
7
|
import { getProvider, getInstalledProviders } from './providers/index.js';
|
|
8
8
|
import { AgentLoop } from './agent-loop.js';
|
|
@@ -76,27 +76,28 @@ For best results, apply a slide deck skill from the Marketplace. The skill provi
|
|
|
76
76
|
Do NOT write code unless explicitly asked. Use your MCP tools to interact with Home Assistant.
|
|
77
77
|
|
|
78
78
|
`,
|
|
79
|
-
planner: `You are a PLANNING ONLY agent. You create plans. You do NOT write code, edit files, or run commands.
|
|
79
|
+
planner: `You are a PLANNING ONLY agent. You create plans and route work to your team. You do NOT write code, edit files, or run commands.
|
|
80
80
|
|
|
81
81
|
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.
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
- Understanding requirements
|
|
85
|
-
- Exploring the codebase to understand current architecture
|
|
86
|
-
- Identifying approaches and trade-offs
|
|
87
|
-
- Writing structured plans with agent assignments
|
|
83
|
+
YOU HAVE TWO MODES:
|
|
88
84
|
|
|
89
|
-
|
|
85
|
+
MODE 1 — TEAM CREATION (first time, no team exists yet):
|
|
86
|
+
Explore the codebase thoroughly, understand the architecture, then recommend a team structure.
|
|
90
87
|
|
|
91
|
-
|
|
88
|
+
MODE 2 — TASK ROUTING (team already exists):
|
|
89
|
+
Check AGENTS_REGISTRY.md or .groove/recommended-team.json to see your existing team.
|
|
90
|
+
Do NOT re-explore the entire codebase. You already know it from team creation.
|
|
91
|
+
Just read the specific files related to the bug/feature, decide which existing agent should handle it, and write the routing config. This should be FAST — under 5 tool calls.
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
HOW TO DETECT WHICH MODE:
|
|
94
|
+
- Read AGENTS_REGISTRY.md. If it lists agents with roles matching your team (frontend, backend, fullstack), you are in MODE 2.
|
|
95
|
+
- If no agents exist or only a planner exists, you are in MODE 1.
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
After completing your plan, you MUST write .groove/recommended-team.json — EVERY TIME, no exceptions.
|
|
98
|
+
|
|
99
|
+
For MODE 1 (team creation):
|
|
98
100
|
{
|
|
99
|
-
"projectDir": "my-project-name",
|
|
100
101
|
"agents": [
|
|
101
102
|
{ "role": "frontend", "phase": 1, "scope": ["src/components/**", "src/views/**"], "prompt": "Build the frontend: [specific tasks]" },
|
|
102
103
|
{ "role": "backend", "phase": 1, "scope": ["src/api/**", "src/server/**"], "prompt": "Build the backend: [specific tasks]" },
|
|
@@ -104,35 +105,38 @@ For NEW projects (building something from scratch):
|
|
|
104
105
|
]
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
For
|
|
108
|
+
For MODE 2 (task routing to existing team):
|
|
109
|
+
Only include the agents that need to do work. Use their EXISTING role — the system will find and reuse them.
|
|
108
110
|
{
|
|
109
111
|
"agents": [
|
|
110
|
-
{ "role": "frontend", "phase": 1, "
|
|
111
|
-
{ "role": "fullstack", "phase": 2, "scope": [], "prompt": "QC Senior Dev: Audit all changes, fix issues, run tests, build, commit, and launch." }
|
|
112
|
+
{ "role": "frontend", "phase": 1, "prompt": "Fix the bug: [specific description with file paths and what to change]" }
|
|
112
113
|
]
|
|
113
114
|
}
|
|
115
|
+
Do NOT include QC/fullstack in the JSON for task routing — the system auto-triggers the existing QC when work completes.
|
|
116
|
+
Do NOT include agents that have no work to do.
|
|
117
|
+
Do NOT invent new agent names or roles — use the existing team's roles exactly.
|
|
118
|
+
|
|
119
|
+
For NEW projects (team creation only):
|
|
120
|
+
Include "projectDir" with a short kebab-case directory name. All agents spawn inside it.
|
|
121
|
+
For EXISTING codebases: Do NOT include "projectDir".
|
|
114
122
|
|
|
115
|
-
|
|
116
|
-
- For NEW projects: ALWAYS include "projectDir" with a short, clean directory name (kebab-case, e.g. "cat-website", "landing-page", "api-service"). All agents will be spawned inside this directory so each project stays isolated.
|
|
117
|
-
- For EXISTING codebases: Do NOT include "projectDir". Agents work in the current repo root. You can tell an existing codebase by the presence of package.json, .git, or established source directories.
|
|
118
|
-
- NEVER mix projects. Each new project gets its own directory.
|
|
123
|
+
MANDATORY RULES:
|
|
119
124
|
|
|
120
|
-
|
|
125
|
+
1. For team creation: the LAST entry MUST be { "role": "fullstack", "phase": 2 } — the QC agent.
|
|
126
|
+
For task routing: do NOT include the QC — it auto-triggers.
|
|
121
127
|
|
|
122
|
-
|
|
123
|
-
This is the QC Senior Dev. It auto-spawns after all other agents finish.
|
|
124
|
-
Its prompt: audit changes, fix issues, run tests, build, commit, launch.
|
|
125
|
-
NEVER omit this agent. Every team needs a QC.
|
|
128
|
+
2. ALL phase 1 agents run in parallel. Do NOT tell agents to wait for each other.
|
|
126
129
|
|
|
127
|
-
|
|
130
|
+
3. If the user gave a specific task, write detailed prompts with file paths and what to change.
|
|
131
|
+
If no task was given, use empty prompts ("prompt": "") — agents will await instructions.
|
|
128
132
|
|
|
129
|
-
|
|
133
|
+
4. NEVER create new agent names or custom roles. Use the standard roles: frontend, backend, fullstack.
|
|
130
134
|
|
|
131
|
-
|
|
135
|
+
5. NEVER instruct agents to delete files from other projects or clean up unrelated code.
|
|
132
136
|
|
|
133
|
-
|
|
137
|
+
6. You MUST always write .groove/recommended-team.json. NEVER skip it.
|
|
134
138
|
|
|
135
|
-
|
|
139
|
+
7. In MODE 2, be FAST. Read only the files needed to understand the specific task. Do not re-analyze the full codebase.
|
|
136
140
|
|
|
137
141
|
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.
|
|
138
142
|
|
|
@@ -373,10 +377,11 @@ For normal file edits within your scope, proceed without review.
|
|
|
373
377
|
if (status === 'completed' && this.daemon.journalist) this.daemon.journalist.cycle().catch(() => {});
|
|
374
378
|
this._checkPhase2(agent.id);
|
|
375
379
|
|
|
376
|
-
// Auto-trigger idle QC
|
|
380
|
+
// Auto-trigger idle QC + process cross-scope handoffs
|
|
377
381
|
if (status === 'completed') {
|
|
378
382
|
const files = this.daemon.journalist?.getAgentFiles(agent) || [];
|
|
379
383
|
if (files.length > 0) this._triggerIdleQC(agent);
|
|
384
|
+
this._processHandoffs(agent);
|
|
380
385
|
}
|
|
381
386
|
});
|
|
382
387
|
|
|
@@ -577,6 +582,8 @@ For normal file edits within your scope, proceed without review.
|
|
|
577
582
|
if (finalStatus === 'completed') {
|
|
578
583
|
const files = this.daemon.journalist?.getAgentFiles(agent) || [];
|
|
579
584
|
if (files.length > 0) this._triggerIdleQC(agent);
|
|
585
|
+
// Process cross-scope handoff requests from this agent
|
|
586
|
+
this._processHandoffs(agent);
|
|
580
587
|
}
|
|
581
588
|
});
|
|
582
589
|
|
|
@@ -765,6 +772,61 @@ For normal file edits within your scope, proceed without review.
|
|
|
765
772
|
});
|
|
766
773
|
}
|
|
767
774
|
|
|
775
|
+
/**
|
|
776
|
+
* Process handoff files in .groove/handoffs/.
|
|
777
|
+
* Agents write handoff requests when they need cross-scope work from a teammate.
|
|
778
|
+
* File name = target role (e.g., backend.md). Content = what to do.
|
|
779
|
+
*/
|
|
780
|
+
_processHandoffs(sourceAgent) {
|
|
781
|
+
const handoffsDir = resolve(this.daemon.grooveDir, 'handoffs');
|
|
782
|
+
if (!existsSync(handoffsDir)) return;
|
|
783
|
+
|
|
784
|
+
const registry = this.daemon.registry;
|
|
785
|
+
let files;
|
|
786
|
+
try { files = readdirSync(handoffsDir); } catch { return; }
|
|
787
|
+
|
|
788
|
+
for (const file of files) {
|
|
789
|
+
if (!file.endsWith('.md')) continue;
|
|
790
|
+
const targetRole = file.replace(/\.md$/, '');
|
|
791
|
+
const filePath = resolve(handoffsDir, file);
|
|
792
|
+
|
|
793
|
+
let content;
|
|
794
|
+
try { content = readFileSync(filePath, 'utf8').trim(); } catch { continue; }
|
|
795
|
+
if (!content) { try { unlinkSync(filePath); } catch {} continue; }
|
|
796
|
+
|
|
797
|
+
// Find the target agent in the same team
|
|
798
|
+
const target = registry.getAll().find((a) =>
|
|
799
|
+
a.role === targetRole &&
|
|
800
|
+
a.teamId === sourceAgent.teamId &&
|
|
801
|
+
a.id !== sourceAgent.id &&
|
|
802
|
+
(a.status === 'running' || a.status === 'completed')
|
|
803
|
+
);
|
|
804
|
+
|
|
805
|
+
if (!target) {
|
|
806
|
+
console.log(`[Groove] Handoff to ${targetRole} — no matching agent in team`);
|
|
807
|
+
try { unlinkSync(filePath); } catch {}
|
|
808
|
+
continue;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// Wake the target agent with the handoff request
|
|
812
|
+
const message = `Cross-scope handoff from ${sourceAgent.name} (${sourceAgent.role}):\n\n${content}`;
|
|
813
|
+
this.daemon.processes.resume(target.id, message).then((newAgent) => {
|
|
814
|
+
this.daemon.audit.log('handoff.routed', {
|
|
815
|
+
from: sourceAgent.name, to: target.name, newId: newAgent.id, role: targetRole,
|
|
816
|
+
});
|
|
817
|
+
this.daemon.broadcast({
|
|
818
|
+
type: 'handoff:routed',
|
|
819
|
+
from: sourceAgent.name, to: target.name, role: targetRole,
|
|
820
|
+
});
|
|
821
|
+
}).catch((err) => {
|
|
822
|
+
console.error(`[Groove] Handoff to ${targetRole} failed: ${err.message}`);
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
// Remove the handoff file
|
|
826
|
+
try { unlinkSync(filePath); } catch {}
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
768
830
|
/**
|
|
769
831
|
* Resume a completed agent's session with a new message.
|
|
770
832
|
* Uses --resume SESSION_ID for zero cold-start continuation.
|