@geminilight/mindos 0.6.35 → 0.6.36
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/_standalone/.mindos-build-version +1 -1
- package/_standalone/.next/BUILD_ID +1 -1
- package/_standalone/.next/app-path-routes-manifest.json +13 -13
- package/_standalone/.next/build-manifest.json +2 -2
- package/_standalone/.next/cache/.previewinfo +1 -1
- package/_standalone/.next/cache/.rscinfo +1 -1
- package/_standalone/.next/cache/config.json +3 -3
- package/_standalone/.next/prerender-manifest.json +3 -3
- package/_standalone/.next/server/app/.well-known/agent-card.json/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/_global-error.html +2 -2
- package/_standalone/.next/server/app/_global-error.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/_standalone/.next/server/app/_not-found/page.js +1 -1
- package/_standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page.js +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/agents/page.js +1 -1
- package/_standalone/.next/server/app/agents/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/agents/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/agents/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/delegations/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/discover/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/config/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/detect/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/install/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/registry/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/session/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/agent-activity/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/ask/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/ask-sessions/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/auth/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/backlinks/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/bootstrap/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/changes/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/export/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/extract-pdf/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/file/import/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/file/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/graph/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/agents/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/install/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/install-skill/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/restart/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/status/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/monitoring/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/recent-files/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/restart/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/list-models/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/reset-token/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/test-key/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/check-path/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/check-port/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/generate-token/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/ls/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/sync/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/tree-version/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/uninstall/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/update-check/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/update-status/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/workflows/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/changes/page.js +1 -1
- package/_standalone/.next/server/app/changes/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/changes/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page.js +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/echo/page.js +1 -1
- package/_standalone/.next/server/app/echo/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/echo/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/explore/page.js +1 -1
- package/_standalone/.next/server/app/explore/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/explore/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/help/page.js +1 -1
- package/_standalone/.next/server/app/help/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/help/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/login/page.js +1 -1
- package/_standalone/.next/server/app/login/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/page.js +1 -1
- package/_standalone/.next/server/app/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/setup/page.js +2 -2
- package/_standalone/.next/server/app/setup/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/trash/page.js +2 -2
- package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/view/[...path]/page.js +3 -3
- package/_standalone/.next/server/app/view/[...path]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/view/[...path]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app-paths-manifest.json +13 -13
- package/_standalone/.next/server/chunks/4931.js +27 -27
- package/_standalone/.next/server/chunks/{733.js → 9360.js} +2 -2
- package/_standalone/.next/server/pages/500.html +2 -2
- package/_standalone/.next/server/server-reference-manifest.js +1 -1
- package/_standalone/.next/server/server-reference-manifest.json +1 -1
- package/_standalone/.next/static/chunks/{1263-31c1efe3fd8f3f99.js → 1263-79beb8734dee7bbd.js} +2 -2
- package/_standalone/.next/static/chunks/app/{layout-8f28cae88387ff74.js → layout-d0f6dc4d3e6f0be4.js} +11 -11
- package/_standalone/.next/static/chunks/app/{page-c1d8353c59791595.js → page-404b0bfb5721b7f8.js} +2 -2
- package/_standalone/.next/static/chunks/app/setup/page-01ab1f549d636057.js +1 -0
- package/_standalone/.next/static/chunks/app/trash/{page-82c45f29e38465b8.js → page-a79804c1df44d3cc.js} +1 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/{page-8d1f8b9247021c34.js → page-d3aceca36a1a9eb2.js} +2 -2
- package/_standalone/.next/trace +53 -53
- package/_standalone/components/setup/StepAI.tsx +66 -3
- package/_standalone/components/setup/StepDots.tsx +18 -10
- package/_standalone/components/setup/StepKB.tsx +26 -0
- package/_standalone/components/setup/constants.tsx +4 -3
- package/_standalone/lib/i18n/modules/onboarding.ts +14 -6
- package/app/components/setup/StepAI.tsx +66 -3
- package/app/components/setup/StepDots.tsx +18 -10
- package/app/components/setup/StepKB.tsx +26 -0
- package/app/components/setup/constants.tsx +4 -3
- package/app/components/setup/index.tsx +22 -32
- package/app/lib/i18n/modules/onboarding.ts +14 -6
- package/package.json +1 -1
- package/_standalone/.next/static/chunks/app/setup/page-f8a85accc3be554f.js +0 -1
- /package/_standalone/.next/static/{o0geoEkWzQqvkqAs4aTu5 → VWZDVb8DL1Pbykh9EOj_Y}/_buildManifest.js +0 -0
- /package/_standalone/.next/static/{o0geoEkWzQqvkqAs4aTu5 → VWZDVb8DL1Pbykh9EOj_Y}/_ssgManifest.js +0 -0
|
@@ -1,16 +1,35 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { Brain, Zap, SkipForward, CheckCircle2, ChevronDown, ChevronRight, Copy } from 'lucide-react';
|
|
4
5
|
import { Field, Input, ApiKeyInput } from '@/components/settings/Primitives';
|
|
5
|
-
import type { SetupState, SetupMessages } from './types';
|
|
6
|
+
import type { SetupState, SetupMessages, PortStatus } from './types';
|
|
7
|
+
import StepPorts from './StepPorts';
|
|
6
8
|
|
|
7
9
|
export interface StepAIProps {
|
|
8
10
|
state: SetupState;
|
|
9
11
|
update: <K extends keyof SetupState>(key: K, val: SetupState[K]) => void;
|
|
10
12
|
s: SetupMessages;
|
|
13
|
+
onCopyToken: () => void;
|
|
14
|
+
// Port props (embedded in Advanced section)
|
|
15
|
+
webPortStatus: PortStatus;
|
|
16
|
+
mcpPortStatus: PortStatus;
|
|
17
|
+
setWebPortStatus: (s: PortStatus) => void;
|
|
18
|
+
setMcpPortStatus: (s: PortStatus) => void;
|
|
19
|
+
checkPort: (port: number, which: 'web' | 'mcp') => void;
|
|
20
|
+
portConflict: boolean;
|
|
11
21
|
}
|
|
12
22
|
|
|
13
|
-
export default function StepAI({ state, update, s }: StepAIProps) {
|
|
23
|
+
export default function StepAI({ state, update, s, onCopyToken, webPortStatus, mcpPortStatus, setWebPortStatus, setMcpPortStatus, checkPort, portConflict }: StepAIProps) {
|
|
24
|
+
const [portsOpen, setPortsOpen] = useState(false);
|
|
25
|
+
|
|
26
|
+
// Auto-expand Advanced section if port check finds a problem
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!portsOpen && (webPortStatus.available === false || mcpPortStatus.available === false || portConflict)) {
|
|
29
|
+
setPortsOpen(true);
|
|
30
|
+
}
|
|
31
|
+
}, [webPortStatus.available, mcpPortStatus.available, portConflict, portsOpen]);
|
|
32
|
+
|
|
14
33
|
const providers = [
|
|
15
34
|
{ id: 'anthropic' as const, icon: <Brain size={18} />, label: 'Anthropic', desc: 'Claude — claude-sonnet-4-6' },
|
|
16
35
|
{ id: 'openai' as const, icon: <Zap size={18} />, label: 'OpenAI', desc: 'GPT or any OpenAI-compatible API' },
|
|
@@ -70,6 +89,50 @@ export default function StepAI({ state, update, s }: StepAIProps) {
|
|
|
70
89
|
)}
|
|
71
90
|
</div>
|
|
72
91
|
)}
|
|
92
|
+
|
|
93
|
+
{/* Advanced: Port Settings (collapsed) */}
|
|
94
|
+
<div className="pt-3 mt-1" style={{ borderTop: '1px solid var(--border)' }}>
|
|
95
|
+
<button
|
|
96
|
+
type="button"
|
|
97
|
+
onClick={() => setPortsOpen(!portsOpen)}
|
|
98
|
+
className="flex items-center gap-1.5 text-xs font-medium"
|
|
99
|
+
style={{ color: 'var(--muted-foreground)' }}>
|
|
100
|
+
{portsOpen ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
|
|
101
|
+
{s.advancedPorts}
|
|
102
|
+
</button>
|
|
103
|
+
{portsOpen && (
|
|
104
|
+
<div className="mt-3 space-y-5">
|
|
105
|
+
{/* MCP Auth Token (read-only) */}
|
|
106
|
+
<div className="space-y-1.5">
|
|
107
|
+
<p className="text-xs font-medium" style={{ color: 'var(--foreground)' }}>
|
|
108
|
+
🔑 {s.tokenSectionTitle}
|
|
109
|
+
</p>
|
|
110
|
+
<div className="flex items-center gap-2">
|
|
111
|
+
<code className="flex-1 truncate text-xs font-mono px-3 py-2 rounded-lg"
|
|
112
|
+
style={{ background: 'var(--muted)', color: 'var(--foreground)' }}>
|
|
113
|
+
{state.authToken}
|
|
114
|
+
</code>
|
|
115
|
+
<button type="button" onClick={onCopyToken}
|
|
116
|
+
className="flex items-center gap-1 px-2.5 py-2 text-xs rounded-lg border transition-colors hover:bg-muted shrink-0"
|
|
117
|
+
style={{ borderColor: 'var(--border)', color: 'var(--foreground)' }}>
|
|
118
|
+
<Copy size={12} /> {s.copyToken}
|
|
119
|
+
</button>
|
|
120
|
+
</div>
|
|
121
|
+
<p className="text-xs" style={{ color: 'var(--muted-foreground)' }}>
|
|
122
|
+
{s.tokenSectionHint}
|
|
123
|
+
</p>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
{/* Port Settings */}
|
|
127
|
+
<StepPorts
|
|
128
|
+
state={state} update={update}
|
|
129
|
+
webPortStatus={webPortStatus} mcpPortStatus={mcpPortStatus}
|
|
130
|
+
setWebPortStatus={setWebPortStatus} setMcpPortStatus={setMcpPortStatus}
|
|
131
|
+
checkPort={checkPort} portConflict={portConflict} s={s}
|
|
132
|
+
/>
|
|
133
|
+
</div>
|
|
134
|
+
)}
|
|
135
|
+
</div>
|
|
73
136
|
</div>
|
|
74
137
|
);
|
|
75
138
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { CheckCircle2 } from 'lucide-react';
|
|
3
4
|
import { useLocale } from '@/lib/LocaleContext';
|
|
4
5
|
|
|
5
6
|
export interface StepDotsProps {
|
|
@@ -7,32 +8,39 @@ export interface StepDotsProps {
|
|
|
7
8
|
setStep: (s: number) => void;
|
|
8
9
|
stepTitles: readonly string[];
|
|
9
10
|
disabled?: boolean;
|
|
11
|
+
/** Number of "numbered" steps to show (Confirm step is not numbered) */
|
|
12
|
+
numberedSteps?: number;
|
|
10
13
|
}
|
|
11
14
|
|
|
12
|
-
export default function StepDots({ step, setStep, stepTitles, disabled }: StepDotsProps) {
|
|
15
|
+
export default function StepDots({ step, setStep, stepTitles, disabled, numberedSteps }: StepDotsProps) {
|
|
13
16
|
const { t } = useLocale();
|
|
17
|
+
const count = numberedSteps ?? stepTitles.length;
|
|
18
|
+
// Only render dots for numbered steps (exclude Confirm)
|
|
19
|
+
const dotsToShow = stepTitles.slice(0, count);
|
|
20
|
+
const isConfirmStep = step >= count;
|
|
21
|
+
|
|
14
22
|
return (
|
|
15
23
|
<div className="flex items-center gap-2 mb-8" role="navigation" aria-label="Setup steps">
|
|
16
|
-
{
|
|
24
|
+
{dotsToShow.map((title: string, i: number) => (
|
|
17
25
|
<div key={i} className="flex items-center gap-2">
|
|
18
|
-
{i > 0 && <div className="w-8 h-px" style={{ background: i <= step ? 'var(--amber)' : 'var(--border)' }} />}
|
|
26
|
+
{i > 0 && <div className="w-8 h-px" style={{ background: i <= step || isConfirmStep ? 'var(--amber)' : 'var(--border)' }} />}
|
|
19
27
|
<button onClick={() => setStep(i)}
|
|
20
28
|
aria-current={i === step ? 'step' : undefined}
|
|
21
29
|
aria-label={title}
|
|
22
30
|
className="flex flex-col items-center gap-1 p-1 -m-1 disabled:cursor-not-allowed disabled:opacity-60"
|
|
23
|
-
disabled={disabled || i
|
|
24
|
-
title={(disabled || i
|
|
31
|
+
disabled={disabled || i > step}
|
|
32
|
+
title={(disabled || i > step) ? t.hints.cannotJumpForward : undefined}>
|
|
25
33
|
<div
|
|
26
34
|
className="w-6 h-6 rounded-full text-xs font-medium flex items-center justify-center transition-colors"
|
|
27
35
|
style={{
|
|
28
|
-
background: i
|
|
29
|
-
color: i <= step ? 'var(--amber-foreground)' : 'var(--muted-foreground)',
|
|
30
|
-
opacity: i <= step ? 1 : 0.5,
|
|
36
|
+
background: (i < step || isConfirmStep) ? 'var(--amber)' : i === step ? 'var(--amber)' : 'var(--muted)',
|
|
37
|
+
color: (i <= step || isConfirmStep) ? 'var(--amber-foreground)' : 'var(--muted-foreground)',
|
|
38
|
+
opacity: (i <= step || isConfirmStep) ? 1 : 0.5,
|
|
31
39
|
}}>
|
|
32
|
-
{i + 1}
|
|
40
|
+
{(i < step || isConfirmStep) ? <CheckCircle2 size={14} /> : i + 1}
|
|
33
41
|
</div>
|
|
34
42
|
<span className="text-[10px] leading-tight hidden sm:inline max-w-[4rem] text-center truncate"
|
|
35
|
-
style={{ color: i === step ? 'var(--foreground)' : 'var(--muted-foreground)', opacity: i <= step ? 1 : 0.5 }}>
|
|
43
|
+
style={{ color: (i === step && !isConfirmStep) ? 'var(--foreground)' : 'var(--muted-foreground)', opacity: (i <= step || isConfirmStep) ? 1 : 0.5 }}>
|
|
36
44
|
{title}
|
|
37
45
|
</span>
|
|
38
46
|
</button>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useRef } from 'react';
|
|
4
|
+
import { AlertCircle } from 'lucide-react';
|
|
4
5
|
import { Field } from '@/components/settings/Primitives';
|
|
5
6
|
import type { Messages } from '@/lib/i18n';
|
|
6
7
|
import type { SetupState } from './types';
|
|
@@ -26,6 +27,7 @@ export interface StepKBProps {
|
|
|
26
27
|
|
|
27
28
|
export default function StepKB({ state, update, t, homeDir }: StepKBProps) {
|
|
28
29
|
const s = t.setup;
|
|
30
|
+
const [passwordTouched, setPasswordTouched] = useState(false);
|
|
29
31
|
// Build platform-aware placeholder, e.g. /Users/alice/MindOS/mind or C:\Users\alice\MindOS\mind
|
|
30
32
|
// Windows homedir always contains \, e.g. C:\Users\Alice — safe to detect by separator
|
|
31
33
|
const sep = homeDir.includes('\\') ? '\\' : '/';
|
|
@@ -232,6 +234,30 @@ export default function StepKB({ state, update, t, homeDir }: StepKBProps) {
|
|
|
232
234
|
</div>
|
|
233
235
|
</div>
|
|
234
236
|
)}
|
|
237
|
+
|
|
238
|
+
{/* ── Security ── */}
|
|
239
|
+
<div className="pt-2 mt-2" style={{ borderTop: '1px solid var(--border)' }}>
|
|
240
|
+
<Field label={<>{s.webPassword} <span style={{ color: 'var(--error)' }}>*</span></>} hint={s.webPasswordHint}>
|
|
241
|
+
<input
|
|
242
|
+
type="password"
|
|
243
|
+
value={state.webPassword}
|
|
244
|
+
onChange={e => { update('webPassword', e.target.value); setPasswordTouched(true); }}
|
|
245
|
+
onBlur={() => setPasswordTouched(true)}
|
|
246
|
+
placeholder="••••••••"
|
|
247
|
+
className="w-full px-3 py-2 text-sm rounded-lg border outline-none transition-colors focus-visible:ring-1 focus-visible:ring-ring"
|
|
248
|
+
style={{
|
|
249
|
+
background: 'var(--input, var(--card))',
|
|
250
|
+
borderColor: passwordTouched && !state.webPassword.trim() ? 'var(--error)' : 'var(--border)',
|
|
251
|
+
color: 'var(--foreground)',
|
|
252
|
+
}}
|
|
253
|
+
/>
|
|
254
|
+
{passwordTouched && !state.webPassword.trim() && (
|
|
255
|
+
<p className="text-xs flex items-center gap-1 mt-1" style={{ color: 'var(--error)' }}>
|
|
256
|
+
<AlertCircle size={11} /> {s.webPasswordRequired}
|
|
257
|
+
</p>
|
|
258
|
+
)}
|
|
259
|
+
</Field>
|
|
260
|
+
</div>
|
|
235
261
|
</div>
|
|
236
262
|
);
|
|
237
263
|
}
|
|
@@ -7,7 +7,8 @@ export const TEMPLATES: Array<{ id: Template; icon: React.ReactNode; dirs: strin
|
|
|
7
7
|
{ id: 'empty', icon: <FileText size={18} />, dirs: ['README.md', 'CONFIG.json', 'INSTRUCTION.md'] },
|
|
8
8
|
];
|
|
9
9
|
|
|
10
|
-
export const TOTAL_STEPS =
|
|
10
|
+
export const TOTAL_STEPS = 4;
|
|
11
11
|
export const STEP_KB = 0;
|
|
12
|
-
export const
|
|
13
|
-
export const STEP_AGENTS =
|
|
12
|
+
export const STEP_AI = 1;
|
|
13
|
+
export const STEP_AGENTS = 2;
|
|
14
|
+
export const STEP_REVIEW = 3;
|
|
@@ -15,7 +15,7 @@ export const onboardingEn = {
|
|
|
15
15
|
dismiss: 'Dismiss',
|
|
16
16
|
},
|
|
17
17
|
setup: {
|
|
18
|
-
stepTitles: ['Knowledge Base', 'AI
|
|
18
|
+
stepTitles: ['Knowledge Base', 'AI Configuration', 'Agent Tools', 'Confirm'],
|
|
19
19
|
// Step 1
|
|
20
20
|
kbPath: 'Knowledge base path',
|
|
21
21
|
kbPathHint: 'Absolute path to your notes directory.',
|
|
@@ -56,8 +56,12 @@ export const onboardingEn = {
|
|
|
56
56
|
generateToken: 'Generate',
|
|
57
57
|
copyToken: 'Copy',
|
|
58
58
|
copiedToken: 'Copied!',
|
|
59
|
-
webPassword: 'Web
|
|
60
|
-
webPasswordHint: '
|
|
59
|
+
webPassword: 'Web Password',
|
|
60
|
+
webPasswordHint: 'Protect your knowledge base from unauthorized browser access.',
|
|
61
|
+
webPasswordRequired: 'Password is required to protect your data.',
|
|
62
|
+
advancedPorts: 'Advanced Settings',
|
|
63
|
+
tokenSectionTitle: 'MCP Auth Token (auto-generated)',
|
|
64
|
+
tokenSectionHint: 'Used by AI agents to connect to your MindOS server.',
|
|
61
65
|
// Step 5 — Agent Tools
|
|
62
66
|
agentToolsTitle: 'Agent Tools',
|
|
63
67
|
agentToolsHint: 'Select AI agents to configure with MindOS MCP. Agents marked "not installed" can be configured now — they will work once you install the app.',
|
|
@@ -210,7 +214,7 @@ export const onboardingZh = {
|
|
|
210
214
|
dismiss: '关闭',
|
|
211
215
|
},
|
|
212
216
|
setup: {
|
|
213
|
-
stepTitles: ['知识库', 'AI
|
|
217
|
+
stepTitles: ['知识库', 'AI 配置', 'Agent 工具', '确认'],
|
|
214
218
|
// Step 1
|
|
215
219
|
kbPath: '知识库路径',
|
|
216
220
|
kbPathHint: '笔记目录的绝对路径。',
|
|
@@ -251,8 +255,12 @@ export const onboardingZh = {
|
|
|
251
255
|
generateToken: '生成',
|
|
252
256
|
copyToken: '复制',
|
|
253
257
|
copiedToken: '已复制!',
|
|
254
|
-
webPassword: '
|
|
255
|
-
webPasswordHint: '
|
|
258
|
+
webPassword: '访问密码',
|
|
259
|
+
webPasswordHint: '保护你的知识库,防止未授权的浏览器访问。',
|
|
260
|
+
webPasswordRequired: '密码是必填项,用于保护你的数据。',
|
|
261
|
+
advancedPorts: '高级设置',
|
|
262
|
+
tokenSectionTitle: 'MCP 认证令牌(已自动生成)',
|
|
263
|
+
tokenSectionHint: 'AI Agent 连接你的 MindOS 服务器时使用。',
|
|
256
264
|
// Step 5 — Agent Tools
|
|
257
265
|
agentToolsTitle: 'Agent 工具',
|
|
258
266
|
agentToolsHint: '选择要与 MindOS MCP 配置的 AI Agent。标注「未安装」的 agent 可以先行配置,安装应用后即可生效。',
|
|
@@ -1,16 +1,35 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { Brain, Zap, SkipForward, CheckCircle2, ChevronDown, ChevronRight, Copy } from 'lucide-react';
|
|
4
5
|
import { Field, Input, ApiKeyInput } from '@/components/settings/Primitives';
|
|
5
|
-
import type { SetupState, SetupMessages } from './types';
|
|
6
|
+
import type { SetupState, SetupMessages, PortStatus } from './types';
|
|
7
|
+
import StepPorts from './StepPorts';
|
|
6
8
|
|
|
7
9
|
export interface StepAIProps {
|
|
8
10
|
state: SetupState;
|
|
9
11
|
update: <K extends keyof SetupState>(key: K, val: SetupState[K]) => void;
|
|
10
12
|
s: SetupMessages;
|
|
13
|
+
onCopyToken: () => void;
|
|
14
|
+
// Port props (embedded in Advanced section)
|
|
15
|
+
webPortStatus: PortStatus;
|
|
16
|
+
mcpPortStatus: PortStatus;
|
|
17
|
+
setWebPortStatus: (s: PortStatus) => void;
|
|
18
|
+
setMcpPortStatus: (s: PortStatus) => void;
|
|
19
|
+
checkPort: (port: number, which: 'web' | 'mcp') => void;
|
|
20
|
+
portConflict: boolean;
|
|
11
21
|
}
|
|
12
22
|
|
|
13
|
-
export default function StepAI({ state, update, s }: StepAIProps) {
|
|
23
|
+
export default function StepAI({ state, update, s, onCopyToken, webPortStatus, mcpPortStatus, setWebPortStatus, setMcpPortStatus, checkPort, portConflict }: StepAIProps) {
|
|
24
|
+
const [portsOpen, setPortsOpen] = useState(false);
|
|
25
|
+
|
|
26
|
+
// Auto-expand Advanced section if port check finds a problem
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!portsOpen && (webPortStatus.available === false || mcpPortStatus.available === false || portConflict)) {
|
|
29
|
+
setPortsOpen(true);
|
|
30
|
+
}
|
|
31
|
+
}, [webPortStatus.available, mcpPortStatus.available, portConflict, portsOpen]);
|
|
32
|
+
|
|
14
33
|
const providers = [
|
|
15
34
|
{ id: 'anthropic' as const, icon: <Brain size={18} />, label: 'Anthropic', desc: 'Claude — claude-sonnet-4-6' },
|
|
16
35
|
{ id: 'openai' as const, icon: <Zap size={18} />, label: 'OpenAI', desc: 'GPT or any OpenAI-compatible API' },
|
|
@@ -70,6 +89,50 @@ export default function StepAI({ state, update, s }: StepAIProps) {
|
|
|
70
89
|
)}
|
|
71
90
|
</div>
|
|
72
91
|
)}
|
|
92
|
+
|
|
93
|
+
{/* Advanced: Port Settings (collapsed) */}
|
|
94
|
+
<div className="pt-3 mt-1" style={{ borderTop: '1px solid var(--border)' }}>
|
|
95
|
+
<button
|
|
96
|
+
type="button"
|
|
97
|
+
onClick={() => setPortsOpen(!portsOpen)}
|
|
98
|
+
className="flex items-center gap-1.5 text-xs font-medium"
|
|
99
|
+
style={{ color: 'var(--muted-foreground)' }}>
|
|
100
|
+
{portsOpen ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
|
|
101
|
+
{s.advancedPorts}
|
|
102
|
+
</button>
|
|
103
|
+
{portsOpen && (
|
|
104
|
+
<div className="mt-3 space-y-5">
|
|
105
|
+
{/* MCP Auth Token (read-only) */}
|
|
106
|
+
<div className="space-y-1.5">
|
|
107
|
+
<p className="text-xs font-medium" style={{ color: 'var(--foreground)' }}>
|
|
108
|
+
🔑 {s.tokenSectionTitle}
|
|
109
|
+
</p>
|
|
110
|
+
<div className="flex items-center gap-2">
|
|
111
|
+
<code className="flex-1 truncate text-xs font-mono px-3 py-2 rounded-lg"
|
|
112
|
+
style={{ background: 'var(--muted)', color: 'var(--foreground)' }}>
|
|
113
|
+
{state.authToken}
|
|
114
|
+
</code>
|
|
115
|
+
<button type="button" onClick={onCopyToken}
|
|
116
|
+
className="flex items-center gap-1 px-2.5 py-2 text-xs rounded-lg border transition-colors hover:bg-muted shrink-0"
|
|
117
|
+
style={{ borderColor: 'var(--border)', color: 'var(--foreground)' }}>
|
|
118
|
+
<Copy size={12} /> {s.copyToken}
|
|
119
|
+
</button>
|
|
120
|
+
</div>
|
|
121
|
+
<p className="text-xs" style={{ color: 'var(--muted-foreground)' }}>
|
|
122
|
+
{s.tokenSectionHint}
|
|
123
|
+
</p>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
{/* Port Settings */}
|
|
127
|
+
<StepPorts
|
|
128
|
+
state={state} update={update}
|
|
129
|
+
webPortStatus={webPortStatus} mcpPortStatus={mcpPortStatus}
|
|
130
|
+
setWebPortStatus={setWebPortStatus} setMcpPortStatus={setMcpPortStatus}
|
|
131
|
+
checkPort={checkPort} portConflict={portConflict} s={s}
|
|
132
|
+
/>
|
|
133
|
+
</div>
|
|
134
|
+
)}
|
|
135
|
+
</div>
|
|
73
136
|
</div>
|
|
74
137
|
);
|
|
75
138
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { CheckCircle2 } from 'lucide-react';
|
|
3
4
|
import { useLocale } from '@/lib/LocaleContext';
|
|
4
5
|
|
|
5
6
|
export interface StepDotsProps {
|
|
@@ -7,32 +8,39 @@ export interface StepDotsProps {
|
|
|
7
8
|
setStep: (s: number) => void;
|
|
8
9
|
stepTitles: readonly string[];
|
|
9
10
|
disabled?: boolean;
|
|
11
|
+
/** Number of "numbered" steps to show (Confirm step is not numbered) */
|
|
12
|
+
numberedSteps?: number;
|
|
10
13
|
}
|
|
11
14
|
|
|
12
|
-
export default function StepDots({ step, setStep, stepTitles, disabled }: StepDotsProps) {
|
|
15
|
+
export default function StepDots({ step, setStep, stepTitles, disabled, numberedSteps }: StepDotsProps) {
|
|
13
16
|
const { t } = useLocale();
|
|
17
|
+
const count = numberedSteps ?? stepTitles.length;
|
|
18
|
+
// Only render dots for numbered steps (exclude Confirm)
|
|
19
|
+
const dotsToShow = stepTitles.slice(0, count);
|
|
20
|
+
const isConfirmStep = step >= count;
|
|
21
|
+
|
|
14
22
|
return (
|
|
15
23
|
<div className="flex items-center gap-2 mb-8" role="navigation" aria-label="Setup steps">
|
|
16
|
-
{
|
|
24
|
+
{dotsToShow.map((title: string, i: number) => (
|
|
17
25
|
<div key={i} className="flex items-center gap-2">
|
|
18
|
-
{i > 0 && <div className="w-8 h-px" style={{ background: i <= step ? 'var(--amber)' : 'var(--border)' }} />}
|
|
26
|
+
{i > 0 && <div className="w-8 h-px" style={{ background: i <= step || isConfirmStep ? 'var(--amber)' : 'var(--border)' }} />}
|
|
19
27
|
<button onClick={() => setStep(i)}
|
|
20
28
|
aria-current={i === step ? 'step' : undefined}
|
|
21
29
|
aria-label={title}
|
|
22
30
|
className="flex flex-col items-center gap-1 p-1 -m-1 disabled:cursor-not-allowed disabled:opacity-60"
|
|
23
|
-
disabled={disabled || i
|
|
24
|
-
title={(disabled || i
|
|
31
|
+
disabled={disabled || i > step}
|
|
32
|
+
title={(disabled || i > step) ? t.hints.cannotJumpForward : undefined}>
|
|
25
33
|
<div
|
|
26
34
|
className="w-6 h-6 rounded-full text-xs font-medium flex items-center justify-center transition-colors"
|
|
27
35
|
style={{
|
|
28
|
-
background: i
|
|
29
|
-
color: i <= step ? 'var(--amber-foreground)' : 'var(--muted-foreground)',
|
|
30
|
-
opacity: i <= step ? 1 : 0.5,
|
|
36
|
+
background: (i < step || isConfirmStep) ? 'var(--amber)' : i === step ? 'var(--amber)' : 'var(--muted)',
|
|
37
|
+
color: (i <= step || isConfirmStep) ? 'var(--amber-foreground)' : 'var(--muted-foreground)',
|
|
38
|
+
opacity: (i <= step || isConfirmStep) ? 1 : 0.5,
|
|
31
39
|
}}>
|
|
32
|
-
{i + 1}
|
|
40
|
+
{(i < step || isConfirmStep) ? <CheckCircle2 size={14} /> : i + 1}
|
|
33
41
|
</div>
|
|
34
42
|
<span className="text-[10px] leading-tight hidden sm:inline max-w-[4rem] text-center truncate"
|
|
35
|
-
style={{ color: i === step ? 'var(--foreground)' : 'var(--muted-foreground)', opacity: i <= step ? 1 : 0.5 }}>
|
|
43
|
+
style={{ color: (i === step && !isConfirmStep) ? 'var(--foreground)' : 'var(--muted-foreground)', opacity: (i <= step || isConfirmStep) ? 1 : 0.5 }}>
|
|
36
44
|
{title}
|
|
37
45
|
</span>
|
|
38
46
|
</button>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useRef } from 'react';
|
|
4
|
+
import { AlertCircle } from 'lucide-react';
|
|
4
5
|
import { Field } from '@/components/settings/Primitives';
|
|
5
6
|
import type { Messages } from '@/lib/i18n';
|
|
6
7
|
import type { SetupState } from './types';
|
|
@@ -26,6 +27,7 @@ export interface StepKBProps {
|
|
|
26
27
|
|
|
27
28
|
export default function StepKB({ state, update, t, homeDir }: StepKBProps) {
|
|
28
29
|
const s = t.setup;
|
|
30
|
+
const [passwordTouched, setPasswordTouched] = useState(false);
|
|
29
31
|
// Build platform-aware placeholder, e.g. /Users/alice/MindOS/mind or C:\Users\alice\MindOS\mind
|
|
30
32
|
// Windows homedir always contains \, e.g. C:\Users\Alice — safe to detect by separator
|
|
31
33
|
const sep = homeDir.includes('\\') ? '\\' : '/';
|
|
@@ -232,6 +234,30 @@ export default function StepKB({ state, update, t, homeDir }: StepKBProps) {
|
|
|
232
234
|
</div>
|
|
233
235
|
</div>
|
|
234
236
|
)}
|
|
237
|
+
|
|
238
|
+
{/* ── Security ── */}
|
|
239
|
+
<div className="pt-2 mt-2" style={{ borderTop: '1px solid var(--border)' }}>
|
|
240
|
+
<Field label={<>{s.webPassword} <span style={{ color: 'var(--error)' }}>*</span></>} hint={s.webPasswordHint}>
|
|
241
|
+
<input
|
|
242
|
+
type="password"
|
|
243
|
+
value={state.webPassword}
|
|
244
|
+
onChange={e => { update('webPassword', e.target.value); setPasswordTouched(true); }}
|
|
245
|
+
onBlur={() => setPasswordTouched(true)}
|
|
246
|
+
placeholder="••••••••"
|
|
247
|
+
className="w-full px-3 py-2 text-sm rounded-lg border outline-none transition-colors focus-visible:ring-1 focus-visible:ring-ring"
|
|
248
|
+
style={{
|
|
249
|
+
background: 'var(--input, var(--card))',
|
|
250
|
+
borderColor: passwordTouched && !state.webPassword.trim() ? 'var(--error)' : 'var(--border)',
|
|
251
|
+
color: 'var(--foreground)',
|
|
252
|
+
}}
|
|
253
|
+
/>
|
|
254
|
+
{passwordTouched && !state.webPassword.trim() && (
|
|
255
|
+
<p className="text-xs flex items-center gap-1 mt-1" style={{ color: 'var(--error)' }}>
|
|
256
|
+
<AlertCircle size={11} /> {s.webPasswordRequired}
|
|
257
|
+
</p>
|
|
258
|
+
)}
|
|
259
|
+
</Field>
|
|
260
|
+
</div>
|
|
235
261
|
</div>
|
|
236
262
|
);
|
|
237
263
|
}
|
|
@@ -7,7 +7,8 @@ export const TEMPLATES: Array<{ id: Template; icon: React.ReactNode; dirs: strin
|
|
|
7
7
|
{ id: 'empty', icon: <FileText size={18} />, dirs: ['README.md', 'CONFIG.json', 'INSTRUCTION.md'] },
|
|
8
8
|
];
|
|
9
9
|
|
|
10
|
-
export const TOTAL_STEPS =
|
|
10
|
+
export const TOTAL_STEPS = 4;
|
|
11
11
|
export const STEP_KB = 0;
|
|
12
|
-
export const
|
|
13
|
-
export const STEP_AGENTS =
|
|
12
|
+
export const STEP_AI = 1;
|
|
13
|
+
export const STEP_AGENTS = 2;
|
|
14
|
+
export const STEP_REVIEW = 3;
|
|
@@ -6,11 +6,9 @@ import { useLocale } from '@/lib/LocaleContext';
|
|
|
6
6
|
import { copyToClipboard } from '@/lib/clipboard';
|
|
7
7
|
import { toast } from '@/lib/toast';
|
|
8
8
|
import type { SetupState, PortStatus, AgentEntry, AgentInstallStatus } from './types';
|
|
9
|
-
import { TOTAL_STEPS, STEP_KB,
|
|
9
|
+
import { TOTAL_STEPS, STEP_KB, STEP_AI, STEP_AGENTS, STEP_REVIEW } from './constants';
|
|
10
10
|
import StepKB from './StepKB';
|
|
11
11
|
import StepAI from './StepAI';
|
|
12
|
-
import StepPorts from './StepPorts';
|
|
13
|
-
import StepSecurity from './StepSecurity';
|
|
14
12
|
import StepAgents from './StepAgents';
|
|
15
13
|
import StepReview from './StepReview';
|
|
16
14
|
import { RestartButton } from './StepReview';
|
|
@@ -122,8 +120,8 @@ export default function SetupWizard() {
|
|
|
122
120
|
openaiModel: 'gpt-5.4',
|
|
123
121
|
openaiBaseUrl: '',
|
|
124
122
|
openaiKeyMask: '',
|
|
125
|
-
webPort:
|
|
126
|
-
mcpPort:
|
|
123
|
+
webPort: 3456,
|
|
124
|
+
mcpPort: 8781,
|
|
127
125
|
authToken: '',
|
|
128
126
|
webPassword: '',
|
|
129
127
|
});
|
|
@@ -184,16 +182,16 @@ export default function SetupWizard() {
|
|
|
184
182
|
});
|
|
185
183
|
}, []);
|
|
186
184
|
|
|
187
|
-
// Auto-check ports when entering
|
|
185
|
+
// Auto-check ports when entering AI step (ports are in Advanced section)
|
|
188
186
|
useEffect(() => {
|
|
189
|
-
if (step ===
|
|
187
|
+
if (step === STEP_AI) {
|
|
190
188
|
checkPort(state.webPort, 'web');
|
|
191
189
|
checkPort(state.mcpPort, 'mcp');
|
|
192
190
|
}
|
|
193
191
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
194
192
|
}, [step]);
|
|
195
193
|
|
|
196
|
-
// Load agents when entering
|
|
194
|
+
// Load agents when entering Agents step
|
|
197
195
|
useEffect(() => {
|
|
198
196
|
if (step === STEP_AGENTS && !agentsLoaded && !agentsLoading) {
|
|
199
197
|
setAgentsLoading(true);
|
|
@@ -256,15 +254,17 @@ export default function SetupWizard() {
|
|
|
256
254
|
const portConflict = state.webPort === state.mcpPort;
|
|
257
255
|
|
|
258
256
|
const canNext = () => {
|
|
259
|
-
if (step === STEP_KB)
|
|
260
|
-
|
|
257
|
+
if (step === STEP_KB) {
|
|
258
|
+
// KB path required + password required
|
|
259
|
+
return state.mindRoot.trim().length > 0 && state.webPassword.trim().length > 0;
|
|
260
|
+
}
|
|
261
|
+
if (step === STEP_AI) {
|
|
262
|
+
// Ports validation (only when Advanced is open and ports were modified)
|
|
261
263
|
if (portConflict) return false;
|
|
262
264
|
if (webPortStatus.checking || mcpPortStatus.checking) return false;
|
|
263
|
-
if
|
|
264
|
-
return
|
|
265
|
-
|
|
266
|
-
state.mcpPort >= 1024 && state.mcpPort <= 65535
|
|
267
|
-
);
|
|
265
|
+
// Allow next if ports haven't been checked yet (user didn't open Advanced)
|
|
266
|
+
if (webPortStatus.available === false || mcpPortStatus.available === false) return false;
|
|
267
|
+
return true;
|
|
268
268
|
}
|
|
269
269
|
return true;
|
|
270
270
|
};
|
|
@@ -359,32 +359,22 @@ export default function SetupWizard() {
|
|
|
359
359
|
</div>
|
|
360
360
|
|
|
361
361
|
<div className="flex justify-center">
|
|
362
|
-
<StepDots step={step} setStep={setStep} stepTitles={s.stepTitles} disabled={submitting || completed} />
|
|
362
|
+
<StepDots step={step} setStep={setStep} stepTitles={s.stepTitles} disabled={submitting || completed} numberedSteps={STEP_REVIEW} />
|
|
363
363
|
</div>
|
|
364
364
|
|
|
365
365
|
<h2 className="text-lg font-semibold mb-5" style={{ color: 'var(--foreground)' }}>
|
|
366
|
-
{s.stepTitles[step]}
|
|
366
|
+
{step === STEP_REVIEW ? `✓ ${s.stepTitles[step]}` : s.stepTitles[step]}
|
|
367
367
|
</h2>
|
|
368
368
|
|
|
369
369
|
{step === 0 && <StepKB state={state} update={update} t={t} homeDir={homeDir} />}
|
|
370
|
-
{step === 1 &&
|
|
371
|
-
|
|
372
|
-
<StepPorts
|
|
373
|
-
state={state} update={update}
|
|
370
|
+
{step === 1 && (
|
|
371
|
+
<StepAI state={state} update={update} s={s} onCopyToken={copyToken}
|
|
374
372
|
webPortStatus={webPortStatus} mcpPortStatus={mcpPortStatus}
|
|
375
373
|
setWebPortStatus={setWebPortStatus} setMcpPortStatus={setMcpPortStatus}
|
|
376
|
-
checkPort={checkPort} portConflict={portConflict}
|
|
377
|
-
/>
|
|
378
|
-
)}
|
|
379
|
-
{step === 3 && (
|
|
380
|
-
<StepSecurity
|
|
381
|
-
authToken={state.authToken}
|
|
382
|
-
onCopy={copyToken} onGenerate={generateToken}
|
|
383
|
-
webPassword={state.webPassword} onPasswordChange={v => update('webPassword', v)}
|
|
384
|
-
s={s}
|
|
374
|
+
checkPort={checkPort} portConflict={portConflict}
|
|
385
375
|
/>
|
|
386
376
|
)}
|
|
387
|
-
{step ===
|
|
377
|
+
{step === 2 && (
|
|
388
378
|
<StepAgents
|
|
389
379
|
agents={agents} agentsLoading={agentsLoading}
|
|
390
380
|
selectedAgents={selectedAgents} setSelectedAgents={setSelectedAgents}
|
|
@@ -394,7 +384,7 @@ export default function SetupWizard() {
|
|
|
394
384
|
template={state.template}
|
|
395
385
|
/>
|
|
396
386
|
)}
|
|
397
|
-
{step ===
|
|
387
|
+
{step === 3 && (
|
|
398
388
|
<StepReview
|
|
399
389
|
state={state} selectedAgents={selectedAgents}
|
|
400
390
|
agentStatuses={agentStatuses} onRetryAgent={retryAgent}
|
|
@@ -15,7 +15,7 @@ export const onboardingEn = {
|
|
|
15
15
|
dismiss: 'Dismiss',
|
|
16
16
|
},
|
|
17
17
|
setup: {
|
|
18
|
-
stepTitles: ['Knowledge Base', 'AI
|
|
18
|
+
stepTitles: ['Knowledge Base', 'AI Configuration', 'Agent Tools', 'Confirm'],
|
|
19
19
|
// Step 1
|
|
20
20
|
kbPath: 'Knowledge base path',
|
|
21
21
|
kbPathHint: 'Absolute path to your notes directory.',
|
|
@@ -56,8 +56,12 @@ export const onboardingEn = {
|
|
|
56
56
|
generateToken: 'Generate',
|
|
57
57
|
copyToken: 'Copy',
|
|
58
58
|
copiedToken: 'Copied!',
|
|
59
|
-
webPassword: 'Web
|
|
60
|
-
webPasswordHint: '
|
|
59
|
+
webPassword: 'Web Password',
|
|
60
|
+
webPasswordHint: 'Protect your knowledge base from unauthorized browser access.',
|
|
61
|
+
webPasswordRequired: 'Password is required to protect your data.',
|
|
62
|
+
advancedPorts: 'Advanced Settings',
|
|
63
|
+
tokenSectionTitle: 'MCP Auth Token (auto-generated)',
|
|
64
|
+
tokenSectionHint: 'Used by AI agents to connect to your MindOS server.',
|
|
61
65
|
// Step 5 — Agent Tools
|
|
62
66
|
agentToolsTitle: 'Agent Tools',
|
|
63
67
|
agentToolsHint: 'Select AI agents to configure with MindOS MCP. Agents marked "not installed" can be configured now — they will work once you install the app.',
|
|
@@ -210,7 +214,7 @@ export const onboardingZh = {
|
|
|
210
214
|
dismiss: '关闭',
|
|
211
215
|
},
|
|
212
216
|
setup: {
|
|
213
|
-
stepTitles: ['知识库', 'AI
|
|
217
|
+
stepTitles: ['知识库', 'AI 配置', 'Agent 工具', '确认'],
|
|
214
218
|
// Step 1
|
|
215
219
|
kbPath: '知识库路径',
|
|
216
220
|
kbPathHint: '笔记目录的绝对路径。',
|
|
@@ -251,8 +255,12 @@ export const onboardingZh = {
|
|
|
251
255
|
generateToken: '生成',
|
|
252
256
|
copyToken: '复制',
|
|
253
257
|
copiedToken: '已复制!',
|
|
254
|
-
webPassword: '
|
|
255
|
-
webPasswordHint: '
|
|
258
|
+
webPassword: '访问密码',
|
|
259
|
+
webPasswordHint: '保护你的知识库,防止未授权的浏览器访问。',
|
|
260
|
+
webPasswordRequired: '密码是必填项,用于保护你的数据。',
|
|
261
|
+
advancedPorts: '高级设置',
|
|
262
|
+
tokenSectionTitle: 'MCP 认证令牌(已自动生成)',
|
|
263
|
+
tokenSectionHint: 'AI Agent 连接你的 MindOS 服务器时使用。',
|
|
256
264
|
// Step 5 — Agent Tools
|
|
257
265
|
agentToolsTitle: 'Agent 工具',
|
|
258
266
|
agentToolsHint: '选择要与 MindOS MCP 配置的 AI Agent。标注「未安装」的 agent 可以先行配置,安装应用后即可生效。',
|
package/package.json
CHANGED