groove-dev 0.26.7 → 0.26.9
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.
- package/node_modules/@groove-dev/daemon/src/agent-loop.js +10 -7
- package/node_modules/@groove-dev/daemon/src/api.js +16 -2
- package/node_modules/@groove-dev/gui/dist/assets/{index-PPbrScja.js → index-CfD162Lt.js} +22 -22
- package/node_modules/@groove-dev/gui/dist/index.html +1 -1
- package/node_modules/@groove-dev/gui/src/stores/groove.js +12 -8
- package/package.json +1 -1
- package/packages/daemon/src/agent-loop.js +10 -7
- package/packages/daemon/src/api.js +16 -2
- package/packages/gui/dist/assets/{index-PPbrScja.js → index-CfD162Lt.js} +22 -22
- package/packages/gui/dist/index.html +1 -1
- package/packages/gui/src/stores/groove.js +12 -8
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
|
7
7
|
<title>Groove GUI</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-CfD162Lt.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/vendor-C0HXlhrU.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/reactflow-BQPfi37R.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/codemirror-BBL3i_JW.js">
|
|
@@ -157,11 +157,13 @@ export const useGrooveStore = create((set, get) => ({
|
|
|
157
157
|
set({ agents });
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
// Text responses → chat bubbles
|
|
161
|
-
//
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
|
|
160
|
+
// Text responses → chat bubbles
|
|
161
|
+
// Skip pure token-level stream chunks (subtype='stream') — too granular
|
|
162
|
+
// Show: subtype='assistant' (Claude Code), subtype='text' (agent loop), type='result',
|
|
163
|
+
// and plain activity events with string data (Gemini/Codex/Ollama CLI)
|
|
164
|
+
const isTokenStream = data.subtype === 'stream';
|
|
165
|
+
const showAsChat = chatText && chatText.trim() && !isTokenStream && (
|
|
166
|
+
data.subtype === 'assistant' || data.subtype === 'text' || data.type === 'result' ||
|
|
165
167
|
(data.type === 'activity' && typeof data.data === 'string')
|
|
166
168
|
);
|
|
167
169
|
if (showAsChat) {
|
|
@@ -171,9 +173,11 @@ export const useGrooveStore = create((set, get) => ({
|
|
|
171
173
|
const last = arr[arr.length - 1];
|
|
172
174
|
const isRecent = last && last.from === 'agent' && (Date.now() - last.timestamp) < 8000;
|
|
173
175
|
|
|
174
|
-
if (isRecent
|
|
175
|
-
//
|
|
176
|
-
|
|
176
|
+
if (isRecent) {
|
|
177
|
+
// Append to the last agent message (streaming from any provider)
|
|
178
|
+
// Claude Code blocks use \n\n separator; plain text uses space
|
|
179
|
+
const sep = data.subtype === 'assistant' ? '\n\n' : ' ';
|
|
180
|
+
arr[arr.length - 1] = { ...last, text: last.text + sep + chatText.trim(), timestamp: Date.now() };
|
|
177
181
|
} else {
|
|
178
182
|
// New message bubble
|
|
179
183
|
arr.push({ from: 'agent', text: chatText.trim(), timestamp: Date.now() });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groove-dev",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.9",
|
|
4
4
|
"description": "Open-source agent orchestration layer — the AI company OS. Local model agent engine (GGUF/Ollama/llama-server), HuggingFace model browser, MCP integrations (Slack, Gmail, Stripe, 15+), agent scheduling (cron), business roles (CMO, CFO, EA). GUI dashboard, multi-agent coordination, zero cold-start, infinite sessions. Works with Claude Code, Codex, Gemini CLI, Ollama, any local model.",
|
|
5
5
|
"license": "FSL-1.1-Apache-2.0",
|
|
6
6
|
"author": "Groove Dev <hello@groovedev.ai> (https://groovedev.ai)",
|
|
@@ -126,18 +126,21 @@ export class AgentLoop extends EventEmitter {
|
|
|
126
126
|
}
|
|
127
127
|
this.messages.push(assistantMsg);
|
|
128
128
|
|
|
129
|
-
//
|
|
130
|
-
if (content) {
|
|
131
|
-
this._writeLog({ type: 'assistant', content: content.slice(0, 2000) });
|
|
132
|
-
this.emit('output', { type: 'activity', subtype: 'text', data: content });
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// No tool calls → turn complete, go idle
|
|
129
|
+
// No tool calls → turn complete, broadcast final text and go idle
|
|
136
130
|
if (!toolCalls || toolCalls.length === 0) {
|
|
131
|
+
if (content) {
|
|
132
|
+
this._writeLog({ type: 'assistant', content: content.slice(0, 2000) });
|
|
133
|
+
}
|
|
137
134
|
this.emit('output', { type: 'result', data: content || 'Turn complete', turns: this.turns });
|
|
138
135
|
break;
|
|
139
136
|
}
|
|
140
137
|
|
|
138
|
+
// Has tool calls — broadcast text before executing tools (if model sent text + tools)
|
|
139
|
+
if (content) {
|
|
140
|
+
this._writeLog({ type: 'assistant', content: content.slice(0, 2000) });
|
|
141
|
+
this.emit('output', { type: 'activity', subtype: 'text', data: content });
|
|
142
|
+
}
|
|
143
|
+
|
|
141
144
|
// Execute each tool call
|
|
142
145
|
for (const call of toolCalls) {
|
|
143
146
|
if (!this.running) break;
|
|
@@ -148,9 +148,23 @@ export function createApi(app, daemon) {
|
|
|
148
148
|
app.post('/api/providers/ollama/pull', async (req, res) => {
|
|
149
149
|
const { model } = req.body;
|
|
150
150
|
if (!model) return res.status(400).json({ error: 'model is required' });
|
|
151
|
-
if (!OllamaProvider.isInstalled()) return res.status(400).json({ error: 'Ollama is not installed' });
|
|
152
|
-
const broadcast = daemon.broadcast
|
|
151
|
+
if (!OllamaProvider.isInstalled()) return res.status(400).json({ error: 'Ollama is not installed. Install with: brew install ollama' });
|
|
152
|
+
const broadcast = daemon.broadcast.bind(daemon);
|
|
153
153
|
try {
|
|
154
|
+
// Auto-start Ollama server if not running
|
|
155
|
+
const running = await OllamaProvider.isServerRunning();
|
|
156
|
+
if (!running) {
|
|
157
|
+
broadcast({ type: 'ollama:serve:starting' });
|
|
158
|
+
OllamaProvider.startServer();
|
|
159
|
+
// Wait for server to be ready (up to 10s)
|
|
160
|
+
for (let i = 0; i < 20; i++) {
|
|
161
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
162
|
+
if (await OllamaProvider.isServerRunning()) break;
|
|
163
|
+
}
|
|
164
|
+
if (!(await OllamaProvider.isServerRunning())) {
|
|
165
|
+
return res.status(500).json({ error: 'Could not start Ollama server. Run `ollama serve` manually.' });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
154
168
|
broadcast({ type: 'ollama:pull:start', model });
|
|
155
169
|
await OllamaProvider.pullModel(model, (progress) => {
|
|
156
170
|
broadcast({ type: 'ollama:pull:progress', model, progress: progress.trim() });
|