groove-dev 0.8.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 (84) hide show
  1. package/CLAUDE.md +197 -0
  2. package/LICENSE +40 -0
  3. package/README.md +115 -0
  4. package/docs/GUI_DESIGN_SPEC.md +402 -0
  5. package/favicon.png +0 -0
  6. package/groove-logo-short.png +0 -0
  7. package/groove-logo.png +0 -0
  8. package/package.json +70 -0
  9. package/packages/cli/bin/groove.js +98 -0
  10. package/packages/cli/package.json +15 -0
  11. package/packages/cli/src/client.js +25 -0
  12. package/packages/cli/src/commands/agents.js +38 -0
  13. package/packages/cli/src/commands/approve.js +50 -0
  14. package/packages/cli/src/commands/config.js +35 -0
  15. package/packages/cli/src/commands/kill.js +15 -0
  16. package/packages/cli/src/commands/nuke.js +19 -0
  17. package/packages/cli/src/commands/providers.js +40 -0
  18. package/packages/cli/src/commands/rotate.js +16 -0
  19. package/packages/cli/src/commands/spawn.js +91 -0
  20. package/packages/cli/src/commands/start.js +31 -0
  21. package/packages/cli/src/commands/status.js +38 -0
  22. package/packages/cli/src/commands/stop.js +15 -0
  23. package/packages/cli/src/commands/team.js +77 -0
  24. package/packages/daemon/package.json +18 -0
  25. package/packages/daemon/src/adaptive.js +237 -0
  26. package/packages/daemon/src/api.js +533 -0
  27. package/packages/daemon/src/classifier.js +126 -0
  28. package/packages/daemon/src/credentials.js +121 -0
  29. package/packages/daemon/src/firstrun.js +93 -0
  30. package/packages/daemon/src/index.js +208 -0
  31. package/packages/daemon/src/introducer.js +238 -0
  32. package/packages/daemon/src/journalist.js +600 -0
  33. package/packages/daemon/src/lockmanager.js +58 -0
  34. package/packages/daemon/src/pm.js +108 -0
  35. package/packages/daemon/src/process.js +361 -0
  36. package/packages/daemon/src/providers/aider.js +72 -0
  37. package/packages/daemon/src/providers/base.js +38 -0
  38. package/packages/daemon/src/providers/claude-code.js +167 -0
  39. package/packages/daemon/src/providers/codex.js +68 -0
  40. package/packages/daemon/src/providers/gemini.js +62 -0
  41. package/packages/daemon/src/providers/index.js +38 -0
  42. package/packages/daemon/src/providers/ollama.js +94 -0
  43. package/packages/daemon/src/registry.js +89 -0
  44. package/packages/daemon/src/rotator.js +185 -0
  45. package/packages/daemon/src/router.js +132 -0
  46. package/packages/daemon/src/state.js +34 -0
  47. package/packages/daemon/src/supervisor.js +178 -0
  48. package/packages/daemon/src/teams.js +203 -0
  49. package/packages/daemon/src/terminal/base.js +27 -0
  50. package/packages/daemon/src/terminal/generic.js +27 -0
  51. package/packages/daemon/src/terminal/tmux.js +64 -0
  52. package/packages/daemon/src/tokentracker.js +124 -0
  53. package/packages/daemon/src/validate.js +122 -0
  54. package/packages/daemon/templates/api-builder.json +18 -0
  55. package/packages/daemon/templates/fullstack.json +18 -0
  56. package/packages/daemon/templates/monorepo.json +24 -0
  57. package/packages/gui/dist/assets/index-BO95Rm1F.js +73 -0
  58. package/packages/gui/dist/assets/index-CPzm9ZE9.css +1 -0
  59. package/packages/gui/dist/favicon.png +0 -0
  60. package/packages/gui/dist/groove-logo-short.png +0 -0
  61. package/packages/gui/dist/groove-logo.png +0 -0
  62. package/packages/gui/dist/index.html +13 -0
  63. package/packages/gui/index.html +12 -0
  64. package/packages/gui/package.json +22 -0
  65. package/packages/gui/public/favicon.png +0 -0
  66. package/packages/gui/public/groove-logo-short.png +0 -0
  67. package/packages/gui/public/groove-logo.png +0 -0
  68. package/packages/gui/src/App.jsx +215 -0
  69. package/packages/gui/src/components/AgentActions.jsx +347 -0
  70. package/packages/gui/src/components/AgentChat.jsx +479 -0
  71. package/packages/gui/src/components/AgentNode.jsx +117 -0
  72. package/packages/gui/src/components/AgentPanel.jsx +115 -0
  73. package/packages/gui/src/components/AgentStats.jsx +333 -0
  74. package/packages/gui/src/components/ApprovalQueue.jsx +156 -0
  75. package/packages/gui/src/components/EmptyState.jsx +100 -0
  76. package/packages/gui/src/components/SpawnPanel.jsx +515 -0
  77. package/packages/gui/src/components/TeamSelector.jsx +162 -0
  78. package/packages/gui/src/main.jsx +9 -0
  79. package/packages/gui/src/stores/groove.js +247 -0
  80. package/packages/gui/src/theme.css +67 -0
  81. package/packages/gui/src/views/AgentTree.jsx +148 -0
  82. package/packages/gui/src/views/CommandCenter.jsx +620 -0
  83. package/packages/gui/src/views/JournalistFeed.jsx +149 -0
  84. package/packages/gui/vite.config.js +19 -0
