ccman 3.0.31 → 3.0.32
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 +2022 -124
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -9,8 +9,1923 @@ 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.32",
|
|
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
|
+
throw new Error("~/.claude.json \u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
1788
|
+
}
|
|
1789
|
+
const fileSize = getFileSize(filePath);
|
|
1790
|
+
const content = fs9.readFileSync(filePath, "utf-8");
|
|
1791
|
+
const config = JSON.parse(content);
|
|
1792
|
+
const projects = config.projects || {};
|
|
1793
|
+
const projectHistory = [];
|
|
1794
|
+
let totalHistoryCount = 0;
|
|
1795
|
+
for (const [projectPath, projectData] of Object.entries(projects)) {
|
|
1796
|
+
const historyCount = projectData.history?.length || 0;
|
|
1797
|
+
totalHistoryCount += historyCount;
|
|
1798
|
+
projectHistory.push({
|
|
1799
|
+
path: projectPath,
|
|
1800
|
+
count: historyCount
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1803
|
+
projectHistory.sort((a, b) => b.count - a.count);
|
|
1804
|
+
const cacheSize = config.cachedChangelog?.length || 0;
|
|
1805
|
+
const historySize = fileSize - cacheSize - 2e4;
|
|
1806
|
+
const avgHistorySize = totalHistoryCount > 0 ? historySize / totalHistoryCount : 0;
|
|
1807
|
+
const estimatedSavings = {
|
|
1808
|
+
conservative: Math.floor(avgHistorySize * Math.max(0, totalHistoryCount - projectHistory.length * 10)) + cacheSize,
|
|
1809
|
+
moderate: Math.floor(avgHistorySize * Math.max(0, totalHistoryCount - projectHistory.length * 5)) + cacheSize,
|
|
1810
|
+
aggressive: Math.floor(historySize) + cacheSize
|
|
1811
|
+
};
|
|
1812
|
+
return {
|
|
1813
|
+
fileSize,
|
|
1814
|
+
fileSizeFormatted: formatBytes(fileSize),
|
|
1815
|
+
projectCount: projectHistory.length,
|
|
1816
|
+
totalHistoryCount,
|
|
1817
|
+
projectHistory,
|
|
1818
|
+
cacheSize,
|
|
1819
|
+
estimatedSavings
|
|
1820
|
+
};
|
|
1821
|
+
}
|
|
1822
|
+
function cleanClaudeJson(options = {}) {
|
|
1823
|
+
const filePath = getClaudeJsonPath();
|
|
1824
|
+
if (!fs9.existsSync(filePath)) {
|
|
1825
|
+
throw new Error("~/.claude.json \u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
1826
|
+
}
|
|
1827
|
+
const backupPath = backupFile(filePath);
|
|
1828
|
+
const sizeBefore = getFileSize(filePath);
|
|
1829
|
+
const content = fs9.readFileSync(filePath, "utf-8");
|
|
1830
|
+
const config = JSON.parse(content);
|
|
1831
|
+
const cleanedItems = applyCleanOptions(config, options);
|
|
1832
|
+
saveJsonAtomic(filePath, config);
|
|
1833
|
+
const sizeAfter = getFileSize(filePath);
|
|
1834
|
+
return {
|
|
1835
|
+
sizeBefore,
|
|
1836
|
+
sizeAfter,
|
|
1837
|
+
saved: sizeBefore - sizeAfter,
|
|
1838
|
+
cleanedItems,
|
|
1839
|
+
backupPath
|
|
1840
|
+
};
|
|
1841
|
+
}
|
|
1842
|
+
function applyCleanOptions(config, options) {
|
|
1843
|
+
let projectHistoryCount = 0;
|
|
1844
|
+
if (options.cleanProjectHistory && config.projects) {
|
|
1845
|
+
const keepCount = options.keepRecentCount ?? 10;
|
|
1846
|
+
const targetProjects = options.projectPaths || [];
|
|
1847
|
+
for (const [projectPath, projectData] of Object.entries(config.projects)) {
|
|
1848
|
+
if (targetProjects.length > 0 && !targetProjects.includes(projectPath)) {
|
|
1849
|
+
continue;
|
|
1850
|
+
}
|
|
1851
|
+
if (projectData.history && Array.isArray(projectData.history)) {
|
|
1852
|
+
const originalCount = projectData.history.length;
|
|
1853
|
+
projectData.history = projectData.history.slice(-keepCount);
|
|
1854
|
+
projectHistoryCount += originalCount - projectData.history.length;
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
if (options.cleanCache) {
|
|
1859
|
+
delete config.cachedChangelog;
|
|
1860
|
+
config.changelogLastFetched = 0;
|
|
1861
|
+
}
|
|
1862
|
+
if (options.cleanStats) {
|
|
1863
|
+
config.numStartups = 0;
|
|
1864
|
+
config.promptQueueUseCount = 0;
|
|
1865
|
+
config.tipsHistory = {};
|
|
1866
|
+
}
|
|
1867
|
+
return {
|
|
1868
|
+
projectHistory: projectHistoryCount,
|
|
1869
|
+
cache: options.cleanCache || false,
|
|
1870
|
+
stats: options.cleanStats || false
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
var CleanPresets;
|
|
1874
|
+
var init_claude_clean = __esm({
|
|
1875
|
+
"../core/dist/claude-clean.js"() {
|
|
1876
|
+
"use strict";
|
|
1877
|
+
init_paths();
|
|
1878
|
+
CleanPresets = {
|
|
1879
|
+
/** 保守清理:保留最近10条记录,清理缓存 */
|
|
1880
|
+
conservative: () => ({
|
|
1881
|
+
cleanProjectHistory: true,
|
|
1882
|
+
keepRecentCount: 10,
|
|
1883
|
+
cleanCache: true,
|
|
1884
|
+
cleanStats: false
|
|
1885
|
+
}),
|
|
1886
|
+
/** 中等清理:保留最近5条记录,清理缓存和统计 */
|
|
1887
|
+
moderate: () => ({
|
|
1888
|
+
cleanProjectHistory: true,
|
|
1889
|
+
keepRecentCount: 5,
|
|
1890
|
+
cleanCache: true,
|
|
1891
|
+
cleanStats: true
|
|
1892
|
+
}),
|
|
1893
|
+
/** 激进清理:清空历史记录,清理缓存和统计 */
|
|
1894
|
+
aggressive: () => ({
|
|
1895
|
+
cleanProjectHistory: true,
|
|
1896
|
+
keepRecentCount: 0,
|
|
1897
|
+
cleanCache: true,
|
|
1898
|
+
cleanStats: true
|
|
1899
|
+
})
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1902
|
+
});
|
|
1903
|
+
|
|
1904
|
+
// ../core/dist/index.js
|
|
1905
|
+
var VERSION;
|
|
1906
|
+
var init_dist = __esm({
|
|
1907
|
+
"../core/dist/index.js"() {
|
|
1908
|
+
"use strict";
|
|
1909
|
+
init_package();
|
|
1910
|
+
init_tool_manager();
|
|
1911
|
+
init_codex2();
|
|
1912
|
+
init_claude2();
|
|
1913
|
+
init_mcp2();
|
|
1914
|
+
init_mcp();
|
|
1915
|
+
init_migrate();
|
|
1916
|
+
init_paths();
|
|
1917
|
+
init_config();
|
|
1918
|
+
init_webdav_client();
|
|
1919
|
+
init_sync_v2();
|
|
1920
|
+
init_crypto();
|
|
1921
|
+
init_merge_advanced();
|
|
1922
|
+
init_export();
|
|
1923
|
+
init_claude_clean();
|
|
1924
|
+
VERSION = package_default.version;
|
|
1925
|
+
}
|
|
1926
|
+
});
|
|
1927
|
+
|
|
12
1928
|
// src/utils/sync-config.ts
|
|
13
|
-
import { getSyncConfig, saveSyncConfig as coreSaveSyncConfig, getConfigPath } from "@ccman/core";
|
|
14
1929
|
function loadSyncConfig() {
|
|
15
1930
|
try {
|
|
16
1931
|
const config = getSyncConfig();
|
|
@@ -22,13 +1937,13 @@ function loadSyncConfig() {
|
|
|
22
1937
|
throw new Error(`\u8BFB\u53D6\u540C\u6B65\u914D\u7F6E\u5931\u8D25: ${error.message}`);
|
|
23
1938
|
}
|
|
24
1939
|
}
|
|
25
|
-
function
|
|
1940
|
+
function saveSyncConfig2(config) {
|
|
26
1941
|
try {
|
|
27
1942
|
const configToSave = { ...config };
|
|
28
1943
|
if (!configToSave.rememberSyncPassword) {
|
|
29
1944
|
delete configToSave.syncPassword;
|
|
30
1945
|
}
|
|
31
|
-
|
|
1946
|
+
saveSyncConfig(configToSave);
|
|
32
1947
|
} catch (error) {
|
|
33
1948
|
throw new Error(`\u4FDD\u5B58\u540C\u6B65\u914D\u7F6E\u5931\u8D25: ${error.message}`);
|
|
34
1949
|
}
|
|
@@ -39,6 +1954,7 @@ function getSyncConfigPath() {
|
|
|
39
1954
|
var init_sync_config = __esm({
|
|
40
1955
|
"src/utils/sync-config.ts"() {
|
|
41
1956
|
"use strict";
|
|
1957
|
+
init_dist();
|
|
42
1958
|
}
|
|
43
1959
|
});
|
|
44
1960
|
|
|
@@ -49,7 +1965,6 @@ __export(config_exports, {
|
|
|
49
1965
|
});
|
|
50
1966
|
import chalk3 from "chalk";
|
|
51
1967
|
import inquirer from "inquirer";
|
|
52
|
-
import { testWebDAVConnection } from "@ccman/core";
|
|
53
1968
|
function configCommand(program2) {
|
|
54
1969
|
program2.command("config").description("\u914D\u7F6E WebDAV \u8FDE\u63A5").action(async () => {
|
|
55
1970
|
try {
|
|
@@ -201,7 +2116,7 @@ function configCommand(program2) {
|
|
|
201
2116
|
console.log();
|
|
202
2117
|
return;
|
|
203
2118
|
}
|
|
204
|
-
|
|
2119
|
+
saveSyncConfig2(newConfig);
|
|
205
2120
|
console.log();
|
|
206
2121
|
console.log(chalk3.green("\u2705 \u914D\u7F6E\u4FDD\u5B58\u6210\u529F"));
|
|
207
2122
|
console.log();
|
|
@@ -243,10 +2158,11 @@ function configCommand(program2) {
|
|
|
243
2158
|
}
|
|
244
2159
|
});
|
|
245
2160
|
}
|
|
246
|
-
var
|
|
2161
|
+
var init_config2 = __esm({
|
|
247
2162
|
"src/commands/sync/config.ts"() {
|
|
248
2163
|
"use strict";
|
|
249
2164
|
init_sync_config();
|
|
2165
|
+
init_dist();
|
|
250
2166
|
}
|
|
251
2167
|
});
|
|
252
2168
|
|
|
@@ -271,7 +2187,7 @@ async function ensureConfigExists() {
|
|
|
271
2187
|
if (!shouldConfig) {
|
|
272
2188
|
return null;
|
|
273
2189
|
}
|
|
274
|
-
const { configCommand: configCommand2 } = await Promise.resolve().then(() => (
|
|
2190
|
+
const { configCommand: configCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
275
2191
|
const cmd = new Command();
|
|
276
2192
|
configCommand2(cmd);
|
|
277
2193
|
await cmd.parseAsync(["node", "ccman", "config"]);
|
|
@@ -290,7 +2206,6 @@ __export(test_exports, {
|
|
|
290
2206
|
testCommand: () => testCommand
|
|
291
2207
|
});
|
|
292
2208
|
import chalk5 from "chalk";
|
|
293
|
-
import { testWebDAVConnection as testWebDAVConnection2 } from "@ccman/core";
|
|
294
2209
|
function testCommand(program2) {
|
|
295
2210
|
program2.command("test").description("\u6D4B\u8BD5 WebDAV \u8FDE\u63A5").action(async () => {
|
|
296
2211
|
try {
|
|
@@ -300,7 +2215,7 @@ function testCommand(program2) {
|
|
|
300
2215
|
return;
|
|
301
2216
|
}
|
|
302
2217
|
console.log(chalk5.bold("\n\u{1F50D} \u6D4B\u8BD5 WebDAV \u8FDE\u63A5...\n"));
|
|
303
|
-
const success = await
|
|
2218
|
+
const success = await testWebDAVConnection(config);
|
|
304
2219
|
if (success) {
|
|
305
2220
|
console.log(chalk5.green("\u2705 \u8FDE\u63A5\u6210\u529F"));
|
|
306
2221
|
console.log();
|
|
@@ -328,6 +2243,7 @@ function testCommand(program2) {
|
|
|
328
2243
|
var init_test = __esm({
|
|
329
2244
|
"src/commands/sync/test.ts"() {
|
|
330
2245
|
"use strict";
|
|
2246
|
+
init_dist();
|
|
331
2247
|
init_helpers();
|
|
332
2248
|
}
|
|
333
2249
|
});
|
|
@@ -339,7 +2255,6 @@ __export(upload_exports, {
|
|
|
339
2255
|
});
|
|
340
2256
|
import chalk6 from "chalk";
|
|
341
2257
|
import inquirer3 from "inquirer";
|
|
342
|
-
import { uploadToCloud, createCodexManager, createClaudeManager } from "@ccman/core";
|
|
343
2258
|
function uploadCommand(program2) {
|
|
344
2259
|
program2.command("upload").description("\u4E0A\u4F20\u672C\u5730\u914D\u7F6E\u5230\u4E91\u7AEF").action(async () => {
|
|
345
2260
|
try {
|
|
@@ -406,6 +2321,7 @@ function uploadCommand(program2) {
|
|
|
406
2321
|
var init_upload = __esm({
|
|
407
2322
|
"src/commands/sync/upload.ts"() {
|
|
408
2323
|
"use strict";
|
|
2324
|
+
init_dist();
|
|
409
2325
|
init_helpers();
|
|
410
2326
|
}
|
|
411
2327
|
});
|
|
@@ -417,7 +2333,6 @@ __export(download_exports, {
|
|
|
417
2333
|
});
|
|
418
2334
|
import chalk7 from "chalk";
|
|
419
2335
|
import inquirer4 from "inquirer";
|
|
420
|
-
import { downloadFromCloud } from "@ccman/core";
|
|
421
2336
|
function downloadCommand(program2) {
|
|
422
2337
|
program2.command("download").description("\u4ECE\u4E91\u7AEF\u4E0B\u8F7D\u914D\u7F6E\u5230\u672C\u5730").action(async () => {
|
|
423
2338
|
try {
|
|
@@ -464,8 +2379,8 @@ function downloadCommand(program2) {
|
|
|
464
2379
|
console.log();
|
|
465
2380
|
if (backupPaths.length > 0) {
|
|
466
2381
|
console.log(chalk7.gray("\u672C\u5730\u5907\u4EFD:"));
|
|
467
|
-
backupPaths.forEach((
|
|
468
|
-
console.log(chalk7.gray(` ${
|
|
2382
|
+
backupPaths.forEach((path12) => {
|
|
2383
|
+
console.log(chalk7.gray(` ${path12}`));
|
|
469
2384
|
});
|
|
470
2385
|
console.log();
|
|
471
2386
|
}
|
|
@@ -480,6 +2395,7 @@ function downloadCommand(program2) {
|
|
|
480
2395
|
var init_download = __esm({
|
|
481
2396
|
"src/commands/sync/download.ts"() {
|
|
482
2397
|
"use strict";
|
|
2398
|
+
init_dist();
|
|
483
2399
|
init_helpers();
|
|
484
2400
|
}
|
|
485
2401
|
});
|
|
@@ -491,7 +2407,6 @@ __export(merge_exports, {
|
|
|
491
2407
|
});
|
|
492
2408
|
import chalk8 from "chalk";
|
|
493
2409
|
import inquirer5 from "inquirer";
|
|
494
|
-
import { mergeSync } from "@ccman/core";
|
|
495
2410
|
function mergeCommand(program2) {
|
|
496
2411
|
program2.command("merge").description("\u667A\u80FD\u5408\u5E76\u672C\u5730\u548C\u4E91\u7AEF\u914D\u7F6E").action(async () => {
|
|
497
2412
|
try {
|
|
@@ -526,8 +2441,8 @@ function mergeCommand(program2) {
|
|
|
526
2441
|
console.log();
|
|
527
2442
|
if (result.backupPaths.length > 0) {
|
|
528
2443
|
console.log(chalk8.gray("\u5907\u4EFD:"));
|
|
529
|
-
result.backupPaths.forEach((
|
|
530
|
-
console.log(chalk8.gray(` ${
|
|
2444
|
+
result.backupPaths.forEach((path12) => {
|
|
2445
|
+
console.log(chalk8.gray(` ${path12}`));
|
|
531
2446
|
});
|
|
532
2447
|
console.log();
|
|
533
2448
|
}
|
|
@@ -543,9 +2458,10 @@ function mergeCommand(program2) {
|
|
|
543
2458
|
}
|
|
544
2459
|
});
|
|
545
2460
|
}
|
|
546
|
-
var
|
|
2461
|
+
var init_merge2 = __esm({
|
|
547
2462
|
"src/commands/sync/merge.ts"() {
|
|
548
2463
|
"use strict";
|
|
2464
|
+
init_dist();
|
|
549
2465
|
init_helpers();
|
|
550
2466
|
}
|
|
551
2467
|
});
|
|
@@ -556,7 +2472,6 @@ __export(status_exports, {
|
|
|
556
2472
|
statusCommand: () => statusCommand
|
|
557
2473
|
});
|
|
558
2474
|
import chalk9 from "chalk";
|
|
559
|
-
import { createCodexManager as createCodexManager2, createClaudeManager as createClaudeManager2 } from "@ccman/core";
|
|
560
2475
|
function statusCommand(program2) {
|
|
561
2476
|
program2.command("status").description("\u67E5\u770B\u540C\u6B65\u72B6\u6001").action(async () => {
|
|
562
2477
|
try {
|
|
@@ -575,8 +2490,8 @@ function statusCommand(program2) {
|
|
|
575
2490
|
console.log(` \u8BA4\u8BC1: ${chalk9.gray(config.authType === "password" ? "Basic Auth" : "Digest Auth")}`);
|
|
576
2491
|
console.log(` \u540C\u6B65\u5BC6\u7801: ${config.syncPassword ? chalk9.green("\u2713 \u5DF2\u4FDD\u5B58") : chalk9.yellow("\u2717 \u672A\u4FDD\u5B58")}`);
|
|
577
2492
|
console.log();
|
|
578
|
-
const codexManager =
|
|
579
|
-
const claudeManager =
|
|
2493
|
+
const codexManager = createCodexManager();
|
|
2494
|
+
const claudeManager = createClaudeManager();
|
|
580
2495
|
const codexProviders = codexManager.list();
|
|
581
2496
|
const claudeProviders = claudeManager.list();
|
|
582
2497
|
console.log(chalk9.bold("\u672C\u5730\u914D\u7F6E:"));
|
|
@@ -602,6 +2517,7 @@ function statusCommand(program2) {
|
|
|
602
2517
|
var init_status = __esm({
|
|
603
2518
|
"src/commands/sync/status.ts"() {
|
|
604
2519
|
"use strict";
|
|
2520
|
+
init_dist();
|
|
605
2521
|
init_sync_config();
|
|
606
2522
|
}
|
|
607
2523
|
});
|
|
@@ -648,7 +2564,7 @@ async function startSyncMenu() {
|
|
|
648
2564
|
try {
|
|
649
2565
|
switch (action) {
|
|
650
2566
|
case "config": {
|
|
651
|
-
const { configCommand: configCommand2 } = await Promise.resolve().then(() => (
|
|
2567
|
+
const { configCommand: configCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
652
2568
|
const cmd = new Command2();
|
|
653
2569
|
configCommand2(cmd);
|
|
654
2570
|
await cmd.parseAsync(["node", "ccman", "config"]);
|
|
@@ -676,7 +2592,7 @@ async function startSyncMenu() {
|
|
|
676
2592
|
break;
|
|
677
2593
|
}
|
|
678
2594
|
case "merge": {
|
|
679
|
-
const { mergeCommand: mergeCommand2 } = await Promise.resolve().then(() => (
|
|
2595
|
+
const { mergeCommand: mergeCommand2 } = await Promise.resolve().then(() => (init_merge2(), merge_exports));
|
|
680
2596
|
const cmd = new Command2();
|
|
681
2597
|
mergeCommand2(cmd);
|
|
682
2598
|
await cmd.parseAsync(["node", "ccman", "merge"]);
|
|
@@ -707,11 +2623,11 @@ async function startSyncMenu() {
|
|
|
707
2623
|
var init_sync = __esm({
|
|
708
2624
|
"src/commands/sync/index.ts"() {
|
|
709
2625
|
"use strict";
|
|
710
|
-
|
|
2626
|
+
init_config2();
|
|
711
2627
|
init_test();
|
|
712
2628
|
init_upload();
|
|
713
2629
|
init_download();
|
|
714
|
-
|
|
2630
|
+
init_merge2();
|
|
715
2631
|
init_status();
|
|
716
2632
|
}
|
|
717
2633
|
});
|
|
@@ -721,8 +2637,8 @@ import { Command as Command3 } from "commander";
|
|
|
721
2637
|
import chalk33 from "chalk";
|
|
722
2638
|
|
|
723
2639
|
// src/utils/logo.ts
|
|
2640
|
+
init_dist();
|
|
724
2641
|
import chalk from "chalk";
|
|
725
|
-
import { VERSION } from "@ccman/core";
|
|
726
2642
|
function printLogo() {
|
|
727
2643
|
console.log(
|
|
728
2644
|
chalk.bold(
|
|
@@ -742,19 +2658,14 @@ function printLogo() {
|
|
|
742
2658
|
}
|
|
743
2659
|
|
|
744
2660
|
// src/commands/codex/add.ts
|
|
2661
|
+
init_dist();
|
|
745
2662
|
import chalk12 from "chalk";
|
|
746
2663
|
import inquirer8 from "inquirer";
|
|
747
|
-
import {
|
|
748
|
-
createCodexManager as createCodexManager4,
|
|
749
|
-
CODEX_PRESETS,
|
|
750
|
-
getCodexConfigPath,
|
|
751
|
-
getCodexAuthPath
|
|
752
|
-
} from "@ccman/core";
|
|
753
2664
|
|
|
754
2665
|
// src/interactive.ts
|
|
2666
|
+
init_dist();
|
|
755
2667
|
import inquirer7 from "inquirer";
|
|
756
2668
|
import chalk11 from "chalk";
|
|
757
|
-
import { createCodexManager as createCodexManager3, createClaudeManager as createClaudeManager3 } from "@ccman/core";
|
|
758
2669
|
|
|
759
2670
|
// src/utils/format.ts
|
|
760
2671
|
import chalk2 from "chalk";
|
|
@@ -938,7 +2849,7 @@ async function showPresetsMenu() {
|
|
|
938
2849
|
console.log(chalk11.yellow("\n\u26A0\uFE0F \u9884\u7F6E\u670D\u52A1\u5546\u7BA1\u7406\u529F\u80FD\u5373\u5C06\u63A8\u51FA\n"));
|
|
939
2850
|
}
|
|
940
2851
|
async function handleAdd(tool) {
|
|
941
|
-
const manager = tool === "codex" ?
|
|
2852
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
942
2853
|
const toolName = tool === "claude" ? "Claude" : "Codex";
|
|
943
2854
|
const presets = manager.listPresets();
|
|
944
2855
|
console.log(chalk11.bold(`
|
|
@@ -1044,7 +2955,7 @@ async function handleAdd(tool) {
|
|
|
1044
2955
|
}
|
|
1045
2956
|
}
|
|
1046
2957
|
async function handleSwitch(tool) {
|
|
1047
|
-
const manager = tool === "codex" ?
|
|
2958
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1048
2959
|
const providers = manager.list();
|
|
1049
2960
|
const current = manager.getCurrent();
|
|
1050
2961
|
if (providers.length === 0) {
|
|
@@ -1069,7 +2980,7 @@ async function handleSwitch(tool) {
|
|
|
1069
2980
|
`));
|
|
1070
2981
|
}
|
|
1071
2982
|
async function handleList(tool) {
|
|
1072
|
-
const manager = tool === "codex" ?
|
|
2983
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1073
2984
|
const providers = manager.list();
|
|
1074
2985
|
const current = manager.getCurrent();
|
|
1075
2986
|
const toolName = tool === "claude" ? "Claude" : "Codex";
|
|
@@ -1084,7 +2995,7 @@ async function handleList(tool) {
|
|
|
1084
2995
|
console.log(formatProviderTable(providers, current?.id));
|
|
1085
2996
|
}
|
|
1086
2997
|
async function handleCurrent(tool) {
|
|
1087
|
-
const manager = tool === "codex" ?
|
|
2998
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1088
2999
|
const current = manager.getCurrent();
|
|
1089
3000
|
const toolName = tool === "claude" ? "Claude" : "Codex";
|
|
1090
3001
|
if (!current) {
|
|
@@ -1105,7 +3016,7 @@ async function handleCurrent(tool) {
|
|
|
1105
3016
|
console.log();
|
|
1106
3017
|
}
|
|
1107
3018
|
async function handleEdit(tool) {
|
|
1108
|
-
const manager = tool === "codex" ?
|
|
3019
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1109
3020
|
const providers = manager.list();
|
|
1110
3021
|
if (providers.length === 0) {
|
|
1111
3022
|
console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
|
|
@@ -1166,7 +3077,7 @@ async function handleEdit(tool) {
|
|
|
1166
3077
|
console.log(chalk11.green("\n\u2705 \u7F16\u8F91\u6210\u529F\n"));
|
|
1167
3078
|
}
|
|
1168
3079
|
async function handleClone(tool) {
|
|
1169
|
-
const manager = tool === "codex" ?
|
|
3080
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1170
3081
|
const providers = manager.list();
|
|
1171
3082
|
if (providers.length === 0) {
|
|
1172
3083
|
console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
|
|
@@ -1213,7 +3124,7 @@ async function handleClone(tool) {
|
|
|
1213
3124
|
console.log();
|
|
1214
3125
|
}
|
|
1215
3126
|
async function handleRemove(tool) {
|
|
1216
|
-
const manager = tool === "codex" ?
|
|
3127
|
+
const manager = tool === "codex" ? createCodexManager() : createClaudeManager();
|
|
1217
3128
|
const providers = manager.list();
|
|
1218
3129
|
if (providers.length === 0) {
|
|
1219
3130
|
console.log(chalk11.yellow("\n\u26A0\uFE0F \u6682\u65E0\u670D\u52A1\u5546\n"));
|
|
@@ -1253,7 +3164,7 @@ async function handleRemove(tool) {
|
|
|
1253
3164
|
function addCommand(program2) {
|
|
1254
3165
|
program2.command("add").description("\u6DFB\u52A0\u65B0\u7684 Codex \u670D\u52A1\u5546(\u4EA4\u4E92\u5F0F)").action(async () => {
|
|
1255
3166
|
try {
|
|
1256
|
-
const manager =
|
|
3167
|
+
const manager = createCodexManager();
|
|
1257
3168
|
console.log(chalk12.bold("\n\u{1F4DD} \u6DFB\u52A0 Codex \u670D\u52A1\u5546\n"));
|
|
1258
3169
|
const { usePreset } = await inquirer8.prompt([
|
|
1259
3170
|
{
|
|
@@ -1370,12 +3281,12 @@ function addCommand(program2) {
|
|
|
1370
3281
|
}
|
|
1371
3282
|
|
|
1372
3283
|
// src/commands/codex/list.ts
|
|
3284
|
+
init_dist();
|
|
1373
3285
|
import chalk13 from "chalk";
|
|
1374
|
-
import { createCodexManager as createCodexManager5 } from "@ccman/core";
|
|
1375
3286
|
function listCommand(program2) {
|
|
1376
3287
|
program2.command("list").alias("ls").description("\u5217\u51FA\u6240\u6709 Codex \u670D\u52A1\u5546").action(async () => {
|
|
1377
3288
|
try {
|
|
1378
|
-
const manager =
|
|
3289
|
+
const manager = createCodexManager();
|
|
1379
3290
|
const providers = manager.list();
|
|
1380
3291
|
const current = manager.getCurrent();
|
|
1381
3292
|
if (providers.length === 0) {
|
|
@@ -1396,18 +3307,13 @@ function listCommand(program2) {
|
|
|
1396
3307
|
}
|
|
1397
3308
|
|
|
1398
3309
|
// src/commands/codex/use.ts
|
|
3310
|
+
init_dist();
|
|
1399
3311
|
import chalk14 from "chalk";
|
|
1400
3312
|
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
3313
|
function useCommand(program2) {
|
|
1408
3314
|
program2.command("use [name]").description("\u5207\u6362 Codex \u670D\u52A1\u5546").action(async (name) => {
|
|
1409
3315
|
try {
|
|
1410
|
-
const manager =
|
|
3316
|
+
const manager = createCodexManager();
|
|
1411
3317
|
const providers = manager.list();
|
|
1412
3318
|
if (providers.length === 0) {
|
|
1413
3319
|
console.log(chalk14.yellow("\n\u26A0\uFE0F \u6682\u65E0 Codex \u670D\u52A1\u5546\n"));
|
|
@@ -1444,8 +3350,8 @@ function useCommand(program2) {
|
|
|
1444
3350
|
console.log(` ${chalk14.gray(`URL: ${provider.baseUrl}`)}`);
|
|
1445
3351
|
console.log();
|
|
1446
3352
|
console.log(chalk14.gray("\u914D\u7F6E\u5DF2\u66F4\u65B0:"));
|
|
1447
|
-
console.log(chalk14.gray(` - ${
|
|
1448
|
-
console.log(chalk14.gray(` - ${
|
|
3353
|
+
console.log(chalk14.gray(` - ${getCodexConfigPath()}`));
|
|
3354
|
+
console.log(chalk14.gray(` - ${getCodexAuthPath()}`));
|
|
1449
3355
|
console.log();
|
|
1450
3356
|
} catch (error) {
|
|
1451
3357
|
if (error instanceof ProviderNotFoundError) {
|
|
@@ -1464,12 +3370,12 @@ function useCommand(program2) {
|
|
|
1464
3370
|
}
|
|
1465
3371
|
|
|
1466
3372
|
// src/commands/codex/current.ts
|
|
3373
|
+
init_dist();
|
|
1467
3374
|
import chalk15 from "chalk";
|
|
1468
|
-
import { createCodexManager as createCodexManager7 } from "@ccman/core";
|
|
1469
3375
|
function currentCommand(program2) {
|
|
1470
3376
|
program2.command("current").description("\u663E\u793A\u5F53\u524D\u4F7F\u7528\u7684 Codex \u670D\u52A1\u5546").action(async () => {
|
|
1471
3377
|
try {
|
|
1472
|
-
const manager =
|
|
3378
|
+
const manager = createCodexManager();
|
|
1473
3379
|
const current = manager.getCurrent();
|
|
1474
3380
|
if (!current) {
|
|
1475
3381
|
console.log(chalk15.yellow("\n\u26A0\uFE0F \u672A\u9009\u62E9\u4EFB\u4F55 Codex \u670D\u52A1\u5546\n"));
|
|
@@ -1495,13 +3401,13 @@ function currentCommand(program2) {
|
|
|
1495
3401
|
}
|
|
1496
3402
|
|
|
1497
3403
|
// src/commands/codex/remove.ts
|
|
3404
|
+
init_dist();
|
|
1498
3405
|
import chalk16 from "chalk";
|
|
1499
3406
|
import inquirer10 from "inquirer";
|
|
1500
|
-
import { createCodexManager as createCodexManager8, ProviderNotFoundError as ProviderNotFoundError2 } from "@ccman/core";
|
|
1501
3407
|
function removeCommand(program2) {
|
|
1502
3408
|
program2.command("remove [name]").alias("rm").description("\u5220\u9664 Codex \u670D\u52A1\u5546").action(async (name) => {
|
|
1503
3409
|
try {
|
|
1504
|
-
const manager =
|
|
3410
|
+
const manager = createCodexManager();
|
|
1505
3411
|
const providers = manager.list();
|
|
1506
3412
|
if (providers.length === 0) {
|
|
1507
3413
|
console.log(chalk16.yellow("\n\u26A0\uFE0F \u6682\u65E0 Codex \u670D\u52A1\u5546\n"));
|
|
@@ -1512,7 +3418,7 @@ function removeCommand(program2) {
|
|
|
1512
3418
|
if (name) {
|
|
1513
3419
|
const provider = manager.findByName(name);
|
|
1514
3420
|
if (!provider) {
|
|
1515
|
-
throw new
|
|
3421
|
+
throw new ProviderNotFoundError(name);
|
|
1516
3422
|
}
|
|
1517
3423
|
targetId = provider.id;
|
|
1518
3424
|
targetName = provider.name;
|
|
@@ -1549,7 +3455,7 @@ function removeCommand(program2) {
|
|
|
1549
3455
|
console.log(chalk16.green(`\u2705 \u5DF2\u5220\u9664: ${targetName}`));
|
|
1550
3456
|
console.log();
|
|
1551
3457
|
} catch (error) {
|
|
1552
|
-
if (error instanceof
|
|
3458
|
+
if (error instanceof ProviderNotFoundError) {
|
|
1553
3459
|
console.error(chalk16.red(`
|
|
1554
3460
|
\u274C \u670D\u52A1\u5546\u4E0D\u5B58\u5728
|
|
1555
3461
|
`));
|
|
@@ -1565,13 +3471,13 @@ function removeCommand(program2) {
|
|
|
1565
3471
|
}
|
|
1566
3472
|
|
|
1567
3473
|
// src/commands/codex/edit.ts
|
|
3474
|
+
init_dist();
|
|
1568
3475
|
import chalk17 from "chalk";
|
|
1569
3476
|
import inquirer11 from "inquirer";
|
|
1570
|
-
import { createCodexManager as createCodexManager9, ProviderNotFoundError as ProviderNotFoundError3 } from "@ccman/core";
|
|
1571
3477
|
function editCommand(program2) {
|
|
1572
3478
|
program2.command("edit [name]").description("\u7F16\u8F91 Codex \u670D\u52A1\u5546").action(async (name) => {
|
|
1573
3479
|
try {
|
|
1574
|
-
const manager =
|
|
3480
|
+
const manager = createCodexManager();
|
|
1575
3481
|
const providers = manager.list();
|
|
1576
3482
|
if (providers.length === 0) {
|
|
1577
3483
|
console.log(chalk17.yellow("\n\u26A0\uFE0F \u6682\u65E0 Codex \u670D\u52A1\u5546\n"));
|
|
@@ -1581,7 +3487,7 @@ function editCommand(program2) {
|
|
|
1581
3487
|
if (name) {
|
|
1582
3488
|
const provider2 = manager.findByName(name);
|
|
1583
3489
|
if (!provider2) {
|
|
1584
|
-
throw new
|
|
3490
|
+
throw new ProviderNotFoundError(name);
|
|
1585
3491
|
}
|
|
1586
3492
|
targetId = provider2.id;
|
|
1587
3493
|
} else {
|
|
@@ -1653,13 +3559,13 @@ function editCommand(program2) {
|
|
|
1653
3559
|
}
|
|
1654
3560
|
|
|
1655
3561
|
// src/commands/codex/clone.ts
|
|
3562
|
+
init_dist();
|
|
1656
3563
|
import chalk18 from "chalk";
|
|
1657
3564
|
import inquirer12 from "inquirer";
|
|
1658
|
-
import { createCodexManager as createCodexManager10, ProviderNotFoundError as ProviderNotFoundError4 } from "@ccman/core";
|
|
1659
3565
|
function cloneCommand(program2) {
|
|
1660
3566
|
program2.command("clone [source-name] [new-name]").description("\u514B\u9686 Codex \u670D\u52A1\u5546").action(async (sourceName, newName) => {
|
|
1661
3567
|
try {
|
|
1662
|
-
const manager =
|
|
3568
|
+
const manager = createCodexManager();
|
|
1663
3569
|
const providers = manager.list();
|
|
1664
3570
|
if (providers.length === 0) {
|
|
1665
3571
|
console.log(chalk18.yellow("\n\u26A0\uFE0F \u6682\u65E0 Codex \u670D\u52A1\u5546\n"));
|
|
@@ -1669,7 +3575,7 @@ function cloneCommand(program2) {
|
|
|
1669
3575
|
if (sourceName) {
|
|
1670
3576
|
const provider = manager.findByName(sourceName);
|
|
1671
3577
|
if (!provider) {
|
|
1672
|
-
throw new
|
|
3578
|
+
throw new ProviderNotFoundError(sourceName);
|
|
1673
3579
|
}
|
|
1674
3580
|
sourceId = provider.id;
|
|
1675
3581
|
} else {
|
|
@@ -1731,17 +3637,13 @@ function createCodexCommands(program2) {
|
|
|
1731
3637
|
}
|
|
1732
3638
|
|
|
1733
3639
|
// src/commands/claude/add.ts
|
|
3640
|
+
init_dist();
|
|
1734
3641
|
import chalk19 from "chalk";
|
|
1735
3642
|
import inquirer13 from "inquirer";
|
|
1736
|
-
import {
|
|
1737
|
-
createClaudeManager as createClaudeManager4,
|
|
1738
|
-
CC_PRESETS,
|
|
1739
|
-
getClaudeConfigPath
|
|
1740
|
-
} from "@ccman/core";
|
|
1741
3643
|
function addCommand2(program2) {
|
|
1742
3644
|
program2.command("add").description("\u6DFB\u52A0\u65B0\u7684 Claude Code \u670D\u52A1\u5546(\u4EA4\u4E92\u5F0F)").action(async () => {
|
|
1743
3645
|
try {
|
|
1744
|
-
const manager =
|
|
3646
|
+
const manager = createClaudeManager();
|
|
1745
3647
|
console.log(chalk19.bold("\n\u{1F4DD} \u6DFB\u52A0 Claude Code \u670D\u52A1\u5546\n"));
|
|
1746
3648
|
const { usePreset } = await inquirer13.prompt([
|
|
1747
3649
|
{
|
|
@@ -1857,12 +3759,12 @@ function addCommand2(program2) {
|
|
|
1857
3759
|
}
|
|
1858
3760
|
|
|
1859
3761
|
// src/commands/claude/list.ts
|
|
3762
|
+
init_dist();
|
|
1860
3763
|
import chalk20 from "chalk";
|
|
1861
|
-
import { createClaudeManager as createClaudeManager5 } from "@ccman/core";
|
|
1862
3764
|
function listCommand2(program2) {
|
|
1863
3765
|
program2.command("list").alias("ls").description("\u5217\u51FA\u6240\u6709 Claude Code \u670D\u52A1\u5546").action(async () => {
|
|
1864
3766
|
try {
|
|
1865
|
-
const manager =
|
|
3767
|
+
const manager = createClaudeManager();
|
|
1866
3768
|
const providers = manager.list();
|
|
1867
3769
|
const current = manager.getCurrent();
|
|
1868
3770
|
if (providers.length === 0) {
|
|
@@ -1883,17 +3785,13 @@ function listCommand2(program2) {
|
|
|
1883
3785
|
}
|
|
1884
3786
|
|
|
1885
3787
|
// src/commands/claude/use.ts
|
|
3788
|
+
init_dist();
|
|
1886
3789
|
import chalk21 from "chalk";
|
|
1887
3790
|
import inquirer14 from "inquirer";
|
|
1888
|
-
import {
|
|
1889
|
-
createClaudeManager as createClaudeManager6,
|
|
1890
|
-
ProviderNotFoundError as ProviderNotFoundError5,
|
|
1891
|
-
getClaudeConfigPath as getClaudeConfigPath2
|
|
1892
|
-
} from "@ccman/core";
|
|
1893
3791
|
function useCommand2(program2) {
|
|
1894
3792
|
program2.command("use [name]").description("\u5207\u6362 Claude Code \u670D\u52A1\u5546").action(async (name) => {
|
|
1895
3793
|
try {
|
|
1896
|
-
const manager =
|
|
3794
|
+
const manager = createClaudeManager();
|
|
1897
3795
|
const providers = manager.list();
|
|
1898
3796
|
if (providers.length === 0) {
|
|
1899
3797
|
console.log(chalk21.yellow("\n\u26A0\uFE0F \u6682\u65E0 Claude Code \u670D\u52A1\u5546\n"));
|
|
@@ -1904,7 +3802,7 @@ function useCommand2(program2) {
|
|
|
1904
3802
|
if (name) {
|
|
1905
3803
|
const provider2 = manager.findByName(name);
|
|
1906
3804
|
if (!provider2) {
|
|
1907
|
-
throw new
|
|
3805
|
+
throw new ProviderNotFoundError(name);
|
|
1908
3806
|
}
|
|
1909
3807
|
targetId = provider2.id;
|
|
1910
3808
|
} else {
|
|
@@ -1930,10 +3828,10 @@ function useCommand2(program2) {
|
|
|
1930
3828
|
console.log(` ${chalk21.gray(`URL: ${provider.baseUrl}`)}`);
|
|
1931
3829
|
console.log();
|
|
1932
3830
|
console.log(chalk21.gray("\u914D\u7F6E\u5DF2\u66F4\u65B0:"));
|
|
1933
|
-
console.log(chalk21.gray(` - ${
|
|
3831
|
+
console.log(chalk21.gray(` - ${getClaudeConfigPath()}`));
|
|
1934
3832
|
console.log();
|
|
1935
3833
|
} catch (error) {
|
|
1936
|
-
if (error instanceof
|
|
3834
|
+
if (error instanceof ProviderNotFoundError) {
|
|
1937
3835
|
console.error(chalk21.red(`
|
|
1938
3836
|
\u274C \u670D\u52A1\u5546\u4E0D\u5B58\u5728: ${error.message}
|
|
1939
3837
|
`));
|
|
@@ -1949,12 +3847,12 @@ function useCommand2(program2) {
|
|
|
1949
3847
|
}
|
|
1950
3848
|
|
|
1951
3849
|
// src/commands/claude/current.ts
|
|
3850
|
+
init_dist();
|
|
1952
3851
|
import chalk22 from "chalk";
|
|
1953
|
-
import { createClaudeManager as createClaudeManager7 } from "@ccman/core";
|
|
1954
3852
|
function currentCommand2(program2) {
|
|
1955
3853
|
program2.command("current").description("\u663E\u793A\u5F53\u524D\u4F7F\u7528\u7684 Claude Code \u670D\u52A1\u5546").action(async () => {
|
|
1956
3854
|
try {
|
|
1957
|
-
const manager =
|
|
3855
|
+
const manager = createClaudeManager();
|
|
1958
3856
|
const current = manager.getCurrent();
|
|
1959
3857
|
if (!current) {
|
|
1960
3858
|
console.log(chalk22.yellow("\n\u26A0\uFE0F \u672A\u9009\u62E9\u4EFB\u4F55 Claude Code \u670D\u52A1\u5546\n"));
|
|
@@ -1980,13 +3878,13 @@ function currentCommand2(program2) {
|
|
|
1980
3878
|
}
|
|
1981
3879
|
|
|
1982
3880
|
// src/commands/claude/remove.ts
|
|
3881
|
+
init_dist();
|
|
1983
3882
|
import chalk23 from "chalk";
|
|
1984
3883
|
import inquirer15 from "inquirer";
|
|
1985
|
-
import { createClaudeManager as createClaudeManager8, ProviderNotFoundError as ProviderNotFoundError6 } from "@ccman/core";
|
|
1986
3884
|
function removeCommand2(program2) {
|
|
1987
3885
|
program2.command("remove [name]").alias("rm").description("\u5220\u9664 Claude Code \u670D\u52A1\u5546").action(async (name) => {
|
|
1988
3886
|
try {
|
|
1989
|
-
const manager =
|
|
3887
|
+
const manager = createClaudeManager();
|
|
1990
3888
|
const providers = manager.list();
|
|
1991
3889
|
if (providers.length === 0) {
|
|
1992
3890
|
console.log(chalk23.yellow("\n\u26A0\uFE0F \u6682\u65E0 Claude Code \u670D\u52A1\u5546\n"));
|
|
@@ -1997,7 +3895,7 @@ function removeCommand2(program2) {
|
|
|
1997
3895
|
if (name) {
|
|
1998
3896
|
const provider = manager.findByName(name);
|
|
1999
3897
|
if (!provider) {
|
|
2000
|
-
throw new
|
|
3898
|
+
throw new ProviderNotFoundError(name);
|
|
2001
3899
|
}
|
|
2002
3900
|
targetId = provider.id;
|
|
2003
3901
|
targetName = provider.name;
|
|
@@ -2034,7 +3932,7 @@ function removeCommand2(program2) {
|
|
|
2034
3932
|
console.log(chalk23.green(`\u2705 \u5DF2\u5220\u9664: ${targetName}`));
|
|
2035
3933
|
console.log();
|
|
2036
3934
|
} catch (error) {
|
|
2037
|
-
if (error instanceof
|
|
3935
|
+
if (error instanceof ProviderNotFoundError) {
|
|
2038
3936
|
console.error(chalk23.red(`
|
|
2039
3937
|
\u274C \u670D\u52A1\u5546\u4E0D\u5B58\u5728
|
|
2040
3938
|
`));
|
|
@@ -2050,13 +3948,13 @@ function removeCommand2(program2) {
|
|
|
2050
3948
|
}
|
|
2051
3949
|
|
|
2052
3950
|
// src/commands/claude/edit.ts
|
|
3951
|
+
init_dist();
|
|
2053
3952
|
import chalk24 from "chalk";
|
|
2054
3953
|
import inquirer16 from "inquirer";
|
|
2055
|
-
import { createClaudeManager as createClaudeManager9, ProviderNotFoundError as ProviderNotFoundError7 } from "@ccman/core";
|
|
2056
3954
|
function editCommand2(program2) {
|
|
2057
3955
|
program2.command("edit [name]").description("\u7F16\u8F91 Claude Code \u670D\u52A1\u5546").action(async (name) => {
|
|
2058
3956
|
try {
|
|
2059
|
-
const manager =
|
|
3957
|
+
const manager = createClaudeManager();
|
|
2060
3958
|
const providers = manager.list();
|
|
2061
3959
|
if (providers.length === 0) {
|
|
2062
3960
|
console.log(chalk24.yellow("\n\u26A0\uFE0F \u6682\u65E0 Claude Code \u670D\u52A1\u5546\n"));
|
|
@@ -2066,7 +3964,7 @@ function editCommand2(program2) {
|
|
|
2066
3964
|
if (name) {
|
|
2067
3965
|
const provider2 = manager.findByName(name);
|
|
2068
3966
|
if (!provider2) {
|
|
2069
|
-
throw new
|
|
3967
|
+
throw new ProviderNotFoundError(name);
|
|
2070
3968
|
}
|
|
2071
3969
|
targetId = provider2.id;
|
|
2072
3970
|
} else {
|
|
@@ -2138,13 +4036,13 @@ function editCommand2(program2) {
|
|
|
2138
4036
|
}
|
|
2139
4037
|
|
|
2140
4038
|
// src/commands/claude/clone.ts
|
|
4039
|
+
init_dist();
|
|
2141
4040
|
import chalk25 from "chalk";
|
|
2142
4041
|
import inquirer17 from "inquirer";
|
|
2143
|
-
import { createClaudeManager as createClaudeManager10, ProviderNotFoundError as ProviderNotFoundError8 } from "@ccman/core";
|
|
2144
4042
|
function cloneCommand2(program2) {
|
|
2145
4043
|
program2.command("clone [source-name] [new-name]").description("\u514B\u9686 Claude Code \u670D\u52A1\u5546").action(async (sourceName, newName) => {
|
|
2146
4044
|
try {
|
|
2147
|
-
const manager =
|
|
4045
|
+
const manager = createClaudeManager();
|
|
2148
4046
|
const providers = manager.list();
|
|
2149
4047
|
if (providers.length === 0) {
|
|
2150
4048
|
console.log(chalk25.yellow("\n\u26A0\uFE0F \u6682\u65E0 Claude Code \u670D\u52A1\u5546\n"));
|
|
@@ -2154,7 +4052,7 @@ function cloneCommand2(program2) {
|
|
|
2154
4052
|
if (sourceName) {
|
|
2155
4053
|
const provider = manager.findByName(sourceName);
|
|
2156
4054
|
if (!provider) {
|
|
2157
|
-
throw new
|
|
4055
|
+
throw new ProviderNotFoundError(sourceName);
|
|
2158
4056
|
}
|
|
2159
4057
|
sourceId = provider.id;
|
|
2160
4058
|
} else {
|
|
@@ -2205,10 +4103,10 @@ function cloneCommand2(program2) {
|
|
|
2205
4103
|
}
|
|
2206
4104
|
|
|
2207
4105
|
// src/commands/clean.ts
|
|
4106
|
+
init_dist();
|
|
2208
4107
|
import chalk26 from "chalk";
|
|
2209
4108
|
import inquirer18 from "inquirer";
|
|
2210
|
-
|
|
2211
|
-
function formatBytes(bytes) {
|
|
4109
|
+
function formatBytes2(bytes) {
|
|
2212
4110
|
if (bytes < 1024) return `${bytes} B`;
|
|
2213
4111
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
2214
4112
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
@@ -2231,9 +4129,9 @@ function displayAnalysis() {
|
|
|
2231
4129
|
}
|
|
2232
4130
|
console.log();
|
|
2233
4131
|
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(
|
|
4132
|
+
console.log(` ${chalk26.green("\u4FDD\u5B88\u6E05\u7406")} (\u4FDD\u755910\u6761): ${chalk26.bold(formatBytes2(analysis.estimatedSavings.conservative))}`);
|
|
4133
|
+
console.log(` ${chalk26.yellow("\u4E2D\u7B49\u6E05\u7406")} (\u4FDD\u75595\u6761): ${chalk26.bold(formatBytes2(analysis.estimatedSavings.moderate))}`);
|
|
4134
|
+
console.log(` ${chalk26.red("\u6FC0\u8FDB\u6E05\u7406")} (\u6E05\u7A7A\u5386\u53F2): ${chalk26.bold(formatBytes2(analysis.estimatedSavings.aggressive))}`);
|
|
2237
4135
|
console.log();
|
|
2238
4136
|
console.log(chalk26.blue(`\u{1F4A1} \u6267\u884C\u6E05\u7406: ccman cc clean
|
|
2239
4137
|
`));
|
|
@@ -2278,9 +4176,9 @@ function cleanCommand(program2) {
|
|
|
2278
4176
|
console.log(chalk26.cyan("\n\u6B63\u5728\u6E05\u7406...\n"));
|
|
2279
4177
|
const result = cleanClaudeJson(cleanOptions);
|
|
2280
4178
|
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(
|
|
4179
|
+
console.log(`\u6E05\u7406\u524D: ${chalk26.bold(formatBytes2(result.sizeBefore))}`);
|
|
4180
|
+
console.log(`\u6E05\u7406\u540E: ${chalk26.bold(formatBytes2(result.sizeAfter))}`);
|
|
4181
|
+
console.log(`\u8282\u7701\u7A7A\u95F4: ${chalk26.green.bold(formatBytes2(result.saved))} (${(result.saved / result.sizeBefore * 100).toFixed(1)}%)`);
|
|
2284
4182
|
console.log();
|
|
2285
4183
|
if (result.cleanedItems.projectHistory > 0) {
|
|
2286
4184
|
console.log(`\u6E05\u7406\u5386\u53F2\u8BB0\u5F55: ${chalk26.bold(result.cleanedItems.projectHistory)} \u6761`);
|
|
@@ -2346,15 +4244,15 @@ async function promptForOptions(analysis) {
|
|
|
2346
4244
|
message: "\u9009\u62E9\u6E05\u7406\u65B9\u6848:",
|
|
2347
4245
|
choices: [
|
|
2348
4246
|
{
|
|
2349
|
-
name: `${chalk26.green("\u4FDD\u5B88\u6E05\u7406")} - \u4FDD\u7559\u6700\u8FD110\u6761\u8BB0\u5F55\uFF0C\u6E05\u7406\u7F13\u5B58 (\u8282\u7701\u7EA6 ${
|
|
4247
|
+
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
4248
|
value: "conservative"
|
|
2351
4249
|
},
|
|
2352
4250
|
{
|
|
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 ${
|
|
4251
|
+
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
4252
|
value: "moderate"
|
|
2355
4253
|
},
|
|
2356
4254
|
{
|
|
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 ${
|
|
4255
|
+
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
4256
|
value: "aggressive"
|
|
2359
4257
|
},
|
|
2360
4258
|
{
|
|
@@ -2422,9 +4320,9 @@ function createClaudeCommands(program2) {
|
|
|
2422
4320
|
}
|
|
2423
4321
|
|
|
2424
4322
|
// src/commands/mcp/add.ts
|
|
4323
|
+
init_dist();
|
|
2425
4324
|
import chalk27 from "chalk";
|
|
2426
4325
|
import inquirer19 from "inquirer";
|
|
2427
|
-
import { createMCPManager, MCP_PRESETS_DETAIL, getClaudeConfigPath as getClaudeConfigPath3 } from "@ccman/core";
|
|
2428
4326
|
function addCommand3(program2) {
|
|
2429
4327
|
program2.command("add").description("\u6DFB\u52A0\u65B0\u7684 MCP \u670D\u52A1\u5668(\u4EA4\u4E92\u5F0F)").action(async () => {
|
|
2430
4328
|
try {
|
|
@@ -2571,7 +4469,7 @@ function addCommand3(program2) {
|
|
|
2571
4469
|
console.log(chalk27.green("\u2705 \u914D\u7F6E\u5DF2\u81EA\u52A8\u540C\u6B65\u5230 ~/.claude.json"));
|
|
2572
4470
|
console.log();
|
|
2573
4471
|
console.log(chalk27.gray("\u914D\u7F6E\u6587\u4EF6:"));
|
|
2574
|
-
console.log(chalk27.gray(` - ${
|
|
4472
|
+
console.log(chalk27.gray(` - ${getClaudeConfigPath()}`));
|
|
2575
4473
|
console.log();
|
|
2576
4474
|
} catch (error) {
|
|
2577
4475
|
console.error(chalk27.red(`
|
|
@@ -2583,12 +4481,12 @@ function addCommand3(program2) {
|
|
|
2583
4481
|
}
|
|
2584
4482
|
|
|
2585
4483
|
// src/commands/mcp/list.ts
|
|
4484
|
+
init_dist();
|
|
2586
4485
|
import chalk28 from "chalk";
|
|
2587
|
-
import { createMCPManager as createMCPManager2 } from "@ccman/core";
|
|
2588
4486
|
function listCommand3(program2) {
|
|
2589
4487
|
program2.command("list").alias("ls").description("\u5217\u51FA\u6240\u6709 MCP \u670D\u52A1\u5668").action(async () => {
|
|
2590
4488
|
try {
|
|
2591
|
-
const manager =
|
|
4489
|
+
const manager = createMCPManager();
|
|
2592
4490
|
const providers = manager.list();
|
|
2593
4491
|
if (providers.length === 0) {
|
|
2594
4492
|
console.log(chalk28.yellow("\n\u26A0\uFE0F \u6682\u65E0 MCP \u670D\u52A1\u5668\n"));
|
|
@@ -2629,13 +4527,13 @@ function listCommand3(program2) {
|
|
|
2629
4527
|
}
|
|
2630
4528
|
|
|
2631
4529
|
// src/commands/mcp/remove.ts
|
|
4530
|
+
init_dist();
|
|
2632
4531
|
import chalk29 from "chalk";
|
|
2633
4532
|
import inquirer20 from "inquirer";
|
|
2634
|
-
import { createMCPManager as createMCPManager3, ProviderNotFoundError as ProviderNotFoundError9, getClaudeConfigPath as getClaudeConfigPath4 } from "@ccman/core";
|
|
2635
4533
|
function removeCommand3(program2) {
|
|
2636
4534
|
program2.command("remove [name]").alias("rm").description("\u5220\u9664 MCP \u670D\u52A1\u5668").action(async (name) => {
|
|
2637
4535
|
try {
|
|
2638
|
-
const manager =
|
|
4536
|
+
const manager = createMCPManager();
|
|
2639
4537
|
const providers = manager.list();
|
|
2640
4538
|
if (providers.length === 0) {
|
|
2641
4539
|
console.log(chalk29.yellow("\n\u26A0\uFE0F \u6682\u65E0 MCP \u670D\u52A1\u5668\n"));
|
|
@@ -2646,7 +4544,7 @@ function removeCommand3(program2) {
|
|
|
2646
4544
|
if (name) {
|
|
2647
4545
|
const provider = manager.findByName(name);
|
|
2648
4546
|
if (!provider) {
|
|
2649
|
-
throw new
|
|
4547
|
+
throw new ProviderNotFoundError(name);
|
|
2650
4548
|
}
|
|
2651
4549
|
targetId = provider.id;
|
|
2652
4550
|
targetName = provider.name;
|
|
@@ -2685,10 +4583,10 @@ function removeCommand3(program2) {
|
|
|
2685
4583
|
console.log(chalk29.green("\u2705 \u914D\u7F6E\u5DF2\u81EA\u52A8\u540C\u6B65\u5230 ~/.claude.json"));
|
|
2686
4584
|
console.log();
|
|
2687
4585
|
console.log(chalk29.gray("\u914D\u7F6E\u6587\u4EF6:"));
|
|
2688
|
-
console.log(chalk29.gray(` - ${
|
|
4586
|
+
console.log(chalk29.gray(` - ${getClaudeConfigPath()}`));
|
|
2689
4587
|
console.log();
|
|
2690
4588
|
} catch (error) {
|
|
2691
|
-
if (error instanceof
|
|
4589
|
+
if (error instanceof ProviderNotFoundError) {
|
|
2692
4590
|
console.error(chalk29.red(`
|
|
2693
4591
|
\u274C MCP \u670D\u52A1\u5668\u4E0D\u5B58\u5728
|
|
2694
4592
|
`));
|
|
@@ -2704,13 +4602,13 @@ function removeCommand3(program2) {
|
|
|
2704
4602
|
}
|
|
2705
4603
|
|
|
2706
4604
|
// src/commands/mcp/edit.ts
|
|
4605
|
+
init_dist();
|
|
2707
4606
|
import chalk30 from "chalk";
|
|
2708
4607
|
import inquirer21 from "inquirer";
|
|
2709
|
-
import { createMCPManager as createMCPManager4, ProviderNotFoundError as ProviderNotFoundError10, getClaudeConfigPath as getClaudeConfigPath5 } from "@ccman/core";
|
|
2710
4608
|
function editCommand3(program2) {
|
|
2711
4609
|
program2.command("edit [name]").description("\u7F16\u8F91 MCP \u670D\u52A1\u5668").action(async (name) => {
|
|
2712
4610
|
try {
|
|
2713
|
-
const manager =
|
|
4611
|
+
const manager = createMCPManager();
|
|
2714
4612
|
const providers = manager.list();
|
|
2715
4613
|
if (providers.length === 0) {
|
|
2716
4614
|
console.log(chalk30.yellow("\n\u26A0\uFE0F \u6682\u65E0 MCP \u670D\u52A1\u5668\n"));
|
|
@@ -2720,7 +4618,7 @@ function editCommand3(program2) {
|
|
|
2720
4618
|
if (name) {
|
|
2721
4619
|
const provider2 = manager.findByName(name);
|
|
2722
4620
|
if (!provider2) {
|
|
2723
|
-
throw new
|
|
4621
|
+
throw new ProviderNotFoundError(name);
|
|
2724
4622
|
}
|
|
2725
4623
|
targetId = provider2.id;
|
|
2726
4624
|
} else {
|
|
@@ -2803,7 +4701,7 @@ function editCommand3(program2) {
|
|
|
2803
4701
|
console.log(chalk30.green("\u2705 \u914D\u7F6E\u5DF2\u81EA\u52A8\u540C\u6B65\u5230 ~/.claude.json"));
|
|
2804
4702
|
console.log();
|
|
2805
4703
|
console.log(chalk30.gray("\u914D\u7F6E\u6587\u4EF6:"));
|
|
2806
|
-
console.log(chalk30.gray(` - ${
|
|
4704
|
+
console.log(chalk30.gray(` - ${getClaudeConfigPath()}`));
|
|
2807
4705
|
console.log();
|
|
2808
4706
|
} catch (error) {
|
|
2809
4707
|
console.error(chalk30.red(`
|
|
@@ -2826,9 +4724,9 @@ function createMCPCommands(program2) {
|
|
|
2826
4724
|
init_sync();
|
|
2827
4725
|
|
|
2828
4726
|
// src/commands/export.ts
|
|
4727
|
+
init_dist();
|
|
2829
4728
|
import chalk31 from "chalk";
|
|
2830
|
-
import
|
|
2831
|
-
import { exportConfig, validateExport } from "@ccman/core";
|
|
4729
|
+
import path10 from "path";
|
|
2832
4730
|
function exportCommand(program2) {
|
|
2833
4731
|
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
4732
|
try {
|
|
@@ -2839,7 +4737,7 @@ function exportCommand(program2) {
|
|
|
2839
4737
|
`));
|
|
2840
4738
|
process.exit(1);
|
|
2841
4739
|
}
|
|
2842
|
-
const resolvedPath = targetDir.startsWith("~") ?
|
|
4740
|
+
const resolvedPath = targetDir.startsWith("~") ? path10.join(process.env.HOME || "", targetDir.slice(1)) : path10.resolve(targetDir);
|
|
2843
4741
|
console.log("\u5BFC\u51FA\u6587\u4EF6:");
|
|
2844
4742
|
console.log(` ${chalk31.cyan("codex.json")} - Codex \u914D\u7F6E`);
|
|
2845
4743
|
console.log(` ${chalk31.cyan("claude.json")} - Claude \u914D\u7F6E`);
|
|
@@ -2868,14 +4766,14 @@ function exportCommand(program2) {
|
|
|
2868
4766
|
}
|
|
2869
4767
|
|
|
2870
4768
|
// src/commands/import.ts
|
|
4769
|
+
init_dist();
|
|
2871
4770
|
import chalk32 from "chalk";
|
|
2872
4771
|
import inquirer22 from "inquirer";
|
|
2873
|
-
import
|
|
2874
|
-
import { importConfig, validateImportDir } from "@ccman/core";
|
|
4772
|
+
import path11 from "path";
|
|
2875
4773
|
function importCommand(program2) {
|
|
2876
4774
|
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
4775
|
try {
|
|
2878
|
-
const resolvedPath = sourceDir.startsWith("~") ?
|
|
4776
|
+
const resolvedPath = sourceDir.startsWith("~") ? path11.join(process.env.HOME || "", sourceDir.slice(1)) : path11.resolve(sourceDir);
|
|
2879
4777
|
console.log(chalk32.bold("\n\u{1F4E5} \u5BFC\u5165\u914D\u7F6E\n"));
|
|
2880
4778
|
const validation = validateImportDir(resolvedPath);
|
|
2881
4779
|
if (!validation.valid) {
|
|
@@ -2950,7 +4848,7 @@ function importCommand(program2) {
|
|
|
2950
4848
|
}
|
|
2951
4849
|
|
|
2952
4850
|
// src/index.ts
|
|
2953
|
-
|
|
4851
|
+
init_dist();
|
|
2954
4852
|
if (process.env.NODE_ENV === "development") {
|
|
2955
4853
|
console.log(chalk33.gray("\n[\u5F00\u53D1\u6A21\u5F0F] \u914D\u7F6E\u76EE\u5F55:"));
|
|
2956
4854
|
console.log(chalk33.gray(` ccman: ${getCcmanDir()}`));
|
|
@@ -2959,7 +4857,7 @@ if (process.env.NODE_ENV === "development") {
|
|
|
2959
4857
|
console.log();
|
|
2960
4858
|
}
|
|
2961
4859
|
var program = new Command3();
|
|
2962
|
-
program.name("ccman").description("Codex/Claude Code API \u670D\u52A1\u5546\u914D\u7F6E\u7BA1\u7406\u5DE5\u5177").version(
|
|
4860
|
+
program.name("ccman").description("Codex/Claude Code API \u670D\u52A1\u5546\u914D\u7F6E\u7BA1\u7406\u5DE5\u5177").version(VERSION).showHelpAfterError(false).exitOverride((err) => {
|
|
2963
4861
|
if (err.code === "commander.helpDisplayed" || err.code === "commander.version") {
|
|
2964
4862
|
process.exit(0);
|
|
2965
4863
|
}
|