groove-dev 0.27.174 → 0.27.179

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.
Files changed (68) hide show
  1. package/AUTONOMOUS_AGENT_FRAMEWORK.md +654 -0
  2. package/innerchat/Screenshot_2026-06-09_at_12.09.42_PM.png +0 -0
  3. package/innerchat/Screenshot_2026-06-09_at_2.19.42_PM.png +0 -0
  4. package/node_modules/@groove-dev/cli/package.json +1 -1
  5. package/node_modules/@groove-dev/daemon/package.json +1 -1
  6. package/node_modules/@groove-dev/daemon/src/api.js +3 -1
  7. package/node_modules/@groove-dev/daemon/src/autostate.js +198 -0
  8. package/node_modules/@groove-dev/daemon/src/index.js +6 -0
  9. package/node_modules/@groove-dev/daemon/src/orchestrator.js +585 -0
  10. package/node_modules/@groove-dev/daemon/src/process.js +27 -2
  11. package/node_modules/@groove-dev/daemon/src/registry.js +2 -1
  12. package/node_modules/@groove-dev/daemon/src/routes/auto-agents.js +264 -0
  13. package/node_modules/@groove-dev/daemon/src/validate.js +6 -0
  14. package/node_modules/@groove-dev/gui/dist/assets/index-CTer01Vg.js +1065 -0
  15. package/node_modules/@groove-dev/gui/dist/assets/index-DTFtRtkx.css +1 -0
  16. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  17. package/node_modules/@groove-dev/gui/package.json +1 -1
  18. package/node_modules/@groove-dev/gui/src/App.jsx +2 -0
  19. package/node_modules/@groove-dev/gui/src/components/agents/agent-config.jsx +53 -0
  20. package/node_modules/@groove-dev/gui/src/components/agents/agent-feed.jsx +4 -4
  21. package/node_modules/@groove-dev/gui/src/components/agents/agent-panel.jsx +95 -2
  22. package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +50 -1
  23. package/node_modules/@groove-dev/gui/src/components/auto-agents/auto-agent-card.jsx +139 -0
  24. package/node_modules/@groove-dev/gui/src/components/auto-agents/auto-agent-detail.jsx +286 -0
  25. package/node_modules/@groove-dev/gui/src/components/auto-agents/setup-wizard.jsx +284 -0
  26. package/node_modules/@groove-dev/gui/src/components/fleet/fleet-pane.jsx +16 -3
  27. package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +2 -1
  28. package/node_modules/@groove-dev/gui/src/stores/groove.js +14 -0
  29. package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +2 -0
  30. package/node_modules/@groove-dev/gui/src/stores/slices/auto-agents-slice.js +149 -0
  31. package/node_modules/@groove-dev/gui/src/stores/slices/ui-slice.js +14 -11
  32. package/node_modules/@groove-dev/gui/src/views/auto-agents.jsx +70 -0
  33. package/node_modules/@groove-dev/gui/src/views/settings.jsx +13 -6
  34. package/package.json +1 -1
  35. package/packages/cli/package.json +1 -1
  36. package/packages/daemon/package.json +1 -1
  37. package/packages/daemon/src/api.js +3 -1
  38. package/packages/daemon/src/autostate.js +198 -0
  39. package/packages/daemon/src/index.js +6 -0
  40. package/packages/daemon/src/orchestrator.js +585 -0
  41. package/packages/daemon/src/process.js +27 -2
  42. package/packages/daemon/src/registry.js +2 -1
  43. package/packages/daemon/src/routes/auto-agents.js +264 -0
  44. package/packages/daemon/src/validate.js +6 -0
  45. package/packages/gui/dist/assets/index-CTer01Vg.js +1065 -0
  46. package/packages/gui/dist/assets/index-DTFtRtkx.css +1 -0
  47. package/packages/gui/dist/index.html +2 -2
  48. package/packages/gui/package.json +1 -1
  49. package/packages/gui/src/App.jsx +2 -0
  50. package/packages/gui/src/components/agents/agent-config.jsx +53 -0
  51. package/packages/gui/src/components/agents/agent-feed.jsx +4 -4
  52. package/packages/gui/src/components/agents/agent-panel.jsx +95 -2
  53. package/packages/gui/src/components/agents/spawn-wizard.jsx +50 -1
  54. package/packages/gui/src/components/auto-agents/auto-agent-card.jsx +139 -0
  55. package/packages/gui/src/components/auto-agents/auto-agent-detail.jsx +286 -0
  56. package/packages/gui/src/components/auto-agents/setup-wizard.jsx +284 -0
  57. package/packages/gui/src/components/fleet/fleet-pane.jsx +16 -3
  58. package/packages/gui/src/components/layout/activity-bar.jsx +2 -1
  59. package/packages/gui/src/stores/groove.js +14 -0
  60. package/packages/gui/src/stores/slices/agents-slice.js +2 -0
  61. package/packages/gui/src/stores/slices/auto-agents-slice.js +149 -0
  62. package/packages/gui/src/stores/slices/ui-slice.js +14 -11
  63. package/packages/gui/src/views/auto-agents.jsx +70 -0
  64. package/packages/gui/src/views/settings.jsx +13 -6
  65. package/node_modules/@groove-dev/gui/dist/assets/index-BvJwMNAX.css +0 -1
  66. package/node_modules/@groove-dev/gui/dist/assets/index-DZY-EWPs.js +0 -1030
  67. package/packages/gui/dist/assets/index-BvJwMNAX.css +0 -1
  68. package/packages/gui/dist/assets/index-DZY-EWPs.js +0 -1030
