groove-dev 0.10.10 → 0.11.0

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 (33) hide show
  1. package/README.md +24 -16
  2. package/node_modules/@groove-dev/cli/package.json +1 -1
  3. package/node_modules/@groove-dev/daemon/package.json +1 -1
  4. package/node_modules/@groove-dev/daemon/src/api.js +22 -0
  5. package/node_modules/@groove-dev/daemon/src/index.js +5 -0
  6. package/node_modules/@groove-dev/daemon/src/indexer.js +324 -0
  7. package/node_modules/@groove-dev/daemon/src/introducer.js +55 -4
  8. package/node_modules/@groove-dev/daemon/src/journalist.js +140 -51
  9. package/node_modules/@groove-dev/daemon/src/process.js +3 -2
  10. package/node_modules/@groove-dev/gui/dist/assets/index-BqZnnVJF.js +73 -0
  11. package/node_modules/@groove-dev/gui/dist/index.html +1 -1
  12. package/node_modules/@groove-dev/gui/package.json +1 -1
  13. package/node_modules/@groove-dev/gui/src/components/AgentNode.jsx +6 -4
  14. package/node_modules/@groove-dev/gui/src/components/AgentStats.jsx +1 -0
  15. package/node_modules/@groove-dev/gui/src/components/SpawnPanel.jsx +70 -0
  16. package/package.json +1 -1
  17. package/packages/cli/package.json +1 -1
  18. package/packages/daemon/package.json +1 -1
  19. package/packages/daemon/src/api.js +22 -0
  20. package/packages/daemon/src/index.js +5 -0
  21. package/packages/daemon/src/indexer.js +324 -0
  22. package/packages/daemon/src/introducer.js +55 -4
  23. package/packages/daemon/src/journalist.js +140 -51
  24. package/packages/daemon/src/process.js +3 -2
  25. package/packages/gui/dist/assets/index-BqZnnVJF.js +73 -0
  26. package/packages/gui/dist/index.html +1 -1
  27. package/packages/gui/package.json +1 -1
  28. package/packages/gui/src/components/AgentNode.jsx +6 -4
  29. package/packages/gui/src/components/AgentStats.jsx +1 -0
  30. package/packages/gui/src/components/SpawnPanel.jsx +70 -0
  31. package/groove-logo.png +0 -0
  32. package/node_modules/@groove-dev/gui/dist/assets/index-BPVh7Oqk.js +0 -73
  33. package/packages/gui/dist/assets/index-BPVh7Oqk.js +0 -73
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>GROOVE</title>
7
- <script type="module" crossorigin src="/assets/index-BPVh7Oqk.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-BqZnnVJF.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-CPzm9ZE9.css">
9
9
  </head>
10
10
  <body>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/gui",
