groove-dev 0.26.17 → 0.26.18
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/api.js +11 -1
- package/node_modules/@groove-dev/daemon/src/process.js +17 -11
- package/node_modules/@groove-dev/gui/dist/assets/{index-GisjgmsR.js → index-aT3nOZj0.js} +21 -21
- package/node_modules/@groove-dev/gui/dist/index.html +1 -1
- package/node_modules/@groove-dev/gui/src/views/agents.jsx +7 -3
- package/package.json +1 -1
- package/packages/daemon/src/api.js +11 -1
- package/packages/daemon/src/process.js +17 -11
- package/packages/gui/dist/assets/{index-GisjgmsR.js → index-aT3nOZj0.js} +21 -21
- package/packages/gui/dist/index.html +1 -1
- package/packages/gui/src/views/agents.jsx +7 -3
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
|
7
7
|
<title>Groove GUI</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-aT3nOZj0.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/vendor-C0HXlhrU.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/reactflow-BQPfi37R.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/codemirror-BBL3i_JW.js">
|
|
@@ -321,17 +321,21 @@ function AgentTreeInner() {
|
|
|
321
321
|
|
|
322
322
|
useEffect(() => { setEdges(targetEdges); }, [targetEdges, setEdges]);
|
|
323
323
|
|
|
324
|
-
// Only fitView when agents are added —
|
|
324
|
+
// Only fitView when agents are added — debounced so team launches (multiple spawns)
|
|
325
|
+
// don't cause repeated zoom/pan jitter
|
|
325
326
|
const agentIdStr = agents.map((a) => a.id).join(',');
|
|
327
|
+
const fitTimer = useRef(null);
|
|
326
328
|
useEffect(() => {
|
|
327
329
|
const currentIds = new Set(agents.map((a) => a.id));
|
|
328
330
|
const isNewAgent = agents.length > 0 && [...currentIds].some((id) => !prevAgentIds.current.has(id));
|
|
329
331
|
prevAgentIds.current = currentIds;
|
|
330
332
|
|
|
331
333
|
if (prevCount === 0 && agents.length > 0) {
|
|
332
|
-
|
|
334
|
+
fitView({ padding: 0.3, maxZoom: 1.2, duration: 0 });
|
|
333
335
|
} else if (isNewAgent) {
|
|
334
|
-
|
|
336
|
+
// Debounce: wait 500ms for batch spawns to settle before fitting
|
|
337
|
+
clearTimeout(fitTimer.current);
|
|
338
|
+
fitTimer.current = setTimeout(() => fitView({ padding: 0.3, maxZoom: 1.2, duration: 300 }), 500);
|
|
335
339
|
}
|
|
336
340
|
setPrevCount(agents.length);
|
|
337
341
|
}, [agentIdStr, prevCount, fitView]); // eslint-disable-line react-hooks/exhaustive-deps
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groove-dev",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.18",
|
|
4
4
|
"description": "Open-source agent orchestration layer — the AI company OS. Local model agent engine (GGUF/Ollama/llama-server), HuggingFace model browser, MCP integrations (Slack, Gmail, Stripe, 15+), agent scheduling (cron), business roles (CMO, CFO, EA). GUI dashboard, multi-agent coordination, zero cold-start, infinite sessions. Works with Claude Code, Codex, Gemini CLI, Ollama, any local model.",
|
|
5
5
|
"license": "FSL-1.1-Apache-2.0",
|
|
6
6
|
"author": "Groove Dev <hello@groovedev.ai> (https://groovedev.ai)",
|
|
@@ -1768,7 +1768,17 @@ Keep responses concise. Help them think, don't lecture them about the system the
|
|
|
1768
1768
|
}
|
|
1769
1769
|
|
|
1770
1770
|
const baseDir = daemon.config?.defaultWorkingDir || daemon.projectDir;
|
|
1771
|
-
|
|
1771
|
+
|
|
1772
|
+
// Use the planner's teamId so launched agents join the correct team.
|
|
1773
|
+
// Accept explicit teamId from request body, or find the most recent planner agent.
|
|
1774
|
+
let launchTeamId = req.body?.teamId || null;
|
|
1775
|
+
if (!launchTeamId) {
|
|
1776
|
+
const planners = daemon.registry.getAll()
|
|
1777
|
+
.filter((a) => a.role === 'planner')
|
|
1778
|
+
.sort((a, b) => (b.lastActivity || '').localeCompare(a.lastActivity || ''));
|
|
1779
|
+
launchTeamId = planners[0]?.teamId || null;
|
|
1780
|
+
}
|
|
1781
|
+
const defaultTeamId = launchTeamId || daemon.teams.getDefault()?.id || null;
|
|
1772
1782
|
|
|
1773
1783
|
// If planner specified a project directory, create it and use it as workingDir
|
|
1774
1784
|
let projectWorkingDir = baseDir;
|
|
@@ -370,8 +370,9 @@ For normal file edits within your scope, proceed without review.
|
|
|
370
370
|
this._checkPhase2(agent.id);
|
|
371
371
|
|
|
372
372
|
// Auto-trigger idle QC in the same team
|
|
373
|
-
if (status === 'completed'
|
|
374
|
-
this.
|
|
373
|
+
if (status === 'completed') {
|
|
374
|
+
const files = this.daemon.journalist?.getAgentFiles(agent) || [];
|
|
375
|
+
if (files.length > 0) this._triggerIdleQC(agent);
|
|
375
376
|
}
|
|
376
377
|
});
|
|
377
378
|
|
|
@@ -567,10 +568,11 @@ For normal file edits within your scope, proceed without review.
|
|
|
567
568
|
// Phase 2 auto-spawn: check if all phase 1 agents for a team are done
|
|
568
569
|
this._checkPhase2(agent.id);
|
|
569
570
|
|
|
570
|
-
// Auto-trigger idle QC: if this agent
|
|
571
|
+
// Auto-trigger idle QC: if this agent modified files and there's an idle QC
|
|
571
572
|
// in the same team, activate it to verify the changes
|
|
572
|
-
if (finalStatus === 'completed'
|
|
573
|
-
this.
|
|
573
|
+
if (finalStatus === 'completed') {
|
|
574
|
+
const files = this.daemon.journalist?.getAgentFiles(agent) || [];
|
|
575
|
+
if (files.length > 0) this._triggerIdleQC(agent);
|
|
574
576
|
}
|
|
575
577
|
});
|
|
576
578
|
|
|
@@ -671,11 +673,14 @@ For normal file edits within your scope, proceed without review.
|
|
|
671
673
|
// Remove from pending
|
|
672
674
|
pending.splice(i, 1);
|
|
673
675
|
|
|
674
|
-
// Check if phase 1 agents did any real work.
|
|
675
|
-
//
|
|
676
|
+
// Check if phase 1 agents did any real work by looking at file modifications.
|
|
677
|
+
// If no agent modified any files, there's nothing to QC.
|
|
678
|
+
const journalist = this.daemon.journalist;
|
|
676
679
|
const phase1Idle = group.waitFor.every((id) => {
|
|
677
680
|
const a = registry.get(id);
|
|
678
|
-
|
|
681
|
+
if (!a) return true;
|
|
682
|
+
const files = journalist?.getAgentFiles(a) || [];
|
|
683
|
+
return files.length === 0;
|
|
679
684
|
});
|
|
680
685
|
|
|
681
686
|
// Auto-spawn phase 2 agents — if phase 1 was idle, clear the prompt
|
|
@@ -716,19 +721,20 @@ For normal file edits within your scope, proceed without review.
|
|
|
716
721
|
|
|
717
722
|
/**
|
|
718
723
|
* Auto-trigger an idle QC agent in the same team when a teammate completes real work.
|
|
719
|
-
* "Idle" = running
|
|
724
|
+
* "Idle" = running fullstack agent that hasn't modified any files yet.
|
|
720
725
|
*/
|
|
721
726
|
_triggerIdleQC(completedAgent) {
|
|
722
727
|
const registry = this.daemon.registry;
|
|
723
728
|
if (!completedAgent.teamId) return;
|
|
724
729
|
|
|
725
|
-
// Find a running fullstack/QC agent in the same team that's idle
|
|
730
|
+
// Find a running fullstack/QC agent in the same team that's idle (no files modified)
|
|
731
|
+
const journalist = this.daemon.journalist;
|
|
726
732
|
const qc = registry.getAll().find((a) =>
|
|
727
733
|
a.id !== completedAgent.id &&
|
|
728
734
|
a.teamId === completedAgent.teamId &&
|
|
729
735
|
a.role === 'fullstack' &&
|
|
730
736
|
a.status === 'running' &&
|
|
731
|
-
(a
|
|
737
|
+
(journalist?.getAgentFiles(a) || []).length === 0
|
|
732
738
|
);
|
|
733
739
|
if (!qc) return;
|
|
734
740
|
|