groove-dev 0.27.144 → 0.27.146

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 (135) hide show
  1. package/CLAUDE.md +7 -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 +12 -6
  5. package/node_modules/@groove-dev/daemon/src/conversations.js +59 -58
  6. package/node_modules/@groove-dev/daemon/src/introducer.js +20 -0
  7. package/node_modules/@groove-dev/daemon/src/process.js +262 -15
  8. package/node_modules/@groove-dev/daemon/src/providers/groove-network.js +1 -3
  9. package/node_modules/@groove-dev/daemon/src/rotator.js +15 -3
  10. package/node_modules/@groove-dev/daemon/src/routes/agents.js +49 -83
  11. package/node_modules/@groove-dev/daemon/templates/lab-general.json +12 -0
  12. package/node_modules/@groove-dev/daemon/templates/llama-cpp-setup.json +12 -0
  13. package/node_modules/@groove-dev/gui/dist/assets/index-BKbsE_hn.js +1011 -0
  14. package/node_modules/@groove-dev/gui/dist/assets/index-CEkPsSAm.css +1 -0
  15. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  16. package/node_modules/@groove-dev/gui/package.json +1 -1
  17. package/node_modules/@groove-dev/gui/src/components/agents/agent-feed.jsx +80 -95
  18. package/node_modules/@groove-dev/gui/src/components/agents/agent-panel.jsx +2 -70
  19. package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +132 -4
  20. package/node_modules/@groove-dev/gui/src/components/chat/chat-header.jsx +3 -8
  21. package/node_modules/@groove-dev/gui/src/components/chat/chat-input.jsx +199 -75
  22. package/node_modules/@groove-dev/gui/src/components/chat/chat-messages.jsx +21 -4
  23. package/node_modules/@groove-dev/gui/src/components/chat/chat-view.jsx +10 -13
  24. package/node_modules/@groove-dev/gui/src/components/chat/model-picker.jsx +3 -3
  25. package/node_modules/@groove-dev/gui/src/components/lab/chat-playground.jsx +42 -34
  26. package/node_modules/@groove-dev/gui/src/components/lab/lab-assistant.jsx +9 -3
  27. package/node_modules/@groove-dev/gui/src/components/lab/metrics-panel.jsx +13 -3
  28. package/node_modules/@groove-dev/gui/src/components/lab/parameter-panel.jsx +66 -65
  29. package/node_modules/@groove-dev/gui/src/components/lab/preset-manager.jsx +17 -14
  30. package/node_modules/@groove-dev/gui/src/components/lab/runtime-config.jsx +124 -127
  31. package/node_modules/@groove-dev/gui/src/components/lab/system-prompt-editor.jsx +10 -8
  32. package/node_modules/@groove-dev/gui/src/components/layout/app-shell.jsx +2 -0
  33. package/node_modules/@groove-dev/gui/src/components/layout/status-bar.jsx +24 -1
  34. package/node_modules/@groove-dev/gui/src/components/ui/question-modal.jsx +107 -0
  35. package/node_modules/@groove-dev/gui/src/components/ui/sheet.jsx +2 -2
  36. package/node_modules/@groove-dev/gui/src/components/ui/slider.jsx +8 -8
  37. package/node_modules/@groove-dev/gui/src/lib/status.js +1 -0
  38. package/node_modules/@groove-dev/gui/src/stores/groove.js +49 -2
  39. package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +18 -2
  40. package/node_modules/@groove-dev/gui/src/stores/slices/chat-slice.js +14 -14
  41. package/node_modules/@groove-dev/gui/src/views/model-lab.jsx +68 -32
  42. package/node_modules/@groove-dev/gui/src/views/models.jsx +57 -36
  43. package/node_modules/axios/CHANGELOG.md +260 -0
  44. package/node_modules/axios/README.md +595 -223
  45. package/node_modules/axios/dist/axios.js +1460 -1090
  46. package/node_modules/axios/dist/axios.js.map +1 -1
  47. package/node_modules/axios/dist/axios.min.js +3 -3
  48. package/node_modules/axios/dist/axios.min.js.map +1 -1
  49. package/node_modules/axios/dist/browser/axios.cjs +1560 -1132
  50. package/node_modules/axios/dist/browser/axios.cjs.map +1 -1
  51. package/node_modules/axios/dist/esm/axios.js +1557 -1128
  52. package/node_modules/axios/dist/esm/axios.js.map +1 -1
  53. package/node_modules/axios/dist/esm/axios.min.js +2 -2
  54. package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
  55. package/node_modules/axios/dist/node/axios.cjs +1594 -1057
  56. package/node_modules/axios/dist/node/axios.cjs.map +1 -1
  57. package/node_modules/axios/index.d.cts +40 -41
  58. package/node_modules/axios/index.d.ts +151 -227
  59. package/node_modules/axios/index.js +2 -0
  60. package/node_modules/axios/lib/adapters/adapters.js +4 -2
  61. package/node_modules/axios/lib/adapters/fetch.js +147 -16
  62. package/node_modules/axios/lib/adapters/http.js +306 -58
  63. package/node_modules/axios/lib/adapters/xhr.js +6 -2
  64. package/node_modules/axios/lib/core/Axios.js +7 -3
  65. package/node_modules/axios/lib/core/AxiosError.js +120 -34
  66. package/node_modules/axios/lib/core/AxiosHeaders.js +27 -25
  67. package/node_modules/axios/lib/core/buildFullPath.js +1 -1
  68. package/node_modules/axios/lib/core/dispatchRequest.js +19 -7
  69. package/node_modules/axios/lib/core/mergeConfig.js +21 -4
  70. package/node_modules/axios/lib/core/settle.js +7 -11
  71. package/node_modules/axios/lib/defaults/index.js +14 -9
  72. package/node_modules/axios/lib/env/data.js +1 -1
  73. package/node_modules/axios/lib/helpers/AxiosURLSearchParams.js +1 -2
  74. package/node_modules/axios/lib/helpers/buildURL.js +1 -1
  75. package/node_modules/axios/lib/helpers/cookies.js +14 -2
  76. package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +28 -1
  77. package/node_modules/axios/lib/helpers/formDataToJSON.js +3 -1
  78. package/node_modules/axios/lib/helpers/formDataToStream.js +3 -2
  79. package/node_modules/axios/lib/helpers/parseProtocol.js +1 -1
  80. package/node_modules/axios/lib/helpers/progressEventReducer.js +5 -5
  81. package/node_modules/axios/lib/helpers/resolveConfig.js +54 -18
  82. package/node_modules/axios/lib/helpers/shouldBypassProxy.js +74 -2
  83. package/node_modules/axios/lib/helpers/toFormData.js +10 -2
  84. package/node_modules/axios/lib/helpers/validator.js +3 -1
  85. package/node_modules/axios/lib/utils.js +33 -21
  86. package/node_modules/axios/package.json +17 -24
  87. package/node_modules/follow-redirects/README.md +7 -5
  88. package/node_modules/follow-redirects/index.js +24 -1
  89. package/node_modules/follow-redirects/package.json +1 -1
  90. package/package.json +1 -1
  91. package/packages/cli/package.json +1 -1
  92. package/packages/daemon/package.json +1 -1
  93. package/packages/daemon/src/api.js +12 -6
  94. package/packages/daemon/src/conversations.js +59 -58
  95. package/packages/daemon/src/introducer.js +20 -0
  96. package/packages/daemon/src/process.js +262 -15
  97. package/packages/daemon/src/providers/groove-network.js +1 -3
  98. package/packages/daemon/src/rotator.js +15 -3
  99. package/packages/daemon/src/routes/agents.js +49 -83
  100. package/packages/daemon/templates/lab-general.json +12 -0
  101. package/packages/daemon/templates/llama-cpp-setup.json +12 -0
  102. package/packages/gui/dist/assets/index-BKbsE_hn.js +1011 -0
  103. package/packages/gui/dist/assets/index-CEkPsSAm.css +1 -0
  104. package/packages/gui/dist/index.html +2 -2
  105. package/packages/gui/package.json +1 -1
  106. package/packages/gui/src/components/agents/agent-feed.jsx +80 -95
  107. package/packages/gui/src/components/agents/agent-panel.jsx +2 -70
  108. package/packages/gui/src/components/agents/spawn-wizard.jsx +132 -4
  109. package/packages/gui/src/components/chat/chat-header.jsx +3 -8
  110. package/packages/gui/src/components/chat/chat-input.jsx +199 -75
  111. package/packages/gui/src/components/chat/chat-messages.jsx +21 -4
  112. package/packages/gui/src/components/chat/chat-view.jsx +10 -13
  113. package/packages/gui/src/components/chat/model-picker.jsx +3 -3
  114. package/packages/gui/src/components/lab/chat-playground.jsx +42 -34
  115. package/packages/gui/src/components/lab/lab-assistant.jsx +9 -3
  116. package/packages/gui/src/components/lab/metrics-panel.jsx +13 -3
  117. package/packages/gui/src/components/lab/parameter-panel.jsx +66 -65
  118. package/packages/gui/src/components/lab/preset-manager.jsx +17 -14
  119. package/packages/gui/src/components/lab/runtime-config.jsx +124 -127
  120. package/packages/gui/src/components/lab/system-prompt-editor.jsx +10 -8
  121. package/packages/gui/src/components/layout/app-shell.jsx +2 -0
  122. package/packages/gui/src/components/layout/status-bar.jsx +24 -1
  123. package/packages/gui/src/components/ui/question-modal.jsx +107 -0
  124. package/packages/gui/src/components/ui/sheet.jsx +2 -2
  125. package/packages/gui/src/components/ui/slider.jsx +8 -8
  126. package/packages/gui/src/lib/status.js +1 -0
  127. package/packages/gui/src/stores/groove.js +49 -2
  128. package/packages/gui/src/stores/slices/agents-slice.js +18 -2
  129. package/packages/gui/src/stores/slices/chat-slice.js +14 -14
  130. package/packages/gui/src/views/model-lab.jsx +68 -32
  131. package/packages/gui/src/views/models.jsx +57 -36
  132. package/node_modules/@groove-dev/gui/dist/assets/index-BcoF6_eF.js +0 -1012
  133. package/node_modules/@groove-dev/gui/dist/assets/index-Dd7qhiEd.css +0 -1
  134. package/packages/gui/dist/assets/index-BcoF6_eF.js +0 -1012
  135. package/packages/gui/dist/assets/index-Dd7qhiEd.css +0 -1
