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
|
@@ -3,22 +3,25 @@ const path = require('path');
|
|
|
3
3
|
const { spawnSync } = require('child_process');
|
|
4
4
|
const yaml = require('js-yaml');
|
|
5
5
|
const ompConfig = require('./omp-config');
|
|
6
|
+
const { MODEL_METADATA, MODEL_ALIASES } = require('../../config/model-metadata');
|
|
7
|
+
const {
|
|
8
|
+
MODEL_METADATA_MODES,
|
|
9
|
+
isPlainObject,
|
|
10
|
+
normalizeProviderConfig,
|
|
11
|
+
resolveModelDefinition,
|
|
12
|
+
serializeModelSelector,
|
|
13
|
+
splitModelSelector
|
|
14
|
+
} = require('./model-definition-schema');
|
|
6
15
|
|
|
7
16
|
const MANAGED_PROVIDER_PREFIX = 'ctx-';
|
|
8
17
|
const MODELS_BACKUP_MARKER = '.ctx-backup-';
|
|
9
18
|
const VISIBILITY_STATE_VERSION = 1;
|
|
10
19
|
const MANAGED_VISIBILITY_STATE_FILE = 'coding-tool-x-omp-managed-visibility.json';
|
|
11
20
|
const NO_MANAGED_MODELS_SELECTOR = `${MANAGED_PROVIDER_PREFIX}coding-tool-x/__no_models_configured__`;
|
|
12
|
-
const THINKING_EFFORT_LEVELS = ['minimal', 'low', 'medium', 'high', 'xhigh'];
|
|
13
|
-
const THINKING_MODES = new Set([
|
|
14
|
-
'effort',
|
|
15
|
-
'budget',
|
|
16
|
-
'google-level',
|
|
17
|
-
'anthropic-adaptive',
|
|
18
|
-
'anthropic-budget-effort'
|
|
19
|
-
]);
|
|
20
|
-
|
|
21
21
|
let lastManagedOmpSyncResult = null;
|
|
22
|
+
const OMP_CATALOG_CACHE_TTL_MS = 10 * 60 * 1000;
|
|
23
|
+
const OMP_CATALOG_FAILURE_CACHE_TTL_MS = 30 * 1000;
|
|
24
|
+
const ompCatalogCache = new Map();
|
|
22
25
|
|
|
23
26
|
function getOmpPaths(env = process.env, options = {}) {
|
|
24
27
|
// Channel CRUD only needs the native OMP file layout. Do not start OMP just
|
|
@@ -61,87 +64,6 @@ function normalizeProviderApi(value = '') {
|
|
|
61
64
|
return normalized;
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
function defaultCost() {
|
|
65
|
-
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function normalizeCost(value) {
|
|
69
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
70
|
-
return defaultCost();
|
|
71
|
-
}
|
|
72
|
-
const numberOrZero = (item) => {
|
|
73
|
-
const number = Number(item);
|
|
74
|
-
return Number.isFinite(number) ? number : 0;
|
|
75
|
-
};
|
|
76
|
-
return {
|
|
77
|
-
input: numberOrZero(value.input),
|
|
78
|
-
output: numberOrZero(value.output),
|
|
79
|
-
cacheRead: numberOrZero(value.cacheRead ?? value.cache_read),
|
|
80
|
-
cacheWrite: numberOrZero(value.cacheWrite ?? value.cache_write)
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function normalizePositiveNumber(value, fallback) {
|
|
85
|
-
const number = Number(value);
|
|
86
|
-
return Number.isFinite(number) && number > 0 ? number : fallback;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function normalizeModelInput(value) {
|
|
90
|
-
if (!Array.isArray(value)) return ['text', 'image'];
|
|
91
|
-
const filtered = value.filter(item => item === 'text' || item === 'image');
|
|
92
|
-
return filtered.length > 0 ? filtered : ['text', 'image'];
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function normalizeThinkingEfforts(value) {
|
|
96
|
-
if (!Array.isArray(value)) return undefined;
|
|
97
|
-
const seen = new Set();
|
|
98
|
-
const filtered = value
|
|
99
|
-
.map(item => String(item || '').trim())
|
|
100
|
-
.filter(item => THINKING_EFFORT_LEVELS.includes(item))
|
|
101
|
-
.filter((item) => {
|
|
102
|
-
if (seen.has(item)) return false;
|
|
103
|
-
seen.add(item);
|
|
104
|
-
return true;
|
|
105
|
-
});
|
|
106
|
-
return filtered.length > 0 ? filtered : undefined;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function normalizeThinking(value) {
|
|
110
|
-
if (Array.isArray(value)) {
|
|
111
|
-
const efforts = normalizeThinkingEfforts(value);
|
|
112
|
-
return efforts ? { mode: 'effort', efforts } : undefined;
|
|
113
|
-
}
|
|
114
|
-
if (typeof value === 'string') {
|
|
115
|
-
const trimmed = value.trim();
|
|
116
|
-
if (THINKING_EFFORT_LEVELS.includes(trimmed)) {
|
|
117
|
-
return { mode: 'effort', efforts: [trimmed] };
|
|
118
|
-
}
|
|
119
|
-
return undefined;
|
|
120
|
-
}
|
|
121
|
-
if (value && typeof value === 'object') {
|
|
122
|
-
const mode = String(value.mode || '').trim();
|
|
123
|
-
if (!THINKING_MODES.has(mode)) return undefined;
|
|
124
|
-
const efforts = normalizeThinkingEfforts(value.efforts || value.levels);
|
|
125
|
-
const minLevel = String(value.minLevel || '').trim();
|
|
126
|
-
const maxLevel = String(value.maxLevel || '').trim();
|
|
127
|
-
const defaultLevel = String(value.defaultLevel || '').trim();
|
|
128
|
-
const hasRange = THINKING_EFFORT_LEVELS.includes(minLevel) && THINKING_EFFORT_LEVELS.includes(maxLevel);
|
|
129
|
-
if (!efforts && !hasRange) return undefined;
|
|
130
|
-
return compactObject({
|
|
131
|
-
mode,
|
|
132
|
-
efforts,
|
|
133
|
-
defaultLevel: THINKING_EFFORT_LEVELS.includes(defaultLevel) ? defaultLevel : undefined,
|
|
134
|
-
minLevel: efforts ? undefined : minLevel,
|
|
135
|
-
maxLevel: efforts ? undefined : maxLevel,
|
|
136
|
-
effortMap: value.effortMap && typeof value.effortMap === 'object' && !Array.isArray(value.effortMap)
|
|
137
|
-
? value.effortMap
|
|
138
|
-
: undefined,
|
|
139
|
-
supportsDisplay: typeof value.supportsDisplay === 'boolean' ? value.supportsDisplay : undefined
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
return undefined;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
67
|
function compactObject(value = {}) {
|
|
146
68
|
const next = { ...value };
|
|
147
69
|
Object.keys(next).forEach((key) => {
|
|
@@ -150,6 +72,15 @@ function compactObject(value = {}) {
|
|
|
150
72
|
return next;
|
|
151
73
|
}
|
|
152
74
|
|
|
75
|
+
function resolveBuiltinOmpMetadata(modelId) {
|
|
76
|
+
const id = String(modelId || '').trim().toLowerCase();
|
|
77
|
+
if (!id) return null;
|
|
78
|
+
const exactKey = Object.keys(MODEL_METADATA).find(key => key.toLowerCase() === id);
|
|
79
|
+
if (exactKey) return MODEL_METADATA[exactKey];
|
|
80
|
+
const aliasKey = Object.keys(MODEL_ALIASES).find(key => key.toLowerCase() === id);
|
|
81
|
+
return aliasKey ? (MODEL_METADATA[MODEL_ALIASES[aliasKey]] || null) : null;
|
|
82
|
+
}
|
|
83
|
+
|
|
153
84
|
function uniqueStrings(values = []) {
|
|
154
85
|
const seen = new Set();
|
|
155
86
|
const result = [];
|
|
@@ -185,46 +116,33 @@ function getOwnProperty(object, key) {
|
|
|
185
116
|
: false;
|
|
186
117
|
}
|
|
187
118
|
|
|
188
|
-
function mergeDefined(base = {}, override = {}) {
|
|
189
|
-
const next = { ...base };
|
|
190
|
-
Object.entries(override || {}).forEach(([key, value]) => {
|
|
191
|
-
if (value !== undefined) {
|
|
192
|
-
next[key] = value;
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
return next;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function buildModelEntry(model = {}, fallbackId = '') {
|
|
199
|
-
const id = String(model.id || model.name || fallbackId || '').trim();
|
|
200
|
-
if (!id) return null;
|
|
201
|
-
return compactObject({
|
|
202
|
-
id,
|
|
203
|
-
name: model.name || id,
|
|
204
|
-
api: model.api ? normalizeProviderApi(model.api) : undefined,
|
|
205
|
-
reasoning: model.reasoning === true,
|
|
206
|
-
thinking: normalizeThinking(model.thinking),
|
|
207
|
-
input: normalizeModelInput(model.input),
|
|
208
|
-
cost: normalizeCost(model.cost),
|
|
209
|
-
contextWindow: normalizePositiveNumber(model.contextWindow || model.context_window, 128000),
|
|
210
|
-
maxTokens: normalizePositiveNumber(model.maxTokens || model.max_tokens, 4096),
|
|
211
|
-
headers: model.headers && typeof model.headers === 'object' && !Array.isArray(model.headers)
|
|
212
|
-
? model.headers
|
|
213
|
-
: undefined,
|
|
214
|
-
compat: model.compat && typeof model.compat === 'object' && !Array.isArray(model.compat)
|
|
215
|
-
? model.compat
|
|
216
|
-
: undefined
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
|
|
220
119
|
function normalizeModels(channel = {}, options = {}) {
|
|
221
120
|
const models = [];
|
|
222
121
|
const catalogIndex = options.catalogIndex instanceof Map ? options.catalogIndex : new Map();
|
|
122
|
+
const defaultMode = MODEL_METADATA_MODES.includes(channel.modelMetadataMode)
|
|
123
|
+
? channel.modelMetadataMode
|
|
124
|
+
: 'auto';
|
|
223
125
|
const add = (value) => {
|
|
224
|
-
const
|
|
225
|
-
if (!
|
|
226
|
-
const
|
|
227
|
-
const
|
|
126
|
+
const raw = typeof value === 'string' ? { id: value } : value;
|
|
127
|
+
if (!raw || typeof raw !== 'object') return;
|
|
128
|
+
const selector = splitModelSelector(raw.id || raw.name || '');
|
|
129
|
+
const id = selector.modelId;
|
|
130
|
+
if (!id || models.some(model => model.id.toLowerCase() === id.toLowerCase())) return;
|
|
131
|
+
const definition = {
|
|
132
|
+
...raw,
|
|
133
|
+
id,
|
|
134
|
+
metadataMode: MODEL_METADATA_MODES.includes(raw.metadataMode) ? raw.metadataMode : defaultMode
|
|
135
|
+
};
|
|
136
|
+
const resolved = resolveModelDefinition(definition, {
|
|
137
|
+
// OMP provider limits are provider-specific. Use exact built-in metadata
|
|
138
|
+
// only; prefix and generic-family fallbacks could silently invent limits.
|
|
139
|
+
builtin: resolveBuiltinOmpMetadata(id) || {},
|
|
140
|
+
catalog: catalogIndex.get(id.toLowerCase()) || {}
|
|
141
|
+
});
|
|
142
|
+
if (Array.isArray(options.warnings)) {
|
|
143
|
+
options.warnings.push(...resolved.warnings.map(message => `${id}: ${message}`));
|
|
144
|
+
}
|
|
145
|
+
const entry = resolved.spec;
|
|
228
146
|
if (entry) models.push(entry);
|
|
229
147
|
};
|
|
230
148
|
|
|
@@ -235,11 +153,7 @@ function normalizeModels(channel = {}, options = {}) {
|
|
|
235
153
|
return;
|
|
236
154
|
}
|
|
237
155
|
if (!model || typeof model !== 'object') return;
|
|
238
|
-
|
|
239
|
-
if (!id || models.some(item => item.id === id)) return;
|
|
240
|
-
const catalogModel = catalogIndex.get(id.toLowerCase()) || {};
|
|
241
|
-
const entry = buildModelEntry(mergeDefined(catalogModel, model), id);
|
|
242
|
-
if (entry) models.push(entry);
|
|
156
|
+
add(model);
|
|
243
157
|
});
|
|
244
158
|
}
|
|
245
159
|
|
|
@@ -248,13 +162,27 @@ function normalizeModels(channel = {}, options = {}) {
|
|
|
248
162
|
if (Array.isArray(channel.allowedModels)) {
|
|
249
163
|
channel.allowedModels.forEach(add);
|
|
250
164
|
}
|
|
165
|
+
if (Array.isArray(channel.modelBindings)) {
|
|
166
|
+
channel.modelBindings.forEach((binding) => add(binding?.modelId || binding?.id || binding));
|
|
167
|
+
}
|
|
251
168
|
|
|
252
169
|
return models.map(compactObject);
|
|
253
170
|
}
|
|
254
171
|
|
|
255
172
|
function readOmpCatalogModels(command, providerId, options = {}) {
|
|
173
|
+
const requestedModelIds = uniqueStrings(options.requestedModelIds);
|
|
174
|
+
const requested = new Set(requestedModelIds.map(modelId => modelId.toLowerCase()));
|
|
175
|
+
const useFullCatalog = requested.size > 0;
|
|
176
|
+
const cacheKey = `${command}\u0000${useFullCatalog ? `requested:${providerId}:${[...requested].sort().join(',')}` : providerId}`;
|
|
177
|
+
const cached = ompCatalogCache.get(cacheKey);
|
|
178
|
+
const now = Date.now();
|
|
179
|
+
const cacheTtl = cached?.failed ? OMP_CATALOG_FAILURE_CACHE_TTL_MS : OMP_CATALOG_CACHE_TTL_MS;
|
|
180
|
+
if (options.forceCatalogRefresh !== true && cached && now - cached.cachedAt < cacheTtl) {
|
|
181
|
+
return cached.models.map(model => ({ ...model }));
|
|
182
|
+
}
|
|
256
183
|
const runner = options.catalogRunner || options.modelsRunner || spawnSync;
|
|
257
|
-
const
|
|
184
|
+
const args = useFullCatalog ? ['models', '--json'] : ['models', providerId, '--json'];
|
|
185
|
+
const result = runner(command, args, {
|
|
258
186
|
encoding: 'utf8',
|
|
259
187
|
env: {
|
|
260
188
|
...process.env,
|
|
@@ -264,26 +192,50 @@ function readOmpCatalogModels(command, providerId, options = {}) {
|
|
|
264
192
|
windowsHide: true
|
|
265
193
|
});
|
|
266
194
|
const status = result?.status === undefined || result?.status === null ? 0 : result.status;
|
|
267
|
-
if (result?.error || status !== 0)
|
|
195
|
+
if (result?.error || status !== 0) {
|
|
196
|
+
ompCatalogCache.set(cacheKey, { cachedAt: now, models: [], failed: true });
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
268
199
|
try {
|
|
269
200
|
const parsed = JSON.parse(normalizeCommandOutput(result?.stdout).trim() || '{}');
|
|
270
|
-
|
|
201
|
+
const rawModels = Array.isArray(parsed.models) ? parsed.models : [];
|
|
202
|
+
let models = rawModels;
|
|
203
|
+
if (useFullCatalog) {
|
|
204
|
+
const providerCandidates = new Set([providerId, `${MANAGED_PROVIDER_PREFIX}${providerId}`]);
|
|
205
|
+
const selected = new Map();
|
|
206
|
+
for (const model of rawModels) {
|
|
207
|
+
const id = String(model?.id || '').trim().toLowerCase();
|
|
208
|
+
if (!requested.has(id)) continue;
|
|
209
|
+
const provider = normalizeProviderId(model?.provider || '');
|
|
210
|
+
const previous = selected.get(id);
|
|
211
|
+
if (!previous || (providerCandidates.has(provider) && !providerCandidates.has(normalizeProviderId(previous.provider || '')))) {
|
|
212
|
+
selected.set(id, model);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
models = [...selected.values()];
|
|
216
|
+
}
|
|
217
|
+
ompCatalogCache.set(cacheKey, { cachedAt: now, models, failed: false });
|
|
218
|
+
return models.map(model => ({ ...model }));
|
|
271
219
|
} catch {
|
|
220
|
+
ompCatalogCache.set(cacheKey, { cachedAt: now, models: [], failed: true });
|
|
272
221
|
return [];
|
|
273
222
|
}
|
|
274
223
|
}
|
|
275
224
|
|
|
225
|
+
|
|
226
|
+
function getOmpCatalogModels(providerId, options = {}) {
|
|
227
|
+
const normalizedProviderId = normalizeProviderId(providerId);
|
|
228
|
+
if (!normalizedProviderId) return [];
|
|
229
|
+
// Catalog sync is an explicit user action. Assume OMP is installed and call
|
|
230
|
+
// it directly instead of paying for a separate `omp --version` probe.
|
|
231
|
+
const command = options.command || options.runtime?.command || options.env?.OMP_COMMAND || process.env.OMP_COMMAND || 'omp';
|
|
232
|
+
return readOmpCatalogModels(command, normalizedProviderId, options);
|
|
233
|
+
}
|
|
234
|
+
|
|
276
235
|
function buildCatalogIndex(channel = {}, options = {}) {
|
|
277
236
|
if (options.catalogFromCli !== true) {
|
|
278
237
|
return new Map();
|
|
279
238
|
}
|
|
280
|
-
const runtime = options.runtime
|
|
281
|
-
|| (typeof ompConfig.resolveOmpRuntime === 'function'
|
|
282
|
-
? ompConfig.resolveOmpRuntime(options.env || process.env, options.runtimeOptions || {})
|
|
283
|
-
: null);
|
|
284
|
-
if (!runtime || runtime.runtime !== 'omp' || !runtime.installed) {
|
|
285
|
-
return new Map();
|
|
286
|
-
}
|
|
287
239
|
|
|
288
240
|
const rawProviderId = normalizeProviderId(channel.providerKey || channel.provider || channel.name || '');
|
|
289
241
|
const providerId = rawProviderId.startsWith(MANAGED_PROVIDER_PREFIX)
|
|
@@ -292,7 +244,7 @@ function buildCatalogIndex(channel = {}, options = {}) {
|
|
|
292
244
|
if (!providerId) return new Map();
|
|
293
245
|
|
|
294
246
|
const index = new Map();
|
|
295
|
-
|
|
247
|
+
getOmpCatalogModels(providerId, options).forEach((model) => {
|
|
296
248
|
const id = String(model?.id || model?.name || '').trim();
|
|
297
249
|
if (id) {
|
|
298
250
|
index.set(id.toLowerCase(), model);
|
|
@@ -305,21 +257,38 @@ function buildProviderEntry(channel = {}, options = {}) {
|
|
|
305
257
|
const catalogIndex = options.catalogIndex instanceof Map
|
|
306
258
|
? options.catalogIndex
|
|
307
259
|
: buildCatalogIndex(channel, options);
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
260
|
+
const providerConfig = isPlainObject(channel.providerConfig) ? channel.providerConfig : {};
|
|
261
|
+
const providerSource = { ...providerConfig };
|
|
262
|
+
for (const key of [
|
|
263
|
+
'headers',
|
|
264
|
+
'compat',
|
|
265
|
+
'remoteCompaction',
|
|
266
|
+
'modelOverrides',
|
|
267
|
+
'authHeader',
|
|
268
|
+
'auth',
|
|
269
|
+
'discovery',
|
|
270
|
+
'disableStrictTools',
|
|
271
|
+
'transport'
|
|
272
|
+
]) {
|
|
273
|
+
if (channel[key] !== undefined) providerSource[key] = channel[key];
|
|
274
|
+
}
|
|
275
|
+
const normalizedProvider = normalizeProviderConfig(providerSource);
|
|
276
|
+
if (Array.isArray(options.warnings)) {
|
|
277
|
+
const providerName = channel.providerKey || channel.provider || channel.name || channel.id || 'provider';
|
|
278
|
+
options.warnings.push(...normalizedProvider.warnings.map(message => `${providerName}: ${message}`));
|
|
279
|
+
}
|
|
280
|
+
const entry = compactObject({
|
|
281
|
+
...normalizedProvider.config,
|
|
282
|
+
baseUrl: String(channel.baseUrl || providerConfig.baseUrl || '').trim(),
|
|
283
|
+
api: normalizeProviderApi(channel.providerApi || channel.api || channel.wireApi || providerConfig.api),
|
|
284
|
+
models: normalizeModels(channel, { catalogIndex, warnings: options.warnings })
|
|
285
|
+
});
|
|
313
286
|
|
|
314
|
-
const apiKey = String(channel.apiKey || '').trim();
|
|
287
|
+
const apiKey = String(channel.apiKey || providerConfig.apiKey || '').trim();
|
|
315
288
|
if (apiKey) {
|
|
316
289
|
entry.apiKey = apiKey;
|
|
317
290
|
}
|
|
318
291
|
|
|
319
|
-
if (channel.headers && typeof channel.headers === 'object' && !Array.isArray(channel.headers)) {
|
|
320
|
-
entry.headers = channel.headers;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
292
|
return entry;
|
|
324
293
|
}
|
|
325
294
|
|
|
@@ -644,6 +613,7 @@ function collectManagedVisibility(channels = [], modelsConfig = { providers: {}
|
|
|
644
613
|
const managedDisabledProviders = [];
|
|
645
614
|
const warnings = [];
|
|
646
615
|
const providers = modelsConfig.providers || {};
|
|
616
|
+
let managedDefaultModel = null;
|
|
647
617
|
|
|
648
618
|
(channels || [])
|
|
649
619
|
.filter(channel => channel && channel.enabled !== false && channel.baseUrl)
|
|
@@ -658,6 +628,20 @@ function collectManagedVisibility(channels = [], modelsConfig = { providers: {}
|
|
|
658
628
|
}
|
|
659
629
|
});
|
|
660
630
|
|
|
631
|
+
const defaultSelection = splitModelSelector(channel.model || '');
|
|
632
|
+
if (!managedDefaultModel && defaultSelection.modelId) {
|
|
633
|
+
const hasDefaultModel = models.some((model) => {
|
|
634
|
+
const modelId = String(model?.id || model?.name || '').trim();
|
|
635
|
+
return modelId.toLowerCase() === defaultSelection.modelId.toLowerCase();
|
|
636
|
+
});
|
|
637
|
+
if (hasDefaultModel) {
|
|
638
|
+
managedDefaultModel = `${managedProviderId}/${serializeModelSelector(
|
|
639
|
+
defaultSelection.modelId,
|
|
640
|
+
defaultSelection.thinkingLevel
|
|
641
|
+
)}`;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
661
645
|
const originalProviderId = getOriginalProviderId(channel);
|
|
662
646
|
if (originalProviderId && !isManagedProviderId(originalProviderId)) {
|
|
663
647
|
pushUnique(managedDisabledProviders, originalProviderId);
|
|
@@ -686,7 +670,7 @@ function collectManagedVisibility(channels = [], modelsConfig = { providers: {}
|
|
|
686
670
|
? managedEnabledModels
|
|
687
671
|
: [NO_MANAGED_MODELS_SELECTOR],
|
|
688
672
|
managedDisabledProviders,
|
|
689
|
-
managedDefaultModel: managedEnabledModels[0] || null,
|
|
673
|
+
managedDefaultModel: managedDefaultModel || managedEnabledModels[0] || null,
|
|
690
674
|
warnings
|
|
691
675
|
};
|
|
692
676
|
}
|
|
@@ -881,7 +865,11 @@ function removeManagedOmpVisibility(options = {}) {
|
|
|
881
865
|
|
|
882
866
|
function writeManagedOmpProviders(channels = [], options = {}) {
|
|
883
867
|
const paths = getOmpPaths();
|
|
884
|
-
const
|
|
868
|
+
const buildWarnings = [];
|
|
869
|
+
const config = buildManagedModelsConfig(channels, readModelsConfig(paths.modelsYml), {
|
|
870
|
+
...options,
|
|
871
|
+
warnings: buildWarnings
|
|
872
|
+
});
|
|
885
873
|
const backupPath = createModelsBackupIfNeeded(paths.modelsYml, options);
|
|
886
874
|
writeModelsConfig(config, paths.modelsYml);
|
|
887
875
|
const visibility = syncManagedOmpVisibility(channels, config, options);
|
|
@@ -889,6 +877,7 @@ function writeManagedOmpProviders(channels = [], options = {}) {
|
|
|
889
877
|
? validateOmpModelsConfig(options)
|
|
890
878
|
: { skipped: true, reason: 'cli-validation-disabled', warnings: [] };
|
|
891
879
|
const warnings = [
|
|
880
|
+
...buildWarnings,
|
|
892
881
|
...(visibility.warnings || []),
|
|
893
882
|
...(validation.warnings || [])
|
|
894
883
|
];
|
|
@@ -975,12 +964,14 @@ module.exports = {
|
|
|
975
964
|
buildManagedExtensionSource,
|
|
976
965
|
buildManagedModelsConfig,
|
|
977
966
|
buildProviderEntry,
|
|
967
|
+
getOmpCatalogModels,
|
|
978
968
|
getManagedProviderId,
|
|
979
969
|
getLastManagedOmpSyncResult,
|
|
980
970
|
isManagedOmpProvidersActive,
|
|
981
971
|
isManagedProviderExtensionActive: isManagedOmpProvidersActive,
|
|
982
972
|
normalizeProviderId,
|
|
983
973
|
normalizeProviderApi,
|
|
974
|
+
normalizeModels,
|
|
984
975
|
readOmpSettingsConfig,
|
|
985
976
|
readModelsConfig,
|
|
986
977
|
removeManagedOmpProviders,
|