groove-dev 0.27.181 → 0.27.183

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 (63) hide show
  1. package/node_modules/@groove-dev/cli/package.json +1 -1
  2. package/node_modules/@groove-dev/daemon/package.json +1 -1
  3. package/node_modules/@groove-dev/daemon/scripts/repair-tokens.mjs +78 -0
  4. package/node_modules/@groove-dev/daemon/src/api.js +1 -1
  5. package/node_modules/@groove-dev/daemon/src/deliver.js +130 -0
  6. package/node_modules/@groove-dev/daemon/src/index.js +8 -3
  7. package/node_modules/@groove-dev/daemon/src/innerchat.js +213 -62
  8. package/node_modules/@groove-dev/daemon/src/journalist.js +15 -8
  9. package/node_modules/@groove-dev/daemon/src/process.js +59 -34
  10. package/node_modules/@groove-dev/daemon/src/providers/claude-code.js +9 -1
  11. package/node_modules/@groove-dev/daemon/src/registry.js +5 -1
  12. package/node_modules/@groove-dev/daemon/src/rename.js +72 -0
  13. package/node_modules/@groove-dev/daemon/src/rotator.js +62 -5
  14. package/node_modules/@groove-dev/daemon/src/routes/agents.js +22 -100
  15. package/node_modules/@groove-dev/daemon/src/routes/innerchat.js +12 -9
  16. package/node_modules/@groove-dev/daemon/src/teams.js +7 -1
  17. package/node_modules/@groove-dev/daemon/src/tokentracker.js +46 -6
  18. package/node_modules/@groove-dev/daemon/test/claude-code-provider.test.js +52 -0
  19. package/node_modules/@groove-dev/daemon/test/innerchat.test.js +197 -111
  20. package/node_modules/@groove-dev/daemon/test/journalist.test.js +4 -2
  21. package/node_modules/@groove-dev/daemon/test/rename.test.js +108 -0
  22. package/node_modules/@groove-dev/daemon/test/rotator.test.js +131 -0
  23. package/node_modules/@groove-dev/daemon/test/tokentracker.test.js +4 -0
  24. package/node_modules/@groove-dev/gui/dist/assets/{index-DTFtRtkx.css → index-CiOy7wVS.css} +1 -1
  25. package/node_modules/@groove-dev/gui/dist/assets/{index-CTer01Vg.js → index-DPjGBQ5X.js} +225 -225
  26. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  27. package/node_modules/@groove-dev/gui/package.json +1 -1
  28. package/node_modules/@groove-dev/gui/src/components/agents/agent-panel.jsx +3 -68
  29. package/node_modules/@groove-dev/gui/src/components/agents/innerchat-relay.jsx +145 -0
  30. package/node_modules/@groove-dev/gui/src/components/chat/chat-messages.jsx +3 -1
  31. package/node_modules/@groove-dev/gui/src/components/fleet/fleet-pane.jsx +15 -1
  32. package/node_modules/@groove-dev/gui/src/components/fleet/fleet-sidebar.jsx +33 -1
  33. package/node_modules/@groove-dev/gui/src/stores/groove.js +29 -44
  34. package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +27 -4
  35. package/package.json +1 -1
  36. package/packages/cli/package.json +1 -1
  37. package/packages/daemon/package.json +1 -1
  38. package/packages/daemon/scripts/repair-tokens.mjs +78 -0
  39. package/packages/daemon/src/api.js +1 -1
  40. package/packages/daemon/src/deliver.js +130 -0
  41. package/packages/daemon/src/index.js +8 -3
  42. package/packages/daemon/src/innerchat.js +213 -62
  43. package/packages/daemon/src/journalist.js +15 -8
  44. package/packages/daemon/src/process.js +59 -34
  45. package/packages/daemon/src/providers/claude-code.js +9 -1
  46. package/packages/daemon/src/registry.js +5 -1
  47. package/packages/daemon/src/rename.js +72 -0
  48. package/packages/daemon/src/rotator.js +62 -5
  49. package/packages/daemon/src/routes/agents.js +22 -100
  50. package/packages/daemon/src/routes/innerchat.js +12 -9
  51. package/packages/daemon/src/teams.js +7 -1
  52. package/packages/daemon/src/tokentracker.js +46 -6
  53. package/packages/gui/dist/assets/{index-DTFtRtkx.css → index-CiOy7wVS.css} +1 -1
  54. package/packages/gui/dist/assets/{index-CTer01Vg.js → index-DPjGBQ5X.js} +225 -225
  55. package/packages/gui/dist/index.html +2 -2
  56. package/packages/gui/package.json +1 -1
  57. package/packages/gui/src/components/agents/agent-panel.jsx +3 -68
  58. package/packages/gui/src/components/agents/innerchat-relay.jsx +145 -0
  59. package/packages/gui/src/components/chat/chat-messages.jsx +3 -1
  60. package/packages/gui/src/components/fleet/fleet-pane.jsx +15 -1
  61. package/packages/gui/src/components/fleet/fleet-sidebar.jsx +33 -1
  62. package/packages/gui/src/stores/groove.js +29 -44
  63. package/packages/gui/src/stores/slices/agents-slice.js +27 -4
@@ -12,6 +12,14 @@ const COLD_START_PER_FILE = 15;
12
12
  const COLD_START_PER_DIR = 40;