@@ -12,6 +12,16 @@ export function registerAgentRoutes(app, daemon) {
12
12
  res.json(daemon.registry.getAll());
13
13
  });
14
14
 
15
+ // List all pending questions from agents awaiting user input
16
+ // (registered before :id route so Express doesn't capture "questions" as an id)
17
+ app.get('/api/agents/questions', (req, res) => {
18
+ const questions = [];
19
+ for (const [, q] of daemon.processes.pendingQuestions) {
20
+ questions.push(q);
21
+ }
22
+ res.json(questions);
23
+ });
24
+
15
25
  // Get single agent
16
26
  app.get('/api/agents/:id', (req, res) => {
17
27
  const agent = daemon.registry.get(req.params.id);
@@ -285,89 +295,12 @@ export function registerAgentRoutes(app, daemon) {
285
295
  daemon.conversations.autoTitle(req.params.id, message.trim());
286
296
  daemon.conversations.touchUpdatedAt(req.params.id);
287
297
 
288
- // API mode lightweight headless streaming, no agent spawned
289
- if (conv.mode === 'api' || !conv.agentId) {
290
- await daemon.conversations.sendMessage(req.params.id, message.trim(), history || [], {
291
- reasoningEffort: validatedEffort,
292
- verbosity: validatedVerbosity,
293
- });
294
- daemon.audit.log('conversation.message', { id: req.params.id, mode: 'api' });
295
- return res.json({ status: 'streaming', mode: 'api' });
296
- }
297
-
298
- // Agent mode — existing behavior
299
- const agent = daemon.registry.get(conv.agentId);
300
- if (!agent) return res.status(400).json({ error: 'Agent no longer exists' });
301
-
302
- // Record user feedback for journalist context
303
- if (daemon.journalist) daemon.journalist.recordUserFeedback(agent, message.trim());
304
-
305
- // Agent loop path — send message directly to the running loop
306
- if (daemon.processes.hasAgentLoop(conv.agentId)) {
307
- const sent = await daemon.processes.sendMessage(conv.agentId, message.trim());
308
- if (sent) {
309
- daemon.audit.log('conversation.message', { id: req.params.id, agentId: conv.agentId });
310
- return res.json({ id: conv.agentId, status: 'message_sent' });
311
- }
312
- }
313
-
314
- // One-shot providers: kill and respawn with the message as prompt
315
- const provider = getProvider(agent.provider);
316
- if (provider?.constructor?.isOneShot) {
317
- const oldConfig = { ...agent };
318
- if (daemon.processes.isRunning(conv.agentId)) {
319
- await daemon.processes.kill(conv.agentId);
320
- }
321
- daemon.registry.remove(conv.agentId);
322
- daemon.locks.release(conv.agentId);
323
-
324
- const newAgent = await daemon.processes.spawn({
325
- role: 'chat',
326
- scope: oldConfig.scope,
327
- provider: oldConfig.provider,
328
- model: oldConfig.model,
329
- prompt: message.trim(),
330
- permission: oldConfig.permission || 'full',
331
- workingDir: oldConfig.workingDir,
332
- name: oldConfig.name,
333
- teamId: oldConfig.teamId,
334
- });
335
-
336
- // Update conversation to point to new agent
337
- const convObj = daemon.conversations.conversations.get(req.params.id);
338
- if (convObj) {
339
- convObj.agentId = newAgent.id;
340
- daemon.conversations._save();
341
- }
342
- daemon.audit.log('conversation.message', { id: req.params.id, agentId: newAgent.id, oneShot: true });
343
- return res.json({ id: newAgent.id, status: 'respawned' });
344
- }
345
-
346
- // Running CLI agent — queue the message
347
- if (daemon.processes.isRunning(conv.agentId)) {
348
- daemon.processes.queueMessage(conv.agentId, message.trim());
349
- daemon.audit.log('conversation.message', { id: req.params.id, agentId: conv.agentId, queued: true });
350
- return res.json({ id: conv.agentId, status: 'message_queued' });
351
- }
352
-
353
- // CLI agent — session resume or rotation
354
- const SESSION_RESUME_CEILING = 5_000_000;
355
- const resumed = !!agent.sessionId && (agent.tokensUsed || 0) < SESSION_RESUME_CEILING;
356
- const newAgent = resumed
357
- ? await daemon.processes.resume(conv.agentId, message.trim())
358
- : await daemon.rotator.rotate(conv.agentId, { additionalPrompt: message.trim() });
359
-
360
- // Update conversation to point to new agent if rotated
361
- if (newAgent.id !== conv.agentId) {
362
- const convObj = daemon.conversations.conversations.get(req.params.id);
363
- if (convObj) {
364
- convObj.agentId = newAgent.id;
365
- daemon.conversations._save();
366
- }
367
- }
368
-
369
- daemon.audit.log('conversation.message', { id: req.params.id, agentId: newAgent.id, resumed });
370
- res.json({ id: newAgent.id, status: resumed ? 'resumed' : 'rotated' });
298
+ await daemon.conversations.sendMessage(req.params.id, message.trim(), history || [], {
299
+ reasoningEffort: validatedEffort,
300
+ verbosity: validatedVerbosity,
301
+ });
302
+ daemon.audit.log('conversation.message', { id: req.params.id, mode: conv.mode || 'api' });
303
+ res.json({ status: 'streaming', mode: conv.mode || 'api' });
371
304
  } catch (err) {
372
305
  res.status(400).json({ error: err.message });
373
306
  }
@@ -583,6 +516,39 @@ export function registerAgentRoutes(app, daemon) {
583
516
  }
584
517
  });
