ccman 3.0.17 → 3.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +243 -145
  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.17",
42
+ version: "3.0.19",
43
43
  type: "module",
44
44
  description: "Core business logic for ccman",
45
45
  main: "./dist/index.js",
@@ -2163,37 +2163,55 @@ var require_toml = __commonJS({
2163
2163
  }
2164
2164
  });
2165
2165
 
2166
+ // ../core/dist/utils/template.js
2167
+ function replaceVariables(template, variables) {
2168
+ const jsonStr = JSON.stringify(template);
2169
+ let result = jsonStr;
2170
+ for (const [key, value] of Object.entries(variables)) {
2171
+ const escapedValue = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
2172
+ result = result.replace(new RegExp(`{{${key}}}`, "g"), escapedValue);
2173
+ }
2174
+ return JSON.parse(result);
2175
+ }
2176
+ function deepMerge(target, source) {
2177
+ const result = { ...target };
2178
+ for (const key in source) {
2179
+ const sourceValue = source[key];
2180
+ const targetValue = result[key];
2181
+ if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
2182
+ result[key] = deepMerge(targetValue, sourceValue);
2183
+ } else {
2184
+ result[key] = sourceValue;
2185
+ }
2186
+ }
2187
+ return result;
2188
+ }
2189
+ var init_template = __esm({
2190
+ "../core/dist/utils/template.js"() {
2191
+ "use strict";
2192
+ }
2193
+ });
2194
+
2166
2195
  // ../core/dist/writers/codex.js
