ccman 3.1.0 → 3.1.2

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.
Files changed (2) hide show
  1. package/dist/index.js +248 -166
  2. package/package.json +1 -1
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.1.0",
18
+ version: "3.1.2",
19
19
  type: "module",
20
20
  description: "Core business logic for ccman",
21
21
  main: "./dist/index.js",
@@ -65,6 +65,59 @@ var init_package = __esm({
65
65
  }
66
66
  });
67
67
 
68
+ // ../core/dist/constants.js
69
+ var TOOL_TYPES, MAIN_TOOL_TYPES, TOOL_CONFIG;
70
+ var init_constants = __esm({
71
+ "../core/dist/constants.js"() {
72
+ "use strict";
73
+ TOOL_TYPES = {
74
+ CODEX: "codex",
75
+ CLAUDE: "claude",
76
+ MCP: "mcp",
77
+ GEMINI: "gemini"
78
+ };
79
+ MAIN_TOOL_TYPES = {
80
+ CODEX: TOOL_TYPES.CODEX,
81
+ CLAUDE: TOOL_TYPES.CLAUDE,
82
+ GEMINI: TOOL_TYPES.GEMINI
83
+ };
84
+ TOOL_CONFIG = {
85
+ [TOOL_TYPES.CODEX]: {
86
+ displayName: "Codex",
87
+ color: "blue",
88
+ textColorClass: "text-blue-600",
89
+ bgColorClass: "bg-blue-50",
90
+ hoverBgColorClass: "hover:bg-blue-100",
91
+ description: "Codex AI \u52A9\u624B"
92
+ },
93
+ [TOOL_TYPES.CLAUDE]: {
94
+ displayName: "Claude Code",
95
+ color: "purple",
96
+ textColorClass: "text-purple-600",
97
+ bgColorClass: "bg-purple-50",
98
+ hoverBgColorClass: "hover:bg-purple-100",
99
+ description: "Claude Code AI \u52A9\u624B"
100
+ },
101
+ [TOOL_TYPES.MCP]: {
102
+ displayName: "MCP",
103
+ color: "gray",
104
+ textColorClass: "text-gray-600",
105
+ bgColorClass: "bg-gray-50",
106
+ hoverBgColorClass: "hover:bg-gray-100",
107
+ description: "MCP \u670D\u52A1"
108
+ },
109
+ [TOOL_TYPES.GEMINI]: {
110
+ displayName: "Gemini CLI",
111
+ color: "green",
112
+ textColorClass: "text-green-600",
113
+ bgColorClass: "bg-green-50",
114
+ hoverBgColorClass: "hover:bg-green-100",
115
+ description: "Gemini CLI AI \u52A9\u624B"
116
+ }
117
+ };
118
+ }
119
+ });
120
+
68
121
  // ../core/dist/paths.js
69
122
  import * as os from "os";
70
123
  import * as path from "path";
@@ -740,8 +793,28 @@ function writeGeminiConfig(provider) {
740
793
  } else {
741
794
  delete env.GEMINI_API_KEY;
742
795
  }
796
+ let modelMeta = null;
743
797
  if (provider.model && provider.model.trim().length > 0) {
744
- env.GEMINI_MODEL = provider.model;
798
+ try {
799
+ const parsed = JSON.parse(provider.model);
800
+ if (parsed && typeof parsed === "object") {
801
+ modelMeta = parsed;
802
+ }
803
+ } catch {
804
+ env.GEMINI_MODEL = provider.model;
805
+ }
806
+ }
807
+ if (modelMeta) {
808
+ if (modelMeta.env && typeof modelMeta.env === "object") {
809
+ for (const [key, value] of Object.entries(modelMeta.env)) {
810
+ if (typeof value === "string") {
811
+ env[key] = value;
812
+ }
813
+ }
814
+ }
815
+ if (!env.GEMINI_MODEL && modelMeta.defaultModel) {
816
+ env.GEMINI_MODEL = modelMeta.defaultModel;
817
+ }
745
818
  }
746
819
  saveEnvFile(envPath, env);
747
820
  }
@@ -1510,87 +1583,77 @@ import fs8 from "fs";
1510
1583
  import path8 from "path";