585
518
 
519
+ // Answer a pending question from an agent
520
+ app.post('/api/agents/:id/answer', async (req, res) => {
521
+ try {
522
+ const { answers } = req.body;
523
+ if (!answers || typeof answers !== 'object') {
524
+ return res.status(400).json({ error: 'answers object is required' });
525
+ }
526
+
527
+ const agent = daemon.registry.get(req.params.id);
528
+ if (!agent) return res.status(404).json({ error: 'Agent not found' });
529
+
530
+ const pending = daemon.processes.pendingQuestions.get(req.params.id);
531
+ if (!pending) return res.status(404).json({ error: 'No pending question for this agent' });
532
+
533
+ daemon.processes.pendingQuestions.delete(req.params.id);
534
+ daemon.registry.update(req.params.id, { pendingQuestion: false });
535
+ daemon.broadcast({ type: 'agent:question:resolved', agentId: req.params.id });
536
+
537
+ // Format the answers as a natural language message for session resume
538
+ const parts = Object.entries(answers).map(([q, a]) => `Q: ${q}\nA: ${a}`);
539
+ const resumeMessage = `The user answered your questions:\n\n${parts.join('\n\n')}\n\nContinue with your task based on these answers.`;
540
+
541
+ const newAgent = agent.sessionId
542
+ ? await daemon.processes.resume(req.params.id, resumeMessage)
543
+ : await daemon.rotator.rotate(req.params.id, { additionalPrompt: resumeMessage });
544
+
545
+ daemon.audit.log('agent.answer', { id: req.params.id, newId: newAgent.id });
546
+ res.json(newAgent);
547
+ } catch (err) {
548
+ res.status(400).json({ error: err.message });
549
+ }
550
+ });
551
+
586
552
  // Query an agent (headless one-shot, agent keeps running)
587
553
  // For agent loop agents: sends message directly to the loop
588
554
  app.post('/api/agents/:id/query', async (req, res) => {
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "lab-general",
3
+ "description": "General-purpose Lab Assistant for runtime management, model configuration, and optimization",
4
+ "agents": [
5
+ {
6
+ "role": "lab-assistant",
7
+ "scope": [],
8
+ "provider": "claude-code",
9
+ "prompt": "You are a GROOVE Lab Assistant — a general-purpose helper for local AI model inference. You help with runtime setup, model configuration, optimization, and troubleshooting.\n\nYou can help with:\n- Setting up inference runtimes (MLX, llama.cpp, vLLM, TGI, Ollama)\n- Model selection and downloading\n- Context window configuration and memory optimization\n- Prompt engineering and system prompt design\n- Performance tuning (quantization, batch size, GPU layers)\n- Troubleshooting server issues\n- Comparing model performance\n\n## System Info\n\nStart by understanding the user's environment if needed:\n```bash\nuname -m && sysctl -n machdep.cpu.brand_string 2>/dev/null; sysctl -n hw.memsize 2>/dev/null | awk '{print $0/1073741824 \" GB\"}'; python3 --version 2>/dev/null\n```\n\n## Runtime Management\n\nCheck existing runtimes:\n```bash\nDAEMON_PORT=$(cat ~/.groove/daemon.port 2>/dev/null || echo 31415)\ncurl -s http://localhost:$DAEMON_PORT/api/lab/runtimes | python3 -m json.tool 2>/dev/null || curl -s http://localhost:$DAEMON_PORT/api/lab/runtimes\n```\n\n## Registering Runtimes\n\nWhen setting up a new runtime, always register it with GROOVE so it can be managed from the UI:\n```bash\nDAEMON_PORT=$(cat ~/.groove/daemon.port 2>/dev/null || echo 31415)\ncurl -s -X POST http://localhost:$DAEMON_PORT/api/lab/runtimes \\\n -H 'Content-Type: application/json' \\\n -d '{\"name\":\"<NAME>\",\"type\":\"<TYPE>\",\"endpoint\":\"http://localhost:<PORT>\",\"launchConfig\":{\"command\":\"<CMD>\",\"args\":[...],\"port\":<PORT>}}'\n```\n\nBe conversational, explain your reasoning, and adapt to what the user needs. If they ask about model configs, context windows, or prompts — help with that directly without trying to set up a new runtime."
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "llama-cpp-setup",
3
+ "description": "Lab Assistant for llama.cpp installation and configuration",
4
+ "agents": [
5
+ {
6
+ "role": "lab-assistant",
7
+ "scope": [],
8
+ "provider": "claude-code",
9
+ "prompt": "You are a GROOVE Lab Assistant. Your job is to help the user set up a llama.cpp inference server. Be conversational, report progress clearly, and explain each step.\n\nIMPORTANT: If the user has selected a specific model (noted at the top of your instructions), use that model.\n\n## Step 1 — System Recon\n\nRun these commands and report what you find:\n- `uname -sm` — OS and architecture\n- `sysctl -n hw.memsize 2>/dev/null | awk '{print $0/1073741824 \" GB\"}'` — RAM (macOS)\n- `llama-server --version 2>/dev/null || llama-cli --version 2>/dev/null || echo 'NOT INSTALLED'`\n- `df -h /` — disk space\n\nSummarize: system info, whether llama.cpp is installed, available memory.\n\n## Step 2 — Install llama.cpp\n\nIf not installed:\n- macOS: `brew install llama.cpp`\n- Linux: build from source or use pre-built binaries from GitHub releases\n\nVerify: `llama-server --version`\n\n## Step 3 — Model Selection\n\nIf a model was pre-selected, use it. Otherwise, recommend based on available RAM:\n- 8 GB — 1-3B Q8 or 7B Q4\n- 16 GB — 7-8B Q8 or 14B Q4\n- 32 GB — 14B Q8 or 32B Q4\n- 64 GB+ — 70B Q4\n\nCheck if the model GGUF file exists in `~/.groove/models/`:\n```bash\nls ~/.groove/models/*.gguf 2>/dev/null\n```\n\n## Step 4 — Launch Server\n\nCheck if port 8080 is available:\n```bash\nlsof -i :8080 -sTCP:LISTEN 2>/dev/null\n```\n\nLaunch:\n```bash\nnohup llama-server -m <MODEL_PATH> --port <PORT> --ctx-size 4096 -ngl 99 > /tmp/llama-server.log 2>&1 &\n```\n\nWait for server to be ready:\n```bash\nuntil curl -s http://localhost:<PORT>/v1/models > /dev/null 2>&1; do sleep 1; done && echo 'Server ready'\n```\n\n## Step 5 — Validation\n\nTest:\n```bash\ncurl -s http://localhost:<PORT>/v1/chat/completions -H 'Content-Type: application/json' -d '{\"model\":\"default\",\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}],\"max_tokens\":20}'\n```\n\n## Step 6 — Runtime Registration (MANDATORY)\n\n```bash\nDAEMON_PORT=$(cat ~/.groove/daemon.port 2>/dev/null || echo 31415)\ncurl -s -X POST http://localhost:$DAEMON_PORT/api/lab/runtimes \\\n -H 'Content-Type: application/json' \\\n -d '{\"name\":\"llama.cpp - <MODEL_SHORT>\",\"type\":\"llama-cpp\",\"endpoint\":\"http://localhost:<PORT>\",\"launchConfig\":{\"command\":\"llama-server\",\"args\":[\"-m\",\"<MODEL_PATH>\",\"--port\",\"<PORT>\",\"--ctx-size\",\"4096\",\"-ngl\",\"99\"],\"port\":<PORT>}}'\n```\n\n## Step 7 — Completion\n\nSummarize: Model, Server URL, Runtime ID, Port, GPU layers.\n\n## Error Handling\n\n- **Metal/CUDA not available**: Remove `-ngl 99` for CPU-only mode.\n- **Model too large**: Suggest smaller quantization or model.\n- **Port in use**: Try next available port."
10
+ }
11
+ ]
12
+ }