@geminilight/mindos 0.5.63 → 0.5.64

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.
Files changed (41) hide show
  1. package/app/app/api/changes/route.ts +7 -1
  2. package/app/app/api/mcp/install-skill/route.ts +9 -24
  3. package/app/app/layout.tsx +1 -0
  4. package/app/app/page.tsx +1 -2
  5. package/app/app/view/[...path]/ViewPageClient.tsx +0 -1
  6. package/app/components/HomeContent.tsx +41 -6
  7. package/app/components/RightAgentDetailPanel.tsx +1 -0
  8. package/app/components/SidebarLayout.tsx +1 -0
  9. package/app/components/agents/AgentsContentPage.tsx +20 -16
  10. package/app/components/agents/AgentsMcpSection.tsx +178 -65
  11. package/app/components/agents/AgentsOverviewSection.tsx +1 -1
  12. package/app/components/agents/AgentsSkillsSection.tsx +78 -55
  13. package/app/components/agents/agents-content-model.ts +16 -0
  14. package/app/components/changes/ChangesBanner.tsx +90 -13
  15. package/app/components/changes/ChangesContentPage.tsx +134 -51
  16. package/app/components/panels/AgentsPanel.tsx +14 -28
  17. package/app/components/panels/AgentsPanelAgentDetail.tsx +5 -4
  18. package/app/components/panels/AgentsPanelAgentGroups.tsx +5 -6
  19. package/app/components/panels/AgentsPanelAgentListRow.tsx +30 -5
  20. package/app/components/panels/AgentsPanelHubNav.tsx +12 -12
  21. package/app/components/panels/PluginsPanel.tsx +3 -3
  22. package/app/components/renderers/agent-inspector/manifest.ts +2 -0
  23. package/app/components/renderers/config/manifest.ts +1 -0
  24. package/app/components/renderers/csv/manifest.ts +1 -0
  25. package/app/components/settings/PluginsTab.tsx +4 -3
  26. package/app/hooks/useMcpData.tsx +3 -2
  27. package/app/lib/core/content-changes.ts +148 -8
  28. package/app/lib/fs.ts +7 -1
  29. package/app/lib/i18n-en.ts +58 -3
  30. package/app/lib/i18n-zh.ts +58 -3
  31. package/app/lib/mcp-agents.ts +42 -0
  32. package/app/lib/renderers/index.ts +1 -2
  33. package/app/lib/renderers/registry.ts +10 -0
  34. package/app/next-env.d.ts +1 -1
  35. package/bin/lib/mcp-agents.js +38 -13
  36. package/package.json +1 -1
  37. package/scripts/migrate-agent-diff.js +146 -0
  38. package/scripts/setup.js +12 -17
  39. package/skills/plugin-core-builtin-migration/SKILL.md +178 -0
  40. package/app/components/renderers/diff/DiffRenderer.tsx +0 -311
  41. package/app/components/renderers/diff/manifest.ts +0 -14
