ccjk 1.4.0 → 2.0.0
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/README.ja.md +249 -297
- package/README.ko.md +241 -290
- package/README.md +216 -360
- package/README.zh-CN.md +234 -311
- package/dist/chunks/claude-code-config-manager.mjs +7 -7
- package/dist/chunks/claude-code-incremental-manager.mjs +1 -1
- package/dist/chunks/codex-config-switch.mjs +3 -3
- package/dist/chunks/codex-uninstaller.mjs +2 -2
- package/dist/chunks/features.mjs +10 -10
- package/dist/chunks/simple-config.mjs +388 -45
- package/dist/chunks/smart-guide.mjs +234 -0
- package/dist/cli.mjs +2325 -1317
- package/dist/i18n/locales/en/marketplace.json +84 -0
- package/dist/i18n/locales/en/menu.json +38 -1
- package/dist/i18n/locales/en/skills.json +140 -0
- package/dist/i18n/locales/en/smartGuide.json +49 -0
- package/dist/i18n/locales/en/subagent.json +69 -0
- package/dist/i18n/locales/en/superpowers.json +58 -0
- package/dist/i18n/locales/en/workflow.json +28 -9
- package/dist/i18n/locales/zh-CN/marketplace.json +84 -0
- package/dist/i18n/locales/zh-CN/menu.json +38 -1
- package/dist/i18n/locales/zh-CN/skills.json +140 -0
- package/dist/i18n/locales/zh-CN/smartGuide.json +49 -0
- package/dist/i18n/locales/zh-CN/subagent.json +69 -0
- package/dist/i18n/locales/zh-CN/superpowers.json +58 -0
- package/dist/i18n/locales/zh-CN/workflow.json +28 -9
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/package.json +26 -27
- package/templates/claude-code/en/workflow/essential/commands/feat.md +196 -51
- package/templates/claude-code/zh-CN/workflow/essential/commands/feat.md +194 -51
- package/templates/common/skills/en/brainstorming.md +64 -0
- package/templates/common/skills/en/code-review.md +81 -0
- package/templates/common/skills/en/documentation-gen.md +808 -0
- package/templates/common/skills/en/executing-plans.md +75 -0
- package/templates/common/skills/en/git-commit.md +216 -0
- package/templates/common/skills/en/interview.md +223 -0
- package/templates/common/skills/en/migration-assistant.md +312 -0
- package/templates/common/skills/en/performance-profiling.md +576 -0
- package/templates/common/skills/en/pr-review.md +341 -0
- package/templates/common/skills/en/refactoring.md +384 -0
- package/templates/common/skills/en/security-audit.md +462 -0
- package/templates/common/skills/en/systematic-debugging.md +82 -0
- package/templates/common/skills/en/tdd-workflow.md +93 -0
- package/templates/common/skills/en/verification.md +81 -0
- package/templates/common/skills/en/workflow.md +370 -0
- package/templates/common/skills/en/writing-plans.md +78 -0
- package/templates/common/skills/zh-CN/documentation-gen.md +807 -0
- package/templates/common/skills/zh-CN/migration-assistant.md +318 -0
- package/templates/common/skills/zh-CN/performance-profiling.md +746 -0
- package/templates/common/skills/zh-CN/pr-review.md +341 -0
- package/templates/common/skills/zh-CN/refactoring.md +384 -0
- package/templates/common/skills/zh-CN/security-audit.md +462 -0
- package/templates/common/smart-guide/en/smart-guide.md +72 -0
- package/templates/common/smart-guide/zh-CN/smart-guide.md +72 -0
- package/templates/common/workflow/sixStep/en/workflow.md +137 -31
- package/templates/common/workflow/sixStep/zh-CN/workflow.md +152 -10
package/dist/cli.mjs
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import cac from 'cac';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
|
-
import { S as STATUS, cj as i18n, r as runConfigWizard, ck as testApiConnection, h as displayCurrentStatus, cl as quickSetup, cm as format, g as COLORS, cn as getAllPresets, co as ensureI18nInitialized, cp as readCcrConfig, cq as isCcrInstalled, cr as installCcr, cs as configureCcrFeature, ct as promptBoolean, cu as handleExitPromptError, cv as handleGeneralError, cw as COMETIX_COMMAND_NAME, cx as COMETIX_COMMANDS, cy as installCometixLine, cz as addNumbersToChoices, cA as checkAndUpdateTools, aR as runCodexUpdate, cB as resolveCodeType$1, cC as
|
|
4
|
+
import { S as STATUS, cj as i18n, r as runConfigWizard, ck as testApiConnection, h as displayCurrentStatus, cl as quickSetup, cm as format, g as COLORS, cn as getAllPresets, co as ensureI18nInitialized, cp as readCcrConfig, cq as isCcrInstalled, cr as installCcr, cs as configureCcrFeature, ct as promptBoolean, cu as handleExitPromptError, cv as handleGeneralError, cw as COMETIX_COMMAND_NAME, cx as COMETIX_COMMANDS, cy as installCometixLine, cz as addNumbersToChoices, cA as checkAndUpdateTools, aR as runCodexUpdate, cB as resolveCodeType$1, X as resolveCodeToolType$1, cC as readZcfConfig, U as isCodeToolType, P as DEFAULT_CODE_TOOL_TYPE, aV as switchCodexProvider, aH as listCodexProviders, aM as readCodexConfig, ay as switchToOfficialLogin, aW as switchToProvider, cD as readJsonConfig, cE as writeJsonConfig, cF as moveToTrash, N as ZCF_CONFIG_FILE, ab as displayBanner, cG as updateZcfConfig, cH as version, cI as resolveAiOutputLanguage, cJ as updatePromptOnly, cK as selectAndInstallWorkflows, cL as checkClaudeCodeVersionAndPrompt, ac as displayBannerWithInfo, Q as CODE_TOOL_BANNERS, aQ as runCodexUninstall, b0 as configureCodexMcp, az as configureCodexApi, aT as runCodexWorkflowImportWithLanguageSelection, aO as runCodexFullInit, i as init, cM as checkSuperpowersInstalled, cN as getSuperpowersSkills, cO as updateSuperpowers, cP as uninstallSuperpowers, cQ as installSuperpowers, cR as installSuperpowersViaGit, T as CODE_TOOL_INFO, b6 as getToolStatus, b7 as getAllToolsStatus, O as CODE_TOOL_TYPES, ae as boxify, b9 as installTool, cS as readZcfConfigAsync, cT as initI18n, bU as quickSync, bA as runDoctor, ch as checkAllVersions, ci as upgradeAll, bs as detectAllConfigs, bx as displayConfigScan, c9 as displayPermissions, cU as selectScriptLanguage, cV as changeLanguage, bT as runOnboarding } from './chunks/simple-config.mjs';
|
|
5
5
|
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
|
|
6
6
|
import { homedir } from 'node:os';
|
|
7
7
|
import inquirer from 'inquirer';
|
|
8
8
|
import { join, resolve as resolve$1 } from 'pathe';
|
|
9
9
|
import { runCcrStop, runCcrStart, runCcrRestart, runCcrStatus, runCcrUi } from './chunks/commands.mjs';
|
|
10
10
|
import { changeScriptLanguageFeature, configureCodexAiMemoryFeature, configureCodexDefaultModelFeature, configureEnvPermissionFeature, configureAiMemoryFeature, configureDefaultModelFeature, configureMcpFeature, configureApiFeature } from './chunks/features.mjs';
|
|
11
|
+
import { readFile, mkdir, writeFile, rm, readdir } from 'node:fs/promises';
|
|
12
|
+
import { isSmartGuideInstalled, generateSkillReferenceCard, removeSmartGuide, injectSmartGuide, generateQuickActionsPanel, QUICK_ACTIONS } from './chunks/smart-guide.mjs';
|
|
11
13
|
import process$1 from 'node:process';
|
|
12
14
|
import { x, exec as exec$1 } from 'tinyexec';
|
|
13
15
|
import { spawn, exec } from 'node:child_process';
|
|
14
16
|
import { promisify } from 'node:util';
|
|
15
|
-
import { pathExists } from 'fs-extra';
|
|
16
17
|
import { ClaudeCodeConfigManager } from './chunks/claude-code-config-manager.mjs';
|
|
17
|
-
import {
|
|
18
|
+
import { pathExists } from 'fs-extra';
|
|
18
19
|
import { join as join$1, resolve, dirname } from 'node:path';
|
|
19
20
|
import { randomUUID } from 'node:crypto';
|
|
20
21
|
import ora from 'ora';
|
|
@@ -230,6 +231,355 @@ ${ansis.dim("\u2500".repeat(50))}
|
|
|
230
231
|
}
|
|
231
232
|
}
|
|
232
233
|
|
|
234
|
+
const DEFAULT_REGISTRY_URL = "https://registry.ccjk.dev/v1";
|
|
235
|
+
const DEFAULT_CACHE_CONFIG = {
|
|
236
|
+
cacheDir: join(homedir(), ".ccjk", "cache"),
|
|
237
|
+
ttl: 3600,
|
|
238
|
+
// 1 hour
|
|
239
|
+
enabled: true
|
|
240
|
+
};
|
|
241
|
+
const BUILTIN_PACKAGES = [
|
|
242
|
+
// Built-in packages will be added here in future versions
|
|
243
|
+
];
|
|
244
|
+
function getCacheFilePath(cacheDir) {
|
|
245
|
+
return join(cacheDir, "registry-cache.json");
|
|
246
|
+
}
|
|
247
|
+
async function isCacheValid(cacheDir, ttl) {
|
|
248
|
+
const cachePath = getCacheFilePath(cacheDir);
|
|
249
|
+
if (!existsSync(cachePath)) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
try {
|
|
253
|
+
const content = await readFile(cachePath, "utf-8");
|
|
254
|
+
const cache = JSON.parse(content);
|
|
255
|
+
const cacheTime = new Date(cache.lastUpdated).getTime();
|
|
256
|
+
const now = Date.now();
|
|
257
|
+
return now - cacheTime < ttl * 1e3;
|
|
258
|
+
} catch {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
async function readCachedRegistry(cacheDir) {
|
|
263
|
+
const cachePath = getCacheFilePath(cacheDir);
|
|
264
|
+
if (!existsSync(cachePath)) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
const content = await readFile(cachePath, "utf-8");
|
|
269
|
+
return JSON.parse(content);
|
|
270
|
+
} catch {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
async function writeCacheRegistry(cacheDir, registry) {
|
|
275
|
+
await mkdir(cacheDir, { recursive: true });
|
|
276
|
+
const cachePath = getCacheFilePath(cacheDir);
|
|
277
|
+
await writeFile(cachePath, JSON.stringify(registry, null, 2));
|
|
278
|
+
}
|
|
279
|
+
async function fetchRemoteRegistry(registryUrl = DEFAULT_REGISTRY_URL, timeout = 3e4) {
|
|
280
|
+
const controller = new AbortController();
|
|
281
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
282
|
+
try {
|
|
283
|
+
const response = await fetch(`${registryUrl}/registry.json`, {
|
|
284
|
+
signal: controller.signal,
|
|
285
|
+
headers: {
|
|
286
|
+
"Accept": "application/json",
|
|
287
|
+
"User-Agent": "ccjk-cli"
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
if (!response.ok) {
|
|
291
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
292
|
+
}
|
|
293
|
+
return await response.json();
|
|
294
|
+
} finally {
|
|
295
|
+
clearTimeout(timeoutId);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
async function getRegistry(options = {}) {
|
|
299
|
+
const cacheConfig = { ...DEFAULT_CACHE_CONFIG, ...options.cache };
|
|
300
|
+
const registryUrl = options.registryUrl || DEFAULT_REGISTRY_URL;
|
|
301
|
+
if (cacheConfig.enabled && !options.forceRefresh) {
|
|
302
|
+
const cacheValid = await isCacheValid(cacheConfig.cacheDir, cacheConfig.ttl);
|
|
303
|
+
if (cacheValid) {
|
|
304
|
+
const cached = await readCachedRegistry(cacheConfig.cacheDir);
|
|
305
|
+
if (cached) {
|
|
306
|
+
return cached;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
try {
|
|
311
|
+
const registry = await fetchRemoteRegistry(registryUrl);
|
|
312
|
+
if (cacheConfig.enabled) {
|
|
313
|
+
await writeCacheRegistry(cacheConfig.cacheDir, registry);
|
|
314
|
+
}
|
|
315
|
+
return registry;
|
|
316
|
+
} catch {
|
|
317
|
+
const cached = await readCachedRegistry(cacheConfig.cacheDir);
|
|
318
|
+
if (cached) {
|
|
319
|
+
return cached;
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
version: "1.0.0",
|
|
323
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
324
|
+
url: registryUrl,
|
|
325
|
+
packages: BUILTIN_PACKAGES,
|
|
326
|
+
categories: {
|
|
327
|
+
"plugin": 0,
|
|
328
|
+
"skill": 0,
|
|
329
|
+
"workflow": 0,
|
|
330
|
+
"agent": 0,
|
|
331
|
+
"mcp-service": 0,
|
|
332
|
+
"output-style": 0,
|
|
333
|
+
"bundle": 0
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
async function searchPackages(options = {}) {
|
|
339
|
+
const registry = await getRegistry();
|
|
340
|
+
let packages = [...registry.packages];
|
|
341
|
+
if (options.query) {
|
|
342
|
+
const query = options.query.toLowerCase();
|
|
343
|
+
packages = packages.filter(
|
|
344
|
+
(pkg) => pkg.name.toLowerCase().includes(query) || pkg.id.toLowerCase().includes(query) || pkg.keywords.some((k) => k.toLowerCase().includes(query)) || Object.values(pkg.description).some((d) => d.toLowerCase().includes(query))
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
if (options.category) {
|
|
348
|
+
packages = packages.filter((pkg) => pkg.category === options.category);
|
|
349
|
+
}
|
|
350
|
+
if (options.author) {
|
|
351
|
+
packages = packages.filter(
|
|
352
|
+
(pkg) => pkg.author.toLowerCase().includes(options.author.toLowerCase())
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
if (options.verified) {
|
|
356
|
+
packages = packages.filter((pkg) => pkg.verified === options.verified);
|
|
357
|
+
}
|
|
358
|
+
if (options.keywords?.length) {
|
|
359
|
+
packages = packages.filter(
|
|
360
|
+
(pkg) => options.keywords.some((k) => pkg.keywords.includes(k))
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
if (options.minRating) {
|
|
364
|
+
packages = packages.filter((pkg) => pkg.rating >= options.minRating);
|
|
365
|
+
}
|
|
366
|
+
if (options.supportedTool) {
|
|
367
|
+
packages = packages.filter(
|
|
368
|
+
(pkg) => pkg.supportedTools?.includes(options.supportedTool)
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
const sortBy = options.sortBy || "downloads";
|
|
372
|
+
const sortDir = options.sortDir || "desc";
|
|
373
|
+
packages.sort((a, b) => {
|
|
374
|
+
let comparison = 0;
|
|
375
|
+
switch (sortBy) {
|
|
376
|
+
case "downloads":
|
|
377
|
+
comparison = a.downloads - b.downloads;
|
|
378
|
+
break;
|
|
379
|
+
case "rating":
|
|
380
|
+
comparison = a.rating - b.rating;
|
|
381
|
+
break;
|
|
382
|
+
case "updated":
|
|
383
|
+
comparison = new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime();
|
|
384
|
+
break;
|
|
385
|
+
case "created":
|
|
386
|
+
comparison = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
|
387
|
+
break;
|
|
388
|
+
case "name":
|
|
389
|
+
comparison = a.name.localeCompare(b.name);
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
return sortDir === "desc" ? -comparison : comparison;
|
|
393
|
+
});
|
|
394
|
+
const total = packages.length;
|
|
395
|
+
const offset = options.offset || 0;
|
|
396
|
+
const limit = options.limit || 20;
|
|
397
|
+
packages = packages.slice(offset, offset + limit);
|
|
398
|
+
return {
|
|
399
|
+
packages,
|
|
400
|
+
total,
|
|
401
|
+
offset,
|
|
402
|
+
limit,
|
|
403
|
+
query: options.query,
|
|
404
|
+
filters: options
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
async function getPackage(packageId) {
|
|
408
|
+
const registry = await getRegistry();
|
|
409
|
+
return registry.packages.find((pkg) => pkg.id === packageId) || null;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const DEFAULT_INSTALL_DIR = join(homedir(), ".ccjk", "packages");
|
|
413
|
+
const INSTALLED_MANIFEST = join(homedir(), ".ccjk", "installed-packages.json");
|
|
414
|
+
async function getInstalledPackages() {
|
|
415
|
+
if (!existsSync(INSTALLED_MANIFEST)) {
|
|
416
|
+
return [];
|
|
417
|
+
}
|
|
418
|
+
try {
|
|
419
|
+
const content = await readFile(INSTALLED_MANIFEST, "utf-8");
|
|
420
|
+
return JSON.parse(content);
|
|
421
|
+
} catch {
|
|
422
|
+
return [];
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
async function saveInstalledPackages(packages) {
|
|
426
|
+
const dir = join(homedir(), ".ccjk");
|
|
427
|
+
await mkdir(dir, { recursive: true });
|
|
428
|
+
await writeFile(INSTALLED_MANIFEST, JSON.stringify(packages, null, 2));
|
|
429
|
+
}
|
|
430
|
+
async function isPackageInstalled(packageId) {
|
|
431
|
+
const installed = await getInstalledPackages();
|
|
432
|
+
return installed.some((pkg) => pkg.package.id === packageId);
|
|
433
|
+
}
|
|
434
|
+
async function installPackage(packageId, options = {}) {
|
|
435
|
+
const startTime = Date.now();
|
|
436
|
+
try {
|
|
437
|
+
const alreadyInstalled = await isPackageInstalled(packageId);
|
|
438
|
+
if (alreadyInstalled && !options.force) {
|
|
439
|
+
const pkg2 = await getPackage(packageId);
|
|
440
|
+
if (!pkg2) {
|
|
441
|
+
return {
|
|
442
|
+
success: false,
|
|
443
|
+
package: {},
|
|
444
|
+
error: i18n.t("marketplace:packageNotFound", { name: packageId })
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
success: true,
|
|
449
|
+
package: pkg2,
|
|
450
|
+
alreadyInstalled: true,
|
|
451
|
+
durationMs: Date.now() - startTime
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
const pkg = await getPackage(packageId);
|
|
455
|
+
if (!pkg) {
|
|
456
|
+
return {
|
|
457
|
+
success: false,
|
|
458
|
+
package: {},
|
|
459
|
+
error: i18n.t("marketplace:packageNotFound", { name: packageId })
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
const warnings = [];
|
|
463
|
+
if (options.codeToolType && pkg.supportedTools) {
|
|
464
|
+
if (!pkg.supportedTools.includes(options.codeToolType)) {
|
|
465
|
+
warnings.push(
|
|
466
|
+
i18n.t("marketplace:incompatibleTool", {
|
|
467
|
+
tool: options.codeToolType,
|
|
468
|
+
supported: pkg.supportedTools.join(", ")
|
|
469
|
+
})
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
const targetDir = options.targetDir || DEFAULT_INSTALL_DIR;
|
|
474
|
+
const installPath = join(targetDir, pkg.id);
|
|
475
|
+
await mkdir(installPath, { recursive: true });
|
|
476
|
+
const installed = await getInstalledPackages();
|
|
477
|
+
const installedPackage = {
|
|
478
|
+
package: pkg,
|
|
479
|
+
path: installPath,
|
|
480
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
481
|
+
source: "marketplace",
|
|
482
|
+
enabled: true
|
|
483
|
+
};
|
|
484
|
+
const existingIndex = installed.findIndex((p) => p.package.id === pkg.id);
|
|
485
|
+
if (existingIndex >= 0) {
|
|
486
|
+
installed[existingIndex] = installedPackage;
|
|
487
|
+
} else {
|
|
488
|
+
installed.push(installedPackage);
|
|
489
|
+
}
|
|
490
|
+
await saveInstalledPackages(installed);
|
|
491
|
+
return {
|
|
492
|
+
success: true,
|
|
493
|
+
package: pkg,
|
|
494
|
+
installedPath: installPath,
|
|
495
|
+
warnings: warnings.length > 0 ? warnings : void 0,
|
|
496
|
+
durationMs: Date.now() - startTime
|
|
497
|
+
};
|
|
498
|
+
} catch (error) {
|
|
499
|
+
return {
|
|
500
|
+
success: false,
|
|
501
|
+
package: {},
|
|
502
|
+
error: error instanceof Error ? error.message : String(error),
|
|
503
|
+
durationMs: Date.now() - startTime
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
async function uninstallPackage(packageId, options = {}) {
|
|
508
|
+
try {
|
|
509
|
+
const installed = await getInstalledPackages();
|
|
510
|
+
const pkg = installed.find((p) => p.package.id === packageId);
|
|
511
|
+
if (!pkg) {
|
|
512
|
+
return {
|
|
513
|
+
success: false,
|
|
514
|
+
packageId,
|
|
515
|
+
error: i18n.t("marketplace:packageNotInstalled", { name: packageId })
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
if (!options.force) {
|
|
519
|
+
const dependents = installed.filter(
|
|
520
|
+
(p) => p.package.dependencies && Object.keys(p.package.dependencies).includes(packageId)
|
|
521
|
+
);
|
|
522
|
+
if (dependents.length > 0) {
|
|
523
|
+
return {
|
|
524
|
+
success: false,
|
|
525
|
+
packageId,
|
|
526
|
+
error: i18n.t("marketplace:packageHasDependents", {
|
|
527
|
+
name: packageId,
|
|
528
|
+
dependents: dependents.map((p) => p.package.name).join(", ")
|
|
529
|
+
})
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
if (existsSync(pkg.path)) {
|
|
534
|
+
await rm(pkg.path, { recursive: true, force: true });
|
|
535
|
+
}
|
|
536
|
+
const updated = installed.filter((p) => p.package.id !== packageId);
|
|
537
|
+
await saveInstalledPackages(updated);
|
|
538
|
+
return {
|
|
539
|
+
success: true,
|
|
540
|
+
packageId
|
|
541
|
+
};
|
|
542
|
+
} catch (error) {
|
|
543
|
+
return {
|
|
544
|
+
success: false,
|
|
545
|
+
packageId,
|
|
546
|
+
error: error instanceof Error ? error.message : String(error)
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
async function updatePackage(packageId) {
|
|
551
|
+
const uninstallResult = await uninstallPackage(packageId, { keepConfig: true });
|
|
552
|
+
if (!uninstallResult.success) {
|
|
553
|
+
return {
|
|
554
|
+
success: false,
|
|
555
|
+
package: {},
|
|
556
|
+
error: uninstallResult.error
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
return await installPackage(packageId, { force: true });
|
|
560
|
+
}
|
|
561
|
+
async function checkForUpdates() {
|
|
562
|
+
const installed = await getInstalledPackages();
|
|
563
|
+
const updates = [];
|
|
564
|
+
for (const installedPkg of installed) {
|
|
565
|
+
const latestPkg = await getPackage(installedPkg.package.id);
|
|
566
|
+
if (!latestPkg)
|
|
567
|
+
continue;
|
|
568
|
+
if (latestPkg.version !== installedPkg.package.version) {
|
|
569
|
+
updates.push({
|
|
570
|
+
id: installedPkg.package.id,
|
|
571
|
+
currentVersion: installedPkg.package.version,
|
|
572
|
+
latestVersion: latestPkg.version,
|
|
573
|
+
breaking: false,
|
|
574
|
+
// TODO: Implement semver comparison
|
|
575
|
+
changelog: latestPkg.changelog,
|
|
576
|
+
releaseDate: latestPkg.updatedAt
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return updates;
|
|
581
|
+
}
|
|
582
|
+
|
|
233
583
|
async function executeCcusage(args = []) {
|
|
234
584
|
try {
|
|
235
585
|
const command = "npx";
|
|
@@ -483,276 +833,331 @@ Defaulting to "claude-code".`));
|
|
|
483
833
|
}
|
|
484
834
|
}
|
|
485
835
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
this.conflictResolution.set("claude-code", ["mcps"]);
|
|
493
|
-
void this._lang;
|
|
494
|
-
}
|
|
495
|
-
/**
|
|
496
|
-
* 1. Remove outputStyle field from settings.json and output-styles directory
|
|
497
|
-
*/
|
|
498
|
-
async removeOutputStyles() {
|
|
499
|
-
const result = {
|
|
500
|
-
success: false,
|
|
501
|
-
removed: [],
|
|
502
|
-
removedConfigs: [],
|
|
503
|
-
errors: [],
|
|
504
|
-
warnings: []
|
|
505
|
-
};
|
|
506
|
-
try {
|
|
507
|
-
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
508
|
-
const outputStylesPath = join(homedir(), ".claude", "output-styles");
|
|
509
|
-
if (await pathExists(settingsPath)) {
|
|
510
|
-
const settings = readJsonConfig(settingsPath) || {};
|
|
511
|
-
if (settings.outputStyle) {
|
|
512
|
-
delete settings.outputStyle;
|
|
513
|
-
writeJsonConfig(settingsPath, settings);
|
|
514
|
-
result.removedConfigs.push("outputStyle field from settings.json");
|
|
515
|
-
}
|
|
516
|
-
} else {
|
|
517
|
-
result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
|
|
518
|
-
}
|
|
519
|
-
if (await pathExists(outputStylesPath)) {
|
|
520
|
-
const trashResult = await moveToTrash(outputStylesPath);
|
|
521
|
-
if (!trashResult[0]?.success) {
|
|
522
|
-
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
523
|
-
}
|
|
524
|
-
result.removed.push("~/.claude/output-styles/");
|
|
525
|
-
} else {
|
|
526
|
-
result.warnings.push(i18n.t("uninstall:outputStylesDirectoryNotFound"));
|
|
527
|
-
}
|
|
528
|
-
result.success = true;
|
|
529
|
-
} catch (error) {
|
|
530
|
-
result.errors.push(`Failed to remove output styles: ${error.message}`);
|
|
836
|
+
async function configSwitchCommand(options) {
|
|
837
|
+
try {
|
|
838
|
+
ensureI18nInitialized();
|
|
839
|
+
if (options.list) {
|
|
840
|
+
await handleList(options.codeType);
|
|
841
|
+
return;
|
|
531
842
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
*/
|
|
537
|
-
async removeCustomCommands() {
|
|
538
|
-
const result = {
|
|
539
|
-
success: false,
|
|
540
|
-
removed: [],
|
|
541
|
-
removedConfigs: [],
|
|
542
|
-
errors: [],
|
|
543
|
-
warnings: []
|
|
544
|
-
};
|
|
545
|
-
try {
|
|
546
|
-
const commandsPath = join(homedir(), ".claude", "commands", "ccjk");
|
|
547
|
-
if (await pathExists(commandsPath)) {
|
|
548
|
-
const trashResult = await moveToTrash(commandsPath);
|
|
549
|
-
if (!trashResult[0]?.success) {
|
|
550
|
-
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
551
|
-
}
|
|
552
|
-
result.removed.push("commands/ccjk/");
|
|
553
|
-
result.success = true;
|
|
554
|
-
} else {
|
|
555
|
-
result.warnings.push(i18n.t("uninstall:commandsNotFound"));
|
|
556
|
-
result.success = true;
|
|
557
|
-
}
|
|
558
|
-
} catch (error) {
|
|
559
|
-
result.errors.push(`Failed to remove custom commands: ${error.message}`);
|
|
843
|
+
if (options.target) {
|
|
844
|
+
const resolvedCodeType = resolveCodeType(options.codeType);
|
|
845
|
+
await handleDirectSwitch(resolvedCodeType, options.target);
|
|
846
|
+
return;
|
|
560
847
|
}
|
|
561
|
-
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
*/
|
|
566
|
-
async removeCustomAgents() {
|
|
567
|
-
const result = {
|
|
568
|
-
success: false,
|
|
569
|
-
removed: [],
|
|
570
|
-
removedConfigs: [],
|
|
571
|
-
errors: [],
|
|
572
|
-
warnings: []
|
|
573
|
-
};
|
|
574
|
-
try {
|
|
575
|
-
const agentsPath = join(homedir(), ".claude", "agents", "ccjk");
|
|
576
|
-
if (await pathExists(agentsPath)) {
|
|
577
|
-
const trashResult = await moveToTrash(agentsPath);
|
|
578
|
-
if (!trashResult[0]?.success) {
|
|
579
|
-
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
580
|
-
}
|
|
581
|
-
result.removed.push("agents/ccjk/");
|
|
582
|
-
result.success = true;
|
|
583
|
-
} else {
|
|
584
|
-
result.warnings.push(i18n.t("uninstall:agentsNotFound"));
|
|
585
|
-
result.success = true;
|
|
586
|
-
}
|
|
587
|
-
} catch (error) {
|
|
588
|
-
result.errors.push(`Failed to remove custom agents: ${error.message}`);
|
|
848
|
+
await handleInteractiveSwitch(options.codeType);
|
|
849
|
+
} catch (error) {
|
|
850
|
+
if (process$1.env.NODE_ENV === "test" || process$1.env.VITEST) {
|
|
851
|
+
throw error;
|
|
589
852
|
}
|
|
590
|
-
|
|
853
|
+
handleGeneralError(error);
|
|
591
854
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
855
|
+
}
|
|
856
|
+
function resolveCodeType(codeType) {
|
|
857
|
+
if (codeType !== void 0) {
|
|
858
|
+
const resolved = resolveCodeToolType$1(codeType);
|
|
859
|
+
return resolved;
|
|
860
|
+
}
|
|
861
|
+
const zcfConfig = readZcfConfig();
|
|
862
|
+
if (zcfConfig?.codeToolType && isCodeToolType(zcfConfig.codeToolType)) {
|
|
863
|
+
return zcfConfig.codeToolType;
|
|
864
|
+
}
|
|
865
|
+
return DEFAULT_CODE_TOOL_TYPE;
|
|
866
|
+
}
|
|
867
|
+
async function handleList(codeType) {
|
|
868
|
+
const targetCodeType = resolveCodeType(codeType);
|
|
869
|
+
if (targetCodeType === "claude-code") {
|
|
870
|
+
await listClaudeCodeProfiles();
|
|
871
|
+
} else if (targetCodeType === "codex") {
|
|
872
|
+
await listCodexProvidersWithDisplay();
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
async function listCodexProvidersWithDisplay() {
|
|
876
|
+
const providers = await listCodexProviders();
|
|
877
|
+
const existingConfig = readCodexConfig();
|
|
878
|
+
const currentProvider = existingConfig?.modelProvider;
|
|
879
|
+
const isCommented = existingConfig?.modelProviderCommented;
|
|
880
|
+
if (!providers || providers.length === 0) {
|
|
881
|
+
console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
console.log(ansis.bold(i18n.t("codex:listProvidersTitle")));
|
|
885
|
+
console.log();
|
|
886
|
+
if (currentProvider && !isCommented) {
|
|
887
|
+
console.log(ansis.cyan(i18n.t("codex:currentProvider", { provider: currentProvider })));
|
|
888
|
+
console.log();
|
|
889
|
+
}
|
|
890
|
+
providers.forEach((provider) => {
|
|
891
|
+
const isCurrent = currentProvider === provider.id && !isCommented;
|
|
892
|
+
const status = isCurrent ? ansis.green("\u25CF ") : " ";
|
|
893
|
+
const current = isCurrent ? ansis.yellow(` (${i18n.t("common:current")})`) : "";
|
|
894
|
+
console.log(`${status}${ansis.white(provider.name)}${current}`);
|
|
895
|
+
console.log(` ${ansis.cyan(`ID: ${provider.id}`)} ${ansis.gray(`(${provider.baseUrl})`)}`);
|
|
896
|
+
if (provider.tempEnvKey) {
|
|
897
|
+
console.log(` ${ansis.gray(`Env: ${provider.tempEnvKey}`)}`);
|
|
618
898
|
}
|
|
619
|
-
|
|
899
|
+
console.log();
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
async function listClaudeCodeProfiles() {
|
|
903
|
+
const config = ClaudeCodeConfigManager.readConfig();
|
|
904
|
+
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
905
|
+
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
906
|
+
return;
|
|
620
907
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
const
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
} else {
|
|
652
|
-
result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
|
|
653
|
-
result.success = true;
|
|
908
|
+
console.log(ansis.bold(i18n.t("multi-config:availableClaudeCodeProfiles")));
|
|
909
|
+
console.log();
|
|
910
|
+
const currentProfileId = config.currentProfileId;
|
|
911
|
+
Object.values(config.profiles).forEach((profile) => {
|
|
912
|
+
const isCurrent = profile.id === currentProfileId;
|
|
913
|
+
const status = isCurrent ? ansis.green("\u25CF ") : " ";
|
|
914
|
+
const current = isCurrent ? ansis.yellow(i18n.t("common:current")) : "";
|
|
915
|
+
console.log(`${status}${ansis.white(profile.name)}${current}`);
|
|
916
|
+
console.log(` ${ansis.cyan(`ID: ${profile.id}`)} ${ansis.gray(`(${profile.authType})`)}`);
|
|
917
|
+
console.log();
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
async function handleDirectSwitch(codeType, target) {
|
|
921
|
+
const resolvedCodeType = resolveCodeType(codeType);
|
|
922
|
+
if (resolvedCodeType === "claude-code") {
|
|
923
|
+
await handleClaudeCodeDirectSwitch(target);
|
|
924
|
+
} else if (resolvedCodeType === "codex") {
|
|
925
|
+
await switchCodexProvider(target);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
async function handleClaudeCodeDirectSwitch(target) {
|
|
929
|
+
if (target === "official") {
|
|
930
|
+
const result = await ClaudeCodeConfigManager.switchToOfficial();
|
|
931
|
+
if (result.success) {
|
|
932
|
+
try {
|
|
933
|
+
await ClaudeCodeConfigManager.applyProfileSettings(null);
|
|
934
|
+
console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToOfficial")));
|
|
935
|
+
} catch (error) {
|
|
936
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
937
|
+
console.log(ansis.red(reason));
|
|
654
938
|
}
|
|
655
|
-
}
|
|
656
|
-
|
|
939
|
+
} else {
|
|
940
|
+
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToOfficial", { error: result.error })));
|
|
657
941
|
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
errors: [],
|
|
669
|
-
warnings: []
|
|
670
|
-
};
|
|
671
|
-
try {
|
|
672
|
-
const claudeJsonPath = join(homedir(), ".claude.json");
|
|
673
|
-
if (await pathExists(claudeJsonPath)) {
|
|
674
|
-
const config = readJsonConfig(claudeJsonPath) || {};
|
|
675
|
-
if (config.mcpServers) {
|
|
676
|
-
delete config.mcpServers;
|
|
677
|
-
writeJsonConfig(claudeJsonPath, config);
|
|
678
|
-
result.removedConfigs.push("mcpServers from .claude.json");
|
|
679
|
-
}
|
|
680
|
-
result.success = true;
|
|
681
|
-
} else {
|
|
682
|
-
result.warnings.push(i18n.t("uninstall:claudeJsonNotFound"));
|
|
683
|
-
result.success = true;
|
|
942
|
+
} else if (target === "ccr") {
|
|
943
|
+
const result = await ClaudeCodeConfigManager.switchToCcr();
|
|
944
|
+
if (result.success) {
|
|
945
|
+
try {
|
|
946
|
+
const profile = ClaudeCodeConfigManager.getProfileById("ccr-proxy");
|
|
947
|
+
await ClaudeCodeConfigManager.applyProfileSettings(profile);
|
|
948
|
+
console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToCcr")));
|
|
949
|
+
} catch (error) {
|
|
950
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
951
|
+
console.log(ansis.red(reason));
|
|
684
952
|
}
|
|
685
|
-
}
|
|
686
|
-
|
|
953
|
+
} else {
|
|
954
|
+
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToCcr", { error: result.error })));
|
|
687
955
|
}
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
const
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
const ccrPath = join(homedir(), ".claude-code-router");
|
|
703
|
-
if (await pathExists(ccrPath)) {
|
|
704
|
-
const trashResult = await moveToTrash(ccrPath);
|
|
705
|
-
if (!trashResult[0]?.success) {
|
|
706
|
-
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
707
|
-
}
|
|
708
|
-
result.removed.push(".claude-code-router/");
|
|
956
|
+
} else {
|
|
957
|
+
const config = ClaudeCodeConfigManager.readConfig();
|
|
958
|
+
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
959
|
+
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
const normalizedTarget = target.trim();
|
|
963
|
+
let resolvedId = normalizedTarget;
|
|
964
|
+
let resolvedProfile = config.profiles[normalizedTarget];
|
|
965
|
+
if (!resolvedProfile) {
|
|
966
|
+
const match = Object.entries(config.profiles).find(([, profile]) => profile.name === normalizedTarget);
|
|
967
|
+
if (match) {
|
|
968
|
+
resolvedId = match[0];
|
|
969
|
+
resolvedProfile = match[1];
|
|
709
970
|
}
|
|
971
|
+
}
|
|
972
|
+
if (!resolvedProfile) {
|
|
973
|
+
console.log(ansis.red(i18n.t("multi-config:profileNameNotFound", { name: target })));
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
const result = await ClaudeCodeConfigManager.switchProfile(resolvedId);
|
|
977
|
+
if (result.success) {
|
|
710
978
|
try {
|
|
711
|
-
await
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
|
|
717
|
-
result.success = true;
|
|
718
|
-
} else {
|
|
719
|
-
result.errors.push(`Failed to uninstall CCR package: ${npmError.message}`);
|
|
720
|
-
}
|
|
979
|
+
await ClaudeCodeConfigManager.applyProfileSettings({ ...resolvedProfile, id: resolvedId });
|
|
980
|
+
console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToProfile", { name: resolvedProfile.name })));
|
|
981
|
+
} catch (error) {
|
|
982
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
983
|
+
console.log(ansis.red(reason));
|
|
721
984
|
}
|
|
722
|
-
}
|
|
723
|
-
|
|
985
|
+
} else {
|
|
986
|
+
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToProfile", { error: result.error })));
|
|
724
987
|
}
|
|
725
|
-
return result;
|
|
726
988
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
989
|
+
}
|
|
990
|
+
async function handleInteractiveSwitch(codeType) {
|
|
991
|
+
const resolvedCodeType = resolveCodeType(codeType);
|
|
992
|
+
if (resolvedCodeType === "claude-code") {
|
|
993
|
+
await handleClaudeCodeInteractiveSwitch();
|
|
994
|
+
} else if (resolvedCodeType === "codex") {
|
|
995
|
+
await handleCodexInteractiveSwitch();
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
async function handleClaudeCodeInteractiveSwitch() {
|
|
999
|
+
const config = ClaudeCodeConfigManager.readConfig();
|
|
1000
|
+
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
1001
|
+
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
const currentProfileId = config.currentProfileId;
|
|
1005
|
+
const createClaudeCodeChoices = (profiles, currentProfileId2) => {
|
|
1006
|
+
const choices2 = [];
|
|
1007
|
+
const isOfficialMode = !currentProfileId2 || currentProfileId2 === "official";
|
|
1008
|
+
choices2.push({
|
|
1009
|
+
name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("codex:useOfficialLogin")}`,
|
|
1010
|
+
value: "official"
|
|
1011
|
+
});
|
|
1012
|
+
const isCcrMode = currentProfileId2 === "ccr-proxy";
|
|
1013
|
+
choices2.push({
|
|
1014
|
+
name: isCcrMode ? `${ansis.green("\u25CF ")}${i18n.t("multi-config:ccrProxyOption")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("multi-config:ccrProxyOption")}`,
|
|
1015
|
+
value: "ccr"
|
|
1016
|
+
});
|
|
1017
|
+
Object.values(profiles).filter((profile) => profile.id !== "ccr-proxy").forEach((profile) => {
|
|
1018
|
+
const isCurrent = profile.id === currentProfileId2;
|
|
1019
|
+
choices2.push({
|
|
1020
|
+
name: isCurrent ? `${ansis.green("\u25CF ")}${profile.name} ${ansis.yellow("(current)")}` : ` ${profile.name}`,
|
|
1021
|
+
value: profile.id
|
|
1022
|
+
});
|
|
1023
|
+
});
|
|
1024
|
+
return choices2;
|
|
1025
|
+
};
|
|
1026
|
+
const choices = createClaudeCodeChoices(config.profiles, currentProfileId);
|
|
1027
|
+
try {
|
|
1028
|
+
const { selectedConfig } = await inquirer.prompt([{
|
|
1029
|
+
type: "list",
|
|
1030
|
+
name: "selectedConfig",
|
|
1031
|
+
message: i18n.t("multi-config:selectClaudeCodeConfiguration"),
|
|
1032
|
+
choices: addNumbersToChoices(choices)
|
|
1033
|
+
}]);
|
|
1034
|
+
if (!selectedConfig) {
|
|
1035
|
+
console.log(ansis.yellow(i18n.t("multi-config:cancelled")));
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
await handleClaudeCodeDirectSwitch(selectedConfig);
|
|
1039
|
+
} catch (error) {
|
|
1040
|
+
if (error.name === "ExitPromptError") {
|
|
1041
|
+
console.log(ansis.cyan(`
|
|
1042
|
+
${i18n.t("common:goodbye")}`));
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
throw error;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
async function handleCodexInteractiveSwitch() {
|
|
1049
|
+
const providers = await listCodexProviders();
|
|
1050
|
+
if (!providers || providers.length === 0) {
|
|
1051
|
+
console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
const existingConfig = readCodexConfig();
|
|
1055
|
+
const currentProvider = existingConfig?.modelProvider;
|
|
1056
|
+
const isCommented = existingConfig?.modelProviderCommented;
|
|
1057
|
+
const createApiConfigChoices = (providers2, currentProvider2, isCommented2) => {
|
|
1058
|
+
const choices2 = [];
|
|
1059
|
+
const isOfficialMode = !currentProvider2 || isCommented2;
|
|
1060
|
+
choices2.push({
|
|
1061
|
+
name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${i18n.t("codex:useOfficialLogin")}`,
|
|
1062
|
+
value: "official"
|
|
1063
|
+
});
|
|
1064
|
+
providers2.forEach((provider) => {
|
|
1065
|
+
const isCurrent = currentProvider2 === provider.id && !isCommented2;
|
|
1066
|
+
choices2.push({
|
|
1067
|
+
name: isCurrent ? `${ansis.green("\u25CF ")}${provider.name} - ${ansis.gray(provider.id)} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${provider.name} - ${ansis.gray(provider.id)}`,
|
|
1068
|
+
value: provider.id
|
|
1069
|
+
});
|
|
1070
|
+
});
|
|
1071
|
+
return choices2;
|
|
1072
|
+
};
|
|
1073
|
+
const choices = createApiConfigChoices(providers, currentProvider, isCommented);
|
|
1074
|
+
try {
|
|
1075
|
+
const { selectedConfig } = await inquirer.prompt([{
|
|
1076
|
+
type: "list",
|
|
1077
|
+
name: "selectedConfig",
|
|
1078
|
+
message: i18n.t("codex:apiConfigSwitchPrompt"),
|
|
1079
|
+
choices: addNumbersToChoices(choices)
|
|
1080
|
+
}]);
|
|
1081
|
+
if (!selectedConfig) {
|
|
1082
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
let success = false;
|
|
1086
|
+
if (selectedConfig === "official") {
|
|
1087
|
+
success = await switchToOfficialLogin();
|
|
1088
|
+
} else {
|
|
1089
|
+
success = await switchToProvider(selectedConfig);
|
|
1090
|
+
}
|
|
1091
|
+
if (!success) {
|
|
1092
|
+
console.log(ansis.red(i18n.t("common:operationFailed")));
|
|
1093
|
+
}
|
|
1094
|
+
} catch (error) {
|
|
1095
|
+
if (error.name === "ExitPromptError") {
|
|
1096
|
+
console.log(ansis.cyan(`
|
|
1097
|
+
${i18n.t("common:goodbye")}`));
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
throw error;
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
const configSwitch = {
|
|
1105
|
+
__proto__: null,
|
|
1106
|
+
configSwitchCommand: configSwitchCommand
|
|
1107
|
+
};
|
|
1108
|
+
|
|
1109
|
+
class ZcfUninstaller {
|
|
1110
|
+
_lang;
|
|
1111
|
+
// Reserved for future i18n support
|
|
1112
|
+
conflictResolution = /* @__PURE__ */ new Map();
|
|
1113
|
+
constructor(lang = "en") {
|
|
1114
|
+
this._lang = lang;
|
|
1115
|
+
this.conflictResolution.set("claude-code", ["mcps"]);
|
|
1116
|
+
void this._lang;
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* 1. Remove outputStyle field from settings.json and output-styles directory
|
|
1120
|
+
*/
|
|
1121
|
+
async removeOutputStyles() {
|
|
1122
|
+
const result = {
|
|
1123
|
+
success: false,
|
|
1124
|
+
removed: [],
|
|
1125
|
+
removedConfigs: [],
|
|
1126
|
+
errors: [],
|
|
1127
|
+
warnings: []
|
|
1128
|
+
};
|
|
1129
|
+
try {
|
|
1130
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
1131
|
+
const outputStylesPath = join(homedir(), ".claude", "output-styles");
|
|
1132
|
+
if (await pathExists(settingsPath)) {
|
|
1133
|
+
const settings = readJsonConfig(settingsPath) || {};
|
|
1134
|
+
if (settings.outputStyle) {
|
|
1135
|
+
delete settings.outputStyle;
|
|
1136
|
+
writeJsonConfig(settingsPath, settings);
|
|
1137
|
+
result.removedConfigs.push("outputStyle field from settings.json");
|
|
1138
|
+
}
|
|
1139
|
+
} else {
|
|
1140
|
+
result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
|
|
1141
|
+
}
|
|
1142
|
+
if (await pathExists(outputStylesPath)) {
|
|
1143
|
+
const trashResult = await moveToTrash(outputStylesPath);
|
|
1144
|
+
if (!trashResult[0]?.success) {
|
|
1145
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1146
|
+
}
|
|
1147
|
+
result.removed.push("~/.claude/output-styles/");
|
|
1148
|
+
} else {
|
|
1149
|
+
result.warnings.push(i18n.t("uninstall:outputStylesDirectoryNotFound"));
|
|
748
1150
|
}
|
|
1151
|
+
result.success = true;
|
|
1152
|
+
} catch (error) {
|
|
1153
|
+
result.errors.push(`Failed to remove output styles: ${error.message}`);
|
|
749
1154
|
}
|
|
750
1155
|
return result;
|
|
751
1156
|
}
|
|
752
1157
|
/**
|
|
753
|
-
*
|
|
1158
|
+
* 2. Remove custom commands directory (commands/ccjk/)
|
|
754
1159
|
*/
|
|
755
|
-
async
|
|
1160
|
+
async removeCustomCommands() {
|
|
756
1161
|
const result = {
|
|
757
1162
|
success: false,
|
|
758
1163
|
removed: [],
|
|
@@ -761,603 +1166,1240 @@ class ZcfUninstaller {
|
|
|
761
1166
|
warnings: []
|
|
762
1167
|
};
|
|
763
1168
|
try {
|
|
764
|
-
const
|
|
765
|
-
if (await pathExists(
|
|
766
|
-
const trashResult = await moveToTrash(
|
|
1169
|
+
const commandsPath = join(homedir(), ".claude", "commands", "ccjk");
|
|
1170
|
+
if (await pathExists(commandsPath)) {
|
|
1171
|
+
const trashResult = await moveToTrash(commandsPath);
|
|
767
1172
|
if (!trashResult[0]?.success) {
|
|
768
1173
|
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
769
1174
|
}
|
|
770
|
-
result.removed.push("
|
|
1175
|
+
result.removed.push("commands/ccjk/");
|
|
1176
|
+
result.success = true;
|
|
1177
|
+
} else {
|
|
1178
|
+
result.warnings.push(i18n.t("uninstall:commandsNotFound"));
|
|
1179
|
+
result.success = true;
|
|
771
1180
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
1181
|
+
} catch (error) {
|
|
1182
|
+
result.errors.push(`Failed to remove custom commands: ${error.message}`);
|
|
1183
|
+
}
|
|
1184
|
+
return result;
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* 3. Remove custom agents directory (agents/ccjk/)
|
|
1188
|
+
*/
|
|
1189
|
+
async removeCustomAgents() {
|
|
1190
|
+
const result = {
|
|
1191
|
+
success: false,
|
|
1192
|
+
removed: [],
|
|
1193
|
+
removedConfigs: [],
|
|
1194
|
+
errors: [],
|
|
1195
|
+
warnings: []
|
|
1196
|
+
};
|
|
1197
|
+
try {
|
|
1198
|
+
const agentsPath = join(homedir(), ".claude", "agents", "ccjk");
|
|
1199
|
+
if (await pathExists(agentsPath)) {
|
|
1200
|
+
const trashResult = await moveToTrash(agentsPath);
|
|
1201
|
+
if (!trashResult[0]?.success) {
|
|
1202
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
780
1203
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
1204
|
+
result.removed.push("agents/ccjk/");
|
|
1205
|
+
result.success = true;
|
|
1206
|
+
} else {
|
|
1207
|
+
result.warnings.push(i18n.t("uninstall:agentsNotFound"));
|
|
1208
|
+
result.success = true;
|
|
1209
|
+
}
|
|
1210
|
+
} catch (error) {
|
|
1211
|
+
result.errors.push(`Failed to remove custom agents: ${error.message}`);
|
|
1212
|
+
}
|
|
1213
|
+
return result;
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* 4. Remove global memory file (CLAUDE.md)
|
|
1217
|
+
*/
|
|
1218
|
+
async removeClaudeMd() {
|
|
1219
|
+
const result = {
|
|
1220
|
+
success: false,
|
|
1221
|
+
removed: [],
|
|
1222
|
+
removedConfigs: [],
|
|
1223
|
+
errors: [],
|
|
1224
|
+
warnings: []
|
|
1225
|
+
};
|
|
1226
|
+
try {
|
|
1227
|
+
const claudeMdPath = join(homedir(), ".claude", "CLAUDE.md");
|
|
1228
|
+
if (await pathExists(claudeMdPath)) {
|
|
1229
|
+
const trashResult = await moveToTrash(claudeMdPath);
|
|
1230
|
+
if (!trashResult[0]?.success) {
|
|
1231
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
787
1232
|
}
|
|
1233
|
+
result.removed.push("CLAUDE.md");
|
|
1234
|
+
result.success = true;
|
|
1235
|
+
} else {
|
|
1236
|
+
result.warnings.push(i18n.t("uninstall:claudeMdNotFound"));
|
|
1237
|
+
result.success = true;
|
|
788
1238
|
}
|
|
789
1239
|
} catch (error) {
|
|
790
|
-
result.errors.push(
|
|
1240
|
+
result.errors.push(`Failed to remove CLAUDE.md: ${error.message}`);
|
|
1241
|
+
}
|
|
1242
|
+
return result;
|
|
1243
|
+
}
|
|
1244
|
+
/**
|
|
1245
|
+
* 5. Remove permissions and environment variables
|
|
1246
|
+
*/
|
|
1247
|
+
async removePermissionsAndEnvs() {
|
|
1248
|
+
const result = {
|
|
1249
|
+
success: false,
|
|
1250
|
+
removed: [],
|
|
1251
|
+
removedConfigs: [],
|
|
1252
|
+
errors: [],
|
|
1253
|
+
warnings: []
|
|
1254
|
+
};
|
|
1255
|
+
try {
|
|
1256
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
1257
|
+
if (await pathExists(settingsPath)) {
|
|
1258
|
+
const settings = readJsonConfig(settingsPath) || {};
|
|
1259
|
+
let modified = false;
|
|
1260
|
+
if (settings.permissions) {
|
|
1261
|
+
delete settings.permissions;
|
|
1262
|
+
result.removedConfigs.push("permissions configuration");
|
|
1263
|
+
modified = true;
|
|
1264
|
+
}
|
|
1265
|
+
if (settings.env) {
|
|
1266
|
+
delete settings.env;
|
|
1267
|
+
result.removedConfigs.push("environment variables");
|
|
1268
|
+
modified = true;
|
|
1269
|
+
}
|
|
1270
|
+
if (modified) {
|
|
1271
|
+
writeJsonConfig(settingsPath, settings);
|
|
1272
|
+
}
|
|
1273
|
+
result.success = true;
|
|
1274
|
+
} else {
|
|
1275
|
+
result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
|
|
1276
|
+
result.success = true;
|
|
1277
|
+
}
|
|
1278
|
+
} catch (error) {
|
|
1279
|
+
result.errors.push(`Failed to remove permissions and envs: ${error.message}`);
|
|
1280
|
+
}
|
|
1281
|
+
return result;
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* 6. Remove MCP servers from .claude.json (mcpServers field only)
|
|
1285
|
+
*/
|
|
1286
|
+
async removeMcps() {
|
|
1287
|
+
const result = {
|
|
1288
|
+
success: false,
|
|
1289
|
+
removed: [],
|
|
1290
|
+
removedConfigs: [],
|
|
1291
|
+
errors: [],
|
|
1292
|
+
warnings: []
|
|
1293
|
+
};
|
|
1294
|
+
try {
|
|
1295
|
+
const claudeJsonPath = join(homedir(), ".claude.json");
|
|
1296
|
+
if (await pathExists(claudeJsonPath)) {
|
|
1297
|
+
const config = readJsonConfig(claudeJsonPath) || {};
|
|
1298
|
+
if (config.mcpServers) {
|
|
1299
|
+
delete config.mcpServers;
|
|
1300
|
+
writeJsonConfig(claudeJsonPath, config);
|
|
1301
|
+
result.removedConfigs.push("mcpServers from .claude.json");
|
|
1302
|
+
}
|
|
1303
|
+
result.success = true;
|
|
1304
|
+
} else {
|
|
1305
|
+
result.warnings.push(i18n.t("uninstall:claudeJsonNotFound"));
|
|
1306
|
+
result.success = true;
|
|
1307
|
+
}
|
|
1308
|
+
} catch (error) {
|
|
1309
|
+
result.errors.push(`Failed to remove MCP servers: ${error.message}`);
|
|
1310
|
+
}
|
|
1311
|
+
return result;
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* 7. Uninstall Claude Code Router and remove configuration
|
|
1315
|
+
*/
|
|
1316
|
+
async uninstallCcr() {
|
|
1317
|
+
const result = {
|
|
1318
|
+
success: false,
|
|
1319
|
+
removed: [],
|
|
1320
|
+
removedConfigs: [],
|
|
1321
|
+
errors: [],
|
|
1322
|
+
warnings: []
|
|
1323
|
+
};
|
|
1324
|
+
try {
|
|
1325
|
+
const ccrPath = join(homedir(), ".claude-code-router");
|
|
1326
|
+
if (await pathExists(ccrPath)) {
|
|
1327
|
+
const trashResult = await moveToTrash(ccrPath);
|
|
1328
|
+
if (!trashResult[0]?.success) {
|
|
1329
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1330
|
+
}
|
|
1331
|
+
result.removed.push(".claude-code-router/");
|
|
1332
|
+
}
|
|
1333
|
+
try {
|
|
1334
|
+
await exec$1("npm", ["uninstall", "-g", "@musistudio/claude-code-router"]);
|
|
1335
|
+
result.removed.push("@musistudio/claude-code-router package");
|
|
1336
|
+
result.success = true;
|
|
1337
|
+
} catch (npmError) {
|
|
1338
|
+
if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
|
|
1339
|
+
result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
|
|
1340
|
+
result.success = true;
|
|
1341
|
+
} else {
|
|
1342
|
+
result.errors.push(`Failed to uninstall CCR package: ${npmError.message}`);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
} catch (error) {
|
|
1346
|
+
result.errors.push(`Failed to uninstall CCR: ${error.message}`);
|
|
1347
|
+
}
|
|
1348
|
+
return result;
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* 8. Uninstall CCometixLine
|
|
1352
|
+
*/
|
|
1353
|
+
async uninstallCcline() {
|
|
1354
|
+
const result = {
|
|
1355
|
+
success: false,
|
|
1356
|
+
removed: [],
|
|
1357
|
+
removedConfigs: [],
|
|
1358
|
+
errors: [],
|
|
1359
|
+
warnings: []
|
|
1360
|
+
};
|
|
1361
|
+
try {
|
|
1362
|
+
await exec$1("npm", ["uninstall", "-g", "@cometix/ccline"]);
|
|
1363
|
+
result.removed.push("@cometix/ccline package");
|
|
1364
|
+
result.success = true;
|
|
1365
|
+
} catch (error) {
|
|
1366
|
+
if (error.message.includes("not found") || error.message.includes("not installed")) {
|
|
1367
|
+
result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
|
|
1368
|
+
result.success = true;
|
|
1369
|
+
} else {
|
|
1370
|
+
result.errors.push(`Failed to uninstall CCometixLine: ${error.message}`);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
return result;
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* 9. Uninstall Claude Code and remove entire .claude.json
|
|
1377
|
+
*/
|
|
1378
|
+
async uninstallClaudeCode() {
|
|
1379
|
+
const result = {
|
|
1380
|
+
success: false,
|
|
1381
|
+
removed: [],
|
|
1382
|
+
removedConfigs: [],
|
|
1383
|
+
errors: [],
|
|
1384
|
+
warnings: []
|
|
1385
|
+
};
|
|
1386
|
+
try {
|
|
1387
|
+
const claudeJsonPath = join(homedir(), ".claude.json");
|
|
1388
|
+
if (await pathExists(claudeJsonPath)) {
|
|
1389
|
+
const trashResult = await moveToTrash(claudeJsonPath);
|
|
1390
|
+
if (!trashResult[0]?.success) {
|
|
1391
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1392
|
+
}
|
|
1393
|
+
result.removed.push(".claude.json (includes MCP configuration)");
|
|
1394
|
+
}
|
|
1395
|
+
try {
|
|
1396
|
+
const { uninstallCodeTool } = await import('./chunks/simple-config.mjs').then(function (n) { return n.dh; });
|
|
1397
|
+
const success = await uninstallCodeTool("claude-code");
|
|
1398
|
+
if (success) {
|
|
1399
|
+
result.removed.push("@anthropic-ai/claude-code");
|
|
1400
|
+
result.success = true;
|
|
1401
|
+
} else {
|
|
1402
|
+
result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: "" }));
|
|
1403
|
+
}
|
|
1404
|
+
} catch (npmError) {
|
|
1405
|
+
if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
|
|
1406
|
+
result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
|
|
1407
|
+
result.success = true;
|
|
1408
|
+
} else {
|
|
1409
|
+
result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${npmError.message}` }));
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
} catch (error) {
|
|
1413
|
+
result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${error.message}` }));
|
|
1414
|
+
}
|
|
1415
|
+
return result;
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* 10. Remove backup files
|
|
1419
|
+
*/
|
|
1420
|
+
async removeBackups() {
|
|
1421
|
+
const result = {
|
|
1422
|
+
success: false,
|
|
1423
|
+
removed: [],
|
|
1424
|
+
removedConfigs: [],
|
|
1425
|
+
errors: [],
|
|
1426
|
+
warnings: []
|
|
1427
|
+
};
|
|
1428
|
+
try {
|
|
1429
|
+
const backupPath = join(homedir(), ".claude", "backup");
|
|
1430
|
+
if (await pathExists(backupPath)) {
|
|
1431
|
+
const trashResult = await moveToTrash(backupPath);
|
|
1432
|
+
if (!trashResult[0]?.success) {
|
|
1433
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1434
|
+
}
|
|
1435
|
+
result.removed.push("backup/");
|
|
1436
|
+
result.success = true;
|
|
1437
|
+
} else {
|
|
1438
|
+
result.warnings.push(i18n.t("uninstall:backupsNotFound"));
|
|
1439
|
+
result.success = true;
|
|
1440
|
+
}
|
|
1441
|
+
} catch (error) {
|
|
1442
|
+
result.errors.push(`Failed to remove backups: ${error.message}`);
|
|
1443
|
+
}
|
|
1444
|
+
return result;
|
|
1445
|
+
}
|
|
1446
|
+
/**
|
|
1447
|
+
* 11. Remove CCJK preference configuration
|
|
1448
|
+
*/
|
|
1449
|
+
async removeZcfConfig() {
|
|
1450
|
+
const result = {
|
|
1451
|
+
success: false,
|
|
1452
|
+
removed: [],
|
|
1453
|
+
removedConfigs: [],
|
|
1454
|
+
errors: [],
|
|
1455
|
+
warnings: []
|
|
1456
|
+
};
|
|
1457
|
+
try {
|
|
1458
|
+
const zcfConfigPath = ZCF_CONFIG_FILE;
|
|
1459
|
+
const relativeName = zcfConfigPath.replace(homedir(), "~");
|
|
1460
|
+
if (await pathExists(zcfConfigPath)) {
|
|
1461
|
+
const trashResult = await moveToTrash(zcfConfigPath);
|
|
1462
|
+
if (!trashResult[0]?.success) {
|
|
1463
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1464
|
+
}
|
|
1465
|
+
result.removed.push(relativeName);
|
|
1466
|
+
result.success = true;
|
|
1467
|
+
} else {
|
|
1468
|
+
result.warnings.push(i18n.t("uninstall:ccjkConfigNotFound"));
|
|
1469
|
+
result.success = true;
|
|
1470
|
+
}
|
|
1471
|
+
} catch (error) {
|
|
1472
|
+
result.errors.push(`Failed to remove CCJK config: ${error.message}`);
|
|
1473
|
+
}
|
|
1474
|
+
return result;
|
|
1475
|
+
}
|
|
1476
|
+
/**
|
|
1477
|
+
* Complete uninstall - remove all directories and packages
|
|
1478
|
+
*/
|
|
1479
|
+
async completeUninstall() {
|
|
1480
|
+
const result = {
|
|
1481
|
+
success: true,
|
|
1482
|
+
removed: [],
|
|
1483
|
+
removedConfigs: [],
|
|
1484
|
+
errors: [],
|
|
1485
|
+
warnings: []
|
|
1486
|
+
};
|
|
1487
|
+
try {
|
|
1488
|
+
const directoriesToRemove = [
|
|
1489
|
+
{ path: join(homedir(), ".claude"), name: "~/.claude/" },
|
|
1490
|
+
{ path: join(homedir(), ".claude.json"), name: "~/.claude.json" },
|
|
1491
|
+
{ path: join(homedir(), ".claude-code-router"), name: "~/.claude-code-router/" }
|
|
1492
|
+
];
|
|
1493
|
+
for (const dir of directoriesToRemove) {
|
|
1494
|
+
try {
|
|
1495
|
+
if (await pathExists(dir.path)) {
|
|
1496
|
+
const trashResult = await moveToTrash(dir.path);
|
|
1497
|
+
if (!trashResult[0]?.success) {
|
|
1498
|
+
result.warnings.push(`Failed to move ${dir.name} to trash: ${trashResult[0]?.error || "Unknown error"}`);
|
|
1499
|
+
}
|
|
1500
|
+
result.removed.push(dir.name);
|
|
1501
|
+
}
|
|
1502
|
+
} catch (error) {
|
|
1503
|
+
result.warnings.push(`Failed to remove ${dir.name}: ${error.message}`);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
const packagesToUninstall = [
|
|
1507
|
+
"@musistudio/claude-code-router",
|
|
1508
|
+
"@cometix/ccline",
|
|
1509
|
+
"@anthropic-ai/claude-code"
|
|
1510
|
+
];
|
|
1511
|
+
for (const pkg of packagesToUninstall) {
|
|
1512
|
+
try {
|
|
1513
|
+
await exec$1("npm", ["uninstall", "-g", pkg]);
|
|
1514
|
+
result.removed.push(`${pkg} package`);
|
|
1515
|
+
} catch (error) {
|
|
1516
|
+
if (error.message.includes("not found") || error.message.includes("not installed")) {
|
|
1517
|
+
if (pkg.includes("claude-code-router")) {
|
|
1518
|
+
result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
|
|
1519
|
+
} else if (pkg.includes("ccline")) {
|
|
1520
|
+
result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
|
|
1521
|
+
} else {
|
|
1522
|
+
result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
|
|
1523
|
+
}
|
|
1524
|
+
} else {
|
|
1525
|
+
result.warnings.push(`Failed to uninstall ${pkg}: ${error.message}`);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
} catch (error) {
|
|
1530
|
+
result.errors.push(`Complete uninstall failed: ${error.message}`);
|
|
1531
|
+
result.success = false;
|
|
1532
|
+
}
|
|
1533
|
+
return result;
|
|
1534
|
+
}
|
|
1535
|
+
/**
|
|
1536
|
+
* Custom uninstall with conflict resolution
|
|
1537
|
+
*/
|
|
1538
|
+
async customUninstall(selectedItems) {
|
|
1539
|
+
const resolvedItems = this.resolveConflicts(selectedItems);
|
|
1540
|
+
const results = [];
|
|
1541
|
+
for (const item of resolvedItems) {
|
|
1542
|
+
try {
|
|
1543
|
+
const result = await this.executeUninstallItem(item);
|
|
1544
|
+
results.push(result);
|
|
1545
|
+
} catch (error) {
|
|
1546
|
+
results.push({
|
|
1547
|
+
success: false,
|
|
1548
|
+
removed: [],
|
|
1549
|
+
removedConfigs: [],
|
|
1550
|
+
errors: [`Failed to execute ${item}: ${error.message}`],
|
|
1551
|
+
warnings: []
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
return results;
|
|
1556
|
+
}
|
|
1557
|
+
/**
|
|
1558
|
+
* Resolve conflicts between uninstall items
|
|
1559
|
+
*/
|
|
1560
|
+
resolveConflicts(items) {
|
|
1561
|
+
const resolved = [...items];
|
|
1562
|
+
for (const [primary, conflicts] of this.conflictResolution) {
|
|
1563
|
+
if (resolved.includes(primary)) {
|
|
1564
|
+
conflicts.forEach((conflict) => {
|
|
1565
|
+
const index = resolved.indexOf(conflict);
|
|
1566
|
+
if (index > -1) {
|
|
1567
|
+
resolved.splice(index, 1);
|
|
1568
|
+
}
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
return resolved;
|
|
1573
|
+
}
|
|
1574
|
+
/**
|
|
1575
|
+
* Execute uninstall for a specific item
|
|
1576
|
+
*/
|
|
1577
|
+
async executeUninstallItem(item) {
|
|
1578
|
+
switch (item) {
|
|
1579
|
+
case "output-styles":
|
|
1580
|
+
return await this.removeOutputStyles();
|
|
1581
|
+
case "commands":
|
|
1582
|
+
return await this.removeCustomCommands();
|
|
1583
|
+
case "agents":
|
|
1584
|
+
return await this.removeCustomAgents();
|
|
1585
|
+
case "claude-md":
|
|
1586
|
+
return await this.removeClaudeMd();
|
|
1587
|
+
case "permissions-envs":
|
|
1588
|
+
return await this.removePermissionsAndEnvs();
|
|
1589
|
+
case "mcps":
|
|
1590
|
+
return await this.removeMcps();
|
|
1591
|
+
case "ccr":
|
|
1592
|
+
return await this.uninstallCcr();
|
|
1593
|
+
case "ccline":
|
|
1594
|
+
return await this.uninstallCcline();
|
|
1595
|
+
case "claude-code":
|
|
1596
|
+
return await this.uninstallClaudeCode();
|
|
1597
|
+
case "backups":
|
|
1598
|
+
return await this.removeBackups();
|
|
1599
|
+
case "ccjk-config":
|
|
1600
|
+
return await this.removeZcfConfig();
|
|
1601
|
+
default:
|
|
1602
|
+
return {
|
|
1603
|
+
success: false,
|
|
1604
|
+
removed: [],
|
|
1605
|
+
removedConfigs: [],
|
|
1606
|
+
errors: [`Unknown uninstall item: ${item}`],
|
|
1607
|
+
warnings: []
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
async function uninstall(options = {}) {
|
|
1614
|
+
try {
|
|
1615
|
+
ensureI18nInitialized();
|
|
1616
|
+
let codeType;
|
|
1617
|
+
if (options.codeType) {
|
|
1618
|
+
try {
|
|
1619
|
+
codeType = await resolveCodeType$1(options.codeType);
|
|
1620
|
+
} catch (error) {
|
|
1621
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1622
|
+
console.error(ansis.red(`${i18n.t("errors:generalError")} ${errorMessage}`));
|
|
1623
|
+
const config = readZcfConfig();
|
|
1624
|
+
codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
|
|
1625
|
+
}
|
|
1626
|
+
} else {
|
|
1627
|
+
const config = readZcfConfig();
|
|
1628
|
+
codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
|
|
1629
|
+
}
|
|
1630
|
+
const uninstaller = new ZcfUninstaller(options.lang || "en");
|
|
1631
|
+
if (codeType === "codex") {
|
|
1632
|
+
const { runCodexUninstall } = await import('./chunks/simple-config.mjs').then(function (n) { return n.dg; });
|
|
1633
|
+
await runCodexUninstall();
|
|
1634
|
+
return;
|
|
1635
|
+
}
|
|
1636
|
+
if (options.mode && options.mode !== "interactive") {
|
|
1637
|
+
if (options.mode === "complete") {
|
|
1638
|
+
await executeCompleteUninstall(uninstaller);
|
|
1639
|
+
return;
|
|
1640
|
+
} else if (options.mode === "custom" && options.items) {
|
|
1641
|
+
let items;
|
|
1642
|
+
if (typeof options.items === "string") {
|
|
1643
|
+
items = options.items.split(",").map((item) => item.trim());
|
|
1644
|
+
} else {
|
|
1645
|
+
items = options.items;
|
|
1646
|
+
}
|
|
1647
|
+
await executeCustomUninstall(uninstaller, items);
|
|
1648
|
+
return;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
await showInteractiveUninstall(uninstaller);
|
|
1652
|
+
} catch (error) {
|
|
1653
|
+
if (!handleExitPromptError(error)) {
|
|
1654
|
+
handleGeneralError(error);
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
async function showInteractiveUninstall(uninstaller) {
|
|
1659
|
+
console.log(ansis.cyan.bold(i18n.t("uninstall:title")));
|
|
1660
|
+
console.log("");
|
|
1661
|
+
const { mainChoice } = await inquirer.prompt({
|
|
1662
|
+
type: "list",
|
|
1663
|
+
name: "mainChoice",
|
|
1664
|
+
message: i18n.t("uninstall:selectMainOption"),
|
|
1665
|
+
choices: addNumbersToChoices([
|
|
1666
|
+
{
|
|
1667
|
+
name: `${i18n.t("uninstall:completeUninstall")} - ${ansis.gray(i18n.t("uninstall:completeUninstallDesc"))}`,
|
|
1668
|
+
value: "complete",
|
|
1669
|
+
short: i18n.t("uninstall:completeUninstall")
|
|
1670
|
+
},
|
|
1671
|
+
{
|
|
1672
|
+
name: `${i18n.t("uninstall:customUninstall")} - ${ansis.gray(i18n.t("uninstall:customUninstallDesc"))}`,
|
|
1673
|
+
value: "custom",
|
|
1674
|
+
short: i18n.t("uninstall:customUninstall")
|
|
1675
|
+
}
|
|
1676
|
+
])
|
|
1677
|
+
});
|
|
1678
|
+
if (!mainChoice) {
|
|
1679
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
if (mainChoice === "complete") {
|
|
1683
|
+
await executeCompleteUninstall(uninstaller);
|
|
1684
|
+
} else {
|
|
1685
|
+
await showCustomUninstallMenu(uninstaller);
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
async function showCustomUninstallMenu(uninstaller) {
|
|
1689
|
+
console.log("");
|
|
1690
|
+
console.log(ansis.cyan(i18n.t("uninstall:selectCustomItems")));
|
|
1691
|
+
const { customItems } = await inquirer.prompt({
|
|
1692
|
+
type: "checkbox",
|
|
1693
|
+
name: "customItems",
|
|
1694
|
+
message: `${i18n.t("uninstall:selectItemsToRemove")} ${i18n.t("common:multiSelectHint")}`,
|
|
1695
|
+
choices: [
|
|
1696
|
+
{
|
|
1697
|
+
name: i18n.t("uninstall:outputStyles"),
|
|
1698
|
+
value: "output-styles"
|
|
1699
|
+
},
|
|
1700
|
+
{
|
|
1701
|
+
name: i18n.t("uninstall:commands"),
|
|
1702
|
+
value: "commands"
|
|
1703
|
+
},
|
|
1704
|
+
{
|
|
1705
|
+
name: i18n.t("uninstall:agents"),
|
|
1706
|
+
value: "agents"
|
|
1707
|
+
},
|
|
1708
|
+
{
|
|
1709
|
+
name: i18n.t("uninstall:claudeMd"),
|
|
1710
|
+
value: "claude-md"
|
|
1711
|
+
},
|
|
1712
|
+
{
|
|
1713
|
+
name: i18n.t("uninstall:permissionsEnvs"),
|
|
1714
|
+
value: "permissions-envs"
|
|
1715
|
+
},
|
|
1716
|
+
{
|
|
1717
|
+
name: i18n.t("uninstall:mcps"),
|
|
1718
|
+
value: "mcps"
|
|
1719
|
+
},
|
|
1720
|
+
{
|
|
1721
|
+
name: i18n.t("uninstall:ccr"),
|
|
1722
|
+
value: "ccr"
|
|
1723
|
+
},
|
|
1724
|
+
{
|
|
1725
|
+
name: i18n.t("uninstall:ccline"),
|
|
1726
|
+
value: "ccline"
|
|
1727
|
+
},
|
|
1728
|
+
{
|
|
1729
|
+
name: i18n.t("uninstall:claudeCode"),
|
|
1730
|
+
value: "claude-code"
|
|
1731
|
+
},
|
|
1732
|
+
{
|
|
1733
|
+
name: i18n.t("uninstall:backups"),
|
|
1734
|
+
value: "backups"
|
|
1735
|
+
},
|
|
1736
|
+
{
|
|
1737
|
+
name: i18n.t("uninstall:ccjkConfig"),
|
|
1738
|
+
value: "ccjk-config"
|
|
1739
|
+
}
|
|
1740
|
+
],
|
|
1741
|
+
validate: (answers) => {
|
|
1742
|
+
if (answers.length === 0) {
|
|
1743
|
+
return i18n.t("uninstall:selectAtLeastOne");
|
|
1744
|
+
}
|
|
1745
|
+
return true;
|
|
1746
|
+
}
|
|
1747
|
+
});
|
|
1748
|
+
if (!customItems || customItems.length === 0) {
|
|
1749
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
await executeCustomUninstall(uninstaller, customItems);
|
|
1753
|
+
}
|
|
1754
|
+
async function executeCompleteUninstall(uninstaller) {
|
|
1755
|
+
console.log("");
|
|
1756
|
+
console.log(ansis.red.bold(i18n.t("uninstall:executingComplete")));
|
|
1757
|
+
console.log(ansis.yellow(i18n.t("uninstall:completeWarning")));
|
|
1758
|
+
const confirm = await promptBoolean({
|
|
1759
|
+
message: i18n.t("uninstall:confirmComplete"),
|
|
1760
|
+
defaultValue: false
|
|
1761
|
+
});
|
|
1762
|
+
if (!confirm) {
|
|
1763
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
console.log("");
|
|
1767
|
+
console.log(ansis.cyan(i18n.t("uninstall:processingComplete")));
|
|
1768
|
+
const result = await uninstaller.completeUninstall();
|
|
1769
|
+
displayUninstallResult("complete", [result]);
|
|
1770
|
+
}
|
|
1771
|
+
async function executeCustomUninstall(uninstaller, items) {
|
|
1772
|
+
console.log("");
|
|
1773
|
+
console.log(ansis.cyan(i18n.t("uninstall:executingCustom")));
|
|
1774
|
+
console.log(ansis.gray(i18n.t("uninstall:selectedItems")));
|
|
1775
|
+
items.forEach((item) => {
|
|
1776
|
+
console.log(` \u2022 ${i18n.t(`uninstall:${item}`)}`);
|
|
1777
|
+
});
|
|
1778
|
+
const confirm = await promptBoolean({
|
|
1779
|
+
message: i18n.t("uninstall:confirmCustom"),
|
|
1780
|
+
defaultValue: false
|
|
1781
|
+
});
|
|
1782
|
+
if (!confirm) {
|
|
1783
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1786
|
+
console.log("");
|
|
1787
|
+
console.log(ansis.cyan(i18n.t("uninstall:processingCustom")));
|
|
1788
|
+
const results = await uninstaller.customUninstall(items);
|
|
1789
|
+
displayUninstallResult("custom", results);
|
|
1790
|
+
}
|
|
1791
|
+
function displayUninstallResult(mode, results) {
|
|
1792
|
+
console.log("");
|
|
1793
|
+
console.log(ansis.cyan("\u2500".repeat(50)));
|
|
1794
|
+
let totalSuccess = 0;
|
|
1795
|
+
let totalErrors = 0;
|
|
1796
|
+
let totalWarnings = 0;
|
|
1797
|
+
results.forEach((result) => {
|
|
1798
|
+
if (result.success) {
|
|
1799
|
+
totalSuccess++;
|
|
1800
|
+
}
|
|
1801
|
+
if (result.removed && result.removed.length > 0) {
|
|
1802
|
+
console.log(ansis.green(`\u{1F5D1}\uFE0F ${i18n.t("uninstall:movedToTrash")}:`));
|
|
1803
|
+
result.removed.forEach((item) => {
|
|
1804
|
+
console.log(ansis.gray(` \u2022 ${item}`));
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
if (result.removedConfigs && result.removedConfigs.length > 0) {
|
|
1808
|
+
console.log(ansis.green(`\u2714 ${i18n.t("uninstall:removedConfigs")}:`));
|
|
1809
|
+
result.removedConfigs.forEach((item) => {
|
|
1810
|
+
console.log(ansis.gray(` \u2022 ${item}`));
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
if (result.errors && result.errors.length > 0) {
|
|
1814
|
+
totalErrors += result.errors.length;
|
|
1815
|
+
console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errors")}:`));
|
|
1816
|
+
result.errors.forEach((error) => {
|
|
1817
|
+
console.log(ansis.red(` \u2022 ${error}`));
|
|
1818
|
+
});
|
|
1819
|
+
}
|
|
1820
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
1821
|
+
totalWarnings += result.warnings.length;
|
|
1822
|
+
console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warnings")}:`));
|
|
1823
|
+
result.warnings.forEach((warning) => {
|
|
1824
|
+
console.log(ansis.yellow(` \u2022 ${warning}`));
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1827
|
+
});
|
|
1828
|
+
const totalRemovedFiles = results.reduce((count, result) => count + (result.removed?.length || 0), 0);
|
|
1829
|
+
const totalRemovedConfigs = results.reduce((count, result) => count + (result.removedConfigs?.length || 0), 0);
|
|
1830
|
+
console.log("");
|
|
1831
|
+
console.log(ansis.cyan("\u2500".repeat(50)));
|
|
1832
|
+
if (mode === "complete") {
|
|
1833
|
+
if (totalErrors === 0) {
|
|
1834
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:completeSuccess")}`));
|
|
1835
|
+
} else {
|
|
1836
|
+
console.log(ansis.yellow.bold(`\u26A0 ${i18n.t("uninstall:completePartialSuccess")}`));
|
|
1837
|
+
}
|
|
1838
|
+
} else {
|
|
1839
|
+
if (totalRemovedFiles > 0 && totalRemovedConfigs > 0) {
|
|
1840
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessBoth", {
|
|
1841
|
+
fileCount: totalRemovedFiles,
|
|
1842
|
+
configCount: totalRemovedConfigs
|
|
1843
|
+
})}`));
|
|
1844
|
+
} else if (totalRemovedFiles > 0) {
|
|
1845
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessFiles", {
|
|
1846
|
+
count: totalRemovedFiles
|
|
1847
|
+
})}`));
|
|
1848
|
+
} else if (totalRemovedConfigs > 0) {
|
|
1849
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessConfigs", {
|
|
1850
|
+
count: totalRemovedConfigs
|
|
1851
|
+
})}`));
|
|
1852
|
+
} else {
|
|
1853
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccess", { count: totalSuccess })}`));
|
|
1854
|
+
}
|
|
1855
|
+
if (totalErrors > 0) {
|
|
1856
|
+
console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errorsCount", { count: totalErrors })}`));
|
|
1857
|
+
}
|
|
1858
|
+
if (totalWarnings > 0) {
|
|
1859
|
+
console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warningsCount", { count: totalWarnings })}`));
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
console.log("");
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
function resolveCodeToolType(optionValue, savedValue) {
|
|
1866
|
+
if (optionValue !== void 0) {
|
|
1867
|
+
const resolved = resolveCodeToolType$1(optionValue);
|
|
1868
|
+
if (resolved !== DEFAULT_CODE_TOOL_TYPE || optionValue === DEFAULT_CODE_TOOL_TYPE) {
|
|
1869
|
+
return resolved;
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
if (savedValue && isCodeToolType(savedValue)) {
|
|
1873
|
+
return savedValue;
|
|
1874
|
+
}
|
|
1875
|
+
return DEFAULT_CODE_TOOL_TYPE;
|
|
1876
|
+
}
|
|
1877
|
+
async function update(options = {}) {
|
|
1878
|
+
try {
|
|
1879
|
+
if (!options.skipBanner) {
|
|
1880
|
+
displayBanner(i18n.t("cli:banner.updateSubtitle"));
|
|
1881
|
+
}
|
|
1882
|
+
const zcfConfig = readZcfConfig();
|
|
1883
|
+
const codeToolType = resolveCodeToolType(options.codeType, zcfConfig?.codeToolType);
|
|
1884
|
+
options.codeType = codeToolType;
|
|
1885
|
+
if (codeToolType === "codex") {
|
|
1886
|
+
await runCodexUpdate();
|
|
1887
|
+
const newPreferredLang = options.configLang || zcfConfig?.preferredLang;
|
|
1888
|
+
if (newPreferredLang) {
|
|
1889
|
+
updateZcfConfig({
|
|
1890
|
+
version,
|
|
1891
|
+
preferredLang: newPreferredLang,
|
|
1892
|
+
codeToolType
|
|
1893
|
+
});
|
|
1894
|
+
} else {
|
|
1895
|
+
updateZcfConfig({
|
|
1896
|
+
version,
|
|
1897
|
+
codeToolType
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
return;
|
|
1901
|
+
}
|
|
1902
|
+
const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.df; });
|
|
1903
|
+
const configLang = await resolveTemplateLanguage(
|
|
1904
|
+
options.configLang,
|
|
1905
|
+
// Command line option
|
|
1906
|
+
zcfConfig,
|
|
1907
|
+
options.skipPrompt
|
|
1908
|
+
// Non-interactive mode flag
|
|
1909
|
+
);
|
|
1910
|
+
const aiOutputLang = await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig, options.skipPrompt);
|
|
1911
|
+
console.log(ansis.cyan(`
|
|
1912
|
+
${i18n.t("configuration:updatingPrompts")}
|
|
1913
|
+
`));
|
|
1914
|
+
await updatePromptOnly(aiOutputLang);
|
|
1915
|
+
await selectAndInstallWorkflows(configLang);
|
|
1916
|
+
await checkClaudeCodeVersionAndPrompt(false);
|
|
1917
|
+
updateZcfConfig({
|
|
1918
|
+
version,
|
|
1919
|
+
templateLang: configLang,
|
|
1920
|
+
// 保存模板语言选择
|
|
1921
|
+
aiOutputLang,
|
|
1922
|
+
codeToolType
|
|
1923
|
+
});
|
|
1924
|
+
} catch (error) {
|
|
1925
|
+
if (!handleExitPromptError(error)) {
|
|
1926
|
+
handleGeneralError(error);
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
const CODE_TOOL_LABELS = {
|
|
1932
|
+
"claude-code": "Claude Code",
|
|
1933
|
+
"codex": "Codex",
|
|
1934
|
+
"aider": "Aider",
|
|
1935
|
+
"continue": "Continue",
|
|
1936
|
+
"cline": "Cline",
|
|
1937
|
+
"cursor": "Cursor"
|
|
1938
|
+
};
|
|
1939
|
+
function getCurrentCodeTool() {
|
|
1940
|
+
const config = readZcfConfig();
|
|
1941
|
+
if (config?.codeToolType && isCodeToolType(config.codeToolType)) {
|
|
1942
|
+
return config.codeToolType;
|
|
1943
|
+
}
|
|
1944
|
+
return DEFAULT_CODE_TOOL_TYPE;
|
|
1945
|
+
}
|
|
1946
|
+
function printSeparator() {
|
|
1947
|
+
console.log(`
|
|
1948
|
+
${ansis.dim("\u2500".repeat(50))}
|
|
1949
|
+
`);
|
|
1950
|
+
}
|
|
1951
|
+
function getCodeToolLabel(codeTool) {
|
|
1952
|
+
return CODE_TOOL_LABELS[codeTool] || codeTool;
|
|
1953
|
+
}
|
|
1954
|
+
async function promptCodeToolSelection(current) {
|
|
1955
|
+
const choices = addNumbersToChoices(Object.entries(CODE_TOOL_LABELS).map(([value, label]) => ({
|
|
1956
|
+
name: label,
|
|
1957
|
+
value,
|
|
1958
|
+
short: label
|
|
1959
|
+
})));
|
|
1960
|
+
const { tool } = await inquirer.prompt({
|
|
1961
|
+
type: "list",
|
|
1962
|
+
name: "tool",
|
|
1963
|
+
message: i18n.t("menu:switchCodeToolPrompt"),
|
|
1964
|
+
default: current,
|
|
1965
|
+
choices
|
|
1966
|
+
});
|
|
1967
|
+
if (!tool) {
|
|
1968
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1969
|
+
return null;
|
|
1970
|
+
}
|
|
1971
|
+
return tool;
|
|
1972
|
+
}
|
|
1973
|
+
async function handleCodeToolSwitch(current) {
|
|
1974
|
+
const newTool = await promptCodeToolSelection(current);
|
|
1975
|
+
if (!newTool || newTool === current) {
|
|
1976
|
+
return false;
|
|
1977
|
+
}
|
|
1978
|
+
updateZcfConfig({ codeToolType: newTool });
|
|
1979
|
+
console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(newTool) })}`));
|
|
1980
|
+
return true;
|
|
1981
|
+
}
|
|
1982
|
+
async function showSuperpowersMenu() {
|
|
1983
|
+
console.log(ansis.cyan(i18n.t("superpowers:menu.title")));
|
|
1984
|
+
console.log(" -------- Superpowers --------");
|
|
1985
|
+
console.log(
|
|
1986
|
+
` ${ansis.cyan("1.")} ${i18n.t("superpowers:menu.install")} ${ansis.gray(`- ${i18n.t("superpowers:menu.installDesc")}`)}`
|
|
1987
|
+
);
|
|
1988
|
+
console.log(
|
|
1989
|
+
` ${ansis.cyan("2.")} ${i18n.t("superpowers:menu.uninstall")} ${ansis.gray(`- ${i18n.t("superpowers:menu.uninstallDesc")}`)}`
|
|
1990
|
+
);
|
|
1991
|
+
console.log(
|
|
1992
|
+
` ${ansis.cyan("3.")} ${i18n.t("superpowers:menu.update")} ${ansis.gray(`- ${i18n.t("superpowers:menu.updateDesc")}`)}`
|
|
1993
|
+
);
|
|
1994
|
+
console.log(
|
|
1995
|
+
` ${ansis.cyan("4.")} ${i18n.t("superpowers:menu.checkStatus")} ${ansis.gray(`- ${i18n.t("superpowers:menu.checkStatusDesc")}`)}`
|
|
1996
|
+
);
|
|
1997
|
+
console.log(
|
|
1998
|
+
` ${ansis.cyan("5.")} ${i18n.t("superpowers:menu.viewSkills")} ${ansis.gray(`- ${i18n.t("superpowers:menu.viewSkillsDesc")}`)}`
|
|
1999
|
+
);
|
|
2000
|
+
console.log(` ${ansis.cyan("0.")} ${i18n.t("superpowers:menu.back")}`);
|
|
2001
|
+
console.log("");
|
|
2002
|
+
const { choice } = await inquirer.prompt({
|
|
2003
|
+
type: "input",
|
|
2004
|
+
name: "choice",
|
|
2005
|
+
message: i18n.t("common:enterChoice"),
|
|
2006
|
+
validate: (value) => {
|
|
2007
|
+
const valid = ["1", "2", "3", "4", "5", "0"];
|
|
2008
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
791
2009
|
}
|
|
792
|
-
|
|
2010
|
+
});
|
|
2011
|
+
if (!choice) {
|
|
2012
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2013
|
+
return;
|
|
793
2014
|
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
if (
|
|
808
|
-
|
|
809
|
-
if (!trashResult[0]?.success) {
|
|
810
|
-
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
811
|
-
}
|
|
812
|
-
result.removed.push("backup/");
|
|
813
|
-
result.success = true;
|
|
814
|
-
} else {
|
|
815
|
-
result.warnings.push(i18n.t("uninstall:backupsNotFound"));
|
|
816
|
-
result.success = true;
|
|
2015
|
+
switch (choice) {
|
|
2016
|
+
case "1": {
|
|
2017
|
+
const { method } = await inquirer.prompt({
|
|
2018
|
+
type: "list",
|
|
2019
|
+
name: "method",
|
|
2020
|
+
message: i18n.t("superpowers:install.selectMethod"),
|
|
2021
|
+
choices: addNumbersToChoices([
|
|
2022
|
+
{ name: i18n.t("superpowers:install.methodNpm"), value: "npm" },
|
|
2023
|
+
{ name: i18n.t("superpowers:install.methodGit"), value: "git" }
|
|
2024
|
+
])
|
|
2025
|
+
});
|
|
2026
|
+
if (method === "npm") {
|
|
2027
|
+
await installSuperpowers({ lang: i18n.language });
|
|
2028
|
+
} else if (method === "git") {
|
|
2029
|
+
await installSuperpowersViaGit();
|
|
817
2030
|
}
|
|
818
|
-
|
|
819
|
-
result.errors.push(`Failed to remove backups: ${error.message}`);
|
|
2031
|
+
break;
|
|
820
2032
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
const zcfConfigPath = ZCF_CONFIG_FILE;
|
|
836
|
-
const relativeName = zcfConfigPath.replace(homedir(), "~");
|
|
837
|
-
if (await pathExists(zcfConfigPath)) {
|
|
838
|
-
const trashResult = await moveToTrash(zcfConfigPath);
|
|
839
|
-
if (!trashResult[0]?.success) {
|
|
840
|
-
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
841
|
-
}
|
|
842
|
-
result.removed.push(relativeName);
|
|
843
|
-
result.success = true;
|
|
2033
|
+
case "2": {
|
|
2034
|
+
const status = await checkSuperpowersInstalled();
|
|
2035
|
+
if (!status.installed) {
|
|
2036
|
+
console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
|
|
2037
|
+
break;
|
|
2038
|
+
}
|
|
2039
|
+
const { confirm } = await inquirer.prompt({
|
|
2040
|
+
type: "confirm",
|
|
2041
|
+
name: "confirm",
|
|
2042
|
+
message: i18n.t("superpowers:uninstall.confirm"),
|
|
2043
|
+
default: false
|
|
2044
|
+
});
|
|
2045
|
+
if (confirm) {
|
|
2046
|
+
await uninstallSuperpowers();
|
|
844
2047
|
} else {
|
|
845
|
-
|
|
846
|
-
result.success = true;
|
|
2048
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
847
2049
|
}
|
|
848
|
-
|
|
849
|
-
result.errors.push(`Failed to remove CCJK config: ${error.message}`);
|
|
2050
|
+
break;
|
|
850
2051
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
async completeUninstall() {
|
|
857
|
-
const result = {
|
|
858
|
-
success: true,
|
|
859
|
-
removed: [],
|
|
860
|
-
removedConfigs: [],
|
|
861
|
-
errors: [],
|
|
862
|
-
warnings: []
|
|
863
|
-
};
|
|
864
|
-
try {
|
|
865
|
-
const directoriesToRemove = [
|
|
866
|
-
{ path: join(homedir(), ".claude"), name: "~/.claude/" },
|
|
867
|
-
{ path: join(homedir(), ".claude.json"), name: "~/.claude.json" },
|
|
868
|
-
{ path: join(homedir(), ".claude-code-router"), name: "~/.claude-code-router/" }
|
|
869
|
-
];
|
|
870
|
-
for (const dir of directoriesToRemove) {
|
|
871
|
-
try {
|
|
872
|
-
if (await pathExists(dir.path)) {
|
|
873
|
-
const trashResult = await moveToTrash(dir.path);
|
|
874
|
-
if (!trashResult[0]?.success) {
|
|
875
|
-
result.warnings.push(`Failed to move ${dir.name} to trash: ${trashResult[0]?.error || "Unknown error"}`);
|
|
876
|
-
}
|
|
877
|
-
result.removed.push(dir.name);
|
|
878
|
-
}
|
|
879
|
-
} catch (error) {
|
|
880
|
-
result.warnings.push(`Failed to remove ${dir.name}: ${error.message}`);
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
const packagesToUninstall = [
|
|
884
|
-
"@musistudio/claude-code-router",
|
|
885
|
-
"@cometix/ccline",
|
|
886
|
-
"@anthropic-ai/claude-code"
|
|
887
|
-
];
|
|
888
|
-
for (const pkg of packagesToUninstall) {
|
|
889
|
-
try {
|
|
890
|
-
await exec$1("npm", ["uninstall", "-g", pkg]);
|
|
891
|
-
result.removed.push(`${pkg} package`);
|
|
892
|
-
} catch (error) {
|
|
893
|
-
if (error.message.includes("not found") || error.message.includes("not installed")) {
|
|
894
|
-
if (pkg.includes("claude-code-router")) {
|
|
895
|
-
result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
|
|
896
|
-
} else if (pkg.includes("ccline")) {
|
|
897
|
-
result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
|
|
898
|
-
} else {
|
|
899
|
-
result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
|
|
900
|
-
}
|
|
901
|
-
} else {
|
|
902
|
-
result.warnings.push(`Failed to uninstall ${pkg}: ${error.message}`);
|
|
903
|
-
}
|
|
904
|
-
}
|
|
2052
|
+
case "3": {
|
|
2053
|
+
const status = await checkSuperpowersInstalled();
|
|
2054
|
+
if (!status.installed) {
|
|
2055
|
+
console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
|
|
2056
|
+
break;
|
|
905
2057
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
result.success = false;
|
|
2058
|
+
await updateSuperpowers();
|
|
2059
|
+
break;
|
|
909
2060
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
const resolvedItems = this.resolveConflicts(selectedItems);
|
|
917
|
-
const results = [];
|
|
918
|
-
for (const item of resolvedItems) {
|
|
919
|
-
try {
|
|
920
|
-
const result = await this.executeUninstallItem(item);
|
|
921
|
-
results.push(result);
|
|
922
|
-
} catch (error) {
|
|
923
|
-
results.push({
|
|
924
|
-
success: false,
|
|
925
|
-
removed: [],
|
|
926
|
-
removedConfigs: [],
|
|
927
|
-
errors: [`Failed to execute ${item}: ${error.message}`],
|
|
928
|
-
warnings: []
|
|
929
|
-
});
|
|
2061
|
+
case "4": {
|
|
2062
|
+
const status = await checkSuperpowersInstalled();
|
|
2063
|
+
if (status.installed) {
|
|
2064
|
+
console.log(ansis.green(`\u2714 ${i18n.t("superpowers:status.installed")}`));
|
|
2065
|
+
} else {
|
|
2066
|
+
console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
|
|
930
2067
|
}
|
|
2068
|
+
break;
|
|
931
2069
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
}
|
|
2070
|
+
case "5": {
|
|
2071
|
+
const status = await checkSuperpowersInstalled();
|
|
2072
|
+
if (!status.installed) {
|
|
2073
|
+
console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
|
|
2074
|
+
break;
|
|
2075
|
+
}
|
|
2076
|
+
const skills = await getSuperpowersSkills();
|
|
2077
|
+
if (skills.length === 0) {
|
|
2078
|
+
console.log(ansis.yellow(i18n.t("superpowers:skills.noSkills")));
|
|
2079
|
+
} else {
|
|
2080
|
+
console.log(ansis.cyan(i18n.t("superpowers:skills.available")));
|
|
2081
|
+
skills.forEach((skill) => {
|
|
2082
|
+
console.log(` ${ansis.green("\u2022")} ${skill}`);
|
|
946
2083
|
});
|
|
947
2084
|
}
|
|
2085
|
+
break;
|
|
948
2086
|
}
|
|
949
|
-
|
|
2087
|
+
case "0":
|
|
2088
|
+
return;
|
|
2089
|
+
default:
|
|
2090
|
+
return;
|
|
950
2091
|
}
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
return await this.removeZcfConfig();
|
|
978
|
-
default:
|
|
979
|
-
return {
|
|
980
|
-
success: false,
|
|
981
|
-
removed: [],
|
|
982
|
-
removedConfigs: [],
|
|
983
|
-
errors: [`Unknown uninstall item: ${item}`],
|
|
984
|
-
warnings: []
|
|
985
|
-
};
|
|
2092
|
+
printSeparator();
|
|
2093
|
+
}
|
|
2094
|
+
async function showMarketplaceMenu() {
|
|
2095
|
+
console.log(ansis.cyan(i18n.t("marketplace:menu.title")));
|
|
2096
|
+
console.log(" -------- Marketplace --------");
|
|
2097
|
+
console.log(
|
|
2098
|
+
` ${ansis.cyan("1.")} ${i18n.t("marketplace:menu.search")} ${ansis.gray(`- ${i18n.t("marketplace:commands.search")}`)}`
|
|
2099
|
+
);
|
|
2100
|
+
console.log(
|
|
2101
|
+
` ${ansis.cyan("2.")} ${i18n.t("marketplace:menu.browse")} ${ansis.gray(`- Browse by category`)}`
|
|
2102
|
+
);
|
|
2103
|
+
console.log(
|
|
2104
|
+
` ${ansis.cyan("3.")} ${i18n.t("marketplace:menu.installed")} ${ansis.gray(`- ${i18n.t("marketplace:commands.list")}`)}`
|
|
2105
|
+
);
|
|
2106
|
+
console.log(
|
|
2107
|
+
` ${ansis.cyan("4.")} ${i18n.t("marketplace:menu.updates")} ${ansis.gray(`- ${i18n.t("marketplace:commands.update")}`)}`
|
|
2108
|
+
);
|
|
2109
|
+
console.log(` ${ansis.cyan("0.")} ${i18n.t("marketplace:menu.back")}`);
|
|
2110
|
+
console.log("");
|
|
2111
|
+
const { choice } = await inquirer.prompt({
|
|
2112
|
+
type: "input",
|
|
2113
|
+
name: "choice",
|
|
2114
|
+
message: i18n.t("common:enterChoice"),
|
|
2115
|
+
validate: (value) => {
|
|
2116
|
+
const valid = ["1", "2", "3", "4", "0"];
|
|
2117
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
986
2118
|
}
|
|
2119
|
+
});
|
|
2120
|
+
if (!choice) {
|
|
2121
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2122
|
+
return;
|
|
987
2123
|
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
2124
|
+
switch (choice) {
|
|
2125
|
+
case "1": {
|
|
2126
|
+
const { query } = await inquirer.prompt({
|
|
2127
|
+
type: "input",
|
|
2128
|
+
name: "query",
|
|
2129
|
+
message: i18n.t("marketplace:prompts.searchQuery")
|
|
2130
|
+
});
|
|
2131
|
+
if (query) {
|
|
2132
|
+
console.log(i18n.t("marketplace:searching", { query }));
|
|
2133
|
+
try {
|
|
2134
|
+
const result = await searchPackages({ query, limit: 10 });
|
|
2135
|
+
if (result.packages.length === 0) {
|
|
2136
|
+
console.log(ansis.yellow(i18n.t("marketplace:noResults")));
|
|
2137
|
+
} else {
|
|
2138
|
+
console.log(ansis.green(i18n.t("marketplace:searchResults", { count: result.total })));
|
|
2139
|
+
console.log("");
|
|
2140
|
+
for (const pkg of result.packages) {
|
|
2141
|
+
console.log(` ${ansis.cyan(pkg.id)} ${ansis.gray(`v${pkg.version}`)}`);
|
|
2142
|
+
const description = pkg.description.en || Object.values(pkg.description)[0] || "";
|
|
2143
|
+
console.log(` ${ansis.dim(description)}`);
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
} catch {
|
|
2147
|
+
console.error(ansis.red(i18n.t("marketplace:searchFailed")));
|
|
2148
|
+
}
|
|
1002
2149
|
}
|
|
1003
|
-
|
|
1004
|
-
const config = readZcfConfig();
|
|
1005
|
-
codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
|
|
2150
|
+
break;
|
|
1006
2151
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
return;
|
|
2152
|
+
case "2": {
|
|
2153
|
+
console.log(ansis.cyan(i18n.t("marketplace:categories.plugin")));
|
|
2154
|
+
console.log(ansis.dim("Category browsing coming soon..."));
|
|
2155
|
+
break;
|
|
1012
2156
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
await
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
let items;
|
|
1019
|
-
if (typeof options.items === "string") {
|
|
1020
|
-
items = options.items.split(",").map((item) => item.trim());
|
|
2157
|
+
case "3": {
|
|
2158
|
+
try {
|
|
2159
|
+
const installed = await getInstalledPackages();
|
|
2160
|
+
if (installed.length === 0) {
|
|
2161
|
+
console.log(ansis.yellow(i18n.t("marketplace:noInstalled")));
|
|
1021
2162
|
} else {
|
|
1022
|
-
|
|
2163
|
+
console.log(ansis.green(i18n.t("marketplace:installedPackages", { count: installed.length })));
|
|
2164
|
+
console.log("");
|
|
2165
|
+
for (const pkg of installed) {
|
|
2166
|
+
const status = pkg.enabled ? ansis.green("\u25CF") : ansis.gray("\u25CB");
|
|
2167
|
+
console.log(` ${status} ${ansis.cyan(pkg.package.id)} ${ansis.gray(`v${pkg.package.version}`)}`);
|
|
2168
|
+
}
|
|
1023
2169
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
2170
|
+
} catch {
|
|
2171
|
+
console.error(ansis.red(i18n.t("marketplace:listFailed")));
|
|
1026
2172
|
}
|
|
2173
|
+
break;
|
|
1027
2174
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
2175
|
+
case "4": {
|
|
2176
|
+
console.log(i18n.t("marketplace:checkingUpdates"));
|
|
2177
|
+
try {
|
|
2178
|
+
const updates = await checkForUpdates();
|
|
2179
|
+
if (updates.length === 0) {
|
|
2180
|
+
console.log(ansis.green(i18n.t("marketplace:noUpdates")));
|
|
2181
|
+
} else {
|
|
2182
|
+
console.log(ansis.cyan(i18n.t("marketplace:updatesAvailable", { count: updates.length })));
|
|
2183
|
+
console.log("");
|
|
2184
|
+
for (const update2 of updates) {
|
|
2185
|
+
console.log(` ${ansis.cyan(update2.id)}: ${update2.currentVersion} \u2192 ${ansis.green(update2.latestVersion)}`);
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
} catch {
|
|
2189
|
+
console.error(ansis.red(i18n.t("marketplace:updateCheckFailed")));
|
|
2190
|
+
}
|
|
2191
|
+
break;
|
|
1032
2192
|
}
|
|
2193
|
+
case "0":
|
|
2194
|
+
return;
|
|
2195
|
+
default:
|
|
2196
|
+
return;
|
|
1033
2197
|
}
|
|
2198
|
+
printSeparator();
|
|
2199
|
+
await showMarketplaceMenu();
|
|
1034
2200
|
}
|
|
1035
|
-
async function
|
|
1036
|
-
|
|
2201
|
+
async function showQuickActionsMenu() {
|
|
2202
|
+
const lang = i18n.language;
|
|
2203
|
+
const isZh = lang === "zh-CN";
|
|
2204
|
+
console.log(ansis.cyan(isZh ? "\u{1F680} \u5FEB\u6377\u64CD\u4F5C" : "\u{1F680} Quick Actions"));
|
|
1037
2205
|
console.log("");
|
|
1038
|
-
|
|
1039
|
-
type: "list",
|
|
1040
|
-
name: "mainChoice",
|
|
1041
|
-
message: i18n.t("uninstall:selectMainOption"),
|
|
1042
|
-
choices: addNumbersToChoices([
|
|
1043
|
-
{
|
|
1044
|
-
name: `${i18n.t("uninstall:completeUninstall")} - ${ansis.gray(i18n.t("uninstall:completeUninstallDesc"))}`,
|
|
1045
|
-
value: "complete",
|
|
1046
|
-
short: i18n.t("uninstall:completeUninstall")
|
|
1047
|
-
},
|
|
1048
|
-
{
|
|
1049
|
-
name: `${i18n.t("uninstall:customUninstall")} - ${ansis.gray(i18n.t("uninstall:customUninstallDesc"))}`,
|
|
1050
|
-
value: "custom",
|
|
1051
|
-
short: i18n.t("uninstall:customUninstall")
|
|
1052
|
-
}
|
|
1053
|
-
])
|
|
1054
|
-
});
|
|
1055
|
-
if (!mainChoice) {
|
|
1056
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1057
|
-
return;
|
|
1058
|
-
}
|
|
1059
|
-
if (mainChoice === "complete") {
|
|
1060
|
-
await executeCompleteUninstall(uninstaller);
|
|
1061
|
-
} else {
|
|
1062
|
-
await showCustomUninstallMenu(uninstaller);
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
async function showCustomUninstallMenu(uninstaller) {
|
|
2206
|
+
console.log(generateQuickActionsPanel(lang));
|
|
1066
2207
|
console.log("");
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
name: i18n.t("uninstall:outputStyles"),
|
|
1075
|
-
value: "output-styles"
|
|
1076
|
-
},
|
|
1077
|
-
{
|
|
1078
|
-
name: i18n.t("uninstall:commands"),
|
|
1079
|
-
value: "commands"
|
|
1080
|
-
},
|
|
1081
|
-
{
|
|
1082
|
-
name: i18n.t("uninstall:agents"),
|
|
1083
|
-
value: "agents"
|
|
1084
|
-
},
|
|
1085
|
-
{
|
|
1086
|
-
name: i18n.t("uninstall:claudeMd"),
|
|
1087
|
-
value: "claude-md"
|
|
1088
|
-
},
|
|
1089
|
-
{
|
|
1090
|
-
name: i18n.t("uninstall:permissionsEnvs"),
|
|
1091
|
-
value: "permissions-envs"
|
|
1092
|
-
},
|
|
1093
|
-
{
|
|
1094
|
-
name: i18n.t("uninstall:mcps"),
|
|
1095
|
-
value: "mcps"
|
|
1096
|
-
},
|
|
1097
|
-
{
|
|
1098
|
-
name: i18n.t("uninstall:ccr"),
|
|
1099
|
-
value: "ccr"
|
|
1100
|
-
},
|
|
1101
|
-
{
|
|
1102
|
-
name: i18n.t("uninstall:ccline"),
|
|
1103
|
-
value: "ccline"
|
|
1104
|
-
},
|
|
1105
|
-
{
|
|
1106
|
-
name: i18n.t("uninstall:claudeCode"),
|
|
1107
|
-
value: "claude-code"
|
|
1108
|
-
},
|
|
1109
|
-
{
|
|
1110
|
-
name: i18n.t("uninstall:backups"),
|
|
1111
|
-
value: "backups"
|
|
1112
|
-
},
|
|
1113
|
-
{
|
|
1114
|
-
name: i18n.t("uninstall:ccjkConfig"),
|
|
1115
|
-
value: "ccjk-config"
|
|
1116
|
-
}
|
|
1117
|
-
],
|
|
1118
|
-
validate: (answers) => {
|
|
1119
|
-
if (answers.length === 0) {
|
|
1120
|
-
return i18n.t("uninstall:selectAtLeastOne");
|
|
1121
|
-
}
|
|
1122
|
-
return true;
|
|
2208
|
+
const { choice } = await inquirer.prompt({
|
|
2209
|
+
type: "input",
|
|
2210
|
+
name: "choice",
|
|
2211
|
+
message: isZh ? "\u8F93\u5165\u6570\u5B57 (1-8) \u6216 0 \u8FD4\u56DE:" : "Enter number (1-8) or 0 to go back:",
|
|
2212
|
+
validate: (value) => {
|
|
2213
|
+
const valid = ["1", "2", "3", "4", "5", "6", "7", "8", "0", "?"];
|
|
2214
|
+
return valid.includes(value) || (isZh ? "\u8BF7\u8F93\u5165\u6709\u6548\u9009\u9879" : "Please enter a valid option");
|
|
1123
2215
|
}
|
|
1124
2216
|
});
|
|
1125
|
-
if (!
|
|
1126
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2217
|
+
if (!choice || choice === "0") {
|
|
1127
2218
|
return;
|
|
1128
2219
|
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
const confirm = await promptBoolean({
|
|
1136
|
-
message: i18n.t("uninstall:confirmComplete"),
|
|
1137
|
-
defaultValue: false
|
|
1138
|
-
});
|
|
1139
|
-
if (!confirm) {
|
|
1140
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2220
|
+
if (choice === "?") {
|
|
2221
|
+
console.log("");
|
|
2222
|
+
console.log(generateSkillReferenceCard(lang));
|
|
2223
|
+
console.log("");
|
|
2224
|
+
printSeparator();
|
|
2225
|
+
await showQuickActionsMenu();
|
|
1141
2226
|
return;
|
|
1142
2227
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
2228
|
+
const actionNum = Number.parseInt(choice, 10);
|
|
2229
|
+
const action = QUICK_ACTIONS.find((a) => a.id === actionNum);
|
|
2230
|
+
if (action) {
|
|
2231
|
+
const actionName = isZh ? action.nameZh : action.name;
|
|
2232
|
+
console.log("");
|
|
2233
|
+
console.log(ansis.green(`\u2714 ${isZh ? "\u6267\u884C" : "Executing"}: ${action.icon} ${actionName}`));
|
|
2234
|
+
console.log(ansis.gray(`${isZh ? "\u547D\u4EE4" : "Command"}: ${action.command}`));
|
|
2235
|
+
console.log("");
|
|
2236
|
+
console.log(ansis.cyan(isZh ? `\u{1F4A1} \u63D0\u793A: \u5728 Claude Code \u4E2D\u8F93\u5165 "${action.command}" \u6216\u76F4\u63A5\u8F93\u5165 "${choice}" \u6765\u6267\u884C\u6B64\u64CD\u4F5C` : `\u{1F4A1} Tip: In Claude Code, type "${action.command}" or just "${choice}" to execute this action`));
|
|
2237
|
+
}
|
|
2238
|
+
printSeparator();
|
|
1147
2239
|
}
|
|
1148
|
-
async function
|
|
2240
|
+
async function showSmartGuideMenu() {
|
|
2241
|
+
const lang = i18n.language;
|
|
2242
|
+
const isZh = lang === "zh-CN";
|
|
2243
|
+
const installed = await isSmartGuideInstalled();
|
|
2244
|
+
console.log(ansis.cyan(isZh ? "\u{1F3AF} \u667A\u80FD\u52A9\u624B" : "\u{1F3AF} Smart Assistant"));
|
|
1149
2245
|
console.log("");
|
|
1150
|
-
console.log(
|
|
1151
|
-
console.log(ansis.gray(i18n.t("uninstall:selectedItems")));
|
|
1152
|
-
items.forEach((item) => {
|
|
1153
|
-
console.log(` \u2022 ${i18n.t(`uninstall:${item}`)}`);
|
|
1154
|
-
});
|
|
1155
|
-
const confirm = await promptBoolean({
|
|
1156
|
-
message: i18n.t("uninstall:confirmCustom"),
|
|
1157
|
-
defaultValue: false
|
|
1158
|
-
});
|
|
1159
|
-
if (!confirm) {
|
|
1160
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1161
|
-
return;
|
|
1162
|
-
}
|
|
2246
|
+
console.log(isZh ? "\u667A\u80FD\u52A9\u624B\u8BA9\u4F60\u5728 Claude Code \u4E2D\u901A\u8FC7\u8F93\u5165\u6570\u5B57\u5FEB\u901F\u6267\u884C\u64CD\u4F5C" : "Smart Assistant lets you execute actions by typing numbers in Claude Code");
|
|
1163
2247
|
console.log("");
|
|
1164
|
-
console.log(ansis.
|
|
1165
|
-
const results = await uninstaller.customUninstall(items);
|
|
1166
|
-
displayUninstallResult("custom", results);
|
|
1167
|
-
}
|
|
1168
|
-
function displayUninstallResult(mode, results) {
|
|
2248
|
+
console.log(` ${isZh ? "\u72B6\u6001" : "Status"}: ${installed ? ansis.green(isZh ? "\u5DF2\u542F\u7528" : "Enabled") : ansis.yellow(isZh ? "\u672A\u542F\u7528" : "Disabled")}`);
|
|
1169
2249
|
console.log("");
|
|
1170
|
-
console.log(ansis.cyan("\
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
results.forEach((result) => {
|
|
1175
|
-
if (result.success) {
|
|
1176
|
-
totalSuccess++;
|
|
1177
|
-
}
|
|
1178
|
-
if (result.removed && result.removed.length > 0) {
|
|
1179
|
-
console.log(ansis.green(`\u{1F5D1}\uFE0F ${i18n.t("uninstall:movedToTrash")}:`));
|
|
1180
|
-
result.removed.forEach((item) => {
|
|
1181
|
-
console.log(ansis.gray(` \u2022 ${item}`));
|
|
1182
|
-
});
|
|
1183
|
-
}
|
|
1184
|
-
if (result.removedConfigs && result.removedConfigs.length > 0) {
|
|
1185
|
-
console.log(ansis.green(`\u2714 ${i18n.t("uninstall:removedConfigs")}:`));
|
|
1186
|
-
result.removedConfigs.forEach((item) => {
|
|
1187
|
-
console.log(ansis.gray(` \u2022 ${item}`));
|
|
1188
|
-
});
|
|
1189
|
-
}
|
|
1190
|
-
if (result.errors && result.errors.length > 0) {
|
|
1191
|
-
totalErrors += result.errors.length;
|
|
1192
|
-
console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errors")}:`));
|
|
1193
|
-
result.errors.forEach((error) => {
|
|
1194
|
-
console.log(ansis.red(` \u2022 ${error}`));
|
|
1195
|
-
});
|
|
1196
|
-
}
|
|
1197
|
-
if (result.warnings && result.warnings.length > 0) {
|
|
1198
|
-
totalWarnings += result.warnings.length;
|
|
1199
|
-
console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warnings")}:`));
|
|
1200
|
-
result.warnings.forEach((warning) => {
|
|
1201
|
-
console.log(ansis.yellow(` \u2022 ${warning}`));
|
|
1202
|
-
});
|
|
1203
|
-
}
|
|
1204
|
-
});
|
|
1205
|
-
const totalRemovedFiles = results.reduce((count, result) => count + (result.removed?.length || 0), 0);
|
|
1206
|
-
const totalRemovedConfigs = results.reduce((count, result) => count + (result.removedConfigs?.length || 0), 0);
|
|
2250
|
+
console.log(` ${ansis.cyan("1.")} ${installed ? isZh ? "\u66F4\u65B0\u667A\u80FD\u52A9\u624B" : "Update Smart Assistant" : isZh ? "\u542F\u7528\u667A\u80FD\u52A9\u624B" : "Enable Smart Assistant"}`);
|
|
2251
|
+
console.log(` ${ansis.cyan("2.")} ${isZh ? "\u7981\u7528\u667A\u80FD\u52A9\u624B" : "Disable Smart Assistant"}`);
|
|
2252
|
+
console.log(` ${ansis.cyan("3.")} ${isZh ? "\u67E5\u770B\u6280\u80FD\u901F\u67E5\u5361" : "View Skills Reference Card"}`);
|
|
2253
|
+
console.log(` ${ansis.cyan("0.")} ${i18n.t("common:back")}`);
|
|
1207
2254
|
console.log("");
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
} else {
|
|
1216
|
-
if (totalRemovedFiles > 0 && totalRemovedConfigs > 0) {
|
|
1217
|
-
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessBoth", {
|
|
1218
|
-
fileCount: totalRemovedFiles,
|
|
1219
|
-
configCount: totalRemovedConfigs
|
|
1220
|
-
})}`));
|
|
1221
|
-
} else if (totalRemovedFiles > 0) {
|
|
1222
|
-
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessFiles", {
|
|
1223
|
-
count: totalRemovedFiles
|
|
1224
|
-
})}`));
|
|
1225
|
-
} else if (totalRemovedConfigs > 0) {
|
|
1226
|
-
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessConfigs", {
|
|
1227
|
-
count: totalRemovedConfigs
|
|
1228
|
-
})}`));
|
|
1229
|
-
} else {
|
|
1230
|
-
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccess", { count: totalSuccess })}`));
|
|
2255
|
+
const { choice } = await inquirer.prompt({
|
|
2256
|
+
type: "input",
|
|
2257
|
+
name: "choice",
|
|
2258
|
+
message: i18n.t("common:enterChoice"),
|
|
2259
|
+
validate: (value) => {
|
|
2260
|
+
const valid = ["1", "2", "3", "0"];
|
|
2261
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
1231
2262
|
}
|
|
1232
|
-
|
|
1233
|
-
|
|
2263
|
+
});
|
|
2264
|
+
if (!choice || choice === "0") {
|
|
2265
|
+
return;
|
|
2266
|
+
}
|
|
2267
|
+
switch (choice) {
|
|
2268
|
+
case "1": {
|
|
2269
|
+
const success = await injectSmartGuide(lang);
|
|
2270
|
+
if (success) {
|
|
2271
|
+
console.log(ansis.green(`\u2714 ${isZh ? "\u667A\u80FD\u52A9\u624B\u5DF2\u542F\u7528" : "Smart Assistant enabled"}`));
|
|
2272
|
+
} else {
|
|
2273
|
+
console.log(ansis.red(isZh ? "\u542F\u7528\u5931\u8D25" : "Failed to enable"));
|
|
2274
|
+
}
|
|
2275
|
+
break;
|
|
1234
2276
|
}
|
|
1235
|
-
|
|
1236
|
-
|
|
2277
|
+
case "2": {
|
|
2278
|
+
if (!installed) {
|
|
2279
|
+
console.log(ansis.yellow(isZh ? "\u667A\u80FD\u52A9\u624B\u672A\u542F\u7528" : "Smart Assistant is not enabled"));
|
|
2280
|
+
break;
|
|
2281
|
+
}
|
|
2282
|
+
const success = await removeSmartGuide();
|
|
2283
|
+
if (success) {
|
|
2284
|
+
console.log(ansis.green(`\u2714 ${isZh ? "\u667A\u80FD\u52A9\u624B\u5DF2\u7981\u7528" : "Smart Assistant disabled"}`));
|
|
2285
|
+
} else {
|
|
2286
|
+
console.log(ansis.red(isZh ? "\u7981\u7528\u5931\u8D25" : "Failed to disable"));
|
|
2287
|
+
}
|
|
2288
|
+
break;
|
|
2289
|
+
}
|
|
2290
|
+
case "3": {
|
|
2291
|
+
console.log("");
|
|
2292
|
+
console.log(generateSkillReferenceCard(lang));
|
|
2293
|
+
break;
|
|
1237
2294
|
}
|
|
1238
2295
|
}
|
|
1239
|
-
|
|
2296
|
+
printSeparator();
|
|
1240
2297
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
2298
|
+
async function showWorkflowsAndSkillsMenu() {
|
|
2299
|
+
const lang = i18n.language;
|
|
2300
|
+
const isZh = lang === "zh-CN";
|
|
2301
|
+
console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.workflowsTitle")));
|
|
2302
|
+
console.log(" -------- Workflows & Skills --------");
|
|
2303
|
+
console.log(` ${ansis.cyan("1.")} ${i18n.t("menu:ccjkFeatures.viewInstalledWorkflows")}`);
|
|
2304
|
+
console.log(` ${ansis.cyan("2.")} ${i18n.t("menu:ccjkFeatures.viewInstalledSkills")}`);
|
|
2305
|
+
console.log(` ${ansis.cyan("3.")} ${i18n.t("menu:ccjkFeatures.installNewWorkflow")}`);
|
|
2306
|
+
console.log(` ${ansis.cyan("4.")} ${isZh ? "\u{1F680} \u5FEB\u6377\u64CD\u4F5C\u9762\u677F" : "\u{1F680} Quick Actions Panel"}`);
|
|
2307
|
+
console.log(` ${ansis.cyan("5.")} ${isZh ? "\u{1F3AF} \u667A\u80FD\u52A9\u624B\u8BBE\u7F6E" : "\u{1F3AF} Smart Assistant Settings"}`);
|
|
2308
|
+
console.log(` ${ansis.cyan("0.")} ${i18n.t("common:back")}`);
|
|
2309
|
+
console.log("");
|
|
2310
|
+
const { choice } = await inquirer.prompt({
|
|
2311
|
+
type: "input",
|
|
2312
|
+
name: "choice",
|
|
2313
|
+
message: i18n.t("common:enterChoice"),
|
|
2314
|
+
validate: (value) => {
|
|
2315
|
+
const valid = ["1", "2", "3", "4", "5", "0"];
|
|
2316
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
1247
2317
|
}
|
|
2318
|
+
});
|
|
2319
|
+
if (!choice) {
|
|
2320
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2321
|
+
return;
|
|
1248
2322
|
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
async function update(options = {}) {
|
|
1255
|
-
try {
|
|
1256
|
-
if (!options.skipBanner) {
|
|
1257
|
-
displayBanner(i18n.t("cli:banner.updateSubtitle"));
|
|
2323
|
+
switch (choice) {
|
|
2324
|
+
case "1": {
|
|
2325
|
+
console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.availableStyles")));
|
|
2326
|
+
console.log(ansis.dim("Feature coming soon - will show installed workflows"));
|
|
2327
|
+
break;
|
|
1258
2328
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
preferredLang: newPreferredLang,
|
|
1269
|
-
codeToolType
|
|
1270
|
-
});
|
|
2329
|
+
case "2": {
|
|
2330
|
+
const status = await checkSuperpowersInstalled();
|
|
2331
|
+
if (!status.installed) {
|
|
2332
|
+
console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
|
|
2333
|
+
break;
|
|
2334
|
+
}
|
|
2335
|
+
const skills = await getSuperpowersSkills();
|
|
2336
|
+
if (skills.length === 0) {
|
|
2337
|
+
console.log(ansis.yellow(i18n.t("menu:ccjkFeatures.noSkillsInstalled")));
|
|
1271
2338
|
} else {
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
2339
|
+
console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.skillCount", { count: skills.length })));
|
|
2340
|
+
console.log("");
|
|
2341
|
+
skills.forEach((skill) => {
|
|
2342
|
+
console.log(` ${ansis.green("\u2022")} ${skill}`);
|
|
1275
2343
|
});
|
|
1276
2344
|
}
|
|
2345
|
+
break;
|
|
2346
|
+
}
|
|
2347
|
+
case "3": {
|
|
2348
|
+
await update({ skipBanner: true });
|
|
2349
|
+
break;
|
|
2350
|
+
}
|
|
2351
|
+
case "4": {
|
|
2352
|
+
printSeparator();
|
|
2353
|
+
await showQuickActionsMenu();
|
|
1277
2354
|
return;
|
|
1278
2355
|
}
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
zcfConfig,
|
|
1284
|
-
options.skipPrompt
|
|
1285
|
-
// Non-interactive mode flag
|
|
1286
|
-
);
|
|
1287
|
-
const aiOutputLang = await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig, options.skipPrompt);
|
|
1288
|
-
console.log(ansis.cyan(`
|
|
1289
|
-
${i18n.t("configuration:updatingPrompts")}
|
|
1290
|
-
`));
|
|
1291
|
-
await updatePromptOnly(aiOutputLang);
|
|
1292
|
-
await selectAndInstallWorkflows(configLang);
|
|
1293
|
-
await checkClaudeCodeVersionAndPrompt(false);
|
|
1294
|
-
updateZcfConfig({
|
|
1295
|
-
version,
|
|
1296
|
-
templateLang: configLang,
|
|
1297
|
-
// 保存模板语言选择
|
|
1298
|
-
aiOutputLang,
|
|
1299
|
-
codeToolType
|
|
1300
|
-
});
|
|
1301
|
-
} catch (error) {
|
|
1302
|
-
if (!handleExitPromptError(error)) {
|
|
1303
|
-
handleGeneralError(error);
|
|
2356
|
+
case "5": {
|
|
2357
|
+
printSeparator();
|
|
2358
|
+
await showSmartGuideMenu();
|
|
2359
|
+
return;
|
|
1304
2360
|
}
|
|
2361
|
+
case "0":
|
|
2362
|
+
return;
|
|
2363
|
+
default:
|
|
2364
|
+
return;
|
|
1305
2365
|
}
|
|
2366
|
+
printSeparator();
|
|
1306
2367
|
}
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
"
|
|
1310
|
-
"
|
|
1311
|
-
"
|
|
1312
|
-
"
|
|
1313
|
-
"
|
|
1314
|
-
"
|
|
1315
|
-
};
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
return DEFAULT_CODE_TOOL_TYPE;
|
|
1322
|
-
}
|
|
1323
|
-
function printSeparator() {
|
|
1324
|
-
console.log(`
|
|
1325
|
-
${ansis.dim("\u2500".repeat(50))}
|
|
1326
|
-
`);
|
|
1327
|
-
}
|
|
1328
|
-
function getCodeToolLabel(codeTool) {
|
|
1329
|
-
return CODE_TOOL_LABELS[codeTool] || codeTool;
|
|
2368
|
+
async function showOutputStylesMenu() {
|
|
2369
|
+
console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.outputStylesTitle")));
|
|
2370
|
+
console.log("");
|
|
2371
|
+
console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.availableStyles")));
|
|
2372
|
+
console.log(` ${ansis.green("\u2022")} speed-coder`);
|
|
2373
|
+
console.log(` ${ansis.green("\u2022")} senior-architect`);
|
|
2374
|
+
console.log(` ${ansis.green("\u2022")} pair-programmer`);
|
|
2375
|
+
console.log(` ${ansis.green("\u2022")} expert-concise`);
|
|
2376
|
+
console.log(` ${ansis.green("\u2022")} teaching-mode`);
|
|
2377
|
+
console.log(` ${ansis.green("\u2022")} casual-friendly`);
|
|
2378
|
+
console.log(` ${ansis.green("\u2022")} technical-precise`);
|
|
2379
|
+
console.log("");
|
|
2380
|
+
console.log(ansis.dim('Tip: Output styles are configured during initialization or via "Configure Claude global memory"'));
|
|
2381
|
+
printSeparator();
|
|
1330
2382
|
}
|
|
1331
|
-
async function
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
short: label
|
|
1336
|
-
})));
|
|
1337
|
-
const { tool } = await inquirer.prompt({
|
|
1338
|
-
type: "list",
|
|
1339
|
-
name: "tool",
|
|
1340
|
-
message: i18n.t("menu:switchCodeToolPrompt"),
|
|
1341
|
-
default: current,
|
|
1342
|
-
choices
|
|
1343
|
-
});
|
|
1344
|
-
if (!tool) {
|
|
1345
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1346
|
-
return null;
|
|
1347
|
-
}
|
|
1348
|
-
return tool;
|
|
2383
|
+
async function showConfigSwitchMenu() {
|
|
2384
|
+
console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.configSwitchTitle")));
|
|
2385
|
+
console.log("");
|
|
2386
|
+
await configSwitchCommand({ codeType: "claude-code" });
|
|
1349
2387
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
2388
|
+
function printCcjkFeaturesSection() {
|
|
2389
|
+
console.log(` -------- ${i18n.t("menu:menuSections.ccjkFeatures")} --------`);
|
|
2390
|
+
console.log(
|
|
2391
|
+
` ${ansis.cyan("W.")} ${i18n.t("menu:menuOptions.workflowsAndSkills")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.workflowsAndSkills")}`)}`
|
|
2392
|
+
);
|
|
2393
|
+
console.log(
|
|
2394
|
+
` ${ansis.cyan("O.")} ${i18n.t("menu:menuOptions.outputStyles")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.outputStyles")}`)}`
|
|
2395
|
+
);
|
|
2396
|
+
console.log(
|
|
2397
|
+
` ${ansis.cyan("C.")} ${i18n.t("menu:menuOptions.configSwitch")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configSwitch")}`)}`
|
|
2398
|
+
);
|
|
2399
|
+
console.log("");
|
|
1358
2400
|
}
|
|
1359
|
-
function
|
|
1360
|
-
console.log(`
|
|
2401
|
+
function printRecommendedPluginsSection() {
|
|
2402
|
+
console.log(` -------- ${i18n.t("menu:menuSections.recommendedPlugins")} --------`);
|
|
1361
2403
|
console.log(
|
|
1362
2404
|
` ${ansis.cyan("R.")} ${i18n.t("menu:menuOptions.ccrManagement")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccrManagement")}`)}`
|
|
1363
2405
|
);
|
|
@@ -1367,6 +2409,12 @@ function printOtherToolsSection() {
|
|
|
1367
2409
|
console.log(
|
|
1368
2410
|
` ${ansis.cyan("L.")} ${i18n.t("menu:menuOptions.cometixLine")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.cometixLine")}`)}`
|
|
1369
2411
|
);
|
|
2412
|
+
console.log(
|
|
2413
|
+
` ${ansis.cyan("P.")} ${i18n.t("menu:menuOptions.superpowers")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.superpowers")}`)}`
|
|
2414
|
+
);
|
|
2415
|
+
console.log(
|
|
2416
|
+
` ${ansis.cyan("M.")} ${i18n.t("menu:menuOptions.marketplace")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.marketplace")}`)}`
|
|
2417
|
+
);
|
|
1370
2418
|
console.log("");
|
|
1371
2419
|
}
|
|
1372
2420
|
function printZcfSection(options) {
|
|
@@ -1411,7 +2459,8 @@ async function showClaudeCodeMenu() {
|
|
|
1411
2459
|
` ${ansis.cyan("7.")} ${i18n.t("menu:menuOptions.configureEnvPermission")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureEnvPermission")}`)}`
|
|
1412
2460
|
);
|
|
1413
2461
|
console.log("");
|
|
1414
|
-
|
|
2462
|
+
printCcjkFeaturesSection();
|
|
2463
|
+
printRecommendedPluginsSection();
|
|
1415
2464
|
printZcfSection({
|
|
1416
2465
|
uninstallOption: i18n.t("menu:menuOptions.uninstall"),
|
|
1417
2466
|
uninstallDescription: i18n.t("menu:menuDescriptions.uninstall"),
|
|
@@ -1423,7 +2472,7 @@ async function showClaudeCodeMenu() {
|
|
|
1423
2472
|
name: "choice",
|
|
1424
2473
|
message: i18n.t("common:enterChoice"),
|
|
1425
2474
|
validate: (value) => {
|
|
1426
|
-
const valid = ["1", "2", "3", "4", "5", "6", "7", "r", "R", "u", "U", "l", "L", "0", "-", "+", "s", "S", "q", "Q"];
|
|
2475
|
+
const valid = ["1", "2", "3", "4", "5", "6", "7", "w", "W", "o", "O", "c", "C", "r", "R", "u", "U", "l", "L", "p", "P", "m", "M", "0", "-", "+", "s", "S", "q", "Q"];
|
|
1427
2476
|
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
1428
2477
|
}
|
|
1429
2478
|
});
|
|
@@ -1454,118 +2503,38 @@ async function showClaudeCodeMenu() {
|
|
|
1454
2503
|
case "7":
|
|
1455
2504
|
await configureEnvPermissionFeature();
|
|
1456
2505
|
break;
|
|
1457
|
-
case "
|
|
1458
|
-
await
|
|
2506
|
+
case "w":
|
|
2507
|
+
await showWorkflowsAndSkillsMenu();
|
|
1459
2508
|
printSeparator();
|
|
1460
2509
|
return void 0;
|
|
1461
|
-
case "
|
|
1462
|
-
await
|
|
2510
|
+
case "o":
|
|
2511
|
+
await showOutputStylesMenu();
|
|
1463
2512
|
printSeparator();
|
|
1464
2513
|
return void 0;
|
|
1465
|
-
case "
|
|
1466
|
-
await
|
|
2514
|
+
case "c":
|
|
2515
|
+
await showConfigSwitchMenu();
|
|
1467
2516
|
printSeparator();
|
|
1468
2517
|
return void 0;
|
|
1469
|
-
case "
|
|
1470
|
-
|
|
1471
|
-
await changeScriptLanguageFeature(currentLang);
|
|
2518
|
+
case "r":
|
|
2519
|
+
await runCcrMenuFeature();
|
|
1472
2520
|
printSeparator();
|
|
1473
2521
|
return void 0;
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
await uninstall();
|
|
2522
|
+
case "u":
|
|
2523
|
+
await runCcusageFeature();
|
|
1477
2524
|
printSeparator();
|
|
1478
2525
|
return void 0;
|
|
1479
|
-
case "
|
|
1480
|
-
await
|
|
2526
|
+
case "l":
|
|
2527
|
+
await runCometixMenuFeature();
|
|
1481
2528
|
printSeparator();
|
|
1482
2529
|
return void 0;
|
|
1483
|
-
case "
|
|
1484
|
-
|
|
1485
|
-
if (switched) {
|
|
1486
|
-
return "switch";
|
|
1487
|
-
}
|
|
2530
|
+
case "p":
|
|
2531
|
+
await showSuperpowersMenu();
|
|
1488
2532
|
printSeparator();
|
|
1489
|
-
return void 0;
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
return
|
|
1494
|
-
default:
|
|
1495
|
-
return void 0;
|
|
1496
|
-
}
|
|
1497
|
-
printSeparator();
|
|
1498
|
-
const shouldContinue = await promptBoolean({
|
|
1499
|
-
message: i18n.t("common:returnToMenu"),
|
|
1500
|
-
defaultValue: true
|
|
1501
|
-
});
|
|
1502
|
-
if (!shouldContinue) {
|
|
1503
|
-
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
1504
|
-
return "exit";
|
|
1505
|
-
}
|
|
1506
|
-
return void 0;
|
|
1507
|
-
}
|
|
1508
|
-
async function showCodexMenu() {
|
|
1509
|
-
console.log(ansis.cyan(i18n.t("menu:selectFunction")));
|
|
1510
|
-
console.log(" -------- Codex --------");
|
|
1511
|
-
console.log(
|
|
1512
|
-
` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.codexFullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexFullInit")}`)}`
|
|
1513
|
-
);
|
|
1514
|
-
console.log(
|
|
1515
|
-
` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.codexImportWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexImportWorkflow")}`)}`
|
|
1516
|
-
);
|
|
1517
|
-
console.log(
|
|
1518
|
-
` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.codexConfigureApi")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureApi")}`)}`
|
|
1519
|
-
);
|
|
1520
|
-
console.log(
|
|
1521
|
-
` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.codexConfigureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureMcp")}`)}`
|
|
1522
|
-
);
|
|
1523
|
-
console.log(
|
|
1524
|
-
` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.codexConfigureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureModel")}`)}`
|
|
1525
|
-
);
|
|
1526
|
-
console.log(
|
|
1527
|
-
` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.codexConfigureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureAiMemory")}`)}`
|
|
1528
|
-
);
|
|
1529
|
-
console.log("");
|
|
1530
|
-
printZcfSection({
|
|
1531
|
-
uninstallOption: i18n.t("menu:menuOptions.codexUninstall"),
|
|
1532
|
-
uninstallDescription: i18n.t("menu:menuDescriptions.codexUninstall"),
|
|
1533
|
-
updateOption: i18n.t("menu:menuOptions.codexCheckUpdates"),
|
|
1534
|
-
updateDescription: i18n.t("menu:menuDescriptions.codexCheckUpdates")
|
|
1535
|
-
});
|
|
1536
|
-
const { choice } = await inquirer.prompt({
|
|
1537
|
-
type: "input",
|
|
1538
|
-
name: "choice",
|
|
1539
|
-
message: i18n.t("common:enterChoice"),
|
|
1540
|
-
validate: (value) => {
|
|
1541
|
-
const valid = ["1", "2", "3", "4", "5", "6", "0", "-", "+", "s", "S", "q", "Q"];
|
|
1542
|
-
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
1543
|
-
}
|
|
1544
|
-
});
|
|
1545
|
-
if (!choice) {
|
|
1546
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1547
|
-
return "exit";
|
|
1548
|
-
}
|
|
1549
|
-
const normalized = choice.toLowerCase();
|
|
1550
|
-
switch (normalized) {
|
|
1551
|
-
case "1":
|
|
1552
|
-
await runCodexFullInit();
|
|
1553
|
-
break;
|
|
1554
|
-
case "2":
|
|
1555
|
-
await runCodexWorkflowImportWithLanguageSelection();
|
|
1556
|
-
break;
|
|
1557
|
-
case "3":
|
|
1558
|
-
await configureCodexApi();
|
|
1559
|
-
break;
|
|
1560
|
-
case "4":
|
|
1561
|
-
await configureCodexMcp();
|
|
1562
|
-
break;
|
|
1563
|
-
case "5":
|
|
1564
|
-
await configureCodexDefaultModelFeature();
|
|
1565
|
-
break;
|
|
1566
|
-
case "6":
|
|
1567
|
-
await configureCodexAiMemoryFeature();
|
|
1568
|
-
break;
|
|
2533
|
+
return void 0;
|
|
2534
|
+
case "m":
|
|
2535
|
+
await showMarketplaceMenu();
|
|
2536
|
+
printSeparator();
|
|
2537
|
+
return void 0;
|
|
1569
2538
|
case "0": {
|
|
1570
2539
|
const currentLang = i18n.language;
|
|
1571
2540
|
await changeScriptLanguageFeature(currentLang);
|
|
@@ -1573,473 +2542,300 @@ async function showCodexMenu() {
|
|
|
1573
2542
|
return void 0;
|
|
1574
2543
|
}
|
|
1575
2544
|
case "-":
|
|
1576
|
-
await
|
|
2545
|
+
await uninstall();
|
|
1577
2546
|
printSeparator();
|
|
1578
2547
|
return void 0;
|
|
1579
2548
|
case "+":
|
|
1580
|
-
await
|
|
2549
|
+
await checkUpdates();
|
|
1581
2550
|
printSeparator();
|
|
1582
2551
|
return void 0;
|
|
1583
2552
|
case "s": {
|
|
1584
|
-
const switched = await handleCodeToolSwitch("
|
|
2553
|
+
const switched = await handleCodeToolSwitch("claude-code");
|
|
1585
2554
|
if (switched) {
|
|
1586
|
-
return "switch";
|
|
1587
|
-
}
|
|
1588
|
-
printSeparator();
|
|
1589
|
-
return void 0;
|
|
1590
|
-
}
|
|
1591
|
-
case "q":
|
|
1592
|
-
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
1593
|
-
return "exit";
|
|
1594
|
-
default:
|
|
1595
|
-
return void 0;
|
|
1596
|
-
}
|
|
1597
|
-
printSeparator();
|
|
1598
|
-
const shouldContinue = await promptBoolean({
|
|
1599
|
-
message: i18n.t("common:returnToMenu"),
|
|
1600
|
-
defaultValue: true
|
|
1601
|
-
});
|
|
1602
|
-
if (!shouldContinue) {
|
|
1603
|
-
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
1604
|
-
return "exit";
|
|
1605
|
-
}
|
|
1606
|
-
return void 0;
|
|
1607
|
-
}
|
|
1608
|
-
async function showMainMenu(options = {}) {
|
|
1609
|
-
try {
|
|
1610
|
-
if (options.codeType) {
|
|
1611
|
-
try {
|
|
1612
|
-
const resolvedType = await resolveCodeType$1(options.codeType);
|
|
1613
|
-
const currentType = getCurrentCodeTool();
|
|
1614
|
-
if (resolvedType !== currentType) {
|
|
1615
|
-
updateZcfConfig({ codeToolType: resolvedType });
|
|
1616
|
-
console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(resolvedType) })}`));
|
|
1617
|
-
}
|
|
1618
|
-
} catch (err) {
|
|
1619
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1620
|
-
console.error(ansis.yellow(errorMessage));
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
let exitMenu = false;
|
|
1624
|
-
while (!exitMenu) {
|
|
1625
|
-
const codeTool = getCurrentCodeTool();
|
|
1626
|
-
displayBannerWithInfo(CODE_TOOL_BANNERS[codeTool] || "CCJK");
|
|
1627
|
-
const result = codeTool === "codex" ? await showCodexMenu() : await showClaudeCodeMenu();
|
|
1628
|
-
if (result === "exit") {
|
|
1629
|
-
exitMenu = true;
|
|
1630
|
-
} else if (result === "switch") {
|
|
1631
|
-
continue;
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1634
|
-
} catch (error) {
|
|
1635
|
-
if (!handleExitPromptError(error)) {
|
|
1636
|
-
handleGeneralError(error);
|
|
1637
|
-
}
|
|
1638
|
-
}
|
|
1639
|
-
}
|
|
1640
|
-
|
|
1641
|
-
async function ccr(options = {}) {
|
|
1642
|
-
try {
|
|
1643
|
-
if (!options.skipBanner) {
|
|
1644
|
-
displayBannerWithInfo();
|
|
1645
|
-
}
|
|
1646
|
-
const continueInCcr = await showCcrMenu();
|
|
1647
|
-
if (!continueInCcr && !options.skipBanner) {
|
|
1648
|
-
await showMainMenu();
|
|
1649
|
-
}
|
|
1650
|
-
} catch (error) {
|
|
1651
|
-
if (!handleExitPromptError(error)) {
|
|
1652
|
-
handleGeneralError(error);
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
|
-
}
|
|
1656
|
-
|
|
1657
|
-
async function checkGitRepo() {
|
|
1658
|
-
try {
|
|
1659
|
-
await exec$1("git", ["rev-parse", "--git-dir"]);
|
|
1660
|
-
return true;
|
|
1661
|
-
} catch {
|
|
1662
|
-
return false;
|
|
1663
|
-
}
|
|
1664
|
-
}
|
|
1665
|
-
async function getGitStatus() {
|
|
1666
|
-
const isRepo = await checkGitRepo();
|
|
1667
|
-
if (!isRepo)
|
|
1668
|
-
return { isRepo: false, hasChanges: false, staged: [], unstaged: [], untracked: [] };
|
|
1669
|
-
const { stdout } = await exec$1("git", ["status", "--porcelain"]);
|
|
1670
|
-
const lines = stdout.trim().split("\n").filter(Boolean);
|
|
1671
|
-
const staged = [];
|
|
1672
|
-
const unstaged = [];
|
|
1673
|
-
const untracked = [];
|
|
1674
|
-
for (const line of lines) {
|
|
1675
|
-
const [s1, s2] = line.substring(0, 2);
|
|
1676
|
-
const file = line.substring(3);
|
|
1677
|
-
if (s1 !== " " && s1 !== "?")
|
|
1678
|
-
staged.push(file);
|
|
1679
|
-
if (s2 !== " ")
|
|
1680
|
-
unstaged.push(file);
|
|
1681
|
-
if (line.startsWith("??"))
|
|
1682
|
-
untracked.push(file);
|
|
1683
|
-
}
|
|
1684
|
-
return {
|
|
1685
|
-
isRepo: true,
|
|
1686
|
-
hasChanges: staged.length + unstaged.length + untracked.length > 0,
|
|
1687
|
-
staged,
|
|
1688
|
-
unstaged,
|
|
1689
|
-
untracked
|
|
1690
|
-
};
|
|
1691
|
-
}
|
|
1692
|
-
async function generateCommitMessage(files) {
|
|
1693
|
-
if (files.length === 0)
|
|
1694
|
-
return "chore: update files";
|
|
1695
|
-
const { stdout: diff } = await exec$1("git", ["diff", "--cached", "--stat"]);
|
|
1696
|
-
const hasTest = files.some((f) => f.includes("test") || f.includes("spec"));
|
|
1697
|
-
const hasDocs = files.some((f) => f.endsWith(".md"));
|
|
1698
|
-
const hasConfig = files.some((f) => f.endsWith(".json") || f.endsWith(".yaml"));
|
|
1699
|
-
const hasTs = files.some((f) => f.endsWith(".ts"));
|
|
1700
|
-
const type = hasTest ? "test" : hasDocs ? "docs" : hasConfig ? "config" : hasTs ? "feat" : "chore";
|
|
1701
|
-
const scope = files.length === 1 ? files[0].split("/")[0] : void 0;
|
|
1702
|
-
const fileList = files.length <= 3 ? files.join(", ") : `${files.length} files`;
|
|
1703
|
-
const message = scope ? `${type}(${scope}): update ${fileList}` : `${type}: update ${fileList}`;
|
|
1704
|
-
return `${message}
|
|
1705
|
-
|
|
1706
|
-
${diff.trim()}`;
|
|
1707
|
-
}
|
|
1708
|
-
async function stageAllChanges() {
|
|
1709
|
-
await exec$1("git", ["add", "-A"]);
|
|
1710
|
-
}
|
|
1711
|
-
async function commitChanges(message) {
|
|
1712
|
-
await exec$1("git", ["commit", "-m", message]);
|
|
1713
|
-
}
|
|
1714
|
-
|
|
1715
|
-
async function commit(options = {}) {
|
|
1716
|
-
if (!await checkGitRepo()) {
|
|
1717
|
-
console.log(ansis.red("\u2717 Not a git repository"));
|
|
1718
|
-
return;
|
|
1719
|
-
}
|
|
1720
|
-
const status = await getGitStatus();
|
|
1721
|
-
if (!status.hasChanges) {
|
|
1722
|
-
console.log(ansis.yellow("No changes to commit"));
|
|
1723
|
-
return;
|
|
1724
|
-
}
|
|
1725
|
-
console.log(ansis.cyan("\n\u{1F4DD} Changes detected:"));
|
|
1726
|
-
if (status.staged.length > 0) {
|
|
1727
|
-
console.log(ansis.green(` Staged: ${status.staged.length} files`));
|
|
1728
|
-
status.staged.forEach((f) => console.log(ansis.gray(` ${f}`)));
|
|
1729
|
-
}
|
|
1730
|
-
if (status.unstaged.length > 0)
|
|
1731
|
-
console.log(ansis.yellow(` Unstaged: ${status.unstaged.length} files`));
|
|
1732
|
-
if (status.untracked.length > 0)
|
|
1733
|
-
console.log(ansis.yellow(` Untracked: ${status.untracked.length} files`));
|
|
1734
|
-
if (status.unstaged.length > 0 || status.untracked.length > 0) {
|
|
1735
|
-
await stageAllChanges();
|
|
1736
|
-
console.log(ansis.green("\n\u2713 All changes staged"));
|
|
1737
|
-
}
|
|
1738
|
-
const allFiles = [...status.staged, ...status.unstaged, ...status.untracked];
|
|
1739
|
-
let message;
|
|
1740
|
-
if (options.message) {
|
|
1741
|
-
message = options.message;
|
|
1742
|
-
} else if (options.auto) {
|
|
1743
|
-
message = await generateCommitMessage(allFiles);
|
|
1744
|
-
console.log(ansis.cyan("\n\u{1F4AC} Generated commit message:"));
|
|
1745
|
-
console.log(ansis.white(message));
|
|
1746
|
-
} else {
|
|
1747
|
-
const suggested = await generateCommitMessage(allFiles);
|
|
1748
|
-
const { commitMessage } = await inquirer.prompt([{
|
|
1749
|
-
type: "input",
|
|
1750
|
-
name: "commitMessage",
|
|
1751
|
-
message: "Commit message:",
|
|
1752
|
-
default: suggested.split("\n")[0]
|
|
1753
|
-
}]);
|
|
1754
|
-
message = commitMessage;
|
|
1755
|
-
}
|
|
1756
|
-
if (options.dryRun) {
|
|
1757
|
-
console.log(ansis.yellow("\n\u{1F50D} Dry run - no commit created"));
|
|
1758
|
-
console.log(ansis.gray("Would commit with:"));
|
|
1759
|
-
console.log(ansis.white(message));
|
|
1760
|
-
return;
|
|
1761
|
-
}
|
|
1762
|
-
try {
|
|
1763
|
-
await commitChanges(message);
|
|
1764
|
-
console.log(ansis.green("\n\u2713 Changes committed"));
|
|
1765
|
-
} catch (error) {
|
|
1766
|
-
console.log(ansis.red(`
|
|
1767
|
-
\u2717 Commit failed: ${error}`));
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
|
-
async function configSwitchCommand(options) {
|
|
1772
|
-
try {
|
|
1773
|
-
ensureI18nInitialized();
|
|
1774
|
-
if (options.list) {
|
|
1775
|
-
await handleList(options.codeType);
|
|
1776
|
-
return;
|
|
1777
|
-
}
|
|
1778
|
-
if (options.target) {
|
|
1779
|
-
const resolvedCodeType = resolveCodeType(options.codeType);
|
|
1780
|
-
await handleDirectSwitch(resolvedCodeType, options.target);
|
|
1781
|
-
return;
|
|
1782
|
-
}
|
|
1783
|
-
await handleInteractiveSwitch(options.codeType);
|
|
1784
|
-
} catch (error) {
|
|
1785
|
-
if (process$1.env.NODE_ENV === "test" || process$1.env.VITEST) {
|
|
1786
|
-
throw error;
|
|
1787
|
-
}
|
|
1788
|
-
handleGeneralError(error);
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
function resolveCodeType(codeType) {
|
|
1792
|
-
if (codeType !== void 0) {
|
|
1793
|
-
const resolved = resolveCodeToolType$1(codeType);
|
|
1794
|
-
return resolved;
|
|
1795
|
-
}
|
|
1796
|
-
const zcfConfig = readZcfConfig();
|
|
1797
|
-
if (zcfConfig?.codeToolType && isCodeToolType(zcfConfig.codeToolType)) {
|
|
1798
|
-
return zcfConfig.codeToolType;
|
|
1799
|
-
}
|
|
1800
|
-
return DEFAULT_CODE_TOOL_TYPE;
|
|
1801
|
-
}
|
|
1802
|
-
async function handleList(codeType) {
|
|
1803
|
-
const targetCodeType = resolveCodeType(codeType);
|
|
1804
|
-
if (targetCodeType === "claude-code") {
|
|
1805
|
-
await listClaudeCodeProfiles();
|
|
1806
|
-
} else if (targetCodeType === "codex") {
|
|
1807
|
-
await listCodexProvidersWithDisplay();
|
|
1808
|
-
}
|
|
1809
|
-
}
|
|
1810
|
-
async function listCodexProvidersWithDisplay() {
|
|
1811
|
-
const providers = await listCodexProviders();
|
|
1812
|
-
const existingConfig = readCodexConfig();
|
|
1813
|
-
const currentProvider = existingConfig?.modelProvider;
|
|
1814
|
-
const isCommented = existingConfig?.modelProviderCommented;
|
|
1815
|
-
if (!providers || providers.length === 0) {
|
|
1816
|
-
console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
|
|
1817
|
-
return;
|
|
1818
|
-
}
|
|
1819
|
-
console.log(ansis.bold(i18n.t("codex:listProvidersTitle")));
|
|
1820
|
-
console.log();
|
|
1821
|
-
if (currentProvider && !isCommented) {
|
|
1822
|
-
console.log(ansis.cyan(i18n.t("codex:currentProvider", { provider: currentProvider })));
|
|
1823
|
-
console.log();
|
|
1824
|
-
}
|
|
1825
|
-
providers.forEach((provider) => {
|
|
1826
|
-
const isCurrent = currentProvider === provider.id && !isCommented;
|
|
1827
|
-
const status = isCurrent ? ansis.green("\u25CF ") : " ";
|
|
1828
|
-
const current = isCurrent ? ansis.yellow(` (${i18n.t("common:current")})`) : "";
|
|
1829
|
-
console.log(`${status}${ansis.white(provider.name)}${current}`);
|
|
1830
|
-
console.log(` ${ansis.cyan(`ID: ${provider.id}`)} ${ansis.gray(`(${provider.baseUrl})`)}`);
|
|
1831
|
-
if (provider.tempEnvKey) {
|
|
1832
|
-
console.log(` ${ansis.gray(`Env: ${provider.tempEnvKey}`)}`);
|
|
2555
|
+
return "switch";
|
|
2556
|
+
}
|
|
2557
|
+
printSeparator();
|
|
2558
|
+
return void 0;
|
|
1833
2559
|
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
1840
|
-
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
1841
|
-
return;
|
|
2560
|
+
case "q":
|
|
2561
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
2562
|
+
return "exit";
|
|
2563
|
+
default:
|
|
2564
|
+
return void 0;
|
|
1842
2565
|
}
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
const isCurrent = profile.id === currentProfileId;
|
|
1848
|
-
const status = isCurrent ? ansis.green("\u25CF ") : " ";
|
|
1849
|
-
const current = isCurrent ? ansis.yellow(i18n.t("common:current")) : "";
|
|
1850
|
-
console.log(`${status}${ansis.white(profile.name)}${current}`);
|
|
1851
|
-
console.log(` ${ansis.cyan(`ID: ${profile.id}`)} ${ansis.gray(`(${profile.authType})`)}`);
|
|
1852
|
-
console.log();
|
|
2566
|
+
printSeparator();
|
|
2567
|
+
const shouldContinue = await promptBoolean({
|
|
2568
|
+
message: i18n.t("common:returnToMenu"),
|
|
2569
|
+
defaultValue: true
|
|
1853
2570
|
});
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
if (resolvedCodeType === "claude-code") {
|
|
1858
|
-
await handleClaudeCodeDirectSwitch(target);
|
|
1859
|
-
} else if (resolvedCodeType === "codex") {
|
|
1860
|
-
await switchCodexProvider(target);
|
|
2571
|
+
if (!shouldContinue) {
|
|
2572
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
2573
|
+
return "exit";
|
|
1861
2574
|
}
|
|
2575
|
+
return void 0;
|
|
1862
2576
|
}
|
|
1863
|
-
async function
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
}
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
}
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
let resolvedId = normalizedTarget;
|
|
1899
|
-
let resolvedProfile = config.profiles[normalizedTarget];
|
|
1900
|
-
if (!resolvedProfile) {
|
|
1901
|
-
const match = Object.entries(config.profiles).find(([, profile]) => profile.name === normalizedTarget);
|
|
1902
|
-
if (match) {
|
|
1903
|
-
resolvedId = match[0];
|
|
1904
|
-
resolvedProfile = match[1];
|
|
1905
|
-
}
|
|
2577
|
+
async function showCodexMenu() {
|
|
2578
|
+
console.log(ansis.cyan(i18n.t("menu:selectFunction")));
|
|
2579
|
+
console.log(" -------- Codex --------");
|
|
2580
|
+
console.log(
|
|
2581
|
+
` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.codexFullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexFullInit")}`)}`
|
|
2582
|
+
);
|
|
2583
|
+
console.log(
|
|
2584
|
+
` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.codexImportWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexImportWorkflow")}`)}`
|
|
2585
|
+
);
|
|
2586
|
+
console.log(
|
|
2587
|
+
` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.codexConfigureApi")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureApi")}`)}`
|
|
2588
|
+
);
|
|
2589
|
+
console.log(
|
|
2590
|
+
` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.codexConfigureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureMcp")}`)}`
|
|
2591
|
+
);
|
|
2592
|
+
console.log(
|
|
2593
|
+
` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.codexConfigureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureModel")}`)}`
|
|
2594
|
+
);
|
|
2595
|
+
console.log(
|
|
2596
|
+
` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.codexConfigureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureAiMemory")}`)}`
|
|
2597
|
+
);
|
|
2598
|
+
console.log("");
|
|
2599
|
+
printZcfSection({
|
|
2600
|
+
uninstallOption: i18n.t("menu:menuOptions.codexUninstall"),
|
|
2601
|
+
uninstallDescription: i18n.t("menu:menuDescriptions.codexUninstall"),
|
|
2602
|
+
updateOption: i18n.t("menu:menuOptions.codexCheckUpdates"),
|
|
2603
|
+
updateDescription: i18n.t("menu:menuDescriptions.codexCheckUpdates")
|
|
2604
|
+
});
|
|
2605
|
+
const { choice } = await inquirer.prompt({
|
|
2606
|
+
type: "input",
|
|
2607
|
+
name: "choice",
|
|
2608
|
+
message: i18n.t("common:enterChoice"),
|
|
2609
|
+
validate: (value) => {
|
|
2610
|
+
const valid = ["1", "2", "3", "4", "5", "6", "0", "-", "+", "s", "S", "q", "Q"];
|
|
2611
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
1906
2612
|
}
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
2613
|
+
});
|
|
2614
|
+
if (!choice) {
|
|
2615
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2616
|
+
return "exit";
|
|
2617
|
+
}
|
|
2618
|
+
const normalized = choice.toLowerCase();
|
|
2619
|
+
switch (normalized) {
|
|
2620
|
+
case "1":
|
|
2621
|
+
await runCodexFullInit();
|
|
2622
|
+
break;
|
|
2623
|
+
case "2":
|
|
2624
|
+
await runCodexWorkflowImportWithLanguageSelection();
|
|
2625
|
+
break;
|
|
2626
|
+
case "3":
|
|
2627
|
+
await configureCodexApi();
|
|
2628
|
+
break;
|
|
2629
|
+
case "4":
|
|
2630
|
+
await configureCodexMcp();
|
|
2631
|
+
break;
|
|
2632
|
+
case "5":
|
|
2633
|
+
await configureCodexDefaultModelFeature();
|
|
2634
|
+
break;
|
|
2635
|
+
case "6":
|
|
2636
|
+
await configureCodexAiMemoryFeature();
|
|
2637
|
+
break;
|
|
2638
|
+
case "0": {
|
|
2639
|
+
const currentLang = i18n.language;
|
|
2640
|
+
await changeScriptLanguageFeature(currentLang);
|
|
2641
|
+
printSeparator();
|
|
2642
|
+
return void 0;
|
|
1910
2643
|
}
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
2644
|
+
case "-":
|
|
2645
|
+
await runCodexUninstall();
|
|
2646
|
+
printSeparator();
|
|
2647
|
+
return void 0;
|
|
2648
|
+
case "+":
|
|
2649
|
+
await runCodexUpdate();
|
|
2650
|
+
printSeparator();
|
|
2651
|
+
return void 0;
|
|
2652
|
+
case "s": {
|
|
2653
|
+
const switched = await handleCodeToolSwitch("codex");
|
|
2654
|
+
if (switched) {
|
|
2655
|
+
return "switch";
|
|
1919
2656
|
}
|
|
1920
|
-
|
|
1921
|
-
|
|
2657
|
+
printSeparator();
|
|
2658
|
+
return void 0;
|
|
1922
2659
|
}
|
|
2660
|
+
case "q":
|
|
2661
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
2662
|
+
return "exit";
|
|
2663
|
+
default:
|
|
2664
|
+
return void 0;
|
|
1923
2665
|
}
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
2666
|
+
printSeparator();
|
|
2667
|
+
const shouldContinue = await promptBoolean({
|
|
2668
|
+
message: i18n.t("common:returnToMenu"),
|
|
2669
|
+
defaultValue: true
|
|
2670
|
+
});
|
|
2671
|
+
if (!shouldContinue) {
|
|
2672
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
2673
|
+
return "exit";
|
|
1931
2674
|
}
|
|
2675
|
+
return void 0;
|
|
1932
2676
|
}
|
|
1933
|
-
async function
|
|
1934
|
-
const config = ClaudeCodeConfigManager.readConfig();
|
|
1935
|
-
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
1936
|
-
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
1937
|
-
return;
|
|
1938
|
-
}
|
|
1939
|
-
const currentProfileId = config.currentProfileId;
|
|
1940
|
-
const createClaudeCodeChoices = (profiles, currentProfileId2) => {
|
|
1941
|
-
const choices2 = [];
|
|
1942
|
-
const isOfficialMode = !currentProfileId2 || currentProfileId2 === "official";
|
|
1943
|
-
choices2.push({
|
|
1944
|
-
name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("codex:useOfficialLogin")}`,
|
|
1945
|
-
value: "official"
|
|
1946
|
-
});
|
|
1947
|
-
const isCcrMode = currentProfileId2 === "ccr-proxy";
|
|
1948
|
-
choices2.push({
|
|
1949
|
-
name: isCcrMode ? `${ansis.green("\u25CF ")}${i18n.t("multi-config:ccrProxyOption")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("multi-config:ccrProxyOption")}`,
|
|
1950
|
-
value: "ccr"
|
|
1951
|
-
});
|
|
1952
|
-
Object.values(profiles).filter((profile) => profile.id !== "ccr-proxy").forEach((profile) => {
|
|
1953
|
-
const isCurrent = profile.id === currentProfileId2;
|
|
1954
|
-
choices2.push({
|
|
1955
|
-
name: isCurrent ? `${ansis.green("\u25CF ")}${profile.name} ${ansis.yellow("(current)")}` : ` ${profile.name}`,
|
|
1956
|
-
value: profile.id
|
|
1957
|
-
});
|
|
1958
|
-
});
|
|
1959
|
-
return choices2;
|
|
1960
|
-
};
|
|
1961
|
-
const choices = createClaudeCodeChoices(config.profiles, currentProfileId);
|
|
2677
|
+
async function showMainMenu(options = {}) {
|
|
1962
2678
|
try {
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
2679
|
+
if (options.codeType) {
|
|
2680
|
+
try {
|
|
2681
|
+
const resolvedType = await resolveCodeType$1(options.codeType);
|
|
2682
|
+
const currentType = getCurrentCodeTool();
|
|
2683
|
+
if (resolvedType !== currentType) {
|
|
2684
|
+
updateZcfConfig({ codeToolType: resolvedType });
|
|
2685
|
+
console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(resolvedType) })}`));
|
|
2686
|
+
}
|
|
2687
|
+
} catch (err) {
|
|
2688
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
2689
|
+
console.error(ansis.yellow(errorMessage));
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
let exitMenu = false;
|
|
2693
|
+
while (!exitMenu) {
|
|
2694
|
+
const codeTool = getCurrentCodeTool();
|
|
2695
|
+
displayBannerWithInfo(CODE_TOOL_BANNERS[codeTool] || "CCJK");
|
|
2696
|
+
const result = codeTool === "codex" ? await showCodexMenu() : await showClaudeCodeMenu();
|
|
2697
|
+
if (result === "exit") {
|
|
2698
|
+
exitMenu = true;
|
|
2699
|
+
} else if (result === "switch") {
|
|
2700
|
+
continue;
|
|
2701
|
+
}
|
|
1972
2702
|
}
|
|
1973
|
-
await handleClaudeCodeDirectSwitch(selectedConfig);
|
|
1974
2703
|
} catch (error) {
|
|
1975
|
-
if (error
|
|
1976
|
-
|
|
1977
|
-
${i18n.t("common:goodbye")}`));
|
|
1978
|
-
return;
|
|
2704
|
+
if (!handleExitPromptError(error)) {
|
|
2705
|
+
handleGeneralError(error);
|
|
1979
2706
|
}
|
|
1980
|
-
throw error;
|
|
1981
2707
|
}
|
|
1982
2708
|
}
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
if (!providers || providers.length === 0) {
|
|
1986
|
-
console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
|
|
1987
|
-
return;
|
|
1988
|
-
}
|
|
1989
|
-
const existingConfig = readCodexConfig();
|
|
1990
|
-
const currentProvider = existingConfig?.modelProvider;
|
|
1991
|
-
const isCommented = existingConfig?.modelProviderCommented;
|
|
1992
|
-
const createApiConfigChoices = (providers2, currentProvider2, isCommented2) => {
|
|
1993
|
-
const choices2 = [];
|
|
1994
|
-
const isOfficialMode = !currentProvider2 || isCommented2;
|
|
1995
|
-
choices2.push({
|
|
1996
|
-
name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${i18n.t("codex:useOfficialLogin")}`,
|
|
1997
|
-
value: "official"
|
|
1998
|
-
});
|
|
1999
|
-
providers2.forEach((provider) => {
|
|
2000
|
-
const isCurrent = currentProvider2 === provider.id && !isCommented2;
|
|
2001
|
-
choices2.push({
|
|
2002
|
-
name: isCurrent ? `${ansis.green("\u25CF ")}${provider.name} - ${ansis.gray(provider.id)} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${provider.name} - ${ansis.gray(provider.id)}`,
|
|
2003
|
-
value: provider.id
|
|
2004
|
-
});
|
|
2005
|
-
});
|
|
2006
|
-
return choices2;
|
|
2007
|
-
};
|
|
2008
|
-
const choices = createApiConfigChoices(providers, currentProvider, isCommented);
|
|
2709
|
+
|
|
2710
|
+
async function ccr(options = {}) {
|
|
2009
2711
|
try {
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
name: "selectedConfig",
|
|
2013
|
-
message: i18n.t("codex:apiConfigSwitchPrompt"),
|
|
2014
|
-
choices: addNumbersToChoices(choices)
|
|
2015
|
-
}]);
|
|
2016
|
-
if (!selectedConfig) {
|
|
2017
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2018
|
-
return;
|
|
2019
|
-
}
|
|
2020
|
-
let success = false;
|
|
2021
|
-
if (selectedConfig === "official") {
|
|
2022
|
-
success = await switchToOfficialLogin();
|
|
2023
|
-
} else {
|
|
2024
|
-
success = await switchToProvider(selectedConfig);
|
|
2712
|
+
if (!options.skipBanner) {
|
|
2713
|
+
displayBannerWithInfo();
|
|
2025
2714
|
}
|
|
2026
|
-
|
|
2027
|
-
|
|
2715
|
+
const continueInCcr = await showCcrMenu();
|
|
2716
|
+
if (!continueInCcr && !options.skipBanner) {
|
|
2717
|
+
await showMainMenu();
|
|
2028
2718
|
}
|
|
2029
2719
|
} catch (error) {
|
|
2030
|
-
if (error
|
|
2031
|
-
|
|
2032
|
-
${i18n.t("common:goodbye")}`));
|
|
2033
|
-
return;
|
|
2720
|
+
if (!handleExitPromptError(error)) {
|
|
2721
|
+
handleGeneralError(error);
|
|
2034
2722
|
}
|
|
2035
|
-
throw error;
|
|
2036
2723
|
}
|
|
2037
2724
|
}
|
|
2038
2725
|
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2726
|
+
async function checkGitRepo() {
|
|
2727
|
+
try {
|
|
2728
|
+
await exec$1("git", ["rev-parse", "--git-dir"]);
|
|
2729
|
+
return true;
|
|
2730
|
+
} catch {
|
|
2731
|
+
return false;
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
async function getGitStatus() {
|
|
2735
|
+
const isRepo = await checkGitRepo();
|
|
2736
|
+
if (!isRepo)
|
|
2737
|
+
return { isRepo: false, hasChanges: false, staged: [], unstaged: [], untracked: [] };
|
|
2738
|
+
const { stdout } = await exec$1("git", ["status", "--porcelain"]);
|
|
2739
|
+
const lines = stdout.trim().split("\n").filter(Boolean);
|
|
2740
|
+
const staged = [];
|
|
2741
|
+
const unstaged = [];
|
|
2742
|
+
const untracked = [];
|
|
2743
|
+
for (const line of lines) {
|
|
2744
|
+
const [s1, s2] = line.substring(0, 2);
|
|
2745
|
+
const file = line.substring(3);
|
|
2746
|
+
if (s1 !== " " && s1 !== "?")
|
|
2747
|
+
staged.push(file);
|
|
2748
|
+
if (s2 !== " ")
|
|
2749
|
+
unstaged.push(file);
|
|
2750
|
+
if (line.startsWith("??"))
|
|
2751
|
+
untracked.push(file);
|
|
2752
|
+
}
|
|
2753
|
+
return {
|
|
2754
|
+
isRepo: true,
|
|
2755
|
+
hasChanges: staged.length + unstaged.length + untracked.length > 0,
|
|
2756
|
+
staged,
|
|
2757
|
+
unstaged,
|
|
2758
|
+
untracked
|
|
2759
|
+
};
|
|
2760
|
+
}
|
|
2761
|
+
async function generateCommitMessage(files) {
|
|
2762
|
+
if (files.length === 0)
|
|
2763
|
+
return "chore: update files";
|
|
2764
|
+
const { stdout: diff } = await exec$1("git", ["diff", "--cached", "--stat"]);
|
|
2765
|
+
const hasTest = files.some((f) => f.includes("test") || f.includes("spec"));
|
|
2766
|
+
const hasDocs = files.some((f) => f.endsWith(".md"));
|
|
2767
|
+
const hasConfig = files.some((f) => f.endsWith(".json") || f.endsWith(".yaml"));
|
|
2768
|
+
const hasTs = files.some((f) => f.endsWith(".ts"));
|
|
2769
|
+
const type = hasTest ? "test" : hasDocs ? "docs" : hasConfig ? "config" : hasTs ? "feat" : "chore";
|
|
2770
|
+
const scope = files.length === 1 ? files[0].split("/")[0] : void 0;
|
|
2771
|
+
const fileList = files.length <= 3 ? files.join(", ") : `${files.length} files`;
|
|
2772
|
+
const message = scope ? `${type}(${scope}): update ${fileList}` : `${type}: update ${fileList}`;
|
|
2773
|
+
return `${message}
|
|
2774
|
+
|
|
2775
|
+
${diff.trim()}`;
|
|
2776
|
+
}
|
|
2777
|
+
async function stageAllChanges() {
|
|
2778
|
+
await exec$1("git", ["add", "-A"]);
|
|
2779
|
+
}
|
|
2780
|
+
async function commitChanges(message) {
|
|
2781
|
+
await exec$1("git", ["commit", "-m", message]);
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2784
|
+
async function commit(options = {}) {
|
|
2785
|
+
if (!await checkGitRepo()) {
|
|
2786
|
+
console.log(ansis.red("\u2717 Not a git repository"));
|
|
2787
|
+
return;
|
|
2788
|
+
}
|
|
2789
|
+
const status = await getGitStatus();
|
|
2790
|
+
if (!status.hasChanges) {
|
|
2791
|
+
console.log(ansis.yellow("No changes to commit"));
|
|
2792
|
+
return;
|
|
2793
|
+
}
|
|
2794
|
+
console.log(ansis.cyan("\n\u{1F4DD} Changes detected:"));
|
|
2795
|
+
if (status.staged.length > 0) {
|
|
2796
|
+
console.log(ansis.green(` Staged: ${status.staged.length} files`));
|
|
2797
|
+
status.staged.forEach((f) => console.log(ansis.gray(` ${f}`)));
|
|
2798
|
+
}
|
|
2799
|
+
if (status.unstaged.length > 0)
|
|
2800
|
+
console.log(ansis.yellow(` Unstaged: ${status.unstaged.length} files`));
|
|
2801
|
+
if (status.untracked.length > 0)
|
|
2802
|
+
console.log(ansis.yellow(` Untracked: ${status.untracked.length} files`));
|
|
2803
|
+
if (status.unstaged.length > 0 || status.untracked.length > 0) {
|
|
2804
|
+
await stageAllChanges();
|
|
2805
|
+
console.log(ansis.green("\n\u2713 All changes staged"));
|
|
2806
|
+
}
|
|
2807
|
+
const allFiles = [...status.staged, ...status.unstaged, ...status.untracked];
|
|
2808
|
+
let message;
|
|
2809
|
+
if (options.message) {
|
|
2810
|
+
message = options.message;
|
|
2811
|
+
} else if (options.auto) {
|
|
2812
|
+
message = await generateCommitMessage(allFiles);
|
|
2813
|
+
console.log(ansis.cyan("\n\u{1F4AC} Generated commit message:"));
|
|
2814
|
+
console.log(ansis.white(message));
|
|
2815
|
+
} else {
|
|
2816
|
+
const suggested = await generateCommitMessage(allFiles);
|
|
2817
|
+
const { commitMessage } = await inquirer.prompt([{
|
|
2818
|
+
type: "input",
|
|
2819
|
+
name: "commitMessage",
|
|
2820
|
+
message: "Commit message:",
|
|
2821
|
+
default: suggested.split("\n")[0]
|
|
2822
|
+
}]);
|
|
2823
|
+
message = commitMessage;
|
|
2824
|
+
}
|
|
2825
|
+
if (options.dryRun) {
|
|
2826
|
+
console.log(ansis.yellow("\n\u{1F50D} Dry run - no commit created"));
|
|
2827
|
+
console.log(ansis.gray("Would commit with:"));
|
|
2828
|
+
console.log(ansis.white(message));
|
|
2829
|
+
return;
|
|
2830
|
+
}
|
|
2831
|
+
try {
|
|
2832
|
+
await commitChanges(message);
|
|
2833
|
+
console.log(ansis.green("\n\u2713 Changes committed"));
|
|
2834
|
+
} catch (error) {
|
|
2835
|
+
console.log(ansis.red(`
|
|
2836
|
+
\u2717 Commit failed: ${error}`));
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2043
2839
|
|
|
2044
2840
|
const projectFoundationQuestions = [
|
|
2045
2841
|
{
|
|
@@ -4942,6 +5738,217 @@ async function listInterviewSessions() {
|
|
|
4942
5738
|
console.log("");
|
|
4943
5739
|
}
|
|
4944
5740
|
|
|
5741
|
+
async function searchCommand(query, _options) {
|
|
5742
|
+
try {
|
|
5743
|
+
console.log(ansis.cyan(i18n.t("marketplace:searching", { query })));
|
|
5744
|
+
const results = await searchPackages({ query });
|
|
5745
|
+
if (results.packages.length === 0) {
|
|
5746
|
+
console.log(ansis.yellow(i18n.t("marketplace:noResults")));
|
|
5747
|
+
return;
|
|
5748
|
+
}
|
|
5749
|
+
console.log(ansis.green(i18n.t("marketplace:searchResults", { count: results.packages.length })));
|
|
5750
|
+
console.log();
|
|
5751
|
+
for (const pkg of results.packages) {
|
|
5752
|
+
const installed = await isPackageInstalled(pkg.name);
|
|
5753
|
+
const installedMark = installed ? ansis.green("\u2713") : ansis.gray("\u25CB");
|
|
5754
|
+
console.log(`${installedMark} ${ansis.bold(pkg.name)} ${ansis.gray(`v${pkg.version}`)}`);
|
|
5755
|
+
console.log(` ${pkg.description.en || Object.values(pkg.description)[0]}`);
|
|
5756
|
+
console.log(` ${ansis.gray(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
|
|
5757
|
+
if (pkg.verified === "verified") {
|
|
5758
|
+
console.log(` ${ansis.blue("\u2713")} ${i18n.t("marketplace:packageInfo.verified")}`);
|
|
5759
|
+
}
|
|
5760
|
+
console.log();
|
|
5761
|
+
}
|
|
5762
|
+
} catch (err) {
|
|
5763
|
+
console.error(ansis.red(i18n.t("marketplace:searchFailed")));
|
|
5764
|
+
console.error(err);
|
|
5765
|
+
throw err;
|
|
5766
|
+
}
|
|
5767
|
+
}
|
|
5768
|
+
async function installCommand(packageName, options) {
|
|
5769
|
+
try {
|
|
5770
|
+
if (await isPackageInstalled(packageName)) {
|
|
5771
|
+
console.log(ansis.yellow(`Package '${packageName}' is already installed`));
|
|
5772
|
+
return;
|
|
5773
|
+
}
|
|
5774
|
+
const pkg = await getPackage(packageName);
|
|
5775
|
+
if (!pkg) {
|
|
5776
|
+
console.error(ansis.red(i18n.t("marketplace:packageNotFound", { name: packageName })));
|
|
5777
|
+
throw new Error(`Package not found: ${packageName}`);
|
|
5778
|
+
}
|
|
5779
|
+
console.log(ansis.cyan(i18n.t("marketplace:installing", { name: packageName })));
|
|
5780
|
+
const result = await installPackage(packageName, {
|
|
5781
|
+
force: options.force,
|
|
5782
|
+
skipVerification: options.skipVerification
|
|
5783
|
+
});
|
|
5784
|
+
if (result.success) {
|
|
5785
|
+
console.log(ansis.green(i18n.t("marketplace:installSuccess", { name: packageName })));
|
|
5786
|
+
if (result.installedPath) {
|
|
5787
|
+
console.log(ansis.gray(`${i18n.t("marketplace:installedAt")}: ${result.installedPath}`));
|
|
5788
|
+
}
|
|
5789
|
+
} else {
|
|
5790
|
+
console.error(ansis.red(i18n.t("marketplace:installFailed", { name: packageName })));
|
|
5791
|
+
if (result.error) {
|
|
5792
|
+
console.error(ansis.red(i18n.t("marketplace:errors.installError", { error: result.error })));
|
|
5793
|
+
}
|
|
5794
|
+
throw new Error(`Install failed: ${packageName}`);
|
|
5795
|
+
}
|
|
5796
|
+
} catch (err) {
|
|
5797
|
+
console.error(ansis.red(i18n.t("marketplace:installFailed", { name: packageName })));
|
|
5798
|
+
console.error(err);
|
|
5799
|
+
throw err;
|
|
5800
|
+
}
|
|
5801
|
+
}
|
|
5802
|
+
async function uninstallCommand(packageName, options) {
|
|
5803
|
+
try {
|
|
5804
|
+
if (!await isPackageInstalled(packageName)) {
|
|
5805
|
+
console.error(ansis.red(i18n.t("marketplace:packageNotInstalled", { name: packageName })));
|
|
5806
|
+
throw new Error(`Package not installed: ${packageName}`);
|
|
5807
|
+
}
|
|
5808
|
+
console.log(ansis.cyan(i18n.t("marketplace:uninstalling", { name: packageName })));
|
|
5809
|
+
const result = await uninstallPackage(packageName, {
|
|
5810
|
+
force: options.force
|
|
5811
|
+
});
|
|
5812
|
+
if (result.success) {
|
|
5813
|
+
console.log(ansis.green(i18n.t("marketplace:uninstallSuccess", { name: packageName })));
|
|
5814
|
+
} else {
|
|
5815
|
+
console.error(ansis.red(i18n.t("marketplace:uninstallFailed", { name: packageName })));
|
|
5816
|
+
if (result.error) {
|
|
5817
|
+
console.error(ansis.red(i18n.t("marketplace:errors.uninstallError", { error: result.error })));
|
|
5818
|
+
}
|
|
5819
|
+
throw new Error(`Uninstall failed: ${packageName}`);
|
|
5820
|
+
}
|
|
5821
|
+
} catch (err) {
|
|
5822
|
+
console.error(ansis.red(i18n.t("marketplace:uninstallFailed", { name: packageName })));
|
|
5823
|
+
console.error(err);
|
|
5824
|
+
throw err;
|
|
5825
|
+
}
|
|
5826
|
+
}
|
|
5827
|
+
async function updateCommand(packageName, _options) {
|
|
5828
|
+
try {
|
|
5829
|
+
if (packageName) {
|
|
5830
|
+
console.log(ansis.cyan(i18n.t("marketplace:updating", { name: packageName })));
|
|
5831
|
+
const result = await updatePackage(packageName);
|
|
5832
|
+
if (result.success) {
|
|
5833
|
+
console.log(ansis.green(i18n.t("marketplace:updateSuccess", { name: packageName })));
|
|
5834
|
+
} else {
|
|
5835
|
+
console.error(ansis.red(i18n.t("marketplace:updateFailed", { name: packageName })));
|
|
5836
|
+
if (result.error) {
|
|
5837
|
+
console.error(ansis.red(result.error));
|
|
5838
|
+
}
|
|
5839
|
+
throw new Error(`Update failed: ${packageName}`);
|
|
5840
|
+
}
|
|
5841
|
+
} else {
|
|
5842
|
+
console.log(ansis.cyan(i18n.t("marketplace:checkingUpdates")));
|
|
5843
|
+
const updates = await checkForUpdates();
|
|
5844
|
+
if (updates.length === 0) {
|
|
5845
|
+
console.log(ansis.green(i18n.t("marketplace:noUpdates")));
|
|
5846
|
+
return;
|
|
5847
|
+
}
|
|
5848
|
+
console.log(ansis.yellow(i18n.t("marketplace:updatesAvailable", { count: updates.length })));
|
|
5849
|
+
console.log();
|
|
5850
|
+
for (const update of updates) {
|
|
5851
|
+
console.log(` ${ansis.bold(update.id)}: ${ansis.gray(update.currentVersion)} \u2192 ${ansis.green(update.latestVersion)}`);
|
|
5852
|
+
}
|
|
5853
|
+
console.log();
|
|
5854
|
+
console.log(ansis.gray(i18n.t("marketplace:updateHint")));
|
|
5855
|
+
}
|
|
5856
|
+
} catch (err) {
|
|
5857
|
+
console.error(ansis.red(i18n.t("marketplace:updateCheckFailed")));
|
|
5858
|
+
console.error(err);
|
|
5859
|
+
throw err;
|
|
5860
|
+
}
|
|
5861
|
+
}
|
|
5862
|
+
async function listCommand(_options) {
|
|
5863
|
+
try {
|
|
5864
|
+
const installedList = await getInstalledPackages();
|
|
5865
|
+
if (installedList.length === 0) {
|
|
5866
|
+
console.log(ansis.yellow(i18n.t("marketplace:noInstalled")));
|
|
5867
|
+
return;
|
|
5868
|
+
}
|
|
5869
|
+
console.log(ansis.green(i18n.t("marketplace:installedPackages", { count: installedList.length })));
|
|
5870
|
+
console.log();
|
|
5871
|
+
for (const installed of installedList) {
|
|
5872
|
+
const pkg = installed.package;
|
|
5873
|
+
console.log(`${ansis.green("\u2713")} ${ansis.bold(pkg.name)} ${ansis.gray(`v${pkg.version}`)}`);
|
|
5874
|
+
console.log(` ${pkg.description.en || Object.values(pkg.description)[0]}`);
|
|
5875
|
+
console.log(` ${ansis.gray(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
|
|
5876
|
+
console.log();
|
|
5877
|
+
}
|
|
5878
|
+
} catch (err) {
|
|
5879
|
+
console.error(ansis.red(i18n.t("marketplace:listFailed")));
|
|
5880
|
+
console.error(err);
|
|
5881
|
+
throw err;
|
|
5882
|
+
}
|
|
5883
|
+
}
|
|
5884
|
+
async function infoCommand(packageName, _options) {
|
|
5885
|
+
try {
|
|
5886
|
+
const pkg = await getPackage(packageName);
|
|
5887
|
+
if (!pkg) {
|
|
5888
|
+
console.error(ansis.red(i18n.t("marketplace:packageNotFound", { name: packageName })));
|
|
5889
|
+
throw new Error(`Package not found: ${packageName}`);
|
|
5890
|
+
}
|
|
5891
|
+
const installed = await isPackageInstalled(packageName);
|
|
5892
|
+
console.log();
|
|
5893
|
+
console.log(ansis.bold.cyan(pkg.name));
|
|
5894
|
+
console.log(ansis.gray("\u2500".repeat(50)));
|
|
5895
|
+
console.log();
|
|
5896
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.description"))}: ${pkg.description.en || Object.values(pkg.description)[0]}`);
|
|
5897
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.version"))}: ${pkg.version}`);
|
|
5898
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
|
|
5899
|
+
if (pkg.author) {
|
|
5900
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.author"))}: ${pkg.author}`);
|
|
5901
|
+
}
|
|
5902
|
+
if (pkg.license) {
|
|
5903
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.license"))}: ${pkg.license}`);
|
|
5904
|
+
}
|
|
5905
|
+
if (pkg.repository) {
|
|
5906
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.repository"))}: ${pkg.repository}`);
|
|
5907
|
+
}
|
|
5908
|
+
if (pkg.downloads !== void 0) {
|
|
5909
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.downloads"))}: ${pkg.downloads.toLocaleString()}`);
|
|
5910
|
+
}
|
|
5911
|
+
if (pkg.rating !== void 0) {
|
|
5912
|
+
const stars = "\u2605".repeat(Math.round(pkg.rating));
|
|
5913
|
+
const emptyStars = "\u2606".repeat(5 - Math.round(pkg.rating));
|
|
5914
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.rating"))}: ${ansis.yellow(stars)}${ansis.gray(emptyStars)} (${pkg.rating}/5)`);
|
|
5915
|
+
}
|
|
5916
|
+
if (pkg.keywords && pkg.keywords.length > 0) {
|
|
5917
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.keywords"))}: ${pkg.keywords.join(", ")}`);
|
|
5918
|
+
}
|
|
5919
|
+
if (pkg.verified === "verified") {
|
|
5920
|
+
console.log(`${ansis.blue("\u2713")} ${i18n.t("marketplace:packageInfo.verified")}`);
|
|
5921
|
+
}
|
|
5922
|
+
console.log();
|
|
5923
|
+
console.log(`${ansis.bold("Status")}: ${installed ? ansis.green("Installed") : ansis.gray("Not installed")}`);
|
|
5924
|
+
console.log();
|
|
5925
|
+
} catch (err) {
|
|
5926
|
+
console.error(ansis.red(i18n.t("marketplace:infoFailed")));
|
|
5927
|
+
console.error(err);
|
|
5928
|
+
throw err;
|
|
5929
|
+
}
|
|
5930
|
+
}
|
|
5931
|
+
async function registerMarketplaceCommands(cli, withLanguageResolution) {
|
|
5932
|
+
cli.command("marketplace:search <query>", i18n.t("marketplace:commands.search")).alias("mp:search").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).action(await withLanguageResolution(async (query, options) => {
|
|
5933
|
+
await searchCommand(query);
|
|
5934
|
+
}));
|
|
5935
|
+
cli.command("marketplace:install <package>", i18n.t("marketplace:commands.install")).alias("mp:install").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).option("--force, -f", i18n.t("marketplace:options.force")).option("--skip-verification", i18n.t("marketplace:options.skipVerification")).action(await withLanguageResolution(async (packageName, options) => {
|
|
5936
|
+
await installCommand(packageName, options);
|
|
5937
|
+
}));
|
|
5938
|
+
cli.command("marketplace:uninstall <package>", i18n.t("marketplace:commands.uninstall")).alias("mp:uninstall").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).option("--force, -f", i18n.t("marketplace:options.force")).action(await withLanguageResolution(async (packageName, options) => {
|
|
5939
|
+
await uninstallCommand(packageName, options);
|
|
5940
|
+
}));
|
|
5941
|
+
cli.command("marketplace:update [package]", i18n.t("marketplace:commands.update")).alias("mp:update").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).action(await withLanguageResolution(async (packageName, options) => {
|
|
5942
|
+
await updateCommand(packageName);
|
|
5943
|
+
}));
|
|
5944
|
+
cli.command("marketplace:list", i18n.t("marketplace:commands.list")).alias("mp:list").alias("mp:ls").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).action(await withLanguageResolution(async (options) => {
|
|
5945
|
+
await listCommand();
|
|
5946
|
+
}));
|
|
5947
|
+
cli.command("marketplace:info <package>", i18n.t("marketplace:commands.info")).alias("mp:info").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).action(await withLanguageResolution(async (packageName, options) => {
|
|
5948
|
+
await infoCommand(packageName);
|
|
5949
|
+
}));
|
|
5950
|
+
}
|
|
5951
|
+
|
|
4945
5952
|
const MCP_SERVERS = [
|
|
4946
5953
|
{ name: "Filesystem", description: "Secure file operations", package: "@modelcontextprotocol/server-filesystem", category: "core" },
|
|
4947
5954
|
{ name: "GitHub", description: "Repository management", package: "@modelcontextprotocol/server-github", category: "dev" },
|
|
@@ -5945,6 +6952,7 @@ async function setupCommands(cli) {
|
|
|
5945
6952
|
cli.command("mcp <action> [...args]", "MCP Server marketplace (search, trending, install)").option("--lang, -l <lang>", "Display language (zh-CN, en)").action(await withLanguageResolution(async (action, args, options) => {
|
|
5946
6953
|
await mcpMarket(action, args, options);
|
|
5947
6954
|
}));
|
|
6955
|
+
await registerMarketplaceCommands(cli, withLanguageResolution);
|
|
5948
6956
|
cli.command("session <action> [id]", "Manage sessions (save, list, restore, export)").action(async (action, id) => {
|
|
5949
6957
|
if (action === "save") {
|
|
5950
6958
|
await saveSession();
|