groove-dev 0.27.73 → 0.27.75
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/cli/package.json +1 -1
- package/node_modules/@groove-dev/daemon/package.json +1 -1
- package/node_modules/@groove-dev/daemon/src/api.js +256 -4
- package/node_modules/@groove-dev/daemon/src/conversations.js +16 -0
- package/node_modules/@groove-dev/daemon/src/index.js +41 -1
- package/node_modules/@groove-dev/daemon/src/preview.js +18 -2
- package/node_modules/@groove-dev/daemon/src/process.js +6 -1
- package/node_modules/@groove-dev/daemon/src/providers/base.js +4 -0
- package/node_modules/@groove-dev/daemon/src/providers/claude-code.js +2 -1
- package/node_modules/@groove-dev/daemon/src/providers/codex.js +41 -1
- package/node_modules/@groove-dev/daemon/src/providers/gemini.js +2 -1
- package/node_modules/@groove-dev/daemon/src/providers/grok.js +156 -0
- package/node_modules/@groove-dev/daemon/src/providers/index.js +26 -9
- package/node_modules/@groove-dev/daemon/src/providers/nano-banana.js +103 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-CAT9SCJi.js +8620 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-CVzz6zyb.css +1 -0
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/package.json +1 -1
- package/node_modules/@groove-dev/gui/src/app.css +29 -0
- package/node_modules/@groove-dev/gui/src/app.jsx +2 -0
- package/node_modules/@groove-dev/gui/src/components/chat/chat-header.jsx +16 -5
- package/node_modules/@groove-dev/gui/src/components/chat/chat-input.jsx +40 -7
- package/node_modules/@groove-dev/gui/src/components/chat/chat-messages.jsx +149 -31
- package/node_modules/@groove-dev/gui/src/components/chat/chat-view.jsx +26 -2
- package/node_modules/@groove-dev/gui/src/components/chat/model-picker.jsx +105 -52
- package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +5 -2
- package/node_modules/@groove-dev/gui/src/components/layout/welcome-splash.jsx +215 -88
- package/node_modules/@groove-dev/gui/src/components/preview/preview-toolbar.jsx +81 -0
- package/node_modules/@groove-dev/gui/src/components/preview/preview-workspace.jsx +263 -0
- package/node_modules/@groove-dev/gui/src/components/preview/screenshot-overlay.jsx +203 -0
- package/node_modules/@groove-dev/gui/src/components/ui/toast.jsx +6 -2
- package/node_modules/@groove-dev/gui/src/stores/groove.js +149 -9
- package/node_modules/@groove-dev/gui/src/views/preview.jsx +6 -0
- package/node_modules/@groove-dev/gui/src/views/settings.jsx +278 -123
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/api.js +256 -4
- package/packages/daemon/src/conversations.js +16 -0
- package/packages/daemon/src/index.js +41 -1
- package/packages/daemon/src/preview.js +18 -2
- package/packages/daemon/src/process.js +6 -1
- package/packages/daemon/src/providers/base.js +4 -0
- package/packages/daemon/src/providers/claude-code.js +2 -1
- package/packages/daemon/src/providers/codex.js +41 -1
- package/packages/daemon/src/providers/gemini.js +2 -1
- package/packages/daemon/src/providers/grok.js +156 -0
- package/packages/daemon/src/providers/index.js +26 -9
- package/packages/daemon/src/providers/nano-banana.js +103 -0
- package/packages/gui/dist/assets/index-CAT9SCJi.js +8620 -0
- package/packages/gui/dist/assets/index-CVzz6zyb.css +1 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/packages/gui/src/app.css +29 -0
- package/packages/gui/src/app.jsx +2 -0
- package/packages/gui/src/components/chat/chat-header.jsx +16 -5
- package/packages/gui/src/components/chat/chat-input.jsx +40 -7
- package/packages/gui/src/components/chat/chat-messages.jsx +149 -31
- package/packages/gui/src/components/chat/chat-view.jsx +26 -2
- package/packages/gui/src/components/chat/model-picker.jsx +105 -52
- package/packages/gui/src/components/layout/activity-bar.jsx +5 -2
- package/packages/gui/src/components/layout/welcome-splash.jsx +215 -88
- package/packages/gui/src/components/preview/preview-toolbar.jsx +81 -0
- package/packages/gui/src/components/preview/preview-workspace.jsx +263 -0
- package/packages/gui/src/components/preview/screenshot-overlay.jsx +203 -0
- package/packages/gui/src/components/ui/toast.jsx +6 -2
- package/packages/gui/src/stores/groove.js +149 -9
- package/packages/gui/src/views/preview.jsx +6 -0
- package/packages/gui/src/views/settings.jsx +278 -123
- package/node_modules/@groove-dev/gui/dist/assets/index-BFc7Ov6v.css +0 -1
- package/node_modules/@groove-dev/gui/dist/assets/index-Deza1S0i.js +0 -8615
- package/packages/gui/dist/assets/index-BFc7Ov6v.css +0 -1
- package/packages/gui/dist/assets/index-Deza1S0i.js +0 -8615
|
@@ -56,8 +56,13 @@ export const useGrooveStore = create((set, get) => ({
|
|
|
56
56
|
selectedPeerId: null,
|
|
57
57
|
},
|
|
58
58
|
|
|
59
|
+
// ── Preview ───────────────────────────────────────────────
|
|
60
|
+
previewState: { url: null, teamId: null, kind: null, deviceSize: 'desktop', screenshotMode: false },
|
|
61
|
+
previewChat: [],
|
|
62
|
+
previewIterating: false,
|
|
63
|
+
|
|
59
64
|
// ── Navigation ────────────────────────────────────────────
|
|
60
|
-
activeView: 'agents', // 'agents' | 'editor' | 'dashboard' | 'marketplace' | 'teams' | 'settings'
|
|
65
|
+
activeView: 'agents', // 'agents' | 'editor' | 'dashboard' | 'marketplace' | 'teams' | 'settings' | 'preview'
|
|
61
66
|
detailPanel: null, // null | { type: 'agent', agentId } | { type: 'spawn' } | { type: 'journalist' }
|
|
62
67
|
teamDetailPanels: {}, // { [teamId]: detailPanel } — persists panel state per team
|
|
63
68
|
commandPaletteOpen: false,
|
|
@@ -455,21 +460,30 @@ export const useGrooveStore = create((set, get) => ({
|
|
|
455
460
|
'success',
|
|
456
461
|
'Project ready to preview',
|
|
457
462
|
msg.url,
|
|
458
|
-
{ label: '
|
|
463
|
+
{ label: 'Open Preview', onClick: () => get().openPreview(msg.url, msg.teamId, msg.kind) },
|
|
459
464
|
{ persistent: true },
|
|
460
465
|
);
|
|
461
466
|
break;
|
|
462
467
|
|
|
463
|
-
case 'preview:failed':
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
468
|
+
case 'preview:failed': {
|
|
469
|
+
const failKind = msg.kind || '';
|
|
470
|
+
if (failKind !== 'no_preview' && failKind !== 'cli' && failKind !== 'none') {
|
|
471
|
+
get().addToast(
|
|
472
|
+
'warning',
|
|
473
|
+
'Preview could not launch',
|
|
474
|
+
msg.reason ? String(msg.reason).slice(0, 200) : 'Unknown error',
|
|
475
|
+
);
|
|
476
|
+
}
|
|
469
477
|
break;
|
|
478
|
+
}
|
|
470
479
|
|
|
471
|
-
case 'preview:stopped':
|
|
480
|
+
case 'preview:stopped': {
|
|
481
|
+
const ps = get().previewState;
|
|
482
|
+
if (ps.teamId && ps.teamId === msg.teamId) {
|
|
483
|
+
set({ previewState: { url: null, teamId: null, kind: null, deviceSize: 'desktop', screenshotMode: false }, previewChat: [], previewIterating: false });
|
|
484
|
+
}
|
|
472
485
|
break;
|
|
486
|
+
}
|
|
473
487
|
|
|
474
488
|
case 'agent:stalled': {
|
|
475
489
|
const name = msg.agentName || msg.agentId;
|
|
@@ -899,6 +913,55 @@ export const useGrooveStore = create((set, get) => ({
|
|
|
899
913
|
break;
|
|
900
914
|
}
|
|
901
915
|
|
|
916
|
+
case 'conversation:image': {
|
|
917
|
+
const { conversationId, prompt, url, b64_json, mimeType, model: imgModel, provider: imgProvider } = msg.data || msg;
|
|
918
|
+
if (!conversationId) break;
|
|
919
|
+
const imageUrl = url || (b64_json ? `data:${mimeType || 'image/png'};base64,${b64_json}` : null);
|
|
920
|
+
set((s) => {
|
|
921
|
+
const msgs = { ...s.conversationMessages };
|
|
922
|
+
if (!msgs[conversationId]) msgs[conversationId] = [];
|
|
923
|
+
const arr = [...msgs[conversationId]];
|
|
924
|
+
const loadingIdx = arr.findLastIndex((m) => m.type === 'image-loading' && m.prompt === prompt);
|
|
925
|
+
if (loadingIdx >= 0) {
|
|
926
|
+
arr[loadingIdx] = { from: 'assistant', type: 'image', imageUrl, prompt, model: imgModel, provider: imgProvider, timestamp: Date.now() };
|
|
927
|
+
} else {
|
|
928
|
+
arr.push({ from: 'assistant', type: 'image', imageUrl, prompt, model: imgModel, provider: imgProvider, timestamp: Date.now() });
|
|
929
|
+
}
|
|
930
|
+
msgs[conversationId] = arr.slice(-200);
|
|
931
|
+
persistJSON('groove:conversationMessages', msgs);
|
|
932
|
+
const isActive = s.streamingConversationId === conversationId;
|
|
933
|
+
return { conversationMessages: msgs, sendingMessage: isActive ? false : s.sendingMessage, streamingConversationId: isActive ? null : s.streamingConversationId };
|
|
934
|
+
});
|
|
935
|
+
break;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
case 'conversation:image-progress': {
|
|
939
|
+
const { conversationId, status, prompt: imgPrompt, error: imgError } = msg.data || msg;
|
|
940
|
+
if (!conversationId) break;
|
|
941
|
+
if (status === 'generating') {
|
|
942
|
+
set((s) => {
|
|
943
|
+
const msgs = { ...s.conversationMessages };
|
|
944
|
+
if (!msgs[conversationId]) msgs[conversationId] = [];
|
|
945
|
+
msgs[conversationId] = [...msgs[conversationId], { from: 'assistant', type: 'image-loading', prompt: imgPrompt, timestamp: Date.now() }];
|
|
946
|
+
return { conversationMessages: msgs, streamingConversationId: conversationId };
|
|
947
|
+
});
|
|
948
|
+
} else if (status === 'error') {
|
|
949
|
+
set((s) => {
|
|
950
|
+
const msgs = { ...s.conversationMessages };
|
|
951
|
+
if (!msgs[conversationId]) msgs[conversationId] = [];
|
|
952
|
+
const arr = [...msgs[conversationId]];
|
|
953
|
+
const loadingIdx = arr.findLastIndex((m) => m.type === 'image-loading');
|
|
954
|
+
if (loadingIdx >= 0) arr.splice(loadingIdx, 1);
|
|
955
|
+
arr.push({ from: 'system', text: `Image generation failed: ${imgError || 'Unknown error'}`, timestamp: Date.now() });
|
|
956
|
+
msgs[conversationId] = arr;
|
|
957
|
+
persistJSON('groove:conversationMessages', msgs);
|
|
958
|
+
const isActive = s.streamingConversationId === conversationId;
|
|
959
|
+
return { conversationMessages: msgs, sendingMessage: isActive ? false : s.sendingMessage, streamingConversationId: isActive ? null : s.streamingConversationId };
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
|
|
902
965
|
case 'conversation:error': {
|
|
903
966
|
const { conversationId, error } = msg.data || msg;
|
|
904
967
|
if (conversationId) {
|
|
@@ -1107,6 +1170,50 @@ export const useGrooveStore = create((set, get) => ({
|
|
|
1107
1170
|
persistJSON('groove:expandedNodes', expanded);
|
|
1108
1171
|
},
|
|
1109
1172
|
|
|
1173
|
+
// ── Preview ──────────────────────────────────────────────
|
|
1174
|
+
|
|
1175
|
+
openPreview(url, teamId, kind) {
|
|
1176
|
+
set({ previewState: { url, teamId, kind, deviceSize: 'desktop', screenshotMode: false }, previewChat: [], activeView: 'preview' });
|
|
1177
|
+
},
|
|
1178
|
+
closePreview() {
|
|
1179
|
+
const { previewState } = get();
|
|
1180
|
+
if (previewState.teamId) {
|
|
1181
|
+
api.delete(`/preview/${previewState.teamId}`).catch(() => {});
|
|
1182
|
+
}
|
|
1183
|
+
set({ previewState: { url: null, teamId: null, kind: null, deviceSize: 'desktop', screenshotMode: false }, previewChat: [], previewIterating: false, activeView: 'agents' });
|
|
1184
|
+
},
|
|
1185
|
+
setPreviewDevice(size) {
|
|
1186
|
+
set((s) => ({ previewState: { ...s.previewState, deviceSize: size } }));
|
|
1187
|
+
},
|
|
1188
|
+
toggleScreenshotMode() {
|
|
1189
|
+
set((s) => ({ previewState: { ...s.previewState, screenshotMode: !s.previewState.screenshotMode } }));
|
|
1190
|
+
},
|
|
1191
|
+
async iteratePreview(message, screenshotBase64) {
|
|
1192
|
+
const { previewState } = get();
|
|
1193
|
+
if (!previewState.teamId) return;
|
|
1194
|
+
|
|
1195
|
+
const userMsg = { role: 'user', content: message, screenshot: screenshotBase64 || null, timestamp: Date.now() };
|
|
1196
|
+
set((s) => ({ previewChat: [...s.previewChat, userMsg], previewIterating: true }));
|
|
1197
|
+
|
|
1198
|
+
try {
|
|
1199
|
+
const body = { message };
|
|
1200
|
+
if (screenshotBase64) body.screenshot = screenshotBase64;
|
|
1201
|
+
const res = await api.post(`/preview/${previewState.teamId}/iterate`, body);
|
|
1202
|
+
const assistantMsg = { role: 'assistant', content: res.response || res.message || 'Changes routed to planner.', timestamp: Date.now() };
|
|
1203
|
+
set((s) => ({ previewChat: [...s.previewChat, assistantMsg], previewIterating: false }));
|
|
1204
|
+
} catch (err) {
|
|
1205
|
+
const errMsg = { role: 'assistant', content: `Failed to iterate: ${err.message}`, timestamp: Date.now() };
|
|
1206
|
+
set((s) => ({ previewChat: [...s.previewChat, errMsg], previewIterating: false }));
|
|
1207
|
+
}
|
|
1208
|
+
},
|
|
1209
|
+
addPreviewChatMessage(role, content, screenshot) {
|
|
1210
|
+
const msg = { role, content, screenshot: screenshot || null, timestamp: Date.now() };
|
|
1211
|
+
set((s) => ({ previewChat: [...s.previewChat, msg] }));
|
|
1212
|
+
},
|
|
1213
|
+
clearPreviewChat() {
|
|
1214
|
+
set({ previewChat: [] });
|
|
1215
|
+
},
|
|
1216
|
+
|
|
1110
1217
|
// ── Toasts ────────────────────────────────────────────────
|
|
1111
1218
|
|
|
1112
1219
|
addToast(type, message, detail, action, options = {}) {
|
|
@@ -1488,6 +1595,13 @@ export const useGrooveStore = create((set, get) => ({
|
|
|
1488
1595
|
get().fetchTreeDir('');
|
|
1489
1596
|
},
|
|
1490
1597
|
|
|
1598
|
+
async removeRecentProject(path) {
|
|
1599
|
+
try {
|
|
1600
|
+
await api.delete('/projects/recent', { path });
|
|
1601
|
+
} catch {}
|
|
1602
|
+
get().fetchProjectDir();
|
|
1603
|
+
},
|
|
1604
|
+
|
|
1491
1605
|
toggleProjectPicker() {
|
|
1492
1606
|
set((s) => ({ showProjectPicker: !s.showProjectPicker }));
|
|
1493
1607
|
},
|
|
@@ -1977,6 +2091,32 @@ export const useGrooveStore = create((set, get) => ({
|
|
|
1977
2091
|
}
|
|
1978
2092
|
},
|
|
1979
2093
|
|
|
2094
|
+
async sendImageMessage(conversationId, prompt, { model, size, quality } = {}) {
|
|
2095
|
+
const conv = get().conversations.find((c) => c.id === conversationId);
|
|
2096
|
+
if (!conv) return;
|
|
2097
|
+
|
|
2098
|
+
set((s) => {
|
|
2099
|
+
const msgs = { ...s.conversationMessages };
|
|
2100
|
+
if (!msgs[conversationId]) msgs[conversationId] = [];
|
|
2101
|
+
msgs[conversationId] = [...msgs[conversationId], { from: 'user', text: prompt, timestamp: Date.now() }];
|
|
2102
|
+
persistJSON('groove:conversationMessages', msgs);
|
|
2103
|
+
return { conversationMessages: msgs, sendingMessage: true, streamingConversationId: conversationId };
|
|
2104
|
+
});
|
|
2105
|
+
|
|
2106
|
+
try {
|
|
2107
|
+
await api.post(`/conversations/${encodeURIComponent(conversationId)}/generate-image`, { prompt, model, size, quality });
|
|
2108
|
+
} catch (err) {
|
|
2109
|
+
set((s) => {
|
|
2110
|
+
const msgs = { ...s.conversationMessages };
|
|
2111
|
+
if (!msgs[conversationId]) msgs[conversationId] = [];
|
|
2112
|
+
msgs[conversationId] = [...msgs[conversationId], { from: 'system', text: `Image failed: ${err.message}`, timestamp: Date.now() }];
|
|
2113
|
+
persistJSON('groove:conversationMessages', msgs);
|
|
2114
|
+
return { conversationMessages: msgs, sendingMessage: false, streamingConversationId: null };
|
|
2115
|
+
});
|
|
2116
|
+
get().addToast('error', 'Image generation failed', err.message);
|
|
2117
|
+
}
|
|
2118
|
+
},
|
|
2119
|
+
|
|
1980
2120
|
// ── Editor ────────────────────────────────────────────────
|
|
1981
2121
|
|
|
1982
2122
|
async openFile(path) {
|