groove-dev 0.10.0 → 0.10.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.
@@ -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-iBqV1c12.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-C9USf6W_.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.0",
3
+ "version": "0.10.2",
4
4
  "description": "GROOVE GUI — visual agent control plane",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -62,30 +62,13 @@ export default function CommandCenter() {
62
62
  return (
63
63
  <div style={s.root}>
64
64
 
65
- {/* ROW 1 — Stat Cards */}
66
- <div style={s.statRow}>
67
- <StatCard
68
- label="Total Tokens"
69
- value={fmtNum(tokens.totalTokens)}
70
- sub={`${data.agents.total} agent${data.agents.total !== 1 ? 's' : ''}`}
71
- />
72
- <StatCard
73
- label="Estimated Savings"
74
- value={estDollarSaved > 0 ? `$${estDollarSaved.toFixed(2)}` : '$0.00'}
75
- sub={`${fmtNum(tokens.savings.total)} tokens saved`}
76
- color={GREEN}
77
- />
78
- <StatCard
79
- label="Efficiency"
80
- value={`${tokens.savings.percentage || 0}%`}
81
- sub="vs uncoordinated"
82
- color={tokens.savings.percentage > 0 ? GREEN : undefined}
83
- />
84
- <StatCard
85
- label="Rotations"
86
- value={rotation.totalRotations}
87
- sub={fmtUptime(uptime)}
88
- />
65
+ {/* ROW 1 — Connected Stat Bar */}
66
+ <div style={s.statBar}>
67
+ <StatCard label="Total Tokens" value={fmtNum(tokens.totalTokens)} sub={`${data.agents.total} agent${data.agents.total !== 1 ? 's' : ''}`} />
68
+ <StatCard label="Tokens Saved" value={fmtNum(tokens.savings.total)} sub={`${tokens.savings.percentage || 0}% efficiency`} color={GREEN} />
69
+ <StatCard label="Est. Savings" value={estDollarSaved > 0 ? `$${estDollarSaved.toFixed(2)}` : '$0.00'} sub="based on token costs" color={GREEN} />
70
+ <StatCard label="Rotations" value={rotation.totalRotations} sub={`${fmtNum(rotation.totalTokensSaved)} tok recovered`} />
71
+ <StatCard label="Uptime" value={fmtUptime(uptime)} sub={`${data.agents.running} running`} />
89
72
  </div>
90
73
 
91
74
  {/* ROW 2 — Area Chart + Donut */}
@@ -119,13 +102,16 @@ export default function CommandCenter() {
119
102
  <HorizBar label="Conflict Prevention" value={tokens.savings.fromConflictPrevention} max={tokens.savings.total || 1} color={AMBER} />
120
103
  <HorizBar label="Cold-Start Skip" value={tokens.savings.fromColdStartSkip} max={tokens.savings.total || 1} color={GREEN} />
121
104
  <div style={s.divider} />
122
- <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, color: '#5c6370', padding: '4px 0' }}>
105
+ <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, color: '#8b929e', padding: '4px 0' }}>
123
106
  <span>Without Groove</span>
124
- <span style={{ color: RED }}>{fmtNum(tokens.savings.estimatedWithoutGroove)}</span>
107
+ <span style={{ color: RED, fontWeight: 600 }}>{fmtNum(tokens.savings.estimatedWithoutGroove)}</span>
125
108
  </div>
126
- <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, color: '#5c6370', padding: '4px 0' }}>
109
+ <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, color: '#8b929e', padding: '4px 0' }}>
127
110
  <span>With Groove</span>
128
- <span style={{ color: GREEN }}>{fmtNum(tokens.totalTokens)}</span>
111
+ <span style={{ color: GREEN, fontWeight: 600 }}>{fmtNum(tokens.totalTokens)}</span>
112
+ </div>
113
+ <div style={{ fontSize: 8, color: '#5c6370', marginTop: 4, lineHeight: 1.4 }}>
114
+ Calculated from: rotation recovery (30% of degraded context), cold-start prevention (2K tokens/skip), conflict avoidance (500 tokens/conflict).
129
115
  </div>
