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.
Files changed (131) hide show
  1. package/node_modules/@groove-dev/cli/package.json +4 -3
  2. package/node_modules/@groove-dev/daemon/google-oauth.json +5 -0
  3. package/node_modules/@groove-dev/daemon/integrations-registry.json +0 -40
  4. package/node_modules/@groove-dev/daemon/package.json +4 -3
  5. package/node_modules/@groove-dev/daemon/src/api.js +212 -21
  6. package/node_modules/@groove-dev/daemon/src/index.js +68 -1
  7. package/node_modules/@groove-dev/daemon/src/integrations.js +59 -20
  8. package/node_modules/@groove-dev/daemon/src/process.js +83 -11
  9. package/node_modules/@groove-dev/daemon/src/providers/claude-code.js +4 -0
  10. package/node_modules/@groove-dev/daemon/src/registry.js +1 -1
  11. package/node_modules/@groove-dev/gui/.groove/audit.log +1 -0
  12. package/node_modules/@groove-dev/gui/.groove/codebase-index.json +64 -0
  13. package/node_modules/@groove-dev/gui/.groove/config.json +10 -0
  14. package/node_modules/@groove-dev/gui/.groove/coordination.md +5 -0
  15. package/node_modules/@groove-dev/gui/.groove/credentials.json +6 -0
  16. package/node_modules/@groove-dev/gui/.groove/daemon.port +1 -0
  17. package/node_modules/@groove-dev/gui/.groove/federation/identity.key +3 -0
  18. package/node_modules/@groove-dev/gui/.groove/federation/identity.pub +3 -0
  19. package/node_modules/@groove-dev/gui/.groove/integrations/package.json +6 -0
  20. package/node_modules/@groove-dev/gui/.groove/state.json +3 -0
  21. package/node_modules/@groove-dev/gui/dist/assets/index-x5suAiK7.js +182 -0
  22. package/node_modules/@groove-dev/gui/dist/index.html +1 -1
  23. package/node_modules/@groove-dev/gui/package.json +5 -4
  24. package/node_modules/@groove-dev/gui/src/App.jsx +149 -76
  25. package/node_modules/@groove-dev/gui/src/components/AgentActions.jsx +130 -1
  26. package/node_modules/@groove-dev/gui/src/components/AgentChat.jsx +47 -7
  27. package/node_modules/@groove-dev/gui/src/components/AgentNode.jsx +13 -83
  28. package/node_modules/@groove-dev/gui/src/components/SpawnPanel.jsx +918 -580
  29. package/node_modules/@groove-dev/gui/src/stores/groove.js +31 -2
  30. package/node_modules/@groove-dev/gui/src/views/AgentTree.jsx +133 -67
  31. package/node_modules/@groove-dev/gui/src/views/FileEditor.jsx +85 -1
  32. package/node_modules/@groove-dev/gui/src/views/IntegrationsStore.jsx +121 -44
  33. package/package.json +1 -2
  34. package/packages/cli/package.json +4 -3
  35. package/packages/daemon/integrations-registry.json +0 -40
  36. package/packages/daemon/package.json +4 -3
  37. package/packages/daemon/src/api.js +212 -21
  38. package/packages/daemon/src/index.js +68 -1
  39. package/packages/daemon/src/integrations.js +59 -20
  40. package/packages/daemon/src/process.js +83 -11
  41. package/packages/daemon/src/providers/claude-code.js +4 -0
  42. package/packages/daemon/src/registry.js +1 -1
  43. package/packages/gui/dist/assets/index-x5suAiK7.js +182 -0
  44. package/packages/gui/dist/index.html +1 -1
  45. package/packages/gui/node_modules/.vite/deps/@codemirror_autocomplete.js +68 -0
  46. package/packages/gui/node_modules/.vite/deps/@codemirror_autocomplete.js.map +7 -0
  47. package/packages/gui/node_modules/.vite/deps/@codemirror_commands.js +1420 -0
  48. package/packages/gui/node_modules/.vite/deps/@codemirror_commands.js.map +7 -0
  49. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-css.js +17 -0
  50. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-css.js.map +7 -0
  51. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-html.js +22 -0
  52. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-html.js.map +7 -0
  53. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-javascript.js +34 -0
  54. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-javascript.js.map +7 -0
  55. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-json.js +101 -0
  56. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-json.js.map +7 -0
  57. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-markdown.js +2534 -0
  58. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-markdown.js.map +7 -0
  59. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-python.js +789 -0
  60. package/packages/gui/node_modules/.vite/deps/@codemirror_lang-python.js.map +7 -0
  61. package/packages/gui/node_modules/.vite/deps/@codemirror_language.js +115 -0
  62. package/packages/gui/node_modules/.vite/deps/@codemirror_language.js.map +7 -0
  63. package/packages/gui/node_modules/.vite/deps/@codemirror_search.js +1136 -0
  64. package/packages/gui/node_modules/.vite/deps/@codemirror_search.js.map +7 -0
  65. package/packages/gui/node_modules/.vite/deps/@codemirror_state.js +63 -0
  66. package/packages/gui/node_modules/.vite/deps/@codemirror_state.js.map +7 -0
  67. package/packages/gui/node_modules/.vite/deps/@codemirror_theme-one-dark.js +179 -0
  68. package/packages/gui/node_modules/.vite/deps/@codemirror_theme-one-dark.js.map +7 -0
  69. package/packages/gui/node_modules/.vite/deps/@codemirror_view.js +104 -0
  70. package/packages/gui/node_modules/.vite/deps/@codemirror_view.js.map +7 -0
  71. package/packages/gui/node_modules/.vite/deps/@xterm_addon-fit.js +46 -0
  72. package/packages/gui/node_modules/.vite/deps/@xterm_addon-fit.js.map +7 -0
  73. package/packages/gui/node_modules/.vite/deps/@xterm_addon-web-links.js +121 -0
  74. package/packages/gui/node_modules/.vite/deps/@xterm_addon-web-links.js.map +7 -0
  75. package/packages/gui/node_modules/.vite/deps/@xterm_xterm.js +9237 -0
  76. package/packages/gui/node_modules/.vite/deps/@xterm_xterm.js.map +7 -0
  77. package/packages/gui/node_modules/.vite/deps/@xyflow_react.js +9934 -0
  78. package/packages/gui/node_modules/.vite/deps/@xyflow_react.js.map +7 -0
  79. package/packages/gui/node_modules/.vite/deps/_metadata.json +184 -0
  80. package/packages/gui/node_modules/.vite/deps/chunk-3EE34IFC.js +5169 -0
  81. package/packages/gui/node_modules/.vite/deps/chunk-3EE34IFC.js.map +7 -0
  82. package/packages/gui/node_modules/.vite/deps/chunk-3IB5EUP7.js +2000 -0
  83. package/packages/gui/node_modules/.vite/deps/chunk-3IB5EUP7.js.map +7 -0
  84. package/packages/gui/node_modules/.vite/deps/chunk-3LBP22MX.js +1115 -0
  85. package/packages/gui/node_modules/.vite/deps/chunk-3LBP22MX.js.map +7 -0
  86. package/packages/gui/node_modules/.vite/deps/chunk-3Q7HT7ZF.js +701 -0
  87. package/packages/gui/node_modules/.vite/deps/chunk-3Q7HT7ZF.js.map +7 -0
  88. package/packages/gui/node_modules/.vite/deps/chunk-44CLUOQE.js +1776 -0
  89. package/packages/gui/node_modules/.vite/deps/chunk-44CLUOQE.js.map +7 -0
  90. package/packages/gui/node_modules/.vite/deps/chunk-5RZAEUNX.js +280 -0
  91. package/packages/gui/node_modules/.vite/deps/chunk-5RZAEUNX.js.map +7 -0
  92. package/packages/gui/node_modules/.vite/deps/chunk-5WRI5ZAA.js +30 -0
  93. package/packages/gui/node_modules/.vite/deps/chunk-5WRI5ZAA.js.map +7 -0
  94. package/packages/gui/node_modules/.vite/deps/chunk-7FYDPZIO.js +1004 -0
  95. package/packages/gui/node_modules/.vite/deps/chunk-7FYDPZIO.js.map +7 -0
  96. package/packages/gui/node_modules/.vite/deps/chunk-BX6POZPY.js +292 -0
  97. package/packages/gui/node_modules/.vite/deps/chunk-BX6POZPY.js.map +7 -0
  98. package/packages/gui/node_modules/.vite/deps/chunk-HVFOBSCQ.js +1062 -0
  99. package/packages/gui/node_modules/.vite/deps/chunk-HVFOBSCQ.js.map +7 -0
  100. package/packages/gui/node_modules/.vite/deps/chunk-RE2FU7ZU.js +10985 -0
  101. package/packages/gui/node_modules/.vite/deps/chunk-RE2FU7ZU.js.map +7 -0
  102. package/packages/gui/node_modules/.vite/deps/chunk-YYJMNVCJ.js +3459 -0
  103. package/packages/gui/node_modules/.vite/deps/chunk-YYJMNVCJ.js.map +7 -0
  104. package/packages/gui/node_modules/.vite/deps/package.json +3 -0
  105. package/packages/gui/node_modules/.vite/deps/react-dom.js +6 -0
  106. package/packages/gui/node_modules/.vite/deps/react-dom.js.map +7 -0
  107. package/packages/gui/node_modules/.vite/deps/react-dom_client.js +20217 -0
  108. package/packages/gui/node_modules/.vite/deps/react-dom_client.js.map +7 -0
  109. package/packages/gui/node_modules/.vite/deps/react.js +5 -0
  110. package/packages/gui/node_modules/.vite/deps/react.js.map +7 -0
  111. package/packages/gui/node_modules/.vite/deps/react_jsx-dev-runtime.js +278 -0
  112. package/packages/gui/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
  113. package/packages/gui/node_modules/.vite/deps/react_jsx-runtime.js +6 -0
  114. package/packages/gui/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
  115. package/packages/gui/node_modules/.vite/deps/zustand.js +56 -0
  116. package/packages/gui/node_modules/.vite/deps/zustand.js.map +7 -0
  117. package/packages/gui/package.json +5 -4
  118. package/packages/gui/src/App.jsx +149 -76
  119. package/packages/gui/src/components/AgentActions.jsx +130 -1
  120. package/packages/gui/src/components/AgentChat.jsx +47 -7
  121. package/packages/gui/src/components/AgentNode.jsx +13 -83
  122. package/packages/gui/src/components/SpawnPanel.jsx +918 -580
  123. package/packages/gui/src/stores/groove.js +31 -2
  124. package/packages/gui/src/views/AgentTree.jsx +133 -67
  125. package/packages/gui/src/views/FileEditor.jsx +85 -1
  126. package/packages/gui/src/views/IntegrationsStore.jsx +121 -44
  127. package/docs/FILE-EDITOR-PLAN.md +0 -253
  128. package/docs/GUI_DESIGN_SPEC.md +0 -402
  129. package/docs/SKILLS-API-SPEC.md +0 -277
  130. package/node_modules/@groove-dev/gui/dist/assets/index-D5dtDQf0.js +0 -156
  131. 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 planning and architecture agent. Research, analyze, and create plans do NOT implement code unless explicitly asked. Focus on:
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": "fullstack", "scope": [], "prompt": "Set up project infrastructure: package.json, tsconfig, vite config, dependencies. Once all other agents finish, audit and QC their work, fix any issues, then launch the dev server. Output the localhost URL where the app can be accessed." },
74
- { "role": "backend", "scope": ["src/api/**", "src/server/**", "src/db/**", "src/lib/**"], "workingDir": "packages/backend", "prompt": "Build the backend: [specific tasks from your plan]" },
75
- { "role": "frontend", "scope": ["src/components/**", "src/views/**", "src/pages/**", "src/styles/**"], "workingDir": "packages/frontend", "prompt": "Build the frontend: [specific tasks from your plan]" }
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
- Include only the agents needed. Set appropriate scopes for each role. Write detailed prompts based on your plan so each agent knows exactly what to build.
79
- If the project is a monorepo or has distinct subdirectories (e.g. packages/, apps/), set "workingDir" to the relative path for each agent so it spawns inside its subdirectory. Omit workingDir for agents that need full project access (like fullstack or planner).
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
- Always include a fullstack agent. Its job: set up infrastructure first, then after all other agents finish, audit their work, fix issues, build the project, launch the dev server, and output the localhost URL so the user can immediately see the result. Include testing/devops only if the project needs them.
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];