ccman 3.3.16 → 3.3.18
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/README.md +69 -65
- package/dist/index.js +529 -198
- package/dist/templates/codex/config.toml +4 -2
- package/dist/templates/openclaw/models.base.template.json +10 -10
- package/dist/templates/openclaw/openclaw.base.template.json +12 -11
- package/dist/templates/opencode/opencode.json +5 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,69 +9,6 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
// ../core/package.json
|
|
13
|
-
var package_default;
|
|
14
|
-
var init_package = __esm({
|
|
15
|
-
"../core/package.json"() {
|
|
16
|
-
package_default = {
|
|
17
|
-
name: "@ccman/core",
|
|
18
|
-
version: "3.3.16",
|
|
19
|
-
type: "module",
|
|
20
|
-
description: "Core business logic for ccman - Manage Codex, Claude Code, Gemini CLI, OpenCode, OpenClaw, and MCP configurations",
|
|
21
|
-
main: "./dist/index.js",
|
|
22
|
-
types: "./dist/index.d.ts",
|
|
23
|
-
files: [
|
|
24
|
-
"dist",
|
|
25
|
-
"templates"
|
|
26
|
-
],
|
|
27
|
-
scripts: {
|
|
28
|
-
build: "tsc",
|
|
29
|
-
test: "vitest run",
|
|
30
|
-
"test:watch": "vitest",
|
|
31
|
-
clean: "rm -rf dist"
|
|
32
|
-
},
|
|
33
|
-
keywords: [
|
|
34
|
-
"codex",
|
|
35
|
-
"claude",
|
|
36
|
-
"claude-code",
|
|
37
|
-
"gemini",
|
|
38
|
-
"gemini-cli",
|
|
39
|
-
"opencode",
|
|
40
|
-
"openclaw",
|
|
41
|
-
"mcp",
|
|
42
|
-
"model-context-protocol",
|
|
43
|
-
"ai",
|
|
44
|
-
"api",
|
|
45
|
-
"config",
|
|
46
|
-
"manager"
|
|
47
|
-
],
|
|
48
|
-
author: "2ue",
|
|
49
|
-
license: "MIT",
|
|
50
|
-
repository: {
|
|
51
|
-
type: "git",
|
|
52
|
-
url: "https://github.com/2ue/ccman.git",
|
|
53
|
-
directory: "packages/core"
|
|
54
|
-
},
|
|
55
|
-
homepage: "https://github.com/2ue/ccman#readme",
|
|
56
|
-
bugs: {
|
|
57
|
-
url: "https://github.com/2ue/ccman/issues"
|
|
58
|
-
},
|
|
59
|
-
dependencies: {
|
|
60
|
-
"@ccman/types": "workspace:*",
|
|
61
|
-
"@iarna/toml": "^2.2.5",
|
|
62
|
-
"proper-lockfile": "^4.1.2",
|
|
63
|
-
webdav: "^5.8.0"
|
|
64
|
-
},
|
|
65
|
-
devDependencies: {
|
|
66
|
-
vitest: "^1.0.0"
|
|
67
|
-
},
|
|
68
|
-
engines: {
|
|
69
|
-
node: ">=18.0.0"
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
12
|
// ../types/dist/index.js
|
|
76
13
|
var TOOL_TYPES, MAIN_TOOL_TYPES, TOOL_CONFIG;
|
|
77
14
|
var init_dist = __esm({
|
|
@@ -273,6 +210,35 @@ var init_file = __esm({
|
|
|
273
210
|
}
|
|
274
211
|
});
|
|
275
212
|
|
|
213
|
+
// ../core/dist/utils/template.js
|
|
214
|
+
function replaceVariables(template, variables) {
|
|
215
|
+
const jsonStr = JSON.stringify(template);
|
|
216
|
+
let result = jsonStr;
|
|
217
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
218
|
+
const escapedValue = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
219
|
+
result = result.replace(new RegExp(`{{${key}}}`, "g"), escapedValue);
|
|
220
|
+
}
|
|
221
|
+
return JSON.parse(result);
|
|
222
|
+
}
|
|
223
|
+
function deepMerge(target, source) {
|
|
224
|
+
const result = { ...target };
|
|
225
|
+
for (const key in source) {
|
|
226
|
+
const sourceValue = source[key];
|
|
227
|
+
const targetValue = result[key];
|
|
228
|
+
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
229
|
+
result[key] = deepMerge(targetValue, sourceValue);
|
|
230
|
+
} else {
|
|
231
|
+
result[key] = sourceValue;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
var init_template = __esm({
|
|
237
|
+
"../core/dist/utils/template.js"() {
|
|
238
|
+
"use strict";
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
276
242
|
// ../core/dist/writers/codex.js
|
|
277
243
|
import * as fs2 from "fs";
|
|
278
244
|
import * as path3 from "path";
|
|
@@ -295,7 +261,7 @@ function resolveTemplatePath(relativePath) {
|
|
|
295
261
|
}
|
|
296
262
|
function resolveCodexProviderKey(provider) {
|
|
297
263
|
const baseUrl = (provider.baseUrl || "").toLowerCase();
|
|
298
|
-
if (baseUrl.includes(
|
|
264
|
+
if (GMN_PROVIDER_HOSTS.some((host) => baseUrl.includes(host)))
|
|
299
265
|
return "gmn";
|
|
300
266
|
return provider.name;
|
|
301
267
|
}
|
|
@@ -310,43 +276,105 @@ function loadCodexTemplateConfig() {
|
|
|
310
276
|
}
|
|
311
277
|
return CODEX_DEFAULT_CONFIG;
|
|
312
278
|
}
|
|
313
|
-
function
|
|
279
|
+
function removeDeprecatedKeys(config) {
|
|
280
|
+
if (config.features && typeof config.features === "object" && !Array.isArray(config.features) && "web_search_request" in config.features) {
|
|
281
|
+
delete config.features.web_search_request;
|
|
282
|
+
}
|
|
283
|
+
if ("web_search_request" in config) {
|
|
284
|
+
delete config.web_search_request;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function loadExistingCodexConfig(configPath) {
|
|
288
|
+
if (!fileExists(configPath)) {
|
|
289
|
+
return {};
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
const content = fs2.readFileSync(configPath, "utf-8");
|
|
293
|
+
return parseToml(content);
|
|
294
|
+
} catch {
|
|
295
|
+
return {};
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function buildManagedProvider(provider, providerKey) {
|
|
299
|
+
return {
|
|
300
|
+
name: providerKey,
|
|
301
|
+
base_url: provider.baseUrl,
|
|
302
|
+
wire_api: "responses",
|
|
303
|
+
requires_openai_auth: true
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function writeCodexConfigOverwrite(provider) {
|
|
314
307
|
ensureDir(getCodexDir());
|
|
315
308
|
const configPath = getCodexConfigPath();
|
|
316
309
|
const templateConfig = loadCodexTemplateConfig();
|
|
317
310
|
const nextConfig = { ...templateConfig };
|
|
318
|
-
|
|
319
|
-
delete nextConfig.features.web_search_request;
|
|
320
|
-
}
|
|
321
|
-
if ("web_search_request" in nextConfig) {
|
|
322
|
-
delete nextConfig.web_search_request;
|
|
323
|
-
}
|
|
311
|
+
removeDeprecatedKeys(nextConfig);
|
|
324
312
|
const providerKey = resolveCodexProviderKey(provider);
|
|
325
313
|
nextConfig.model_provider = providerKey;
|
|
326
|
-
nextConfig.model = provider.model || nextConfig.model || "gpt-5.
|
|
314
|
+
nextConfig.model = provider.model || nextConfig.model || "gpt-5.4";
|
|
327
315
|
nextConfig.model_providers = {
|
|
328
|
-
[providerKey]:
|
|
329
|
-
name: providerKey,
|
|
330
|
-
base_url: provider.baseUrl,
|
|
331
|
-
wire_api: "responses",
|
|
332
|
-
requires_openai_auth: true
|
|
333
|
-
}
|
|
316
|
+
[providerKey]: buildManagedProvider(provider, providerKey)
|
|
334
317
|
};
|
|
335
318
|
fs2.writeFileSync(configPath, stringifyToml(nextConfig), { mode: 384 });
|
|
336
319
|
const authPath = getCodexAuthPath();
|
|
337
320
|
const auth = { OPENAI_API_KEY: provider.apiKey };
|
|
338
321
|
writeJSON(authPath, auth);
|
|
339
322
|
}
|
|
340
|
-
|
|
323
|
+
function writeCodexConfigMerge(provider) {
|
|
324
|
+
ensureDir(getCodexDir());
|
|
325
|
+
const configPath = getCodexConfigPath();
|
|
326
|
+
const existingConfig = loadExistingCodexConfig(configPath);
|
|
327
|
+
const templateConfig = loadCodexTemplateConfig();
|
|
328
|
+
const nextConfig = deepMerge(templateConfig, existingConfig);
|
|
329
|
+
const providerKey = resolveCodexProviderKey(provider);
|
|
330
|
+
removeDeprecatedKeys(nextConfig);
|
|
331
|
+
nextConfig.model_provider = providerKey;
|
|
332
|
+
nextConfig.model = provider.model || nextConfig.model || "gpt-5.4";
|
|
333
|
+
const existingProviders = nextConfig.model_providers && typeof nextConfig.model_providers === "object" && !Array.isArray(nextConfig.model_providers) ? { ...nextConfig.model_providers } : {};
|
|
334
|
+
const lowerProviderKey = providerKey.toLowerCase();
|
|
335
|
+
for (const key of Object.keys(existingProviders)) {
|
|
336
|
+
if (key.toLowerCase() === lowerProviderKey) {
|
|
337
|
+
delete existingProviders[key];
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
nextConfig.model_providers = {
|
|
341
|
+
...existingProviders,
|
|
342
|
+
[providerKey]: buildManagedProvider(provider, providerKey)
|
|
343
|
+
};
|
|
344
|
+
fs2.writeFileSync(configPath, stringifyToml(nextConfig), { mode: 384 });
|
|
345
|
+
const authPath = getCodexAuthPath();
|
|
346
|
+
let existingAuth = { OPENAI_API_KEY: "" };
|
|
347
|
+
if (fileExists(authPath)) {
|
|
348
|
+
try {
|
|
349
|
+
existingAuth = readJSON(authPath);
|
|
350
|
+
} catch {
|
|
351
|
+
existingAuth = { OPENAI_API_KEY: "" };
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
const nextAuth = {
|
|
355
|
+
...existingAuth,
|
|
356
|
+
OPENAI_API_KEY: provider.apiKey
|
|
357
|
+
};
|
|
358
|
+
writeJSON(authPath, nextAuth);
|
|
359
|
+
}
|
|
360
|
+
function writeCodexConfig(provider, options = {}) {
|
|
361
|
+
if (options.mode === "overwrite") {
|
|
362
|
+
writeCodexConfigOverwrite(provider);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
writeCodexConfigMerge(provider);
|
|
366
|
+
}
|
|
367
|
+
var __filename, __dirname, CODEX_DEFAULT_CONFIG, GMN_PROVIDER_HOSTS;
|
|
341
368
|
var init_codex = __esm({
|
|
342
369
|
"../core/dist/writers/codex.js"() {
|
|
343
370
|
"use strict";
|
|
344
371
|
init_paths();
|
|
345
372
|
init_file();
|
|
373
|
+
init_template();
|
|
346
374
|
__filename = fileURLToPath(import.meta.url);
|
|
347
375
|
__dirname = path3.dirname(__filename);
|
|
348
376
|
CODEX_DEFAULT_CONFIG = {
|
|
349
|
-
model: "gpt-5.
|
|
377
|
+
model: "gpt-5.4",
|
|
350
378
|
model_reasoning_effort: "xhigh",
|
|
351
379
|
disable_response_storage: true,
|
|
352
380
|
sandbox_mode: "danger-full-access",
|
|
@@ -392,35 +420,15 @@ var init_codex = __esm({
|
|
|
392
420
|
hide_gpt5_1_migration_prompt: true
|
|
393
421
|
}
|
|
394
422
|
};
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
result = result.replace(new RegExp(`{{${key}}}`, "g"), escapedValue);
|
|
405
|
-
}
|
|
406
|
-
return JSON.parse(result);
|
|
407
|
-
}
|
|
408
|
-
function deepMerge(target, source) {
|
|
409
|
-
const result = { ...target };
|
|
410
|
-
for (const key in source) {
|
|
411
|
-
const sourceValue = source[key];
|
|
412
|
-
const targetValue = result[key];
|
|
413
|
-
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
414
|
-
result[key] = deepMerge(targetValue, sourceValue);
|
|
415
|
-
} else {
|
|
416
|
-
result[key] = sourceValue;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
return result;
|
|
420
|
-
}
|
|
421
|
-
var init_template = __esm({
|
|
422
|
-
"../core/dist/utils/template.js"() {
|
|
423
|
-
"use strict";
|
|
423
|
+
GMN_PROVIDER_HOSTS = [
|
|
424
|
+
"gmn.chuangzuoli.com",
|
|
425
|
+
"cdn.gmnchuangzuoli.com",
|
|
426
|
+
"gmncodex.com",
|
|
427
|
+
"gmncode.cn",
|
|
428
|
+
"cdn.gmncode.cn",
|
|
429
|
+
"gmn.codex.com",
|
|
430
|
+
"cdn.gmncode.com"
|
|
431
|
+
];
|
|
424
432
|
}
|
|
425
433
|
});
|
|
426
434
|
|
|
@@ -454,19 +462,23 @@ function loadClaudeTemplateConfig() {
|
|
|
454
462
|
}
|
|
455
463
|
return CLAUDE_CONFIG_TEMPLATE;
|
|
456
464
|
}
|
|
457
|
-
function writeClaudeConfig(provider) {
|
|
465
|
+
function writeClaudeConfig(provider, options = {}) {
|
|
458
466
|
ensureDir(getClaudeDir());
|
|
459
467
|
const configPath = getClaudeConfigPath();
|
|
460
|
-
let userConfig = {};
|
|
461
|
-
if (fileExists(configPath)) {
|
|
462
|
-
const content = fs3.readFileSync(configPath, "utf-8");
|
|
463
|
-
userConfig = JSON.parse(content);
|
|
464
|
-
}
|
|
465
468
|
const defaultTemplate = loadClaudeTemplateConfig();
|
|
466
469
|
const defaultConfig = replaceVariables(defaultTemplate, {
|
|
467
470
|
apiKey: provider.apiKey,
|
|
468
471
|
baseUrl: provider.baseUrl
|
|
469
472
|
});
|
|
473
|
+
if (options.mode === "overwrite") {
|
|
474
|
+
fs3.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2), { mode: 384 });
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
let userConfig = {};
|
|
478
|
+
if (fileExists(configPath)) {
|
|
479
|
+
const content = fs3.readFileSync(configPath, "utf-8");
|
|
480
|
+
userConfig = JSON.parse(content);
|
|
481
|
+
}
|
|
470
482
|
const mergedConfig = deepMerge(defaultConfig, userConfig);
|
|
471
483
|
mergedConfig.env = mergedConfig.env || {};
|
|
472
484
|
mergedConfig.env.ANTHROPIC_AUTH_TOKEN = provider.apiKey;
|
|
@@ -893,13 +905,14 @@ function saveEnvFile(envPath, env) {
|
|
|
893
905
|
fs5.writeFileSync(tempPath, content, { mode: 384 });
|
|
894
906
|
fs5.renameSync(tempPath, envPath);
|
|
895
907
|
}
|
|
896
|
-
function writeGeminiConfig(provider) {
|
|
908
|
+
function writeGeminiConfig(provider, options = {}) {
|
|
897
909
|
const settingsPath = getGeminiSettingsPath();
|
|
898
910
|
const envPath = getGeminiEnvPath();
|
|
899
911
|
const dir = getGeminiDir();
|
|
900
912
|
ensureDir(dir);
|
|
913
|
+
const settingsTemplate = loadGeminiSettingsTemplate();
|
|
901
914
|
let userSettings = {};
|
|
902
|
-
if (fileExists(settingsPath)) {
|
|
915
|
+
if (options.mode !== "overwrite" && fileExists(settingsPath)) {
|
|
903
916
|
try {
|
|
904
917
|
const content = fs5.readFileSync(settingsPath, "utf-8");
|
|
905
918
|
const parsed = JSON.parse(content);
|
|
@@ -910,8 +923,7 @@ function writeGeminiConfig(provider) {
|
|
|
910
923
|
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6 Gemini settings.json: ${error.message}`);
|
|
911
924
|
}
|
|
912
925
|
}
|
|
913
|
-
const
|
|
914
|
-
const settings = deepMerge(settingsTemplate, userSettings);
|
|
926
|
+
const settings = options.mode === "overwrite" ? { ...settingsTemplate } : deepMerge(settingsTemplate, userSettings);
|
|
915
927
|
if (!settings.ide || typeof settings.ide !== "object") {
|
|
916
928
|
settings.ide = {};
|
|
917
929
|
}
|
|
@@ -936,7 +948,7 @@ function writeGeminiConfig(provider) {
|
|
|
936
948
|
} catch (error) {
|
|
937
949
|
throw new Error(`\u5199\u5165 Gemini settings.json \u5931\u8D25: ${error.message}`);
|
|
938
950
|
}
|
|
939
|
-
const existingEnv = loadEnvFile(envPath);
|
|
951
|
+
const existingEnv = options.mode === "overwrite" ? {} : loadEnvFile(envPath);
|
|
940
952
|
const templateEnv = loadGeminiEnvTemplate(provider);
|
|
941
953
|
const env = {
|
|
942
954
|
...existingEnv,
|
|
@@ -1063,7 +1075,8 @@ function enforceAgentStoreFalse(agent) {
|
|
|
1063
1075
|
}
|
|
1064
1076
|
function enforceModelStoreFalse(models) {
|
|
1065
1077
|
const base = models && typeof models === "object" && !Array.isArray(models) ? models : {};
|
|
1066
|
-
|
|
1078
|
+
const mergedModels = deepMerge(DEFAULT_MODELS, base);
|
|
1079
|
+
return deepMerge(mergedModels, {
|
|
1067
1080
|
[OPENCODE_MODEL_KEY]: {
|
|
1068
1081
|
options: {
|
|
1069
1082
|
store: false
|
|
@@ -1074,20 +1087,31 @@ function enforceModelStoreFalse(models) {
|
|
|
1074
1087
|
high: {},
|
|
1075
1088
|
xhigh: {}
|
|
1076
1089
|
}
|
|
1090
|
+
},
|
|
1091
|
+
[OPENCODE_SECONDARY_MODEL_KEY]: {
|
|
1092
|
+
options: {
|
|
1093
|
+
store: false
|
|
1094
|
+
},
|
|
1095
|
+
variants: {
|
|
1096
|
+
low: {},
|
|
1097
|
+
medium: {},
|
|
1098
|
+
high: {},
|
|
1099
|
+
xhigh: {}
|
|
1100
|
+
}
|
|
1077
1101
|
}
|
|
1078
1102
|
});
|
|
1079
1103
|
}
|
|
1080
|
-
function writeOpenCodeConfig(provider) {
|
|
1104
|
+
function writeOpenCodeConfig(provider, options = {}) {
|
|
1081
1105
|
ensureDir(getOpenCodeDir());
|
|
1082
1106
|
const configPath = getOpenCodeConfigPath();
|
|
1083
|
-
const existingConfig = fileExists(configPath) ? readJSON(configPath) : {};
|
|
1107
|
+
const existingConfig = options.mode === "overwrite" ? {} : fileExists(configPath) ? readJSON(configPath) : {};
|
|
1084
1108
|
const meta = parseProviderMeta(provider.model);
|
|
1085
1109
|
const template = loadOpenCodeTemplateConfig();
|
|
1086
1110
|
const defaultConfig = replaceVariables(template, {
|
|
1087
1111
|
baseUrl: provider.baseUrl,
|
|
1088
1112
|
apiKey: provider.apiKey
|
|
1089
1113
|
});
|
|
1090
|
-
const mergedConfig = deepMerge(defaultConfig, existingConfig);
|
|
1114
|
+
const mergedConfig = options.mode === "overwrite" ? { ...defaultConfig } : deepMerge(defaultConfig, existingConfig);
|
|
1091
1115
|
const templateProvider = defaultConfig.provider?.[OPENCODE_PROVIDER_KEY];
|
|
1092
1116
|
const existingProvider = mergedConfig.provider?.[OPENCODE_PROVIDER_KEY];
|
|
1093
1117
|
const models = enforceModelStoreFalse(meta?.models || existingProvider?.models || templateProvider?.models || DEFAULT_MODELS);
|
|
@@ -1100,7 +1124,7 @@ function writeOpenCodeConfig(provider) {
|
|
|
1100
1124
|
},
|
|
1101
1125
|
models
|
|
1102
1126
|
});
|
|
1103
|
-
const existingProviders = mergedConfig.provider && typeof mergedConfig.provider === "object" && !Array.isArray(mergedConfig.provider) ? { ...mergedConfig.provider } : {};
|
|
1127
|
+
const existingProviders = options.mode === "overwrite" ? {} : mergedConfig.provider && typeof mergedConfig.provider === "object" && !Array.isArray(mergedConfig.provider) ? { ...mergedConfig.provider } : {};
|
|
1104
1128
|
const nextConfig = {
|
|
1105
1129
|
...mergedConfig,
|
|
1106
1130
|
$schema: OPENCODE_SCHEMA,
|
|
@@ -1113,7 +1137,7 @@ function writeOpenCodeConfig(provider) {
|
|
|
1113
1137
|
};
|
|
1114
1138
|
writeJSON(configPath, nextConfig);
|
|
1115
1139
|
}
|
|
1116
|
-
var OPENCODE_SCHEMA, OPENCODE_PROVIDER_KEY, OPENCODE_MODEL, OPENCODE_MODEL_KEY, __filename4, __dirname4, DEFAULT_MODELS, OPENCODE_CONFIG_TEMPLATE;
|
|
1140
|
+
var OPENCODE_SCHEMA, OPENCODE_PROVIDER_KEY, OPENCODE_MODEL, OPENCODE_MODEL_KEY, OPENCODE_SECONDARY_MODEL_KEY, __filename4, __dirname4, DEFAULT_MODELS, OPENCODE_CONFIG_TEMPLATE;
|
|
1117
1141
|
var init_opencode2 = __esm({
|
|
1118
1142
|
"../core/dist/writers/opencode.js"() {
|
|
1119
1143
|
"use strict";
|
|
@@ -1122,13 +1146,26 @@ var init_opencode2 = __esm({
|
|
|
1122
1146
|
init_template();
|
|
1123
1147
|
OPENCODE_SCHEMA = "https://opencode.ai/config.json";
|
|
1124
1148
|
OPENCODE_PROVIDER_KEY = "openai";
|
|
1125
|
-
OPENCODE_MODEL = "openai/gpt-5.
|
|
1126
|
-
OPENCODE_MODEL_KEY = "gpt-5.
|
|
1149
|
+
OPENCODE_MODEL = "openai/gpt-5.4";
|
|
1150
|
+
OPENCODE_MODEL_KEY = "gpt-5.4";
|
|
1151
|
+
OPENCODE_SECONDARY_MODEL_KEY = "gpt-5.3-codex";
|
|
1127
1152
|
__filename4 = fileURLToPath4(import.meta.url);
|
|
1128
1153
|
__dirname4 = path7.dirname(__filename4);
|
|
1129
1154
|
DEFAULT_MODELS = {
|
|
1130
1155
|
[OPENCODE_MODEL_KEY]: {
|
|
1131
|
-
name: "GPT-5.
|
|
1156
|
+
name: "GPT-5.4",
|
|
1157
|
+
options: {
|
|
1158
|
+
store: false
|
|
1159
|
+
},
|
|
1160
|
+
variants: {
|
|
1161
|
+
low: {},
|
|
1162
|
+
medium: {},
|
|
1163
|
+
high: {},
|
|
1164
|
+
xhigh: {}
|
|
1165
|
+
}
|
|
1166
|
+
},
|
|
1167
|
+
[OPENCODE_SECONDARY_MODEL_KEY]: {
|
|
1168
|
+
name: "GPT-5.3 Codex",
|
|
1132
1169
|
options: {
|
|
1133
1170
|
store: false
|
|
1134
1171
|
},
|
|
@@ -1257,7 +1294,7 @@ function replaceProviderEntry(providers, providerName, nextProvider) {
|
|
|
1257
1294
|
}
|
|
1258
1295
|
return result;
|
|
1259
1296
|
}
|
|
1260
|
-
function writeOpenClawConfig(provider) {
|
|
1297
|
+
function writeOpenClawConfig(provider, options = {}) {
|
|
1261
1298
|
const configPath = getOpenClawConfigPath();
|
|
1262
1299
|
const modelsPath = getOpenClawModelsPath();
|
|
1263
1300
|
const homeDir = path8.dirname(getOpenClawDir());
|
|
@@ -1273,6 +1310,26 @@ function writeOpenClawConfig(provider) {
|
|
|
1273
1310
|
};
|
|
1274
1311
|
const nextOpenClawConfig = replaceVariables(rawConfigTemplate, variables);
|
|
1275
1312
|
const nextModelsConfig = replaceVariables(rawModelsTemplate, variables);
|
|
1313
|
+
if (options.mode === "overwrite") {
|
|
1314
|
+
const overwriteConfig = {
|
|
1315
|
+
...nextOpenClawConfig,
|
|
1316
|
+
agents: {
|
|
1317
|
+
...nextOpenClawConfig.agents,
|
|
1318
|
+
defaults: {
|
|
1319
|
+
...nextOpenClawConfig.agents?.defaults || {},
|
|
1320
|
+
workspace: homeDir,
|
|
1321
|
+
imageModel: nextOpenClawConfig.agents?.defaults?.imageModel || `${providerName}/gpt-5.4`,
|
|
1322
|
+
model: {
|
|
1323
|
+
...nextOpenClawConfig.agents?.defaults?.model || {},
|
|
1324
|
+
primary: nextOpenClawConfig.agents?.defaults?.model?.primary || `${providerName}/gpt-5.4`
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
};
|
|
1329
|
+
writeJSON(configPath, overwriteConfig);
|
|
1330
|
+
writeJSON(modelsPath, nextModelsConfig);
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1276
1333
|
const existingOpenClawConfig = loadExistingJSON(configPath) || {};
|
|
1277
1334
|
const existingModelsConfig = loadExistingJSON(modelsPath) || {};
|
|
1278
1335
|
const mergedConfigModels = deepMerge(existingOpenClawConfig.models || {}, nextOpenClawConfig.models || {});
|
|
@@ -1282,7 +1339,8 @@ function writeOpenClawConfig(provider) {
|
|
|
1282
1339
|
const mergedAgents = deepMerge(nextOpenClawConfig.agents || {}, existingOpenClawConfig.agents || {});
|
|
1283
1340
|
const mergedDefaults = mergedAgents.defaults || {};
|
|
1284
1341
|
const mergedModel = mergedDefaults.model || {};
|
|
1285
|
-
const templatePrimary = nextOpenClawConfig.agents?.defaults?.model?.primary || `${providerName}/gpt-5.
|
|
1342
|
+
const templatePrimary = nextOpenClawConfig.agents?.defaults?.model?.primary || `${providerName}/gpt-5.4`;
|
|
1343
|
+
const templateImageModel = nextOpenClawConfig.agents?.defaults?.imageModel || `${providerName}/gpt-5.4`;
|
|
1286
1344
|
const workspace = typeof mergedDefaults.workspace === "string" && mergedDefaults.workspace.trim() ? mergedDefaults.workspace : homeDir;
|
|
1287
1345
|
const finalOpenClawConfig = {
|
|
1288
1346
|
...existingOpenClawConfig,
|
|
@@ -1292,6 +1350,7 @@ function writeOpenClawConfig(provider) {
|
|
|
1292
1350
|
defaults: {
|
|
1293
1351
|
...mergedDefaults,
|
|
1294
1352
|
workspace,
|
|
1353
|
+
imageModel: templateImageModel,
|
|
1295
1354
|
model: {
|
|
1296
1355
|
...mergedModel,
|
|
1297
1356
|
primary: templatePrimary
|
|
@@ -1308,7 +1367,7 @@ function writeOpenClawConfig(provider) {
|
|
|
1308
1367
|
writeJSON(configPath, finalOpenClawConfig);
|
|
1309
1368
|
writeJSON(modelsPath, finalModelsConfig);
|
|
1310
1369
|
}
|
|
1311
|
-
var DEFAULT_PROVIDER_NAME, PRIMARY_MODEL_ID, __filename5, __dirname5, OPENCLAW_CONFIG_TEMPLATE, OPENCLAW_MODELS_TEMPLATE;
|
|
1370
|
+
var DEFAULT_PROVIDER_NAME, PRIMARY_MODEL_ID, SECONDARY_MODEL_ID, PRIMARY_MODEL_INPUTS, SECONDARY_MODEL_INPUTS, __filename5, __dirname5, OPENCLAW_CONFIG_TEMPLATE, OPENCLAW_MODELS_TEMPLATE;
|
|
1312
1371
|
var init_openclaw2 = __esm({
|
|
1313
1372
|
"../core/dist/writers/openclaw.js"() {
|
|
1314
1373
|
"use strict";
|
|
@@ -1316,7 +1375,10 @@ var init_openclaw2 = __esm({
|
|
|
1316
1375
|
init_file();
|
|
1317
1376
|
init_template();
|
|
1318
1377
|
DEFAULT_PROVIDER_NAME = "gmn";
|
|
1319
|
-
PRIMARY_MODEL_ID = "gpt-5.
|
|
1378
|
+
PRIMARY_MODEL_ID = "gpt-5.4";
|
|
1379
|
+
SECONDARY_MODEL_ID = "gpt-5.3-codex";
|
|
1380
|
+
PRIMARY_MODEL_INPUTS = ["text", "image"];
|
|
1381
|
+
SECONDARY_MODEL_INPUTS = ["text", "image"];
|
|
1320
1382
|
__filename5 = fileURLToPath5(import.meta.url);
|
|
1321
1383
|
__dirname5 = path8.dirname(__filename5);
|
|
1322
1384
|
OPENCLAW_CONFIG_TEMPLATE = {
|
|
@@ -1334,24 +1396,24 @@ var init_openclaw2 = __esm({
|
|
|
1334
1396
|
authHeader: true,
|
|
1335
1397
|
models: [
|
|
1336
1398
|
{
|
|
1337
|
-
id: "gpt-5.
|
|
1338
|
-
name: "gpt-5.
|
|
1399
|
+
id: "gpt-5.4",
|
|
1400
|
+
name: "gpt-5.4",
|
|
1339
1401
|
api: "openai-responses",
|
|
1340
|
-
reasoning:
|
|
1341
|
-
input:
|
|
1402
|
+
reasoning: true,
|
|
1403
|
+
input: PRIMARY_MODEL_INPUTS,
|
|
1342
1404
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1343
|
-
contextWindow:
|
|
1344
|
-
maxTokens:
|
|
1405
|
+
contextWindow: 105e4,
|
|
1406
|
+
maxTokens: 128e3
|
|
1345
1407
|
},
|
|
1346
1408
|
{
|
|
1347
|
-
id:
|
|
1348
|
-
name:
|
|
1409
|
+
id: SECONDARY_MODEL_ID,
|
|
1410
|
+
name: SECONDARY_MODEL_ID,
|
|
1349
1411
|
api: "openai-responses",
|
|
1350
1412
|
reasoning: false,
|
|
1351
|
-
input:
|
|
1413
|
+
input: SECONDARY_MODEL_INPUTS,
|
|
1352
1414
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1353
|
-
contextWindow:
|
|
1354
|
-
maxTokens:
|
|
1415
|
+
contextWindow: 4e5,
|
|
1416
|
+
maxTokens: 128e3
|
|
1355
1417
|
}
|
|
1356
1418
|
]
|
|
1357
1419
|
}
|
|
@@ -1360,8 +1422,9 @@ var init_openclaw2 = __esm({
|
|
|
1360
1422
|
agents: {
|
|
1361
1423
|
defaults: {
|
|
1362
1424
|
workspace: "",
|
|
1425
|
+
imageModel: "{{providerName}}/gpt-5.4",
|
|
1363
1426
|
model: {
|
|
1364
|
-
primary: "{{providerName}}/gpt-5.
|
|
1427
|
+
primary: "{{providerName}}/gpt-5.4"
|
|
1365
1428
|
},
|
|
1366
1429
|
thinkingDefault: "xhigh"
|
|
1367
1430
|
}
|
|
@@ -1380,24 +1443,24 @@ var init_openclaw2 = __esm({
|
|
|
1380
1443
|
},
|
|
1381
1444
|
models: [
|
|
1382
1445
|
{
|
|
1383
|
-
id: "gpt-5.
|
|
1384
|
-
name: "gpt-5.
|
|
1446
|
+
id: "gpt-5.4",
|
|
1447
|
+
name: "gpt-5.4",
|
|
1385
1448
|
api: "openai-responses",
|
|
1386
|
-
reasoning:
|
|
1387
|
-
input:
|
|
1449
|
+
reasoning: true,
|
|
1450
|
+
input: PRIMARY_MODEL_INPUTS,
|
|
1388
1451
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1389
|
-
contextWindow:
|
|
1390
|
-
maxTokens:
|
|
1452
|
+
contextWindow: 105e4,
|
|
1453
|
+
maxTokens: 128e3
|
|
1391
1454
|
},
|
|
1392
1455
|
{
|
|
1393
|
-
id:
|
|
1394
|
-
name:
|
|
1456
|
+
id: SECONDARY_MODEL_ID,
|
|
1457
|
+
name: SECONDARY_MODEL_ID,
|
|
1395
1458
|
api: "openai-responses",
|
|
1396
1459
|
reasoning: false,
|
|
1397
|
-
input:
|
|
1460
|
+
input: SECONDARY_MODEL_INPUTS,
|
|
1398
1461
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1399
|
-
contextWindow:
|
|
1400
|
-
maxTokens:
|
|
1462
|
+
contextWindow: 4e5,
|
|
1463
|
+
maxTokens: 128e3
|
|
1401
1464
|
}
|
|
1402
1465
|
]
|
|
1403
1466
|
}
|
|
@@ -1537,7 +1600,7 @@ function createToolManager(tool) {
|
|
|
1537
1600
|
return void 0;
|
|
1538
1601
|
return config.providers.find((p) => p.name.trim().toLowerCase() === lowerName);
|
|
1539
1602
|
},
|
|
1540
|
-
switch(id) {
|
|
1603
|
+
switch(id, options) {
|
|
1541
1604
|
const config = loadConfig2();
|
|
1542
1605
|
const provider = config.providers.find((p) => p.id === id);
|
|
1543
1606
|
if (!provider) {
|
|
@@ -1546,7 +1609,7 @@ function createToolManager(tool) {
|
|
|
1546
1609
|
config.currentProviderId = id;
|
|
1547
1610
|
provider.lastUsedAt = Date.now();
|
|
1548
1611
|
saveConfig2(config);
|
|
1549
|
-
toolConfig.writer(provider);
|
|
1612
|
+
toolConfig.writer(provider, options);
|
|
1550
1613
|
},
|
|
1551
1614
|
getCurrent() {
|
|
1552
1615
|
const config = loadConfig2();
|
|
@@ -1559,10 +1622,11 @@ function createToolManager(tool) {
|
|
|
1559
1622
|
// 注:edit 方法的"复杂度"来自必要的业务逻辑(检查存在性、名称冲突、更新 4 个可选字段、同步配置)
|
|
1560
1623
|
// 每个 if 都不可避免,没有特殊情况或嵌套逻辑,因此禁用 complexity 检查
|
|
1561
1624
|
// eslint-disable-next-line complexity
|
|
1562
|
-
edit(id, updates) {
|
|
1625
|
+
edit(id, updates, options = {}) {
|
|
1563
1626
|
const config = loadConfig2();
|
|
1564
1627
|
const provider = config.providers.find((p) => p.id === id);
|
|
1565
1628
|
const normalizedUpdates = trimProviderUpdates(updates);
|
|
1629
|
+
const shouldApplyWrite = options.applyWrite !== false;
|
|
1566
1630
|
if (!provider) {
|
|
1567
1631
|
throw new ProviderNotFoundError(id);
|
|
1568
1632
|
}
|
|
@@ -1587,10 +1651,10 @@ function createToolManager(tool) {
|
|
|
1587
1651
|
provider.model = normalizedUpdates.model;
|
|
1588
1652
|
provider.lastModified = Date.now();
|
|
1589
1653
|
saveConfig2(config);
|
|
1590
|
-
if (config.currentProviderId === id) {
|
|
1654
|
+
if (shouldApplyWrite && config.currentProviderId === id) {
|
|
1591
1655
|
toolConfig.writer(provider);
|
|
1592
1656
|
}
|
|
1593
|
-
if (toolConfig.autoSync) {
|
|
1657
|
+
if (shouldApplyWrite && toolConfig.autoSync) {
|
|
1594
1658
|
toolConfig.writer(provider);
|
|
1595
1659
|
}
|
|
1596
1660
|
return provider;
|
|
@@ -2806,11 +2870,11 @@ var init_claude_clean = __esm({
|
|
|
2806
2870
|
});
|
|
2807
2871
|
|
|
2808
2872
|
// ../core/dist/index.js
|
|
2809
|
-
|
|
2873
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
2874
|
+
var pkg, VERSION;
|
|
2810
2875
|
var init_dist2 = __esm({
|
|
2811
2876
|
"../core/dist/index.js"() {
|
|
2812
2877
|
"use strict";
|
|
2813
|
-
init_package();
|
|
2814
2878
|
init_constants();
|
|
2815
2879
|
init_tool_manager();
|
|
2816
2880
|
init_codex2();
|
|
@@ -2829,7 +2893,8 @@ var init_dist2 = __esm({
|
|
|
2829
2893
|
init_merge_advanced();
|
|
2830
2894
|
init_export();
|
|
2831
2895
|
init_claude_clean();
|
|
2832
|
-
|
|
2896
|
+
pkg = JSON.parse(readFileSync10(new URL("../package.json", import.meta.url), "utf-8"));
|
|
2897
|
+
VERSION = pkg.version;
|
|
2833
2898
|
}
|
|
2834
2899
|
});
|
|
2835
2900
|
|
|
@@ -7151,19 +7216,187 @@ import fs13 from "fs";
|
|
|
7151
7216
|
import path15 from "path";
|
|
7152
7217
|
import chalk54 from "chalk";
|
|
7153
7218
|
import inquirer38 from "inquirer";
|
|
7219
|
+
|
|
7220
|
+
// src/utils/endpoint-latency.ts
|
|
7221
|
+
import { request as httpRequest } from "http";
|
|
7222
|
+
import { request as httpsRequest } from "https";
|
|
7223
|
+
import { performance } from "perf_hooks";
|
|
7224
|
+
function normalizeEndpointUrl(url) {
|
|
7225
|
+
const normalized = url.trim().replace(/\/+$/, "");
|
|
7226
|
+
new URL(normalized);
|
|
7227
|
+
return normalized;
|
|
7228
|
+
}
|
|
7229
|
+
function calculateMedian(values) {
|
|
7230
|
+
if (values.length === 0) {
|
|
7231
|
+
throw new Error("\u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u91C7\u6837\u503C");
|
|
7232
|
+
}
|
|
7233
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
7234
|
+
const middle = Math.floor(sorted.length / 2);
|
|
7235
|
+
if (sorted.length % 2 === 0) {
|
|
7236
|
+
return Math.round((sorted[middle - 1] + sorted[middle]) / 2);
|
|
7237
|
+
}
|
|
7238
|
+
return sorted[middle];
|
|
7239
|
+
}
|
|
7240
|
+
function probeOnce(url, timeoutMs) {
|
|
7241
|
+
return new Promise((resolve6) => {
|
|
7242
|
+
const target = new URL(url);
|
|
7243
|
+
const requester = target.protocol === "http:" ? httpRequest : httpsRequest;
|
|
7244
|
+
const start = performance.now();
|
|
7245
|
+
let settled = false;
|
|
7246
|
+
const finish = (result) => {
|
|
7247
|
+
if (settled) return;
|
|
7248
|
+
settled = true;
|
|
7249
|
+
resolve6(result);
|
|
7250
|
+
};
|
|
7251
|
+
const req = requester(
|
|
7252
|
+
target,
|
|
7253
|
+
{
|
|
7254
|
+
method: "GET",
|
|
7255
|
+
headers: {
|
|
7256
|
+
Accept: "application/json",
|
|
7257
|
+
"Cache-Control": "no-cache",
|
|
7258
|
+
"User-Agent": "ccman-latency-probe/1.0"
|
|
7259
|
+
}
|
|
7260
|
+
},
|
|
7261
|
+
(response) => {
|
|
7262
|
+
const latencyMs = Math.max(1, Math.round(performance.now() - start));
|
|
7263
|
+
const statusCode = response.statusCode ?? null;
|
|
7264
|
+
response.destroy();
|
|
7265
|
+
finish({ latencyMs, statusCode });
|
|
7266
|
+
}
|
|
7267
|
+
);
|
|
7268
|
+
req.setTimeout(timeoutMs, () => {
|
|
7269
|
+
req.destroy(new Error(`\u6D4B\u901F\u8D85\u65F6\uFF08>${timeoutMs}ms\uFF09`));
|
|
7270
|
+
});
|
|
7271
|
+
req.on("error", (error) => {
|
|
7272
|
+
finish({
|
|
7273
|
+
latencyMs: null,
|
|
7274
|
+
statusCode: null,
|
|
7275
|
+
error: error.message
|
|
7276
|
+
});
|
|
7277
|
+
});
|
|
7278
|
+
req.end();
|
|
7279
|
+
});
|
|
7280
|
+
}
|
|
7281
|
+
async function probeCandidate(candidate, originalIndex, options) {
|
|
7282
|
+
const normalizedUrl = normalizeEndpointUrl(candidate.url);
|
|
7283
|
+
const normalizedProbeUrl = candidate.probeUrl ? normalizeEndpointUrl(candidate.probeUrl) : normalizedUrl;
|
|
7284
|
+
const samples = [];
|
|
7285
|
+
let statusCode = null;
|
|
7286
|
+
let lastError;
|
|
7287
|
+
for (let index = 0; index < options.sampleCount; index += 1) {
|
|
7288
|
+
const result = await probeOnce(normalizedProbeUrl, options.timeoutMs);
|
|
7289
|
+
if (result.latencyMs !== null) {
|
|
7290
|
+
samples.push(result.latencyMs);
|
|
7291
|
+
statusCode = result.statusCode;
|
|
7292
|
+
} else if (!lastError) {
|
|
7293
|
+
lastError = result.error;
|
|
7294
|
+
}
|
|
7295
|
+
}
|
|
7296
|
+
return {
|
|
7297
|
+
...candidate,
|
|
7298
|
+
url: normalizedUrl,
|
|
7299
|
+
probeUrl: normalizedProbeUrl,
|
|
7300
|
+
originalIndex,
|
|
7301
|
+
samples,
|
|
7302
|
+
statusCode,
|
|
7303
|
+
latencyMs: samples.length > 0 ? calculateMedian(samples) : null,
|
|
7304
|
+
error: samples.length > 0 ? void 0 : lastError || "\u6D4B\u901F\u5931\u8D25"
|
|
7305
|
+
};
|
|
7306
|
+
}
|
|
7307
|
+
async function probeEndpointCandidates(candidates, options = {}) {
|
|
7308
|
+
const resolvedOptions = {
|
|
7309
|
+
sampleCount: options.sampleCount ?? 3,
|
|
7310
|
+
timeoutMs: options.timeoutMs ?? 2500
|
|
7311
|
+
};
|
|
7312
|
+
return Promise.all(
|
|
7313
|
+
candidates.map((candidate, index) => probeCandidate(candidate, index, resolvedOptions))
|
|
7314
|
+
);
|
|
7315
|
+
}
|
|
7316
|
+
function sortEndpointProbeResults(results) {
|
|
7317
|
+
return [...results].sort((left, right) => {
|
|
7318
|
+
const leftReachable = left.latencyMs !== null;
|
|
7319
|
+
const rightReachable = right.latencyMs !== null;
|
|
7320
|
+
if (leftReachable && !rightReachable) return -1;
|
|
7321
|
+
if (!leftReachable && rightReachable) return 1;
|
|
7322
|
+
if (!leftReachable && !rightReachable) return left.originalIndex - right.originalIndex;
|
|
7323
|
+
if (left.latencyMs !== right.latencyMs) {
|
|
7324
|
+
return (left.latencyMs || 0) - (right.latencyMs || 0);
|
|
7325
|
+
}
|
|
7326
|
+
return left.originalIndex - right.originalIndex;
|
|
7327
|
+
});
|
|
7328
|
+
}
|
|
7329
|
+
function pickDefaultEndpoint(results) {
|
|
7330
|
+
return sortEndpointProbeResults(results)[0];
|
|
7331
|
+
}
|
|
7332
|
+
|
|
7333
|
+
// src/commands/gmn.ts
|
|
7154
7334
|
var DEFAULT_PROVIDER_NAME2 = "gmn";
|
|
7155
7335
|
var VALID_PLATFORMS = ["codex", "opencode", "openclaw"];
|
|
7156
7336
|
var DEFAULT_PLATFORMS = ["codex", "opencode"];
|
|
7157
|
-
var
|
|
7158
|
-
|
|
7159
|
-
|
|
7337
|
+
var GMN_BASE_URLS = [
|
|
7338
|
+
{
|
|
7339
|
+
label: "\u539F\u59CB\u5730\u5740",
|
|
7340
|
+
url: "https://gmn.chuangzuoli.com",
|
|
7341
|
+
description: "GMN \u539F\u59CB\u5165\u53E3"
|
|
7342
|
+
},
|
|
7343
|
+
{
|
|
7344
|
+
label: "\u65E7\u57DF\u540D CDN",
|
|
7345
|
+
url: "https://cdn.gmnchuangzuoli.com",
|
|
7346
|
+
description: "CDN \u56DE\u56FD\u52A0\u901F"
|
|
7347
|
+
},
|
|
7348
|
+
{
|
|
7349
|
+
label: "\u963F\u91CC\u4E91 CDN",
|
|
7350
|
+
url: "https://gmncodex.com",
|
|
7351
|
+
description: "\u963F\u91CC\u4E91\u89E3\u6790 CDN \u56DE\u56FD\u52A0\u901F"
|
|
7352
|
+
},
|
|
7353
|
+
{
|
|
7354
|
+
label: "\u5168\u7403\u8FB9\u7F18 A",
|
|
7355
|
+
url: "https://gmncode.cn",
|
|
7356
|
+
description: "\u5168\u7403\u8FB9\u7F18\u8282\u70B9\u52A0\u901F"
|
|
7357
|
+
},
|
|
7358
|
+
{
|
|
7359
|
+
label: "CF CDN A",
|
|
7360
|
+
url: "https://cdn.gmncode.cn",
|
|
7361
|
+
description: "CF \u89E3\u6790 CDN \u56DE\u56FD\u52A0\u901F"
|
|
7362
|
+
},
|
|
7363
|
+
{
|
|
7364
|
+
label: "\u5168\u7403\u8FB9\u7F18 B",
|
|
7365
|
+
url: "https://gmn.codex.com",
|
|
7366
|
+
description: "\u5168\u7403\u8FB9\u7F18\u8282\u70B9\u52A0\u901F"
|
|
7367
|
+
},
|
|
7368
|
+
{
|
|
7369
|
+
label: "CF CDN B",
|
|
7370
|
+
url: "https://cdn.gmncode.com",
|
|
7371
|
+
description: "CF \u89E3\u6790 CDN \u56DE\u56FD\u52A0\u901F"
|
|
7372
|
+
}
|
|
7373
|
+
];
|
|
7374
|
+
var GMN_PROFILE = {
|
|
7375
|
+
commandName: "gmn",
|
|
7376
|
+
title: "GMN",
|
|
7377
|
+
baseUrls: GMN_BASE_URLS
|
|
7378
|
+
};
|
|
7379
|
+
var GMN1_PROFILE = {
|
|
7380
|
+
commandName: "gmn1",
|
|
7381
|
+
title: "GMN1",
|
|
7382
|
+
baseUrls: [
|
|
7383
|
+
{
|
|
7384
|
+
label: "GMN1 \u9ED8\u8BA4\u7EBF\u8DEF",
|
|
7385
|
+
url: "https://gmncode.cn",
|
|
7386
|
+
description: "\u5168\u7403\u8FB9\u7F18\u8282\u70B9\u52A0\u901F"
|
|
7387
|
+
}
|
|
7388
|
+
]
|
|
7389
|
+
};
|
|
7390
|
+
var TOTAL_STEPS = 4;
|
|
7391
|
+
var BASE_URL_PROBE_SAMPLE_COUNT = 3;
|
|
7392
|
+
var BASE_URL_PROBE_TIMEOUT_MS = 2500;
|
|
7160
7393
|
function renderStep(current, total, title) {
|
|
7161
7394
|
const barLength = total;
|
|
7162
7395
|
const filledLength = Math.min(current, total);
|
|
7163
7396
|
const bar = `${"\u25A0".repeat(filledLength)}${"\u25A1".repeat(barLength - filledLength)}`;
|
|
7164
7397
|
return `\u6B65\u9AA4 ${current}/${total} [${bar}] ${title}`;
|
|
7165
7398
|
}
|
|
7166
|
-
function printBanner() {
|
|
7399
|
+
function printBanner(title) {
|
|
7167
7400
|
printLogo();
|
|
7168
7401
|
console.log(
|
|
7169
7402
|
chalk54.cyanBright(
|
|
@@ -7174,7 +7407,7 @@ function printBanner() {
|
|
|
7174
7407
|
" \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551",
|
|
7175
7408
|
" \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551",
|
|
7176
7409
|
" \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D",
|
|
7177
|
-
|
|
7410
|
+
` CCMAN ${title} \u4E00\u952E\u914D\u7F6E\u5411\u5BFC`
|
|
7178
7411
|
].join("\n")
|
|
7179
7412
|
)
|
|
7180
7413
|
);
|
|
@@ -7225,12 +7458,12 @@ function parsePlatforms(platformArg) {
|
|
|
7225
7458
|
}
|
|
7226
7459
|
return platforms;
|
|
7227
7460
|
}
|
|
7228
|
-
async function promptApiKey() {
|
|
7461
|
+
async function promptApiKey(title) {
|
|
7229
7462
|
const answers = await inquirer38.prompt([
|
|
7230
7463
|
{
|
|
7231
7464
|
type: "password",
|
|
7232
7465
|
name: "apiKey",
|
|
7233
|
-
message:
|
|
7466
|
+
message: `\u8BF7\u8F93\u5165 ${title} API Key:`,
|
|
7234
7467
|
mask: "*",
|
|
7235
7468
|
validate: (value) => {
|
|
7236
7469
|
if (!value?.trim()) return "API Key \u4E0D\u80FD\u4E3A\u7A7A";
|
|
@@ -7240,7 +7473,7 @@ async function promptApiKey() {
|
|
|
7240
7473
|
]);
|
|
7241
7474
|
return answers.apiKey.trim();
|
|
7242
7475
|
}
|
|
7243
|
-
async function promptPlatforms() {
|
|
7476
|
+
async function promptPlatforms(title) {
|
|
7244
7477
|
const answers = await inquirer38.prompt([
|
|
7245
7478
|
{
|
|
7246
7479
|
type: "checkbox",
|
|
@@ -7250,7 +7483,7 @@ async function promptPlatforms() {
|
|
|
7250
7483
|
choices: [
|
|
7251
7484
|
{ name: "Codex\uFF08\u9700\u5355\u72EC\u8BA2\u9605 OpenAI \u5957\u9910\uFF09", value: "codex" },
|
|
7252
7485
|
{ name: "OpenCode\uFF08\u4E0E Codex \u5171\u4EAB OpenAI \u5957\u9910\uFF09", value: "opencode" },
|
|
7253
|
-
{ name:
|
|
7486
|
+
{ name: `OpenClaw\uFF08${title} /v1 \u7AEF\u70B9\uFF0C\u9ED8\u8BA4\u4E0D\u9009\u4E2D\uFF09`, value: "openclaw" },
|
|
7254
7487
|
{ name: "\u5168\u90E8\uFF08\u5C06\u4F9D\u6B21\u914D\u7F6E Codex\u3001OpenCode\u3001OpenClaw\uFF09", value: "all" }
|
|
7255
7488
|
],
|
|
7256
7489
|
default: DEFAULT_PLATFORMS,
|
|
@@ -7266,11 +7499,83 @@ async function promptPlatforms() {
|
|
|
7266
7499
|
}
|
|
7267
7500
|
return selected;
|
|
7268
7501
|
}
|
|
7269
|
-
async function resolvePlatforms(platformArg) {
|
|
7502
|
+
async function resolvePlatforms(platformArg, title = "GMN") {
|
|
7270
7503
|
if (platformArg && platformArg.trim().length > 0) {
|
|
7271
7504
|
return parsePlatforms(platformArg);
|
|
7272
7505
|
}
|
|
7273
|
-
return promptPlatforms();
|
|
7506
|
+
return promptPlatforms(title);
|
|
7507
|
+
}
|
|
7508
|
+
function formatLatency(result) {
|
|
7509
|
+
if (result.latencyMs === null) {
|
|
7510
|
+
return result.error || "\u6D4B\u901F\u5931\u8D25";
|
|
7511
|
+
}
|
|
7512
|
+
return `${result.latencyMs} ms`;
|
|
7513
|
+
}
|
|
7514
|
+
function buildProbeCandidates(baseUrls, platforms) {
|
|
7515
|
+
const openClawOnly = platforms.length === 1 && platforms[0] === "openclaw";
|
|
7516
|
+
return baseUrls.map((item) => ({
|
|
7517
|
+
...item,
|
|
7518
|
+
probeUrl: openClawOnly ? buildOpenClawBaseUrl(item.url) : item.url
|
|
7519
|
+
}));
|
|
7520
|
+
}
|
|
7521
|
+
function printBaseUrlProbeResults(results, platforms) {
|
|
7522
|
+
const usingOpenClawPath = platforms.length === 1 && platforms[0] === "openclaw";
|
|
7523
|
+
console.log(
|
|
7524
|
+
chalk54.gray(
|
|
7525
|
+
`\u6D4B\u901F\u65B9\u5F0F\uFF1AHTTPS \u9996\u5305\u5EF6\u8FDF\uFF08${BASE_URL_PROBE_SAMPLE_COUNT} \u6B21\u4E2D\u4F4D\u6570\uFF09${usingOpenClawPath ? "\uFF0C\u5F53\u524D\u4EC5\u68C0\u6D4B OpenClaw \u7684 /v1 \u7AEF\u70B9" : ""}`
|
|
7526
|
+
)
|
|
7527
|
+
);
|
|
7528
|
+
for (const result of results) {
|
|
7529
|
+
const latencyText = result.latencyMs === null ? chalk54.red(formatLatency(result)) : chalk54.green(formatLatency(result));
|
|
7530
|
+
console.log(` ${chalk54.cyan(result.label)} \xB7 ${latencyText}`);
|
|
7531
|
+
console.log(chalk54.gray(` ${result.url}`));
|
|
7532
|
+
console.log(chalk54.gray(` ${result.description}`));
|
|
7533
|
+
}
|
|
7534
|
+
}
|
|
7535
|
+
async function resolveOpenAiBaseUrl(profile, platforms, baseUrlArg) {
|
|
7536
|
+
if (baseUrlArg && baseUrlArg.trim().length > 0) {
|
|
7537
|
+
const normalized = normalizeEndpointUrl(baseUrlArg);
|
|
7538
|
+
console.log(chalk54.gray(`\u5DF2\u901A\u8FC7\u53C2\u6570\u6307\u5B9A Base URL: ${normalized}`));
|
|
7539
|
+
return normalized;
|
|
7540
|
+
}
|
|
7541
|
+
const probeResults = sortEndpointProbeResults(
|
|
7542
|
+
await probeEndpointCandidates(buildProbeCandidates(profile.baseUrls, platforms), {
|
|
7543
|
+
sampleCount: BASE_URL_PROBE_SAMPLE_COUNT,
|
|
7544
|
+
timeoutMs: BASE_URL_PROBE_TIMEOUT_MS
|
|
7545
|
+
})
|
|
7546
|
+
);
|
|
7547
|
+
if (probeResults.length === 0) {
|
|
7548
|
+
throw new Error("\u6CA1\u6709\u53EF\u7528\u7684 Base URL \u5019\u9009\u9879");
|
|
7549
|
+
}
|
|
7550
|
+
printBaseUrlProbeResults(probeResults, platforms);
|
|
7551
|
+
const defaultResult = pickDefaultEndpoint(probeResults) || probeResults[0];
|
|
7552
|
+
const allFailed = probeResults.every((result) => result.latencyMs === null);
|
|
7553
|
+
if (allFailed) {
|
|
7554
|
+
console.log(chalk54.yellow("\u26A0\uFE0F \u6240\u6709\u5019\u9009\u5730\u5740\u6D4B\u901F\u5931\u8D25\uFF0C\u5C06\u9ED8\u8BA4\u9009\u4E2D\u7B2C\u4E00\u4E2A\u5730\u5740\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u624B\u52A8\u5207\u6362\u3002"));
|
|
7555
|
+
} else {
|
|
7556
|
+
console.log(chalk54.gray(`\u9ED8\u8BA4\u5DF2\u9009\u5EF6\u8FDF\u6700\u4F4E\u5730\u5740\uFF1A${defaultResult.url}`));
|
|
7557
|
+
}
|
|
7558
|
+
if (probeResults.length === 1) {
|
|
7559
|
+
console.log(chalk54.green(`\u5DF2\u81EA\u52A8\u9009\u62E9: ${defaultResult.url}`));
|
|
7560
|
+
return defaultResult.url;
|
|
7561
|
+
}
|
|
7562
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
7563
|
+
console.log(chalk54.yellow(`\u975E\u4EA4\u4E92\u73AF\u5883\uFF0C\u5DF2\u81EA\u52A8\u4F7F\u7528\u9ED8\u8BA4\u5730\u5740\uFF1A${defaultResult.url}`));
|
|
7564
|
+
return defaultResult.url;
|
|
7565
|
+
}
|
|
7566
|
+
const answers = await inquirer38.prompt([
|
|
7567
|
+
{
|
|
7568
|
+
type: "list",
|
|
7569
|
+
name: "baseUrl",
|
|
7570
|
+
message: "\u9009\u62E9\u8981\u4F7F\u7528\u7684 Base URL\uFF08\u9ED8\u8BA4\u5DF2\u9009\u5EF6\u8FDF\u6700\u4F4E\uFF09:",
|
|
7571
|
+
choices: probeResults.map((result) => ({
|
|
7572
|
+
name: `${result.label} \xB7 ${result.url} \xB7 ${formatLatency(result)} \xB7 ${result.description}`,
|
|
7573
|
+
value: result.url
|
|
7574
|
+
})),
|
|
7575
|
+
default: defaultResult.url
|
|
7576
|
+
}
|
|
7577
|
+
]);
|
|
7578
|
+
return answers.baseUrl;
|
|
7274
7579
|
}
|
|
7275
7580
|
function resolveProviderName2(providerNameArg) {
|
|
7276
7581
|
if (providerNameArg === void 0) {
|
|
@@ -7357,14 +7662,18 @@ function rollbackFromBackupOrThrow(result) {
|
|
|
7357
7662
|
throw new Error(`\u56DE\u6EDA\u5931\u8D25: ${errors.join("; ")}`);
|
|
7358
7663
|
}
|
|
7359
7664
|
}
|
|
7360
|
-
|
|
7361
|
-
|
|
7665
|
+
function buildOpenClawBaseUrl(openaiBaseUrl) {
|
|
7666
|
+
const normalized = openaiBaseUrl.replace(/\/+$/, "");
|
|
7667
|
+
return `${normalized}/v1`;
|
|
7668
|
+
}
|
|
7669
|
+
async function runGmnCommand(profile, apiKey, platformArg, providerNameArg, baseUrlArg) {
|
|
7670
|
+
printBanner(profile.title);
|
|
7362
7671
|
let platforms;
|
|
7363
7672
|
let providerName;
|
|
7364
7673
|
try {
|
|
7365
7674
|
console.log(chalk54.cyan(`
|
|
7366
7675
|
${renderStep(1, TOTAL_STEPS, "\u9009\u62E9\u8981\u914D\u7F6E\u7684\u5DE5\u5177")}`));
|
|
7367
|
-
platforms = await resolvePlatforms(platformArg);
|
|
7676
|
+
platforms = await resolvePlatforms(platformArg, profile.title);
|
|
7368
7677
|
providerName = resolveProviderName2(providerNameArg);
|
|
7369
7678
|
} catch (error) {
|
|
7370
7679
|
console.error(chalk54.red(`\u274C ${error.message}`));
|
|
@@ -7373,11 +7682,26 @@ ${renderStep(1, TOTAL_STEPS, "\u9009\u62E9\u8981\u914D\u7F6E\u7684\u5DE5\u5177")
|
|
|
7373
7682
|
console.log(chalk54.gray(`\u5DF2\u9009\u62E9: ${platforms.join(", ")}`));
|
|
7374
7683
|
console.log(chalk54.gray(`\u670D\u52A1\u5546\u540D\u79F0: ${providerName}`));
|
|
7375
7684
|
printKeyNotice();
|
|
7685
|
+
console.log(chalk54.cyan(`
|
|
7686
|
+
${renderStep(2, TOTAL_STEPS, "\u6D4B\u901F\u5E76\u9009\u62E9 Base URL")}`));
|
|
7687
|
+
let openaiBaseUrl;
|
|
7688
|
+
try {
|
|
7689
|
+
openaiBaseUrl = await resolveOpenAiBaseUrl(profile, platforms, baseUrlArg);
|
|
7690
|
+
} catch (error) {
|
|
7691
|
+
console.error(chalk54.red(`\u274C ${error.message}`));
|
|
7692
|
+
process.exit(1);
|
|
7693
|
+
}
|
|
7694
|
+
const openclawBaseUrl = buildOpenClawBaseUrl(openaiBaseUrl);
|
|
7695
|
+
const platformBaseUrls = {
|
|
7696
|
+
codex: openaiBaseUrl,
|
|
7697
|
+
opencode: openaiBaseUrl,
|
|
7698
|
+
openclaw: openclawBaseUrl
|
|
7699
|
+
};
|
|
7376
7700
|
let resolvedApiKey = apiKey?.trim();
|
|
7377
7701
|
console.log(chalk54.cyan(`
|
|
7378
|
-
${renderStep(
|
|
7702
|
+
${renderStep(3, TOTAL_STEPS, "\u8F93\u5165 API Key")}`));
|
|
7379
7703
|
if (!resolvedApiKey) {
|
|
7380
|
-
resolvedApiKey = await promptApiKey();
|
|
7704
|
+
resolvedApiKey = await promptApiKey(profile.title);
|
|
7381
7705
|
} else {
|
|
7382
7706
|
console.log(chalk54.gray("\u5DF2\u901A\u8FC7\u53C2\u6570\u63D0\u4F9B API Key\uFF08\u5DF2\u9690\u85CF\uFF09"));
|
|
7383
7707
|
}
|
|
@@ -7385,27 +7709,19 @@ ${renderStep(2, TOTAL_STEPS, "\u8F93\u5165 API Key")}`));
|
|
|
7385
7709
|
console.error(chalk54.red("\u274C \u9519\u8BEF: API Key \u4E0D\u80FD\u4E3A\u7A7A"));
|
|
7386
7710
|
process.exit(1);
|
|
7387
7711
|
}
|
|
7388
|
-
const openaiBaseUrl = GMN_OPENAI_BASE_URL;
|
|
7389
|
-
const platformBaseUrls = {
|
|
7390
|
-
codex: openaiBaseUrl,
|
|
7391
|
-
opencode: openaiBaseUrl,
|
|
7392
|
-
openclaw: GMN_OPENCLAW_BASE_URL
|
|
7393
|
-
};
|
|
7394
7712
|
console.log(chalk54.cyan(`
|
|
7395
|
-
${renderStep(
|
|
7713
|
+
${renderStep(4, TOTAL_STEPS, "\u5F00\u59CB\u5199\u5165\u914D\u7F6E")}`));
|
|
7396
7714
|
console.log(chalk54.gray(`\u5DF2\u9009\u62E9\u5E73\u53F0: ${platforms.join(", ")}`));
|
|
7397
|
-
|
|
7398
|
-
console.log(chalk54.gray(`OpenAI Base URL: ${openaiBaseUrl}`));
|
|
7399
|
-
}
|
|
7715
|
+
console.log(chalk54.gray(`OpenAI Base URL: ${openaiBaseUrl}`));
|
|
7400
7716
|
if (platforms.includes("openclaw")) {
|
|
7401
|
-
console.log(chalk54.gray(`OpenClaw Base URL: ${
|
|
7717
|
+
console.log(chalk54.gray(`OpenClaw Base URL: ${openclawBaseUrl}`));
|
|
7402
7718
|
}
|
|
7403
7719
|
printWriteTargets(platforms);
|
|
7404
7720
|
console.log();
|
|
7405
7721
|
const backupRootDir = path15.join(
|
|
7406
7722
|
getCcmanDir(),
|
|
7407
7723
|
"backups",
|
|
7408
|
-
|
|
7724
|
+
`${profile.commandName}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
|
7409
7725
|
);
|
|
7410
7726
|
fs13.mkdirSync(backupRootDir, { recursive: true, mode: 448 });
|
|
7411
7727
|
console.log(chalk54.gray(`\u5907\u4EFD\u6839\u76EE\u5F55: ${backupRootDir}`));
|
|
@@ -7434,8 +7750,12 @@ ${renderStep(3, TOTAL_STEPS, "\u5F00\u59CB\u5199\u5165\u914D\u7F6E")}`));
|
|
|
7434
7750
|
}
|
|
7435
7751
|
const baseUrl = platformBaseUrls[platform];
|
|
7436
7752
|
const existing = findPreferredProvider(manager.list(), providerName);
|
|
7437
|
-
const provider = existing ? manager.edit(
|
|
7438
|
-
|
|
7753
|
+
const provider = existing ? manager.edit(
|
|
7754
|
+
existing.id,
|
|
7755
|
+
{ name: providerName, baseUrl, apiKey: resolvedApiKey },
|
|
7756
|
+
{ applyWrite: false }
|
|
7757
|
+
) : manager.add({ name: providerName, baseUrl, apiKey: resolvedApiKey });
|
|
7758
|
+
manager.switch(provider.id, { mode: "overwrite" });
|
|
7439
7759
|
completed += 1;
|
|
7440
7760
|
console.log(chalk54.green(`\u2705 ${name}`));
|
|
7441
7761
|
successBackups.push({
|
|
@@ -7462,7 +7782,7 @@ ${renderStep(3, TOTAL_STEPS, "\u5F00\u59CB\u5199\u5165\u914D\u7F6E")}`));
|
|
|
7462
7782
|
}
|
|
7463
7783
|
}
|
|
7464
7784
|
console.log(chalk54.green(`
|
|
7465
|
-
\u{1F389}
|
|
7785
|
+
\u{1F389} ${profile.title} \u914D\u7F6E\u5B8C\u6210\uFF01(${completed}/${tools.length})`));
|
|
7466
7786
|
console.log();
|
|
7467
7787
|
console.log(chalk54.bold("\u5907\u4EFD\u4FE1\u606F:"));
|
|
7468
7788
|
if (successBackups.length === 0) {
|
|
@@ -7481,6 +7801,12 @@ ${renderStep(3, TOTAL_STEPS, "\u5F00\u59CB\u5199\u5165\u914D\u7F6E")}`));
|
|
|
7481
7801
|
}
|
|
7482
7802
|
console.log(chalk54.gray("\u63D0\u793A\uFF1A\u8BF7\u91CD\u542F\u5BF9\u5E94\u5DE5\u5177/\u63D2\u4EF6\u4EE5\u4F7F\u914D\u7F6E\u751F\u6548\u3002"));
|
|
7483
7803
|
}
|
|
7804
|
+
async function gmnCommand(apiKey, platformArg, providerNameArg, baseUrlArg) {
|
|
7805
|
+
await runGmnCommand(GMN_PROFILE, apiKey, platformArg, providerNameArg, baseUrlArg);
|
|
7806
|
+
}
|
|
7807
|
+
async function gmn1Command(apiKey, platformArg, providerNameArg, baseUrlArg) {
|
|
7808
|
+
await runGmnCommand(GMN1_PROFILE, apiKey, platformArg, providerNameArg, baseUrlArg);
|
|
7809
|
+
}
|
|
7484
7810
|
|
|
7485
7811
|
// src/index.ts
|
|
7486
7812
|
init_dist2();
|
|
@@ -7516,7 +7842,9 @@ program.on("command:*", (operands) => {
|
|
|
7516
7842
|
"sync",
|
|
7517
7843
|
"export",
|
|
7518
7844
|
"import",
|
|
7519
|
-
"gmn"
|
|
7845
|
+
"gmn",
|
|
7846
|
+
"gmn1",
|
|
7847
|
+
"gmncode"
|
|
7520
7848
|
];
|
|
7521
7849
|
const suggestions = availableCommands.filter(
|
|
7522
7850
|
(cmd) => cmd.includes(unknownCommand) || unknownCommand.includes(cmd)
|
|
@@ -7575,8 +7903,11 @@ sync.action(async () => {
|
|
|
7575
7903
|
});
|
|
7576
7904
|
exportCommand(program);
|
|
7577
7905
|
importCommand(program);
|
|
7578
|
-
program.command("gmn [apiKey]").description("\u914D\u7F6E GMN \u5230 Codex\u3001OpenCode\u3001OpenClaw").option("-p, --platform <platforms>", "\u6307\u5B9A\u5E73\u53F0 (codex,opencode,openclaw,all)").option("-n, --name <providerName>", "\u6307\u5B9A\u670D\u52A1\u5546\u540D\u79F0\uFF08\u9ED8\u8BA4: gmn\uFF09").action(async (apiKey, options) => {
|
|
7579
|
-
await gmnCommand(apiKey, options.platform, options.name);
|
|
7906
|
+
program.command("gmn [apiKey]").description("\u914D\u7F6E GMN \u5230 Codex\u3001OpenCode\u3001OpenClaw\uFF08\u81EA\u52A8\u6D4B\u901F\u5E76\u9ED8\u8BA4\u9009\u62E9\u6700\u4F4E\u5EF6\u8FDF\u7EBF\u8DEF\uFF09").option("-p, --platform <platforms>", "\u6307\u5B9A\u5E73\u53F0 (codex,opencode,openclaw,all)").option("-n, --name <providerName>", "\u6307\u5B9A\u670D\u52A1\u5546\u540D\u79F0\uFF08\u9ED8\u8BA4: gmn\uFF09").option("-b, --base-url <baseUrl>", "\u6307\u5B9A Base URL\uFF1B\u4E0D\u6307\u5B9A\u65F6\u81EA\u52A8\u6D4B\u901F\u5E76\u53EF\u624B\u52A8\u5207\u6362").action(async (apiKey, options) => {
|
|
7907
|
+
await gmnCommand(apiKey, options.platform, options.name, options.baseUrl);
|
|
7908
|
+
});
|
|
7909
|
+
program.command("gmn1 [apiKey]").alias("gmncode").description("\u914D\u7F6E GMN1 \u5230 Codex\u3001OpenCode\u3001OpenClaw\uFF08\u9ED8\u8BA4 URL: https://gmncode.cn\uFF09").option("-p, --platform <platforms>", "\u6307\u5B9A\u5E73\u53F0 (codex,opencode,openclaw,all)").option("-n, --name <providerName>", "\u6307\u5B9A\u670D\u52A1\u5546\u540D\u79F0\uFF08\u9ED8\u8BA4: gmn\uFF09").option("-b, --base-url <baseUrl>", "\u6307\u5B9A Base URL\uFF1B\u4E0D\u6307\u5B9A\u65F6\u81EA\u52A8\u6D4B\u901F\u5E76\u53EF\u624B\u52A8\u5207\u6362").action(async (apiKey, options) => {
|
|
7910
|
+
await gmn1Command(apiKey, options.platform, options.name, options.baseUrl);
|
|
7580
7911
|
});
|
|
7581
7912
|
(async () => {
|
|
7582
7913
|
if (!process.argv.slice(2).length) {
|