coding-tool-x 3.7.8 → 3.7.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/dist/web/assets/{Analytics-BE5H9JGG.js → Analytics-CkUtnoz9.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-z118k1BE.js → ConfigTemplates-BwPqhE-N.js} +1 -1
- package/dist/web/assets/{Home-CBhtmOIN.js → Home-BANl91zG.js} +1 -1
- package/dist/web/assets/{PluginManager-CGhfZ3t8.js → PluginManager-JMXWl37b.js} +1 -1
- package/dist/web/assets/{ProjectList-BMPLJtgQ.js → ProjectList-CZwDgVvt.js} +1 -1
- package/dist/web/assets/{SessionList-D9e7wGF1.js → SessionList-2fZmN7Au.js} +1 -1
- package/dist/web/assets/{SkillManager-DJpdUmnk.js → SkillManager-Bhzhkeis.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-C0Ud_V7v.js → WorkspaceManager-B3lhhBD0.js} +1 -1
- package/dist/web/assets/index-C5nLTbOk.css +1 -0
- package/dist/web/assets/index-LYvv7wtx.js +2 -0
- package/dist/web/assets/{naive-ui-CVyvdmg1.js → naive-ui-BALVpMgd.js} +1 -1
- package/dist/web/index.html +3 -3
- package/package.json +1 -1
- package/src/config/model-metadata.json +9 -1
- package/src/server/api/omp-channels.js +85 -2
- package/src/server/api/settings.js +93 -9
- package/src/server/services/model-definition-schema.js +570 -0
- package/src/server/services/omp-channels.js +9 -1
- package/src/server/services/omp-settings-manager.js +145 -154
- package/dist/web/assets/index-CeTaG4IX.js +0 -2
- package/dist/web/assets/index-S8wrU2Nf.css +0 -1
package/dist/web/index.html
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
<link rel="icon" href="/favicon.ico">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>coding-tool-x · AI 编程工作台</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-LYvv7wtx.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/markdown-BNJfEgCA.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vue-vendor-B5RqjEjQ.js">
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/naive-ui-
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/naive-ui-BALVpMgd.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/icons-nGdSKQn2.js">
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/vendors-DQA4Hw9v.js">
|
|
14
14
|
<link rel="stylesheet" crossorigin href="/assets/markdown-BfC0goYb.css">
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-C5nLTbOk.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="app"></div>
|
package/package.json
CHANGED
|
@@ -91,7 +91,15 @@
|
|
|
91
91
|
},
|
|
92
92
|
"gpt-5.5": {
|
|
93
93
|
"limit": { "context": 1050000, "output": 128000 },
|
|
94
|
-
"pricing": { "input": 5, "output": 30, "cacheRead": 0.5 }
|
|
94
|
+
"pricing": { "input": 5, "output": 30, "cacheRead": 0.5 },
|
|
95
|
+
"reasoning": true,
|
|
96
|
+
"thinking": {
|
|
97
|
+
"mode": "effort",
|
|
98
|
+
"efforts": ["low", "medium", "high", "xhigh"],
|
|
99
|
+
"defaultLevel": "medium"
|
|
100
|
+
},
|
|
101
|
+
"input": ["text", "image"],
|
|
102
|
+
"supportsTools": true
|
|
95
103
|
},
|
|
96
104
|
"gpt-5.4": {
|
|
97
105
|
"limit": { "context": 1050000, "output": 128000 },
|
|
@@ -26,9 +26,37 @@ const {
|
|
|
26
26
|
getCachedOmpAuthProviderSnapshot,
|
|
27
27
|
getOmpAuthProviderCacheMeta
|
|
28
28
|
} = require('../services/omp-auth-providers');
|
|
29
|
+
const {
|
|
30
|
+
MODEL_SCHEMA_VERSION,
|
|
31
|
+
MODEL_METADATA_MODES,
|
|
32
|
+
getPublicModelFieldSchema,
|
|
33
|
+
normalizeCatalogModelList,
|
|
34
|
+
redactSensitiveFields,
|
|
35
|
+
validateModelDefinitions,
|
|
36
|
+
validateProviderConfig
|
|
37
|
+
} = require('../services/model-definition-schema');
|
|
38
|
+
const { getOmpCatalogModels } = require('../services/omp-settings-manager');
|
|
29
39
|
|
|
30
40
|
const CHANNEL_LIST_AUTH_OPTIONS = { accountCheck: false, includeStatus: false };
|
|
31
41
|
|
|
42
|
+
function validateOmpModelPayload(payload = {}) {
|
|
43
|
+
if (payload.modelMetadataMode !== undefined && !MODEL_METADATA_MODES.includes(payload.modelMetadataMode)) {
|
|
44
|
+
return `modelMetadataMode must be one of: ${MODEL_METADATA_MODES.join(', ')}`;
|
|
45
|
+
}
|
|
46
|
+
if (payload.models !== undefined) {
|
|
47
|
+
const validation = validateModelDefinitions(payload.models);
|
|
48
|
+
if (!validation.valid) return validation.error;
|
|
49
|
+
}
|
|
50
|
+
if (payload.modelBindings !== undefined && !Array.isArray(payload.modelBindings)) {
|
|
51
|
+
return 'modelBindings must be an array';
|
|
52
|
+
}
|
|
53
|
+
if (payload.providerConfig !== undefined) {
|
|
54
|
+
const validation = validateProviderConfig(payload.providerConfig);
|
|
55
|
+
if (!validation.valid) return validation.error;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
32
60
|
function uniqueModels(models = []) {
|
|
33
61
|
const seen = new Set();
|
|
34
62
|
const result = [];
|
|
@@ -322,6 +350,44 @@ module.exports = () => {
|
|
|
322
350
|
}
|
|
323
351
|
});
|
|
324
352
|
|
|
353
|
+
router.post('/catalog-metadata', (req, res) => {
|
|
354
|
+
try {
|
|
355
|
+
const providerKey = String(req.body?.providerKey || '').trim();
|
|
356
|
+
if (!providerKey) {
|
|
357
|
+
return res.status(400).json({ error: 'providerKey is required' });
|
|
358
|
+
}
|
|
359
|
+
const requestedModelIds = uniqueModels([
|
|
360
|
+
req.body?.model,
|
|
361
|
+
req.body?.speedTestModel,
|
|
362
|
+
...(Array.isArray(req.body?.allowedModels) ? req.body.allowedModels : []),
|
|
363
|
+
...(Array.isArray(req.body?.models)
|
|
364
|
+
? req.body.models.map(model => typeof model === 'string' ? model : (model?.id || model?.name))
|
|
365
|
+
: [])
|
|
366
|
+
]);
|
|
367
|
+
const rawModels = getOmpCatalogModels(providerKey, {
|
|
368
|
+
forceCatalogRefresh: req.body?.forceRefresh === true,
|
|
369
|
+
catalogTimeout: 5000,
|
|
370
|
+
requestedModelIds
|
|
371
|
+
});
|
|
372
|
+
const normalizedCatalog = normalizeCatalogModelList(rawModels);
|
|
373
|
+
const models = normalizedCatalog.models.map(model => redactSensitiveFields(model));
|
|
374
|
+
const warnings = normalizedCatalog.warnings.slice();
|
|
375
|
+
if (models.length === 0) {
|
|
376
|
+
warnings.push('OMP catalog did not return model metadata; existing manual definitions were left unchanged.');
|
|
377
|
+
}
|
|
378
|
+
res.json({
|
|
379
|
+
schemaVersion: MODEL_SCHEMA_VERSION,
|
|
380
|
+
fieldSchema: getPublicModelFieldSchema(),
|
|
381
|
+
providerKey,
|
|
382
|
+
models,
|
|
383
|
+
warnings
|
|
384
|
+
});
|
|
385
|
+
} catch (error) {
|
|
386
|
+
console.error('[OMP Channels API] Error reading OMP catalog metadata:', error);
|
|
387
|
+
res.status(502).json({ error: 'Failed to read OMP model metadata' });
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
|
|
325
391
|
router.post('/', (req, res) => {
|
|
326
392
|
try {
|
|
327
393
|
const {
|
|
@@ -344,9 +410,18 @@ module.exports = () => {
|
|
|
344
410
|
presetId,
|
|
345
411
|
websiteUrl,
|
|
346
412
|
balanceToken,
|
|
347
|
-
balanceUserId
|
|
413
|
+
balanceUserId,
|
|
414
|
+
models,
|
|
415
|
+
modelMetadataMode,
|
|
416
|
+
modelBindings,
|
|
417
|
+
providerConfig
|
|
348
418
|
} = req.body || {};
|
|
349
419
|
|
|
420
|
+
const modelPayloadError = validateOmpModelPayload(req.body || {});
|
|
421
|
+
if (modelPayloadError) {
|
|
422
|
+
return res.status(400).json({ error: modelPayloadError });
|
|
423
|
+
}
|
|
424
|
+
|
|
350
425
|
if (!name || !baseUrl) {
|
|
351
426
|
return res.status(400).json({ error: 'Missing required fields: name and baseUrl' });
|
|
352
427
|
}
|
|
@@ -372,7 +447,11 @@ module.exports = () => {
|
|
|
372
447
|
presetId,
|
|
373
448
|
websiteUrl: websiteUrl || '',
|
|
374
449
|
balanceToken: balanceToken || '',
|
|
375
|
-
balanceUserId: balanceUserId || null
|
|
450
|
+
balanceUserId: balanceUserId || null,
|
|
451
|
+
models: Array.isArray(models) ? models : [],
|
|
452
|
+
modelMetadataMode: modelMetadataMode || 'auto',
|
|
453
|
+
modelBindings: Array.isArray(modelBindings) ? modelBindings : [],
|
|
454
|
+
providerConfig: providerConfig || {}
|
|
376
455
|
});
|
|
377
456
|
res.json(channel);
|
|
378
457
|
broadcastSchedulerState('omp', getSchedulerState('omp'));
|
|
@@ -384,6 +463,10 @@ module.exports = () => {
|
|
|
384
463
|
|
|
385
464
|
router.put('/:channelId', (req, res) => {
|
|
386
465
|
try {
|
|
466
|
+
const modelPayloadError = validateOmpModelPayload(req.body || {});
|
|
467
|
+
if (modelPayloadError) {
|
|
468
|
+
return res.status(400).json({ error: modelPayloadError });
|
|
469
|
+
}
|
|
387
470
|
const channel = updateChannel(req.params.channelId, req.body || {});
|
|
388
471
|
res.json(channel);
|
|
389
472
|
broadcastSchedulerState('omp', getSchedulerState('omp'));
|
|
@@ -7,21 +7,68 @@ const {
|
|
|
7
7
|
saveDefaultSpeedTestModels
|
|
8
8
|
} = require('../../config/model-metadata');
|
|
9
9
|
const { loadConfig, saveConfig } = require('../../config/loader');
|
|
10
|
+
const {
|
|
11
|
+
MODEL_SCHEMA_VERSION,
|
|
12
|
+
getPublicModelFieldSchema,
|
|
13
|
+
isPlainObject,
|
|
14
|
+
redactSensitiveFields,
|
|
15
|
+
resolveModelDefinition,
|
|
16
|
+
validateModelDefinitions
|
|
17
|
+
} = require('../services/model-definition-schema');
|
|
18
|
+
|
|
19
|
+
function mergeMetadata(base = {}, override = {}) {
|
|
20
|
+
const result = { ...base };
|
|
21
|
+
for (const [key, value] of Object.entries(override || {})) {
|
|
22
|
+
if (isPlainObject(value) && isPlainObject(result[key])) result[key] = { ...result[key], ...value };
|
|
23
|
+
else if (value !== undefined) result[key] = value;
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function normalizeDefinitions(value) {
|
|
29
|
+
if (Array.isArray(value)) {
|
|
30
|
+
return Object.fromEntries(value
|
|
31
|
+
.filter(item => item && typeof item === 'object' && item.id)
|
|
32
|
+
.map(item => [String(item.id), item]));
|
|
33
|
+
}
|
|
34
|
+
return isPlainObject(value) ? value : {};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function buildResolvedModelSettings(definitions, overrides) {
|
|
38
|
+
const ids = new Set([
|
|
39
|
+
...Object.keys(MODEL_METADATA),
|
|
40
|
+
...Object.keys(overrides || {}),
|
|
41
|
+
...Object.keys(definitions || {})
|
|
42
|
+
]);
|
|
43
|
+
const resolvedModels = {};
|
|
44
|
+
const provenance = {};
|
|
45
|
+
const warnings = {};
|
|
46
|
+
for (const id of ids) {
|
|
47
|
+
const stored = definitions[id] || {
|
|
48
|
+
id,
|
|
49
|
+
metadataMode: 'hybrid',
|
|
50
|
+
overrides: overrides[id] || {}
|
|
51
|
+
};
|
|
52
|
+
const resolved = resolveModelDefinition(stored, { builtin: MODEL_METADATA[id] || {} });
|
|
53
|
+
resolvedModels[id] = resolved.spec;
|
|
54
|
+
provenance[id] = resolved.provenance;
|
|
55
|
+
if (resolved.warnings.length > 0) warnings[id] = resolved.warnings;
|
|
56
|
+
}
|
|
57
|
+
return { resolvedModels, provenance, warnings };
|
|
58
|
+
}
|
|
10
59
|
|
|
11
60
|
function handleGetModelSettings(req, res) {
|
|
12
61
|
try {
|
|
13
62
|
const config = loadConfig();
|
|
14
63
|
const overrides = config.modelMetadataOverrides || {};
|
|
64
|
+
const definitions = normalizeDefinitions(config.modelDefinitions);
|
|
15
65
|
const defaultSpeedTestModels = getDefaultSpeedTestModels();
|
|
16
66
|
|
|
17
67
|
// Build merged table: built-in + user overrides
|
|
18
68
|
const merged = {};
|
|
19
69
|
for (const [id, meta] of Object.entries(MODEL_METADATA)) {
|
|
20
70
|
merged[id] = overrides[id]
|
|
21
|
-
?
|
|
22
|
-
limit: { ...meta.limit, ...(overrides[id].limit || {}) },
|
|
23
|
-
pricing: { ...meta.pricing, ...(overrides[id].pricing || {}) }
|
|
24
|
-
}
|
|
71
|
+
? mergeMetadata(meta, overrides[id])
|
|
25
72
|
: meta;
|
|
26
73
|
}
|
|
27
74
|
|
|
@@ -32,9 +79,16 @@ function handleGetModelSettings(req, res) {
|
|
|
32
79
|
}
|
|
33
80
|
}
|
|
34
81
|
|
|
82
|
+
const resolved = buildResolvedModelSettings(definitions, overrides);
|
|
35
83
|
res.json({
|
|
36
|
-
|
|
37
|
-
|
|
84
|
+
schemaVersion: MODEL_SCHEMA_VERSION,
|
|
85
|
+
fieldSchema: getPublicModelFieldSchema(),
|
|
86
|
+
models: redactSensitiveFields(merged),
|
|
87
|
+
overrides: redactSensitiveFields(overrides),
|
|
88
|
+
definitions: redactSensitiveFields(definitions),
|
|
89
|
+
resolvedModels: redactSensitiveFields(resolved.resolvedModels),
|
|
90
|
+
provenance: resolved.provenance,
|
|
91
|
+
warnings: resolved.warnings,
|
|
38
92
|
builtinModelIds: Object.keys(MODEL_METADATA),
|
|
39
93
|
lastUpdated: METADATA_LAST_UPDATED,
|
|
40
94
|
defaultSpeedTestModels
|
|
@@ -52,7 +106,7 @@ router.get('/model-metadata', handleGetModelSettings);
|
|
|
52
106
|
|
|
53
107
|
function handleSaveModelSettings(req, res) {
|
|
54
108
|
try {
|
|
55
|
-
const { overrides, defaultSpeedTestModels } = req.body || {};
|
|
109
|
+
const { overrides, definitions, defaultSpeedTestModels } = req.body || {};
|
|
56
110
|
if (overrides !== undefined && (typeof overrides !== 'object' || overrides === null || Array.isArray(overrides))) {
|
|
57
111
|
return res.status(400).json({ error: 'overrides must be an object' });
|
|
58
112
|
}
|
|
@@ -63,6 +117,9 @@ function handleSaveModelSettings(req, res) {
|
|
|
63
117
|
if (typeof modelId !== 'string' || !modelId.trim()) {
|
|
64
118
|
return res.status(400).json({ error: `Invalid model ID: "${modelId}"` });
|
|
65
119
|
}
|
|
120
|
+
if (!isPlainObject(meta)) {
|
|
121
|
+
return res.status(400).json({ error: `${modelId}: metadata must be an object` });
|
|
122
|
+
}
|
|
66
123
|
if (meta.limit !== undefined) {
|
|
67
124
|
if (typeof meta.limit !== 'object') {
|
|
68
125
|
return res.status(400).json({ error: `${modelId}: limit must be an object` });
|
|
@@ -87,19 +144,46 @@ function handleSaveModelSettings(req, res) {
|
|
|
87
144
|
}
|
|
88
145
|
}
|
|
89
146
|
|
|
147
|
+
if (definitions !== undefined && !Array.isArray(definitions) && !isPlainObject(definitions)) {
|
|
148
|
+
return res.status(400).json({ error: 'definitions must be an object or array' });
|
|
149
|
+
}
|
|
150
|
+
if (Array.isArray(definitions)) {
|
|
151
|
+
const validation = validateModelDefinitions(definitions);
|
|
152
|
+
if (!validation.valid) {
|
|
153
|
+
return res.status(400).json({ error: validation.error });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const normalizedDefinitions = definitions === undefined ? undefined : normalizeDefinitions(definitions);
|
|
157
|
+
if (normalizedDefinitions) {
|
|
158
|
+
const definitionList = Object.entries(normalizedDefinitions).map(([id, definition]) => ({
|
|
159
|
+
...(isPlainObject(definition) ? definition : {}),
|
|
160
|
+
id: isPlainObject(definition) && definition.id ? definition.id : id
|
|
161
|
+
}));
|
|
162
|
+
const validation = validateModelDefinitions(definitionList);
|
|
163
|
+
if (!validation.valid) {
|
|
164
|
+
return res.status(400).json({ error: validation.error });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
90
168
|
const config = loadConfig();
|
|
91
169
|
const newConfig = {
|
|
92
170
|
...config,
|
|
93
171
|
modelMetadataOverrides: overrides && typeof overrides === 'object'
|
|
94
172
|
? overrides
|
|
95
|
-
: (config.modelMetadataOverrides || {})
|
|
173
|
+
: (config.modelMetadataOverrides || {}),
|
|
174
|
+
modelDefinitions: normalizedDefinitions === undefined
|
|
175
|
+
? (config.modelDefinitions || {})
|
|
176
|
+
: normalizedDefinitions,
|
|
177
|
+
modelMetadataSchemaVersion: MODEL_SCHEMA_VERSION
|
|
96
178
|
};
|
|
97
179
|
saveConfig(newConfig);
|
|
98
180
|
const persistedDefaultSpeedTestModels = saveDefaultSpeedTestModels(defaultSpeedTestModels);
|
|
99
181
|
|
|
100
182
|
res.json({
|
|
101
183
|
success: true,
|
|
102
|
-
|
|
184
|
+
schemaVersion: MODEL_SCHEMA_VERSION,
|
|
185
|
+
overrides: redactSensitiveFields(newConfig.modelMetadataOverrides),
|
|
186
|
+
definitions: redactSensitiveFields(newConfig.modelDefinitions),
|
|
103
187
|
defaultSpeedTestModels: persistedDefaultSpeedTestModels
|
|
104
188
|
});
|
|
105
189
|
} catch (error) {
|