jvibe 1.1.8 → 1.1.10
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/CHANGELOG.md +42 -0
- package/README.md +39 -0
- package/bin/jvibe.js +14 -12
- package/lib/migrations/index.js +1 -8
- package/lib/plugins/core-tools.js +397 -0
- package/lib/plugins/plugins-yaml.js +49 -0
- package/lib/plugins/registry.json +397 -11
- package/package.json +1 -1
- package/scripts/init.js +37 -0
- package/scripts/plugins.js +159 -0
- package/scripts/setup.js +116 -59
- package/scripts/upgrade.js +29 -106
- package/template/.claude/commands/JVibe:init.md +1 -1
- package/template/.claude/hooks/load-jvibe-full-context.sh +146 -47
- package/template/.claude/hooks/sync-jvibe-context.sh +47 -12
- package/template/.claude/settings.json +4 -4
- package/template/.claude/skills/agent-browser/SKILL.md +252 -0
- package/template/.jvibe-doc-hash.json +3 -3
- package/template/.opencode/command/jvibe-init.md +1 -1
- package/template/docs/.jvibe/plugins.yaml +0 -2
- package/template/docs/core/Appendix.md +2 -12
- package/template/docs/core/Feature-List.md +20 -24
- package/template/docs/core/Standards.md +2 -6
|
@@ -5,49 +5,435 @@
|
|
|
5
5
|
"id": "serena",
|
|
6
6
|
"name": "Serena",
|
|
7
7
|
"category": "memory",
|
|
8
|
+
"description": "符号分析 + 项目记忆",
|
|
8
9
|
"integration": { "type": "mcp" },
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
"claude": {
|
|
11
|
+
"mcpServerName": "serena",
|
|
12
|
+
"mcpAliases": ["serena"],
|
|
13
|
+
"mcpServer": {
|
|
14
|
+
"command": "npx",
|
|
15
|
+
"args": ["-y", "serena-slim"]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
16
18
|
"default_tier": "core"
|
|
17
19
|
},
|
|
18
20
|
{
|
|
19
21
|
"id": "filesystem-mcp",
|
|
20
22
|
"name": "Filesystem MCP",
|
|
21
23
|
"category": "filesystem",
|
|
24
|
+
"description": "基础文件操作",
|
|
22
25
|
"integration": { "type": "mcp" },
|
|
26
|
+
"claude": {
|
|
27
|
+
"mcpServerName": "filesystem",
|
|
28
|
+
"mcpAliases": ["filesystem", "filesystem-mcp"],
|
|
29
|
+
"mcpServer": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "{{project_root}}"]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
23
34
|
"default_tier": "core"
|
|
24
35
|
},
|
|
25
36
|
{
|
|
26
37
|
"id": "github-mcp",
|
|
27
38
|
"name": "GitHub MCP",
|
|
28
39
|
"category": "git",
|
|
40
|
+
"description": "Git/代码托管",
|
|
29
41
|
"integration": { "type": "mcp" },
|
|
30
|
-
"
|
|
42
|
+
"claude": {
|
|
43
|
+
"mcpServerName": "github",
|
|
44
|
+
"mcpAliases": ["github", "github-mcp"],
|
|
45
|
+
"mcpServer": {
|
|
46
|
+
"command": "npx",
|
|
47
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
48
|
+
"env": {
|
|
49
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN": "{{GITHUB_PERSONAL_ACCESS_TOKEN}}"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"requires": { "env": ["GITHUB_PERSONAL_ACCESS_TOKEN"] },
|
|
54
|
+
"default_tier": "project"
|
|
31
55
|
},
|
|
32
56
|
{
|
|
33
57
|
"id": "context7",
|
|
34
58
|
"name": "Context7",
|
|
35
59
|
"category": "docs",
|
|
60
|
+
"description": "查询库/框架文档",
|
|
36
61
|
"integration": { "type": "mcp" },
|
|
62
|
+
"claude": {
|
|
63
|
+
"mcpServerName": "context7",
|
|
64
|
+
"mcpAliases": ["context7", "context7-mcp"],
|
|
65
|
+
"mcpServer": {
|
|
66
|
+
"command": "npx",
|
|
67
|
+
"args": ["-y", "@upstash/context7-mcp"]
|
|
68
|
+
}
|
|
69
|
+
},
|
|
37
70
|
"default_tier": "core"
|
|
38
71
|
},
|
|
39
72
|
{
|
|
40
73
|
"id": "agent-browser",
|
|
41
74
|
"name": "Agent Browser",
|
|
42
75
|
"category": "browser",
|
|
43
|
-
"
|
|
76
|
+
"description": "浏览器自动化(Skill 形态)",
|
|
77
|
+
"integration": { "type": "skill" },
|
|
78
|
+
"claude": {
|
|
79
|
+
"skillName": "agent-browser",
|
|
80
|
+
"skillSource": "https://raw.githubusercontent.com/vercel-labs/agent-browser/v0.6.0/skills/agent-browser/SKILL.md",
|
|
81
|
+
"skillDir": ".claude/skills/agent-browser",
|
|
82
|
+
"globalInstall": "npm install -g agent-browser && agent-browser install",
|
|
83
|
+
"allowedTools": ["Bash(agent-browser:*)"]
|
|
84
|
+
},
|
|
44
85
|
"default_tier": "core"
|
|
45
86
|
},
|
|
87
|
+
|
|
88
|
+
{
|
|
89
|
+
"id": "postgres-mcp",
|
|
90
|
+
"name": "PostgreSQL",
|
|
91
|
+
"category": "database",
|
|
92
|
+
"description": "PostgreSQL 数据库操作",
|
|
93
|
+
"integration": { "type": "mcp" },
|
|
94
|
+
"claude": {
|
|
95
|
+
"mcpServerName": "postgres",
|
|
96
|
+
"mcpAliases": ["postgres", "postgresql"],
|
|
97
|
+
"mcpServer": {
|
|
98
|
+
"command": "npx",
|
|
99
|
+
"args": ["-y", "@modelcontextprotocol/server-postgres"],
|
|
100
|
+
"env": {
|
|
101
|
+
"POSTGRES_CONNECTION_STRING": "{{POSTGRES_CONNECTION_STRING}}"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"requires": { "env": ["POSTGRES_CONNECTION_STRING"] },
|
|
106
|
+
"default_tier": "project"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"id": "mysql-mcp",
|
|
110
|
+
"name": "MySQL",
|
|
111
|
+
"category": "database",
|
|
112
|
+
"description": "MySQL 数据库操作",
|
|
113
|
+
"integration": { "type": "mcp" },
|
|
114
|
+
"claude": {
|
|
115
|
+
"mcpServerName": "mysql",
|
|
116
|
+
"mcpAliases": ["mysql"],
|
|
117
|
+
"mcpServer": {
|
|
118
|
+
"command": "npx",
|
|
119
|
+
"args": ["-y", "mysql-mcp"],
|
|
120
|
+
"env": {
|
|
121
|
+
"MYSQL_HOST": "{{MYSQL_HOST}}",
|
|
122
|
+
"MYSQL_PORT": "{{MYSQL_PORT}}",
|
|
123
|
+
"MYSQL_USER": "{{MYSQL_USER}}",
|
|
124
|
+
"MYSQL_PASSWORD": "{{MYSQL_PASSWORD}}",
|
|
125
|
+
"MYSQL_DATABASE": "{{MYSQL_DATABASE}}"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"requires": { "env": ["MYSQL_HOST", "MYSQL_USER", "MYSQL_PASSWORD", "MYSQL_DATABASE"] },
|
|
130
|
+
"default_tier": "project"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"id": "mongodb-mcp",
|
|
134
|
+
"name": "MongoDB",
|
|
135
|
+
"category": "database",
|
|
136
|
+
"description": "MongoDB 数据库操作",
|
|
137
|
+
"integration": { "type": "mcp" },
|
|
138
|
+
"claude": {
|
|
139
|
+
"mcpServerName": "mongodb",
|
|
140
|
+
"mcpAliases": ["mongodb", "mongo"],
|
|
141
|
+
"mcpServer": {
|
|
142
|
+
"command": "npx",
|
|
143
|
+
"args": ["-y", "mcp-mongo-server"],
|
|
144
|
+
"env": {
|
|
145
|
+
"MONGODB_URI": "{{MONGODB_URI}}"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"requires": { "env": ["MONGODB_URI"] },
|
|
150
|
+
"default_tier": "project"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"id": "supabase-mcp",
|
|
154
|
+
"name": "Supabase",
|
|
155
|
+
"category": "database",
|
|
156
|
+
"description": "Supabase 数据库 + Auth + Storage",
|
|
157
|
+
"integration": { "type": "mcp" },
|
|
158
|
+
"claude": {
|
|
159
|
+
"mcpServerName": "supabase",
|
|
160
|
+
"mcpAliases": ["supabase"],
|
|
161
|
+
"mcpServer": {
|
|
162
|
+
"command": "npx",
|
|
163
|
+
"args": ["-y", "@supabase/mcp-server-supabase", "--access-token", "{{SUPABASE_ACCESS_TOKEN}}"]
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
"requires": { "env": ["SUPABASE_ACCESS_TOKEN"] },
|
|
167
|
+
"default_tier": "project"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"id": "redis-mcp",
|
|
171
|
+
"name": "Redis",
|
|
172
|
+
"category": "database",
|
|
173
|
+
"description": "Redis 缓存操作",
|
|
174
|
+
"integration": { "type": "mcp" },
|
|
175
|
+
"claude": {
|
|
176
|
+
"mcpServerName": "redis",
|
|
177
|
+
"mcpAliases": ["redis"],
|
|
178
|
+
"mcpServer": {
|
|
179
|
+
"command": "npx",
|
|
180
|
+
"args": ["-y", "@modelcontextprotocol/server-redis"],
|
|
181
|
+
"env": {
|
|
182
|
+
"REDIS_URL": "{{REDIS_URL}}"
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
"requires": { "env": ["REDIS_URL"] },
|
|
187
|
+
"default_tier": "project"
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
{
|
|
191
|
+
"id": "docker-mcp",
|
|
192
|
+
"name": "Docker",
|
|
193
|
+
"category": "container",
|
|
194
|
+
"description": "Docker 容器管理",
|
|
195
|
+
"integration": { "type": "mcp" },
|
|
196
|
+
"claude": {
|
|
197
|
+
"mcpServerName": "docker",
|
|
198
|
+
"mcpAliases": ["docker"],
|
|
199
|
+
"mcpServer": {
|
|
200
|
+
"command": "npx",
|
|
201
|
+
"args": ["-y", "mcp-server-docker"]
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
"default_tier": "project"
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"id": "kubernetes-mcp",
|
|
208
|
+
"name": "Kubernetes",
|
|
209
|
+
"category": "container",
|
|
210
|
+
"description": "Kubernetes 集群管理",
|
|
211
|
+
"integration": { "type": "mcp" },
|
|
212
|
+
"claude": {
|
|
213
|
+
"mcpServerName": "kubernetes",
|
|
214
|
+
"mcpAliases": ["kubernetes", "k8s"],
|
|
215
|
+
"mcpServer": {
|
|
216
|
+
"command": "npx",
|
|
217
|
+
"args": ["-y", "mcp-server-kubernetes"]
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
"default_tier": "project"
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
{
|
|
224
|
+
"id": "aws-mcp",
|
|
225
|
+
"name": "AWS",
|
|
226
|
+
"category": "cloud",
|
|
227
|
+
"description": "AWS 云服务管理",
|
|
228
|
+
"integration": { "type": "mcp" },
|
|
229
|
+
"claude": {
|
|
230
|
+
"mcpServerName": "aws",
|
|
231
|
+
"mcpAliases": ["aws"],
|
|
232
|
+
"mcpServer": {
|
|
233
|
+
"command": "npx",
|
|
234
|
+
"args": ["-y", "mcp-server-aws"],
|
|
235
|
+
"env": {
|
|
236
|
+
"AWS_ACCESS_KEY_ID": "{{AWS_ACCESS_KEY_ID}}",
|
|
237
|
+
"AWS_SECRET_ACCESS_KEY": "{{AWS_SECRET_ACCESS_KEY}}",
|
|
238
|
+
"AWS_REGION": "{{AWS_REGION}}"
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"requires": { "env": ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION"] },
|
|
243
|
+
"default_tier": "project"
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
"id": "gcp-mcp",
|
|
247
|
+
"name": "Google Cloud",
|
|
248
|
+
"category": "cloud",
|
|
249
|
+
"description": "GCP 云服务管理",
|
|
250
|
+
"integration": { "type": "mcp" },
|
|
251
|
+
"claude": {
|
|
252
|
+
"mcpServerName": "gcp",
|
|
253
|
+
"mcpAliases": ["gcp", "google-cloud"],
|
|
254
|
+
"mcpServer": {
|
|
255
|
+
"command": "npx",
|
|
256
|
+
"args": ["-y", "gcp-mcp"],
|
|
257
|
+
"env": {
|
|
258
|
+
"GOOGLE_APPLICATION_CREDENTIALS": "{{GOOGLE_APPLICATION_CREDENTIALS}}"
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
"requires": { "env": ["GOOGLE_APPLICATION_CREDENTIALS"] },
|
|
263
|
+
"default_tier": "project"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"id": "azure-mcp",
|
|
267
|
+
"name": "Azure",
|
|
268
|
+
"category": "cloud",
|
|
269
|
+
"description": "Azure 云服务管理",
|
|
270
|
+
"integration": { "type": "mcp" },
|
|
271
|
+
"claude": {
|
|
272
|
+
"mcpServerName": "azure",
|
|
273
|
+
"mcpAliases": ["azure"],
|
|
274
|
+
"mcpServer": {
|
|
275
|
+
"command": "npx",
|
|
276
|
+
"args": ["-y", "mcp-server-azure"],
|
|
277
|
+
"env": {
|
|
278
|
+
"AZURE_SUBSCRIPTION_ID": "{{AZURE_SUBSCRIPTION_ID}}",
|
|
279
|
+
"AZURE_CLIENT_ID": "{{AZURE_CLIENT_ID}}",
|
|
280
|
+
"AZURE_CLIENT_SECRET": "{{AZURE_CLIENT_SECRET}}",
|
|
281
|
+
"AZURE_TENANT_ID": "{{AZURE_TENANT_ID}}"
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
"requires": { "env": ["AZURE_SUBSCRIPTION_ID", "AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET", "AZURE_TENANT_ID"] },
|
|
286
|
+
"default_tier": "project"
|
|
287
|
+
},
|
|
288
|
+
|
|
46
289
|
{
|
|
47
290
|
"id": "playwright-mcp",
|
|
48
|
-
"name": "Playwright
|
|
49
|
-
"category": "
|
|
291
|
+
"name": "Playwright",
|
|
292
|
+
"category": "testing",
|
|
293
|
+
"description": "浏览器自动化测试",
|
|
294
|
+
"integration": { "type": "mcp" },
|
|
295
|
+
"claude": {
|
|
296
|
+
"mcpServerName": "playwright",
|
|
297
|
+
"mcpAliases": ["playwright"],
|
|
298
|
+
"mcpServer": {
|
|
299
|
+
"command": "npx",
|
|
300
|
+
"args": ["-y", "@playwright/mcp"]
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
"default_tier": "project"
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"id": "puppeteer-mcp",
|
|
307
|
+
"name": "Puppeteer",
|
|
308
|
+
"category": "testing",
|
|
309
|
+
"description": "Chrome 无头浏览器测试",
|
|
310
|
+
"integration": { "type": "mcp" },
|
|
311
|
+
"claude": {
|
|
312
|
+
"mcpServerName": "puppeteer",
|
|
313
|
+
"mcpAliases": ["puppeteer"],
|
|
314
|
+
"mcpServer": {
|
|
315
|
+
"command": "npx",
|
|
316
|
+
"args": ["-y", "@hisma/server-puppeteer"]
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
"default_tier": "project"
|
|
320
|
+
},
|
|
321
|
+
|
|
322
|
+
{
|
|
323
|
+
"id": "chrome-devtools-mcp",
|
|
324
|
+
"name": "Chrome DevTools",
|
|
325
|
+
"category": "frontend",
|
|
326
|
+
"description": "Chrome 开发者工具调试",
|
|
327
|
+
"integration": { "type": "mcp" },
|
|
328
|
+
"claude": {
|
|
329
|
+
"mcpServerName": "chrome-devtools",
|
|
330
|
+
"mcpAliases": ["chrome-devtools", "devtools"],
|
|
331
|
+
"mcpServer": {
|
|
332
|
+
"command": "npx",
|
|
333
|
+
"args": ["-y", "chrome-devtools-mcp"]
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
"default_tier": "project"
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
{
|
|
340
|
+
"id": "figma-mcp",
|
|
341
|
+
"name": "Figma",
|
|
342
|
+
"category": "design",
|
|
343
|
+
"description": "Figma 设计文件操作",
|
|
344
|
+
"integration": { "type": "mcp" },
|
|
345
|
+
"claude": {
|
|
346
|
+
"mcpServerName": "figma",
|
|
347
|
+
"mcpAliases": ["figma"],
|
|
348
|
+
"mcpServer": {
|
|
349
|
+
"command": "npx",
|
|
350
|
+
"args": ["-y", "mcp-figma"]
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
"default_tier": "project"
|
|
354
|
+
},
|
|
355
|
+
|
|
356
|
+
{
|
|
357
|
+
"id": "slack-mcp",
|
|
358
|
+
"name": "Slack",
|
|
359
|
+
"category": "communication",
|
|
360
|
+
"description": "Slack 消息与频道管理",
|
|
361
|
+
"integration": { "type": "mcp" },
|
|
362
|
+
"claude": {
|
|
363
|
+
"mcpServerName": "slack",
|
|
364
|
+
"mcpAliases": ["slack"],
|
|
365
|
+
"mcpServer": {
|
|
366
|
+
"command": "npx",
|
|
367
|
+
"args": ["-y", "slack-mcp-server"],
|
|
368
|
+
"env": {
|
|
369
|
+
"SLACK_MCP_XOXB_TOKEN": "{{SLACK_MCP_XOXB_TOKEN}}"
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
"requires": { "env": ["SLACK_MCP_XOXB_TOKEN"] },
|
|
374
|
+
"default_tier": "project"
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
"id": "discord-mcp",
|
|
378
|
+
"name": "Discord",
|
|
379
|
+
"category": "communication",
|
|
380
|
+
"description": "Discord 消息与服务器管理",
|
|
381
|
+
"integration": { "type": "mcp" },
|
|
382
|
+
"claude": {
|
|
383
|
+
"mcpServerName": "discord",
|
|
384
|
+
"mcpAliases": ["discord"],
|
|
385
|
+
"mcpServer": {
|
|
386
|
+
"command": "npx",
|
|
387
|
+
"args": ["-y", "mcp-server-discord"],
|
|
388
|
+
"env": {
|
|
389
|
+
"DISCORD_BOT_TOKEN": "{{DISCORD_BOT_TOKEN}}"
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
"requires": { "env": ["DISCORD_BOT_TOKEN"] },
|
|
394
|
+
"default_tier": "project"
|
|
395
|
+
},
|
|
396
|
+
|
|
397
|
+
{
|
|
398
|
+
"id": "notion-mcp",
|
|
399
|
+
"name": "Notion",
|
|
400
|
+
"category": "docs",
|
|
401
|
+
"description": "Notion 页面与数据库操作",
|
|
402
|
+
"integration": { "type": "mcp" },
|
|
403
|
+
"claude": {
|
|
404
|
+
"mcpServerName": "notion",
|
|
405
|
+
"mcpAliases": ["notion"],
|
|
406
|
+
"mcpServer": {
|
|
407
|
+
"command": "npx",
|
|
408
|
+
"args": ["-y", "@notionhq/notion-mcp-server"],
|
|
409
|
+
"env": {
|
|
410
|
+
"NOTION_TOKEN": "{{NOTION_TOKEN}}"
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
"requires": { "env": ["NOTION_TOKEN"] },
|
|
415
|
+
"default_tier": "project"
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
"id": "confluence-mcp",
|
|
419
|
+
"name": "Confluence",
|
|
420
|
+
"category": "docs",
|
|
421
|
+
"description": "Confluence 文档协作",
|
|
50
422
|
"integration": { "type": "mcp" },
|
|
423
|
+
"claude": {
|
|
424
|
+
"mcpServerName": "confluence",
|
|
425
|
+
"mcpAliases": ["confluence"],
|
|
426
|
+
"mcpServer": {
|
|
427
|
+
"command": "npx",
|
|
428
|
+
"args": ["-y", "@answerai/confluence-mcp"],
|
|
429
|
+
"env": {
|
|
430
|
+
"CONFLUENCE_BASE_URL": "{{CONFLUENCE_BASE_URL}}",
|
|
431
|
+
"CONFLUENCE_USER_EMAIL": "{{CONFLUENCE_USER_EMAIL}}",
|
|
432
|
+
"CONFLUENCE_API_TOKEN": "{{CONFLUENCE_API_TOKEN}}"
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
"requires": { "env": ["CONFLUENCE_BASE_URL", "CONFLUENCE_USER_EMAIL", "CONFLUENCE_API_TOKEN"] },
|
|
51
437
|
"default_tier": "project"
|
|
52
438
|
}
|
|
53
439
|
]
|
package/package.json
CHANGED
package/scripts/init.js
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
const fs = require('fs-extra');
|
|
7
7
|
const path = require('path');
|
|
8
8
|
const chalk = require('chalk');
|
|
9
|
+
const {
|
|
10
|
+
loadPluginRegistry,
|
|
11
|
+
configureClaudeCoreTools
|
|
12
|
+
} = require('../lib/plugins/core-tools');
|
|
9
13
|
|
|
10
14
|
const TEMPLATE_DIR = path.join(__dirname, '../template');
|
|
11
15
|
|
|
@@ -30,6 +34,8 @@ async function init(options = {}) {
|
|
|
30
34
|
console.log(chalk.blue('\n🚀 正在初始化 JVibe...\n'));
|
|
31
35
|
|
|
32
36
|
try {
|
|
37
|
+
const pluginRegistry = await loadPluginRegistry();
|
|
38
|
+
|
|
33
39
|
// 1. 检查是否已存在 JVibe 配置
|
|
34
40
|
const claudeDir = path.join(cwd, '.claude');
|
|
35
41
|
const opencodeDir = path.join(cwd, '.opencode');
|
|
@@ -143,6 +149,37 @@ async function init(options = {}) {
|
|
|
143
149
|
await fs.writeJson(opencodeMetaPath, opencodeMeta, { spaces: 2 });
|
|
144
150
|
}
|
|
145
151
|
|
|
152
|
+
// 6.5 配置 Core Tools(MCP Servers + Skills,仅写入缺失项)
|
|
153
|
+
const coreToolsResult = await configureClaudeCoreTools(cwd, pluginRegistry);
|
|
154
|
+
if (coreToolsResult && coreToolsResult.error) {
|
|
155
|
+
console.log(chalk.yellow(`⚠️ Core Tools 自动配置已跳过:${coreToolsResult.error}`));
|
|
156
|
+
} else if (coreToolsResult) {
|
|
157
|
+
const mcpAdded = typeof coreToolsResult.mcpAdded === 'number'
|
|
158
|
+
? coreToolsResult.mcpAdded
|
|
159
|
+
: coreToolsResult.added - (coreToolsResult.skillsAdded ? coreToolsResult.skillsAdded.length : 0);
|
|
160
|
+
if (mcpAdded > 0) {
|
|
161
|
+
console.log(chalk.gray(` 已写入 MCP Server 配置: ${mcpAdded} 项 (.claude/settings.local.json)`));
|
|
162
|
+
}
|
|
163
|
+
if (Array.isArray(coreToolsResult.skillsAdded) && coreToolsResult.skillsAdded.length > 0) {
|
|
164
|
+
console.log(chalk.gray(` 已安装 Skill: ${coreToolsResult.skillsAdded.length} 项`));
|
|
165
|
+
}
|
|
166
|
+
if (Array.isArray(coreToolsResult.skillsNeedingCli) && coreToolsResult.skillsNeedingCli.length > 0) {
|
|
167
|
+
coreToolsResult.skillsNeedingCli.forEach(({ pluginId, globalInstall }) => {
|
|
168
|
+
if (!pluginId || !globalInstall) return;
|
|
169
|
+
console.log(chalk.yellow(`⚠️ ${pluginId} 需要全局安装 CLI: ${globalInstall}`));
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (coreToolsResult && Array.isArray(coreToolsResult.missingTemplates) && coreToolsResult.missingTemplates.length > 0) {
|
|
174
|
+
console.log(chalk.yellow(`⚠️ 以下 Core Tools 未提供自动配置模板,请手动配置: ${coreToolsResult.missingTemplates.join(', ')}`));
|
|
175
|
+
}
|
|
176
|
+
if (coreToolsResult && Array.isArray(coreToolsResult.missingEnv) && coreToolsResult.missingEnv.length > 0) {
|
|
177
|
+
coreToolsResult.missingEnv.forEach(({ pluginId, keys }) => {
|
|
178
|
+
if (!pluginId || !Array.isArray(keys) || keys.length === 0) return;
|
|
179
|
+
console.log(chalk.yellow(`⚠️ ${pluginId} 可能缺少环境变量: ${keys.join(', ')}`));
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
146
183
|
// 7. 输出成功信息
|
|
147
184
|
console.log(chalk.green('\n✅ JVibe 初始化完成!\n'));
|
|
148
185
|
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JVibe Plugins Script
|
|
3
|
+
* 配置/检查插件(先从 Core Tools 开始)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs-extra');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const { spawn } = require('child_process');
|
|
10
|
+
const readline = require('readline');
|
|
11
|
+
const {
|
|
12
|
+
loadPluginRegistry,
|
|
13
|
+
configureClaudeCoreTools
|
|
14
|
+
} = require('../lib/plugins/core-tools');
|
|
15
|
+
|
|
16
|
+
function askQuestion(question) {
|
|
17
|
+
// 非交互环境(CI / stdin 重定向 / 管道)下,避免 readline 卡住。
|
|
18
|
+
// 默认选择 "n"(跳过安装),以免误触发全局安装。
|
|
19
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
20
|
+
return Promise.resolve('n');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const rl = readline.createInterface({
|
|
24
|
+
input: process.stdin,
|
|
25
|
+
output: process.stdout
|
|
26
|
+
});
|
|
27
|
+
return new Promise(resolve => {
|
|
28
|
+
let resolved = false;
|
|
29
|
+
const finish = (answer) => {
|
|
30
|
+
if (resolved) return;
|
|
31
|
+
resolved = true;
|
|
32
|
+
try { rl.close(); } catch {}
|
|
33
|
+
resolve((answer || '').trim().toLowerCase());
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
rl.on('close', () => finish('n'));
|
|
37
|
+
rl.on('SIGINT', () => finish('n'));
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
rl.question(question, finish);
|
|
41
|
+
} catch {
|
|
42
|
+
finish('n');
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function installSkillCli(globalInstall) {
|
|
48
|
+
return new Promise((resolve) => {
|
|
49
|
+
console.log(chalk.gray(` 正在安装: ${globalInstall}`));
|
|
50
|
+
|
|
51
|
+
// 解析命令
|
|
52
|
+
const parts = globalInstall.split('&&').map(s => s.trim());
|
|
53
|
+
|
|
54
|
+
const runCommand = (cmd, callback) => {
|
|
55
|
+
const [command, ...args] = cmd.split(/\s+/);
|
|
56
|
+
const child = spawn(command, args, {
|
|
57
|
+
stdio: 'inherit',
|
|
58
|
+
shell: true
|
|
59
|
+
});
|
|
60
|
+
child.on('close', code => callback(code === 0));
|
|
61
|
+
child.on('error', () => callback(false));
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const runSequentially = (commands, index = 0) => {
|
|
65
|
+
if (index >= commands.length) {
|
|
66
|
+
resolve(true);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
runCommand(commands[index], success => {
|
|
70
|
+
if (!success) {
|
|
71
|
+
resolve(false);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
runSequentially(commands, index + 1);
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
runSequentially(parts);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function configureCore() {
|
|
83
|
+
const cwd = process.cwd();
|
|
84
|
+
|
|
85
|
+
const registry = await loadPluginRegistry();
|
|
86
|
+
const claudeDir = path.join(cwd, '.claude');
|
|
87
|
+
|
|
88
|
+
if (!await fs.pathExists(claudeDir)) {
|
|
89
|
+
console.log(chalk.yellow('⚠️ 未检测到 .claude/,已跳过 Core Tools 配置'));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const result = await configureClaudeCoreTools(cwd, registry);
|
|
94
|
+
if (result && result.error) {
|
|
95
|
+
console.log(chalk.yellow(`⚠️ Core Tools 自动配置已跳过:${result.error}`));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// MCP Server 配置结果
|
|
100
|
+
const mcpAdded = typeof result.mcpAdded === 'number'
|
|
101
|
+
? result.mcpAdded
|
|
102
|
+
: result.added - (result.skillsAdded ? result.skillsAdded.length : 0);
|
|
103
|
+
if (mcpAdded > 0) {
|
|
104
|
+
console.log(chalk.green(`✅ 已写入 MCP Server 配置: ${mcpAdded} 项 (.claude/settings.local.json)`));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Skill 配置结果
|
|
108
|
+
if (result && Array.isArray(result.skillsAdded) && result.skillsAdded.length > 0) {
|
|
109
|
+
console.log(chalk.green(`✅ 已安装 Skill: ${result.skillsAdded.length} 项`));
|
|
110
|
+
|
|
111
|
+
for (const { pluginId, skillDir } of result.skillsAdded) {
|
|
112
|
+
console.log(chalk.gray(` - ${pluginId} → ${skillDir}`));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Skill CLI 安装提示(即使 Skill 已存在也提示)
|
|
117
|
+
if (result && Array.isArray(result.skillsNeedingCli) && result.skillsNeedingCli.length > 0) {
|
|
118
|
+
for (const { pluginId, cliCommand, globalInstall } of result.skillsNeedingCli) {
|
|
119
|
+
if (!globalInstall) continue;
|
|
120
|
+
const label = cliCommand ? `${pluginId} (${cliCommand})` : pluginId;
|
|
121
|
+
const answer = await askQuestion(chalk.yellow(` ⚠️ ${label} 需要全局安装 CLI,是否现在安装?(Y/n) `));
|
|
122
|
+
if (answer === '' || answer === 'y' || answer === 'yes') {
|
|
123
|
+
const success = await installSkillCli(globalInstall);
|
|
124
|
+
if (success) {
|
|
125
|
+
console.log(chalk.green(` ✅ ${pluginId} CLI 安装成功`));
|
|
126
|
+
} else {
|
|
127
|
+
console.log(chalk.red(` ❌ ${pluginId} CLI 安装失败,请手动执行: ${globalInstall}`));
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
console.log(chalk.gray(` 跳过安装,稍后可手动执行: ${globalInstall}`));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (
|
|
136
|
+
mcpAdded === 0 &&
|
|
137
|
+
(!result.skillsAdded || result.skillsAdded.length === 0) &&
|
|
138
|
+
(!result.skillsNeedingCli || result.skillsNeedingCli.length === 0)
|
|
139
|
+
) {
|
|
140
|
+
console.log(chalk.green('✅ Core Tools 配置已存在,无需重复写入'));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (result && Array.isArray(result.missingTemplates) && result.missingTemplates.length > 0) {
|
|
144
|
+
console.log(chalk.yellow(`⚠️ 以下 Core Tools 未提供自动配置模板,请手动配置: ${result.missingTemplates.join(', ')}`));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (result && Array.isArray(result.missingEnv) && result.missingEnv.length > 0) {
|
|
148
|
+
console.log(chalk.yellow('⚠️ 以下 Core Tools 可能缺少环境变量,启动 MCP Server 时可能失败:'));
|
|
149
|
+
result.missingEnv.forEach(({ pluginId, keys }) => {
|
|
150
|
+
if (!pluginId || !Array.isArray(keys) || keys.length === 0) return;
|
|
151
|
+
console.log(chalk.yellow(` - ${pluginId}: ${keys.join(', ')}`));
|
|
152
|
+
});
|
|
153
|
+
console.log(chalk.gray(' 提示:在当前 shell 中 export 对应变量后重试'));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module.exports = {
|
|
158
|
+
configureCore
|
|
159
|
+
};
|