@geminilight/mindos 0.5.21 → 0.5.23
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/ask/route.ts +31 -9
- package/app/app/api/bootstrap/route.ts +1 -0
- package/app/app/api/monitoring/route.ts +95 -0
- package/app/app/globals.css +14 -0
- package/app/app/setup/page.tsx +3 -2
- package/app/components/ActivityBar.tsx +183 -0
- package/app/components/AskFab.tsx +39 -97
- package/app/components/AskModal.tsx +13 -371
- package/app/components/Breadcrumb.tsx +4 -4
- package/app/components/FileTree.tsx +21 -4
- package/app/components/Logo.tsx +39 -0
- package/app/components/Panel.tsx +152 -0
- package/app/components/RightAskPanel.tsx +72 -0
- package/app/components/SettingsModal.tsx +9 -235
- package/app/components/SidebarLayout.tsx +426 -12
- package/app/components/SyncStatusBar.tsx +74 -53
- package/app/components/TableOfContents.tsx +4 -2
- package/app/components/ask/AskContent.tsx +418 -0
- package/app/components/ask/MessageList.tsx +2 -2
- package/app/components/panels/AgentsPanel.tsx +231 -0
- package/app/components/panels/PanelHeader.tsx +35 -0
- package/app/components/panels/PluginsPanel.tsx +106 -0
- package/app/components/panels/SearchPanel.tsx +178 -0
- package/app/components/panels/SyncPopover.tsx +105 -0
- package/app/components/renderers/csv/TableView.tsx +4 -4
- package/app/components/settings/AgentsTab.tsx +240 -0
- package/app/components/settings/AiTab.tsx +39 -1
- package/app/components/settings/KnowledgeTab.tsx +116 -2
- package/app/components/settings/McpTab.tsx +6 -6
- package/app/components/settings/MonitoringTab.tsx +202 -0
- package/app/components/settings/SettingsContent.tsx +343 -0
- package/app/components/settings/types.ts +1 -1
- package/app/components/setup/index.tsx +2 -23
- package/app/hooks/useResizeDrag.ts +78 -0
- package/app/instrumentation.ts +7 -2
- package/app/lib/agent/log.ts +1 -0
- package/app/lib/agent/model.ts +33 -10
- package/app/lib/api.ts +12 -3
- package/app/lib/core/csv.ts +2 -1
- package/app/lib/core/fs-ops.ts +7 -6
- package/app/lib/core/index.ts +1 -1
- package/app/lib/core/lines.ts +7 -6
- package/app/lib/core/search-index.ts +174 -0
- package/app/lib/core/search.ts +30 -1
- package/app/lib/core/security.ts +6 -3
- package/app/lib/errors.ts +108 -0
- package/app/lib/format.ts +19 -0
- package/app/lib/fs.ts +6 -3
- package/app/lib/i18n-en.ts +49 -6
- package/app/lib/i18n-zh.ts +48 -5
- package/app/lib/metrics.ts +81 -0
- package/app/next-env.d.ts +1 -1
- package/app/next.config.ts +1 -1
- package/app/package.json +2 -2
- package/bin/cli.js +27 -97
- package/package.json +4 -2
- package/scripts/setup.js +2 -12
- package/skills/mindos/SKILL.md +226 -8
- package/skills/mindos-zh/SKILL.md +226 -8
- package/app/package-lock.json +0 -15736
package/app/lib/i18n-zh.ts
CHANGED
|
@@ -41,7 +41,7 @@ export const zh = {
|
|
|
41
41
|
createToActivate: '创建 {file} 以启用此插件',
|
|
42
42
|
shortcuts: {
|
|
43
43
|
searchFiles: '搜索文件',
|
|
44
|
-
askAI: '
|
|
44
|
+
askAI: 'MindOS Agent',
|
|
45
45
|
editFile: '编辑文件',
|
|
46
46
|
save: '保存',
|
|
47
47
|
settings: '设置',
|
|
@@ -55,7 +55,7 @@ export const zh = {
|
|
|
55
55
|
},
|
|
56
56
|
sidebar: {
|
|
57
57
|
searchTitle: '搜索 (⌘K)',
|
|
58
|
-
askTitle: '
|
|
58
|
+
askTitle: 'MindOS Agent (⌘/)',
|
|
59
59
|
settingsTitle: '设置 (⌘,)',
|
|
60
60
|
collapseTitle: '收起侧栏',
|
|
61
61
|
expandTitle: '展开侧栏',
|
|
@@ -129,7 +129,7 @@ export const zh = {
|
|
|
129
129
|
},
|
|
130
130
|
settings: {
|
|
131
131
|
title: '设置',
|
|
132
|
-
tabs: { ai: 'AI', appearance: '外观', knowledge: '
|
|
132
|
+
tabs: { ai: 'AI', appearance: '外观', knowledge: '通用', sync: '同步', mcp: 'MCP & Skills', plugins: '插件', shortcuts: '快捷键', monitoring: '监控', agents: 'Agents' },
|
|
133
133
|
ai: {
|
|
134
134
|
provider: '服务商',
|
|
135
135
|
model: '模型',
|
|
@@ -287,6 +287,49 @@ export const zh = {
|
|
|
287
287
|
configureFor: '配置目标',
|
|
288
288
|
configPath: '配置路径',
|
|
289
289
|
},
|
|
290
|
+
monitoring: {
|
|
291
|
+
system: '系统',
|
|
292
|
+
heapMemory: '堆内存',
|
|
293
|
+
rss: 'RSS',
|
|
294
|
+
uptime: '运行时间',
|
|
295
|
+
nodeVersion: 'Node',
|
|
296
|
+
application: '应用',
|
|
297
|
+
requests: '请求数',
|
|
298
|
+
toolCalls: '工具调用',
|
|
299
|
+
avgResponse: '平均响应',
|
|
300
|
+
tokens: 'Token',
|
|
301
|
+
errors: '错误',
|
|
302
|
+
knowledgeBase: '知识库',
|
|
303
|
+
files: '文件数',
|
|
304
|
+
totalSize: '总大小',
|
|
305
|
+
rootPath: '根目录',
|
|
306
|
+
mcpStatus: '状态',
|
|
307
|
+
mcpRunning: '运行中',
|
|
308
|
+
mcpStopped: '已停止',
|
|
309
|
+
mcpPort: '端口',
|
|
310
|
+
autoRefresh: '每 5 秒自动刷新',
|
|
311
|
+
fetchError: '加载监控数据失败',
|
|
312
|
+
},
|
|
313
|
+
agents: {
|
|
314
|
+
mcpServer: 'MCP 服务器',
|
|
315
|
+
running: '运行中',
|
|
316
|
+
stopped: '未运行',
|
|
317
|
+
onPort: (port: number) => `端口 :${port}`,
|
|
318
|
+
refresh: '刷新',
|
|
319
|
+
refreshing: '刷新中...',
|
|
320
|
+
connected: '已连接',
|
|
321
|
+
connectedCount: (n: number) => `已连接 (${n})`,
|
|
322
|
+
detectedNotConfigured: '已检测未配置',
|
|
323
|
+
detectedCount: (n: number) => `已检测未配置 (${n})`,
|
|
324
|
+
notDetected: '未检测到',
|
|
325
|
+
notDetectedCount: (n: number) => `未检测到 (${n})`,
|
|
326
|
+
showAll: '显示全部',
|
|
327
|
+
hideAll: '收起',
|
|
328
|
+
connect: '连接',
|
|
329
|
+
noAgents: '本机未检测到任何 Agent。',
|
|
330
|
+
fetchError: '加载 Agent 数据失败',
|
|
331
|
+
autoRefresh: '每 30 秒自动刷新',
|
|
332
|
+
},
|
|
290
333
|
save: '保存',
|
|
291
334
|
saved: '已保存',
|
|
292
335
|
saveFailed: '保存失败',
|
|
@@ -305,7 +348,7 @@ export const zh = {
|
|
|
305
348
|
},
|
|
306
349
|
shortcuts: [
|
|
307
350
|
{ keys: ['⌘', 'K'], description: '搜索' },
|
|
308
|
-
{ keys: ['⌘', '/'], description: '
|
|
351
|
+
{ keys: ['⌘', '/'], description: 'MindOS Agent' },
|
|
309
352
|
{ keys: ['⌘', ','], description: '设置' },
|
|
310
353
|
{ keys: ['E'], description: '编辑当前文件' },
|
|
311
354
|
{ keys: ['⌘', 'S'], description: '保存' },
|
|
@@ -450,7 +493,7 @@ export const zh = {
|
|
|
450
493
|
welcomeTitle: '欢迎使用 MindOS!',
|
|
451
494
|
welcomeDesc: '初始化完成。可以开始向 AI 提问、浏览知识库,或配置 MCP Agent。',
|
|
452
495
|
welcomeLinkReconfigure: '重新配置',
|
|
453
|
-
welcomeLinkAskAI: '
|
|
496
|
+
welcomeLinkAskAI: 'MindOS Agent',
|
|
454
497
|
welcomeLinkMCP: 'MCP 设置',
|
|
455
498
|
},
|
|
456
499
|
guide: {
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory metrics collector for MindOS runtime observability.
|
|
3
|
+
*
|
|
4
|
+
* Singleton — import { metrics } from '@/lib/metrics' in any server-side code.
|
|
5
|
+
* Data resets when the process restarts (no persistence needed).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface MetricsSnapshot {
|
|
9
|
+
processStartTime: number;
|
|
10
|
+
agentRequests: number;
|
|
11
|
+
toolExecutions: number;
|
|
12
|
+
totalTokens: { input: number; output: number };
|
|
13
|
+
avgResponseTimeMs: number;
|
|
14
|
+
errors: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const MAX_RESPONSE_TIMES = 100;
|
|
18
|
+
|
|
19
|
+
class MetricsCollector {
|
|
20
|
+
private processStartTime = Date.now();
|
|
21
|
+
private agentRequests = 0;
|
|
22
|
+
private toolExecutions = 0;
|
|
23
|
+
private totalTokens = { input: 0, output: 0 };
|
|
24
|
+
private responseTimes: number[] = [];
|
|
25
|
+
private errors = 0;
|
|
26
|
+
|
|
27
|
+
/** Record a completed agent request with its duration. */
|
|
28
|
+
recordRequest(durationMs: number): void {
|
|
29
|
+
this.agentRequests++;
|
|
30
|
+
this.responseTimes.push(durationMs);
|
|
31
|
+
if (this.responseTimes.length > MAX_RESPONSE_TIMES) {
|
|
32
|
+
this.responseTimes.shift();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Increment the tool execution counter. */
|
|
37
|
+
recordToolExecution(): void {
|
|
38
|
+
this.toolExecutions++;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Accumulate token usage. */
|
|
42
|
+
recordTokens(input: number, output: number): void {
|
|
43
|
+
this.totalTokens.input += input;
|
|
44
|
+
this.totalTokens.output += output;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Increment the error counter. */
|
|
48
|
+
recordError(): void {
|
|
49
|
+
this.errors++;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Return a read-only snapshot of all metrics. */
|
|
53
|
+
getSnapshot(): MetricsSnapshot {
|
|
54
|
+
const avg =
|
|
55
|
+
this.responseTimes.length > 0
|
|
56
|
+
? Math.round(this.responseTimes.reduce((a, b) => a + b, 0) / this.responseTimes.length)
|
|
57
|
+
: 0;
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
processStartTime: this.processStartTime,
|
|
61
|
+
agentRequests: this.agentRequests,
|
|
62
|
+
toolExecutions: this.toolExecutions,
|
|
63
|
+
totalTokens: { ...this.totalTokens },
|
|
64
|
+
avgResponseTimeMs: avg,
|
|
65
|
+
errors: this.errors,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Reset all counters (useful for testing). */
|
|
70
|
+
reset(): void {
|
|
71
|
+
this.processStartTime = Date.now();
|
|
72
|
+
this.agentRequests = 0;
|
|
73
|
+
this.toolExecutions = 0;
|
|
74
|
+
this.totalTokens = { input: 0, output: 0 };
|
|
75
|
+
this.responseTimes = [];
|
|
76
|
+
this.errors = 0;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Global singleton — shared across all requests in the same Node process. */
|
|
81
|
+
export const metrics = new MetricsCollector();
|
package/app/next-env.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="next" />
|
|
2
2
|
/// <reference types="next/image-types/global" />
|
|
3
|
-
import "./.next/types/routes.d.ts";
|
|
3
|
+
import "./.next/dev/types/routes.d.ts";
|
|
4
4
|
|
|
5
5
|
// NOTE: This file should not be edited
|
|
6
6
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
package/app/next.config.ts
CHANGED
|
@@ -3,7 +3,7 @@ import path from "path";
|
|
|
3
3
|
|
|
4
4
|
const nextConfig: NextConfig = {
|
|
5
5
|
transpilePackages: ['github-slugger'],
|
|
6
|
-
serverExternalPackages: ['pdfjs-dist', 'pdf-parse', 'chokidar'],
|
|
6
|
+
serverExternalPackages: ['pdfjs-dist', 'pdf-parse', 'chokidar', 'openai', '@mariozechner/pi-ai', '@mariozechner/pi-agent-core'],
|
|
7
7
|
outputFileTracingRoot: path.join(__dirname),
|
|
8
8
|
turbopack: {
|
|
9
9
|
root: path.join(__dirname),
|
package/app/package.json
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"@codemirror/state": "^6.5.4",
|
|
17
17
|
"@codemirror/theme-one-dark": "^6.1.3",
|
|
18
18
|
"@codemirror/view": "^6.39.16",
|
|
19
|
-
"@mariozechner/pi-agent-core": "^0.
|
|
20
|
-
"@mariozechner/pi-ai": "^0.
|
|
19
|
+
"@mariozechner/pi-agent-core": "^0.61.0",
|
|
20
|
+
"@mariozechner/pi-ai": "^0.61.0",
|
|
21
21
|
"@sinclair/typebox": "^0.34.33",
|
|
22
22
|
"@tiptap/extension-image": "^3.20.1",
|
|
23
23
|
"@tiptap/extension-link": "^3.20.1",
|
package/bin/cli.js
CHANGED
|
@@ -245,7 +245,7 @@ const commands = {
|
|
|
245
245
|
// Do NOT call start() here — kickstart -k would kill the just-started process,
|
|
246
246
|
// causing a port-conflict race condition with KeepAlive restart loops.
|
|
247
247
|
console.log(dim(' (First run may take a few minutes to install dependencies and build the app.)'));
|
|
248
|
-
const ready = await waitForHttp(Number(webPort), { retries:
|
|
248
|
+
const ready = await waitForHttp(Number(webPort), { retries: 120, intervalMs: 2000, label: 'Web UI', logFile: LOG_PATH });
|
|
249
249
|
if (!ready) {
|
|
250
250
|
console.error(red('\n✘ Service started but Web UI did not become ready in time.'));
|
|
251
251
|
console.error(dim(' Check logs with: mindos logs\n'));
|
|
@@ -271,36 +271,22 @@ const commands = {
|
|
|
271
271
|
const webPort = process.env.MINDOS_WEB_PORT || '3456';
|
|
272
272
|
const mcpPort = process.env.MINDOS_MCP_PORT || '8781';
|
|
273
273
|
|
|
274
|
-
// ── Auto-migrate
|
|
274
|
+
// ── Auto-migrate user-rules.md to root user-skill-rules.md ─────────────
|
|
275
275
|
try {
|
|
276
276
|
const cfg = JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
|
|
277
277
|
const mr = cfg.mindRoot;
|
|
278
278
|
if (mr && existsSync(mr)) {
|
|
279
279
|
const isZh = cfg.disabledSkills?.includes('mindos');
|
|
280
280
|
const sName = isZh ? 'mindos-zh' : 'mindos';
|
|
281
|
-
const lang = isZh ? 'zh' : 'en';
|
|
282
281
|
const sDir = resolve(mr, '.agents', 'skills', sName);
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
// Migrate
|
|
286
|
-
if (
|
|
287
|
-
const
|
|
288
|
-
if (existsSync(
|
|
289
|
-
cpSync(
|
|
290
|
-
|
|
291
|
-
const p = resolve(sDir, f);
|
|
292
|
-
if (existsSync(p)) rmSync(p);
|
|
293
|
-
}
|
|
294
|
-
console.log(` ${green('✓')} ${dim('Skill rules migrated to skill-rules.md')}`);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
// Init if .agents/skills/ doesn't exist at all
|
|
298
|
-
if (!existsSync(sDir)) {
|
|
299
|
-
const srcDir = resolve(ROOT, 'templates', 'skill-rules', lang);
|
|
300
|
-
if (existsSync(srcDir)) {
|
|
301
|
-
mkdirSync(sDir, { recursive: true });
|
|
302
|
-
cpSync(srcDir, sDir, { recursive: true });
|
|
303
|
-
console.log(` ${green('✓')} ${dim('Skill rules initialized')}`);
|
|
282
|
+
const rootUserRules = resolve(mr, 'user-skill-rules.md');
|
|
283
|
+
|
|
284
|
+
// Migrate: .agents/skills/{name}/user-rules.md → {mindRoot}/user-skill-rules.md
|
|
285
|
+
if (!existsSync(rootUserRules)) {
|
|
286
|
+
const oldUserRules = resolve(sDir, 'user-rules.md');
|
|
287
|
+
if (existsSync(oldUserRules)) {
|
|
288
|
+
cpSync(oldUserRules, rootUserRules);
|
|
289
|
+
console.log(` ${green('✓')} ${dim('Migrated user-rules.md → user-skill-rules.md')}`);
|
|
304
290
|
}
|
|
305
291
|
}
|
|
306
292
|
}
|
|
@@ -440,7 +426,6 @@ ${dim('Shortcut: mindos start --daemon → install + start in one step')}
|
|
|
440
426
|
|
|
441
427
|
// ── init-skills ──────────────────────────────────────────────────────────
|
|
442
428
|
'init-skills': async () => {
|
|
443
|
-
const force = process.argv.includes('--force');
|
|
444
429
|
console.log(`\n${bold('📦 Initialize Skill Rules')}\n`);
|
|
445
430
|
|
|
446
431
|
if (!existsSync(CONFIG_PATH)) {
|
|
@@ -460,56 +445,23 @@ ${dim('Shortcut: mindos start --daemon → install + start in one step')}
|
|
|
460
445
|
process.exit(1);
|
|
461
446
|
}
|
|
462
447
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
if (!existsSync(sourceDir)) {
|
|
470
|
-
console.log(` ${red('✘')} Template not found: ${dim(sourceDir)}\n`);
|
|
471
|
-
process.exit(1);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
const files = ['skill-rules.md', 'user-rules.md'];
|
|
475
|
-
mkdirSync(skillDir, { recursive: true });
|
|
476
|
-
|
|
477
|
-
let count = 0;
|
|
478
|
-
for (const file of files) {
|
|
479
|
-
const dest = resolve(skillDir, file);
|
|
480
|
-
const src = resolve(sourceDir, file);
|
|
481
|
-
if (!existsSync(src)) continue;
|
|
482
|
-
|
|
483
|
-
// Never overwrite user-rules.md even with --force
|
|
484
|
-
if (file === 'user-rules.md' && existsSync(dest)) {
|
|
485
|
-
console.log(` ${dim('skip')} ${file} (user rules preserved)`);
|
|
486
|
-
continue;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
if (existsSync(dest) && !force) {
|
|
490
|
-
console.log(` ${dim('skip')} ${file} (already exists)`);
|
|
491
|
-
continue;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
cpSync(src, dest);
|
|
495
|
-
console.log(` ${green('✓')} ${file}${force ? ' (reset)' : ''}`);
|
|
496
|
-
count++;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// Clean up legacy split files from v3
|
|
500
|
-
for (const legacy of ['rules.md', 'patterns.md', 'proactive.md']) {
|
|
501
|
-
const legacyPath = resolve(skillDir, legacy);
|
|
502
|
-
if (existsSync(legacyPath)) {
|
|
503
|
-
rmSync(legacyPath);
|
|
504
|
-
console.log(` ${dim('cleanup')} ${legacy} (merged into skill-rules.md)`);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
if (count === 0) {
|
|
509
|
-
console.log(`\n ${dim('All files already exist. Use --force to reset defaults (user-rules.md is always preserved).')}\n`);
|
|
448
|
+
// Skill operating rules are now built into SKILL.md (shipped with the app).
|
|
449
|
+
// This command only initializes user-skill-rules.md for personalization.
|
|
450
|
+
const dest = resolve(mindRoot, 'user-skill-rules.md');
|
|
451
|
+
if (existsSync(dest)) {
|
|
452
|
+
console.log(` ${dim('skip')} user-skill-rules.md (already exists)\n`);
|
|
510
453
|
} else {
|
|
511
|
-
|
|
454
|
+
const isZh = config.disabledSkills?.includes('mindos');
|
|
455
|
+
const lang = isZh ? 'zh' : 'en';
|
|
456
|
+
const src = resolve(ROOT, 'templates', 'skill-rules', lang, 'user-rules.md');
|
|
457
|
+
if (existsSync(src)) {
|
|
458
|
+
cpSync(src, dest);
|
|
459
|
+
console.log(` ${green('✓')} user-skill-rules.md created at ${dim(mindRoot)}\n`);
|
|
460
|
+
} else {
|
|
461
|
+
console.log(` ${dim('skip')} Template not found, create user-skill-rules.md manually if needed.\n`);
|
|
462
|
+
}
|
|
512
463
|
}
|
|
464
|
+
console.log(` ${dim('Note: Operating rules are now built into the app. No install needed.')}\n`);
|
|
513
465
|
},
|
|
514
466
|
|
|
515
467
|
// ── doctor ─────────────────────────────────────────────────────────────────
|
|
@@ -727,7 +679,7 @@ ${dim('Shortcut: mindos start --daemon → install + start in one step')}
|
|
|
727
679
|
const webPort = updateConfig.port ?? 3456;
|
|
728
680
|
const mcpPort = updateConfig.mcpPort ?? 8781;
|
|
729
681
|
console.log(dim(' (Waiting for Web UI to come back up — first run after update includes a rebuild...)'));
|
|
730
|
-
const ready = await waitForHttp(Number(webPort), { retries:
|
|
682
|
+
const ready = await waitForHttp(Number(webPort), { retries: 120, intervalMs: 2000, label: 'Web UI', logFile: LOG_PATH });
|
|
731
683
|
if (ready) {
|
|
732
684
|
const localIP = getLocalIP();
|
|
733
685
|
console.log(`\n${'─'.repeat(53)}`);
|
|
@@ -746,28 +698,6 @@ ${dim('Shortcut: mindos start --daemon → install + start in one step')}
|
|
|
746
698
|
console.log(dim(' Run `mindos start` — it will rebuild automatically.'));
|
|
747
699
|
console.log(` ${dim('View changelog:')} ${cyan('https://github.com/GeminiLight/MindOS/releases')}\n`);
|
|
748
700
|
}
|
|
749
|
-
|
|
750
|
-
// ── Check if skill rules need updating ──────────────────────────────────
|
|
751
|
-
try {
|
|
752
|
-
const updateCfg = JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
|
|
753
|
-
const mindRoot = updateCfg.mindRoot;
|
|
754
|
-
if (mindRoot && existsSync(mindRoot)) {
|
|
755
|
-
const isZh = updateCfg.disabledSkills?.includes('mindos');
|
|
756
|
-
const sName = isZh ? 'mindos-zh' : 'mindos';
|
|
757
|
-
const lang = isZh ? 'zh' : 'en';
|
|
758
|
-
const installedRules = resolve(mindRoot, '.agents', 'skills', sName, 'skill-rules.md');
|
|
759
|
-
const tplRules = resolve(ROOT, 'templates', 'skill-rules', lang, 'skill-rules.md');
|
|
760
|
-
if (existsSync(installedRules) && existsSync(tplRules)) {
|
|
761
|
-
const uVer = readFileSync(installedRules, 'utf-8').match(/<!--\s*version:\s*(\S+)\s*-->/)?.[1];
|
|
762
|
-
const tVer = readFileSync(tplRules, 'utf-8').match(/<!--\s*version:\s*(\S+)\s*-->/)?.[1];
|
|
763
|
-
if (uVer && tVer && uVer !== tVer) {
|
|
764
|
-
console.log(` ${yellow('!')} Skill rules ${dim(uVer)} → ${bold(tVer)} available. Run ${cyan('mindos init-skills --force')} to update ${dim('(user-rules.md preserved)')}\n`);
|
|
765
|
-
}
|
|
766
|
-
} else if (!existsSync(resolve(mindRoot, '.agents', 'skills', sName))) {
|
|
767
|
-
console.log(` ${dim('Tip:')} Run ${cyan('mindos init-skills')} to enable skill rules in your knowledge base.\n`);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
} catch {}
|
|
771
701
|
},
|
|
772
702
|
|
|
773
703
|
// ── uninstall ──────────────────────────────────────────────────────────────
|
|
@@ -1212,7 +1142,7 @@ ${row('mindos gateway <subcommand>', 'Manage background service (install/u
|
|
|
1212
1142
|
${bold('Config & Diagnostics:')}
|
|
1213
1143
|
${row('mindos config <subcommand>', 'View/update config (show/validate/set/unset)')}
|
|
1214
1144
|
${row('mindos doctor', 'Health check (config, ports, build, daemon)')}
|
|
1215
|
-
${row('mindos init-skills
|
|
1145
|
+
${row('mindos init-skills', 'Create user-skill-rules.md for personalization')}
|
|
1216
1146
|
${row('mindos update', 'Update MindOS to the latest version')}
|
|
1217
1147
|
${row('mindos uninstall', 'Fully uninstall MindOS (stop, remove daemon, npm uninstall)')}
|
|
1218
1148
|
${row('mindos logs', 'Tail service logs (~/.mindos/mindos.log)')}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geminilight/mindos",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.23",
|
|
4
4
|
"description": "MindOS — Human-Agent Collaborative Mind System. Local-first knowledge base that syncs your mind to all AI Agents via MCP.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mindos",
|
|
@@ -57,7 +57,9 @@
|
|
|
57
57
|
"!assets/images",
|
|
58
58
|
"!mcp/node_modules",
|
|
59
59
|
"!mcp/dist",
|
|
60
|
-
"!mcp/package-lock.json"
|
|
60
|
+
"!mcp/package-lock.json",
|
|
61
|
+
"!mcp/*.tgz",
|
|
62
|
+
"!app/package-lock.json"
|
|
61
63
|
],
|
|
62
64
|
"scripts": {
|
|
63
65
|
"setup": "node scripts/setup.js",
|
package/scripts/setup.js
CHANGED
|
@@ -1205,18 +1205,8 @@ async function main() {
|
|
|
1205
1205
|
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\n');
|
|
1206
1206
|
console.log(`\n${c.green(t('cfgSaved'))}: ${c.dim(CONFIG_PATH)}`);
|
|
1207
1207
|
|
|
1208
|
-
// ──
|
|
1209
|
-
|
|
1210
|
-
const skillRulesDir = resolve(mindDir, '.agents', 'skills', skillName);
|
|
1211
|
-
if (!existsSync(skillRulesDir)) {
|
|
1212
|
-
const skillRulesLang = selectedTemplate === 'zh' ? 'zh' : 'en';
|
|
1213
|
-
const skillRulesSource = resolve(ROOT, 'templates', 'skill-rules', skillRulesLang);
|
|
1214
|
-
if (existsSync(skillRulesSource)) {
|
|
1215
|
-
mkdirSync(skillRulesDir, { recursive: true });
|
|
1216
|
-
cpSync(skillRulesSource, skillRulesDir, { recursive: true });
|
|
1217
|
-
console.log(`${c.green('✓')} ${c.dim(`Skill rules initialized: ${skillRulesDir}`)}`);
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1208
|
+
// ── Skill rules are now built into SKILL.md — no install needed ──────────
|
|
1209
|
+
// user-skill-rules.md will be created on first preference capture or via `mindos init-skills`.
|
|
1220
1210
|
|
|
1221
1211
|
// ── Step 7: MCP Agent Install ──────────────────────────────────────────────
|
|
1222
1212
|
write('\n');
|