@adversity/coding-tool-x 3.0.6 → 3.1.1

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 (133) hide show
  1. package/CHANGELOG.md +38 -18
  2. package/README.md +8 -8
  3. package/dist/web/assets/ConfigTemplates-Bidwfdf2.css +1 -0
  4. package/dist/web/assets/ConfigTemplates-ZrK_s7ma.js +1 -0
  5. package/dist/web/assets/Home-B8YfhZ3c.js +1 -0
  6. package/dist/web/assets/Home-Di2qsylF.css +1 -0
  7. package/dist/web/assets/PluginManager-BD7QUZbU.js +1 -0
  8. package/dist/web/assets/PluginManager-ROyoZ-6m.css +1 -0
  9. package/dist/web/assets/ProjectList-C1fQb9OW.css +1 -0
  10. package/dist/web/assets/ProjectList-DRb1DuHV.js +1 -0
  11. package/dist/web/assets/SessionList-BGJWyneI.css +1 -0
  12. package/dist/web/assets/SessionList-lZ0LKzfT.js +1 -0
  13. package/dist/web/assets/SkillManager-C1xG5B4Q.js +1 -0
  14. package/dist/web/assets/SkillManager-D7pd-d_P.css +1 -0
  15. package/dist/web/assets/Terminal-DGNJeVtc.css +1 -0
  16. package/dist/web/assets/Terminal-DksBo_lM.js +1 -0
  17. package/dist/web/assets/WorkspaceManager-Burx7XOo.js +1 -0
  18. package/dist/web/assets/WorkspaceManager-CrwgQgmP.css +1 -0
  19. package/dist/web/assets/icons-kcfLIMBB.js +1 -0
  20. package/dist/web/assets/index-Ufv5rCa5.css +1 -0
  21. package/dist/web/assets/index-lAkrRC3h.js +2 -0
  22. package/dist/web/assets/markdown-BfC0goYb.css +10 -0
  23. package/dist/web/assets/markdown-C9MYpaSi.js +1 -0
  24. package/dist/web/assets/naive-ui-CSrLusZZ.js +1 -0
  25. package/dist/web/assets/{vendors-D2HHw_aW.js → vendors-CO3Upi1d.js} +2 -2
  26. package/dist/web/assets/vue-vendor-DqyWIXEb.js +45 -0
  27. package/dist/web/assets/xterm-6GBZ9nXN.css +32 -0
  28. package/dist/web/assets/xterm-BJzAjXCH.js +13 -0
  29. package/dist/web/index.html +8 -6
  30. package/package.json +4 -2
  31. package/src/commands/channels.js +48 -1
  32. package/src/commands/cli-type.js +4 -2
  33. package/src/commands/daemon.js +92 -13
  34. package/src/commands/doctor.js +10 -9
  35. package/src/commands/list.js +1 -1
  36. package/src/commands/logs.js +6 -4
  37. package/src/commands/port-config.js +24 -4
  38. package/src/commands/proxy-control.js +12 -6
  39. package/src/commands/search.js +1 -1
  40. package/src/commands/security.js +3 -2
  41. package/src/commands/stats.js +226 -52
  42. package/src/commands/switch.js +1 -1
  43. package/src/commands/toggle-proxy.js +31 -6
  44. package/src/commands/ui.js +8 -1
  45. package/src/commands/update.js +97 -0
  46. package/src/commands/workspace.js +1 -1
  47. package/src/config/default.js +39 -2
  48. package/src/config/loader.js +74 -8
  49. package/src/config/paths.js +105 -33
  50. package/src/index.js +67 -4
  51. package/src/plugins/constants.js +3 -2
  52. package/src/plugins/plugin-api.js +1 -1
  53. package/src/reset-config.js +4 -2
  54. package/src/server/api/agents.js +57 -14
  55. package/src/server/api/channels.js +112 -33
  56. package/src/server/api/codex-channels.js +111 -18
  57. package/src/server/api/codex-proxy.js +14 -8
  58. package/src/server/api/commands.js +71 -18
  59. package/src/server/api/config-export.js +0 -6
  60. package/src/server/api/config-registry.js +11 -3
  61. package/src/server/api/config.js +376 -5
  62. package/src/server/api/convert.js +133 -0
  63. package/src/server/api/dashboard.js +22 -6
  64. package/src/server/api/gemini-channels.js +107 -18
  65. package/src/server/api/gemini-proxy.js +14 -8
  66. package/src/server/api/gemini-sessions.js +1 -1
  67. package/src/server/api/health-check.js +4 -3
  68. package/src/server/api/mcp.js +3 -3
  69. package/src/server/api/opencode-channels.js +419 -0
  70. package/src/server/api/opencode-projects.js +99 -0
  71. package/src/server/api/opencode-proxy.js +198 -0
  72. package/src/server/api/opencode-sessions.js +403 -0
  73. package/src/server/api/opencode-statistics.js +57 -0
  74. package/src/server/api/plugins.js +66 -19
  75. package/src/server/api/prompts.js +2 -2
  76. package/src/server/api/proxy.js +7 -4
  77. package/src/server/api/sessions.js +3 -0
  78. package/src/server/api/skills.js +69 -18
  79. package/src/server/api/workspaces.js +78 -6
  80. package/src/server/codex-proxy-server.js +32 -19
  81. package/src/server/dev-server.js +1 -1
  82. package/src/server/gemini-proxy-server.js +17 -3
  83. package/src/server/index.js +164 -48
  84. package/src/server/opencode-proxy-server.js +4375 -0
  85. package/src/server/proxy-server.js +30 -19
  86. package/src/server/services/agents-service.js +61 -24
  87. package/src/server/services/channel-scheduler.js +9 -5
  88. package/src/server/services/channels.js +70 -12
  89. package/src/server/services/codex-channels.js +61 -23
  90. package/src/server/services/codex-settings-manager.js +271 -49
  91. package/src/server/services/codex-statistics-service.js +2 -2
  92. package/src/server/services/commands-service.js +84 -25
  93. package/src/server/services/config-export-service.js +7 -45
  94. package/src/server/services/config-registry-service.js +63 -17
  95. package/src/server/services/config-sync-manager.js +160 -7
  96. package/src/server/services/config-templates-service.js +204 -51
  97. package/src/server/services/env-checker.js +26 -12
  98. package/src/server/services/env-manager.js +126 -18
  99. package/src/server/services/favorites.js +5 -3
  100. package/src/server/services/gemini-channels.js +37 -15
  101. package/src/server/services/gemini-statistics-service.js +2 -2
  102. package/src/server/services/mcp-service.js +350 -9
  103. package/src/server/services/model-detector.js +707 -221
  104. package/src/server/services/network-access.js +80 -0
  105. package/src/server/services/opencode-channels.js +206 -0
  106. package/src/server/services/opencode-gateway-converter.js +639 -0
  107. package/src/server/services/opencode-sessions.js +663 -0
  108. package/src/server/services/opencode-settings-manager.js +342 -0
  109. package/src/server/services/opencode-statistics-service.js +255 -0
  110. package/src/server/services/plugins-service.js +479 -22
  111. package/src/server/services/prompts-service.js +53 -11
  112. package/src/server/services/proxy-runtime.js +1 -1
  113. package/src/server/services/repo-scanner-base.js +1 -1
  114. package/src/server/services/security-config.js +1 -1
  115. package/src/server/services/session-cache.js +1 -1
  116. package/src/server/services/skill-service.js +300 -46
  117. package/src/server/services/speed-test.js +464 -186
  118. package/src/server/services/statistics-service.js +2 -2
  119. package/src/server/services/terminal-commands.js +10 -3
  120. package/src/server/services/terminal-config.js +1 -1
  121. package/src/server/services/ui-config.js +1 -1
  122. package/src/server/services/workspace-service.js +57 -100
  123. package/src/server/websocket-server.js +132 -3
  124. package/src/ui/menu.js +49 -40
  125. package/src/utils/port-helper.js +22 -8
  126. package/src/utils/session.js +5 -4
  127. package/dist/web/assets/icons-BxudHPiX.js +0 -1
  128. package/dist/web/assets/index-D2VfwJBa.js +0 -14
  129. package/dist/web/assets/index-oXBzu0bd.css +0 -41
  130. package/dist/web/assets/naive-ui-DT-Uur8K.js +0 -1
  131. package/dist/web/assets/vue-vendor-6JaYHOiI.js +0 -44
  132. package/src/server/api/permissions.js +0 -385
  133. package/src/server/services/permission-templates-service.js +0 -308