@@ -418,12 +418,19 @@ function ProviderCard({ provider, onKeyChange }) {
418
418
 
419
419
  {/* Connected state */}
420
420
  {provider.hasKey && !settingKey && (
421
- <div className="flex items-center gap-2 mb-3">
422
- <div className="flex-1 flex items-center gap-1.5 h-8 px-2.5 bg-success/8 border border-success/20 rounded-md text-2xs font-sans text-success">
423
- <Check size={10} /> API Connected
421
+ <div className="space-y-1.5 mb-3">
422
+ {isSubscription && isReady && (
423
+ <div className="flex items-center gap-1.5 h-8 px-2.5 bg-accent/8 border border-accent/20 rounded-md text-2xs font-sans text-accent">
424
+ <Check size={10} /> Subscription active
425
+ </div>
426
+ )}
427
+ <div className="flex items-center gap-2">
428
+ <div className="flex-1 flex items-center gap-1.5 h-8 px-2.5 bg-success/8 border border-success/20 rounded-md text-2xs font-sans text-success">
429
+ <Check size={10} /> {isSubscription ? 'API key stored (usage credits)' : 'API Connected'}
430
+ </div>
431
+ <button onClick={() => { setSettingKey(true); setShowKey(false); setKeyInput(''); }} className="text-2xs text-text-4 hover:text-accent cursor-pointer font-sans">Edit</button>
432
+ <button onClick={handleDeleteKey} className="text-2xs text-text-4 hover:text-danger cursor-pointer font-sans">Remove</button>
424
433
  </div>
425
- <button onClick={() => { setSettingKey(true); setShowKey(false); setKeyInput(''); }} className="text-2xs text-text-4 hover:text-accent cursor-pointer font-sans">Edit</button>
426
- <button onClick={handleDeleteKey} className="text-2xs text-text-4 hover:text-danger cursor-pointer font-sans">Remove</button>
427
434
  </div>
428
435
  )}
429
436
 
@@ -492,7 +499,7 @@ function ProviderCard({ provider, onKeyChange }) {
492
499
  className="w-full h-8 text-2xs gap-1.5 mt-2"
493
500
  >
494
501
  <Key size={11} />
495
- Add API key for headless mode
502
+ {provider.id === 'claude-code' ? 'Add API key (usage credits + headless)' : 'Add API key for headless mode'}
496
503
  </Button>
497
504
  )}
