zcf 2.12.12 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -4
- package/dist/chunks/codex-config-switch.mjs +419 -0
- package/dist/chunks/codex-uninstaller.mjs +404 -0
- package/dist/chunks/simple-config.mjs +1862 -374
- package/dist/cli.mjs +1416 -194
- package/dist/i18n/locales/en/cli.json +4 -0
- package/dist/i18n/locales/en/codex.json +102 -0
- package/dist/i18n/locales/en/common.json +4 -1
- package/dist/i18n/locales/en/configuration.json +10 -4
- package/dist/i18n/locales/en/language.json +8 -2
- package/dist/i18n/locales/en/mcp.json +4 -3
- package/dist/i18n/locales/en/menu.json +22 -2
- package/dist/i18n/locales/en/uninstall.json +56 -0
- package/dist/i18n/locales/zh-CN/cli.json +4 -0
- package/dist/i18n/locales/zh-CN/codex.json +102 -0
- package/dist/i18n/locales/zh-CN/common.json +4 -1
- package/dist/i18n/locales/zh-CN/configuration.json +10 -4
- package/dist/i18n/locales/zh-CN/language.json +8 -2
- package/dist/i18n/locales/zh-CN/mcp.json +4 -3
- package/dist/i18n/locales/zh-CN/menu.json +22 -2
- package/dist/i18n/locales/zh-CN/uninstall.json +56 -0
- package/dist/index.d.mts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.mjs +2 -1
- package/dist/shared/zcf.DGjQxTq_.mjs +34 -0
- package/package.json +17 -13
- package/templates/{common → claude-code/common}/settings.json +2 -1
- package/templates/codex/common/config.toml +0 -0
- package/templates/codex/en/system-prompt/engineer-professional.md +87 -0
- package/templates/codex/en/system-prompt/laowang-engineer.md +126 -0
- package/templates/codex/en/system-prompt/nekomata-engineer.md +119 -0
- package/templates/codex/en/workflow/sixStep/prompts/workflow.md +211 -0
- package/templates/codex/zh-CN/system-prompt/engineer-professional.md +88 -0
- package/templates/codex/zh-CN/system-prompt/laowang-engineer.md +126 -0
- package/templates/codex/zh-CN/system-prompt/nekomata-engineer.md +119 -0
- package/templates/codex/zh-CN/workflow/sixStep/prompts/workflow.md +211 -0
- /package/templates/{CLAUDE.md → claude-code/CLAUDE.md} +0 -0
- /package/templates/{en → claude-code/en}/output-styles/engineer-professional.md +0 -0
- /package/templates/{en → claude-code/en}/output-styles/laowang-engineer.md +0 -0
- /package/templates/{en → claude-code/en}/output-styles/nekomata-engineer.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/bmad/commands/bmad-init.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/common/agents/get-current-datetime.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/common/agents/init-architect.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/common/commands/init-project.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/git/commands/git-cleanBranches.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/git/commands/git-commit.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/git/commands/git-rollback.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/git/commands/git-worktree.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/plan/agents/planner.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/plan/agents/ui-ux-designer.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/plan/commands/feat.md +0 -0
- /package/templates/{en → claude-code/en}/workflow/sixStep/commands/workflow.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/output-styles/engineer-professional.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/output-styles/laowang-engineer.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/output-styles/nekomata-engineer.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/bmad/commands/bmad-init.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/common/agents/get-current-datetime.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/common/agents/init-architect.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/common/commands/init-project.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/git/commands/git-cleanBranches.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/git/commands/git-commit.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/git/commands/git-rollback.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/git/commands/git-worktree.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/plan/agents/planner.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/plan/agents/ui-ux-designer.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/plan/commands/feat.md +0 -0
- /package/templates/{zh-CN → claude-code/zh-CN}/workflow/sixStep/commands/workflow.md +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import cac from 'cac';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
|
-
import {
|
|
5
|
-
import { existsSync
|
|
4
|
+
import { a0 as ensureI18nInitialized, W as i18n, a3 as readCcrConfig, a4 as isCcrInstalled, a5 as installCcr, a6 as configureCcrFeature, a7 as handleExitPromptError, a8 as handleGeneralError, l as SUPPORTED_LANGS, a2 as addNumbersToChoices, n as LANG_LABELS, a9 as updateZcfConfig, aa as changeLanguage, ab as readZcfConfig, o as openSettingsJson, d as importRecommendedPermissions, b as importRecommendedEnv, P as applyAiLanguageDirective, ac as configureOutputStyle, N as getExistingModelConfig, J as updateCustomModel, K as updateDefaultModel, ad as isWindows, r as readMcpConfig, v as fixWindowsMcpConfig, w as writeMcpConfig, ae as selectMcpServices, s as backupMcpConfig, af as getMcpServices, u as buildMcpServerConfig, t as mergeMcpServers, O as getExistingApiConfig, ag as formatApiKeyDisplay, x as addCompletedOnboarding, ah as modifyApiConfigPartially, ai as setupCcrConfiguration, aj as validateApiKey, H as configureApi, ak as COMETIX_COMMAND_NAME, al as COMETIX_COMMANDS, am as installCometixLine, an as checkAndUpdateTools, ao as readJsonConfig, ap as writeJsonConfig, h as ZCF_CONFIG_FILE, aq as displayBanner, ar as runCodexUpdate, as as version, at as resolveAiOutputLanguage, au as updatePromptOnly, av as selectAndInstallWorkflows, aw as checkClaudeCodeVersionAndPrompt, k as isCodeToolType, D as DEFAULT_CODE_TOOL_TYPE, ax as displayBannerWithInfo, ay as runCodexUninstall, az as configureCodexMcp, aA as configureCodexApi, aB as runCodexWorkflowImport, aC as runCodexFullInit, i as init, aD as listCodexProviders, aE as getCurrentCodexProvider, aF as switchCodexProvider, X as readCodexConfig, aG as switchToOfficialLogin, aH as switchToProvider, aI as readZcfConfigAsync, aJ as initI18n, aK as selectScriptLanguage } from './chunks/simple-config.mjs';
|
|
5
|
+
import { existsSync } from 'node:fs';
|
|
6
6
|
import { homedir } from 'node:os';
|
|
7
7
|
import inquirer from 'inquirer';
|
|
8
8
|
import { join } from 'pathe';
|
|
9
9
|
import { exec, spawn } from 'node:child_process';
|
|
10
10
|
import { promisify } from 'node:util';
|
|
11
11
|
import process from 'node:process';
|
|
12
|
-
import { x } from 'tinyexec';
|
|
12
|
+
import { x, exec as exec$1 } from 'tinyexec';
|
|
13
|
+
import { pathExists } from 'fs-extra';
|
|
14
|
+
import { m as moveToTrash } from './shared/zcf.DGjQxTq_.mjs';
|
|
13
15
|
import 'dayjs';
|
|
14
16
|
import 'node:url';
|
|
15
17
|
import 'ora';
|
|
16
18
|
import 'semver';
|
|
19
|
+
import 'smol-toml';
|
|
17
20
|
import 'node:fs/promises';
|
|
18
21
|
import 'i18next';
|
|
19
22
|
import 'i18next-fs-backend';
|
|
23
|
+
import 'trash';
|
|
20
24
|
|
|
21
25
|
const execAsync$1 = promisify(exec);
|
|
22
26
|
async function runCcrUi(apiKey) {
|
|
@@ -398,7 +402,7 @@ async function configureMcpFeature() {
|
|
|
398
402
|
const existingConfig = readMcpConfig() || { mcpServers: {} };
|
|
399
403
|
const fixedConfig = fixWindowsMcpConfig(existingConfig);
|
|
400
404
|
writeMcpConfig(fixedConfig);
|
|
401
|
-
console.log(ansis.green(`\u2714
|
|
405
|
+
console.log(ansis.green(`\u2714 ${i18n.t("configuration:windowsMcpConfigFixed")}`));
|
|
402
406
|
}
|
|
403
407
|
}
|
|
404
408
|
const selectedServices = await selectMcpServices();
|
|
@@ -418,9 +422,9 @@ async function configureMcpFeature() {
|
|
|
418
422
|
let config = service.config;
|
|
419
423
|
if (service.requiresApiKey) {
|
|
420
424
|
const { apiKey } = await inquirer.prompt({
|
|
421
|
-
type: "
|
|
425
|
+
type: "password",
|
|
422
426
|
name: "apiKey",
|
|
423
|
-
message: service.apiKeyPrompt,
|
|
427
|
+
message: service.apiKeyPrompt + i18n.t("common:inputHidden"),
|
|
424
428
|
validate: async (value) => !!value || i18n.t("api:keyRequired")
|
|
425
429
|
});
|
|
426
430
|
if (apiKey) {
|
|
@@ -555,7 +559,7 @@ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existi
|
|
|
555
559
|
return;
|
|
556
560
|
}
|
|
557
561
|
}
|
|
558
|
-
const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
562
|
+
const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aM; });
|
|
559
563
|
const aiOutputLang = await selectAiOutputLanguage();
|
|
560
564
|
applyAiLanguageDirective(aiOutputLang);
|
|
561
565
|
updateZcfConfig({ aiOutputLang });
|
|
@@ -564,25 +568,6 @@ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existi
|
|
|
564
568
|
await configureOutputStyle();
|
|
565
569
|
}
|
|
566
570
|
}
|
|
567
|
-
async function clearZcfCacheFeature() {
|
|
568
|
-
ensureI18nInitialized();
|
|
569
|
-
const { confirm } = await inquirer.prompt({
|
|
570
|
-
type: "confirm",
|
|
571
|
-
name: "confirm",
|
|
572
|
-
message: i18n.t("configuration:confirmClearCache") || "Clear all ZCF preferences cache?",
|
|
573
|
-
default: false
|
|
574
|
-
});
|
|
575
|
-
if (!confirm) {
|
|
576
|
-
await handleCancellation();
|
|
577
|
-
return;
|
|
578
|
-
}
|
|
579
|
-
if (existsSync(ZCF_CONFIG_FILE)) {
|
|
580
|
-
unlinkSync(ZCF_CONFIG_FILE);
|
|
581
|
-
console.log(ansis.green(`\u2714 ${i18n.t("configuration:cacheCleared") || "ZCF cache cleared"}`));
|
|
582
|
-
} else {
|
|
583
|
-
console.log(ansis.yellow("No cache found"));
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
571
|
async function changeScriptLanguageFeature(currentLang) {
|
|
587
572
|
ensureI18nInitialized();
|
|
588
573
|
const { lang } = await inquirer.prompt({
|
|
@@ -605,6 +590,214 @@ async function changeScriptLanguageFeature(currentLang) {
|
|
|
605
590
|
console.log(ansis.green(`\u2714 ${i18n.t("language:languageChanged") || "Language changed"}`));
|
|
606
591
|
return lang;
|
|
607
592
|
}
|
|
593
|
+
async function configureCodexDefaultModelFeature() {
|
|
594
|
+
ensureI18nInitialized();
|
|
595
|
+
const { readCodexConfig } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aN; });
|
|
596
|
+
const existingConfig = readCodexConfig();
|
|
597
|
+
const currentModel = existingConfig?.model;
|
|
598
|
+
if (currentModel) {
|
|
599
|
+
console.log(`
|
|
600
|
+
${ansis.blue(`\u2139 ${i18n.t("configuration:existingModelConfig") || "Existing model configuration"}`)}`);
|
|
601
|
+
const modelDisplay = currentModel === "gpt-5-codex" ? "GPT-5-Codex" : currentModel === "gpt-5" ? "GPT-5" : currentModel.charAt(0).toUpperCase() + currentModel.slice(1);
|
|
602
|
+
console.log(ansis.gray(` ${i18n.t("configuration:currentModel") || "Current model"}: ${modelDisplay}
|
|
603
|
+
`));
|
|
604
|
+
const { modify } = await inquirer.prompt({
|
|
605
|
+
type: "confirm",
|
|
606
|
+
name: "modify",
|
|
607
|
+
message: i18n.t("configuration:modifyModel") || "Modify model configuration?",
|
|
608
|
+
default: false
|
|
609
|
+
});
|
|
610
|
+
if (!modify) {
|
|
611
|
+
console.log(ansis.green(`\u2714 ${i18n.t("configuration:keepModel") || "Keeping existing model configuration"}`));
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
const { model } = await inquirer.prompt({
|
|
616
|
+
type: "list",
|
|
617
|
+
name: "model",
|
|
618
|
+
message: i18n.t("configuration:selectDefaultModel") || "Select default model",
|
|
619
|
+
choices: addNumbersToChoices([
|
|
620
|
+
{
|
|
621
|
+
name: i18n.t("configuration:codexModelOptions.gpt5"),
|
|
622
|
+
value: "gpt-5"
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
name: i18n.t("configuration:codexModelOptions.gpt5Codex"),
|
|
626
|
+
value: "gpt-5-codex"
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
name: i18n.t("configuration:codexModelOptions.custom"),
|
|
630
|
+
value: "custom"
|
|
631
|
+
}
|
|
632
|
+
]),
|
|
633
|
+
default: currentModel ? ["gpt-5", "gpt-5-codex", "custom"].indexOf(currentModel) : 1
|
|
634
|
+
// Default to gpt-5-codex
|
|
635
|
+
});
|
|
636
|
+
if (!model) {
|
|
637
|
+
await handleCancellation();
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
if (model === "custom") {
|
|
641
|
+
const { customModel } = await inquirer.prompt({
|
|
642
|
+
type: "input",
|
|
643
|
+
name: "customModel",
|
|
644
|
+
message: `${i18n.t("configuration:enterCustomModel")}${i18n.t("common:emptyToSkip")}`,
|
|
645
|
+
default: ""
|
|
646
|
+
});
|
|
647
|
+
if (!customModel.trim()) {
|
|
648
|
+
console.log(ansis.yellow(`\u26A0 ${i18n.t("configuration:customModelSkipped") || "Custom model configuration skipped"}`));
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
await updateCodexModelProvider(customModel.trim());
|
|
652
|
+
console.log(ansis.green(`\u2714 ${i18n.t("configuration:customModelConfigured") || "Custom model configuration completed"}`));
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
await updateCodexModelProvider(model);
|
|
656
|
+
console.log(ansis.green(`\u2714 ${i18n.t("configuration:modelConfigured") || "Default model configured"}`));
|
|
657
|
+
}
|
|
658
|
+
async function configureCodexAiMemoryFeature() {
|
|
659
|
+
ensureI18nInitialized();
|
|
660
|
+
const { option } = await inquirer.prompt({
|
|
661
|
+
type: "list",
|
|
662
|
+
name: "option",
|
|
663
|
+
message: i18n.t("configuration:selectMemoryOption") || "Select configuration option",
|
|
664
|
+
choices: addNumbersToChoices([
|
|
665
|
+
{
|
|
666
|
+
name: i18n.t("configuration:configureAiLanguage") || "Configure AI output language",
|
|
667
|
+
value: "language"
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
name: i18n.t("configuration:configureSystemPromptStyle") || "Configure global AI system prompt style",
|
|
671
|
+
value: "systemPrompt"
|
|
672
|
+
}
|
|
673
|
+
])
|
|
674
|
+
});
|
|
675
|
+
if (!option) {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
if (option === "language") {
|
|
679
|
+
const zcfConfig = readZcfConfig();
|
|
680
|
+
const existingLang = zcfConfig?.aiOutputLang;
|
|
681
|
+
if (existingLang) {
|
|
682
|
+
console.log(
|
|
683
|
+
`
|
|
684
|
+
${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existing AI output language configuration"}`)}`
|
|
685
|
+
);
|
|
686
|
+
console.log(ansis.gray(` ${i18n.t("configuration:currentLanguage") || "Current language"}: ${existingLang}
|
|
687
|
+
`));
|
|
688
|
+
const { modify } = await inquirer.prompt({
|
|
689
|
+
type: "confirm",
|
|
690
|
+
name: "modify",
|
|
691
|
+
message: i18n.t("configuration:modifyLanguage") || "Modify AI output language?",
|
|
692
|
+
default: false
|
|
693
|
+
});
|
|
694
|
+
if (!modify) {
|
|
695
|
+
console.log(ansis.green(`\u2714 ${i18n.t("configuration:keepLanguage") || "Keeping existing language configuration"}`));
|
|
696
|
+
await ensureLanguageDirectiveInAgents(existingLang);
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aM; });
|
|
701
|
+
const aiOutputLang = await selectAiOutputLanguage();
|
|
702
|
+
await updateCodexLanguageDirective(aiOutputLang);
|
|
703
|
+
updateZcfConfig({ aiOutputLang });
|
|
704
|
+
console.log(ansis.green(`\u2714 ${i18n.t("configuration:aiLanguageConfigured") || "AI output language configured"}`));
|
|
705
|
+
} else if (option === "systemPrompt") {
|
|
706
|
+
const zcfConfig = readZcfConfig();
|
|
707
|
+
const currentLang = zcfConfig?.aiOutputLang || "English";
|
|
708
|
+
const { runCodexSystemPromptSelection } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aN; });
|
|
709
|
+
await runCodexSystemPromptSelection();
|
|
710
|
+
await ensureLanguageDirectiveInAgents(currentLang);
|
|
711
|
+
console.log(ansis.green(`\u2714 ${i18n.t("configuration:systemPromptConfigured")}`));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
async function updateCodexModelProvider(modelProvider) {
|
|
715
|
+
const { readCodexConfig, writeCodexConfig, backupCodexConfig, getBackupMessage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aN; });
|
|
716
|
+
const backupPath = backupCodexConfig();
|
|
717
|
+
if (backupPath) {
|
|
718
|
+
console.log(ansis.gray(getBackupMessage(backupPath)));
|
|
719
|
+
}
|
|
720
|
+
const existingConfig = readCodexConfig();
|
|
721
|
+
const updatedConfig = {
|
|
722
|
+
...existingConfig,
|
|
723
|
+
model: modelProvider,
|
|
724
|
+
// Set the model field
|
|
725
|
+
modelProvider: existingConfig?.modelProvider || null,
|
|
726
|
+
// Preserve existing API provider
|
|
727
|
+
providers: existingConfig?.providers || [],
|
|
728
|
+
mcpServices: existingConfig?.mcpServices || [],
|
|
729
|
+
managed: true,
|
|
730
|
+
otherConfig: existingConfig?.otherConfig || [],
|
|
731
|
+
modelProviderCommented: existingConfig?.modelProviderCommented
|
|
732
|
+
};
|
|
733
|
+
writeCodexConfig(updatedConfig);
|
|
734
|
+
}
|
|
735
|
+
async function ensureLanguageDirectiveInAgents(aiOutputLang) {
|
|
736
|
+
const { readFile, writeFile, exists } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aL; });
|
|
737
|
+
const { homedir } = await import('node:os');
|
|
738
|
+
const { join } = await import('pathe');
|
|
739
|
+
const CODEX_AGENTS_FILE = join(homedir(), ".codex", "AGENTS.md");
|
|
740
|
+
if (!exists(CODEX_AGENTS_FILE)) {
|
|
741
|
+
console.log(ansis.yellow(i18n.t("codex:agentsFileNotFound")));
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
const content = readFile(CODEX_AGENTS_FILE);
|
|
745
|
+
const languageLabels = {
|
|
746
|
+
"Chinese": "Chinese-simplified",
|
|
747
|
+
"English": "English",
|
|
748
|
+
"zh-CN": "Chinese-simplified",
|
|
749
|
+
"en": "English"
|
|
750
|
+
};
|
|
751
|
+
const langLabel = languageLabels[aiOutputLang] || aiOutputLang;
|
|
752
|
+
const hasLanguageDirective = /\*\*Most Important:\s*Always respond in [^*]+\*\*/i.test(content);
|
|
753
|
+
if (!hasLanguageDirective) {
|
|
754
|
+
const { backupCodexAgents, getBackupMessage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aN; });
|
|
755
|
+
const backupPath = backupCodexAgents();
|
|
756
|
+
if (backupPath) {
|
|
757
|
+
console.log(ansis.gray(getBackupMessage(backupPath)));
|
|
758
|
+
}
|
|
759
|
+
let updatedContent = content;
|
|
760
|
+
if (!updatedContent.endsWith("\n")) {
|
|
761
|
+
updatedContent += "\n";
|
|
762
|
+
}
|
|
763
|
+
updatedContent += `
|
|
764
|
+
**Most Important:Always respond in ${langLabel}**
|
|
765
|
+
`;
|
|
766
|
+
writeFile(CODEX_AGENTS_FILE, updatedContent);
|
|
767
|
+
console.log(ansis.gray(` ${i18n.t("configuration:addedLanguageDirective")}: ${langLabel}`));
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
async function updateCodexLanguageDirective(aiOutputLang) {
|
|
771
|
+
const { readFile, writeFile, exists } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aL; });
|
|
772
|
+
const { backupCodexAgents, getBackupMessage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aN; });
|
|
773
|
+
const { homedir } = await import('node:os');
|
|
774
|
+
const { join } = await import('pathe');
|
|
775
|
+
const CODEX_AGENTS_FILE = join(homedir(), ".codex", "AGENTS.md");
|
|
776
|
+
if (!exists(CODEX_AGENTS_FILE)) {
|
|
777
|
+
console.log(ansis.yellow(i18n.t("codex:agentsFileNotFound")));
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
const backupPath = backupCodexAgents();
|
|
781
|
+
if (backupPath) {
|
|
782
|
+
console.log(ansis.gray(getBackupMessage(backupPath)));
|
|
783
|
+
}
|
|
784
|
+
let content = readFile(CODEX_AGENTS_FILE);
|
|
785
|
+
const languageLabels = {
|
|
786
|
+
"Chinese": "Chinese-simplified",
|
|
787
|
+
"English": "English",
|
|
788
|
+
"zh-CN": "Chinese-simplified",
|
|
789
|
+
"en": "English"
|
|
790
|
+
};
|
|
791
|
+
const langLabel = languageLabels[aiOutputLang] || aiOutputLang;
|
|
792
|
+
content = content.replace(/\*\*Most Important:\s*Always respond in [^*]+\*\*\s*/g, "");
|
|
793
|
+
if (!content.endsWith("\n")) {
|
|
794
|
+
content += "\n";
|
|
795
|
+
}
|
|
796
|
+
content += `
|
|
797
|
+
**Most Important:Always respond in ${langLabel}**
|
|
798
|
+
`;
|
|
799
|
+
writeFile(CODEX_AGENTS_FILE, content);
|
|
800
|
+
}
|
|
608
801
|
async function configureEnvPermissionFeature() {
|
|
609
802
|
ensureI18nInitialized();
|
|
610
803
|
const { choice } = await inquirer.prompt({
|
|
@@ -866,33 +1059,783 @@ async function checkUpdates(options = {}) {
|
|
|
866
1059
|
}
|
|
867
1060
|
}
|
|
868
1061
|
|
|
1062
|
+
class ZcfUninstaller {
|
|
1063
|
+
_lang;
|
|
1064
|
+
// Reserved for future i18n support
|
|
1065
|
+
conflictResolution = /* @__PURE__ */ new Map();
|
|
1066
|
+
constructor(lang = "en") {
|
|
1067
|
+
this._lang = lang;
|
|
1068
|
+
this.conflictResolution.set("claude-code", ["mcps"]);
|
|
1069
|
+
void this._lang;
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* 1. Remove outputStyle field from settings.json and output-styles directory
|
|
1073
|
+
*/
|
|
1074
|
+
async removeOutputStyles() {
|
|
1075
|
+
const result = {
|
|
1076
|
+
success: false,
|
|
1077
|
+
removed: [],
|
|
1078
|
+
removedConfigs: [],
|
|
1079
|
+
errors: [],
|
|
1080
|
+
warnings: []
|
|
1081
|
+
};
|
|
1082
|
+
try {
|
|
1083
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
1084
|
+
const outputStylesPath = join(homedir(), ".claude", "output-styles");
|
|
1085
|
+
if (await pathExists(settingsPath)) {
|
|
1086
|
+
const settings = readJsonConfig(settingsPath) || {};
|
|
1087
|
+
if (settings.outputStyle) {
|
|
1088
|
+
delete settings.outputStyle;
|
|
1089
|
+
writeJsonConfig(settingsPath, settings);
|
|
1090
|
+
result.removedConfigs.push("outputStyle field from settings.json");
|
|
1091
|
+
}
|
|
1092
|
+
} else {
|
|
1093
|
+
result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
|
|
1094
|
+
}
|
|
1095
|
+
if (await pathExists(outputStylesPath)) {
|
|
1096
|
+
const trashResult = await moveToTrash(outputStylesPath);
|
|
1097
|
+
if (!trashResult[0]?.success) {
|
|
1098
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1099
|
+
}
|
|
1100
|
+
result.removed.push("~/.claude/output-styles/");
|
|
1101
|
+
} else {
|
|
1102
|
+
result.warnings.push(i18n.t("uninstall:outputStylesDirectoryNotFound"));
|
|
1103
|
+
}
|
|
1104
|
+
result.success = true;
|
|
1105
|
+
} catch (error) {
|
|
1106
|
+
result.errors.push(`Failed to remove output styles: ${error.message}`);
|
|
1107
|
+
}
|
|
1108
|
+
return result;
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* 2. Remove custom commands directory (commands/zcf/)
|
|
1112
|
+
*/
|
|
1113
|
+
async removeCustomCommands() {
|
|
1114
|
+
const result = {
|
|
1115
|
+
success: false,
|
|
1116
|
+
removed: [],
|
|
1117
|
+
removedConfigs: [],
|
|
1118
|
+
errors: [],
|
|
1119
|
+
warnings: []
|
|
1120
|
+
};
|
|
1121
|
+
try {
|
|
1122
|
+
const commandsPath = join(homedir(), ".claude", "commands", "zcf");
|
|
1123
|
+
if (await pathExists(commandsPath)) {
|
|
1124
|
+
const trashResult = await moveToTrash(commandsPath);
|
|
1125
|
+
if (!trashResult[0]?.success) {
|
|
1126
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1127
|
+
}
|
|
1128
|
+
result.removed.push("commands/zcf/");
|
|
1129
|
+
result.success = true;
|
|
1130
|
+
} else {
|
|
1131
|
+
result.warnings.push(i18n.t("uninstall:commandsNotFound"));
|
|
1132
|
+
result.success = true;
|
|
1133
|
+
}
|
|
1134
|
+
} catch (error) {
|
|
1135
|
+
result.errors.push(`Failed to remove custom commands: ${error.message}`);
|
|
1136
|
+
}
|
|
1137
|
+
return result;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* 3. Remove custom agents directory (agents/zcf/)
|
|
1141
|
+
*/
|
|
1142
|
+
async removeCustomAgents() {
|
|
1143
|
+
const result = {
|
|
1144
|
+
success: false,
|
|
1145
|
+
removed: [],
|
|
1146
|
+
removedConfigs: [],
|
|
1147
|
+
errors: [],
|
|
1148
|
+
warnings: []
|
|
1149
|
+
};
|
|
1150
|
+
try {
|
|
1151
|
+
const agentsPath = join(homedir(), ".claude", "agents", "zcf");
|
|
1152
|
+
if (await pathExists(agentsPath)) {
|
|
1153
|
+
const trashResult = await moveToTrash(agentsPath);
|
|
1154
|
+
if (!trashResult[0]?.success) {
|
|
1155
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1156
|
+
}
|
|
1157
|
+
result.removed.push("agents/zcf/");
|
|
1158
|
+
result.success = true;
|
|
1159
|
+
} else {
|
|
1160
|
+
result.warnings.push(i18n.t("uninstall:agentsNotFound"));
|
|
1161
|
+
result.success = true;
|
|
1162
|
+
}
|
|
1163
|
+
} catch (error) {
|
|
1164
|
+
result.errors.push(`Failed to remove custom agents: ${error.message}`);
|
|
1165
|
+
}
|
|
1166
|
+
return result;
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* 4. Remove global memory file (CLAUDE.md)
|
|
1170
|
+
*/
|
|
1171
|
+
async removeClaudeMd() {
|
|
1172
|
+
const result = {
|
|
1173
|
+
success: false,
|
|
1174
|
+
removed: [],
|
|
1175
|
+
removedConfigs: [],
|
|
1176
|
+
errors: [],
|
|
1177
|
+
warnings: []
|
|
1178
|
+
};
|
|
1179
|
+
try {
|
|
1180
|
+
const claudeMdPath = join(homedir(), ".claude", "CLAUDE.md");
|
|
1181
|
+
if (await pathExists(claudeMdPath)) {
|
|
1182
|
+
const trashResult = await moveToTrash(claudeMdPath);
|
|
1183
|
+
if (!trashResult[0]?.success) {
|
|
1184
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1185
|
+
}
|
|
1186
|
+
result.removed.push("CLAUDE.md");
|
|
1187
|
+
result.success = true;
|
|
1188
|
+
} else {
|
|
1189
|
+
result.warnings.push(i18n.t("uninstall:claudeMdNotFound"));
|
|
1190
|
+
result.success = true;
|
|
1191
|
+
}
|
|
1192
|
+
} catch (error) {
|
|
1193
|
+
result.errors.push(`Failed to remove CLAUDE.md: ${error.message}`);
|
|
1194
|
+
}
|
|
1195
|
+
return result;
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* 5. Remove permissions and environment variables
|
|
1199
|
+
*/
|
|
1200
|
+
async removePermissionsAndEnvs() {
|
|
1201
|
+
const result = {
|
|
1202
|
+
success: false,
|
|
1203
|
+
removed: [],
|
|
1204
|
+
removedConfigs: [],
|
|
1205
|
+
errors: [],
|
|
1206
|
+
warnings: []
|
|
1207
|
+
};
|
|
1208
|
+
try {
|
|
1209
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
1210
|
+
if (await pathExists(settingsPath)) {
|
|
1211
|
+
const settings = readJsonConfig(settingsPath) || {};
|
|
1212
|
+
let modified = false;
|
|
1213
|
+
if (settings.permissions) {
|
|
1214
|
+
delete settings.permissions;
|
|
1215
|
+
result.removedConfigs.push("permissions configuration");
|
|
1216
|
+
modified = true;
|
|
1217
|
+
}
|
|
1218
|
+
if (settings.env) {
|
|
1219
|
+
delete settings.env;
|
|
1220
|
+
result.removedConfigs.push("environment variables");
|
|
1221
|
+
modified = true;
|
|
1222
|
+
}
|
|
1223
|
+
if (modified) {
|
|
1224
|
+
writeJsonConfig(settingsPath, settings);
|
|
1225
|
+
}
|
|
1226
|
+
result.success = true;
|
|
1227
|
+
} else {
|
|
1228
|
+
result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
|
|
1229
|
+
result.success = true;
|
|
1230
|
+
}
|
|
1231
|
+
} catch (error) {
|
|
1232
|
+
result.errors.push(`Failed to remove permissions and envs: ${error.message}`);
|
|
1233
|
+
}
|
|
1234
|
+
return result;
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* 6. Remove MCP servers from .claude.json (mcpServers field only)
|
|
1238
|
+
*/
|
|
1239
|
+
async removeMcps() {
|
|
1240
|
+
const result = {
|
|
1241
|
+
success: false,
|
|
1242
|
+
removed: [],
|
|
1243
|
+
removedConfigs: [],
|
|
1244
|
+
errors: [],
|
|
1245
|
+
warnings: []
|
|
1246
|
+
};
|
|
1247
|
+
try {
|
|
1248
|
+
const claudeJsonPath = join(homedir(), ".claude.json");
|
|
1249
|
+
if (await pathExists(claudeJsonPath)) {
|
|
1250
|
+
const config = readJsonConfig(claudeJsonPath) || {};
|
|
1251
|
+
if (config.mcpServers) {
|
|
1252
|
+
delete config.mcpServers;
|
|
1253
|
+
writeJsonConfig(claudeJsonPath, config);
|
|
1254
|
+
result.removedConfigs.push("mcpServers from .claude.json");
|
|
1255
|
+
}
|
|
1256
|
+
result.success = true;
|
|
1257
|
+
} else {
|
|
1258
|
+
result.warnings.push(i18n.t("uninstall:claudeJsonNotFound"));
|
|
1259
|
+
result.success = true;
|
|
1260
|
+
}
|
|
1261
|
+
} catch (error) {
|
|
1262
|
+
result.errors.push(`Failed to remove MCP servers: ${error.message}`);
|
|
1263
|
+
}
|
|
1264
|
+
return result;
|
|
1265
|
+
}
|
|
1266
|
+
/**
|
|
1267
|
+
* 7. Uninstall Claude Code Router and remove configuration
|
|
1268
|
+
*/
|
|
1269
|
+
async uninstallCcr() {
|
|
1270
|
+
const result = {
|
|
1271
|
+
success: false,
|
|
1272
|
+
removed: [],
|
|
1273
|
+
removedConfigs: [],
|
|
1274
|
+
errors: [],
|
|
1275
|
+
warnings: []
|
|
1276
|
+
};
|
|
1277
|
+
try {
|
|
1278
|
+
const ccrPath = join(homedir(), ".claude-code-router");
|
|
1279
|
+
if (await pathExists(ccrPath)) {
|
|
1280
|
+
const trashResult = await moveToTrash(ccrPath);
|
|
1281
|
+
if (!trashResult[0]?.success) {
|
|
1282
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1283
|
+
}
|
|
1284
|
+
result.removed.push(".claude-code-router/");
|
|
1285
|
+
}
|
|
1286
|
+
try {
|
|
1287
|
+
await exec$1("npm", ["uninstall", "-g", "@musistudio/claude-code-router"]);
|
|
1288
|
+
result.removed.push("@musistudio/claude-code-router package");
|
|
1289
|
+
result.success = true;
|
|
1290
|
+
} catch (npmError) {
|
|
1291
|
+
if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
|
|
1292
|
+
result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
|
|
1293
|
+
result.success = true;
|
|
1294
|
+
} else {
|
|
1295
|
+
result.errors.push(`Failed to uninstall CCR package: ${npmError.message}`);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
} catch (error) {
|
|
1299
|
+
result.errors.push(`Failed to uninstall CCR: ${error.message}`);
|
|
1300
|
+
}
|
|
1301
|
+
return result;
|
|
1302
|
+
}
|
|
1303
|
+
/**
|
|
1304
|
+
* 8. Uninstall CCometixLine
|
|
1305
|
+
*/
|
|
1306
|
+
async uninstallCcline() {
|
|
1307
|
+
const result = {
|
|
1308
|
+
success: false,
|
|
1309
|
+
removed: [],
|
|
1310
|
+
removedConfigs: [],
|
|
1311
|
+
errors: [],
|
|
1312
|
+
warnings: []
|
|
1313
|
+
};
|
|
1314
|
+
try {
|
|
1315
|
+
await exec$1("npm", ["uninstall", "-g", "@cometix/ccline"]);
|
|
1316
|
+
result.removed.push("@cometix/ccline package");
|
|
1317
|
+
result.success = true;
|
|
1318
|
+
} catch (error) {
|
|
1319
|
+
if (error.message.includes("not found") || error.message.includes("not installed")) {
|
|
1320
|
+
result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
|
|
1321
|
+
result.success = true;
|
|
1322
|
+
} else {
|
|
1323
|
+
result.errors.push(`Failed to uninstall CCometixLine: ${error.message}`);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
return result;
|
|
1327
|
+
}
|
|
1328
|
+
/**
|
|
1329
|
+
* 9. Uninstall Claude Code and remove entire .claude.json
|
|
1330
|
+
*/
|
|
1331
|
+
async uninstallClaudeCode() {
|
|
1332
|
+
const result = {
|
|
1333
|
+
success: false,
|
|
1334
|
+
removed: [],
|
|
1335
|
+
removedConfigs: [],
|
|
1336
|
+
errors: [],
|
|
1337
|
+
warnings: []
|
|
1338
|
+
};
|
|
1339
|
+
try {
|
|
1340
|
+
const claudeJsonPath = join(homedir(), ".claude.json");
|
|
1341
|
+
if (await pathExists(claudeJsonPath)) {
|
|
1342
|
+
const trashResult = await moveToTrash(claudeJsonPath);
|
|
1343
|
+
if (!trashResult[0]?.success) {
|
|
1344
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1345
|
+
}
|
|
1346
|
+
result.removed.push(".claude.json (includes MCP configuration)");
|
|
1347
|
+
}
|
|
1348
|
+
try {
|
|
1349
|
+
await exec$1("npm", ["uninstall", "-g", "@anthropic-ai/claude-code"]);
|
|
1350
|
+
result.removed.push("@anthropic-ai/claude-code package");
|
|
1351
|
+
result.success = true;
|
|
1352
|
+
} catch (npmError) {
|
|
1353
|
+
if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
|
|
1354
|
+
result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
|
|
1355
|
+
result.success = true;
|
|
1356
|
+
} else {
|
|
1357
|
+
result.errors.push(`Failed to uninstall Claude Code package: ${npmError.message}`);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
} catch (error) {
|
|
1361
|
+
result.errors.push(`Failed to uninstall Claude Code: ${error.message}`);
|
|
1362
|
+
}
|
|
1363
|
+
return result;
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* 10. Remove backup files
|
|
1367
|
+
*/
|
|
1368
|
+
async removeBackups() {
|
|
1369
|
+
const result = {
|
|
1370
|
+
success: false,
|
|
1371
|
+
removed: [],
|
|
1372
|
+
removedConfigs: [],
|
|
1373
|
+
errors: [],
|
|
1374
|
+
warnings: []
|
|
1375
|
+
};
|
|
1376
|
+
try {
|
|
1377
|
+
const backupPath = join(homedir(), ".claude", "backup");
|
|
1378
|
+
if (await pathExists(backupPath)) {
|
|
1379
|
+
const trashResult = await moveToTrash(backupPath);
|
|
1380
|
+
if (!trashResult[0]?.success) {
|
|
1381
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1382
|
+
}
|
|
1383
|
+
result.removed.push("backup/");
|
|
1384
|
+
result.success = true;
|
|
1385
|
+
} else {
|
|
1386
|
+
result.warnings.push(i18n.t("uninstall:backupsNotFound"));
|
|
1387
|
+
result.success = true;
|
|
1388
|
+
}
|
|
1389
|
+
} catch (error) {
|
|
1390
|
+
result.errors.push(`Failed to remove backups: ${error.message}`);
|
|
1391
|
+
}
|
|
1392
|
+
return result;
|
|
1393
|
+
}
|
|
1394
|
+
/**
|
|
1395
|
+
* 11. Remove ZCF preference configuration
|
|
1396
|
+
*/
|
|
1397
|
+
async removeZcfConfig() {
|
|
1398
|
+
const result = {
|
|
1399
|
+
success: false,
|
|
1400
|
+
removed: [],
|
|
1401
|
+
removedConfigs: [],
|
|
1402
|
+
errors: [],
|
|
1403
|
+
warnings: []
|
|
1404
|
+
};
|
|
1405
|
+
try {
|
|
1406
|
+
const zcfConfigPath = ZCF_CONFIG_FILE;
|
|
1407
|
+
const relativeName = zcfConfigPath.replace(homedir(), "~");
|
|
1408
|
+
if (await pathExists(zcfConfigPath)) {
|
|
1409
|
+
const trashResult = await moveToTrash(zcfConfigPath);
|
|
1410
|
+
if (!trashResult[0]?.success) {
|
|
1411
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
1412
|
+
}
|
|
1413
|
+
result.removed.push(relativeName);
|
|
1414
|
+
result.success = true;
|
|
1415
|
+
} else {
|
|
1416
|
+
result.warnings.push(i18n.t("uninstall:zcfConfigNotFound"));
|
|
1417
|
+
result.success = true;
|
|
1418
|
+
}
|
|
1419
|
+
} catch (error) {
|
|
1420
|
+
result.errors.push(`Failed to remove ZCF config: ${error.message}`);
|
|
1421
|
+
}
|
|
1422
|
+
return result;
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Complete uninstall - remove all directories and packages
|
|
1426
|
+
*/
|
|
1427
|
+
async completeUninstall() {
|
|
1428
|
+
const result = {
|
|
1429
|
+
success: true,
|
|
1430
|
+
removed: [],
|
|
1431
|
+
removedConfigs: [],
|
|
1432
|
+
errors: [],
|
|
1433
|
+
warnings: []
|
|
1434
|
+
};
|
|
1435
|
+
try {
|
|
1436
|
+
const directoriesToRemove = [
|
|
1437
|
+
{ path: join(homedir(), ".claude"), name: "~/.claude/" },
|
|
1438
|
+
{ path: join(homedir(), ".claude.json"), name: "~/.claude.json" },
|
|
1439
|
+
{ path: join(homedir(), ".claude-code-router"), name: "~/.claude-code-router/" }
|
|
1440
|
+
];
|
|
1441
|
+
for (const dir of directoriesToRemove) {
|
|
1442
|
+
try {
|
|
1443
|
+
if (await pathExists(dir.path)) {
|
|
1444
|
+
const trashResult = await moveToTrash(dir.path);
|
|
1445
|
+
if (!trashResult[0]?.success) {
|
|
1446
|
+
result.warnings.push(`Failed to move ${dir.name} to trash: ${trashResult[0]?.error || "Unknown error"}`);
|
|
1447
|
+
}
|
|
1448
|
+
result.removed.push(dir.name);
|
|
1449
|
+
}
|
|
1450
|
+
} catch (error) {
|
|
1451
|
+
result.warnings.push(`Failed to remove ${dir.name}: ${error.message}`);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
const packagesToUninstall = [
|
|
1455
|
+
"@musistudio/claude-code-router",
|
|
1456
|
+
"@cometix/ccline",
|
|
1457
|
+
"@anthropic-ai/claude-code"
|
|
1458
|
+
];
|
|
1459
|
+
for (const pkg of packagesToUninstall) {
|
|
1460
|
+
try {
|
|
1461
|
+
await exec$1("npm", ["uninstall", "-g", pkg]);
|
|
1462
|
+
result.removed.push(`${pkg} package`);
|
|
1463
|
+
} catch (error) {
|
|
1464
|
+
if (error.message.includes("not found") || error.message.includes("not installed")) {
|
|
1465
|
+
if (pkg.includes("claude-code-router")) {
|
|
1466
|
+
result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
|
|
1467
|
+
} else if (pkg.includes("ccline")) {
|
|
1468
|
+
result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
|
|
1469
|
+
} else {
|
|
1470
|
+
result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
|
|
1471
|
+
}
|
|
1472
|
+
} else {
|
|
1473
|
+
result.warnings.push(`Failed to uninstall ${pkg}: ${error.message}`);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
} catch (error) {
|
|
1478
|
+
result.errors.push(`Complete uninstall failed: ${error.message}`);
|
|
1479
|
+
result.success = false;
|
|
1480
|
+
}
|
|
1481
|
+
return result;
|
|
1482
|
+
}
|
|
1483
|
+
/**
|
|
1484
|
+
* Custom uninstall with conflict resolution
|
|
1485
|
+
*/
|
|
1486
|
+
async customUninstall(selectedItems) {
|
|
1487
|
+
const resolvedItems = this.resolveConflicts(selectedItems);
|
|
1488
|
+
const results = [];
|
|
1489
|
+
for (const item of resolvedItems) {
|
|
1490
|
+
try {
|
|
1491
|
+
const result = await this.executeUninstallItem(item);
|
|
1492
|
+
results.push(result);
|
|
1493
|
+
} catch (error) {
|
|
1494
|
+
results.push({
|
|
1495
|
+
success: false,
|
|
1496
|
+
removed: [],
|
|
1497
|
+
removedConfigs: [],
|
|
1498
|
+
errors: [`Failed to execute ${item}: ${error.message}`],
|
|
1499
|
+
warnings: []
|
|
1500
|
+
});
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
return results;
|
|
1504
|
+
}
|
|
1505
|
+
/**
|
|
1506
|
+
* Resolve conflicts between uninstall items
|
|
1507
|
+
*/
|
|
1508
|
+
resolveConflicts(items) {
|
|
1509
|
+
const resolved = [...items];
|
|
1510
|
+
for (const [primary, conflicts] of this.conflictResolution) {
|
|
1511
|
+
if (resolved.includes(primary)) {
|
|
1512
|
+
conflicts.forEach((conflict) => {
|
|
1513
|
+
const index = resolved.indexOf(conflict);
|
|
1514
|
+
if (index > -1) {
|
|
1515
|
+
resolved.splice(index, 1);
|
|
1516
|
+
}
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
return resolved;
|
|
1521
|
+
}
|
|
1522
|
+
/**
|
|
1523
|
+
* Execute uninstall for a specific item
|
|
1524
|
+
*/
|
|
1525
|
+
async executeUninstallItem(item) {
|
|
1526
|
+
switch (item) {
|
|
1527
|
+
case "output-styles":
|
|
1528
|
+
return await this.removeOutputStyles();
|
|
1529
|
+
case "commands":
|
|
1530
|
+
return await this.removeCustomCommands();
|
|
1531
|
+
case "agents":
|
|
1532
|
+
return await this.removeCustomAgents();
|
|
1533
|
+
case "claude-md":
|
|
1534
|
+
return await this.removeClaudeMd();
|
|
1535
|
+
case "permissions-envs":
|
|
1536
|
+
return await this.removePermissionsAndEnvs();
|
|
1537
|
+
case "mcps":
|
|
1538
|
+
return await this.removeMcps();
|
|
1539
|
+
case "ccr":
|
|
1540
|
+
return await this.uninstallCcr();
|
|
1541
|
+
case "ccline":
|
|
1542
|
+
return await this.uninstallCcline();
|
|
1543
|
+
case "claude-code":
|
|
1544
|
+
return await this.uninstallClaudeCode();
|
|
1545
|
+
case "backups":
|
|
1546
|
+
return await this.removeBackups();
|
|
1547
|
+
case "zcf-config":
|
|
1548
|
+
return await this.removeZcfConfig();
|
|
1549
|
+
default:
|
|
1550
|
+
return {
|
|
1551
|
+
success: false,
|
|
1552
|
+
removed: [],
|
|
1553
|
+
removedConfigs: [],
|
|
1554
|
+
errors: [`Unknown uninstall item: ${item}`],
|
|
1555
|
+
warnings: []
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
async function uninstall(options = {}) {
|
|
1562
|
+
try {
|
|
1563
|
+
ensureI18nInitialized();
|
|
1564
|
+
const uninstaller = new ZcfUninstaller(options.lang || "en");
|
|
1565
|
+
if (options.mode && options.mode !== "interactive") {
|
|
1566
|
+
if (options.mode === "complete") {
|
|
1567
|
+
await executeCompleteUninstall(uninstaller);
|
|
1568
|
+
return;
|
|
1569
|
+
} else if (options.mode === "custom" && options.items) {
|
|
1570
|
+
let items;
|
|
1571
|
+
if (typeof options.items === "string") {
|
|
1572
|
+
items = options.items.split(",").map((item) => item.trim());
|
|
1573
|
+
} else {
|
|
1574
|
+
items = options.items;
|
|
1575
|
+
}
|
|
1576
|
+
await executeCustomUninstall(uninstaller, items);
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
await showInteractiveUninstall(uninstaller);
|
|
1581
|
+
} catch (error) {
|
|
1582
|
+
if (!handleExitPromptError(error)) {
|
|
1583
|
+
handleGeneralError(error);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
async function showInteractiveUninstall(uninstaller) {
|
|
1588
|
+
console.log(ansis.cyan.bold(i18n.t("uninstall:title")));
|
|
1589
|
+
console.log(ansis.yellow(i18n.t("uninstall:warning")));
|
|
1590
|
+
console.log("");
|
|
1591
|
+
const { mainChoice } = await inquirer.prompt({
|
|
1592
|
+
type: "list",
|
|
1593
|
+
name: "mainChoice",
|
|
1594
|
+
message: i18n.t("uninstall:selectMainOption"),
|
|
1595
|
+
choices: addNumbersToChoices([
|
|
1596
|
+
{
|
|
1597
|
+
name: `${i18n.t("uninstall:completeUninstall")} - ${ansis.gray(i18n.t("uninstall:completeUninstallDesc"))}`,
|
|
1598
|
+
value: "complete",
|
|
1599
|
+
short: i18n.t("uninstall:completeUninstall")
|
|
1600
|
+
},
|
|
1601
|
+
{
|
|
1602
|
+
name: `${i18n.t("uninstall:customUninstall")} - ${ansis.gray(i18n.t("uninstall:customUninstallDesc"))}`,
|
|
1603
|
+
value: "custom",
|
|
1604
|
+
short: i18n.t("uninstall:customUninstall")
|
|
1605
|
+
}
|
|
1606
|
+
])
|
|
1607
|
+
});
|
|
1608
|
+
if (!mainChoice) {
|
|
1609
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
if (mainChoice === "complete") {
|
|
1613
|
+
await executeCompleteUninstall(uninstaller);
|
|
1614
|
+
} else {
|
|
1615
|
+
await showCustomUninstallMenu(uninstaller);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
async function showCustomUninstallMenu(uninstaller) {
|
|
1619
|
+
console.log("");
|
|
1620
|
+
console.log(ansis.cyan(i18n.t("uninstall:selectCustomItems")));
|
|
1621
|
+
const { customItems } = await inquirer.prompt({
|
|
1622
|
+
type: "checkbox",
|
|
1623
|
+
name: "customItems",
|
|
1624
|
+
message: `${i18n.t("uninstall:selectItemsToRemove")} ${i18n.t("common:multiSelectHint")}`,
|
|
1625
|
+
choices: [
|
|
1626
|
+
{
|
|
1627
|
+
name: i18n.t("uninstall:outputStyles"),
|
|
1628
|
+
value: "output-styles"
|
|
1629
|
+
},
|
|
1630
|
+
{
|
|
1631
|
+
name: i18n.t("uninstall:commands"),
|
|
1632
|
+
value: "commands"
|
|
1633
|
+
},
|
|
1634
|
+
{
|
|
1635
|
+
name: i18n.t("uninstall:agents"),
|
|
1636
|
+
value: "agents"
|
|
1637
|
+
},
|
|
1638
|
+
{
|
|
1639
|
+
name: i18n.t("uninstall:claudeMd"),
|
|
1640
|
+
value: "claude-md"
|
|
1641
|
+
},
|
|
1642
|
+
{
|
|
1643
|
+
name: i18n.t("uninstall:permissionsEnvs"),
|
|
1644
|
+
value: "permissions-envs"
|
|
1645
|
+
},
|
|
1646
|
+
{
|
|
1647
|
+
name: i18n.t("uninstall:mcps"),
|
|
1648
|
+
value: "mcps"
|
|
1649
|
+
},
|
|
1650
|
+
{
|
|
1651
|
+
name: i18n.t("uninstall:ccr"),
|
|
1652
|
+
value: "ccr"
|
|
1653
|
+
},
|
|
1654
|
+
{
|
|
1655
|
+
name: i18n.t("uninstall:ccline"),
|
|
1656
|
+
value: "ccline"
|
|
1657
|
+
},
|
|
1658
|
+
{
|
|
1659
|
+
name: i18n.t("uninstall:claudeCode"),
|
|
1660
|
+
value: "claude-code"
|
|
1661
|
+
},
|
|
1662
|
+
{
|
|
1663
|
+
name: i18n.t("uninstall:backups"),
|
|
1664
|
+
value: "backups"
|
|
1665
|
+
},
|
|
1666
|
+
{
|
|
1667
|
+
name: i18n.t("uninstall:zcfConfig"),
|
|
1668
|
+
value: "zcf-config"
|
|
1669
|
+
}
|
|
1670
|
+
],
|
|
1671
|
+
validate: (answers) => {
|
|
1672
|
+
if (answers.length === 0) {
|
|
1673
|
+
return i18n.t("uninstall:selectAtLeastOne");
|
|
1674
|
+
}
|
|
1675
|
+
return true;
|
|
1676
|
+
}
|
|
1677
|
+
});
|
|
1678
|
+
if (!customItems || customItems.length === 0) {
|
|
1679
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
await executeCustomUninstall(uninstaller, customItems);
|
|
1683
|
+
}
|
|
1684
|
+
async function executeCompleteUninstall(uninstaller) {
|
|
1685
|
+
console.log("");
|
|
1686
|
+
console.log(ansis.red.bold(i18n.t("uninstall:executingComplete")));
|
|
1687
|
+
console.log(ansis.yellow(i18n.t("uninstall:completeWarning")));
|
|
1688
|
+
const { confirm } = await inquirer.prompt({
|
|
1689
|
+
type: "confirm",
|
|
1690
|
+
name: "confirm",
|
|
1691
|
+
message: i18n.t("uninstall:confirmComplete"),
|
|
1692
|
+
default: false
|
|
1693
|
+
});
|
|
1694
|
+
if (!confirm) {
|
|
1695
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
console.log("");
|
|
1699
|
+
console.log(ansis.cyan(i18n.t("uninstall:processingComplete")));
|
|
1700
|
+
const result = await uninstaller.completeUninstall();
|
|
1701
|
+
displayUninstallResult("complete", [result]);
|
|
1702
|
+
}
|
|
1703
|
+
async function executeCustomUninstall(uninstaller, items) {
|
|
1704
|
+
console.log("");
|
|
1705
|
+
console.log(ansis.cyan(i18n.t("uninstall:executingCustom")));
|
|
1706
|
+
console.log(ansis.gray(i18n.t("uninstall:selectedItems")));
|
|
1707
|
+
items.forEach((item) => {
|
|
1708
|
+
console.log(` \u2022 ${i18n.t(`uninstall:${item}`)}`);
|
|
1709
|
+
});
|
|
1710
|
+
const { confirm } = await inquirer.prompt({
|
|
1711
|
+
type: "confirm",
|
|
1712
|
+
name: "confirm",
|
|
1713
|
+
message: i18n.t("uninstall:confirmCustom"),
|
|
1714
|
+
default: false
|
|
1715
|
+
});
|
|
1716
|
+
if (!confirm) {
|
|
1717
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1718
|
+
return;
|
|
1719
|
+
}
|
|
1720
|
+
console.log("");
|
|
1721
|
+
console.log(ansis.cyan(i18n.t("uninstall:processingCustom")));
|
|
1722
|
+
const results = await uninstaller.customUninstall(items);
|
|
1723
|
+
displayUninstallResult("custom", results);
|
|
1724
|
+
}
|
|
1725
|
+
function displayUninstallResult(mode, results) {
|
|
1726
|
+
console.log("");
|
|
1727
|
+
console.log(ansis.cyan("\u2500".repeat(50)));
|
|
1728
|
+
let totalSuccess = 0;
|
|
1729
|
+
let totalErrors = 0;
|
|
1730
|
+
let totalWarnings = 0;
|
|
1731
|
+
results.forEach((result) => {
|
|
1732
|
+
if (result.success) {
|
|
1733
|
+
totalSuccess++;
|
|
1734
|
+
}
|
|
1735
|
+
if (result.removed && result.removed.length > 0) {
|
|
1736
|
+
console.log(ansis.green(`\u{1F5D1}\uFE0F ${i18n.t("uninstall:movedToTrash")}:`));
|
|
1737
|
+
result.removed.forEach((item) => {
|
|
1738
|
+
console.log(ansis.gray(` \u2022 ${item}`));
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1741
|
+
if (result.removedConfigs && result.removedConfigs.length > 0) {
|
|
1742
|
+
console.log(ansis.green(`\u2714 ${i18n.t("uninstall:removedConfigs")}:`));
|
|
1743
|
+
result.removedConfigs.forEach((item) => {
|
|
1744
|
+
console.log(ansis.gray(` \u2022 ${item}`));
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
if (result.errors && result.errors.length > 0) {
|
|
1748
|
+
totalErrors += result.errors.length;
|
|
1749
|
+
console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errors")}:`));
|
|
1750
|
+
result.errors.forEach((error) => {
|
|
1751
|
+
console.log(ansis.red(` \u2022 ${error}`));
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1754
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
1755
|
+
totalWarnings += result.warnings.length;
|
|
1756
|
+
console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warnings")}:`));
|
|
1757
|
+
result.warnings.forEach((warning) => {
|
|
1758
|
+
console.log(ansis.yellow(` \u2022 ${warning}`));
|
|
1759
|
+
});
|
|
1760
|
+
}
|
|
1761
|
+
});
|
|
1762
|
+
const totalRemovedFiles = results.reduce((count, result) => count + (result.removed?.length || 0), 0);
|
|
1763
|
+
const totalRemovedConfigs = results.reduce((count, result) => count + (result.removedConfigs?.length || 0), 0);
|
|
1764
|
+
console.log("");
|
|
1765
|
+
console.log(ansis.cyan("\u2500".repeat(50)));
|
|
1766
|
+
if (mode === "complete") {
|
|
1767
|
+
if (totalErrors === 0) {
|
|
1768
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:completeSuccess")}`));
|
|
1769
|
+
} else {
|
|
1770
|
+
console.log(ansis.yellow.bold(`\u26A0 ${i18n.t("uninstall:completePartialSuccess")}`));
|
|
1771
|
+
}
|
|
1772
|
+
} else {
|
|
1773
|
+
if (totalRemovedFiles > 0 && totalRemovedConfigs > 0) {
|
|
1774
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessBoth", {
|
|
1775
|
+
fileCount: totalRemovedFiles,
|
|
1776
|
+
configCount: totalRemovedConfigs
|
|
1777
|
+
})}`));
|
|
1778
|
+
} else if (totalRemovedFiles > 0) {
|
|
1779
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessFiles", {
|
|
1780
|
+
count: totalRemovedFiles
|
|
1781
|
+
})}`));
|
|
1782
|
+
} else if (totalRemovedConfigs > 0) {
|
|
1783
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessConfigs", {
|
|
1784
|
+
count: totalRemovedConfigs
|
|
1785
|
+
})}`));
|
|
1786
|
+
} else {
|
|
1787
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccess", { count: totalSuccess })}`));
|
|
1788
|
+
}
|
|
1789
|
+
if (totalErrors > 0) {
|
|
1790
|
+
console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errorsCount", { count: totalErrors })}`));
|
|
1791
|
+
}
|
|
1792
|
+
if (totalWarnings > 0) {
|
|
1793
|
+
console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warningsCount", { count: totalWarnings })}`));
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
console.log("");
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
function resolveCodeToolType(optionValue, savedValue) {
|
|
1800
|
+
if (isCodeToolType(optionValue)) {
|
|
1801
|
+
return optionValue;
|
|
1802
|
+
}
|
|
1803
|
+
if (savedValue && isCodeToolType(savedValue)) {
|
|
1804
|
+
return savedValue;
|
|
1805
|
+
}
|
|
1806
|
+
return DEFAULT_CODE_TOOL_TYPE;
|
|
1807
|
+
}
|
|
869
1808
|
async function update(options = {}) {
|
|
870
1809
|
try {
|
|
871
1810
|
if (!options.skipBanner) {
|
|
872
1811
|
displayBanner(i18n.t("cli:banner.updateSubtitle"));
|
|
873
1812
|
}
|
|
874
1813
|
const zcfConfig = readZcfConfig();
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
892
|
-
process.exit(0);
|
|
1814
|
+
const codeToolType = resolveCodeToolType(options.codeType, zcfConfig?.codeToolType);
|
|
1815
|
+
options.codeType = codeToolType;
|
|
1816
|
+
if (codeToolType === "codex") {
|
|
1817
|
+
await runCodexUpdate();
|
|
1818
|
+
const newPreferredLang = options.configLang || zcfConfig?.preferredLang;
|
|
1819
|
+
if (newPreferredLang) {
|
|
1820
|
+
updateZcfConfig({
|
|
1821
|
+
version,
|
|
1822
|
+
preferredLang: newPreferredLang,
|
|
1823
|
+
codeToolType
|
|
1824
|
+
});
|
|
1825
|
+
} else {
|
|
1826
|
+
updateZcfConfig({
|
|
1827
|
+
version,
|
|
1828
|
+
codeToolType
|
|
1829
|
+
});
|
|
893
1830
|
}
|
|
894
|
-
|
|
1831
|
+
return;
|
|
895
1832
|
}
|
|
1833
|
+
const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.aM; });
|
|
1834
|
+
const configLang = await resolveTemplateLanguage(
|
|
1835
|
+
options.configLang,
|
|
1836
|
+
// Command line option
|
|
1837
|
+
zcfConfig
|
|
1838
|
+
);
|
|
896
1839
|
const aiOutputLang = await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig);
|
|
897
1840
|
console.log(ansis.cyan(`
|
|
898
1841
|
${i18n.t("configuration:updatingPrompts")}
|
|
@@ -902,7 +1845,10 @@ ${i18n.t("configuration:updatingPrompts")}
|
|
|
902
1845
|
await checkClaudeCodeVersionAndPrompt(false);
|
|
903
1846
|
updateZcfConfig({
|
|
904
1847
|
version,
|
|
905
|
-
|
|
1848
|
+
templateLang: configLang,
|
|
1849
|
+
// 保存模板语言选择
|
|
1850
|
+
aiOutputLang,
|
|
1851
|
+
codeToolType
|
|
906
1852
|
});
|
|
907
1853
|
} catch (error) {
|
|
908
1854
|
if (!handleExitPromptError(error)) {
|
|
@@ -911,156 +1857,321 @@ ${i18n.t("configuration:updatingPrompts")}
|
|
|
911
1857
|
}
|
|
912
1858
|
}
|
|
913
1859
|
|
|
1860
|
+
const CODE_TOOL_LABELS = {
|
|
1861
|
+
"claude-code": "Claude Code",
|
|
1862
|
+
"codex": "Codex"
|
|
1863
|
+
};
|
|
1864
|
+
const CODE_TOOL_BANNERS = {
|
|
1865
|
+
"claude-code": "for Claude Code",
|
|
1866
|
+
"codex": "for Codex"
|
|
1867
|
+
};
|
|
1868
|
+
function getCurrentCodeTool() {
|
|
1869
|
+
const config = readZcfConfig();
|
|
1870
|
+
if (config?.codeToolType && isCodeToolType(config.codeToolType)) {
|
|
1871
|
+
return config.codeToolType;
|
|
1872
|
+
}
|
|
1873
|
+
return DEFAULT_CODE_TOOL_TYPE;
|
|
1874
|
+
}
|
|
1875
|
+
function printSeparator() {
|
|
1876
|
+
console.log(`
|
|
1877
|
+
${ansis.dim("\u2500".repeat(50))}
|
|
1878
|
+
`);
|
|
1879
|
+
}
|
|
1880
|
+
function getCodeToolLabel(codeTool) {
|
|
1881
|
+
return CODE_TOOL_LABELS[codeTool] || codeTool;
|
|
1882
|
+
}
|
|
1883
|
+
async function promptCodeToolSelection(current) {
|
|
1884
|
+
const choices = addNumbersToChoices(Object.entries(CODE_TOOL_LABELS).map(([value, label]) => ({
|
|
1885
|
+
name: label,
|
|
1886
|
+
value,
|
|
1887
|
+
short: label
|
|
1888
|
+
})));
|
|
1889
|
+
const { tool } = await inquirer.prompt({
|
|
1890
|
+
type: "list",
|
|
1891
|
+
name: "tool",
|
|
1892
|
+
message: i18n.t("menu:switchCodeToolPrompt"),
|
|
1893
|
+
default: current,
|
|
1894
|
+
choices
|
|
1895
|
+
});
|
|
1896
|
+
if (!tool) {
|
|
1897
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1898
|
+
return null;
|
|
1899
|
+
}
|
|
1900
|
+
return tool;
|
|
1901
|
+
}
|
|
1902
|
+
async function handleCodeToolSwitch(current) {
|
|
1903
|
+
const newTool = await promptCodeToolSelection(current);
|
|
1904
|
+
if (!newTool || newTool === current) {
|
|
1905
|
+
return false;
|
|
1906
|
+
}
|
|
1907
|
+
updateZcfConfig({ codeToolType: newTool });
|
|
1908
|
+
console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(newTool) })}`));
|
|
1909
|
+
return true;
|
|
1910
|
+
}
|
|
1911
|
+
function printOtherToolsSection() {
|
|
1912
|
+
console.log(` --------- ${i18n.t("menu:menuSections.otherTools")} ----------`);
|
|
1913
|
+
console.log(
|
|
1914
|
+
` ${ansis.cyan("R.")} ${i18n.t("menu:menuOptions.ccrManagement")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccrManagement")}`)}`
|
|
1915
|
+
);
|
|
1916
|
+
console.log(
|
|
1917
|
+
` ${ansis.cyan("U.")} ${i18n.t("menu:menuOptions.ccusage")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccusage")}`)}`
|
|
1918
|
+
);
|
|
1919
|
+
console.log(
|
|
1920
|
+
` ${ansis.cyan("L.")} ${i18n.t("menu:menuOptions.cometixLine")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.cometixLine")}`)}`
|
|
1921
|
+
);
|
|
1922
|
+
console.log("");
|
|
1923
|
+
}
|
|
1924
|
+
function printZcfSection(options) {
|
|
1925
|
+
console.log(" ------------ ZCF ------------");
|
|
1926
|
+
console.log(
|
|
1927
|
+
` ${ansis.cyan("0.")} ${i18n.t("menu:menuOptions.changeLanguage")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.changeLanguage")}`)}`
|
|
1928
|
+
);
|
|
1929
|
+
console.log(
|
|
1930
|
+
` ${ansis.cyan("S.")} ${i18n.t("menu:menuOptions.switchCodeTool")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.switchCodeTool")}`)}`
|
|
1931
|
+
);
|
|
1932
|
+
console.log(
|
|
1933
|
+
` ${ansis.cyan("-.")} ${options.uninstallOption} ${ansis.gray(`- ${options.uninstallDescription}`)}`
|
|
1934
|
+
);
|
|
1935
|
+
console.log(
|
|
1936
|
+
` ${ansis.cyan("+.")} ${options.updateOption} ${ansis.gray(`- ${options.updateDescription}`)}`
|
|
1937
|
+
);
|
|
1938
|
+
console.log(` ${ansis.red("Q.")} ${ansis.red(i18n.t("menu:menuOptions.exit"))}`);
|
|
1939
|
+
console.log("");
|
|
1940
|
+
}
|
|
1941
|
+
async function showClaudeCodeMenu() {
|
|
1942
|
+
console.log(ansis.cyan(i18n.t("menu:selectFunction")));
|
|
1943
|
+
console.log(" -------- Claude Code --------");
|
|
1944
|
+
console.log(
|
|
1945
|
+
` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.fullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.fullInit")}`)}`
|
|
1946
|
+
);
|
|
1947
|
+
console.log(
|
|
1948
|
+
` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.importWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.importWorkflow")}`)}`
|
|
1949
|
+
);
|
|
1950
|
+
console.log(
|
|
1951
|
+
` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.configureApiOrCcr")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureApiOrCcr")}`)}`
|
|
1952
|
+
);
|
|
1953
|
+
console.log(
|
|
1954
|
+
` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.configureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureMcp")}`)}`
|
|
1955
|
+
);
|
|
1956
|
+
console.log(
|
|
1957
|
+
` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.configureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureModel")}`)}`
|
|
1958
|
+
);
|
|
1959
|
+
console.log(
|
|
1960
|
+
` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.configureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureAiMemory")}`)}`
|
|
1961
|
+
);
|
|
1962
|
+
console.log(
|
|
1963
|
+
` ${ansis.cyan("7.")} ${i18n.t("menu:menuOptions.configureEnvPermission")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureEnvPermission")}`)}`
|
|
1964
|
+
);
|
|
1965
|
+
console.log("");
|
|
1966
|
+
printOtherToolsSection();
|
|
1967
|
+
printZcfSection({
|
|
1968
|
+
uninstallOption: i18n.t("menu:menuOptions.uninstall"),
|
|
1969
|
+
uninstallDescription: i18n.t("menu:menuDescriptions.uninstall"),
|
|
1970
|
+
updateOption: i18n.t("menu:menuOptions.checkUpdates"),
|
|
1971
|
+
updateDescription: i18n.t("menu:menuDescriptions.checkUpdates")
|
|
1972
|
+
});
|
|
1973
|
+
const { choice } = await inquirer.prompt({
|
|
1974
|
+
type: "input",
|
|
1975
|
+
name: "choice",
|
|
1976
|
+
message: i18n.t("common:enterChoice"),
|
|
1977
|
+
validate: (value) => {
|
|
1978
|
+
const valid = ["1", "2", "3", "4", "5", "6", "7", "r", "R", "u", "U", "l", "L", "0", "-", "+", "s", "S", "q", "Q"];
|
|
1979
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
1980
|
+
}
|
|
1981
|
+
});
|
|
1982
|
+
if (!choice) {
|
|
1983
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1984
|
+
return "exit";
|
|
1985
|
+
}
|
|
1986
|
+
const normalized = choice.toLowerCase();
|
|
1987
|
+
switch (normalized) {
|
|
1988
|
+
case "1":
|
|
1989
|
+
await init({ skipBanner: true });
|
|
1990
|
+
break;
|
|
1991
|
+
case "2":
|
|
1992
|
+
await update({ skipBanner: true });
|
|
1993
|
+
break;
|
|
1994
|
+
case "3":
|
|
1995
|
+
await configureApiFeature();
|
|
1996
|
+
break;
|
|
1997
|
+
case "4":
|
|
1998
|
+
await configureMcpFeature();
|
|
1999
|
+
break;
|
|
2000
|
+
case "5":
|
|
2001
|
+
await configureDefaultModelFeature();
|
|
2002
|
+
break;
|
|
2003
|
+
case "6":
|
|
2004
|
+
await configureAiMemoryFeature();
|
|
2005
|
+
break;
|
|
2006
|
+
case "7":
|
|
2007
|
+
await configureEnvPermissionFeature();
|
|
2008
|
+
break;
|
|
2009
|
+
case "r":
|
|
2010
|
+
await runCcrMenuFeature();
|
|
2011
|
+
printSeparator();
|
|
2012
|
+
return void 0;
|
|
2013
|
+
case "u":
|
|
2014
|
+
await runCcusageFeature();
|
|
2015
|
+
printSeparator();
|
|
2016
|
+
return void 0;
|
|
2017
|
+
case "l":
|
|
2018
|
+
await runCometixMenuFeature();
|
|
2019
|
+
printSeparator();
|
|
2020
|
+
return void 0;
|
|
2021
|
+
case "0": {
|
|
2022
|
+
const currentLang = i18n.language;
|
|
2023
|
+
await changeScriptLanguageFeature(currentLang);
|
|
2024
|
+
printSeparator();
|
|
2025
|
+
return void 0;
|
|
2026
|
+
}
|
|
2027
|
+
case "-":
|
|
2028
|
+
await uninstall();
|
|
2029
|
+
printSeparator();
|
|
2030
|
+
return void 0;
|
|
2031
|
+
case "+":
|
|
2032
|
+
await checkUpdates();
|
|
2033
|
+
printSeparator();
|
|
2034
|
+
return void 0;
|
|
2035
|
+
case "s": {
|
|
2036
|
+
const switched = await handleCodeToolSwitch("claude-code");
|
|
2037
|
+
if (switched) {
|
|
2038
|
+
return "switch";
|
|
2039
|
+
}
|
|
2040
|
+
printSeparator();
|
|
2041
|
+
return void 0;
|
|
2042
|
+
}
|
|
2043
|
+
case "q":
|
|
2044
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
2045
|
+
return "exit";
|
|
2046
|
+
default:
|
|
2047
|
+
return void 0;
|
|
2048
|
+
}
|
|
2049
|
+
printSeparator();
|
|
2050
|
+
const { continue: shouldContinue } = await inquirer.prompt({
|
|
2051
|
+
type: "confirm",
|
|
2052
|
+
name: "continue",
|
|
2053
|
+
message: i18n.t("common:returnToMenu"),
|
|
2054
|
+
default: true
|
|
2055
|
+
});
|
|
2056
|
+
if (!shouldContinue) {
|
|
2057
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
2058
|
+
return "exit";
|
|
2059
|
+
}
|
|
2060
|
+
return void 0;
|
|
2061
|
+
}
|
|
2062
|
+
async function showCodexMenu() {
|
|
2063
|
+
console.log(ansis.cyan(i18n.t("menu:selectFunction")));
|
|
2064
|
+
console.log(" -------- Codex --------");
|
|
2065
|
+
console.log(
|
|
2066
|
+
` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.codexFullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexFullInit")}`)}`
|
|
2067
|
+
);
|
|
2068
|
+
console.log(
|
|
2069
|
+
` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.codexImportWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexImportWorkflow")}`)}`
|
|
2070
|
+
);
|
|
2071
|
+
console.log(
|
|
2072
|
+
` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.codexConfigureApi")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureApi")}`)}`
|
|
2073
|
+
);
|
|
2074
|
+
console.log(
|
|
2075
|
+
` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.codexConfigureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureMcp")}`)}`
|
|
2076
|
+
);
|
|
2077
|
+
console.log(
|
|
2078
|
+
` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.codexConfigureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureModel")}`)}`
|
|
2079
|
+
);
|
|
2080
|
+
console.log(
|
|
2081
|
+
` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.codexConfigureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureAiMemory")}`)}`
|
|
2082
|
+
);
|
|
2083
|
+
console.log("");
|
|
2084
|
+
printZcfSection({
|
|
2085
|
+
uninstallOption: i18n.t("menu:menuOptions.codexUninstall"),
|
|
2086
|
+
uninstallDescription: i18n.t("menu:menuDescriptions.codexUninstall"),
|
|
2087
|
+
updateOption: i18n.t("menu:menuOptions.codexCheckUpdates"),
|
|
2088
|
+
updateDescription: i18n.t("menu:menuDescriptions.codexCheckUpdates")
|
|
2089
|
+
});
|
|
2090
|
+
const { choice } = await inquirer.prompt({
|
|
2091
|
+
type: "input",
|
|
2092
|
+
name: "choice",
|
|
2093
|
+
message: i18n.t("common:enterChoice"),
|
|
2094
|
+
validate: (value) => {
|
|
2095
|
+
const valid = ["1", "2", "3", "4", "5", "6", "0", "-", "+", "s", "S", "q", "Q"];
|
|
2096
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
2097
|
+
}
|
|
2098
|
+
});
|
|
2099
|
+
if (!choice) {
|
|
2100
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2101
|
+
return "exit";
|
|
2102
|
+
}
|
|
2103
|
+
const normalized = choice.toLowerCase();
|
|
2104
|
+
switch (normalized) {
|
|
2105
|
+
case "1":
|
|
2106
|
+
await runCodexFullInit();
|
|
2107
|
+
break;
|
|
2108
|
+
case "2":
|
|
2109
|
+
await runCodexWorkflowImport();
|
|
2110
|
+
break;
|
|
2111
|
+
case "3":
|
|
2112
|
+
await configureCodexApi();
|
|
2113
|
+
break;
|
|
2114
|
+
case "4":
|
|
2115
|
+
await configureCodexMcp();
|
|
2116
|
+
break;
|
|
2117
|
+
case "5":
|
|
2118
|
+
await configureCodexDefaultModelFeature();
|
|
2119
|
+
break;
|
|
2120
|
+
case "6":
|
|
2121
|
+
await configureCodexAiMemoryFeature();
|
|
2122
|
+
break;
|
|
2123
|
+
case "0": {
|
|
2124
|
+
const currentLang = i18n.language;
|
|
2125
|
+
await changeScriptLanguageFeature(currentLang);
|
|
2126
|
+
printSeparator();
|
|
2127
|
+
return void 0;
|
|
2128
|
+
}
|
|
2129
|
+
case "-":
|
|
2130
|
+
await runCodexUninstall();
|
|
2131
|
+
printSeparator();
|
|
2132
|
+
return void 0;
|
|
2133
|
+
case "+":
|
|
2134
|
+
await runCodexUpdate();
|
|
2135
|
+
printSeparator();
|
|
2136
|
+
return void 0;
|
|
2137
|
+
case "s": {
|
|
2138
|
+
const switched = await handleCodeToolSwitch("codex");
|
|
2139
|
+
if (switched) {
|
|
2140
|
+
return "switch";
|
|
2141
|
+
}
|
|
2142
|
+
printSeparator();
|
|
2143
|
+
return void 0;
|
|
2144
|
+
}
|
|
2145
|
+
case "q":
|
|
2146
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
2147
|
+
return "exit";
|
|
2148
|
+
default:
|
|
2149
|
+
return void 0;
|
|
2150
|
+
}
|
|
2151
|
+
printSeparator();
|
|
2152
|
+
const { continue: shouldContinue } = await inquirer.prompt({
|
|
2153
|
+
type: "confirm",
|
|
2154
|
+
name: "continue",
|
|
2155
|
+
message: i18n.t("common:returnToMenu"),
|
|
2156
|
+
default: true
|
|
2157
|
+
});
|
|
2158
|
+
if (!shouldContinue) {
|
|
2159
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
2160
|
+
return "exit";
|
|
2161
|
+
}
|
|
2162
|
+
return void 0;
|
|
2163
|
+
}
|
|
914
2164
|
async function showMainMenu() {
|
|
915
2165
|
try {
|
|
916
|
-
displayBannerWithInfo();
|
|
917
2166
|
let exitMenu = false;
|
|
918
2167
|
while (!exitMenu) {
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
);
|
|
924
|
-
console.log(
|
|
925
|
-
` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.importWorkflow")} ${ansis.gray(
|
|
926
|
-
`- ${i18n.t("menu:menuDescriptions.importWorkflow")}`
|
|
927
|
-
)}`
|
|
928
|
-
);
|
|
929
|
-
console.log(
|
|
930
|
-
` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.configureApiOrCcr")} ${ansis.gray(
|
|
931
|
-
`- ${i18n.t("menu:menuDescriptions.configureApiOrCcr")}`
|
|
932
|
-
)}`
|
|
933
|
-
);
|
|
934
|
-
console.log(
|
|
935
|
-
` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.configureMcp")} ${ansis.gray(
|
|
936
|
-
`- ${i18n.t("menu:menuDescriptions.configureMcp")}`
|
|
937
|
-
)}`
|
|
938
|
-
);
|
|
939
|
-
console.log(
|
|
940
|
-
` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.configureModel")} ${ansis.gray(
|
|
941
|
-
`- ${i18n.t("menu:menuDescriptions.configureModel")}`
|
|
942
|
-
)}`
|
|
943
|
-
);
|
|
944
|
-
console.log(
|
|
945
|
-
` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.configureAiMemory")} ${ansis.gray(
|
|
946
|
-
`- ${i18n.t("menu:menuDescriptions.configureAiMemory")}`
|
|
947
|
-
)}`
|
|
948
|
-
);
|
|
949
|
-
console.log(
|
|
950
|
-
` ${ansis.cyan("7.")} ${i18n.t("menu:menuOptions.configureEnvPermission")} ${ansis.gray(
|
|
951
|
-
`- ${i18n.t("menu:menuDescriptions.configureEnvPermission")}`
|
|
952
|
-
)}`
|
|
953
|
-
);
|
|
954
|
-
console.log("");
|
|
955
|
-
console.log(` --------- ${i18n.t("menu:menuSections.otherTools")} ----------`);
|
|
956
|
-
console.log(
|
|
957
|
-
` ${ansis.cyan("R.")} ${i18n.t("menu:menuOptions.ccrManagement")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccrManagement")}`)}`
|
|
958
|
-
);
|
|
959
|
-
console.log(
|
|
960
|
-
` ${ansis.cyan("U.")} ${i18n.t("menu:menuOptions.ccusage")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccusage")}`)}`
|
|
961
|
-
);
|
|
962
|
-
console.log(
|
|
963
|
-
` ${ansis.cyan("L.")} ${i18n.t("menu:menuOptions.cometixLine")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.cometixLine")}`)}`
|
|
964
|
-
);
|
|
965
|
-
console.log("");
|
|
966
|
-
console.log(" ------------ ZCF ------------");
|
|
967
|
-
console.log(
|
|
968
|
-
` ${ansis.cyan("0.")} ${i18n.t("menu:menuOptions.changeLanguage")} ${ansis.gray(
|
|
969
|
-
`- ${i18n.t("menu:menuDescriptions.changeLanguage")}`
|
|
970
|
-
)}`
|
|
971
|
-
);
|
|
972
|
-
console.log(
|
|
973
|
-
` ${ansis.cyan("-.")} ${i18n.t("menu:menuOptions.clearCache")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.clearCache")}`)}`
|
|
974
|
-
);
|
|
975
|
-
console.log(
|
|
976
|
-
` ${ansis.cyan("+.")} ${i18n.t("menu:menuOptions.checkUpdates")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.checkUpdates")}`)}`
|
|
977
|
-
);
|
|
978
|
-
console.log(` ${ansis.red("Q.")} ${ansis.red(i18n.t("menu:menuOptions.exit"))}`);
|
|
979
|
-
console.log("");
|
|
980
|
-
const { choice } = await inquirer.prompt({
|
|
981
|
-
type: "input",
|
|
982
|
-
name: "choice",
|
|
983
|
-
message: i18n.t("common:enterChoice"),
|
|
984
|
-
validate: (value) => {
|
|
985
|
-
const valid = ["1", "2", "3", "4", "5", "6", "7", "r", "R", "u", "U", "l", "L", "0", "-", "+", "q", "Q"];
|
|
986
|
-
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
987
|
-
}
|
|
988
|
-
});
|
|
989
|
-
if (!choice) {
|
|
990
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2168
|
+
const codeTool = getCurrentCodeTool();
|
|
2169
|
+
displayBannerWithInfo(CODE_TOOL_BANNERS[codeTool] || "ZCF");
|
|
2170
|
+
const result = codeTool === "codex" ? await showCodexMenu() : await showClaudeCodeMenu();
|
|
2171
|
+
if (result === "exit") {
|
|
991
2172
|
exitMenu = true;
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
switch (choice.toLowerCase()) {
|
|
995
|
-
case "1":
|
|
996
|
-
await init({ skipBanner: true });
|
|
997
|
-
break;
|
|
998
|
-
case "2":
|
|
999
|
-
await update({ skipBanner: true });
|
|
1000
|
-
break;
|
|
1001
|
-
case "3":
|
|
1002
|
-
await configureApiFeature();
|
|
1003
|
-
break;
|
|
1004
|
-
case "4":
|
|
1005
|
-
await configureMcpFeature();
|
|
1006
|
-
break;
|
|
1007
|
-
case "5":
|
|
1008
|
-
await configureDefaultModelFeature();
|
|
1009
|
-
break;
|
|
1010
|
-
case "6":
|
|
1011
|
-
await configureAiMemoryFeature();
|
|
1012
|
-
break;
|
|
1013
|
-
case "7":
|
|
1014
|
-
await configureEnvPermissionFeature();
|
|
1015
|
-
break;
|
|
1016
|
-
case "r":
|
|
1017
|
-
case "R":
|
|
1018
|
-
await runCcrMenuFeature();
|
|
1019
|
-
break;
|
|
1020
|
-
case "u":
|
|
1021
|
-
case "U":
|
|
1022
|
-
await runCcusageFeature();
|
|
1023
|
-
break;
|
|
1024
|
-
case "l":
|
|
1025
|
-
case "L":
|
|
1026
|
-
await runCometixMenuFeature();
|
|
1027
|
-
break;
|
|
1028
|
-
case "0": {
|
|
1029
|
-
const currentLang = i18n.language;
|
|
1030
|
-
await changeScriptLanguageFeature(currentLang);
|
|
1031
|
-
break;
|
|
1032
|
-
}
|
|
1033
|
-
case "-":
|
|
1034
|
-
await clearZcfCacheFeature();
|
|
1035
|
-
break;
|
|
1036
|
-
case "+":
|
|
1037
|
-
await checkUpdates();
|
|
1038
|
-
break;
|
|
1039
|
-
case "q":
|
|
1040
|
-
exitMenu = true;
|
|
1041
|
-
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
1042
|
-
break;
|
|
1043
|
-
}
|
|
1044
|
-
if (!exitMenu && choice.toLowerCase() !== "q") {
|
|
1045
|
-
if (choice === "0" || choice === "-" || choice === "+" || choice.toLowerCase() === "u" || choice.toLowerCase() === "r" || choice.toLowerCase() === "l") {
|
|
1046
|
-
console.log(`
|
|
1047
|
-
${ansis.dim("\u2500".repeat(50))}
|
|
1048
|
-
`);
|
|
1049
|
-
continue;
|
|
1050
|
-
}
|
|
1051
|
-
console.log(`
|
|
1052
|
-
${ansis.dim("\u2500".repeat(50))}
|
|
1053
|
-
`);
|
|
1054
|
-
const { continue: shouldContinue } = await inquirer.prompt({
|
|
1055
|
-
type: "confirm",
|
|
1056
|
-
name: "continue",
|
|
1057
|
-
message: i18n.t("common:returnToMenu"),
|
|
1058
|
-
default: true
|
|
1059
|
-
});
|
|
1060
|
-
if (!shouldContinue) {
|
|
1061
|
-
exitMenu = true;
|
|
1062
|
-
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
1063
|
-
}
|
|
2173
|
+
} else if (result === "switch") {
|
|
2174
|
+
continue;
|
|
1064
2175
|
}
|
|
1065
2176
|
}
|
|
1066
2177
|
} catch (error) {
|
|
@@ -1086,6 +2197,103 @@ async function ccr(options = {}) {
|
|
|
1086
2197
|
}
|
|
1087
2198
|
}
|
|
1088
2199
|
|
|
2200
|
+
async function configSwitchCommand(options) {
|
|
2201
|
+
try {
|
|
2202
|
+
ensureI18nInitialized();
|
|
2203
|
+
if (options.list) {
|
|
2204
|
+
await handleListProviders();
|
|
2205
|
+
return;
|
|
2206
|
+
}
|
|
2207
|
+
if (options.provider) {
|
|
2208
|
+
await handleDirectSwitch(options.provider);
|
|
2209
|
+
return;
|
|
2210
|
+
}
|
|
2211
|
+
await handleInteractiveSwitch();
|
|
2212
|
+
} catch (error) {
|
|
2213
|
+
if (process.env.NODE_ENV === "test" || process.env.VITEST) {
|
|
2214
|
+
throw error;
|
|
2215
|
+
}
|
|
2216
|
+
handleGeneralError(error);
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
async function handleListProviders() {
|
|
2220
|
+
const providers = await listCodexProviders();
|
|
2221
|
+
const currentProvider = await getCurrentCodexProvider();
|
|
2222
|
+
console.log(ansis.cyan(i18n.t("codex:listProvidersTitle")));
|
|
2223
|
+
console.log("");
|
|
2224
|
+
if (providers.length === 0) {
|
|
2225
|
+
console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2228
|
+
if (currentProvider) {
|
|
2229
|
+
console.log(ansis.green(`${i18n.t("codex:currentProvider", { provider: currentProvider })}`));
|
|
2230
|
+
console.log("");
|
|
2231
|
+
}
|
|
2232
|
+
for (const provider of providers) {
|
|
2233
|
+
const marker = currentProvider === provider.id ? ansis.green("\u25CF ") : " ";
|
|
2234
|
+
console.log(`${marker}${ansis.cyan(provider.id)} - ${provider.name}`);
|
|
2235
|
+
console.log(` ${ansis.gray(provider.baseUrl)}`);
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
async function handleDirectSwitch(providerId) {
|
|
2239
|
+
await switchCodexProvider(providerId);
|
|
2240
|
+
}
|
|
2241
|
+
async function handleInteractiveSwitch() {
|
|
2242
|
+
const providers = await listCodexProviders();
|
|
2243
|
+
if (!providers || providers.length === 0) {
|
|
2244
|
+
console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
|
|
2245
|
+
return;
|
|
2246
|
+
}
|
|
2247
|
+
const existingConfig = readCodexConfig();
|
|
2248
|
+
const currentProvider = existingConfig?.modelProvider;
|
|
2249
|
+
const isCommented = existingConfig?.modelProviderCommented;
|
|
2250
|
+
const createApiConfigChoices = (providers2, currentProvider2, isCommented2) => {
|
|
2251
|
+
const choices2 = [];
|
|
2252
|
+
const isOfficialMode = !currentProvider2 || isCommented2;
|
|
2253
|
+
choices2.push({
|
|
2254
|
+
name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${i18n.t("codex:useOfficialLogin")}`,
|
|
2255
|
+
value: "official"
|
|
2256
|
+
});
|
|
2257
|
+
providers2.forEach((provider) => {
|
|
2258
|
+
const isCurrent = currentProvider2 === provider.id && !isCommented2;
|
|
2259
|
+
choices2.push({
|
|
2260
|
+
name: isCurrent ? `${ansis.green("\u25CF ")}${provider.name} - ${ansis.gray(provider.id)} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${provider.name} - ${ansis.gray(provider.id)}`,
|
|
2261
|
+
value: provider.id
|
|
2262
|
+
});
|
|
2263
|
+
});
|
|
2264
|
+
return choices2;
|
|
2265
|
+
};
|
|
2266
|
+
const choices = createApiConfigChoices(providers, currentProvider, isCommented);
|
|
2267
|
+
try {
|
|
2268
|
+
const { selectedConfig } = await inquirer.prompt([{
|
|
2269
|
+
type: "list",
|
|
2270
|
+
name: "selectedConfig",
|
|
2271
|
+
message: i18n.t("codex:apiConfigSwitchPrompt"),
|
|
2272
|
+
choices: addNumbersToChoices(choices)
|
|
2273
|
+
}]);
|
|
2274
|
+
if (!selectedConfig) {
|
|
2275
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2276
|
+
return;
|
|
2277
|
+
}
|
|
2278
|
+
let success = false;
|
|
2279
|
+
if (selectedConfig === "official") {
|
|
2280
|
+
success = await switchToOfficialLogin();
|
|
2281
|
+
} else {
|
|
2282
|
+
success = await switchToProvider(selectedConfig);
|
|
2283
|
+
}
|
|
2284
|
+
if (!success) {
|
|
2285
|
+
console.log(ansis.red(i18n.t("common:operationFailed")));
|
|
2286
|
+
}
|
|
2287
|
+
} catch (error) {
|
|
2288
|
+
if (error.name === "ExitPromptError") {
|
|
2289
|
+
console.log(ansis.cyan(`
|
|
2290
|
+
${i18n.t("common:goodbye")}`));
|
|
2291
|
+
return;
|
|
2292
|
+
}
|
|
2293
|
+
throw error;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
|
|
1089
2297
|
async function resolveAndSwitchLanguage(lang, options, skipPrompt = false) {
|
|
1090
2298
|
const zcfConfig = await readZcfConfigAsync();
|
|
1091
2299
|
const targetLang = options?.allLang || lang || options?.lang || zcfConfig?.preferredLang || (skipPrompt ? "en" : await selectScriptLanguage());
|
|
@@ -1116,7 +2324,7 @@ function extractLanguageOptions(options) {
|
|
|
1116
2324
|
function customizeHelp(sections) {
|
|
1117
2325
|
sections.unshift({
|
|
1118
2326
|
title: "",
|
|
1119
|
-
body: ansis.cyan.bold(`ZCF - Zero-Config
|
|
2327
|
+
body: ansis.cyan.bold(`ZCF - Zero-Config Code Flow v${version}`)
|
|
1120
2328
|
});
|
|
1121
2329
|
sections.push({
|
|
1122
2330
|
title: ansis.yellow(i18n.t("cli:help.commands")),
|
|
@@ -1128,6 +2336,7 @@ function customizeHelp(sections) {
|
|
|
1128
2336
|
` ${ansis.cyan("zcf update")} | ${ansis.cyan("u")} ${i18n.t("cli:help.commandDescriptions.updateWorkflowFiles")}`,
|
|
1129
2337
|
` ${ansis.cyan("zcf ccr")} ${i18n.t("cli:help.commandDescriptions.configureCcrProxy")}`,
|
|
1130
2338
|
` ${ansis.cyan("zcf ccu")} [args] ${i18n.t("cli:help.commandDescriptions.claudeCodeUsageAnalysis")}`,
|
|
2339
|
+
` ${ansis.cyan("zcf uninstall")} ${i18n.t("cli:help.commandDescriptions.uninstallConfigurations")}`,
|
|
1131
2340
|
` ${ansis.cyan("zcf check-updates")} ${i18n.t("cli:help.commandDescriptions.checkUpdateVersions")}`,
|
|
1132
2341
|
"",
|
|
1133
2342
|
ansis.gray(` ${i18n.t("cli:help.shortcuts")}`),
|
|
@@ -1157,6 +2366,7 @@ function customizeHelp(sections) {
|
|
|
1157
2366
|
` ${ansis.green("--workflows, -w")} <list> ${i18n.t("cli:help.optionDescriptions.workflows")} (${i18n.t("cli:help.defaults.prefix")} all workflows)`,
|
|
1158
2367
|
` ${ansis.green("--output-styles, -o")} <styles> ${i18n.t("cli:help.optionDescriptions.outputStyles")} (${i18n.t("cli:help.defaults.prefix")} all custom styles)`,
|
|
1159
2368
|
` ${ansis.green("--default-output-style, -d")} <style> ${i18n.t("cli:help.optionDescriptions.defaultOutputStyle")} (${i18n.t("cli:help.defaults.prefix")} engineer-professional)`,
|
|
2369
|
+
` ${ansis.green("--code-type, -T")} <type> ${i18n.t("cli:help.optionDescriptions.codeToolType")} (claude-code, codex)`,
|
|
1160
2370
|
` ${ansis.green("--install-cometix-line, -x")} <value> ${i18n.t("cli:help.optionDescriptions.installStatuslineTool")} (${i18n.t("cli:help.defaults.prefix")} true)`
|
|
1161
2371
|
].join("\n")
|
|
1162
2372
|
});
|
|
@@ -1180,6 +2390,9 @@ function customizeHelp(sections) {
|
|
|
1180
2390
|
` ${ansis.cyan("npx zcf ccu")} ${ansis.gray(`# ${i18n.t("cli:help.defaults.dailyUsage")}`)}`,
|
|
1181
2391
|
` ${ansis.cyan("npx zcf ccu monthly --json")}`,
|
|
1182
2392
|
"",
|
|
2393
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.uninstallConfigurations")}`),
|
|
2394
|
+
` ${ansis.cyan("npx zcf uninstall")} ${ansis.gray(`# ${i18n.t("cli:help.defaults.interactiveUninstall")}`)}`,
|
|
2395
|
+
"",
|
|
1183
2396
|
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.checkAndUpdateTools")}`),
|
|
1184
2397
|
` ${ansis.cyan("npx zcf check-updates")} ${ansis.gray(`# ${i18n.t("cli:help.defaults.updateTools")}`)}`,
|
|
1185
2398
|
` ${ansis.cyan("npx zcf check")}`,
|
|
@@ -1200,10 +2413,10 @@ async function setupCommands(cli) {
|
|
|
1200
2413
|
await initI18n(defaultLang);
|
|
1201
2414
|
} catch {
|
|
1202
2415
|
}
|
|
1203
|
-
cli.command("", "Show interactive menu (default)").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--force, -f", "Force overwrite existing configuration").action(await withLanguageResolution(async () => {
|
|
2416
|
+
cli.command("", "Show interactive menu (default)").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--force, -f", "Force overwrite existing configuration").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex)", { default: DEFAULT_CODE_TOOL_TYPE }).action(await withLanguageResolution(async () => {
|
|
1204
2417
|
await showMainMenu();
|
|
1205
2418
|
}));
|
|
1206
|
-
cli.command("init", "Initialize Claude Code configuration").alias("i").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--ai-output-lang, -a <lang>", "AI output language").option("--force, -f", "Force overwrite existing configuration").option("--skip-prompt, -s", "Skip all interactive prompts (non-interactive mode)").option("--config-action, -r <action>", `Config handling (new/backup/merge/docs-only/skip), ${i18n.t("cli:help.defaults.prefix")} backup`).option("--api-type, -t <type>", "API type (auth_token/api_key/ccr_proxy/skip)").option("--api-key, -k <key>", "API key (used for both API key and auth token types)").option("--api-url, -u <url>", "Custom API URL").option("--mcp-services, -m <services>", `Comma-separated MCP services to install (context7,mcp-deepwiki,Playwright,exa), "skip" to skip all, "all" for all non-key services, ${i18n.t("cli:help.defaults.prefix")} all`).option("--workflows, -w <workflows>", `Comma-separated workflows to install (sixStepsWorkflow,featPlanUx,gitWorkflow,bmadWorkflow), "skip" to skip all, "all" for all workflows, ${i18n.t("cli:help.defaults.prefix")} all`).option("--output-styles, -o <styles>", `Comma-separated output styles (engineer-professional,nekomata-engineer,laowang-engineer,default,explanatory,learning), "skip" to skip all, "all" for all custom styles, ${i18n.t("cli:help.defaults.prefix")} all`).option("--default-output-style, -d <style>", `Default output style, ${i18n.t("cli:help.defaults.prefix")} engineer-professional`).option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--install-cometix-line, -x <value>", `Install CCometixLine statusline tool (true/false), ${i18n.t("cli:help.defaults.prefix")} true`).action(await withLanguageResolution(async (options) => {
|
|
2419
|
+
cli.command("init", "Initialize Claude Code configuration").alias("i").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--ai-output-lang, -a <lang>", "AI output language").option("--force, -f", "Force overwrite existing configuration").option("--skip-prompt, -s", "Skip all interactive prompts (non-interactive mode)").option("--config-action, -r <action>", `Config handling (new/backup/merge/docs-only/skip), ${i18n.t("cli:help.defaults.prefix")} backup`).option("--api-type, -t <type>", "API type (auth_token/api_key/ccr_proxy/skip)").option("--api-key, -k <key>", "API key (used for both API key and auth token types)").option("--api-url, -u <url>", "Custom API URL").option("--mcp-services, -m <services>", `Comma-separated MCP services to install (context7,mcp-deepwiki,Playwright,exa), "skip" to skip all, "all" for all non-key services, ${i18n.t("cli:help.defaults.prefix")} all`).option("--workflows, -w <workflows>", `Comma-separated workflows to install (sixStepsWorkflow,featPlanUx,gitWorkflow,bmadWorkflow), "skip" to skip all, "all" for all workflows, ${i18n.t("cli:help.defaults.prefix")} all`).option("--output-styles, -o <styles>", `Comma-separated output styles (engineer-professional,nekomata-engineer,laowang-engineer,default,explanatory,learning), "skip" to skip all, "all" for all custom styles, ${i18n.t("cli:help.defaults.prefix")} all`).option("--default-output-style, -d <style>", `Default output style, ${i18n.t("cli:help.defaults.prefix")} engineer-professional`).option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex)", { default: DEFAULT_CODE_TOOL_TYPE }).option("--install-cometix-line, -x <value>", `Install CCometixLine statusline tool (true/false), ${i18n.t("cli:help.defaults.prefix")} true`).action(await withLanguageResolution(async (options) => {
|
|
1207
2420
|
await init(options);
|
|
1208
2421
|
}));
|
|
1209
2422
|
cli.command("update", "Update Claude Code prompts only").alias("u").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").action(await withLanguageResolution(async (options) => {
|
|
@@ -1215,6 +2428,15 @@ async function setupCommands(cli) {
|
|
|
1215
2428
|
cli.command("ccu [...args]", "Run Claude Code usage analysis tool").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").allowUnknownOptions().action(await withLanguageResolution(async (args) => {
|
|
1216
2429
|
await executeCcusage(args);
|
|
1217
2430
|
}));
|
|
2431
|
+
cli.command("config-switch [provider]", "Switch Codex provider or list available providers").alias("cs").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--list", "List available providers").action(await withLanguageResolution(async (provider, options) => {
|
|
2432
|
+
await configSwitchCommand({
|
|
2433
|
+
provider,
|
|
2434
|
+
list: options.list
|
|
2435
|
+
});
|
|
2436
|
+
}));
|
|
2437
|
+
cli.command("uninstall", "Remove ZCF configurations and tools").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--mode, -m <mode>", "Uninstall mode (complete/custom/interactive), default: interactive").option("--items, -i <items>", "Comma-separated items for custom uninstall mode").action(await withLanguageResolution(async (options) => {
|
|
2438
|
+
await uninstall(options);
|
|
2439
|
+
}));
|
|
1218
2440
|
cli.command("check-updates", "Check and update Claude Code and CCR to latest versions").alias("check").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").action(await withLanguageResolution(async () => {
|
|
1219
2441
|
await checkUpdates();
|
|
1220
2442
|
}));
|