ccman 3.3.3 → 3.3.5

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/index.js CHANGED
@@ -15,7 +15,7 @@ var init_package = __esm({
15
15
  "../core/package.json"() {
16
16
  package_default = {
17
17
  name: "@ccman/core",
18
- version: "3.3.3",
18
+ version: "3.3.5",
19
19
  type: "module",
20
20
  description: "Core business logic for ccman - Manage Codex, Claude Code, Gemini CLI, and MCP configurations",
21
21
  main: "./dist/index.js",
@@ -269,10 +269,25 @@ import * as fs2 from "fs";
269
269
  import * as path3 from "path";
270
270
  import { fileURLToPath } from "url";
271
271
  import { parse as parseToml, stringify as stringifyToml } from "@iarna/toml";
272
+ function resolveTemplatePath(relativePath) {
273
+ const candidates = [
274
+ // @ccman/core runtime (dist/writers -> templates)
275
+ path3.resolve(__dirname, "../../templates", relativePath),
276
+ // Bundled CLI runtime (dist -> dist/templates)
277
+ path3.resolve(__dirname, "templates", relativePath),
278
+ // Fallback (some bundlers/layouts)
279
+ path3.resolve(__dirname, "../templates", relativePath)
280
+ ];
281
+ for (const candidate of candidates) {
282
+ if (fs2.existsSync(candidate))
283
+ return candidate;
284
+ }
285
+ return null;
286
+ }
272
287
  function loadCodexTemplateConfig() {
273
288
  try {
274
- const templatePath = path3.resolve(__dirname, "../../templates/codex/config.toml");
275
- if (fs2.existsSync(templatePath)) {
289
+ const templatePath = resolveTemplatePath("codex/config.toml");
290
+ if (templatePath) {
276
291
  const content = fs2.readFileSync(templatePath, "utf-8");
277
292
  return parseToml(content);
278
293
  }
@@ -321,10 +336,10 @@ var init_codex = __esm({
321
336
  __filename = fileURLToPath(import.meta.url);
322
337
  __dirname = path3.dirname(__filename);
323
338
  CODEX_DEFAULT_CONFIG = {
324
- model: "gpt-5.1",
339
+ model: "gpt-5.1-code-max",
325
340
  model_reasoning_effort: "high",
326
341
  disable_response_storage: true,
327
- sandbox_mode: "workspace-write",
342
+ sandbox_mode: "danger-full-access",
328
343
  windows_wsl_setup_acknowledged: true,
329
344
  approval_policy: "never",
330
345
  profile: "auto-max",
@@ -356,7 +371,7 @@ var init_codex = __esm({
356
371
  approval_policy: "never",
357
372
  sandbox_mode: "workspace-write"
358
373
  },
359
- "review": {
374
+ review: {
360
375
  approval_policy: "on-request",
361
376
  sandbox_mode: "workspace-write"
362
377
  }
@@ -372,10 +387,25 @@ var init_codex = __esm({
372
387
  import * as fs3 from "fs";
373
388
  import * as path4 from "path";
374
389
  import { fileURLToPath as fileURLToPath2 } from "url";
390
+ function resolveTemplatePath2(relativePath) {
391
+ const candidates = [
392
+ // @ccman/core runtime (dist/writers -> templates)
393
+ path4.resolve(__dirname2, "../../templates", relativePath),
394
+ // Bundled CLI runtime (dist -> dist/templates)
395
+ path4.resolve(__dirname2, "templates", relativePath),
396
+ // Fallback (some bundlers/layouts)
397
+ path4.resolve(__dirname2, "../templates", relativePath)
398
+ ];
399
+ for (const candidate of candidates) {
400
+ if (fs3.existsSync(candidate))
401
+ return candidate;
402
+ }
403
+ return null;
404
+ }
375
405
  function loadClaudeTemplateConfig() {
376
406
  try {
377
- const templatePath = path4.resolve(__dirname2, "../../templates/claude/settings.json");
378
- if (fs3.existsSync(templatePath)) {
407
+ const templatePath = resolveTemplatePath2("claude/settings.json");
408
+ if (templatePath) {
379
409
  const content = fs3.readFileSync(templatePath, "utf-8");
380
410
  return JSON.parse(content);
381
411
  }
@@ -421,7 +451,8 @@ var init_claude = __esm({
421
451
  permissions: {
422
452
  allow: [],
423
453
  deny: []
424
- }
454
+ },
455
+ alwaysThinkingEnabled: true
425
456
  };
426
457
  }
427
458
  });
@@ -733,7 +764,7 @@ var init_opencode = __esm({
733
764
  },
734
765
  {
735
766
  name: "GMN (COM)",
736
- baseUrl: "https://gmn.chuangzuoli.com",
767
+ baseUrl: "https://gmn.chuangzuoli.com/v1",
737
768
  description: "GMN \u670D\u52A1 (OpenCode \u517C\u5BB9)"
738
769
  }
739
770
  ];
@@ -857,6 +888,38 @@ var init_gemini2 = __esm({
857
888
  });
858
889
 
859
890
  // ../core/dist/writers/opencode.js
891
+ import * as fs6 from "fs";
892
+ import * as path6 from "path";
893
+ import { fileURLToPath as fileURLToPath3 } from "url";
894
+ function resolveTemplatePath3(relativePath) {
895
+ const candidates = [
896
+ // @ccman/core runtime (dist/writers -> templates)
897
+ path6.resolve(__dirname3, "../../templates", relativePath),
898
+ // Bundled CLI runtime (dist -> dist/templates)
899
+ path6.resolve(__dirname3, "templates", relativePath),
900
+ // Fallback (some bundlers/layouts)
901
+ path6.resolve(__dirname3, "../templates", relativePath)
902
+ ];
903
+ for (const candidate of candidates) {
904
+ if (fs6.existsSync(candidate))
905
+ return candidate;
906
+ }
907
+ return null;
908
+ }
909
+ function loadOpenCodeTemplateConfig() {
910
+ try {
911
+ const templatePath = resolveTemplatePath3("opencode/opencode.json");
912
+ if (templatePath) {
913
+ const content = fs6.readFileSync(templatePath, "utf-8");
914
+ const parsed = JSON.parse(content);
915
+ if (parsed && typeof parsed === "object") {
916
+ return parsed;
917
+ }
918
+ }
919
+ } catch {
920
+ }
921
+ return OPENCODE_CONFIG_TEMPLATE;
922
+ }
860
923
  function parseProviderMeta(raw) {
861
924
  if (!raw || !raw.trim())
862
925
  return null;
@@ -870,76 +933,124 @@ function parseProviderMeta(raw) {
870
933
  }
871
934
  return null;
872
935
  }
873
- function toProviderKey(name) {
874
- const normalized = name.trim().toLowerCase();
875
- const collapsed = normalized.replace(/\s+/g, "-");
876
- const cleaned = collapsed.replace(/[^a-z0-9-_]/g, "");
877
- return cleaned || "provider";
936
+ function enforceAgentStoreFalse(agent) {
937
+ const base = agent && typeof agent === "object" && !Array.isArray(agent) ? agent : {};
938
+ return deepMerge(base, {
939
+ build: {
940
+ options: {
941
+ store: false
942
+ }
943
+ },
944
+ plan: {
945
+ options: {
946
+ store: false
947
+ }
948
+ }
949
+ });
950
+ }
951
+ function enforceModelStoreFalse(models) {
952
+ const base = models && typeof models === "object" && !Array.isArray(models) ? models : {};
953
+ return deepMerge(base, {
954
+ [OPENCODE_MODEL_KEY]: {
955
+ options: {
956
+ store: false
957
+ },
958
+ variants: {
959
+ low: {},
960
+ medium: {},
961
+ high: {},
962
+ xhigh: {}
963
+ }
964
+ }
965
+ });
878
966
  }
879
967
  function writeOpenCodeConfig(provider) {
880
968
  ensureDir(getOpenCodeDir());
881
969
  const configPath = getOpenCodeConfigPath();
882
970
  const existingConfig = fileExists(configPath) ? readJSON(configPath) : {};
883
971
  const meta = parseProviderMeta(provider.model);
884
- const npmPackage = meta?.npm || DEFAULT_NPM_PACKAGE;
885
- const providerKey = toProviderKey(provider.name);
886
- const existingProvider = existingConfig.provider?.[providerKey];
887
- const models = meta?.models || existingProvider?.models || DEFAULT_MODELS;
888
- const providerConfig = {
889
- ...existingProvider,
890
- npm: npmPackage,
891
- name: provider.name,
972
+ const template = loadOpenCodeTemplateConfig();
973
+ const defaultConfig = replaceVariables(template, {
974
+ baseUrl: provider.baseUrl,
975
+ apiKey: provider.apiKey
976
+ });
977
+ const mergedConfig = deepMerge(defaultConfig, existingConfig);
978
+ const templateProvider = defaultConfig.provider?.[OPENCODE_PROVIDER_KEY];
979
+ const existingProvider = mergedConfig.provider?.[OPENCODE_PROVIDER_KEY];
980
+ const models = enforceModelStoreFalse(meta?.models || existingProvider?.models || templateProvider?.models || DEFAULT_MODELS);
981
+ const providerConfig = deepMerge(templateProvider || {}, {
982
+ ...existingProvider || {},
892
983
  options: {
893
984
  ...existingProvider?.options || {},
894
985
  baseURL: provider.baseUrl,
895
986
  apiKey: provider.apiKey
896
987
  },
897
988
  models
898
- };
899
- const existingProviders = existingConfig.provider && typeof existingConfig.provider === "object" ? { ...existingConfig.provider } : {};
989
+ });
990
+ const existingProviders = mergedConfig.provider && typeof mergedConfig.provider === "object" && !Array.isArray(mergedConfig.provider) ? { ...mergedConfig.provider } : {};
900
991
  const nextConfig = {
901
- ...existingConfig,
992
+ ...mergedConfig,
902
993
  $schema: OPENCODE_SCHEMA,
994
+ model: OPENCODE_MODEL,
995
+ agent: enforceAgentStoreFalse(mergedConfig.agent),
903
996
  provider: {
904
997
  ...existingProviders,
905
- [providerKey]: providerConfig
998
+ [OPENCODE_PROVIDER_KEY]: providerConfig
906
999
  }
907
1000
  };
908
1001
  writeJSON(configPath, nextConfig);
909
1002
  }
910
- var OPENCODE_SCHEMA, DEFAULT_NPM_PACKAGE, DEFAULT_MODELS;
1003
+ var OPENCODE_SCHEMA, OPENCODE_PROVIDER_KEY, OPENCODE_MODEL, OPENCODE_MODEL_KEY, __filename3, __dirname3, DEFAULT_MODELS, OPENCODE_CONFIG_TEMPLATE;
911
1004
  var init_opencode2 = __esm({
912
1005
  "../core/dist/writers/opencode.js"() {
913
1006
  "use strict";
914
1007
  init_paths();
915
1008
  init_file();
1009
+ init_template();
916
1010
  OPENCODE_SCHEMA = "https://opencode.ai/config.json";
917
- DEFAULT_NPM_PACKAGE = "@ai-sdk/openai";
1011
+ OPENCODE_PROVIDER_KEY = "openai";
1012
+ OPENCODE_MODEL = "openai/gpt-5.2-codex";
1013
+ OPENCODE_MODEL_KEY = "gpt-5.2-codex";
1014
+ __filename3 = fileURLToPath3(import.meta.url);
1015
+ __dirname3 = path6.dirname(__filename3);
918
1016
  DEFAULT_MODELS = {
919
- "gpt-5.2-codex": {
1017
+ [OPENCODE_MODEL_KEY]: {
1018
+ name: "GPT-5.2 Codex",
1019
+ options: {
1020
+ store: false
1021
+ },
920
1022
  variants: {
921
- xhigh: {
922
- reasoningEffort: "xhigh",
923
- textVerbosity: "low",
924
- reasoningSummary: "auto"
925
- },
926
- high: {
927
- reasoningEffort: "high",
928
- textVerbosity: "low",
929
- reasoningSummary: "auto"
930
- },
931
- medium: {
932
- reasoningEffort: "medium",
933
- textVerbosity: "low",
934
- reasoningSummary: "auto"
1023
+ low: {},
1024
+ medium: {},
1025
+ high: {},
1026
+ xhigh: {}
1027
+ }
1028
+ }
1029
+ };
1030
+ OPENCODE_CONFIG_TEMPLATE = {
1031
+ provider: {
1032
+ [OPENCODE_PROVIDER_KEY]: {
1033
+ options: {
1034
+ baseURL: "{{baseUrl}}",
1035
+ apiKey: "{{apiKey}}"
935
1036
  },
936
- low: {
937
- reasoningEffort: "low",
938
- textVerbosity: "low",
939
- reasoningSummary: "auto"
1037
+ models: DEFAULT_MODELS
1038
+ }
1039
+ },
1040
+ agent: {
1041
+ build: {
1042
+ options: {
1043
+ store: false
1044
+ }
1045
+ },
1046
+ plan: {
1047
+ options: {
1048
+ store: false
940
1049
  }
941
1050
  }
942
- }
1051
+ },
1052
+ $schema: OPENCODE_SCHEMA,
1053
+ model: OPENCODE_MODEL
943
1054
  };
944
1055
  }
945
1056
  });
@@ -971,7 +1082,7 @@ var init_tool_manager_types = __esm({
971
1082
  });
972
1083
 
973
1084
  // ../core/dist/tool-manager.js
974
- import * as path6 from "path";
1085
+ import * as path7 from "path";
975
1086
  function createToolManager(tool) {
976
1087
  const toolConfig = TOOL_CONFIGS[tool];
977
1088
  const configPath = toolConfig.configPath;
@@ -1245,17 +1356,17 @@ var init_tool_manager = __esm({
1245
1356
  init_tool_manager_types();
1246
1357
  TOOL_CONFIGS = {
1247
1358
  codex: {
1248
- configPath: path6.join(getCcmanDir(), "codex.json"),
1359
+ configPath: path7.join(getCcmanDir(), "codex.json"),
1249
1360
  builtinPresets: CODEX_PRESETS,
1250
1361
  writer: writeCodexConfig
1251
1362
  },
1252
1363
  claude: {
1253
- configPath: path6.join(getCcmanDir(), "claude.json"),
1364
+ configPath: path7.join(getCcmanDir(), "claude.json"),
1254
1365
  builtinPresets: CC_PRESETS,
1255
1366
  writer: writeClaudeConfig
1256
1367
  },
1257
1368
  mcp: {
1258
- configPath: path6.join(getCcmanDir(), "mcp.json"),
1369
+ configPath: path7.join(getCcmanDir(), "mcp.json"),
1259
1370
  builtinPresets: MCP_PRESETS,
1260
1371
  writer: writeMCPConfig,
1261
1372
  autoSync: true,
@@ -1285,12 +1396,12 @@ var init_tool_manager = __esm({
1285
1396
  }
1286
1397
  },
1287
1398
  gemini: {
1288
- configPath: path6.join(getCcmanDir(), "gemini.json"),
1399
+ configPath: path7.join(getCcmanDir(), "gemini.json"),
1289
1400
  builtinPresets: GEMINI_PRESETS,
1290
1401
  writer: writeGeminiConfig
1291
1402
  },
1292
1403
  opencode: {
1293
- configPath: path6.join(getCcmanDir(), "opencode.json"),
1404
+ configPath: path7.join(getCcmanDir(), "opencode.json"),
1294
1405
  builtinPresets: OPENCODE_PRESETS,
1295
1406
  writer: writeOpenCodeConfig
1296
1407
  }
@@ -1307,20 +1418,20 @@ var init_migrate = __esm({
1307
1418
  });
1308
1419
 
1309
1420
  // ../core/dist/config.js
1310
- import * as fs6 from "fs";
1421
+ import * as fs7 from "fs";
1311
1422
  function ensureConfigDir() {
1312
1423
  const dir = getCcmanDir();
1313
- if (!fs6.existsSync(dir)) {
1314
- fs6.mkdirSync(dir, { recursive: true, mode: 448 });
1424
+ if (!fs7.existsSync(dir)) {
1425
+ fs7.mkdirSync(dir, { recursive: true, mode: 448 });
1315
1426
  }
1316
1427
  }
1317
1428
  function loadConfig() {
1318
1429
  const configPath = getConfigPath();
1319
- if (!fs6.existsSync(configPath)) {
1430
+ if (!fs7.existsSync(configPath)) {
1320
1431
  return {};
1321
1432
  }
1322
1433
  try {
1323
- const content = fs6.readFileSync(configPath, "utf-8");
1434
+ const content = fs7.readFileSync(configPath, "utf-8");
1324
1435
  return JSON.parse(content);
1325
1436
  } catch (error) {
1326
1437
  throw new Error(`Failed to load config: ${error.message}`);
@@ -1331,10 +1442,10 @@ function saveConfig(config) {
1331
1442
  const configPath = getConfigPath();
1332
1443
  try {
1333
1444
  const tempPath = `${configPath}.tmp`;
1334
- fs6.writeFileSync(tempPath, JSON.stringify(config, null, 2), {
1445
+ fs7.writeFileSync(tempPath, JSON.stringify(config, null, 2), {
1335
1446
  mode: 384
1336
1447
  });
1337
- fs6.renameSync(tempPath, configPath);
1448
+ fs7.renameSync(tempPath, configPath);
1338
1449
  } catch (error) {
1339
1450
  throw new Error(`Failed to save config: ${error.message}`);
1340
1451
  }
@@ -1658,24 +1769,24 @@ var init_merge_advanced = __esm({
1658
1769
  });
1659
1770
 
1660
1771
  // ../core/dist/sync/merge.js
1661
- import fs7 from "fs";
1662
- import path7 from "path";
1772
+ import fs8 from "fs";
1773
+ import path8 from "path";
1663
1774
  function backupConfig(configPath, keepCount = 3) {
1664
- if (!fs7.existsSync(configPath)) {
1775
+ if (!fs8.existsSync(configPath)) {
1665
1776
  throw new Error(`\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${configPath}`);
1666
1777
  }
1667
1778
  const timestamp = Date.now();
1668
1779
  const backupPath = `${configPath}.backup.${timestamp}`;
1669
- fs7.copyFileSync(configPath, backupPath);
1780
+ fs8.copyFileSync(configPath, backupPath);
1670
1781
  cleanupOldBackups(configPath, keepCount);
1671
1782
  return backupPath;
1672
1783
  }
1673
1784
  function cleanupOldBackups(configPath, keepCount) {
1674
- const dir = path7.dirname(configPath);
1675
- const basename = path7.basename(configPath);
1785
+ const dir = path8.dirname(configPath);
1786
+ const basename = path8.basename(configPath);
1676
1787
  const backupPrefix = `${basename}.backup.`;
1677
1788
  try {
1678
- const files = fs7.readdirSync(dir);
1789
+ const files = fs8.readdirSync(dir);
1679
1790
  const backups = files.filter((f) => f.startsWith(backupPrefix)).map((f) => {
1680
1791
  const timestampStr = f.substring(backupPrefix.length);
1681
1792
  const timestamp = parseInt(timestampStr, 10);
@@ -1684,14 +1795,14 @@ function cleanupOldBackups(configPath, keepCount) {
1684
1795
  }
1685
1796
  return {
1686
1797
  name: f,
1687
- path: path7.join(dir, f),
1798
+ path: path8.join(dir, f),
1688
1799
  timestamp
1689
1800
  };
1690
1801
  }).filter((backup) => backup !== null).sort((a, b) => b.timestamp - a.timestamp);
1691
1802
  const toDelete = backups.slice(keepCount);
1692
1803
  for (const backup of toDelete) {
1693
1804
  try {
1694
- fs7.unlinkSync(backup.path);
1805
+ fs8.unlinkSync(backup.path);
1695
1806
  } catch (error) {
1696
1807
  console.warn(`\u65E0\u6CD5\u5220\u9664\u65E7\u5907\u4EFD\u6587\u4EF6 ${backup.name}: ${error.message}`);
1697
1808
  }
@@ -1707,14 +1818,14 @@ var init_merge = __esm({
1707
1818
  });
1708
1819
 
1709
1820
  // ../core/dist/sync/sync-v2.js
1710
- import fs8 from "fs";
1711
- import path8 from "path";
1821
+ import fs9 from "fs";
1822
+ import path9 from "path";
1712
1823
  async function uploadToCloud(config, password) {
1713
1824
  const ccmanDir2 = getCcmanDir();
1714
1825
  const toolKeys = Object.keys(TOOL_SYNC_CONFIG);
1715
1826
  for (const tool of toolKeys) {
1716
1827
  const { remotePath, configFilename } = TOOL_SYNC_CONFIG[tool];
1717
- const configPath = path8.join(ccmanDir2, configFilename);
1828
+ const configPath = path9.join(ccmanDir2, configFilename);
1718
1829
  const localConfig = readJSON(configPath);
1719
1830
  const encryptedProviders = encryptProviders(localConfig.providers, password);
1720
1831
  const encryptedConfig = {
@@ -1760,8 +1871,8 @@ async function downloadFromCloud(config, password) {
1760
1871
  try {
1761
1872
  for (const tool of toolKeys) {
1762
1873
  const { configFilename } = TOOL_SYNC_CONFIG[tool];
1763
- const configPath = path8.join(ccmanDir2, configFilename);
1764
- if (fs8.existsSync(configPath)) {
1874
+ const configPath = path9.join(ccmanDir2, configFilename);
1875
+ if (fs9.existsSync(configPath)) {
1765
1876
  backupPaths.push(backupConfig(configPath));
1766
1877
  }
1767
1878
  }
@@ -1773,7 +1884,7 @@ async function downloadFromCloud(config, password) {
1773
1884
  if (!remoteConfig || !decryptedProviders)
1774
1885
  continue;
1775
1886
  const { configFilename } = TOOL_SYNC_CONFIG[tool];
1776
- const configPath = path8.join(ccmanDir2, configFilename);
1887
+ const configPath = path9.join(ccmanDir2, configFilename);
1777
1888
  const newConfig = {
1778
1889
  ...remoteConfig,
1779
1890
  // 使用云端配置的所有字段
@@ -1789,8 +1900,8 @@ async function downloadFromCloud(config, password) {
1789
1900
  } catch (error) {
1790
1901
  for (const backupPath of backupPaths) {
1791
1902
  const originalPath = backupPath.replace(/\.backup\.\d+$/, "");
1792
- if (fs8.existsSync(backupPath)) {
1793
- fs8.copyFileSync(backupPath, originalPath);
1903
+ if (fs9.existsSync(backupPath)) {
1904
+ fs9.copyFileSync(backupPath, originalPath);
1794
1905
  }
1795
1906
  }
1796
1907
  throw new Error(`\u8986\u76D6\u914D\u7F6E\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
@@ -1815,7 +1926,7 @@ async function mergeSync(config, password) {
1815
1926
  for (let i = 0; i < toolKeys.length; i++) {
1816
1927
  const tool = toolKeys[i];
1817
1928
  const { remotePath, configFilename } = TOOL_SYNC_CONFIG[tool];
1818
- const configPath = path8.join(ccmanDir2, configFilename);
1929
+ const configPath = path9.join(ccmanDir2, configFilename);
1819
1930
  const localConfig = readJSON(configPath);
1820
1931
  let remoteProviders = [];
1821
1932
  if (existsChecks[i]) {
@@ -1847,8 +1958,8 @@ async function mergeSync(config, password) {
1847
1958
  try {
1848
1959
  for (const tool of toolKeys) {
1849
1960
  const { configFilename } = TOOL_SYNC_CONFIG[tool];
1850
- const configPath = path8.join(ccmanDir2, configFilename);
1851
- if (fs8.existsSync(configPath)) {
1961
+ const configPath = path9.join(ccmanDir2, configFilename);
1962
+ if (fs9.existsSync(configPath)) {
1852
1963
  backupPaths.push(backupConfig(configPath));
1853
1964
  }
1854
1965
  }
@@ -1859,7 +1970,7 @@ async function mergeSync(config, password) {
1859
1970
  for (let i = 0; i < mergeDataList.length; i++) {
1860
1971
  const { tool, localConfig, mergeResult } = mergeDataList[i];
1861
1972
  const { remotePath, configFilename } = TOOL_SYNC_CONFIG[tool];
1862
- const configPath = path8.join(ccmanDir2, configFilename);
1973
+ const configPath = path9.join(ccmanDir2, configFilename);
1863
1974
  let remoteConfig = null;
1864
1975
  if (existsChecks[i]) {
1865
1976
  const jsonContent2 = await downloadFromWebDAV(config, remotePath);
@@ -1895,8 +2006,8 @@ async function mergeSync(config, password) {
1895
2006
  } catch (error) {
1896
2007
  for (const backupPath of backupPaths) {
1897
2008
  const originalPath = backupPath.replace(/\.backup\.\d+$/, "");
1898
- if (fs8.existsSync(backupPath)) {
1899
- fs8.copyFileSync(backupPath, originalPath);
2009
+ if (fs9.existsSync(backupPath)) {
2010
+ fs9.copyFileSync(backupPath, originalPath);
1900
2011
  }
1901
2012
  }
1902
2013
  throw new Error(`\u5408\u5E76\u914D\u7F6E\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
@@ -1949,12 +2060,12 @@ var init_sync_v2 = __esm({
1949
2060
  });
1950
2061
 
1951
2062
  // ../core/dist/export.js
1952
- import * as fs9 from "fs";
1953
- import * as path9 from "path";
2063
+ import * as fs10 from "fs";
2064
+ import * as path10 from "path";
1954
2065
  function validateExport() {
1955
2066
  const ccmanDir2 = getCcmanDir();
1956
- const codexPath = path9.join(ccmanDir2, CODEX_CONFIG_FILE);
1957
- const claudePath = path9.join(ccmanDir2, CLAUDE_CONFIG_FILE);
2067
+ const codexPath = path10.join(ccmanDir2, CODEX_CONFIG_FILE);
2068
+ const claudePath = path10.join(ccmanDir2, CLAUDE_CONFIG_FILE);
1958
2069
  const missingFiles = [];
1959
2070
  if (!fileExists(codexPath)) {
1960
2071
  missingFiles.push(CODEX_CONFIG_FILE);
@@ -1979,7 +2090,7 @@ function validateImportDir(sourceDir) {
1979
2090
  foundFiles: []
1980
2091
  };
1981
2092
  }
1982
- const stats = fs9.statSync(sourceDir);
2093
+ const stats = fs10.statSync(sourceDir);
1983
2094
  if (!stats.isDirectory()) {
1984
2095
  return {
1985
2096
  valid: false,
@@ -1987,8 +2098,8 @@ function validateImportDir(sourceDir) {
1987
2098
  foundFiles: []
1988
2099
  };
1989
2100
  }
1990
- const codexPath = path9.join(sourceDir, CODEX_CONFIG_FILE);
1991
- const claudePath = path9.join(sourceDir, CLAUDE_CONFIG_FILE);
2101
+ const codexPath = path10.join(sourceDir, CODEX_CONFIG_FILE);
2102
+ const claudePath = path10.join(sourceDir, CLAUDE_CONFIG_FILE);
1992
2103
  const foundFiles = [];
1993
2104
  if (fileExists(codexPath)) {
1994
2105
  foundFiles.push(CODEX_CONFIG_FILE);
@@ -2016,16 +2127,16 @@ function exportConfig(targetDir) {
2016
2127
  ensureDir(targetDir);
2017
2128
  const ccmanDir2 = getCcmanDir();
2018
2129
  const exportedFiles = [];
2019
- const codexSrc = path9.join(ccmanDir2, CODEX_CONFIG_FILE);
2020
- const codexDst = path9.join(targetDir, CODEX_CONFIG_FILE);
2130
+ const codexSrc = path10.join(ccmanDir2, CODEX_CONFIG_FILE);
2131
+ const codexDst = path10.join(targetDir, CODEX_CONFIG_FILE);
2021
2132
  if (fileExists(codexSrc)) {
2022
- fs9.copyFileSync(codexSrc, codexDst);
2133
+ fs10.copyFileSync(codexSrc, codexDst);
2023
2134
  exportedFiles.push(CODEX_CONFIG_FILE);
2024
2135
  }
2025
- const claudeSrc = path9.join(ccmanDir2, CLAUDE_CONFIG_FILE);
2026
- const claudeDst = path9.join(targetDir, CLAUDE_CONFIG_FILE);
2136
+ const claudeSrc = path10.join(ccmanDir2, CLAUDE_CONFIG_FILE);
2137
+ const claudeDst = path10.join(targetDir, CLAUDE_CONFIG_FILE);
2027
2138
  if (fileExists(claudeSrc)) {
2028
- fs9.copyFileSync(claudeSrc, claudeDst);
2139
+ fs10.copyFileSync(claudeSrc, claudeDst);
2029
2140
  exportedFiles.push(CLAUDE_CONFIG_FILE);
2030
2141
  }
2031
2142
  return {
@@ -2045,23 +2156,23 @@ function importConfig(sourceDir) {
2045
2156
  ensureDir(ccmanDir2);
2046
2157
  try {
2047
2158
  if (validation.foundFiles.includes(CODEX_CONFIG_FILE)) {
2048
- const codexDst = path9.join(ccmanDir2, CODEX_CONFIG_FILE);
2159
+ const codexDst = path10.join(ccmanDir2, CODEX_CONFIG_FILE);
2049
2160
  if (fileExists(codexDst)) {
2050
2161
  const backupPath = backupConfig(codexDst);
2051
2162
  backupPaths.push(backupPath);
2052
2163
  }
2053
- const codexSrc = path9.join(sourceDir, CODEX_CONFIG_FILE);
2054
- fs9.copyFileSync(codexSrc, codexDst);
2164
+ const codexSrc = path10.join(sourceDir, CODEX_CONFIG_FILE);
2165
+ fs10.copyFileSync(codexSrc, codexDst);
2055
2166
  importedFiles.push(CODEX_CONFIG_FILE);
2056
2167
  }
2057
2168
  if (validation.foundFiles.includes(CLAUDE_CONFIG_FILE)) {
2058
- const claudeDst = path9.join(ccmanDir2, CLAUDE_CONFIG_FILE);
2169
+ const claudeDst = path10.join(ccmanDir2, CLAUDE_CONFIG_FILE);
2059
2170
  if (fileExists(claudeDst)) {
2060
2171
  const backupPath = backupConfig(claudeDst);
2061
2172
  backupPaths.push(backupPath);
2062
2173
  }
2063
- const claudeSrc = path9.join(sourceDir, CLAUDE_CONFIG_FILE);
2064
- fs9.copyFileSync(claudeSrc, claudeDst);
2174
+ const claudeSrc = path10.join(sourceDir, CLAUDE_CONFIG_FILE);
2175
+ fs10.copyFileSync(claudeSrc, claudeDst);
2065
2176
  importedFiles.push(CLAUDE_CONFIG_FILE);
2066
2177
  }
2067
2178
  return {
@@ -2073,7 +2184,7 @@ function importConfig(sourceDir) {
2073
2184
  for (const backupPath of backupPaths) {
2074
2185
  const originalPath = backupPath.replace(/\.backup\.\d+$/, "");
2075
2186
  if (fileExists(backupPath)) {
2076
- fs9.copyFileSync(backupPath, originalPath);
2187
+ fs10.copyFileSync(backupPath, originalPath);
2077
2188
  }
2078
2189
  }
2079
2190
  throw new Error(`\u5BFC\u5165\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
@@ -2092,7 +2203,7 @@ var init_export = __esm({
2092
2203
  });
2093
2204
 
2094
2205
  // ../core/dist/claude-clean.js
2095
- import * as fs10 from "fs";
2206
+ import * as fs11 from "fs";
2096
2207
  function formatBytes(bytes) {
2097
2208
  if (bytes < 1024)
2098
2209
  return `${bytes} B`;
@@ -2102,7 +2213,7 @@ function formatBytes(bytes) {
2102
2213
  }
2103
2214
  function getFileSize(filePath) {
2104
2215
  try {
2105
- const stats = fs10.statSync(filePath);
2216
+ const stats = fs11.statSync(filePath);
2106
2217
  return stats.size;
2107
2218
  } catch {
2108
2219
  return 0;
@@ -2111,18 +2222,18 @@ function getFileSize(filePath) {
2111
2222
  function backupFile(filePath) {
2112
2223
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-").split(".")[0];
2113
2224
  const backupPath = `${filePath}.backup-${timestamp}`;
2114
- fs10.copyFileSync(filePath, backupPath);
2225
+ fs11.copyFileSync(filePath, backupPath);
2115
2226
  return backupPath;
2116
2227
  }
2117
2228
  function saveJsonAtomic(filePath, data) {
2118
2229
  const tempPath = `${filePath}.tmp`;
2119
2230
  const content = JSON.stringify(data, null, 2);
2120
- fs10.writeFileSync(tempPath, content, { mode: 384 });
2121
- fs10.renameSync(tempPath, filePath);
2231
+ fs11.writeFileSync(tempPath, content, { mode: 384 });
2232
+ fs11.renameSync(tempPath, filePath);
2122
2233
  }
2123
2234
  function analyzeClaudeJson() {
2124
2235
  const filePath = getClaudeJsonPath();
2125
- if (!fs10.existsSync(filePath)) {
2236
+ if (!fs11.existsSync(filePath)) {
2126
2237
  return {
2127
2238
  fileSize: 0,
2128
2239
  fileSizeFormatted: "0 B",
@@ -2138,7 +2249,7 @@ function analyzeClaudeJson() {
2138
2249
  };
2139
2250
  }
2140
2251
  const fileSize = getFileSize(filePath);
2141
- const content = fs10.readFileSync(filePath, "utf-8");
2252
+ const content = fs11.readFileSync(filePath, "utf-8");
2142
2253
  const config = JSON.parse(content);
2143
2254
  const projects = config.projects || {};
2144
2255
  const projectHistory = [];
@@ -2172,12 +2283,12 @@ function analyzeClaudeJson() {
2172
2283
  }
2173
2284
  function cleanClaudeJson(options = {}) {
2174
2285
  const filePath = getClaudeJsonPath();
2175
- if (!fs10.existsSync(filePath)) {
2286
+ if (!fs11.existsSync(filePath)) {
2176
2287
  throw new Error(`${filePath} \u6587\u4EF6\u4E0D\u5B58\u5728`);
2177
2288
  }
2178
2289
  const backupPath = backupFile(filePath);
2179
2290
  const sizeBefore = getFileSize(filePath);
2180
- const content = fs10.readFileSync(filePath, "utf-8");
2291
+ const content = fs11.readFileSync(filePath, "utf-8");
2181
2292
  const config = JSON.parse(content);
2182
2293
  const cleanedItems = applyCleanOptions(config, options);
2183
2294
  saveJsonAtomic(filePath, config);
@@ -2733,8 +2844,8 @@ function downloadCommand(program2) {
2733
2844
  console.log();
2734
2845
  if (backupPaths.length > 0) {
2735
2846
  console.log(chalk7.gray("\u672C\u5730\u5907\u4EFD:"));
2736
- backupPaths.forEach((path12) => {
2737
- console.log(chalk7.gray(` ${path12}`));
2847
+ backupPaths.forEach((path13) => {
2848
+ console.log(chalk7.gray(` ${path13}`));
2738
2849
  });
2739
2850
  console.log();
2740
2851
  }
@@ -2795,8 +2906,8 @@ function mergeCommand(program2) {
2795
2906
  console.log();
2796
2907
  if (result.backupPaths.length > 0) {
2797
2908
  console.log(chalk8.gray("\u5907\u4EFD:"));
2798
- result.backupPaths.forEach((path12) => {
2799
- console.log(chalk8.gray(` ${path12}`));
2909
+ result.backupPaths.forEach((path13) => {
2910
+ console.log(chalk8.gray(` ${path13}`));
2800
2911
  });
2801
2912
  console.log();
2802
2913
  }
@@ -3006,7 +3117,7 @@ function printLogo() {
3006
3117
  `
3007
3118
  )
3008
3119
  );
3009
- console.log(chalk.gray(" Codex/Claude Code API \u670D\u52A1\u5546\u914D\u7F6E\u7BA1\u7406\u5DE5\u5177"));
3120
+ console.log(chalk.gray(" \u591A\u5DE5\u5177 AI \u670D\u52A1\u5546\u914D\u7F6E\u7BA1\u7406\u5DE5\u5177"));
3010
3121
  console.log(chalk.gray(` \u7248\u672C ${VERSION}
3011
3122
  `));
3012
3123
  }
@@ -3046,27 +3157,6 @@ function formatProviderTable(providers, currentId) {
3046
3157
  return lines.join("\n");
3047
3158
  }
3048
3159
 
3049
- // src/utils/opencode.ts
3050
- var DEFAULT_OPENCODE_NPM = "@ai-sdk/openai";
3051
- function parseOpenCodeMeta(raw) {
3052
- if (!raw || !raw.trim()) return null;
3053
- try {
3054
- const parsed = JSON.parse(raw);
3055
- if (parsed && typeof parsed === "object") {
3056
- return parsed;
3057
- }
3058
- } catch {
3059
- return { npm: raw };
3060
- }
3061
- return null;
3062
- }
3063
- function buildOpenCodeModel(meta) {
3064
- const payload = {};
3065
- if (meta.npm) payload.npm = meta.npm;
3066
- if (meta.models) payload.models = meta.models;
3067
- return JSON.stringify(payload);
3068
- }
3069
-
3070
3160
  // src/interactive.ts
3071
3161
  var CLI_TOOL_CONFIG = {
3072
3162
  [TOOL_TYPES.CODEX]: { name: "Codex", emoji: "\u{1F536}", cmd: "cx" },
@@ -3333,20 +3423,7 @@ async function handleAdd(tool) {
3333
3423
  baseUrl = answers.baseUrl;
3334
3424
  apiKey = answers.apiKey;
3335
3425
  }
3336
- let model;
3337
- if (tool === TOOL_TYPES.OPENCODE) {
3338
- const { npmPackage } = await inquirer7.prompt([
3339
- {
3340
- type: "input",
3341
- name: "npmPackage",
3342
- message: "\u517C\u5BB9\u5305 (npm):",
3343
- default: DEFAULT_OPENCODE_NPM,
3344
- validate: (value) => value ? true : "npm \u5305\u4E0D\u80FD\u4E3A\u7A7A"
3345
- }
3346
- ]);
3347
- model = buildOpenCodeModel({ npm: npmPackage });
3348
- }
3349
- const provider = manager.add({ name, desc, baseUrl, apiKey, model });
3426
+ const provider = manager.add({ name, desc, baseUrl, apiKey });
3350
3427
  console.log();
3351
3428
  console.log(chalk11.green("\u2705 \u6DFB\u52A0\u6210\u529F"));
3352
3429
  console.log();
@@ -3449,8 +3526,6 @@ async function handleEdit(tool) {
3449
3526
  }
3450
3527
  ]);
3451
3528
  const provider = providers.find((p) => p.id === providerId);
3452
- const meta = tool === TOOL_TYPES.OPENCODE ? parseOpenCodeMeta(provider.model) : null;
3453
- const currentNpm = meta?.npm || DEFAULT_OPENCODE_NPM;
3454
3529
  const answers = await inquirer7.prompt([
3455
3530
  {
3456
3531
  type: "input",
@@ -3485,25 +3560,11 @@ async function handleEdit(tool) {
3485
3560
  mask: "*"
3486
3561
  }
3487
3562
  ]);
3488
- let model;
3489
- if (tool === TOOL_TYPES.OPENCODE) {
3490
- const { npmPackage } = await inquirer7.prompt([
3491
- {
3492
- type: "input",
3493
- name: "npmPackage",
3494
- message: "\u517C\u5BB9\u5305 (npm):",
3495
- default: currentNpm,
3496
- validate: (value) => value ? true : "npm \u5305\u4E0D\u80FD\u4E3A\u7A7A"
3497
- }
3498
- ]);
3499
- model = buildOpenCodeModel({ npm: npmPackage, models: meta?.models });
3500
- }
3501
3563
  manager.edit(providerId, {
3502
3564
  name: answers.name,
3503
3565
  desc: answers.desc || void 0,
3504
3566
  baseUrl: answers.baseUrl,
3505
- apiKey: answers.apiKey || void 0,
3506
- model
3567
+ apiKey: answers.apiKey || void 0
3507
3568
  });
3508
3569
  console.log(chalk11.green("\n\u2705 \u7F16\u8F91\u6210\u529F\n"));
3509
3570
  }
@@ -3526,8 +3587,6 @@ async function handleClone(tool) {
3526
3587
  }
3527
3588
  ]);
3528
3589
  const provider = providers.find((p) => p.id === providerId);
3529
- const meta = tool === TOOL_TYPES.OPENCODE ? parseOpenCodeMeta(provider.model) : null;
3530
- const currentNpm = meta?.npm || DEFAULT_OPENCODE_NPM;
3531
3590
  const answers = await inquirer7.prompt([
3532
3591
  {
3533
3592
  type: "input",
@@ -3544,26 +3603,12 @@ async function handleClone(tool) {
3544
3603
  validate: (value) => value ? true : "API \u5BC6\u94A5\u4E0D\u80FD\u4E3A\u7A7A"
3545
3604
  }
3546
3605
  ]);
3547
- let model;
3548
- if (tool === TOOL_TYPES.OPENCODE) {
3549
- const { npmPackage } = await inquirer7.prompt([
3550
- {
3551
- type: "input",
3552
- name: "npmPackage",
3553
- message: "\u517C\u5BB9\u5305 (npm):",
3554
- default: currentNpm,
3555
- validate: (value) => value ? true : "npm \u5305\u4E0D\u80FD\u4E3A\u7A7A"
3556
- }
3557
- ]);
3558
- model = buildOpenCodeModel({ npm: npmPackage, models: meta?.models });
3559
- }
3560
3606
  const newProvider = manager.add({
3561
3607
  name: answers.name,
3562
3608
  // 克隆时不继承描述,留空让用户后续编辑
3563
3609
  desc: void 0,
3564
3610
  baseUrl: provider.baseUrl,
3565
- apiKey: answers.apiKey,
3566
- model
3611
+ apiKey: answers.apiKey
3567
3612
  });
3568
3613
  console.log(chalk11.green("\n\u2705 \u514B\u9686\u6210\u529F\n"));
3569
3614
  console.log(` ${chalk11.bold(newProvider.name)}`);
@@ -5686,21 +5731,11 @@ function addCommand5(program2) {
5686
5731
  baseUrl = answers.baseUrl;
5687
5732
  apiKey = answers.apiKey;
5688
5733
  }
5689
- const { npmPackage } = await inquirer27.prompt([
5690
- {
5691
- type: "input",
5692
- name: "npmPackage",
5693
- message: "\u517C\u5BB9\u5305 (npm):",
5694
- default: DEFAULT_OPENCODE_NPM,
5695
- validate: (value) => value ? true : "npm \u5305\u4E0D\u80FD\u4E3A\u7A7A"
5696
- }
5697
- ]);
5698
5734
  const provider = manager.add({
5699
5735
  name,
5700
5736
  desc,
5701
5737
  baseUrl,
5702
- apiKey,
5703
- model: buildOpenCodeModel({ npm: npmPackage })
5738
+ apiKey
5704
5739
  });
5705
5740
  console.log();
5706
5741
  console.log(chalk38.green("\u2705 \u6DFB\u52A0\u6210\u529F"));
@@ -5880,32 +5915,17 @@ function editCommand5(program2) {
5880
5915
  targetId = selectedId;
5881
5916
  }
5882
5917
  const provider = manager.get(targetId);
5883
- const meta = parseOpenCodeMeta(provider.model);
5884
- const currentNpm = meta?.npm || DEFAULT_OPENCODE_NPM;
5885
5918
  const input = await promptProviderForm({
5886
5919
  name: provider.name,
5887
5920
  desc: provider.desc ?? "",
5888
5921
  baseUrl: provider.baseUrl,
5889
5922
  apiKey: provider.apiKey
5890
5923
  });
5891
- const { npmPackage } = await inquirer29.prompt([
5892
- {
5893
- type: "input",
5894
- name: "npmPackage",
5895
- message: "\u517C\u5BB9\u5305 (npm):",
5896
- default: currentNpm,
5897
- validate: (value) => value ? true : "npm \u5305\u4E0D\u80FD\u4E3A\u7A7A"
5898
- }
5899
- ]);
5900
5924
  manager.edit(targetId, {
5901
5925
  name: input.name,
5902
5926
  desc: input.desc,
5903
5927
  baseUrl: input.baseUrl,
5904
- apiKey: input.apiKey,
5905
- model: buildOpenCodeModel({
5906
- npm: npmPackage,
5907
- models: meta?.models
5908
- })
5928
+ apiKey: input.apiKey
5909
5929
  });
5910
5930
  console.log(chalk42.green("\n\u2705 \u7F16\u8F91\u6210\u529F\n"));
5911
5931
  } catch (error) {
@@ -6027,8 +6047,6 @@ function cloneCommand4(program2) {
6027
6047
  sourceId = selectedId;
6028
6048
  }
6029
6049
  const source = manager.get(sourceId);
6030
- const meta = parseOpenCodeMeta(source.model);
6031
- const currentNpm = meta?.npm || DEFAULT_OPENCODE_NPM;
6032
6050
  let cloned;
6033
6051
  if (newName) {
6034
6052
  cloned = manager.clone(sourceId, newName);
@@ -6042,24 +6060,11 @@ function cloneCommand4(program2) {
6042
6060
  baseUrl: source.baseUrl,
6043
6061
  apiKey: source.apiKey
6044
6062
  });
6045
- const { npmPackage } = await inquirer31.prompt([
6046
- {
6047
- type: "input",
6048
- name: "npmPackage",
6049
- message: "\u517C\u5BB9\u5305 (npm):",
6050
- default: currentNpm,
6051
- validate: (value) => value ? true : "npm \u5305\u4E0D\u80FD\u4E3A\u7A7A"
6052
- }
6053
- ]);
6054
6063
  cloned = manager.add({
6055
6064
  name: input.name,
6056
6065
  desc: input.desc,
6057
6066
  baseUrl: input.baseUrl,
6058
- apiKey: input.apiKey,
6059
- model: buildOpenCodeModel({
6060
- npm: npmPackage,
6061
- models: meta?.models
6062
- })
6067
+ apiKey: input.apiKey
6063
6068
  });
6064
6069
  }
6065
6070
  console.log();
@@ -6095,7 +6100,7 @@ init_sync();
6095
6100
  // src/commands/export.ts
6096
6101
  init_dist2();
6097
6102
  import chalk45 from "chalk";
6098
- import path10 from "path";
6103
+ import path11 from "path";
6099
6104
  function exportCommand(program2) {
6100
6105
  program2.command("export <\u76EE\u6807\u76EE\u5F55>").description("\u5BFC\u51FA\u914D\u7F6E\u5230\u672C\u5730\u76EE\u5F55\uFF08\u5305\u542B API Key\uFF09").action(async (targetDir) => {
6101
6106
  try {
@@ -6106,7 +6111,7 @@ function exportCommand(program2) {
6106
6111
  `));
6107
6112
  process.exit(1);
6108
6113
  }
6109
- const resolvedPath = targetDir.startsWith("~") ? path10.join(process.env.HOME || "", targetDir.slice(1)) : path10.resolve(targetDir);
6114
+ const resolvedPath = targetDir.startsWith("~") ? path11.join(process.env.HOME || "", targetDir.slice(1)) : path11.resolve(targetDir);
6110
6115
  console.log("\u5BFC\u51FA\u6587\u4EF6:");
6111
6116
  console.log(` ${chalk45.cyan("codex.json")} - Codex \u914D\u7F6E`);
6112
6117
  console.log(` ${chalk45.cyan("claude.json")} - Claude \u914D\u7F6E`);
@@ -6138,11 +6143,11 @@ function exportCommand(program2) {
6138
6143
  init_dist2();
6139
6144
  import chalk46 from "chalk";
6140
6145
  import inquirer32 from "inquirer";
6141
- import path11 from "path";
6146
+ import path12 from "path";
6142
6147
  function importCommand(program2) {
6143
6148
  program2.command("import <\u6E90\u76EE\u5F55>").description("\u4ECE\u672C\u5730\u76EE\u5F55\u5BFC\u5165\u914D\u7F6E\uFF08\u4F1A\u8986\u76D6\u5F53\u524D\u914D\u7F6E\uFF09").action(async (sourceDir) => {
6144
6149
  try {
6145
- const resolvedPath = sourceDir.startsWith("~") ? path11.join(process.env.HOME || "", sourceDir.slice(1)) : path11.resolve(sourceDir);
6150
+ const resolvedPath = sourceDir.startsWith("~") ? path12.join(process.env.HOME || "", sourceDir.slice(1)) : path12.resolve(sourceDir);
6146
6151
  console.log(chalk46.bold("\n\u{1F4E5} \u5BFC\u5165\u914D\u7F6E\n"));
6147
6152
  const validation = validateImportDir(resolvedPath);
6148
6153
  if (!validation.valid) {
@@ -6231,6 +6236,66 @@ var GMN_OPENAI_BASE_URLS = {
6231
6236
  cn: "https://gmn.chuangzuoli.cn/openai",
6232
6237
  com: "https://gmn.chuangzuoli.com"
6233
6238
  };
6239
+ var TOTAL_STEPS = 4;
6240
+ function renderStep(current, total, title) {
6241
+ const barLength = total;
6242
+ const filledLength = Math.min(current, total);
6243
+ const bar = `${"\u25A0".repeat(filledLength)}${"\u25A1".repeat(barLength - filledLength)}`;
6244
+ return `\u6B65\u9AA4 ${current}/${total} [${bar}] ${title}`;
6245
+ }
6246
+ function printBanner() {
6247
+ printLogo();
6248
+ console.log(
6249
+ chalk47.cyanBright(
6250
+ [
6251
+ " \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557",
6252
+ " \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551",
6253
+ " \u2588\u2588\u2551 \u2588\u2588\u2588\u2557 \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551",
6254
+ " \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",
6255
+ " \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",
6256
+ " \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D",
6257
+ " CCMAN GMN \u4E00\u952E\u914D\u7F6E\u5411\u5BFC"
6258
+ ].join("\n")
6259
+ )
6260
+ );
6261
+ console.log(chalk47.gray("\u81EA\u52A8\u5199\u5165\u9009\u4E2D\u5DE5\u5177\u914D\u7F6E\uFF0C\u652F\u6301\u591A\u9009\u4E0E\u7AEF\u70B9\u9009\u62E9\u3002\n"));
6262
+ }
6263
+ function printKeyNotice() {
6264
+ console.log(
6265
+ chalk47.yellow(
6266
+ [
6267
+ "\u63D0\u793A\uFF1ACodex \u4E0E OpenCode \u5171\u4EAB OpenAI \u5957\u9910/\u7AEF\u70B9\uFF1BGemini \u4E0E Claude \u9700\u5355\u72EC\u8BA2\u9605\u3002",
6268
+ "\u4F8B\u5982\uFF1AGemini \u5957\u9910\u4E0D\u80FD\u7528\u4E8E Codex/OpenCode\uFF0CClaude \u5957\u9910\u4E5F\u4E0D\u80FD\u901A\u7528\u3002",
6269
+ "VS Code \u7684 Codex \u63D2\u4EF6\u82E5\u4F7F\u7528\u672C\u673A\u9ED8\u8BA4\u914D\u7F6E\uFF0C\u4E5F\u4F1A\u8DDF\u968F\u672C\u6B21\u5199\u5165\u751F\u6548\u3002"
6270
+ ].join("\n")
6271
+ )
6272
+ );
6273
+ }
6274
+ function printWriteTargets(platforms) {
6275
+ console.log(chalk47.gray(`\u5199\u5165\u76EE\u5F55: ${getCcmanDir()}`));
6276
+ if (platforms.includes("codex")) {
6277
+ console.log(chalk47.gray(` - Codex: ${getCodexConfigPath()}`));
6278
+ console.log(chalk47.gray(` - Codex: ${getCodexAuthPath()}`));
6279
+ }
6280
+ if (platforms.includes("claude")) {
6281
+ console.log(chalk47.gray(` - Claude Code: ${getClaudeConfigPath()}`));
6282
+ }
6283
+ if (platforms.includes("gemini")) {
6284
+ console.log(chalk47.gray(` - Gemini CLI: ${getGeminiSettingsPath()}`));
6285
+ console.log(chalk47.gray(` - Gemini CLI: ${getGeminiEnvPath()}`));
6286
+ }
6287
+ if (platforms.includes("opencode")) {
6288
+ console.log(chalk47.gray(` - OpenCode: ${getOpenCodeConfigPath()}`));
6289
+ }
6290
+ const env = process.env.NODE_ENV;
6291
+ if (env === "development" || env === "test") {
6292
+ console.log(
6293
+ chalk47.yellow(
6294
+ `\u26A0\uFE0F \u5F53\u524D NODE_ENV=${env}\uFF0C\u5C06\u5199\u5165\u5F00\u53D1/\u6D4B\u8BD5\u76EE\u5F55\uFF1B\u5982\u9700\u5199\u5165\u771F\u5B9E HOME\uFF0C\u8BF7\u5728\u751F\u4EA7\u73AF\u5883\u8FD0\u884C\uFF08unset NODE_ENV\uFF09\u3002`
6295
+ )
6296
+ );
6297
+ }
6298
+ }
6234
6299
  function parsePlatforms(platformArg) {
6235
6300
  if (platformArg === "all") {
6236
6301
  return [...VALID_PLATFORMS];
@@ -6263,13 +6328,14 @@ async function promptPlatforms() {
6263
6328
  {
6264
6329
  type: "checkbox",
6265
6330
  name: "platforms",
6266
- message: "\u9009\u62E9\u5E73\u53F0:",
6331
+ message: "\u9009\u62E9\u8981\u914D\u7F6E\u7684\u5DE5\u5177\uFF08\u53EF\u591A\u9009\uFF0C\u7A7A\u683C\u9009\u62E9 / a\u5168\u9009 / i\u53CD\u9009 / \u56DE\u8F66\u786E\u8BA4\uFF09:",
6332
+ dontShowHints: true,
6267
6333
  choices: [
6268
- { name: "Claude Code", value: "claude" },
6269
- { name: "Codex", value: "codex" },
6270
- { name: "Gemini CLI", value: "gemini" },
6271
- { name: "OpenCode", value: "opencode" },
6272
- { name: "\u5168\u90E8 (all)", value: "all" }
6334
+ { name: "Claude Code\uFF08\u9700\u5355\u72EC\u8BA2\u9605 Claude \u5957\u9910\uFF09", value: "claude" },
6335
+ { name: "Codex\uFF08\u9700\u5355\u72EC\u8BA2\u9605 OpenAI \u5957\u9910\uFF09", value: "codex" },
6336
+ { name: "Gemini CLI\uFF08\u9700\u5355\u72EC\u8BA2\u9605 Gemini \u5957\u9910\uFF09", value: "gemini" },
6337
+ { name: "OpenCode\uFF08\u4E0E Codex \u5171\u4EAB OpenAI \u5957\u9910\uFF09", value: "opencode" },
6338
+ { name: "\u5168\u90E8\uFF08\u5C06\u4F9D\u6B21\u914D\u7F6E\u6240\u6709\u5DE5\u5177\uFF09", value: "all" }
6273
6339
  ],
6274
6340
  default: DEFAULT_PLATFORMS,
6275
6341
  validate: (value) => {
@@ -6306,10 +6372,10 @@ async function resolveOpenAIDomain(domainArg, platforms) {
6306
6372
  {
6307
6373
  type: "list",
6308
6374
  name: "domain",
6309
- message: "\u9009\u62E9 Codex/OpenCode \u7684 OpenAI Base URL:",
6375
+ message: "\u9009\u62E9 Codex/OpenCode \u7684 OpenAI Base URL\uFF08\u53EA\u5F71\u54CD\u8FD9\u4E24\u4E2A\u5DE5\u5177\uFF09:",
6310
6376
  choices: [
6311
- { name: `CN ${GMN_OPENAI_BASE_URLS.cn}`, value: "cn" },
6312
- { name: `COM ${GMN_OPENAI_BASE_URLS.com}`, value: "com" }
6377
+ { name: `CN\uFF08\u56FD\u5185\uFF09 ${GMN_OPENAI_BASE_URLS.cn}`, value: "cn" },
6378
+ { name: `COM\uFF08\u56FD\u9645\uFF09 ${GMN_OPENAI_BASE_URLS.com}`, value: "com" }
6313
6379
  ],
6314
6380
  default: "cn"
6315
6381
  }
@@ -6317,23 +6383,42 @@ async function resolveOpenAIDomain(domainArg, platforms) {
6317
6383
  return answers.domain;
6318
6384
  }
6319
6385
  async function gmnCommand(apiKey, platformArg, domainArg) {
6386
+ printBanner();
6320
6387
  let platforms;
6321
6388
  try {
6389
+ console.log(chalk47.cyan(`
6390
+ ${renderStep(1, TOTAL_STEPS, "\u9009\u62E9\u8981\u914D\u7F6E\u7684\u5DE5\u5177")}`));
6322
6391
  platforms = await resolvePlatforms(platformArg);
6323
6392
  } catch (error) {
6324
6393
  console.error(chalk47.red(`\u274C ${error.message}`));
6325
6394
  process.exit(1);
6326
6395
  }
6396
+ console.log(chalk47.gray(`\u5DF2\u9009\u62E9: ${platforms.join(", ")}`));
6397
+ printKeyNotice();
6327
6398
  let openaiDomain;
6328
6399
  try {
6400
+ if (platforms.includes("codex") || platforms.includes("opencode")) {
6401
+ console.log(
6402
+ chalk47.cyan(`
6403
+ ${renderStep(2, TOTAL_STEPS, "\u9009\u62E9 OpenAI \u7AEF\u70B9 (\u4EC5 Codex/OpenCode)")}`)
6404
+ );
6405
+ } else {
6406
+ console.log(chalk47.cyan(`
6407
+ ${renderStep(2, TOTAL_STEPS, "\u9009\u62E9 OpenAI \u7AEF\u70B9 (\u5DF2\u8DF3\u8FC7)")}`));
6408
+ console.log(chalk47.gray("\u672A\u9009\u62E9 Codex/OpenCode\uFF0C\u5C06\u8DF3\u8FC7\u6B64\u6B65\u9AA4\u3002"));
6409
+ }
6329
6410
  openaiDomain = await resolveOpenAIDomain(domainArg, platforms);
6330
6411
  } catch (error) {
6331
6412
  console.error(chalk47.red(`\u274C ${error.message}`));
6332
6413
  process.exit(1);
6333
6414
  }
6334
6415
  let resolvedApiKey = apiKey?.trim();
6416
+ console.log(chalk47.cyan(`
6417
+ ${renderStep(3, TOTAL_STEPS, "\u8F93\u5165 API Key")}`));
6335
6418
  if (!resolvedApiKey) {
6336
6419
  resolvedApiKey = await promptApiKey();
6420
+ } else {
6421
+ console.log(chalk47.gray("\u5DF2\u901A\u8FC7\u53C2\u6570\u63D0\u4F9B API Key\uFF08\u5DF2\u9690\u85CF\uFF09"));
6337
6422
  }
6338
6423
  if (!resolvedApiKey?.trim()) {
6339
6424
  console.error(chalk47.red("\u274C \u9519\u8BEF: API Key \u4E0D\u80FD\u4E3A\u7A7A"));
@@ -6346,9 +6431,14 @@ async function gmnCommand(apiKey, platformArg, domainArg) {
6346
6431
  gemini: GMN_BASE_URLS.gemini,
6347
6432
  opencode: openaiBaseUrl
6348
6433
  };
6349
- console.log(chalk47.cyan("\u{1F680} \u5F00\u59CB\u914D\u7F6E GMN..."));
6350
- console.log(chalk47.gray(`\u5E73\u53F0: ${platforms.join(", ")}
6351
- `));
6434
+ console.log(chalk47.cyan(`
6435
+ ${renderStep(4, TOTAL_STEPS, "\u5F00\u59CB\u5199\u5165\u914D\u7F6E")}`));
6436
+ console.log(chalk47.gray(`\u5DF2\u9009\u62E9\u5E73\u53F0: ${platforms.join(", ")}`));
6437
+ if (platforms.includes("codex") || platforms.includes("opencode")) {
6438
+ console.log(chalk47.gray(`OpenAI \u7AEF\u70B9: ${openaiBaseUrl}`));
6439
+ }
6440
+ printWriteTargets(platforms);
6441
+ console.log();
6352
6442
  const ALL_TOOLS = {
6353
6443
  claude: { name: "Claude Code", manager: createClaudeManager() },
6354
6444
  codex: { name: "Codex", manager: createCodexManager() },
@@ -6359,19 +6449,23 @@ async function gmnCommand(apiKey, platformArg, domainArg) {
6359
6449
  platform,
6360
6450
  ...ALL_TOOLS[platform]
6361
6451
  }));
6452
+ let completed = 0;
6362
6453
  for (const { platform, name, manager } of tools) {
6363
6454
  try {
6455
+ console.log(chalk47.gray(`\u2192 \u914D\u7F6E ${name}...`));
6364
6456
  const baseUrl = platformBaseUrls[platform];
6365
6457
  const existing = manager.findByName(PROVIDER_NAME);
6366
6458
  const provider = existing ? manager.edit(existing.id, { baseUrl, apiKey: resolvedApiKey }) : manager.add({ name: PROVIDER_NAME, baseUrl, apiKey: resolvedApiKey });
6367
6459
  manager.switch(provider.id);
6460
+ completed += 1;
6368
6461
  console.log(chalk47.green(`\u2705 ${name}`));
6369
6462
  } catch (error) {
6370
6463
  console.error(chalk47.red(`\u274C ${name}: ${error.message}`));
6371
6464
  }
6372
6465
  }
6373
- console.log(chalk47.green("\n\u{1F389} GMN \u914D\u7F6E\u5B8C\u6210\uFF01"));
6374
- console.log(chalk47.gray("\u63D0\u793A\uFF1A\u8BF7\u91CD\u542F\u5BF9\u5E94\u7684\u5DE5\u5177\u4EE5\u4F7F\u914D\u7F6E\u751F\u6548\u3002"));
6466
+ console.log(chalk47.green(`
6467
+ \u{1F389} GMN \u914D\u7F6E\u5B8C\u6210\uFF01(${completed}/${tools.length})`));
6468
+ console.log(chalk47.gray("\u63D0\u793A\uFF1A\u8BF7\u91CD\u542F\u5BF9\u5E94\u5DE5\u5177/\u63D2\u4EF6\u4EE5\u4F7F\u914D\u7F6E\u751F\u6548\u3002"));
6375
6469
  }
6376
6470
 
6377
6471
  // src/index.ts
@@ -0,0 +1,38 @@
1
+ {
2
+ "provider": {
3
+ "openai": {
4
+ "options": {
5
+ "baseURL": "{{baseUrl}}",
6
+ "apiKey": "{{apiKey}}"
7
+ },
8
+ "models": {
9
+ "gpt-5.2-codex": {
10
+ "name": "GPT-5.2 Codex",
11
+ "options": {
12
+ "store": false
13
+ },
14
+ "variants": {
15
+ "low": {},
16
+ "medium": {},
17
+ "high": {},
18
+ "xhigh": {}
19
+ }
20
+ }
21
+ }
22
+ }
23
+ },
24
+ "agent": {
25
+ "build": {
26
+ "options": {
27
+ "store": false
28
+ }
29
+ },
30
+ "plan": {
31
+ "options": {
32
+ "store": false
33
+ }
34
+ }
35
+ },
36
+ "$schema": "https://opencode.ai/config.json",
37
+ "model": "openai/gpt-5.2-codex"
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccman",
3
- "version": "3.3.3",
3
+ "version": "3.3.5",
4
4
  "type": "module",
5
5
  "description": "Manage Codex, Claude Code, Gemini CLI, OpenCode, and MCP API service provider configurations",
6
6
  "main": "./dist/index.js",