3
- "version": "0.10.10",
3
+ "version": "0.11.0",
4
4
  "description": "GROOVE GUI — visual agent control plane",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -35,10 +35,12 @@ export default function AgentNode({ data }) {
35
35
  ? data.tokensUsed > 999 ? `${(data.tokensUsed / 1000).toFixed(1)}k` : `${data.tokensUsed}`
36
36
  : '0';
37
37
 
38
- // Get scope summary for activity text
39
- const activity = data.scope?.length > 0
40
- ? data.scope[0].replace(/\/\*\*$/, '').replace(/^src\//, '')
41
- : data.role;
38
+ // Get scope summary for activity text — prefer workingDir if set
39
+ const activity = data.workingDir
40
+ ? data.workingDir.replace(/^\.\//, '')
41
+ : data.scope?.length > 0
42
+ ? data.scope[0].replace(/\/\*\*$/, '').replace(/^src\//, '')
43
+ : data.role;
42
44
 
43
45
  return (
44
46
  <div style={{
@@ -61,6 +61,7 @@ export default function AgentStats({ agent }) {
61
61
  <InfoRow label="Role" value={agent.role} />
62
62
  <InfoRow label="Provider" value={agent.provider} />
63
63
  <InfoRow label="Model" value={agent.model || 'default'} />
64
+ {agent.workingDir && <InfoRow label="Directory" value={agent.workingDir} />}
64
65
  <InfoRow label="Scope" value={(agent.scope || []).join(', ') || 'unrestricted'} />
65
66
  <InfoRow label="Spawned" value={agent.spawnedAt ? new Date(agent.spawnedAt).toLocaleTimeString() : '-'} />
66
67
  <InfoRow label="Last Active" value={agent.lastActivity ? new Date(agent.lastActivity).toLocaleTimeString() : '-'} />
@@ -34,12 +34,15 @@ export default function SpawnPanel() {
34
34
  const [submitting, setSubmitting] = useState(false);
35
35
  const [error, setError] = useState('');
36
36
  const [showAdvanced, setShowAdvanced] = useState(false);
37
+ const [workingDir, setWorkingDir] = useState('');
38
+ const [workspaces, setWorkspaces] = useState([]);
37
39
  const [connectingProvider, setConnectingProvider] = useState(null);
38
40
  const [apiKeyInput, setApiKeyInput] = useState('');
39
41
  const [keySaving, setKeySaving] = useState(false);
40
42
 
41
43
  useEffect(() => {
42
44
  fetchProviders();
45
+ fetchWorkspaces();
43
46
  }, []);
44
47
 
45
48
  async function fetchProviders() {
@@ -49,6 +52,14 @@ export default function SpawnPanel() {
49
52
  } catch { /* ignore */ }
50
53
  }
51
54
 
55
+ async function fetchWorkspaces() {
56
+ try {
57
+ const res = await fetch('/api/indexer/workspaces');
58
+ const data = await res.json();
59
+ setWorkspaces(data.workspaces || []);
60
+ } catch { /* ignore */ }
61
+ }
62
+
52
63
  const selectedPreset = ROLE_PRESETS.find((p) => p.id === role);
53
64
  const effectiveScope = role === 'custom'
54
65
  ? scope
@@ -113,6 +124,7 @@ export default function SpawnPanel() {
113
124
  model: model || 'auto',
114
125
  provider,
115
126
  permission,
127
+ ...(workingDir.trim() ? { workingDir: workingDir.trim() } : {}),
116
128
  });
117
129
  closeDetail();
118
130
  } catch (err) {
@@ -198,6 +210,42 @@ export default function SpawnPanel() {
198
210
  rows={3}
199
211
  />
200
212
 
213
+ {/* Workspace picker — visible by default when workspaces detected */}
214
+ {workspaces.length > 0 && (
215
+ <>
216
+ <div style={styles.label}>DIRECTORY</div>
217
+ <div style={styles.wsRow}>
218
+ <button
219
+ type="button"
220
+ onClick={() => setWorkingDir('')}
221
+ style={{
222
+ ...styles.wsBtn,
223
+ ...(!workingDir ? { borderColor: 'var(--accent)', color: 'var(--text-bright)' } : {}),
224
+ }}
225
+ >
226
+ project root
227
+ </button>
228
+ {workspaces.map((ws) => (
229
+ <button
230
+ key={ws.path}
231
+ type="button"
232
+ onClick={() => setWorkingDir(ws.path)}
233
+ style={{
234
+ ...styles.wsBtn,
235
+ ...(workingDir === ws.path ? { borderColor: 'var(--accent)', color: 'var(--text-bright)' } : {}),
236
+ }}
237
+ title={`${ws.name} (${ws.files} files)`}
238
+ >
239
+ {ws.path}
240
+ </button>
241
+ ))}
242
+ </div>
243
+ <div style={styles.hint}>
244
+ Agent spawns inside this directory and only sees this subtree
245
+ </div>
246
+ </>
247
+ )}
248
+
201
249
  {/* Permissions */}
202
250
  <div style={styles.label}>PERMISSIONS</div>
203
251
  <div style={styles.permGrid}>
@@ -231,6 +279,18 @@ export default function SpawnPanel() {
231
279
 
232
280
  {showAdvanced && (
233
281
  <>
282
+ {/* Working directory — manual input for custom paths */}
283
+ <div style={styles.label}>WORKING DIRECTORY</div>
284
+ <input
285
+ style={styles.input}
286
+ placeholder="e.g. packages/frontend (default: project root)"
287
+ value={workingDir}
288
+ onChange={(e) => setWorkingDir(e.target.value)}
289
+ />
290
+ <div style={styles.hint}>
291
+ Relative path — or use the directory buttons above
292
+ </div>
293
+
234
294
  {/* Provider selector with connection flow */}
235
295
  <div style={styles.label}>PROVIDER</div>
236
296
  {providerList.map((p) => {
@@ -501,6 +561,16 @@ const styles = {
501
561
  hint: {
502
562
  fontSize: 10, color: 'var(--text-muted)', marginTop: 3,
503
563
  },
564
+ wsRow: {
565
+ display: 'flex', flexWrap: 'wrap', gap: 4, marginTop: 6,
566
+ },
567
+ wsBtn: {
568
+ background: 'var(--bg-surface)', border: '1px solid var(--border)',
569
+ borderRadius: 2, padding: '3px 8px',
570
+ color: 'var(--text-dim)', fontSize: 10, cursor: 'pointer',
571
+ fontFamily: 'var(--font)',
572
+ transition: 'color 0.1s, border-color 0.1s',
573
+ },
504
574
  error: {
505
575
  color: 'var(--red)', fontSize: 11, marginTop: 8,
506
576
  },
package/groove-logo.png DELETED
Binary file