2167
2196
  function writeCodexConfig(provider) {
2168
2197
  ensureDir(getCodexDir());
2169
2198
  const configPath = getCodexConfigPath();
2170
- let config;
2199
+ let userConfig = {};
2171
2200
  if (fileExists(configPath)) {
2172
2201
  const content = fs2.readFileSync(configPath, "utf-8");
2173
- config = (0, import_toml.parse)(content);
2174
- } else {
2175
- config = {};
2202
+ userConfig = (0, import_toml.parse)(content);
2176
2203
  }
2177
- config.model_provider = provider.name;
2178
- config.model_providers = config.model_providers || {};
2179
- config.model_providers[provider.name] = {
2204
+ const mergedConfig = deepMerge(CODEX_DEFAULT_CONFIG, userConfig);
2205
+ mergedConfig.model_provider = provider.name;
2206
+ mergedConfig.model = provider.model || mergedConfig.model || "gpt-5-codex";
2207
+ mergedConfig.model_providers = mergedConfig.model_providers || {};
2208
+ mergedConfig.model_providers[provider.name] = {
2180
2209
  name: provider.name,
2181
2210
  base_url: provider.baseUrl,
2182
2211
  wire_api: "responses",
2183
- // 固定值
2184
2212
  requires_openai_auth: true
2185
- // 固定值
2186
2213
  };
2187
- if (!config.model) {
2188
- config.model = "gpt-5";
2189
- }
2190
- if (!config.model_reasoning_effort) {
2191
- config.model_reasoning_effort = "high";
2192
- }
2193
- if (!("disable_response_storage" in config)) {
2194
- config.disable_response_storage = true;
2195
- }
2196
- fs2.writeFileSync(configPath, (0, import_toml.stringify)(config), { mode: 384 });
2214
+ fs2.writeFileSync(configPath, (0, import_toml.stringify)(mergedConfig), { mode: 384 });
2197
2215
  const authPath = getCodexAuthPath();
2198
2216
  let auth;
2199
2217
  if (fileExists(authPath)) {
@@ -2205,7 +2223,7 @@ function writeCodexConfig(provider) {
2205
2223
  auth.OPENAI_API_KEY = provider.apiKey;
2206
2224
  fs2.writeFileSync(authPath, JSON.stringify(auth, null, 2), { mode: 384 });
2207
2225
  }
2208
- var fs2, import_toml;
2226
+ var fs2, import_toml, CODEX_DEFAULT_CONFIG;
2209
2227
  var init_codex = __esm({
2210
2228
  "../core/dist/writers/codex.js"() {
2211
2229
  "use strict";
@@ -2213,6 +2231,29 @@ var init_codex = __esm({
2213
2231
  import_toml = __toESM(require_toml(), 1);
2214
2232
  init_paths();
2215
2233
  init_file();
2234
+ init_template();
2235
+ CODEX_DEFAULT_CONFIG = {
2236
+ model_reasoning_effort: "high",
2237
+ disable_response_storage: true,
2238
+ sandbox_mode: "workspace-write",
2239
+ windows_wsl_setup_acknowledged: true,
2240
+ features: {
2241
+ plan_tool: true,
2242
+ apply_patch_freeform: true,
2243
+ view_image_tool: true,
2244
+ web_search_request: true,
2245
+ unified_exec: false,
2246
+ streamable_shell: false,
2247
+ rmcp_client: true
2248
+ },
2249
+ tools: {
2250
+ web_search: true,
2251
+ view_image: true
2252
+ },
2253
+ sandbox_workspace_write: {
2254
+ network_access: true
2255
+ }
2256
+ };
2216
2257
  }
2217
2258
  });
2218
2259
 
@@ -2220,42 +2261,38 @@ var init_codex = __esm({
2220
2261
  function writeClaudeConfig(provider) {
2221
2262
  ensureDir(getClaudeDir());
2222
2263
  const configPath = getClaudeConfigPath();
2223
- let settings;
2264
+ let userConfig = {};
2224
2265
  if (fileExists(configPath)) {
2225
2266
  const content = fs3.readFileSync(configPath, "utf-8");
2226
- settings = JSON.parse(content);
2227
- } else {
2228
- settings = {};
2229
- }
2230
- if (!settings.env) {
2231
- settings.env = {};
2232
- }
2233
- settings.env.ANTHROPIC_AUTH_TOKEN = provider.apiKey;
2234
- settings.env.ANTHROPIC_BASE_URL = provider.baseUrl;
2235
- if (!("CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC" in settings.env)) {
2236
- settings.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = 1;
2237
- }
2238
- if (!("CLAUDE_CODE_MAX_OUTPUT_TOKENS" in settings.env)) {
2239
- settings.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS = 32e3;
2267
+ userConfig = JSON.parse(content);
2240
2268
  }
2241
- if (!settings.permissions) {
2242
- settings.permissions = { allow: [], deny: [] };
2243
- }
2244
- if (!settings.permissions.allow) {
2245
- settings.permissions.allow = [];
2246
- }
2247
- if (!settings.permissions.deny) {
2248
- settings.permissions.deny = [];
2249
- }
2250
- fs3.writeFileSync(configPath, JSON.stringify(settings, null, 2), { mode: 384 });
2269
+ const defaultConfig = replaceVariables(CLAUDE_CONFIG_TEMPLATE, {
2270
+ apiKey: provider.apiKey,
2271
+ baseUrl: provider.baseUrl
2272
+ });
2273
+ const mergedConfig = deepMerge(defaultConfig, userConfig);
2274
+ fs3.writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2), { mode: 384 });
2251
2275
  }
2252
- var fs3;
2276
+ var fs3, CLAUDE_CONFIG_TEMPLATE;
2253
2277
  var init_claude = __esm({
2254
2278
  "../core/dist/writers/claude.js"() {
2255
2279
  "use strict";
2256
2280
  fs3 = __toESM(require("fs"), 1);
2257
2281
  init_paths();
2258
2282
  init_file();
2283
+ init_template();
2284
+ CLAUDE_CONFIG_TEMPLATE = {
2285
+ env: {
2286
+ ANTHROPIC_AUTH_TOKEN: "{{apiKey}}",
2287
+ ANTHROPIC_BASE_URL: "{{baseUrl}}",
2288
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1,
2289
+ CLAUDE_CODE_MAX_OUTPUT_TOKENS: 32e3
2290
+ },
2291
+ permissions: {
2292
+ allow: [],
2293
+ deny: []
2294
+ }
2295
+ };
2259
2296
  }
2260
2297
  });
2261
2298
 
@@ -2342,8 +2379,8 @@ function createCodexManager() {
2342
2379
  ensureDir(getCcmanDir());
2343
2380
  const initialConfig = {
2344
2381
  providers: [],
2345
- presets: [...CODEX_PRESETS]
2346
- // 初始化内置预置到配置文件
2382
+ presets: []
2383
+ // 只存储用户自定义预置
2347
2384
  };
2348
2385
  writeJSON(configPath, initialConfig);
2349
2386
  return initialConfig;
@@ -2366,6 +2403,8 @@ function createCodexManager() {
2366
2403
  name: input.name,
2367
2404
  baseUrl: input.baseUrl,
2368
2405
  apiKey: input.apiKey,
2406
+ model: input.model,
2407
+ // 保存 model 字段
2369
2408
  createdAt: timestamp,
2370
2409
  lastModified: timestamp
2371
2410
  };
@@ -2387,7 +2426,8 @@ function createCodexManager() {
2387
2426
  },
2388
2427
  findByName(name) {
2389
2428
  const config = loadConfig2();
2390
- return config.providers.find((p) => p.name === name);
2429
+ const lowerName = name.toLowerCase();
2430
+ return config.providers.find((p) => p.name.toLowerCase() === lowerName);
2391
2431
  },
2392
2432
  switch(id) {
2393
2433
  const config = loadConfig2();
@@ -2426,6 +2466,8 @@ function createCodexManager() {
2426
2466
  provider.baseUrl = updates.baseUrl;
2427
2467
  if (updates.apiKey !== void 0)
2428
2468
  provider.apiKey = updates.apiKey;
2469
+ if (updates.model !== void 0)
2470
+ provider.model = updates.model;
2429
2471
  provider.lastModified = Date.now();
2430
2472
  saveConfig2(config);
2431
2473
  if (config.currentProviderId === id) {
@@ -2535,8 +2577,8 @@ function createClaudeManager() {
2535
2577
  ensureDir(getCcmanDir());
2536
2578
  const initialConfig = {
2537
2579
  providers: [],
2538
- presets: [...CC_PRESETS]
2539
- // 初始化内置预置到配置文件
2580
+ presets: []
2581
+ // 只存储用户自定义预置
2540
2582
  };
2541
2583
  writeJSON(configPath, initialConfig);
2542
2584
  return initialConfig;
@@ -2580,7 +2622,8 @@ function createClaudeManager() {
2580
2622
  },
2581
2623
  findByName(name) {
2582
2624
  const config = loadConfig2();
2583
- return config.providers.find((p) => p.name === name);
2625
+ const lowerName = name.toLowerCase();
2626
+ return config.providers.find((p) => p.name.toLowerCase() === lowerName);
2584
2627
  },
2585
2628
  switch(id) {
2586
2629
  const config = loadConfig2();
@@ -3001,22 +3044,22 @@ var require_url_parse = __commonJS({
3001
3044
  }
3002
3045
  function resolve(relative, base) {
3003
3046
  if (relative === "") return base;
3004
- var path11 = (base || "/").split("/").slice(0, -1).concat(relative.split("/")), i2 = path11.length, last = path11[i2 - 1], unshift = false, up = 0;
3047
+ var path12 = (base || "/").split("/").slice(0, -1).concat(relative.split("/")), i2 = path12.length, last = path12[i2 - 1], unshift = false, up = 0;
3005
3048
  while (i2--) {
3006
- if (path11[i2] === ".") {
3007
- path11.splice(i2, 1);
3008
- } else if (path11[i2] === "..") {
3009
- path11.splice(i2, 1);
3049
+ if (path12[i2] === ".") {
3050
+ path12.splice(i2, 1);
3051
+ } else if (path12[i2] === "..") {
3052
+ path12.splice(i2, 1);
3010
3053
  up++;
3011
3054
  } else if (up) {
3012
3055
  if (i2 === 0) unshift = true;
3013
- path11.splice(i2, 1);
3056
+ path12.splice(i2, 1);
3014
3057
  up--;
3015
3058
  }
3016
3059
  }
3017
- if (unshift) path11.unshift("");
3018
- if (last === "." || last === "..") path11.push("");
3019
- return path11.join("/");
3060
+ if (unshift) path12.unshift("");
3061
+ if (last === "." || last === "..") path12.push("");
3062
+ return path12.join("/");
3020
3063
  }
3021
3064
  function Url(address, location, parser) {
3022
3065
  address = trimLeft(address);
@@ -3442,14 +3485,14 @@ var require_path_posix = __commonJS({
3442
3485
  posix.resolve = function() {
3443
3486
  var resolvedPath = "", resolvedAbsolute = false;
3444
3487
  for (var i2 = arguments.length - 1; i2 >= -1 && !resolvedAbsolute; i2--) {
3445
- var path11 = i2 >= 0 ? arguments[i2] : process.cwd();
3446
- if (!isString(path11)) {
3488
+ var path12 = i2 >= 0 ? arguments[i2] : process.cwd();
3489
+ if (!isString(path12)) {
3447
3490
  throw new TypeError("Arguments to path.resolve must be strings");
3448
- } else if (!path11) {
3491
+ } else if (!path12) {
3449
3492
  continue;
3450
3493
  }
3451
- resolvedPath = path11 + "/" + resolvedPath;
3452
- resolvedAbsolute = path11.charAt(0) === "/";
3494
+ resolvedPath = path12 + "/" + resolvedPath;
3495
+ resolvedAbsolute = path12.charAt(0) === "/";
3453
3496
  }
3454
3497
  resolvedPath = normalizeArray(
3455
3498
  resolvedPath.split("/"),
@@ -3457,36 +3500,36 @@ var require_path_posix = __commonJS({
3457
3500
  ).join("/");
3458
3501
  return (resolvedAbsolute ? "/" : "") + resolvedPath || ".";
3459
3502
  };
3460
- posix.normalize = function(path11) {
3461
- var isAbsolute = posix.isAbsolute(path11), trailingSlash = path11.substr(-1) === "/";
3462
- path11 = normalizeArray(path11.split("/"), !isAbsolute).join("/");
3463
- if (!path11 && !isAbsolute) {
3464
- path11 = ".";
3503
+ posix.normalize = function(path12) {
3504
+ var isAbsolute = posix.isAbsolute(path12), trailingSlash = path12.substr(-1) === "/";
3505
+ path12 = normalizeArray(path12.split("/"), !isAbsolute).join("/");
3506
+ if (!path12 && !isAbsolute) {
3507
+ path12 = ".";
3465
3508
  }
3466
- if (path11 && trailingSlash) {
3467
- path11 += "/";
3509
+ if (path12 && trailingSlash) {
3510
+ path12 += "/";
3468
3511
  }
3469
- return (isAbsolute ? "/" : "") + path11;
3512
+ return (isAbsolute ? "/" : "") + path12;
3470
3513
  };
3471
- posix.isAbsolute = function(path11) {
3472
- return path11.charAt(0) === "/";
3514
+ posix.isAbsolute = function(path12) {
3515
+ return path12.charAt(0) === "/";
3473
3516
  };
3474
3517
  posix.join = function() {
3475
- var path11 = "";
3518
+ var path12 = "";
3476
3519
  for (var i2 = 0; i2 < arguments.length; i2++) {
3477
3520
  var segment = arguments[i2];
3478
3521
  if (!isString(segment)) {
3479
3522
  throw new TypeError("Arguments to path.join must be strings");
3480
3523
  }
3481
3524
  if (segment) {
3482
- if (!path11) {
3483
- path11 += segment;
3525
+ if (!path12) {
3526
+ path12 += segment;
3484
3527
  } else {
3485
- path11 += "/" + segment;
3528
+ path12 += "/" + segment;
3486
3529
  }
3487
3530
  }
3488
3531
  }
3489
- return posix.normalize(path11);
3532
+ return posix.normalize(path12);
3490
3533
  };
3491
3534
  posix.relative = function(from, to) {
3492
3535
  from = posix.resolve(from).substr(1);
@@ -3520,11 +3563,11 @@ var require_path_posix = __commonJS({
3520
3563
  outputParts = outputParts.concat(toParts.slice(samePartsLength));
3521
3564
  return outputParts.join("/");
3522
3565
  };
3523
- posix._makeLong = function(path11) {
3524
- return path11;
3566
+ posix._makeLong = function(path12) {
3567
+ return path12;
3525
3568
  };
3526
- posix.dirname = function(path11) {
3527
- var result = posixSplitPath(path11), root = result[0], dir = result[1];
3569
+ posix.dirname = function(path12) {
3570
+ var result = posixSplitPath(path12), root = result[0], dir = result[1];
3528
3571
  if (!root && !dir) {
3529
3572
  return ".";
3530
3573
  }
@@ -3533,15 +3576,15 @@ var require_path_posix = __commonJS({
3533
3576
  }
3534
3577
  return root + dir;
3535
3578
  };
3536
- posix.basename = function(path11, ext2) {
3537
- var f3 = posixSplitPath(path11)[2];
3579
+ posix.basename = function(path12, ext2) {
3580
+ var f3 = posixSplitPath(path12)[2];
3538
3581
  if (ext2 && f3.substr(-1 * ext2.length) === ext2) {
3539
3582
  f3 = f3.substr(0, f3.length - ext2.length);
3540
3583
  }
3541
3584
  return f3;
3542
3585
  };
3543
- posix.extname = function(path11) {
3544
- return posixSplitPath(path11)[3];
3586
+ posix.extname = function(path12) {
3587
+ return posixSplitPath(path12)[3];
3545
3588
  };
3546
3589
  posix.format = function(pathObject) {
3547
3590
  if (!util.isObject(pathObject)) {
@@ -14939,10 +14982,10 @@ var require_nested_property = __commonJS({
14939
14982
  return false;
14940
14983
  }
14941
14984
  }
14942
- function traverse(object, path11) {
14985
+ function traverse(object, path12) {
14943
14986
  var callback = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : function() {
14944
14987
  };
14945
- var segments = path11.split(PATH_DELIMITER);
14988
+ var segments = path12.split(PATH_DELIMITER);
14946
14989
  var length = segments.length;
14947
14990
  var _loop = function _loop2(idx2) {
14948
14991
  var currentSegment = segments[idx2];
@@ -15184,11 +15227,11 @@ async function createDirectory(context, dirPath, options = {}) {
15184
15227
  const response = await request(requestOptions, context);
15185
15228
  handleResponseCode(context, response);
15186
15229
  }
15187
- function ensureCollectionPath(path11) {
15188
- if (!path11.endsWith("/")) {
15189
- return path11 + "/";
15230
+ function ensureCollectionPath(path12) {
15231
+ if (!path12.endsWith("/")) {
15232
+ return path12 + "/";
15190
15233
  }
15191
- return path11;
15234
+ return path12;
15192
15235
  }
15193
15236
  async function createDirectoryRecursively(context, dirPath, options = {}) {
15194
15237
  const paths = getAllDirectories(normalisePath(dirPath));
@@ -15563,7 +15606,7 @@ var init_xml = __esm({
15563
15606
  });
15564
15607
 
15565
15608
  // ../../node_modules/.pnpm/webdav@5.8.0/node_modules/webdav/dist/node/operations/lock.js
15566
- async function lock(context, path11, options = {}) {
15609
+ async function lock(context, path12, options = {}) {
15567
15610
  const { refreshToken, timeout = DEFAULT_TIMEOUT } = options;
15568
15611
  const headers = {
15569
15612
  Accept: "text/plain,application/xml",
@@ -15573,7 +15616,7 @@ async function lock(context, path11, options = {}) {
15573
15616
  headers.If = refreshToken;
15574
15617
  }
15575
15618
  const requestOptions = prepareRequestOptions({
15576
- url: joinURL(context.remoteURL, encodePath(path11)),
15619
+ url: joinURL(context.remoteURL, encodePath(path12)),
15577
15620
  method: "LOCK",
15578
15621
  headers,
15579
15622
  data: generateLockXML(context.contactHref)
@@ -15593,9 +15636,9 @@ async function lock(context, path11, options = {}) {
15593
15636
  serverTimeout
15594
15637
  };
15595
15638
  }
15596
- async function unlock(context, path11, token, options = {}) {
15639
+ async function unlock(context, path12, token, options = {}) {
15597
15640
  const requestOptions = prepareRequestOptions({
15598
- url: joinURL(context.remoteURL, encodePath(path11)),
15641
+ url: joinURL(context.remoteURL, encodePath(path12)),
15599
15642
  method: "UNLOCK",
15600
15643
  headers: {
15601
15644
  "Lock-Token": token
@@ -15645,9 +15688,9 @@ var init_quota = __esm({
15645
15688
 
15646
15689
  // ../../node_modules/.pnpm/webdav@5.8.0/node_modules/webdav/dist/node/operations/getQuota.js
15647
15690
  async function getQuota(context, options = {}) {
15648
- const path11 = options.path || "/";
15691
+ const path12 = options.path || "/";
15649
15692
  const requestOptions = prepareRequestOptions({
15650
- url: joinURL(context.remoteURL, path11),
15693
+ url: joinURL(context.remoteURL, path12),
15651
15694
  method: "PROPFIND",
15652
15695
  headers: {
15653
15696
  Accept: "text/plain,application/xml",
@@ -15987,29 +16030,29 @@ function createClient(remoteURL, options = {}) {
15987
16030
  setupAuth(context, username, password, token, ha1);
15988
16031
  return {
15989
16032
  copyFile: (filename, destination, options2) => copyFile(context, filename, destination, options2),
15990
- createDirectory: (path11, options2) => createDirectory(context, path11, options2),
16033
+ createDirectory: (path12, options2) => createDirectory(context, path12, options2),
15991
16034
  createReadStream: (filename, options2) => createReadStream2(context, filename, options2),
15992
16035
  createWriteStream: (filename, options2, callback) => createWriteStream(context, filename, options2, callback),
15993
- customRequest: (path11, requestOptions) => customRequest(context, path11, requestOptions),
16036
+ customRequest: (path12, requestOptions) => customRequest(context, path12, requestOptions),
15994
16037
  deleteFile: (filename, options2) => deleteFile(context, filename, options2),
15995
- exists: (path11, options2) => exists(context, path11, options2),
15996
- getDirectoryContents: (path11, options2) => getDirectoryContents(context, path11, options2),
16038
+ exists: (path12, options2) => exists(context, path12, options2),
16039
+ getDirectoryContents: (path12, options2) => getDirectoryContents(context, path12, options2),
15997
16040
  getFileContents: (filename, options2) => getFileContents(context, filename, options2),
15998
16041
  getFileDownloadLink: (filename) => getFileDownloadLink(context, filename),
15999
16042
  getFileUploadLink: (filename) => getFileUploadLink(context, filename),
16000
16043
  getHeaders: () => Object.assign({}, context.headers),
16001
16044
  getQuota: (options2) => getQuota(context, options2),
16002
- lock: (path11, options2) => lock(context, path11, options2),
16045
+ lock: (path12, options2) => lock(context, path12, options2),
16003
16046
  moveFile: (filename, destinationFilename, options2) => moveFile(context, filename, destinationFilename, options2),
16004
16047
  putFileContents: (filename, data, options2) => putFileContents(context, filename, data, options2),
16005
16048
  partialUpdateFileContents: (filePath, start, end, data, options2) => partialUpdateFileContents(context, filePath, start, end, data, options2),
16006
- getDAVCompliance: (path11) => getDAVCompliance(context, path11),
16007
- search: (path11, options2) => getSearch2(context, path11, options2),
16049
+ getDAVCompliance: (path12) => getDAVCompliance(context, path12),
16050
+ search: (path12, options2) => getSearch2(context, path12, options2),
16008
16051
  setHeaders: (headers2) => {
16009
16052
  context.headers = Object.assign({}, headers2);
16010
16053
  },
16011
- stat: (path11, options2) => getStat(context, path11, options2),
16012
- unlock: (path11, token2, options2) => unlock(context, path11, token2, options2)
16054
+ stat: (path12, options2) => getStat(context, path12, options2),
16055
+ unlock: (path12, token2, options2) => unlock(context, path12, token2, options2)
16013
16056
  };
16014
16057
  }
16015
16058
  var DEFAULT_CONTACT_HREF;
@@ -16182,20 +16225,52 @@ var init_webdav_client = __esm({
16182
16225
  });
16183
16226
 
16184
16227
  // ../core/dist/sync/merge.js
16185
- function backupConfig(configPath) {
16228
+ function backupConfig(configPath, keepCount = 3) {
16186
16229
  if (!import_fs.default.existsSync(configPath)) {
16187
16230
  throw new Error(`\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${configPath}`);
16188
16231
  }
16189
16232
  const timestamp = Date.now();
16190
16233
  const backupPath = `${configPath}.backup.${timestamp}`;
16191
16234
  import_fs.default.copyFileSync(configPath, backupPath);
16235
+ cleanupOldBackups(configPath, keepCount);
16192
16236
  return backupPath;
16193
16237
  }
16194
- var import_fs;
16238
+ function cleanupOldBackups(configPath, keepCount) {
16239
+ const dir = import_path17.default.dirname(configPath);
16240
+ const basename2 = import_path17.default.basename(configPath);
16241
+ const backupPrefix = `${basename2}.backup.`;
16242
+ try {
16243
+ const files = import_fs.default.readdirSync(dir);
16244
+ const backups = files.filter((f3) => f3.startsWith(backupPrefix)).map((f3) => {
16245
+ const timestampStr = f3.substring(backupPrefix.length);
16246
+ const timestamp = parseInt(timestampStr, 10);
16247
+ if (isNaN(timestamp)) {
16248
+ return null;
16249
+ }
16250
+ return {
16251
+ name: f3,
16252
+ path: import_path17.default.join(dir, f3),
16253
+ timestamp
16254
+ };
16255
+ }).filter((backup) => backup !== null).sort((a, b) => b.timestamp - a.timestamp);
16256
+ const toDelete = backups.slice(keepCount);
16257
+ for (const backup of toDelete) {
16258
+ try {
16259
+ import_fs.default.unlinkSync(backup.path);
16260
+ } catch (error) {
16261
+ console.warn(`\u65E0\u6CD5\u5220\u9664\u65E7\u5907\u4EFD\u6587\u4EF6 ${backup.name}: ${error.message}`);
16262
+ }
16263
+ }
16264
+ } catch (error) {
16265
+ console.warn(`\u6E05\u7406\u65E7\u5907\u4EFD\u65F6\u51FA\u9519: ${error.message}`);
16266
+ }
16267
+ }
16268
+ var import_fs, import_path17;
16195
16269
  var init_merge2 = __esm({
16196
16270
  "../core/dist/sync/merge.js"() {
16197
16271
  "use strict";
16198
16272
  import_fs = __toESM(require("fs"), 1);
16273
+ import_path17 = __toESM(require("path"), 1);
16199
16274
  }
16200
16275
  });
16201
16276
 
@@ -16372,8 +16447,8 @@ var init_merge_advanced = __esm({
16372
16447
  // ../core/dist/sync/sync-v2.js
16373
16448
  async function uploadToCloud(config, password) {
16374
16449
  const ccmanDir2 = getCcmanDir();
16375
- const codexConfigPath = import_path17.default.join(ccmanDir2, "codex.json");
16376
- const claudeConfigPath = import_path17.default.join(ccmanDir2, "claude.json");
16450
+ const codexConfigPath = import_path18.default.join(ccmanDir2, "codex.json");
16451
+ const claudeConfigPath = import_path18.default.join(ccmanDir2, "claude.json");
16377
16452
  const codexConfig = readJSON(codexConfigPath);
16378
16453
  const claudeConfig = readJSON(claudeConfigPath);
16379
16454
  const encryptedCodexProviders = encryptProviders(codexConfig.providers, password);
@@ -16416,8 +16491,8 @@ async function downloadFromCloud(config, password) {
16416
16491
  }
16417
16492
  const backupPaths = [];
16418
16493
  const ccmanDir2 = getCcmanDir();
16419
- const codexConfigPath = import_path17.default.join(ccmanDir2, "codex.json");
16420
- const claudeConfigPath = import_path17.default.join(ccmanDir2, "claude.json");
16494
+ const codexConfigPath = import_path18.default.join(ccmanDir2, "codex.json");
16495
+ const claudeConfigPath = import_path18.default.join(ccmanDir2, "claude.json");
16421
16496
  try {
16422
16497
  if (import_fs2.default.existsSync(codexConfigPath)) {
16423
16498
  backupPaths.push(backupConfig(codexConfigPath));
@@ -16439,6 +16514,7 @@ async function downloadFromCloud(config, password) {
16439
16514
  // 保留本地 presets
16440
16515
  };
16441
16516
  writeJSON(codexConfigPath, newCodexConfig);
16517
+ applyCurrentProvider("codex", newCodexConfig);
16442
16518
  }
16443
16519
  if (remoteClaudeConfig && decryptedClaudeProviders) {
16444
16520
  const newClaudeConfig = {
@@ -16448,8 +16524,9 @@ async function downloadFromCloud(config, password) {
16448
16524
  // 保留本地 presets
16449
16525
  };
16450
16526
  writeJSON(claudeConfigPath, newClaudeConfig);
16527
+ applyCurrentProvider("claude", newClaudeConfig);
16451
16528
  }
16452
- console.log("\u2705 \u914D\u7F6E\u5DF2\u4ECE\u4E91\u7AEF\u4E0B\u8F7D\u5E76\u8986\u76D6\u672C\u5730");
16529
+ console.log("\u2705 \u914D\u7F6E\u5DF2\u4ECE\u4E91\u7AEF\u4E0B\u8F7D\u5E76\u5E94\u7528");
16453
16530
  return backupPaths;
16454
16531
  } catch (error) {
16455
16532
  for (const backupPath of backupPaths) {
@@ -16489,8 +16566,8 @@ async function mergeSync(config, password) {
16489
16566
  throw new Error("\u89E3\u5BC6\u5931\u8D25\uFF1A\u5BC6\u7801\u9519\u8BEF\u6216\u6570\u636E\u635F\u574F");
16490
16567
  }
16491
16568
  const ccmanDir2 = getCcmanDir();
16492
- const codexConfigPath = import_path17.default.join(ccmanDir2, "codex.json");
16493
- const claudeConfigPath = import_path17.default.join(ccmanDir2, "claude.json");
16569
+ const codexConfigPath = import_path18.default.join(ccmanDir2, "codex.json");
16570
+ const claudeConfigPath = import_path18.default.join(ccmanDir2, "claude.json");
16494
16571
  const localCodexConfig = readJSON(codexConfigPath);
16495
16572
  const localClaudeConfig = readJSON(claudeConfigPath);
16496
16573
  const codexMergeResult = mergeProviders(localCodexConfig.providers, remoteCodexProviders);
@@ -16527,6 +16604,8 @@ async function mergeSync(config, password) {
16527
16604
  };
16528
16605
  writeJSON(codexConfigPath, mergedCodexConfig);
16529
16606
  writeJSON(claudeConfigPath, mergedClaudeConfig);
16607
+ applyCurrentProvider("codex", mergedCodexConfig);
16608
+ applyCurrentProvider("claude", mergedClaudeConfig);
16530
16609
  const encryptedCodexProviders = encryptProviders(codexMergeResult.merged, password);
16531
16610
  const encryptedClaudeProviders = encryptProviders(claudeMergeResult.merged, password);
16532
16611
  const encryptedCodexConfig = {
@@ -16556,18 +16635,34 @@ async function mergeSync(config, password) {
16556
16635
  throw new Error(`\u5408\u5E76\u914D\u7F6E\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
16557
16636
  }
16558
16637
  }
16559
- var import_fs2, import_path17, CODEX_REMOTE_PATH, CLAUDE_REMOTE_PATH;
16638
+ function applyCurrentProvider(tool, config) {
16639
+ if (!config.currentProviderId) {
16640
+ return;
16641
+ }
16642
+ const provider = config.providers.find((p) => p.id === config.currentProviderId);
16643
+ if (!provider) {
16644
+ return;
16645
+ }
16646
+ if (tool === "codex") {
16647
+ writeCodexConfig(provider);
16648
+ } else {
16649
+ writeClaudeConfig(provider);
16650
+ }
16651
+ }
16652
+ var import_fs2, import_path18, CODEX_REMOTE_PATH, CLAUDE_REMOTE_PATH;
16560
16653
  var init_sync_v2 = __esm({
16561
16654
  "../core/dist/sync/sync-v2.js"() {
16562
16655
  "use strict";
16563
16656
  import_fs2 = __toESM(require("fs"), 1);
16564
- import_path17 = __toESM(require("path"), 1);
16657
+ import_path18 = __toESM(require("path"), 1);
16565
16658
  init_webdav_client();
16566
16659
  init_crypto2();
16567
16660
  init_merge_advanced();
16568
16661
  init_merge2();
16569
16662
  init_paths();
16570
16663
  init_file();
16664
+ init_codex();
16665
+ init_claude();
16571
16666
  CODEX_REMOTE_PATH = ".ccman/codex.json";
16572
16667
  CLAUDE_REMOTE_PATH = ".ccman/claude.json";
16573
16668
  }
@@ -16576,8 +16671,8 @@ var init_sync_v2 = __esm({
16576
16671
  // ../core/dist/export.js
16577
16672
  function validateExport() {
16578
16673
  const ccmanDir2 = getCcmanDir();
16579
- const codexPath = path8.join(ccmanDir2, CODEX_CONFIG_FILE);
16580
- const claudePath = path8.join(ccmanDir2, CLAUDE_CONFIG_FILE);
16674
+ const codexPath = path9.join(ccmanDir2, CODEX_CONFIG_FILE);
16675
+ const claudePath = path9.join(ccmanDir2, CLAUDE_CONFIG_FILE);
16581
16676
  const missingFiles = [];
16582
16677
  if (!fileExists(codexPath)) {
16583
16678
  missingFiles.push(CODEX_CONFIG_FILE);
@@ -16610,8 +16705,8 @@ function validateImportDir(sourceDir) {
16610
16705
  foundFiles: []
16611
16706
  };
16612
16707
  }
16613
- const codexPath = path8.join(sourceDir, CODEX_CONFIG_FILE);
16614
- const claudePath = path8.join(sourceDir, CLAUDE_CONFIG_FILE);
16708
+ const codexPath = path9.join(sourceDir, CODEX_CONFIG_FILE);
16709
+ const claudePath = path9.join(sourceDir, CLAUDE_CONFIG_FILE);
16615
16710
  const foundFiles = [];
16616
16711
  if (fileExists(codexPath)) {
16617
16712
  foundFiles.push(CODEX_CONFIG_FILE);
@@ -16639,14 +16734,14 @@ function exportConfig(targetDir) {
16639
16734
  ensureDir(targetDir);
16640
16735
  const ccmanDir2 = getCcmanDir();
16641
16736
  const exportedFiles = [];
16642
- const codexSrc = path8.join(ccmanDir2, CODEX_CONFIG_FILE);
16643
- const codexDst = path8.join(targetDir, CODEX_CONFIG_FILE);
16737
+ const codexSrc = path9.join(ccmanDir2, CODEX_CONFIG_FILE);
16738
+ const codexDst = path9.join(targetDir, CODEX_CONFIG_FILE);
16644
16739
  if (fileExists(codexSrc)) {
16645
16740
  fs8.copyFileSync(codexSrc, codexDst);
16646
16741
  exportedFiles.push(CODEX_CONFIG_FILE);
16647
16742
  }
16648
- const claudeSrc = path8.join(ccmanDir2, CLAUDE_CONFIG_FILE);
16649
- const claudeDst = path8.join(targetDir, CLAUDE_CONFIG_FILE);
16743
+ const claudeSrc = path9.join(ccmanDir2, CLAUDE_CONFIG_FILE);
16744
+ const claudeDst = path9.join(targetDir, CLAUDE_CONFIG_FILE);
16650
16745
  if (fileExists(claudeSrc)) {
16651
16746
  fs8.copyFileSync(claudeSrc, claudeDst);
16652
16747
  exportedFiles.push(CLAUDE_CONFIG_FILE);
@@ -16668,22 +16763,22 @@ function importConfig(sourceDir) {
16668
16763
  ensureDir(ccmanDir2);
16669
16764
  try {
16670
16765
  if (validation.foundFiles.includes(CODEX_CONFIG_FILE)) {
16671
- const codexDst = path8.join(ccmanDir2, CODEX_CONFIG_FILE);
16766
+ const codexDst = path9.join(ccmanDir2, CODEX_CONFIG_FILE);
16672
16767
  if (fileExists(codexDst)) {
16673
16768
  const backupPath = backupConfig(codexDst);
16674
16769
  backupPaths.push(backupPath);
16675
16770
  }
16676
- const codexSrc = path8.join(sourceDir, CODEX_CONFIG_FILE);
16771
+ const codexSrc = path9.join(sourceDir, CODEX_CONFIG_FILE);
16677
16772
  fs8.copyFileSync(codexSrc, codexDst);
16678
16773
  importedFiles.push(CODEX_CONFIG_FILE);
16679
16774
  }
16680
16775
  if (validation.foundFiles.includes(CLAUDE_CONFIG_FILE)) {
16681
- const claudeDst = path8.join(ccmanDir2, CLAUDE_CONFIG_FILE);
16776
+ const claudeDst = path9.join(ccmanDir2, CLAUDE_CONFIG_FILE);
16682
16777
  if (fileExists(claudeDst)) {
16683
16778
  const backupPath = backupConfig(claudeDst);
16684
16779
  backupPaths.push(backupPath);
16685
16780
  }
16686
- const claudeSrc = path8.join(sourceDir, CLAUDE_CONFIG_FILE);
16781
+ const claudeSrc = path9.join(sourceDir, CLAUDE_CONFIG_FILE);
16687
16782
  fs8.copyFileSync(claudeSrc, claudeDst);
16688
16783
  importedFiles.push(CLAUDE_CONFIG_FILE);
16689
16784
  }
@@ -16702,12 +16797,12 @@ function importConfig(sourceDir) {
16702
16797
  throw new Error(`\u5BFC\u5165\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
16703
16798
  }
16704
16799
  }
16705
- var fs8, path8, CODEX_CONFIG_FILE, CLAUDE_CONFIG_FILE;
16800
+ var fs8, path9, CODEX_CONFIG_FILE, CLAUDE_CONFIG_FILE;
16706
16801
  var init_export = __esm({
16707
16802
  "../core/dist/export.js"() {
16708
16803
  "use strict";
16709
16804
  fs8 = __toESM(require("fs"), 1);
16710
- path8 = __toESM(require("path"), 1);
16805
+ path9 = __toESM(require("path"), 1);
16711
16806
  init_paths();
16712
16807
  init_file();
16713
16808
  init_merge2();
@@ -17185,8 +17280,8 @@ function downloadCommand(program2) {
17185
17280
  console.log();
17186
17281
  if (backupPaths.length > 0) {
17187
17282
  console.log(import_chalk6.default.gray("\u672C\u5730\u5907\u4EFD:"));
17188
- backupPaths.forEach((path11) => {
17189
- console.log(import_chalk6.default.gray(` ${path11}`));
17283
+ backupPaths.forEach((path12) => {
17284
+ console.log(import_chalk6.default.gray(` ${path12}`));
17190
17285
  });
17191
17286
  console.log();
17192
17287
  }
@@ -17250,8 +17345,8 @@ function mergeCommand(program2) {
17250
17345
  console.log();
17251
17346
  if (result.backupPaths.length > 0) {
17252
17347
  console.log(import_chalk7.default.gray("\u5907\u4EFD:"));
17253
- result.backupPaths.forEach((path11) => {
17254
- console.log(import_chalk7.default.gray(` ${path11}`));
17348
+ result.backupPaths.forEach((path12) => {
17349
+ console.log(import_chalk7.default.gray(` ${path12}`));
17255
17350
  });
17256
17351
  console.log();
17257
17352
  }
@@ -17454,6 +17549,7 @@ var import_chalk27 = __toESM(require("chalk"));
17454
17549
 
17455
17550
  // src/utils/logo.ts
17456
17551
  var import_chalk = __toESM(require("chalk"));
17552
+ init_dist4();
17457
17553
  function printLogo() {
17458
17554
  console.log(
17459
17555
  import_chalk.default.bold(
@@ -17467,7 +17563,9 @@ function printLogo() {
17467
17563
  `
17468
17564
  )
17469
17565
  );
17470
- console.log(import_chalk.default.gray(" Codex/Claude Code API \u670D\u52A1\u5546\u914D\u7F6E\u7BA1\u7406\u5DE5\u5177\n"));
17566
+ console.log(import_chalk.default.gray(" Codex/Claude Code API \u670D\u52A1\u5546\u914D\u7F6E\u7BA1\u7406\u5DE5\u5177"));
17567
+ console.log(import_chalk.default.gray(` \u7248\u672C ${VERSION}
17568
+ `));
17471
17569
  }
17472
17570
 
17473
17571
  // src/commands/codex/add.ts
@@ -18893,7 +18991,7 @@ init_sync2();
18893
18991
 
18894
18992
  // src/commands/export.ts
18895
18993
  var import_chalk25 = __toESM(require("chalk"));
18896
- var import_path18 = __toESM(require("path"));
18994
+ var import_path19 = __toESM(require("path"));
18897
18995
  init_dist4();
18898
18996
  function exportCommand(program2) {
18899
18997
  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) => {
@@ -18905,7 +19003,7 @@ function exportCommand(program2) {
18905
19003
  `));
18906
19004
  process.exit(1);
18907
19005
  }
18908
- const resolvedPath = targetDir.startsWith("~") ? import_path18.default.join(process.env.HOME || "", targetDir.slice(1)) : import_path18.default.resolve(targetDir);
19006
+ const resolvedPath = targetDir.startsWith("~") ? import_path19.default.join(process.env.HOME || "", targetDir.slice(1)) : import_path19.default.resolve(targetDir);
18909
19007
  console.log("\u5BFC\u51FA\u6587\u4EF6:");
18910
19008
  console.log(` ${import_chalk25.default.cyan("codex.json")} - Codex \u914D\u7F6E`);
18911
19009
  console.log(` ${import_chalk25.default.cyan("claude.json")} - Claude \u914D\u7F6E`);
@@ -18936,12 +19034,12 @@ function exportCommand(program2) {
18936
19034
  // src/commands/import.ts
18937
19035
  var import_chalk26 = __toESM(require("chalk"));
18938
19036
  var import_inquirer17 = __toESM(require("inquirer"));
18939
- var import_path19 = __toESM(require("path"));
19037
+ var import_path20 = __toESM(require("path"));
18940
19038
  init_dist4();
18941
19039
  function importCommand(program2) {
18942
19040
  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) => {
18943
19041
  try {
18944
- const resolvedPath = sourceDir.startsWith("~") ? import_path19.default.join(process.env.HOME || "", sourceDir.slice(1)) : import_path19.default.resolve(sourceDir);
19042
+ const resolvedPath = sourceDir.startsWith("~") ? import_path20.default.join(process.env.HOME || "", sourceDir.slice(1)) : import_path20.default.resolve(sourceDir);
18945
19043
  console.log(import_chalk26.default.bold("\n\u{1F4E5} \u5BFC\u5165\u914D\u7F6E\n"));
18946
19044
  const validation = validateImportDir(resolvedPath);
18947
19045
  if (!validation.valid) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccman",
3
- "version": "3.0.17",
3
+ "version": "3.0.19",
4
4
  "description": "Manage Codex and Claude Code API service provider configurations",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {