zcf 3.3.3 → 3.4.1
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 +19 -867
- 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 +679 -170
- package/dist/cli.mjs +46 -34
- package/dist/i18n/locales/en/codex.json +17 -3
- package/dist/i18n/locales/en/common.json +3 -1
- package/dist/i18n/locales/en/configuration.json +2 -0
- 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 +17 -3
- package/dist/i18n/locales/zh-CN/common.json +3 -1
- package/dist/i18n/locales/zh-CN/configuration.json +2 -0
- 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 +54 -8
- package/dist/index.d.ts +54 -8
- 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.1";
|
|
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")));
|
|
@@ -2119,7 +2150,7 @@ async function updateClaudeCode(force = false, skipPrompt = false) {
|
|
|
2119
2150
|
}
|
|
2120
2151
|
const updateSpinner = ora(format(i18n.t("updater:updating"), { tool: "Claude Code" })).start();
|
|
2121
2152
|
try {
|
|
2122
|
-
await execAsync$2("
|
|
2153
|
+
await execAsync$2("claude update");
|
|
2123
2154
|
updateSpinner.succeed(format(i18n.t("updater:updateSuccess"), { tool: "Claude Code" }));
|
|
2124
2155
|
return true;
|
|
2125
2156
|
} catch (error) {
|
|
@@ -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,57 @@ function getRootDir$1() {
|
|
|
3002
3007
|
}
|
|
3003
3008
|
return dirname(currentFilePath);
|
|
3004
3009
|
}
|
|
3005
|
-
async function
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3010
|
+
async function detectCodexInstallMethod() {
|
|
3011
|
+
try {
|
|
3012
|
+
const brewResult = await x("brew", ["list", "--cask", "codex"], { throwOnError: false });
|
|
3013
|
+
if (brewResult.exitCode === 0) {
|
|
3014
|
+
return "homebrew";
|
|
3015
|
+
}
|
|
3016
|
+
} catch {
|
|
3011
3017
|
}
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
+
try {
|
|
3019
|
+
const npmResult = await x("npm", ["list", "-g", "@openai/codex"], { throwOnError: false });
|
|
3020
|
+
if (npmResult.exitCode === 0 && npmResult.stdout.includes("@openai/codex")) {
|
|
3021
|
+
return "npm";
|
|
3022
|
+
}
|
|
3023
|
+
} catch {
|
|
3018
3024
|
}
|
|
3025
|
+
return "unknown";
|
|
3026
|
+
}
|
|
3027
|
+
async function executeCodexInstallation(isUpdate, skipMethodSelection = false) {
|
|
3019
3028
|
if (isUpdate) {
|
|
3029
|
+
console.log(ansis.cyan(i18n.t("codex:updatingCli")));
|
|
3030
|
+
const installMethod = await detectCodexInstallMethod();
|
|
3031
|
+
if (installMethod === "homebrew") {
|
|
3032
|
+
console.log(ansis.gray(i18n.t("codex:detectedHomebrew")));
|
|
3033
|
+
const result = await x("brew", ["upgrade", "--cask", "codex"]);
|
|
3034
|
+
if (result.exitCode !== 0) {
|
|
3035
|
+
throw new Error(`Failed to update codex via Homebrew: exit code ${result.exitCode}`);
|
|
3036
|
+
}
|
|
3037
|
+
} else if (installMethod === "npm") {
|
|
3038
|
+
console.log(ansis.gray(i18n.t("codex:detectedNpm")));
|
|
3039
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", "@openai/codex@latest"]);
|
|
3040
|
+
if (usedSudo)
|
|
3041
|
+
console.log(ansis.yellow(i18n.t("codex:usingSudo")));
|
|
3042
|
+
const result = await x(command, args);
|
|
3043
|
+
if (result.exitCode !== 0) {
|
|
3044
|
+
throw new Error(`Failed to update codex CLI: exit code ${result.exitCode}`);
|
|
3045
|
+
}
|
|
3046
|
+
} else {
|
|
3047
|
+
console.log(ansis.yellow(i18n.t("codex:unknownInstallMethod")));
|
|
3048
|
+
console.log(ansis.gray(i18n.t("codex:fallingBackToNpm")));
|
|
3049
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", "@openai/codex@latest"]);
|
|
3050
|
+
if (usedSudo)
|
|
3051
|
+
console.log(ansis.yellow(i18n.t("codex:usingSudo")));
|
|
3052
|
+
const result = await x(command, args);
|
|
3053
|
+
if (result.exitCode !== 0) {
|
|
3054
|
+
throw new Error(`Failed to update codex CLI: exit code ${result.exitCode}`);
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3020
3057
|
console.log(ansis.green(i18n.t("codex:updateSuccess")));
|
|
3021
3058
|
} else {
|
|
3022
|
-
|
|
3059
|
+
const { installCodex } = await Promise.resolve().then(function () { return installer; });
|
|
3060
|
+
await installCodex(skipMethodSelection);
|
|
3023
3061
|
}
|
|
3024
3062
|
}
|
|
3025
3063
|
function getUninstallOptions() {
|
|
@@ -3143,14 +3181,23 @@ function parseCodexConfig(content) {
|
|
|
3143
3181
|
}
|
|
3144
3182
|
const mcpServices = [];
|
|
3145
3183
|
if (tomlData.mcp_servers) {
|
|
3184
|
+
const KNOWN_MCP_FIELDS = /* @__PURE__ */ new Set(["command", "args", "env", "startup_timeout_ms"]);
|
|
3146
3185
|
for (const [id, mcpData] of Object.entries(tomlData.mcp_servers)) {
|
|
3147
3186
|
const mcp = mcpData;
|
|
3187
|
+
const extraFields = {};
|
|
3188
|
+
for (const [key, value] of Object.entries(mcp)) {
|
|
3189
|
+
if (!KNOWN_MCP_FIELDS.has(key)) {
|
|
3190
|
+
extraFields[key] = value;
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3148
3193
|
mcpServices.push({
|
|
3149
3194
|
id,
|
|
3150
3195
|
command: mcp.command || id,
|
|
3151
3196
|
args: mcp.args || [],
|
|
3152
3197
|
env: Object.keys(mcp.env || {}).length > 0 ? mcp.env : void 0,
|
|
3153
|
-
startup_timeout_ms: mcp.startup_timeout_ms
|
|
3198
|
+
startup_timeout_ms: mcp.startup_timeout_ms,
|
|
3199
|
+
// Only add extraFields if there are any extra fields
|
|
3200
|
+
extraFields: Object.keys(extraFields).length > 0 ? extraFields : void 0
|
|
3154
3201
|
});
|
|
3155
3202
|
}
|
|
3156
3203
|
}
|
|
@@ -3249,6 +3296,70 @@ function parseCodexConfig(content) {
|
|
|
3249
3296
|
};
|
|
3250
3297
|
}
|
|
3251
3298
|
}
|
|
3299
|
+
function formatInlineTableValue(value) {
|
|
3300
|
+
if (value === null || value === void 0) {
|
|
3301
|
+
return "";
|
|
3302
|
+
}
|
|
3303
|
+
if (typeof value === "string") {
|
|
3304
|
+
const normalized = normalizeTomlPath(value);
|
|
3305
|
+
return `'${normalized}'`;
|
|
3306
|
+
}
|
|
3307
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
3308
|
+
return String(value);
|
|
3309
|
+
}
|
|
3310
|
+
if (Array.isArray(value)) {
|
|
3311
|
+
const items = value.map((item) => {
|
|
3312
|
+
if (typeof item === "string") {
|
|
3313
|
+
const normalized = normalizeTomlPath(item);
|
|
3314
|
+
return `'${normalized}'`;
|
|
3315
|
+
}
|
|
3316
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
3317
|
+
return formatInlineTable(item);
|
|
3318
|
+
}
|
|
3319
|
+
return String(item);
|
|
3320
|
+
}).join(", ");
|
|
3321
|
+
return `[${items}]`;
|
|
3322
|
+
}
|
|
3323
|
+
if (typeof value === "object") {
|
|
3324
|
+
return formatInlineTable(value);
|
|
3325
|
+
}
|
|
3326
|
+
return String(value);
|
|
3327
|
+
}
|
|
3328
|
+
function formatInlineTable(obj) {
|
|
3329
|
+
const entries = Object.entries(obj).filter(([_, v]) => v !== null && v !== void 0).map(([k, v]) => `${k} = ${formatInlineTableValue(v)}`).join(", ");
|
|
3330
|
+
return `{${entries}}`;
|
|
3331
|
+
}
|
|
3332
|
+
function formatTomlField(key, value) {
|
|
3333
|
+
if (value === null || value === void 0) {
|
|
3334
|
+
return "";
|
|
3335
|
+
}
|
|
3336
|
+
if (typeof value === "string") {
|
|
3337
|
+
const normalized = normalizeTomlPath(value);
|
|
3338
|
+
const escaped = normalized.replace(/"/g, '\\"');
|
|
3339
|
+
return `${key} = "${escaped}"`;
|
|
3340
|
+
}
|
|
3341
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
3342
|
+
return `${key} = ${value}`;
|
|
3343
|
+
}
|
|
3344
|
+
if (Array.isArray(value)) {
|
|
3345
|
+
const items = value.map((item) => {
|
|
3346
|
+
if (typeof item === "string") {
|
|
3347
|
+
const normalized = normalizeTomlPath(item);
|
|
3348
|
+
const escaped = normalized.replace(/"/g, '\\"');
|
|
3349
|
+
return `"${escaped}"`;
|
|
3350
|
+
}
|
|
3351
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
3352
|
+
return formatInlineTable(item);
|
|
3353
|
+
}
|
|
3354
|
+
return String(item);
|
|
3355
|
+
}).join(", ");
|
|
3356
|
+
return `${key} = [${items}]`;
|
|
3357
|
+
}
|
|
3358
|
+
if (typeof value === "object") {
|
|
3359
|
+
return `${key} = ${formatInlineTable(value)}`;
|
|
3360
|
+
}
|
|
3361
|
+
return "";
|
|
3362
|
+
}
|
|
3252
3363
|
function readCodexConfig() {
|
|
3253
3364
|
if (!exists(CODEX_CONFIG_FILE))
|
|
3254
3365
|
return null;
|
|
@@ -3317,16 +3428,25 @@ function renderCodexConfig(data) {
|
|
|
3317
3428
|
lines.push("# --- MCP servers added by ZCF ---");
|
|
3318
3429
|
for (const service of data.mcpServices) {
|
|
3319
3430
|
lines.push(`[mcp_servers.${service.id}]`);
|
|
3320
|
-
|
|
3431
|
+
const normalizedCommand = normalizeTomlPath(service.command);
|
|
3432
|
+
lines.push(`command = "${normalizedCommand}"`);
|
|
3321
3433
|
const argsString = service.args.length > 0 ? service.args.map((arg) => `"${arg}"`).join(", ") : "";
|
|
3322
3434
|
lines.push(`args = [${argsString}]`);
|
|
3323
3435
|
if (service.env && Object.keys(service.env).length > 0) {
|
|
3324
|
-
const envEntries = Object.entries(service.env).map(([key, value]) => `${key} =
|
|
3436
|
+
const envEntries = Object.entries(service.env).map(([key, value]) => `${key} = '${value}'`).join(", ");
|
|
3325
3437
|
lines.push(`env = {${envEntries}}`);
|
|
3326
3438
|
}
|
|
3327
3439
|
if (service.startup_timeout_ms) {
|
|
3328
3440
|
lines.push(`startup_timeout_ms = ${service.startup_timeout_ms}`);
|
|
3329
3441
|
}
|
|
3442
|
+
if (service.extraFields) {
|
|
3443
|
+
for (const [key, value] of Object.entries(service.extraFields)) {
|
|
3444
|
+
const formatted = formatTomlField(key, value);
|
|
3445
|
+
if (formatted) {
|
|
3446
|
+
lines.push(formatted);
|
|
3447
|
+
}
|
|
3448
|
+
}
|
|
3449
|
+
}
|
|
3330
3450
|
lines.push("");
|
|
3331
3451
|
}
|
|
3332
3452
|
if (lines[lines.length - 1] === "") {
|
|
@@ -3349,28 +3469,48 @@ function writeAuthFile(newEntries) {
|
|
|
3349
3469
|
const merged = { ...existing, ...newEntries };
|
|
3350
3470
|
writeJsonConfig(CODEX_AUTH_FILE, merged, { pretty: true });
|
|
3351
3471
|
}
|
|
3352
|
-
async function isCodexInstalled() {
|
|
3472
|
+
async function isCodexInstalled$1() {
|
|
3353
3473
|
try {
|
|
3354
|
-
const
|
|
3355
|
-
if (
|
|
3356
|
-
return
|
|
3474
|
+
const npmResult = await x("npm", ["list", "-g", "--depth=0"]);
|
|
3475
|
+
if (npmResult.exitCode === 0 && npmResult.stdout.includes("@openai/codex@")) {
|
|
3476
|
+
return true;
|
|
3477
|
+
}
|
|
3478
|
+
} catch {
|
|
3479
|
+
}
|
|
3480
|
+
try {
|
|
3481
|
+
const brewResult = await x("brew", ["list", "--cask", "codex"], { throwOnError: false });
|
|
3482
|
+
if (brewResult.exitCode === 0) {
|
|
3483
|
+
return true;
|
|
3357
3484
|
}
|
|
3358
|
-
return result.stdout.includes("@openai/codex@");
|
|
3359
3485
|
} catch {
|
|
3360
|
-
return false;
|
|
3361
3486
|
}
|
|
3487
|
+
return false;
|
|
3362
3488
|
}
|
|
3363
3489
|
async function getCodexVersion() {
|
|
3364
3490
|
try {
|
|
3365
|
-
const
|
|
3366
|
-
if (
|
|
3367
|
-
|
|
3491
|
+
const npmResult = await x("npm", ["list", "-g", "--depth=0"]);
|
|
3492
|
+
if (npmResult.exitCode === 0) {
|
|
3493
|
+
const match = npmResult.stdout.match(/@openai\/codex@(\S+)/);
|
|
3494
|
+
if (match) {
|
|
3495
|
+
return match[1];
|
|
3496
|
+
}
|
|
3497
|
+
}
|
|
3498
|
+
} catch {
|
|
3499
|
+
}
|
|
3500
|
+
try {
|
|
3501
|
+
const brewResult = await x("brew", ["info", "--cask", "codex", "--json=v2"], { throwOnError: false });
|
|
3502
|
+
if (brewResult.exitCode === 0) {
|
|
3503
|
+
const info = JSON.parse(brewResult.stdout);
|
|
3504
|
+
if (info.casks && Array.isArray(info.casks) && info.casks.length > 0) {
|
|
3505
|
+
const cask = info.casks[0];
|
|
3506
|
+
if (cask.installed && typeof cask.installed === "string") {
|
|
3507
|
+
return cask.installed;
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3368
3510
|
}
|
|
3369
|
-
const match = result.stdout.match(/@openai\/codex@(\S+)/);
|
|
3370
|
-
return match ? match[1] : null;
|
|
3371
3511
|
} catch {
|
|
3372
|
-
return null;
|
|
3373
3512
|
}
|
|
3513
|
+
return null;
|
|
3374
3514
|
}
|
|
3375
3515
|
async function checkCodexUpdate() {
|
|
3376
3516
|
try {
|
|
@@ -3418,19 +3558,19 @@ async function checkCodexUpdate() {
|
|
|
3418
3558
|
};
|
|
3419
3559
|
}
|
|
3420
3560
|
}
|
|
3421
|
-
async function installCodexCli() {
|
|
3561
|
+
async function installCodexCli(skipMethodSelection = false) {
|
|
3422
3562
|
ensureI18nInitialized();
|
|
3423
|
-
if (await isCodexInstalled()) {
|
|
3563
|
+
if (await isCodexInstalled$1()) {
|
|
3424
3564
|
const { needsUpdate } = await checkCodexUpdate();
|
|
3425
3565
|
if (needsUpdate) {
|
|
3426
|
-
await executeCodexInstallation(true);
|
|
3566
|
+
await executeCodexInstallation(true, skipMethodSelection);
|
|
3427
3567
|
return;
|
|
3428
3568
|
} else {
|
|
3429
3569
|
console.log(ansis.yellow(i18n.t("codex:alreadyInstalled")));
|
|
3430
3570
|
return;
|
|
3431
3571
|
}
|
|
3432
3572
|
}
|
|
3433
|
-
await executeCodexInstallation(false);
|
|
3573
|
+
await executeCodexInstallation(false, skipMethodSelection);
|
|
3434
3574
|
}
|
|
3435
3575
|
async function runCodexWorkflowImportWithLanguageSelection(options) {
|
|
3436
3576
|
ensureI18nInitialized();
|
|
@@ -3874,15 +4014,13 @@ async function configureCodexApi(options) {
|
|
|
3874
4014
|
if (existingProvider || sessionProvider) {
|
|
3875
4015
|
const sourceType = existingProvider ? "existing" : "session";
|
|
3876
4016
|
const sourceProvider = existingProvider || sessionProvider;
|
|
3877
|
-
const
|
|
3878
|
-
type: "confirm",
|
|
3879
|
-
name: "shouldOverwrite",
|
|
4017
|
+
const shouldOverwrite = await promptBoolean({
|
|
3880
4018
|
message: i18n.t("codex:providerDuplicatePrompt", {
|
|
3881
4019
|
name: sourceProvider.name,
|
|
3882
4020
|
source: sourceType === "existing" ? i18n.t("codex:existingConfig") : i18n.t("codex:currentSession")
|
|
3883
4021
|
}),
|
|
3884
|
-
|
|
3885
|
-
}
|
|
4022
|
+
defaultValue: false
|
|
4023
|
+
});
|
|
3886
4024
|
if (!shouldOverwrite) {
|
|
3887
4025
|
console.log(ansis.yellow(i18n.t("codex:providerDuplicateSkipped")));
|
|
3888
4026
|
continue;
|
|
@@ -3908,12 +4046,10 @@ async function configureCodexApi(options) {
|
|
|
3908
4046
|
providers.push(newProvider);
|
|
3909
4047
|
currentSessionProviders.set(providerId, newProvider);
|
|
3910
4048
|
authEntries[envKey] = answers.apiKey;
|
|
3911
|
-
const
|
|
3912
|
-
type: "confirm",
|
|
3913
|
-
name: "addAnother",
|
|
4049
|
+
const addAnother = await promptBoolean({
|
|
3914
4050
|
message: i18n.t("codex:addProviderPrompt"),
|
|
3915
|
-
|
|
3916
|
-
}
|
|
4051
|
+
defaultValue: false
|
|
4052
|
+
});
|
|
3917
4053
|
addMore = addAnother;
|
|
3918
4054
|
}
|
|
3919
4055
|
if (providers.length === 0) {
|
|
@@ -3947,7 +4083,7 @@ async function configureCodexApi(options) {
|
|
|
3947
4083
|
}
|
|
3948
4084
|
async function runCodexFullInit(options) {
|
|
3949
4085
|
ensureI18nInitialized();
|
|
3950
|
-
await installCodexCli();
|
|
4086
|
+
await installCodexCli(options?.skipPrompt || false);
|
|
3951
4087
|
const aiOutputLang = await runCodexWorkflowImportWithLanguageSelection(options);
|
|
3952
4088
|
await configureCodexApi(options);
|
|
3953
4089
|
await configureCodexMcp(options);
|
|
@@ -4012,11 +4148,9 @@ async function runCodexUpdate(force = false, skipPrompt = false) {
|
|
|
4012
4148
|
console.log(ansis.cyan(format(i18n.t("codex:currentVersion"), { version: currentVersion || "" })));
|
|
4013
4149
|
console.log(ansis.cyan(format(i18n.t("codex:latestVersion"), { version: latestVersion })));
|
|
4014
4150
|
if (!skipPrompt) {
|
|
4015
|
-
const
|
|
4016
|
-
type: "confirm",
|
|
4017
|
-
name: "confirm",
|
|
4151
|
+
const confirm = await promptBoolean({
|
|
4018
4152
|
message: i18n.t("codex:confirmUpdate"),
|
|
4019
|
-
|
|
4153
|
+
defaultValue: true
|
|
4020
4154
|
});
|
|
4021
4155
|
if (!confirm) {
|
|
4022
4156
|
console.log(ansis.gray(i18n.t("codex:updateSkipped")));
|
|
@@ -4064,12 +4198,10 @@ async function runCodexUninstall() {
|
|
|
4064
4198
|
}
|
|
4065
4199
|
try {
|
|
4066
4200
|
if (mode === "complete") {
|
|
4067
|
-
const
|
|
4068
|
-
type: "confirm",
|
|
4069
|
-
name: "confirm",
|
|
4201
|
+
const confirm = await promptBoolean({
|
|
4070
4202
|
message: i18n.t("codex:uninstallPrompt"),
|
|
4071
|
-
|
|
4072
|
-
}
|
|
4203
|
+
defaultValue: false
|
|
4204
|
+
});
|
|
4073
4205
|
if (!confirm) {
|
|
4074
4206
|
handleUninstallCancellation();
|
|
4075
4207
|
return;
|
|
@@ -4246,7 +4378,7 @@ const codex = {
|
|
|
4246
4378
|
getBackupMessage: getBackupMessage,
|
|
4247
4379
|
getCodexVersion: getCodexVersion,
|
|
4248
4380
|
installCodexCli: installCodexCli,
|
|
4249
|
-
isCodexInstalled: isCodexInstalled,
|
|
4381
|
+
isCodexInstalled: isCodexInstalled$1,
|
|
4250
4382
|
listCodexProviders: listCodexProviders,
|
|
4251
4383
|
parseCodexConfig: parseCodexConfig,
|
|
4252
4384
|
readCodexConfig: readCodexConfig,
|
|
@@ -4528,11 +4660,9 @@ async function configureOutputStyle(preselectedStyles, preselectedDefault) {
|
|
|
4528
4660
|
const availableStyles = getAvailableOutputStyles();
|
|
4529
4661
|
if (hasLegacyPersonalityFiles() && !preselectedStyles) {
|
|
4530
4662
|
console.log(ansis.yellow(`\u26A0\uFE0F ${i18n.t("configuration:legacyFilesDetected")}`));
|
|
4531
|
-
const
|
|
4532
|
-
type: "confirm",
|
|
4533
|
-
name: "cleanupLegacy",
|
|
4663
|
+
const cleanupLegacy = await promptBoolean({
|
|
4534
4664
|
message: i18n.t("configuration:cleanupLegacyFiles"),
|
|
4535
|
-
|
|
4665
|
+
defaultValue: true
|
|
4536
4666
|
});
|
|
4537
4667
|
if (cleanupLegacy) {
|
|
4538
4668
|
cleanupLegacyPersonalityFiles();
|
|
@@ -4827,7 +4957,9 @@ ${ansis.cyan(i18n.t("common:complete"))}`);
|
|
|
4827
4957
|
}
|
|
4828
4958
|
|
|
4829
4959
|
function handleExitPromptError(error) {
|
|
4830
|
-
|
|
4960
|
+
const isExitError = error instanceof Error && (error.name === "ExitPromptError" || error.message?.includes("ExitPromptError") || error.message?.includes("User force closed the prompt"));
|
|
4961
|
+
if (isExitError) {
|
|
4962
|
+
ensureI18nInitialized();
|
|
4831
4963
|
console.log(ansis.cyan(`
|
|
4832
4964
|
${i18n.t("common:goodbye")}
|
|
4833
4965
|
`));
|
|
@@ -4847,13 +4979,17 @@ function handleGeneralError(error) {
|
|
|
4847
4979
|
async function isClaudeCodeInstalled() {
|
|
4848
4980
|
return await commandExists("claude");
|
|
4849
4981
|
}
|
|
4850
|
-
async function installClaudeCode() {
|
|
4982
|
+
async function installClaudeCode(skipMethodSelection = false) {
|
|
4851
4983
|
ensureI18nInitialized();
|
|
4984
|
+
const codeType = "claude-code";
|
|
4852
4985
|
const installed = await isClaudeCodeInstalled();
|
|
4853
4986
|
if (installed) {
|
|
4854
4987
|
console.log(ansis.green(`\u2714 ${i18n.t("installation:alreadyInstalled")}`));
|
|
4988
|
+
const version = await detectInstalledVersion(codeType);
|
|
4989
|
+
if (version) {
|
|
4990
|
+
console.log(ansis.gray(` ${i18n.t("installation:detectedVersion", { version })}`));
|
|
4991
|
+
}
|
|
4855
4992
|
await updateClaudeCode();
|
|
4856
|
-
await setInstallMethod("npm");
|
|
4857
4993
|
return;
|
|
4858
4994
|
}
|
|
4859
4995
|
if (isTermux()) {
|
|
@@ -4872,31 +5008,100 @@ async function installClaudeCode() {
|
|
|
4872
5008
|
}
|
|
4873
5009
|
console.log(ansis.gray(i18n.t("installation:wslPathInfo", { path: `${homedir()}/.claude/` })));
|
|
4874
5010
|
}
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
5011
|
+
if (skipMethodSelection) {
|
|
5012
|
+
console.log(i18n.t("installation:installing"));
|
|
5013
|
+
try {
|
|
5014
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", "@anthropic-ai/claude-code"]);
|
|
5015
|
+
if (usedSudo) {
|
|
5016
|
+
console.log(ansis.yellow(`\u2139 ${i18n.t("installation:usingSudo")}`));
|
|
5017
|
+
}
|
|
5018
|
+
await exec(command, args);
|
|
5019
|
+
console.log(`\u2714 ${i18n.t("installation:installSuccess")}`);
|
|
5020
|
+
await setInstallMethod("npm");
|
|
5021
|
+
if (isTermux()) {
|
|
5022
|
+
console.log(ansis.gray(`
|
|
4886
5023
|
Claude Code installed to: ${getTermuxPrefix()}/bin/claude`));
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
5024
|
+
}
|
|
5025
|
+
if (isWSL()) {
|
|
5026
|
+
console.log(ansis.gray(`
|
|
4890
5027
|
${i18n.t("installation:wslInstallSuccess")}`));
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
5028
|
+
}
|
|
5029
|
+
} catch (error) {
|
|
5030
|
+
console.error(`\u2716 ${i18n.t("installation:installFailed")}`);
|
|
5031
|
+
if (isTermux()) {
|
|
5032
|
+
console.error(ansis.yellow(`
|
|
4896
5033
|
${i18n.t("installation:termuxInstallHint")}
|
|
4897
5034
|
`));
|
|
5035
|
+
}
|
|
5036
|
+
throw error;
|
|
5037
|
+
}
|
|
5038
|
+
return;
|
|
5039
|
+
}
|
|
5040
|
+
const method = await selectInstallMethod(codeType);
|
|
5041
|
+
if (!method) {
|
|
5042
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
5043
|
+
return;
|
|
5044
|
+
}
|
|
5045
|
+
const success = await executeInstallMethod(method, codeType);
|
|
5046
|
+
if (!success) {
|
|
5047
|
+
const retrySuccess = await handleInstallFailure(codeType, [method]);
|
|
5048
|
+
if (!retrySuccess) {
|
|
5049
|
+
console.error(ansis.red(`\u2716 ${i18n.t("installation:installFailed")}`));
|
|
5050
|
+
throw new Error(i18n.t("installation:installFailed"));
|
|
5051
|
+
}
|
|
5052
|
+
}
|
|
5053
|
+
if (isTermux()) {
|
|
5054
|
+
console.log(ansis.gray(`
|
|
5055
|
+
Claude Code installed to: ${getTermuxPrefix()}/bin/claude`));
|
|
5056
|
+
}
|
|
5057
|
+
if (isWSL()) {
|
|
5058
|
+
console.log(ansis.gray(`
|
|
5059
|
+
${i18n.t("installation:wslInstallSuccess")}`));
|
|
5060
|
+
}
|
|
5061
|
+
}
|
|
5062
|
+
async function isCodexInstalled() {
|
|
5063
|
+
return await commandExists("codex");
|
|
5064
|
+
}
|
|
5065
|
+
async function installCodex(skipMethodSelection = false) {
|
|
5066
|
+
ensureI18nInitialized();
|
|
5067
|
+
const codeType = "codex";
|
|
5068
|
+
const codeTypeName = i18n.t("common:codex");
|
|
5069
|
+
const installed = await isCodexInstalled();
|
|
5070
|
+
if (installed) {
|
|
5071
|
+
console.log(ansis.green(`\u2714 ${codeTypeName} ${i18n.t("installation:alreadyInstalled")}`));
|
|
5072
|
+
const version = await detectInstalledVersion(codeType);
|
|
5073
|
+
if (version) {
|
|
5074
|
+
console.log(ansis.gray(` ${i18n.t("installation:detectedVersion", { version })}`));
|
|
5075
|
+
}
|
|
5076
|
+
return;
|
|
5077
|
+
}
|
|
5078
|
+
if (skipMethodSelection) {
|
|
5079
|
+
console.log(i18n.t("installation:installingWith", { method: "npm", codeType: codeTypeName }));
|
|
5080
|
+
try {
|
|
5081
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", "@openai/codex"]);
|
|
5082
|
+
if (usedSudo) {
|
|
5083
|
+
console.log(ansis.yellow(`\u2139 ${i18n.t("installation:usingSudo")}`));
|
|
5084
|
+
}
|
|
5085
|
+
await exec(command, args);
|
|
5086
|
+
console.log(ansis.green(`\u2714 ${codeTypeName} ${i18n.t("installation:installSuccess")}`));
|
|
5087
|
+
} catch (error) {
|
|
5088
|
+
console.error(ansis.red(`\u2716 ${codeTypeName} ${i18n.t("installation:installFailed")}`));
|
|
5089
|
+
throw error;
|
|
5090
|
+
}
|
|
5091
|
+
return;
|
|
5092
|
+
}
|
|
5093
|
+
const method = await selectInstallMethod(codeType);
|
|
5094
|
+
if (!method) {
|
|
5095
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
5096
|
+
return;
|
|
5097
|
+
}
|
|
5098
|
+
const success = await executeInstallMethod(method, codeType);
|
|
5099
|
+
if (!success) {
|
|
5100
|
+
const retrySuccess = await handleInstallFailure(codeType, [method]);
|
|
5101
|
+
if (!retrySuccess) {
|
|
5102
|
+
console.error(ansis.red(`\u2716 ${codeTypeName} ${i18n.t("installation:installFailed")}`));
|
|
5103
|
+
throw new Error(i18n.t("installation:installFailed"));
|
|
4898
5104
|
}
|
|
4899
|
-
throw error;
|
|
4900
5105
|
}
|
|
4901
5106
|
}
|
|
4902
5107
|
async function isLocalClaudeCodeInstalled() {
|
|
@@ -4930,28 +5135,298 @@ async function removeLocalClaudeCode() {
|
|
|
4930
5135
|
throw new Error(`${i18n.t("installation:failedToRemoveLocalInstallation")}: ${error}`);
|
|
4931
5136
|
}
|
|
4932
5137
|
}
|
|
4933
|
-
async function
|
|
5138
|
+
async function getInstallMethodFromConfig(codeType) {
|
|
4934
5139
|
try {
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
config
|
|
5140
|
+
if (codeType === "claude-code") {
|
|
5141
|
+
const { readMcpConfig } = await Promise.resolve().then(function () { return claudeConfig; });
|
|
5142
|
+
const config = readMcpConfig();
|
|
5143
|
+
return config?.installMethod || null;
|
|
4939
5144
|
}
|
|
4940
|
-
|
|
4941
|
-
|
|
5145
|
+
} catch {
|
|
5146
|
+
}
|
|
5147
|
+
return null;
|
|
5148
|
+
}
|
|
5149
|
+
async function uninstallCodeTool(codeType) {
|
|
5150
|
+
ensureI18nInitialized();
|
|
5151
|
+
const codeTypeName = codeType === "claude-code" ? i18n.t("common:claudeCode") : i18n.t("common:codex");
|
|
5152
|
+
let method = await getInstallMethodFromConfig(codeType);
|
|
5153
|
+
if (!method) {
|
|
5154
|
+
if (codeType === "claude-code") {
|
|
5155
|
+
try {
|
|
5156
|
+
const result = await exec("brew", ["list", "--cask", "claude-code"]);
|
|
5157
|
+
if (result.exitCode === 0) {
|
|
5158
|
+
method = "homebrew";
|
|
5159
|
+
}
|
|
5160
|
+
} catch {
|
|
5161
|
+
}
|
|
5162
|
+
} else if (codeType === "codex") {
|
|
5163
|
+
try {
|
|
5164
|
+
const result = await exec("brew", ["list", "codex"]);
|
|
5165
|
+
if (result.exitCode === 0) {
|
|
5166
|
+
method = "homebrew";
|
|
5167
|
+
}
|
|
5168
|
+
} catch {
|
|
5169
|
+
}
|
|
5170
|
+
}
|
|
5171
|
+
if (!method) {
|
|
5172
|
+
method = "npm";
|
|
5173
|
+
}
|
|
5174
|
+
}
|
|
5175
|
+
if (method === "native") {
|
|
5176
|
+
const platform = getPlatform();
|
|
5177
|
+
if (platform === "macos" || platform === "linux") {
|
|
5178
|
+
try {
|
|
5179
|
+
const testResult = codeType === "claude-code" ? await exec("brew", ["list", "--cask", "claude-code"]) : await exec("brew", ["list", "codex"]);
|
|
5180
|
+
if (testResult.exitCode === 0) {
|
|
5181
|
+
method = "homebrew";
|
|
5182
|
+
}
|
|
5183
|
+
} catch {
|
|
5184
|
+
method = "manual";
|
|
5185
|
+
}
|
|
5186
|
+
} else {
|
|
5187
|
+
method = "manual";
|
|
5188
|
+
}
|
|
5189
|
+
}
|
|
5190
|
+
const spinner = ora(i18n.t("installation:uninstallingWith", { method, codeType: codeTypeName })).start();
|
|
5191
|
+
try {
|
|
5192
|
+
switch (method) {
|
|
5193
|
+
case "npm":
|
|
5194
|
+
case "npm-global": {
|
|
5195
|
+
const packageName = codeType === "claude-code" ? "@anthropic-ai/claude-code" : "@openai/codex";
|
|
5196
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["uninstall", "-g", packageName]);
|
|
5197
|
+
if (usedSudo) {
|
|
5198
|
+
spinner.info(i18n.t("installation:usingSudo"));
|
|
5199
|
+
spinner.start();
|
|
5200
|
+
}
|
|
5201
|
+
await exec(command, args);
|
|
5202
|
+
break;
|
|
5203
|
+
}
|
|
5204
|
+
case "homebrew": {
|
|
5205
|
+
if (codeType === "claude-code") {
|
|
5206
|
+
await exec("brew", ["uninstall", "--cask", "claude-code"]);
|
|
5207
|
+
} else {
|
|
5208
|
+
await exec("brew", ["uninstall", "codex"]);
|
|
5209
|
+
}
|
|
5210
|
+
break;
|
|
5211
|
+
}
|
|
5212
|
+
case "manual":
|
|
5213
|
+
default: {
|
|
5214
|
+
spinner.warn(i18n.t("installation:manualUninstallRequired", { codeType: codeTypeName }));
|
|
5215
|
+
const command = codeType === "claude-code" ? "claude" : "codex";
|
|
5216
|
+
try {
|
|
5217
|
+
const whichCmd = getPlatform() === "windows" ? "where" : "which";
|
|
5218
|
+
const result = await exec(whichCmd, [command]);
|
|
5219
|
+
if (result.stdout) {
|
|
5220
|
+
const binaryPath = result.stdout.trim().split("\n")[0];
|
|
5221
|
+
spinner.info(i18n.t("installation:binaryLocation", { path: binaryPath }));
|
|
5222
|
+
const platform = getPlatform();
|
|
5223
|
+
if (platform === "windows") {
|
|
5224
|
+
const quotedBinaryPath = `"${binaryPath}"`;
|
|
5225
|
+
await exec("cmd", ["/c", "del", "/f", "/q", quotedBinaryPath]);
|
|
5226
|
+
} else {
|
|
5227
|
+
const { command: rmCmd, args: rmArgs } = wrapCommandWithSudo("rm", ["-f", binaryPath]);
|
|
5228
|
+
if (rmCmd === "sudo") {
|
|
5229
|
+
spinner.info(i18n.t("installation:usingSudo"));
|
|
5230
|
+
spinner.start();
|
|
5231
|
+
}
|
|
5232
|
+
await exec(rmCmd, rmArgs);
|
|
5233
|
+
}
|
|
5234
|
+
}
|
|
5235
|
+
} catch {
|
|
5236
|
+
spinner.fail(i18n.t("installation:failedToLocateBinary", { command }));
|
|
5237
|
+
return false;
|
|
5238
|
+
}
|
|
5239
|
+
break;
|
|
5240
|
+
}
|
|
5241
|
+
}
|
|
5242
|
+
spinner.succeed(i18n.t("installation:uninstallSuccess", { method, codeType: codeTypeName }));
|
|
5243
|
+
return true;
|
|
5244
|
+
} catch (error) {
|
|
5245
|
+
spinner.fail(i18n.t("installation:uninstallFailed", { method, codeType: codeTypeName }));
|
|
5246
|
+
if (error instanceof Error) {
|
|
5247
|
+
console.error(ansis.gray(error.message));
|
|
5248
|
+
}
|
|
5249
|
+
return false;
|
|
5250
|
+
}
|
|
5251
|
+
}
|
|
5252
|
+
async function setInstallMethod(method, codeType = "claude-code") {
|
|
5253
|
+
try {
|
|
5254
|
+
if (codeType === "claude-code") {
|
|
5255
|
+
const { readMcpConfig, writeMcpConfig } = await Promise.resolve().then(function () { return claudeConfig; });
|
|
5256
|
+
let config = readMcpConfig();
|
|
5257
|
+
if (!config) {
|
|
5258
|
+
config = { mcpServers: {} };
|
|
5259
|
+
}
|
|
5260
|
+
config.installMethod = method === "npm" ? "npm-global" : method;
|
|
5261
|
+
writeMcpConfig(config);
|
|
5262
|
+
}
|
|
5263
|
+
} catch (error) {
|
|
5264
|
+
console.error("Failed to set installMethod:", error);
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5267
|
+
async function detectInstalledVersion(codeType) {
|
|
5268
|
+
try {
|
|
5269
|
+
const command = codeType === "claude-code" ? "claude" : "codex";
|
|
5270
|
+
const result = await exec(command, ["--version"]);
|
|
5271
|
+
if (result.exitCode === 0 && result.stdout) {
|
|
5272
|
+
const versionMatch = result.stdout.match(/(\d+\.\d+\.\d+)/);
|
|
5273
|
+
return versionMatch ? versionMatch[1] : result.stdout.trim();
|
|
5274
|
+
}
|
|
5275
|
+
} catch {
|
|
5276
|
+
}
|
|
5277
|
+
return null;
|
|
5278
|
+
}
|
|
5279
|
+
function getInstallMethodOptions(codeType, recommendedMethods) {
|
|
5280
|
+
const allMethods = ["npm", "homebrew", "curl", "powershell", "cmd"];
|
|
5281
|
+
const platform = getPlatform();
|
|
5282
|
+
const availableMethods = allMethods.filter((method) => {
|
|
5283
|
+
if (codeType === "codex" && !["npm", "homebrew"].includes(method)) {
|
|
5284
|
+
return false;
|
|
5285
|
+
}
|
|
5286
|
+
if (method === "homebrew")
|
|
5287
|
+
return platform === "macos" || platform === "linux";
|
|
5288
|
+
if (method === "curl")
|
|
5289
|
+
return platform !== "windows" || isWSL();
|
|
5290
|
+
if (method === "powershell" || method === "cmd")
|
|
5291
|
+
return platform === "windows";
|
|
5292
|
+
return true;
|
|
5293
|
+
});
|
|
5294
|
+
const topRecommended = recommendedMethods.length > 0 ? recommendedMethods[0] : null;
|
|
5295
|
+
return availableMethods.map((method) => {
|
|
5296
|
+
const isTopRecommended = method === topRecommended;
|
|
5297
|
+
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)}`);
|
|
5298
|
+
return {
|
|
5299
|
+
title,
|
|
5300
|
+
value: method
|
|
5301
|
+
};
|
|
5302
|
+
});
|
|
5303
|
+
}
|
|
5304
|
+
async function selectInstallMethod(codeType, excludeMethods = []) {
|
|
5305
|
+
ensureI18nInitialized();
|
|
5306
|
+
const codeTypeName = codeType === "claude-code" ? i18n.t("common:claudeCode") : i18n.t("common:codex");
|
|
5307
|
+
const recommendedMethods = getRecommendedInstallMethods(codeType);
|
|
5308
|
+
const methodOptions = getInstallMethodOptions(codeType, recommendedMethods).filter((option) => !excludeMethods.includes(option.value));
|
|
5309
|
+
if (methodOptions.length === 0) {
|
|
5310
|
+
console.log(ansis.yellow(i18n.t("installation:noMoreMethods")));
|
|
5311
|
+
return null;
|
|
5312
|
+
}
|
|
5313
|
+
const response = await inquirer.prompt({
|
|
5314
|
+
type: "list",
|
|
5315
|
+
name: "method",
|
|
5316
|
+
message: i18n.t("installation:selectInstallMethod", { codeType: codeTypeName }),
|
|
5317
|
+
choices: methodOptions.map((opt) => ({
|
|
5318
|
+
name: opt.title,
|
|
5319
|
+
value: opt.value
|
|
5320
|
+
}))
|
|
5321
|
+
});
|
|
5322
|
+
return response.method || null;
|
|
5323
|
+
}
|
|
5324
|
+
async function executeInstallMethod(method, codeType) {
|
|
5325
|
+
ensureI18nInitialized();
|
|
5326
|
+
const codeTypeName = codeType === "claude-code" ? i18n.t("common:claudeCode") : i18n.t("common:codex");
|
|
5327
|
+
const spinner = ora(i18n.t("installation:installingWith", { method, codeType: codeTypeName })).start();
|
|
5328
|
+
try {
|
|
5329
|
+
switch (method) {
|
|
5330
|
+
case "npm": {
|
|
5331
|
+
const packageName = codeType === "claude-code" ? "@anthropic-ai/claude-code" : "@openai/codex";
|
|
5332
|
+
const { command, args, usedSudo } = wrapCommandWithSudo("npm", ["install", "-g", packageName]);
|
|
5333
|
+
if (usedSudo) {
|
|
5334
|
+
spinner.info(i18n.t("installation:usingSudo"));
|
|
5335
|
+
spinner.start();
|
|
5336
|
+
}
|
|
5337
|
+
await exec(command, args);
|
|
5338
|
+
await setInstallMethod("npm", codeType);
|
|
5339
|
+
break;
|
|
5340
|
+
}
|
|
5341
|
+
case "homebrew": {
|
|
5342
|
+
if (codeType === "claude-code") {
|
|
5343
|
+
await exec("brew", ["install", "--cask", "claude-code"]);
|
|
5344
|
+
} else {
|
|
5345
|
+
await exec("brew", ["install", "codex"]);
|
|
5346
|
+
}
|
|
5347
|
+
await setInstallMethod("homebrew", codeType);
|
|
5348
|
+
break;
|
|
5349
|
+
}
|
|
5350
|
+
case "curl": {
|
|
5351
|
+
if (codeType === "claude-code") {
|
|
5352
|
+
await exec("bash", ["-c", "curl -fsSL https://claude.ai/install.sh | bash"]);
|
|
5353
|
+
} else {
|
|
5354
|
+
spinner.stop();
|
|
5355
|
+
return await executeInstallMethod("npm", codeType);
|
|
5356
|
+
}
|
|
5357
|
+
await setInstallMethod("curl", codeType);
|
|
5358
|
+
break;
|
|
5359
|
+
}
|
|
5360
|
+
case "powershell": {
|
|
5361
|
+
if (codeType === "claude-code") {
|
|
5362
|
+
await exec("powershell", ["-Command", "irm https://claude.ai/install.ps1 | iex"]);
|
|
5363
|
+
} else {
|
|
5364
|
+
spinner.stop();
|
|
5365
|
+
return await executeInstallMethod("npm", codeType);
|
|
5366
|
+
}
|
|
5367
|
+
await setInstallMethod("powershell", codeType);
|
|
5368
|
+
break;
|
|
5369
|
+
}
|
|
5370
|
+
case "cmd": {
|
|
5371
|
+
if (codeType === "claude-code") {
|
|
5372
|
+
await exec("cmd", ["/c", "curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd"]);
|
|
5373
|
+
} else {
|
|
5374
|
+
spinner.stop();
|
|
5375
|
+
return await executeInstallMethod("npm", codeType);
|
|
5376
|
+
}
|
|
5377
|
+
await setInstallMethod("cmd", codeType);
|
|
5378
|
+
break;
|
|
5379
|
+
}
|
|
5380
|
+
default:
|
|
5381
|
+
throw new Error(`Unsupported install method: ${method}`);
|
|
5382
|
+
}
|
|
5383
|
+
spinner.succeed(i18n.t("installation:installMethodSuccess", { method }));
|
|
5384
|
+
return true;
|
|
4942
5385
|
} catch (error) {
|
|
4943
|
-
|
|
5386
|
+
spinner.fail(i18n.t("installation:installMethodFailed", { method }));
|
|
5387
|
+
if (error instanceof Error) {
|
|
5388
|
+
console.error(ansis.gray(error.message));
|
|
5389
|
+
}
|
|
5390
|
+
return false;
|
|
5391
|
+
}
|
|
5392
|
+
}
|
|
5393
|
+
async function handleInstallFailure(codeType, failedMethods) {
|
|
5394
|
+
ensureI18nInitialized();
|
|
5395
|
+
const response = await inquirer.prompt({
|
|
5396
|
+
type: "confirm",
|
|
5397
|
+
name: "retry",
|
|
5398
|
+
message: i18n.t("installation:tryAnotherMethod"),
|
|
5399
|
+
default: true
|
|
5400
|
+
});
|
|
5401
|
+
if (!response.retry) {
|
|
5402
|
+
return false;
|
|
5403
|
+
}
|
|
5404
|
+
const newMethod = await selectInstallMethod(codeType, failedMethods);
|
|
5405
|
+
if (!newMethod) {
|
|
5406
|
+
return false;
|
|
4944
5407
|
}
|
|
5408
|
+
const success = await executeInstallMethod(newMethod, codeType);
|
|
5409
|
+
if (success) {
|
|
5410
|
+
return true;
|
|
5411
|
+
}
|
|
5412
|
+
return await handleInstallFailure(codeType, [...failedMethods, newMethod]);
|
|
4945
5413
|
}
|
|
4946
5414
|
|
|
4947
5415
|
const installer = {
|
|
4948
5416
|
__proto__: null,
|
|
5417
|
+
detectInstalledVersion: detectInstalledVersion,
|
|
5418
|
+
executeInstallMethod: executeInstallMethod,
|
|
4949
5419
|
getInstallationStatus: getInstallationStatus,
|
|
5420
|
+
handleInstallFailure: handleInstallFailure,
|
|
4950
5421
|
installClaudeCode: installClaudeCode,
|
|
5422
|
+
installCodex: installCodex,
|
|
4951
5423
|
isClaudeCodeInstalled: isClaudeCodeInstalled,
|
|
5424
|
+
isCodexInstalled: isCodexInstalled,
|
|
4952
5425
|
isLocalClaudeCodeInstalled: isLocalClaudeCodeInstalled,
|
|
4953
5426
|
removeLocalClaudeCode: removeLocalClaudeCode,
|
|
4954
|
-
|
|
5427
|
+
selectInstallMethod: selectInstallMethod,
|
|
5428
|
+
setInstallMethod: setInstallMethod,
|
|
5429
|
+
uninstallCodeTool: uninstallCodeTool
|
|
4955
5430
|
};
|
|
4956
5431
|
|
|
4957
5432
|
async function chooseInstallationMethod() {
|
|
@@ -5521,7 +5996,7 @@ async function init(options = {}) {
|
|
|
5521
5996
|
if (installationStatus.hasLocal) {
|
|
5522
5997
|
if (!installationStatus.hasGlobal) {
|
|
5523
5998
|
console.log(ansis.blue(`${i18n.t("installation:installingGlobalClaudeCode")}...`));
|
|
5524
|
-
await installClaudeCode();
|
|
5999
|
+
await installClaudeCode(true);
|
|
5525
6000
|
console.log(ansis.green(`\u2714 ${i18n.t("installation:globalInstallationCompleted")}`));
|
|
5526
6001
|
}
|
|
5527
6002
|
if (installationStatus.hasGlobal && installationStatus.hasLocal) {
|
|
@@ -5535,20 +6010,14 @@ async function init(options = {}) {
|
|
|
5535
6010
|
}
|
|
5536
6011
|
} else {
|
|
5537
6012
|
if (options.skipPrompt) {
|
|
5538
|
-
await installClaudeCode();
|
|
6013
|
+
await installClaudeCode(true);
|
|
5539
6014
|
} else {
|
|
5540
|
-
const
|
|
5541
|
-
type: "confirm",
|
|
5542
|
-
name: "shouldInstall",
|
|
6015
|
+
const shouldInstall = await promptBoolean({
|
|
5543
6016
|
message: i18n.t("installation:installPrompt"),
|
|
5544
|
-
|
|
6017
|
+
defaultValue: true
|
|
5545
6018
|
});
|
|
5546
|
-
if (shouldInstall === void 0) {
|
|
5547
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
5548
|
-
process.exit(0);
|
|
5549
|
-
}
|
|
5550
6019
|
if (shouldInstall) {
|
|
5551
|
-
await installClaudeCode();
|
|
6020
|
+
await installClaudeCode(false);
|
|
5552
6021
|
} else {
|
|
5553
6022
|
console.log(ansis.yellow(i18n.t("common:skip")));
|
|
5554
6023
|
}
|
|
@@ -5610,18 +6079,21 @@ async function init(options = {}) {
|
|
|
5610
6079
|
options.apiModel = options.apiModel || preset.claudeCode.defaultModels[0];
|
|
5611
6080
|
options.apiFastModel = options.apiFastModel || preset.claudeCode.defaultModels[1];
|
|
5612
6081
|
}
|
|
6082
|
+
await saveSingleConfigToToml(apiConfig, options.provider, options);
|
|
5613
6083
|
} else if (options.apiType === "auth_token" && options.apiKey) {
|
|
5614
6084
|
apiConfig = {
|
|
5615
6085
|
authType: "auth_token",
|
|
5616
6086
|
key: options.apiKey,
|
|
5617
6087
|
url: options.apiUrl || API_DEFAULT_URL
|
|
5618
6088
|
};
|
|
6089
|
+
await saveSingleConfigToToml(apiConfig, void 0, options);
|
|
5619
6090
|
} else if (options.apiType === "api_key" && options.apiKey) {
|
|
5620
6091
|
apiConfig = {
|
|
5621
6092
|
authType: "api_key",
|
|
5622
6093
|
key: options.apiKey,
|
|
5623
6094
|
url: options.apiUrl || API_DEFAULT_URL
|
|
5624
6095
|
};
|
|
6096
|
+
await saveSingleConfigToToml(apiConfig, void 0, options);
|
|
5625
6097
|
} else if (options.apiType === "ccr_proxy") {
|
|
5626
6098
|
const ccrStatus = await isCcrInstalled();
|
|
5627
6099
|
if (!ccrStatus.hasCorrectPackage) {
|
|
@@ -5753,16 +6225,10 @@ async function init(options = {}) {
|
|
|
5753
6225
|
if (options.skipPrompt) {
|
|
5754
6226
|
shouldConfigureMcp = options.mcpServices !== false;
|
|
5755
6227
|
} else {
|
|
5756
|
-
const
|
|
5757
|
-
type: "confirm",
|
|
5758
|
-
name: "shouldConfigureMcp",
|
|
6228
|
+
const userChoice = await promptBoolean({
|
|
5759
6229
|
message: i18n.t("mcp:configureMcp"),
|
|
5760
|
-
|
|
6230
|
+
defaultValue: true
|
|
5761
6231
|
});
|
|
5762
|
-
if (userChoice === void 0) {
|
|
5763
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
5764
|
-
process.exit(0);
|
|
5765
|
-
}
|
|
5766
6232
|
shouldConfigureMcp = userChoice;
|
|
5767
6233
|
}
|
|
5768
6234
|
if (shouldConfigureMcp) {
|
|
@@ -5838,16 +6304,10 @@ async function init(options = {}) {
|
|
|
5838
6304
|
if (options.skipPrompt) {
|
|
5839
6305
|
shouldInstallCometix = options.installCometixLine !== false;
|
|
5840
6306
|
} else {
|
|
5841
|
-
const
|
|
5842
|
-
type: "confirm",
|
|
5843
|
-
name: "shouldInstallCometix",
|
|
6307
|
+
const userChoice = await promptBoolean({
|
|
5844
6308
|
message: i18n.t("cometix:installCometixPrompt"),
|
|
5845
|
-
|
|
6309
|
+
defaultValue: true
|
|
5846
6310
|
});
|
|
5847
|
-
if (userChoice === void 0) {
|
|
5848
|
-
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
5849
|
-
process.exit(0);
|
|
5850
|
-
}
|
|
5851
6311
|
shouldInstallCometix = userChoice;
|
|
5852
6312
|
}
|
|
5853
6313
|
if (shouldInstallCometix) {
|
|
@@ -6003,6 +6463,55 @@ async function handleCodexConfigs(configs) {
|
|
|
6003
6463
|
console.log(ansis.green(`\u2714 ${i18n.t("multi-config:defaultProviderSet", { name: defaultConfig.name })}`));
|
|
6004
6464
|
}
|
|
6005
6465
|
}
|
|
6466
|
+
async function saveSingleConfigToToml(apiConfig, provider, options) {
|
|
6467
|
+
try {
|
|
6468
|
+
const { ClaudeCodeConfigManager } = await import('./claude-code-config-manager.mjs');
|
|
6469
|
+
const profile = await convertSingleConfigToProfile(apiConfig, provider, options);
|
|
6470
|
+
const result = await ClaudeCodeConfigManager.addProfile(profile);
|
|
6471
|
+
if (result.success) {
|
|
6472
|
+
const savedProfile = result.addedProfile || ClaudeCodeConfigManager.getProfileByName(profile.name) || profile;
|
|
6473
|
+
if (savedProfile.id) {
|
|
6474
|
+
await ClaudeCodeConfigManager.switchProfile(savedProfile.id);
|
|
6475
|
+
await ClaudeCodeConfigManager.applyProfileSettings(savedProfile);
|
|
6476
|
+
}
|
|
6477
|
+
console.log(ansis.green(`\u2714 ${i18n.t("configuration:singleConfigSaved", { name: profile.name })}`));
|
|
6478
|
+
} else {
|
|
6479
|
+
console.warn(ansis.yellow(`${i18n.t("configuration:singleConfigSaveFailed")}: ${result.error}`));
|
|
6480
|
+
}
|
|
6481
|
+
} catch (error) {
|
|
6482
|
+
console.warn(ansis.yellow(`${i18n.t("configuration:singleConfigSaveFailed")}: ${error instanceof Error ? error.message : String(error)}`));
|
|
6483
|
+
}
|
|
6484
|
+
}
|
|
6485
|
+
async function convertSingleConfigToProfile(apiConfig, provider, options) {
|
|
6486
|
+
const { ClaudeCodeConfigManager } = await import('./claude-code-config-manager.mjs');
|
|
6487
|
+
const configName = provider && provider !== "custom" ? provider : "custom-config";
|
|
6488
|
+
let baseUrl = apiConfig.url || API_DEFAULT_URL;
|
|
6489
|
+
let primaryModel = options?.apiModel;
|
|
6490
|
+
let fastModel = options?.apiFastModel;
|
|
6491
|
+
let authType = apiConfig.authType;
|
|
6492
|
+
if (provider && provider !== "custom") {
|
|
6493
|
+
const { getProviderPreset } = await import('./api-providers.mjs');
|
|
6494
|
+
const preset = getProviderPreset(provider);
|
|
6495
|
+
if (preset?.claudeCode) {
|
|
6496
|
+
baseUrl = apiConfig.url || preset.claudeCode.baseUrl;
|
|
6497
|
+
authType = preset.claudeCode.authType;
|
|
6498
|
+
if (preset.claudeCode.defaultModels && preset.claudeCode.defaultModels.length >= 2) {
|
|
6499
|
+
primaryModel = primaryModel || preset.claudeCode.defaultModels[0];
|
|
6500
|
+
fastModel = fastModel || preset.claudeCode.defaultModels[1];
|
|
6501
|
+
}
|
|
6502
|
+
}
|
|
6503
|
+
}
|
|
6504
|
+
const profile = {
|
|
6505
|
+
name: configName,
|
|
6506
|
+
authType,
|
|
6507
|
+
apiKey: apiConfig.key,
|
|
6508
|
+
baseUrl,
|
|
6509
|
+
primaryModel,
|
|
6510
|
+
fastModel,
|
|
6511
|
+
id: ClaudeCodeConfigManager.generateProfileId(configName)
|
|
6512
|
+
};
|
|
6513
|
+
return profile;
|
|
6514
|
+
}
|
|
6006
6515
|
async function convertToClaudeCodeProfile(config) {
|
|
6007
6516
|
const { ClaudeCodeConfigManager } = await import('./claude-code-config-manager.mjs');
|
|
6008
6517
|
let baseUrl = config.url;
|
|
@@ -6134,4 +6643,4 @@ async function openSettingsJson() {
|
|
|
6134
6643
|
}
|
|
6135
6644
|
}
|
|
6136
6645
|
|
|
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,
|
|
6646
|
+
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 };
|