groove-dev 0.27.156 → 0.27.159
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/journalist.js +61 -16
- package/node_modules/@groove-dev/daemon/src/process.js +130 -2
- package/node_modules/@groove-dev/daemon/src/rotator.js +2 -1
- package/node_modules/@groove-dev/daemon/src/routes/files.js +28 -6
- package/node_modules/@groove-dev/daemon/src/tunnel-manager.js +89 -71
- package/node_modules/@groove-dev/gui/dist/assets/index-Bij9o_dc.js +1020 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-Dzofq3wS.css +1 -0
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/package.json +1 -2
- package/node_modules/@groove-dev/gui/src/app.css +2 -2
- package/node_modules/@groove-dev/gui/src/components/agents/agent-feed.jsx +8 -8
- package/node_modules/@groove-dev/gui/src/components/agents/diff-viewer.jsx +2 -2
- package/node_modules/@groove-dev/gui/src/components/agents/workspace-mode.jsx +11 -2
- package/node_modules/@groove-dev/gui/src/components/dashboard/cache-ring.jsx +2 -2
- package/node_modules/@groove-dev/gui/src/components/dashboard/token-chart.jsx +2 -2
- package/node_modules/@groove-dev/gui/src/components/editor/terminal.jsx +1 -1
- package/node_modules/@groove-dev/gui/src/components/layout/welcome-splash.jsx +8 -1
- package/node_modules/@groove-dev/gui/src/components/network/activity-chart.jsx +4 -4
- package/node_modules/@groove-dev/gui/src/components/network/performance-dashboard.jsx +1 -1
- package/node_modules/@groove-dev/gui/src/components/settings/quick-connect.jsx +18 -6
- package/node_modules/@groove-dev/gui/src/components/settings/ssh-wizard.jsx +122 -17
- package/node_modules/@groove-dev/gui/src/stores/groove.js +9 -1
- package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +69 -38
- package/node_modules/@groove-dev/gui/src/views/memory.jsx +121 -49
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/journalist.js +61 -16
- package/packages/daemon/src/process.js +130 -2
- package/packages/daemon/src/rotator.js +2 -1
- package/packages/daemon/src/routes/files.js +28 -6
- package/packages/daemon/src/tunnel-manager.js +89 -71
- package/packages/gui/dist/assets/index-Bij9o_dc.js +1020 -0
- package/packages/gui/dist/assets/index-Dzofq3wS.css +1 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -2
- package/packages/gui/src/app.css +2 -2
- package/packages/gui/src/components/agents/agent-feed.jsx +8 -8
- package/packages/gui/src/components/agents/diff-viewer.jsx +2 -2
- package/packages/gui/src/components/agents/workspace-mode.jsx +11 -2
- package/packages/gui/src/components/dashboard/cache-ring.jsx +2 -2
- package/packages/gui/src/components/dashboard/token-chart.jsx +2 -2
- package/packages/gui/src/components/editor/terminal.jsx +1 -1
- package/packages/gui/src/components/layout/welcome-splash.jsx +8 -1
- package/packages/gui/src/components/network/activity-chart.jsx +4 -4
- package/packages/gui/src/components/network/performance-dashboard.jsx +1 -1
- package/packages/gui/src/components/settings/quick-connect.jsx +18 -6
- package/packages/gui/src/components/settings/ssh-wizard.jsx +122 -17
- package/packages/gui/src/stores/groove.js +9 -1
- package/packages/gui/src/stores/slices/agents-slice.js +69 -38
- package/packages/gui/src/views/memory.jsx +121 -49
- package/ssh/error.png +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/CHANGELOG.md +0 -2
- package/node_modules/@fontsource-variable/jetbrains-mono/LICENSE +0 -93
- package/node_modules/@fontsource-variable/jetbrains-mono/README.md +0 -48
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-cyrillic-ext-wght-italic.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-cyrillic-ext-wght-normal.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-cyrillic-wght-italic.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-cyrillic-wght-normal.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-greek-wght-italic.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-greek-wght-normal.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-latin-ext-wght-italic.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-latin-ext-wght-normal.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-latin-wght-italic.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-latin-wght-normal.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-vietnamese-wght-italic.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-vietnamese-wght-normal.woff2 +0 -0
- package/node_modules/@fontsource-variable/jetbrains-mono/index.css +0 -59
- package/node_modules/@fontsource-variable/jetbrains-mono/metadata.json +0 -29
- package/node_modules/@fontsource-variable/jetbrains-mono/package.json +0 -47
- package/node_modules/@fontsource-variable/jetbrains-mono/scss/metadata.scss +0 -46
- package/node_modules/@fontsource-variable/jetbrains-mono/scss/mixins.scss +0 -193
- package/node_modules/@fontsource-variable/jetbrains-mono/unicode.json +0 -8
- package/node_modules/@fontsource-variable/jetbrains-mono/wght-italic.css +0 -59
- package/node_modules/@fontsource-variable/jetbrains-mono/wght.css +0 -59
- package/node_modules/@groove-dev/gui/dist/assets/index-COQYX12F.js +0 -1015
- package/node_modules/@groove-dev/gui/dist/assets/index-Diw6wDPU.css +0 -1
- package/node_modules/@groove-dev/gui/dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/node_modules/@groove-dev/gui/dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/node_modules/@groove-dev/gui/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/node_modules/@groove-dev/gui/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/node_modules/@groove-dev/gui/dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/packages/gui/dist/assets/index-COQYX12F.js +0 -1015
- package/packages/gui/dist/assets/index-Diw6wDPU.css +0 -1
- package/packages/gui/dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/packages/gui/dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/packages/gui/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/packages/gui/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/packages/gui/dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
|
@@ -7,7 +7,7 @@ import { useGrooveStore } from '../../stores/groove';
|
|
|
7
7
|
import { cn } from '../../lib/cn';
|
|
8
8
|
import {
|
|
9
9
|
FolderSearch, Check, X, AlertTriangle, Loader2,
|
|
10
|
-
ExternalLink, Server, KeyRound, Settings, Plug,
|
|
10
|
+
ExternalLink, Server, KeyRound, Settings, Plug, Terminal, Copy, RefreshCw,
|
|
11
11
|
} from 'lucide-react';
|
|
12
12
|
|
|
13
13
|
const STEPS = [
|
|
@@ -110,6 +110,111 @@ function InfoCard({ icon: Icon, title, iconColor, children }) {
|
|
|
110
110
|
);
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
function CopyableCommand({ command }) {
|
|
114
|
+
const [copied, setCopied] = useState(false);
|
|
115
|
+
return (
|
|
116
|
+
<div className="flex items-center gap-1.5 group">
|
|
117
|
+
<code className="flex-1 text-2xs font-mono text-text-1 bg-surface-0 px-2.5 py-1.5 rounded-md border border-border-subtle truncate">
|
|
118
|
+
{command}
|
|
119
|
+
</code>
|
|
120
|
+
<button
|
|
121
|
+
onClick={() => { navigator.clipboard.writeText(command); setCopied(true); setTimeout(() => setCopied(false), 1500); }}
|
|
122
|
+
className="p-1.5 text-text-4 hover:text-text-1 cursor-pointer transition-colors flex-shrink-0"
|
|
123
|
+
title="Copy"
|
|
124
|
+
>
|
|
125
|
+
{copied ? <Check size={11} className="text-success" /> : <Copy size={11} />}
|
|
126
|
+
</button>
|
|
127
|
+
</div>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function SetupStatus({ testResult, user, host, sshPort, testLoading, onRetest }) {
|
|
132
|
+
const allGood = testResult.nodeInstalled && testResult.grooveInstalled && testResult.daemonRunning;
|
|
133
|
+
const needsNode = !testResult.nodeInstalled;
|
|
134
|
+
const needsGroove = testResult.nodeInstalled && !testResult.grooveInstalled;
|
|
135
|
+
const needsDaemon = testResult.grooveInstalled && !testResult.daemonRunning;
|
|
136
|
+
const sshTarget = `${user}@${host}${sshPort !== 22 ? ` -p ${sshPort}` : ''}`;
|
|
137
|
+
|
|
138
|
+
if (allGood) {
|
|
139
|
+
return (
|
|
140
|
+
<InfoCard icon={Check} title="Ready to Connect" iconColor="bg-success/10 text-success">
|
|
141
|
+
<div className="space-y-2.5">
|
|
142
|
+
<div className="flex items-center gap-2 text-2xs font-sans">
|
|
143
|
+
<StatusDot status="running" size="sm" />
|
|
144
|
+
<span className="text-text-1">Node.js {testResult.nodeVersion}</span>
|
|
145
|
+
</div>
|
|
146
|
+
<div className="flex items-center gap-2 text-2xs font-sans">
|
|
147
|
+
<StatusDot status="running" size="sm" />
|
|
148
|
+
<span className="text-text-1">Groove Installed{testResult.remoteVersion ? ` (v${testResult.remoteVersion})` : ''}</span>
|
|
149
|
+
</div>
|
|
150
|
+
<div className="flex items-center gap-2 text-2xs font-sans">
|
|
151
|
+
<StatusDot status="running" size="sm" />
|
|
152
|
+
<span className="text-text-1">Daemon Running</span>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
</InfoCard>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<div className="rounded-xl border border-warning/25 bg-gradient-to-br from-warning/[0.04] to-transparent px-5 py-4">
|
|
161
|
+
<div className="flex items-center justify-between mb-3">
|
|
162
|
+
<div className="flex items-center gap-2.5">
|
|
163
|
+
<div className="w-7 h-7 rounded-lg bg-warning/10 flex items-center justify-center flex-shrink-0">
|
|
164
|
+
<Terminal size={13} className="text-warning" />
|
|
165
|
+
</div>
|
|
166
|
+
<span className="text-sm font-semibold text-text-0 font-sans">Remote Setup Required</span>
|
|
167
|
+
</div>
|
|
168
|
+
<button
|
|
169
|
+
onClick={onRetest}
|
|
170
|
+
disabled={testLoading}
|
|
171
|
+
className="flex items-center gap-1 text-2xs text-text-3 hover:text-text-1 font-sans cursor-pointer transition-colors disabled:opacity-50"
|
|
172
|
+
>
|
|
173
|
+
<RefreshCw size={10} className={testLoading ? 'animate-spin' : ''} />
|
|
174
|
+
Re-test
|
|
175
|
+
</button>
|
|
176
|
+
</div>
|
|
177
|
+
|
|
178
|
+
<div className="space-y-2.5 mb-3">
|
|
179
|
+
<div className="flex items-center gap-2 text-2xs font-sans">
|
|
180
|
+
<StatusDot status={testResult.reachable ? 'running' : 'crashed'} size="sm" />
|
|
181
|
+
<span className="text-text-1">Reachable</span>
|
|
182
|
+
</div>
|
|
183
|
+
<div className="flex items-center gap-2 text-2xs font-sans">
|
|
184
|
+
<StatusDot status={testResult.nodeInstalled ? 'running' : 'stopped'} size="sm" />
|
|
185
|
+
<span className="text-text-1">Node.js{testResult.nodeVersion ? ` ${testResult.nodeVersion}` : ''}</span>
|
|
186
|
+
</div>
|
|
187
|
+
<div className="flex items-center gap-2 text-2xs font-sans">
|
|
188
|
+
<StatusDot status={testResult.grooveInstalled ? 'running' : 'stopped'} size="sm" />
|
|
189
|
+
<span className="text-text-1">Groove{testResult.remoteVersion ? ` v${testResult.remoteVersion}` : ''}</span>
|
|
190
|
+
</div>
|
|
191
|
+
<div className="flex items-center gap-2 text-2xs font-sans">
|
|
192
|
+
<StatusDot status={testResult.daemonRunning ? 'running' : 'stopped'} size="sm" />
|
|
193
|
+
<span className="text-text-1">Daemon</span>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
<div className="border-t border-border-subtle pt-3 space-y-2">
|
|
198
|
+
<p className="text-2xs text-text-3 font-sans">SSH in and run{needsNode ? '' : needsGroove ? '' : ''}:</p>
|
|
199
|
+
<CopyableCommand command={`ssh ${sshTarget}`} />
|
|
200
|
+
{needsNode && (
|
|
201
|
+
<>
|
|
202
|
+
<CopyableCommand command='curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash' />
|
|
203
|
+
<CopyableCommand command="source ~/.bashrc && nvm install 20" />
|
|
204
|
+
</>
|
|
205
|
+
)}
|
|
206
|
+
{(needsNode || needsGroove) && (
|
|
207
|
+
<CopyableCommand command="npm i -g groove-dev" />
|
|
208
|
+
)}
|
|
209
|
+
{(needsNode || needsGroove || needsDaemon) && (
|
|
210
|
+
<CopyableCommand command="groove start" />
|
|
211
|
+
)}
|
|
212
|
+
<p className="text-2xs text-text-4 font-sans mt-1">Then click Re-test above.</p>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
113
218
|
export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
114
219
|
const remoteHomedir = useGrooveStore((s) => s.remoteHomedir);
|
|
115
220
|
const [step, setStep] = useState(0);
|
|
@@ -140,6 +245,13 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
140
245
|
setAutoConnect(server.autoConnect || false);
|
|
141
246
|
setCompletedSteps([0, 1]);
|
|
142
247
|
setStep(2);
|
|
248
|
+
setTestResult(null);
|
|
249
|
+
setTestLoading(true);
|
|
250
|
+
onTest().then((result) => {
|
|
251
|
+
setTestResult(result);
|
|
252
|
+
}).catch((err) => {
|
|
253
|
+
setTestResult({ error: err.message || 'Test failed' });
|
|
254
|
+
}).finally(() => setTestLoading(false));
|
|
143
255
|
} else {
|
|
144
256
|
setName('');
|
|
145
257
|
setHost('');
|
|
@@ -150,6 +262,7 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
150
262
|
setAutoConnect(false);
|
|
151
263
|
setCompletedSteps([]);
|
|
152
264
|
setStep(0);
|
|
265
|
+
setTestResult(null);
|
|
153
266
|
}
|
|
154
267
|
}, [server]);
|
|
155
268
|
|
|
@@ -402,22 +515,14 @@ export function SSHWizard({ server, onSave, onTest, onConnect, onCancel }) {
|
|
|
402
515
|
</FieldCard>
|
|
403
516
|
|
|
404
517
|
{testResult && !testResult.error ? (
|
|
405
|
-
<
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
<span className="text-text-1">Groove Installed</span>
|
|
414
|
-
</div>
|
|
415
|
-
<div className="flex items-center gap-2 text-2xs font-sans">
|
|
416
|
-
<StatusDot status={testResult.daemonRunning ? 'running' : 'stopped'} size="sm" />
|
|
417
|
-
<span className="text-text-1">Daemon Running</span>
|
|
418
|
-
</div>
|
|
419
|
-
</div>
|
|
420
|
-
</InfoCard>
|
|
518
|
+
<SetupStatus
|
|
519
|
+
testResult={testResult}
|
|
520
|
+
user={user}
|
|
521
|
+
host={host}
|
|
522
|
+
sshPort={sshPort}
|
|
523
|
+
testLoading={testLoading}
|
|
524
|
+
onRetest={handleTest}
|
|
525
|
+
/>
|
|
421
526
|
) : (
|
|
422
527
|
<InfoCard icon={Server} title={name || 'Server'}>
|
|
423
528
|
<div className="space-y-2 text-2xs font-sans">
|
|
@@ -198,7 +198,11 @@ export const useGrooveStore = create((set, get) => ({
|
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
200
|
for (const id of removed) delete timeline[id];
|
|
201
|
-
|
|
201
|
+
const updates = { agents, tokenTimeline: timeline, hydrated: true };
|
|
202
|
+
if (removed.length > 0 && st.detailPanel?.type === 'agent' && removed.includes(st.detailPanel.agentId)) {
|
|
203
|
+
updates.detailPanel = null;
|
|
204
|
+
}
|
|
205
|
+
set(updates);
|
|
202
206
|
break;
|
|
203
207
|
}
|
|
204
208
|
|
|
@@ -366,6 +370,10 @@ export const useGrooveStore = create((set, get) => ({
|
|
|
366
370
|
break;
|
|
367
371
|
}
|
|
368
372
|
|
|
373
|
+
case 'recommended-team:ready':
|
|
374
|
+
if (!get().recommendedTeam) get().checkRecommendedTeam();
|
|
375
|
+
break;
|
|
376
|
+
|
|
369
377
|
case 'phase2:spawned':
|
|
370
378
|
get().addToast('info', `QC agent ${msg.name} auto-spawned`, 'Auditing phase 1 work');
|
|
371
379
|
break;
|
|
@@ -169,10 +169,11 @@ export const createAgentsSlice = (set, get) => ({
|
|
|
169
169
|
return data;
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
// CLI agent: was stopped + resumed/rotated — transfer state to new agent ID
|
|
172
|
+
// CLI agent: was stopped + resumed/rotated — transfer state to new agent ID.
|
|
173
|
+
// Only transfer if the rotation:complete WebSocket handler hasn't already done it.
|
|
173
174
|
const newAgent = data;
|
|
174
175
|
for (const key of ['chatHistory', 'activityLog', 'tokenTimeline']) {
|
|
175
|
-
if (snapshot[key]?.length) {
|
|
176
|
+
if (snapshot[key]?.length && !get()[key]?.[newAgent.id]?.length) {
|
|
176
177
|
set((s) => ({ [key]: { ...s[key], [newAgent.id]: [...snapshot[key]] } }));
|
|
177
178
|
}
|
|
178
179
|
}
|
|
@@ -380,6 +381,13 @@ export const createAgentsSlice = (set, get) => ({
|
|
|
380
381
|
get().addChatMessage(agentId, 'system', text);
|
|
381
382
|
};
|
|
382
383
|
|
|
384
|
+
const startThinking = () => {
|
|
385
|
+
set((s) => ({ thinkingAgents: new Set([...s.thinkingAgents, agentId]) }));
|
|
386
|
+
};
|
|
387
|
+
const stopThinking = () => {
|
|
388
|
+
set((s) => { const next = new Set(s.thinkingAgents); next.delete(agentId); return { thinkingAgents: next }; });
|
|
389
|
+
};
|
|
390
|
+
|
|
383
391
|
try {
|
|
384
392
|
switch (command) {
|
|
385
393
|
case 'instruct': {
|
|
@@ -391,8 +399,11 @@ export const createAgentsSlice = (set, get) => ({
|
|
|
391
399
|
if (tags.length === 0) { addSystemMsg('Usage: save #tag your message here'); return true; }
|
|
392
400
|
const content = rest.replace(/#[\w/.-]+/g, '').trim();
|
|
393
401
|
if (!content) { addSystemMsg('Usage: save #tag your message here'); return true; }
|
|
394
|
-
|
|
395
|
-
|
|
402
|
+
startThinking();
|
|
403
|
+
try {
|
|
404
|
+
await get().saveKeeperItem(tags[0], content);
|
|
405
|
+
addSystemMsg(`Saved to #${tags[0]}`);
|
|
406
|
+
} finally { stopThinking(); }
|
|
396
407
|
return { passthrough: content };
|
|
397
408
|
}
|
|
398
409
|
|
|
@@ -400,36 +411,48 @@ export const createAgentsSlice = (set, get) => ({
|
|
|
400
411
|
if (tags.length === 0) { addSystemMsg('Usage: append #tag content to add'); return true; }
|
|
401
412
|
const content = rest.replace(/#[\w/.-]+/g, '').trim();
|
|
402
413
|
if (!content) { addSystemMsg('Usage: append #tag content to add'); return true; }
|
|
403
|
-
|
|
404
|
-
|
|
414
|
+
startThinking();
|
|
415
|
+
try {
|
|
416
|
+
await get().appendKeeperItem(tags[0], content);
|
|
417
|
+
addSystemMsg(`Appended to #${tags[0]}`);
|
|
418
|
+
} finally { stopThinking(); }
|
|
405
419
|
return { passthrough: content };
|
|
406
420
|
}
|
|
407
421
|
|
|
408
422
|
case 'update': {
|
|
409
423
|
if (tags.length === 0) { addSystemMsg('Usage: [update] #tag'); return true; }
|
|
410
424
|
get().addChatMessage(agentId, 'user', message, false);
|
|
411
|
-
|
|
412
|
-
|
|
425
|
+
startThinking();
|
|
426
|
+
try {
|
|
427
|
+
const existing = await get().getKeeperItem(tags[0]);
|
|
428
|
+
set({ keeperEditing: { tag: tags[0], content: existing?.content || '', isNew: !existing } });
|
|
429
|
+
} finally { stopThinking(); }
|
|
413
430
|
return true;
|
|
414
431
|
}
|
|
415
432
|
|
|
416
433
|
case 'delete': {
|
|
417
434
|
if (tags.length === 0) { addSystemMsg('Usage: [delete] #tag'); return true; }
|
|
418
435
|
get().addChatMessage(agentId, 'user', message, false);
|
|
419
|
-
|
|
420
|
-
|
|
436
|
+
startThinking();
|
|
437
|
+
try {
|
|
438
|
+
await get().deleteKeeperItem(tags[0]);
|
|
439
|
+
addSystemMsg(`Deleted #${tags[0]}`);
|
|
440
|
+
} finally { stopThinking(); }
|
|
421
441
|
return true;
|
|
422
442
|
}
|
|
423
443
|
|
|
424
444
|
case 'view': {
|
|
425
445
|
if (tags.length === 0) { addSystemMsg('Usage: [view] #tag'); return true; }
|
|
426
446
|
get().addChatMessage(agentId, 'user', message, false);
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
447
|
+
startThinking();
|
|
448
|
+
try {
|
|
449
|
+
const item = await get().getKeeperItem(tags[0]);
|
|
450
|
+
if (item) {
|
|
451
|
+
set({ keeperEditing: { tag: tags[0], content: item.content, isNew: false, readOnly: true } });
|
|
452
|
+
} else {
|
|
453
|
+
addSystemMsg(`#${tags[0]} not found`);
|
|
454
|
+
}
|
|
455
|
+
} finally { stopThinking(); }
|
|
433
456
|
return true;
|
|
434
457
|
}
|
|
435
458
|
|
|
@@ -437,21 +460,22 @@ export const createAgentsSlice = (set, get) => ({
|
|
|
437
460
|
if (tags.length === 0) { addSystemMsg('Usage: [read] #tag1 #tag2 ...'); return true; }
|
|
438
461
|
const userText = rest.replace(/#[\w/.-]+/g, '').trim();
|
|
439
462
|
get().addChatMessage(agentId, 'user', message, false);
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
463
|
+
startThinking();
|
|
464
|
+
try {
|
|
465
|
+
const readBrief = await api.post('/keeper/pull', { tags });
|
|
466
|
+
if (readBrief?.brief) {
|
|
467
|
+
const memoryBlock = `\n\n---\nContext from memories (${tags.map(t => '#' + t).join(', ')}):\n\n${readBrief.brief}`;
|
|
468
|
+
await api.post(`/agents/${encodeURIComponent(agentId)}/instruct`, {
|
|
469
|
+
message: userText ? `${userText}${memoryBlock}` : `Here is context from my tagged memories:\n\n${readBrief.brief}`,
|
|
470
|
+
});
|
|
471
|
+
addSystemMsg(`Sent ${tags.map(t => '#' + t).join(', ')} to agent`);
|
|
472
|
+
} else {
|
|
473
|
+
addSystemMsg(`No memories found for ${tags.map(t => '#' + t).join(', ')}`);
|
|
474
|
+
if (userText) {
|
|
475
|
+
await api.post(`/agents/${encodeURIComponent(agentId)}/instruct`, { message: userText });
|
|
476
|
+
}
|
|
453
477
|
}
|
|
454
|
-
}
|
|
478
|
+
} finally { stopThinking(); }
|
|
455
479
|
return true;
|
|
456
480
|
}
|
|
457
481
|
|
|
@@ -459,12 +483,15 @@ export const createAgentsSlice = (set, get) => ({
|
|
|
459
483
|
if (tags.length === 0) { addSystemMsg('Usage: [doc] #tag'); return true; }
|
|
460
484
|
get().addChatMessage(agentId, 'user', message, false);
|
|
461
485
|
addSystemMsg(`Generating doc for #${tags[0]}...`);
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
486
|
+
startThinking();
|
|
487
|
+
try {
|
|
488
|
+
const history = get().chatHistory[agentId] || [];
|
|
489
|
+
const result = await api.post('/keeper/doc', { tag: tags[0], chatHistory: history, agentId });
|
|
490
|
+
if (result?.content) {
|
|
491
|
+
addSystemMsg(`Doc #${tags[0]} generated (${result.size}B)`);
|
|
492
|
+
set({ keeperEditing: { tag: tags[0], content: result.content, isNew: false } });
|
|
493
|
+
}
|
|
494
|
+
} finally { stopThinking(); }
|
|
468
495
|
return true;
|
|
469
496
|
}
|
|
470
497
|
|
|
@@ -473,12 +500,16 @@ export const createAgentsSlice = (set, get) => ({
|
|
|
473
500
|
if (!linkMatch || tags.length === 0) { addSystemMsg('Usage: [link] #tag path/to/doc'); return true; }
|
|
474
501
|
const docPath = linkMatch[2].trim();
|
|
475
502
|
get().addChatMessage(agentId, 'user', message, false);
|
|
476
|
-
|
|
477
|
-
|
|
503
|
+
startThinking();
|
|
504
|
+
try {
|
|
505
|
+
await api.post('/keeper/link', { tag: tags[0], docPath });
|
|
506
|
+
addSystemMsg(`Linked #${tags[0]} → ${docPath}`);
|
|
507
|
+
} finally { stopThinking(); }
|
|
478
508
|
return true;
|
|
479
509
|
}
|
|
480
510
|
}
|
|
481
511
|
} catch (err) {
|
|
512
|
+
stopThinking();
|
|
482
513
|
addSystemMsg(`Keeper error: ${err.message}`);
|
|
483
514
|
return true;
|
|
484
515
|
}
|