groove-dev 0.27.172 → 0.27.175

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 (47) hide show
  1. package/innerchat/Screenshot_2026-06-09_at_12.09.42_PM.png +0 -0
  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 +2 -0
  5. package/node_modules/@groove-dev/daemon/src/index.js +2 -0
  6. package/node_modules/@groove-dev/daemon/src/innerchat.js +100 -0
  7. package/node_modules/@groove-dev/daemon/src/process.js +5 -0
  8. package/node_modules/@groove-dev/daemon/src/providers/claude-code.js +2 -1
  9. package/node_modules/@groove-dev/daemon/src/routes/innerchat.js +34 -0
  10. package/node_modules/@groove-dev/daemon/src/validate.js +2 -2
  11. package/node_modules/@groove-dev/daemon/test/innerchat.test.js +203 -0
  12. package/node_modules/@groove-dev/gui/dist/assets/{index-BsCp-oqa.js → index-BMaxZVeX.js} +227 -222
  13. package/node_modules/@groove-dev/gui/dist/assets/index-BvJwMNAX.css +1 -0
  14. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  15. package/node_modules/@groove-dev/gui/package.json +1 -1
  16. package/node_modules/@groove-dev/gui/src/components/agents/agent-config.jsx +1 -0
  17. package/node_modules/@groove-dev/gui/src/components/agents/agent-feed.jsx +4 -4
  18. package/node_modules/@groove-dev/gui/src/components/agents/recommended-team-card.jsx +1 -1
  19. package/node_modules/@groove-dev/gui/src/components/chat/chat-messages.jsx +25 -1
  20. package/node_modules/@groove-dev/gui/src/components/fleet/fleet-pane.jsx +16 -3
  21. package/node_modules/@groove-dev/gui/src/stores/groove.js +51 -0
  22. package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +16 -0
  23. package/node_modules/@groove-dev/gui/src/views/agents.jsx +1 -1
  24. package/package.json +1 -1
  25. package/packages/cli/package.json +1 -1
  26. package/packages/daemon/package.json +1 -1
  27. package/packages/daemon/src/api.js +2 -0
  28. package/packages/daemon/src/index.js +2 -0
  29. package/packages/daemon/src/innerchat.js +100 -0
  30. package/packages/daemon/src/process.js +5 -0
  31. package/packages/daemon/src/providers/claude-code.js +2 -1
  32. package/packages/daemon/src/routes/innerchat.js +34 -0
  33. package/packages/daemon/src/validate.js +2 -2
  34. package/packages/gui/dist/assets/{index-BsCp-oqa.js → index-BMaxZVeX.js} +227 -222
  35. package/packages/gui/dist/assets/index-BvJwMNAX.css +1 -0
  36. package/packages/gui/dist/index.html +2 -2
  37. package/packages/gui/package.json +1 -1
  38. package/packages/gui/src/components/agents/agent-config.jsx +1 -0
  39. package/packages/gui/src/components/agents/agent-feed.jsx +4 -4
  40. package/packages/gui/src/components/agents/recommended-team-card.jsx +1 -1
  41. package/packages/gui/src/components/chat/chat-messages.jsx +25 -1
  42. package/packages/gui/src/components/fleet/fleet-pane.jsx +16 -3
  43. package/packages/gui/src/stores/groove.js +51 -0
  44. package/packages/gui/src/stores/slices/agents-slice.js +16 -0
  45. package/packages/gui/src/views/agents.jsx +1 -1
  46. package/node_modules/@groove-dev/gui/dist/assets/index-BrMU-6gi.css +0 -1
  47. package/packages/gui/dist/assets/index-BrMU-6gi.css +0 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/daemon",
3
- "version": "0.27.172",
3
+ "version": "0.27.175",
4
4
  "description": "GROOVE daemon — agent orchestration engine",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -27,6 +27,7 @@ import { registerIntegrationRoutes } from './routes/integrations.js';
27
27
  import { registerFileRoutes, resetEditorRoot } from './routes/files.js';
28
28
  import { registerNetworkRoutes } from './routes/network.js';
29
29
  import { registerScheduleRoutes } from './routes/schedules.js';
30
+ import { registerInnerChatRoutes } from './routes/innerchat.js';
30
31
 
31
32
  const __dirname = dirname(fileURLToPath(import.meta.url));
32
33
  const pkgVersion = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
