zcf 3.3.3 → 3.4.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 +16 -870
- package/dist/chunks/claude-code-config-manager.mjs +8 -7
- package/dist/chunks/claude-code-incremental-manager.mjs +19 -33
- package/dist/chunks/codex-config-switch.mjs +16 -23
- package/dist/chunks/codex-provider-manager.mjs +21 -24
- package/dist/chunks/codex-uninstaller.mjs +12 -6
- package/dist/chunks/commands.mjs +2 -1
- package/dist/chunks/features.mjs +21 -30
- package/dist/chunks/simple-config.mjs +476 -158
- package/dist/cli.mjs +46 -34
- package/dist/i18n/locales/en/codex.json +13 -3
- package/dist/i18n/locales/en/common.json +3 -1
- package/dist/i18n/locales/en/installation.json +15 -1
- package/dist/i18n/locales/en/uninstall.json +2 -2
- package/dist/i18n/locales/zh-CN/codex.json +13 -3
- package/dist/i18n/locales/zh-CN/common.json +3 -1
- package/dist/i18n/locales/zh-CN/installation.json +15 -1
- package/dist/i18n/locales/zh-CN/uninstall.json +2 -2
- package/dist/index.d.mts +52 -7
- package/dist/index.d.ts +52 -7
- package/dist/index.mjs +2 -1
- package/package.json +2 -1
|
@@ -9,6 +9,7 @@ import { promisify } from 'node:util';
|
|
|
9
9
|
import dayjs from 'dayjs';
|
|
10
10
|
import { dirname, join } from 'pathe';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import toggleModule from 'inquirer-toggle';
|
|
12
13
|
import ora from 'ora';
|
|
13
14
|
import semver from 'semver';
|
|
14
15
|
import { stringify, parse } from 'smol-toml';
|
|
@@ -17,7 +18,7 @@ import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
|
|
|
17
18
|
import i18next from 'i18next';
|
|
18
19
|
import Backend from 'i18next-fs-backend';
|
|
19
20
|
|
|
20
|
-
const version = "3.
|
|
21
|
+
const version = "3.4.0";
|
|
21
22
|
const homepage = "https://github.com/UfoMiao/zcf";
|
|
22
23
|
|
|
23
24
|
const i18n = i18next.createInstance();
|
|
@@ -589,6 +590,9 @@ function getMcpCommand(command = "npx") {
|
|
|
589
590
|
}
|
|
590
591
|
return [command];
|
|
591
592
|
}
|
|
593
|
+
function normalizeTomlPath(str) {
|
|
594
|
+
return str.replace(/\\+/g, "/").replace(/\/+/g, "/");
|
|
595
|
+
}
|
|
592
596
|
function getSystemRoot() {
|
|
593
597
|
if (!isWindows())
|
|
594
598
|
return null;
|
|
@@ -598,7 +602,7 @@ function getSystemRoot() {
|
|
|
598
602
|
systemRoot = env.SYSTEMROOT;
|
|
599
603
|
else if (Object.prototype.hasOwnProperty.call(env, "SystemRoot") && env.SystemRoot)
|
|
600
604
|
systemRoot = env.SystemRoot;
|
|
601
|
-
return systemRoot
|
|
605
|
+
return normalizeTomlPath(systemRoot);
|
|
602
606
|
}
|
|
603
607
|
function shouldUseSudoForGlobalInstall() {
|
|
604
608
|
if (isTermux())
|
|
@@ -635,7 +639,7 @@ function wrapCommandWithSudo(command, args) {
|
|
|
635
639
|
}
|
|
636
640
|
const WRITE_CHECK_FLAG = 2;
|
|
637
641
|
function normalizePath(path) {
|
|
638
|
-
return path
|
|
642
|
+
return normalizeTomlPath(path).replace(/\/+$/, "");
|
|
639
643
|
}
|
|
640
644
|
function isPathInsideHome(path) {
|
|
641
645
|
const home = process.env.HOME;
|
|
@@ -702,6 +706,30 @@ async function commandExists(command) {
|
|
|
702
706
|
}
|
|
703
707
|
return false;
|
|
704
708
|
}
|
|
709
|
+
function getRecommendedInstallMethods(codeType) {
|
|
710
|
+
const platform2 = getPlatform();
|
|
711
|
+
const wsl = isWSL();
|
|
712
|
+
if (codeType === "claude-code") {
|
|
713
|
+
if (platform2 === "macos") {
|
|
714
|
+
return ["homebrew", "curl", "npm"];
|
|
715
|
+
}
|
|
716
|
+
if (platform2 === "linux" || wsl) {
|
|
717
|
+
return ["curl", "npm"];
|
|
718
|
+
}
|
|
719
|
+
if (platform2 === "windows") {
|
|
720
|
+
return ["powershell", "npm"];
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
if (codeType === "codex") {
|
|
724
|
+
if (platform2 === "macos") {
|
|
725
|
+
return ["homebrew", "npm"];
|
|
726
|
+
}
|
|
727
|
+
if (platform2 === "linux" || wsl || platform2 === "windows") {
|
|
728
|
+
return ["npm"];
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return ["npm"];
|
|
732
|
+
}
|
|
705
733
|
|
|
706
734
|
class FileSystemError extends Error {
|
|
707
735
|
constructor(message, path, cause) {
|
|
@@ -1485,6 +1513,16 @@ const config$1 = {
|
|
|
1485
1513
|
updateDefaultModel: updateDefaultModel
|
|
1486
1514
|
};
|
|
1487
1515
|
|
|
1516
|
+
const togglePrompt = toggleModule?.default?.default || toggleModule?.default || toggleModule;
|
|
1517
|
+
async function promptBoolean(options) {
|
|
1518
|
+
const { message, defaultValue = false, theme } = options;
|
|
1519
|
+
return await togglePrompt({
|
|
1520
|
+
message,
|
|
1521
|
+
default: defaultValue,
|
|
1522
|
+
...theme ? { theme } : {}
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1488
1526
|
const PROVIDER_PRESETS_URL = "https://pub-0dc3e1677e894f07bbea11b17a29e032.r2.dev/providers.json";
|
|
1489
1527
|
async function fetchProviderPresets() {
|
|
1490
1528
|
try {
|
|
@@ -1848,13 +1886,10 @@ async function setupCcrConfiguration() {
|
|
|
1848
1886
|
console.log(ansis.blue(`\u2139 ${i18n.t("ccr:existingCcrConfig")}`));
|
|
1849
1887
|
let shouldBackupAndReconfigure = false;
|
|
1850
1888
|
try {
|
|
1851
|
-
|
|
1852
|
-
type: "confirm",
|
|
1853
|
-
name: "overwrite",
|
|
1889
|
+
shouldBackupAndReconfigure = await promptBoolean({
|
|
1854
1890
|
message: i18n.t("ccr:overwriteCcrConfig"),
|
|
1855
|
-
|
|
1891
|
+
defaultValue: false
|
|
1856
1892
|
});
|
|
1857
|
-
shouldBackupAndReconfigure = result.overwrite;
|
|
1858
1893
|
} catch (error) {
|
|
1859
1894
|
if (error.name === "ExitPromptError") {
|
|
1860
1895
|
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
@@ -2054,11 +2089,9 @@ async function updateCcr(force = false, skipPrompt = false) {
|
|
|
2054
2089
|
console.log(ansis.cyan(format(i18n.t("updater:currentVersion"), { version: currentVersion || "" })));
|
|
2055
2090
|
console.log(ansis.cyan(format(i18n.t("updater:latestVersion"), { version: latestVersion })));
|
|
2056
2091
|
if (!skipPrompt) {
|
|
2057
|
-
const
|
|
2058
|
-
type: "confirm",
|
|
2059
|
-
name: "confirm",
|
|
2092
|
+
const confirm = await promptBoolean({
|
|
2060
2093
|
message: format(i18n.t("updater:confirmUpdate"), { tool: "CCR" }),
|
|
2061
|
-
|
|
2094
|
+
defaultValue: true
|
|
2062
2095
|
});
|
|
2063
2096
|
if (!confirm) {
|
|
2064
2097
|
console.log(ansis.gray(i18n.t("updater:updateSkipped")));
|
|
@@ -2104,11 +2137,9 @@ async function updateClaudeCode(force = false, skipPrompt = false) {
|
|
|
2104
2137
|
console.log(ansis.cyan(format(i18n.t("updater:currentVersion"), { version: currentVersion || "" })));
|
|
2105
2138
|
console.log(ansis.cyan(format(i18n.t("updater:latestVersion"), { version: latestVersion })));
|
|
2106
2139
|
if (!skipPrompt) {
|
|
2107
|
-
const
|
|
2108
|
-
type: "confirm",
|
|
2109
|
-
name: "confirm",
|
|
2140
|
+
const confirm = await promptBoolean({
|
|
2110
2141
|
message: format(i18n.t("updater:confirmUpdate"), { tool: "Claude Code" }),
|
|
2111
|
-
|
|
2142
|
+
defaultValue: true
|
|
2112
2143
|
});
|
|
2113
2144
|
if (!confirm) {
|
|
2114
2145
|
console.log(ansis.gray(i18n.t("updater:updateSkipped")));
|
|
@@ -2154,11 +2185,9 @@ async function updateCometixLine(force = false, skipPrompt = false) {
|
|
|
2154
2185
|
console.log(ansis.cyan(format(i18n.t("updater:currentVersion"), { version: currentVersion || "" })));
|
|
2155
2186
|
console.log(ansis.cyan(format(i18n.t("updater:latestVersion"), { version: latestVersion })));
|
|
2156
2187
|
if (!skipPrompt) {
|
|
2157
|
-
const
|
|
2158
|
-
type: "confirm",
|
|
2159
|
-
name: "confirm",
|
|
2188
|
+
const confirm = await promptBoolean({
|
|
2160
2189
|
message: format(i18n.t("updater:confirmUpdate"), { tool: "CCometixLine" }),
|
|
2161
|
-
|
|
2190
|
+
defaultValue: true
|
|
2162
2191
|
});
|
|
2163
2192
|
if (!confirm) {
|
|
2164
2193
|
console.log(ansis.gray(i18n.t("updater:updateSkipped")));
|
|
@@ -2657,16 +2686,10 @@ async function resolveAiOutputLanguage(scriptLang, commandLineOption, savedConfi
|
|
|
2657
2686
|
}
|
|
2658
2687
|
const currentLanguageLabel = getAiOutputLanguageLabel(savedConfig.aiOutputLang) || savedConfig.aiOutputLang;
|
|
2659
2688
|
console.log(ansis.blue(`${i18n.t("language:currentConfigFound")}: ${currentLanguageLabel}`));
|
|
2660
|
-
const
|
|
2661
|
-
type: "confirm",
|
|
2662
|
-
name: "shouldModify",
|
|
2689
|
+
const shouldModify = await promptBoolean({
|
|
2663
2690
|
message: i18n.t("language:modifyConfigPrompt"),
|
|
2664
|
-
|
|
2691
|
+
defaultValue: false
|
|
2665
2692
|
});
|
|
2666
|
-
if (shouldModify === void 0) {
|
|
2667
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2668
|
-
process.exit(0);
|
|
2669
|
-
}
|
|
2670
2693
|
if (!shouldModify) {
|
|
2671
2694
|
console.log(ansis.gray(`\u2714 ${i18n.t("language:aiOutputLangHint")}: ${currentLanguageLabel}`));
|
|
2672
2695
|
return savedConfig.aiOutputLang;
|
|
@@ -2712,16 +2735,10 @@ async function resolveTemplateLanguage(commandLineOption, savedConfig, skipPromp
|
|
|
2712
2735
|
}
|
|
2713
2736
|
const currentLanguageLabel = LANG_LABELS[savedConfig.templateLang];
|
|
2714
2737
|
console.log(ansis.blue(`${i18n.t("language:currentTemplateLanguageFound")}: ${currentLanguageLabel}`));
|
|
2715
|
-
const
|
|
2716
|
-
type: "confirm",
|
|
2717
|
-
name: "shouldModify",
|
|
2738
|
+
const shouldModify = await promptBoolean({
|
|
2718
2739
|
message: i18n.t("language:modifyTemplateLanguagePrompt"),
|
|
2719
|
-
|
|
2740
|
+
defaultValue: false
|
|
2720
2741
|
});
|
|
2721
|
-
if (shouldModify === void 0) {
|
|
2722
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2723
|
-
process.exit(0);
|
|
2724
|
-
}
|
|
2725
2742
|
if (!shouldModify) {
|
|
2726
2743
|
console.log(ansis.gray(`\u2714 ${i18n.t("language:selectConfigLang")}: ${currentLanguageLabel}`));
|
|
2727
2744
|
return savedConfig.templateLang;
|
|
@@ -2733,16 +2750,10 @@ async function resolveTemplateLanguage(commandLineOption, savedConfig, skipPromp
|
|
|
2733
2750
|
return savedConfig.preferredLang;
|
|
2734
2751
|
}
|
|
2735
2752
|
console.log(ansis.yellow(`${i18n.t("language:usingFallbackTemplate")}: ${LANG_LABELS[savedConfig.preferredLang]}`));
|
|
2736
|
-
const
|
|
2737
|
-
type: "confirm",
|
|
2738
|
-
name: "shouldModify",
|
|
2753
|
+
const shouldModify = await promptBoolean({
|
|
2739
2754
|
message: i18n.t("language:modifyTemplateLanguagePrompt"),
|
|
2740
|
-
|
|
2755
|
+
defaultValue: false
|
|
2741
2756
|
});
|
|
2742
|
-
if (shouldModify === void 0) {
|
|
2743
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2744
|
-
process.exit(0);
|
|
2745
|
-
}
|
|
2746
2757
|
if (!shouldModify) {
|
|
2747
2758
|
return savedConfig.preferredLang;
|
|
2748
2759
|
}
|
|
@@ -2766,16 +2777,10 @@ async function resolveSystemPromptStyle(availablePrompts, commandLineOption, sav
|
|
|
2766
2777
|
return currentStyleId;
|
|
2767
2778
|
}
|
|
2768
2779
|
console.log(ansis.blue(`${i18n.t("language:currentSystemPromptFound")}: ${currentStyle.name}`));
|
|
2769
|
-
const
|
|
2770
|
-
type: "confirm",
|
|
2771
|
-
name: "shouldModify",
|
|
2780
|
+
const shouldModify = await promptBoolean({
|
|
2772
2781
|
message: i18n.t("language:modifySystemPromptPrompt"),
|
|
2773
|
-
|
|
2782
|
+
defaultValue: false
|
|
2774
2783
|
});
|
|
2775
|
-
if (shouldModify === void 0) {
|
|
2776
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
2777
|
-
process.exit(0);
|
|
2778
|
-
}
|
|
2779
2784
|
if (!shouldModify) {
|
|
2780
2785
|
console.log(ansis.gray(`\u2714 ${i18n.t("language:currentSystemPromptFound")}: ${currentStyle.name}`));
|
|
2781
2786
|
return currentStyleId;
|
|
@@ -3002,24 +3007,20 @@ function getRootDir$1() {
|
|
|
3002
3007
|
}
|
|
3003
3008
|
return dirname(currentFilePath);
|
|
3004
3009
|
}
|
|
3005
|
-
async function executeCodexInstallation(isUpdate) {
|
|
3006
|
-
const action = isUpdate ? "update" : "install";
|
|
3010
|
+
async function executeCodexInstallation(isUpdate, skipMethodSelection = false) {
|
|
3007
3011
|
if (isUpdate) {
|
|
3008
3012
|
console.log(ansis.cyan(i18n.t("codex:updatingCli")));
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
if (result.exitCode !== 0) {
|
|
3017
|
-
throw new Error(`Failed to ${action} codex CLI: exit code ${result.exitCode}`);
|
|
3018
|
-
}
|
|
3019
|
-
if (isUpdate) {
|
|
3013
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", "@openai/codex@latest"]);
|
|
3014
|
+
if (usedSudo)
|
|
3015
|
+
console.log(ansis.yellow(i18n.t("codex:usingSudo")));
|
|
3016
|
+
const result = await x(command, args);
|
|
3017
|
+
if (result.exitCode !== 0) {
|
|
3018
|
+
throw new Error(`Failed to update codex CLI: exit code ${result.exitCode}`);
|
|
3019
|
+
}
|
|
3020
3020
|
console.log(ansis.green(i18n.t("codex:updateSuccess")));
|
|
3021
3021
|
} else {
|
|
3022
|
-
|
|
3022
|
+
const { installCodex } = await Promise.resolve().then(function () { return installer; });
|
|
3023
|
+
await installCodex(skipMethodSelection);
|
|
3023
3024
|
}
|
|
3024
3025
|
}
|
|
3025
3026
|
function getUninstallOptions() {
|
|
@@ -3317,11 +3318,12 @@ function renderCodexConfig(data) {
|
|
|
3317
3318
|
lines.push("# --- MCP servers added by ZCF ---");
|
|
3318
3319
|
for (const service of data.mcpServices) {
|
|
3319
3320
|
lines.push(`[mcp_servers.${service.id}]`);
|
|
3320
|
-
|
|
3321
|
+
const normalizedCommand = normalizeTomlPath(service.command);
|
|
3322
|
+
lines.push(`command = "${normalizedCommand}"`);
|
|
3321
3323
|
const argsString = service.args.length > 0 ? service.args.map((arg) => `"${arg}"`).join(", ") : "";
|
|
3322
3324
|
lines.push(`args = [${argsString}]`);
|
|
3323
3325
|
if (service.env && Object.keys(service.env).length > 0) {
|
|
3324
|
-
const envEntries = Object.entries(service.env).map(([key, value]) => `${key} =
|
|
3326
|
+
const envEntries = Object.entries(service.env).map(([key, value]) => `${key} = '${value}'`).join(", ");
|
|
3325
3327
|
lines.push(`env = {${envEntries}}`);
|
|
3326
3328
|
}
|
|
3327
3329
|
if (service.startup_timeout_ms) {
|
|
@@ -3349,7 +3351,7 @@ function writeAuthFile(newEntries) {
|
|
|
3349
3351
|
const merged = { ...existing, ...newEntries };
|
|
3350
3352
|
writeJsonConfig(CODEX_AUTH_FILE, merged, { pretty: true });
|
|
3351
3353
|
}
|
|
3352
|
-
async function isCodexInstalled() {
|
|
3354
|
+
async function isCodexInstalled$1() {
|
|
3353
3355
|
try {
|
|
3354
3356
|
const result = await x("npm", ["list", "-g", "--depth=0"]);
|
|
3355
3357
|
if (result.exitCode !== 0) {
|
|
@@ -3418,19 +3420,19 @@ async function checkCodexUpdate() {
|
|
|
3418
3420
|
};
|
|
3419
3421
|
}
|
|
3420
3422
|
}
|
|
3421
|
-
async function installCodexCli() {
|
|
3423
|
+
async function installCodexCli(skipMethodSelection = false) {
|
|
3422
3424
|
ensureI18nInitialized();
|
|
3423
|
-
if (await isCodexInstalled()) {
|
|
3425
|
+
if (await isCodexInstalled$1()) {
|
|
3424
3426
|
const { needsUpdate } = await checkCodexUpdate();
|
|
3425
3427
|
if (needsUpdate) {
|
|
3426
|
-
await executeCodexInstallation(true);
|
|
3428
|
+
await executeCodexInstallation(true, skipMethodSelection);
|
|
3427
3429
|
return;
|
|
3428
3430
|
} else {
|
|
3429
3431
|
console.log(ansis.yellow(i18n.t("codex:alreadyInstalled")));
|
|
3430
3432
|
return;
|
|
3431
3433
|
}
|
|
3432
3434
|
}
|
|
3433
|
-
await executeCodexInstallation(false);
|
|
3435
|
+
await executeCodexInstallation(false, skipMethodSelection);
|
|
3434
3436
|
}
|
|
3435
3437
|
async function runCodexWorkflowImportWithLanguageSelection(options) {
|
|
3436
3438
|
ensureI18nInitialized();
|
|
@@ -3874,15 +3876,13 @@ async function configureCodexApi(options) {
|
|
|
3874
3876
|
if (existingProvider || sessionProvider) {
|
|
3875
3877
|
const sourceType = existingProvider ? "existing" : "session";
|
|
3876
3878
|
const sourceProvider = existingProvider || sessionProvider;
|
|
3877
|
-
const
|
|
3878
|
-
type: "confirm",
|
|
3879
|
-
name: "shouldOverwrite",
|
|
3879
|
+
const shouldOverwrite = await promptBoolean({
|
|
3880
3880
|
message: i18n.t("codex:providerDuplicatePrompt", {
|
|
3881
3881
|
name: sourceProvider.name,
|
|
3882
3882
|
source: sourceType === "existing" ? i18n.t("codex:existingConfig") : i18n.t("codex:currentSession")
|
|
3883
3883
|
}),
|
|
3884
|
-
|
|
3885
|
-
}
|
|
3884
|
+
defaultValue: false
|
|
3885
|
+
});
|
|
3886
3886
|
if (!shouldOverwrite) {
|
|
3887
3887
|
console.log(ansis.yellow(i18n.t("codex:providerDuplicateSkipped")));
|
|
3888
3888
|
continue;
|
|
@@ -3908,12 +3908,10 @@ async function configureCodexApi(options) {
|
|
|
3908
3908
|
providers.push(newProvider);
|
|
3909
3909
|
currentSessionProviders.set(providerId, newProvider);
|
|
3910
3910
|
authEntries[envKey] = answers.apiKey;
|
|
3911
|
-
const
|
|
3912
|
-
type: "confirm",
|
|
3913
|
-
name: "addAnother",
|
|
3911
|
+
const addAnother = await promptBoolean({
|
|
3914
3912
|
message: i18n.t("codex:addProviderPrompt"),
|
|
3915
|
-
|
|
3916
|
-
}
|
|
3913
|
+
defaultValue: false
|
|
3914
|
+
});
|
|
3917
3915
|
addMore = addAnother;
|
|
3918
3916
|
}
|
|
3919
3917
|
if (providers.length === 0) {
|
|
@@ -3947,7 +3945,7 @@ async function configureCodexApi(options) {
|
|
|
3947
3945
|
}
|
|
3948
3946
|
async function runCodexFullInit(options) {
|
|
3949
3947
|
ensureI18nInitialized();
|
|
3950
|
-
await installCodexCli();
|
|
3948
|
+
await installCodexCli(options?.skipPrompt || false);
|
|
3951
3949
|
const aiOutputLang = await runCodexWorkflowImportWithLanguageSelection(options);
|
|
3952
3950
|
await configureCodexApi(options);
|
|
3953
3951
|
await configureCodexMcp(options);
|
|
@@ -4012,11 +4010,9 @@ async function runCodexUpdate(force = false, skipPrompt = false) {
|
|
|
4012
4010
|
console.log(ansis.cyan(format(i18n.t("codex:currentVersion"), { version: currentVersion || "" })));
|
|
4013
4011
|
console.log(ansis.cyan(format(i18n.t("codex:latestVersion"), { version: latestVersion })));
|
|
4014
4012
|
if (!skipPrompt) {
|
|
4015
|
-
const
|
|
4016
|
-
type: "confirm",
|
|
4017
|
-
name: "confirm",
|
|
4013
|
+
const confirm = await promptBoolean({
|
|
4018
4014
|
message: i18n.t("codex:confirmUpdate"),
|
|
4019
|
-
|
|
4015
|
+
defaultValue: true
|
|
4020
4016
|
});
|
|
4021
4017
|
if (!confirm) {
|
|
4022
4018
|
console.log(ansis.gray(i18n.t("codex:updateSkipped")));
|
|
@@ -4064,12 +4060,10 @@ async function runCodexUninstall() {
|
|
|
4064
4060
|
}
|
|
4065
4061
|
try {
|
|
4066
4062
|
if (mode === "complete") {
|
|
4067
|
-
const
|
|
4068
|
-
type: "confirm",
|
|
4069
|
-
name: "confirm",
|
|
4063
|
+
const confirm = await promptBoolean({
|
|
4070
4064
|
message: i18n.t("codex:uninstallPrompt"),
|
|
4071
|
-
|
|
4072
|
-
}
|
|
4065
|
+
defaultValue: false
|
|
4066
|
+
});
|
|
4073
4067
|
if (!confirm) {
|
|
4074
4068
|
handleUninstallCancellation();
|
|
4075
4069
|
return;
|
|
@@ -4246,7 +4240,7 @@ const codex = {
|
|
|
4246
4240
|
getBackupMessage: getBackupMessage,
|
|
4247
4241
|
getCodexVersion: getCodexVersion,
|
|
4248
4242
|
installCodexCli: installCodexCli,
|
|
4249
|
-
isCodexInstalled: isCodexInstalled,
|
|
4243
|
+
isCodexInstalled: isCodexInstalled$1,
|
|
4250
4244
|
listCodexProviders: listCodexProviders,
|
|
4251
4245
|
parseCodexConfig: parseCodexConfig,
|
|
4252
4246
|
readCodexConfig: readCodexConfig,
|
|
@@ -4528,11 +4522,9 @@ async function configureOutputStyle(preselectedStyles, preselectedDefault) {
|
|
|
4528
4522
|
const availableStyles = getAvailableOutputStyles();
|
|
4529
4523
|
if (hasLegacyPersonalityFiles() && !preselectedStyles) {
|
|
4530
4524
|
console.log(ansis.yellow(`\u26A0\uFE0F ${i18n.t("configuration:legacyFilesDetected")}`));
|
|
4531
|
-
const
|
|
4532
|
-
type: "confirm",
|
|
4533
|
-
name: "cleanupLegacy",
|
|
4525
|
+
const cleanupLegacy = await promptBoolean({
|
|
4534
4526
|
message: i18n.t("configuration:cleanupLegacyFiles"),
|
|
4535
|
-
|
|
4527
|
+
defaultValue: true
|
|
4536
4528
|
});
|
|
4537
4529
|
if (cleanupLegacy) {
|
|
4538
4530
|
cleanupLegacyPersonalityFiles();
|
|
@@ -4827,7 +4819,9 @@ ${ansis.cyan(i18n.t("common:complete"))}`);
|
|
|
4827
4819
|
}
|
|
4828
4820
|
|
|
4829
4821
|
function handleExitPromptError(error) {
|
|
4830
|
-
|
|
4822
|
+
const isExitError = error instanceof Error && (error.name === "ExitPromptError" || error.message?.includes("ExitPromptError") || error.message?.includes("User force closed the prompt"));
|
|
4823
|
+
if (isExitError) {
|
|
4824
|
+
ensureI18nInitialized();
|
|
4831
4825
|
console.log(ansis.cyan(`
|
|
4832
4826
|
${i18n.t("common:goodbye")}
|
|
4833
4827
|
`));
|
|
@@ -4847,13 +4841,17 @@ function handleGeneralError(error) {
|
|
|
4847
4841
|
async function isClaudeCodeInstalled() {
|
|
4848
4842
|
return await commandExists("claude");
|
|
4849
4843
|
}
|
|
4850
|
-
async function installClaudeCode() {
|
|
4844
|
+
async function installClaudeCode(skipMethodSelection = false) {
|
|
4851
4845
|
ensureI18nInitialized();
|
|
4846
|
+
const codeType = "claude-code";
|
|
4852
4847
|
const installed = await isClaudeCodeInstalled();
|
|
4853
4848
|
if (installed) {
|
|
4854
4849
|
console.log(ansis.green(`\u2714 ${i18n.t("installation:alreadyInstalled")}`));
|
|
4850
|
+
const version = await detectInstalledVersion(codeType);
|
|
4851
|
+
if (version) {
|
|
4852
|
+
console.log(ansis.gray(` ${i18n.t("installation:detectedVersion", { version })}`));
|
|
4853
|
+
}
|
|
4855
4854
|
await updateClaudeCode();
|
|
4856
|
-
await setInstallMethod("npm");
|
|
4857
4855
|
return;
|
|
4858
4856
|
}
|
|
4859
4857
|
if (isTermux()) {
|
|
@@ -4872,31 +4870,100 @@ async function installClaudeCode() {
|
|
|
4872
4870
|
}
|
|
4873
4871
|
console.log(ansis.gray(i18n.t("installation:wslPathInfo", { path: `${homedir()}/.claude/` })));
|
|
4874
4872
|
}
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4873
|
+
if (skipMethodSelection) {
|
|
4874
|
+
console.log(i18n.t("installation:installing"));
|
|
4875
|
+
try {
|
|
4876
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", "@anthropic-ai/claude-code"]);
|
|
4877
|
+
if (usedSudo) {
|
|
4878
|
+
console.log(ansis.yellow(`\u2139 ${i18n.t("installation:usingSudo")}`));
|
|
4879
|
+
}
|
|
4880
|
+
await exec(command, args);
|
|
4881
|
+
console.log(`\u2714 ${i18n.t("installation:installSuccess")}`);
|
|
4882
|
+
await setInstallMethod("npm");
|
|
4883
|
+
if (isTermux()) {
|
|
4884
|
+
console.log(ansis.gray(`
|
|
4886
4885
|
Claude Code installed to: ${getTermuxPrefix()}/bin/claude`));
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4886
|
+
}
|
|
4887
|
+
if (isWSL()) {
|
|
4888
|
+
console.log(ansis.gray(`
|
|
4890
4889
|
${i18n.t("installation:wslInstallSuccess")}`));
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4890
|
+
}
|
|
4891
|
+
} catch (error) {
|
|
4892
|
+
console.error(`\u2716 ${i18n.t("installation:installFailed")}`);
|
|
4893
|
+
if (isTermux()) {
|
|
4894
|
+
console.error(ansis.yellow(`
|
|
4896
4895
|
${i18n.t("installation:termuxInstallHint")}
|
|
4897
4896
|
`));
|
|
4897
|
+
}
|
|
4898
|
+
throw error;
|
|
4899
|
+
}
|
|
4900
|
+
return;
|
|
4901
|
+
}
|
|
4902
|
+
const method = await selectInstallMethod(codeType);
|
|
4903
|
+
if (!method) {
|
|
4904
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
4905
|
+
return;
|
|
4906
|
+
}
|
|
4907
|
+
const success = await executeInstallMethod(method, codeType);
|
|
4908
|
+
if (!success) {
|
|
4909
|
+
const retrySuccess = await handleInstallFailure(codeType, [method]);
|
|
4910
|
+
if (!retrySuccess) {
|
|
4911
|
+
console.error(ansis.red(`\u2716 ${i18n.t("installation:installFailed")}`));
|
|
4912
|
+
throw new Error(i18n.t("installation:installFailed"));
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4915
|
+
if (isTermux()) {
|
|
4916
|
+
console.log(ansis.gray(`
|
|
4917
|
+
Claude Code installed to: ${getTermuxPrefix()}/bin/claude`));
|
|
4918
|
+
}
|
|
4919
|
+
if (isWSL()) {
|
|
4920
|
+
console.log(ansis.gray(`
|
|
4921
|
+
${i18n.t("installation:wslInstallSuccess")}`));
|
|
4922
|
+
}
|
|
4923
|
+
}
|
|
4924
|
+
async function isCodexInstalled() {
|
|
4925
|
+
return await commandExists("codex");
|
|
4926
|
+
}
|
|
4927
|
+
async function installCodex(skipMethodSelection = false) {
|
|
4928
|
+
ensureI18nInitialized();
|
|
4929
|
+
const codeType = "codex";
|
|
4930
|
+
const codeTypeName = i18n.t("common:codex");
|
|
4931
|
+
const installed = await isCodexInstalled();
|
|
4932
|
+
if (installed) {
|
|
4933
|
+
console.log(ansis.green(`\u2714 ${codeTypeName} ${i18n.t("installation:alreadyInstalled")}`));
|
|
4934
|
+
const version = await detectInstalledVersion(codeType);
|
|
4935
|
+
if (version) {
|
|
4936
|
+
console.log(ansis.gray(` ${i18n.t("installation:detectedVersion", { version })}`));
|
|
4937
|
+
}
|
|
4938
|
+
return;
|
|
4939
|
+
}
|
|
4940
|
+
if (skipMethodSelection) {
|
|
4941
|
+
console.log(i18n.t("installation:installingWith", { method: "npm", codeType: codeTypeName }));
|
|
4942
|
+
try {
|
|
4943
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", "@openai/codex"]);
|
|
4944
|
+
if (usedSudo) {
|
|
4945
|
+
console.log(ansis.yellow(`\u2139 ${i18n.t("installation:usingSudo")}`));
|
|
4946
|
+
}
|
|
4947
|
+
await exec(command, args);
|
|
4948
|
+
console.log(ansis.green(`\u2714 ${codeTypeName} ${i18n.t("installation:installSuccess")}`));
|
|
4949
|
+
} catch (error) {
|
|
4950
|
+
console.error(ansis.red(`\u2716 ${codeTypeName} ${i18n.t("installation:installFailed")}`));
|
|
4951
|
+
throw error;
|
|
4952
|
+
}
|
|
4953
|
+
return;
|
|
4954
|
+
}
|
|
4955
|
+
const method = await selectInstallMethod(codeType);
|
|
4956
|
+
if (!method) {
|
|
4957
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
4958
|
+
return;
|
|
4959
|
+
}
|
|
4960
|
+
const success = await executeInstallMethod(method, codeType);
|
|
4961
|
+
if (!success) {
|
|
4962
|
+
const retrySuccess = await handleInstallFailure(codeType, [method]);
|
|
4963
|
+
if (!retrySuccess) {
|
|
4964
|
+
console.error(ansis.red(`\u2716 ${codeTypeName} ${i18n.t("installation:installFailed")}`));
|
|
4965
|
+
throw new Error(i18n.t("installation:installFailed"));
|
|
4898
4966
|
}
|
|
4899
|
-
throw error;
|
|
4900
4967
|
}
|
|
4901
4968
|
}
|
|
4902
4969
|
async function isLocalClaudeCodeInstalled() {
|
|
@@ -4930,28 +4997,297 @@ async function removeLocalClaudeCode() {
|
|
|
4930
4997
|
throw new Error(`${i18n.t("installation:failedToRemoveLocalInstallation")}: ${error}`);
|
|
4931
4998
|
}
|
|
4932
4999
|
}
|
|
4933
|
-
async function
|
|
5000
|
+
async function getInstallMethodFromConfig(codeType) {
|
|
4934
5001
|
try {
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
config
|
|
5002
|
+
if (codeType === "claude-code") {
|
|
5003
|
+
const { readMcpConfig } = await Promise.resolve().then(function () { return claudeConfig; });
|
|
5004
|
+
const config = readMcpConfig();
|
|
5005
|
+
return config?.installMethod || null;
|
|
4939
5006
|
}
|
|
4940
|
-
|
|
4941
|
-
|
|
5007
|
+
} catch {
|
|
5008
|
+
}
|
|
5009
|
+
return null;
|
|
5010
|
+
}
|
|
5011
|
+
async function uninstallCodeTool(codeType) {
|
|
5012
|
+
ensureI18nInitialized();
|
|
5013
|
+
const codeTypeName = codeType === "claude-code" ? i18n.t("common:claudeCode") : i18n.t("common:codex");
|
|
5014
|
+
let method = await getInstallMethodFromConfig(codeType);
|
|
5015
|
+
if (!method) {
|
|
5016
|
+
if (codeType === "claude-code") {
|
|
5017
|
+
try {
|
|
5018
|
+
const result = await exec("brew", ["list", "--cask", "claude-code"]);
|
|
5019
|
+
if (result.exitCode === 0) {
|
|
5020
|
+
method = "homebrew";
|
|
5021
|
+
}
|
|
5022
|
+
} catch {
|
|
5023
|
+
}
|
|
5024
|
+
} else if (codeType === "codex") {
|
|
5025
|
+
try {
|
|
5026
|
+
const result = await exec("brew", ["list", "codex"]);
|
|
5027
|
+
if (result.exitCode === 0) {
|
|
5028
|
+
method = "homebrew";
|
|
5029
|
+
}
|
|
5030
|
+
} catch {
|
|
5031
|
+
}
|
|
5032
|
+
}
|
|
5033
|
+
if (!method) {
|
|
5034
|
+
method = "npm";
|
|
5035
|
+
}
|
|
5036
|
+
}
|
|
5037
|
+
if (method === "native") {
|
|
5038
|
+
const platform = getPlatform();
|
|
5039
|
+
if (platform === "macos" || platform === "linux") {
|
|
5040
|
+
try {
|
|
5041
|
+
const testResult = codeType === "claude-code" ? await exec("brew", ["list", "--cask", "claude-code"]) : await exec("brew", ["list", "codex"]);
|
|
5042
|
+
if (testResult.exitCode === 0) {
|
|
5043
|
+
method = "homebrew";
|
|
5044
|
+
}
|
|
5045
|
+
} catch {
|
|
5046
|
+
method = "manual";
|
|
5047
|
+
}
|
|
5048
|
+
} else {
|
|
5049
|
+
method = "manual";
|
|
5050
|
+
}
|
|
5051
|
+
}
|
|
5052
|
+
const spinner = ora(i18n.t("installation:uninstallingWith", { method, codeType: codeTypeName })).start();
|
|
5053
|
+
try {
|
|
5054
|
+
switch (method) {
|
|
5055
|
+
case "npm": {
|
|
5056
|
+
const packageName = codeType === "claude-code" ? "@anthropic-ai/claude-code" : "@openai/codex";
|
|
5057
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["uninstall", "-g", packageName]);
|
|
5058
|
+
if (usedSudo) {
|
|
5059
|
+
spinner.info(i18n.t("installation:usingSudo"));
|
|
5060
|
+
spinner.start();
|
|
5061
|
+
}
|
|
5062
|
+
await exec(command, args);
|
|
5063
|
+
break;
|
|
5064
|
+
}
|
|
5065
|
+
case "homebrew": {
|
|
5066
|
+
if (codeType === "claude-code") {
|
|
5067
|
+
await exec("brew", ["uninstall", "--cask", "claude-code"]);
|
|
5068
|
+
} else {
|
|
5069
|
+
await exec("brew", ["uninstall", "codex"]);
|
|
5070
|
+
}
|
|
5071
|
+
break;
|
|
5072
|
+
}
|
|
5073
|
+
case "manual":
|
|
5074
|
+
default: {
|
|
5075
|
+
spinner.warn(i18n.t("installation:manualUninstallRequired", { codeType: codeTypeName }));
|
|
5076
|
+
const command = codeType === "claude-code" ? "claude" : "codex";
|
|
5077
|
+
try {
|
|
5078
|
+
const whichCmd = getPlatform() === "windows" ? "where" : "which";
|
|
5079
|
+
const result = await exec(whichCmd, [command]);
|
|
5080
|
+
if (result.stdout) {
|
|
5081
|
+
const binaryPath = result.stdout.trim().split("\n")[0];
|
|
5082
|
+
spinner.info(i18n.t("installation:binaryLocation", { path: binaryPath }));
|
|
5083
|
+
const platform = getPlatform();
|
|
5084
|
+
if (platform === "windows") {
|
|
5085
|
+
const quotedBinaryPath = `"${binaryPath}"`;
|
|
5086
|
+
await exec("cmd", ["/c", "del", "/f", "/q", quotedBinaryPath]);
|
|
5087
|
+
} else {
|
|
5088
|
+
const { command: rmCmd, args: rmArgs } = wrapCommandWithSudo("rm", ["-f", binaryPath]);
|
|
5089
|
+
if (rmCmd === "sudo") {
|
|
5090
|
+
spinner.info(i18n.t("installation:usingSudo"));
|
|
5091
|
+
spinner.start();
|
|
5092
|
+
}
|
|
5093
|
+
await exec(rmCmd, rmArgs);
|
|
5094
|
+
}
|
|
5095
|
+
}
|
|
5096
|
+
} catch {
|
|
5097
|
+
spinner.fail(i18n.t("installation:failedToLocateBinary", { command }));
|
|
5098
|
+
return false;
|
|
5099
|
+
}
|
|
5100
|
+
break;
|
|
5101
|
+
}
|
|
5102
|
+
}
|
|
5103
|
+
spinner.succeed(i18n.t("installation:uninstallSuccess", { method, codeType: codeTypeName }));
|
|
5104
|
+
return true;
|
|
5105
|
+
} catch (error) {
|
|
5106
|
+
spinner.fail(i18n.t("installation:uninstallFailed", { method, codeType: codeTypeName }));
|
|
5107
|
+
if (error instanceof Error) {
|
|
5108
|
+
console.error(ansis.gray(error.message));
|
|
5109
|
+
}
|
|
5110
|
+
return false;
|
|
5111
|
+
}
|
|
5112
|
+
}
|
|
5113
|
+
async function setInstallMethod(method = "npm", codeType = "claude-code") {
|
|
5114
|
+
try {
|
|
5115
|
+
if (codeType === "claude-code") {
|
|
5116
|
+
const { readMcpConfig, writeMcpConfig } = await Promise.resolve().then(function () { return claudeConfig; });
|
|
5117
|
+
let config = readMcpConfig();
|
|
5118
|
+
if (!config) {
|
|
5119
|
+
config = { mcpServers: {} };
|
|
5120
|
+
}
|
|
5121
|
+
config.installMethod = method === "npm" ? "npm" : "native";
|
|
5122
|
+
writeMcpConfig(config);
|
|
5123
|
+
}
|
|
5124
|
+
} catch (error) {
|
|
5125
|
+
console.error("Failed to set installMethod:", error);
|
|
5126
|
+
}
|
|
5127
|
+
}
|
|
5128
|
+
async function detectInstalledVersion(codeType) {
|
|
5129
|
+
try {
|
|
5130
|
+
const command = codeType === "claude-code" ? "claude" : "codex";
|
|
5131
|
+
const result = await exec(command, ["--version"]);
|
|
5132
|
+
if (result.exitCode === 0 && result.stdout) {
|
|
5133
|
+
const versionMatch = result.stdout.match(/(\d+\.\d+\.\d+)/);
|
|
5134
|
+
return versionMatch ? versionMatch[1] : result.stdout.trim();
|
|
5135
|
+
}
|
|
5136
|
+
} catch {
|
|
5137
|
+
}
|
|
5138
|
+
return null;
|
|
5139
|
+
}
|
|
5140
|
+
function getInstallMethodOptions(codeType, recommendedMethods) {
|
|
5141
|
+
const allMethods = ["npm", "homebrew", "curl", "powershell", "cmd"];
|
|
5142
|
+
const platform = getPlatform();
|
|
5143
|
+
const availableMethods = allMethods.filter((method) => {
|
|
5144
|
+
if (codeType === "codex" && !["npm", "homebrew"].includes(method)) {
|
|
5145
|
+
return false;
|
|
5146
|
+
}
|
|
5147
|
+
if (method === "homebrew")
|
|
5148
|
+
return platform === "macos" || platform === "linux";
|
|
5149
|
+
if (method === "curl")
|
|
5150
|
+
return platform !== "windows" || isWSL();
|
|
5151
|
+
if (method === "powershell" || method === "cmd")
|
|
5152
|
+
return platform === "windows";
|
|
5153
|
+
return true;
|
|
5154
|
+
});
|
|
5155
|
+
const topRecommended = recommendedMethods.length > 0 ? recommendedMethods[0] : null;
|
|
5156
|
+
return availableMethods.map((method) => {
|
|
5157
|
+
const isTopRecommended = method === topRecommended;
|
|
5158
|
+
const title = isTopRecommended ? `${i18n.t(`installation:installMethod${method.charAt(0).toUpperCase() + method.slice(1)}`)} ${ansis.green(`[${i18n.t("installation:recommendedMethod")}]`)}` : i18n.t(`installation:installMethod${method.charAt(0).toUpperCase() + method.slice(1)}`);
|
|
5159
|
+
return {
|
|
5160
|
+
title,
|
|
5161
|
+
value: method
|
|
5162
|
+
};
|
|
5163
|
+
});
|
|
5164
|
+
}
|
|
5165
|
+
async function selectInstallMethod(codeType, excludeMethods = []) {
|
|
5166
|
+
ensureI18nInitialized();
|
|
5167
|
+
const codeTypeName = codeType === "claude-code" ? i18n.t("common:claudeCode") : i18n.t("common:codex");
|
|
5168
|
+
const recommendedMethods = getRecommendedInstallMethods(codeType);
|
|
5169
|
+
const methodOptions = getInstallMethodOptions(codeType, recommendedMethods).filter((option) => !excludeMethods.includes(option.value));
|
|
5170
|
+
if (methodOptions.length === 0) {
|
|
5171
|
+
console.log(ansis.yellow(i18n.t("installation:noMoreMethods")));
|
|
5172
|
+
return null;
|
|
5173
|
+
}
|
|
5174
|
+
const response = await inquirer.prompt({
|
|
5175
|
+
type: "list",
|
|
5176
|
+
name: "method",
|
|
5177
|
+
message: i18n.t("installation:selectInstallMethod", { codeType: codeTypeName }),
|
|
5178
|
+
choices: methodOptions.map((opt) => ({
|
|
5179
|
+
name: opt.title,
|
|
5180
|
+
value: opt.value
|
|
5181
|
+
}))
|
|
5182
|
+
});
|
|
5183
|
+
return response.method || null;
|
|
5184
|
+
}
|
|
5185
|
+
async function executeInstallMethod(method, codeType) {
|
|
5186
|
+
ensureI18nInitialized();
|
|
5187
|
+
const codeTypeName = codeType === "claude-code" ? i18n.t("common:claudeCode") : i18n.t("common:codex");
|
|
5188
|
+
const spinner = ora(i18n.t("installation:installingWith", { method, codeType: codeTypeName })).start();
|
|
5189
|
+
try {
|
|
5190
|
+
switch (method) {
|
|
5191
|
+
case "npm": {
|
|
5192
|
+
const packageName = codeType === "claude-code" ? "@anthropic-ai/claude-code" : "@openai/codex";
|
|
5193
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", packageName]);
|
|
5194
|
+
if (usedSudo) {
|
|
5195
|
+
spinner.info(i18n.t("installation:usingSudo"));
|
|
5196
|
+
spinner.start();
|
|
5197
|
+
}
|
|
5198
|
+
await exec(command, args);
|
|
5199
|
+
await setInstallMethod("npm", codeType);
|
|
5200
|
+
break;
|
|
5201
|
+
}
|
|
5202
|
+
case "homebrew": {
|
|
5203
|
+
if (codeType === "claude-code") {
|
|
5204
|
+
await exec("brew", ["install", "--cask", "claude-code"]);
|
|
5205
|
+
} else {
|
|
5206
|
+
await exec("brew", ["install", "codex"]);
|
|
5207
|
+
}
|
|
5208
|
+
await setInstallMethod("homebrew", codeType);
|
|
5209
|
+
break;
|
|
5210
|
+
}
|
|
5211
|
+
case "curl": {
|
|
5212
|
+
if (codeType === "claude-code") {
|
|
5213
|
+
await exec("bash", ["-c", "curl -fsSL https://claude.ai/install.sh | bash"]);
|
|
5214
|
+
} else {
|
|
5215
|
+
spinner.stop();
|
|
5216
|
+
return await executeInstallMethod("npm", codeType);
|
|
5217
|
+
}
|
|
5218
|
+
await setInstallMethod("curl", codeType);
|
|
5219
|
+
break;
|
|
5220
|
+
}
|
|
5221
|
+
case "powershell": {
|
|
5222
|
+
if (codeType === "claude-code") {
|
|
5223
|
+
await exec("powershell", ["-Command", "irm https://claude.ai/install.ps1 | iex"]);
|
|
5224
|
+
} else {
|
|
5225
|
+
spinner.stop();
|
|
5226
|
+
return await executeInstallMethod("npm", codeType);
|
|
5227
|
+
}
|
|
5228
|
+
await setInstallMethod("powershell", codeType);
|
|
5229
|
+
break;
|
|
5230
|
+
}
|
|
5231
|
+
case "cmd": {
|
|
5232
|
+
if (codeType === "claude-code") {
|
|
5233
|
+
await exec("cmd", ["/c", "curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd"]);
|
|
5234
|
+
} else {
|
|
5235
|
+
spinner.stop();
|
|
5236
|
+
return await executeInstallMethod("npm", codeType);
|
|
5237
|
+
}
|
|
5238
|
+
await setInstallMethod("cmd", codeType);
|
|
5239
|
+
break;
|
|
5240
|
+
}
|
|
5241
|
+
default:
|
|
5242
|
+
throw new Error(`Unsupported install method: ${method}`);
|
|
5243
|
+
}
|
|
5244
|
+
spinner.succeed(i18n.t("installation:installMethodSuccess", { method }));
|
|
5245
|
+
return true;
|
|
4942
5246
|
} catch (error) {
|
|
4943
|
-
|
|
5247
|
+
spinner.fail(i18n.t("installation:installMethodFailed", { method }));
|
|
5248
|
+
if (error instanceof Error) {
|
|
5249
|
+
console.error(ansis.gray(error.message));
|
|
5250
|
+
}
|
|
5251
|
+
return false;
|
|
4944
5252
|
}
|
|
4945
5253
|
}
|
|
5254
|
+
async function handleInstallFailure(codeType, failedMethods) {
|
|
5255
|
+
ensureI18nInitialized();
|
|
5256
|
+
const response = await inquirer.prompt({
|
|
5257
|
+
type: "confirm",
|
|
5258
|
+
name: "retry",
|
|
5259
|
+
message: i18n.t("installation:tryAnotherMethod"),
|
|
5260
|
+
default: true
|
|
5261
|
+
});
|
|
5262
|
+
if (!response.retry) {
|
|
5263
|
+
return false;
|
|
5264
|
+
}
|
|
5265
|
+
const newMethod = await selectInstallMethod(codeType, failedMethods);
|
|
5266
|
+
if (!newMethod) {
|
|
5267
|
+
return false;
|
|
5268
|
+
}
|
|
5269
|
+
const success = await executeInstallMethod(newMethod, codeType);
|
|
5270
|
+
if (success) {
|
|
5271
|
+
return true;
|
|
5272
|
+
}
|
|
5273
|
+
return await handleInstallFailure(codeType, [...failedMethods, newMethod]);
|
|
5274
|
+
}
|
|
4946
5275
|
|
|
4947
5276
|
const installer = {
|
|
4948
5277
|
__proto__: null,
|
|
5278
|
+
detectInstalledVersion: detectInstalledVersion,
|
|
5279
|
+
executeInstallMethod: executeInstallMethod,
|
|
4949
5280
|
getInstallationStatus: getInstallationStatus,
|
|
5281
|
+
handleInstallFailure: handleInstallFailure,
|
|
4950
5282
|
installClaudeCode: installClaudeCode,
|
|
5283
|
+
installCodex: installCodex,
|
|
4951
5284
|
isClaudeCodeInstalled: isClaudeCodeInstalled,
|
|
5285
|
+
isCodexInstalled: isCodexInstalled,
|
|
4952
5286
|
isLocalClaudeCodeInstalled: isLocalClaudeCodeInstalled,
|
|
4953
5287
|
removeLocalClaudeCode: removeLocalClaudeCode,
|
|
4954
|
-
|
|
5288
|
+
selectInstallMethod: selectInstallMethod,
|
|
5289
|
+
setInstallMethod: setInstallMethod,
|
|
5290
|
+
uninstallCodeTool: uninstallCodeTool
|
|
4955
5291
|
};
|
|
4956
5292
|
|
|
4957
5293
|
async function chooseInstallationMethod() {
|
|
@@ -5521,7 +5857,7 @@ async function init(options = {}) {
|
|
|
5521
5857
|
if (installationStatus.hasLocal) {
|
|
5522
5858
|
if (!installationStatus.hasGlobal) {
|
|
5523
5859
|
console.log(ansis.blue(`${i18n.t("installation:installingGlobalClaudeCode")}...`));
|
|
5524
|
-
await installClaudeCode();
|
|
5860
|
+
await installClaudeCode(true);
|
|
5525
5861
|
console.log(ansis.green(`\u2714 ${i18n.t("installation:globalInstallationCompleted")}`));
|
|
5526
5862
|
}
|
|
5527
5863
|
if (installationStatus.hasGlobal && installationStatus.hasLocal) {
|
|
@@ -5535,20 +5871,14 @@ async function init(options = {}) {
|
|
|
5535
5871
|
}
|
|
5536
5872
|
} else {
|
|
5537
5873
|
if (options.skipPrompt) {
|
|
5538
|
-
await installClaudeCode();
|
|
5874
|
+
await installClaudeCode(true);
|
|
5539
5875
|
} else {
|
|
5540
|
-
const
|
|
5541
|
-
type: "confirm",
|
|
5542
|
-
name: "shouldInstall",
|
|
5876
|
+
const shouldInstall = await promptBoolean({
|
|
5543
5877
|
message: i18n.t("installation:installPrompt"),
|
|
5544
|
-
|
|
5878
|
+
defaultValue: true
|
|
5545
5879
|
});
|
|
5546
|
-
if (shouldInstall === void 0) {
|
|
5547
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
5548
|
-
process.exit(0);
|
|
5549
|
-
}
|
|
5550
5880
|
if (shouldInstall) {
|
|
5551
|
-
await installClaudeCode();
|
|
5881
|
+
await installClaudeCode(false);
|
|
5552
5882
|
} else {
|
|
5553
5883
|
console.log(ansis.yellow(i18n.t("common:skip")));
|
|
5554
5884
|
}
|
|
@@ -5753,16 +6083,10 @@ async function init(options = {}) {
|
|
|
5753
6083
|
if (options.skipPrompt) {
|
|
5754
6084
|
shouldConfigureMcp = options.mcpServices !== false;
|
|
5755
6085
|
} else {
|
|
5756
|
-
const
|
|
5757
|
-
type: "confirm",
|
|
5758
|
-
name: "shouldConfigureMcp",
|
|
6086
|
+
const userChoice = await promptBoolean({
|
|
5759
6087
|
message: i18n.t("mcp:configureMcp"),
|
|
5760
|
-
|
|
6088
|
+
defaultValue: true
|
|
5761
6089
|
});
|
|
5762
|
-
if (userChoice === void 0) {
|
|
5763
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
5764
|
-
process.exit(0);
|
|
5765
|
-
}
|
|
5766
6090
|
shouldConfigureMcp = userChoice;
|
|
5767
6091
|
}
|
|
5768
6092
|
if (shouldConfigureMcp) {
|
|
@@ -5838,16 +6162,10 @@ async function init(options = {}) {
|
|
|
5838
6162
|
if (options.skipPrompt) {
|
|
5839
6163
|
shouldInstallCometix = options.installCometixLine !== false;
|
|
5840
6164
|
} else {
|
|
5841
|
-
const
|
|
5842
|
-
type: "confirm",
|
|
5843
|
-
name: "shouldInstallCometix",
|
|
6165
|
+
const userChoice = await promptBoolean({
|
|
5844
6166
|
message: i18n.t("cometix:installCometixPrompt"),
|
|
5845
|
-
|
|
6167
|
+
defaultValue: true
|
|
5846
6168
|
});
|
|
5847
|
-
if (userChoice === void 0) {
|
|
5848
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
5849
|
-
process.exit(0);
|
|
5850
|
-
}
|
|
5851
6169
|
shouldInstallCometix = userChoice;
|
|
5852
6170
|
}
|
|
5853
6171
|
if (shouldInstallCometix) {
|
|
@@ -6134,4 +6452,4 @@ async function openSettingsJson() {
|
|
|
6134
6452
|
}
|
|
6135
6453
|
}
|
|
6136
6454
|
|
|
6137
|
-
export { getExistingModelConfig as $, API_DEFAULT_URL as A, getAiOutputLanguageLabel as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, getMcpConfigPath as E, readMcpConfig as F, writeMcpConfig as G, backupMcpConfig as H, mergeMcpServers as I, buildMcpServerConfig as J, fixWindowsMcpConfig as K, LEGACY_ZCF_CONFIG_FILES as L, addCompletedOnboarding as M, ensureApiKeyApproved as N, removeApiKeyFromRejected as O, manageApiKeyApproval as P, setPrimaryApiKey as Q, ensureClaudeDir as R, SETTINGS_FILE as S, backupExistingConfig as T, copyConfigFiles as U, configureApi as V, mergeConfigs as W, updateCustomModel as X, updateDefaultModel as Y, ZCF_CONFIG_DIR as Z, mergeSettingsFile as _, commandExists as a,
|
|
6455
|
+
export { getExistingModelConfig as $, API_DEFAULT_URL as A, getAiOutputLanguageLabel as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, getMcpConfigPath as E, readMcpConfig as F, writeMcpConfig as G, backupMcpConfig as H, mergeMcpServers as I, buildMcpServerConfig as J, fixWindowsMcpConfig as K, LEGACY_ZCF_CONFIG_FILES as L, addCompletedOnboarding as M, ensureApiKeyApproved as N, removeApiKeyFromRejected as O, manageApiKeyApproval as P, setPrimaryApiKey as Q, ensureClaudeDir as R, SETTINGS_FILE as S, backupExistingConfig as T, copyConfigFiles as U, configureApi as V, mergeConfigs as W, updateCustomModel as X, updateDefaultModel as Y, ZCF_CONFIG_DIR as Z, mergeSettingsFile as _, commandExists as a, displayBannerWithInfo as a$, getExistingApiConfig as a0, applyAiLanguageDirective as a1, switchToOfficialLogin$1 as a2, promptApiConfigurationAction as a3, isClaudeCodeInstalled as a4, installClaudeCode as a5, isCodexInstalled as a6, installCodex as a7, isLocalClaudeCodeInstalled as a8, getInstallationStatus as a9, readZcfConfig as aA, configureOutputStyle as aB, isWindows as aC, selectMcpServices as aD, getMcpServices as aE, isCcrInstalled as aF, installCcr as aG, setupCcrConfiguration as aH, modifyApiConfigPartially as aI, formatApiKeyDisplay as aJ, readCcrConfig as aK, configureCcrFeature as aL, handleExitPromptError as aM, handleGeneralError as aN, COMETIX_COMMAND_NAME as aO, COMETIX_COMMANDS as aP, installCometixLine as aQ, checkAndUpdateTools as aR, runCodexUpdate as aS, resolveCodeType as aT, writeJsonConfig as aU, displayBanner as aV, version as aW, resolveAiOutputLanguage as aX, updatePromptOnly as aY, selectAndInstallWorkflows as aZ, checkClaudeCodeVersionAndPrompt as a_, removeLocalClaudeCode as aa, uninstallCodeTool as ab, setInstallMethod as ac, detectInstalledVersion as ad, selectInstallMethod as ae, executeInstallMethod as af, handleInstallFailure as ag, ensureI18nInitialized as ah, i18n as ai, addNumbersToChoices as aj, validateApiKey as ak, promptBoolean as al, ensureDir as am, readDefaultTomlConfig as an, createDefaultTomlConfig as ao, exists as ap, readJsonConfig as aq, writeTomlConfig as ar, copyFile as as, detectConfigManagementMode as at, readCodexConfig as au, backupCodexComplete as av, writeCodexConfig as aw, writeAuthFile as ax, updateZcfConfig as ay, changeLanguage as az, importRecommendedEnv as b, runCodexUninstall as b0, configureCodexMcp as b1, configureCodexApi as b2, runCodexWorkflowImportWithLanguageSelection as b3, runCodexFullInit as b4, switchCodexProvider as b5, listCodexProviders as b6, switchToOfficialLogin as b7, switchToProvider as b8, readZcfConfigAsync as b9, initI18n as ba, selectScriptLanguage as bb, index as bc, fsOperations as bd, jsonConfig as be, claudeConfig as bf, config$1 as bg, config as bh, prompts as bi, codex as bj, installer as bk, cleanupPermissions as c, importRecommendedPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, CLAUDE_VSC_CONFIG_FILE as h, init as i, CODEX_DIR as j, CODEX_CONFIG_FILE as k, CODEX_AUTH_FILE as l, mergeAndCleanPermissions as m, CODEX_AGENTS_FILE as n, openSettingsJson as o, CODEX_PROMPTS_DIR as p, ZCF_CONFIG_FILE as q, CODE_TOOL_TYPES as r, CODE_TOOL_BANNERS as s, CODE_TOOL_ALIASES as t, isCodeToolType as u, API_ENV_KEY as v, resolveCodeToolType as w, SUPPORTED_LANGS as x, LANG_LABELS as y, AI_OUTPUT_LANGUAGES as z };
|