@@ -0,0 +1,149 @@
1
+ // GROOVE GUI — Journalist Feed (detail panel)
2
+ // FSL-1.1-Apache-2.0 — see LICENSE
3
+
4
+ import React, { useState, useEffect } from 'react';
5
+
6
+ export default function JournalistFeed() {
7
+ const [data, setData] = useState(null);
8
+ const [loading, setLoading] = useState(true);
9
+
10
+ useEffect(() => {
11
+ fetchJournalist();
12
+ const interval = setInterval(fetchJournalist, 10_000);
13
+ return () => clearInterval(interval);
14
+ }, []);
15
+
16
+ async function fetchJournalist() {
17
+ try {
18
+ const res = await fetch('/api/journalist');
19
+ setData(await res.json());
20
+ } catch { /* ignore */ }
21
+ setLoading(false);
22
+ }
23
+
24
+ async function triggerCycle() {
25
+ setLoading(true);
26
+ try {
27
+ await fetch('/api/journalist/cycle', { method: 'POST' });
28
+ await fetchJournalist();
29
+ } catch { /* ignore */ }
30
+ setLoading(false);
31
+ }
32
+
33
+ return (
34
+ <div style={{ paddingTop: 4 }}>
35
+ <div style={styles.header}>
36
+ <span style={styles.title}>THE JOURNALIST</span>
37
+ <button onClick={triggerCycle} disabled={loading} style={styles.btn}>
38
+ {loading ? 'synthesizing...' : 'Run Cycle'}
39
+ </button>
40
+ </div>
41
+
42
+ {/* Status */}
43
+ <div style={styles.statusRow}>
44
+ <span>Status: {data?.running ? 'active' : 'stopped'}</span>
45
+ <span>Cycles: {data?.cycleCount || 0}</span>
46
+ {data?.lastCycleAt && (
47
+ <span>Last: {new Date(data.lastCycleAt).toLocaleTimeString()}</span>
48
+ )}
49
+ </div>
50
+
51
+ {/* Latest synthesis */}
52
+ {data?.lastSynthesis ? (
53
+ <div>
54
+ <div style={styles.sectionLabel}>SUMMARY</div>
55
+ <div style={styles.textBox}>{data.lastSynthesis.summary}</div>
56
+
57
+ {data.lastSynthesis.projectMap && (
58
+ <>
59
+ <div style={styles.sectionLabel}>PROJECT MAP</div>
60
+ <pre style={styles.codeBox}>{data.lastSynthesis.projectMap}</pre>
61
+ </>
62
+ )}
63
+
64
+ {data.lastSynthesis.decisions && (
65
+ <>
66
+ <div style={styles.sectionLabel}>DECISIONS</div>
67
+ <pre style={styles.codeBox}>{data.lastSynthesis.decisions}</pre>
68
+ </>
69
+ )}
70
+ </div>
71
+ ) : (
72
+ <div style={styles.empty}>
73
+ No synthesis yet. The Journalist runs every 2 minutes when agents are active.
74
+ </div>
75
+ )}
76
+
77
+ {/* History */}
78
+ {data?.history?.length > 0 && (
79
+ <>
80
+ <div style={styles.sectionLabel}>HISTORY</div>
81
+ <div style={styles.historyList}>
82
+ {data.history.slice().reverse().map((h, i) => (
83
+ <div key={i} style={styles.historyEntry}>
84
+ <span style={styles.historyTime}>
85
+ {new Date(h.timestamp).toLocaleTimeString()}
86
+ </span>
87
+ <span style={styles.historyText}>
88
+ Cycle {h.cycle}: {h.agentCount} agent{h.agentCount !== 1 ? 's' : ''} — {h.summary?.slice(0, 80)}
89
+ </span>
90
+ </div>
91
+ ))}
92
+ </div>
93
+ </>
94
+ )}
95
+ </div>
96
+ );
97
+ }
98
+
99
+ const styles = {
100
+ header: {
101
+ display: 'flex', justifyContent: 'space-between', alignItems: 'center',
102
+ marginBottom: 10,
103
+ },
104
+ title: {
105
+ fontSize: 11, fontWeight: 600, color: 'var(--text-dim)',
106
+ textTransform: 'uppercase', letterSpacing: 1.5,
107
+ },
108
+ btn: {
109
+ padding: '3px 10px',
110
+ background: 'transparent', border: '1px solid var(--purple)',
111
+ borderRadius: 2,
112
+ color: 'var(--purple)', fontSize: 11, cursor: 'pointer',
113
+ fontFamily: 'var(--font)',
114
+ },
115
+ statusRow: {
116
+ display: 'flex', gap: 12, fontSize: 11, color: 'var(--text-dim)',
117
+ marginBottom: 12, padding: '6px 0',
118
+ borderBottom: '1px solid var(--border)',
119
+ flexWrap: 'wrap',
120
+ },
121
+ sectionLabel: {
122
+ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase',
123
+ letterSpacing: 1.5, marginBottom: 4, marginTop: 12, fontWeight: 600,
124
+ },
125
+ textBox: {
126
+ background: 'var(--bg-base)', border: '1px solid var(--border)', borderRadius: 2,
127
+ padding: 8, fontSize: 12, color: 'var(--text-primary)', lineHeight: 1.5,
128
+ },
129
+ codeBox: {
130
+ background: 'var(--bg-base)', border: '1px solid var(--border)', borderRadius: 2,
131
+ padding: 8, fontSize: 11, color: 'var(--text-dim)', lineHeight: 1.5,
132
+ whiteSpace: 'pre-wrap',
133
+ maxHeight: 200, overflowY: 'auto', margin: 0,
134
+ },
135
+ empty: {
136
+ color: 'var(--text-dim)', fontSize: 12, padding: 16, textAlign: 'center',
137
+ },
138
+ historyList: {
139
+ maxHeight: 160, overflowY: 'auto',
140
+ background: 'var(--bg-base)', borderRadius: 2,
141
+ border: '1px solid var(--border)',
142
+ },
143
+ historyEntry: {
144
+ padding: '4px 8px', borderBottom: '1px solid var(--bg-surface)',
145
+ fontSize: 10, display: 'flex', gap: 6,
146
+ },
147
+ historyTime: { color: 'var(--text-dim)', whiteSpace: 'nowrap' },
148
+ historyText: { color: 'var(--text-primary)' },
149
+ };
@@ -0,0 +1,19 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ server: {
7
+ port: 3142,
8
+ proxy: {
9
+ '/api': 'http://localhost:31415',
10
+ '/ws': {
11
+ target: 'ws://localhost:31415',
12
+ ws: true,
13
+ },
14
+ },
15
+ },
16
+ build: {
17
+ outDir: 'dist',
18
+ },
19
+ });