@geminilight/mindos 0.2.0 → 0.3.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/README.md +3 -3
- package/README_zh.md +38 -5
- package/app/README.md +1 -1
- package/app/app/api/init/route.ts +22 -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/layout.tsx +10 -1
- package/app/app/page.tsx +5 -0
- package/app/app/register-sw.tsx +15 -0
- package/app/app/setup/page.tsx +9 -0
- package/app/components/HomeContent.tsx +8 -2
- package/app/components/OnboardingView.tsx +161 -0
- package/app/components/SettingsModal.tsx +7 -1
- package/app/components/SetupWizard.tsx +479 -0
- package/app/components/Sidebar.tsx +28 -4
- package/app/components/SyncStatusBar.tsx +273 -0
- package/app/components/renderers/AgentInspectorRenderer.tsx +8 -5
- package/app/components/settings/SyncTab.tsx +113 -21
- package/app/lib/agent/log.ts +44 -0
- package/app/lib/agent/tools.ts +39 -18
- package/app/lib/i18n.ts +170 -0
- package/app/lib/renderers/index.ts +13 -0
- package/app/lib/settings.ts +13 -2
- package/app/lib/template.ts +45 -0
- package/app/public/icons/icon-192.png +0 -0
- package/app/public/icons/icon-512.png +0 -0
- package/app/public/manifest.json +26 -0
- package/app/public/sw.js +66 -0
- package/bin/cli.js +21 -0
- package/bin/lib/mcp-install.js +225 -70
- package/bin/lib/startup.js +24 -1
- package/mcp/src/index.ts +37 -10
- package/package.json +1 -1
- package/scripts/setup.js +105 -2
- package/templates/README.md +1 -1
package/scripts/setup.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Usage: npm run setup OR mindos onboard
|
|
7
7
|
*
|
|
8
8
|
* Steps:
|
|
9
|
-
* 1. Choose knowledge base path → default
|
|
9
|
+
* 1. Choose knowledge base path → default ~/MindOS
|
|
10
10
|
* 2. Choose template (en / zh / empty / custom) → copy to knowledge base path
|
|
11
11
|
* 3. Choose ports (web + mcp) — checked for conflicts upfront
|
|
12
12
|
* 4. Auth token (auto-generated or passphrase-seeded)
|
|
@@ -26,7 +26,7 @@ import { homedir, tmpdir, networkInterfaces } from 'node:os';
|
|
|
26
26
|
import { fileURLToPath } from 'node:url';
|
|
27
27
|
import { createInterface } from 'node:readline';
|
|
28
28
|
import { pipeline } from 'node:stream/promises';
|
|
29
|
-
import { execSync } from 'node:child_process';
|
|
29
|
+
import { execSync, spawn } from 'node:child_process';
|
|
30
30
|
import { randomBytes, createHash } from 'node:crypto';
|
|
31
31
|
import { createConnection } from 'node:net';
|
|
32
32
|
|
|
@@ -41,6 +41,14 @@ const T = {
|
|
|
41
41
|
title: { en: '🧠 MindOS Setup', zh: '🧠 MindOS 初始化' },
|
|
42
42
|
langHint: { en: ' ← → switch language / 切换语言 ↑ ↓ navigate Enter confirm', zh: ' ← → switch language / 切换语言 ↑ ↓ 上下切换 Enter 确认' },
|
|
43
43
|
|
|
44
|
+
// mode selection
|
|
45
|
+
modePrompt: { en: 'Setup mode', zh: '配置方式' },
|
|
46
|
+
modeOpts: { en: ['CLI — terminal wizard', 'GUI — browser wizard (recommended)'], zh: ['CLI — 终端向导', 'GUI — 浏览器向导(推荐)'] },
|
|
47
|
+
modeVals: ['cli', 'gui'],
|
|
48
|
+
guiStarting: { en: '⏳ Starting server for GUI setup...', zh: '⏳ 正在启动服务...' },
|
|
49
|
+
guiReady: { en: (url) => `🌐 Complete setup in browser: ${url}`, zh: (url) => `🌐 在浏览器中完成配置: ${url}` },
|
|
50
|
+
guiOpenFailed: { en: (url) => ` Could not open browser automatically. Open this URL manually:\n ${url}`, zh: (url) => ` 无法自动打开浏览器,请手动访问:\n ${url}` },
|
|
51
|
+
|
|
44
52
|
// step labels
|
|
45
53
|
step: { en: (n, total) => `Step ${n}/${total}`, zh: (n, total) => `步骤 ${n}/${total}` },
|
|
46
54
|
stepTitles: {
|
|
@@ -109,6 +117,8 @@ const T = {
|
|
|
109
117
|
yesNo: { en: '[y/N]', zh: '[y/N]' },
|
|
110
118
|
yesNoDefault: { en: '[Y/n]', zh: '[Y/n]' },
|
|
111
119
|
startNow: { en: 'Start MindOS now?', zh: '现在启动 MindOS?' },
|
|
120
|
+
syncSetup: { en: 'Set up cross-device sync via Git?', zh: '是否配置 Git 跨设备同步?' },
|
|
121
|
+
syncLater: { en: ' → Run `mindos sync init` anytime to set up sync later.', zh: ' → 随时运行 `mindos sync init` 配置同步。' },
|
|
112
122
|
|
|
113
123
|
// next steps (onboard — keep it minimal, details shown on `mindos start`)
|
|
114
124
|
nextSteps: {
|
|
@@ -491,11 +501,95 @@ async function applyTemplate(tpl, mindDir) {
|
|
|
491
501
|
}
|
|
492
502
|
}
|
|
493
503
|
|
|
504
|
+
// ── GUI Setup ─────────────────────────────────────────────────────────────────
|
|
505
|
+
|
|
506
|
+
function openBrowser(url) {
|
|
507
|
+
try {
|
|
508
|
+
const platform = process.platform;
|
|
509
|
+
if (platform === 'darwin') {
|
|
510
|
+
execSync(`open "${url}"`, { stdio: 'ignore' });
|
|
511
|
+
} else if (platform === 'linux') {
|
|
512
|
+
// Check for WSL
|
|
513
|
+
const isWSL = existsSync('/proc/version') &&
|
|
514
|
+
readFileSync('/proc/version', 'utf-8').toLowerCase().includes('microsoft');
|
|
515
|
+
if (isWSL) {
|
|
516
|
+
execSync(`cmd.exe /c start "${url}"`, { stdio: 'ignore' });
|
|
517
|
+
} else {
|
|
518
|
+
execSync(`xdg-open "${url}"`, { stdio: 'ignore' });
|
|
519
|
+
}
|
|
520
|
+
} else {
|
|
521
|
+
execSync(`cmd.exe /c start "${url}"`, { stdio: 'ignore' });
|
|
522
|
+
}
|
|
523
|
+
return true;
|
|
524
|
+
} catch {
|
|
525
|
+
return false;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
async function startGuiSetup() {
|
|
530
|
+
// Ensure ~/.mindos directory exists
|
|
531
|
+
mkdirSync(MINDOS_DIR, { recursive: true });
|
|
532
|
+
|
|
533
|
+
// Read or create config, set setupPending
|
|
534
|
+
let config = {};
|
|
535
|
+
try { config = JSON.parse(readFileSync(CONFIG_PATH, 'utf-8')); } catch { /* ignore */ }
|
|
536
|
+
config.setupPending = true;
|
|
537
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\n');
|
|
538
|
+
|
|
539
|
+
// Find a free port
|
|
540
|
+
const port = await findFreePort(3000);
|
|
541
|
+
if (config.port === undefined) {
|
|
542
|
+
config.port = port;
|
|
543
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\n');
|
|
544
|
+
}
|
|
545
|
+
const usePort = config.port || port;
|
|
546
|
+
|
|
547
|
+
write(c.yellow(t('guiStarting') + '\n'));
|
|
548
|
+
|
|
549
|
+
// Start the server in the background
|
|
550
|
+
const cliPath = resolve(__dirname, '../bin/cli.js');
|
|
551
|
+
const child = spawn(process.execPath, [cliPath, 'start'], {
|
|
552
|
+
detached: true,
|
|
553
|
+
stdio: 'ignore',
|
|
554
|
+
env: { ...process.env, PORT: String(usePort) },
|
|
555
|
+
});
|
|
556
|
+
child.unref();
|
|
557
|
+
|
|
558
|
+
// Wait for the server to be ready
|
|
559
|
+
const { waitForHttp } = await import('../bin/lib/gateway.js');
|
|
560
|
+
const ready = await waitForHttp(usePort, { retries: 60, intervalMs: 1000, label: 'MindOS' });
|
|
561
|
+
|
|
562
|
+
if (!ready) {
|
|
563
|
+
write(c.red('\n✘ Server failed to start.\n'));
|
|
564
|
+
process.exit(1);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const url = `http://localhost:${usePort}/setup`;
|
|
568
|
+
console.log(`\n${c.green(tf('guiReady', url))}\n`);
|
|
569
|
+
|
|
570
|
+
const opened = openBrowser(url);
|
|
571
|
+
if (!opened) {
|
|
572
|
+
console.log(c.dim(tf('guiOpenFailed', url)));
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
process.exit(0);
|
|
576
|
+
}
|
|
577
|
+
|
|
494
578
|
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
495
579
|
|
|
496
580
|
async function main() {
|
|
497
581
|
console.log(`\n${c.bold(t('title'))}\n\n${c.dim(t('langHint'))}\n`);
|
|
498
582
|
|
|
583
|
+
// ── Mode selection: CLI or GUI ───────────────────────────────────────────
|
|
584
|
+
const mode = await select('modePrompt', 'modeOpts', 'modeVals');
|
|
585
|
+
|
|
586
|
+
if (mode === 'gui') {
|
|
587
|
+
await startGuiSetup();
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// ── CLI mode continues below ─────────────────────────────────────────────
|
|
592
|
+
|
|
499
593
|
// ── Early overwrite check ─────────────────────────────────────────────────
|
|
500
594
|
if (existsSync(CONFIG_PATH)) {
|
|
501
595
|
let existing = {};
|
|
@@ -674,6 +768,15 @@ async function main() {
|
|
|
674
768
|
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\n');
|
|
675
769
|
console.log(`\n${c.green(t('cfgSaved'))}: ${c.dim(CONFIG_PATH)}`);
|
|
676
770
|
|
|
771
|
+
// ── Sync setup (optional) ──────────────────────────────────────────────────
|
|
772
|
+
const wantSync = await askYesNo('syncSetup');
|
|
773
|
+
if (wantSync) {
|
|
774
|
+
const { initSync } = await import('../bin/lib/sync.js');
|
|
775
|
+
await initSync(mindDir);
|
|
776
|
+
} else {
|
|
777
|
+
console.log(c.dim(t('syncLater')));
|
|
778
|
+
}
|
|
779
|
+
|
|
677
780
|
const installDaemon = startMode === 'daemon' || process.argv.includes('--install-daemon');
|
|
678
781
|
finish(mindDir, config.startMode, config.mcpPort, config.authToken, installDaemon);
|
|
679
782
|
}
|
package/templates/README.md
CHANGED
|
@@ -18,7 +18,7 @@ If you need to manually initialize:
|
|
|
18
18
|
mindos onboard
|
|
19
19
|
|
|
20
20
|
# 2) Or copy a preset manually to your knowledge base directory
|
|
21
|
-
cp -r templates/en
|
|
21
|
+
cp -r templates/en ~/MindOS
|
|
22
22
|
# then set mindRoot in ~/.mindos/config.json
|
|
23
23
|
|
|
24
24
|
# 3) Start filling content from 👤 Profile (en) or 👤 画像 (zh)
|