@geminilight/mindos 0.2.1 → 0.4.0
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/api/init/route.ts +7 -41
- package/app/app/api/mcp/agents/route.ts +72 -0
- package/app/app/api/mcp/install/route.ts +95 -0
- package/app/app/api/mcp/status/route.ts +47 -0
- package/app/app/api/settings/route.ts +3 -0
- package/app/app/api/setup/generate-token/route.ts +23 -0
- package/app/app/api/setup/route.ts +81 -0
- package/app/app/api/skills/route.ts +208 -0
- package/app/app/api/sync/route.ts +54 -3
- package/app/app/api/update-check/route.ts +52 -0
- package/app/app/globals.css +12 -0
- package/app/app/layout.tsx +4 -2
- package/app/app/login/page.tsx +20 -13
- package/app/app/page.tsx +22 -2
- package/app/app/setup/page.tsx +9 -0
- package/app/app/view/[...path]/ViewPageClient.tsx +47 -21
- package/app/app/view/[...path]/loading.tsx +1 -1
- package/app/app/view/[...path]/not-found.tsx +101 -0
- package/app/components/AskFab.tsx +1 -1
- package/app/components/AskModal.tsx +1 -1
- package/app/components/Backlinks.tsx +1 -1
- package/app/components/Breadcrumb.tsx +13 -3
- package/app/components/CsvView.tsx +5 -6
- package/app/components/DirView.tsx +42 -21
- package/app/components/FindInPage.tsx +211 -0
- package/app/components/HomeContent.tsx +97 -44
- package/app/components/JsonView.tsx +1 -2
- package/app/components/MarkdownEditor.tsx +1 -2
- package/app/components/OnboardingView.tsx +6 -7
- package/app/components/SettingsModal.tsx +5 -2
- package/app/components/SetupWizard.tsx +479 -0
- package/app/components/Sidebar.tsx +1 -1
- package/app/components/UpdateBanner.tsx +101 -0
- package/app/components/renderers/{AgentInspectorRenderer.tsx → agent-inspector/AgentInspectorRenderer.tsx} +13 -11
- package/app/components/renderers/agent-inspector/manifest.ts +14 -0
- package/app/components/renderers/{BacklinksRenderer.tsx → backlinks/BacklinksRenderer.tsx} +6 -6
- package/app/components/renderers/backlinks/manifest.ts +14 -0
- package/app/components/renderers/config/manifest.ts +14 -0
- package/app/components/renderers/csv/BoardView.tsx +12 -12
- package/app/components/renderers/csv/ConfigPanel.tsx +7 -8
- package/app/components/renderers/{CsvRenderer.tsx → csv/CsvRenderer.tsx} +8 -9
- package/app/components/renderers/csv/GalleryView.tsx +3 -3
- package/app/components/renderers/csv/TableView.tsx +4 -5
- package/app/components/renderers/csv/manifest.ts +14 -0
- package/app/components/renderers/{DiffRenderer.tsx → diff/DiffRenderer.tsx} +10 -9
- package/app/components/renderers/diff/manifest.ts +14 -0
- package/app/components/renderers/{GraphRenderer.tsx → graph/GraphRenderer.tsx} +4 -5
- package/app/components/renderers/graph/manifest.ts +14 -0
- package/app/components/renderers/{SummaryRenderer.tsx → summary/SummaryRenderer.tsx} +6 -6
- package/app/components/renderers/summary/manifest.ts +14 -0
- package/app/components/renderers/{TimelineRenderer.tsx → timeline/TimelineRenderer.tsx} +6 -6
- package/app/components/renderers/timeline/manifest.ts +14 -0
- package/app/components/renderers/{TodoRenderer.tsx → todo/TodoRenderer.tsx} +2 -2
- package/app/components/renderers/todo/manifest.ts +14 -0
- package/app/components/renderers/{WorkflowRenderer.tsx → workflow/WorkflowRenderer.tsx} +13 -13
- package/app/components/renderers/workflow/manifest.ts +14 -0
- package/app/components/settings/McpTab.tsx +549 -0
- package/app/components/settings/SyncTab.tsx +139 -50
- package/app/components/settings/types.ts +1 -1
- package/app/data/pages/home.png +0 -0
- package/app/lib/i18n.ts +270 -10
- package/app/lib/renderers/index.ts +20 -89
- package/app/lib/renderers/registry.ts +4 -1
- package/app/lib/settings.ts +15 -1
- package/app/lib/template.ts +45 -0
- package/app/package.json +1 -0
- package/app/types/semver.d.ts +8 -0
- package/bin/cli.js +137 -24
- package/bin/lib/build.js +53 -18
- package/bin/lib/colors.js +3 -1
- package/bin/lib/config.js +4 -0
- package/bin/lib/constants.js +2 -0
- package/bin/lib/debug.js +10 -0
- package/bin/lib/startup.js +21 -20
- package/bin/lib/stop.js +41 -3
- package/bin/lib/sync.js +65 -53
- package/bin/lib/update-check.js +94 -0
- package/bin/lib/utils.js +2 -2
- package/package.json +1 -1
- package/scripts/gen-renderer-index.js +57 -0
- package/scripts/setup.js +117 -1
- /package/app/components/renderers/{ConfigRenderer.tsx → config/ConfigRenderer.tsx} +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RendererDefinition } from '@/lib/renderers/registry';
|
|
2
|
+
|
|
3
|
+
export const manifest: RendererDefinition = {
|
|
4
|
+
id: 'summary',
|
|
5
|
+
name: 'AI Briefing',
|
|
6
|
+
description: 'Streams an AI-generated daily briefing summarizing your most recently modified files — key changes, recurring themes, and suggested next actions.',
|
|
7
|
+
author: 'MindOS',
|
|
8
|
+
icon: '✨',
|
|
9
|
+
tags: ['ai', 'summary', 'briefing', 'daily'],
|
|
10
|
+
builtin: true,
|
|
11
|
+
entryPath: 'DAILY.md',
|
|
12
|
+
match: ({ filePath }) => /\b(SUMMARY|summary|Summary|BRIEFING|briefing|Briefing|DAILY|daily|Daily)\b.*\.md$/i.test(filePath),
|
|
13
|
+
load: () => import('./SummaryRenderer').then(m => ({ default: m.SummaryRenderer })),
|
|
14
|
+
};
|
|
@@ -71,7 +71,7 @@ function renderInline(text: string): string {
|
|
|
71
71
|
return text
|
|
72
72
|
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
|
|
73
73
|
.replace(/\*(.+?)\*/g, '<em>$1</em>')
|
|
74
|
-
.replace(/`(.+?)`/g, '<code
|
|
74
|
+
.replace(/`(.+?)`/g, '<code class="font-display" style="font-size:0.85em;padding:1px 5px;border-radius:4px;background:var(--muted)">$1</code>')
|
|
75
75
|
.replace(/\[\[([^\]|]+)(?:\|([^\]]+))?\]\]/g, (_, target, alias) =>
|
|
76
76
|
`<span style="color:var(--amber);cursor:pointer" title="${target}">${alias ?? target}</span>`)
|
|
77
77
|
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" style="color:var(--amber)">$1</a>');
|
|
@@ -131,7 +131,7 @@ export function TimelineRenderer({ content }: RendererContext) {
|
|
|
131
131
|
|
|
132
132
|
if (entries.length === 0) {
|
|
133
133
|
return (
|
|
134
|
-
<div style={{ padding: '3rem 1rem', textAlign: 'center', color: 'var(--muted-foreground)',
|
|
134
|
+
<div className="font-display" style={{ padding: '3rem 1rem', textAlign: 'center', color: 'var(--muted-foreground)', fontSize: 13 }}>
|
|
135
135
|
No timeline entries found. Add <code style={{ background: 'var(--muted)', padding: '1px 6px', borderRadius: 4 }}>## 2025-01-15</code> headings to create entries.
|
|
136
136
|
</div>
|
|
137
137
|
);
|
|
@@ -141,7 +141,7 @@ export function TimelineRenderer({ content }: RendererContext) {
|
|
|
141
141
|
<div style={{ maxWidth: 720, margin: '0 auto', padding: '1.5rem 0' }}>
|
|
142
142
|
{/* count pill */}
|
|
143
143
|
<div style={{ marginBottom: '1.5rem', display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
144
|
-
<span style={{
|
|
144
|
+
<span className="font-display" style={{ fontSize: 11, color: 'var(--muted-foreground)' }}>
|
|
145
145
|
{entries.length} {entries.length === 1 ? 'entry' : 'entries'}
|
|
146
146
|
</span>
|
|
147
147
|
</div>
|
|
@@ -176,11 +176,11 @@ export function TimelineRenderer({ content }: RendererContext) {
|
|
|
176
176
|
}}>
|
|
177
177
|
{/* header */}
|
|
178
178
|
<div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap', marginBottom: 8 }}>
|
|
179
|
-
<span style={{
|
|
179
|
+
<span style={{ fontWeight: 600, fontSize: '0.9rem', color: 'var(--foreground)' }}>
|
|
180
180
|
{entry.heading}
|
|
181
181
|
</span>
|
|
182
182
|
{entry.date && (
|
|
183
|
-
<span style={{
|
|
183
|
+
<span className="font-display" style={{ fontSize: '0.7rem', color: 'var(--muted-foreground)', opacity: 0.7, flexShrink: 0 }}>
|
|
184
184
|
{formatDate(entry.date)}
|
|
185
185
|
</span>
|
|
186
186
|
)}
|
|
@@ -197,7 +197,7 @@ export function TimelineRenderer({ content }: RendererContext) {
|
|
|
197
197
|
{entry.tags.map(tag => {
|
|
198
198
|
const c = tagColor(tag);
|
|
199
199
|
return (
|
|
200
|
-
<span key={tag} style={{ fontSize: '0.68rem', padding: '1px 8px', borderRadius: 999,
|
|
200
|
+
<span key={tag} className="font-display" style={{ fontSize: '0.68rem', padding: '1px 8px', borderRadius: 999, background: c.bg, color: c.text }}>
|
|
201
201
|
#{tag}
|
|
202
202
|
</span>
|
|
203
203
|
);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RendererDefinition } from '@/lib/renderers/registry';
|
|
2
|
+
|
|
3
|
+
export const manifest: RendererDefinition = {
|
|
4
|
+
id: 'timeline',
|
|
5
|
+
name: 'Timeline',
|
|
6
|
+
description: 'Renders changelog and journal files as a vertical timeline. Any markdown with ## date headings (e.g. ## 2025-01-15) becomes a card in the feed.',
|
|
7
|
+
author: 'MindOS',
|
|
8
|
+
icon: '📅',
|
|
9
|
+
tags: ['timeline', 'changelog', 'journal', 'history'],
|
|
10
|
+
builtin: true,
|
|
11
|
+
entryPath: 'CHANGELOG.md',
|
|
12
|
+
match: ({ filePath }) => /\b(CHANGELOG|changelog|TIMELINE|timeline|journal|Journal|diary|Diary)\b.*\.md$/i.test(filePath),
|
|
13
|
+
load: () => import('./TimelineRenderer').then(m => ({ default: m.TimelineRenderer })),
|
|
14
|
+
};
|
|
@@ -358,7 +358,7 @@ function SectionCard({
|
|
|
358
358
|
>
|
|
359
359
|
<div className="flex items-center gap-2">
|
|
360
360
|
<span className={`w-2 h-2 rounded-full shrink-0 ${style.dot}`} />
|
|
361
|
-
<span className={`text-xs font-semibold uppercase tracking-wider ${style.label}`}
|
|
361
|
+
<span className={`text-xs font-semibold uppercase tracking-wider ${style.label} font-display`}>
|
|
362
362
|
{name}
|
|
363
363
|
</span>
|
|
364
364
|
<span className="text-xs text-muted-foreground">{done}/{total}</span>
|
|
@@ -441,7 +441,7 @@ export function TodoRenderer({ content, saveAction }: RendererContext) {
|
|
|
441
441
|
<div className="max-w-[900px] mx-auto xl:mr-[220px] px-0 py-2">
|
|
442
442
|
{/* Summary header */}
|
|
443
443
|
<div className="mb-6">
|
|
444
|
-
<p className="text-xs text-muted-foreground
|
|
444
|
+
<p className="text-xs text-muted-foreground font-display">
|
|
445
445
|
{totalDone} / {totalItems} completed
|
|
446
446
|
</p>
|
|
447
447
|
<div className="mt-1.5 w-48 h-1.5 bg-muted rounded-full overflow-hidden">
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RendererDefinition } from '@/lib/renderers/registry';
|
|
2
|
+
|
|
3
|
+
export const manifest: RendererDefinition = {
|
|
4
|
+
id: 'todo',
|
|
5
|
+
name: 'TODO Board',
|
|
6
|
+
description: 'Renders TODO.md/TODO.csv as an interactive kanban board grouped by section. Check items off directly — changes are written back to the source file.',
|
|
7
|
+
author: 'MindOS',
|
|
8
|
+
icon: '✅',
|
|
9
|
+
tags: ['productivity', 'tasks', 'markdown'],
|
|
10
|
+
builtin: true,
|
|
11
|
+
entryPath: 'TODO.md',
|
|
12
|
+
match: ({ filePath }) => /\bTODO\b.*\.(md|csv)$/i.test(filePath),
|
|
13
|
+
load: () => import('./TodoRenderer').then(m => ({ default: m.TodoRenderer })),
|
|
14
|
+
};
|
|
@@ -75,7 +75,7 @@ function parseWorkflow(content: string): { meta: WorkflowMeta; steps: WorkflowSt
|
|
|
75
75
|
function renderInline(text: string): string {
|
|
76
76
|
return text
|
|
77
77
|
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
|
|
78
|
-
.replace(/`(.+?)`/g, `<code
|
|
78
|
+
.replace(/`(.+?)`/g, `<code class="font-display" style="font-size:.82em;padding:1px 5px;border-radius:4px;background:var(--muted)">$1</code>`)
|
|
79
79
|
.replace(/\*(.+?)\*/g, '<em>$1</em>');
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -188,7 +188,7 @@ function StepCard({
|
|
|
188
188
|
<div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '11px 14px' }}>
|
|
189
189
|
<StatusIcon status={step.status} />
|
|
190
190
|
<span
|
|
191
|
-
style={{ flex: 1,
|
|
191
|
+
style={{ flex: 1, fontWeight: 600, fontSize: '.88rem', color: 'var(--foreground)', cursor: hasBody || hasOutput ? 'pointer' : 'default' }}
|
|
192
192
|
onClick={() => (hasBody || hasOutput) && setExpanded(v => !v)}
|
|
193
193
|
>
|
|
194
194
|
{step.heading}
|
|
@@ -204,7 +204,7 @@ function StepCard({
|
|
|
204
204
|
style={{
|
|
205
205
|
display: 'flex', alignItems: 'center', gap: 4,
|
|
206
206
|
padding: '3px 10px', borderRadius: 6, fontSize: '0.72rem',
|
|
207
|
-
|
|
207
|
+
cursor: canRun ? 'pointer' : 'not-allowed',
|
|
208
208
|
border: 'none', background: canRun ? 'var(--amber)' : 'var(--muted)',
|
|
209
209
|
color: canRun ? '#131210' : 'var(--muted-foreground)',
|
|
210
210
|
opacity: canRun ? 1 : 0.5,
|
|
@@ -216,7 +216,7 @@ function StepCard({
|
|
|
216
216
|
onClick={onSkip}
|
|
217
217
|
style={{
|
|
218
218
|
padding: '3px 8px', borderRadius: 6, fontSize: '0.72rem',
|
|
219
|
-
|
|
219
|
+
cursor: 'pointer',
|
|
220
220
|
border: '1px solid var(--border)', background: 'transparent',
|
|
221
221
|
color: 'var(--muted-foreground)',
|
|
222
222
|
}}
|
|
@@ -226,12 +226,12 @@ function StepCard({
|
|
|
226
226
|
</>
|
|
227
227
|
)}
|
|
228
228
|
{step.status === 'running' && (
|
|
229
|
-
<span style={{
|
|
229
|
+
<span className="font-display" style={{ fontSize: '0.7rem', color: 'var(--amber)' }}>executing…</span>
|
|
230
230
|
)}
|
|
231
231
|
{(step.status === 'done' || step.status === 'error') && (
|
|
232
232
|
<button
|
|
233
233
|
onClick={() => setExpanded(v => !v)}
|
|
234
|
-
style={{ padding: '3px 8px', borderRadius: 6, fontSize: '0.72rem',
|
|
234
|
+
style={{ padding: '3px 8px', borderRadius: 6, fontSize: '0.72rem', cursor: 'pointer', border: '1px solid var(--border)', background: 'transparent', color: 'var(--muted-foreground)' }}
|
|
235
235
|
>
|
|
236
236
|
<ChevronDown size={11} style={{ display: 'inline', transform: expanded ? 'rotate(180deg)' : 'none', transition: 'transform .15s' }} />
|
|
237
237
|
</button>
|
|
@@ -251,10 +251,10 @@ function StepCard({
|
|
|
251
251
|
<div style={{ padding: '10px 14px', background: 'var(--background)', position: 'relative' }}>
|
|
252
252
|
<div style={{ display: 'flex', alignItems: 'center', gap: 5, marginBottom: 6 }}>
|
|
253
253
|
<Sparkles size={11} style={{ color: 'var(--amber)' }} />
|
|
254
|
-
<span style={{
|
|
254
|
+
<span className="font-display" style={{ fontSize: '0.68rem', color: 'var(--muted-foreground)', textTransform: 'uppercase', letterSpacing: '.06em' }}>AI Output</span>
|
|
255
255
|
{step.status === 'running' && <span style={{ width: 5, height: 5, borderRadius: '50%', background: 'var(--amber)', animation: 'pulse 1.2s ease-in-out infinite', marginLeft: 4 }} />}
|
|
256
256
|
</div>
|
|
257
|
-
<div style={{
|
|
257
|
+
<div style={{ fontSize: '.82rem', lineHeight: 1.7, color: 'var(--foreground)', whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>
|
|
258
258
|
{step.output}
|
|
259
259
|
</div>
|
|
260
260
|
</div>
|
|
@@ -326,7 +326,7 @@ export function WorkflowRenderer({ filePath, content }: RendererContext) {
|
|
|
326
326
|
|
|
327
327
|
if (steps.length === 0) {
|
|
328
328
|
return (
|
|
329
|
-
<div style={{ padding: '3rem 1rem', textAlign: 'center', color: 'var(--muted-foreground)',
|
|
329
|
+
<div className="font-display" style={{ padding: '3rem 1rem', textAlign: 'center', color: 'var(--muted-foreground)', fontSize: 12 }}>
|
|
330
330
|
No steps found. Add <code style={{ background: 'var(--muted)', padding: '1px 5px', borderRadius: 4 }}>## Step N: …</code> headings to define workflow steps.
|
|
331
331
|
</div>
|
|
332
332
|
);
|
|
@@ -337,7 +337,7 @@ export function WorkflowRenderer({ filePath, content }: RendererContext) {
|
|
|
337
337
|
{/* header */}
|
|
338
338
|
<div style={{ marginBottom: '1.2rem' }}>
|
|
339
339
|
{parsed.meta.description && (
|
|
340
|
-
<p style={{
|
|
340
|
+
<p style={{ fontSize: '.82rem', color: 'var(--muted-foreground)', lineHeight: 1.6, marginBottom: 12 }}>
|
|
341
341
|
{parsed.meta.description}
|
|
342
342
|
</p>
|
|
343
343
|
)}
|
|
@@ -348,7 +348,7 @@ export function WorkflowRenderer({ filePath, content }: RendererContext) {
|
|
|
348
348
|
<div style={{ flex: 1, minWidth: 120, height: 4, borderRadius: 999, background: 'var(--border)', overflow: 'hidden' }}>
|
|
349
349
|
<div style={{ height: '100%', width: `${progress}%`, background: 'var(--amber)', borderRadius: 999, transition: 'width .3s' }} />
|
|
350
350
|
</div>
|
|
351
|
-
<span style={{
|
|
351
|
+
<span className="font-display" style={{ fontSize: '0.7rem', color: 'var(--muted-foreground)', flexShrink: 0 }}>
|
|
352
352
|
{doneCount}/{steps.length} done
|
|
353
353
|
</span>
|
|
354
354
|
|
|
@@ -360,7 +360,7 @@ export function WorkflowRenderer({ filePath, content }: RendererContext) {
|
|
|
360
360
|
style={{
|
|
361
361
|
display: 'flex', alignItems: 'center', gap: 5,
|
|
362
362
|
padding: '4px 12px', borderRadius: 7, fontSize: '0.75rem',
|
|
363
|
-
|
|
363
|
+
cursor: running ? 'not-allowed' : 'pointer',
|
|
364
364
|
border: 'none', background: running ? 'var(--muted)' : 'var(--amber)',
|
|
365
365
|
color: running ? 'var(--muted-foreground)' : '#131210',
|
|
366
366
|
opacity: running ? 0.7 : 1,
|
|
@@ -374,7 +374,7 @@ export function WorkflowRenderer({ filePath, content }: RendererContext) {
|
|
|
374
374
|
{/* reset */}
|
|
375
375
|
<button
|
|
376
376
|
onClick={reset}
|
|
377
|
-
style={{ padding: '4px 10px', borderRadius: 7, fontSize: '0.75rem',
|
|
377
|
+
style={{ padding: '4px 10px', borderRadius: 7, fontSize: '0.75rem', cursor: 'pointer', border: '1px solid var(--border)', background: 'transparent', color: 'var(--muted-foreground)', display: 'flex', alignItems: 'center', gap: 4 }}
|
|
378
378
|
>
|
|
379
379
|
<RotateCcw size={11} /> Reset
|
|
380
380
|
</button>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RendererDefinition } from '@/lib/renderers/registry';
|
|
2
|
+
|
|
3
|
+
export const manifest: RendererDefinition = {
|
|
4
|
+
id: 'workflow',
|
|
5
|
+
name: 'Workflow Runner',
|
|
6
|
+
description: 'Parses step-by-step workflow markdown into an interactive runner. Execute steps sequentially with AI assistance.',
|
|
7
|
+
author: 'MindOS',
|
|
8
|
+
icon: '⚡',
|
|
9
|
+
tags: ['workflow', 'automation', 'steps', 'ai'],
|
|
10
|
+
builtin: true,
|
|
11
|
+
entryPath: 'Workflow.md',
|
|
12
|
+
match: ({ filePath }) => /\b(Workflow|workflow|WORKFLOW)\b.*\.md$/i.test(filePath),
|
|
13
|
+
load: () => import('./WorkflowRenderer').then(m => ({ default: m.WorkflowRenderer })),
|
|
14
|
+
};
|