groove-dev 0.27.196 → 0.27.197
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 +3 -5
- package/node_modules/@groove-dev/daemon/src/chatstore.js +104 -0
- package/node_modules/@groove-dev/daemon/src/index.js +3 -2
- package/node_modules/@groove-dev/daemon/src/process.js +1 -1
- package/node_modules/@groove-dev/daemon/src/routes/agents.js +1 -175
- package/node_modules/@groove-dev/daemon/src/routes/chat-history.js +34 -0
- package/node_modules/@groove-dev/daemon/test/chatstore.test.js +86 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-Da2nbd6M.js +1043 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-zmrIbwNm.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.jsx +0 -2
- package/node_modules/@groove-dev/gui/src/components/agents/agent-config.jsx +2 -2
- package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +3 -3
- package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +2 -3
- package/node_modules/@groove-dev/gui/src/components/layout/breadcrumb-bar.jsx +1 -1
- package/node_modules/@groove-dev/gui/src/components/layout/command-palette.jsx +1 -1
- package/node_modules/@groove-dev/gui/src/stores/groove.js +5 -163
- package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +52 -2
- package/node_modules/@groove-dev/gui/src/views/marketplace.jsx +1 -1
- package/node_modules/@groove-dev/gui/src/views/settings.jsx +0 -61
- 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 +3 -5
- package/packages/daemon/src/chatstore.js +104 -0
- package/packages/daemon/src/index.js +3 -2
- package/packages/daemon/src/process.js +1 -1
- package/packages/daemon/src/routes/agents.js +1 -175
- package/packages/daemon/src/routes/chat-history.js +34 -0
- package/packages/gui/dist/assets/index-Da2nbd6M.js +1043 -0
- package/packages/gui/dist/assets/index-zmrIbwNm.css +1 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/packages/gui/src/App.jsx +0 -2
- package/packages/gui/src/components/agents/agent-config.jsx +2 -2
- package/packages/gui/src/components/agents/spawn-wizard.jsx +3 -3
- package/packages/gui/src/components/layout/activity-bar.jsx +2 -3
- package/packages/gui/src/components/layout/breadcrumb-bar.jsx +1 -1
- package/packages/gui/src/components/layout/command-palette.jsx +1 -1
- package/packages/gui/src/stores/groove.js +5 -163
- package/packages/gui/src/stores/slices/agents-slice.js +52 -2
- package/packages/gui/src/views/marketplace.jsx +1 -1
- package/packages/gui/src/views/settings.jsx +0 -61
- package/node_modules/@groove-dev/daemon/src/conversations.js +0 -576
- package/node_modules/@groove-dev/gui/dist/assets/index-Cat5pJUx.css +0 -1
- package/node_modules/@groove-dev/gui/dist/assets/index-L8xSnvHj.js +0 -1070
- package/node_modules/@groove-dev/gui/src/components/chat/chat-header.jsx +0 -198
- package/node_modules/@groove-dev/gui/src/components/chat/chat-input.jsx +0 -367
- package/node_modules/@groove-dev/gui/src/components/chat/chat-messages.jsx +0 -527
- package/node_modules/@groove-dev/gui/src/components/chat/chat-view.jsx +0 -212
- package/node_modules/@groove-dev/gui/src/components/chat/conversation-list.jsx +0 -163
- package/node_modules/@groove-dev/gui/src/components/chat/model-picker.jsx +0 -201
- package/node_modules/@groove-dev/gui/src/stores/slices/chat-slice.js +0 -227
- package/node_modules/@groove-dev/gui/src/views/chat.jsx +0 -6
- package/packages/daemon/src/conversations.js +0 -576
- package/packages/gui/dist/assets/index-Cat5pJUx.css +0 -1
- package/packages/gui/dist/assets/index-L8xSnvHj.js +0 -1070
- package/packages/gui/src/components/chat/chat-header.jsx +0 -198
- package/packages/gui/src/components/chat/chat-input.jsx +0 -367
- package/packages/gui/src/components/chat/chat-messages.jsx +0 -527
- package/packages/gui/src/components/chat/chat-view.jsx +0 -212
- package/packages/gui/src/components/chat/conversation-list.jsx +0 -163
- package/packages/gui/src/components/chat/model-picker.jsx +0 -201
- package/packages/gui/src/stores/slices/chat-slice.js +0 -227
- package/packages/gui/src/views/chat.jsx +0 -6
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
// FSL-1.1-Apache-2.0 — see LICENSE
|
|
2
|
-
|
|
3
|
-
import { api } from '../../lib/api';
|
|
4
|
-
import { loadJSON, persistJSON } from '../helpers.js';
|
|
5
|
-
|
|
6
|
-
const _modeChangePending = new Set();
|
|
7
|
-
|
|
8
|
-
export const createChatSlice = (set, get) => ({
|
|
9
|
-
// ── Conversations (Chat view) ────────────────────────────
|
|
10
|
-
conversations: [],
|
|
11
|
-
activeConversationId: localStorage.getItem('groove:activeConversationId') || null,
|
|
12
|
-
conversationMessages: loadJSON('groove:conversationMessages'),
|
|
13
|
-
conversationActiveTools: {},
|
|
14
|
-
sendingMessage: false,
|
|
15
|
-
streamingConversationId: null,
|
|
16
|
-
conversationRoles: loadJSON('groove:conversationRoles'),
|
|
17
|
-
conversationReasoningEffort: loadJSON('groove:conversationReasoningEffort'),
|
|
18
|
-
conversationVerbosity: loadJSON('groove:conversationVerbosity'),
|
|
19
|
-
|
|
20
|
-
// ── Conversations (Chat view) ────────────────────────────
|
|
21
|
-
|
|
22
|
-
async fetchConversations() {
|
|
23
|
-
try {
|
|
24
|
-
const data = await api.get('/conversations');
|
|
25
|
-
set({ conversations: data.conversations || data || [] });
|
|
26
|
-
} catch { /* endpoint may not exist yet */ }
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
async createConversation(provider, model, mode = 'api') {
|
|
30
|
-
try {
|
|
31
|
-
const conv = await api.post('/conversations', { provider, model, mode });
|
|
32
|
-
set((s) => ({
|
|
33
|
-
conversations: [conv, ...s.conversations.filter((c) => c.id !== conv.id)],
|
|
34
|
-
activeConversationId: conv.id,
|
|
35
|
-
}));
|
|
36
|
-
localStorage.setItem('groove:activeConversationId', conv.id);
|
|
37
|
-
return conv;
|
|
38
|
-
} catch (err) {
|
|
39
|
-
get().addToast('error', 'Failed to create conversation', err.message);
|
|
40
|
-
throw err;
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
async setConversationMode(id, mode) {
|
|
45
|
-
if (_modeChangePending.has(id)) return;
|
|
46
|
-
_modeChangePending.add(id);
|
|
47
|
-
try {
|
|
48
|
-
const conv = await api.patch(`/conversations/${encodeURIComponent(id)}`, { mode });
|
|
49
|
-
set((s) => ({ conversations: s.conversations.map((c) => c.id === id ? { ...c, ...conv } : c) }));
|
|
50
|
-
} catch (err) {
|
|
51
|
-
get().addToast('error', 'Mode change failed', err.message);
|
|
52
|
-
} finally {
|
|
53
|
-
_modeChangePending.delete(id);
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
async setConversationModel(id, provider, model) {
|
|
58
|
-
try {
|
|
59
|
-
const conv = await api.patch(`/conversations/${encodeURIComponent(id)}`, { provider, model });
|
|
60
|
-
set((s) => ({ conversations: s.conversations.map((c) => c.id === id ? { ...c, ...conv } : c) }));
|
|
61
|
-
} catch (err) {
|
|
62
|
-
get().addToast('error', 'Model change failed', err.message);
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
async stopChatStreaming(conversationId) {
|
|
67
|
-
try {
|
|
68
|
-
await api.post(`/conversations/${encodeURIComponent(conversationId)}/stop`);
|
|
69
|
-
set({ sendingMessage: false, streamingConversationId: null });
|
|
70
|
-
} catch { /* ignore */ }
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
async deleteConversation(id) {
|
|
74
|
-
try {
|
|
75
|
-
await api.delete(`/conversations/${encodeURIComponent(id)}`);
|
|
76
|
-
set((s) => {
|
|
77
|
-
const conversations = s.conversations.filter((c) => c.id !== id);
|
|
78
|
-
const conversationMessages = { ...s.conversationMessages };
|
|
79
|
-
delete conversationMessages[id];
|
|
80
|
-
persistJSON('groove:conversationMessages', conversationMessages);
|
|
81
|
-
const activeConversationId = s.activeConversationId === id
|
|
82
|
-
? (conversations[0]?.id || null)
|
|
83
|
-
: s.activeConversationId;
|
|
84
|
-
localStorage.setItem('groove:activeConversationId', activeConversationId || '');
|
|
85
|
-
const conversationRoles = { ...s.conversationRoles };
|
|
86
|
-
delete conversationRoles[id];
|
|
87
|
-
persistJSON('groove:conversationRoles', conversationRoles);
|
|
88
|
-
const conversationReasoningEffort = { ...s.conversationReasoningEffort };
|
|
89
|
-
delete conversationReasoningEffort[id];
|
|
90
|
-
persistJSON('groove:conversationReasoningEffort', conversationReasoningEffort);
|
|
91
|
-
const conversationVerbosity = { ...s.conversationVerbosity };
|
|
92
|
-
delete conversationVerbosity[id];
|
|
93
|
-
persistJSON('groove:conversationVerbosity', conversationVerbosity);
|
|
94
|
-
return { conversations, conversationMessages, conversationRoles, conversationReasoningEffort, conversationVerbosity, activeConversationId };
|
|
95
|
-
});
|
|
96
|
-
} catch (err) {
|
|
97
|
-
get().addToast('error', 'Delete failed', err.message);
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
async renameConversation(id, title) {
|
|
102
|
-
try {
|
|
103
|
-
const conv = await api.patch(`/conversations/${encodeURIComponent(id)}`, { title });
|
|
104
|
-
set((s) => ({ conversations: s.conversations.map((c) => c.id === id ? { ...c, ...conv } : c) }));
|
|
105
|
-
} catch (err) {
|
|
106
|
-
get().addToast('error', 'Rename failed', err.message);
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
async pinConversation(id, pinned) {
|
|
111
|
-
try {
|
|
112
|
-
const conv = await api.patch(`/conversations/${encodeURIComponent(id)}`, { pinned });
|
|
113
|
-
set((s) => ({ conversations: s.conversations.map((c) => c.id === id ? { ...c, ...conv } : c) }));
|
|
114
|
-
} catch (err) {
|
|
115
|
-
get().addToast('error', 'Pin failed', err.message);
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
|
|
119
|
-
setActiveConversation(id) {
|
|
120
|
-
set({ activeConversationId: id });
|
|
121
|
-
localStorage.setItem('groove:activeConversationId', id || '');
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
setConversationRole(id, role) {
|
|
125
|
-
set((s) => {
|
|
126
|
-
const roles = { ...s.conversationRoles };
|
|
127
|
-
if (role) {
|
|
128
|
-
roles[id] = role;
|
|
129
|
-
} else {
|
|
130
|
-
delete roles[id];
|
|
131
|
-
}
|
|
132
|
-
persistJSON('groove:conversationRoles', roles);
|
|
133
|
-
return { conversationRoles: roles };
|
|
134
|
-
});
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
setConversationReasoningEffort(id, effort) {
|
|
138
|
-
set((s) => {
|
|
139
|
-
const map = { ...s.conversationReasoningEffort };
|
|
140
|
-
map[id] = effort || 'medium';
|
|
141
|
-
persistJSON('groove:conversationReasoningEffort', map);
|
|
142
|
-
return { conversationReasoningEffort: map };
|
|
143
|
-
});
|
|
144
|
-
},
|
|
145
|
-
|
|
146
|
-
setConversationVerbosity(id, verbosity) {
|
|
147
|
-
set((s) => {
|
|
148
|
-
const map = { ...s.conversationVerbosity };
|
|
149
|
-
map[id] = verbosity || 'medium';
|
|
150
|
-
persistJSON('groove:conversationVerbosity', map);
|
|
151
|
-
return { conversationVerbosity: map };
|
|
152
|
-
});
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
async sendChatMessage(conversationId, message) {
|
|
156
|
-
const conv = get().conversations.find((c) => c.id === conversationId);
|
|
157
|
-
if (!conv) return;
|
|
158
|
-
|
|
159
|
-
// Add user message to local state immediately
|
|
160
|
-
set((s) => {
|
|
161
|
-
const msgs = { ...s.conversationMessages };
|
|
162
|
-
if (!msgs[conversationId]) msgs[conversationId] = [];
|
|
163
|
-
msgs[conversationId] = [...msgs[conversationId], { from: 'user', text: message, timestamp: Date.now() }];
|
|
164
|
-
persistJSON('groove:conversationMessages', msgs);
|
|
165
|
-
return { conversationMessages: msgs, sendingMessage: true, streamingConversationId: conversationId };
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
try {
|
|
169
|
-
const body = { message };
|
|
170
|
-
const history = get().conversationMessages[conversationId] || [];
|
|
171
|
-
body.history = history.slice(0, -1);
|
|
172
|
-
|
|
173
|
-
const role = get().conversationRoles?.[conversationId];
|
|
174
|
-
const rules = ['Never use emojis in your responses.', 'Be professional, concise, and direct.'];
|
|
175
|
-
if (role && role !== 'chat') rules.unshift(`You are a professional ${role}. Respond with deep expertise in that domain.`);
|
|
176
|
-
if (role === 'research') rules.unshift('You are a research assistant. Help explore ideas, synthesize information, and provide thorough analysis with sources when possible.');
|
|
177
|
-
const systemCtx = rules.join(' ');
|
|
178
|
-
body.history = [
|
|
179
|
-
{ from: 'user', text: `Instructions: ${systemCtx}` },
|
|
180
|
-
{ from: 'assistant', text: 'Understood.' },
|
|
181
|
-
...body.history,
|
|
182
|
-
];
|
|
183
|
-
const effort = get().conversationReasoningEffort?.[conversationId] || 'medium';
|
|
184
|
-
const verbosity = get().conversationVerbosity?.[conversationId] || 'medium';
|
|
185
|
-
if (conv.provider === 'codex') {
|
|
186
|
-
body.reasoning_effort = effort;
|
|
187
|
-
body.verbosity = verbosity;
|
|
188
|
-
}
|
|
189
|
-
await api.post(`/conversations/${encodeURIComponent(conversationId)}/message`, body);
|
|
190
|
-
} catch (err) {
|
|
191
|
-
set((s) => {
|
|
192
|
-
const msgs = { ...s.conversationMessages };
|
|
193
|
-
if (!msgs[conversationId]) msgs[conversationId] = [];
|
|
194
|
-
msgs[conversationId] = [...msgs[conversationId], { from: 'system', text: `Failed: ${err.message}`, timestamp: Date.now() }];
|
|
195
|
-
persistJSON('groove:conversationMessages', msgs);
|
|
196
|
-
return { conversationMessages: msgs, sendingMessage: false, streamingConversationId: null };
|
|
197
|
-
});
|
|
198
|
-
get().addToast('error', 'Message failed', err.message);
|
|
199
|
-
}
|
|
200
|
-
},
|
|
201
|
-
|
|
202
|
-
async sendImageMessage(conversationId, prompt, { model, size, quality } = {}) {
|
|
203
|
-
const conv = get().conversations.find((c) => c.id === conversationId);
|
|
204
|
-
if (!conv) return;
|
|
205
|
-
|
|
206
|
-
set((s) => {
|
|
207
|
-
const msgs = { ...s.conversationMessages };
|
|
208
|
-
if (!msgs[conversationId]) msgs[conversationId] = [];
|
|
209
|
-
msgs[conversationId] = [...msgs[conversationId], { from: 'user', text: prompt, timestamp: Date.now() }];
|
|
210
|
-
persistJSON('groove:conversationMessages', msgs);
|
|
211
|
-
return { conversationMessages: msgs, sendingMessage: true, streamingConversationId: conversationId };
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
try {
|
|
215
|
-
await api.post(`/conversations/${encodeURIComponent(conversationId)}/generate-image`, { prompt, model, size, quality });
|
|
216
|
-
} catch (err) {
|
|
217
|
-
set((s) => {
|
|
218
|
-
const msgs = { ...s.conversationMessages };
|
|
219
|
-
if (!msgs[conversationId]) msgs[conversationId] = [];
|
|
220
|
-
msgs[conversationId] = [...msgs[conversationId], { from: 'system', text: `Image failed: ${err.message}`, timestamp: Date.now() }];
|
|
221
|
-
persistJSON('groove:conversationMessages', msgs);
|
|
222
|
-
return { conversationMessages: msgs, sendingMessage: false, streamingConversationId: null };
|
|
223
|
-
});
|
|
224
|
-
get().addToast('error', 'Image generation failed', err.message);
|
|
225
|
-
}
|
|
226
|
-
},
|
|
227
|
-
});
|