@@ -8,7 +8,24 @@ const express = require('express');
8
8
  const { PluginsService } = require('../services/plugins-service');
9
9
 
10
10
  const router = express.Router();
11
- const pluginsService = new PluginsService();
11
+ const SUPPORTED_PLATFORMS = ['claude', 'opencode'];
12
+ const pluginServices = new Map();
13
+
14
+ function resolvePlatform(rawPlatform) {
15
+ return SUPPORTED_PLATFORMS.includes(rawPlatform) ? rawPlatform : 'claude';
16
+ }
17
+
18
+ function getPlatform(req) {
19
+ return resolvePlatform(req.query?.platform || req.body?.platform);
20
+ }
21
+
22
+ function getPluginsService(req) {
23
+ const platform = getPlatform(req);
24
+ if (!pluginServices.has(platform)) {
25
+ pluginServices.set(platform, new PluginsService(platform));
26
+ }
27
+ return { platform, service: pluginServices.get(platform) };
28
+ }
12
29
 
13
30
  /**
14
31
  * 获取插件列表
@@ -16,10 +33,12 @@ const pluginsService = new PluginsService();
16
33
  */
17
34
  router.get('/', (req, res) => {
18
35
  try {
19
- const result = pluginsService.listPlugins();
36
+ const { platform, service } = getPluginsService(req);
37
+ const result = service.listPlugins();
20
38
 
21
39
  res.json({
22
40
  success: true,
41
+ platform,
23
42
  ...result
24
43
  });
25
44
  } catch (err) {
@@ -37,10 +56,12 @@ router.get('/', (req, res) => {
37
56
  */
38
57
  router.get('/market', async (req, res) => {
39
58
  try {
40
- const plugins = await pluginsService.getMarketPlugins();
59
+ const { platform, service } = getPluginsService(req);
60
+ const plugins = await service.getMarketPlugins();
41
61
 
42
62
  res.json({
43
63
  success: true,
64
+ platform,
44
65
  plugins
45
66
  });
46
67
  } catch (err) {
@@ -55,26 +76,29 @@ router.get('/market', async (req, res) => {
55
76
  /**
56
77
  * 安装插件
57
78
  * POST /api/plugins/install
58
- * Body: { directory, repo: { owner, name, branch } }
79
+ * Body: { directory, repo: { owner, name, branch } } or { source }
59
80
  */
60
81
  router.post('/install', async (req, res) => {
61
82
  try {
62
- const { directory, repo, gitUrl } = req.body;
83
+ const { platform, service } = getPluginsService(req);
84
+ const { directory, repo, gitUrl, source } = req.body;
63
85
 
64
86
  // Support both new format (directory + repo) and legacy format (gitUrl)
65
87
  let installUrl;
66
- if (directory && repo) {
88
+ if (source) {
89
+ installUrl = source;
90
+ } else if (directory && repo) {
67
91
  installUrl = `https://github.com/${repo.owner}/${repo.name}/tree/${repo.branch || 'main'}/${directory}`;
68
92
  } else if (gitUrl) {
69
93
  installUrl = gitUrl;
70
94
  } else {
71
95
  return res.status(400).json({
72
96
  success: false,
73
- message: 'Either (directory + repo) or gitUrl is required'
97
+ message: 'Either source, (directory + repo), or gitUrl is required'
74
98
  });
75
99
  }
76
100
 
77
- const result = await pluginsService.installPlugin(installUrl);
101
+ const result = await service.installPlugin(installUrl);
78
102
 
79
103
  if (!result.success) {
80
104
  return res.status(400).json({
@@ -85,6 +109,7 @@ router.post('/install', async (req, res) => {
85
109
 
86
110
  res.json({
87
111
  success: true,
112
+ platform,
88
113
  plugin: result.plugin,
89
114
  message: `Plugin "${result.plugin.name}" installed successfully`
90
115
  });
@@ -105,9 +130,11 @@ router.post('/install', async (req, res) => {
105
130
  */
106
131
  router.get('/repos', (req, res) => {
107
132
  try {
108
- const repos = pluginsService.getRepos();
133
+ const { platform, service } = getPluginsService(req);
134
+ const repos = service.getRepos();
109
135
  res.json({
110
136
  success: true,
137
+ platform,
111
138
  repos
112
139
  });
113
140
  } catch (err) {
@@ -126,6 +153,7 @@ router.get('/repos', (req, res) => {
126
153
  */
127
154
  router.post('/repos', (req, res) => {
128
155
  try {
156
+ const { platform, service } = getPluginsService(req);
129
157
  const repo = req.body;
130
158
 
131
159
  if (!repo || !repo.url) {
@@ -135,10 +163,11 @@ router.post('/repos', (req, res) => {
135
163
  });
136
164
  }
137
165
 
138
- const repos = pluginsService.addRepo(repo);
166
+ const repos = service.addRepo(repo);
139
167
 
140
168
  res.json({
141
169
  success: true,
170
+ platform,
142
171
  repos,
143
172
  message: 'Repository added successfully'
144
173
  });
@@ -157,12 +186,14 @@ router.post('/repos', (req, res) => {
157
186
  */
158
187
  router.delete('/repos/:owner/:name', (req, res) => {
159
188
  try {
189
+ const { platform, service } = getPluginsService(req);
160
190
  const { owner, name } = req.params;
161
191
 
162
- const repos = pluginsService.removeRepo(owner, name);
192
+ const repos = service.removeRepo(owner, name);
163
193
 
164
194
  res.json({
165
195
  success: true,
196
+ platform,
166
197
  repos,
167
198
  message: 'Repository removed successfully'
168
199
  });
@@ -182,6 +213,7 @@ router.delete('/repos/:owner/:name', (req, res) => {
182
213
  */
183
214
  router.put('/repos/:owner/:name/toggle', (req, res) => {
184
215
  try {
216
+ const { platform, service } = getPluginsService(req);
185
217
  const { owner, name } = req.params;
186
218
  const { enabled } = req.body;
187
219
 
@@ -192,10 +224,11 @@ router.put('/repos/:owner/:name/toggle', (req, res) => {
192
224
  });
193
225
  }
194
226
 
195
- const repos = pluginsService.toggleRepo(owner, name, enabled);
227
+ const repos = service.toggleRepo(owner, name, enabled);
196
228
 
197
229
  res.json({
198
230
  success: true,
231
+ platform,
199
232
  repos,
200
233
  message: `Repository ${enabled ? 'enabled' : 'disabled'} successfully`
201
234
  });
@@ -214,10 +247,12 @@ router.put('/repos/:owner/:name/toggle', (req, res) => {
214
247
  */
215
248
  router.post('/repos/sync', async (req, res) => {
216
249
  try {
217
- const result = await pluginsService.syncRepos();
250
+ const { platform, service } = getPluginsService(req);
251
+ const result = await service.syncRepos();
218
252
 
219
253
  res.json({
220
254
  success: true,
255
+ platform,
221
256
  ...result,
222
257
  message: 'Repositories synced successfully'
223
258
  });
@@ -236,10 +271,12 @@ router.post('/repos/sync', async (req, res) => {
236
271
  */
237
272
  router.post('/sync', async (req, res) => {
238
273
  try {
239
- const result = await pluginsService.syncPlugins();
274
+ const { platform, service } = getPluginsService(req);
275
+ const result = await service.syncPlugins();
240
276
 
241
277
  res.json({
242
278
  success: true,
279
+ platform,
243
280
  ...result,
244
281
  message: 'Plugins synced successfully'
245
282
  });
@@ -259,6 +296,7 @@ router.post('/sync', async (req, res) => {
259
296
  */
260
297
  router.get('/:name/readme', async (req, res) => {
261
298
  try {
299
+ const { platform, service } = getPluginsService(req);
262
300
  const { name } = req.params;
263
301
  const { repoOwner, repoName, repoBranch, directory, source, repoUrl } = req.query;
264
302
 
@@ -272,10 +310,11 @@ router.get('/:name/readme', async (req, res) => {
272
310
  repoUrl
273
311
  };
274
312
 
275
- const readme = await pluginsService.getPluginReadme(pluginInfo);
313
+ const readme = await service.getPluginReadme(pluginInfo);
276
314
 
277
315
  res.json({
278
316
  success: true,
317
+ platform,
279
318
  readme
280
319
  });
281
320
  } catch (err) {
@@ -294,9 +333,10 @@ router.get('/:name/readme', async (req, res) => {
294
333
  */
295
334
  router.get('/:name', (req, res) => {
296
335
  try {
336
+ const { platform, service } = getPluginsService(req);
297
337
  const { name } = req.params;
298
338
 
299
- const plugin = pluginsService.getPlugin(name);
339
+ const plugin = service.getPlugin(name);
300
340
 
301
341
  if (!plugin) {
302
342
  return res.status(404).json({
@@ -307,6 +347,7 @@ router.get('/:name', (req, res) => {
307
347
 
308
348
  res.json({
309
349
  success: true,
350
+ platform,
310
351
  plugin
311
352
  });
312
353
  } catch (err) {
@@ -324,9 +365,10 @@ router.get('/:name', (req, res) => {
324
365
  */
325
366
  router.delete('/:name', (req, res) => {
326
367
  try {
368
+ const { platform, service } = getPluginsService(req);
327
369
  const { name } = req.params;
328
370
 
329
- const result = pluginsService.uninstallPlugin(name);
371
+ const result = service.uninstallPlugin(name);
330
372
 
331
373
  if (!result.success) {
332
374
  return res.status(400).json({
@@ -337,6 +379,7 @@ router.delete('/:name', (req, res) => {
337
379
 
338
380
  res.json({
339
381
  success: true,
382
+ platform,
340
383
  message: result.message
341
384
  });
342
385
  } catch (err) {
@@ -355,6 +398,7 @@ router.delete('/:name', (req, res) => {
355
398
  */
356
399
  router.put('/:name/toggle', (req, res) => {
357
400
  try {
401
+ const { platform, service } = getPluginsService(req);
358
402
  const { name } = req.params;
359
403
  const { enabled } = req.body;
360
404
 
@@ -365,10 +409,11 @@ router.put('/:name/toggle', (req, res) => {
365
409
  });
366
410
  }
367
411
 
368
- const plugin = pluginsService.togglePlugin(name, enabled);
412
+ const plugin = service.togglePlugin(name, enabled);
369
413
 
370
414
  res.json({
371
415
  success: true,
416
+ platform,
372
417
  plugin,
373
418
  message: `Plugin "${name}" ${enabled ? 'enabled' : 'disabled'} successfully`
374
419
  });
@@ -388,6 +433,7 @@ router.put('/:name/toggle', (req, res) => {
388
433
  */
389
434
  router.put('/:name/config', (req, res) => {
390
435
  try {
436
+ const { platform, service } = getPluginsService(req);
391
437
  const { name } = req.params;
392
438
  const { config } = req.body;
393
439
 
@@ -398,10 +444,11 @@ router.put('/:name/config', (req, res) => {
398
444
  });
399
445
  }
400
446
 
401
- const result = pluginsService.updatePluginConfig(name, config);
447
+ const result = service.updatePluginConfig(name, config);
402
448
 
403
449
  res.json({
404
450
  success: true,
451
+ platform,
405
452
  message: result.message
406
453
  });
407
454
  } catch (err) {
@@ -203,7 +203,7 @@ router.get('/platform/:platform', (req, res) => {
203
203
  try {
204
204
  const { platform } = req.params;
205
205
 
206
- if (!['claude', 'codex', 'gemini'].includes(platform)) {
206
+ if (!['claude', 'codex', 'gemini', 'opencode'].includes(platform)) {
207
207
  return res.status(400).json({
208
208
  success: false,
209
209
  error: `无效的平台: ${platform}`
@@ -234,7 +234,7 @@ router.post('/import/:platform', (req, res) => {
234
234
  const { platform } = req.params;
235
235
  const { name } = req.body;
236
236
 
237
- if (!['claude', 'codex', 'gemini'].includes(platform)) {
237
+ if (!['claude', 'codex', 'gemini', 'opencode'].includes(platform)) {
238
238
  return res.status(400).json({
239
239
  success: false,
240
240
  error: `无效的平台: ${platform}`
@@ -12,6 +12,7 @@ const {
12
12
  } = require('../services/settings-manager');
13
13
  const { getAllChannels } = require('../services/channels');
14
14
  const { clearAllLogs } = require('../websocket-server');
15
+ const { PATHS, ensureStorageDirMigrated } = require('../../config/paths');
15
16
  const fs = require('fs');
16
17
  const path = require('path');
17
18
  const os = require('os');
@@ -28,18 +29,20 @@ function sanitizeChannelForResponse(channel) {
28
29
 
29
30
  // 保存激活渠道ID
30
31
  function saveActiveChannelId(channelId) {
31
- const dir = path.join(os.homedir(), '.claude', 'cc-tool');
32
+ ensureStorageDirMigrated();
33
+ const filePath = PATHS.activeChannel.claude;
34
+ const dir = path.dirname(filePath);
32
35
  if (!fs.existsSync(dir)) {
33
36
  fs.mkdirSync(dir, { recursive: true });
34
37
  }
35
- const filePath = path.join(dir, 'active-channel.json');
36
38
  fs.writeFileSync(filePath, JSON.stringify({ activeChannelId: channelId }, null, 2), 'utf8');
37
39
  }
38
40
 
39
41
 
40
42
  // 加载上次激活的渠道ID
41
43
  function loadActiveChannelId() {
42
- const filePath = path.join(os.homedir(), '.claude', 'cc-tool', 'active-channel.json');
44
+ ensureStorageDirMigrated();
45
+ const filePath = PATHS.activeChannel.claude;
43
46
  try {
44
47
  if (fs.existsSync(filePath)) {
45
48
  const content = fs.readFileSync(filePath, 'utf8');
@@ -246,7 +249,7 @@ router.post('/stop', async (req, res) => {
246
249
  }
247
250
  }
248
251
 
249
- const activeChannelPath = path.join(os.homedir(), '.claude', 'cc-tool', 'active-channel.json');
252
+ const activeChannelPath = PATHS.activeChannel.claude;
250
253
  if (fs.existsSync(activeChannelPath)) {
251
254
  fs.unlinkSync(activeChannelPath);
252
255
  console.log('✅ Removed active-channel.json');
@@ -189,6 +189,9 @@ module.exports = (config) => {
189
189
  try {
190
190
  const { projectName } = req.params;
191
191
  const { order } = req.body;
192
+ if (!Array.isArray(order)) {
193
+ return res.status(400).json({ error: 'order must be an array' });
194
+ }
192
195
  saveSessionOrder(projectName, order);
193
196
  res.json({ success: true });
194
197
  } catch (error) {
@@ -6,7 +6,24 @@ const express = require('express');
6
6
  const { SkillService } = require('../services/skill-service');
7
7
 
8
8
  const router = express.Router();
9
- const skillService = new SkillService();
9
+ const SUPPORTED_PLATFORMS = ['claude', 'codex', 'opencode'];
10
+ const skillServices = new Map();
11
+
12
+ function resolvePlatform(rawPlatform) {
13
+ return SUPPORTED_PLATFORMS.includes(rawPlatform) ? rawPlatform : 'claude';
14
+ }
15
+
16
+ function getPlatform(req) {
17
+ return resolvePlatform(req.query?.platform || req.body?.platform);
18
+ }
19
+
20
+ function getSkillService(req) {
21
+ const platform = getPlatform(req);
22
+ if (!skillServices.has(platform)) {
23
+ skillServices.set(platform, new SkillService(platform));
24
+ }
25
+ return { platform, service: skillServices.get(platform) };
26
+ }
10
27
 
11
28
  /**
12
29
  * 获取技能列表
@@ -15,10 +32,12 @@ const skillService = new SkillService();
15
32
  */
16
33
  router.get('/', async (req, res) => {
17
34
  try {
35
+ const { platform, service } = getSkillService(req);
18
36
  const forceRefresh = req.query.refresh === '1';
19
- const skills = await skillService.listSkills(forceRefresh);
37
+ const skills = await service.listSkills(forceRefresh);
20
38
  res.json({
21
39
  success: true,
40
+ platform,
22
41
  skills,
23
42
  total: skills.length,
24
43
  installed: skills.filter(s => s.installed).length
@@ -38,6 +57,7 @@ router.get('/', async (req, res) => {
38
57
  */
39
58
  router.get('/detail/*', async (req, res) => {
40
59
  try {
60
+ const { platform, service } = getSkillService(req);
41
61
  const directory = req.params[0]; // 获取通配符匹配的路径
42
62
  if (!directory) {
43
63
  return res.status(400).json({
@@ -46,9 +66,10 @@ router.get('/detail/*', async (req, res) => {
46
66
  });
47
67
  }
48
68
 
49
- const result = await skillService.getSkillDetail(directory);
69
+ const result = await service.getSkillDetail(directory);
50
70
  res.json({
51
71
  success: true,
72
+ platform,
52
73
  ...result
53
74
  });
54
75
  } catch (err) {
@@ -66,9 +87,11 @@ router.get('/detail/*', async (req, res) => {
66
87
  */
67
88
  router.get('/installed', (req, res) => {
68
89
  try {
69
- const skills = skillService.getInstalledSkills();
90
+ const { platform, service } = getSkillService(req);
91
+ const skills = service.getInstalledSkills();
70
92
  res.json({
71
93
  success: true,
94
+ platform,
72
95
  skills
73
96
  });
74
97
  } catch (err) {
@@ -89,6 +112,7 @@ router.get('/installed', (req, res) => {
89
112
  */
90
113
  router.post('/install', async (req, res) => {
91
114
  try {
115
+ const { platform, service } = getSkillService(req);
92
116
  const { directory, fullDirectory, repo } = req.body;
93
117
 
94
118
  if (!directory) {
@@ -105,7 +129,7 @@ router.post('/install', async (req, res) => {
105
129
  });
106
130
  }
107
131
 
108
- const result = await skillService.installSkill(
132
+ const result = await service.installSkill(
109
133
  directory,
110
134
  {
111
135
  owner: repo.owner,
@@ -117,6 +141,7 @@ router.post('/install', async (req, res) => {
117
141
 
118
142
  res.json({
119
143
  success: true,
144
+ platform,
120
145
  ...result
121
146
  });
122
147
  } catch (err) {
@@ -135,6 +160,7 @@ router.post('/install', async (req, res) => {
135
160
  */
136
161
  router.post('/create', (req, res) => {
137
162
  try {
163
+ const { platform, service } = getSkillService(req);
138
164
  const { name, directory, description, content } = req.body;
139
165
 
140
166
  if (!directory) {
@@ -159,7 +185,7 @@ router.post('/create', (req, res) => {
159
185
  });
160
186
  }
161
187
 
162
- const result = skillService.createCustomSkill({
188
+ const result = service.createCustomSkill({
163
189
  name: name || directory,
164
190
  directory,
165
191
  description: description || '',
@@ -168,6 +194,7 @@ router.post('/create', (req, res) => {
168
194
 
169
195
  res.json({
170
196
  success: true,
197
+ platform,
171
198
  ...result
172
199
  });
173
200
  } catch (err) {
@@ -186,6 +213,7 @@ router.post('/create', (req, res) => {
186
213
  */
187
214
  router.post('/uninstall', (req, res) => {
188
215
  try {
216
+ const { platform, service } = getSkillService(req);
189
217
  const { directory } = req.body;
190
218
 
191
219
  if (!directory) {
@@ -195,10 +223,11 @@ router.post('/uninstall', (req, res) => {
195
223
  });
196
224
  }
197
225
 
198
- const result = skillService.uninstallSkill(directory);
226
+ const result = service.uninstallSkill(directory);
199
227
 
200
228
  res.json({
201
229
  success: true,
230
+ platform,
202
231
  ...result
203
232
  });
204
233
  } catch (err) {
@@ -216,9 +245,11 @@ router.post('/uninstall', (req, res) => {
216
245
  */
217
246
  router.get('/repos', (req, res) => {
218
247
  try {
219
- const repos = skillService.loadRepos();
248
+ const { platform, service } = getSkillService(req);
249
+ const repos = service.loadRepos();
220
250
  res.json({
221
251
  success: true,
252
+ platform,
222
253
  repos
223
254
  });
224
255
  } catch (err) {
@@ -238,6 +269,7 @@ router.get('/repos', (req, res) => {
238
269
  */
239
270
  router.post('/repos', (req, res) => {
240
271
  try {
272
+ const { platform, service } = getSkillService(req);
241
273
  const { owner, name, branch = 'main', directory = '', enabled = true } = req.body;
242
274
 
243
275
  if (!owner || !name) {
@@ -247,10 +279,11 @@ router.post('/repos', (req, res) => {
247
279
  });
248
280
  }
249
281
 
250
- const repos = skillService.addRepo({ owner, name, branch, directory, enabled });
282
+ const repos = service.addRepo({ owner, name, branch, directory, enabled });
251
283
 
252
284
  res.json({
253
285
  success: true,
286
+ platform,
254
287
  repos
255
288
  });
256
289
  } catch (err) {
@@ -269,12 +302,14 @@ router.post('/repos', (req, res) => {
269
302
  */
270
303
  router.delete('/repos/:owner/:name', (req, res) => {
271
304
  try {
305
+ const { platform, service } = getSkillService(req);
272
306
  const { owner, name } = req.params;
273
307
  const { directory = '' } = req.query;
274
- const repos = skillService.removeRepo(owner, name, directory);
308
+ const repos = service.removeRepo(owner, name, directory);
275
309
 
276
310
  res.json({
277
311
  success: true,
312
+ platform,
278
313
  repos
279
314
  });
280
315
  } catch (err) {
@@ -294,13 +329,15 @@ router.delete('/repos/:owner/:name', (req, res) => {
294
329
  */
295
330
  router.put('/repos/:owner/:name/toggle', (req, res) => {
296
331
  try {
332
+ const { platform, service } = getSkillService(req);
297
333
  const { owner, name } = req.params;
298
334
  const { enabled, directory = '' } = req.body;
299
335
 
300
- const repos = skillService.toggleRepo(owner, name, directory, enabled);
336
+ const repos = service.toggleRepo(owner, name, directory, enabled);
301
337
 
302
338
  res.json({
303
339
  success: true,
340
+ platform,
304
341
  repos
305
342
  });
306
343
  } catch (err) {
@@ -321,6 +358,7 @@ router.put('/repos/:owner/:name/toggle', (req, res) => {
321
358
  */
322
359
  router.post('/create-with-files', (req, res) => {
323
360
  try {
361
+ const { platform, service } = getSkillService(req);
324
362
  const { directory, files } = req.body;
325
363
 
326
364
  if (!directory) {
@@ -345,10 +383,11 @@ router.post('/create-with-files', (req, res) => {
345
383
  });
346
384
  }
347
385
 
348
- const result = skillService.createSkillWithFiles({ directory, files });
386
+ const result = service.createSkillWithFiles({ directory, files });
349
387
 
350
388
  res.json({
351
389
  success: true,
390
+ platform,
352
391
  ...result
353
392
  });
354
393
  } catch (err) {
@@ -366,11 +405,13 @@ router.post('/create-with-files', (req, res) => {
366
405
  */
367
406
  router.get('/:directory/files', (req, res) => {
368
407
  try {
408
+ const { platform, service } = getSkillService(req);
369
409
  const { directory } = req.params;
370
- const files = skillService.getSkillFiles(directory);
410
+ const files = service.getSkillFiles(directory);
371
411
 
372
412
  res.json({
373
413
  success: true,
414
+ platform,
374
415
  directory,
375
416
  files
376
417
  });
@@ -390,6 +431,7 @@ router.get('/:directory/files', (req, res) => {
390
431
  */
391
432
  router.get('/:directory/file/*', (req, res) => {
392
433
  try {
434
+ const { platform, service } = getSkillService(req);
393
435
  const { directory } = req.params;
394
436
  const filePath = req.params[0];
395
437
 
@@ -400,10 +442,11 @@ router.get('/:directory/file/*', (req, res) => {
400
442
  });
401
443
  }
402
444
 
403
- const result = skillService.getSkillFileContent(directory, filePath);
445
+ const result = service.getSkillFileContent(directory, filePath);
404
446
 
405
447
  res.json({
406
448
  success: true,
449
+ platform,
407
450
  ...result
408
451
  });
409
452
  } catch (err) {
@@ -422,6 +465,7 @@ router.get('/:directory/file/*', (req, res) => {
422
465
  */
423
466
  router.post('/:directory/files', (req, res) => {
424
467
  try {
468
+ const { platform, service } = getSkillService(req);
425
469
  const { directory } = req.params;
426
470
  const { files } = req.body;
427
471
 
@@ -432,10 +476,11 @@ router.post('/:directory/files', (req, res) => {
432
476
  });
433
477
  }
434
478
 
435
- const result = skillService.addSkillFiles(directory, files);
479
+ const result = service.addSkillFiles(directory, files);
436
480
 
437
481
  res.json({
438
482
  success: true,
483
+ platform,
439
484
  ...result
440
485
  });
441
486
  } catch (err) {
@@ -453,6 +498,7 @@ router.post('/:directory/files', (req, res) => {
453
498
  */
454
499
  router.delete('/:directory/file/*', (req, res) => {
455
500
  try {
501
+ const { platform, service } = getSkillService(req);
456
502
  const { directory } = req.params;
457
503
  const filePath = req.params[0];
458
504
 
@@ -463,10 +509,11 @@ router.delete('/:directory/file/*', (req, res) => {
463
509
  });
464
510
  }
465
511
 
466
- const result = skillService.deleteSkillFile(directory, filePath);
512
+ const result = service.deleteSkillFile(directory, filePath);
467
513
 
468
514
  res.json({
469
515
  success: true,
516
+ platform,
470
517
  ...result
471
518
  });
472
519
  } catch (err) {
@@ -485,6 +532,7 @@ router.delete('/:directory/file/*', (req, res) => {
485
532
  */
486
533
  router.put('/:directory/file/*', (req, res) => {
487
534
  try {
535
+ const { platform, service } = getSkillService(req);
488
536
  const { directory } = req.params;
489
537
  const filePath = req.params[0];
490
538
  const { content, isBase64 = false } = req.body;
@@ -503,10 +551,11 @@ router.put('/:directory/file/*', (req, res) => {
503
551
  });
504
552
  }
505
553
 
506
- const result = skillService.updateSkillFile(directory, filePath, content, isBase64);
554
+ const result = service.updateSkillFile(directory, filePath, content, isBase64);
507
555
 
508
556
  res.json({
509
557
  success: true,
558
+ platform,
510
559
  ...result
511
560
  });
512
561
  } catch (err) {
@@ -529,6 +578,7 @@ router.put('/:directory/file/*', (req, res) => {
529
578
  */
530
579
  router.post('/convert', (req, res) => {
531
580
  try {
581
+ const { platform, service } = getSkillService(req);
532
582
  const { content, targetFormat } = req.body;
533
583
 
534
584
  if (!content) {
@@ -545,10 +595,11 @@ router.post('/convert', (req, res) => {
545
595
  });
546
596
  }
547
597
 
548
- const result = skillService.convertSkillFormat(content, targetFormat);
598
+ const result = service.convertSkillFormat(content, targetFormat);
549
599
 
550
600
  res.json({
551
601
  success: true,
602
+ platform,
552
603
  ...result
553
604
  });
554
605
  } catch (err) {