ccjk 1.5.0 → 2.0.2
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 +222 -364
- package/README.zh-CN.md +553 -295
- 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-provider-manager.mjs +1 -1
- package/dist/chunks/codex-uninstaller.mjs +2 -2
- package/dist/chunks/commands.mjs +1 -1
- package/dist/chunks/features.mjs +10 -10
- package/dist/chunks/simple-config.mjs +321 -389
- package/dist/chunks/smart-guide.mjs +234 -0
- package/dist/cli.mjs +1795 -433
- package/dist/i18n/locales/en/configuration.json +12 -1
- 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/zh-CN/configuration.json +12 -1
- 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/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +366 -7
- package/package.json +26 -27
- 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/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,
|
|
5
|
-
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { S as STATUS, ch as i18n, n as runConfigWizard, ci as testApiConnection, m as displayCurrentStatus, cj as quickSetup, ck as format, k as COLORS, cl as getAllPresets, cm as ensureI18nInitialized, cn as readCcrConfig, co as isCcrInstalled, cp as installCcr, cq as configureCcrFeature, cr as promptBoolean, cs as handleExitPromptError, ct as handleGeneralError, cu as COMETIX_COMMAND_NAME, cv as COMETIX_COMMANDS, cw as installCometixLine, cx as addNumbersToChoices, cy as checkAndUpdateTools, aW as runCodexUpdate, cz as resolveCodeType$1, a2 as resolveCodeToolType$1, cA as readZcfConfig, $ as isCodeToolType, W as DEFAULT_CODE_TOOL_TYPE, a_ as switchCodexProvider, aM as listCodexProviders, aR as readCodexConfig, aD as switchToOfficialLogin, a$ as switchToProvider, cB as readJsonConfig, cC as writeJsonConfig, cD as moveToTrash, U as ZCF_CONFIG_FILE, ah as displayBanner, cE as updateZcfConfig, v as version, cF as resolveAiOutputLanguage, cG as updatePromptOnly, cH as selectAndInstallWorkflows, cI as checkClaudeCodeVersionAndPrompt, l as init, ai as displayBannerWithInfo, X as CODE_TOOL_BANNERS, y as CLAUDE_DIR, aV as runCodexUninstall, b5 as configureCodexMcp, aE as configureCodexApi, aY as runCodexWorkflowImportWithLanguageSelection, aT as runCodexFullInit, cJ as checkSuperpowersInstalled, cK as getSuperpowersSkills, cL as updateSuperpowers, cM as uninstallSuperpowers, cN as installSuperpowers, cO as installSuperpowersViaGit, q as commandExists, z as SETTINGS_FILE, _ as CODE_TOOL_INFO, bb as getToolStatus, bc as getAllToolsStatus, V as CODE_TOOL_TYPES, aj as boxify, be as installTool, cP as readZcfConfigAsync, cQ as initI18n, bV as quickSync, cf as checkAllVersions, cg as upgradeAll, i as detectAllConfigs, bB as displayConfigScan, c9 as displayPermissions, cR as selectScriptLanguage, cS as changeLanguage, bU as runOnboarding } from './chunks/simple-config.mjs';
|
|
5
|
+
import { existsSync, readdirSync, 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,124 +833,397 @@ 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
|
-
|
|
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}`)}`);
|
|
898
|
+
}
|
|
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;
|
|
907
|
+
}
|
|
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));
|
|
938
|
+
}
|
|
939
|
+
} else {
|
|
940
|
+
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToOfficial", { error: result.error })));
|
|
941
|
+
}
|
|
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));
|
|
952
|
+
}
|
|
953
|
+
} else {
|
|
954
|
+
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToCcr", { error: result.error })));
|
|
955
|
+
}
|
|
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];
|
|
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) {
|
|
978
|
+
try {
|
|
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));
|
|
984
|
+
}
|
|
985
|
+
} else {
|
|
986
|
+
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToProfile", { error: result.error })));
|
|
987
|
+
}
|
|
988
|
+
}
|
|
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"));
|
|
1150
|
+
}
|
|
1151
|
+
result.success = true;
|
|
1152
|
+
} catch (error) {
|
|
1153
|
+
result.errors.push(`Failed to remove output styles: ${error.message}`);
|
|
1154
|
+
}
|
|
1155
|
+
return result;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* 2. Remove custom commands directory (commands/ccjk/)
|
|
1159
|
+
*/
|
|
1160
|
+
async removeCustomCommands() {
|
|
1161
|
+
const result = {
|
|
1162
|
+
success: false,
|
|
1163
|
+
removed: [],
|
|
1164
|
+
removedConfigs: [],
|
|
1165
|
+
errors: [],
|
|
1166
|
+
warnings: []
|
|
1167
|
+
};
|
|
1168
|
+
try {
|
|
1169
|
+
const commandsPath = join(homedir(), ".claude", "commands", "ccjk");
|
|
1170
|
+
if (await pathExists(commandsPath)) {
|
|
1171
|
+
const trashResult = await moveToTrash(commandsPath);
|
|
1172
|
+
if (!trashResult[0]?.success) {
|
|
1173
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1174
|
+
}
|
|
1175
|
+
result.removed.push("commands/ccjk/");
|
|
1176
|
+
result.success = true;
|
|
1177
|
+
} else {
|
|
1178
|
+
result.warnings.push(i18n.t("uninstall:commandsNotFound"));
|
|
1179
|
+
result.success = true;
|
|
1180
|
+
}
|
|
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");
|
|
1203
|
+
}
|
|
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 {
|
|
604
1227
|
const claudeMdPath = join(homedir(), ".claude", "CLAUDE.md");
|
|
605
1228
|
if (await pathExists(claudeMdPath)) {
|
|
606
1229
|
const trashResult = await moveToTrash(claudeMdPath);
|
|
@@ -770,7 +1393,7 @@ class ZcfUninstaller {
|
|
|
770
1393
|
result.removed.push(".claude.json (includes MCP configuration)");
|
|
771
1394
|
}
|
|
772
1395
|
try {
|
|
773
|
-
const { uninstallCodeTool } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
1396
|
+
const { uninstallCodeTool } = await import('./chunks/simple-config.mjs').then(function (n) { return n.de; });
|
|
774
1397
|
const success = await uninstallCodeTool("claude-code");
|
|
775
1398
|
if (success) {
|
|
776
1399
|
result.removed.push("@anthropic-ai/claude-code");
|
|
@@ -1006,7 +1629,7 @@ async function uninstall(options = {}) {
|
|
|
1006
1629
|
}
|
|
1007
1630
|
const uninstaller = new ZcfUninstaller(options.lang || "en");
|
|
1008
1631
|
if (codeType === "codex") {
|
|
1009
|
-
const { runCodexUninstall } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
1632
|
+
const { runCodexUninstall } = await import('./chunks/simple-config.mjs').then(function (n) { return n.dd; });
|
|
1010
1633
|
await runCodexUninstall();
|
|
1011
1634
|
return;
|
|
1012
1635
|
}
|
|
@@ -1276,7 +1899,7 @@ async function update(options = {}) {
|
|
|
1276
1899
|
}
|
|
1277
1900
|
return;
|
|
1278
1901
|
}
|
|
1279
|
-
const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
1902
|
+
const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.dc; });
|
|
1280
1903
|
const configLang = await resolveTemplateLanguage(
|
|
1281
1904
|
options.configLang,
|
|
1282
1905
|
// Command line option
|
|
@@ -1325,39 +1948,458 @@ function printSeparator() {
|
|
|
1325
1948
|
${ansis.dim("\u2500".repeat(50))}
|
|
1326
1949
|
`);
|
|
1327
1950
|
}
|
|
1328
|
-
function getCodeToolLabel(codeTool) {
|
|
1329
|
-
return CODE_TOOL_LABELS[codeTool] || codeTool;
|
|
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");
|
|
2009
|
+
}
|
|
2010
|
+
});
|
|
2011
|
+
if (!choice) {
|
|
2012
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
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();
|
|
2030
|
+
}
|
|
2031
|
+
break;
|
|
2032
|
+
}
|
|
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();
|
|
2047
|
+
} else {
|
|
2048
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2049
|
+
}
|
|
2050
|
+
break;
|
|
2051
|
+
}
|
|
2052
|
+
case "3": {
|
|
2053
|
+
const status = await checkSuperpowersInstalled();
|
|
2054
|
+
if (!status.installed) {
|
|
2055
|
+
console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
|
|
2056
|
+
break;
|
|
2057
|
+
}
|
|
2058
|
+
await updateSuperpowers();
|
|
2059
|
+
break;
|
|
2060
|
+
}
|
|
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")));
|
|
2067
|
+
}
|
|
2068
|
+
break;
|
|
2069
|
+
}
|
|
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}`);
|
|
2083
|
+
});
|
|
2084
|
+
}
|
|
2085
|
+
break;
|
|
2086
|
+
}
|
|
2087
|
+
case "0":
|
|
2088
|
+
return;
|
|
2089
|
+
default:
|
|
2090
|
+
return;
|
|
2091
|
+
}
|
|
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");
|
|
2118
|
+
}
|
|
2119
|
+
});
|
|
2120
|
+
if (!choice) {
|
|
2121
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
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
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
break;
|
|
2151
|
+
}
|
|
2152
|
+
case "2": {
|
|
2153
|
+
console.log(ansis.cyan(i18n.t("marketplace:categories.plugin")));
|
|
2154
|
+
console.log(ansis.dim("Category browsing coming soon..."));
|
|
2155
|
+
break;
|
|
2156
|
+
}
|
|
2157
|
+
case "3": {
|
|
2158
|
+
try {
|
|
2159
|
+
const installed = await getInstalledPackages();
|
|
2160
|
+
if (installed.length === 0) {
|
|
2161
|
+
console.log(ansis.yellow(i18n.t("marketplace:noInstalled")));
|
|
2162
|
+
} else {
|
|
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
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
} catch {
|
|
2171
|
+
console.error(ansis.red(i18n.t("marketplace:listFailed")));
|
|
2172
|
+
}
|
|
2173
|
+
break;
|
|
2174
|
+
}
|
|
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;
|
|
2192
|
+
}
|
|
2193
|
+
case "0":
|
|
2194
|
+
return;
|
|
2195
|
+
default:
|
|
2196
|
+
return;
|
|
2197
|
+
}
|
|
2198
|
+
printSeparator();
|
|
2199
|
+
await showMarketplaceMenu();
|
|
2200
|
+
}
|
|
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"));
|
|
2205
|
+
console.log("");
|
|
2206
|
+
console.log(generateQuickActionsPanel(lang));
|
|
2207
|
+
console.log("");
|
|
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");
|
|
2215
|
+
}
|
|
2216
|
+
});
|
|
2217
|
+
if (!choice || choice === "0") {
|
|
2218
|
+
return;
|
|
2219
|
+
}
|
|
2220
|
+
if (choice === "?") {
|
|
2221
|
+
console.log("");
|
|
2222
|
+
console.log(generateSkillReferenceCard(lang));
|
|
2223
|
+
console.log("");
|
|
2224
|
+
printSeparator();
|
|
2225
|
+
await showQuickActionsMenu();
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
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();
|
|
2239
|
+
}
|
|
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"));
|
|
2245
|
+
console.log("");
|
|
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");
|
|
2247
|
+
console.log("");
|
|
2248
|
+
console.log(` ${isZh ? "\u72B6\u6001" : "Status"}: ${installed ? ansis.green(isZh ? "\u5DF2\u542F\u7528" : "Enabled") : ansis.yellow(isZh ? "\u672A\u542F\u7528" : "Disabled")}`);
|
|
2249
|
+
console.log("");
|
|
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")}`);
|
|
2254
|
+
console.log("");
|
|
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");
|
|
2262
|
+
}
|
|
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;
|
|
2276
|
+
}
|
|
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;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
printSeparator();
|
|
2297
|
+
}
|
|
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");
|
|
2317
|
+
}
|
|
2318
|
+
});
|
|
2319
|
+
if (!choice) {
|
|
2320
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
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;
|
|
2328
|
+
}
|
|
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")));
|
|
2338
|
+
} else {
|
|
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}`);
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
2345
|
+
break;
|
|
2346
|
+
}
|
|
2347
|
+
case "3": {
|
|
2348
|
+
await update({ skipBanner: true });
|
|
2349
|
+
break;
|
|
2350
|
+
}
|
|
2351
|
+
case "4": {
|
|
2352
|
+
printSeparator();
|
|
2353
|
+
await showQuickActionsMenu();
|
|
2354
|
+
return;
|
|
2355
|
+
}
|
|
2356
|
+
case "5": {
|
|
2357
|
+
printSeparator();
|
|
2358
|
+
await showSmartGuideMenu();
|
|
2359
|
+
return;
|
|
2360
|
+
}
|
|
2361
|
+
case "0":
|
|
2362
|
+
return;
|
|
2363
|
+
default:
|
|
2364
|
+
return;
|
|
2365
|
+
}
|
|
2366
|
+
printSeparator();
|
|
2367
|
+
}
|
|
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,6 +2503,18 @@ async function showClaudeCodeMenu() {
|
|
|
1454
2503
|
case "7":
|
|
1455
2504
|
await configureEnvPermissionFeature();
|
|
1456
2505
|
break;
|
|
2506
|
+
case "w":
|
|
2507
|
+
await showWorkflowsAndSkillsMenu();
|
|
2508
|
+
printSeparator();
|
|
2509
|
+
return void 0;
|
|
2510
|
+
case "o":
|
|
2511
|
+
await showOutputStylesMenu();
|
|
2512
|
+
printSeparator();
|
|
2513
|
+
return void 0;
|
|
2514
|
+
case "c":
|
|
2515
|
+
await showConfigSwitchMenu();
|
|
2516
|
+
printSeparator();
|
|
2517
|
+
return void 0;
|
|
1457
2518
|
case "r":
|
|
1458
2519
|
await runCcrMenuFeature();
|
|
1459
2520
|
printSeparator();
|
|
@@ -1466,6 +2527,14 @@ async function showClaudeCodeMenu() {
|
|
|
1466
2527
|
await runCometixMenuFeature();
|
|
1467
2528
|
printSeparator();
|
|
1468
2529
|
return void 0;
|
|
2530
|
+
case "p":
|
|
2531
|
+
await showSuperpowersMenu();
|
|
2532
|
+
printSeparator();
|
|
2533
|
+
return void 0;
|
|
2534
|
+
case "m":
|
|
2535
|
+
await showMarketplaceMenu();
|
|
2536
|
+
printSeparator();
|
|
2537
|
+
return void 0;
|
|
1469
2538
|
case "0": {
|
|
1470
2539
|
const currentLang = i18n.language;
|
|
1471
2540
|
await changeScriptLanguageFeature(currentLang);
|
|
@@ -1605,8 +2674,77 @@ async function showCodexMenu() {
|
|
|
1605
2674
|
}
|
|
1606
2675
|
return void 0;
|
|
1607
2676
|
}
|
|
2677
|
+
async function isFirstTimeUser() {
|
|
2678
|
+
const config = readZcfConfig();
|
|
2679
|
+
if (!config || !config.version) {
|
|
2680
|
+
return true;
|
|
2681
|
+
}
|
|
2682
|
+
if (!existsSync(join(CLAUDE_DIR, "commands"))) {
|
|
2683
|
+
return true;
|
|
2684
|
+
}
|
|
2685
|
+
return false;
|
|
2686
|
+
}
|
|
2687
|
+
async function showNewUserWelcome() {
|
|
2688
|
+
console.log("");
|
|
2689
|
+
console.log(ansis.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
|
|
2690
|
+
console.log(ansis.bold.cyan("\u2551") + ansis.bold.white(" \u{1F44B} \u6B22\u8FCE\u4F7F\u7528 CCJK\uFF01 ") + ansis.bold.cyan("\u2551"));
|
|
2691
|
+
console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
|
|
2692
|
+
console.log(`${ansis.bold.cyan("\u2551")} CCJK \u5E2E\u52A9\u60A8\u5FEB\u901F\u914D\u7F6E Claude Code \u5F00\u53D1\u73AF\u5883 ${ansis.bold.cyan("\u2551")}`);
|
|
2693
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u5305\u62EC API \u8BBE\u7F6E\u3001\u5DE5\u4F5C\u6D41\u6A21\u677F\u3001MCP \u670D\u52A1\u7B49 ${ansis.bold.cyan("\u2551")}`);
|
|
2694
|
+
console.log(ansis.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
|
|
2695
|
+
console.log("");
|
|
2696
|
+
const { mode } = await inquirer.prompt({
|
|
2697
|
+
type: "list",
|
|
2698
|
+
name: "mode",
|
|
2699
|
+
message: "\u8BF7\u9009\u62E9\uFF1A",
|
|
2700
|
+
choices: [
|
|
2701
|
+
{
|
|
2702
|
+
name: ansis.green("\u{1F680} \u5FEB\u901F\u5F00\u59CB") + ansis.dim(" - \u63A8\u8350\u65B0\u624B\uFF0C3\u5206\u949F\u5B8C\u6210\u914D\u7F6E"),
|
|
2703
|
+
value: "quick"
|
|
2704
|
+
},
|
|
2705
|
+
{
|
|
2706
|
+
name: ansis.cyan("\u2699\uFE0F \u5B8C\u6574\u914D\u7F6E") + ansis.dim(" - \u81EA\u5B9A\u4E49\u6240\u6709\u9009\u9879"),
|
|
2707
|
+
value: "full"
|
|
2708
|
+
},
|
|
2709
|
+
{
|
|
2710
|
+
name: ansis.yellow("\u{1F4D6} \u67E5\u770B\u5E2E\u52A9") + ansis.dim(" - \u4E86\u89E3 CCJK \u529F\u80FD"),
|
|
2711
|
+
value: "help"
|
|
2712
|
+
}
|
|
2713
|
+
]
|
|
2714
|
+
});
|
|
2715
|
+
return mode;
|
|
2716
|
+
}
|
|
2717
|
+
async function showFeaturesOverview() {
|
|
2718
|
+
console.log("");
|
|
2719
|
+
console.log(ansis.bold.cyan("\u{1F4D6} CCJK \u529F\u80FD\u4ECB\u7ECD"));
|
|
2720
|
+
console.log("");
|
|
2721
|
+
console.log(ansis.cyan("\u6838\u5FC3\u529F\u80FD\uFF1A"));
|
|
2722
|
+
console.log(` ${ansis.green("\u2022")} API \u914D\u7F6E - \u652F\u6301 Auth Token\u3001API Key\u3001CCR \u4EE3\u7406`);
|
|
2723
|
+
console.log(` ${ansis.green("\u2022")} \u5DE5\u4F5C\u6D41\u6A21\u677F - Git\u3001SixStep\u3001Common Tools \u7B49\u9884\u8BBE\u5DE5\u4F5C\u6D41`);
|
|
2724
|
+
console.log(` ${ansis.green("\u2022")} MCP \u670D\u52A1 - \u4EE3\u7801\u5E93\u641C\u7D22\u3001\u6587\u4EF6\u7CFB\u7EDF\u3001\u7F51\u7EDC\u641C\u7D22\u7B49`);
|
|
2725
|
+
console.log(` ${ansis.green("\u2022")} \u8F93\u51FA\u98CE\u683C - \u591A\u79CD AI \u8F93\u51FA\u98CE\u683C\uFF08\u901F\u5EA6\u4F18\u5148\u3001\u67B6\u6784\u5E08\u3001\u7ED3\u5BF9\u7F16\u7A0B\u7B49\uFF09`);
|
|
2726
|
+
console.log("");
|
|
2727
|
+
console.log(ansis.cyan("\u63A8\u8350\u63D2\u4EF6\uFF1A"));
|
|
2728
|
+
console.log(` ${ansis.green("\u2022")} CCR - Claude Code Router \u4EE3\u7406\u5DE5\u5177`);
|
|
2729
|
+
console.log(` ${ansis.green("\u2022")} CCusage - API \u4F7F\u7528\u91CF\u7EDF\u8BA1\u5DE5\u5177`);
|
|
2730
|
+
console.log(` ${ansis.green("\u2022")} Cometix - \u72B6\u6001\u680F\u589E\u5F3A\u5DE5\u5177`);
|
|
2731
|
+
console.log(` ${ansis.green("\u2022")} Superpowers - \u6280\u80FD\u6269\u5C55\u7CFB\u7EDF`);
|
|
2732
|
+
console.log("");
|
|
2733
|
+
console.log(ansis.dim("\u6309 Enter \u7EE7\u7EED..."));
|
|
2734
|
+
await inquirer.prompt([{ type: "input", name: "continue", message: "" }]);
|
|
2735
|
+
}
|
|
1608
2736
|
async function showMainMenu(options = {}) {
|
|
1609
2737
|
try {
|
|
2738
|
+
if (await isFirstTimeUser()) {
|
|
2739
|
+
const mode = await showNewUserWelcome();
|
|
2740
|
+
if (mode === "quick") {
|
|
2741
|
+
await init({ skipPrompt: false });
|
|
2742
|
+
return;
|
|
2743
|
+
} else if (mode === "help") {
|
|
2744
|
+
await showFeaturesOverview();
|
|
2745
|
+
return showMainMenu(options);
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
1610
2748
|
if (options.codeType) {
|
|
1611
2749
|
try {
|
|
1612
2750
|
const resolvedType = await resolveCodeType$1(options.codeType);
|
|
@@ -1746,300 +2884,217 @@ async function commit(options = {}) {
|
|
|
1746
2884
|
} else {
|
|
1747
2885
|
const suggested = await generateCommitMessage(allFiles);
|
|
1748
2886
|
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}`)}`);
|
|
1833
|
-
}
|
|
1834
|
-
console.log();
|
|
1835
|
-
});
|
|
1836
|
-
}
|
|
1837
|
-
async function listClaudeCodeProfiles() {
|
|
1838
|
-
const config = ClaudeCodeConfigManager.readConfig();
|
|
1839
|
-
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
1840
|
-
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
1841
|
-
return;
|
|
1842
|
-
}
|
|
1843
|
-
console.log(ansis.bold(i18n.t("multi-config:availableClaudeCodeProfiles")));
|
|
1844
|
-
console.log();
|
|
1845
|
-
const currentProfileId = config.currentProfileId;
|
|
1846
|
-
Object.values(config.profiles).forEach((profile) => {
|
|
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();
|
|
1853
|
-
});
|
|
1854
|
-
}
|
|
1855
|
-
async function handleDirectSwitch(codeType, target) {
|
|
1856
|
-
const resolvedCodeType = resolveCodeType(codeType);
|
|
1857
|
-
if (resolvedCodeType === "claude-code") {
|
|
1858
|
-
await handleClaudeCodeDirectSwitch(target);
|
|
1859
|
-
} else if (resolvedCodeType === "codex") {
|
|
1860
|
-
await switchCodexProvider(target);
|
|
1861
|
-
}
|
|
1862
|
-
}
|
|
1863
|
-
async function handleClaudeCodeDirectSwitch(target) {
|
|
1864
|
-
if (target === "official") {
|
|
1865
|
-
const result = await ClaudeCodeConfigManager.switchToOfficial();
|
|
1866
|
-
if (result.success) {
|
|
1867
|
-
try {
|
|
1868
|
-
await ClaudeCodeConfigManager.applyProfileSettings(null);
|
|
1869
|
-
console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToOfficial")));
|
|
1870
|
-
} catch (error) {
|
|
1871
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
1872
|
-
console.log(ansis.red(reason));
|
|
1873
|
-
}
|
|
1874
|
-
} else {
|
|
1875
|
-
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToOfficial", { error: result.error })));
|
|
1876
|
-
}
|
|
1877
|
-
} else if (target === "ccr") {
|
|
1878
|
-
const result = await ClaudeCodeConfigManager.switchToCcr();
|
|
1879
|
-
if (result.success) {
|
|
1880
|
-
try {
|
|
1881
|
-
const profile = ClaudeCodeConfigManager.getProfileById("ccr-proxy");
|
|
1882
|
-
await ClaudeCodeConfigManager.applyProfileSettings(profile);
|
|
1883
|
-
console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToCcr")));
|
|
1884
|
-
} catch (error) {
|
|
1885
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
1886
|
-
console.log(ansis.red(reason));
|
|
1887
|
-
}
|
|
1888
|
-
} else {
|
|
1889
|
-
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToCcr", { error: result.error })));
|
|
1890
|
-
}
|
|
1891
|
-
} else {
|
|
1892
|
-
const config = ClaudeCodeConfigManager.readConfig();
|
|
1893
|
-
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
1894
|
-
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
1895
|
-
return;
|
|
1896
|
-
}
|
|
1897
|
-
const normalizedTarget = target.trim();
|
|
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
|
-
}
|
|
1906
|
-
}
|
|
1907
|
-
if (!resolvedProfile) {
|
|
1908
|
-
console.log(ansis.red(i18n.t("multi-config:profileNameNotFound", { name: target })));
|
|
1909
|
-
return;
|
|
1910
|
-
}
|
|
1911
|
-
const result = await ClaudeCodeConfigManager.switchProfile(resolvedId);
|
|
1912
|
-
if (result.success) {
|
|
1913
|
-
try {
|
|
1914
|
-
await ClaudeCodeConfigManager.applyProfileSettings({ ...resolvedProfile, id: resolvedId });
|
|
1915
|
-
console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToProfile", { name: resolvedProfile.name })));
|
|
1916
|
-
} catch (error) {
|
|
1917
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
1918
|
-
console.log(ansis.red(reason));
|
|
1919
|
-
}
|
|
1920
|
-
} else {
|
|
1921
|
-
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToProfile", { error: result.error })));
|
|
1922
|
-
}
|
|
2887
|
+
type: "input",
|
|
2888
|
+
name: "commitMessage",
|
|
2889
|
+
message: "Commit message:",
|
|
2890
|
+
default: suggested.split("\n")[0]
|
|
2891
|
+
}]);
|
|
2892
|
+
message = commitMessage;
|
|
2893
|
+
}
|
|
2894
|
+
if (options.dryRun) {
|
|
2895
|
+
console.log(ansis.yellow("\n\u{1F50D} Dry run - no commit created"));
|
|
2896
|
+
console.log(ansis.gray("Would commit with:"));
|
|
2897
|
+
console.log(ansis.white(message));
|
|
2898
|
+
return;
|
|
2899
|
+
}
|
|
2900
|
+
try {
|
|
2901
|
+
await commitChanges(message);
|
|
2902
|
+
console.log(ansis.green("\n\u2713 Changes committed"));
|
|
2903
|
+
} catch (error) {
|
|
2904
|
+
console.log(ansis.red(`
|
|
2905
|
+
\u2717 Commit failed: ${error}`));
|
|
1923
2906
|
}
|
|
1924
2907
|
}
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
await handleCodexInteractiveSwitch();
|
|
2908
|
+
|
|
2909
|
+
async function checkClaudeCode() {
|
|
2910
|
+
const hasCommand = await commandExists("claude");
|
|
2911
|
+
if (hasCommand) {
|
|
2912
|
+
return { name: "Claude Code", status: "ok", message: "Installed" };
|
|
1931
2913
|
}
|
|
2914
|
+
return {
|
|
2915
|
+
name: "Claude Code",
|
|
2916
|
+
status: "error",
|
|
2917
|
+
message: "Not installed",
|
|
2918
|
+
fix: "Run: npm install -g @anthropic-ai/claude-code"
|
|
2919
|
+
};
|
|
1932
2920
|
}
|
|
1933
|
-
async function
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
1937
|
-
return;
|
|
2921
|
+
async function checkClaudeDir() {
|
|
2922
|
+
if (existsSync(CLAUDE_DIR)) {
|
|
2923
|
+
return { name: "Config Directory", status: "ok", message: CLAUDE_DIR };
|
|
1938
2924
|
}
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
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;
|
|
2925
|
+
return {
|
|
2926
|
+
name: "Config Directory",
|
|
2927
|
+
status: "error",
|
|
2928
|
+
message: "Does not exist",
|
|
2929
|
+
fix: "Run: npx ccjk init"
|
|
1960
2930
|
};
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
2931
|
+
}
|
|
2932
|
+
async function checkSettings() {
|
|
2933
|
+
if (existsSync(SETTINGS_FILE)) {
|
|
2934
|
+
return { name: "settings.json", status: "ok", message: "Configured" };
|
|
2935
|
+
}
|
|
2936
|
+
return {
|
|
2937
|
+
name: "settings.json",
|
|
2938
|
+
status: "warning",
|
|
2939
|
+
message: "Not found",
|
|
2940
|
+
fix: "Run: npx ccjk init"
|
|
2941
|
+
};
|
|
2942
|
+
}
|
|
2943
|
+
async function checkWorkflows() {
|
|
2944
|
+
const commandsDir = join(CLAUDE_DIR, "commands");
|
|
2945
|
+
if (existsSync(commandsDir)) {
|
|
2946
|
+
try {
|
|
2947
|
+
const files = readdirSync(commandsDir, { recursive: true });
|
|
2948
|
+
const mdFiles = files.filter((f) => String(f).endsWith(".md"));
|
|
2949
|
+
return {
|
|
2950
|
+
name: "Workflows",
|
|
2951
|
+
status: "ok",
|
|
2952
|
+
message: `${mdFiles.length} commands installed`
|
|
2953
|
+
};
|
|
2954
|
+
} catch {
|
|
2955
|
+
return { name: "Workflows", status: "warning", message: "Cannot read directory" };
|
|
1972
2956
|
}
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
2957
|
+
}
|
|
2958
|
+
return {
|
|
2959
|
+
name: "Workflows",
|
|
2960
|
+
status: "warning",
|
|
2961
|
+
message: "Not installed",
|
|
2962
|
+
fix: "Run: npx ccjk update"
|
|
2963
|
+
};
|
|
2964
|
+
}
|
|
2965
|
+
async function checkMcp() {
|
|
2966
|
+
const mcpConfigPath = join(CLAUDE_DIR, "mcp.json");
|
|
2967
|
+
const settingsPath = SETTINGS_FILE;
|
|
2968
|
+
if (existsSync(settingsPath)) {
|
|
2969
|
+
try {
|
|
2970
|
+
const { readFileSync } = await import('node:fs');
|
|
2971
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
2972
|
+
if (settings.mcpServers && Object.keys(settings.mcpServers).length > 0) {
|
|
2973
|
+
const count = Object.keys(settings.mcpServers).length;
|
|
2974
|
+
return { name: "MCP Services", status: "ok", message: `${count} services configured` };
|
|
2975
|
+
}
|
|
2976
|
+
} catch {
|
|
1979
2977
|
}
|
|
1980
|
-
throw error;
|
|
1981
2978
|
}
|
|
2979
|
+
if (existsSync(mcpConfigPath)) {
|
|
2980
|
+
return { name: "MCP Services", status: "ok", message: "Configured" };
|
|
2981
|
+
}
|
|
2982
|
+
return {
|
|
2983
|
+
name: "MCP Services",
|
|
2984
|
+
status: "warning",
|
|
2985
|
+
message: "Not configured",
|
|
2986
|
+
fix: "Run: npx ccjk init and select MCP services"
|
|
2987
|
+
};
|
|
1982
2988
|
}
|
|
1983
|
-
async function
|
|
1984
|
-
const
|
|
1985
|
-
if (
|
|
1986
|
-
|
|
1987
|
-
return;
|
|
2989
|
+
async function checkCcr() {
|
|
2990
|
+
const hasCcr = await commandExists("ccr");
|
|
2991
|
+
if (hasCcr) {
|
|
2992
|
+
return { name: "CCR Proxy", status: "ok", message: "Installed" };
|
|
1988
2993
|
}
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
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;
|
|
2994
|
+
return {
|
|
2995
|
+
name: "CCR Proxy",
|
|
2996
|
+
status: "warning",
|
|
2997
|
+
message: "Not installed (optional)",
|
|
2998
|
+
fix: "Run: npx ccjk ccr to install"
|
|
2007
2999
|
};
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
}
|
|
2020
|
-
|
|
2021
|
-
if (selectedConfig === "official") {
|
|
2022
|
-
success = await switchToOfficialLogin();
|
|
2023
|
-
} else {
|
|
2024
|
-
success = await switchToProvider(selectedConfig);
|
|
2025
|
-
}
|
|
2026
|
-
if (!success) {
|
|
2027
|
-
console.log(ansis.red(i18n.t("common:operationFailed")));
|
|
2028
|
-
}
|
|
2029
|
-
} catch (error) {
|
|
2030
|
-
if (error.name === "ExitPromptError") {
|
|
2031
|
-
console.log(ansis.cyan(`
|
|
2032
|
-
${i18n.t("common:goodbye")}`));
|
|
2033
|
-
return;
|
|
3000
|
+
}
|
|
3001
|
+
async function checkOutputStyles() {
|
|
3002
|
+
const stylesDir = join(CLAUDE_DIR, "output-styles");
|
|
3003
|
+
if (existsSync(stylesDir)) {
|
|
3004
|
+
try {
|
|
3005
|
+
const files = readdirSync(stylesDir).filter((f) => f.endsWith(".md"));
|
|
3006
|
+
return {
|
|
3007
|
+
name: "Output Styles",
|
|
3008
|
+
status: "ok",
|
|
3009
|
+
message: `${files.length} styles available`
|
|
3010
|
+
};
|
|
3011
|
+
} catch {
|
|
3012
|
+
return { name: "Output Styles", status: "warning", message: "Cannot read directory" };
|
|
2034
3013
|
}
|
|
2035
|
-
throw error;
|
|
2036
3014
|
}
|
|
3015
|
+
return {
|
|
3016
|
+
name: "Output Styles",
|
|
3017
|
+
status: "warning",
|
|
3018
|
+
message: "Not installed",
|
|
3019
|
+
fix: "Run: npx ccjk init"
|
|
3020
|
+
};
|
|
3021
|
+
}
|
|
3022
|
+
async function doctor() {
|
|
3023
|
+
console.log("");
|
|
3024
|
+
console.log(ansis.bold.cyan("\u{1F50D} CCJK Health Check"));
|
|
3025
|
+
console.log(ansis.dim("\u2500".repeat(50)));
|
|
3026
|
+
console.log("");
|
|
3027
|
+
const checks = [
|
|
3028
|
+
checkClaudeCode,
|
|
3029
|
+
checkClaudeDir,
|
|
3030
|
+
checkSettings,
|
|
3031
|
+
checkWorkflows,
|
|
3032
|
+
checkMcp,
|
|
3033
|
+
checkCcr,
|
|
3034
|
+
checkOutputStyles
|
|
3035
|
+
];
|
|
3036
|
+
let hasErrors = false;
|
|
3037
|
+
let hasWarnings = false;
|
|
3038
|
+
for (const check of checks) {
|
|
3039
|
+
const result = await check();
|
|
3040
|
+
const statusIcon = result.status === "ok" ? ansis.green("\u2705") : result.status === "warning" ? ansis.yellow("\u26A0\uFE0F") : ansis.red("\u274C");
|
|
3041
|
+
const statusColor = result.status === "ok" ? ansis.green : result.status === "warning" ? ansis.yellow : ansis.red;
|
|
3042
|
+
console.log(`${statusIcon} ${ansis.bold(result.name)}: ${statusColor(result.message)}`);
|
|
3043
|
+
if (result.fix) {
|
|
3044
|
+
console.log(ansis.dim(` \u{1F4A1} Fix: ${result.fix}`));
|
|
3045
|
+
}
|
|
3046
|
+
if (result.status === "error")
|
|
3047
|
+
hasErrors = true;
|
|
3048
|
+
if (result.status === "warning")
|
|
3049
|
+
hasWarnings = true;
|
|
3050
|
+
}
|
|
3051
|
+
console.log("");
|
|
3052
|
+
console.log(ansis.dim("\u2500".repeat(50)));
|
|
3053
|
+
if (hasErrors) {
|
|
3054
|
+
console.log(ansis.red("\u274C Issues found - please follow the suggestions above"));
|
|
3055
|
+
} else if (hasWarnings) {
|
|
3056
|
+
console.log(ansis.yellow("\u26A0\uFE0F Configuration is functional, but some features may be limited"));
|
|
3057
|
+
} else {
|
|
3058
|
+
console.log(ansis.green("\u2705 All checks passed - CCJK is properly configured!"));
|
|
3059
|
+
}
|
|
3060
|
+
console.log("");
|
|
2037
3061
|
}
|
|
2038
3062
|
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
};
|
|
3063
|
+
async function showFeatures() {
|
|
3064
|
+
console.log("");
|
|
3065
|
+
console.log(ansis.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
|
|
3066
|
+
console.log(ansis.bold.cyan("\u2551") + ansis.bold.white(" \u{1F4E6} CCJK \u529F\u80FD\u4E00\u89C8 ") + ansis.bold.cyan("\u2551"));
|
|
3067
|
+
console.log(ansis.bold.cyan("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
|
|
3068
|
+
console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
|
|
3069
|
+
console.log(ansis.bold.cyan("\u2551") + ansis.bold.yellow(" \u{1F527} CLI \u547D\u4EE4 ") + ansis.bold.cyan("\u2551"));
|
|
3070
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.cyan("ccjk init")} \u521D\u59CB\u5316\u73AF\u5883\u914D\u7F6E ${ansis.bold.cyan("\u2551")}`);
|
|
3071
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.cyan("ccjk update")} \u66F4\u65B0\u5DE5\u4F5C\u6D41\u548C\u6A21\u677F ${ansis.bold.cyan("\u2551")}`);
|
|
3072
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.cyan("ccjk cs")} \u5207\u6362 API \u914D\u7F6E ${ansis.bold.cyan("\u2551")}`);
|
|
3073
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.cyan("ccjk doctor")} \u8BCA\u65AD\u914D\u7F6E\u95EE\u9898 ${ansis.bold.cyan("\u2551")}`);
|
|
3074
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.cyan("ccjk ccr")} CCR \u4EE3\u7406\u7BA1\u7406 ${ansis.bold.cyan("\u2551")}`);
|
|
3075
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u2514\u2500 ${ansis.cyan("ccjk ccu")} \u4F7F\u7528\u91CF\u7EDF\u8BA1 ${ansis.bold.cyan("\u2551")}`);
|
|
3076
|
+
console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
|
|
3077
|
+
console.log(ansis.bold.cyan("\u2551") + ansis.bold.yellow(" \u{1F4CB} \u5DE5\u4F5C\u6D41\uFF08\u5728 Claude Code \u4E2D\u4F7F\u7528\uFF09 ") + ansis.bold.cyan("\u2551"));
|
|
3078
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.green("/ccjk:workflow")} \u516D\u9636\u6BB5\u5F00\u53D1\u6D41\u7A0B ${ansis.bgGreen.black(" \u63A8\u8350 ")} ${ansis.bold.cyan("\u2551")}`);
|
|
3079
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.green("/ccjk:feat")} \u529F\u80FD\u89C4\u5212\u6D41\u7A0B ${ansis.bold.cyan("\u2551")}`);
|
|
3080
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.green("/git-commit")} \u667A\u80FD\u63D0\u4EA4 ${ansis.bgYellow.black(" \u70ED\u95E8 ")} ${ansis.bold.cyan("\u2551")}`);
|
|
3081
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.green("/git-rollback")} \u56DE\u6EDA\u66F4\u6539 ${ansis.bold.cyan("\u2551")}`);
|
|
3082
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u2514\u2500 ${ansis.green("/git-cleanup")} \u6E05\u7406\u5206\u652F ${ansis.bold.cyan("\u2551")}`);
|
|
3083
|
+
console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
|
|
3084
|
+
console.log(ansis.bold.cyan("\u2551") + ansis.bold.yellow(" \u{1F3A8} \u8F93\u51FA\u98CE\u683C ") + ansis.bold.cyan("\u2551"));
|
|
3085
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.magenta("senior-architect")} \u8D44\u6DF1\u67B6\u6784\u5E08\u98CE\u683C ${ansis.bold.cyan("\u2551")}`);
|
|
3086
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.magenta("pair-programmer")} \u7ED3\u5BF9\u7F16\u7A0B\u98CE\u683C ${ansis.bold.cyan("\u2551")}`);
|
|
3087
|
+
console.log(`${ansis.bold.cyan("\u2551")} \u2514\u2500 ${ansis.magenta("speed-coder")} \u5FEB\u901F\u7F16\u7801\u98CE\u683C ${ansis.bold.cyan("\u2551")}`);
|
|
3088
|
+
console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
|
|
3089
|
+
console.log(ansis.bold.cyan("\u2551") + ansis.bold.yellow(" \u26A1 \u5FEB\u6377\u64CD\u4F5C\uFF08\u5728 Claude Code \u4E2D\u8F93\u5165\u6570\u5B57\uFF09 ") + ansis.bold.cyan("\u2551"));
|
|
3090
|
+
console.log(`${ansis.bold.cyan("\u2551")} ${ansis.dim("1=\u667A\u80FD\u63D0\u4EA4 2=\u4EE3\u7801\u5BA1\u67E5 3=\u7F16\u5199\u6D4B\u8BD5 4=\u89C4\u5212\u529F\u80FD")} ${ansis.bold.cyan("\u2551")}`);
|
|
3091
|
+
console.log(`${ansis.bold.cyan("\u2551")} ${ansis.dim("5=\u8C03\u8BD5\u95EE\u9898 6=\u5934\u8111\u98CE\u66B4 7=\u9A8C\u8BC1\u4EE3\u7801 8=\u5199\u6587\u6863")} ${ansis.bold.cyan("\u2551")}`);
|
|
3092
|
+
console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
|
|
3093
|
+
console.log(ansis.bold.cyan("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
|
|
3094
|
+
console.log(ansis.bold.cyan("\u2551") + ansis.dim(" \u{1F4A1} \u63D0\u793A\uFF1A\u8F93\u5165 ccjk <\u547D\u4EE4> --help \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5 ") + ansis.bold.cyan("\u2551"));
|
|
3095
|
+
console.log(ansis.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
|
|
3096
|
+
console.log("");
|
|
3097
|
+
}
|
|
2043
3098
|
|
|
2044
3099
|
const projectFoundationQuestions = [
|
|
2045
3100
|
{
|
|
@@ -4942,6 +5997,217 @@ async function listInterviewSessions() {
|
|
|
4942
5997
|
console.log("");
|
|
4943
5998
|
}
|
|
4944
5999
|
|
|
6000
|
+
async function searchCommand(query, _options) {
|
|
6001
|
+
try {
|
|
6002
|
+
console.log(ansis.cyan(i18n.t("marketplace:searching", { query })));
|
|
6003
|
+
const results = await searchPackages({ query });
|
|
6004
|
+
if (results.packages.length === 0) {
|
|
6005
|
+
console.log(ansis.yellow(i18n.t("marketplace:noResults")));
|
|
6006
|
+
return;
|
|
6007
|
+
}
|
|
6008
|
+
console.log(ansis.green(i18n.t("marketplace:searchResults", { count: results.packages.length })));
|
|
6009
|
+
console.log();
|
|
6010
|
+
for (const pkg of results.packages) {
|
|
6011
|
+
const installed = await isPackageInstalled(pkg.name);
|
|
6012
|
+
const installedMark = installed ? ansis.green("\u2713") : ansis.gray("\u25CB");
|
|
6013
|
+
console.log(`${installedMark} ${ansis.bold(pkg.name)} ${ansis.gray(`v${pkg.version}`)}`);
|
|
6014
|
+
console.log(` ${pkg.description.en || Object.values(pkg.description)[0]}`);
|
|
6015
|
+
console.log(` ${ansis.gray(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
|
|
6016
|
+
if (pkg.verified === "verified") {
|
|
6017
|
+
console.log(` ${ansis.blue("\u2713")} ${i18n.t("marketplace:packageInfo.verified")}`);
|
|
6018
|
+
}
|
|
6019
|
+
console.log();
|
|
6020
|
+
}
|
|
6021
|
+
} catch (err) {
|
|
6022
|
+
console.error(ansis.red(i18n.t("marketplace:searchFailed")));
|
|
6023
|
+
console.error(err);
|
|
6024
|
+
throw err;
|
|
6025
|
+
}
|
|
6026
|
+
}
|
|
6027
|
+
async function installCommand(packageName, options) {
|
|
6028
|
+
try {
|
|
6029
|
+
if (await isPackageInstalled(packageName)) {
|
|
6030
|
+
console.log(ansis.yellow(`Package '${packageName}' is already installed`));
|
|
6031
|
+
return;
|
|
6032
|
+
}
|
|
6033
|
+
const pkg = await getPackage(packageName);
|
|
6034
|
+
if (!pkg) {
|
|
6035
|
+
console.error(ansis.red(i18n.t("marketplace:packageNotFound", { name: packageName })));
|
|
6036
|
+
throw new Error(`Package not found: ${packageName}`);
|
|
6037
|
+
}
|
|
6038
|
+
console.log(ansis.cyan(i18n.t("marketplace:installing", { name: packageName })));
|
|
6039
|
+
const result = await installPackage(packageName, {
|
|
6040
|
+
force: options.force,
|
|
6041
|
+
skipVerification: options.skipVerification
|
|
6042
|
+
});
|
|
6043
|
+
if (result.success) {
|
|
6044
|
+
console.log(ansis.green(i18n.t("marketplace:installSuccess", { name: packageName })));
|
|
6045
|
+
if (result.installedPath) {
|
|
6046
|
+
console.log(ansis.gray(`${i18n.t("marketplace:installedAt")}: ${result.installedPath}`));
|
|
6047
|
+
}
|
|
6048
|
+
} else {
|
|
6049
|
+
console.error(ansis.red(i18n.t("marketplace:installFailed", { name: packageName })));
|
|
6050
|
+
if (result.error) {
|
|
6051
|
+
console.error(ansis.red(i18n.t("marketplace:errors.installError", { error: result.error })));
|
|
6052
|
+
}
|
|
6053
|
+
throw new Error(`Install failed: ${packageName}`);
|
|
6054
|
+
}
|
|
6055
|
+
} catch (err) {
|
|
6056
|
+
console.error(ansis.red(i18n.t("marketplace:installFailed", { name: packageName })));
|
|
6057
|
+
console.error(err);
|
|
6058
|
+
throw err;
|
|
6059
|
+
}
|
|
6060
|
+
}
|
|
6061
|
+
async function uninstallCommand(packageName, options) {
|
|
6062
|
+
try {
|
|
6063
|
+
if (!await isPackageInstalled(packageName)) {
|
|
6064
|
+
console.error(ansis.red(i18n.t("marketplace:packageNotInstalled", { name: packageName })));
|
|
6065
|
+
throw new Error(`Package not installed: ${packageName}`);
|
|
6066
|
+
}
|
|
6067
|
+
console.log(ansis.cyan(i18n.t("marketplace:uninstalling", { name: packageName })));
|
|
6068
|
+
const result = await uninstallPackage(packageName, {
|
|
6069
|
+
force: options.force
|
|
6070
|
+
});
|
|
6071
|
+
if (result.success) {
|
|
6072
|
+
console.log(ansis.green(i18n.t("marketplace:uninstallSuccess", { name: packageName })));
|
|
6073
|
+
} else {
|
|
6074
|
+
console.error(ansis.red(i18n.t("marketplace:uninstallFailed", { name: packageName })));
|
|
6075
|
+
if (result.error) {
|
|
6076
|
+
console.error(ansis.red(i18n.t("marketplace:errors.uninstallError", { error: result.error })));
|
|
6077
|
+
}
|
|
6078
|
+
throw new Error(`Uninstall failed: ${packageName}`);
|
|
6079
|
+
}
|
|
6080
|
+
} catch (err) {
|
|
6081
|
+
console.error(ansis.red(i18n.t("marketplace:uninstallFailed", { name: packageName })));
|
|
6082
|
+
console.error(err);
|
|
6083
|
+
throw err;
|
|
6084
|
+
}
|
|
6085
|
+
}
|
|
6086
|
+
async function updateCommand(packageName, _options) {
|
|
6087
|
+
try {
|
|
6088
|
+
if (packageName) {
|
|
6089
|
+
console.log(ansis.cyan(i18n.t("marketplace:updating", { name: packageName })));
|
|
6090
|
+
const result = await updatePackage(packageName);
|
|
6091
|
+
if (result.success) {
|
|
6092
|
+
console.log(ansis.green(i18n.t("marketplace:updateSuccess", { name: packageName })));
|
|
6093
|
+
} else {
|
|
6094
|
+
console.error(ansis.red(i18n.t("marketplace:updateFailed", { name: packageName })));
|
|
6095
|
+
if (result.error) {
|
|
6096
|
+
console.error(ansis.red(result.error));
|
|
6097
|
+
}
|
|
6098
|
+
throw new Error(`Update failed: ${packageName}`);
|
|
6099
|
+
}
|
|
6100
|
+
} else {
|
|
6101
|
+
console.log(ansis.cyan(i18n.t("marketplace:checkingUpdates")));
|
|
6102
|
+
const updates = await checkForUpdates();
|
|
6103
|
+
if (updates.length === 0) {
|
|
6104
|
+
console.log(ansis.green(i18n.t("marketplace:noUpdates")));
|
|
6105
|
+
return;
|
|
6106
|
+
}
|
|
6107
|
+
console.log(ansis.yellow(i18n.t("marketplace:updatesAvailable", { count: updates.length })));
|
|
6108
|
+
console.log();
|
|
6109
|
+
for (const update of updates) {
|
|
6110
|
+
console.log(` ${ansis.bold(update.id)}: ${ansis.gray(update.currentVersion)} \u2192 ${ansis.green(update.latestVersion)}`);
|
|
6111
|
+
}
|
|
6112
|
+
console.log();
|
|
6113
|
+
console.log(ansis.gray(i18n.t("marketplace:updateHint")));
|
|
6114
|
+
}
|
|
6115
|
+
} catch (err) {
|
|
6116
|
+
console.error(ansis.red(i18n.t("marketplace:updateCheckFailed")));
|
|
6117
|
+
console.error(err);
|
|
6118
|
+
throw err;
|
|
6119
|
+
}
|
|
6120
|
+
}
|
|
6121
|
+
async function listCommand(_options) {
|
|
6122
|
+
try {
|
|
6123
|
+
const installedList = await getInstalledPackages();
|
|
6124
|
+
if (installedList.length === 0) {
|
|
6125
|
+
console.log(ansis.yellow(i18n.t("marketplace:noInstalled")));
|
|
6126
|
+
return;
|
|
6127
|
+
}
|
|
6128
|
+
console.log(ansis.green(i18n.t("marketplace:installedPackages", { count: installedList.length })));
|
|
6129
|
+
console.log();
|
|
6130
|
+
for (const installed of installedList) {
|
|
6131
|
+
const pkg = installed.package;
|
|
6132
|
+
console.log(`${ansis.green("\u2713")} ${ansis.bold(pkg.name)} ${ansis.gray(`v${pkg.version}`)}`);
|
|
6133
|
+
console.log(` ${pkg.description.en || Object.values(pkg.description)[0]}`);
|
|
6134
|
+
console.log(` ${ansis.gray(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
|
|
6135
|
+
console.log();
|
|
6136
|
+
}
|
|
6137
|
+
} catch (err) {
|
|
6138
|
+
console.error(ansis.red(i18n.t("marketplace:listFailed")));
|
|
6139
|
+
console.error(err);
|
|
6140
|
+
throw err;
|
|
6141
|
+
}
|
|
6142
|
+
}
|
|
6143
|
+
async function infoCommand(packageName, _options) {
|
|
6144
|
+
try {
|
|
6145
|
+
const pkg = await getPackage(packageName);
|
|
6146
|
+
if (!pkg) {
|
|
6147
|
+
console.error(ansis.red(i18n.t("marketplace:packageNotFound", { name: packageName })));
|
|
6148
|
+
throw new Error(`Package not found: ${packageName}`);
|
|
6149
|
+
}
|
|
6150
|
+
const installed = await isPackageInstalled(packageName);
|
|
6151
|
+
console.log();
|
|
6152
|
+
console.log(ansis.bold.cyan(pkg.name));
|
|
6153
|
+
console.log(ansis.gray("\u2500".repeat(50)));
|
|
6154
|
+
console.log();
|
|
6155
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.description"))}: ${pkg.description.en || Object.values(pkg.description)[0]}`);
|
|
6156
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.version"))}: ${pkg.version}`);
|
|
6157
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
|
|
6158
|
+
if (pkg.author) {
|
|
6159
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.author"))}: ${pkg.author}`);
|
|
6160
|
+
}
|
|
6161
|
+
if (pkg.license) {
|
|
6162
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.license"))}: ${pkg.license}`);
|
|
6163
|
+
}
|
|
6164
|
+
if (pkg.repository) {
|
|
6165
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.repository"))}: ${pkg.repository}`);
|
|
6166
|
+
}
|
|
6167
|
+
if (pkg.downloads !== void 0) {
|
|
6168
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.downloads"))}: ${pkg.downloads.toLocaleString()}`);
|
|
6169
|
+
}
|
|
6170
|
+
if (pkg.rating !== void 0) {
|
|
6171
|
+
const stars = "\u2605".repeat(Math.round(pkg.rating));
|
|
6172
|
+
const emptyStars = "\u2606".repeat(5 - Math.round(pkg.rating));
|
|
6173
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.rating"))}: ${ansis.yellow(stars)}${ansis.gray(emptyStars)} (${pkg.rating}/5)`);
|
|
6174
|
+
}
|
|
6175
|
+
if (pkg.keywords && pkg.keywords.length > 0) {
|
|
6176
|
+
console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.keywords"))}: ${pkg.keywords.join(", ")}`);
|
|
6177
|
+
}
|
|
6178
|
+
if (pkg.verified === "verified") {
|
|
6179
|
+
console.log(`${ansis.blue("\u2713")} ${i18n.t("marketplace:packageInfo.verified")}`);
|
|
6180
|
+
}
|
|
6181
|
+
console.log();
|
|
6182
|
+
console.log(`${ansis.bold("Status")}: ${installed ? ansis.green("Installed") : ansis.gray("Not installed")}`);
|
|
6183
|
+
console.log();
|
|
6184
|
+
} catch (err) {
|
|
6185
|
+
console.error(ansis.red(i18n.t("marketplace:infoFailed")));
|
|
6186
|
+
console.error(err);
|
|
6187
|
+
throw err;
|
|
6188
|
+
}
|
|
6189
|
+
}
|
|
6190
|
+
async function registerMarketplaceCommands(cli, withLanguageResolution) {
|
|
6191
|
+
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) => {
|
|
6192
|
+
await searchCommand(query);
|
|
6193
|
+
}));
|
|
6194
|
+
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) => {
|
|
6195
|
+
await installCommand(packageName, options);
|
|
6196
|
+
}));
|
|
6197
|
+
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) => {
|
|
6198
|
+
await uninstallCommand(packageName, options);
|
|
6199
|
+
}));
|
|
6200
|
+
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) => {
|
|
6201
|
+
await updateCommand(packageName);
|
|
6202
|
+
}));
|
|
6203
|
+
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) => {
|
|
6204
|
+
await listCommand();
|
|
6205
|
+
}));
|
|
6206
|
+
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) => {
|
|
6207
|
+
await infoCommand(packageName);
|
|
6208
|
+
}));
|
|
6209
|
+
}
|
|
6210
|
+
|
|
4945
6211
|
const MCP_SERVERS = [
|
|
4946
6212
|
{ name: "Filesystem", description: "Secure file operations", package: "@modelcontextprotocol/server-filesystem", category: "core" },
|
|
4947
6213
|
{ name: "GitHub", description: "Repository management", package: "@modelcontextprotocol/server-github", category: "dev" },
|
|
@@ -5695,6 +6961,93 @@ async function toolsCommand(action = "list", target, options = {}) {
|
|
|
5695
6961
|
}
|
|
5696
6962
|
}
|
|
5697
6963
|
|
|
6964
|
+
const WORKFLOW_METADATA = {
|
|
6965
|
+
"workflow": { description: "\u516D\u9636\u6BB5\u5F00\u53D1\u6D41\u7A0B", tags: ["\u63A8\u8350", "\u6838\u5FC3"] },
|
|
6966
|
+
"feat": { description: "\u529F\u80FD\u89C4\u5212\u6D41\u7A0B", tags: ["\u63A8\u8350"] },
|
|
6967
|
+
"git-commit": { description: "\u667A\u80FD Git \u63D0\u4EA4", tags: ["\u70ED\u95E8", "Git"] },
|
|
6968
|
+
"git-rollback": { description: "\u56DE\u6EDA\u66F4\u6539", tags: ["Git"] },
|
|
6969
|
+
"git-cleanup": { description: "\u6E05\u7406\u5206\u652F", tags: ["Git"] },
|
|
6970
|
+
"git-worktree": { description: "\u5DE5\u4F5C\u6811\u7BA1\u7406", tags: ["Git"] },
|
|
6971
|
+
"bmad": { description: "BMad \u654F\u6377\u6D41\u7A0B", tags: ["\u654F\u6377"] },
|
|
6972
|
+
"spec": { description: "\u89C4\u683C\u9A71\u52A8\u5F00\u53D1", tags: ["\u89C4\u5212"] }
|
|
6973
|
+
};
|
|
6974
|
+
function getInstalledWorkflows() {
|
|
6975
|
+
const commandsDir = join(CLAUDE_DIR, "commands");
|
|
6976
|
+
const workflows = [];
|
|
6977
|
+
if (!existsSync(commandsDir)) {
|
|
6978
|
+
return workflows;
|
|
6979
|
+
}
|
|
6980
|
+
function scanDir(dir, prefix = "") {
|
|
6981
|
+
try {
|
|
6982
|
+
const items = readdirSync(dir, { withFileTypes: true });
|
|
6983
|
+
for (const item of items) {
|
|
6984
|
+
if (item.isDirectory()) {
|
|
6985
|
+
scanDir(join(dir, item.name), `${prefix}${item.name}/`);
|
|
6986
|
+
} else if (item.name.endsWith(".md")) {
|
|
6987
|
+
const name = item.name.replace(".md", "");
|
|
6988
|
+
const fullName = prefix ? `${prefix.replace(/\/$/, "")}:${name}` : name;
|
|
6989
|
+
const meta = WORKFLOW_METADATA[name] || {};
|
|
6990
|
+
workflows.push({
|
|
6991
|
+
name: `/${fullName}`,
|
|
6992
|
+
path: join(dir, item.name),
|
|
6993
|
+
description: meta.description,
|
|
6994
|
+
installed: true,
|
|
6995
|
+
tags: meta.tags
|
|
6996
|
+
});
|
|
6997
|
+
}
|
|
6998
|
+
}
|
|
6999
|
+
} catch {
|
|
7000
|
+
}
|
|
7001
|
+
}
|
|
7002
|
+
scanDir(commandsDir);
|
|
7003
|
+
return workflows;
|
|
7004
|
+
}
|
|
7005
|
+
function formatTags(tags) {
|
|
7006
|
+
if (!tags || tags.length === 0)
|
|
7007
|
+
return "";
|
|
7008
|
+
return tags.map((tag) => {
|
|
7009
|
+
switch (tag) {
|
|
7010
|
+
case "\u63A8\u8350":
|
|
7011
|
+
return ansis.bgGreen.black(` ${tag} `);
|
|
7012
|
+
case "\u70ED\u95E8":
|
|
7013
|
+
return ansis.bgYellow.black(` ${tag} `);
|
|
7014
|
+
case "\u6838\u5FC3":
|
|
7015
|
+
return ansis.bgBlue.white(` ${tag} `);
|
|
7016
|
+
case "Git":
|
|
7017
|
+
return ansis.bgMagenta.white(` ${tag} `);
|
|
7018
|
+
default:
|
|
7019
|
+
return ansis.bgGray.white(` ${tag} `);
|
|
7020
|
+
}
|
|
7021
|
+
}).join(" ");
|
|
7022
|
+
}
|
|
7023
|
+
async function showWorkflows() {
|
|
7024
|
+
console.log("");
|
|
7025
|
+
console.log(ansis.bold.cyan("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
7026
|
+
console.log(ansis.bold.cyan("\u2502") + ansis.bold.white(" \u{1F4CB} CCJK \u5DE5\u4F5C\u6D41\u7BA1\u7406 ") + ansis.bold.cyan("\u2502"));
|
|
7027
|
+
console.log(ansis.bold.cyan("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"));
|
|
7028
|
+
const workflows = getInstalledWorkflows();
|
|
7029
|
+
if (workflows.length === 0) {
|
|
7030
|
+
console.log(ansis.bold.cyan("\u2502") + ansis.yellow(" \u26A0\uFE0F \u672A\u5B89\u88C5\u4EFB\u4F55\u5DE5\u4F5C\u6D41 ") + ansis.bold.cyan("\u2502"));
|
|
7031
|
+
console.log(ansis.bold.cyan("\u2502") + ansis.dim(" \u8FD0\u884C npx ccjk init \u6216 npx ccjk update \u5B89\u88C5\u5DE5\u4F5C\u6D41 ") + ansis.bold.cyan("\u2502"));
|
|
7032
|
+
} else {
|
|
7033
|
+
console.log(ansis.bold.cyan("\u2502") + ansis.bold.green(` \u2705 \u5DF2\u5B89\u88C5\u5DE5\u4F5C\u6D41 (${workflows.length})`) + " ".repeat(42 - String(workflows.length).length) + ansis.bold.cyan("\u2502"));
|
|
7034
|
+
console.log(`${ansis.bold.cyan("\u2502")} ${ansis.bold.cyan("\u2502")}`);
|
|
7035
|
+
for (const wf of workflows) {
|
|
7036
|
+
const tags = formatTags(wf.tags);
|
|
7037
|
+
const desc = wf.description || "";
|
|
7038
|
+
const nameCol = ansis.green(wf.name.padEnd(20));
|
|
7039
|
+
const descCol = ansis.dim(desc.padEnd(25));
|
|
7040
|
+
console.log(ansis.bold.cyan("\u2502") + ` ${nameCol} ${descCol} ${tags}`.padEnd(60) + ansis.bold.cyan("\u2502"));
|
|
7041
|
+
}
|
|
7042
|
+
}
|
|
7043
|
+
console.log(`${ansis.bold.cyan("\u2502")} ${ansis.bold.cyan("\u2502")}`);
|
|
7044
|
+
console.log(ansis.bold.cyan("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"));
|
|
7045
|
+
console.log(ansis.bold.cyan("\u2502") + ansis.dim(" \u{1F4A1} \u5728 Claude Code \u4E2D\u8F93\u5165\u5DE5\u4F5C\u6D41\u540D\u79F0\u5373\u53EF\u4F7F\u7528 ") + ansis.bold.cyan("\u2502"));
|
|
7046
|
+
console.log(ansis.bold.cyan("\u2502") + ansis.dim(" \u4F8B\u5982: /ccjk:workflow \u5B9E\u73B0\u7528\u6237\u767B\u5F55\u529F\u80FD ") + ansis.bold.cyan("\u2502"));
|
|
7047
|
+
console.log(ansis.bold.cyan("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
7048
|
+
console.log("");
|
|
7049
|
+
}
|
|
7050
|
+
|
|
5698
7051
|
async function resolveAndSwitchLanguage(lang, options, skipPrompt = false) {
|
|
5699
7052
|
const ccjkConfig = await readZcfConfigAsync();
|
|
5700
7053
|
const targetLang = options?.allLang || lang || options?.lang || ccjkConfig?.preferredLang || (skipPrompt ? "en" : await selectScriptLanguage());
|
|
@@ -5742,6 +7095,8 @@ function customizeHelp(sections) {
|
|
|
5742
7095
|
` ${ansis.cyan("ccjk quick")} Express interview (~10 questions)`,
|
|
5743
7096
|
` ${ansis.cyan("ccjk deep")} Deep dive interview (~40+ questions)`,
|
|
5744
7097
|
` ${ansis.cyan("ccjk mcp")} <action> MCP Server marketplace (search, trending, install)`,
|
|
7098
|
+
` ${ansis.cyan("ccjk workflows")} | ${ansis.cyan("wf")} Manage installed workflows`,
|
|
7099
|
+
` ${ansis.cyan("ccjk doctor")} Health check and diagnostics`,
|
|
5745
7100
|
` ${ansis.cyan("ccjk uninstall")} ${i18n.t("cli:help.commandDescriptions.uninstallConfigurations")}`,
|
|
5746
7101
|
` ${ansis.cyan("ccjk check-updates")} ${i18n.t("cli:help.commandDescriptions.checkUpdateVersions")}`,
|
|
5747
7102
|
"",
|
|
@@ -5876,8 +7231,8 @@ async function setupCommands(cli) {
|
|
|
5876
7231
|
cli.command("sync", "Quick sync - update knowledge base from current project").action(async () => {
|
|
5877
7232
|
await quickSync();
|
|
5878
7233
|
});
|
|
5879
|
-
cli.command("doctor", "Run environment health check").
|
|
5880
|
-
await
|
|
7234
|
+
cli.command("doctor", "Run environment health check").action(async () => {
|
|
7235
|
+
await doctor();
|
|
5881
7236
|
});
|
|
5882
7237
|
cli.command("versions", "Check Claude Code, CCJK, and plugin versions").alias("ver").action(async () => {
|
|
5883
7238
|
await checkAllVersions();
|
|
@@ -5945,6 +7300,7 @@ async function setupCommands(cli) {
|
|
|
5945
7300
|
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
7301
|
await mcpMarket(action, args, options);
|
|
5947
7302
|
}));
|
|
7303
|
+
await registerMarketplaceCommands(cli, withLanguageResolution);
|
|
5948
7304
|
cli.command("session <action> [id]", "Manage sessions (save, list, restore, export)").action(async (action, id) => {
|
|
5949
7305
|
if (action === "save") {
|
|
5950
7306
|
await saveSession();
|
|
@@ -5958,6 +7314,12 @@ async function setupCommands(cli) {
|
|
|
5958
7314
|
console.error(`Unknown action: ${action}. Use: save, list, restore, or export`);
|
|
5959
7315
|
}
|
|
5960
7316
|
});
|
|
7317
|
+
cli.command("features", "Show all available features").action(async () => {
|
|
7318
|
+
await showFeatures();
|
|
7319
|
+
});
|
|
7320
|
+
cli.command("workflows", "Manage installed workflows").alias("wf").option("--lang, -l <lang>", "Display language (zh-CN, en)").action(await withLanguageResolution(async () => {
|
|
7321
|
+
await showWorkflows();
|
|
7322
|
+
}));
|
|
5961
7323
|
cli.help((sections) => customizeHelp(sections));
|
|
5962
7324
|
cli.version(version);
|
|
5963
7325
|
}
|