ccman 3.0.20 → 3.0.22

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 +108 -120
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -39,7 +39,7 @@ var init_package = __esm({
39
39
  "../core/package.json"() {
40
40
  package_default = {
41
41
  name: "@ccman/core",
42
- version: "3.0.20",
42
+ version: "3.0.22",
43
43
  type: "module",
44
44
  description: "Core business logic for ccman",
45
45
  main: "./dist/index.js",
@@ -16309,24 +16309,14 @@ function decryptApiKey(encryptedApiKey, password) {
16309
16309
  }
16310
16310
  function encryptProviders(providers, password) {
16311
16311
  return providers.map((provider) => ({
16312
- id: provider.id,
16313
- name: provider.name,
16314
- baseUrl: provider.baseUrl,
16315
- encryptedApiKey: encryptApiKey(provider.apiKey, password),
16316
- createdAt: provider.createdAt,
16317
- lastModified: provider.lastModified,
16318
- lastUsedAt: provider.lastUsedAt
16312
+ ...provider,
16313
+ apiKey: encryptApiKey(provider.apiKey, password)
16319
16314
  }));
16320
16315
  }
16321
16316
  function decryptProviders(encryptedProviders, password) {
16322
16317
  return encryptedProviders.map((provider) => ({
16323
- id: provider.id,
16324
- name: provider.name,
16325
- baseUrl: provider.baseUrl,
16326
- apiKey: decryptApiKey(provider.encryptedApiKey, password),
16327
- createdAt: provider.createdAt,
16328
- lastModified: provider.lastModified,
16329
- lastUsedAt: provider.lastUsedAt
16318
+ ...provider,
16319
+ apiKey: decryptApiKey(provider.apiKey, password)
16330
16320
  }));
16331
16321
  }
16332
16322
  var crypto, ALGORITHM, KEY_LENGTH, IV_LENGTH, SALT_LENGTH, TAG_LENGTH, PBKDF2_ITERATIONS;
@@ -16344,15 +16334,6 @@ var init_crypto2 = __esm({
16344
16334
  });
16345
16335
 
16346
16336
  // ../core/dist/sync/merge-advanced.js
16347
- function ensureLastModified(provider) {
16348
- if (provider.lastModified === void 0) {
16349
- return {
16350
- ...provider,
16351
- lastModified: provider.createdAt
16352
- };
16353
- }
16354
- return provider;
16355
- }
16356
16337
  function isSameConfig(a, b) {
16357
16338
  return a.baseUrl === b.baseUrl && a.apiKey === b.apiKey;
16358
16339
  }
@@ -16377,49 +16358,26 @@ function resolveNameConflict(existingProviders, newProvider) {
16377
16358
  };
16378
16359
  }
16379
16360
  function mergeProviders(local, remote) {
16380
- const localProviders = local.map(ensureLastModified);
16381
- const remoteProviders = remote.map(ensureLastModified);
16382
16361
  const mergedMap = /* @__PURE__ */ new Map();
16383
16362
  let hasChanges = false;
16384
- for (const localProvider of localProviders) {
16363
+ for (const localProvider of local) {
16385
16364
  mergedMap.set(localProvider.id, localProvider);
16386
16365
  }
16387
- for (const remoteProvider of remoteProviders) {
16388
- if (mergedMap.has(remoteProvider.id)) {
16389
- const localProvider = mergedMap.get(remoteProvider.id);
16390
- if (remoteProvider.lastModified > localProvider.lastModified) {
16391
- console.log(`provider ${remoteProvider.id} \u8FDC\u7A0B\u66F4\u65B0\uFF0C\u4F7F\u7528\u8FDC\u7A0B\u7248\u672C`);
16392
- mergedMap.set(remoteProvider.id, remoteProvider);
16393
- hasChanges = true;
16394
- } else if (remoteProvider.lastModified < localProvider.lastModified) {
16395
- console.log(`provider ${remoteProvider.id} \u672C\u5730\u66F4\u65B0\uFF0C\u4F7F\u7528\u672C\u5730\u7248\u672C`);
16366
+ for (const remoteProvider of remote) {
16367
+ const existingLocal = Array.from(mergedMap.values()).find((p) => isSameConfig(p, remoteProvider));
16368
+ if (existingLocal) {
16369
+ mergedMap.delete(existingLocal.id);
16370
+ mergedMap.set(remoteProvider.id, remoteProvider);
16371
+ if (!isProviderEqual(existingLocal, remoteProvider)) {
16396
16372
  hasChanges = true;
16397
- } else {
16398
- if (!isProviderEqual(localProvider, remoteProvider)) {
16399
- console.log(`provider ${remoteProvider.id} \u65F6\u95F4\u6233\u76F8\u540C\u4F46\u5185\u5BB9\u4E0D\u540C\uFF0C\u4F7F\u7528\u8FDC\u7A0B\u7248\u672C`);
16400
- mergedMap.set(remoteProvider.id, remoteProvider);
16401
- hasChanges = true;
16402
- }
16373
+ console.log(`\u76F8\u540C\u914D\u7F6E (${remoteProvider.baseUrl})\uFF0C\u4F7F\u7528\u4E91\u7AEF\u6570\u636E`);
16403
16374
  }
16404
16375
  } else {
16405
- const existingWithSameConfig = Array.from(mergedMap.values()).find((p) => isSameConfig(p, remoteProvider));
16406
- if (existingWithSameConfig) {
16407
- if (remoteProvider.lastModified > existingWithSameConfig.lastModified) {
16408
- console.log(`\u76F8\u540C\u914D\u7F6E (${remoteProvider.baseUrl})\uFF0C\u8FDC\u7A0B\u66F4\u65B0\uFF0C\u66FF\u6362 ${existingWithSameConfig.id} \u4E3A ${remoteProvider.id}`);
16409
- mergedMap.delete(existingWithSameConfig.id);
16410
- mergedMap.set(remoteProvider.id, remoteProvider);
16411
- hasChanges = true;
16412
- } else {
16413
- console.log(`\u76F8\u540C\u914D\u7F6E (${remoteProvider.baseUrl})\uFF0C\u672C\u5730\u66F4\u65B0\uFF0C\u4FDD\u7559 ${existingWithSameConfig.id}`);
16414
- hasChanges = true;
16415
- }
16416
- } else {
16417
- console.log(`\u65B0 provider ${remoteProvider.id}\uFF0C\u6DFB\u52A0\u5230\u5408\u5E76\u5217\u8868`);
16418
- const existingProviders = Array.from(mergedMap.values());
16419
- const resolvedProvider = resolveNameConflict(existingProviders, remoteProvider);
16420
- mergedMap.set(resolvedProvider.id, resolvedProvider);
16421
- hasChanges = true;
16422
- }
16376
+ const existingProviders = Array.from(mergedMap.values());
16377
+ const resolvedProvider = resolveNameConflict(existingProviders, remoteProvider);
16378
+ mergedMap.set(resolvedProvider.id, resolvedProvider);
16379
+ hasChanges = true;
16380
+ console.log(`\u65B0 provider ${resolvedProvider.name}\uFF0C\u6DFB\u52A0\u5230\u5408\u5E76\u5217\u8868`);
16423
16381
  }
16424
16382
  }
16425
16383
  const merged = Array.from(mergedMap.values());
@@ -16428,6 +16386,43 @@ function mergeProviders(local, remote) {
16428
16386
  hasChanges
16429
16387
  };
16430
16388
  }
16389
+ function resolvePresetNameConflict(existingPresets, newPreset) {
16390
+ const existingNames = new Set(existingPresets.map((p) => p.name));
16391
+ if (!existingNames.has(newPreset.name)) {
16392
+ return newPreset;
16393
+ }
16394
+ let suffix = 2;
16395
+ let newName = `${newPreset.name}_${suffix}`;
16396
+ while (existingNames.has(newName)) {
16397
+ suffix++;
16398
+ newName = `${newPreset.name}_${suffix}`;
16399
+ }
16400
+ console.log(`preset name \u51B2\u7A81\uFF1A\u5C06 "${newPreset.name}" \u91CD\u547D\u540D\u4E3A "${newName}"`);
16401
+ return {
16402
+ ...newPreset,
16403
+ name: newName
16404
+ };
16405
+ }
16406
+ function mergePresets(local, remote) {
16407
+ const localPresets = local || [];
16408
+ const remotePresets = remote || [];
16409
+ const mergedMap = /* @__PURE__ */ new Map();
16410
+ for (const preset of localPresets) {
16411
+ mergedMap.set(preset.baseUrl, preset);
16412
+ }
16413
+ for (const remotePreset of remotePresets) {
16414
+ const existingLocal = mergedMap.get(remotePreset.baseUrl);
16415
+ if (existingLocal) {
16416
+ mergedMap.set(remotePreset.baseUrl, remotePreset);
16417
+ console.log(`preset ${remotePreset.name} (${remotePreset.baseUrl})\uFF0C\u4F7F\u7528\u4E91\u7AEF\u6570\u636E`);
16418
+ } else {
16419
+ const existingPresets = Array.from(mergedMap.values());
16420
+ const resolvedPreset = resolvePresetNameConflict(existingPresets, remotePreset);
16421
+ mergedMap.set(resolvedPreset.baseUrl, resolvedPreset);
16422
+ }
16423
+ }
16424
+ return Array.from(mergedMap.values());
16425
+ }
16431
16426
  var init_merge_advanced = __esm({
16432
16427
  "../core/dist/sync/merge-advanced.js"() {
16433
16428
  "use strict";
@@ -16444,12 +16439,16 @@ async function uploadToCloud(config, password) {
16444
16439
  const encryptedCodexProviders = encryptProviders(codexConfig.providers, password);
16445
16440
  const encryptedClaudeProviders = encryptProviders(claudeConfig.providers, password);
16446
16441
  const encryptedCodexConfig = {
16447
- currentProviderId: codexConfig.currentProviderId,
16442
+ ...codexConfig,
16443
+ // 保留所有字段
16448
16444
  providers: encryptedCodexProviders
16445
+ // 只替换 providers(加密后的)
16449
16446
  };
16450
16447
  const encryptedClaudeConfig = {
16451
- currentProviderId: claudeConfig.currentProviderId,
16448
+ ...claudeConfig,
16449
+ // 保留所有字段
16452
16450
  providers: encryptedClaudeProviders
16451
+ // 只替换 providers(加密后的)
16453
16452
  };
16454
16453
  const codexJson = JSON.stringify(encryptedCodexConfig, null, 2);
16455
16454
  const claudeJson = JSON.stringify(encryptedClaudeConfig, null, 2);
@@ -16494,24 +16493,22 @@ async function downloadFromCloud(config, password) {
16494
16493
  throw new Error(`\u5907\u4EFD\u5931\u8D25: ${error.message}`);
16495
16494
  }
16496
16495
  try {
16497
- const currentCodexConfig = readJSON(codexConfigPath);
16498
- const currentClaudeConfig = readJSON(claudeConfigPath);
16499
16496
  if (remoteCodexConfig && decryptedCodexProviders) {
16500
16497
  const newCodexConfig = {
16501
- currentProviderId: remoteCodexConfig.currentProviderId,
16502
- providers: decryptedCodexProviders,
16503
- presets: currentCodexConfig.presets
16504
- // 保留本地 presets
16498
+ ...remoteCodexConfig,
16499
+ // 使用云端配置的所有字段
16500
+ providers: decryptedCodexProviders
16501
+ // 只替换 providers(解密后的)
16505
16502
  };
16506
16503
  writeJSON(codexConfigPath, newCodexConfig);
16507
16504
  applyCurrentProvider("codex", newCodexConfig);
16508
16505
  }
16509
16506
  if (remoteClaudeConfig && decryptedClaudeProviders) {
16510
16507
  const newClaudeConfig = {
16511
- currentProviderId: remoteClaudeConfig.currentProviderId,
16512
- providers: decryptedClaudeProviders,
16513
- presets: currentClaudeConfig.presets
16514
- // 保留本地 presets
16508
+ ...remoteClaudeConfig,
16509
+ // 使用云端配置的所有字段
16510
+ providers: decryptedClaudeProviders
16511
+ // 只替换 providers(解密后的)
16515
16512
  };
16516
16513
  writeJSON(claudeConfigPath, newClaudeConfig);
16517
16514
  applyCurrentProvider("claude", newClaudeConfig);
@@ -16581,16 +16578,24 @@ async function mergeSync(config, password) {
16581
16578
  } catch (error) {
16582
16579
  throw new Error(`\u5907\u4EFD\u5931\u8D25: ${error.message}`);
16583
16580
  }
16581
+ const mergedCodexPresets = mergePresets(localCodexConfig.presets, remoteCodexConfig?.presets);
16582
+ const mergedClaudePresets = mergePresets(localClaudeConfig.presets, remoteClaudeConfig?.presets);
16584
16583
  try {
16585
16584
  const mergedCodexConfig = {
16586
- currentProviderId: localCodexConfig.currentProviderId,
16585
+ ...localCodexConfig,
16586
+ // 保留本地配置的所有字段
16587
16587
  providers: codexMergeResult.merged,
16588
- presets: localCodexConfig.presets
16588
+ // 替换为合并后的 providers
16589
+ presets: mergedCodexPresets
16590
+ // 替换为合并后的 presets
16589
16591
  };
16590
16592
  const mergedClaudeConfig = {
16591
- currentProviderId: localClaudeConfig.currentProviderId,
16593
+ ...localClaudeConfig,
16594
+ // 保留本地配置的所有字段
16592
16595
  providers: claudeMergeResult.merged,
16593
- presets: localClaudeConfig.presets
16596
+ // 替换为合并后的 providers
16597
+ presets: mergedClaudePresets
16598
+ // 替换为合并后的 presets
16594
16599
  };
16595
16600
  writeJSON(codexConfigPath, mergedCodexConfig);
16596
16601
  writeJSON(claudeConfigPath, mergedClaudeConfig);
@@ -16599,12 +16604,16 @@ async function mergeSync(config, password) {
16599
16604
  const encryptedCodexProviders = encryptProviders(codexMergeResult.merged, password);
16600
16605
  const encryptedClaudeProviders = encryptProviders(claudeMergeResult.merged, password);
16601
16606
  const encryptedCodexConfig = {
16602
- currentProviderId: mergedCodexConfig.currentProviderId,
16607
+ ...mergedCodexConfig,
16608
+ // 保留合并后配置的所有字段
16603
16609
  providers: encryptedCodexProviders
16610
+ // 只替换 providers(加密后的)
16604
16611
  };
16605
16612
  const encryptedClaudeConfig = {
16606
- currentProviderId: mergedClaudeConfig.currentProviderId,
16613
+ ...mergedClaudeConfig,
16614
+ // 保留合并后配置的所有字段
16607
16615
  providers: encryptedClaudeProviders
16616
+ // 只替换 providers(加密后的)
16608
16617
  };
16609
16618
  const codexJson2 = JSON.stringify(encryptedCodexConfig, null, 2);
16610
16619
  const claudeJson2 = JSON.stringify(encryptedClaudeConfig, null, 2);
@@ -16824,45 +16833,12 @@ var init_dist4 = __esm({
16824
16833
  });
16825
16834
 
16826
16835
  // src/utils/sync-config.ts
16827
- function getMachineId() {
16828
- return import_crypto4.default.createHash("sha256").update(import_os.default.hostname() + import_os.default.userInfo().username).digest();
16829
- }
16830
- function encrypt(text) {
16831
- const key = getMachineId();
16832
- const iv = import_crypto4.default.randomBytes(16);
16833
- const cipher = import_crypto4.default.createCipheriv("aes-256-cbc", key, iv);
16834
- let encrypted = cipher.update(text, "utf8", "hex");
16835
- encrypted += cipher.final("hex");
16836
- return iv.toString("hex") + ":" + encrypted;
16837
- }
16838
- function decrypt(encrypted) {
16839
- const parts = encrypted.split(":");
16840
- const iv = Buffer.from(parts[0], "hex");
16841
- const encryptedText = parts[1];
16842
- const key = getMachineId();
16843
- const decipher = import_crypto4.default.createDecipheriv("aes-256-cbc", key, iv);
16844
- let decrypted = decipher.update(encryptedText, "hex", "utf8");
16845
- decrypted += decipher.final("utf8");
16846
- return decrypted;
16847
- }
16848
16836
  function loadSyncConfig() {
16849
16837
  try {
16850
16838
  const config = getSyncConfig();
16851
16839
  if (!config) {
16852
16840
  return null;
16853
16841
  }
16854
- if (config.password && config.password.includes(":")) {
16855
- try {
16856
- config.password = decrypt(config.password);
16857
- } catch {
16858
- }
16859
- }
16860
- if (config.syncPassword && config.syncPassword.includes(":")) {
16861
- try {
16862
- config.syncPassword = decrypt(config.syncPassword);
16863
- } catch {
16864
- }
16865
- }
16866
16842
  return config;
16867
16843
  } catch (error) {
16868
16844
  throw new Error(`\u8BFB\u53D6\u540C\u6B65\u914D\u7F6E\u5931\u8D25: ${error.message}`);
@@ -16871,12 +16847,7 @@ function loadSyncConfig() {
16871
16847
  function saveSyncConfig2(config) {
16872
16848
  try {
16873
16849
  const configToSave = { ...config };
16874
- if (configToSave.password) {
16875
- configToSave.password = encrypt(configToSave.password);
16876
- }
16877
- if (configToSave.syncPassword && configToSave.rememberSyncPassword) {
16878
- configToSave.syncPassword = encrypt(configToSave.syncPassword);
16879
- } else {
16850
+ if (!configToSave.rememberSyncPassword) {
16880
16851
  delete configToSave.syncPassword;
16881
16852
  }
16882
16853
  configToSave.lastSync = Date.now();
@@ -16888,12 +16859,9 @@ function saveSyncConfig2(config) {
16888
16859
  function getSyncConfigPath() {
16889
16860
  return getConfigPath();
16890
16861
  }
16891
- var import_crypto4, import_os;
16892
16862
  var init_sync_config = __esm({
16893
16863
  "src/utils/sync-config.ts"() {
16894
16864
  "use strict";
16895
- import_crypto4 = __toESM(require("crypto"));
16896
- import_os = __toESM(require("os"));
16897
16865
  init_dist4();
16898
16866
  }
16899
16867
  });
@@ -19119,6 +19087,26 @@ program.name("ccman").description("Codex/Claude Code API \u670D\u52A1\u5546\u914
19119
19087
  }
19120
19088
  throw err;
19121
19089
  });
19090
+ program.on("command:*", (operands) => {
19091
+ const unknownCommand = operands[0];
19092
+ console.error(import_chalk27.default.red(`
19093
+ \u274C \u672A\u77E5\u547D\u4EE4: ${unknownCommand}
19094
+ `));
19095
+ const availableCommands = ["cx", "cc", "sync", "export", "import"];
19096
+ const suggestions = availableCommands.filter(
19097
+ (cmd) => cmd.includes(unknownCommand) || unknownCommand.includes(cmd)
19098
+ );
19099
+ if (suggestions.length > 0) {
19100
+ console.log(import_chalk27.default.yellow("\u{1F4A1} \u4F60\u662F\u4E0D\u662F\u60F3\u8F93\u5165:"));
19101
+ suggestions.forEach((cmd) => {
19102
+ console.log(import_chalk27.default.cyan(` ccman ${cmd}`));
19103
+ });
19104
+ console.log();
19105
+ }
19106
+ console.log(import_chalk27.default.gray("\u67E5\u770B\u6240\u6709\u53EF\u7528\u547D\u4EE4: ") + import_chalk27.default.cyan("ccman --help"));
19107
+ console.log();
19108
+ process.exit(1);
19109
+ });
19122
19110
  var cx = program.command("cx").description("\u7BA1\u7406 Codex \u670D\u52A1\u5546");
19123
19111
  createCodexCommands(cx);
19124
19112
  cx.action(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccman",
3
- "version": "3.0.20",
3
+ "version": "3.0.22",
4
4
  "description": "Manage Codex and Claude Code API service provider configurations",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {