groove-dev 0.27.143 → 0.27.145

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 (251) hide show
  1. package/CLAUDE.md +0 -7
  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 +1086 -6532
  5. package/node_modules/@groove-dev/daemon/src/conversations.js +18 -48
  6. package/node_modules/@groove-dev/daemon/src/gateways/manager.js +35 -1
  7. package/node_modules/@groove-dev/daemon/src/index.js +3 -0
  8. package/node_modules/@groove-dev/daemon/src/journalist.js +23 -13
  9. package/node_modules/@groove-dev/daemon/src/mlx-server.js +365 -0
  10. package/node_modules/@groove-dev/daemon/src/model-lab.js +308 -12
  11. package/node_modules/@groove-dev/daemon/src/pm.js +1 -1
  12. package/node_modules/@groove-dev/daemon/src/process.js +2 -2
  13. package/node_modules/@groove-dev/daemon/src/providers/local.js +36 -8
  14. package/node_modules/@groove-dev/daemon/src/registry.js +21 -5
  15. package/node_modules/@groove-dev/daemon/src/routes/agents.js +812 -0
  16. package/node_modules/@groove-dev/daemon/src/routes/coordination.js +318 -0
  17. package/node_modules/@groove-dev/daemon/src/routes/files.js +751 -0
  18. package/node_modules/@groove-dev/daemon/src/routes/integrations.js +485 -0
  19. package/node_modules/@groove-dev/daemon/src/routes/network.js +1784 -0
  20. package/node_modules/@groove-dev/daemon/src/routes/providers.js +755 -0
  21. package/node_modules/@groove-dev/daemon/src/routes/schedules.js +110 -0
  22. package/node_modules/@groove-dev/daemon/src/routes/teams.js +650 -0
  23. package/node_modules/@groove-dev/daemon/src/scheduler.js +456 -24
  24. package/node_modules/@groove-dev/daemon/src/teams.js +1 -1
  25. package/node_modules/@groove-dev/daemon/src/validate.js +38 -1
  26. package/node_modules/@groove-dev/daemon/templates/mlx-setup.json +12 -0
  27. package/node_modules/@groove-dev/daemon/templates/tgi-setup.json +1 -1
  28. package/node_modules/@groove-dev/daemon/templates/vllm-setup.json +1 -1
  29. package/node_modules/@groove-dev/daemon/test/introducer.test.js +3 -3
  30. package/node_modules/@groove-dev/daemon/test/journalist.test.js +7 -10
  31. package/node_modules/@groove-dev/daemon/test/registry.test.js +38 -0
  32. package/node_modules/@groove-dev/gui/dist/assets/index-Bxc0gU06.js +1006 -0
  33. package/node_modules/@groove-dev/gui/dist/assets/index-C0pztKBn.css +1 -0
  34. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  35. package/node_modules/@groove-dev/gui/package.json +1 -1
  36. package/node_modules/@groove-dev/gui/src/{app.jsx → App.jsx} +0 -2
  37. package/node_modules/@groove-dev/gui/src/app.css +35 -0
  38. package/node_modules/@groove-dev/gui/src/components/agents/agent-config.jsx +1 -128
  39. package/node_modules/@groove-dev/gui/src/components/agents/agent-feed.jsx +210 -112
  40. package/node_modules/@groove-dev/gui/src/components/agents/agent-node.jsx +8 -13
  41. package/node_modules/@groove-dev/gui/src/components/agents/agent-panel.jsx +2 -70
  42. package/node_modules/@groove-dev/gui/src/components/agents/code-review.jsx +159 -122
  43. package/node_modules/@groove-dev/gui/src/components/agents/diff-viewer.jsx +23 -23
  44. package/node_modules/@groove-dev/gui/src/components/agents/journalist-panel.jsx +1 -1
  45. package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +2 -135
  46. package/node_modules/@groove-dev/gui/src/components/automations/automation-card.jsx +274 -0
  47. package/node_modules/@groove-dev/gui/src/components/automations/automation-wizard.jsx +1136 -0
  48. package/node_modules/@groove-dev/gui/src/components/chat/chat-header.jsx +2 -0
  49. package/node_modules/@groove-dev/gui/src/components/chat/chat-input.jsx +68 -66
  50. package/node_modules/@groove-dev/gui/src/components/chat/chat-view.jsx +4 -8
  51. package/node_modules/@groove-dev/gui/src/components/dashboard/activity-feed.jsx +3 -3
  52. package/node_modules/@groove-dev/gui/src/components/dashboard/cache-ring.jsx +5 -5
  53. package/node_modules/@groove-dev/gui/src/components/dashboard/context-gauges.jsx +6 -8
  54. package/node_modules/@groove-dev/gui/src/components/dashboard/fleet-panel.jsx +8 -14
  55. package/node_modules/@groove-dev/gui/src/components/dashboard/intel-panel.jsx +238 -656
  56. package/node_modules/@groove-dev/gui/src/components/dashboard/kpi-card.jsx +3 -3
  57. package/node_modules/@groove-dev/gui/src/components/dashboard/routing-chart.jsx +3 -3
  58. package/node_modules/@groove-dev/gui/src/components/dashboard/team-burn-panel.jsx +1 -1
  59. package/node_modules/@groove-dev/gui/src/components/dashboard/token-chart.jsx +4 -4
  60. package/node_modules/@groove-dev/gui/src/components/lab/chat-playground.jsx +39 -31
  61. package/node_modules/@groove-dev/gui/src/components/lab/lab-assistant.jsx +316 -82
  62. package/node_modules/@groove-dev/gui/src/components/lab/metrics-panel.jsx +187 -32
  63. package/node_modules/@groove-dev/gui/src/components/lab/parameter-panel.jsx +200 -18
  64. package/node_modules/@groove-dev/gui/src/components/lab/preset-manager.jsx +17 -14
  65. package/node_modules/@groove-dev/gui/src/components/lab/runtime-config.jsx +335 -152
  66. package/node_modules/@groove-dev/gui/src/components/lab/system-prompt-editor.jsx +10 -8
  67. package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +2 -4
  68. package/node_modules/@groove-dev/gui/src/components/layout/terminal-panel.jsx +4 -2
  69. package/node_modules/@groove-dev/gui/src/components/layout/welcome-splash.jsx +137 -108
  70. package/node_modules/@groove-dev/gui/src/components/network/network-health.jsx +2 -2
  71. package/node_modules/@groove-dev/gui/src/components/network/performance-dashboard.jsx +4 -4
  72. package/node_modules/@groove-dev/gui/src/components/settings/ssh-wizard.jsx +81 -99
  73. package/node_modules/@groove-dev/gui/src/components/ui/sheet.jsx +5 -2
  74. package/node_modules/@groove-dev/gui/src/components/ui/slider.jsx +8 -8
  75. package/node_modules/@groove-dev/gui/src/lib/cron.js +64 -0
  76. package/node_modules/@groove-dev/gui/src/lib/status.js +25 -24
  77. package/node_modules/@groove-dev/gui/src/lib/theme-hex.js +1 -0
  78. package/node_modules/@groove-dev/gui/src/stores/groove.js +51 -3144
  79. package/node_modules/@groove-dev/gui/src/stores/helpers.js +10 -0
  80. package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +459 -0
  81. package/node_modules/@groove-dev/gui/src/stores/slices/automations-slice.js +96 -0
  82. package/node_modules/@groove-dev/gui/src/stores/slices/chat-slice.js +226 -0
  83. package/node_modules/@groove-dev/gui/src/stores/slices/editor-slice.js +285 -0
  84. package/node_modules/@groove-dev/gui/src/stores/slices/marketplace-slice.js +461 -0
  85. package/node_modules/@groove-dev/gui/src/stores/slices/network-slice.js +361 -0
  86. package/node_modules/@groove-dev/gui/src/stores/slices/preview-slice.js +109 -0
  87. package/node_modules/@groove-dev/gui/src/stores/slices/providers-slice.js +897 -0
  88. package/node_modules/@groove-dev/gui/src/stores/slices/teams-slice.js +413 -0
  89. package/node_modules/@groove-dev/gui/src/stores/slices/ui-slice.js +98 -0
  90. package/node_modules/@groove-dev/gui/src/views/agents.jsx +5 -5
  91. package/node_modules/@groove-dev/gui/src/views/dashboard.jsx +12 -13
  92. package/node_modules/@groove-dev/gui/src/views/marketplace.jsx +191 -3
  93. package/node_modules/@groove-dev/gui/src/views/model-lab.jsx +54 -12
  94. package/node_modules/@groove-dev/gui/src/views/models.jsx +419 -496
  95. package/node_modules/@groove-dev/gui/src/views/network.jsx +3 -3
  96. package/node_modules/@groove-dev/gui/src/views/settings.jsx +81 -94
  97. package/node_modules/@groove-dev/gui/src/views/teams.jsx +40 -483
  98. package/node_modules/axios/CHANGELOG.md +260 -0
  99. package/node_modules/axios/README.md +595 -223
  100. package/node_modules/axios/dist/axios.js +1460 -1090
  101. package/node_modules/axios/dist/axios.js.map +1 -1
  102. package/node_modules/axios/dist/axios.min.js +3 -3
  103. package/node_modules/axios/dist/axios.min.js.map +1 -1
  104. package/node_modules/axios/dist/browser/axios.cjs +1560 -1132
  105. package/node_modules/axios/dist/browser/axios.cjs.map +1 -1
  106. package/node_modules/axios/dist/esm/axios.js +1557 -1128
  107. package/node_modules/axios/dist/esm/axios.js.map +1 -1
  108. package/node_modules/axios/dist/esm/axios.min.js +2 -2
  109. package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
  110. package/node_modules/axios/dist/node/axios.cjs +1594 -1057
  111. package/node_modules/axios/dist/node/axios.cjs.map +1 -1
  112. package/node_modules/axios/index.d.cts +40 -41
  113. package/node_modules/axios/index.d.ts +151 -227
  114. package/node_modules/axios/index.js +2 -0
  115. package/node_modules/axios/lib/adapters/adapters.js +4 -2
  116. package/node_modules/axios/lib/adapters/fetch.js +147 -16
  117. package/node_modules/axios/lib/adapters/http.js +306 -58
  118. package/node_modules/axios/lib/adapters/xhr.js +6 -2
  119. package/node_modules/axios/lib/core/Axios.js +7 -3
  120. package/node_modules/axios/lib/core/AxiosError.js +120 -34
  121. package/node_modules/axios/lib/core/AxiosHeaders.js +27 -25
  122. package/node_modules/axios/lib/core/buildFullPath.js +1 -1
  123. package/node_modules/axios/lib/core/dispatchRequest.js +19 -7
  124. package/node_modules/axios/lib/core/mergeConfig.js +21 -4
  125. package/node_modules/axios/lib/core/settle.js +7 -11
  126. package/node_modules/axios/lib/defaults/index.js +14 -9
  127. package/node_modules/axios/lib/env/data.js +1 -1
  128. package/node_modules/axios/lib/helpers/AxiosURLSearchParams.js +1 -2
  129. package/node_modules/axios/lib/helpers/buildURL.js +1 -1
  130. package/node_modules/axios/lib/helpers/cookies.js +14 -2
  131. package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +28 -1
  132. package/node_modules/axios/lib/helpers/formDataToJSON.js +3 -1
  133. package/node_modules/axios/lib/helpers/formDataToStream.js +3 -2
  134. package/node_modules/axios/lib/helpers/parseProtocol.js +1 -1
  135. package/node_modules/axios/lib/helpers/progressEventReducer.js +5 -5
  136. package/node_modules/axios/lib/helpers/resolveConfig.js +54 -18
  137. package/node_modules/axios/lib/helpers/shouldBypassProxy.js +74 -2
  138. package/node_modules/axios/lib/helpers/toFormData.js +10 -2
  139. package/node_modules/axios/lib/helpers/validator.js +3 -1
  140. package/node_modules/axios/lib/utils.js +33 -21
  141. package/node_modules/axios/package.json +17 -24
  142. package/node_modules/follow-redirects/README.md +7 -5
  143. package/node_modules/follow-redirects/index.js +24 -1
  144. package/node_modules/follow-redirects/package.json +1 -1
  145. package/package.json +1 -1
  146. package/packages/cli/package.json +1 -1
  147. package/packages/daemon/package.json +1 -1
  148. package/packages/daemon/src/api.js +1086 -6532
  149. package/packages/daemon/src/conversations.js +18 -48
  150. package/packages/daemon/src/gateways/manager.js +35 -1
  151. package/packages/daemon/src/index.js +3 -0
  152. package/packages/daemon/src/journalist.js +23 -13
  153. package/packages/daemon/src/mlx-server.js +365 -0
  154. package/packages/daemon/src/model-lab.js +308 -12
  155. package/packages/daemon/src/pm.js +1 -1
  156. package/packages/daemon/src/process.js +2 -2
  157. package/packages/daemon/src/providers/local.js +36 -8
  158. package/packages/daemon/src/registry.js +21 -5
  159. package/packages/daemon/src/routes/agents.js +812 -0
  160. package/packages/daemon/src/routes/coordination.js +318 -0
  161. package/packages/daemon/src/routes/files.js +751 -0
  162. package/packages/daemon/src/routes/integrations.js +485 -0
  163. package/packages/daemon/src/routes/network.js +1784 -0
  164. package/packages/daemon/src/routes/providers.js +755 -0
  165. package/packages/daemon/src/routes/schedules.js +110 -0
  166. package/packages/daemon/src/routes/teams.js +650 -0
  167. package/packages/daemon/src/scheduler.js +456 -24
  168. package/packages/daemon/src/teams.js +1 -1
  169. package/packages/daemon/src/validate.js +38 -1
  170. package/packages/daemon/templates/mlx-setup.json +12 -0
  171. package/packages/daemon/templates/tgi-setup.json +1 -1
  172. package/packages/daemon/templates/vllm-setup.json +1 -1
  173. package/packages/gui/dist/assets/index-Bxc0gU06.js +1006 -0
  174. package/packages/gui/dist/assets/index-C0pztKBn.css +1 -0
  175. package/packages/gui/dist/index.html +2 -2
  176. package/packages/gui/package.json +1 -1
  177. package/packages/gui/src/{app.jsx → App.jsx} +0 -2
  178. package/packages/gui/src/app.css +35 -0
  179. package/packages/gui/src/components/agents/agent-config.jsx +1 -128
  180. package/packages/gui/src/components/agents/agent-feed.jsx +210 -112
  181. package/packages/gui/src/components/agents/agent-node.jsx +8 -13
  182. package/packages/gui/src/components/agents/agent-panel.jsx +2 -70
  183. package/packages/gui/src/components/agents/code-review.jsx +159 -122
  184. package/packages/gui/src/components/agents/diff-viewer.jsx +23 -23
  185. package/packages/gui/src/components/agents/journalist-panel.jsx +1 -1
  186. package/packages/gui/src/components/agents/spawn-wizard.jsx +2 -135
  187. package/packages/gui/src/components/automations/automation-card.jsx +274 -0
  188. package/packages/gui/src/components/automations/automation-wizard.jsx +1136 -0
  189. package/packages/gui/src/components/chat/chat-header.jsx +2 -0
  190. package/packages/gui/src/components/chat/chat-input.jsx +68 -66
  191. package/packages/gui/src/components/chat/chat-view.jsx +4 -8
  192. package/packages/gui/src/components/dashboard/activity-feed.jsx +3 -3
  193. package/packages/gui/src/components/dashboard/cache-ring.jsx +5 -5
  194. package/packages/gui/src/components/dashboard/context-gauges.jsx +6 -8
  195. package/packages/gui/src/components/dashboard/fleet-panel.jsx +8 -14
  196. package/packages/gui/src/components/dashboard/intel-panel.jsx +238 -656
  197. package/packages/gui/src/components/dashboard/kpi-card.jsx +3 -3
  198. package/packages/gui/src/components/dashboard/routing-chart.jsx +3 -3
  199. package/packages/gui/src/components/dashboard/team-burn-panel.jsx +1 -1
  200. package/packages/gui/src/components/dashboard/token-chart.jsx +4 -4
  201. package/packages/gui/src/components/lab/chat-playground.jsx +39 -31
  202. package/packages/gui/src/components/lab/lab-assistant.jsx +316 -82
  203. package/packages/gui/src/components/lab/metrics-panel.jsx +187 -32
  204. package/packages/gui/src/components/lab/parameter-panel.jsx +200 -18
  205. package/packages/gui/src/components/lab/preset-manager.jsx +17 -14
  206. package/packages/gui/src/components/lab/runtime-config.jsx +335 -152
  207. package/packages/gui/src/components/lab/system-prompt-editor.jsx +10 -8
  208. package/packages/gui/src/components/layout/activity-bar.jsx +2 -4
  209. package/packages/gui/src/components/layout/terminal-panel.jsx +4 -2
  210. package/packages/gui/src/components/layout/welcome-splash.jsx +137 -108
  211. package/packages/gui/src/components/network/network-health.jsx +2 -2
  212. package/packages/gui/src/components/network/performance-dashboard.jsx +4 -4
  213. package/packages/gui/src/components/settings/ssh-wizard.jsx +81 -99
  214. package/packages/gui/src/components/ui/sheet.jsx +5 -2
  215. package/packages/gui/src/components/ui/slider.jsx +8 -8
  216. package/packages/gui/src/lib/cron.js +64 -0
  217. package/packages/gui/src/lib/status.js +25 -24
  218. package/packages/gui/src/lib/theme-hex.js +1 -0
  219. package/packages/gui/src/stores/groove.js +51 -3144
  220. package/packages/gui/src/stores/helpers.js +10 -0
  221. package/packages/gui/src/stores/slices/agents-slice.js +459 -0
  222. package/packages/gui/src/stores/slices/automations-slice.js +96 -0
  223. package/packages/gui/src/stores/slices/chat-slice.js +226 -0
  224. package/packages/gui/src/stores/slices/editor-slice.js +285 -0
  225. package/packages/gui/src/stores/slices/marketplace-slice.js +461 -0
  226. package/packages/gui/src/stores/slices/network-slice.js +361 -0
  227. package/packages/gui/src/stores/slices/preview-slice.js +109 -0
  228. package/packages/gui/src/stores/slices/providers-slice.js +897 -0
  229. package/packages/gui/src/stores/slices/teams-slice.js +413 -0
  230. package/packages/gui/src/stores/slices/ui-slice.js +98 -0
  231. package/packages/gui/src/views/agents.jsx +5 -5
  232. package/packages/gui/src/views/dashboard.jsx +12 -13
  233. package/packages/gui/src/views/marketplace.jsx +191 -3
  234. package/packages/gui/src/views/model-lab.jsx +54 -12
  235. package/packages/gui/src/views/models.jsx +419 -496
  236. package/packages/gui/src/views/network.jsx +3 -3
  237. package/packages/gui/src/views/settings.jsx +81 -94
  238. package/packages/gui/src/views/teams.jsx +40 -483
  239. package/SECURITY_SWEEP.md +0 -228
  240. package/TRAINING_DATA_v4.md +0 -6
  241. package/node_modules/@groove-dev/gui/dist/assets/index-CCVvAoQn.css +0 -1
  242. package/node_modules/@groove-dev/gui/dist/assets/index-DGIv_TRm.js +0 -984
  243. package/node_modules/@groove-dev/gui/src/components/agents/agent-chat.jsx +0 -379
  244. package/node_modules/@groove-dev/gui/src/views/preview.jsx +0 -6
  245. package/node_modules/@groove-dev/gui/src/views/subscription-panel.jsx +0 -327
  246. package/packages/gui/dist/assets/index-CCVvAoQn.css +0 -1
  247. package/packages/gui/dist/assets/index-DGIv_TRm.js +0 -984
  248. package/packages/gui/src/components/agents/agent-chat.jsx +0 -379
  249. package/packages/gui/src/views/preview.jsx +0 -6
  250. package/packages/gui/src/views/subscription-panel.jsx +0 -327
  251. package/test.py +0 -571
@@ -8,6 +8,8 @@ import { cn } from '../../lib/cn';
8
8
  import { roleColor } from '../../lib/status';
9
9
 
10
10
  const CHAT_ROLES = [
11
+ { id: 'chat', label: 'Chat', desc: 'General conversation' },
12
+ { id: 'research', label: 'Research Assistant', desc: 'Explore ideas, web search' },
11
13
  { id: 'fullstack', label: 'Fullstack', desc: 'End-to-end engineering' },
12
14
  { id: 'backend', label: 'Backend', desc: 'APIs, services, databases' },
13
15
  { id: 'frontend', label: 'Frontend', desc: 'UI, components, styling' },
@@ -1,6 +1,6 @@
1
1
  // FSL-1.1-Apache-2.0 — see LICENSE
2
2
  import { useState, useRef, useEffect, useCallback } from 'react';
3
- import { Send, Loader2, Square, Paperclip, Image as ImageIcon, Zap, Bot, GripHorizontal } from 'lucide-react';
3
+ import { SendHorizontal, Loader2, Square, Paperclip, Image as ImageIcon, Zap, Bot, GripHorizontal } from 'lucide-react';
4
4
  import { cn } from '../../lib/cn';
5
5
  import { formatModelName } from './model-picker';
6
6
 
@@ -19,7 +19,7 @@ const VERBOSITY_OPTIONS = [
19
19
 
20
20
  export function ChatInput({ onSend, onStop, sending, streaming, disabled, isImageModel, currentModel, replyContext, onClearReply, role, isCodex, reasoningEffort, onReasoningEffortChange, verbosity, onVerbosityChange, mode, onModeChange, modeChanging }) {
21
21
  const [input, setInput] = useState('');
22
- const [inputHeight, setInputHeight] = useState(40);
22
+ const [inputHeight, setInputHeight] = useState(88);
23
23
  const textareaRef = useRef(null);
24
24
  const fileInputRef = useRef(null);
25
25
 
@@ -32,7 +32,6 @@ export function ChatInput({ onSend, onStop, sending, streaming, disabled, isImag
32
32
  if (!text || sending || disabled) return;
33
33
  onSend(text);
34
34
  setInput('');
35
- setInputHeight(40);
36
35
  }
37
36
 
38
37
  function onKeyDown(e) {
@@ -54,7 +53,7 @@ export function ChatInput({ onSend, onStop, sending, streaming, disabled, isImag
54
53
  e.preventDefault();
55
54
  const startY = e.clientY;
56
55
  const startH = inputHeight;
57
- const onMove = (ev) => setInputHeight(Math.min(Math.max(40, startH - (ev.clientY - startY)), 400));
56
+ const onMove = (ev) => setInputHeight(Math.min(Math.max(56, startH - (ev.clientY - startY)), 400));
58
57
  const onUp = () => {
59
58
  window.removeEventListener('mousemove', onMove);
60
59
  window.removeEventListener('mouseup', onUp);
@@ -76,95 +75,97 @@ export function ChatInput({ onSend, onStop, sending, streaming, disabled, isImag
76
75
  : 'Send a message...';
77
76
 
78
77
  return (
79
- <div className="border-t border-border-subtle bg-surface-1">
78
+ <div className="px-4 pb-3">
80
79
  <div
81
80
  onMouseDown={onDragStart}
82
- className="flex items-center justify-center h-3 cursor-row-resize hover:bg-surface-3/50 transition-colors group"
81
+ className="flex items-center justify-center h-5 cursor-row-resize group"
83
82
  >
84
- <GripHorizontal size={10} className="text-text-4 group-hover:text-text-2 transition-colors" />
83
+ <GripHorizontal size={12} className="text-text-4 group-hover:text-text-2 transition-colors" />
85
84
  </div>
86
85
 
87
- <div className="px-4 pb-3">
88
- {replyContext && (
89
- <div className="flex items-center gap-2 mb-2 px-3 py-2 rounded-lg bg-accent/5 border border-accent/15">
90
- <ImageIcon size={12} className="text-accent flex-shrink-0" />
91
- <span className="flex-1 text-2xs text-text-2 font-sans truncate">Iterating: &quot;{replyContext.prompt}&quot;</span>
92
- <button onClick={onClearReply} className="text-text-4 hover:text-text-1 cursor-pointer flex-shrink-0">
93
- <Square size={10} />
94
- </button>
95
- </div>
96
- )}
97
-
98
- <textarea
99
- ref={textareaRef}
100
- value={input}
101
- onChange={(e) => setInput(e.target.value)}
102
- onKeyDown={onKeyDown}
103
- placeholder={placeholder}
104
- disabled={disabled}
105
- rows={1}
106
- style={{ height: inputHeight }}
107
- className={cn(
108
- 'w-full resize-none rounded-xl px-4 py-2.5 text-sm',
109
- 'bg-surface-0 border text-text-0 font-sans',
110
- 'placeholder:text-text-4',
111
- 'focus:outline-none focus:ring-1',
112
- 'border-border focus:ring-accent/40',
113
- 'disabled:opacity-50 disabled:cursor-not-allowed',
114
- )}
86
+ {replyContext && (
87
+ <div className="flex items-center gap-2 mb-2 px-3 py-2 rounded-lg bg-accent/5 border border-accent/15">
88
+ <ImageIcon size={12} className="text-accent flex-shrink-0" />
89
+ <span className="flex-1 text-2xs text-text-2 font-sans truncate">Iterating: &quot;{replyContext.prompt}&quot;</span>
90
+ <button onClick={onClearReply} className="text-text-4 hover:text-text-1 cursor-pointer flex-shrink-0">
91
+ <Square size={10} />
92
+ </button>
93
+ </div>
94
+ )}
95
+
96
+ <div className="flex flex-col rounded-lg border border-border-subtle bg-surface-0 transition-colors overflow-hidden focus-within:border-text-4/40">
97
+ <input
98
+ ref={fileInputRef}
99
+ type="file"
100
+ multiple
101
+ accept=".pdf,.png,.jpg,.jpeg,.gif,.svg,.csv,.txt,.md,.json,.yaml,.yml,.docx,.pptx,.xlsx"
102
+ onChange={handleFileSelect}
103
+ className="hidden"
115
104
  />
116
105
 
117
- <div className="flex items-center gap-2 mt-2">
118
- <input
119
- ref={fileInputRef}
120
- type="file"
121
- multiple
122
- accept=".pdf,.png,.jpg,.jpeg,.gif,.svg,.csv,.txt,.md,.json,.yaml,.yml,.docx,.pptx,.xlsx"
123
- onChange={handleFileSelect}
124
- className="hidden"
106
+ <div className="px-1">
107
+ <textarea
108
+ ref={textareaRef}
109
+ value={input}
110
+ onChange={(e) => setInput(e.target.value)}
111
+ onKeyDown={onKeyDown}
112
+ placeholder={placeholder}
113
+ disabled={disabled}
114
+ rows={1}
115
+ className={cn(
116
+ 'w-full resize-none px-3 py-2.5 text-[13px]',
117
+ 'bg-transparent font-sans text-text-0',
118
+ 'placeholder:text-text-4',
119
+ 'focus:outline-none',
120
+ 'disabled:opacity-40 disabled:cursor-not-allowed',
121
+ )}
122
+ style={{ height: inputHeight }}
125
123
  />
124
+ </div>
125
+
126
+ <div className="flex items-center gap-1.5 px-1.5 pb-1.5 pt-0.5">
126
127
  <button
127
128
  onClick={() => fileInputRef.current?.click()}
128
129
  disabled={disabled}
129
- className="w-8 h-8 flex items-center justify-center rounded-lg text-text-4 hover:text-text-1 hover:bg-surface-3 transition-colors cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed flex-shrink-0"
130
+ className="w-7 h-7 flex items-center justify-center rounded-md text-text-4 hover:text-text-1 transition-colors cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed"
130
131
  title="Attach file"
131
132
  >
132
133
  <Paperclip size={14} />
133
134
  </button>
134
135
 
135
- <div className="flex items-center h-7 rounded-lg bg-surface-3 border border-border-subtle p-0.5">
136
+ <div className="flex items-center h-6 rounded-md bg-surface-3 border border-border-subtle p-0.5">
136
137
  <button
137
138
  onClick={() => onModeChange?.('api')}
138
139
  disabled={modeChanging}
139
140
  className={cn(
140
- 'flex items-center gap-1 h-6 px-2 rounded-md text-2xs font-semibold font-sans transition-colors cursor-pointer',
141
+ 'flex items-center gap-1 h-5 px-2 rounded text-2xs font-semibold font-sans transition-colors cursor-pointer',
141
142
  'disabled:opacity-50 disabled:cursor-not-allowed',
142
- currentMode === 'api' ? 'bg-accent/15 text-accent border border-accent/25' : 'text-text-3 hover:text-text-1',
143
+ currentMode === 'api' ? 'bg-accent/15 text-accent' : 'text-text-3 hover:text-text-1',
143
144
  )}
144
145
  title="Lightweight — fast and cheap, no tools"
145
146
  >
146
- <Zap size={11} /> Chat
147
+ <Zap size={10} /> Chat
147
148
  </button>
148
149
  <button
149
150
  onClick={() => onModeChange?.('agent')}
150
151
  disabled={modeChanging}
151
152
  className={cn(
152
- 'flex items-center gap-1 h-6 px-2 rounded-md text-2xs font-semibold font-sans transition-colors cursor-pointer',
153
+ 'flex items-center gap-1 h-5 px-2 rounded text-2xs font-semibold font-sans transition-colors cursor-pointer',
153
154
  'disabled:opacity-50 disabled:cursor-not-allowed',
154
- currentMode === 'agent' ? 'bg-purple/15 text-purple border border-purple/25' : 'text-text-3 hover:text-text-1',
155
+ currentMode === 'agent' ? 'bg-purple/15 text-purple' : 'text-text-3 hover:text-text-1',
155
156
  )}
156
157
  title="Full agent — tools, files, session resume"
157
158
  >
158
- <Bot size={11} /> Agent
159
+ <Bot size={10} /> Agent
159
160
  </button>
160
161
  </div>
161
162
 
162
163
  {currentModel && (
163
164
  <div className={cn(
164
- 'flex items-center gap-1 h-6 px-2 rounded-md text-2xs font-mono border',
165
+ 'flex items-center gap-1 h-5 px-2 rounded text-2xs font-mono',
165
166
  isImageModel
166
- ? 'bg-purple/8 border-purple/20 text-purple'
167
- : 'bg-surface-3 border-border-subtle text-text-3',
167
+ ? 'bg-purple/8 text-purple'
168
+ : 'text-text-3',
168
169
  )}>
169
170
  {isImageModel && <ImageIcon size={9} />}
170
171
  <span className="max-w-[80px] truncate">{formatModelName(currentModel)}</span>
@@ -173,13 +174,13 @@ export function ChatInput({ onSend, onStop, sending, streaming, disabled, isImag
173
174
 
174
175
  {isCodex && (
175
176
  <>
176
- <div className="flex items-center h-6 rounded-md bg-surface-3 border border-border-subtle p-0.5">
177
+ <div className="flex items-center h-5 rounded bg-surface-3 border border-border-subtle p-0.5">
177
178
  {EFFORT_OPTIONS.map((opt) => (
178
179
  <button
179
180
  key={opt.value}
180
181
  onClick={() => onReasoningEffortChange?.(opt.value)}
181
182
  className={cn(
182
- 'h-5 px-1.5 rounded text-2xs font-semibold font-sans transition-colors cursor-pointer',
183
+ 'h-4 px-1.5 rounded text-2xs font-semibold font-sans transition-colors cursor-pointer',
183
184
  reasoningEffort === opt.value
184
185
  ? 'bg-accent/15 text-accent'
185
186
  : 'text-text-4 hover:text-text-1',
@@ -191,13 +192,13 @@ export function ChatInput({ onSend, onStop, sending, streaming, disabled, isImag
191
192
  ))}
192
193
  </div>
193
194
 
194
- <div className="flex items-center h-6 rounded-md bg-surface-3 border border-border-subtle p-0.5">
195
+ <div className="flex items-center h-5 rounded bg-surface-3 border border-border-subtle p-0.5">
195
196
  {VERBOSITY_OPTIONS.map((opt) => (
196
197
  <button
197
198
  key={opt.value}
198
199
  onClick={() => onVerbosityChange?.(opt.value)}
199
200
  className={cn(
200
- 'h-5 px-1.5 rounded text-2xs font-semibold font-sans transition-colors cursor-pointer',
201
+ 'h-4 px-1.5 rounded text-2xs font-semibold font-sans transition-colors cursor-pointer',
201
202
  verbosity === opt.value
202
203
  ? 'bg-accent/15 text-accent'
203
204
  : 'text-text-4 hover:text-text-1',
@@ -216,24 +217,25 @@ export function ChatInput({ onSend, onStop, sending, streaming, disabled, isImag
216
217
  {isActive ? (
217
218
  <button
218
219
  onClick={onStop}
219
- className="w-8 h-8 flex items-center justify-center rounded-lg bg-danger/80 text-white hover:bg-danger transition-all cursor-pointer shadow-lg shadow-danger/20 flex-shrink-0"
220
220
  title="Stop generation"
221
+ className="group w-7 h-7 flex items-center justify-center rounded-md transition-colors cursor-pointer"
221
222
  >
222
- <Square size={14} fill="currentColor" />
223
+ <span className="relative flex items-center justify-center w-3.5 h-3.5">
224
+ <span className="absolute inset-0 rounded-full bg-accent/30 group-hover:bg-red-500/30 animate-ping [animation-duration:2s] transition-colors" />
225
+ <span className="relative w-2.5 h-2.5 rounded-full bg-accent group-hover:bg-red-500 transition-colors" />
226
+ </span>
223
227
  </button>
224
228
  ) : (
225
229
  <button
226
230
  onClick={handleSend}
227
231
  disabled={!canSend}
228
232
  className={cn(
229
- 'w-8 h-8 flex items-center justify-center rounded-lg transition-all cursor-pointer flex-shrink-0',
230
- 'disabled:opacity-20 disabled:cursor-not-allowed',
231
- canSend
232
- ? 'bg-accent/15 text-accent hover:bg-accent/25 border border-accent/25'
233
- : 'bg-surface-4 text-text-4',
233
+ 'w-7 h-7 flex items-center justify-center rounded-md transition-colors cursor-pointer',
234
+ 'disabled:opacity-15 disabled:cursor-not-allowed',
235
+ canSend ? 'text-text-0 hover:text-text-1' : 'text-text-4',
234
236
  )}
235
237
  >
236
- {sending ? <Loader2 size={14} className="animate-spin" /> : <Send size={14} />}
238
+ {sending ? <Loader2 size={15} className="animate-spin" /> : <SendHorizontal size={15} />}
237
239
  </button>
238
240
  )}
239
241
  </div>
@@ -37,7 +37,7 @@ export function ChatView() {
37
37
  const setActiveConversation = useGrooveStore((s) => s.setActiveConversation);
38
38
  const sendChatMessage = useGrooveStore((s) => s.sendChatMessage);
39
39
  const sendImageMessage = useGrooveStore((s) => s.sendImageMessage);
40
- const stopAgent = useGrooveStore((s) => s.stopAgent);
40
+
41
41
  const stopChatStreaming = useGrooveStore((s) => s.stopChatStreaming);
42
42
  const setConversationMode = useGrooveStore((s) => s.setConversationMode);
43
43
  const setConversationModel = useGrooveStore((s) => s.setConversationModel);
@@ -54,7 +54,7 @@ export function ChatView() {
54
54
  const [replyContext, setReplyContext] = useState(null);
55
55
  const [modeChanging, setModeChanging] = useState(false);
56
56
 
57
- const activeRole = activeConversationId ? (conversationRoles?.[activeConversationId] || null) : null;
57
+ const activeRole = activeConversationId ? (conversationRoles?.[activeConversationId] || 'chat') : 'chat';
58
58
  const activeReasoningEffort = activeConversationId ? (conversationReasoningEffort?.[activeConversationId] || 'medium') : 'medium';
59
59
  const activeVerbosity = activeConversationId ? (conversationVerbosity?.[activeConversationId] || 'medium') : 'medium';
60
60
 
@@ -101,12 +101,8 @@ export function ChatView() {
101
101
 
102
102
  const handleStop = useCallback(() => {
103
103
  if (!activeConversation) return;
104
- if (activeConversation.mode === 'agent' && activeConversation.agentId) {
105
- stopAgent(activeConversation.agentId);
106
- } else {
107
- stopChatStreaming(activeConversationId);
108
- }
109
- }, [activeConversation, activeConversationId, stopAgent, stopChatStreaming]);
104
+ stopChatStreaming(activeConversationId);
105
+ }, [activeConversation, activeConversationId, stopChatStreaming]);
110
106
 
111
107
  const handleModelChange = useCallback(async (selection) => {
112
108
  if (activeConversationId) {
@@ -13,11 +13,11 @@ const ICONS = {
13
13
  };
14
14
 
15
15
  const ICON_COLORS = {
16
- spawn: 'text-accent',
17
- complete: 'text-success',
16
+ spawn: 'text-text-2',
17
+ complete: 'text-text-2',
18
18
  crash: 'text-danger',
19
19
  kill: 'text-text-3',
20
- rotate: 'text-purple',
20
+ rotate: 'text-text-2',
21
21
  error: 'text-danger',
22
22
  };
23
23
 
@@ -1,6 +1,6 @@
1
1
  // FSL-1.1-Apache-2.0 — see LICENSE
2
2
  import { useRef, useEffect, memo } from 'react';
3
- import { HEX } from '../../lib/theme-hex';
3
+ import { HEX, hexAlpha } from '../../lib/theme-hex';
4
4
  import { fmtNum } from '../../lib/format';
5
5
 
6
6
  const CacheRing = memo(function CacheRing({ cacheRead = 0, cacheCreation = 0, totalInput = 0, size = 140 }) {
@@ -47,7 +47,7 @@ const CacheRing = memo(function CacheRing({ cacheRead = 0, cacheCreation = 0, to
47
47
  const segEnd = startAngle + sweep * readPct;
48
48
  ctx.beginPath();
49
49
  ctx.arc(cx, cy, radius, startAngle, segEnd);
50
- ctx.strokeStyle = HEX.accent;
50
+ ctx.strokeStyle = HEX.text0;
51
51
  ctx.lineWidth = strokeWidth;
52
52
  ctx.lineCap = 'round';
53
53
  ctx.stroke();
@@ -58,7 +58,7 @@ const CacheRing = memo(function CacheRing({ cacheRead = 0, cacheCreation = 0, to
58
58
  const segEnd = segStart + sweep * createPct;
59
59
  ctx.beginPath();
60
60
  ctx.arc(cx, cy, radius, segStart, segEnd);
61
- ctx.strokeStyle = HEX.purple;
61
+ ctx.strokeStyle = HEX.text3;
62
62
  ctx.lineWidth = strokeWidth;
63
63
  ctx.lineCap = 'butt';
64
64
  ctx.stroke();
@@ -85,8 +85,8 @@ const CacheRing = memo(function CacheRing({ cacheRead = 0, cacheCreation = 0, to
85
85
  style={{ width: size, height: size }}
86
86
  />
87
87
  <div className="w-full mt-3 space-y-1.5 max-w-[160px]">
88
- <StatRow color={HEX.accent} label="Read" value={fmtNum(cacheRead)} />
89
- <StatRow color={HEX.purple} label="Create" value={fmtNum(cacheCreation)} />
88
+ <StatRow color={HEX.text0} label="Read" value={fmtNum(cacheRead)} />
89
+ <StatRow color={HEX.text3} label="Create" value={fmtNum(cacheCreation)} />
90
90
  <StatRow color={HEX.surface5} label="Miss" value={fmtNum(Math.max(totalInput - cacheRead - cacheCreation, 0))} />
91
91
  </div>
92
92
  </div>
@@ -8,10 +8,8 @@ const RADIUS = (SIZE - STROKE) / 2;
8
8
  const CIRCUMFERENCE = 2 * Math.PI * RADIUS;
9
9
  const START_ANGLE = -90;
10
10
 
11
- function gaugeColor(pct) {
12
- if (pct > 80) return HEX.danger;
13
- if (pct > 60) return HEX.warning;
14
- return HEX.success;
11
+ function gaugeColor() {
12
+ return HEX.text1;
15
13
  }
16
14
 
17
15
  function MiniGauge({ name, pct, threshold }) {
@@ -44,7 +42,7 @@ function MiniGauge({ name, pct, threshold }) {
44
42
  fill="none" strokeWidth={1}
45
43
  strokeLinecap="butt"
46
44
  style={{
47
- stroke: HEX.purple,
45
+ stroke: HEX.text3,
48
46
  strokeDasharray: `1 ${CIRCUMFERENCE - 1}`,
49
47
  strokeDashoffset: -(threshold / 100) * CIRCUMFERENCE,
50
48
  }}
@@ -68,11 +66,11 @@ function MiniGauge({ name, pct, threshold }) {
68
66
  function FleetSummary({ zones }) {
69
67
  return (
70
68
  <div className="flex items-center gap-2 text-2xs font-mono">
71
- <span className="text-success">{zones.healthy}</span>
69
+ <span className="text-text-2">{zones.healthy}</span>
72
70
  <span className="text-text-4">/</span>
73
- <span className="text-warning">{zones.warning}</span>
71
+ <span className="text-text-2">{zones.warning}</span>
74
72
  <span className="text-text-4">/</span>
75
- <span className="text-danger">{zones.critical}</span>
73
+ <span className="text-text-2">{zones.critical}</span>
76
74
  </div>
77
75
  );
78
76
  }
@@ -20,15 +20,15 @@ function shortModel(id) {
20
20
  const AgentRow = memo(function AgentRow({ agent, isRotating }) {
21
21
  const isAlive = agent.status === 'running' || agent.status === 'starting';
22
22
  const contextPct = Math.round((agent.contextUsage || 0) * 100);
23
- const sColor = isRotating ? '#c678dd' : statusColor(agent.status);
23
+ const sColor = isRotating ? HEX.accent : statusColor(agent.status);
24
24
  const quality = agent.quality;
25
25
  const successRate = quality?.toolSuccessRate != null ? Math.round(quality.toolSuccessRate * 100) : null;
26
26
  const thresholdPct = agent.rotationThreshold ? Math.round(agent.rotationThreshold * 100) : null;
27
27
  const rc = roleColor(agent.role);
28
- const barColor = contextPct > 80 ? HEX.danger : contextPct > 60 ? HEX.warning : HEX.accent;
28
+ const barColor = HEX.text1;
29
29
 
30
30
  return (
31
- <div className="px-3 pl-6 py-2 hover:bg-[rgba(51,175,188,0.06)] transition-colors space-y-1.5">
31
+ <div className="px-3 pl-6 py-2 hover:bg-surface-4 transition-colors space-y-1.5">
32
32
  {/* Top row */}
33
33
  <div className="flex items-center gap-2 min-w-0">
34
34
  {/* Status dot */}
@@ -64,13 +64,7 @@ const AgentRow = memo(function AgentRow({ agent, isRotating }) {
64
64
 
65
65
  {/* Quality badge */}
66
66
  {successRate != null && (
67
- <span
68
- className="text-2xs font-mono font-bold px-1 py-px rounded-sm flex-shrink-0"
69
- style={{
70
- color: successRate >= 90 ? '#4ae168' : successRate >= 70 ? '#e5c07b' : '#e06c75',
71
- background: successRate >= 90 ? 'rgba(74,225,104,0.1)' : successRate >= 70 ? 'rgba(229,192,123,0.1)' : 'rgba(224,108,117,0.1)',
72
- }}
73
- >
67
+ <span className="text-2xs font-mono font-bold px-1 py-px rounded-sm flex-shrink-0 text-text-1 bg-surface-4">
74
68
  {successRate}%
75
69
  </span>
76
70
  )}
@@ -95,7 +89,7 @@ const AgentRow = memo(function AgentRow({ agent, isRotating }) {
95
89
  <div className="flex items-center gap-2">
96
90
  <div
97
91
  className="relative flex-1 h-0.5 rounded-sm overflow-visible"
98
- style={{ background: hexAlpha(HEX.accent, 0.12) }}
92
+ style={{ background: hexAlpha(HEX.text4, 0.2) }}
99
93
  >
100
94
  <div
101
95
  className="absolute inset-y-0 left-0 rounded-sm transition-all duration-700"
@@ -104,7 +98,7 @@ const AgentRow = memo(function AgentRow({ agent, isRotating }) {
104
98
  {thresholdPct && (
105
99
  <div
106
100
  className="absolute top-[-1px] w-px h-[4px]"
107
- style={{ left: `${thresholdPct}%`, background: HEX.purple }}
101
+ style={{ left: `${thresholdPct}%`, background: HEX.text3 }}
108
102
  title={`Rotation at ${thresholdPct}%`}
109
103
  />
110
104
  )}
@@ -126,7 +120,7 @@ function TeamSection({ team, members, rotatingSet }) {
126
120
  <div>
127
121
  <button
128
122
  onClick={() => setExpanded((e) => !e)}
129
- className="w-full flex items-center gap-2 px-3 py-1.5 text-left transition-colors hover:bg-[rgba(51,175,188,0.08)] bg-[rgba(51,175,188,0.05)]"
123
+ className="w-full flex items-center gap-2 px-3 py-1.5 text-left transition-colors hover:bg-surface-4 bg-surface-3"
130
124
  style={{ borderLeft: isActive ? `2px solid ${HEX.accent}` : '2px solid transparent' }}
131
125
  >
132
126
  {expanded
@@ -142,7 +136,7 @@ function TeamSection({ team, members, rotatingSet }) {
142
136
  )}
143
137
  <span
144
138
  className="text-2xs font-mono tabular-nums flex-shrink-0 ml-1.5"
145
- style={{ color: isActive ? HEX.accent : undefined }}
139
+ style={{ color: isActive ? HEX.text1 : undefined }}
146
140
  >
147
141
  {runningCount}/{members.length}
148
142
  </span>