@@ -32,6 +32,9 @@ export const en = {
32
32
  cancelCreate: 'Cancel',
33
33
  continueEditing: 'Continue editing',
34
34
  newNote: 'New Notes',
35
+ builtinFeatures: 'Built-in capabilities',
36
+ builtinActive: 'Active',
37
+ builtinInactive: 'Not active',
35
38
  plugins: 'Extensions',
36
39
  showMore: 'Show more',
37
40
  showLess: 'Show less',
@@ -124,6 +127,41 @@ export const en = {
124
127
  noSessions: 'No saved sessions.',
125
128
  draftingHint: 'AI is still running — you can draft the next step now.',
126
129
  },
130
+ changes: {
131
+ unreadBanner: (n: number) => `${n} content change${n === 1 ? '' : 's'} unread`,
132
+ reviewNow: 'Review now',
133
+ dismiss: 'Dismiss notification',
134
+ title: 'Content changes',
135
+ subtitle: 'Review recent edits across user and agent operations.',
136
+ eventsCount: (n: number) => `${n} event${n === 1 ? '' : 's'}`,
137
+ unreadCount: (n: number) => `${n} unread`,
138
+ refresh: 'Refresh',
139
+ markSeen: 'Mark seen',
140
+ markAllRead: 'Mark all read',
141
+ filters: {
142
+ filePath: 'File path',
143
+ filePathPlaceholder: 'e.g. Projects/plan.md',
144
+ source: 'Agents (source)',
145
+ operation: 'Tools (operation)',
146
+ operationAll: 'All operations',
147
+ keyword: 'Keyword',
148
+ keywordPlaceholder: 'summary / op / path',
149
+ all: 'All',
150
+ agent: 'Agent',
151
+ user: 'User',
152
+ system: 'System',
153
+ },
154
+ loading: 'Loading changes...',
155
+ empty: 'No content changes yet.',
156
+ open: 'Open',
157
+ unchangedLines: (n: number) => `... ${n} unchanged lines ...`,
158
+ relativeTime: {
159
+ justNow: 'just now',
160
+ minutesAgo: (n: number) => `${n}m ago`,
161
+ hoursAgo: (n: number) => `${n}h ago`,
162
+ daysAgo: (n: number) => `${n}d ago`,
163
+ },
164
+ },
127
165
  panels: {
128
166
  agents: {
129
167
  title: 'Agents',
@@ -139,9 +177,11 @@ export const en = {
139
177
  noAgents: 'No agents detected.',
140
178
  autoRefresh: 'Auto-refresh every 30s',
141
179
  connect: 'Connect',
142
- openDashboard: 'Dashboard',
143
180
  installing: 'Installing...',
144
- install: (name: string) => `Install ${name}`,
181
+ install: 'Install',
182
+ installSuccess: 'Installed',
183
+ installFailed: 'Install failed',
184
+ retryInstall: 'Retry',
145
185
  // Snippet section
146
186
  copyConfig: 'Copy Config',
147
187
  copied: 'Copied!',
@@ -286,6 +326,18 @@ export const en = {
286
326
  title: 'MCP health',
287
327
  refresh: 'Refresh',
288
328
  connectionGraph: 'Connection graph',
329
+ tabs: {
330
+ manage: 'Manage',
331
+ topology: 'Topology',
332
+ },
333
+ searchPlaceholder: 'Search agents...',
334
+ emptyState: 'No agents match current filters.',
335
+ filters: {
336
+ all: 'All',
337
+ connected: 'Connected',
338
+ detected: 'Detected',
339
+ notFound: 'Not found',
340
+ },
289
341
  table: {
290
342
  agent: 'Agent',
291
343
  status: 'Status',
@@ -302,8 +354,11 @@ export const en = {
302
354
  skills: {
303
355
  title: 'Skills',
304
356
  capabilityGroups: 'Capability groups',
357
+ tabs: {
358
+ manage: 'Manage',
359
+ matrix: 'Matrix',
360
+ },
305
361
  searchPlaceholder: 'Search skills...',
306
- matrixToggle: 'Skill x Agent compatibility matrix',
307
362
  sourceAll: 'All',
308
363
  sourceBuiltin: 'Built-in',
309
364
  sourceUser: 'Custom',
@@ -57,6 +57,9 @@ export const zh = {
57
57
  cancelCreate: '取消',
58
58
  continueEditing: '继续编辑',
59
59
  newNote: '新建笔记',
60
+ builtinFeatures: '内建能力',
61
+ builtinActive: '已启用',
62
+ builtinInactive: '未激活',
60
63
  plugins: '插件扩展',
61
64
  showMore: '查看更多',
62
65
  showLess: '收起',
@@ -149,6 +152,41 @@ export const zh = {
149
152
  noSessions: '暂无历史对话。',
150
153
  draftingHint: 'AI 仍在执行,你可以先输入下一步。',
151
154
  },
155
+ changes: {
156
+ unreadBanner: (n: number) => `${n} 条内容变更未读`,
157
+ reviewNow: '立即查看',
158
+ dismiss: '关闭提醒',
159
+ title: '内容变更',
160
+ subtitle: '集中查看用户与 Agent 的最近编辑记录。',
161
+ eventsCount: (n: number) => `${n} 条事件`,
162
+ unreadCount: (n: number) => `${n} 条未读`,
163
+ refresh: '刷新',
164
+ markSeen: '标记已读',
165
+ markAllRead: '全部已读',
166
+ filters: {
167
+ filePath: '文件路径',
168
+ filePathPlaceholder: '例如:Projects/plan.md',
169
+ source: 'Agents(来源)',
170
+ operation: 'Tools(操作)',
171
+ operationAll: '全部操作',
172
+ keyword: '关键词',
173
+ keywordPlaceholder: '摘要 / 操作 / 路径',
174
+ all: '全部',
175
+ agent: 'Agent',
176
+ user: '用户',
177
+ system: '系统',
178
+ },
179
+ loading: '正在加载变更...',
180
+ empty: '暂无内容变更。',
181
+ open: '打开',
182
+ unchangedLines: (n: number) => `... ${n} 行未变更 ...`,
183
+ relativeTime: {
184
+ justNow: '刚刚',
185
+ minutesAgo: (n: number) => `${n} 分钟前`,
186
+ hoursAgo: (n: number) => `${n} 小时前`,
187
+ daysAgo: (n: number) => `${n} 天前`,
188
+ },
189
+ },
152
190
  panels: {
153
191
  agents: {
154
192
  title: '智能体',
@@ -164,9 +202,11 @@ export const zh = {
164
202
  noAgents: '未检测到智能体。',
165
203
  autoRefresh: '每 30 秒自动刷新',
166
204
  connect: '连接',
167
- openDashboard: '仪表盘',
168
205
  installing: '安装中...',
169
- install: (name: string) => `安装 ${name}`,
206
+ install: '安装',
207
+ installSuccess: '已安装',
208
+ installFailed: '安装失败',
209
+ retryInstall: '重试',
170
210
  // Snippet section
171
211
  copyConfig: '复制配置',
172
212
  copied: '已复制!',
@@ -310,6 +350,18 @@ export const zh = {
310
350
  title: 'MCP 健康',
311
351
  refresh: '刷新',
312
352
  connectionGraph: '连接图谱',
353
+ tabs: {
354
+ manage: '管理',
355
+ topology: '图谱',
356
+ },
357
+ searchPlaceholder: '搜索 Agent...',
358
+ emptyState: '当前筛选条件下没有匹配的 Agent。',
359
+ filters: {
360
+ all: '全部',
361
+ connected: '已连接',
362
+ detected: '已检测',
363
+ notFound: '未找到',
364
+ },
313
365
  table: {
314
366
  agent: 'Agent',
315
367
  status: '状态',
@@ -326,8 +378,11 @@ export const zh = {
326
378
  skills: {
327
379
  title: 'Skills',
328
380
  capabilityGroups: '能力分组',
381
+ tabs: {
382
+ manage: '管理',
383
+ matrix: '矩阵',
384
+ },
329
385
  searchPlaceholder: '搜索技能...',
330
- matrixToggle: 'Skill x Agent 兼容矩阵',
331
386
  sourceAll: '全部',
332
387
  sourceBuiltin: '内置',
333
388
  sourceUser: '自定义',
@@ -33,6 +33,13 @@ export interface AgentDef {
33
33
  presenceDirs?: string[];
34
34
  }
35
35
 
36
+ export type SkillInstallMode = 'universal' | 'additional' | 'unsupported';
37
+ export interface SkillAgentRegistration {
38
+ mode: SkillInstallMode;
39
+ /** npx skills `-a` value for additional agents. */
40
+ skillAgentName?: string;
41
+ }
42
+
36
43
  export const MCP_AGENTS: Record<string, AgentDef> = {
37
44
  'claude-code': {
38
45
  name: 'Claude Code',
@@ -161,6 +168,15 @@ export const MCP_AGENTS: Record<string, AgentDef> = {
161
168
  presenceCli: 'qwen',
162
169
  presenceDirs: ['~/.qwen/'],
163
170
  },
171
+ 'qoder': {
172
+ name: 'Qoder',
173
+ project: null,
174
+ global: '~/.qoder.json',
175
+ key: 'mcpServers',
176
+ preferredTransport: 'stdio',
177
+ presenceCli: 'qoder',
178
+ presenceDirs: ['~/.qoder/', '~/.qoder.json'],
179
+ },
164
180
  'trae-cn': {
165
181
  name: 'Trae CN',
166
182
  project: '.trae/mcp.json',
@@ -215,6 +231,32 @@ export const MCP_AGENTS: Record<string, AgentDef> = {
215
231
  },
216
232
  };
217
233
 
234
+ /**
235
+ * Skill-install registry keyed by MCP agent key.
236
+ * Keep in sync with docs and bin/lib/mcp-agents.js.
237
+ */
238
+ export const SKILL_AGENT_REGISTRY: Record<string, SkillAgentRegistration> = {
239
+ 'claude-code': { mode: 'additional', skillAgentName: 'claude-code' },
240
+ 'cursor': { mode: 'universal' },
241
+ 'windsurf': { mode: 'additional', skillAgentName: 'windsurf' },
242
+ 'cline': { mode: 'universal' },
243
+ 'trae': { mode: 'additional', skillAgentName: 'trae' },
244
+ 'gemini-cli': { mode: 'universal' },
245
+ 'openclaw': { mode: 'additional', skillAgentName: 'openclaw' },
246
+ 'codebuddy': { mode: 'additional', skillAgentName: 'codebuddy' },
247
+ 'iflow-cli': { mode: 'additional', skillAgentName: 'iflow-cli' },
248
+ 'kimi-cli': { mode: 'universal' },
249
+ 'opencode': { mode: 'universal' },
250
+ 'pi': { mode: 'additional', skillAgentName: 'pi' },
251
+ 'augment': { mode: 'additional', skillAgentName: 'augment' },
252
+ 'qwen-code': { mode: 'additional', skillAgentName: 'qwen-code' },
253
+ 'qoder': { mode: 'additional', skillAgentName: 'qoder' },
254
+ 'trae-cn': { mode: 'additional', skillAgentName: 'trae-cn' },
255
+ 'roo': { mode: 'additional', skillAgentName: 'roo' },
256
+ 'vscode': { mode: 'universal' },
257
+ 'codex': { mode: 'universal' },
258
+ };
259
+
218
260
  /* ── MindOS MCP Install Detection ──────────────────────────────────────── */
219
261
 
220
262
  export function detectInstalled(agentKey: string): { installed: boolean; scope?: string; transport?: string; configPath?: string } {
@@ -7,7 +7,6 @@ import { manifest as agentInspector } from '@/components/renderers/agent-inspect
7
7
  import { manifest as backlinks } from '@/components/renderers/backlinks/manifest';
8
8
  import { manifest as config } from '@/components/renderers/config/manifest';
9
9
  import { manifest as csv } from '@/components/renderers/csv/manifest';
10
- import { manifest as diff } from '@/components/renderers/diff/manifest';
11
10
  import { manifest as summary } from '@/components/renderers/summary/manifest';
12
11
  import { manifest as timeline } from '@/components/renderers/timeline/manifest';
13
12
  import { manifest as todo } from '@/components/renderers/todo/manifest';
@@ -15,7 +14,7 @@ import { manifest as workflow } from '@/components/renderers/workflow/manifest';
15
14
  import { manifest as graph } from '@/components/renderers/graph/manifest';
16
15
 
17
16
  const manifests = [
18
- agentInspector, backlinks, config, csv, diff, summary, timeline, todo, workflow, graph,
17
+ agentInspector, backlinks, config, csv, summary, timeline, todo, workflow, graph,
19
18
  ];
20
19
 
21
20
  for (const m of manifests) {
@@ -16,6 +16,11 @@ export interface RendererDefinition {
16
16
  tags: string[];
17
17
  builtin: boolean; // true = ships with MindOS; false = user-installed (future)
18
18
  core?: boolean; // true = default renderer for a file type, cannot be disabled by user
19
+ /**
20
+ * App-builtin feature (not a user-facing plugin).
21
+ * When true, keep renderer functional but hide from Plugins surfaces.
22
+ */
23
+ appBuiltinFeature?: boolean;
19
24
  entryPath?: string; // canonical entry file shown on home page (e.g. 'TODO.md')
20
25
  match: (ctx: Pick<RendererContext, 'filePath' | 'extension'>) => boolean;
21
26
  // Provide either `component` (eager) or `load` (lazy). Prefer `load` for code-splitting.
@@ -78,3 +83,8 @@ export function resolveRenderer(
78
83
  export function getAllRenderers(): RendererDefinition[] {
79
84
  return registry;
80
85
  }
86
+
87
+ /** User-facing plugins only (exclude app-builtin features like CSV). */
88
+ export function getPluginRenderers(): RendererDefinition[] {
89
+ return registry.filter((r) => !r.appBuiltinFeature);
90
+ }
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/dev/types/routes.d.ts";
3
+ import "./.next/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.
@@ -26,16 +26,6 @@ export const MCP_AGENTS = {
26
26
  presenceCli: 'claude',
27
27
  presenceDirs: ['~/.claude/'],
28
28
  },
29
- 'claude-desktop': {
30
- name: 'Claude Desktop',
31
- project: null,
32
- global: process.platform === 'darwin'
33
- ? '~/Library/Application Support/Claude/claude_desktop_config.json'
34
- : '~/.config/Claude/claude_desktop_config.json',
35
- key: 'mcpServers',
36
- preferredTransport: 'http',
37
- presenceDirs: ['~/Library/Application Support/Claude/', '~/.config/Claude/'],
38
- },
39
29
  'cursor': {
40
30
  name: 'Cursor',
41
31
  project: '.cursor/mcp.json',
@@ -94,11 +84,11 @@ export const MCP_AGENTS = {
94
84
  'codebuddy': {
95
85
  name: 'CodeBuddy',
96
86
  project: null,
97
- global: '~/.claude-internal/.claude.json',
87
+ global: '~/.codebuddy/mcp.json',
98
88
  key: 'mcpServers',
99
89
  preferredTransport: 'stdio',
100
- presenceCli: 'claude-internal',
101
- presenceDirs: ['~/.claude-internal/'],
90
+ presenceCli: 'codebuddy',
91
+ presenceDirs: ['~/.codebuddy/'],
102
92
  },
103
93
  'iflow-cli': {
104
94
  name: 'iFlow CLI',
@@ -154,6 +144,15 @@ export const MCP_AGENTS = {
154
144
  presenceCli: 'qwen',
155
145
  presenceDirs: ['~/.qwen/'],
156
146
  },
147
+ 'qoder': {
148
+ name: 'Qoder',
149
+ project: null,
150
+ global: '~/.qoder.json',
151
+ key: 'mcpServers',
152
+ preferredTransport: 'stdio',
153
+ presenceCli: 'qoder',
154
+ presenceDirs: ['~/.qoder/', '~/.qoder.json'],
155
+ },
157
156
  'trae-cn': {
158
157
  name: 'Trae CN',
159
158
  project: '.trae/mcp.json',
@@ -183,6 +182,32 @@ export const MCP_AGENTS = {
183
182
  },
184
183
  };
185
184
 
185
+ /**
186
+ * Skill-install registry keyed by MCP agent key.
187
+ * Keep in sync with app/lib/mcp-agents.ts.
188
+ */
189
+ export const SKILL_AGENT_REGISTRY = {
190
+ 'claude-code': { mode: 'additional', skillAgentName: 'claude-code' },
191
+ 'cursor': { mode: 'universal' },
192
+ 'windsurf': { mode: 'additional', skillAgentName: 'windsurf' },
193
+ 'cline': { mode: 'universal' },
194
+ 'trae': { mode: 'additional', skillAgentName: 'trae' },
195
+ 'gemini-cli': { mode: 'universal' },
196
+ 'openclaw': { mode: 'additional', skillAgentName: 'openclaw' },
197
+ 'codebuddy': { mode: 'additional', skillAgentName: 'codebuddy' },
198
+ 'iflow-cli': { mode: 'additional', skillAgentName: 'iflow-cli' },
199
+ 'kimi-cli': { mode: 'universal' },
200
+ 'opencode': { mode: 'universal' },
201
+ 'pi': { mode: 'additional', skillAgentName: 'pi' },
202
+ 'augment': { mode: 'additional', skillAgentName: 'augment' },
203
+ 'qwen-code': { mode: 'additional', skillAgentName: 'qwen-code' },
204
+ 'qoder': { mode: 'additional', skillAgentName: 'qoder' },
205
+ 'trae-cn': { mode: 'additional', skillAgentName: 'trae-cn' },
206
+ 'roo': { mode: 'additional', skillAgentName: 'roo' },
207
+ 'vscode': { mode: 'universal' },
208
+ 'codex': { mode: 'universal' },
209
+ };
210
+
186
211
  export function detectAgentPresence(agentKey) {
187
212
  const agent = MCP_AGENTS[agentKey];
188
213
  if (!agent) return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geminilight/mindos",
3
- "version": "0.5.63",
3
+ "version": "0.5.64",
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",
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * One-shot migration helper:
4
+ * Import legacy Agent-Diff.md ```agent-diff blocks into .mindos/change-log.json.
5
+ *
6
+ * Usage:
7
+ * node scripts/migrate-agent-diff.js --mind-root /abs/path/to/mindRoot
8
+ */
9
+
10
+ import fs from 'fs';
11
+ import path from 'path';
12
+
13
+ const MAX_EVENTS = 500;
14
+ const MAX_TEXT_CHARS = 12_000;
15
+
16
+ function parseArgs(argv) {
17
+ let mindRoot = '';
18
+ for (let i = 0; i < argv.length; i++) {
19
+ if (argv[i] === '--mind-root') {
20
+ mindRoot = argv[i + 1] || '';
21
+ i += 1;
22
+ }
23
+ }
24
+ return { mindRoot };
25
+ }
26
+
27
+ function normalizeText(value) {
28
+ if (typeof value !== 'string') return { value: undefined, truncated: false };
29
+ if (value.length <= MAX_TEXT_CHARS) return { value, truncated: false };
30
+ return { value: value.slice(0, MAX_TEXT_CHARS), truncated: true };
31
+ }
32
+
33
+ function nowIso() {
34
+ return new Date().toISOString();
35
+ }
36
+
37
+ function validIso(ts) {
38
+ if (typeof ts !== 'string') return nowIso();
39
+ const ms = new Date(ts).getTime();
40
+ return Number.isFinite(ms) ? new Date(ms).toISOString() : nowIso();
41
+ }
42
+
43
+ function parseLegacyBlocks(raw) {
44
+ const blocks = [];
45
+ const re = /```agent-diff\s*\n([\s\S]*?)```/g;
46
+ let m;
47
+ while ((m = re.exec(raw)) !== null) {
48
+ try {
49
+ blocks.push(JSON.parse(m[1].trim()));
50
+ } catch {
51
+ // Keep migration best-effort.
52
+ }
53
+ }
54
+ return blocks;
55
+ }
56
+
57
+ function readJson(file, fallback) {
58
+ try {
59
+ if (!fs.existsSync(file)) return fallback;
60
+ return JSON.parse(fs.readFileSync(file, 'utf-8'));
61
+ } catch {
62
+ return fallback;
63
+ }
64
+ }
65
+
66
+ function main() {
67
+ const { mindRoot } = parseArgs(process.argv.slice(2));
68
+ if (!mindRoot) {
69
+ console.error('Missing --mind-root');
70
+ process.exit(1);
71
+ }
72
+ const root = path.resolve(mindRoot);
73
+ if (!fs.existsSync(root) || !fs.statSync(root).isDirectory()) {
74
+ console.error('Invalid mind root:', root);
75
+ process.exit(1);
76
+ }
77
+
78
+ const legacyFile = path.join(root, 'Agent-Diff.md');
79
+ if (!fs.existsSync(legacyFile)) {
80
+ console.log('No Agent-Diff.md found. Nothing to migrate.');
81
+ return;
82
+ }
83
+
84
+ const logDir = path.join(root, '.mindos');
85
+ const logFile = path.join(logDir, 'change-log.json');
86
+ const state = readJson(logFile, {
87
+ version: 1,
88
+ lastSeenAt: null,
89
+ events: [],
90
+ legacy: { agentDiffImportedCount: 0, lastImportedAt: null },
91
+ });
92
+
93
+ const raw = fs.readFileSync(legacyFile, 'utf-8');
94
+ const blocks = parseLegacyBlocks(raw);
95
+ const importedCount = Number(state?.legacy?.agentDiffImportedCount || 0);
96
+ if (blocks.length <= importedCount) {
97
+ if (blocks.length > 0) {
98
+ fs.rmSync(legacyFile, { force: true });
99
+ console.log('Legacy Agent-Diff.md already migrated; removed legacy file.');
100
+ return;
101
+ }
102
+ console.log('No new legacy blocks to import.');
103
+ return;
104
+ }
105
+
106
+ const incoming = blocks.slice(importedCount);
107
+ const imported = incoming.map((entry, idx) => {
108
+ const before = normalizeText(entry?.before);
109
+ const after = normalizeText(entry?.after);
110
+ const tool = typeof entry?.tool === 'string' && entry.tool.trim() ? entry.tool.trim() : 'unknown-tool';
111
+ const targetPath = typeof entry?.path === 'string' && entry.path.trim() ? entry.path : 'Agent-Diff.md';
112
+ return {
113
+ id: `legacy-script-${Date.now().toString(36)}-${idx.toString(36)}`,
114
+ ts: validIso(entry?.ts),
115
+ op: 'legacy_agent_diff_import',
116
+ path: targetPath,
117
+ source: 'agent',
118
+ summary: `Imported legacy agent diff (${tool})`,
119
+ before: before.value,
120
+ after: after.value,
121
+ truncated: before.truncated || after.truncated || undefined,
122
+ };
123
+ });
124
+
125
+ const merged = [...(Array.isArray(state.events) ? state.events : []), ...imported].sort(
126
+ (a, b) => new Date(b.ts).getTime() - new Date(a.ts).getTime(),
127
+ ).slice(0, MAX_EVENTS);
128
+
129
+ const next = {
130
+ version: 1,
131
+ lastSeenAt: typeof state.lastSeenAt === 'string' ? state.lastSeenAt : null,
132
+ events: merged,
133
+ legacy: {
134
+ agentDiffImportedCount: blocks.length,
135
+ lastImportedAt: nowIso(),
136
+ },
137
+ };
138
+
139
+ fs.mkdirSync(logDir, { recursive: true });
140
+ fs.writeFileSync(logFile, JSON.stringify(next, null, 2), 'utf-8');
141
+ fs.rmSync(legacyFile, { force: true });
142
+ console.log(`Imported ${imported.length} legacy block(s) into ${logFile}`);
143
+ console.log('Removed legacy Agent-Diff.md');
144
+ }
145
+
146
+ main();
package/scripts/setup.js CHANGED
@@ -30,7 +30,7 @@ import { execSync, spawn } from 'node:child_process';
30
30
  import { randomBytes, createHash } from 'node:crypto';
31
31
  import { createConnection } from 'node:net';
32
32
  import http from 'node:http';
33
- import { MCP_AGENTS, detectAgentPresence } from '../bin/lib/mcp-agents.js';
33
+ import { MCP_AGENTS, SKILL_AGENT_REGISTRY, detectAgentPresence } from '../bin/lib/mcp-agents.js';
34
34
 
35
35
  const __dirname = dirname(fileURLToPath(import.meta.url));
36
36
  const ROOT = resolve(__dirname, '..');
@@ -750,20 +750,7 @@ const UNIVERSAL_AGENTS = new Set([
750
750
  'cline', 'codex', 'cursor', 'gemini-cli',
751
751
  'github-copilot', 'kimi-cli', 'opencode', 'warp',
752
752
  ]);
753
- const SKILL_UNSUPPORTED = new Set(['claude-desktop']);
754
- const AGENT_NAME_MAP = {
755
- 'claude-code': 'claude-code',
756
- 'windsurf': 'windsurf',
757
- 'trae': 'trae',
758
- 'openclaw': 'openclaw',
759
- 'codebuddy': 'codebuddy',
760
- 'iflow-cli': 'iflow-cli',
761
- 'pi': 'pi',
762
- 'augment': 'augment',
763
- 'qwen-code': 'qwen-code',
764
- 'trae-cn': 'trae-cn',
765
- 'roo': 'roo',
766
- };
753
+ const SKILL_UNSUPPORTED = new Set([]);
767
754
 
768
755
  /**
769
756
  * Install the appropriate MindOS Skill to selected agents via `npx skills add`.
@@ -782,8 +769,16 @@ function runSkillInstallStep(template, selectedAgents) {
782
769
 
783
770
  // Filter to non-universal, skill-capable agents
784
771
  const additionalAgents = selectedAgents
785
- .filter(key => !UNIVERSAL_AGENTS.has(key) && !SKILL_UNSUPPORTED.has(key))
786
- .map(key => AGENT_NAME_MAP[key] || key);
772
+ .flatMap((key) => {
773
+ if (SKILL_UNSUPPORTED.has(key)) return [];
774
+ // Keep backward-compatibility for non-MCP universal keys.
775
+ if (UNIVERSAL_AGENTS.has(key)) return [];
776
+ const reg = SKILL_AGENT_REGISTRY[key];
777
+ if (!reg) return [key];
778
+ if (reg.mode === 'unsupported') return [];
779
+ if (reg.mode === 'universal') return [];
780
+ return [reg.skillAgentName || key];
781
+ });
787
782
 
788
783
  // Each agent needs its own -a flag (skills CLI does NOT accept comma-separated)
789
784
  const agentFlags = additionalAgents.length > 0