498
505
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groove-dev",
3
- "version": "0.27.174",
3
+ "version": "0.27.179",
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)",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/cli",
3
- "version": "0.27.174",
3
+ "version": "0.27.179",
4
4
  "description": "GROOVE CLI — manage AI coding agents from your terminal",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/daemon",
3
- "version": "0.27.174",
3
+ "version": "0.27.179",
4
4
  "description": "GROOVE daemon — agent orchestration engine",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -28,6 +28,7 @@ import { registerFileRoutes, resetEditorRoot } from './routes/files.js';
28
28
  import { registerNetworkRoutes } from './routes/network.js';
29
29
  import { registerScheduleRoutes } from './routes/schedules.js';
30
30
  import { registerInnerChatRoutes } from './routes/innerchat.js';
31
+ import { registerAutoAgentRoutes } from './routes/auto-agents.js';
31
32
 
32
33
  const __dirname = dirname(fileURLToPath(import.meta.url));
33
34
  const pkgVersion = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
@@ -127,7 +128,7 @@ export function createApi(app, daemon) {
127
128
  next();
128
129
  });
129
130
 
130
- app.use(express.json({ limit: '6mb' }));
131
+ app.use(express.json({ limit: '100mb' }));
131
132
 
132
133
  // Health check
133
134
  app.get('/api/health', (req, res) => {
@@ -177,6 +178,7 @@ export function createApi(app, daemon) {
177
178
  registerNetworkRoutes(app, daemon);
178
179
  registerScheduleRoutes(app, daemon);
179
180
  registerInnerChatRoutes(app, daemon);
181
+ registerAutoAgentRoutes(app, daemon);
180
182
 
181
183
 
182
184
  // Token usage
@@ -0,0 +1,198 @@
1
+ // GROOVE — Auto Agent State Persistence
2
+ // FSL-1.1-Apache-2.0 — see LICENSE
3
+ //
4
+ // Manages the persistent state layer for autonomous agents:
5
+ // .groove/auto/<agentDefId>/
6
+ // state.json — phase, cycle, history, champion
7
+ // journal.jsonl — append-only accumulated knowledge
8
+ // roadmap.md — staged goals with graduation criteria
9
+ // prompt.md — system prompt (identity + tools + rules)
10
+ // runs/ — per-run logs and output
11
+
12
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync, readdirSync, renameSync, copyFileSync, statSync, rmSync } from 'fs';
13
+ import { resolve } from 'path';
14
+ import { randomUUID } from 'crypto';
15
+
16
+ const MAX_HISTORY = 200;
17
+ const MAX_JOURNAL_ENTRIES = 500;
18
+
19
+ function safeJsonParse(str, fallback) {
20
+ try { return JSON.parse(str); } catch { return fallback; }
21
+ }
22
+
23
+ function safeDict(obj, key) {
24
+ const v = obj?.[key];
25
+ return v && typeof v === 'object' && !Array.isArray(v) ? v : {};
26
+ }
27
+
28
+ export class AutoState {
29
+ constructor(grooveDir) {
30
+ this.baseDir = resolve(grooveDir, 'auto');
31
+ mkdirSync(this.baseDir, { recursive: true });
32
+ }
33
+
34
+ _agentDir(defId) {
35
+ const dir = resolve(this.baseDir, defId);
36
+ mkdirSync(dir, { recursive: true });
37
+ mkdirSync(resolve(dir, 'runs'), { recursive: true });
38
+ return dir;
39
+ }
40
+
41
+ // --- State (state.json) ---
42
+
43
+ getState(defId) {
44
+ const p = resolve(this._agentDir(defId), 'state.json');
45
+ if (!existsSync(p)) return this._defaultState();
46
+ return safeJsonParse(readFileSync(p, 'utf8'), this._defaultState());
47
+ }
48
+
49
+ setState(defId, updates) {
50
+ const dir = this._agentDir(defId);
51
+ const p = resolve(dir, 'state.json');
52
+ const bak = resolve(dir, 'state.json.bak');
53
+ const current = this.getState(defId);
54
+
55
+ const merged = { ...current };
56
+ const allowed = ['phase', 'phase_note', 'cycle', 'current_run', 'champion', 'paused', 'error'];
57
+ for (const key of allowed) {
58
+ if (key in updates) merged[key] = updates[key];
59
+ }
60
+ merged.updatedAt = new Date().toISOString();
61
+
62
+ if (existsSync(p)) {
63
+ try { copyFileSync(p, bak); } catch { /* best effort */ }
64
+ }
65
+ const tmp = resolve(dir, `state.${randomUUID().slice(0, 8)}.tmp`);
66
+ writeFileSync(tmp, JSON.stringify(merged, null, 2));
67
+ renameSync(tmp, p);
68
+ return merged;
69
+ }
70
+
71
+ appendHistory(defId, entry) {
72
+ const state = this.getState(defId);
73
+ if (!Array.isArray(state.history)) state.history = [];
74
+ state.history.push({
75
+ ...entry,
76
+ timestamp: new Date().toISOString(),
77
+ });
78
+ if (state.history.length > MAX_HISTORY) {
79
+ state.history = state.history.slice(-MAX_HISTORY);
80
+ }
81
+ this.setState(defId, { history: state.history });
82
+ return state.history;
83
+ }
84
+
85
+ _defaultState() {
86
+ return {
87
+ phase: 'idle',
88
+ phase_note: '',
89
+ cycle: 0,
90
+ current_run: null,
91
+ champion: null,
92
+ history: [],
93
+ paused: false,
94
+ error: null,
95
+ createdAt: new Date().toISOString(),
96
+ updatedAt: new Date().toISOString(),
97
+ };
98
+ }
99
+
100
+ // --- Journal (journal.jsonl) ---
101
+
102
+ getJournal(defId, { limit = 50, since } = {}) {
103
+ const p = resolve(this._agentDir(defId), 'journal.jsonl');
104
+ if (!existsSync(p)) return [];
105
+ const lines = readFileSync(p, 'utf8').trim().split('\n').filter(Boolean);
106
+ let entries = lines.map(l => safeJsonParse(l, null)).filter(Boolean);
107
+ if (since) {
108
+ entries = entries.filter(e => e.timestamp >= since);
109
+ }
110
+ return entries.slice(-limit);
111
+ }
112
+
113
+ appendJournal(defId, entry) {
114
+ const p = resolve(this._agentDir(defId), 'journal.jsonl');
115
+ const record = {
116
+ ...entry,
117
+ timestamp: new Date().toISOString(),
118
+ };
119
+ appendFileSync(p, JSON.stringify(record) + '\n');
120
+ this._pruneJournal(defId);
121
+ return record;
122
+ }
123
+
124
+ _pruneJournal(defId) {
125
+ const p = resolve(this._agentDir(defId), 'journal.jsonl');
126
+ if (!existsSync(p)) return;
127
+ const lines = readFileSync(p, 'utf8').trim().split('\n').filter(Boolean);
128
+ if (lines.length > MAX_JOURNAL_ENTRIES) {
129
+ writeFileSync(p, lines.slice(-MAX_JOURNAL_ENTRIES).join('\n') + '\n');
130
+ }
131
+ }
132
+
133
+ // --- Roadmap (roadmap.md) ---
134
+
135
+ getRoadmap(defId) {
136
+ const p = resolve(this._agentDir(defId), 'roadmap.md');
137
+ if (!existsSync(p)) return '';
138
+ return readFileSync(p, 'utf8');
139
+ }
140
+
141
+ setRoadmap(defId, content) {
142
+ const p = resolve(this._agentDir(defId), 'roadmap.md');
143
+ writeFileSync(p, content);
144
+ }
145
+
146
+ // --- Prompt (prompt.md) ---
147
+
148
+ getPrompt(defId) {
149
+ const p = resolve(this._agentDir(defId), 'prompt.md');
150
+ if (!existsSync(p)) return '';
151
+ return readFileSync(p, 'utf8');
152
+ }
153
+
154
+ setPrompt(defId, content) {
155
+ const p = resolve(this._agentDir(defId), 'prompt.md');
156
+ writeFileSync(p, content);
157
+ }
158
+
159
+ // --- Run Logs ---
160
+
161
+ logRun(defId, runId, data) {
162
+ const dir = resolve(this._agentDir(defId), 'runs');
163
+ const p = resolve(dir, `${runId}.json`);
164
+ writeFileSync(p, JSON.stringify(data, null, 2));
165
+ }
166
+
167
+ getRunLog(defId, runId) {
168
+ const p = resolve(this._agentDir(defId), 'runs', `${runId}.json`);
169
+ if (!existsSync(p)) return null;
170
+ return safeJsonParse(readFileSync(p, 'utf8'), null);
171
+ }
172
+
173
+ listRuns(defId, { limit = 20 } = {}) {
174
+ const dir = resolve(this._agentDir(defId), 'runs');
175
+ if (!existsSync(dir)) return [];
176
+ const files = readdirSync(dir)
177
+ .filter(f => f.endsWith('.json'))
178
+ .map(f => {
179
+ const stat = statSync(resolve(dir, f));
180
+ return { runId: f.replace('.json', ''), mtime: stat.mtimeMs };
181
+ })
182
+ .sort((a, b) => b.mtime - a.mtime)
183
+ .slice(0, limit);
184
+ return files.map(f => {
185
+ const data = safeJsonParse(readFileSync(resolve(dir, `${f.runId}.json`), 'utf8'), {});
186
+ return { runId: f.runId, ...data };
187
+ });
188
+ }
189
+
190
+ // --- Cleanup ---
191
+
192
+ deleteAll(defId) {
193
+ const dir = resolve(this.baseDir, defId);
194
+ if (existsSync(dir)) {
195
+ rmSync(dir, { recursive: true, force: true });
196
+ }
197
+ }
198
+ }
@@ -47,6 +47,8 @@ import { RepoImporter } from './repo-import.js';
47
47
  import { ConversationManager } from './conversations.js';
48
48
  import { Toys } from './toys.js';
49
49
  import { InnerChat } from './innerchat.js';
50
+ import { AutoState } from './autostate.js';
51
+ import { Orchestrator } from './orchestrator.js';
50
52
  import { TrajectoryCapture, ConsentManager } from '../../../moe-training/client/index.js';
51
53
  import { isFirstRun, runFirstTimeSetup, loadConfig, saveConfig, printWelcome } from './firstrun.js';
52
54
  import { bindDaemon as bindGrooveNetworkDaemon } from './providers/groove-network.js';
@@ -160,6 +162,8 @@ export class Daemon {
160
162
  this.modelLab = new ModelLab(this);
161
163
  this.toys = new Toys(this);
162
164
  this.innerchat = new InnerChat(this);
165
+ this.autoState = new AutoState(this.grooveDir);
166
+ this.orchestrator = new Orchestrator(this);
163
167
  this.trajectoryCapture = null;
164
168
 
165
169
  // Hook teams.delete to clean up agent-loop session files
@@ -613,6 +617,7 @@ export class Daemon {
613
617
  this.journalist.start();
614
618
  this.rotator.start();
615
619
  this.scheduler.start();
620
+ this.orchestrator.start();
616
621
  this.timeline.start();
617
622
  this.gateways.start();
618
623
  this.federation.initialize();
@@ -837,6 +842,7 @@ export class Daemon {
837
842
  this.journalist.stop();
838
843
  this.rotator.stop();
839
844
  this.scheduler.stop();
845
+ this.orchestrator.stop();
840
846
  this.timeline.stop();
841
847
  if (this._gcInterval) clearInterval(this._gcInterval);
842
848
  if (this._stateSaveInterval) clearInterval(this._stateSaveInterval);