yingclaw 2.5.17 → 2.5.19
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/bin/cli.js +63 -17
- package/lib/autostart.js +31 -0
- package/lib/config.js +3 -0
- package/lib/desktop.js +79 -17
- package/lib/gateway.js +3 -2
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -21,7 +21,7 @@ const {
|
|
|
21
21
|
} = require('../lib/config');
|
|
22
22
|
const { execSync, spawn, spawnSync } = require('child_process');
|
|
23
23
|
const pkg = require('../package.json');
|
|
24
|
-
const { getGatewayAutostartStatus, installGatewayAutostart } = require('../lib/autostart');
|
|
24
|
+
const { getGatewayAutostartStatus, installGatewayAutostart, removeGatewayAutostart } = require('../lib/autostart');
|
|
25
25
|
const { buildMenuStatusLines, buildStatusView } = require('../lib/panel');
|
|
26
26
|
const { buildClaudeInstallCommand, checkNodeEnv, getNodeInstallGuide, getInstallFailureHints } = require('../lib/install');
|
|
27
27
|
const { clearClaudeDesktopConfig, isDesktopConfigured, openClaudeDesktop, writeClaudeDesktopConfig } = require('../lib/desktop');
|
|
@@ -32,6 +32,7 @@ const {
|
|
|
32
32
|
checkDesktopGatewayStatus,
|
|
33
33
|
createGatewayServer,
|
|
34
34
|
ensureDesktopGatewayConfig,
|
|
35
|
+
isDesktopChatModel,
|
|
35
36
|
} = require('../lib/gateway');
|
|
36
37
|
const { runDoctorChecks, summarize, STATUS_OK, STATUS_FAIL, STATUS_WARN, STATUS_INFO } = require('../lib/doctor');
|
|
37
38
|
|
|
@@ -101,6 +102,20 @@ function getSavedConfigHint() {
|
|
|
101
102
|
return '⚠ API Key 以明文存储在 ~/.clawai.json';
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
function clearCurrentProcessClaudeEnv() {
|
|
106
|
+
for (const key of CLEAR_CLAUDE_ENV_KEYS) {
|
|
107
|
+
delete process.env[key];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function desktopConfigClearedPaths(result) {
|
|
112
|
+
const path = require('path');
|
|
113
|
+
return [
|
|
114
|
+
...(Array.isArray(result.dataDirs) ? result.dataDirs.map(dir => path.join(dir, 'configLibrary/')) : []),
|
|
115
|
+
...(Array.isArray(result.files) ? result.files : [result.file]),
|
|
116
|
+
].filter(Boolean);
|
|
117
|
+
}
|
|
118
|
+
|
|
104
119
|
async function offerDesktopSync(chalk, ora, config) {
|
|
105
120
|
if (!isDesktopConfigured()) return;
|
|
106
121
|
const syncDesktop = await confirm({ message: 'Claude 桌面应用已配置,是否同步新模型?', default: true });
|
|
@@ -151,6 +166,15 @@ async function promptModelFromChoices({ chalk, choices, message, backLabel = '
|
|
|
151
166
|
}).then(v => v.trim());
|
|
152
167
|
}
|
|
153
168
|
|
|
169
|
+
function getChatModelChoices(models) {
|
|
170
|
+
return models.filter(isDesktopChatModel).map(id => ({ name: id, value: id }));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function formatFetchedModelCount(chalk, total, chatCount) {
|
|
174
|
+
if (total === chatCount) return chalk.green(`已获取 ${chatCount} 个可用聊天模型`);
|
|
175
|
+
return chalk.green(`已获取 ${total} 个模型,其中 ${chatCount} 个可用于 Claude/桌面聊天`);
|
|
176
|
+
}
|
|
177
|
+
|
|
154
178
|
async function promptManualModel(chalk, message, defaultValue) {
|
|
155
179
|
return input({
|
|
156
180
|
message: chalk.cyan(message),
|
|
@@ -185,8 +209,12 @@ async function configureCustomProvider({ chalk, ora, existingConfig }) {
|
|
|
185
209
|
const onlineResult = await fetchModelsFromBaseUrl('custom', apiKey, baseUrl);
|
|
186
210
|
if (onlineResult) {
|
|
187
211
|
modelsUrl = onlineResult.modelsUrl;
|
|
188
|
-
|
|
189
|
-
modelChoices
|
|
212
|
+
modelChoices = getChatModelChoices(onlineResult.models);
|
|
213
|
+
if (modelChoices.length > 0) {
|
|
214
|
+
fetchSpinner.succeed(formatFetchedModelCount(chalk, onlineResult.models.length, modelChoices.length));
|
|
215
|
+
} else {
|
|
216
|
+
fetchSpinner.warn(chalk.yellow(`已获取 ${onlineResult.models.length} 个模型,但没有可用于 Claude/桌面聊天的模型`));
|
|
217
|
+
}
|
|
190
218
|
} else {
|
|
191
219
|
fetchSpinner.warn(chalk.yellow('无法自动获取模型列表,改为手动输入模型'));
|
|
192
220
|
}
|
|
@@ -338,9 +366,15 @@ async function runConfigFlow({ writeCodeEnv = false } = {}) {
|
|
|
338
366
|
const onlineModels = await fetchModels(providerKey, apiKey);
|
|
339
367
|
let modelChoices;
|
|
340
368
|
if (onlineModels && onlineModels.length > 0) {
|
|
341
|
-
|
|
342
|
-
modelChoices
|
|
343
|
-
|
|
369
|
+
modelChoices = getChatModelChoices(onlineModels);
|
|
370
|
+
if (modelChoices.length > 0) {
|
|
371
|
+
fetchSpinner.succeed(formatFetchedModelCount(chalk, onlineModels.length, modelChoices.length));
|
|
372
|
+
availableModels = onlineModels;
|
|
373
|
+
} else {
|
|
374
|
+
fetchSpinner.warn(chalk.yellow(`已获取 ${onlineModels.length} 个模型,但没有可用于 Claude/桌面聊天的模型,使用内置默认列表`));
|
|
375
|
+
modelChoices = provider.models;
|
|
376
|
+
availableModels = provider.models.map(m => m.value);
|
|
377
|
+
}
|
|
344
378
|
} else {
|
|
345
379
|
fetchSpinner.warn(chalk.yellow('无法获取在线列表,使用内置默认列表'));
|
|
346
380
|
modelChoices = provider.models;
|
|
@@ -644,9 +678,15 @@ program
|
|
|
644
678
|
let modelChoices;
|
|
645
679
|
let availableModels;
|
|
646
680
|
if (onlineModels && onlineModels.length > 0) {
|
|
647
|
-
|
|
648
|
-
modelChoices
|
|
649
|
-
|
|
681
|
+
modelChoices = getChatModelChoices(onlineModels);
|
|
682
|
+
if (modelChoices.length > 0) {
|
|
683
|
+
fetchSpinner.succeed(formatFetchedModelCount(chalk, onlineModels.length, modelChoices.length));
|
|
684
|
+
availableModels = onlineModels;
|
|
685
|
+
} else {
|
|
686
|
+
fetchSpinner.warn(chalk.yellow(`已获取 ${onlineModels.length} 个模型,但没有可用于 Claude/桌面聊天的模型,使用内置默认列表`));
|
|
687
|
+
modelChoices = provider.models;
|
|
688
|
+
availableModels = provider.models.map(m => m.value);
|
|
689
|
+
}
|
|
650
690
|
} else {
|
|
651
691
|
fetchSpinner.warn(chalk.yellow('无法获取在线列表,使用内置默认列表'));
|
|
652
692
|
modelChoices = provider.models;
|
|
@@ -763,7 +803,10 @@ program
|
|
|
763
803
|
spinner.warn(chalk.yellow('当前系统暂不支持自动配置 Claude 桌面应用'));
|
|
764
804
|
return;
|
|
765
805
|
}
|
|
766
|
-
|
|
806
|
+
const extraFiles = Array.isArray(result.files) && result.files.length > 1
|
|
807
|
+
? chalk.dim(`(已同步 ${result.files.length} 个配置位置)`)
|
|
808
|
+
: '';
|
|
809
|
+
spinner.succeed(chalk.green(`Claude 桌面应用配置已写入 → ${result.file}`) + extraFiles);
|
|
767
810
|
} catch (e) {
|
|
768
811
|
spinner.fail(chalk.red(`写入失败: ${e.message}`));
|
|
769
812
|
return;
|
|
@@ -856,10 +899,7 @@ program
|
|
|
856
899
|
|
|
857
900
|
if (result.result === 'updated') {
|
|
858
901
|
spinner.succeed(chalk.green('Claude 桌面应用已恢复默认'));
|
|
859
|
-
const cleared =
|
|
860
|
-
result.dataDir ? require('path').join(result.dataDir, 'configLibrary/') : null,
|
|
861
|
-
result.file,
|
|
862
|
-
].filter(Boolean);
|
|
902
|
+
const cleared = desktopConfigClearedPaths(result);
|
|
863
903
|
console.log(boxen(
|
|
864
904
|
chalk.bold('已清除 Claude 桌面应用第三方推理配置:\n\n') +
|
|
865
905
|
cleared.map(f => chalk.cyan(' • ' + f)).join('\n'),
|
|
@@ -916,8 +956,11 @@ program
|
|
|
916
956
|
const cleared = resetConfig();
|
|
917
957
|
const desktopCleared = clearClaudeDesktopConfig();
|
|
918
958
|
if (desktopCleared.result === 'updated') {
|
|
919
|
-
|
|
920
|
-
|
|
959
|
+
cleared.push(...desktopConfigClearedPaths(desktopCleared));
|
|
960
|
+
}
|
|
961
|
+
const autostartCleared = removeGatewayAutostart();
|
|
962
|
+
if (autostartCleared.result === 'removed' && autostartCleared.file) {
|
|
963
|
+
cleared.push(autostartCleared.file);
|
|
921
964
|
}
|
|
922
965
|
|
|
923
966
|
if (cleared.length === 0) {
|
|
@@ -1246,10 +1289,13 @@ async function runMenu() {
|
|
|
1246
1289
|
});
|
|
1247
1290
|
|
|
1248
1291
|
// 改 config 的命令需要刷新缓存
|
|
1249
|
-
if (['config', 'switch', 'reset', 'code-reset'].includes(resolvedAction)) {
|
|
1292
|
+
if (['config', 'switch', 'reset', 'code-reset', 'desktop-reset'].includes(resolvedAction)) {
|
|
1250
1293
|
lastCheckResult = undefined;
|
|
1251
1294
|
lastCheckedHash = null;
|
|
1252
1295
|
}
|
|
1296
|
+
if (process.platform === 'win32' && ['reset', 'code-reset'].includes(resolvedAction)) {
|
|
1297
|
+
clearCurrentProcessClaudeEnv();
|
|
1298
|
+
}
|
|
1253
1299
|
// 安装 Claude 后刷新检测缓存
|
|
1254
1300
|
if (resolvedAction === 'install') {
|
|
1255
1301
|
invalidateClaudeInstalledCache();
|
package/lib/autostart.js
CHANGED
|
@@ -188,6 +188,36 @@ function installGatewayAutostart(options = {}) {
|
|
|
188
188
|
return { result: 'installed', file };
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
function removeGatewayAutostart(options = {}) {
|
|
192
|
+
const platform = options.platform || process.platform;
|
|
193
|
+
if (platform === 'win32') {
|
|
194
|
+
const file = options.file || getWindowsStartupScriptPath(options);
|
|
195
|
+
if (!fs.existsSync(file)) {
|
|
196
|
+
return { result: 'missing', file };
|
|
197
|
+
}
|
|
198
|
+
fs.unlinkSync(file);
|
|
199
|
+
return { result: 'removed', file };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (platform !== 'darwin') {
|
|
203
|
+
return { result: 'unsupported', file: null };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const homeDir = options.homeDir || os.homedir();
|
|
207
|
+
const file = options.file || getMacLaunchAgentPath({ homeDir });
|
|
208
|
+
const uid = options.uid || (typeof process.getuid === 'function' ? process.getuid() : null);
|
|
209
|
+
const runner = options.runner || spawnSync;
|
|
210
|
+
|
|
211
|
+
if (uid != null) {
|
|
212
|
+
runLaunchctl(runner, ['bootout', `gui/${uid}/${GATEWAY_LAUNCH_AGENT_LABEL}`], { optional: true });
|
|
213
|
+
}
|
|
214
|
+
if (!fs.existsSync(file)) {
|
|
215
|
+
return { result: 'missing', file };
|
|
216
|
+
}
|
|
217
|
+
fs.unlinkSync(file);
|
|
218
|
+
return { result: 'removed', file };
|
|
219
|
+
}
|
|
220
|
+
|
|
191
221
|
function getGatewayAutostartStatus(options = {}) {
|
|
192
222
|
const platform = options.platform || process.platform;
|
|
193
223
|
if (platform === 'win32') {
|
|
@@ -237,4 +267,5 @@ module.exports = {
|
|
|
237
267
|
getMacLaunchAgentPath,
|
|
238
268
|
getWindowsStartupScriptPath,
|
|
239
269
|
installGatewayAutostart,
|
|
270
|
+
removeGatewayAutostart,
|
|
240
271
|
};
|
package/lib/config.js
CHANGED
|
@@ -407,6 +407,9 @@ function clearClaudeCodeEnv(options = {}) {
|
|
|
407
407
|
|
|
408
408
|
if (platform === 'win32') {
|
|
409
409
|
runWindowsEnvCommands(buildWindowsClearEnvCommands(), options.runner || spawnSync, { ignoreErrors: true });
|
|
410
|
+
for (const key of CLEAR_CLAUDE_ENV_KEYS) {
|
|
411
|
+
delete process.env[key];
|
|
412
|
+
}
|
|
410
413
|
cleared.push(WINDOWS_ENV_LABEL);
|
|
411
414
|
return cleared;
|
|
412
415
|
}
|
package/lib/desktop.js
CHANGED
|
@@ -55,6 +55,25 @@ function getClaudeDesktopDataDir(options = {}) {
|
|
|
55
55
|
return null;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
function getClaudeDesktopDataDirs(options = {}) {
|
|
59
|
+
if (options.dataDir) return [options.dataDir];
|
|
60
|
+
|
|
61
|
+
const platform = options.platform || process.platform;
|
|
62
|
+
const homeDir = options.homeDir || os.homedir();
|
|
63
|
+
|
|
64
|
+
if (platform === 'win32') {
|
|
65
|
+
const roamingAppData = options.appData || process.env.APPDATA || [homeDir, 'AppData', 'Roaming'].join('\\');
|
|
66
|
+
const localAppData = options.localAppData || process.env.LOCALAPPDATA || [homeDir, 'AppData', 'Local'].join('\\');
|
|
67
|
+
return [...new Set([
|
|
68
|
+
roamingAppData + '\\Claude-3p',
|
|
69
|
+
localAppData + '\\Claude-3p',
|
|
70
|
+
])];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const dataDir = getClaudeDesktopDataDir(options);
|
|
74
|
+
return dataDir ? [dataDir] : [];
|
|
75
|
+
}
|
|
76
|
+
|
|
58
77
|
function getClaudeDesktopConfigPath(options = {}) {
|
|
59
78
|
const platform = options.platform || process.platform;
|
|
60
79
|
const dataDir = options.dataDir || getClaudeDesktopDataDir(options);
|
|
@@ -172,7 +191,8 @@ function buildClaudeDesktopDirectEnterpriseConfig(config, options = {}) {
|
|
|
172
191
|
|
|
173
192
|
// 只清除 yingclaw 写入的那条 entry,保留用户其它 3P 配置
|
|
174
193
|
function clearClaudeDesktopConfigLibrary(options = {}) {
|
|
175
|
-
const
|
|
194
|
+
const dataDir = options.dataDir || getClaudeDesktopDataDir(options);
|
|
195
|
+
const dir = options.configLibraryDir || (dataDir ? path.join(dataDir, 'configLibrary') : null);
|
|
176
196
|
if (!dir || !fs.existsSync(dir)) {
|
|
177
197
|
return { result: 'missing', dir };
|
|
178
198
|
}
|
|
@@ -214,17 +234,11 @@ function clearClaudeDesktopConfigLibrary(options = {}) {
|
|
|
214
234
|
return { result: 'updated', dir };
|
|
215
235
|
}
|
|
216
236
|
|
|
217
|
-
|
|
218
|
-
function writeClaudeDesktopConfig(config, options = {}) {
|
|
237
|
+
function writeClaudeDesktopConfigToDir(config, options, dataDir) {
|
|
219
238
|
const effectiveConfig = options.direct
|
|
220
239
|
? config
|
|
221
240
|
: ensureDesktopGatewayConfig(config, options);
|
|
222
241
|
|
|
223
|
-
const dataDir = options.dataDir || getClaudeDesktopDataDir(options);
|
|
224
|
-
if (!dataDir) {
|
|
225
|
-
return { result: 'unsupported', file: null };
|
|
226
|
-
}
|
|
227
|
-
|
|
228
242
|
const configLibraryDir = path.join(dataDir, 'configLibrary');
|
|
229
243
|
const existingMetaFile = path.join(configLibraryDir, '_meta.json');
|
|
230
244
|
const existingMeta = readJsonFile(existingMetaFile);
|
|
@@ -257,7 +271,7 @@ function writeClaudeDesktopConfig(config, options = {}) {
|
|
|
257
271
|
appliedId: uuid,
|
|
258
272
|
entries: [...otherEntries, { id: uuid, name: YINGCLAW_ENTRY_NAME }],
|
|
259
273
|
isManaged: typeof existingMeta.isManaged === 'boolean' ? existingMeta.isManaged : false,
|
|
260
|
-
platform: existingMeta.platform || process.platform,
|
|
274
|
+
platform: existingMeta.platform || options.platform || process.platform,
|
|
261
275
|
};
|
|
262
276
|
|
|
263
277
|
fs.mkdirSync(configLibraryDir, { recursive: true });
|
|
@@ -295,9 +309,32 @@ function writeClaudeDesktopConfig(config, options = {}) {
|
|
|
295
309
|
return { result: beforeEntry === entryBody ? 'unchanged' : 'updated', file, config: effectiveConfig };
|
|
296
310
|
}
|
|
297
311
|
|
|
298
|
-
|
|
312
|
+
// 写入 Claude-3p/configLibrary/ 下的 enterprise config 条目(主进程从此处读取)
|
|
313
|
+
function writeClaudeDesktopConfig(config, options = {}) {
|
|
314
|
+
const dataDirs = options.configFile
|
|
315
|
+
? [options.dataDir || path.dirname(options.configFile)]
|
|
316
|
+
: getClaudeDesktopDataDirs(options);
|
|
317
|
+
if (dataDirs.length === 0) {
|
|
318
|
+
return { result: 'unsupported', file: null, files: [] };
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const results = dataDirs.map((dataDir, index) => {
|
|
322
|
+
const writeOptions = index === 0
|
|
323
|
+
? options
|
|
324
|
+
: { ...options, configFile: null, dataDir };
|
|
325
|
+
return writeClaudeDesktopConfigToDir(config, writeOptions, dataDir);
|
|
326
|
+
});
|
|
327
|
+
const primary = results[0];
|
|
328
|
+
return {
|
|
329
|
+
...primary,
|
|
330
|
+
result: results.some((item) => item.result === 'updated') ? 'updated' : primary.result,
|
|
331
|
+
files: results.map((item) => item.file).filter(Boolean),
|
|
332
|
+
dataDirs,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function clearClaudeDesktopConfigAtDir(options = {}, dataDir) {
|
|
299
337
|
// Derive dataDir only when configFile is not explicitly overridden (to avoid touching real system dirs in tests)
|
|
300
|
-
const dataDir = options.dataDir || (options.configFile ? null : getClaudeDesktopDataDir(options));
|
|
301
338
|
const file = options.configFile || (dataDir ? path.join(dataDir, 'claude_desktop_config.json') : null);
|
|
302
339
|
|
|
303
340
|
// Clear configLibrary regardless of whether the main config file exists
|
|
@@ -320,7 +357,7 @@ function clearClaudeDesktopConfig(options = {}) {
|
|
|
320
357
|
// Remove legacy enterpriseConfig gateway keys
|
|
321
358
|
if (next.enterpriseConfig && typeof next.enterpriseConfig === 'object') {
|
|
322
359
|
const enterpriseConfig = { ...next.enterpriseConfig };
|
|
323
|
-
for (const key of
|
|
360
|
+
for (const key of MAC_POLICY_KEYS) {
|
|
324
361
|
delete enterpriseConfig[key];
|
|
325
362
|
}
|
|
326
363
|
if (Object.keys(enterpriseConfig).length > 0) {
|
|
@@ -338,12 +375,36 @@ function clearClaudeDesktopConfig(options = {}) {
|
|
|
338
375
|
return { result: 'updated', file, dataDir };
|
|
339
376
|
}
|
|
340
377
|
|
|
378
|
+
function clearClaudeDesktopConfig(options = {}) {
|
|
379
|
+
const dataDirs = options.configFile
|
|
380
|
+
? [options.dataDir || path.dirname(options.configFile)]
|
|
381
|
+
: getClaudeDesktopDataDirs(options);
|
|
382
|
+
|
|
383
|
+
if (dataDirs.length === 0) {
|
|
384
|
+
return { result: 'missing', file: null, files: [], dataDir: null, dataDirs: [] };
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const results = dataDirs.map((dataDir, index) => {
|
|
388
|
+
const clearOptions = index === 0
|
|
389
|
+
? options
|
|
390
|
+
: { ...options, configFile: null, dataDir };
|
|
391
|
+
return clearClaudeDesktopConfigAtDir(clearOptions, dataDir);
|
|
392
|
+
});
|
|
393
|
+
const primary = results[0];
|
|
394
|
+
return {
|
|
395
|
+
...primary,
|
|
396
|
+
result: results.some((item) => item.result === 'updated') ? 'updated' : primary.result,
|
|
397
|
+
files: results.map((item) => item.file).filter(Boolean),
|
|
398
|
+
dataDirs,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
341
402
|
function isDesktopConfigured(options = {}) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
403
|
+
return getClaudeDesktopDataDirs(options).some((dir) => {
|
|
404
|
+
const meta = readJsonFile(path.join(dir, 'configLibrary', '_meta.json'));
|
|
405
|
+
if (!Array.isArray(meta.entries)) return false;
|
|
406
|
+
return meta.entries.some((entry) => entry && entry.name === YINGCLAW_ENTRY_NAME);
|
|
407
|
+
});
|
|
347
408
|
}
|
|
348
409
|
|
|
349
410
|
function buildClaudeDesktopOpenCommands(platform = process.platform, options = {}) {
|
|
@@ -432,6 +493,7 @@ module.exports = {
|
|
|
432
493
|
getClaudeDesktopConfigLibraryDir,
|
|
433
494
|
getClaudeDesktopConfigPath,
|
|
434
495
|
getClaudeDesktopDataDir,
|
|
496
|
+
getClaudeDesktopDataDirs,
|
|
435
497
|
isDesktopConfigured,
|
|
436
498
|
openClaudeDesktop,
|
|
437
499
|
writeClaudeDesktopConfig,
|
package/lib/gateway.js
CHANGED
|
@@ -59,8 +59,9 @@ function desktopRouteLabel(routeId) {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
function isDesktopChatModel(model) {
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
const value = String(model || '');
|
|
63
|
+
return !/(^|[-_])(tts|voice|voiceclone|voicedesign|speech|audio|image|video|embedding|embed|rerank|moderation)([-_]|$)/i.test(value)
|
|
64
|
+
&& !/(cogview|cogvideo|wanx|flux|sdxl|stable-diffusion)/i.test(value);
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
function buildDesktopGatewayRoutes(config) {
|