1511
1584
  async function uploadToCloud(config, password) {
1512
1585
  const ccmanDir2 = getCcmanDir();
1513
- const codexConfigPath = path8.join(ccmanDir2, "codex.json");
1514
- const claudeConfigPath = path8.join(ccmanDir2, "claude.json");
1515
- const codexConfig = readJSON(codexConfigPath);
1516
- const claudeConfig = readJSON(claudeConfigPath);
1517
- const encryptedCodexProviders = encryptProviders(codexConfig.providers, password);
1518
- const encryptedClaudeProviders = encryptProviders(claudeConfig.providers, password);
1519
- const encryptedCodexConfig = {
1520
- ...codexConfig,
1521
- // 保留所有字段
1522
- providers: encryptedCodexProviders
1523
- // 只替换 providers(加密后的)
1524
- };
1525
- const encryptedClaudeConfig = {
1526
- ...claudeConfig,
1527
- // 保留所有字段
1528
- providers: encryptedClaudeProviders
1529
- // 只替换 providers(加密后的)
1530
- };
1531
- const codexJson = JSON.stringify(encryptedCodexConfig, null, 2);
1532
- const claudeJson = JSON.stringify(encryptedClaudeConfig, null, 2);
1533
- await uploadToWebDAV(config, CODEX_REMOTE_PATH, codexJson);
1534
- await uploadToWebDAV(config, CLAUDE_REMOTE_PATH, claudeJson);
1586
+ const toolKeys = Object.keys(TOOL_SYNC_CONFIG);
1587
+ for (const tool of toolKeys) {
1588
+ const { remotePath, configFilename } = TOOL_SYNC_CONFIG[tool];
1589
+ const configPath = path8.join(ccmanDir2, configFilename);
1590
+ const localConfig = readJSON(configPath);
1591
+ const encryptedProviders = encryptProviders(localConfig.providers, password);
1592
+ const encryptedConfig = {
1593
+ ...localConfig,
1594
+ // 保留所有字段
1595
+ providers: encryptedProviders
1596
+ // 只替换 providers(加密后的)
1597
+ };
1598
+ const jsonContent = JSON.stringify(encryptedConfig, null, 2);
1599
+ await uploadToWebDAV(config, remotePath, jsonContent);
1600
+ }
1535
1601
  updateLastSyncTime();
1536
1602
  console.log("\u2705 \u914D\u7F6E\u5DF2\u4E0A\u4F20\u5230\u4E91\u7AEF");
1537
1603
  }
