total-recall-brain 3.6.3 → 3.6.4
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/frontend/src/api.ts
CHANGED
|
@@ -530,6 +530,13 @@ export async function triggerDream(): Promise<{ success: boolean; status: string
|
|
|
530
530
|
return res.json()
|
|
531
531
|
}
|
|
532
532
|
|
|
533
|
+
export async function runAgentDiagnostics(): Promise<{ success: boolean; output: string }> {
|
|
534
|
+
const res = await apiFetch(`${API_BASE}/api/diagnostics/agents`, { method: 'POST' })
|
|
535
|
+
if (!res.ok) throw new Error(`Diagnostics API error: ${res.status}`)
|
|
536
|
+
return res.json()
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
|
|
533
540
|
export async function fetchGraph(): Promise<{ nodes: MemoryNode[]; routes: unknown[] }> {
|
|
534
541
|
const res = await apiFetch(`${API_BASE}/api/graph`)
|
|
535
542
|
if (!res.ok) throw new Error(`Graph API error: ${res.status}`)
|
|
@@ -166,7 +166,7 @@ function CollabDashboard({ token, username, onLogout, onSelectSandbox }: { token
|
|
|
166
166
|
<p style={{ fontSize: '12px', color: 'var(--text-secondary)' }}>Share annotations and real-time page chat rooms</p>
|
|
167
167
|
</div>
|
|
168
168
|
<div style={{ display: 'flex', gap: '10px' }}>
|
|
169
|
-
<button className="btn btn-purple" onClick={onSelectSandbox}>🌐 Open
|
|
169
|
+
<button className="btn btn-purple" onClick={onSelectSandbox}>🌐 Open Browse Workspace</button>
|
|
170
170
|
<button className="btn btn-ghost" onClick={onLogout} style={{ color: '#f87171' }}>Logout</button>
|
|
171
171
|
</div>
|
|
172
172
|
</div>
|
|
@@ -219,7 +219,7 @@ function CollabDashboard({ token, username, onLogout, onSelectSandbox }: { token
|
|
|
219
219
|
function CollabSandbox({ token, username, onBack }: { token: string, username: string, onBack: () => void }) {
|
|
220
220
|
const [groups, setGroups] = useState<CollabGroup[]>([]);
|
|
221
221
|
const [selectedGroup, setSelectedGroup] = useState<CollabGroup | null>(null);
|
|
222
|
-
const [
|
|
222
|
+
const [activeBrowseUrl, setActiveBrowseUrl] = useState('https://news.ycombinator.com');
|
|
223
223
|
const [activeUrl, setActiveUrl] = useState('https://news.ycombinator.com');
|
|
224
224
|
const [annotations, setAnnotations] = useState<Annotation[]>([]);
|
|
225
225
|
const [noteText, setNoteText] = useState('');
|
|
@@ -313,9 +313,9 @@ function CollabSandbox({ token, username, onBack }: { token: string, username: s
|
|
|
313
313
|
|
|
314
314
|
const handleUrlSubmit = (e: React.FormEvent) => {
|
|
315
315
|
e.preventDefault();
|
|
316
|
-
if (!
|
|
316
|
+
if (!activeBrowseUrl.trim()) return;
|
|
317
317
|
setChatMessages([]); setSystemLogs([]); setActiveUsers([]);
|
|
318
|
-
setActiveUrl(
|
|
318
|
+
setActiveUrl(activeBrowseUrl);
|
|
319
319
|
};
|
|
320
320
|
|
|
321
321
|
const handleAddAnnotation = async (e: React.FormEvent) => {
|
|
@@ -348,14 +348,14 @@ function CollabSandbox({ token, username, onBack }: { token: string, username: s
|
|
|
348
348
|
<div style={{ display: 'flex', gap: '16px', alignItems: 'center', justifyContent: 'space-between', background: 'rgba(255,255,255,0.02)', padding: '12px 20px', borderRadius: '8px', border: '1px solid var(--border)', flexWrap: 'wrap' }}>
|
|
349
349
|
<button className="btn btn-ghost" onClick={onBack}>← Back to Workspaces</button>
|
|
350
350
|
<form onSubmit={handleUrlSubmit} style={{ display: 'flex', gap: '10px', flex: '1', minWidth: '250px' }}>
|
|
351
|
-
<input type="text" value={
|
|
352
|
-
<button type="submit" className="btn btn-purple">
|
|
351
|
+
<input type="text" value={activeBrowseUrl} onChange={e => setActiveBrowseUrl(e.target.value)} style={{ background: 'rgba(0,0,0,0.2)', border: '1px solid var(--border)', color: '#fff', padding: '6px 12px', borderRadius: '6px', flex: '1', fontFamily: 'monospace' }} />
|
|
352
|
+
<button type="submit" className="btn btn-purple">Connect URL</button>
|
|
353
353
|
</form>
|
|
354
354
|
<div style={{ fontSize: '13px', color: wsConnected ? '#34d399' : '#f87171' }}>● {wsConnected ? 'Connected' : 'Disconnected'}</div>
|
|
355
355
|
</div>
|
|
356
356
|
|
|
357
357
|
<div style={{ fontSize: '13px', color: 'var(--text-secondary)' }}>
|
|
358
|
-
|
|
358
|
+
Active browse context URL: <strong style={{ color: 'var(--purple-primary)', fontFamily: 'monospace' }}>{activeUrl}</strong>
|
|
359
359
|
</div>
|
|
360
360
|
|
|
361
361
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 340px', gap: '20px', height: '500px' }}>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, useEffect, useRef } from 'react';
|
|
2
|
-
import { fetchHealth, fetchLogs } from '../api';
|
|
2
|
+
import { fetchHealth, fetchLogs, runAgentDiagnostics } from '../api';
|
|
3
3
|
import type { HealthData } from '../types';
|
|
4
4
|
|
|
5
5
|
export default function DeploymentsPage() {
|
|
@@ -9,9 +9,9 @@ export default function DeploymentsPage() {
|
|
|
9
9
|
const [error, setError] = useState<string | null>(null);
|
|
10
10
|
const [success, setSuccess] = useState<string | null>(null);
|
|
11
11
|
|
|
12
|
-
//
|
|
13
|
-
const [
|
|
14
|
-
const [
|
|
12
|
+
// CLI Agent Diagnostics state
|
|
13
|
+
const [runningDiagnostics, setRunningDiagnostics] = useState(false);
|
|
14
|
+
const [diagnosticLogs, setDiagnosticLogs] = useState<string | null>(null);
|
|
15
15
|
|
|
16
16
|
const consoleEndRef = useRef<HTMLDivElement>(null);
|
|
17
17
|
|
|
@@ -44,29 +44,36 @@ export default function DeploymentsPage() {
|
|
|
44
44
|
}
|
|
45
45
|
}, [logs]);
|
|
46
46
|
|
|
47
|
-
const
|
|
47
|
+
const handleRunDiagnostics = async (e: React.FormEvent) => {
|
|
48
48
|
e.preventDefault();
|
|
49
|
-
|
|
49
|
+
setRunningDiagnostics(true);
|
|
50
50
|
setError(null);
|
|
51
51
|
setSuccess(null);
|
|
52
|
+
setDiagnosticLogs(null);
|
|
52
53
|
try {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
const res = await runAgentDiagnostics();
|
|
55
|
+
setDiagnosticLogs(res.output);
|
|
56
|
+
if (res.success) {
|
|
57
|
+
setSuccess('CLI Agent diagnostics completed successfully.');
|
|
58
|
+
} else {
|
|
59
|
+
setError('CLI Agent diagnostics finished with warnings or missing binaries.');
|
|
60
|
+
}
|
|
61
|
+
void fetchSystemData();
|
|
56
62
|
} catch (err: unknown) {
|
|
57
|
-
setError((err as Error).message || '
|
|
63
|
+
setError((err as Error).message || 'Diagnostics execution failed.');
|
|
58
64
|
} finally {
|
|
59
|
-
|
|
65
|
+
setRunningDiagnostics(false);
|
|
60
66
|
}
|
|
61
67
|
};
|
|
62
68
|
|
|
63
|
-
const
|
|
64
|
-
{ id: '
|
|
65
|
-
{ id: '
|
|
66
|
-
{ id: '
|
|
67
|
-
{ id: '
|
|
69
|
+
const AGENTS_LIST = [
|
|
70
|
+
{ id: 'antigravity', name: 'Antigravity (Gemini SDK)', desc: 'Primary core developer agent' },
|
|
71
|
+
{ id: 'gemini', name: 'Gemini CLI', desc: 'Direct Gemini assistant binary' },
|
|
72
|
+
{ id: 'claude', name: 'Claude Code', desc: 'Anthropic developer CLI wrapper' },
|
|
73
|
+
{ id: 'codex', name: 'Codex CLI', desc: 'OpenAI agent binary integration' }
|
|
68
74
|
];
|
|
69
75
|
|
|
76
|
+
|
|
70
77
|
return (
|
|
71
78
|
<div className="page" style={{ display: 'flex', flexDirection: 'column', height: '100%', overflowY: 'auto' }}>
|
|
72
79
|
<div className="page-header" style={{ marginBottom: 24 }}>
|
|
@@ -146,7 +153,7 @@ export default function DeploymentsPage() {
|
|
|
146
153
|
|
|
147
154
|
</div>
|
|
148
155
|
|
|
149
|
-
|
|
156
|
+
{/* CLI Agents Catalog & Diagnostics */}
|
|
150
157
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(360px, 1fr))', gap: 24 }}>
|
|
151
158
|
|
|
152
159
|
{/* Catalog */}
|
|
@@ -154,31 +161,31 @@ export default function DeploymentsPage() {
|
|
|
154
161
|
<div style={{ display: 'flex', alignItems: 'center', gap: 10, borderBottom: '1px solid var(--border)', paddingBottom: 12 }}>
|
|
155
162
|
<span style={{ fontSize: 20 }}>🧠</span>
|
|
156
163
|
<div>
|
|
157
|
-
<h3 style={{ fontSize: 14, fontWeight: 600 }}>
|
|
158
|
-
<p style={{ fontSize: 11, color: 'var(--text-tertiary)' }}>
|
|
164
|
+
<h3 style={{ fontSize: 14, fontWeight: 600 }}>CLI Reasoning Agents</h3>
|
|
165
|
+
<p style={{ fontSize: 11, color: 'var(--text-tertiary)' }}>Headless CLI reasoning agents configured on system</p>
|
|
159
166
|
</div>
|
|
160
167
|
</div>
|
|
161
168
|
|
|
162
169
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
|
163
|
-
{
|
|
164
|
-
const
|
|
170
|
+
{AGENTS_LIST.map((a) => {
|
|
171
|
+
const activeAgent = health?.cli_agents?.includes(a.id);
|
|
165
172
|
return (
|
|
166
|
-
<div key={
|
|
173
|
+
<div key={a.id} style={{ display: 'flex', alignItems: 'center', gap: 12, background: 'var(--bg-tertiary)', padding: 12, borderRadius: 8, border: '1px solid var(--border)' }}>
|
|
167
174
|
<div style={{ flex: 1 }}>
|
|
168
175
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
169
|
-
<span style={{ fontSize: 12, fontWeight: 600, color: 'var(--text-primary)' }}>{
|
|
176
|
+
<span style={{ fontSize: 12, fontWeight: 600, color: 'var(--text-primary)' }}>{a.name}</span>
|
|
170
177
|
<span className="badge" style={{
|
|
171
178
|
fontSize: 9,
|
|
172
179
|
padding: '2px 6px',
|
|
173
|
-
background:
|
|
174
|
-
color:
|
|
175
|
-
border:
|
|
180
|
+
background: activeAgent ? 'rgba(16, 185, 129, 0.1)' : 'rgba(239, 68, 68, 0.1)',
|
|
181
|
+
color: activeAgent ? '#10b981' : '#ef4444',
|
|
182
|
+
border: activeAgent ? '1px solid rgba(16, 185, 129, 0.2)' : '1px solid rgba(239, 68, 68, 0.2)'
|
|
176
183
|
}}>
|
|
177
|
-
{
|
|
184
|
+
{activeAgent ? 'available' : 'missing'}
|
|
178
185
|
</span>
|
|
179
186
|
</div>
|
|
180
|
-
<div style={{ fontSize: 10, color: 'var(--text-secondary)', marginTop: 2 }}>{
|
|
181
|
-
<div style={{ fontSize: 9, color: 'var(--text-tertiary)', marginTop: 4 }}>ID: {
|
|
187
|
+
<div style={{ fontSize: 10, color: 'var(--text-secondary)', marginTop: 2 }}>{a.desc}</div>
|
|
188
|
+
<div style={{ fontSize: 9, color: 'var(--text-tertiary)', marginTop: 4 }}>Registry ID: {a.id}</div>
|
|
182
189
|
</div>
|
|
183
190
|
</div>
|
|
184
191
|
);
|
|
@@ -186,42 +193,24 @@ export default function DeploymentsPage() {
|
|
|
186
193
|
</div>
|
|
187
194
|
</div>
|
|
188
195
|
|
|
189
|
-
{/*
|
|
196
|
+
{/* Diagnostics Form */}
|
|
190
197
|
<div className="card" style={{ padding: 24, background: 'rgba(18, 18, 26, 0.6)', backdropFilter: 'blur(8px)', border: '1px solid var(--border)', display: 'flex', flexDirection: 'column', gap: 20 }}>
|
|
191
198
|
<div style={{ display: 'flex', alignItems: 'center', gap: 10, borderBottom: '1px solid var(--border)', paddingBottom: 12 }}>
|
|
192
199
|
<span style={{ fontSize: 20 }}>📡</span>
|
|
193
200
|
<div>
|
|
194
|
-
<h3 style={{ fontSize: 14, fontWeight: 600 }}>
|
|
195
|
-
<p style={{ fontSize: 11, color: 'var(--text-tertiary)' }}>Trigger
|
|
201
|
+
<h3 style={{ fontSize: 14, fontWeight: 600 }}>CLI Agent Diagnostics</h3>
|
|
202
|
+
<p style={{ fontSize: 11, color: 'var(--text-tertiary)' }}>Trigger active paths check and verify registered agents</p>
|
|
196
203
|
</div>
|
|
197
204
|
</div>
|
|
198
205
|
|
|
199
|
-
<
|
|
200
|
-
<
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
id="model_pull"
|
|
204
|
-
value={modelToPull}
|
|
205
|
-
onChange={(e) => setModelToPull(e.target.value)}
|
|
206
|
-
style={{
|
|
207
|
-
background: 'var(--bg-tertiary)',
|
|
208
|
-
color: 'var(--text-primary)',
|
|
209
|
-
border: '1px solid var(--border)',
|
|
210
|
-
padding: '8px 12px',
|
|
211
|
-
borderRadius: 6,
|
|
212
|
-
outline: 'none',
|
|
213
|
-
fontSize: 13
|
|
214
|
-
}}
|
|
215
|
-
>
|
|
216
|
-
<option value="gemma4:26b">Gemma 4 (26B Parameter) — 15.6 GB</option>
|
|
217
|
-
<option value="gemma5:32b">Gemma 5 Pro (32B Parameter) — 19.2 GB</option>
|
|
218
|
-
<option value="llama3:70b">Llama 3 (70B Parameter) — 40 GB</option>
|
|
219
|
-
</select>
|
|
220
|
-
</div>
|
|
206
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
|
207
|
+
<p style={{ fontSize: 12, lineHeight: 1.5, color: 'var(--text-secondary)' }}>
|
|
208
|
+
This executes a diagnostic check on registered reasoning agents (equivalent to running <code>npx total-recall upgrade --agents</code> in the background) to audit paths and verify binaries.
|
|
209
|
+
</p>
|
|
221
210
|
|
|
222
211
|
<button
|
|
223
|
-
|
|
224
|
-
disabled={
|
|
212
|
+
onClick={handleRunDiagnostics}
|
|
213
|
+
disabled={runningDiagnostics}
|
|
225
214
|
style={{
|
|
226
215
|
background: 'linear-gradient(135deg, var(--accent), var(--accent-hover))',
|
|
227
216
|
color: '#fff',
|
|
@@ -230,12 +219,32 @@ export default function DeploymentsPage() {
|
|
|
230
219
|
fontWeight: 500,
|
|
231
220
|
border: 'none',
|
|
232
221
|
marginTop: 8,
|
|
233
|
-
cursor:
|
|
222
|
+
cursor: runningDiagnostics ? 'not-allowed' : 'pointer'
|
|
234
223
|
}}
|
|
235
224
|
>
|
|
236
|
-
{
|
|
225
|
+
{runningDiagnostics ? '⏳ Running Audit...' : '🚀 Run Diagnostics Audit'}
|
|
237
226
|
</button>
|
|
238
|
-
</
|
|
227
|
+
</div>
|
|
228
|
+
|
|
229
|
+
{diagnosticLogs && (
|
|
230
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 10 }}>
|
|
231
|
+
<span style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)' }}>Diagnostics Console Output:</span>
|
|
232
|
+
<pre style={{
|
|
233
|
+
background: '#07070a',
|
|
234
|
+
border: '1px solid var(--border)',
|
|
235
|
+
padding: 10,
|
|
236
|
+
borderRadius: 6,
|
|
237
|
+
fontFamily: 'var(--font-mono)',
|
|
238
|
+
fontSize: 11,
|
|
239
|
+
color: '#e6edf3',
|
|
240
|
+
whiteSpace: 'pre-wrap',
|
|
241
|
+
maxHeight: 150,
|
|
242
|
+
overflowY: 'auto'
|
|
243
|
+
}}>
|
|
244
|
+
{diagnosticLogs}
|
|
245
|
+
</pre>
|
|
246
|
+
</div>
|
|
247
|
+
)}
|
|
239
248
|
</div>
|
|
240
249
|
|
|
241
250
|
</div>
|
package/package.json
CHANGED
package/src/server/rest.mjs
CHANGED
|
@@ -468,6 +468,25 @@ router.get('/api/vault/status', requireAuth, requireScope('memory:read'), async
|
|
|
468
468
|
}
|
|
469
469
|
});
|
|
470
470
|
|
|
471
|
+
/**
|
|
472
|
+
* POST /api/diagnostics/agents
|
|
473
|
+
* Run `upgrade --agents` diagnostics checks and return the console text output.
|
|
474
|
+
*/
|
|
475
|
+
router.post('/api/diagnostics/agents', requireAuth, requireScope('health:read'), async (req, res) => {
|
|
476
|
+
try {
|
|
477
|
+
const result = spawnSync('node', [path.join(ROOT, 'bin', 'total-recall.mjs'), 'upgrade', '--agents'], {
|
|
478
|
+
encoding: 'utf8',
|
|
479
|
+
cwd: ROOT,
|
|
480
|
+
env: { ...process.env }
|
|
481
|
+
});
|
|
482
|
+
const output = (result.stdout || '') + (result.stderr || '');
|
|
483
|
+
res.json({ success: result.status === 0, output });
|
|
484
|
+
} catch (err) {
|
|
485
|
+
serverError(res, err);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
|
|
471
490
|
// ─── Keys ─────────── (moved to ./routes/keys.mjs)
|
|
472
491
|
// ─── Sessions ─────── (moved to ./routes/sessions.mjs)
|
|
473
492
|
// ─── Sandbox ──────────────────────────────────────────────────────────────────
|