130
116
  {journalist.lastSummary && (
131
117
  <>
@@ -176,9 +162,9 @@ export default function CommandCenter() {
176
162
  function StatCard({ label, value, sub, color }) {
177
163
  return (
178
164
  <div style={s.statCard}>
179
- <div style={{ fontSize: 22, fontWeight: 700, color: color || '#e6e6e6', lineHeight: 1 }}>{value}</div>
180
- <div style={{ fontSize: 9, color: '#5c6370', marginTop: 6, textTransform: 'uppercase', letterSpacing: 1 }}>{label}</div>
181
- {sub && <div style={{ fontSize: 9, color: '#3e4451', marginTop: 3 }}>{sub}</div>}
165
+ <div style={{ fontSize: 10, color: '#8b929e', textTransform: 'uppercase', letterSpacing: 1, marginBottom: 6 }}>{label}</div>
166
+ <div style={{ fontSize: 20, fontWeight: 700, color: color || '#e6e6e6', lineHeight: 1 }}>{value}</div>
167
+ {sub && <div style={{ fontSize: 9, color: '#6b7280', marginTop: 4 }}>{sub}</div>}
182
168
  </div>
183
169
  );
184
170
  }
@@ -437,13 +423,14 @@ const s = {
437
423
  loadingBar: { width: 120, height: 2, background: '#282c34', borderRadius: 1, overflow: 'hidden' },
438
424
  loadingFill: { width: '40%', height: '100%', background: ACCENT, animation: 'pulse 1.5s infinite' },
439
425
 
440
- // Stat cards row
441
- statRow: {
442
- display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12,
443
- flexShrink: 0,
426
+ // Stat bar — connected, no gaps
427
+ statBar: {
428
+ display: 'flex', flexShrink: 0,
429
+ background: '#282c34', borderRadius: 12, overflow: 'hidden',
444
430
  },
445
431
  statCard: {
446
- background: '#282c34', borderRadius: 12, padding: '16px 18px',
432
+ flex: 1, padding: '14px 16px',
433
+ borderRight: '1px solid #1e222a',
447
434
  display: 'flex', flexDirection: 'column',
448
435
  },
449
436
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groove-dev",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "Open-source agent orchestration layer for AI coding tools. GUI dashboard, multi-agent coordination, zero cold-start (Journalist), infinite sessions (adaptive context rotation), AI Project Manager, Quick Launch. Works with Claude Code, Codex, Gemini CLI, Ollama.",
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.10.0",
3
+ "version": "0.10.2",
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.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "GROOVE daemon — agent orchestration engine",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -165,6 +165,15 @@ For normal file edits within your scope, proceed without review.
165
165
  const spawnLine = `[${new Date().toISOString()}] GROOVE spawning: ${command} [${safeArgs.length} args]\n`;
166
166
  logStream.write(spawnLine);
167
167
 
168
+ // Inject API key from credential store if the provider needs one
169
+ const providerMeta = getProvider(agent.provider);
170
+ if (providerMeta?.constructor?.envKey) {
171
+ const storedKey = this.daemon.credentials.getKey(agent.provider);
172
+ if (storedKey) {
173
+ env[providerMeta.constructor.envKey] = storedKey;
174
+ }
175
+ }
176
+
168
177
  // Spawn the process
169
178
  const proc = cpSpawn(command, args, {
170
179
  cwd: agent.workingDir || this.daemon.projectDir,
@@ -11,6 +11,9 @@ export class CodexProvider extends Provider {
11
11
  static authType = 'api-key';
12
12
  static envKey = 'OPENAI_API_KEY';
13
13
  static models = [
14
+ { id: 'gpt-5.4', name: 'GPT-5.4', tier: 'heavy' },
15
+ { id: 'gpt-5.4-mini', name: 'GPT-5.4 Mini', tier: 'medium' },
16
+ { id: 'gpt-5.4-nano', name: 'GPT-5.4 Nano', tier: 'light' },
14
17
  { id: 'o3', name: 'o3', tier: 'heavy' },
15
18
  { id: 'o4-mini', name: 'o4-mini', tier: 'medium' },
16
19
  ];
@@ -11,6 +11,9 @@ export class GeminiProvider extends Provider {
11
11
  static authType = 'api-key';
12
12
  static envKey = 'GEMINI_API_KEY';
13
13
  static models = [
14
+ { id: 'gemini-3.0-pro', name: 'Gemini 3.0 Pro', tier: 'heavy' },
15
+ { id: 'gemini-3.0-flash', name: 'Gemini 3.0 Flash', tier: 'medium' },
16
+ { id: 'gemini-3.0-flash-lite', name: 'Gemini 3.0 Flash Lite', tier: 'light' },
14
17
  { id: 'gemini-2.5-pro', name: 'Gemini 2.5 Pro', tier: 'heavy' },
15
18
  { id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash', tier: 'medium' },
16
19
  ];