@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.
- package/app/app/api/changes/route.ts +7 -1
- package/app/app/api/mcp/install-skill/route.ts +9 -24
- package/app/app/layout.tsx +1 -0
- package/app/app/page.tsx +1 -2
- package/app/app/view/[...path]/ViewPageClient.tsx +0 -1
- package/app/components/HomeContent.tsx +41 -6
- package/app/components/RightAgentDetailPanel.tsx +1 -0
- package/app/components/SidebarLayout.tsx +1 -0
- package/app/components/agents/AgentsContentPage.tsx +20 -16
- package/app/components/agents/AgentsMcpSection.tsx +178 -65
- package/app/components/agents/AgentsOverviewSection.tsx +1 -1
- package/app/components/agents/AgentsSkillsSection.tsx +78 -55
- package/app/components/agents/agents-content-model.ts +16 -0
- package/app/components/changes/ChangesBanner.tsx +90 -13
- package/app/components/changes/ChangesContentPage.tsx +134 -51
- package/app/components/panels/AgentsPanel.tsx +14 -28
- package/app/components/panels/AgentsPanelAgentDetail.tsx +5 -4
- package/app/components/panels/AgentsPanelAgentGroups.tsx +5 -6
- package/app/components/panels/AgentsPanelAgentListRow.tsx +30 -5
- package/app/components/panels/AgentsPanelHubNav.tsx +12 -12
- package/app/components/panels/PluginsPanel.tsx +3 -3
- package/app/components/renderers/agent-inspector/manifest.ts +2 -0
- package/app/components/renderers/config/manifest.ts +1 -0
- package/app/components/renderers/csv/manifest.ts +1 -0
- package/app/components/settings/PluginsTab.tsx +4 -3
- package/app/hooks/useMcpData.tsx +3 -2
- package/app/lib/core/content-changes.ts +148 -8
- package/app/lib/fs.ts +7 -1
- package/app/lib/i18n-en.ts +58 -3
- package/app/lib/i18n-zh.ts +58 -3
- package/app/lib/mcp-agents.ts +42 -0
- package/app/lib/renderers/index.ts +1 -2
- package/app/lib/renderers/registry.ts +10 -0
- package/app/next-env.d.ts +1 -1
- package/bin/lib/mcp-agents.js +38 -13
- package/package.json +1 -1
- package/scripts/migrate-agent-diff.js +146 -0
- package/scripts/setup.js +12 -17
- package/skills/plugin-core-builtin-migration/SKILL.md +178 -0
- package/app/components/renderers/diff/DiffRenderer.tsx +0 -311
- package/app/components/renderers/diff/manifest.ts +0 -14
package/app/lib/i18n-en.ts
CHANGED
|
@@ -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:
|
|
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',
|
package/app/lib/i18n-zh.ts
CHANGED
|
@@ -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:
|
|
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: '自定义',
|
package/app/lib/mcp-agents.ts
CHANGED
|
@@ -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,
|
|
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/
|
|
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.
|
package/bin/lib/mcp-agents.js
CHANGED
|
@@ -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: '~/.
|
|
87
|
+
global: '~/.codebuddy/mcp.json',
|
|
98
88
|
key: 'mcpServers',
|
|
99
89
|
preferredTransport: 'stdio',
|
|
100
|
-
presenceCli: '
|
|
101
|
-
presenceDirs: ['~/.
|
|
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
|
@@ -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([
|
|
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
|
-
.
|
|
786
|
-
|
|
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
|