@geminilight/mindos 0.5.36 → 0.5.37
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/app/app/globals.css
CHANGED
|
@@ -75,7 +75,7 @@ body {
|
|
|
75
75
|
--ring: var(--amber);
|
|
76
76
|
--radius: 0.5rem;
|
|
77
77
|
--amber: #c8873a;
|
|
78
|
-
--amber-dim: rgba(200, 135, 58, 0.
|
|
78
|
+
--amber-dim: rgba(200, 135, 58, 0.18);
|
|
79
79
|
--amber-subtle: rgba(200, 135, 30, 0.08);
|
|
80
80
|
--amber-foreground: #131210;
|
|
81
81
|
--success: #7aad80;
|
|
@@ -110,7 +110,7 @@ body {
|
|
|
110
110
|
--input: rgba(232, 228, 220, 0.1);
|
|
111
111
|
--ring: var(--amber);
|
|
112
112
|
--amber: #d4954a;
|
|
113
|
-
--amber-dim: rgba(212, 149, 74, 0.
|
|
113
|
+
--amber-dim: rgba(212, 149, 74, 0.20);
|
|
114
114
|
--amber-subtle: rgba(212, 149, 74, 0.10);
|
|
115
115
|
--amber-foreground: #131210;
|
|
116
116
|
--success: #7aad80;
|
|
@@ -300,6 +300,10 @@ body {
|
|
|
300
300
|
backdrop-filter: blur(8px);
|
|
301
301
|
-webkit-backdrop-filter: blur(8px);
|
|
302
302
|
}
|
|
303
|
+
.dark .modal-backdrop {
|
|
304
|
+
background: rgba(0, 0, 0, 0.65);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
303
307
|
|
|
304
308
|
/* Micro type scale: text-2xs = 10px (between nothing and text-xs 12px) */
|
|
305
309
|
@layer utilities {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { AlertCircle } from 'lucide-react';
|
|
3
4
|
import AskContent from '@/components/ask/AskContent';
|
|
5
|
+
import ErrorBoundary from '@/components/ErrorBoundary';
|
|
4
6
|
import { useResizeDrag } from '@/hooks/useResizeDrag';
|
|
5
7
|
|
|
6
8
|
const DEFAULT_WIDTH = 380;
|
|
@@ -47,16 +49,29 @@ export default function RightAskPanel({
|
|
|
47
49
|
role="complementary"
|
|
48
50
|
aria-label="MindOS Agent panel"
|
|
49
51
|
>
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
<ErrorBoundary fallback={
|
|
53
|
+
<div className="flex flex-col items-center justify-center h-full gap-3 px-6 text-center">
|
|
54
|
+
<AlertCircle size={20} className="text-muted-foreground" />
|
|
55
|
+
<p className="text-sm text-muted-foreground">AI panel encountered an error.</p>
|
|
56
|
+
<button
|
|
57
|
+
onClick={() => window.location.reload()}
|
|
58
|
+
className="text-xs px-3 py-1.5 rounded-lg border border-border text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
|
|
59
|
+
>
|
|
60
|
+
Reload page
|
|
61
|
+
</button>
|
|
62
|
+
</div>
|
|
63
|
+
}>
|
|
64
|
+
<AskContent
|
|
65
|
+
visible={open}
|
|
66
|
+
variant="panel"
|
|
67
|
+
currentFile={open ? currentFile : undefined}
|
|
68
|
+
initialMessage={initialMessage}
|
|
69
|
+
onFirstMessage={onFirstMessage}
|
|
70
|
+
onClose={onClose}
|
|
71
|
+
askMode={askMode}
|
|
72
|
+
onModeSwitch={onModeSwitch}
|
|
73
|
+
/>
|
|
74
|
+
</ErrorBoundary>
|
|
60
75
|
|
|
61
76
|
{/* Drag resize handle — LEFT edge */}
|
|
62
77
|
<div
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useState, useEffect, useCallback } from 'react';
|
|
3
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
4
4
|
import { useRouter } from 'next/navigation';
|
|
5
5
|
import { getAllRenderers, isRendererEnabled, setRendererEnabled, loadDisabledState } from '@/lib/renderers/registry';
|
|
6
6
|
import { Toggle } from '../settings/Primitives';
|
|
@@ -27,25 +27,25 @@ export default function PluginsPanel({ active, maximized, onMaximize }: PluginsP
|
|
|
27
27
|
setMounted(true);
|
|
28
28
|
}, []);
|
|
29
29
|
|
|
30
|
-
// Check which entry files exist
|
|
30
|
+
// Check which entry files exist — fetch once on mount, cache result
|
|
31
|
+
const fetchedRef = useRef(false);
|
|
31
32
|
useEffect(() => {
|
|
32
|
-
if (!mounted ||
|
|
33
|
+
if (!mounted || fetchedRef.current) return;
|
|
34
|
+
fetchedRef.current = true;
|
|
33
35
|
const entryPaths = getAllRenderers()
|
|
34
36
|
.map(r => r.entryPath)
|
|
35
37
|
.filter((p): p is string => !!p);
|
|
36
38
|
if (entryPaths.length === 0) return;
|
|
37
39
|
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
}, [mounted, active]);
|
|
40
|
+
// Single request: fetch all file paths and check which entry paths exist
|
|
41
|
+
fetch('/api/files')
|
|
42
|
+
.then(r => r.ok ? r.json() : [])
|
|
43
|
+
.then((allPaths: string[]) => {
|
|
44
|
+
const pathSet = new Set(allPaths);
|
|
45
|
+
setExistingFiles(new Set(entryPaths.filter(p => pathSet.has(p))));
|
|
46
|
+
})
|
|
47
|
+
.catch(() => {});
|
|
48
|
+
}, [mounted]);
|
|
49
49
|
|
|
50
50
|
const renderers = mounted ? getAllRenderers() : [];
|
|
51
51
|
const enabledCount = mounted ? renderers.filter(r => isRendererEnabled(r.id)).length : 0;
|
|
@@ -86,7 +86,9 @@ export default function PluginsPanel({ active, maximized, onMaximize }: PluginsP
|
|
|
86
86
|
${!enabled ? 'opacity-50' : ''}
|
|
87
87
|
`}
|
|
88
88
|
onClick={canOpen ? () => handleOpen(r.entryPath!) : undefined}
|
|
89
|
+
onKeyDown={canOpen ? (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleOpen(r.entryPath!); } } : undefined}
|
|
89
90
|
role={canOpen ? 'link' : undefined}
|
|
91
|
+
tabIndex={canOpen ? 0 : undefined}
|
|
90
92
|
>
|
|
91
93
|
{/* Top row: status dot + icon + name + toggle */}
|
|
92
94
|
<div className="flex items-center justify-between gap-2">
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useCallback, useSyncExternalStore, useRef } from 'react';
|
|
4
|
-
import { Copy, Check, RefreshCw, Trash2, Sparkles, ChevronDown, ChevronRight, Loader2, Cpu, Zap, Database as DatabaseIcon, HardDrive } from 'lucide-react';
|
|
4
|
+
import { Copy, Check, RefreshCw, Trash2, Sparkles, ChevronDown, ChevronRight, Loader2, Cpu, Zap, Database as DatabaseIcon, HardDrive, RotateCcw } from 'lucide-react';
|
|
5
5
|
import type { KnowledgeTabProps } from './types';
|
|
6
6
|
import { Field, Input, EnvBadge, SectionLabel, Toggle } from './Primitives';
|
|
7
7
|
import { apiFetch } from '@/lib/api';
|
|
@@ -49,6 +49,27 @@ export function KnowledgeTab({ data, setData, t }: KnowledgeTabProps) {
|
|
|
49
49
|
});
|
|
50
50
|
}, [guideDismissed]);
|
|
51
51
|
|
|
52
|
+
const handleRestartWalkthrough = useCallback(() => {
|
|
53
|
+
apiFetch('/api/setup', {
|
|
54
|
+
method: 'PATCH',
|
|
55
|
+
headers: { 'Content-Type': 'application/json' },
|
|
56
|
+
body: JSON.stringify({
|
|
57
|
+
guideState: {
|
|
58
|
+
active: true,
|
|
59
|
+
dismissed: false,
|
|
60
|
+
walkthroughStep: 0,
|
|
61
|
+
walkthroughDismissed: false,
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
})
|
|
65
|
+
.then(() => {
|
|
66
|
+
setGuideActive(true);
|
|
67
|
+
setGuideDismissed(false);
|
|
68
|
+
window.dispatchEvent(new Event('guide-state-updated'));
|
|
69
|
+
})
|
|
70
|
+
.catch(err => console.error('Failed to restart walkthrough:', err));
|
|
71
|
+
}, []);
|
|
72
|
+
|
|
52
73
|
const origin = useSyncExternalStore(
|
|
53
74
|
() => () => {},
|
|
54
75
|
() => `${window.location.protocol}//${window.location.hostname}`,
|
|
@@ -207,6 +228,13 @@ export function KnowledgeTab({ data, setData, t }: KnowledgeTabProps) {
|
|
|
207
228
|
</div>
|
|
208
229
|
<Toggle checked={!guideDismissed} onChange={() => handleGuideToggle()} />
|
|
209
230
|
</div>
|
|
231
|
+
<button
|
|
232
|
+
onClick={handleRestartWalkthrough}
|
|
233
|
+
className="flex items-center gap-1.5 mt-2 px-3 py-1.5 text-xs rounded-lg border border-border text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
|
|
234
|
+
>
|
|
235
|
+
<RotateCcw size={12} />
|
|
236
|
+
{k.restartWalkthrough ?? 'Restart walkthrough'}
|
|
237
|
+
</button>
|
|
210
238
|
</div>
|
|
211
239
|
)}
|
|
212
240
|
|
package/app/lib/i18n-en.ts
CHANGED
|
@@ -234,6 +234,7 @@ export const en = {
|
|
|
234
234
|
authTokenClear: 'Clear token',
|
|
235
235
|
authTokenResetConfirm: 'Regenerate token? All existing MCP clients will need to update their config.',
|
|
236
236
|
authTokenMcpPort: 'MCP port',
|
|
237
|
+
restartWalkthrough: 'Restart walkthrough',
|
|
237
238
|
},
|
|
238
239
|
sync: {
|
|
239
240
|
emptyTitle: 'Cross-device Sync',
|
package/app/lib/i18n-zh.ts
CHANGED
package/package.json
CHANGED