1538
1604
  async function downloadFromCloud(config, password) {
1539
- const codexExists = await existsOnWebDAV(config, CODEX_REMOTE_PATH);
1540
- const claudeExists = await existsOnWebDAV(config, CLAUDE_REMOTE_PATH);
1541
- if (!codexExists && !claudeExists) {
1605
+ const ccmanDir2 = getCcmanDir();
1606
+ const toolKeys = Object.keys(TOOL_SYNC_CONFIG);
1607
+ const existsChecks = await Promise.all(toolKeys.map(async (tool) => {
1608
+ const { remotePath } = TOOL_SYNC_CONFIG[tool];
1609
+ return existsOnWebDAV(config, remotePath);
1610
+ }));
1611
+ if (!existsChecks.some((exists) => exists)) {
1542
1612
  throw new Error("\u8FDC\u7A0B\u914D\u7F6E\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u4E0A\u4F20\u914D\u7F6E");
1543
1613
  }
1544
- const codexJson = codexExists ? await downloadFromWebDAV(config, CODEX_REMOTE_PATH) : null;
1545
- const claudeJson = claudeExists ? await downloadFromWebDAV(config, CLAUDE_REMOTE_PATH) : null;
1546
- const remoteCodexConfig = codexJson ? JSON.parse(codexJson) : null;
1547
- const remoteClaudeConfig = claudeJson ? JSON.parse(claudeJson) : null;
1548
- let decryptedCodexProviders = null;
1549
- let decryptedClaudeProviders = null;
1550
- try {
1551
- if (remoteCodexConfig) {
1552
- decryptedCodexProviders = decryptProviders(remoteCodexConfig.providers, password);
1553
- }
1554
- if (remoteClaudeConfig) {
1555
- decryptedClaudeProviders = decryptProviders(remoteClaudeConfig.providers, password);
1614
+ const remoteConfigs = [];
1615
+ for (let i = 0; i < toolKeys.length; i++) {
1616
+ const tool = toolKeys[i];
1617
+ const { remotePath } = TOOL_SYNC_CONFIG[tool];
1618
+ if (existsChecks[i]) {
1619
+ const jsonContent = await downloadFromWebDAV(config, remotePath);
1620
+ const remoteConfig = JSON.parse(jsonContent);
1621
+ try {
1622
+ const decryptedProviders = decryptProviders(remoteConfig.providers, password);
1623
+ remoteConfigs.push({ tool, config: remoteConfig, decryptedProviders });
1624
+ } catch (error) {
1625
+ throw new Error("\u89E3\u5BC6\u5931\u8D25\uFF1A\u5BC6\u7801\u9519\u8BEF\u6216\u6570\u636E\u635F\u574F");
1626
+ }
1627
+ } else {
1628
+ remoteConfigs.push({ tool, config: null, decryptedProviders: null });
1556
1629
  }
1557
- } catch (error) {
1558
- throw new Error("\u89E3\u5BC6\u5931\u8D25\uFF1A\u5BC6\u7801\u9519\u8BEF\u6216\u6570\u636E\u635F\u574F");
1559
1630
  }
1560
1631
  const backupPaths = [];
1561
- const ccmanDir2 = getCcmanDir();
1562
- const codexConfigPath = path8.join(ccmanDir2, "codex.json");
1563
- const claudeConfigPath = path8.join(ccmanDir2, "claude.json");
1564
1632
  try {
1565
- if (fs8.existsSync(codexConfigPath)) {
1566
- backupPaths.push(backupConfig(codexConfigPath));
1567
- }
1568
- if (fs8.existsSync(claudeConfigPath)) {
1569
- backupPaths.push(backupConfig(claudeConfigPath));
1633
+ for (const tool of toolKeys) {
1634
+ const { configFilename } = TOOL_SYNC_CONFIG[tool];
1635
+ const configPath = path8.join(ccmanDir2, configFilename);
1636
+ if (fs8.existsSync(configPath)) {
1637
+ backupPaths.push(backupConfig(configPath));
1638
+ }
1570
1639
  }
1571
1640
  } catch (error) {
1572
1641
  throw new Error(`\u5907\u4EFD\u5931\u8D25: ${error.message}`);
1573
1642
  }
1574
1643
  try {
1575
- if (remoteCodexConfig && decryptedCodexProviders) {
1576
- const newCodexConfig = {
1577
- ...remoteCodexConfig,
1578
- // 使用云端配置的所有字段
1579
- providers: decryptedCodexProviders
1580
- // 只替换 providers(解密后的)
1581
- };
1582
- writeJSON(codexConfigPath, newCodexConfig);
1583
- applyCurrentProvider("codex", newCodexConfig);
1584
- }
1585
- if (remoteClaudeConfig && decryptedClaudeProviders) {
1586
- const newClaudeConfig = {
1587
- ...remoteClaudeConfig,
1644
+ for (const { tool, config: remoteConfig, decryptedProviders } of remoteConfigs) {
1645
+ if (!remoteConfig || !decryptedProviders)
1646
+ continue;
1647
+ const { configFilename } = TOOL_SYNC_CONFIG[tool];
1648
+ const configPath = path8.join(ccmanDir2, configFilename);
1649
+ const newConfig = {
1650
+ ...remoteConfig,
1588
1651
  // 使用云端配置的所有字段
1589
- providers: decryptedClaudeProviders
1652
+ providers: decryptedProviders
1590
1653
  // 只替换 providers(解密后的)
1591
1654
  };
1592
- writeJSON(claudeConfigPath, newClaudeConfig);
1593
- applyCurrentProvider("claude", newClaudeConfig);
1655
+ writeJSON(configPath, newConfig);
1656
+ applyCurrentProvider(tool, newConfig);
1594
1657
  }
1595
1658
  updateLastSyncTime();
1596
1659
  console.log("\u2705 \u914D\u7F6E\u5DF2\u4ECE\u4E91\u7AEF\u4E0B\u8F7D\u5E76\u5E94\u7528");
@@ -1606,9 +1669,13 @@ async function downloadFromCloud(config, password) {
1606
1669
  }
1607
1670
  }
1608
1671
  async function mergeSync(config, password) {
1609
- const codexExists = await existsOnWebDAV(config, CODEX_REMOTE_PATH);
1610
- const claudeExists = await existsOnWebDAV(config, CLAUDE_REMOTE_PATH);
1611
- if (!codexExists && !claudeExists) {
1672
+ const ccmanDir2 = getCcmanDir();
1673
+ const toolKeys = Object.keys(TOOL_SYNC_CONFIG);
1674
+ const existsChecks = await Promise.all(toolKeys.map(async (tool) => {
1675
+ const { remotePath } = TOOL_SYNC_CONFIG[tool];
1676
+ return existsOnWebDAV(config, remotePath);
1677
+ }));
1678
+ if (!existsChecks.some((exists) => exists)) {
1612
1679
  console.log("\u8FDC\u7A0B\u914D\u7F6E\u4E0D\u5B58\u5728\uFF0C\u6267\u884C\u4E0A\u4F20\u64CD\u4F5C");
1613
1680
  await uploadToCloud(config, password);
1614
1681
  return {
@@ -1616,30 +1683,31 @@ async function mergeSync(config, password) {
1616
1683
  backupPaths: []
1617
1684
  };
1618
1685
  }
1619
- const codexJson = codexExists ? await downloadFromWebDAV(config, CODEX_REMOTE_PATH) : null;
1620
- const claudeJson = claudeExists ? await downloadFromWebDAV(config, CLAUDE_REMOTE_PATH) : null;
1621
- const remoteCodexConfig = codexJson ? JSON.parse(codexJson) : null;
1622
- const remoteClaudeConfig = claudeJson ? JSON.parse(claudeJson) : null;
1623
- let remoteCodexProviders = [];
1624
- let remoteClaudeProviders = [];
1625
- try {
1626
- if (remoteCodexConfig) {
1627
- remoteCodexProviders = decryptProviders(remoteCodexConfig.providers, password);
1628
- }
1629
- if (remoteClaudeConfig) {
1630
- remoteClaudeProviders = decryptProviders(remoteClaudeConfig.providers, password);
1686
+ const mergeDataList = [];
1687
+ for (let i = 0; i < toolKeys.length; i++) {
1688
+ const tool = toolKeys[i];
1689
+ const { remotePath, configFilename } = TOOL_SYNC_CONFIG[tool];
1690
+ const configPath = path8.join(ccmanDir2, configFilename);
1691
+ const localConfig = readJSON(configPath);
1692
+ let remoteProviders = [];
1693
+ if (existsChecks[i]) {
1694
+ try {
1695
+ const jsonContent = await downloadFromWebDAV(config, remotePath);
1696
+ const remoteConfig = JSON.parse(jsonContent);
1697
+ remoteProviders = decryptProviders(remoteConfig.providers, password);
1698
+ } catch (error) {
1699
+ throw new Error("\u89E3\u5BC6\u5931\u8D25\uFF1A\u5BC6\u7801\u9519\u8BEF\u6216\u6570\u636E\u635F\u574F");
1700
+ }
1631
1701
  }
1632
- } catch (error) {
1633
- throw new Error("\u89E3\u5BC6\u5931\u8D25\uFF1A\u5BC6\u7801\u9519\u8BEF\u6216\u6570\u636E\u635F\u574F");
1702
+ const mergeResult = mergeProviders(localConfig.providers, remoteProviders);
1703
+ mergeDataList.push({
1704
+ tool,
1705
+ localConfig,
1706
+ remoteProviders,
1707
+ mergeResult
1708
+ });
1634
1709
  }
1635
- const ccmanDir2 = getCcmanDir();
1636
- const codexConfigPath = path8.join(ccmanDir2, "codex.json");
1637
- const claudeConfigPath = path8.join(ccmanDir2, "claude.json");
1638
- const localCodexConfig = readJSON(codexConfigPath);
1639
- const localClaudeConfig = readJSON(claudeConfigPath);
1640
- const codexMergeResult = mergeProviders(localCodexConfig.providers, remoteCodexProviders);
1641
- const claudeMergeResult = mergeProviders(localClaudeConfig.providers, remoteClaudeProviders);
1642
- const hasChanges = codexMergeResult.hasChanges || claudeMergeResult.hasChanges;
1710
+ const hasChanges = mergeDataList.some((data) => data.mergeResult.hasChanges);
1643
1711
  if (!hasChanges) {
1644
1712
  console.log("\u2139\uFE0F \u914D\u7F6E\u5DF2\u540C\u6B65\uFF0C\u65E0\u9700\u64CD\u4F5C");
1645
1713
  return {
@@ -1649,56 +1717,47 @@ async function mergeSync(config, password) {
1649
1717
  }
1650
1718
  const backupPaths = [];
1651
1719
  try {
1652
- if (fs8.existsSync(codexConfigPath)) {
1653
- backupPaths.push(backupConfig(codexConfigPath));
1654
- }
1655
- if (fs8.existsSync(claudeConfigPath)) {
1656
- backupPaths.push(backupConfig(claudeConfigPath));
1720
+ for (const tool of toolKeys) {
1721
+ const { configFilename } = TOOL_SYNC_CONFIG[tool];
1722
+ const configPath = path8.join(ccmanDir2, configFilename);
1723
+ if (fs8.existsSync(configPath)) {
1724
+ backupPaths.push(backupConfig(configPath));
1725
+ }
1657
1726
  }
1658
1727
  } catch (error) {
1659
1728
  throw new Error(`\u5907\u4EFD\u5931\u8D25: ${error.message}`);
1660
1729
  }
1661
- const mergedCodexPresets = mergePresets(localCodexConfig.presets, remoteCodexConfig?.presets);
1662
- const mergedClaudePresets = mergePresets(localClaudeConfig.presets, remoteClaudeConfig?.presets);
1663
1730
  try {
1664
- const mergedCodexConfig = {
1665
- ...localCodexConfig,
1666
- // 保留本地配置的所有字段
1667
- providers: codexMergeResult.merged,
1668
- // 替换为合并后的 providers
1669
- presets: mergedCodexPresets
1670
- // 替换为合并后的 presets
1671
- };
1672
- const mergedClaudeConfig = {
1673
- ...localClaudeConfig,
1674
- // 保留本地配置的所有字段
1675
- providers: claudeMergeResult.merged,
1676
- // 替换为合并后的 providers
1677
- presets: mergedClaudePresets
1678
- // 替换为合并后的 presets
1679
- };
1680
- writeJSON(codexConfigPath, mergedCodexConfig);
1681
- writeJSON(claudeConfigPath, mergedClaudeConfig);
1682
- applyCurrentProvider("codex", mergedCodexConfig);
1683
- applyCurrentProvider("claude", mergedClaudeConfig);
1684
- const encryptedCodexProviders = encryptProviders(codexMergeResult.merged, password);
1685
- const encryptedClaudeProviders = encryptProviders(claudeMergeResult.merged, password);
1686
- const encryptedCodexConfig = {
1687
- ...mergedCodexConfig,
1688
- // 保留合并后配置的所有字段
1689
- providers: encryptedCodexProviders
1690
- // 只替换 providers(加密后的)
1691
- };
1692
- const encryptedClaudeConfig = {
1693
- ...mergedClaudeConfig,
1694
- // 保留合并后配置的所有字段
1695
- providers: encryptedClaudeProviders
1696
- // 只替换 providers(加密后的)
1697
- };
1698
- const codexJson2 = JSON.stringify(encryptedCodexConfig, null, 2);
1699
- const claudeJson2 = JSON.stringify(encryptedClaudeConfig, null, 2);
1700
- await uploadToWebDAV(config, CODEX_REMOTE_PATH, codexJson2);
1701
- await uploadToWebDAV(config, CLAUDE_REMOTE_PATH, claudeJson2);
1731
+ for (let i = 0; i < mergeDataList.length; i++) {
1732
+ const { tool, localConfig, mergeResult } = mergeDataList[i];
1733
+ const { remotePath, configFilename } = TOOL_SYNC_CONFIG[tool];
1734
+ const configPath = path8.join(ccmanDir2, configFilename);
1735
+ let remoteConfig = null;
1736
+ if (existsChecks[i]) {
1737
+ const jsonContent2 = await downloadFromWebDAV(config, remotePath);
1738
+ remoteConfig = JSON.parse(jsonContent2);
1739
+ }
1740
+ const mergedPresets = mergePresets(localConfig.presets, remoteConfig?.presets);
1741
+ const mergedConfig = {
1742
+ ...localConfig,
1743
+ // 保留本地配置的所有字段
1744
+ providers: mergeResult.merged,
1745
+ // 替换为合并后的 providers
1746
+ presets: mergedPresets
1747
+ // 替换为合并后的 presets
1748
+ };
1749
+ writeJSON(configPath, mergedConfig);
1750
+ applyCurrentProvider(tool, mergedConfig);
1751
+ const encryptedProviders = encryptProviders(mergeResult.merged, password);
1752
+ const encryptedConfig = {
1753
+ ...mergedConfig,
1754
+ // 保留合并后配置的所有字段
1755
+ providers: encryptedProviders
1756
+ // 只替换 providers(加密后的)
1757
+ };
1758
+ const jsonContent = JSON.stringify(encryptedConfig, null, 2);
1759
+ await uploadToWebDAV(config, remotePath, jsonContent);
1760
+ }
1702
1761
  updateLastSyncTime();
1703
1762
  console.log("\u2705 \u914D\u7F6E\u5DF2\u5408\u5E76\u5E76\u540C\u6B65\u5230\u4E91\u7AEF");
1704
1763
  return {
@@ -1723,13 +1782,10 @@ function applyCurrentProvider(tool, config) {
1723
1782
  if (!provider) {
1724
1783
  return;
1725
1784
  }
1726
- if (tool === "codex") {
1727
- writeCodexConfig(provider);
1728
- } else {
1729
- writeClaudeConfig(provider);
1730
- }
1785
+ const { writerFunc } = TOOL_SYNC_CONFIG[tool];
1786
+ writerFunc(provider);
1731
1787
  }
1732
- var CODEX_REMOTE_PATH, CLAUDE_REMOTE_PATH;
1788
+ var TOOL_SYNC_CONFIG;
1733
1789
  var init_sync_v2 = __esm({
1734
1790
  "../core/dist/sync/sync-v2.js"() {
1735
1791
  "use strict";
@@ -1742,8 +1798,25 @@ var init_sync_v2 = __esm({
1742
1798
  init_file();
1743
1799
  init_codex();
1744
1800
  init_claude();
1745
- CODEX_REMOTE_PATH = ".ccman/codex.json";
1746
- CLAUDE_REMOTE_PATH = ".ccman/claude.json";
1801
+ init_gemini2();
1802
+ init_constants();
1803
+ TOOL_SYNC_CONFIG = {
1804
+ [MAIN_TOOL_TYPES.CODEX]: {
1805
+ remotePath: ".ccman/codex.json",
1806
+ configFilename: "codex.json",
1807
+ writerFunc: writeCodexConfig
1808
+ },
1809
+ [MAIN_TOOL_TYPES.CLAUDE]: {
1810
+ remotePath: ".ccman/claude.json",
1811
+ configFilename: "claude.json",
1812
+ writerFunc: writeClaudeConfig
1813
+ },
1814
+ [MAIN_TOOL_TYPES.GEMINI]: {
1815
+ remotePath: ".ccman/gemini.json",
1816
+ configFilename: "gemini.json",
1817
+ writerFunc: writeGeminiConfig
1818
+ }
1819
+ };
1747
1820
  }
1748
1821
  });
1749
1822
 
@@ -2057,6 +2130,7 @@ var init_dist = __esm({
2057
2130
  "../core/dist/index.js"() {
2058
2131
  "use strict";
2059
2132
  init_package();
2133
+ init_constants();
2060
2134
  init_tool_manager();
2061
2135
  init_codex2();
2062
2136
  init_claude2();
@@ -2844,11 +2918,21 @@ function formatProviderTable(providers, currentId) {
2844
2918
  }
2845
2919
 
2846
2920
  // src/interactive.ts
2847
- var TOOL_CONFIG = {
2848
- codex: { name: "Codex", emoji: "\u{1F536}", cmd: "cx" },
2849
- claude: { name: "Claude", emoji: "\u{1F537}", cmd: "cc" },
2850
- gemini: { name: "Gemini", emoji: "\u{1F48E}", cmd: "gm" }
2921
+ var CLI_TOOL_CONFIG = {
2922
+ [TOOL_TYPES.CODEX]: { name: "Codex", emoji: "\u{1F536}", cmd: "cx" },
2923
+ [TOOL_TYPES.CLAUDE]: { name: "Claude", emoji: "\u{1F537}", cmd: "cc" },
2924
+ [TOOL_TYPES.GEMINI]: { name: "Gemini", emoji: "\u{1F48E}", cmd: "gm" }
2851
2925
  };
2926
+ function getManager(tool) {
2927
+ switch (tool) {
2928
+ case TOOL_TYPES.CODEX:
2929
+ return createCodexManager();
2930
+ case TOOL_TYPES.CLAUDE:
2931
+ return createClaudeManager();
2932
+ case TOOL_TYPES.GEMINI:
2933
+ return createGeminiManager();
2934
+ }
2935
+ }
2852
2936
  async function promptProviderForm(defaults) {
2853
2937
  const answers = await inquirer7.prompt([
2854
2938
  {
@@ -2936,16 +3020,16 @@ async function startMainMenu() {
2936
3020
  }
2937
3021
  }
2938
3022
  async function startClaudeMenu() {
2939
- await showToolMenu("claude");
3023
+ await showToolMenu(TOOL_TYPES.CLAUDE);
2940
3024
  }
2941
3025
  async function startCodexMenu() {
2942
- await showToolMenu("codex");
3026
+ await showToolMenu(TOOL_TYPES.CODEX);
2943
3027
  }
2944
3028
  async function startGeminiMenu() {
2945
- await showToolMenu("gemini");
3029
+ await showToolMenu(TOOL_TYPES.GEMINI);
2946
3030
  }
2947
3031
  async function showToolMenu(tool) {
2948
- const { name: toolName, emoji: toolEmoji } = TOOL_CONFIG[tool];
3032
+ const { name: toolName, emoji: toolEmoji } = CLI_TOOL_CONFIG[tool];
2949
3033
  while (true) {
2950
3034
  console.log();
2951
3035
  const { action } = await inquirer7.prompt([
@@ -2959,7 +3043,7 @@ async function showToolMenu(tool) {
2959
3043
  { name: "\u{1F4CB} \u5217\u51FA\u6240\u6709\u670D\u52A1\u5546", value: "list" },
2960
3044
  { name: "\u{1F441}\uFE0F \u67E5\u770B\u5F53\u524D\u670D\u52A1\u5546", value: "current" },
2961
3045
  { name: "\u270F\uFE0F \u7F16\u8F91\u670D\u52A1\u5546", value: "edit" },
2962
- { name: "\u{1F4CB} \u514B\u9686\u670D\u52A1\u5546", value: "clone" },
3046
+ { name: "\u{1F501} \u514B\u9686\u670D\u52A1\u5546", value: "clone" },
2963
3047
  { name: "\u{1F5D1}\uFE0F \u5220\u9664\u670D\u52A1\u5546", value: "remove" },
2964
3048
  { name: "\u2B05\uFE0F \u8FD4\u56DE\u4E0A\u7EA7", value: "back" }
2965
3049
  ]
@@ -3010,8 +3094,8 @@ async function showPresetsMenu() {
3010
3094
  console.log(chalk11.yellow("\n\u26A0\uFE0F \u9884\u7F6E\u670D\u52A1\u5546\u7BA1\u7406\u529F\u80FD\u5373\u5C06\u63A8\u51FA\n"));
3011
3095
  }
3012
3096
  async function handleAdd(tool) {
3013
- const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3014
- const { name: toolName, cmd } = TOOL_CONFIG[tool];
3097
+ const manager = getManager(tool);
3098
+ const { name: toolName, cmd } = CLI_TOOL_CONFIG[tool];
3015
3099
  const presets = manager.listPresets();
3016
3100
  console.log(chalk11.bold(`
3017
3101
  \u{1F4DD} \u6DFB\u52A0 ${toolName} \u670D\u52A1\u5546
@@ -3109,14 +3193,12 @@ async function handleAdd(tool) {
3109
3193
  manager.switch(provider.id);
3110
3194
  console.log(chalk11.green("\u2705 \u5DF2\u5207\u6362\u5230\u65B0\u670D\u52A1\u5546\n"));
3111
3195
  } else {
3112
- console.log(
3113
- chalk11.blue("\u{1F4A1} \u7A0D\u540E\u5207\u6362:") + chalk11.white(` ccman ${cmd} use "${provider.name}"
3114
- `)
3115
- );
3196
+ console.log(chalk11.blue("\u{1F4A1} \u7A0D\u540E\u5207\u6362:") + chalk11.white(` ccman ${cmd} use "${provider.name}"
3197
+ `));
3116
3198
  }
3117
3199
  }
3118
3200
  async function handleSwitch(tool) {
3119
- const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3201
+ const manager = getManager(tool);
3120
3202
  const providers = manager.list();
3121
3203
  const current = manager.getCurrent();
3122
3204
  if (providers.length === 0) {
@@ -3141,10 +3223,10 @@ async function handleSwitch(tool) {
3141
3223
  `));
3142
3224
  }
3143
3225
  async function handleList(tool) {
3144
- const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3226
+ const manager = getManager(tool);
3145
3227
  const providers = manager.list();
3146
3228
  const current = manager.getCurrent();
3147
- const { name: toolName } = TOOL_CONFIG[tool];
3229
+ const { name: toolName } = CLI_TOOL_CONFIG[tool];
3148
3230
  if (providers.length === 0) {
3149
3231
  console.log(chalk11.yellow(`
3150
3232
  \u26A0\uFE0F \u6682\u65E0 ${toolName} \u670D\u52A1\u5546
@@ -3156,9 +3238,9 @@ async function handleList(tool) {
3156
3238
  console.log(formatProviderTable(providers, current?.id));
3157
3239
  }
3158
3240
  async function handleCurrent(tool) {
3159
- const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3241
+ const manager = getManager(tool);
3160
3242
  const current = manager.getCurrent();
3161
- const { name: toolName } = TOOL_CONFIG[tool];
3243
+ const { name: toolName } = CLI_TOOL_CONFIG[tool];
3162
3244
  if (!current) {
3163
3245
  console.log(chalk11.yellow(`
3164
3246
  \u26A0\uFE0F \u672A\u9009\u62E9\u4EFB\u4F55 ${toolName} \u670D\u52A1\u5546
@@ -3177,7 +3259,7 @@ async function handleCurrent(tool) {
3177
3259
  console.log();
3178
3260
  }
3179
3261
  async function handleEdit(tool) {
3180
- const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3262
+ const manager = getManager(tool);
3181
3263
  const providers = manager.list();
3182
3264
  if (providers.length === 0) {
3183
3265
  console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
@@ -3238,7 +3320,7 @@ async function handleEdit(tool) {
3238
3320
  console.log(chalk11.green("\n\u2705 \u7F16\u8F91\u6210\u529F\n"));
3239
3321
  }
3240
3322
  async function handleClone(tool) {
3241
- const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3323
+ const manager = getManager(tool);
3242
3324
  const providers = manager.list();
3243
3325
  if (providers.length === 0) {
3244
3326
  console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
@@ -3285,7 +3367,7 @@ async function handleClone(tool) {
3285
3367
  console.log();
3286
3368
  }
3287
3369
  async function handleRemove(tool) {
3288
- const manager = tool === "codex" ? createCodexManager() : tool === "claude" ? createClaudeManager() : createGeminiManager();
3370
+ const manager = getManager(tool);
3289
3371
  const providers = manager.list();
3290
3372
  if (providers.length === 0) {
3291
3373
  console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccman",
3
- "version": "3.1.0",
3
+ "version": "3.1.2",
4
4
  "type": "module",
5
5
  "description": "Manage Codex and Claude Code API service provider configurations",
6
6
  "main": "./dist/index.js",