@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.
@@ -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: { gitUrl }
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
- if (!gitUrl) {
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: 'Git URL is required'
73
+ message: 'Either (directory + repo) or gitUrl is required'
47
74
  });
48
75
  }
49
76
 
50
- const result = await pluginsService.installPlugin(gitUrl);
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/:id
156
+ * DELETE /api/plugins/repos/:owner/:name
130
157
  */
131
- router.delete('/repos/:id', (req, res) => {
158
+ router.delete('/repos/:owner/:name', (req, res) => {
132
159
  try {
133
- const { id } = req.params;
160
+ const { owner, name } = req.params;
134
161
 
135
- const repos = pluginsService.removeRepo(id);
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);