@geminilight/mindos 0.5.63 → 0.5.65
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/README.md +4 -0
- package/README_zh.md +4 -0
- package/app/app/api/ask/route.ts +12 -0
- package/app/app/api/changes/route.ts +7 -1
- package/app/app/api/file/route.ts +9 -0
- package/app/app/api/mcp/agents/route.ts +27 -1
- package/app/app/api/mcp/install-skill/route.ts +9 -24
- package/app/app/api/skills/route.ts +18 -2
- package/app/app/api/tree-version/route.ts +8 -0
- package/app/app/layout.tsx +1 -0
- package/app/app/page.tsx +1 -2
- package/app/app/view/[...path]/ViewPageClient.tsx +0 -1
- package/app/components/ActivityBar.tsx +2 -2
- package/app/components/Backlinks.tsx +5 -5
- package/app/components/CreateSpaceModal.tsx +3 -2
- package/app/components/DirPicker.tsx +1 -1
- package/app/components/DirView.tsx +2 -3
- package/app/components/EditorWrapper.tsx +3 -3
- package/app/components/FileTree.tsx +25 -10
- package/app/components/GuideCard.tsx +4 -4
- package/app/components/HomeContent.tsx +44 -14
- package/app/components/MarkdownView.tsx +2 -2
- package/app/components/OnboardingView.tsx +1 -1
- package/app/components/Panel.tsx +1 -1
- package/app/components/RightAgentDetailPanel.tsx +2 -1
- package/app/components/RightAskPanel.tsx +1 -1
- package/app/components/SearchModal.tsx +10 -2
- package/app/components/SidebarLayout.tsx +36 -10
- package/app/components/ThemeToggle.tsx +1 -1
- package/app/components/agents/AgentDetailContent.tsx +454 -59
- package/app/components/agents/AgentsContentPage.tsx +89 -20
- package/app/components/agents/AgentsMcpSection.tsx +513 -85
- package/app/components/agents/AgentsOverviewSection.tsx +418 -59
- package/app/components/agents/AgentsPrimitives.tsx +335 -0
- package/app/components/agents/AgentsSkillsSection.tsx +746 -105
- package/app/components/agents/SkillDetailPopover.tsx +416 -0
- package/app/components/agents/agents-content-model.ts +308 -10
- package/app/components/ask/AskContent.tsx +34 -5
- package/app/components/ask/FileChip.tsx +1 -0
- package/app/components/ask/MentionPopover.tsx +13 -1
- package/app/components/ask/MessageList.tsx +5 -7
- package/app/components/ask/ToolCallBlock.tsx +4 -4
- package/app/components/changes/ChangesBanner.tsx +89 -13
- package/app/components/changes/ChangesContentPage.tsx +134 -51
- package/app/components/echo/EchoHero.tsx +10 -24
- package/app/components/echo/EchoInsightCollapsible.tsx +52 -43
- package/app/components/echo/EchoPageSections.tsx +13 -9
- package/app/components/echo/EchoSegmentNav.tsx +14 -11
- package/app/components/echo/EchoSegmentPageClient.tsx +64 -43
- package/app/components/explore/ExploreContent.tsx +3 -7
- package/app/components/explore/UseCaseCard.tsx +4 -15
- package/app/components/panels/AgentsPanel.tsx +22 -128
- package/app/components/panels/AgentsPanelAgentDetail.tsx +7 -6
- package/app/components/panels/AgentsPanelAgentGroups.tsx +8 -13
- package/app/components/panels/AgentsPanelAgentListRow.tsx +39 -16
- package/app/components/panels/AgentsPanelHubNav.tsx +12 -12
- package/app/components/panels/EchoPanel.tsx +8 -10
- package/app/components/panels/PanelNavRow.tsx +9 -2
- package/app/components/panels/PluginsPanel.tsx +5 -5
- package/app/components/renderers/agent-inspector/AgentInspectorRenderer.tsx +30 -8
- package/app/components/renderers/agent-inspector/manifest.ts +5 -3
- package/app/components/renderers/config/manifest.ts +1 -0
- package/app/components/renderers/csv/manifest.ts +1 -0
- package/app/components/renderers/todo/manifest.ts +1 -0
- package/app/components/settings/AiTab.tsx +3 -3
- package/app/components/settings/AppearanceTab.tsx +2 -2
- package/app/components/settings/KnowledgeTab.tsx +3 -3
- package/app/components/settings/McpAgentInstall.tsx +3 -6
- package/app/components/settings/McpSkillCreateForm.tsx +2 -3
- package/app/components/settings/McpSkillRow.tsx +2 -3
- package/app/components/settings/McpSkillsSection.tsx +2 -2
- package/app/components/settings/McpTab.tsx +12 -13
- package/app/components/settings/MonitoringTab.tsx +13 -13
- package/app/components/settings/PluginsTab.tsx +6 -5
- package/app/components/settings/Primitives.tsx +3 -4
- package/app/components/settings/SettingsContent.tsx +3 -3
- package/app/components/settings/SyncTab.tsx +11 -17
- package/app/components/settings/UpdateTab.tsx +18 -21
- package/app/components/settings/types.ts +14 -0
- package/app/components/setup/StepKB.tsx +1 -1
- package/app/hooks/useMcpData.tsx +7 -4
- package/app/hooks/useMention.ts +25 -8
- package/app/lib/agent/log.ts +15 -18
- package/app/lib/agent/stream-consumer.ts +3 -0
- package/app/lib/agent/to-agent-messages.ts +6 -4
- package/app/lib/core/agent-audit-log.ts +280 -0
- package/app/lib/core/content-changes.ts +148 -8
- package/app/lib/core/index.ts +11 -0
- package/app/lib/fs.ts +16 -1
- package/app/lib/i18n-en.ts +317 -36
- package/app/lib/i18n-zh.ts +316 -35
- package/app/lib/mcp-agents.ts +273 -2
- package/app/lib/renderers/index.ts +1 -2
- package/app/lib/renderers/registry.ts +10 -0
- package/app/lib/types.ts +2 -0
- package/app/next-env.d.ts +1 -1
- package/bin/lib/mcp-agents.js +38 -13
- package/package.json +1 -1
- package/scripts/migrate-agent-audit-log.js +170 -0
- package/scripts/migrate-agent-diff.js +146 -0
- package/scripts/setup.js +12 -17
- package/skills/plugin-core-builtin-migration/SKILL.md +178 -0
- package/app/components/renderers/diff/DiffRenderer.tsx +0 -311
- package/app/components/renderers/diff/manifest.ts +0 -14
|
@@ -5,8 +5,7 @@ import { FileText, Table, Clock, Sparkles, ArrowRight, FilePlus, Search, Chevron
|
|
|
5
5
|
import { useState, useEffect, useMemo } from 'react';
|
|
6
6
|
import { useLocale } from '@/lib/LocaleContext';
|
|
7
7
|
import { encodePath, relativeTime, extractEmoji, stripEmoji } from '@/lib/utils';
|
|
8
|
-
import { getAllRenderers } from '@/lib/renderers/registry';
|
|
9
|
-
import '@/lib/renderers/index'; // registers all renderers
|
|
8
|
+
import { getAllRenderers, getPluginRenderers } from '@/lib/renderers/registry';
|
|
10
9
|
import OnboardingView from './OnboardingView';
|
|
11
10
|
import GuideCard from './GuideCard';
|
|
12
11
|
import CreateSpaceModal from './CreateSpaceModal';
|
|
@@ -116,23 +115,20 @@ export default function HomeContent({ recent, existingFiles, spaces, dirPaths }:
|
|
|
116
115
|
}, [suggestions.length]);
|
|
117
116
|
|
|
118
117
|
const existingSet = new Set(existingFiles ?? []);
|
|
118
|
+
const spaceList = spaces ?? [];
|
|
119
|
+
const { groups, rootFiles } = useMemo(() => groupBySpace(recent, spaceList), [recent, spaceList]);
|
|
119
120
|
|
|
120
|
-
// Empty knowledge base → show onboarding
|
|
121
121
|
if (recent.length === 0) {
|
|
122
122
|
return <OnboardingView />;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
const formatTime = (mtime: number) => relativeTime(mtime, t.home.relativeTime);
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
const
|
|
127
|
+
const availablePlugins = getPluginRenderers().filter(r => r.entryPath && existingSet.has(r.entryPath));
|
|
128
|
+
const builtinFeatures = getAllRenderers().filter((r) => r.appBuiltinFeature && r.id !== 'csv');
|
|
129
129
|
|
|
130
130
|
const lastFile = recent[0];
|
|
131
131
|
|
|
132
|
-
// Group recent files by Space
|
|
133
|
-
const spaceList = spaces ?? [];
|
|
134
|
-
const { groups, rootFiles } = useMemo(() => groupBySpace(recent, spaceList), [recent, spaceList]);
|
|
135
|
-
|
|
136
132
|
return (
|
|
137
133
|
<div className="content-width px-4 md:px-6 py-8 md:py-12">
|
|
138
134
|
<GuideCard
|
|
@@ -159,7 +155,7 @@ export default function HomeContent({ recent, existingFiles, spaces, dirPaths }:
|
|
|
159
155
|
onClick={triggerAsk}
|
|
160
156
|
title="⌘/"
|
|
161
157
|
data-walkthrough="ask-button"
|
|
162
|
-
className="flex-1 flex items-center gap-3 px-4 py-3 rounded-xl border border-border bg-card transition-all duration-150 hover:border-amber
|
|
158
|
+
className="flex-1 flex items-center gap-3 px-4 py-3 rounded-xl border border-border bg-card transition-all duration-150 hover:border-[var(--amber)]/50 hover:bg-[var(--amber)]/8"
|
|
163
159
|
>
|
|
164
160
|
<Sparkles size={15} className="shrink-0 text-[var(--amber)]" />
|
|
165
161
|
<span className="text-sm flex-1 text-left text-foreground">
|
|
@@ -236,7 +232,7 @@ export default function HomeContent({ recent, existingFiles, spaces, dirPaths }:
|
|
|
236
232
|
className={`flex items-start gap-3 px-3.5 py-3 rounded-xl border transition-all duration-150 hover:translate-x-0.5 ${
|
|
237
233
|
isEmpty
|
|
238
234
|
? 'border-dashed border-border/50 opacity-50 hover:opacity-70'
|
|
239
|
-
: 'border-border hover:border-amber
|
|
235
|
+
: 'border-border hover:border-[var(--amber)]/30 hover:bg-muted/40'
|
|
240
236
|
}`}
|
|
241
237
|
>
|
|
242
238
|
{emoji ? (
|
|
@@ -275,7 +271,41 @@ export default function HomeContent({ recent, existingFiles, spaces, dirPaths }:
|
|
|
275
271
|
<CreateSpaceModal t={t} dirPaths={dirPaths ?? []} />
|
|
276
272
|
</section>
|
|
277
273
|
|
|
278
|
-
{/* ── Section 2:
|
|
274
|
+
{/* ── Section 2: Built-in capabilities ── */}
|
|
275
|
+
{builtinFeatures.length > 0 && (
|
|
276
|
+
<section className="mb-8">
|
|
277
|
+
<SectionTitle icon={<Puzzle size={13} />} count={builtinFeatures.length}>
|
|
278
|
+
{t.home.builtinFeatures}
|
|
279
|
+
</SectionTitle>
|
|
280
|
+
<div className="flex flex-wrap gap-2">
|
|
281
|
+
{builtinFeatures.map((r) => {
|
|
282
|
+
const active = !!r.entryPath && existingSet.has(r.entryPath);
|
|
283
|
+
if (active && r.entryPath) {
|
|
284
|
+
return (
|
|
285
|
+
<Link key={r.id} href={`/view/${encodePath(r.entryPath)}`}>
|
|
286
|
+
<span className="inline-flex items-center gap-2 px-3 py-2 rounded-lg border border-border text-xs transition-all duration-150 hover:border-[var(--amber)]/30 hover:bg-muted/60">
|
|
287
|
+
<span className="text-sm leading-none" suppressHydrationWarning>{r.icon}</span>
|
|
288
|
+
<span className="font-medium text-foreground">{r.name}</span>
|
|
289
|
+
</span>
|
|
290
|
+
</Link>
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
return (
|
|
294
|
+
<span
|
|
295
|
+
key={r.id}
|
|
296
|
+
className="inline-flex items-center gap-2 px-3 py-2 rounded-lg border border-dashed border-border text-xs text-muted-foreground opacity-70"
|
|
297
|
+
title={r.entryPath ? t.home.createToActivate.replace('{file}', r.entryPath) : t.home.builtinInactive}
|
|
298
|
+
>
|
|
299
|
+
<span className="text-sm leading-none" suppressHydrationWarning>{r.icon}</span>
|
|
300
|
+
<span className="font-medium">{r.name}</span>
|
|
301
|
+
</span>
|
|
302
|
+
);
|
|
303
|
+
})}
|
|
304
|
+
</div>
|
|
305
|
+
</section>
|
|
306
|
+
)}
|
|
307
|
+
|
|
308
|
+
{/* ── Section 3: Extensions ── */}
|
|
279
309
|
{availablePlugins.length > 0 && (
|
|
280
310
|
<section className="mb-8">
|
|
281
311
|
<SectionTitle
|
|
@@ -300,7 +330,7 @@ export default function HomeContent({ recent, existingFiles, spaces, dirPaths }:
|
|
|
300
330
|
<Link
|
|
301
331
|
key={r.id}
|
|
302
332
|
href={`/view/${encodePath(r.entryPath!)}`}
|
|
303
|
-
className="inline-flex items-center gap-2 px-3 py-2 rounded-lg border border-border text-xs transition-all duration-150 hover:border-amber
|
|
333
|
+
className="inline-flex items-center gap-2 px-3 py-2 rounded-lg border border-border text-xs transition-all duration-150 hover:border-[var(--amber)]/30 hover:bg-muted/60"
|
|
304
334
|
>
|
|
305
335
|
<span className="text-sm leading-none" suppressHydrationWarning>{r.icon}</span>
|
|
306
336
|
<span className="font-medium text-foreground">{r.name}</span>
|
|
@@ -310,7 +340,7 @@ export default function HomeContent({ recent, existingFiles, spaces, dirPaths }:
|
|
|
310
340
|
</section>
|
|
311
341
|
)}
|
|
312
342
|
|
|
313
|
-
{/* ── Section
|
|
343
|
+
{/* ── Section 4: Recently Edited ── */}
|
|
314
344
|
{recent.length > 0 && (
|
|
315
345
|
<section className="mb-12">
|
|
316
346
|
<SectionTitle icon={<Clock size={13} />} count={recent.length}>{t.home.recentlyEdited}</SectionTitle>
|
|
@@ -31,8 +31,8 @@ function CopyButton({ code }: { code: string }) {
|
|
|
31
31
|
className="
|
|
32
32
|
absolute top-2.5 right-2.5
|
|
33
33
|
p-1.5 rounded-md
|
|
34
|
-
bg-
|
|
35
|
-
text-
|
|
34
|
+
bg-muted hover:bg-accent
|
|
35
|
+
text-muted-foreground hover:text-foreground
|
|
36
36
|
transition-colors duration-100
|
|
37
37
|
opacity-0 group-hover:opacity-100
|
|
38
38
|
"
|
|
@@ -100,7 +100,7 @@ export default function OnboardingView() {
|
|
|
100
100
|
key={tpl.id}
|
|
101
101
|
disabled={isDisabled}
|
|
102
102
|
onClick={() => handleSelect(tpl.id)}
|
|
103
|
-
className="group relative flex flex-col items-start gap-3 p-5 rounded-xl border border-border bg-card text-left transition-all duration-150 hover:border-amber
|
|
103
|
+
className="group relative flex flex-col items-start gap-3 p-5 rounded-xl border border-border bg-card text-left transition-all duration-150 hover:border-[var(--amber)]/50 hover:bg-[var(--amber)]/5 disabled:opacity-60 disabled:cursor-not-allowed"
|
|
104
104
|
>
|
|
105
105
|
{/* Icon + title */}
|
|
106
106
|
<div className="flex items-center gap-2.5 w-full">
|
package/app/components/Panel.tsx
CHANGED
|
@@ -149,7 +149,7 @@ export default function Panel({
|
|
|
149
149
|
className="absolute top-0 -right-[3px] w-[6px] h-full cursor-col-resize z-40 group hidden md:block"
|
|
150
150
|
onMouseDown={handleMouseDown}
|
|
151
151
|
>
|
|
152
|
-
<div className="absolute right-[2px] top-0 w-[2px] h-full opacity-0 group-hover:opacity-100 bg-amber
|
|
152
|
+
<div className="absolute right-[2px] top-0 w-[2px] h-full opacity-0 group-hover:opacity-100 bg-[var(--amber)]/60 transition-opacity" />
|
|
153
153
|
</div>
|
|
154
154
|
)}
|
|
155
155
|
</aside>
|
|
@@ -70,6 +70,7 @@ export default function RightAgentDetailPanel({
|
|
|
70
70
|
connected: p.connected,
|
|
71
71
|
installing: p.installing,
|
|
72
72
|
install: p.install,
|
|
73
|
+
installFailed: p.installFailed,
|
|
73
74
|
copyConfig: p.copyConfig,
|
|
74
75
|
copied: p.copied,
|
|
75
76
|
transportLocal: p.transportLocal,
|
|
@@ -95,7 +96,7 @@ export default function RightAgentDetailPanel({
|
|
|
95
96
|
aria-hidden={!open || !resolved}
|
|
96
97
|
>
|
|
97
98
|
{resolved && (
|
|
98
|
-
<div className="flex flex-col flex-1 min-h-0 overflow-
|
|
99
|
+
<div className="flex flex-col flex-1 min-h-0 overflow-y-auto">
|
|
99
100
|
<AgentsPanelAgentDetail
|
|
100
101
|
agent={resolved.agent}
|
|
101
102
|
agentStatus={resolved.status}
|
|
@@ -81,7 +81,7 @@ export default function RightAskPanel({
|
|
|
81
81
|
className="absolute top-0 -left-[3px] w-[6px] h-full cursor-col-resize z-40 group hidden md:block"
|
|
82
82
|
onMouseDown={handleMouseDown}
|
|
83
83
|
>
|
|
84
|
-
<div className="absolute left-[2px] top-0 w-[2px] h-full opacity-0 group-hover:opacity-100 bg-amber
|
|
84
|
+
<div className="absolute left-[2px] top-0 w-[2px] h-full opacity-0 group-hover:opacity-100 bg-[var(--amber)]/60 transition-opacity" />
|
|
85
85
|
</div>
|
|
86
86
|
</aside>
|
|
87
87
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
3
|
+
import { useState, useEffect, useCallback, useRef, useLayoutEffect } from 'react';
|
|
4
4
|
import { useRouter } from 'next/navigation';
|
|
5
5
|
import { Search, X, FileText, Table } from 'lucide-react';
|
|
6
6
|
import { SearchResult } from '@/lib/types';
|
|
@@ -32,6 +32,7 @@ export default function SearchModal({ open, onClose }: SearchModalProps) {
|
|
|
32
32
|
const [loading, setLoading] = useState(false);
|
|
33
33
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
34
34
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
35
|
+
const resultsRef = useRef<HTMLDivElement>(null);
|
|
35
36
|
const router = useRouter();
|
|
36
37
|
const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
37
38
|
const { t } = useLocale();
|
|
@@ -99,6 +100,13 @@ export default function SearchModal({ open, onClose }: SearchModalProps) {
|
|
|
99
100
|
return () => window.removeEventListener('keydown', handler);
|
|
100
101
|
}, [open, onClose, results, selectedIndex, navigate]);
|
|
101
102
|
|
|
103
|
+
useLayoutEffect(() => {
|
|
104
|
+
const container = resultsRef.current;
|
|
105
|
+
if (!container) return;
|
|
106
|
+
const selected = container.children[selectedIndex] as HTMLElement | undefined;
|
|
107
|
+
selected?.scrollIntoView({ block: 'nearest' });
|
|
108
|
+
}, [selectedIndex]);
|
|
109
|
+
|
|
102
110
|
if (!open) return null;
|
|
103
111
|
|
|
104
112
|
return (
|
|
@@ -134,7 +142,7 @@ export default function SearchModal({ open, onClose }: SearchModalProps) {
|
|
|
134
142
|
</div>
|
|
135
143
|
|
|
136
144
|
{/* Results */}
|
|
137
|
-
<div className="max-h-[50vh] md:max-h-80 overflow-y-auto flex-1">
|
|
145
|
+
<div ref={resultsRef} className="max-h-[50vh] md:max-h-80 overflow-y-auto flex-1">
|
|
138
146
|
{results.length === 0 && query && !loading && (
|
|
139
147
|
<div className="px-4 py-8 text-center text-sm text-muted-foreground">{t.search.noResults}</div>
|
|
140
148
|
)}
|
|
@@ -31,6 +31,7 @@ import { FileNode } from '@/lib/types';
|
|
|
31
31
|
import { useLocale } from '@/lib/LocaleContext';
|
|
32
32
|
import { WalkthroughProvider } from './walkthrough';
|
|
33
33
|
import McpProvider from '@/hooks/useMcpData';
|
|
34
|
+
import '@/lib/renderers/index'; // client-side renderer registration source of truth
|
|
34
35
|
import { useLeftPanel } from '@/hooks/useLeftPanel';
|
|
35
36
|
import { useAskPanel } from '@/hooks/useAskPanel';
|
|
36
37
|
import type { Tab } from './settings/types';
|
|
@@ -136,18 +137,43 @@ export default function SidebarLayout({ fileTree, children }: SidebarLayoutProps
|
|
|
136
137
|
|
|
137
138
|
const agentDockOpen = agentDetailKey !== null && lp.activePanel === 'agents';
|
|
138
139
|
|
|
139
|
-
// Refresh file tree
|
|
140
|
+
// Refresh file tree when server-side tree version changes.
|
|
141
|
+
// Polls a lightweight version counter every 3s — only calls router.refresh()
|
|
142
|
+
// (which rebuilds the full tree) when the version actually changes.
|
|
140
143
|
useEffect(() => {
|
|
144
|
+
let lastVersion = -1;
|
|
145
|
+
let stopped = false;
|
|
146
|
+
|
|
147
|
+
const checkVersion = async () => {
|
|
148
|
+
if (stopped || document.visibilityState === 'hidden') return;
|
|
149
|
+
try {
|
|
150
|
+
const res = await fetch('/api/tree-version');
|
|
151
|
+
if (!res.ok) return;
|
|
152
|
+
const { v } = (await res.json()) as { v: number };
|
|
153
|
+
if (lastVersion === -1) {
|
|
154
|
+
lastVersion = v;
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (v !== lastVersion) {
|
|
158
|
+
lastVersion = v;
|
|
159
|
+
router.refresh();
|
|
160
|
+
window.dispatchEvent(new Event('mindos:files-changed'));
|
|
161
|
+
}
|
|
162
|
+
} catch (err) { console.debug('[tree-version] poll failed', err); }
|
|
163
|
+
};
|
|
164
|
+
|
|
141
165
|
const onVisible = () => {
|
|
142
|
-
if (document.visibilityState === 'visible')
|
|
166
|
+
if (document.visibilityState === 'visible') void checkVersion();
|
|
143
167
|
};
|
|
168
|
+
|
|
169
|
+
void checkVersion();
|
|
170
|
+
const interval = setInterval(() => void checkVersion(), 3_000);
|
|
144
171
|
document.addEventListener('visibilitychange', onVisible);
|
|
145
|
-
|
|
146
|
-
if (document.visibilityState === 'visible') router.refresh();
|
|
147
|
-
}, 30_000);
|
|
172
|
+
|
|
148
173
|
return () => {
|
|
149
|
-
|
|
174
|
+
stopped = true;
|
|
150
175
|
clearInterval(interval);
|
|
176
|
+
document.removeEventListener('visibilitychange', onVisible);
|
|
151
177
|
};
|
|
152
178
|
}, [router]);
|
|
153
179
|
|
|
@@ -223,8 +249,7 @@ export default function SidebarLayout({ fileTree, children }: SidebarLayoutProps
|
|
|
223
249
|
{/* Skip link */}
|
|
224
250
|
<a
|
|
225
251
|
href="#main-content"
|
|
226
|
-
className="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-[60] focus:px-4 focus:py-2 focus:rounded-lg focus:text-sm focus:font-medium focus:font-display"
|
|
227
|
-
style={{ background: 'var(--amber)', color: 'var(--amber-foreground)' }}
|
|
252
|
+
className="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-[60] focus:px-4 focus:py-2 focus:rounded-lg focus:text-sm focus:font-medium focus:font-display bg-[var(--amber)] text-[var(--amber-foreground)]"
|
|
228
253
|
>
|
|
229
254
|
Skip to main content
|
|
230
255
|
</a>
|
|
@@ -234,7 +259,9 @@ export default function SidebarLayout({ fileTree, children }: SidebarLayoutProps
|
|
|
234
259
|
activePanel={railActivePanel}
|
|
235
260
|
onPanelChange={lp.setActivePanel}
|
|
236
261
|
onAgentsClick={() => {
|
|
237
|
-
lp.
|
|
262
|
+
const wasActive = lp.activePanel === 'agents';
|
|
263
|
+
lp.setActivePanel(wasActive ? null : 'agents');
|
|
264
|
+
if (!wasActive) router.push('/agents');
|
|
238
265
|
setAgentDetailKey(null);
|
|
239
266
|
}}
|
|
240
267
|
syncStatus={syncStatus}
|
|
@@ -272,7 +299,6 @@ export default function SidebarLayout({ fileTree, children }: SidebarLayoutProps
|
|
|
272
299
|
maximized={lp.panelMaximized}
|
|
273
300
|
onMaximize={lp.handlePanelMaximize}
|
|
274
301
|
selectedAgentKey={agentDockOpen ? agentDetailKey : null}
|
|
275
|
-
onOpenAgentDetail={setAgentDetailKey}
|
|
276
302
|
/>
|
|
277
303
|
</div>
|
|
278
304
|
<div className={`flex flex-col h-full ${lp.activePanel === 'discover' ? '' : 'hidden'}`}>
|
|
@@ -27,7 +27,7 @@ export default function ThemeToggle() {
|
|
|
27
27
|
return (
|
|
28
28
|
<button
|
|
29
29
|
onClick={toggle}
|
|
30
|
-
className="p-1.5 rounded-lg hover:bg-
|
|
30
|
+
className="p-1.5 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-colors"
|
|
31
31
|
title={dark ? 'Switch to light mode' : 'Switch to dark mode'}
|
|
32
32
|
>
|
|
33
33
|
{dark ? <Sun size={15} /> : <Moon size={15} />}
|