@@ -175,6 +176,7 @@ export function createApi(app, daemon) {
175
176
  registerFileRoutes(app, daemon);
176
177
  registerNetworkRoutes(app, daemon);
177
178
  registerScheduleRoutes(app, daemon);
179
+ registerInnerChatRoutes(app, daemon);
178
180
 
179
181
 
180
182
  // Token usage
@@ -46,6 +46,7 @@ import { MLXServerManager } from './mlx-server.js';
46
46
  import { RepoImporter } from './repo-import.js';
47
47
  import { ConversationManager } from './conversations.js';
48
48
  import { Toys } from './toys.js';
49
+ import { InnerChat } from './innerchat.js';
49
50
  import { TrajectoryCapture, ConsentManager } from '../../../moe-training/client/index.js';
50
51
  import { isFirstRun, runFirstTimeSetup, loadConfig, saveConfig, printWelcome } from './firstrun.js';
51
52
  import { bindDaemon as bindGrooveNetworkDaemon } from './providers/groove-network.js';
@@ -158,6 +159,7 @@ export class Daemon {
158
159
  this.repoImporter = new RepoImporter(this);
159
160
  this.modelLab = new ModelLab(this);
160
161
  this.toys = new Toys(this);
162
+ this.innerchat = new InnerChat(this);
161
163
  this.trajectoryCapture = null;
162
164
 
163
165
  // Hook teams.delete to clean up agent-loop session files
@@ -0,0 +1,100 @@
1
+ // FSL-1.1-Apache-2.0 — see LICENSE
2
+
3
+ import { randomUUID } from 'crypto';
4
+
5
+ export class InnerChat {
6
+ constructor(daemon) {
7
+ this.daemon = daemon;
8
+ this.messages = new Map();
9
+ this.pendingResponses = new Map();
10
+ }
11
+
12
+ async send(fromAgentId, toAgentId, message) {
13
+ const fromAgent = this.daemon.registry.get(fromAgentId);
14
+ const toAgent = this.daemon.registry.get(toAgentId);
15
+ if (!fromAgent) throw new Error(`Sender agent ${fromAgentId} not found`);
16
+ if (!toAgent) throw new Error(`Target agent ${toAgentId} not found`);
17
+
18
+ const id = randomUUID().slice(0, 12);
19
+ const msg = {
20
+ id,
21
+ from: { id: fromAgent.id, name: fromAgent.name, role: fromAgent.role },
22
+ to: { id: toAgent.id, name: toAgent.name, role: toAgent.role },
23
+ message,
24
+ response: null,
25
+ status: 'sent',
26
+ timestamp: Date.now(),
27
+ respondedAt: null,
28
+ };
29
+
30
+ this.messages.set(id, msg);
31
+ this.pendingResponses.set(toAgentId, id);
32
+
33
+ const wrapped = `[InnerChat from ${fromAgent.name} (${fromAgent.role})]\n\n${message}\n\nReply normally — your response will be relayed back to ${fromAgent.name}.`;
34
+
35
+ let deliveryStatus = 'sent';
36
+ if (this.daemon.processes.hasAgentLoop(toAgentId)) {
37
+ const sent = await this.daemon.processes.sendMessage(toAgentId, wrapped, 'agent');
38
+ deliveryStatus = sent ? 'delivered' : 'queued';
39
+ } else if (this.daemon.processes.isRunning(toAgentId)) {
40
+ this.daemon.processes.queueMessage(toAgentId, wrapped);
41
+ deliveryStatus = 'queued';
42
+ } else {
43
+ throw new Error(`Target agent ${toAgent.name} is not running`);
44
+ }
45
+
46
+ msg.status = deliveryStatus;
47
+ this.daemon.broadcast({ type: 'innerchat:sent', data: msg });
48
+ this.daemon.audit.log('innerchat.send', { id, from: fromAgentId, to: toAgentId });
49
+
50
+ return msg;
51
+ }
52
+
53
+ onAgentOutput(agentId, output) {
54
+ const messageId = this.pendingResponses.get(agentId);
55
+ if (!messageId) return;
56
+ if (output.type !== 'result') return;
57
+
58
+ const msg = this.messages.get(messageId);
59
+ if (!msg) return;
60
+
61
+ let responseText = '';
62
+ if (typeof output.data === 'string') {
63
+ responseText = output.data;
64
+ } else if (Array.isArray(output.data)) {
65
+ responseText = output.data.filter(b => b.type === 'text').map(b => b.text).join('\n');
66
+ }
67
+ if (!responseText.trim()) return;
68
+
69
+ msg.response = responseText.trim();
70
+ msg.status = 'responded';
71
+ msg.respondedAt = Date.now();
72
+ this.pendingResponses.delete(agentId);
73
+
74
+ const relay = `[InnerChat reply from ${msg.to.name} (${msg.to.role})]\n\n${msg.response}`;
75
+ const senderId = msg.from.id;
76
+ if (this.daemon.processes.hasAgentLoop(senderId)) {
77
+ this.daemon.processes.sendMessage(senderId, relay, 'agent').catch(() => {});
78
+ } else if (this.daemon.processes.isRunning(senderId)) {
79
+ this.daemon.processes.queueMessage(senderId, relay);
80
+ }
81
+
82
+ this.daemon.broadcast({ type: 'innerchat:response', data: msg });
83
+ this.daemon.audit.log('innerchat.response', { id: messageId, from: msg.from.id, to: msg.to.id });
84
+ }
85
+
86
+ getMessages(agentId = null) {
87
+ const all = Array.from(this.messages.values());
88
+ if (!agentId) return all;
89
+ return all.filter(m => m.from.id === agentId || m.to.id === agentId);
90
+ }
91
+
92
+ getMessage(id) {
93
+ return this.messages.get(id) || null;
94
+ }
95
+
96
+ getPending(agentId) {
97
+ const messageId = this.pendingResponses.get(agentId);
98
+ return messageId ? this.messages.get(messageId) : null;
99
+ }
100
+ }
@@ -1582,6 +1582,11 @@ For normal file edits within your scope, proceed without review.
1582
1582
 
1583
1583
  registry.update(agentId, updates);
1584
1584
 
1585
+ // Notify innerchat for response capture
1586
+ if (this.daemon.innerchat) {
1587
+ this.daemon.innerchat.onAgentOutput(agentId, output);
1588
+ }
1589
+
1585
1590
  // Throttle streaming broadcasts to 4/sec per agent
1586
1591
  const isStreaming = output.type !== 'result';
1587
1592
  if (isStreaming) {
@@ -39,6 +39,7 @@ export class ClaudeCodeProvider extends Provider {
39
39
  static authType = 'subscription';
40
40
  static managesOwnContext = true; // Claude Code compacts context internally (~25-37% → 2-8%)
41
41
  static models = [
42
+ { id: 'claude-fable-5', name: 'Claude Fable 5', tier: 'heavy', contextWindow: 1_000_000 },
42
43
  { id: 'claude-opus-4-8', name: 'Claude Opus 4.8', tier: 'heavy', contextWindow: 1_000_000 },
43
44
  { id: 'claude-opus-4-6', name: 'Claude Opus 4.6', tier: 'heavy', contextWindow: 1_000_000 },
44
45
  { id: 'claude-sonnet-4-6', name: 'Claude Sonnet 4.6', tier: 'medium', contextWindow: 200_000 },
@@ -74,7 +75,7 @@ export class ClaudeCodeProvider extends Provider {
74
75
  normalizeConfig(config) {
75
76
  if (typeof config.reasoningEffort === 'number') {
76
77
  const e = config.reasoningEffort;
77
- config.effort = e <= 20 ? 'none' : e <= 40 ? 'low' : e <= 60 ? 'medium' : e <= 80 ? 'high' : 'xhigh';
78
+ config.effort = e <= 15 ? 'none' : e <= 30 ? 'low' : e <= 50 ? 'medium' : e <= 70 ? 'high' : e <= 85 ? 'xhigh' : 'ultra';
78
79
  }
79
80
  return config;
80
81
  }
@@ -0,0 +1,34 @@
1
+ // FSL-1.1-Apache-2.0 — see LICENSE
2
+
3
+ export function registerInnerChatRoutes(app, daemon) {
4
+ app.post('/api/innerchat/send', async (req, res) => {
5
+ try {
6
+ const { from, to, message } = req.body;
7
+ if (!from || typeof from !== 'string') return res.status(400).json({ error: 'from (agent ID) is required' });
8
+ if (!to || typeof to !== 'string') return res.status(400).json({ error: 'to (agent ID) is required' });
9
+ if (!message || typeof message !== 'string' || !message.trim()) return res.status(400).json({ error: 'message is required' });
10
+ if (from === to) return res.status(400).json({ error: 'cannot send a message to yourself' });
11
+
12
+ const msg = await daemon.innerchat.send(from, to, message.trim());
13
+ res.json(msg);
14
+ } catch (err) {
15
+ res.status(400).json({ error: err.message });
16
+ }
17
+ });
18
+
19
+ app.get('/api/innerchat/messages', (req, res) => {
20
+ const { agentId } = req.query;
21
+ res.json({ messages: daemon.innerchat.getMessages(agentId || null) });
22
+ });
23
+
24
+ app.get('/api/innerchat/messages/:id', (req, res) => {
25
+ const msg = daemon.innerchat.getMessage(req.params.id);
26
+ if (!msg) return res.status(404).json({ error: 'Message not found' });
27
+ res.json(msg);
28
+ });
29
+
30
+ app.get('/api/innerchat/pending/:agentId', (req, res) => {
31
+ const pending = daemon.innerchat.getPending(req.params.agentId);
32
+ res.json({ pending: pending || null });
33
+ });
34
+ }
@@ -112,7 +112,7 @@ export function validateAgentConfig(config) {
112
112
  if (!isNaN(v) && v >= 0 && v <= 100) verbosity = Math.round(v);
113
113
  }
114
114
 
115
- const validEffort = ['min', 'low', 'default', 'high', 'max'];
115
+ const validEffort = ['min', 'low', 'default', 'high', 'max', 'ultra'];
116
116
  const effort = validEffort.includes(config.effort) ? config.effort : undefined;
117
117
 
118
118
  const validRouting = ['fixed', 'auto', 'auto-floor'];
@@ -227,7 +227,7 @@ export function validateGatewayConfig(config) {
227
227
  };
228
228
  }
229
229
 
230
- const VALID_REASONING_EFFORTS = ['none', 'low', 'medium', 'high', 'xhigh'];
230
+ const VALID_REASONING_EFFORTS = ['none', 'low', 'medium', 'high', 'xhigh', 'ultra'];
231
231
  const VALID_VERBOSITIES = ['low', 'medium'];
232
232
 
233
233
  export function validateReasoningEffort(value) {