13
13
  // Estimated tokens wasted per file conflict (agent discovers, backs off, retries)
14
14
  const CONFLICT_OVERHEAD = 500;
15
+ // Max per-agent session records kept. Aggregates are cumulative and unaffected;
16
+ // windowed queries (getVelocity/getTokensInWindow) only need the recent tail,
17
+ // which 500 records covers by orders of magnitude. Uncapped, tokens.json grew
18
+ // to 13.8MB and was rewritten on every assistant stream event.
19
+ const SESSION_CAP = 500;
20
+ // Debounce window for persisting to disk. record() fires per assistant event —
21
+ // writing the full ledger each time is a hot-path full-file rewrite.
22
+ const SAVE_DEBOUNCE_MS = 5_000;
15
23
 
16
24
  export class TokenTracker {
17
25
  constructor(grooveDir) {
@@ -23,6 +31,7 @@ export class TokenTracker {
23
31
  this.coldStartsSkipped = 0;
24
32
  this.projectFiles = 0; // Set from indexer stats
25
33
  this.projectDirs = 0;
34
+ this._saveTimer = null;
26
35
  this.load();
27
36
  }
28
37
 
@@ -47,6 +56,7 @@ export class TokenTracker {
47
56
  if (!entry.totalDurationMs) entry.totalDurationMs = 0;
48
57
  if (!entry.totalTurns) entry.totalTurns = 0;
49
58
  if (!entry.modelDistribution) entry.modelDistribution = {};
59
+ this._capSessions(entry);
50
60
  }
51
61
  } catch {
52
62
  this.usage = {};
@@ -55,6 +65,10 @@ export class TokenTracker {
55
65
  }
56
66
 
57
67
  save() {
68
+ if (this._saveTimer) {
69
+ clearTimeout(this._saveTimer);
70
+ this._saveTimer = null;
71
+ }
58
72
  writeFileSync(this.path, JSON.stringify({
59
73
  usage: this.usage,
60
74
  rotationSavings: this.rotationSavings,
@@ -64,6 +78,30 @@ export class TokenTracker {
64
78
  }, null, 2));
65
79
  }
66
80
 
81
+ // Debounced persistence for hot-path recording. In-memory state is always
82
+ // current; at most SAVE_DEBOUNCE_MS of records are at risk on a crash.
83
+ _scheduleSave() {
84
+ if (this._saveTimer) return;
85
+ this._saveTimer = setTimeout(() => {
86
+ this._saveTimer = null;
87
+ try { this.save(); } catch { /* best-effort */ }
88
+ }, SAVE_DEBOUNCE_MS);
89
+ this._saveTimer.unref?.();
90
+ }
91
+
92
+ // Write any pending debounced state to disk. Call on daemon shutdown.
93
+ flush() {
94
+ if (this._saveTimer) {
95
+ try { this.save(); } catch { /* best-effort */ }
96
+ }
97
+ }
98
+
99
+ _capSessions(entry) {
100
+ if (Array.isArray(entry.sessions) && entry.sessions.length > SESSION_CAP) {
101
+ entry.sessions.splice(0, entry.sessions.length - SESSION_CAP);
102
+ }
103
+ }
104
+
67
105
  _initAgent(agentId) {
68
106
  if (!this.usage[agentId]) {
69
107
  this.usage[agentId] = {
@@ -89,7 +127,8 @@ export class TokenTracker {
89
127
  if (typeof detail === 'number') {
90
128
  entry.total += detail;
91
129
  entry.sessions.push({ tokens: detail, timestamp: new Date().toISOString() });
92
- this.save();
130
+ this._capSessions(entry);
131
+ this._scheduleSave();
93
132
  return;
94
133
  }
95
134
 
@@ -121,8 +160,9 @@ export class TokenTracker {
121
160
  projectRoot: detail.projectRoot || null,
122
161
  timestamp: new Date().toISOString(),
123
162
  });
163
+ this._capSessions(entry);
124
164
 
125
- this.save();
165
+ this._scheduleSave();
126
166
  }
127
167
 
128
168
  // Sum tokens recorded for an agent since a given timestamp.
@@ -152,25 +192,25 @@ export class TokenTracker {
152
192
  if (costUsd) entry.totalCostUsd += costUsd;
153
193
  if (durationMs) entry.totalDurationMs += durationMs;
154
194
  if (turns) entry.totalTurns += turns;
155
- this.save();
195
+ this._scheduleSave();
156
196
  }
157
197
 
158
198
  // Record that a rotation saved context tokens
159
199
  recordRotation(agentId, tokensBefore) {
160
200
  this.rotationSavings += Math.round(tokensBefore * 0.3); // ~30% of context was degraded
161
- this.save();
201
+ this._scheduleSave();
162
202
  }
163
203
 
164
204
  // Record that a conflict was prevented (scope enforcement)
165
205
  recordConflictPrevented() {
166
206
  this.conflictsPrevented++;
167
- this.save();
207
+ this._scheduleSave();
168
208
  }
169
209
 
170
210
  // Record that a cold-start was skipped (Journalist provided context)
171
211
  recordColdStartSkipped() {
172
212
  this.coldStartsSkipped++;
173
- this.save();
213
+ this._scheduleSave();
174
214
  }
175
215
 
176
216
  // Set project size from indexer for dynamic cold-start estimation