coding-tool-x 3.6.7 → 3.6.9
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/{Analytics-CKycBI0G.js → Analytics-BuBlsbcI.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-CACLQb8e.js → ConfigTemplates-DQczxuOX.js} +1 -1
- package/dist/web/assets/Home-BvAzzWnB.js +1 -0
- package/dist/web/assets/Home-CIua-b-o.css +1 -0
- package/dist/web/assets/{PluginManager-CQJl_uso.js → PluginManager-C8gAlaps.js} +1 -1
- package/dist/web/assets/{ProjectList-DSkvQFEP.js → ProjectList-nqgi6_cR.js} +1 -1
- package/dist/web/assets/{SessionList-Czjs1GN1.js → SessionList-D8AxMYy6.js} +1 -1
- package/dist/web/assets/{SkillManager-Cg1xZ5Cv.js → SkillManager-BDbNbNkK.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-COjYeKvN.js → WorkspaceManager-DGGaGW2c.js} +1 -1
- package/dist/web/assets/index-Dsh4Q5Cg.css +1 -0
- package/dist/web/assets/index-y-eEayxR.js +2 -0
- package/dist/web/assets/{naive-ui-DM897mIP.js → naive-ui-kcWDeJwl.js} +1 -1
- package/dist/web/index.html +3 -3
- package/package.json +1 -1
- package/src/commands/stats.js +1 -1
- package/src/config/channel-preset-websites.js +2 -1
- package/src/config/paths.js +8 -0
- package/src/server/api/agents.js +16 -54
- package/src/server/api/claude-hooks.js +1 -1
- package/src/server/api/claude-statistics.js +57 -0
- package/src/server/api/commands.js +16 -54
- package/src/server/api/dashboard.js +2 -2
- package/src/server/api/gemini-channels.js +2 -0
- package/src/server/api/hooks.js +4 -1
- package/src/server/api/plugins.js +46 -69
- package/src/server/api/skills.js +21 -77
- package/src/server/api/validation-errors.js +34 -0
- package/src/server/gemini-proxy-server.js +205 -21
- package/src/server/index.js +1 -0
- package/src/server/services/agents-service.js +166 -75
- package/src/server/services/base/base-channel-service.js +15 -0
- package/src/server/services/base/response-usage-parser.js +44 -0
- package/src/server/services/channel-balance.js +86 -1
- package/src/server/services/claude-statistics-service.js +139 -0
- package/src/server/services/commands-service.js +203 -121
- package/src/server/services/config-artifact-paths.js +116 -0
- package/src/server/services/config-export-service.js +7 -6
- package/src/server/services/config-registry-service.js +2 -2
- package/src/server/services/config-sync-manager.js +45 -11
- package/src/server/services/config-templates-service.js +21 -19
- package/src/server/services/format-converter.js +42 -4
- package/src/server/services/gemini-channels.js +30 -1
- package/src/server/services/gemini-sessions.js +347 -61
- package/src/server/services/mcp-client.js +236 -49
- package/src/server/services/mcp-service.js +51 -64
- package/src/server/services/notification-hooks.js +659 -88
- package/src/server/services/opencode-channels.js +15 -0
- package/src/server/services/plugins-service.js +1137 -86
- package/src/server/services/repo-scanner-base.js +6 -29
- package/src/server/services/skill-service.js +198 -65
- package/dist/web/assets/Home-BeGkC4bb.css +0 -1
- package/dist/web/assets/Home-Bk6sP5Ed.js +0 -1
- package/dist/web/assets/index-0isNzXNY.css +0 -1
- package/dist/web/assets/index-fWgvlZQx.js +0 -2
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
const express = require('express');
|
|
8
8
|
const { PluginsService } = require('../services/plugins-service');
|
|
9
9
|
const { maskToken } = require('../services/oauth-utils');
|
|
10
|
+
const { sendApiError } = require('./validation-errors');
|
|
10
11
|
|
|
11
12
|
const router = express.Router();
|
|
12
|
-
const SUPPORTED_PLATFORMS = ['claude', 'opencode'];
|
|
13
|
+
const SUPPORTED_PLATFORMS = ['claude', 'codex', 'gemini', 'opencode'];
|
|
13
14
|
const pluginServices = new Map();
|
|
14
15
|
|
|
15
16
|
function resolvePlatform(rawPlatform) {
|
|
@@ -41,7 +42,8 @@ function extractRepoPayload(source = {}) {
|
|
|
41
42
|
projectPath: repo.projectPath || source.projectPath || '',
|
|
42
43
|
localPath: repo.localPath || source.localPath || '',
|
|
43
44
|
repoUrl: repo.repoUrl || repo.url || source.repoUrl || source.url || '',
|
|
44
|
-
token: repo.token || source.token || ''
|
|
45
|
+
token: repo.token || source.token || '',
|
|
46
|
+
marketplace: repo.marketplace || source.marketplace || ''
|
|
45
47
|
};
|
|
46
48
|
}
|
|
47
49
|
|
|
@@ -63,6 +65,28 @@ function sanitizeRepos(service, repos = []) {
|
|
|
63
65
|
return (Array.isArray(repos) ? repos : []).map(sanitizeRepo);
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
/**
|
|
69
|
+
* 获取平台插件能力
|
|
70
|
+
* GET /api/plugins/capabilities
|
|
71
|
+
*/
|
|
72
|
+
router.get('/capabilities', (req, res) => {
|
|
73
|
+
try {
|
|
74
|
+
const { platform, service } = getPluginsService(req);
|
|
75
|
+
const capabilities = typeof service.getCapabilities === 'function'
|
|
76
|
+
? service.getCapabilities()
|
|
77
|
+
: { platform, supportsPlugins: true };
|
|
78
|
+
|
|
79
|
+
res.json({
|
|
80
|
+
success: true,
|
|
81
|
+
platform,
|
|
82
|
+
capabilities
|
|
83
|
+
});
|
|
84
|
+
} catch (err) {
|
|
85
|
+
console.error('[Plugins API] Get capabilities error:', err);
|
|
86
|
+
sendApiError(res, err);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
66
90
|
/**
|
|
67
91
|
* 获取插件列表
|
|
68
92
|
* GET /api/plugins
|
|
@@ -79,10 +103,7 @@ router.get('/', (req, res) => {
|
|
|
79
103
|
});
|
|
80
104
|
} catch (err) {
|
|
81
105
|
console.error('[Plugins API] List plugins error:', err);
|
|
82
|
-
res
|
|
83
|
-
success: false,
|
|
84
|
-
message: err.message
|
|
85
|
-
});
|
|
106
|
+
sendApiError(res, err);
|
|
86
107
|
}
|
|
87
108
|
});
|
|
88
109
|
|
|
@@ -107,10 +128,7 @@ router.get('/market', async (req, res) => {
|
|
|
107
128
|
});
|
|
108
129
|
} catch (err) {
|
|
109
130
|
console.error('[Plugins API] Get market plugins error:', err);
|
|
110
|
-
res
|
|
111
|
-
success: false,
|
|
112
|
-
message: err.message
|
|
113
|
-
});
|
|
131
|
+
sendApiError(res, err);
|
|
114
132
|
}
|
|
115
133
|
});
|
|
116
134
|
|
|
@@ -123,12 +141,13 @@ router.post('/install', async (req, res) => {
|
|
|
123
141
|
try {
|
|
124
142
|
const { platform, service } = getPluginsService(req);
|
|
125
143
|
const { directory, repo, gitUrl, source } = req.body;
|
|
144
|
+
const hasDirectoryField = Object.prototype.hasOwnProperty.call(req.body, 'directory');
|
|
126
145
|
|
|
127
146
|
// Support both new format (directory + repo) and legacy format (gitUrl)
|
|
128
147
|
let installUrl;
|
|
129
148
|
if (source) {
|
|
130
149
|
installUrl = source;
|
|
131
|
-
} else if (
|
|
150
|
+
} else if (repo && hasDirectoryField) {
|
|
132
151
|
installUrl = '';
|
|
133
152
|
} else if (gitUrl) {
|
|
134
153
|
installUrl = gitUrl;
|
|
@@ -141,10 +160,10 @@ router.post('/install', async (req, res) => {
|
|
|
141
160
|
|
|
142
161
|
const result = await service.installPlugin(
|
|
143
162
|
installUrl,
|
|
144
|
-
|
|
163
|
+
repo && hasDirectoryField
|
|
145
164
|
? {
|
|
146
165
|
...extractRepoPayload({ repo }),
|
|
147
|
-
directory
|
|
166
|
+
directory: directory || ''
|
|
148
167
|
}
|
|
149
168
|
: null
|
|
150
169
|
);
|
|
@@ -164,10 +183,7 @@ router.post('/install', async (req, res) => {
|
|
|
164
183
|
});
|
|
165
184
|
} catch (err) {
|
|
166
185
|
console.error('[Plugins API] Install plugin error:', err);
|
|
167
|
-
res
|
|
168
|
-
success: false,
|
|
169
|
-
message: err.message
|
|
170
|
-
});
|
|
186
|
+
sendApiError(res, err);
|
|
171
187
|
}
|
|
172
188
|
});
|
|
173
189
|
|
|
@@ -188,10 +204,7 @@ router.get('/repos', (req, res) => {
|
|
|
188
204
|
});
|
|
189
205
|
} catch (err) {
|
|
190
206
|
console.error('[Plugins API] Get repos error:', err);
|
|
191
|
-
res
|
|
192
|
-
success: false,
|
|
193
|
-
message: err.message
|
|
194
|
-
});
|
|
207
|
+
sendApiError(res, err);
|
|
195
208
|
}
|
|
196
209
|
});
|
|
197
210
|
|
|
@@ -223,10 +236,7 @@ router.post('/repos', (req, res) => {
|
|
|
223
236
|
});
|
|
224
237
|
} catch (err) {
|
|
225
238
|
console.error('[Plugins API] Add repo error:', err);
|
|
226
|
-
res
|
|
227
|
-
success: false,
|
|
228
|
-
message: err.message
|
|
229
|
-
});
|
|
239
|
+
sendApiError(res, err);
|
|
230
240
|
}
|
|
231
241
|
});
|
|
232
242
|
|
|
@@ -243,10 +253,7 @@ router.delete('/repos', (req, res) => {
|
|
|
243
253
|
});
|
|
244
254
|
} catch (err) {
|
|
245
255
|
console.error('[Plugins API] Remove repo error:', err);
|
|
246
|
-
res
|
|
247
|
-
success: false,
|
|
248
|
-
message: err.message
|
|
249
|
-
});
|
|
256
|
+
sendApiError(res, err);
|
|
250
257
|
}
|
|
251
258
|
});
|
|
252
259
|
|
|
@@ -271,10 +278,7 @@ router.put('/repos/toggle', (req, res) => {
|
|
|
271
278
|
});
|
|
272
279
|
} catch (err) {
|
|
273
280
|
console.error('[Plugins API] Toggle repo error:', err);
|
|
274
|
-
res
|
|
275
|
-
success: false,
|
|
276
|
-
message: err.message
|
|
277
|
-
});
|
|
281
|
+
sendApiError(res, err);
|
|
278
282
|
}
|
|
279
283
|
});
|
|
280
284
|
|
|
@@ -298,10 +302,7 @@ router.delete('/repos/:owner/:name', (req, res) => {
|
|
|
298
302
|
});
|
|
299
303
|
} catch (err) {
|
|
300
304
|
console.error('[Plugins API] Remove repo error:', err);
|
|
301
|
-
res
|
|
302
|
-
success: false,
|
|
303
|
-
message: err.message
|
|
304
|
-
});
|
|
305
|
+
sendApiError(res, err);
|
|
305
306
|
}
|
|
306
307
|
});
|
|
307
308
|
|
|
@@ -333,10 +334,7 @@ router.put('/repos/:owner/:name/toggle', (req, res) => {
|
|
|
333
334
|
});
|
|
334
335
|
} catch (err) {
|
|
335
336
|
console.error('[Plugins API] Toggle repo error:', err);
|
|
336
|
-
res
|
|
337
|
-
success: false,
|
|
338
|
-
message: err.message
|
|
339
|
-
});
|
|
337
|
+
sendApiError(res, err);
|
|
340
338
|
}
|
|
341
339
|
});
|
|
342
340
|
|
|
@@ -367,10 +365,7 @@ router.put('/repos/auth', (req, res) => {
|
|
|
367
365
|
});
|
|
368
366
|
} catch (err) {
|
|
369
367
|
console.error('[Plugins API] Update repo auth error:', err);
|
|
370
|
-
res
|
|
371
|
-
success: false,
|
|
372
|
-
message: err.message
|
|
373
|
-
});
|
|
368
|
+
sendApiError(res, err);
|
|
374
369
|
}
|
|
375
370
|
});
|
|
376
371
|
|
|
@@ -391,10 +386,7 @@ router.post('/repos/sync', async (req, res) => {
|
|
|
391
386
|
});
|
|
392
387
|
} catch (err) {
|
|
393
388
|
console.error('[Plugins API] Sync repos error:', err);
|
|
394
|
-
res
|
|
395
|
-
success: false,
|
|
396
|
-
message: err.message
|
|
397
|
-
});
|
|
389
|
+
sendApiError(res, err);
|
|
398
390
|
}
|
|
399
391
|
});
|
|
400
392
|
|
|
@@ -415,10 +407,7 @@ router.post('/sync', async (req, res) => {
|
|
|
415
407
|
});
|
|
416
408
|
} catch (err) {
|
|
417
409
|
console.error('[Plugins API] Sync plugins error:', err);
|
|
418
|
-
res
|
|
419
|
-
success: false,
|
|
420
|
-
message: err.message
|
|
421
|
-
});
|
|
410
|
+
sendApiError(res, err);
|
|
422
411
|
}
|
|
423
412
|
});
|
|
424
413
|
|
|
@@ -504,10 +493,7 @@ router.get('/:name', (req, res) => {
|
|
|
504
493
|
});
|
|
505
494
|
} catch (err) {
|
|
506
495
|
console.error('[Plugins API] Get plugin error:', err);
|
|
507
|
-
res
|
|
508
|
-
success: false,
|
|
509
|
-
message: err.message
|
|
510
|
-
});
|
|
496
|
+
sendApiError(res, err);
|
|
511
497
|
}
|
|
512
498
|
});
|
|
513
499
|
|
|
@@ -536,10 +522,7 @@ router.delete('/:name', (req, res) => {
|
|
|
536
522
|
});
|
|
537
523
|
} catch (err) {
|
|
538
524
|
console.error('[Plugins API] Uninstall plugin error:', err);
|
|
539
|
-
res
|
|
540
|
-
success: false,
|
|
541
|
-
message: err.message
|
|
542
|
-
});
|
|
525
|
+
sendApiError(res, err);
|
|
543
526
|
}
|
|
544
527
|
});
|
|
545
528
|
|
|
@@ -571,10 +554,7 @@ router.put('/:name/toggle', (req, res) => {
|
|
|
571
554
|
});
|
|
572
555
|
} catch (err) {
|
|
573
556
|
console.error('[Plugins API] Toggle plugin error:', err);
|
|
574
|
-
res
|
|
575
|
-
success: false,
|
|
576
|
-
message: err.message
|
|
577
|
-
});
|
|
557
|
+
sendApiError(res, err);
|
|
578
558
|
}
|
|
579
559
|
});
|
|
580
560
|
|
|
@@ -605,10 +585,7 @@ router.put('/:name/config', (req, res) => {
|
|
|
605
585
|
});
|
|
606
586
|
} catch (err) {
|
|
607
587
|
console.error('[Plugins API] Update plugin config error:', err);
|
|
608
|
-
res
|
|
609
|
-
success: false,
|
|
610
|
-
message: err.message
|
|
611
|
-
});
|
|
588
|
+
sendApiError(res, err);
|
|
612
589
|
}
|
|
613
590
|
});
|
|
614
591
|
|
package/src/server/api/skills.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
const express = require('express');
|
|
6
6
|
const { SkillService } = require('../services/skill-service');
|
|
7
7
|
const { maskToken } = require('../services/oauth-utils');
|
|
8
|
+
const { sendApiError } = require('./validation-errors');
|
|
8
9
|
|
|
9
10
|
const router = express.Router();
|
|
10
11
|
const SUPPORTED_PLATFORMS = ['claude', 'codex', 'gemini', 'opencode'];
|
|
@@ -84,10 +85,7 @@ router.get('/', async (req, res) => {
|
|
|
84
85
|
});
|
|
85
86
|
} catch (err) {
|
|
86
87
|
console.error('[Skills API] List skills error:', err);
|
|
87
|
-
res
|
|
88
|
-
success: false,
|
|
89
|
-
message: err.message
|
|
90
|
-
});
|
|
88
|
+
sendApiError(res, err);
|
|
91
89
|
}
|
|
92
90
|
});
|
|
93
91
|
|
|
@@ -116,10 +114,7 @@ router.get('/detail/*', async (req, res) => {
|
|
|
116
114
|
});
|
|
117
115
|
} catch (err) {
|
|
118
116
|
console.error('[Skills API] Get skill detail error:', err);
|
|
119
|
-
res
|
|
120
|
-
success: false,
|
|
121
|
-
message: err.message
|
|
122
|
-
});
|
|
117
|
+
sendApiError(res, err);
|
|
123
118
|
}
|
|
124
119
|
});
|
|
125
120
|
|
|
@@ -138,10 +133,7 @@ router.get('/installed', (req, res) => {
|
|
|
138
133
|
});
|
|
139
134
|
} catch (err) {
|
|
140
135
|
console.error('[Skills API] Get installed skills error:', err);
|
|
141
|
-
res
|
|
142
|
-
success: false,
|
|
143
|
-
message: err.message
|
|
144
|
-
});
|
|
136
|
+
sendApiError(res, err);
|
|
145
137
|
}
|
|
146
138
|
});
|
|
147
139
|
|
|
@@ -184,10 +176,7 @@ router.post('/install', async (req, res) => {
|
|
|
184
176
|
});
|
|
185
177
|
} catch (err) {
|
|
186
178
|
console.error('[Skills API] Install skill error:', err);
|
|
187
|
-
res
|
|
188
|
-
success: false,
|
|
189
|
-
message: err.message
|
|
190
|
-
});
|
|
179
|
+
sendApiError(res, err);
|
|
191
180
|
}
|
|
192
181
|
});
|
|
193
182
|
|
|
@@ -209,7 +198,7 @@ router.post('/install-local', (req, res) => {
|
|
|
209
198
|
res.json({ success: true, platform, ...result });
|
|
210
199
|
} catch (err) {
|
|
211
200
|
console.error('[Skills API] Install local skill error:', err);
|
|
212
|
-
res
|
|
201
|
+
sendApiError(res, err);
|
|
213
202
|
}
|
|
214
203
|
});
|
|
215
204
|
|
|
@@ -259,10 +248,7 @@ router.post('/create', (req, res) => {
|
|
|
259
248
|
});
|
|
260
249
|
} catch (err) {
|
|
261
250
|
console.error('[Skills API] Create skill error:', err);
|
|
262
|
-
res
|
|
263
|
-
success: false,
|
|
264
|
-
message: err.message
|
|
265
|
-
});
|
|
251
|
+
sendApiError(res, err);
|
|
266
252
|
}
|
|
267
253
|
});
|
|
268
254
|
|
|
@@ -292,10 +278,7 @@ router.post('/uninstall', (req, res) => {
|
|
|
292
278
|
});
|
|
293
279
|
} catch (err) {
|
|
294
280
|
console.error('[Skills API] Uninstall skill error:', err);
|
|
295
|
-
res
|
|
296
|
-
success: false,
|
|
297
|
-
message: err.message
|
|
298
|
-
});
|
|
281
|
+
sendApiError(res, err);
|
|
299
282
|
}
|
|
300
283
|
});
|
|
301
284
|
|
|
@@ -314,10 +297,7 @@ router.get('/repos', (req, res) => {
|
|
|
314
297
|
});
|
|
315
298
|
} catch (err) {
|
|
316
299
|
console.error('[Skills API] Get repos error:', err);
|
|
317
|
-
res
|
|
318
|
-
success: false,
|
|
319
|
-
message: err.message
|
|
320
|
-
});
|
|
300
|
+
sendApiError(res, err);
|
|
321
301
|
}
|
|
322
302
|
});
|
|
323
303
|
|
|
@@ -349,10 +329,7 @@ router.post('/repos', (req, res) => {
|
|
|
349
329
|
});
|
|
350
330
|
} catch (err) {
|
|
351
331
|
console.error('[Skills API] Add repo error:', err);
|
|
352
|
-
res
|
|
353
|
-
success: false,
|
|
354
|
-
message: err.message
|
|
355
|
-
});
|
|
332
|
+
sendApiError(res, err);
|
|
356
333
|
}
|
|
357
334
|
});
|
|
358
335
|
|
|
@@ -369,10 +346,7 @@ router.delete('/repos', (req, res) => {
|
|
|
369
346
|
});
|
|
370
347
|
} catch (err) {
|
|
371
348
|
console.error('[Skills API] Remove repo error:', err);
|
|
372
|
-
res
|
|
373
|
-
success: false,
|
|
374
|
-
message: err.message
|
|
375
|
-
});
|
|
349
|
+
sendApiError(res, err);
|
|
376
350
|
}
|
|
377
351
|
});
|
|
378
352
|
|
|
@@ -390,10 +364,7 @@ router.put('/repos/toggle', (req, res) => {
|
|
|
390
364
|
});
|
|
391
365
|
} catch (err) {
|
|
392
366
|
console.error('[Skills API] Toggle repo error:', err);
|
|
393
|
-
res
|
|
394
|
-
success: false,
|
|
395
|
-
message: err.message
|
|
396
|
-
});
|
|
367
|
+
sendApiError(res, err);
|
|
397
368
|
}
|
|
398
369
|
});
|
|
399
370
|
|
|
@@ -425,10 +396,7 @@ router.put('/repos/auth', (req, res) => {
|
|
|
425
396
|
});
|
|
426
397
|
} catch (err) {
|
|
427
398
|
console.error('[Skills API] Update repo auth error:', err);
|
|
428
|
-
res
|
|
429
|
-
success: false,
|
|
430
|
-
message: err.message
|
|
431
|
-
});
|
|
399
|
+
sendApiError(res, err);
|
|
432
400
|
}
|
|
433
401
|
});
|
|
434
402
|
|
|
@@ -451,10 +419,7 @@ router.delete('/repos/:owner/:name', (req, res) => {
|
|
|
451
419
|
});
|
|
452
420
|
} catch (err) {
|
|
453
421
|
console.error('[Skills API] Remove repo error:', err);
|
|
454
|
-
res
|
|
455
|
-
success: false,
|
|
456
|
-
message: err.message
|
|
457
|
-
});
|
|
422
|
+
sendApiError(res, err);
|
|
458
423
|
}
|
|
459
424
|
});
|
|
460
425
|
|
|
@@ -479,10 +444,7 @@ router.put('/repos/:owner/:name/toggle', (req, res) => {
|
|
|
479
444
|
});
|
|
480
445
|
} catch (err) {
|
|
481
446
|
console.error('[Skills API] Toggle repo error:', err);
|
|
482
|
-
res
|
|
483
|
-
success: false,
|
|
484
|
-
message: err.message
|
|
485
|
-
});
|
|
447
|
+
sendApiError(res, err);
|
|
486
448
|
}
|
|
487
449
|
});
|
|
488
450
|
|
|
@@ -529,10 +491,7 @@ router.post('/create-with-files', (req, res) => {
|
|
|
529
491
|
});
|
|
530
492
|
} catch (err) {
|
|
531
493
|
console.error('[Skills API] Create skill with files error:', err);
|
|
532
|
-
res
|
|
533
|
-
success: false,
|
|
534
|
-
message: err.message
|
|
535
|
-
});
|
|
494
|
+
sendApiError(res, err);
|
|
536
495
|
}
|
|
537
496
|
});
|
|
538
497
|
|
|
@@ -554,10 +513,7 @@ router.get('/:directory/files', (req, res) => {
|
|
|
554
513
|
});
|
|
555
514
|
} catch (err) {
|
|
556
515
|
console.error('[Skills API] Get skill files error:', err);
|
|
557
|
-
res
|
|
558
|
-
success: false,
|
|
559
|
-
message: err.message
|
|
560
|
-
});
|
|
516
|
+
sendApiError(res, err);
|
|
561
517
|
}
|
|
562
518
|
});
|
|
563
519
|
|
|
@@ -588,10 +544,7 @@ router.get('/:directory/file/*', (req, res) => {
|
|
|
588
544
|
});
|
|
589
545
|
} catch (err) {
|
|
590
546
|
console.error('[Skills API] Get skill file content error:', err);
|
|
591
|
-
res
|
|
592
|
-
success: false,
|
|
593
|
-
message: err.message
|
|
594
|
-
});
|
|
547
|
+
sendApiError(res, err);
|
|
595
548
|
}
|
|
596
549
|
});
|
|
597
550
|
|
|
@@ -622,10 +575,7 @@ router.post('/:directory/files', (req, res) => {
|
|
|
622
575
|
});
|
|
623
576
|
} catch (err) {
|
|
624
577
|
console.error('[Skills API] Add skill files error:', err);
|
|
625
|
-
res
|
|
626
|
-
success: false,
|
|
627
|
-
message: err.message
|
|
628
|
-
});
|
|
578
|
+
sendApiError(res, err);
|
|
629
579
|
}
|
|
630
580
|
});
|
|
631
581
|
|
|
@@ -655,10 +605,7 @@ router.delete('/:directory/file/*', (req, res) => {
|
|
|
655
605
|
});
|
|
656
606
|
} catch (err) {
|
|
657
607
|
console.error('[Skills API] Delete skill file error:', err);
|
|
658
|
-
res
|
|
659
|
-
success: false,
|
|
660
|
-
message: err.message
|
|
661
|
-
});
|
|
608
|
+
sendApiError(res, err);
|
|
662
609
|
}
|
|
663
610
|
});
|
|
664
611
|
|
|
@@ -697,10 +644,7 @@ router.put('/:directory/file/*', (req, res) => {
|
|
|
697
644
|
});
|
|
698
645
|
} catch (err) {
|
|
699
646
|
console.error('[Skills API] Update skill file error:', err);
|
|
700
|
-
res
|
|
701
|
-
success: false,
|
|
702
|
-
message: err.message
|
|
703
|
-
});
|
|
647
|
+
sendApiError(res, err);
|
|
704
648
|
}
|
|
705
649
|
});
|
|
706
650
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const VALIDATION_ERROR_PATTERNS = [
|
|
2
|
+
/^Invalid\b/i,
|
|
3
|
+
/不能为空/,
|
|
4
|
+
/不合法/,
|
|
5
|
+
/只能包含/,
|
|
6
|
+
/不能包含/,
|
|
7
|
+
/必须/,
|
|
8
|
+
/不能/,
|
|
9
|
+
/Missing\b/i,
|
|
10
|
+
/requires?/i,
|
|
11
|
+
/required/i,
|
|
12
|
+
/escapes/i,
|
|
13
|
+
/not support/i,
|
|
14
|
+
/不支持/
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
function isValidationError(error) {
|
|
18
|
+
const message = String(error?.message || error || '');
|
|
19
|
+
return VALIDATION_ERROR_PATTERNS.some(pattern => pattern.test(message));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function sendApiError(res, error, fallbackStatus = 500, extra = {}) {
|
|
23
|
+
const status = isValidationError(error) ? 400 : fallbackStatus;
|
|
24
|
+
return res.status(status).json({
|
|
25
|
+
success: false,
|
|
26
|
+
message: error?.message || String(error),
|
|
27
|
+
...extra
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = {
|
|
32
|
+
isValidationError,
|
|
33
|
+
sendApiError
|
|
34
|
+
};
|