ccman 3.0.31 → 3.0.33
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 +2034 -124
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -9,8 +9,1935 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// ../core/package.json
|
|
13
|
+
var package_default;
|
|
14
|
+
var init_package = __esm({
|
|
15
|
+
"../core/package.json"() {
|
|
16
|
+
package_default = {
|
|
17
|
+
name: "@ccman/core",
|
|
18
|
+
version: "3.0.33",
|
|
19
|
+
type: "module",
|
|
20
|
+
description: "Core business logic for ccman",
|
|
21
|
+
main: "./dist/index.js",
|
|
22
|
+
types: "./dist/index.d.ts",
|
|
23
|
+
files: [
|
|
24
|
+
"dist",
|
|
25
|
+
"templates"
|
|
26
|
+
],
|
|
27
|
+
scripts: {
|
|
28
|
+
build: "tsc",
|
|
29
|
+
test: "vitest run",
|
|
30
|
+
"test:watch": "vitest",
|
|
31
|
+
clean: "rm -rf dist"
|
|
32
|
+
},
|
|
33
|
+
keywords: [
|
|
34
|
+
"codex",
|
|
35
|
+
"claude",
|
|
36
|
+
"claude-code",
|
|
37
|
+
"ai",
|
|
38
|
+
"api",
|
|
39
|
+
"config",
|
|
40
|
+
"manager"
|
|
41
|
+
],
|
|
42
|
+
author: "2ue",
|
|
43
|
+
license: "MIT",
|
|
44
|
+
repository: {
|
|
45
|
+
type: "git",
|
|
46
|
+
url: "https://github.com/2ue/ccm.git",
|
|
47
|
+
directory: "packages/core"
|
|
48
|
+
},
|
|
49
|
+
homepage: "https://github.com/2ue/ccm#readme",
|
|
50
|
+
bugs: {
|
|
51
|
+
url: "https://github.com/2ue/ccm/issues"
|
|
52
|
+
},
|
|
53
|
+
dependencies: {
|
|
54
|
+
"@iarna/toml": "^2.2.5",
|
|
55
|
+
"proper-lockfile": "^4.1.2",
|
|
56
|
+
webdav: "^5.8.0"
|
|
57
|
+
},
|
|
58
|
+
devDependencies: {
|
|
59
|
+
vitest: "^1.0.0"
|
|
60
|
+
},
|
|
61
|
+
engines: {
|
|
62
|
+
node: ">=18.0.0"
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// ../core/dist/paths.js
|
|
69
|
+
import * as os from "os";
|
|
70
|
+
import * as path from "path";
|
|
71
|
+
function getCcmanDir() {
|
|
72
|
+
return ccmanDir;
|
|
73
|
+
}
|
|
74
|
+
function getCodexDir() {
|
|
75
|
+
return codexDir;
|
|
76
|
+
}
|
|
77
|
+
function getClaudeDir() {
|
|
78
|
+
return claudeDir;
|
|
79
|
+
}
|
|
80
|
+
function getConfigPath() {
|
|
81
|
+
return path.join(ccmanDir, "config.json");
|
|
82
|
+
}
|
|
83
|
+
function getCodexConfigPath() {
|
|
84
|
+
return path.join(codexDir, "config.toml");
|
|
85
|
+
}
|
|
86
|
+
function getCodexAuthPath() {
|
|
87
|
+
return path.join(codexDir, "auth.json");
|
|
88
|
+
}
|
|
89
|
+
function getClaudeConfigPath() {
|
|
90
|
+
return path.join(claudeDir, "settings.json");
|
|
91
|
+
}
|
|
92
|
+
function getClaudeJsonPath() {
|
|
93
|
+
return path.join(rootDir, ".claude.json");
|
|
94
|
+
}
|
|
95
|
+
var isDev, isTest, rootDir, ccmanDir, codexDir, claudeDir;
|
|
96
|
+
var init_paths = __esm({
|
|
97
|
+
"../core/dist/paths.js"() {
|
|
98
|
+
"use strict";
|
|
99
|
+
isDev = process.env.NODE_ENV === "development";
|
|
100
|
+
isTest = process.env.NODE_ENV === "test";
|
|
101
|
+
if (isTest) {
|
|
102
|
+
rootDir = path.join(os.tmpdir(), `ccman-test-${process.pid}`);
|
|
103
|
+
} else if (isDev) {
|
|
104
|
+
rootDir = path.join(os.tmpdir(), "ccman-dev");
|
|
105
|
+
} else {
|
|
106
|
+
rootDir = os.homedir();
|
|
107
|
+
}
|
|
108
|
+
ccmanDir = path.join(rootDir, ".ccman");
|
|
109
|
+
codexDir = path.join(rootDir, ".codex");
|
|
110
|
+
claudeDir = path.join(rootDir, ".claude");
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ../core/dist/utils/file.js
|
|
115
|
+
import * as fs from "fs";
|
|
116
|
+
import * as path2 from "path";
|
|
117
|
+
function ensureDir(dir) {
|
|
118
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
119
|
+
}
|
|
120
|
+
function readJSON(filePath) {
|
|
121
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
122
|
+
return JSON.parse(content);
|
|
123
|
+
}
|
|
124
|
+
function writeJSON(filePath, data) {
|
|
125
|
+
const dir = path2.dirname(filePath);
|
|
126
|
+
ensureDir(dir);
|
|
127
|
+
const tmpPath = `${filePath}.tmp`;
|
|
128
|
+
fs.writeFileSync(tmpPath, JSON.stringify(data, null, 2), { mode: 384 });
|
|
129
|
+
fs.renameSync(tmpPath, filePath);
|
|
130
|
+
}
|
|
131
|
+
function fileExists(filePath) {
|
|
132
|
+
try {
|
|
133
|
+
fs.accessSync(filePath, fs.constants.F_OK);
|
|
134
|
+
return true;
|
|
135
|
+
} catch {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
var init_file = __esm({
|
|
140
|
+
"../core/dist/utils/file.js"() {
|
|
141
|
+
"use strict";
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// ../core/dist/utils/template.js
|
|
146
|
+
function replaceVariables(template, variables) {
|
|
147
|
+
const jsonStr = JSON.stringify(template);
|
|
148
|
+
let result = jsonStr;
|
|
149
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
150
|
+
const escapedValue = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
151
|
+
result = result.replace(new RegExp(`{{${key}}}`, "g"), escapedValue);
|
|
152
|
+
}
|
|
153
|
+
return JSON.parse(result);
|
|
154
|
+
}
|
|
155
|
+
function deepMerge(target, source) {
|
|
156
|
+
const result = { ...target };
|
|
157
|
+
for (const key in source) {
|
|
158
|
+
const sourceValue = source[key];
|
|
159
|
+
const targetValue = result[key];
|
|
160
|
+
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
161
|
+
result[key] = deepMerge(targetValue, sourceValue);
|
|
162
|
+
} else {
|
|
163
|
+
result[key] = sourceValue;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
var init_template = __esm({
|
|
169
|
+
"../core/dist/utils/template.js"() {
|
|
170
|
+
"use strict";
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// ../core/dist/writers/codex.js
|
|
175
|
+
import * as fs2 from "fs";
|
|
176
|
+
import * as path3 from "path";
|
|
177
|
+
import { fileURLToPath } from "url";
|
|
178
|
+
import { parse as parseToml, stringify as stringifyToml } from "@iarna/toml";
|
|
179
|
+
function loadCodexTemplateConfig() {
|
|
180
|
+
try {
|
|
181
|
+
const templatePath = path3.resolve(__dirname, "../../templates/codex/config.toml");
|
|
182
|
+
if (fs2.existsSync(templatePath)) {
|
|
183
|
+
const content = fs2.readFileSync(templatePath, "utf-8");
|
|
184
|
+
return parseToml(content);
|
|
185
|
+
}
|
|
186
|
+
} catch {
|
|
187
|
+
}
|
|
188
|
+
return CODEX_DEFAULT_CONFIG;
|
|
189
|
+
}
|
|
190
|
+
function writeCodexConfig(provider) {
|
|
191
|
+
ensureDir(getCodexDir());
|
|
192
|
+
const configPath = getCodexConfigPath();
|
|
193
|
+
let userConfig = {};
|
|
194
|
+
if (fileExists(configPath)) {
|
|
195
|
+
const content = fs2.readFileSync(configPath, "utf-8");
|
|
196
|
+
userConfig = parseToml(content);
|
|
197
|
+
}
|
|
198
|
+
const templateConfig = loadCodexTemplateConfig();
|
|
199
|
+
const mergedConfig = deepMerge(templateConfig, userConfig);
|
|
200
|
+
mergedConfig.model_provider = provider.name;
|
|
201
|
+
mergedConfig.model = provider.model || mergedConfig.model || "gpt-5-codex";
|
|
202
|
+
mergedConfig.model_providers = mergedConfig.model_providers || {};
|
|
203
|
+
mergedConfig.model_providers[provider.name] = {
|
|
204
|
+
name: provider.name,
|
|
205
|
+
base_url: provider.baseUrl,
|
|
206
|
+
wire_api: "responses",
|
|
207
|
+
requires_openai_auth: true
|
|
208
|
+
};
|
|
209
|
+
fs2.writeFileSync(configPath, stringifyToml(mergedConfig), { mode: 384 });
|
|
210
|
+
const authPath = getCodexAuthPath();
|
|
211
|
+
let auth;
|
|
212
|
+
if (fileExists(authPath)) {
|
|
213
|
+
const content = fs2.readFileSync(authPath, "utf-8");
|
|
214
|
+
auth = JSON.parse(content);
|
|
215
|
+
} else {
|
|
216
|
+
auth = { OPENAI_API_KEY: "" };
|
|
217
|
+
}
|
|
218
|
+
auth.OPENAI_API_KEY = provider.apiKey;
|
|
219
|
+
fs2.writeFileSync(authPath, JSON.stringify(auth, null, 2), { mode: 384 });
|
|
220
|
+
}
|
|
221
|
+
var __filename, __dirname, CODEX_DEFAULT_CONFIG;
|
|
222
|
+
var init_codex = __esm({
|
|
223
|
+
"../core/dist/writers/codex.js"() {
|
|
224
|
+
"use strict";
|
|
225
|
+
init_paths();
|
|
226
|
+
init_file();
|
|
227
|
+
init_template();
|
|
228
|
+
__filename = fileURLToPath(import.meta.url);
|
|
229
|
+
__dirname = path3.dirname(__filename);
|
|
230
|
+
CODEX_DEFAULT_CONFIG = {
|
|
231
|
+
model: "gpt-5.1",
|
|
232
|
+
model_reasoning_effort: "high",
|
|
233
|
+
disable_response_storage: true,
|
|
234
|
+
sandbox_mode: "workspace-write",
|
|
235
|
+
windows_wsl_setup_acknowledged: true,
|
|
236
|
+
approval_policy: "never",
|
|
237
|
+
profile: "auto-max",
|
|
238
|
+
file_opener: "vscode",
|
|
239
|
+
history: {
|
|
240
|
+
persistence: "save-all"
|
|
241
|
+
},
|
|
242
|
+
tui: {
|
|
243
|
+
notifications: true
|
|
244
|
+
},
|
|
245
|
+
shell_environment_policy: {
|
|
246
|
+
inherit: "all",
|
|
247
|
+
ignore_default_excludes: false
|
|
248
|
+
},
|
|
249
|
+
features: {
|
|
250
|
+
plan_tool: true,
|
|
251
|
+
apply_patch_freeform: true,
|
|
252
|
+
view_image_tool: true,
|
|
253
|
+
web_search_request: true,
|
|
254
|
+
unified_exec: false,
|
|
255
|
+
streamable_shell: false,
|
|
256
|
+
rmcp_client: true
|
|
257
|
+
},
|
|
258
|
+
sandbox_workspace_write: {
|
|
259
|
+
network_access: true
|
|
260
|
+
},
|
|
261
|
+
profiles: {
|
|
262
|
+
"auto-max": {
|
|
263
|
+
approval_policy: "never",
|
|
264
|
+
sandbox_mode: "workspace-write"
|
|
265
|
+
},
|
|
266
|
+
"review": {
|
|
267
|
+
approval_policy: "on-request",
|
|
268
|
+
sandbox_mode: "workspace-write"
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
notice: {
|
|
272
|
+
hide_gpt5_1_migration_prompt: true
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// ../core/dist/writers/claude.js
|
|
279
|
+
import * as fs3 from "fs";
|
|
280
|
+
import * as path4 from "path";
|
|
281
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
282
|
+
function loadClaudeTemplateConfig() {
|
|
283
|
+
try {
|
|
284
|
+
const templatePath = path4.resolve(__dirname2, "../../templates/claude/settings.json");
|
|
285
|
+
if (fs3.existsSync(templatePath)) {
|
|
286
|
+
const content = fs3.readFileSync(templatePath, "utf-8");
|
|
287
|
+
return JSON.parse(content);
|
|
288
|
+
}
|
|
289
|
+
} catch {
|
|
290
|
+
}
|
|
291
|
+
return CLAUDE_CONFIG_TEMPLATE;
|
|
292
|
+
}
|
|
293
|
+
function writeClaudeConfig(provider) {
|
|
294
|
+
ensureDir(getClaudeDir());
|
|
295
|
+
const configPath = getClaudeConfigPath();
|
|
296
|
+
let userConfig = {};
|
|
297
|
+
if (fileExists(configPath)) {
|
|
298
|
+
const content = fs3.readFileSync(configPath, "utf-8");
|
|
299
|
+
userConfig = JSON.parse(content);
|
|
300
|
+
}
|
|
301
|
+
const defaultTemplate = loadClaudeTemplateConfig();
|
|
302
|
+
const defaultConfig = replaceVariables(defaultTemplate, {
|
|
303
|
+
apiKey: provider.apiKey,
|
|
304
|
+
baseUrl: provider.baseUrl
|
|
305
|
+
});
|
|
306
|
+
const mergedConfig = deepMerge(defaultConfig, userConfig);
|
|
307
|
+
mergedConfig.env = mergedConfig.env || {};
|
|
308
|
+
mergedConfig.env.ANTHROPIC_AUTH_TOKEN = provider.apiKey;
|
|
309
|
+
mergedConfig.env.ANTHROPIC_BASE_URL = provider.baseUrl;
|
|
310
|
+
fs3.writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2), { mode: 384 });
|
|
311
|
+
}
|
|
312
|
+
var __filename2, __dirname2, CLAUDE_CONFIG_TEMPLATE;
|
|
313
|
+
var init_claude = __esm({
|
|
314
|
+
"../core/dist/writers/claude.js"() {
|
|
315
|
+
"use strict";
|
|
316
|
+
init_paths();
|
|
317
|
+
init_file();
|
|
318
|
+
init_template();
|
|
319
|
+
__filename2 = fileURLToPath2(import.meta.url);
|
|
320
|
+
__dirname2 = path4.dirname(__filename2);
|
|
321
|
+
CLAUDE_CONFIG_TEMPLATE = {
|
|
322
|
+
env: {
|
|
323
|
+
ANTHROPIC_AUTH_TOKEN: "{{apiKey}}",
|
|
324
|
+
ANTHROPIC_BASE_URL: "{{baseUrl}}",
|
|
325
|
+
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1,
|
|
326
|
+
CLAUDE_CODE_MAX_OUTPUT_TOKENS: 32e3
|
|
327
|
+
},
|
|
328
|
+
permissions: {
|
|
329
|
+
allow: [],
|
|
330
|
+
deny: []
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// ../core/dist/writers/mcp.js
|
|
337
|
+
import * as fs4 from "fs";
|
|
338
|
+
import * as path5 from "path";
|
|
339
|
+
function getMCPConfigPath() {
|
|
340
|
+
return path5.join(getCcmanDir(), "mcp.json");
|
|
341
|
+
}
|
|
342
|
+
function migrateMCPConfig(config) {
|
|
343
|
+
if (Array.isArray(config.managedServerNames)) {
|
|
344
|
+
config.managedServerNames = {
|
|
345
|
+
claude: config.managedServerNames,
|
|
346
|
+
codex: [],
|
|
347
|
+
cursor: [],
|
|
348
|
+
windsurf: []
|
|
349
|
+
};
|
|
350
|
+
} else if (!config.managedServerNames) {
|
|
351
|
+
config.managedServerNames = {
|
|
352
|
+
claude: [],
|
|
353
|
+
codex: [],
|
|
354
|
+
cursor: [],
|
|
355
|
+
windsurf: []
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
if (config.servers) {
|
|
359
|
+
for (const server of config.servers) {
|
|
360
|
+
if (!server.enabledApps) {
|
|
361
|
+
server.enabledApps = ["claude"];
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
} else {
|
|
365
|
+
config.servers = [];
|
|
366
|
+
}
|
|
367
|
+
return config;
|
|
368
|
+
}
|
|
369
|
+
function loadMCPConfig() {
|
|
370
|
+
const configPath = getMCPConfigPath();
|
|
371
|
+
if (!fileExists(configPath)) {
|
|
372
|
+
return {
|
|
373
|
+
servers: [],
|
|
374
|
+
managedServerNames: {
|
|
375
|
+
claude: [],
|
|
376
|
+
codex: [],
|
|
377
|
+
cursor: [],
|
|
378
|
+
windsurf: []
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
const config = readJSON(configPath);
|
|
383
|
+
return migrateMCPConfig(config);
|
|
384
|
+
}
|
|
385
|
+
function saveMCPConfig(config) {
|
|
386
|
+
const configPath = getMCPConfigPath();
|
|
387
|
+
writeJSON(configPath, config);
|
|
388
|
+
}
|
|
389
|
+
function providerToMCPServer(provider) {
|
|
390
|
+
let env;
|
|
391
|
+
let description;
|
|
392
|
+
if (provider.model) {
|
|
393
|
+
try {
|
|
394
|
+
const modelData = JSON.parse(provider.model);
|
|
395
|
+
env = modelData.env;
|
|
396
|
+
description = modelData.description;
|
|
397
|
+
} catch (error) {
|
|
398
|
+
env = JSON.parse(provider.model);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return {
|
|
402
|
+
id: provider.id,
|
|
403
|
+
name: provider.name,
|
|
404
|
+
command: provider.baseUrl,
|
|
405
|
+
args: provider.apiKey.split(" ").filter((arg) => arg.length > 0),
|
|
406
|
+
env,
|
|
407
|
+
description,
|
|
408
|
+
createdAt: provider.createdAt,
|
|
409
|
+
lastModified: provider.lastModified,
|
|
410
|
+
enabledApps: ["claude"]
|
|
411
|
+
// 新创建的 MCP 默认启用 Claude
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
function mcpServerToProvider(server) {
|
|
415
|
+
let model;
|
|
416
|
+
if (server.env || server.description) {
|
|
417
|
+
model = JSON.stringify({
|
|
418
|
+
env: server.env,
|
|
419
|
+
description: server.description
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
return {
|
|
423
|
+
id: server.id,
|
|
424
|
+
name: server.name,
|
|
425
|
+
baseUrl: server.command,
|
|
426
|
+
apiKey: server.args.join(" "),
|
|
427
|
+
model,
|
|
428
|
+
createdAt: server.createdAt,
|
|
429
|
+
lastModified: server.lastModified
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
function writeMCPConfigForApp(app, _provider) {
|
|
433
|
+
const mcpConfig = loadMCPConfig();
|
|
434
|
+
const enabledServers = mcpConfig.servers.filter((server) => server.enabledApps.includes(app));
|
|
435
|
+
let configPath;
|
|
436
|
+
let configDir;
|
|
437
|
+
switch (app) {
|
|
438
|
+
case "claude":
|
|
439
|
+
configPath = getClaudeConfigPath();
|
|
440
|
+
configDir = getClaudeDir();
|
|
441
|
+
break;
|
|
442
|
+
case "codex":
|
|
443
|
+
return;
|
|
444
|
+
case "cursor":
|
|
445
|
+
return;
|
|
446
|
+
case "windsurf":
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
ensureDir(configDir);
|
|
450
|
+
let appConfig = {};
|
|
451
|
+
if (fileExists(configPath)) {
|
|
452
|
+
try {
|
|
453
|
+
const content = fs4.readFileSync(configPath, "utf-8");
|
|
454
|
+
appConfig = JSON.parse(content);
|
|
455
|
+
} catch (error) {
|
|
456
|
+
throw new Error(`\u65E0\u6CD5\u8BFB\u53D6 ${app} \u914D\u7F6E\u6587\u4EF6: ${error.message}`);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
const existingMCPs = appConfig.mcpServers || {};
|
|
460
|
+
const userMCPs = {};
|
|
461
|
+
const managedNames = mcpConfig.managedServerNames[app] || [];
|
|
462
|
+
for (const [name, config] of Object.entries(existingMCPs)) {
|
|
463
|
+
if (!managedNames.includes(name)) {
|
|
464
|
+
userMCPs[name] = config;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
const ccmanMCPs = {};
|
|
468
|
+
for (const server of enabledServers) {
|
|
469
|
+
ccmanMCPs[server.name] = {
|
|
470
|
+
command: server.command,
|
|
471
|
+
args: server.args,
|
|
472
|
+
env: server.env
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
appConfig.mcpServers = {
|
|
476
|
+
...ccmanMCPs,
|
|
477
|
+
// ccman 管理的
|
|
478
|
+
...userMCPs
|
|
479
|
+
// 用户手动配置的(优先级更高)
|
|
480
|
+
};
|
|
481
|
+
const tempPath = `${configPath}.tmp`;
|
|
482
|
+
fs4.writeFileSync(tempPath, JSON.stringify(appConfig, null, 2), {
|
|
483
|
+
mode: 384
|
|
484
|
+
});
|
|
485
|
+
fs4.renameSync(tempPath, configPath);
|
|
486
|
+
}
|
|
487
|
+
function writeMCPConfig(_provider) {
|
|
488
|
+
writeMCPConfigForApp("claude", _provider);
|
|
489
|
+
}
|
|
490
|
+
var init_mcp = __esm({
|
|
491
|
+
"../core/dist/writers/mcp.js"() {
|
|
492
|
+
"use strict";
|
|
493
|
+
init_paths();
|
|
494
|
+
init_file();
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
// ../core/dist/presets/codex.js
|
|
499
|
+
var CODEX_PRESETS;
|
|
500
|
+
var init_codex2 = __esm({
|
|
501
|
+
"../core/dist/presets/codex.js"() {
|
|
502
|
+
"use strict";
|
|
503
|
+
CODEX_PRESETS = [
|
|
504
|
+
{
|
|
505
|
+
name: "88Code",
|
|
506
|
+
baseUrl: "https://www.88code.org/openai/v1",
|
|
507
|
+
description: "88Code API \u670D\u52A1"
|
|
508
|
+
}
|
|
509
|
+
];
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
// ../core/dist/presets/claude.js
|
|
514
|
+
var CC_PRESETS;
|
|
515
|
+
var init_claude2 = __esm({
|
|
516
|
+
"../core/dist/presets/claude.js"() {
|
|
517
|
+
"use strict";
|
|
518
|
+
CC_PRESETS = [
|
|
519
|
+
{
|
|
520
|
+
name: "Anthropic Official",
|
|
521
|
+
baseUrl: "https://api.anthropic.com",
|
|
522
|
+
description: "Anthropic \u5B98\u65B9 API"
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
name: "AnyRouter",
|
|
526
|
+
baseUrl: "https://anyrouter.top",
|
|
527
|
+
description: "AnyRouter API \u670D\u52A1"
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
name: "PackyCode",
|
|
531
|
+
baseUrl: "https://api.packycode.com",
|
|
532
|
+
description: "PackyCode API \u670D\u52A1"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
name: "88Code",
|
|
536
|
+
baseUrl: "https://www.88code.org/api",
|
|
537
|
+
description: "88Code API \u670D\u52A1"
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
name: "KKYYXX",
|
|
541
|
+
baseUrl: "https://api.kkyyxx.xyz",
|
|
542
|
+
description: "KKYYXX API \u670D\u52A1"
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
name: "BigModel",
|
|
546
|
+
baseUrl: "https://open.bigmodel.cn/api/anthropic",
|
|
547
|
+
description: "\u667A\u8C31 BigModel API"
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
name: "ModelScope",
|
|
551
|
+
baseUrl: "https://api-inference.modelscope.cn/v1/chat/completions",
|
|
552
|
+
description: "\u963F\u91CC\u4E91 ModelScope API"
|
|
553
|
+
}
|
|
554
|
+
];
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
// ../core/dist/presets/mcp.js
|
|
559
|
+
var MCP_PRESETS_DETAIL, MCP_PRESETS;
|
|
560
|
+
var init_mcp2 = __esm({
|
|
561
|
+
"../core/dist/presets/mcp.js"() {
|
|
562
|
+
"use strict";
|
|
563
|
+
MCP_PRESETS_DETAIL = [
|
|
564
|
+
{
|
|
565
|
+
name: "filesystem",
|
|
566
|
+
command: "npx",
|
|
567
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files"],
|
|
568
|
+
description: "\u6587\u4EF6\u7CFB\u7EDF\u8BBF\u95EE",
|
|
569
|
+
argsPlaceholder: "\u9700\u8981\u4FEE\u6539\u7B2C3\u4E2A\u53C2\u6570\u4E3A\u5141\u8BB8\u8BBF\u95EE\u7684\u76EE\u5F55\u8DEF\u5F84"
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
name: "github",
|
|
573
|
+
command: "npx",
|
|
574
|
+
args: ["-y", "@modelcontextprotocol/server-github"],
|
|
575
|
+
description: "GitHub \u96C6\u6210",
|
|
576
|
+
envRequired: ["GITHUB_PERSONAL_ACCESS_TOKEN"]
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
name: "postgres",
|
|
580
|
+
command: "npx",
|
|
581
|
+
args: ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"],
|
|
582
|
+
description: "PostgreSQL \u6570\u636E\u5E93",
|
|
583
|
+
argsPlaceholder: "\u9700\u8981\u4FEE\u6539\u7B2C3\u4E2A\u53C2\u6570\u4E3A\u6570\u636E\u5E93\u8FDE\u63A5\u5B57\u7B26\u4E32"
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
name: "brave-search",
|
|
587
|
+
command: "npx",
|
|
588
|
+
args: ["-y", "@modelcontextprotocol/server-brave-search"],
|
|
589
|
+
description: "Brave \u641C\u7D22",
|
|
590
|
+
envRequired: ["BRAVE_API_KEY"]
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
name: "google-maps",
|
|
594
|
+
command: "npx",
|
|
595
|
+
args: ["-y", "@modelcontextprotocol/server-google-maps"],
|
|
596
|
+
description: "Google Maps",
|
|
597
|
+
envRequired: ["GOOGLE_MAPS_API_KEY"]
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
name: "puppeteer",
|
|
601
|
+
command: "npx",
|
|
602
|
+
args: ["-y", "@modelcontextprotocol/server-puppeteer"],
|
|
603
|
+
description: "\u6D4F\u89C8\u5668\u81EA\u52A8\u5316"
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
name: "sqlite",
|
|
607
|
+
command: "npx",
|
|
608
|
+
args: ["-y", "@modelcontextprotocol/server-sqlite", "/path/to/database.db"],
|
|
609
|
+
description: "SQLite \u6570\u636E\u5E93",
|
|
610
|
+
argsPlaceholder: "\u9700\u8981\u4FEE\u6539\u7B2C3\u4E2A\u53C2\u6570\u4E3A\u6570\u636E\u5E93\u6587\u4EF6\u8DEF\u5F84"
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
name: "sequential-thinking",
|
|
614
|
+
command: "npx",
|
|
615
|
+
args: ["-y", "@modelcontextprotocol/server-sequential-thinking"],
|
|
616
|
+
description: "\u5E8F\u5217\u601D\u8003\u589E\u5F3A"
|
|
617
|
+
}
|
|
618
|
+
];
|
|
619
|
+
MCP_PRESETS = MCP_PRESETS_DETAIL.map((preset) => ({
|
|
620
|
+
name: preset.name,
|
|
621
|
+
baseUrl: preset.command,
|
|
622
|
+
// 字段映射:command → baseUrl
|
|
623
|
+
description: preset.description
|
|
624
|
+
}));
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
// ../core/dist/tool-manager.types.js
|
|
629
|
+
var ProviderNotFoundError, ProviderNameConflictError, PresetNameConflictError;
|
|
630
|
+
var init_tool_manager_types = __esm({
|
|
631
|
+
"../core/dist/tool-manager.types.js"() {
|
|
632
|
+
"use strict";
|
|
633
|
+
ProviderNotFoundError = class extends Error {
|
|
634
|
+
constructor(id) {
|
|
635
|
+
super(`\u670D\u52A1\u5546\u4E0D\u5B58\u5728: ${id}`);
|
|
636
|
+
this.name = "ProviderNotFoundError";
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
ProviderNameConflictError = class extends Error {
|
|
640
|
+
constructor(name) {
|
|
641
|
+
super(`\u670D\u52A1\u5546\u540D\u79F0\u5DF2\u5B58\u5728: ${name}`);
|
|
642
|
+
this.name = "ProviderNameConflictError";
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
PresetNameConflictError = class extends Error {
|
|
646
|
+
constructor(name) {
|
|
647
|
+
super(`\u9884\u7F6E\u540D\u79F0\u5DF2\u5B58\u5728: ${name}`);
|
|
648
|
+
this.name = "PresetNameConflictError";
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
// ../core/dist/tool-manager.js
|
|
655
|
+
import * as path6 from "path";
|
|
656
|
+
function createToolManager(tool) {
|
|
657
|
+
const toolConfig = TOOL_CONFIGS[tool];
|
|
658
|
+
const configPath = toolConfig.configPath;
|
|
659
|
+
function generateId() {
|
|
660
|
+
const timestamp = Date.now();
|
|
661
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
662
|
+
return `${tool}-${timestamp}-${random}`;
|
|
663
|
+
}
|
|
664
|
+
function loadConfig2() {
|
|
665
|
+
if (toolConfig.customLoader) {
|
|
666
|
+
return toolConfig.customLoader();
|
|
667
|
+
}
|
|
668
|
+
if (!fileExists(configPath)) {
|
|
669
|
+
ensureDir(getCcmanDir());
|
|
670
|
+
const initialConfig = {
|
|
671
|
+
providers: [],
|
|
672
|
+
presets: []
|
|
673
|
+
};
|
|
674
|
+
writeJSON(configPath, initialConfig);
|
|
675
|
+
return initialConfig;
|
|
676
|
+
}
|
|
677
|
+
return readJSON(configPath);
|
|
678
|
+
}
|
|
679
|
+
function saveConfig2(config) {
|
|
680
|
+
if (toolConfig.customSaver) {
|
|
681
|
+
toolConfig.customSaver(config);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
writeJSON(configPath, config);
|
|
685
|
+
}
|
|
686
|
+
return {
|
|
687
|
+
add(input) {
|
|
688
|
+
const config = loadConfig2();
|
|
689
|
+
const nameExists = config.providers.some((p) => p.name === input.name);
|
|
690
|
+
if (nameExists) {
|
|
691
|
+
throw new ProviderNameConflictError(input.name);
|
|
692
|
+
}
|
|
693
|
+
const timestamp = Date.now();
|
|
694
|
+
const provider = {
|
|
695
|
+
id: generateId(),
|
|
696
|
+
name: input.name,
|
|
697
|
+
desc: input.desc,
|
|
698
|
+
baseUrl: input.baseUrl,
|
|
699
|
+
apiKey: input.apiKey,
|
|
700
|
+
model: input.model,
|
|
701
|
+
createdAt: timestamp,
|
|
702
|
+
lastModified: timestamp
|
|
703
|
+
};
|
|
704
|
+
config.providers.push(provider);
|
|
705
|
+
saveConfig2(config);
|
|
706
|
+
if (toolConfig.autoSync) {
|
|
707
|
+
toolConfig.writer(provider);
|
|
708
|
+
}
|
|
709
|
+
return provider;
|
|
710
|
+
},
|
|
711
|
+
list() {
|
|
712
|
+
const config = loadConfig2();
|
|
713
|
+
return config.providers;
|
|
714
|
+
},
|
|
715
|
+
get(id) {
|
|
716
|
+
const config = loadConfig2();
|
|
717
|
+
const provider = config.providers.find((p) => p.id === id);
|
|
718
|
+
if (!provider) {
|
|
719
|
+
throw new ProviderNotFoundError(id);
|
|
720
|
+
}
|
|
721
|
+
return provider;
|
|
722
|
+
},
|
|
723
|
+
findByName(name) {
|
|
724
|
+
const config = loadConfig2();
|
|
725
|
+
const lowerName = name.toLowerCase();
|
|
726
|
+
return config.providers.find((p) => p.name.toLowerCase() === lowerName);
|
|
727
|
+
},
|
|
728
|
+
switch(id) {
|
|
729
|
+
const config = loadConfig2();
|
|
730
|
+
const provider = config.providers.find((p) => p.id === id);
|
|
731
|
+
if (!provider) {
|
|
732
|
+
throw new ProviderNotFoundError(id);
|
|
733
|
+
}
|
|
734
|
+
config.currentProviderId = id;
|
|
735
|
+
provider.lastUsedAt = Date.now();
|
|
736
|
+
saveConfig2(config);
|
|
737
|
+
toolConfig.writer(provider);
|
|
738
|
+
},
|
|
739
|
+
getCurrent() {
|
|
740
|
+
const config = loadConfig2();
|
|
741
|
+
if (!config.currentProviderId) {
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
const provider = config.providers.find((p) => p.id === config.currentProviderId);
|
|
745
|
+
return provider || null;
|
|
746
|
+
},
|
|
747
|
+
// 注:edit 方法的"复杂度"来自必要的业务逻辑(检查存在性、名称冲突、更新 4 个可选字段、同步配置)
|
|
748
|
+
// 每个 if 都不可避免,没有特殊情况或嵌套逻辑,因此禁用 complexity 检查
|
|
749
|
+
// eslint-disable-next-line complexity
|
|
750
|
+
edit(id, updates) {
|
|
751
|
+
const config = loadConfig2();
|
|
752
|
+
const provider = config.providers.find((p) => p.id === id);
|
|
753
|
+
if (!provider) {
|
|
754
|
+
throw new ProviderNotFoundError(id);
|
|
755
|
+
}
|
|
756
|
+
if (updates.name !== void 0 && updates.name !== provider.name) {
|
|
757
|
+
const nameConflict = config.providers.some((p) => p.id !== id && p.name === updates.name);
|
|
758
|
+
if (nameConflict) {
|
|
759
|
+
throw new ProviderNameConflictError(updates.name);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
if (updates.name !== void 0)
|
|
763
|
+
provider.name = updates.name;
|
|
764
|
+
if (updates.desc !== void 0)
|
|
765
|
+
provider.desc = updates.desc;
|
|
766
|
+
if (updates.baseUrl !== void 0)
|
|
767
|
+
provider.baseUrl = updates.baseUrl;
|
|
768
|
+
if (updates.apiKey !== void 0)
|
|
769
|
+
provider.apiKey = updates.apiKey;
|
|
770
|
+
if (updates.model !== void 0)
|
|
771
|
+
provider.model = updates.model;
|
|
772
|
+
provider.lastModified = Date.now();
|
|
773
|
+
saveConfig2(config);
|
|
774
|
+
if (config.currentProviderId === id) {
|
|
775
|
+
toolConfig.writer(provider);
|
|
776
|
+
}
|
|
777
|
+
if (toolConfig.autoSync) {
|
|
778
|
+
toolConfig.writer(provider);
|
|
779
|
+
}
|
|
780
|
+
return provider;
|
|
781
|
+
},
|
|
782
|
+
remove(id) {
|
|
783
|
+
const config = loadConfig2();
|
|
784
|
+
const index = config.providers.findIndex((p) => p.id === id);
|
|
785
|
+
if (index === -1) {
|
|
786
|
+
throw new ProviderNotFoundError(id);
|
|
787
|
+
}
|
|
788
|
+
if (config.currentProviderId === id) {
|
|
789
|
+
config.currentProviderId = void 0;
|
|
790
|
+
}
|
|
791
|
+
config.providers.splice(index, 1);
|
|
792
|
+
saveConfig2(config);
|
|
793
|
+
if (toolConfig.autoSync) {
|
|
794
|
+
toolConfig.writer({});
|
|
795
|
+
}
|
|
796
|
+
},
|
|
797
|
+
clone(sourceId, newName) {
|
|
798
|
+
const source = this.get(sourceId);
|
|
799
|
+
const config = loadConfig2();
|
|
800
|
+
const nameExists = config.providers.some((p) => p.name === newName);
|
|
801
|
+
if (nameExists) {
|
|
802
|
+
throw new ProviderNameConflictError(newName);
|
|
803
|
+
}
|
|
804
|
+
const timestamp = Date.now();
|
|
805
|
+
const newProvider = {
|
|
806
|
+
...source,
|
|
807
|
+
id: generateId(),
|
|
808
|
+
name: newName,
|
|
809
|
+
desc: void 0,
|
|
810
|
+
createdAt: timestamp,
|
|
811
|
+
lastModified: timestamp,
|
|
812
|
+
lastUsedAt: void 0
|
|
813
|
+
};
|
|
814
|
+
config.providers.push(newProvider);
|
|
815
|
+
saveConfig2(config);
|
|
816
|
+
return newProvider;
|
|
817
|
+
},
|
|
818
|
+
addPreset(input) {
|
|
819
|
+
const config = loadConfig2();
|
|
820
|
+
if (!config.presets) {
|
|
821
|
+
config.presets = [];
|
|
822
|
+
}
|
|
823
|
+
const allPresets = [...toolConfig.builtinPresets, ...config.presets];
|
|
824
|
+
const nameExists = allPresets.some((p) => p.name === input.name);
|
|
825
|
+
if (nameExists) {
|
|
826
|
+
throw new PresetNameConflictError(input.name);
|
|
827
|
+
}
|
|
828
|
+
const preset = {
|
|
829
|
+
name: input.name,
|
|
830
|
+
baseUrl: input.baseUrl,
|
|
831
|
+
description: input.description
|
|
832
|
+
};
|
|
833
|
+
config.presets.push(preset);
|
|
834
|
+
saveConfig2(config);
|
|
835
|
+
return {
|
|
836
|
+
...preset,
|
|
837
|
+
isBuiltIn: false
|
|
838
|
+
};
|
|
839
|
+
},
|
|
840
|
+
listPresets() {
|
|
841
|
+
const config = loadConfig2();
|
|
842
|
+
const userPresets = config.presets || [];
|
|
843
|
+
const builtinWithFlag = toolConfig.builtinPresets.map((p) => ({
|
|
844
|
+
...p,
|
|
845
|
+
isBuiltIn: true
|
|
846
|
+
}));
|
|
847
|
+
const userWithFlag = userPresets.map((p) => ({
|
|
848
|
+
...p,
|
|
849
|
+
isBuiltIn: false
|
|
850
|
+
}));
|
|
851
|
+
return [...builtinWithFlag, ...userWithFlag];
|
|
852
|
+
},
|
|
853
|
+
editPreset(name, updates) {
|
|
854
|
+
const config = loadConfig2();
|
|
855
|
+
if (!config.presets) {
|
|
856
|
+
config.presets = [];
|
|
857
|
+
}
|
|
858
|
+
const preset = config.presets.find((p) => p.name === name);
|
|
859
|
+
if (!preset) {
|
|
860
|
+
throw new Error(`\u9884\u7F6E\u4E0D\u5B58\u5728: ${name}`);
|
|
861
|
+
}
|
|
862
|
+
if (updates.name !== void 0 && updates.name !== preset.name) {
|
|
863
|
+
const allPresets = [...toolConfig.builtinPresets, ...config.presets];
|
|
864
|
+
const nameConflict = allPresets.some((p) => p.name !== name && p.name === updates.name);
|
|
865
|
+
if (nameConflict) {
|
|
866
|
+
throw new PresetNameConflictError(updates.name);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
if (updates.name !== void 0)
|
|
870
|
+
preset.name = updates.name;
|
|
871
|
+
if (updates.baseUrl !== void 0)
|
|
872
|
+
preset.baseUrl = updates.baseUrl;
|
|
873
|
+
if (updates.description !== void 0)
|
|
874
|
+
preset.description = updates.description;
|
|
875
|
+
saveConfig2(config);
|
|
876
|
+
return {
|
|
877
|
+
...preset,
|
|
878
|
+
isBuiltIn: false
|
|
879
|
+
};
|
|
880
|
+
},
|
|
881
|
+
removePreset(name) {
|
|
882
|
+
const config = loadConfig2();
|
|
883
|
+
if (!config.presets) {
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
const index = config.presets.findIndex((p) => p.name === name);
|
|
887
|
+
if (index === -1) {
|
|
888
|
+
throw new Error(`Preset not found: ${name}`);
|
|
889
|
+
}
|
|
890
|
+
config.presets.splice(index, 1);
|
|
891
|
+
saveConfig2(config);
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
function createCodexManager() {
|
|
896
|
+
return createToolManager("codex");
|
|
897
|
+
}
|
|
898
|
+
function createClaudeManager() {
|
|
899
|
+
return createToolManager("claude");
|
|
900
|
+
}
|
|
901
|
+
function createMCPManager() {
|
|
902
|
+
return createToolManager("mcp");
|
|
903
|
+
}
|
|
904
|
+
var TOOL_CONFIGS;
|
|
905
|
+
var init_tool_manager = __esm({
|
|
906
|
+
"../core/dist/tool-manager.js"() {
|
|
907
|
+
"use strict";
|
|
908
|
+
init_paths();
|
|
909
|
+
init_file();
|
|
910
|
+
init_codex();
|
|
911
|
+
init_claude();
|
|
912
|
+
init_mcp();
|
|
913
|
+
init_codex2();
|
|
914
|
+
init_claude2();
|
|
915
|
+
init_mcp2();
|
|
916
|
+
init_tool_manager_types();
|
|
917
|
+
TOOL_CONFIGS = {
|
|
918
|
+
codex: {
|
|
919
|
+
configPath: path6.join(getCcmanDir(), "codex.json"),
|
|
920
|
+
builtinPresets: CODEX_PRESETS,
|
|
921
|
+
writer: writeCodexConfig
|
|
922
|
+
},
|
|
923
|
+
claude: {
|
|
924
|
+
configPath: path6.join(getCcmanDir(), "claude.json"),
|
|
925
|
+
builtinPresets: CC_PRESETS,
|
|
926
|
+
writer: writeClaudeConfig
|
|
927
|
+
},
|
|
928
|
+
mcp: {
|
|
929
|
+
configPath: path6.join(getCcmanDir(), "mcp.json"),
|
|
930
|
+
builtinPresets: MCP_PRESETS,
|
|
931
|
+
writer: writeMCPConfig,
|
|
932
|
+
autoSync: true,
|
|
933
|
+
// MCP 需要在每个操作后自动同步到 ~/.claude.json
|
|
934
|
+
// MCP 使用特殊的配置格式(MCPConfig),需要自定义 loader/saver
|
|
935
|
+
customLoader: () => {
|
|
936
|
+
const mcpConfig = loadMCPConfig();
|
|
937
|
+
return {
|
|
938
|
+
providers: mcpConfig.servers.map(mcpServerToProvider),
|
|
939
|
+
presets: []
|
|
940
|
+
};
|
|
941
|
+
},
|
|
942
|
+
customSaver: (config) => {
|
|
943
|
+
const mcpConfig = loadMCPConfig();
|
|
944
|
+
mcpConfig.servers = config.providers.map((provider) => {
|
|
945
|
+
const existingServer = mcpConfig.servers.find((s) => s.id === provider.id);
|
|
946
|
+
const mcpServer = providerToMCPServer(provider);
|
|
947
|
+
if (existingServer) {
|
|
948
|
+
mcpServer.enabledApps = existingServer.enabledApps;
|
|
949
|
+
}
|
|
950
|
+
return mcpServer;
|
|
951
|
+
});
|
|
952
|
+
for (const app of ["claude", "codex", "cursor", "windsurf"]) {
|
|
953
|
+
mcpConfig.managedServerNames[app] = mcpConfig.servers.filter((s) => s.enabledApps.includes(app)).map((s) => s.name);
|
|
954
|
+
}
|
|
955
|
+
saveMCPConfig(mcpConfig);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
// ../core/dist/migrate.js
|
|
963
|
+
var init_migrate = __esm({
|
|
964
|
+
"../core/dist/migrate.js"() {
|
|
965
|
+
"use strict";
|
|
966
|
+
init_paths();
|
|
967
|
+
}
|
|
968
|
+
});
|
|
969
|
+
|
|
970
|
+
// ../core/dist/config.js
|
|
971
|
+
import * as fs5 from "fs";
|
|
972
|
+
function ensureConfigDir() {
|
|
973
|
+
const dir = getCcmanDir();
|
|
974
|
+
if (!fs5.existsSync(dir)) {
|
|
975
|
+
fs5.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
function loadConfig() {
|
|
979
|
+
const configPath = getConfigPath();
|
|
980
|
+
if (!fs5.existsSync(configPath)) {
|
|
981
|
+
return {};
|
|
982
|
+
}
|
|
983
|
+
try {
|
|
984
|
+
const content = fs5.readFileSync(configPath, "utf-8");
|
|
985
|
+
return JSON.parse(content);
|
|
986
|
+
} catch (error) {
|
|
987
|
+
throw new Error(`Failed to load config: ${error.message}`);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
function saveConfig(config) {
|
|
991
|
+
ensureConfigDir();
|
|
992
|
+
const configPath = getConfigPath();
|
|
993
|
+
try {
|
|
994
|
+
const tempPath = `${configPath}.tmp`;
|
|
995
|
+
fs5.writeFileSync(tempPath, JSON.stringify(config, null, 2), {
|
|
996
|
+
mode: 384
|
|
997
|
+
});
|
|
998
|
+
fs5.renameSync(tempPath, configPath);
|
|
999
|
+
} catch (error) {
|
|
1000
|
+
throw new Error(`Failed to save config: ${error.message}`);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
function getSyncConfig() {
|
|
1004
|
+
const config = loadConfig();
|
|
1005
|
+
return config.sync || null;
|
|
1006
|
+
}
|
|
1007
|
+
function saveSyncConfig(syncConfig) {
|
|
1008
|
+
const config = loadConfig();
|
|
1009
|
+
config.sync = syncConfig;
|
|
1010
|
+
saveConfig(config);
|
|
1011
|
+
}
|
|
1012
|
+
function updateLastSyncTime() {
|
|
1013
|
+
const config = loadConfig();
|
|
1014
|
+
if (config.sync) {
|
|
1015
|
+
config.sync.lastSync = Date.now();
|
|
1016
|
+
saveConfig(config);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
var init_config = __esm({
|
|
1020
|
+
"../core/dist/config.js"() {
|
|
1021
|
+
"use strict";
|
|
1022
|
+
init_paths();
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
1025
|
+
|
|
1026
|
+
// ../core/dist/sync/webdav-client.js
|
|
1027
|
+
import { createClient } from "webdav";
|
|
1028
|
+
function normalizePath(dir) {
|
|
1029
|
+
if (!dir || dir === "/") {
|
|
1030
|
+
return "/";
|
|
1031
|
+
}
|
|
1032
|
+
const normalized = dir.trim().replace(/^\/+/, "").replace(/\/+$/, "");
|
|
1033
|
+
return `/${normalized}`;
|
|
1034
|
+
}
|
|
1035
|
+
function joinPath(baseDir, filename) {
|
|
1036
|
+
const normalizedBase = normalizePath(baseDir);
|
|
1037
|
+
const normalizedFile = filename.replace(/^\/+/, "");
|
|
1038
|
+
if (normalizedBase === "/") {
|
|
1039
|
+
return `/${normalizedFile}`;
|
|
1040
|
+
}
|
|
1041
|
+
return `${normalizedBase}/${normalizedFile}`;
|
|
1042
|
+
}
|
|
1043
|
+
function createWebDAVClient(config) {
|
|
1044
|
+
const client = createClient(config.webdavUrl, {
|
|
1045
|
+
username: config.username,
|
|
1046
|
+
password: config.password,
|
|
1047
|
+
authType: config.authType || "password",
|
|
1048
|
+
// 默认使用 Basic Auth
|
|
1049
|
+
maxBodyLength: 100 * 1024 * 1024,
|
|
1050
|
+
// 100MB
|
|
1051
|
+
maxContentLength: 100 * 1024 * 1024
|
|
1052
|
+
// 100MB
|
|
1053
|
+
});
|
|
1054
|
+
return client;
|
|
1055
|
+
}
|
|
1056
|
+
async function testWebDAVConnection(config) {
|
|
1057
|
+
const remoteDir = normalizePath(config.remoteDir || "/");
|
|
1058
|
+
try {
|
|
1059
|
+
const client = createWebDAVClient(config);
|
|
1060
|
+
await client.getDirectoryContents(remoteDir);
|
|
1061
|
+
return true;
|
|
1062
|
+
} catch (error) {
|
|
1063
|
+
return false;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
async function ensureDirectory(config, dirPath) {
|
|
1067
|
+
const client = createWebDAVClient(config);
|
|
1068
|
+
const normalizedPath = normalizePath(dirPath);
|
|
1069
|
+
if (normalizedPath === "/") {
|
|
1070
|
+
return true;
|
|
1071
|
+
}
|
|
1072
|
+
try {
|
|
1073
|
+
const exists = await client.exists(normalizedPath);
|
|
1074
|
+
if (exists) {
|
|
1075
|
+
return true;
|
|
1076
|
+
}
|
|
1077
|
+
const parentPath = normalizedPath.substring(0, normalizedPath.lastIndexOf("/"));
|
|
1078
|
+
if (parentPath && parentPath !== "/") {
|
|
1079
|
+
await ensureDirectory(config, parentPath);
|
|
1080
|
+
}
|
|
1081
|
+
await client.createDirectory(normalizedPath);
|
|
1082
|
+
return true;
|
|
1083
|
+
} catch (error) {
|
|
1084
|
+
console.warn(`\u521B\u5EFA\u76EE\u5F55 ${normalizedPath} \u5931\u8D25\uFF0C\u5C06\u5C1D\u8BD5\u76F4\u63A5\u4E0A\u4F20\u6587\u4EF6:`, error.message);
|
|
1085
|
+
return false;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
function isPathNotFoundError(error) {
|
|
1089
|
+
const msg = error.message.toLowerCase();
|
|
1090
|
+
return msg.includes("404") || msg.includes("409") || msg.includes("not found") || msg.includes("conflict");
|
|
1091
|
+
}
|
|
1092
|
+
async function uploadToWebDAV(config, filename, data) {
|
|
1093
|
+
const client = createWebDAVClient(config);
|
|
1094
|
+
const remoteDir = normalizePath(config.remoteDir || "/");
|
|
1095
|
+
const fullPath = joinPath(remoteDir, filename);
|
|
1096
|
+
try {
|
|
1097
|
+
await client.putFileContents(fullPath, data, { overwrite: true });
|
|
1098
|
+
} catch (firstError) {
|
|
1099
|
+
if (isPathNotFoundError(firstError)) {
|
|
1100
|
+
const dirPath = fullPath.substring(0, fullPath.lastIndexOf("/"));
|
|
1101
|
+
if (dirPath && dirPath !== "/") {
|
|
1102
|
+
await ensureDirectory(config, dirPath);
|
|
1103
|
+
await client.putFileContents(fullPath, data, { overwrite: true });
|
|
1104
|
+
} else {
|
|
1105
|
+
throw firstError;
|
|
1106
|
+
}
|
|
1107
|
+
} else {
|
|
1108
|
+
throw firstError;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
try {
|
|
1112
|
+
const exists = await client.exists(fullPath);
|
|
1113
|
+
if (!exists) {
|
|
1114
|
+
throw new Error(`\u6587\u4EF6\u4E0A\u4F20\u540E\u672A\u5728\u670D\u52A1\u5668\u4E0A\u627E\u5230: ${fullPath}`);
|
|
1115
|
+
}
|
|
1116
|
+
} catch (verifyError) {
|
|
1117
|
+
const errorMsg = verifyError.message;
|
|
1118
|
+
if (errorMsg.includes("multistatus") || errorMsg.includes("Invalid response")) {
|
|
1119
|
+
throw new Error(`WebDAV \u914D\u7F6E\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\uFF1A
|
|
1120
|
+
1. URL \u662F\u5426\u4E3A WebDAV \u7AEF\u70B9\uFF08\u4E0D\u662F\u7F51\u9875\u5730\u5740\uFF09
|
|
1121
|
+
2. \u7528\u6237\u540D\u548C\u5BC6\u7801\u662F\u5426\u6B63\u786E
|
|
1122
|
+
3. \u8BA4\u8BC1\u7C7B\u578B\u662F\u5426\u5339\u914D
|
|
1123
|
+
|
|
1124
|
+
\u8BE6\u7EC6\uFF1A${errorMsg}`);
|
|
1125
|
+
}
|
|
1126
|
+
throw verifyError;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
async function downloadFromWebDAV(config, filename) {
|
|
1130
|
+
const client = createWebDAVClient(config);
|
|
1131
|
+
const remoteDir = normalizePath(config.remoteDir || "/");
|
|
1132
|
+
const fullPath = joinPath(remoteDir, filename);
|
|
1133
|
+
try {
|
|
1134
|
+
const contents = await client.getFileContents(fullPath, { format: "text" });
|
|
1135
|
+
return contents;
|
|
1136
|
+
} catch (error) {
|
|
1137
|
+
throw new Error(`\u4E0B\u8F7D\u5931\u8D25: ${error.message}`);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
async function existsOnWebDAV(config, filename) {
|
|
1141
|
+
const client = createWebDAVClient(config);
|
|
1142
|
+
const remoteDir = normalizePath(config.remoteDir || "/");
|
|
1143
|
+
const fullPath = joinPath(remoteDir, filename);
|
|
1144
|
+
try {
|
|
1145
|
+
return await client.exists(fullPath);
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
return false;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
var init_webdav_client = __esm({
|
|
1151
|
+
"../core/dist/sync/webdav-client.js"() {
|
|
1152
|
+
"use strict";
|
|
1153
|
+
}
|
|
1154
|
+
});
|
|
1155
|
+
|
|
1156
|
+
// ../core/dist/sync/crypto.js
|
|
1157
|
+
import * as crypto from "crypto";
|
|
1158
|
+
function deriveKey(password, salt) {
|
|
1159
|
+
return crypto.pbkdf2Sync(password, salt, PBKDF2_ITERATIONS, KEY_LENGTH, "sha256");
|
|
1160
|
+
}
|
|
1161
|
+
function encryptApiKey(apiKey, password) {
|
|
1162
|
+
if (typeof apiKey !== "string") {
|
|
1163
|
+
throw new Error("API Key \u7F3A\u5931\u6216\u7C7B\u578B\u9519\u8BEF\uFF0C\u65E0\u6CD5\u52A0\u5BC6");
|
|
1164
|
+
}
|
|
1165
|
+
if (!password) {
|
|
1166
|
+
throw new Error("\u540C\u6B65\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A");
|
|
1167
|
+
}
|
|
1168
|
+
const salt = crypto.randomBytes(SALT_LENGTH);
|
|
1169
|
+
const iv = crypto.randomBytes(IV_LENGTH);
|
|
1170
|
+
const key = deriveKey(password, salt);
|
|
1171
|
+
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
|
|
1172
|
+
let encrypted = cipher.update(apiKey, "utf8");
|
|
1173
|
+
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
1174
|
+
const tag = cipher.getAuthTag();
|
|
1175
|
+
const result = Buffer.concat([salt, iv, tag, encrypted]);
|
|
1176
|
+
return result.toString("base64");
|
|
1177
|
+
}
|
|
1178
|
+
function decryptApiKey(encryptedApiKey, password) {
|
|
1179
|
+
try {
|
|
1180
|
+
const data = Buffer.from(encryptedApiKey, "base64");
|
|
1181
|
+
const salt = data.subarray(0, SALT_LENGTH);
|
|
1182
|
+
const iv = data.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);
|
|
1183
|
+
const tag = data.subarray(SALT_LENGTH + IV_LENGTH, SALT_LENGTH + IV_LENGTH + TAG_LENGTH);
|
|
1184
|
+
const encrypted = data.subarray(SALT_LENGTH + IV_LENGTH + TAG_LENGTH);
|
|
1185
|
+
const key = deriveKey(password, salt);
|
|
1186
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
|
|
1187
|
+
decipher.setAuthTag(tag);
|
|
1188
|
+
let decrypted = decipher.update(encrypted);
|
|
1189
|
+
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
1190
|
+
return decrypted.toString("utf8");
|
|
1191
|
+
} catch (error) {
|
|
1192
|
+
throw new Error("\u89E3\u5BC6\u5931\u8D25\uFF1A\u5BC6\u7801\u9519\u8BEF\u6216\u6570\u636E\u635F\u574F");
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
function encryptProviders(providers, password) {
|
|
1196
|
+
return providers.map((provider) => {
|
|
1197
|
+
if (typeof provider.apiKey !== "string" || provider.apiKey.length === 0) {
|
|
1198
|
+
throw new Error(`\u670D\u52A1\u5546 "${provider.name}" \u7684 API Key \u4E3A\u7A7A\u6216\u7F3A\u5931\uFF0C\u8BF7\u5148\u5728 ccman \u4E2D\u8865\u5168\u540E\u518D\u8FDB\u884C\u540C\u6B65`);
|
|
1199
|
+
}
|
|
1200
|
+
return {
|
|
1201
|
+
...provider,
|
|
1202
|
+
apiKey: encryptApiKey(provider.apiKey, password)
|
|
1203
|
+
};
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
function decryptProviders(encryptedProviders, password) {
|
|
1207
|
+
return encryptedProviders.map((provider) => ({
|
|
1208
|
+
...provider,
|
|
1209
|
+
apiKey: decryptApiKey(provider.apiKey, password)
|
|
1210
|
+
}));
|
|
1211
|
+
}
|
|
1212
|
+
var ALGORITHM, KEY_LENGTH, IV_LENGTH, SALT_LENGTH, TAG_LENGTH, PBKDF2_ITERATIONS;
|
|
1213
|
+
var init_crypto = __esm({
|
|
1214
|
+
"../core/dist/sync/crypto.js"() {
|
|
1215
|
+
"use strict";
|
|
1216
|
+
ALGORITHM = "aes-256-gcm";
|
|
1217
|
+
KEY_LENGTH = 32;
|
|
1218
|
+
IV_LENGTH = 16;
|
|
1219
|
+
SALT_LENGTH = 32;
|
|
1220
|
+
TAG_LENGTH = 16;
|
|
1221
|
+
PBKDF2_ITERATIONS = 1e5;
|
|
1222
|
+
}
|
|
1223
|
+
});
|
|
1224
|
+
|
|
1225
|
+
// ../core/dist/sync/merge-advanced.js
|
|
1226
|
+
function isSameConfig(a, b) {
|
|
1227
|
+
return a.baseUrl === b.baseUrl && a.apiKey === b.apiKey;
|
|
1228
|
+
}
|
|
1229
|
+
function isProviderEqual(a, b) {
|
|
1230
|
+
return a.id === b.id && a.name === b.name && a.baseUrl === b.baseUrl && a.apiKey === b.apiKey;
|
|
1231
|
+
}
|
|
1232
|
+
function resolveNameConflict(existingProviders, newProvider) {
|
|
1233
|
+
const existingNames = new Set(existingProviders.map((p) => p.name));
|
|
1234
|
+
if (!existingNames.has(newProvider.name)) {
|
|
1235
|
+
return newProvider;
|
|
1236
|
+
}
|
|
1237
|
+
let suffix = 2;
|
|
1238
|
+
let newName = `${newProvider.name}_${suffix}`;
|
|
1239
|
+
while (existingNames.has(newName)) {
|
|
1240
|
+
suffix++;
|
|
1241
|
+
newName = `${newProvider.name}_${suffix}`;
|
|
1242
|
+
}
|
|
1243
|
+
console.log(`name \u51B2\u7A81\uFF1A\u5C06 "${newProvider.name}" \u91CD\u547D\u540D\u4E3A "${newName}"`);
|
|
1244
|
+
return {
|
|
1245
|
+
...newProvider,
|
|
1246
|
+
name: newName
|
|
1247
|
+
};
|
|
1248
|
+
}
|
|
1249
|
+
function mergeProviders(local, remote) {
|
|
1250
|
+
const mergedMap = /* @__PURE__ */ new Map();
|
|
1251
|
+
let hasChanges = false;
|
|
1252
|
+
for (const localProvider of local) {
|
|
1253
|
+
mergedMap.set(localProvider.id, localProvider);
|
|
1254
|
+
}
|
|
1255
|
+
for (const remoteProvider of remote) {
|
|
1256
|
+
const existingLocal = Array.from(mergedMap.values()).find((p) => isSameConfig(p, remoteProvider));
|
|
1257
|
+
if (existingLocal) {
|
|
1258
|
+
mergedMap.delete(existingLocal.id);
|
|
1259
|
+
mergedMap.set(remoteProvider.id, remoteProvider);
|
|
1260
|
+
if (!isProviderEqual(existingLocal, remoteProvider)) {
|
|
1261
|
+
hasChanges = true;
|
|
1262
|
+
console.log(`\u76F8\u540C\u914D\u7F6E (${remoteProvider.baseUrl})\uFF0C\u4F7F\u7528\u4E91\u7AEF\u6570\u636E`);
|
|
1263
|
+
}
|
|
1264
|
+
} else {
|
|
1265
|
+
const existingProviders = Array.from(mergedMap.values());
|
|
1266
|
+
const resolvedProvider = resolveNameConflict(existingProviders, remoteProvider);
|
|
1267
|
+
mergedMap.set(resolvedProvider.id, resolvedProvider);
|
|
1268
|
+
hasChanges = true;
|
|
1269
|
+
console.log(`\u65B0 provider ${resolvedProvider.name}\uFF0C\u6DFB\u52A0\u5230\u5408\u5E76\u5217\u8868`);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
const merged = Array.from(mergedMap.values());
|
|
1273
|
+
return {
|
|
1274
|
+
merged,
|
|
1275
|
+
hasChanges
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
function resolvePresetNameConflict(existingPresets, newPreset) {
|
|
1279
|
+
const existingNames = new Set(existingPresets.map((p) => p.name));
|
|
1280
|
+
if (!existingNames.has(newPreset.name)) {
|
|
1281
|
+
return newPreset;
|
|
1282
|
+
}
|
|
1283
|
+
let suffix = 2;
|
|
1284
|
+
let newName = `${newPreset.name}_${suffix}`;
|
|
1285
|
+
while (existingNames.has(newName)) {
|
|
1286
|
+
suffix++;
|
|
1287
|
+
newName = `${newPreset.name}_${suffix}`;
|
|
1288
|
+
}
|
|
1289
|
+
console.log(`preset name \u51B2\u7A81\uFF1A\u5C06 "${newPreset.name}" \u91CD\u547D\u540D\u4E3A "${newName}"`);
|
|
1290
|
+
return {
|
|
1291
|
+
...newPreset,
|
|
1292
|
+
name: newName
|
|
1293
|
+
};
|
|
1294
|
+
}
|
|
1295
|
+
function mergePresets(local, remote) {
|
|
1296
|
+
const localPresets = local || [];
|
|
1297
|
+
const remotePresets = remote || [];
|
|
1298
|
+
const mergedMap = /* @__PURE__ */ new Map();
|
|
1299
|
+
for (const preset of localPresets) {
|
|
1300
|
+
mergedMap.set(preset.baseUrl, preset);
|
|
1301
|
+
}
|
|
1302
|
+
for (const remotePreset of remotePresets) {
|
|
1303
|
+
const existingLocal = mergedMap.get(remotePreset.baseUrl);
|
|
1304
|
+
if (existingLocal) {
|
|
1305
|
+
mergedMap.set(remotePreset.baseUrl, remotePreset);
|
|
1306
|
+
console.log(`preset ${remotePreset.name} (${remotePreset.baseUrl})\uFF0C\u4F7F\u7528\u4E91\u7AEF\u6570\u636E`);
|
|
1307
|
+
} else {
|
|
1308
|
+
const existingPresets = Array.from(mergedMap.values());
|
|
1309
|
+
const resolvedPreset = resolvePresetNameConflict(existingPresets, remotePreset);
|
|
1310
|
+
mergedMap.set(resolvedPreset.baseUrl, resolvedPreset);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
return Array.from(mergedMap.values());
|
|
1314
|
+
}
|
|
1315
|
+
var init_merge_advanced = __esm({
|
|
1316
|
+
"../core/dist/sync/merge-advanced.js"() {
|
|
1317
|
+
"use strict";
|
|
1318
|
+
}
|
|
1319
|
+
});
|
|
1320
|
+
|
|
1321
|
+
// ../core/dist/sync/merge.js
|
|
1322
|
+
import fs6 from "fs";
|
|
1323
|
+
import path7 from "path";
|
|
1324
|
+
function backupConfig(configPath, keepCount = 3) {
|
|
1325
|
+
if (!fs6.existsSync(configPath)) {
|
|
1326
|
+
throw new Error(`\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${configPath}`);
|
|
1327
|
+
}
|
|
1328
|
+
const timestamp = Date.now();
|
|
1329
|
+
const backupPath = `${configPath}.backup.${timestamp}`;
|
|
1330
|
+
fs6.copyFileSync(configPath, backupPath);
|
|
1331
|
+
cleanupOldBackups(configPath, keepCount);
|
|
1332
|
+
return backupPath;
|
|
1333
|
+
}
|
|
1334
|
+
function cleanupOldBackups(configPath, keepCount) {
|
|
1335
|
+
const dir = path7.dirname(configPath);
|
|
1336
|
+
const basename = path7.basename(configPath);
|
|
1337
|
+
const backupPrefix = `${basename}.backup.`;
|
|
1338
|
+
try {
|
|
1339
|
+
const files = fs6.readdirSync(dir);
|
|
1340
|
+
const backups = files.filter((f) => f.startsWith(backupPrefix)).map((f) => {
|
|
1341
|
+
const timestampStr = f.substring(backupPrefix.length);
|
|
1342
|
+
const timestamp = parseInt(timestampStr, 10);
|
|
1343
|
+
if (isNaN(timestamp)) {
|
|
1344
|
+
return null;
|
|
1345
|
+
}
|
|
1346
|
+
return {
|
|
1347
|
+
name: f,
|
|
1348
|
+
path: path7.join(dir, f),
|
|
1349
|
+
timestamp
|
|
1350
|
+
};
|
|
1351
|
+
}).filter((backup) => backup !== null).sort((a, b) => b.timestamp - a.timestamp);
|
|
1352
|
+
const toDelete = backups.slice(keepCount);
|
|
1353
|
+
for (const backup of toDelete) {
|
|
1354
|
+
try {
|
|
1355
|
+
fs6.unlinkSync(backup.path);
|
|
1356
|
+
} catch (error) {
|
|
1357
|
+
console.warn(`\u65E0\u6CD5\u5220\u9664\u65E7\u5907\u4EFD\u6587\u4EF6 ${backup.name}: ${error.message}`);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
} catch (error) {
|
|
1361
|
+
console.warn(`\u6E05\u7406\u65E7\u5907\u4EFD\u65F6\u51FA\u9519: ${error.message}`);
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
var init_merge = __esm({
|
|
1365
|
+
"../core/dist/sync/merge.js"() {
|
|
1366
|
+
"use strict";
|
|
1367
|
+
}
|
|
1368
|
+
});
|
|
1369
|
+
|
|
1370
|
+
// ../core/dist/sync/sync-v2.js
|
|
1371
|
+
import fs7 from "fs";
|
|
1372
|
+
import path8 from "path";
|
|
1373
|
+
async function uploadToCloud(config, password) {
|
|
1374
|
+
const ccmanDir2 = getCcmanDir();
|
|
1375
|
+
const codexConfigPath = path8.join(ccmanDir2, "codex.json");
|
|
1376
|
+
const claudeConfigPath = path8.join(ccmanDir2, "claude.json");
|
|
1377
|
+
const codexConfig = readJSON(codexConfigPath);
|
|
1378
|
+
const claudeConfig = readJSON(claudeConfigPath);
|
|
1379
|
+
const encryptedCodexProviders = encryptProviders(codexConfig.providers, password);
|
|
1380
|
+
const encryptedClaudeProviders = encryptProviders(claudeConfig.providers, password);
|
|
1381
|
+
const encryptedCodexConfig = {
|
|
1382
|
+
...codexConfig,
|
|
1383
|
+
// 保留所有字段
|
|
1384
|
+
providers: encryptedCodexProviders
|
|
1385
|
+
// 只替换 providers(加密后的)
|
|
1386
|
+
};
|
|
1387
|
+
const encryptedClaudeConfig = {
|
|
1388
|
+
...claudeConfig,
|
|
1389
|
+
// 保留所有字段
|
|
1390
|
+
providers: encryptedClaudeProviders
|
|
1391
|
+
// 只替换 providers(加密后的)
|
|
1392
|
+
};
|
|
1393
|
+
const codexJson = JSON.stringify(encryptedCodexConfig, null, 2);
|
|
1394
|
+
const claudeJson = JSON.stringify(encryptedClaudeConfig, null, 2);
|
|
1395
|
+
await uploadToWebDAV(config, CODEX_REMOTE_PATH, codexJson);
|
|
1396
|
+
await uploadToWebDAV(config, CLAUDE_REMOTE_PATH, claudeJson);
|
|
1397
|
+
updateLastSyncTime();
|
|
1398
|
+
console.log("\u2705 \u914D\u7F6E\u5DF2\u4E0A\u4F20\u5230\u4E91\u7AEF");
|
|
1399
|
+
}
|
|
1400
|
+
async function downloadFromCloud(config, password) {
|
|
1401
|
+
const codexExists = await existsOnWebDAV(config, CODEX_REMOTE_PATH);
|
|
1402
|
+
const claudeExists = await existsOnWebDAV(config, CLAUDE_REMOTE_PATH);
|
|
1403
|
+
if (!codexExists && !claudeExists) {
|
|
1404
|
+
throw new Error("\u8FDC\u7A0B\u914D\u7F6E\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u4E0A\u4F20\u914D\u7F6E");
|
|
1405
|
+
}
|
|
1406
|
+
const codexJson = codexExists ? await downloadFromWebDAV(config, CODEX_REMOTE_PATH) : null;
|
|
1407
|
+
const claudeJson = claudeExists ? await downloadFromWebDAV(config, CLAUDE_REMOTE_PATH) : null;
|
|
1408
|
+
const remoteCodexConfig = codexJson ? JSON.parse(codexJson) : null;
|
|
1409
|
+
const remoteClaudeConfig = claudeJson ? JSON.parse(claudeJson) : null;
|
|
1410
|
+
let decryptedCodexProviders = null;
|
|
1411
|
+
let decryptedClaudeProviders = null;
|
|
1412
|
+
try {
|
|
1413
|
+
if (remoteCodexConfig) {
|
|
1414
|
+
decryptedCodexProviders = decryptProviders(remoteCodexConfig.providers, password);
|
|
1415
|
+
}
|
|
1416
|
+
if (remoteClaudeConfig) {
|
|
1417
|
+
decryptedClaudeProviders = decryptProviders(remoteClaudeConfig.providers, password);
|
|
1418
|
+
}
|
|
1419
|
+
} catch (error) {
|
|
1420
|
+
throw new Error("\u89E3\u5BC6\u5931\u8D25\uFF1A\u5BC6\u7801\u9519\u8BEF\u6216\u6570\u636E\u635F\u574F");
|
|
1421
|
+
}
|
|
1422
|
+
const backupPaths = [];
|
|
1423
|
+
const ccmanDir2 = getCcmanDir();
|
|
1424
|
+
const codexConfigPath = path8.join(ccmanDir2, "codex.json");
|
|
1425
|
+
const claudeConfigPath = path8.join(ccmanDir2, "claude.json");
|
|
1426
|
+
try {
|
|
1427
|
+
if (fs7.existsSync(codexConfigPath)) {
|
|
1428
|
+
backupPaths.push(backupConfig(codexConfigPath));
|
|
1429
|
+
}
|
|
1430
|
+
if (fs7.existsSync(claudeConfigPath)) {
|
|
1431
|
+
backupPaths.push(backupConfig(claudeConfigPath));
|
|
1432
|
+
}
|
|
1433
|
+
} catch (error) {
|
|
1434
|
+
throw new Error(`\u5907\u4EFD\u5931\u8D25: ${error.message}`);
|
|
1435
|
+
}
|
|
1436
|
+
try {
|
|
1437
|
+
if (remoteCodexConfig && decryptedCodexProviders) {
|
|
1438
|
+
const newCodexConfig = {
|
|
1439
|
+
...remoteCodexConfig,
|
|
1440
|
+
// 使用云端配置的所有字段
|
|
1441
|
+
providers: decryptedCodexProviders
|
|
1442
|
+
// 只替换 providers(解密后的)
|
|
1443
|
+
};
|
|
1444
|
+
writeJSON(codexConfigPath, newCodexConfig);
|
|
1445
|
+
applyCurrentProvider("codex", newCodexConfig);
|
|
1446
|
+
}
|
|
1447
|
+
if (remoteClaudeConfig && decryptedClaudeProviders) {
|
|
1448
|
+
const newClaudeConfig = {
|
|
1449
|
+
...remoteClaudeConfig,
|
|
1450
|
+
// 使用云端配置的所有字段
|
|
1451
|
+
providers: decryptedClaudeProviders
|
|
1452
|
+
// 只替换 providers(解密后的)
|
|
1453
|
+
};
|
|
1454
|
+
writeJSON(claudeConfigPath, newClaudeConfig);
|
|
1455
|
+
applyCurrentProvider("claude", newClaudeConfig);
|
|
1456
|
+
}
|
|
1457
|
+
updateLastSyncTime();
|
|
1458
|
+
console.log("\u2705 \u914D\u7F6E\u5DF2\u4ECE\u4E91\u7AEF\u4E0B\u8F7D\u5E76\u5E94\u7528");
|
|
1459
|
+
return backupPaths;
|
|
1460
|
+
} catch (error) {
|
|
1461
|
+
for (const backupPath of backupPaths) {
|
|
1462
|
+
const originalPath = backupPath.replace(/\.backup\.\d+$/, "");
|
|
1463
|
+
if (fs7.existsSync(backupPath)) {
|
|
1464
|
+
fs7.copyFileSync(backupPath, originalPath);
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
throw new Error(`\u8986\u76D6\u914D\u7F6E\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
async function mergeSync(config, password) {
|
|
1471
|
+
const codexExists = await existsOnWebDAV(config, CODEX_REMOTE_PATH);
|
|
1472
|
+
const claudeExists = await existsOnWebDAV(config, CLAUDE_REMOTE_PATH);
|
|
1473
|
+
if (!codexExists && !claudeExists) {
|
|
1474
|
+
console.log("\u8FDC\u7A0B\u914D\u7F6E\u4E0D\u5B58\u5728\uFF0C\u6267\u884C\u4E0A\u4F20\u64CD\u4F5C");
|
|
1475
|
+
await uploadToCloud(config, password);
|
|
1476
|
+
return {
|
|
1477
|
+
hasChanges: true,
|
|
1478
|
+
backupPaths: []
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
const codexJson = codexExists ? await downloadFromWebDAV(config, CODEX_REMOTE_PATH) : null;
|
|
1482
|
+
const claudeJson = claudeExists ? await downloadFromWebDAV(config, CLAUDE_REMOTE_PATH) : null;
|
|
1483
|
+
const remoteCodexConfig = codexJson ? JSON.parse(codexJson) : null;
|
|
1484
|
+
const remoteClaudeConfig = claudeJson ? JSON.parse(claudeJson) : null;
|
|
1485
|
+
let remoteCodexProviders = [];
|
|
1486
|
+
let remoteClaudeProviders = [];
|
|
1487
|
+
try {
|
|
1488
|
+
if (remoteCodexConfig) {
|
|
1489
|
+
remoteCodexProviders = decryptProviders(remoteCodexConfig.providers, password);
|
|
1490
|
+
}
|
|
1491
|
+
if (remoteClaudeConfig) {
|
|
1492
|
+
remoteClaudeProviders = decryptProviders(remoteClaudeConfig.providers, password);
|
|
1493
|
+
}
|
|
1494
|
+
} catch (error) {
|
|
1495
|
+
throw new Error("\u89E3\u5BC6\u5931\u8D25\uFF1A\u5BC6\u7801\u9519\u8BEF\u6216\u6570\u636E\u635F\u574F");
|
|
1496
|
+
}
|
|
1497
|
+
const ccmanDir2 = getCcmanDir();
|
|
1498
|
+
const codexConfigPath = path8.join(ccmanDir2, "codex.json");
|
|
1499
|
+
const claudeConfigPath = path8.join(ccmanDir2, "claude.json");
|
|
1500
|
+
const localCodexConfig = readJSON(codexConfigPath);
|
|
1501
|
+
const localClaudeConfig = readJSON(claudeConfigPath);
|
|
1502
|
+
const codexMergeResult = mergeProviders(localCodexConfig.providers, remoteCodexProviders);
|
|
1503
|
+
const claudeMergeResult = mergeProviders(localClaudeConfig.providers, remoteClaudeProviders);
|
|
1504
|
+
const hasChanges = codexMergeResult.hasChanges || claudeMergeResult.hasChanges;
|
|
1505
|
+
if (!hasChanges) {
|
|
1506
|
+
console.log("\u2139\uFE0F \u914D\u7F6E\u5DF2\u540C\u6B65\uFF0C\u65E0\u9700\u64CD\u4F5C");
|
|
1507
|
+
return {
|
|
1508
|
+
hasChanges: false,
|
|
1509
|
+
backupPaths: []
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1512
|
+
const backupPaths = [];
|
|
1513
|
+
try {
|
|
1514
|
+
if (fs7.existsSync(codexConfigPath)) {
|
|
1515
|
+
backupPaths.push(backupConfig(codexConfigPath));
|
|
1516
|
+
}
|
|
1517
|
+
if (fs7.existsSync(claudeConfigPath)) {
|
|
1518
|
+
backupPaths.push(backupConfig(claudeConfigPath));
|
|
1519
|
+
}
|
|
1520
|
+
} catch (error) {
|
|
1521
|
+
throw new Error(`\u5907\u4EFD\u5931\u8D25: ${error.message}`);
|
|
1522
|
+
}
|
|
1523
|
+
const mergedCodexPresets = mergePresets(localCodexConfig.presets, remoteCodexConfig?.presets);
|
|
1524
|
+
const mergedClaudePresets = mergePresets(localClaudeConfig.presets, remoteClaudeConfig?.presets);
|
|
1525
|
+
try {
|
|
1526
|
+
const mergedCodexConfig = {
|
|
1527
|
+
...localCodexConfig,
|
|
1528
|
+
// 保留本地配置的所有字段
|
|
1529
|
+
providers: codexMergeResult.merged,
|
|
1530
|
+
// 替换为合并后的 providers
|
|
1531
|
+
presets: mergedCodexPresets
|
|
1532
|
+
// 替换为合并后的 presets
|
|
1533
|
+
};
|
|
1534
|
+
const mergedClaudeConfig = {
|
|
1535
|
+
...localClaudeConfig,
|
|
1536
|
+
// 保留本地配置的所有字段
|
|
1537
|
+
providers: claudeMergeResult.merged,
|
|
1538
|
+
// 替换为合并后的 providers
|
|
1539
|
+
presets: mergedClaudePresets
|
|
1540
|
+
// 替换为合并后的 presets
|
|
1541
|
+
};
|
|
1542
|
+
writeJSON(codexConfigPath, mergedCodexConfig);
|
|
1543
|
+
writeJSON(claudeConfigPath, mergedClaudeConfig);
|
|
1544
|
+
applyCurrentProvider("codex", mergedCodexConfig);
|
|
1545
|
+
applyCurrentProvider("claude", mergedClaudeConfig);
|
|
1546
|
+
const encryptedCodexProviders = encryptProviders(codexMergeResult.merged, password);
|
|
1547
|
+
const encryptedClaudeProviders = encryptProviders(claudeMergeResult.merged, password);
|
|
1548
|
+
const encryptedCodexConfig = {
|
|
1549
|
+
...mergedCodexConfig,
|
|
1550
|
+
// 保留合并后配置的所有字段
|
|
1551
|
+
providers: encryptedCodexProviders
|
|
1552
|
+
// 只替换 providers(加密后的)
|
|
1553
|
+
};
|
|
1554
|
+
const encryptedClaudeConfig = {
|
|
1555
|
+
...mergedClaudeConfig,
|
|
1556
|
+
// 保留合并后配置的所有字段
|
|
1557
|
+
providers: encryptedClaudeProviders
|
|
1558
|
+
// 只替换 providers(加密后的)
|
|
1559
|
+
};
|
|
1560
|
+
const codexJson2 = JSON.stringify(encryptedCodexConfig, null, 2);
|
|
1561
|
+
const claudeJson2 = JSON.stringify(encryptedClaudeConfig, null, 2);
|
|
1562
|
+
await uploadToWebDAV(config, CODEX_REMOTE_PATH, codexJson2);
|
|
1563
|
+
await uploadToWebDAV(config, CLAUDE_REMOTE_PATH, claudeJson2);
|
|
1564
|
+
updateLastSyncTime();
|
|
1565
|
+
console.log("\u2705 \u914D\u7F6E\u5DF2\u5408\u5E76\u5E76\u540C\u6B65\u5230\u4E91\u7AEF");
|
|
1566
|
+
return {
|
|
1567
|
+
hasChanges: true,
|
|
1568
|
+
backupPaths
|
|
1569
|
+
};
|
|
1570
|
+
} catch (error) {
|
|
1571
|
+
for (const backupPath of backupPaths) {
|
|
1572
|
+
const originalPath = backupPath.replace(/\.backup\.\d+$/, "");
|
|
1573
|
+
if (fs7.existsSync(backupPath)) {
|
|
1574
|
+
fs7.copyFileSync(backupPath, originalPath);
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
throw new Error(`\u5408\u5E76\u914D\u7F6E\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
function applyCurrentProvider(tool, config) {
|
|
1581
|
+
if (!config.currentProviderId) {
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1584
|
+
const provider = config.providers.find((p) => p.id === config.currentProviderId);
|
|
1585
|
+
if (!provider) {
|
|
1586
|
+
return;
|
|
1587
|
+
}
|
|
1588
|
+
if (tool === "codex") {
|
|
1589
|
+
writeCodexConfig(provider);
|
|
1590
|
+
} else {
|
|
1591
|
+
writeClaudeConfig(provider);
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
var CODEX_REMOTE_PATH, CLAUDE_REMOTE_PATH;
|
|
1595
|
+
var init_sync_v2 = __esm({
|
|
1596
|
+
"../core/dist/sync/sync-v2.js"() {
|
|
1597
|
+
"use strict";
|
|
1598
|
+
init_config();
|
|
1599
|
+
init_webdav_client();
|
|
1600
|
+
init_crypto();
|
|
1601
|
+
init_merge_advanced();
|
|
1602
|
+
init_merge();
|
|
1603
|
+
init_paths();
|
|
1604
|
+
init_file();
|
|
1605
|
+
init_codex();
|
|
1606
|
+
init_claude();
|
|
1607
|
+
CODEX_REMOTE_PATH = ".ccman/codex.json";
|
|
1608
|
+
CLAUDE_REMOTE_PATH = ".ccman/claude.json";
|
|
1609
|
+
}
|
|
1610
|
+
});
|
|
1611
|
+
|
|
1612
|
+
// ../core/dist/export.js
|
|
1613
|
+
import * as fs8 from "fs";
|
|
1614
|
+
import * as path9 from "path";
|
|
1615
|
+
function validateExport() {
|
|
1616
|
+
const ccmanDir2 = getCcmanDir();
|
|
1617
|
+
const codexPath = path9.join(ccmanDir2, CODEX_CONFIG_FILE);
|
|
1618
|
+
const claudePath = path9.join(ccmanDir2, CLAUDE_CONFIG_FILE);
|
|
1619
|
+
const missingFiles = [];
|
|
1620
|
+
if (!fileExists(codexPath)) {
|
|
1621
|
+
missingFiles.push(CODEX_CONFIG_FILE);
|
|
1622
|
+
}
|
|
1623
|
+
if (!fileExists(claudePath)) {
|
|
1624
|
+
missingFiles.push(CLAUDE_CONFIG_FILE);
|
|
1625
|
+
}
|
|
1626
|
+
if (missingFiles.length > 0) {
|
|
1627
|
+
return {
|
|
1628
|
+
valid: false,
|
|
1629
|
+
message: `\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${missingFiles.join(", ")}`,
|
|
1630
|
+
missingFiles
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
return { valid: true };
|
|
1634
|
+
}
|
|
1635
|
+
function validateImportDir(sourceDir) {
|
|
1636
|
+
if (!fileExists(sourceDir)) {
|
|
1637
|
+
return {
|
|
1638
|
+
valid: false,
|
|
1639
|
+
message: `\u76EE\u5F55\u4E0D\u5B58\u5728: ${sourceDir}`,
|
|
1640
|
+
foundFiles: []
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
const stats = fs8.statSync(sourceDir);
|
|
1644
|
+
if (!stats.isDirectory()) {
|
|
1645
|
+
return {
|
|
1646
|
+
valid: false,
|
|
1647
|
+
message: `\u4E0D\u662F\u6709\u6548\u7684\u76EE\u5F55: ${sourceDir}`,
|
|
1648
|
+
foundFiles: []
|
|
1649
|
+
};
|
|
1650
|
+
}
|
|
1651
|
+
const codexPath = path9.join(sourceDir, CODEX_CONFIG_FILE);
|
|
1652
|
+
const claudePath = path9.join(sourceDir, CLAUDE_CONFIG_FILE);
|
|
1653
|
+
const foundFiles = [];
|
|
1654
|
+
if (fileExists(codexPath)) {
|
|
1655
|
+
foundFiles.push(CODEX_CONFIG_FILE);
|
|
1656
|
+
}
|
|
1657
|
+
if (fileExists(claudePath)) {
|
|
1658
|
+
foundFiles.push(CLAUDE_CONFIG_FILE);
|
|
1659
|
+
}
|
|
1660
|
+
if (foundFiles.length === 0) {
|
|
1661
|
+
return {
|
|
1662
|
+
valid: false,
|
|
1663
|
+
message: `\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6 (${CODEX_CONFIG_FILE} \u6216 ${CLAUDE_CONFIG_FILE})`,
|
|
1664
|
+
foundFiles: []
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
return {
|
|
1668
|
+
valid: true,
|
|
1669
|
+
foundFiles
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
function exportConfig(targetDir) {
|
|
1673
|
+
const validation = validateExport();
|
|
1674
|
+
if (!validation.valid) {
|
|
1675
|
+
throw new Error(validation.message);
|
|
1676
|
+
}
|
|
1677
|
+
ensureDir(targetDir);
|
|
1678
|
+
const ccmanDir2 = getCcmanDir();
|
|
1679
|
+
const exportedFiles = [];
|
|
1680
|
+
const codexSrc = path9.join(ccmanDir2, CODEX_CONFIG_FILE);
|
|
1681
|
+
const codexDst = path9.join(targetDir, CODEX_CONFIG_FILE);
|
|
1682
|
+
if (fileExists(codexSrc)) {
|
|
1683
|
+
fs8.copyFileSync(codexSrc, codexDst);
|
|
1684
|
+
exportedFiles.push(CODEX_CONFIG_FILE);
|
|
1685
|
+
}
|
|
1686
|
+
const claudeSrc = path9.join(ccmanDir2, CLAUDE_CONFIG_FILE);
|
|
1687
|
+
const claudeDst = path9.join(targetDir, CLAUDE_CONFIG_FILE);
|
|
1688
|
+
if (fileExists(claudeSrc)) {
|
|
1689
|
+
fs8.copyFileSync(claudeSrc, claudeDst);
|
|
1690
|
+
exportedFiles.push(CLAUDE_CONFIG_FILE);
|
|
1691
|
+
}
|
|
1692
|
+
return {
|
|
1693
|
+
success: true,
|
|
1694
|
+
targetDir,
|
|
1695
|
+
exportedFiles
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
function importConfig(sourceDir) {
|
|
1699
|
+
const validation = validateImportDir(sourceDir);
|
|
1700
|
+
if (!validation.valid) {
|
|
1701
|
+
throw new Error(validation.message);
|
|
1702
|
+
}
|
|
1703
|
+
const ccmanDir2 = getCcmanDir();
|
|
1704
|
+
const backupPaths = [];
|
|
1705
|
+
const importedFiles = [];
|
|
1706
|
+
ensureDir(ccmanDir2);
|
|
1707
|
+
try {
|
|
1708
|
+
if (validation.foundFiles.includes(CODEX_CONFIG_FILE)) {
|
|
1709
|
+
const codexDst = path9.join(ccmanDir2, CODEX_CONFIG_FILE);
|
|
1710
|
+
if (fileExists(codexDst)) {
|
|
1711
|
+
const backupPath = backupConfig(codexDst);
|
|
1712
|
+
backupPaths.push(backupPath);
|
|
1713
|
+
}
|
|
1714
|
+
const codexSrc = path9.join(sourceDir, CODEX_CONFIG_FILE);
|
|
1715
|
+
fs8.copyFileSync(codexSrc, codexDst);
|
|
1716
|
+
importedFiles.push(CODEX_CONFIG_FILE);
|
|
1717
|
+
}
|
|
1718
|
+
if (validation.foundFiles.includes(CLAUDE_CONFIG_FILE)) {
|
|
1719
|
+
const claudeDst = path9.join(ccmanDir2, CLAUDE_CONFIG_FILE);
|
|
1720
|
+
if (fileExists(claudeDst)) {
|
|
1721
|
+
const backupPath = backupConfig(claudeDst);
|
|
1722
|
+
backupPaths.push(backupPath);
|
|
1723
|
+
}
|
|
1724
|
+
const claudeSrc = path9.join(sourceDir, CLAUDE_CONFIG_FILE);
|
|
1725
|
+
fs8.copyFileSync(claudeSrc, claudeDst);
|
|
1726
|
+
importedFiles.push(CLAUDE_CONFIG_FILE);
|
|
1727
|
+
}
|
|
1728
|
+
return {
|
|
1729
|
+
success: true,
|
|
1730
|
+
backupPaths,
|
|
1731
|
+
importedFiles
|
|
1732
|
+
};
|
|
1733
|
+
} catch (error) {
|
|
1734
|
+
for (const backupPath of backupPaths) {
|
|
1735
|
+
const originalPath = backupPath.replace(/\.backup\.\d+$/, "");
|
|
1736
|
+
if (fileExists(backupPath)) {
|
|
1737
|
+
fs8.copyFileSync(backupPath, originalPath);
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
throw new Error(`\u5BFC\u5165\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5907\u4EFD: ${error.message}`);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
var CODEX_CONFIG_FILE, CLAUDE_CONFIG_FILE;
|
|
1744
|
+
var init_export = __esm({
|
|
1745
|
+
"../core/dist/export.js"() {
|
|
1746
|
+
"use strict";
|
|
1747
|
+
init_paths();
|
|
1748
|
+
init_file();
|
|
1749
|
+
init_merge();
|
|
1750
|
+
CODEX_CONFIG_FILE = "codex.json";
|
|
1751
|
+
CLAUDE_CONFIG_FILE = "claude.json";
|
|
1752
|
+
}
|
|
1753
|
+
});
|
|
1754
|
+
|
|
1755
|
+
// ../core/dist/claude-clean.js
|
|
1756
|
+
import * as fs9 from "fs";
|
|
1757
|
+
function formatBytes(bytes) {
|
|
1758
|
+
if (bytes < 1024)
|
|
1759
|
+
return `${bytes} B`;
|
|
1760
|
+
if (bytes < 1024 * 1024)
|
|
1761
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1762
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1763
|
+
}
|
|
1764
|
+
function getFileSize(filePath) {
|
|
1765
|
+
try {
|
|
1766
|
+
const stats = fs9.statSync(filePath);
|
|
1767
|
+
return stats.size;
|
|
1768
|
+
} catch {
|
|
1769
|
+
return 0;
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
function backupFile(filePath) {
|
|
1773
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-").split(".")[0];
|
|
1774
|
+
const backupPath = `${filePath}.backup-${timestamp}`;
|
|
1775
|
+
fs9.copyFileSync(filePath, backupPath);
|
|
1776
|
+
return backupPath;
|
|
1777
|
+
}
|
|
1778
|
+
function saveJsonAtomic(filePath, data) {
|
|
1779
|
+
const tempPath = `${filePath}.tmp`;
|
|
1780
|
+
const content = JSON.stringify(data, null, 2);
|
|
1781
|
+
fs9.writeFileSync(tempPath, content, { mode: 384 });
|
|
1782
|
+
fs9.renameSync(tempPath, filePath);
|
|
1783
|
+
}
|
|
1784
|
+
function analyzeClaudeJson() {
|
|
1785
|
+
const filePath = getClaudeJsonPath();
|
|
1786
|
+
if (!fs9.existsSync(filePath)) {
|
|
1787
|
+
return {
|
|
1788
|
+
fileSize: 0,
|
|
1789
|
+
fileSizeFormatted: "0 B",
|
|
1790
|
+
projectCount: 0,
|
|
1791
|
+
totalHistoryCount: 0,
|
|
1792
|
+
projectHistory: [],
|
|
1793
|
+
cacheSize: 0,
|
|
1794
|
+
estimatedSavings: {
|
|
1795
|
+
conservative: 0,
|
|
1796
|
+
moderate: 0,
|
|
1797
|
+
aggressive: 0
|
|
1798
|
+
}
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1801
|
+
const fileSize = getFileSize(filePath);
|
|
1802
|
+
const content = fs9.readFileSync(filePath, "utf-8");
|
|
1803
|
+
const config = JSON.parse(content);
|
|
1804
|
+
const projects = config.projects || {};
|
|
1805
|
+
const projectHistory = [];
|
|
1806
|
+
let totalHistoryCount = 0;
|
|
1807
|
+
for (const [projectPath, projectData] of Object.entries(projects)) {
|
|
1808
|
+
const historyCount = projectData.history?.length || 0;
|
|
1809
|
+
totalHistoryCount += historyCount;
|
|
1810
|
+
projectHistory.push({
|
|
1811
|
+
path: projectPath,
|
|
1812
|
+
count: historyCount
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
projectHistory.sort((a, b) => b.count - a.count);
|
|
1816
|
+
const cacheSize = config.cachedChangelog?.length || 0;
|
|
1817
|
+
const historySize = fileSize - cacheSize - 2e4;
|
|
1818
|
+
const avgHistorySize = totalHistoryCount > 0 ? historySize / totalHistoryCount : 0;
|
|
1819
|
+
const estimatedSavings = {
|
|
1820
|
+
conservative: Math.floor(avgHistorySize * Math.max(0, totalHistoryCount - projectHistory.length * 10)) + cacheSize,
|
|
1821
|
+
moderate: Math.floor(avgHistorySize * Math.max(0, totalHistoryCount - projectHistory.length * 5)) + cacheSize,
|
|
1822
|
+
aggressive: Math.floor(historySize) + cacheSize
|
|
1823
|
+
};
|
|
1824
|
+
return {
|
|
1825
|
+
fileSize,
|
|
1826
|
+
fileSizeFormatted: formatBytes(fileSize),
|
|
1827
|
+
projectCount: projectHistory.length,
|
|
1828
|
+
totalHistoryCount,
|
|
1829
|
+
projectHistory,
|
|
1830
|
+
cacheSize,
|
|
1831
|
+
estimatedSavings
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
function cleanClaudeJson(options = {}) {
|
|
1835
|
+
const filePath = getClaudeJsonPath();
|
|
1836
|
+
if (!fs9.existsSync(filePath)) {
|
|
1837
|
+
throw new Error(`${filePath} \u6587\u4EF6\u4E0D\u5B58\u5728`);
|
|
1838
|
+
}
|
|
1839
|
+
const backupPath = backupFile(filePath);
|
|
1840
|
+
const sizeBefore = getFileSize(filePath);
|
|
1841
|
+
const content = fs9.readFileSync(filePath, "utf-8");
|
|
1842
|
+
const config = JSON.parse(content);
|
|
1843
|
+
const cleanedItems = applyCleanOptions(config, options);
|
|
1844
|
+
saveJsonAtomic(filePath, config);
|
|
1845
|
+
const sizeAfter = getFileSize(filePath);
|
|
1846
|
+
return {
|
|
1847
|
+
sizeBefore,
|
|
1848
|
+
sizeAfter,
|
|
1849
|
+
saved: sizeBefore - sizeAfter,
|
|
1850
|
+
cleanedItems,
|
|
1851
|
+
backupPath
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
function applyCleanOptions(config, options) {
|
|
1855
|
+
let projectHistoryCount = 0;
|
|
1856
|
+
if (options.cleanProjectHistory && config.projects) {
|
|
1857
|
+
const keepCount = options.keepRecentCount ?? 10;
|
|
1858
|
+
const targetProjects = options.projectPaths || [];
|
|
1859
|
+
for (const [projectPath, projectData] of Object.entries(config.projects)) {
|
|
1860
|
+
if (targetProjects.length > 0 && !targetProjects.includes(projectPath)) {
|
|
1861
|
+
continue;
|
|
1862
|
+
}
|
|
1863
|
+
if (projectData.history && Array.isArray(projectData.history)) {
|
|
1864
|
+
const originalCount = projectData.history.length;
|
|
1865
|
+
projectData.history = projectData.history.slice(-keepCount);
|
|
1866
|
+
projectHistoryCount += originalCount - projectData.history.length;
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
if (options.cleanCache) {
|
|
1871
|
+
delete config.cachedChangelog;
|
|
1872
|
+
config.changelogLastFetched = 0;
|
|
1873
|
+
}
|
|
1874
|
+
if (options.cleanStats) {
|
|
1875
|
+
config.numStartups = 0;
|
|
1876
|
+
config.promptQueueUseCount = 0;
|
|
1877
|
+
config.tipsHistory = {};
|
|
1878
|
+
}
|
|
1879
|
+
return {
|
|
1880
|
+
projectHistory: projectHistoryCount,
|
|
1881
|
+
cache: options.cleanCache || false,
|
|
1882
|
+
stats: options.cleanStats || false
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1885
|
+
var CleanPresets;
|
|
1886
|
+
var init_claude_clean = __esm({
|
|
1887
|
+
"../core/dist/claude-clean.js"() {
|
|
1888
|
+
"use strict";
|
|
1889
|
+
init_paths();
|
|
1890
|
+
CleanPresets = {
|
|
1891
|
+
/** 保守清理:保留最近10条记录,清理缓存 */
|
|
1892
|
+
conservative: () => ({
|
|
1893
|
+
cleanProjectHistory: true,
|
|
1894
|
+
keepRecentCount: 10,
|
|
1895
|
+
cleanCache: true,
|
|
1896
|
+
cleanStats: false
|
|
1897
|
+
}),
|
|
1898
|
+
/** 中等清理:保留最近5条记录,清理缓存和统计 */
|
|
1899
|
+
moderate: () => ({
|
|
1900
|
+
cleanProjectHistory: true,
|
|
1901
|
+
keepRecentCount: 5,
|
|
1902
|
+
cleanCache: true,
|
|
1903
|
+
cleanStats: true
|
|
1904
|
+
}),
|
|
1905
|
+
/** 激进清理:清空历史记录,清理缓存和统计 */
|
|
1906
|
+
aggressive: () => ({
|
|
1907
|
+
cleanProjectHistory: true,
|
|
1908
|
+
keepRecentCount: 0,
|
|
1909
|
+
cleanCache: true,
|
|
1910
|
+
cleanStats: true
|
|
1911
|
+
})
|
|
1912
|
+
};
|
|
1913
|
+
}
|
|
1914
|
+
});
|
|
1915
|
+
|
|
1916
|
+
// ../core/dist/index.js
|
|
1917
|
+
var VERSION;
|
|
1918
|
+
var init_dist = __esm({
|
|
1919
|
+
"../core/dist/index.js"() {
|
|
1920
|
+
"use strict";
|
|
1921
|
+
init_package();
|
|
1922
|
+
init_tool_manager();
|
|
1923
|
+
init_codex2();
|
|
1924
|
+
init_claude2();
|
|
1925
|
+
init_mcp2();
|
|
1926
|
+
init_mcp();
|
|
1927
|
+
init_migrate();
|
|
1928
|
+
init_paths();
|
|
1929
|
+
init_config();
|
|
1930
|
+
init_webdav_client();
|
|
1931
|
+
init_sync_v2();
|
|
1932
|
+
init_crypto();
|
|
1933
|
+
init_merge_advanced();
|
|
1934
|
+
init_export();
|
|
1935
|
+
init_claude_clean();
|
|
1936
|
+
VERSION = package_default.version;
|
|
1937
|
+
}
|
|
1938
|
+
});
|
|
1939
|
+
|
|
12
1940
|
// src/utils/sync-config.ts
|
|
13
|
-
import { getSyncConfig, saveSyncConfig as coreSaveSyncConfig, getConfigPath } from "@ccman/core";
|
|
14
1941
|
function loadSyncConfig() {
|
|
15
1942
|
try {
|
|
16
1943
|
const config = getSyncConfig();
|
|
@@ -22,13 +1949,13 @@ function loadSyncConfig() {
|
|
|
22
1949
|
throw new Error(`\u8BFB\u53D6\u540C\u6B65\u914D\u7F6E\u5931\u8D25: ${error.message}`);
|
|
23
1950
|
}
|
|
24
1951
|
}
|
|
25
|
-
function
|
|
1952
|
+
function saveSyncConfig2(config) {
|
|
26
1953
|
try {
|
|
27
1954
|
const configToSave = { ...config };
|
|
28
1955
|
if (!configToSave.rememberSyncPassword) {
|
|
29
1956
|
delete configToSave.syncPassword;
|
|
30
1957
|
}
|
|
31
|
-
|
|
1958
|
+
saveSyncConfig(configToSave);
|
|
32
1959
|
} catch (error) {
|
|
33
1960
|
throw new Error(`\u4FDD\u5B58\u540C\u6B65\u914D\u7F6E\u5931\u8D25: ${error.message}`);
|
|
34
1961
|
}
|
|
@@ -39,6 +1966,7 @@ function getSyncConfigPath() {
|
|
|
39
1966
|
var init_sync_config = __esm({
|
|
40
1967
|
"src/utils/sync-config.ts"() {
|
|
41
1968
|
"use strict";
|
|
1969
|
+
init_dist();
|
|
42
1970
|
}
|
|
43
1971
|
});
|
|
44
1972
|
|
|
@@ -49,7 +1977,6 @@ __export(config_exports, {
|
|
|
49
1977
|
});
|
|
50
1978
|
import chalk3 from "chalk";
|
|
51
1979
|
import inquirer from "inquirer";
|
|
52
|
-
import { testWebDAVConnection } from "@ccman/core";
|
|
53
1980
|
function configCommand(program2) {
|
|
54
1981
|
program2.command("config").description("\u914D\u7F6E WebDAV \u8FDE\u63A5").action(async () => {
|
|
55
1982
|
try {
|
|
@@ -201,7 +2128,7 @@ function configCommand(program2) {
|
|
|
201
2128
|
console.log();
|
|
202
2129
|
return;
|
|
203
2130
|
}
|
|
204
|
-
|
|
2131
|
+
saveSyncConfig2(newConfig);
|
|
205
2132
|
console.log();
|
|
206
2133
|
console.log(chalk3.green("\u2705 \u914D\u7F6E\u4FDD\u5B58\u6210\u529F"));
|
|
207
2134
|
console.log();
|
|
@@ -243,10 +2170,11 @@ function configCommand(program2) {
|
|
|
243
2170
|
}
|
|
244
2171
|
});
|
|
245
2172
|
}
|
|
246
|
-
var
|
|
2173
|
+
var init_config2 = __esm({
|
|
247
2174
|
"src/commands/sync/config.ts"() {
|
|
248
2175
|
"use strict";
|
|
249
2176
|
init_sync_config();
|
|
2177
|
+
init_dist();
|
|
250
2178
|
}
|
|
251
2179
|
});
|
|
252
2180
|
|
|
@@ -271,7 +2199,7 @@ async function ensureConfigExists() {
|
|
|
271
2199
|
if (!shouldConfig) {
|
|
272
2200
|
return null;
|
|
273
2201
|
}
|
|
274
|
-
const { configCommand: configCommand2 } = await Promise.resolve().then(() => (
|
|
2202
|
+
const { configCommand: configCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
275
2203
|
const cmd = new Command();
|
|
276
2204
|
configCommand2(cmd);
|
|
277
2205
|
await cmd.parseAsync(["node", "ccman", "config"]);
|
|
@@ -290,7 +2218,6 @@ __export(test_exports, {
|
|
|
290
2218
|
testCommand: () => testCommand
|
|
291
2219
|
});
|
|
292
2220
|
import chalk5 from "chalk";
|
|
293
|
-
import { testWebDAVConnection as testWebDAVConnection2 } from "@ccman/core";
|
|
294
2221
|
function testCommand(program2) {
|
|
295
2222
|
program2.command("test").description("\u6D4B\u8BD5 WebDAV \u8FDE\u63A5").action(async () => {
|
|
296
2223
|
try {
|
|
@@ -300,7 +2227,7 @@ function testCommand(program2) {
|
|
|
300
2227
|
return;
|
|
301
2228
|
}
|
|
302
2229
|
console.log(chalk5.bold("\n\u{1F50D} \u6D4B\u8BD5 WebDAV \u8FDE\u63A5...\n"));
|
|
303
|
-
const success = await
|
|
2230
|
+
const success = await testWebDAVConnection(config);
|
|
304
2231
|
if (success) {
|
|
305
2232
|
console.log(chalk5.green("\u2705 \u8FDE\u63A5\u6210\u529F"));
|
|
306
2233
|
console.log();
|
|
@@ -328,6 +2255,7 @@ function testCommand(program2) {
|
|
|
328
2255
|
var init_test = __esm({
|
|
329
2256
|
"src/commands/sync/test.ts"() {
|
|
330
2257
|
"use strict";
|
|
2258
|
+
init_dist();
|
|
331
2259
|
init_helpers();
|
|
332
2260
|
}
|
|
333
2261
|
});
|
|
@@ -339,7 +2267,6 @@ __export(upload_exports, {
|
|
|
339
2267
|
});
|
|
340
2268
|
import chalk6 from "chalk";
|
|
341
2269
|
import inquirer3 from "inquirer";
|
|
342
|
-
import { uploadToCloud, createCodexManager, createClaudeManager } from "@ccman/core";
|
|
343
2270
|
function uploadCommand(program2) {
|
|
344
2271
|
program2.command("upload").description("\u4E0A\u4F20\u672C\u5730\u914D\u7F6E\u5230\u4E91\u7AEF").action(async () => {
|
|
345
2272
|
try {
|
|
@@ -406,6 +2333,7 @@ function uploadCommand(program2) {
|
|
|
406
2333
|
var init_upload = __esm({
|
|
407
2334
|
"src/commands/sync/upload.ts"() {
|
|
408
2335
|
"use strict";
|
|
2336
|
+
init_dist();
|
|
409
2337
|
init_helpers();
|
|
410
2338
|
}
|
|
411
2339
|
});
|
|
@@ -417,7 +2345,6 @@ __export(download_exports, {
|
|
|
417
2345
|
});
|
|
418
2346
|
import chalk7 from "chalk";
|
|
419
2347
|
import inquirer4 from "inquirer";
|
|
420
|
-
import { downloadFromCloud } from "@ccman/core";
|
|
421
2348
|
function downloadCommand(program2) {
|
|
422
2349
|
program2.command("download").description("\u4ECE\u4E91\u7AEF\u4E0B\u8F7D\u914D\u7F6E\u5230\u672C\u5730").action(async () => {
|
|
423
2350
|
try {
|
|
@@ -464,8 +2391,8 @@ function downloadCommand(program2) {
|
|
|
464
2391
|
console.log();
|
|
465
2392
|
if (backupPaths.length > 0) {
|
|
466
2393
|
console.log(chalk7.gray("\u672C\u5730\u5907\u4EFD:"));
|
|
467
|
-
backupPaths.forEach((
|
|
468
|
-
console.log(chalk7.gray(` ${
|
|
2394
|
+
backupPaths.forEach((path12) => {
|
|
2395
|
+
console.log(chalk7.gray(` ${path12}`));
|
|
469
2396
|
});
|
|
470
2397
|
console.log();
|
|
471
2398
|
}
|
|
@@ -480,6 +2407,7 @@ function downloadCommand(program2) {
|
|
|
480
2407
|
var init_download = __esm({
|
|
481
2408
|
"src/commands/sync/download.ts"() {
|
|
482
2409
|
"use strict";
|
|
2410
|
+
init_dist();
|
|
483
2411
|
init_helpers();
|
|
484
2412
|
}
|
|
485
2413
|
});
|
|
@@ -491,7 +2419,6 @@ __export(merge_exports, {
|
|
|
491
2419
|
});
|
|
492
2420
|
import chalk8 from "chalk";
|
|
493
2421
|
import inquirer5 from "inquirer";
|
|
494
|
-
import { mergeSync } from "@ccman/core";
|
|
495
2422
|
function mergeCommand(program2) {
|
|
496
2423
|
program2.command("merge").description("\u667A\u80FD\u5408\u5E76\u672C\u5730\u548C\u4E91\u7AEF\u914D\u7F6E").action(async () => {
|
|
497
2424
|
try {
|
|
@@ -526,8 +2453,8 @@ function mergeCommand(program2) {
|
|
|
526
2453
|
console.log();
|
|
527
2454
|
if (result.backupPaths.length > 0) {
|
|
528
2455
|
console.log(chalk8.gray("\u5907\u4EFD:"));
|
|
529
|
-
result.backupPaths.forEach((
|
|
530
|
-
console.log(chalk8.gray(` ${
|
|
2456
|
+
result.backupPaths.forEach((path12) => {
|
|
2457
|
+
console.log(chalk8.gray(` ${path12}`));
|
|
531
2458
|
});
|
|
532
2459
|
console.log();
|
|
533
2460
|
}
|
|
@@ -543,9 +2470,10 @@ function mergeCommand(program2) {
|
|
|
543
2470
|
}
|
|
544
2471
|
});
|
|
545
2472
|
}
|
|
546
|
-
var
|
|
2473
|
+
var init_merge2 = __esm({
|
|
547
2474
|
"src/commands/sync/merge.ts"() {
|
|
548
2475
|
"use strict";
|
|
2476
|
+
init_dist();
|
|
549
2477
|
init_helpers();
|
|
550
2478
|
}
|
|
551
2479
|
});
|
|
@@ -556,7 +2484,6 @@ __export(status_exports, {
|
|
|
556
2484
|
statusCommand: () => statusCommand
|
|
557
2485
|
});
|
|
558
2486
|
import chalk9 from "chalk";
|
|
559
|
-
import { createCodexManager as createCodexManager2, createClaudeManager as createClaudeManager2 } from "@ccman/core";
|
|
560
2487
|
function statusCommand(program2) {
|
|
561
2488
|
program2.command("status").description("\u67E5\u770B\u540C\u6B65\u72B6\u6001").action(async () => {
|
|
562
2489
|
try {
|
|
@@ -575,8 +2502,8 @@ function statusCommand(program2) {
|
|
|
575
2502
|
console.log(` \u8BA4\u8BC1: ${chalk9.gray(config.authType === "password" ? "Basic Auth" : "Digest Auth")}`);
|
|
576
2503
|
console.log(` \u540C\u6B65\u5BC6\u7801: ${config.syncPassword ? chalk9.green("\u2713 \u5DF2\u4FDD\u5B58") : chalk9.yellow("\u2717 \u672A\u4FDD\u5B58")}`);
|
|
577
2504
|
console.log();
|
|
578
|
-
const codexManager =
|
|
579
|
-
const claudeManager =
|
|
2505
|
+
const codexManager = createCodexManager();
|
|
2506
|
+
const claudeManager = createClaudeManager();
|
|
580
2507
|
const codexProviders = codexManager.list();
|
|
581
2508
|
const claudeProviders = claudeManager.list();
|
|
582
2509
|
console.log(chalk9.bold("\u672C\u5730\u914D\u7F6E:"));
|
|
@@ -602,6 +2529,7 @@ function statusCommand(program2) {
|
|
|
602
2529
|
var init_status = __esm({
|
|
603
2530
|
"src/commands/sync/status.ts"() {
|
|
604
2531
|
"use strict";
|
|
2532
|
+
init_dist();
|
|
605
2533
|
init_sync_config();
|
|
606
2534
|
}
|
|
607
2535
|
});
|
|
@@ -648,7 +2576,7 @@ async function startSyncMenu() {
|
|
|
648
2576
|
try {
|
|
649
2577
|
switch (action) {
|
|
650
2578
|
case "config": {
|
|
651
|
-
const { configCommand: configCommand2 } = await Promise.resolve().then(() => (
|
|
2579
|
+
const { configCommand: configCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
652
2580
|
const cmd = new Command2();
|
|
653
2581
|
configCommand2(cmd);
|
|
654
2582
|
await cmd.parseAsync(["node", "ccman", "config"]);
|
|
@@ -676,7 +2604,7 @@ async function startSyncMenu() {
|
|
|
676
2604
|
break;
|
|
677
2605
|
}
|
|
678
2606
|
case "merge": {
|
|
679
|
-
const { mergeCommand: mergeCommand2 } = await Promise.resolve().then(() => (
|
|
2607
|
+
const { mergeCommand: mergeCommand2 } = await Promise.resolve().then(() => (init_merge2(), merge_exports));
|
|
680
2608
|
const cmd = new Command2();
|
|
681
2609
|
mergeCommand2(cmd);
|
|
682
2610
|
await cmd.parseAsync(["node", "ccman", "merge"]);
|
|
@@ -707,11 +2635,11 @@ async function startSyncMenu() {
|
|
|
707
2635
|
var init_sync = __esm({
|
|
708
2636
|
"src/commands/sync/index.ts"() {
|
|
709
2637
|
"use strict";
|
|
710
|
-
|
|
2638
|
+
init_config2();
|
|
711
2639
|
init_test();
|
|
712
2640
|
init_upload();
|
|
713
2641
|
init_download();
|
|
714
|
-
|
|
2642
|
+
init_merge2();
|
|
715
2643
|
init_status();
|
|
716
2644
|
}
|
|
717
2645
|
});
|
|
@@ -721,8 +2649,8 @@ import { Command as Command3 } from "commander";
|
|
|
721
2649
|
import chalk33 from "chalk";
|
|
722
2650
|
|
|
723
2651
|
// src/utils/logo.ts
|
|
2652
|
+
init_dist();
|
|
724
2653
|
import chalk from "chalk";
|
|
725
|
-
import { VERSION } from "@ccman/core";
|
|
726
2654
|
function printLogo() {
|
|
727
2655
|
console.log(
|
|
728
2656
|
chalk.bold(
|
|
@@ -742,19 +2670,14 @@ function printLogo() {
|
|
|
742
2670
|
}
|
|
743
2671
|
|
|
744
2672
|
// src/commands/codex/add.ts
|
|
2673
|
+
init_dist();
|
|
745
2674
|
import chalk12 from "chalk";
|
|
746
2675
|
import inquirer8 from "inquirer";
|
|
747
|
-
import {
|
|
748
|
-
createCodexManager as createCodexManager4,
|
|
749
|
-
CODEX_PRESETS,
|
|
750
|
-
getCodexConfigPath,
|
|
751
|
-
getCodexAuthPath
|
|
752
|
-
} from "@ccman/core";
|
|
753
2676
|
|
|
754
2677
|
// src/interactive.ts
|
|
2678
|
+
init_dist();
|
|
755
2679
|
import inquirer7 from "inquirer";
|
|
756
2680
|
import chalk11 from "chalk";
|
|
757
|
-
import { createCodexManager as createCodexManager3, createClaudeManager as createClaudeManager3 } from "@ccman/core";
|
|
758
2681
|
|
|
759
2682
|
// src/utils/format.ts
|
|
760
2683
|
import chalk2 from "chalk";
|
|
@@ -938,7 +2861,7 @@ async function showPresetsMenu() {
|
|
|
938
2861
|
console.log(chalk11.yellow("\n\u26A0\uFE0F \u9884\u7F6E\u670D\u52A1\u5546\u7BA1\u7406\u529F\u80FD\u5373\u5C06\u63A8\u51FA\n"));
|
|
939
2862
|
}
|
|
940
2863
|
async function handleAdd(tool) {
|
|
941
|
-
const manager = tool === "codex" ?
|
|
2864
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
942
2865
|
const toolName = tool === "claude" ? "Claude" : "Codex";
|
|
943
2866
|
const presets = manager.listPresets();
|
|
944
2867
|
console.log(chalk11.bold(`
|
|
@@ -1044,7 +2967,7 @@ async function handleAdd(tool) {
|
|
|
1044
2967
|
}
|
|
1045
2968
|
}
|
|
1046
2969
|
async function handleSwitch(tool) {
|
|
1047
|
-
const manager = tool === "codex" ?
|
|
2970
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1048
2971
|
const providers = manager.list();
|
|
1049
2972
|
const current = manager.getCurrent();
|
|
1050
2973
|
if (providers.length === 0) {
|
|
@@ -1069,7 +2992,7 @@ async function handleSwitch(tool) {
|
|
|
1069
2992
|
`));
|
|
1070
2993
|
}
|
|
1071
2994
|
async function handleList(tool) {
|
|
1072
|
-
const manager = tool === "codex" ?
|
|
2995
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1073
2996
|
const providers = manager.list();
|
|
1074
2997
|
const current = manager.getCurrent();
|
|
1075
2998
|
const toolName = tool === "claude" ? "Claude" : "Codex";
|
|
@@ -1084,7 +3007,7 @@ async function handleList(tool) {
|
|
|
1084
3007
|
console.log(formatProviderTable(providers, current?.id));
|
|
1085
3008
|
}
|
|
1086
3009
|
async function handleCurrent(tool) {
|
|
1087
|
-
const manager = tool === "codex" ?
|
|
3010
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1088
3011
|
const current = manager.getCurrent();
|
|
1089
3012
|
const toolName = tool === "claude" ? "Claude" : "Codex";
|
|
1090
3013
|
if (!current) {
|
|
@@ -1105,7 +3028,7 @@ async function handleCurrent(tool) {
|
|
|
1105
3028
|
console.log();
|
|
1106
3029
|
}
|
|
1107
3030
|
async function handleEdit(tool) {
|
|
1108
|
-
const manager = tool === "codex" ?
|
|
3031
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1109
3032
|
const providers = manager.list();
|
|
1110
3033
|
if (providers.length === 0) {
|
|
1111
3034
|
console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
|
|
@@ -1166,7 +3089,7 @@ async function handleEdit(tool) {
|
|
|
1166
3089
|
console.log(chalk11.green("\n\u2705 \u7F16\u8F91\u6210\u529F\n"));
|
|
1167
3090
|
}
|
|
1168
3091
|
async function handleClone(tool) {
|
|
1169
|
-
const manager = tool === "codex" ?
|
|
3092
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1170
3093
|
const providers = manager.list();
|
|
1171
3094
|
if (providers.length === 0) {
|
|
1172
3095
|
console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
|
|
@@ -1213,7 +3136,7 @@ async function handleClone(tool) {
|
|
|
1213
3136
|
console.log();
|
|
1214
3137
|
}
|
|
1215
3138
|
async function handleRemove(tool) {
|
|
1216
|
-
const manager = tool === "codex" ?
|
|
3139
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1217
3140
|
const providers = manager.list();
|
|
1218
3141
|
if (providers.length === 0) {
|
|
1219
3142
|
console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
|
|
@@ -1253,7 +3176,7 @@ async function handleRemove(tool) {
|
|
|
1253
3176
|
function addCommand(program2) {
|
|
1254
3177
|
program2.command("add").description("\u6DFB\u52A0\u65B0\u7684 Codex \u670D\u52A1\u5546(\u4EA4\u4E92\u5F0F)").action(async () => {
|
|
1255
3178
|
try {
|
|
1256
|
-
const manager =
|
|
3179
|
+
const manager = createCodexManager();
|
|
1257
3180
|
console.log(chalk12.bold("\n\u{1F4DD} \u6DFB\u52A0 Codex \u670D\u52A1\u5546\n"));
|
|
1258
3181
|
const { usePreset } = await inquirer8.prompt([
|
|
1259
3182
|
{
|
|
@@ -1370,12 +3293,12 @@ function addCommand(program2) {
|
|
|
1370
3293
|
}
|
|
1371
3294
|
|
|
1372
3295
|
// src/commands/codex/list.ts
|
|
3296
|
+
init_dist();
|
|
1373
3297
|
import chalk13 from "chalk";
|
|
1374
|
-
import { createCodexManager as createCodexManager5 } from "@ccman/core";
|
|
1375
3298
|
function listCommand(program2) {
|
|
1376
3299
|
program2.command("list").alias("ls").description("\u5217\u51FA\u6240\u6709 Codex \u670D\u52A1\u5546").action(async () => {
|
|
1377
3300
|
try {
|
|
1378
|
-
const manager =
|
|
3301
|
+
const manager = createCodexManager();
|
|
1379
3302
|
const providers = manager.list();
|
|
1380
3303
|
const current = manager.getCurrent();
|
|
1381
3304
|
if (providers.length === 0) {
|
|
@@ -1396,18 +3319,13 @@ function listCommand(program2) {
|
|
|
1396
3319
|
}
|
|
1397
3320
|
|
|
1398
3321
|
// src/commands/codex/use.ts
|
|
3322
|
+
init_dist();
|
|
1399
3323
|
import chalk14 from "chalk";
|
|
1400
3324
|
import inquirer9 from "inquirer";
|
|
1401
|
-
import {
|
|
1402
|
-
createCodexManager as createCodexManager6,
|
|
1403
|
-
ProviderNotFoundError,
|
|
1404
|
-
getCodexConfigPath as getCodexConfigPath2,
|
|
1405
|
-
getCodexAuthPath as getCodexAuthPath2
|
|
1406
|
-
} from "@ccman/core";
|
|
1407
3325
|
function useCommand(program2) {
|
|
1408
3326
|
program2.command("use [name]").description("\u5207\u6362 Codex \u670D\u52A1\u5546").action(async (name) => {
|
|
1409
3327
|
try {
|
|
1410
|
-
const manager =
|
|
3328
|
+
const manager = createCodexManager();
|
|
1411
3329
|
const providers = manager.list();
|
|
1412
3330
|
if (providers.length === 0) {
|
|
1413
3331
|
console.log(chalk14.yellow("\n\u26A0\uFE0F \u6682\u65E0 Codex \u670D\u52A1\u5546\n"));
|
|
@@ -1444,8 +3362,8 @@ function useCommand(program2) {
|
|
|
1444
3362
|
console.log(` ${chalk14.gray(`URL: ${provider.baseUrl}`)}`);
|
|
1445
3363
|
console.log();
|
|
1446
3364
|
console.log(chalk14.gray("\u914D\u7F6E\u5DF2\u66F4\u65B0:"));
|
|
1447
|
-
console.log(chalk14.gray(` - ${
|
|
1448
|
-
console.log(chalk14.gray(` - ${
|
|
3365
|
+
console.log(chalk14.gray(` - ${getCodexConfigPath()}`));
|
|
3366
|
+
console.log(chalk14.gray(` - ${getCodexAuthPath()}`));
|
|
1449
3367
|
console.log();
|
|
1450
3368
|
} catch (error) {
|
|
1451
3369
|
if (error instanceof ProviderNotFoundError) {
|
|
@@ -1464,12 +3382,12 @@ function useCommand(program2) {
|
|
|
1464
3382
|
}
|
|
1465
3383
|
|
|
1466
3384
|
// src/commands/codex/current.ts
|
|
3385
|
+
init_dist();
|
|
1467
3386
|
import chalk15 from "chalk";
|
|
1468
|
-
import { createCodexManager as createCodexManager7 } from "@ccman/core";
|
|
1469
3387
|
function currentCommand(program2) {
|
|
1470
3388
|
program2.command("current").description("\u663E\u793A\u5F53\u524D\u4F7F\u7528\u7684 Codex \u670D\u52A1\u5546").action(async () => {
|
|
1471
3389
|
try {
|
|
1472
|
-
const manager =
|
|
3390
|
+
const manager = createCodexManager();
|
|
1473
3391
|
const current = manager.getCurrent();
|
|
1474
3392
|
if (!current) {
|
|
1475
3393
|
console.log(chalk15.yellow("\n\u26A0\uFE0F \u672A\u9009\u62E9\u4EFB\u4F55 Codex \u670D\u52A1\u5546\n"));
|
|
@@ -1495,13 +3413,13 @@ function currentCommand(program2) {
|
|
|
1495
3413
|
}
|
|
1496
3414
|
|
|
1497
3415
|
// src/commands/codex/remove.ts
|
|
3416
|
+
init_dist();
|
|
1498
3417
|
import chalk16 from "chalk";
|
|
1499
3418
|
import inquirer10 from "inquirer";
|
|
1500
|
-
import { createCodexManager as createCodexManager8, ProviderNotFoundError as ProviderNotFoundError2 } from "@ccman/core";
|
|
1501
3419
|
function removeCommand(program2) {
|
|
1502
3420
|
program2.command("remove [name]").alias("rm").description("\u5220\u9664 Codex \u670D\u52A1\u5546").action(async (name) => {
|
|
1503
3421
|
try {
|
|
1504
|
-
const manager =
|
|
3422
|
+
const manager = createCodexManager();
|
|
1505
3423
|
const providers = manager.list();
|
|
1506
3424
|
if (providers.length === 0) {
|
|
1507
3425
|
console.log(chalk16.yellow("\n\u26A0\uFE0F \u6682\u65E0 Codex \u670D\u52A1\u5546\n"));
|
|
@@ -1512,7 +3430,7 @@ function removeCommand(program2) {
|
|
|
1512
3430
|
if (name) {
|
|
1513
3431
|
const provider = manager.findByName(name);
|
|
1514
3432
|
if (!provider) {
|
|
1515
|
-
throw new
|
|
3433
|
+
throw new ProviderNotFoundError(name);
|
|
1516
3434
|
}
|
|
1517
3435
|
targetId = provider.id;
|
|
1518
3436
|
targetName = provider.name;
|
|
@@ -1549,7 +3467,7 @@ function removeCommand(program2) {
|
|
|
1549
3467
|
console.log(chalk16.green(`\u2705 \u5DF2\u5220\u9664: ${targetName}`));
|
|
1550
3468
|
console.log();
|
|
1551
3469
|
} catch (error) {
|
|
1552
|
-
if (error instanceof
|
|
3470
|
+
if (error instanceof ProviderNotFoundError) {
|
|
1553
3471
|
console.error(chalk16.red(`
|
|
1554
3472
|
\u274C \u670D\u52A1\u5546\u4E0D\u5B58\u5728
|
|
1555
3473
|
`));
|
|
@@ -1565,13 +3483,13 @@ function removeCommand(program2) {
|
|
|
1565
3483
|
}
|
|
1566
3484
|
|
|
1567
3485
|
// src/commands/codex/edit.ts
|
|
3486
|
+
init_dist();
|
|
1568
3487
|
import chalk17 from "chalk";
|
|
1569
3488
|
import inquirer11 from "inquirer";
|
|
1570
|
-
import { createCodexManager as createCodexManager9, ProviderNotFoundError as ProviderNotFoundError3 } from "@ccman/core";
|
|
1571
3489
|
function editCommand(program2) {
|
|
1572
3490
|
program2.command("edit [name]").description("\u7F16\u8F91 Codex \u670D\u52A1\u5546").action(async (name) => {
|
|
1573
3491
|
try {
|
|
1574
|
-
const manager =
|
|
3492
|
+
const manager = createCodexManager();
|
|
1575
3493
|
const providers = manager.list();
|
|
1576
3494
|
if (providers.length === 0) {
|
|
1577
3495
|
console.log(chalk17.yellow("\n\u26A0\uFE0F \u6682\u65E0 Codex \u670D\u52A1\u5546\n"));
|
|
@@ -1581,7 +3499,7 @@ function editCommand(program2) {
|
|
|
1581
3499
|
if (name) {
|
|
1582
3500
|
const provider2 = manager.findByName(name);
|
|
1583
3501
|
if (!provider2) {
|
|
1584
|
-
throw new
|
|
3502
|
+
throw new ProviderNotFoundError(name);
|
|
1585
3503
|
}
|
|
1586
3504
|
targetId = provider2.id;
|
|
1587
3505
|
} else {
|
|
@@ -1653,13 +3571,13 @@ function editCommand(program2) {
|
|
|
1653
3571
|
}
|
|
1654
3572
|
|
|
1655
3573
|
// src/commands/codex/clone.ts
|
|
3574
|
+
init_dist();
|
|
1656
3575
|
import chalk18 from "chalk";
|
|
1657
3576
|
import inquirer12 from "inquirer";
|
|
1658
|
-
import { createCodexManager as createCodexManager10, ProviderNotFoundError as ProviderNotFoundError4 } from "@ccman/core";
|
|
1659
3577
|
function cloneCommand(program2) {
|
|
1660
3578
|
program2.command("clone [source-name] [new-name]").description("\u514B\u9686 Codex \u670D\u52A1\u5546").action(async (sourceName, newName) => {
|
|
1661
3579
|
try {
|
|
1662
|
-
const manager =
|
|
3580
|
+
const manager = createCodexManager();
|
|
1663
3581
|
const providers = manager.list();
|
|
1664
3582
|
if (providers.length === 0) {
|
|
1665
3583
|
console.log(chalk18.yellow("\n\u26A0\uFE0F \u6682\u65E0 Codex \u670D\u52A1\u5546\n"));
|
|
@@ -1669,7 +3587,7 @@ function cloneCommand(program2) {
|
|
|
1669
3587
|
if (sourceName) {
|
|
1670
3588
|
const provider = manager.findByName(sourceName);
|
|
1671
3589
|
if (!provider) {
|
|
1672
|
-
throw new
|
|
3590
|
+
throw new ProviderNotFoundError(sourceName);
|
|
1673
3591
|
}
|
|
1674
3592
|
sourceId = provider.id;
|
|
1675
3593
|
} else {
|
|
@@ -1731,17 +3649,13 @@ function createCodexCommands(program2) {
|
|
|
1731
3649
|
}
|
|
1732
3650
|
|
|
1733
3651
|
// src/commands/claude/add.ts
|
|
3652
|
+
init_dist();
|
|
1734
3653
|
import chalk19 from "chalk";
|
|
1735
3654
|
import inquirer13 from "inquirer";
|
|
1736
|
-
import {
|
|
1737
|
-
createClaudeManager as createClaudeManager4,
|
|
1738
|
-
CC_PRESETS,
|
|
1739
|
-
getClaudeConfigPath
|
|
1740
|
-
} from "@ccman/core";
|
|
1741
3655
|
function addCommand2(program2) {
|
|
1742
3656
|
program2.command("add").description("\u6DFB\u52A0\u65B0\u7684 Claude Code \u670D\u52A1\u5546(\u4EA4\u4E92\u5F0F)").action(async () => {
|
|
1743
3657
|
try {
|
|
1744
|
-
const manager =
|
|
3658
|
+
const manager = createClaudeManager();
|
|
1745
3659
|
console.log(chalk19.bold("\n\u{1F4DD} \u6DFB\u52A0 Claude Code \u670D\u52A1\u5546\n"));
|
|
1746
3660
|
const { usePreset } = await inquirer13.prompt([
|
|
1747
3661
|
{
|
|
@@ -1857,12 +3771,12 @@ function addCommand2(program2) {
|
|
|
1857
3771
|
}
|
|
1858
3772
|
|
|
1859
3773
|
// src/commands/claude/list.ts
|
|
3774
|
+
init_dist();
|
|
1860
3775
|
import chalk20 from "chalk";
|
|
1861
|
-
import { createClaudeManager as createClaudeManager5 } from "@ccman/core";
|
|
1862
3776
|
function listCommand2(program2) {
|
|
1863
3777
|
program2.command("list").alias("ls").description("\u5217\u51FA\u6240\u6709 Claude Code \u670D\u52A1\u5546").action(async () => {
|
|
1864
3778
|
try {
|
|
1865
|
-
const manager =
|
|
3779
|
+
const manager = createClaudeManager();
|
|
1866
3780
|
const providers = manager.list();
|
|
1867
3781
|
const current = manager.getCurrent();
|
|
1868
3782
|
if (providers.length === 0) {
|
|
@@ -1883,17 +3797,13 @@ function listCommand2(program2) {
|
|
|
1883
3797
|
}
|
|
1884
3798
|
|
|
1885
3799
|
// src/commands/claude/use.ts
|
|
3800
|
+
init_dist();
|
|
1886
3801
|
import chalk21 from "chalk";
|
|
1887
3802
|
import inquirer14 from "inquirer";
|
|
1888
|
-
import {
|
|
1889
|
-
createClaudeManager as createClaudeManager6,
|
|
1890
|
-
ProviderNotFoundError as ProviderNotFoundError5,
|
|
1891
|
-
getClaudeConfigPath as getClaudeConfigPath2
|
|
1892
|
-
} from "@ccman/core";
|
|
1893
3803
|
function useCommand2(program2) {
|
|
1894
3804
|
program2.command("use [name]").description("\u5207\u6362 Claude Code \u670D\u52A1\u5546").action(async (name) => {
|
|
1895
3805
|
try {
|
|
1896
|
-
const manager =
|
|
3806
|
+
const manager = createClaudeManager();
|
|
1897
3807
|
const providers = manager.list();
|
|
1898
3808
|
if (providers.length === 0) {
|
|
1899
3809
|
console.log(chalk21.yellow("\n\u26A0\uFE0F \u6682\u65E0 Claude Code \u670D\u52A1\u5546\n"));
|
|
@@ -1904,7 +3814,7 @@ function useCommand2(program2) {
|
|
|
1904
3814
|
if (name) {
|
|
1905
3815
|
const provider2 = manager.findByName(name);
|
|
1906
3816
|
if (!provider2) {
|
|
1907
|
-
throw new
|
|
3817
|
+
throw new ProviderNotFoundError(name);
|
|
1908
3818
|
}
|
|
1909
3819
|
targetId = provider2.id;
|
|
1910
3820
|
} else {
|
|
@@ -1930,10 +3840,10 @@ function useCommand2(program2) {
|
|
|
1930
3840
|
console.log(` ${chalk21.gray(`URL: ${provider.baseUrl}`)}`);
|
|
1931
3841
|
console.log();
|
|
1932
3842
|
console.log(chalk21.gray("\u914D\u7F6E\u5DF2\u66F4\u65B0:"));
|
|
1933
|
-
console.log(chalk21.gray(` - ${
|
|
3843
|
+
console.log(chalk21.gray(` - ${getClaudeConfigPath()}`));
|
|
1934
3844
|
console.log();
|
|
1935
3845
|
} catch (error) {
|
|
1936
|
-
if (error instanceof
|
|
3846
|
+
if (error instanceof ProviderNotFoundError) {
|
|
1937
3847
|
console.error(chalk21.red(`
|
|
1938
3848
|
\u274C \u670D\u52A1\u5546\u4E0D\u5B58\u5728: ${error.message}
|
|
1939
3849
|
`));
|
|
@@ -1949,12 +3859,12 @@ function useCommand2(program2) {
|
|
|
1949
3859
|
}
|
|
1950
3860
|
|
|
1951
3861
|
// src/commands/claude/current.ts
|
|
3862
|
+
init_dist();
|
|
1952
3863
|
import chalk22 from "chalk";
|
|
1953
|
-
import { createClaudeManager as createClaudeManager7 } from "@ccman/core";
|
|
1954
3864
|
function currentCommand2(program2) {
|
|
1955
3865
|
program2.command("current").description("\u663E\u793A\u5F53\u524D\u4F7F\u7528\u7684 Claude Code \u670D\u52A1\u5546").action(async () => {
|
|
1956
3866
|
try {
|
|
1957
|
-
const manager =
|
|
3867
|
+
const manager = createClaudeManager();
|
|
1958
3868
|
const current = manager.getCurrent();
|
|
1959
3869
|
if (!current) {
|
|
1960
3870
|
console.log(chalk22.yellow("\n\u26A0\uFE0F \u672A\u9009\u62E9\u4EFB\u4F55 Claude Code \u670D\u52A1\u5546\n"));
|
|
@@ -1980,13 +3890,13 @@ function currentCommand2(program2) {
|
|
|
1980
3890
|
}
|
|
1981
3891
|
|
|
1982
3892
|
// src/commands/claude/remove.ts
|
|
3893
|
+
init_dist();
|
|
1983
3894
|
import chalk23 from "chalk";
|
|
1984
3895
|
import inquirer15 from "inquirer";
|
|
1985
|
-
import { createClaudeManager as createClaudeManager8, ProviderNotFoundError as ProviderNotFoundError6 } from "@ccman/core";
|
|
1986
3896
|
function removeCommand2(program2) {
|
|
1987
3897
|
program2.command("remove [name]").alias("rm").description("\u5220\u9664 Claude Code \u670D\u52A1\u5546").action(async (name) => {
|
|
1988
3898
|
try {
|
|
1989
|
-
const manager =
|
|
3899
|
+
const manager = createClaudeManager();
|
|
1990
3900
|
const providers = manager.list();
|
|
1991
3901
|
if (providers.length === 0) {
|
|
1992
3902
|
console.log(chalk23.yellow("\n\u26A0\uFE0F \u6682\u65E0 Claude Code \u670D\u52A1\u5546\n"));
|
|
@@ -1997,7 +3907,7 @@ function removeCommand2(program2) {
|
|
|
1997
3907
|
if (name) {
|
|
1998
3908
|
const provider = manager.findByName(name);
|
|
1999
3909
|
if (!provider) {
|
|
2000
|
-
throw new
|
|
3910
|
+
throw new ProviderNotFoundError(name);
|
|
2001
3911
|
}
|
|
2002
3912
|
targetId = provider.id;
|
|
2003
3913
|
targetName = provider.name;
|
|
@@ -2034,7 +3944,7 @@ function removeCommand2(program2) {
|
|
|
2034
3944
|
console.log(chalk23.green(`\u2705 \u5DF2\u5220\u9664: ${targetName}`));
|
|
2035
3945
|
console.log();
|
|
2036
3946
|
} catch (error) {
|
|
2037
|
-
if (error instanceof
|
|
3947
|
+
if (error instanceof ProviderNotFoundError) {
|
|
2038
3948
|
console.error(chalk23.red(`
|
|
2039
3949
|
\u274C \u670D\u52A1\u5546\u4E0D\u5B58\u5728
|
|
2040
3950
|
`));
|
|
@@ -2050,13 +3960,13 @@ function removeCommand2(program2) {
|
|
|
2050
3960
|
}
|
|
2051
3961
|
|
|
2052
3962
|
// src/commands/claude/edit.ts
|
|
3963
|
+
init_dist();
|
|
2053
3964
|
import chalk24 from "chalk";
|
|
2054
3965
|
import inquirer16 from "inquirer";
|
|
2055
|
-
import { createClaudeManager as createClaudeManager9, ProviderNotFoundError as ProviderNotFoundError7 } from "@ccman/core";
|
|
2056
3966
|
function editCommand2(program2) {
|
|
2057
3967
|
program2.command("edit [name]").description("\u7F16\u8F91 Claude Code \u670D\u52A1\u5546").action(async (name) => {
|
|
2058
3968
|
try {
|
|
2059
|
-
const manager =
|
|
3969
|
+
const manager = createClaudeManager();
|
|
2060
3970
|
const providers = manager.list();
|
|
2061
3971
|
if (providers.length === 0) {
|
|
2062
3972
|
console.log(chalk24.yellow("\n\u26A0\uFE0F \u6682\u65E0 Claude Code \u670D\u52A1\u5546\n"));
|
|
@@ -2066,7 +3976,7 @@ function editCommand2(program2) {
|
|
|
2066
3976
|
if (name) {
|
|
2067
3977
|
const provider2 = manager.findByName(name);
|
|
2068
3978
|
if (!provider2) {
|
|
2069
|
-
throw new
|
|
3979
|
+
throw new ProviderNotFoundError(name);
|
|
2070
3980
|
}
|
|
2071
3981
|
targetId = provider2.id;
|
|
2072
3982
|
} else {
|
|
@@ -2138,13 +4048,13 @@ function editCommand2(program2) {
|
|
|
2138
4048
|
}
|
|
2139
4049
|
|
|
2140
4050
|
// src/commands/claude/clone.ts
|
|
4051
|
+
init_dist();
|
|
2141
4052
|
import chalk25 from "chalk";
|
|
2142
4053
|
import inquirer17 from "inquirer";
|
|
2143
|
-
import { createClaudeManager as createClaudeManager10, ProviderNotFoundError as ProviderNotFoundError8 } from "@ccman/core";
|
|
2144
4054
|
function cloneCommand2(program2) {
|
|
2145
4055
|
program2.command("clone [source-name] [new-name]").description("\u514B\u9686 Claude Code \u670D\u52A1\u5546").action(async (sourceName, newName) => {
|
|
2146
4056
|
try {
|
|
2147
|
-
const manager =
|
|
4057
|
+
const manager = createClaudeManager();
|
|
2148
4058
|
const providers = manager.list();
|
|
2149
4059
|
if (providers.length === 0) {
|
|
2150
4060
|
console.log(chalk25.yellow("\n\u26A0\uFE0F \u6682\u65E0 Claude Code \u670D\u52A1\u5546\n"));
|
|
@@ -2154,7 +4064,7 @@ function cloneCommand2(program2) {
|
|
|
2154
4064
|
if (sourceName) {
|
|
2155
4065
|
const provider = manager.findByName(sourceName);
|
|
2156
4066
|
if (!provider) {
|
|
2157
|
-
throw new
|
|
4067
|
+
throw new ProviderNotFoundError(sourceName);
|
|
2158
4068
|
}
|
|
2159
4069
|
sourceId = provider.id;
|
|
2160
4070
|
} else {
|
|
@@ -2205,10 +4115,10 @@ function cloneCommand2(program2) {
|
|
|
2205
4115
|
}
|
|
2206
4116
|
|
|
2207
4117
|
// src/commands/clean.ts
|
|
4118
|
+
init_dist();
|
|
2208
4119
|
import chalk26 from "chalk";
|
|
2209
4120
|
import inquirer18 from "inquirer";
|
|
2210
|
-
|
|
2211
|
-
function formatBytes(bytes) {
|
|
4121
|
+
function formatBytes2(bytes) {
|
|
2212
4122
|
if (bytes < 1024) return `${bytes} B`;
|
|
2213
4123
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
2214
4124
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
@@ -2231,9 +4141,9 @@ function displayAnalysis() {
|
|
|
2231
4141
|
}
|
|
2232
4142
|
console.log();
|
|
2233
4143
|
console.log(chalk26.cyan("\u9884\u8BA1\u53EF\u8282\u7701\u7A7A\u95F4:"));
|
|
2234
|
-
console.log(` ${chalk26.green("\u4FDD\u5B88\u6E05\u7406")} (\u4FDD\u755910\u6761): ${chalk26.bold(
|
|
2235
|
-
console.log(` ${chalk26.yellow("\u4E2D\u7B49\u6E05\u7406")} (\u4FDD\u75595\u6761): ${chalk26.bold(
|
|
2236
|
-
console.log(` ${chalk26.red("\u6FC0\u8FDB\u6E05\u7406")} (\u6E05\u7A7A\u5386\u53F2): ${chalk26.bold(
|
|
4144
|
+
console.log(` ${chalk26.green("\u4FDD\u5B88\u6E05\u7406")} (\u4FDD\u755910\u6761): ${chalk26.bold(formatBytes2(analysis.estimatedSavings.conservative))}`);
|
|
4145
|
+
console.log(` ${chalk26.yellow("\u4E2D\u7B49\u6E05\u7406")} (\u4FDD\u75595\u6761): ${chalk26.bold(formatBytes2(analysis.estimatedSavings.moderate))}`);
|
|
4146
|
+
console.log(` ${chalk26.red("\u6FC0\u8FDB\u6E05\u7406")} (\u6E05\u7A7A\u5386\u53F2): ${chalk26.bold(formatBytes2(analysis.estimatedSavings.aggressive))}`);
|
|
2237
4147
|
console.log();
|
|
2238
4148
|
console.log(chalk26.blue(`\u{1F4A1} \u6267\u884C\u6E05\u7406: ccman cc clean
|
|
2239
4149
|
`));
|
|
@@ -2278,9 +4188,9 @@ function cleanCommand(program2) {
|
|
|
2278
4188
|
console.log(chalk26.cyan("\n\u6B63\u5728\u6E05\u7406...\n"));
|
|
2279
4189
|
const result = cleanClaudeJson(cleanOptions);
|
|
2280
4190
|
console.log(chalk26.green("\u2705 \u6E05\u7406\u5B8C\u6210\n"));
|
|
2281
|
-
console.log(`\u6E05\u7406\u524D: ${chalk26.bold(
|
|
2282
|
-
console.log(`\u6E05\u7406\u540E: ${chalk26.bold(
|
|
2283
|
-
console.log(`\u8282\u7701\u7A7A\u95F4: ${chalk26.green.bold(
|
|
4191
|
+
console.log(`\u6E05\u7406\u524D: ${chalk26.bold(formatBytes2(result.sizeBefore))}`);
|
|
4192
|
+
console.log(`\u6E05\u7406\u540E: ${chalk26.bold(formatBytes2(result.sizeAfter))}`);
|
|
4193
|
+
console.log(`\u8282\u7701\u7A7A\u95F4: ${chalk26.green.bold(formatBytes2(result.saved))} (${(result.saved / result.sizeBefore * 100).toFixed(1)}%)`);
|
|
2284
4194
|
console.log();
|
|
2285
4195
|
if (result.cleanedItems.projectHistory > 0) {
|
|
2286
4196
|
console.log(`\u6E05\u7406\u5386\u53F2\u8BB0\u5F55: ${chalk26.bold(result.cleanedItems.projectHistory)} \u6761`);
|
|
@@ -2346,15 +4256,15 @@ async function promptForOptions(analysis) {
|
|
|
2346
4256
|
message: "\u9009\u62E9\u6E05\u7406\u65B9\u6848:",
|
|
2347
4257
|
choices: [
|
|
2348
4258
|
{
|
|
2349
|
-
name: `${chalk26.green("\u4FDD\u5B88\u6E05\u7406")} - \u4FDD\u7559\u6700\u8FD110\u6761\u8BB0\u5F55\uFF0C\u6E05\u7406\u7F13\u5B58 (\u8282\u7701\u7EA6 ${
|
|
4259
|
+
name: `${chalk26.green("\u4FDD\u5B88\u6E05\u7406")} - \u4FDD\u7559\u6700\u8FD110\u6761\u8BB0\u5F55\uFF0C\u6E05\u7406\u7F13\u5B58 (\u8282\u7701\u7EA6 ${formatBytes2(analysis.estimatedSavings.conservative)})`,
|
|
2350
4260
|
value: "conservative"
|
|
2351
4261
|
},
|
|
2352
4262
|
{
|
|
2353
|
-
name: `${chalk26.yellow("\u4E2D\u7B49\u6E05\u7406")} - \u4FDD\u7559\u6700\u8FD15\u6761\u8BB0\u5F55\uFF0C\u6E05\u7406\u7F13\u5B58\u548C\u7EDF\u8BA1 (\u8282\u7701\u7EA6 ${
|
|
4263
|
+
name: `${chalk26.yellow("\u4E2D\u7B49\u6E05\u7406")} - \u4FDD\u7559\u6700\u8FD15\u6761\u8BB0\u5F55\uFF0C\u6E05\u7406\u7F13\u5B58\u548C\u7EDF\u8BA1 (\u8282\u7701\u7EA6 ${formatBytes2(analysis.estimatedSavings.moderate)})`,
|
|
2354
4264
|
value: "moderate"
|
|
2355
4265
|
},
|
|
2356
4266
|
{
|
|
2357
|
-
name: `${chalk26.red("\u6FC0\u8FDB\u6E05\u7406")} - \u6E05\u7A7A\u5386\u53F2\u8BB0\u5F55\uFF0C\u6E05\u7406\u7F13\u5B58\u548C\u7EDF\u8BA1 (\u8282\u7701\u7EA6 ${
|
|
4267
|
+
name: `${chalk26.red("\u6FC0\u8FDB\u6E05\u7406")} - \u6E05\u7A7A\u5386\u53F2\u8BB0\u5F55\uFF0C\u6E05\u7406\u7F13\u5B58\u548C\u7EDF\u8BA1 (\u8282\u7701\u7EA6 ${formatBytes2(analysis.estimatedSavings.aggressive)})`,
|
|
2358
4268
|
value: "aggressive"
|
|
2359
4269
|
},
|
|
2360
4270
|
{
|
|
@@ -2422,9 +4332,9 @@ function createClaudeCommands(program2) {
|
|
|
2422
4332
|
}
|
|
2423
4333
|
|
|
2424
4334
|
// src/commands/mcp/add.ts
|
|
4335
|
+
init_dist();
|
|
2425
4336
|
import chalk27 from "chalk";
|
|
2426
4337
|
import inquirer19 from "inquirer";
|
|
2427
|
-
import { createMCPManager, MCP_PRESETS_DETAIL, getClaudeConfigPath as getClaudeConfigPath3 } from "@ccman/core";
|
|
2428
4338
|
function addCommand3(program2) {
|
|
2429
4339
|
program2.command("add").description("\u6DFB\u52A0\u65B0\u7684 MCP \u670D\u52A1\u5668(\u4EA4\u4E92\u5F0F)").action(async () => {
|
|
2430
4340
|
try {
|
|
@@ -2571,7 +4481,7 @@ function addCommand3(program2) {
|
|
|
2571
4481
|
console.log(chalk27.green("\u2705 \u914D\u7F6E\u5DF2\u81EA\u52A8\u540C\u6B65\u5230 ~/.claude.json"));
|
|
2572
4482
|
console.log();
|
|
2573
4483
|
console.log(chalk27.gray("\u914D\u7F6E\u6587\u4EF6:"));
|
|
2574
|
-
console.log(chalk27.gray(` - ${
|
|
4484
|
+
console.log(chalk27.gray(` - ${getClaudeConfigPath()}`));
|
|
2575
4485
|
console.log();
|
|
2576
4486
|
} catch (error) {
|
|
2577
4487
|
console.error(chalk27.red(`
|
|
@@ -2583,12 +4493,12 @@ function addCommand3(program2) {
|
|
|
2583
4493
|
}
|
|
2584
4494
|
|
|
2585
4495
|
// src/commands/mcp/list.ts
|
|
4496
|
+
init_dist();
|
|
2586
4497
|
import chalk28 from "chalk";
|
|
2587
|
-
import { createMCPManager as createMCPManager2 } from "@ccman/core";
|
|
2588
4498
|
function listCommand3(program2) {
|
|
2589
4499
|
program2.command("list").alias("ls").description("\u5217\u51FA\u6240\u6709 MCP \u670D\u52A1\u5668").action(async () => {
|
|
2590
4500
|
try {
|
|
2591
|
-
const manager =
|
|
4501
|
+
const manager = createMCPManager();
|
|
2592
4502
|
const providers = manager.list();
|
|
2593
4503
|
if (providers.length === 0) {
|
|
2594
4504
|
console.log(chalk28.yellow("\n\u26A0\uFE0F \u6682\u65E0 MCP \u670D\u52A1\u5668\n"));
|
|
@@ -2629,13 +4539,13 @@ function listCommand3(program2) {
|
|
|
2629
4539
|
}
|
|
2630
4540
|
|
|
2631
4541
|
// src/commands/mcp/remove.ts
|
|
4542
|
+
init_dist();
|
|
2632
4543
|
import chalk29 from "chalk";
|
|
2633
4544
|
import inquirer20 from "inquirer";
|
|
2634
|
-
import { createMCPManager as createMCPManager3, ProviderNotFoundError as ProviderNotFoundError9, getClaudeConfigPath as getClaudeConfigPath4 } from "@ccman/core";
|
|
2635
4545
|
function removeCommand3(program2) {
|
|
2636
4546
|
program2.command("remove [name]").alias("rm").description("\u5220\u9664 MCP \u670D\u52A1\u5668").action(async (name) => {
|
|
2637
4547
|
try {
|
|
2638
|
-
const manager =
|
|
4548
|
+
const manager = createMCPManager();
|
|
2639
4549
|
const providers = manager.list();
|
|
2640
4550
|
if (providers.length === 0) {
|
|
2641
4551
|
console.log(chalk29.yellow("\n\u26A0\uFE0F \u6682\u65E0 MCP \u670D\u52A1\u5668\n"));
|
|
@@ -2646,7 +4556,7 @@ function removeCommand3(program2) {
|
|
|
2646
4556
|
if (name) {
|
|
2647
4557
|
const provider = manager.findByName(name);
|
|
2648
4558
|
if (!provider) {
|
|
2649
|
-
throw new
|
|
4559
|
+
throw new ProviderNotFoundError(name);
|
|
2650
4560
|
}
|
|
2651
4561
|
targetId = provider.id;
|
|
2652
4562
|
targetName = provider.name;
|
|
@@ -2685,10 +4595,10 @@ function removeCommand3(program2) {
|
|
|
2685
4595
|
console.log(chalk29.green("\u2705 \u914D\u7F6E\u5DF2\u81EA\u52A8\u540C\u6B65\u5230 ~/.claude.json"));
|
|
2686
4596
|
console.log();
|
|
2687
4597
|
console.log(chalk29.gray("\u914D\u7F6E\u6587\u4EF6:"));
|
|
2688
|
-
console.log(chalk29.gray(` - ${
|
|
4598
|
+
console.log(chalk29.gray(` - ${getClaudeConfigPath()}`));
|
|
2689
4599
|
console.log();
|
|
2690
4600
|
} catch (error) {
|
|
2691
|
-
if (error instanceof
|
|
4601
|
+
if (error instanceof ProviderNotFoundError) {
|
|
2692
4602
|
console.error(chalk29.red(`
|
|
2693
4603
|
\u274C MCP \u670D\u52A1\u5668\u4E0D\u5B58\u5728
|
|
2694
4604
|
`));
|
|
@@ -2704,13 +4614,13 @@ function removeCommand3(program2) {
|
|
|
2704
4614
|
}
|
|
2705
4615
|
|
|
2706
4616
|
// src/commands/mcp/edit.ts
|
|
4617
|
+
init_dist();
|
|
2707
4618
|
import chalk30 from "chalk";
|
|
2708
4619
|
import inquirer21 from "inquirer";
|
|
2709
|
-
import { createMCPManager as createMCPManager4, ProviderNotFoundError as ProviderNotFoundError10, getClaudeConfigPath as getClaudeConfigPath5 } from "@ccman/core";
|
|
2710
4620
|
function editCommand3(program2) {
|
|
2711
4621
|
program2.command("edit [name]").description("\u7F16\u8F91 MCP \u670D\u52A1\u5668").action(async (name) => {
|
|
2712
4622
|
try {
|
|
2713
|
-
const manager =
|
|
4623
|
+
const manager = createMCPManager();
|
|
2714
4624
|
const providers = manager.list();
|
|
2715
4625
|
if (providers.length === 0) {
|
|
2716
4626
|
console.log(chalk30.yellow("\n\u26A0\uFE0F \u6682\u65E0 MCP \u670D\u52A1\u5668\n"));
|
|
@@ -2720,7 +4630,7 @@ function editCommand3(program2) {
|
|
|
2720
4630
|
if (name) {
|
|
2721
4631
|
const provider2 = manager.findByName(name);
|
|
2722
4632
|
if (!provider2) {
|
|
2723
|
-
throw new
|
|
4633
|
+
throw new ProviderNotFoundError(name);
|
|
2724
4634
|
}
|
|
2725
4635
|
targetId = provider2.id;
|
|
2726
4636
|
} else {
|
|
@@ -2803,7 +4713,7 @@ function editCommand3(program2) {
|
|
|
2803
4713
|
console.log(chalk30.green("\u2705 \u914D\u7F6E\u5DF2\u81EA\u52A8\u540C\u6B65\u5230 ~/.claude.json"));
|
|
2804
4714
|
console.log();
|
|
2805
4715
|
console.log(chalk30.gray("\u914D\u7F6E\u6587\u4EF6:"));
|
|
2806
|
-
console.log(chalk30.gray(` - ${
|
|
4716
|
+
console.log(chalk30.gray(` - ${getClaudeConfigPath()}`));
|
|
2807
4717
|
console.log();
|
|
2808
4718
|
} catch (error) {
|
|
2809
4719
|
console.error(chalk30.red(`
|
|
@@ -2826,9 +4736,9 @@ function createMCPCommands(program2) {
|
|
|
2826
4736
|
init_sync();
|
|
2827
4737
|
|
|
2828
4738
|
// src/commands/export.ts
|
|
4739
|
+
init_dist();
|
|
2829
4740
|
import chalk31 from "chalk";
|
|
2830
|
-
import
|
|
2831
|
-
import { exportConfig, validateExport } from "@ccman/core";
|
|
4741
|
+
import path10 from "path";
|
|
2832
4742
|
function exportCommand(program2) {
|
|
2833
4743
|
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) => {
|
|
2834
4744
|
try {
|
|
@@ -2839,7 +4749,7 @@ function exportCommand(program2) {
|
|
|
2839
4749
|
`));
|
|
2840
4750
|
process.exit(1);
|
|
2841
4751
|
}
|
|
2842
|
-
const resolvedPath = targetDir.startsWith("~") ?
|
|
4752
|
+
const resolvedPath = targetDir.startsWith("~") ? path10.join(process.env.HOME || "", targetDir.slice(1)) : path10.resolve(targetDir);
|
|
2843
4753
|
console.log("\u5BFC\u51FA\u6587\u4EF6:");
|
|
2844
4754
|
console.log(` ${chalk31.cyan("codex.json")} - Codex \u914D\u7F6E`);
|
|
2845
4755
|
console.log(` ${chalk31.cyan("claude.json")} - Claude \u914D\u7F6E`);
|
|
@@ -2868,14 +4778,14 @@ function exportCommand(program2) {
|
|
|
2868
4778
|
}
|
|
2869
4779
|
|
|
2870
4780
|
// src/commands/import.ts
|
|
4781
|
+
init_dist();
|
|
2871
4782
|
import chalk32 from "chalk";
|
|
2872
4783
|
import inquirer22 from "inquirer";
|
|
2873
|
-
import
|
|
2874
|
-
import { importConfig, validateImportDir } from "@ccman/core";
|
|
4784
|
+
import path11 from "path";
|
|
2875
4785
|
function importCommand(program2) {
|
|
2876
4786
|
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) => {
|
|
2877
4787
|
try {
|
|
2878
|
-
const resolvedPath = sourceDir.startsWith("~") ?
|
|
4788
|
+
const resolvedPath = sourceDir.startsWith("~") ? path11.join(process.env.HOME || "", sourceDir.slice(1)) : path11.resolve(sourceDir);
|
|
2879
4789
|
console.log(chalk32.bold("\n\u{1F4E5} \u5BFC\u5165\u914D\u7F6E\n"));
|
|
2880
4790
|
const validation = validateImportDir(resolvedPath);
|
|
2881
4791
|
if (!validation.valid) {
|
|
@@ -2950,7 +4860,7 @@ function importCommand(program2) {
|
|
|
2950
4860
|
}
|
|
2951
4861
|
|
|
2952
4862
|
// src/index.ts
|
|
2953
|
-
|
|
4863
|
+
init_dist();
|
|
2954
4864
|
if (process.env.NODE_ENV === "development") {
|
|
2955
4865
|
console.log(chalk33.gray("\n[\u5F00\u53D1\u6A21\u5F0F] \u914D\u7F6E\u76EE\u5F55:"));
|
|
2956
4866
|
console.log(chalk33.gray(` ccman: ${getCcmanDir()}`));
|
|
@@ -2959,7 +4869,7 @@ if (process.env.NODE_ENV === "development") {
|
|
|
2959
4869
|
console.log();
|
|
2960
4870
|
}
|
|
2961
4871
|
var program = new Command3();
|
|
2962
|
-
program.name("ccman").description("Codex/Claude Code API \u670D\u52A1\u5546\u914D\u7F6E\u7BA1\u7406\u5DE5\u5177").version(
|
|
4872
|
+
program.name("ccman").description("Codex/Claude Code API \u670D\u52A1\u5546\u914D\u7F6E\u7BA1\u7406\u5DE5\u5177").version(VERSION).showHelpAfterError(false).exitOverride((err) => {
|
|
2963
4873
|
if (err.code === "commander.helpDisplayed" || err.code === "commander.version") {
|
|
2964
4874
|
process.exit(0);
|
|
2965
4875
|
}
|