@adversity/coding-tool-x 2.6.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web/assets/icons-BlzwYoRU.js +1 -0
- package/dist/web/assets/{index-Ej0MPDUI.js → index-AtwYwBZD.js} +2 -2
- package/dist/web/assets/index-BNHWEpD4.css +41 -0
- package/dist/web/assets/{naive-ui-sh0u_0bf.js → naive-ui-BcSq2wzw.js} +1 -1
- package/dist/web/assets/{vendors-CzcvkTIS.js → vendors-D2HHw_aW.js} +1 -1
- package/dist/web/assets/{vue-vendor-CEeI-Azr.js → vue-vendor-6JaYHOiI.js} +1 -1
- package/dist/web/index.html +6 -6
- package/package.json +2 -1
- package/src/plugins/constants.js +14 -0
- package/src/plugins/event-bus.js +54 -0
- package/src/plugins/manifest-validator.js +129 -0
- package/src/plugins/plugin-api.js +128 -0
- package/src/plugins/plugin-installer.js +601 -0
- package/src/plugins/plugin-loader.js +229 -0
- package/src/plugins/plugin-manager.js +170 -0
- package/src/plugins/registry.js +152 -0
- package/src/plugins/schema/plugin-manifest.json +115 -0
- package/src/server/api/mcp.js +1 -1
- package/src/server/api/plugins.js +150 -10
- package/src/server/api/sessions.js +4 -4
- package/src/server/services/plugins-service.js +537 -37
- package/src/server/services/sessions.js +72 -16
- package/dist/web/assets/icons-CNM9_Fh0.js +0 -1
- package/dist/web/assets/index-BcmuQT-z.css +0 -41
|
@@ -31,23 +31,50 @@ router.get('/', (req, res) => {
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* 获取市场插件列表
|
|
36
|
+
* GET /api/plugins/market
|
|
37
|
+
*/
|
|
38
|
+
router.get('/market', async (req, res) => {
|
|
39
|
+
try {
|
|
40
|
+
const plugins = await pluginsService.getMarketPlugins();
|
|
41
|
+
|
|
42
|
+
res.json({
|
|
43
|
+
success: true,
|
|
44
|
+
plugins
|
|
45
|
+
});
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.error('[Plugins API] Get market plugins error:', err);
|
|
48
|
+
res.status(500).json({
|
|
49
|
+
success: false,
|
|
50
|
+
message: err.message
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
34
55
|
/**
|
|
35
56
|
* 安装插件
|
|
36
57
|
* POST /api/plugins/install
|
|
37
|
-
* Body: {
|
|
58
|
+
* Body: { directory, repo: { owner, name, branch } }
|
|
38
59
|
*/
|
|
39
60
|
router.post('/install', async (req, res) => {
|
|
40
61
|
try {
|
|
41
|
-
const { gitUrl } = req.body;
|
|
42
|
-
|
|
43
|
-
|
|
62
|
+
const { directory, repo, gitUrl } = req.body;
|
|
63
|
+
|
|
64
|
+
// Support both new format (directory + repo) and legacy format (gitUrl)
|
|
65
|
+
let installUrl;
|
|
66
|
+
if (directory && repo) {
|
|
67
|
+
installUrl = `https://github.com/${repo.owner}/${repo.name}/tree/${repo.branch || 'main'}/${directory}`;
|
|
68
|
+
} else if (gitUrl) {
|
|
69
|
+
installUrl = gitUrl;
|
|
70
|
+
} else {
|
|
44
71
|
return res.status(400).json({
|
|
45
72
|
success: false,
|
|
46
|
-
message: '
|
|
73
|
+
message: 'Either (directory + repo) or gitUrl is required'
|
|
47
74
|
});
|
|
48
75
|
}
|
|
49
76
|
|
|
50
|
-
const result = await pluginsService.installPlugin(
|
|
77
|
+
const result = await pluginsService.installPlugin(installUrl);
|
|
51
78
|
|
|
52
79
|
if (!result.success) {
|
|
53
80
|
return res.status(400).json({
|
|
@@ -126,13 +153,13 @@ router.post('/repos', (req, res) => {
|
|
|
126
153
|
|
|
127
154
|
/**
|
|
128
155
|
* 删除插件仓库
|
|
129
|
-
* DELETE /api/plugins/repos/:
|
|
156
|
+
* DELETE /api/plugins/repos/:owner/:name
|
|
130
157
|
*/
|
|
131
|
-
router.delete('/repos/:
|
|
158
|
+
router.delete('/repos/:owner/:name', (req, res) => {
|
|
132
159
|
try {
|
|
133
|
-
const {
|
|
160
|
+
const { owner, name } = req.params;
|
|
134
161
|
|
|
135
|
-
const repos = pluginsService.removeRepo(
|
|
162
|
+
const repos = pluginsService.removeRepo(owner, name);
|
|
136
163
|
|
|
137
164
|
res.json({
|
|
138
165
|
success: true,
|
|
@@ -148,6 +175,119 @@ router.delete('/repos/:id', (req, res) => {
|
|
|
148
175
|
}
|
|
149
176
|
});
|
|
150
177
|
|
|
178
|
+
/**
|
|
179
|
+
* 切换插件仓库启用状态
|
|
180
|
+
* PUT /api/plugins/repos/:owner/:name/toggle
|
|
181
|
+
* Body: { enabled }
|
|
182
|
+
*/
|
|
183
|
+
router.put('/repos/:owner/:name/toggle', (req, res) => {
|
|
184
|
+
try {
|
|
185
|
+
const { owner, name } = req.params;
|
|
186
|
+
const { enabled } = req.body;
|
|
187
|
+
|
|
188
|
+
if (typeof enabled !== 'boolean') {
|
|
189
|
+
return res.status(400).json({
|
|
190
|
+
success: false,
|
|
191
|
+
message: 'enabled must be a boolean'
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const repos = pluginsService.toggleRepo(owner, name, enabled);
|
|
196
|
+
|
|
197
|
+
res.json({
|
|
198
|
+
success: true,
|
|
199
|
+
repos,
|
|
200
|
+
message: `Repository ${enabled ? 'enabled' : 'disabled'} successfully`
|
|
201
|
+
});
|
|
202
|
+
} catch (err) {
|
|
203
|
+
console.error('[Plugins API] Toggle repo error:', err);
|
|
204
|
+
res.status(500).json({
|
|
205
|
+
success: false,
|
|
206
|
+
message: err.message
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* 同步仓库到 Claude Code marketplace
|
|
213
|
+
* POST /api/plugins/repos/sync
|
|
214
|
+
*/
|
|
215
|
+
router.post('/repos/sync', async (req, res) => {
|
|
216
|
+
try {
|
|
217
|
+
const result = await pluginsService.syncRepos();
|
|
218
|
+
|
|
219
|
+
res.json({
|
|
220
|
+
success: true,
|
|
221
|
+
...result,
|
|
222
|
+
message: 'Repositories synced successfully'
|
|
223
|
+
});
|
|
224
|
+
} catch (err) {
|
|
225
|
+
console.error('[Plugins API] Sync repos error:', err);
|
|
226
|
+
res.status(500).json({
|
|
227
|
+
success: false,
|
|
228
|
+
message: err.message
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* 同步本地插件列表
|
|
235
|
+
* POST /api/plugins/sync
|
|
236
|
+
*/
|
|
237
|
+
router.post('/sync', async (req, res) => {
|
|
238
|
+
try {
|
|
239
|
+
const result = await pluginsService.syncPlugins();
|
|
240
|
+
|
|
241
|
+
res.json({
|
|
242
|
+
success: true,
|
|
243
|
+
...result,
|
|
244
|
+
message: 'Plugins synced successfully'
|
|
245
|
+
});
|
|
246
|
+
} catch (err) {
|
|
247
|
+
console.error('[Plugins API] Sync plugins error:', err);
|
|
248
|
+
res.status(500).json({
|
|
249
|
+
success: false,
|
|
250
|
+
message: err.message
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* 获取插件 README
|
|
257
|
+
* GET /api/plugins/:name/readme
|
|
258
|
+
* Query: repoOwner, repoName, repoBranch, directory, source, repoUrl
|
|
259
|
+
*/
|
|
260
|
+
router.get('/:name/readme', async (req, res) => {
|
|
261
|
+
try {
|
|
262
|
+
const { name } = req.params;
|
|
263
|
+
const { repoOwner, repoName, repoBranch, directory, source, repoUrl } = req.query;
|
|
264
|
+
|
|
265
|
+
const pluginInfo = {
|
|
266
|
+
name,
|
|
267
|
+
repoOwner,
|
|
268
|
+
repoName,
|
|
269
|
+
repoBranch,
|
|
270
|
+
directory,
|
|
271
|
+
source,
|
|
272
|
+
repoUrl
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const readme = await pluginsService.getPluginReadme(pluginInfo);
|
|
276
|
+
|
|
277
|
+
res.json({
|
|
278
|
+
success: true,
|
|
279
|
+
readme
|
|
280
|
+
});
|
|
281
|
+
} catch (err) {
|
|
282
|
+
console.error('[Plugins API] Get plugin README error:', err);
|
|
283
|
+
res.status(500).json({
|
|
284
|
+
success: false,
|
|
285
|
+
message: err.message,
|
|
286
|
+
readme: ''
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
|
|
151
291
|
/**
|
|
152
292
|
* 获取单个插件详情
|
|
153
293
|
* GET /api/plugins/:name
|
|
@@ -10,7 +10,7 @@ const { broadcastLog } = require('../websocket-server');
|
|
|
10
10
|
|
|
11
11
|
module.exports = (config) => {
|
|
12
12
|
// GET /api/sessions/search/global - Search sessions across all projects
|
|
13
|
-
router.get('/search/global', (req, res) => {
|
|
13
|
+
router.get('/search/global', async (req, res) => {
|
|
14
14
|
try {
|
|
15
15
|
const { keyword, context } = req.query;
|
|
16
16
|
|
|
@@ -19,7 +19,7 @@ module.exports = (config) => {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
const contextLength = context ? parseInt(context) : 35;
|
|
22
|
-
const results = searchSessionsAcrossProjects(config, keyword, contextLength);
|
|
22
|
+
const results = await searchSessionsAcrossProjects(config, keyword, contextLength);
|
|
23
23
|
|
|
24
24
|
res.json({
|
|
25
25
|
keyword,
|
|
@@ -33,10 +33,10 @@ module.exports = (config) => {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
// GET /api/sessions/recent - Get recent sessions across all projects
|
|
36
|
-
router.get('/recent/list', (req, res) => {
|
|
36
|
+
router.get('/recent/list', async (req, res) => {
|
|
37
37
|
try {
|
|
38
38
|
const limit = parseInt(req.query.limit) || 5;
|
|
39
|
-
const sessions = getRecentSessions(config, limit);
|
|
39
|
+
const sessions = await getRecentSessions(config, limit);
|
|
40
40
|
res.json({ sessions });
|
|
41
41
|
} catch (error) {
|
|
42
42
|
console.error('Error fetching recent sessions:', error);
|