zcf 2.0.1 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +28 -26
- package/dist/cli.mjs +121 -165
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.mjs +2 -2
- package/dist/shared/{zcf.DAPPHkhV.mjs → zcf.BAnSslet.mjs} +311 -250
- package/package.json +3 -2
- package/templates/en/commands/workflow.md +68 -6
- package/templates/zh-CN/commands/feat.md +1 -1
- package/templates/zh-CN/commands/workflow.md +69 -8
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
2
|
import ansis from 'ansis';
|
|
3
3
|
import { existsSync, mkdirSync, copyFileSync, writeFileSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
4
4
|
import { homedir, platform } from 'node:os';
|
|
@@ -7,7 +7,7 @@ import dayjs from 'dayjs';
|
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
import { exec } from 'tinyexec';
|
|
9
9
|
|
|
10
|
-
const version = "2.
|
|
10
|
+
const version = "2.1.2";
|
|
11
11
|
const homepage = "https://github.com/UfoMiao/zcf";
|
|
12
12
|
|
|
13
13
|
const CLAUDE_DIR = join(homedir(), ".claude");
|
|
@@ -33,14 +33,18 @@ const I18N = {
|
|
|
33
33
|
aiOutputLangHint: "AI \u5C06\u4F7F\u7528\u6B64\u8BED\u8A00\u56DE\u590D\u4F60\u7684\u95EE\u9898",
|
|
34
34
|
enterCustomLanguage: "\u8BF7\u8F93\u5165\u81EA\u5B9A\u4E49\u8BED\u8A00\uFF08\u4F8B\u5982\uFF1AJapanese, French \u7B49\uFF09",
|
|
35
35
|
configLangHint: {
|
|
36
|
-
"zh-CN": "\
|
|
37
|
-
en: "\
|
|
36
|
+
"zh-CN": "\u4FBF\u4E8E\u4E2D\u6587\u7528\u6237\u81EA\u5B9A\u4E49",
|
|
37
|
+
en: "\u63A8\u8350\uFF0Ctoken \u6D88\u8017\u66F4\u4F4E"
|
|
38
38
|
},
|
|
39
39
|
installPrompt: "\u68C0\u6D4B\u5230 Claude Code \u672A\u5B89\u88C5\uFF0C\u662F\u5426\u81EA\u52A8\u5B89\u88C5\uFF1F",
|
|
40
40
|
installing: "\u6B63\u5728\u5B89\u88C5 Claude Code...",
|
|
41
41
|
installSuccess: "Claude Code \u5B89\u88C5\u6210\u529F",
|
|
42
42
|
installFailed: "Claude Code \u5B89\u88C5\u5931\u8D25",
|
|
43
43
|
npmNotFound: "npm \u672A\u5B89\u88C5\u3002\u8BF7\u5148\u5B89\u88C5 Node.js \u548C npm\u3002",
|
|
44
|
+
termuxDetected: "\u68C0\u6D4B\u5230 Termux \u73AF\u5883",
|
|
45
|
+
termuxInstallHint: "\u5728 Termux \u4E2D\uFF0C\u8BF7\u5148\u8FD0\u884C: pkg install nodejs \u6216 pkg install nodejs-lts",
|
|
46
|
+
termuxPathInfo: "\u4F7F\u7528 Termux \u8DEF\u5F84: {path}",
|
|
47
|
+
termuxEnvironmentInfo: "Termux \u73AF\u5883\u901A\u8FC7 pkg \u7BA1\u7406\u5668\u63D0\u4F9B Node.js \u548C npm",
|
|
44
48
|
configureApi: "\u9009\u62E9 API \u8BA4\u8BC1\u65B9\u5F0F",
|
|
45
49
|
useAuthToken: "\u4F7F\u7528 Auth Token (OAuth \u8BA4\u8BC1)",
|
|
46
50
|
authTokenDesc: "\u9002\u7528\u4E8E\u901A\u8FC7 OAuth \u6216\u6D4F\u89C8\u5668\u767B\u5F55\u83B7\u53D6\u7684\u4EE4\u724C",
|
|
@@ -78,7 +82,7 @@ const I18N = {
|
|
|
78
82
|
configSuccess: "\u914D\u7F6E\u6587\u4EF6\u5DF2\u590D\u5236\u5230",
|
|
79
83
|
apiConfigSuccess: "API \u914D\u7F6E\u5B8C\u6210",
|
|
80
84
|
mcpConfigSuccess: "MCP \u670D\u52A1\u5DF2\u914D\u7F6E",
|
|
81
|
-
selectMcpServices: "\u9009\u62E9\u8981\u5B89\u88C5\u7684 MCP \u670D\u52A1\uFF08\u7A7A\u683C\u9009\u62E9\uFF0C\u56DE\u8F66\u786E\u8BA4\uFF09",
|
|
85
|
+
selectMcpServices: "\u9009\u62E9\u8981\u5B89\u88C5\u7684 MCP \u670D\u52A1\uFF08\u7A7A\u683C\u9009\u62E9\uFF0Ca\u5168\u9009\uFF0Ci\u53CD\u9009\uFF0C\u56DE\u8F66\u786E\u8BA4\uFF09",
|
|
82
86
|
allServices: "\u5168\u90E8\u5B89\u88C5",
|
|
83
87
|
mcpServiceInstalled: "\u5DF2\u9009\u62E9\u7684 MCP \u670D\u52A1",
|
|
84
88
|
enterExaApiKey: "\u8BF7\u8F93\u5165 Exa API Key\uFF08\u53EF\u4ECE https://dashboard.exa.ai/api-keys \u83B7\u53D6\uFF09",
|
|
@@ -126,7 +130,7 @@ const I18N = {
|
|
|
126
130
|
changeLanguage: "\u66F4\u6539 ZCF \u754C\u9762\u8BED\u8A00"
|
|
127
131
|
},
|
|
128
132
|
returnToMenu: "\u8FD4\u56DE\u4E3B\u83DC\u5355\uFF1F",
|
|
129
|
-
goodbye: "\u518D\u89C1\uFF01
|
|
133
|
+
goodbye: "\u{1F44B} \u611F\u8C22\u4F7F\u7528 ZCF\uFF01\u518D\u89C1\uFF01",
|
|
130
134
|
// Model config
|
|
131
135
|
selectDefaultModel: "\u9009\u62E9\u9ED8\u8BA4\u6A21\u578B",
|
|
132
136
|
modelConfigSuccess: "\u9ED8\u8BA4\u6A21\u578B\u5DF2\u914D\u7F6E",
|
|
@@ -204,14 +208,18 @@ const I18N = {
|
|
|
204
208
|
aiOutputLangHint: "AI will respond to you in this language",
|
|
205
209
|
enterCustomLanguage: "Enter custom language (e.g., Japanese, French, etc.)",
|
|
206
210
|
configLangHint: {
|
|
207
|
-
"zh-CN": "
|
|
208
|
-
en: "
|
|
211
|
+
"zh-CN": "easier for Chinese users to customize",
|
|
212
|
+
en: "recommended, lower token consumption"
|
|
209
213
|
},
|
|
210
214
|
installPrompt: "Claude Code not found. Install automatically?",
|
|
211
215
|
installing: "Installing Claude Code...",
|
|
212
216
|
installSuccess: "Claude Code installed successfully",
|
|
213
217
|
installFailed: "Failed to install Claude Code",
|
|
214
218
|
npmNotFound: "npm is not installed. Please install Node.js and npm first.",
|
|
219
|
+
termuxDetected: "Termux environment detected",
|
|
220
|
+
termuxInstallHint: "In Termux, please run first: pkg install nodejs or pkg install nodejs-lts",
|
|
221
|
+
termuxPathInfo: "Using Termux path: {path}",
|
|
222
|
+
termuxEnvironmentInfo: "Termux environment provides Node.js and npm through pkg manager",
|
|
215
223
|
configureApi: "Select API authentication method",
|
|
216
224
|
useAuthToken: "Use Auth Token (OAuth authentication)",
|
|
217
225
|
authTokenDesc: "For tokens obtained via OAuth or browser login",
|
|
@@ -249,7 +257,7 @@ const I18N = {
|
|
|
249
257
|
configSuccess: "Config files copied to",
|
|
250
258
|
apiConfigSuccess: "API configured",
|
|
251
259
|
mcpConfigSuccess: "MCP services configured",
|
|
252
|
-
selectMcpServices: "Select MCP services to install (space to select, enter to confirm)",
|
|
260
|
+
selectMcpServices: "Select MCP services to install (space to select, a to select all, i to deselect, enter to confirm)",
|
|
253
261
|
allServices: "Install all",
|
|
254
262
|
mcpServiceInstalled: "Selected MCP services",
|
|
255
263
|
enterExaApiKey: "Enter Exa API Key (get from https://dashboard.exa.ai/api-keys)",
|
|
@@ -297,7 +305,7 @@ const I18N = {
|
|
|
297
305
|
changeLanguage: "Change ZCF interface language"
|
|
298
306
|
},
|
|
299
307
|
returnToMenu: "Return to main menu?",
|
|
300
|
-
goodbye: "
|
|
308
|
+
goodbye: "\u{1F44B} Thanks for using ZCF! Goodbye!",
|
|
301
309
|
// Model config
|
|
302
310
|
selectDefaultModel: "Select default model",
|
|
303
311
|
modelConfigSuccess: "Default model configured",
|
|
@@ -663,54 +671,54 @@ async function configureAiPersonality(scriptLang, showExisting = true) {
|
|
|
663
671
|
console.log(
|
|
664
672
|
ansis.gray(` ${i18n.currentPersonality || "Current personality"}: ${personalityInfo.name[scriptLang]}`)
|
|
665
673
|
);
|
|
666
|
-
const
|
|
674
|
+
const { modify } = await inquirer.prompt({
|
|
667
675
|
type: "confirm",
|
|
668
676
|
name: "modify",
|
|
669
677
|
message: i18n.modifyPersonality || "Modify AI personality?",
|
|
670
|
-
|
|
678
|
+
default: false
|
|
671
679
|
});
|
|
672
|
-
if (!
|
|
680
|
+
if (!modify) {
|
|
673
681
|
console.log(ansis.green(`\u2714 ${i18n.keepPersonality || "Keeping existing personality"}`));
|
|
674
682
|
return;
|
|
675
683
|
}
|
|
676
684
|
}
|
|
677
685
|
}
|
|
678
|
-
const
|
|
679
|
-
type: "
|
|
686
|
+
const { personality } = await inquirer.prompt({
|
|
687
|
+
type: "list",
|
|
680
688
|
name: "personality",
|
|
681
689
|
message: i18n.selectAiPersonality || "Select AI personality",
|
|
682
690
|
choices: AI_PERSONALITIES.map((p) => ({
|
|
683
|
-
|
|
691
|
+
name: p.id !== "custom" ? `${p.name[scriptLang]} - ${ansis.gray(p.directive[scriptLang].substring(0, 50) + "...")}` : `${p.name[scriptLang]} - ${ansis.gray(i18n.customPersonalityHint || "Define your own personality")}`,
|
|
684
692
|
value: p.id,
|
|
685
|
-
|
|
693
|
+
short: p.name[scriptLang]
|
|
686
694
|
})),
|
|
687
|
-
|
|
695
|
+
default: existingPersonality ? AI_PERSONALITIES.findIndex((p) => p.id === existingPersonality) : 0
|
|
688
696
|
});
|
|
689
|
-
if (!
|
|
697
|
+
if (!personality) {
|
|
690
698
|
console.log(ansis.yellow(i18n.cancelled));
|
|
691
699
|
return;
|
|
692
700
|
}
|
|
693
701
|
let directive = "";
|
|
694
|
-
if (
|
|
695
|
-
const
|
|
696
|
-
type: "
|
|
697
|
-
name: "
|
|
702
|
+
if (personality === "custom") {
|
|
703
|
+
const { customDirective } = await inquirer.prompt({
|
|
704
|
+
type: "input",
|
|
705
|
+
name: "customDirective",
|
|
698
706
|
message: i18n.enterCustomPersonality || "Enter custom personality directive",
|
|
699
707
|
validate: (value) => !!value || i18n.directiveCannotBeEmpty
|
|
700
708
|
});
|
|
701
|
-
if (!
|
|
709
|
+
if (!customDirective) {
|
|
702
710
|
console.log(ansis.yellow(i18n.cancelled));
|
|
703
711
|
return;
|
|
704
712
|
}
|
|
705
|
-
directive =
|
|
713
|
+
directive = customDirective;
|
|
706
714
|
} else {
|
|
707
|
-
const selected = AI_PERSONALITIES.find((p) => p.id ===
|
|
715
|
+
const selected = AI_PERSONALITIES.find((p) => p.id === personality);
|
|
708
716
|
if (selected) {
|
|
709
717
|
directive = selected.directive[scriptLang];
|
|
710
718
|
}
|
|
711
719
|
}
|
|
712
720
|
await applyPersonalityDirective(directive);
|
|
713
|
-
updateZcfConfig({ aiPersonality:
|
|
721
|
+
updateZcfConfig({ aiPersonality: personality });
|
|
714
722
|
console.log(ansis.green(`\u2714 ${i18n.personalityConfigured || "AI personality configured"}`));
|
|
715
723
|
}
|
|
716
724
|
async function applyPersonalityDirective(directive) {
|
|
@@ -750,6 +758,29 @@ function displayBannerWithInfo(subtitle) {
|
|
|
750
758
|
`));
|
|
751
759
|
}
|
|
752
760
|
|
|
761
|
+
function handleExitPromptError(error) {
|
|
762
|
+
if (error instanceof Error && error.name === "ExitPromptError") {
|
|
763
|
+
const zcfConfig = readZcfConfig();
|
|
764
|
+
const defaultLang = zcfConfig?.preferredLang || "zh-CN";
|
|
765
|
+
const i18n = I18N[defaultLang];
|
|
766
|
+
console.log(ansis.cyan(`
|
|
767
|
+
${i18n.goodbye}
|
|
768
|
+
`));
|
|
769
|
+
process.exit(0);
|
|
770
|
+
}
|
|
771
|
+
return false;
|
|
772
|
+
}
|
|
773
|
+
function handleGeneralError(error, lang) {
|
|
774
|
+
const zcfConfig = readZcfConfig();
|
|
775
|
+
const defaultLang = lang || zcfConfig?.preferredLang || "en";
|
|
776
|
+
const errorMsg = I18N[defaultLang].error;
|
|
777
|
+
console.error(ansis.red(`${errorMsg}:`), error);
|
|
778
|
+
if (error instanceof Error) {
|
|
779
|
+
console.error(ansis.gray(`Stack: ${error.stack}`));
|
|
780
|
+
}
|
|
781
|
+
process.exit(1);
|
|
782
|
+
}
|
|
783
|
+
|
|
753
784
|
function mergeArraysUnique(arr1, arr2) {
|
|
754
785
|
const combined = [...arr1 || [], ...arr2 || []];
|
|
755
786
|
return [...new Set(combined)];
|
|
@@ -1006,31 +1037,31 @@ function formatApiKeyDisplay(apiKey) {
|
|
|
1006
1037
|
async function configureApiCompletely(i18n, scriptLang, preselectedAuthType) {
|
|
1007
1038
|
let authType = preselectedAuthType;
|
|
1008
1039
|
if (!authType) {
|
|
1009
|
-
const
|
|
1010
|
-
type: "
|
|
1040
|
+
const { authType: selectedAuthType } = await inquirer.prompt({
|
|
1041
|
+
type: "list",
|
|
1011
1042
|
name: "authType",
|
|
1012
1043
|
message: i18n.configureApi,
|
|
1013
1044
|
choices: [
|
|
1014
1045
|
{
|
|
1015
|
-
|
|
1046
|
+
name: `${i18n.useAuthToken} - ${ansis.gray(i18n.authTokenDesc)}`,
|
|
1016
1047
|
value: "auth_token",
|
|
1017
|
-
|
|
1048
|
+
short: i18n.useAuthToken
|
|
1018
1049
|
},
|
|
1019
1050
|
{
|
|
1020
|
-
|
|
1051
|
+
name: `${i18n.useApiKey} - ${ansis.gray(i18n.apiKeyDesc)}`,
|
|
1021
1052
|
value: "api_key",
|
|
1022
|
-
|
|
1053
|
+
short: i18n.useApiKey
|
|
1023
1054
|
}
|
|
1024
1055
|
]
|
|
1025
1056
|
});
|
|
1026
|
-
if (!
|
|
1057
|
+
if (!selectedAuthType) {
|
|
1027
1058
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1028
1059
|
return null;
|
|
1029
1060
|
}
|
|
1030
|
-
authType =
|
|
1061
|
+
authType = selectedAuthType;
|
|
1031
1062
|
}
|
|
1032
|
-
const
|
|
1033
|
-
type: "
|
|
1063
|
+
const { url } = await inquirer.prompt({
|
|
1064
|
+
type: "input",
|
|
1034
1065
|
name: "url",
|
|
1035
1066
|
message: i18n.enterApiUrl,
|
|
1036
1067
|
validate: (value) => {
|
|
@@ -1043,13 +1074,13 @@ async function configureApiCompletely(i18n, scriptLang, preselectedAuthType) {
|
|
|
1043
1074
|
}
|
|
1044
1075
|
}
|
|
1045
1076
|
});
|
|
1046
|
-
if (
|
|
1077
|
+
if (url === void 0) {
|
|
1047
1078
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1048
1079
|
return null;
|
|
1049
1080
|
}
|
|
1050
1081
|
const keyMessage = authType === "auth_token" ? i18n.enterAuthToken : i18n.enterApiKey;
|
|
1051
|
-
const
|
|
1052
|
-
type: "
|
|
1082
|
+
const { key } = await inquirer.prompt({
|
|
1083
|
+
type: "input",
|
|
1053
1084
|
name: "key",
|
|
1054
1085
|
message: keyMessage,
|
|
1055
1086
|
validate: (value) => {
|
|
@@ -1063,115 +1094,107 @@ async function configureApiCompletely(i18n, scriptLang, preselectedAuthType) {
|
|
|
1063
1094
|
return true;
|
|
1064
1095
|
}
|
|
1065
1096
|
});
|
|
1066
|
-
if (
|
|
1097
|
+
if (key === void 0) {
|
|
1067
1098
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1068
1099
|
return null;
|
|
1069
1100
|
}
|
|
1070
|
-
console.log(ansis.gray(` API Key: ${formatApiKeyDisplay(
|
|
1071
|
-
return { url
|
|
1101
|
+
console.log(ansis.gray(` API Key: ${formatApiKeyDisplay(key)}`));
|
|
1102
|
+
return { url, key, authType };
|
|
1072
1103
|
}
|
|
1073
1104
|
async function modifyApiConfigPartially(existingConfig, i18n, scriptLang) {
|
|
1074
1105
|
let currentConfig = { ...existingConfig };
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1106
|
+
const latestConfig = getExistingApiConfig();
|
|
1107
|
+
if (latestConfig) {
|
|
1108
|
+
currentConfig = latestConfig;
|
|
1109
|
+
}
|
|
1110
|
+
const { item } = await inquirer.prompt({
|
|
1111
|
+
type: "list",
|
|
1112
|
+
name: "item",
|
|
1113
|
+
message: i18n.selectModifyItems,
|
|
1114
|
+
choices: [
|
|
1115
|
+
{ name: i18n.modifyApiUrl, value: "url" },
|
|
1116
|
+
{ name: i18n.modifyApiKey, value: "key" },
|
|
1117
|
+
{ name: i18n.modifyAuthType, value: "authType" }
|
|
1118
|
+
]
|
|
1119
|
+
});
|
|
1120
|
+
if (!item) {
|
|
1121
|
+
console.log(ansis.yellow(i18n.cancelled));
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
if (item === "url") {
|
|
1125
|
+
const { url } = await inquirer.prompt({
|
|
1126
|
+
type: "input",
|
|
1127
|
+
name: "url",
|
|
1128
|
+
message: i18n.enterNewApiUrl.replace("{url}", currentConfig.url || i18n.none),
|
|
1129
|
+
default: currentConfig.url,
|
|
1130
|
+
validate: (value) => {
|
|
1131
|
+
if (!value) return i18n.urlRequired;
|
|
1132
|
+
try {
|
|
1133
|
+
new URL(value);
|
|
1134
|
+
return true;
|
|
1135
|
+
} catch {
|
|
1136
|
+
return i18n.invalidUrl;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1089
1139
|
});
|
|
1090
|
-
if (
|
|
1140
|
+
if (url === void 0) {
|
|
1091
1141
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1092
1142
|
return;
|
|
1093
1143
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1144
|
+
currentConfig.url = url;
|
|
1145
|
+
const savedConfig = configureApi(currentConfig);
|
|
1146
|
+
if (savedConfig) {
|
|
1147
|
+
console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
|
|
1148
|
+
console.log(ansis.gray(` ${i18n.apiConfigUrl}: ${savedConfig.url}`));
|
|
1149
|
+
}
|
|
1150
|
+
} else if (item === "key") {
|
|
1151
|
+
const authType = currentConfig.authType || "auth_token";
|
|
1152
|
+
const keyMessage = authType === "auth_token" ? i18n.enterNewApiKey.replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.none) : i18n.enterNewApiKey.replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.none);
|
|
1153
|
+
const { key } = await inquirer.prompt({
|
|
1154
|
+
type: "input",
|
|
1155
|
+
name: "key",
|
|
1156
|
+
message: keyMessage,
|
|
1157
|
+
validate: (value) => {
|
|
1158
|
+
if (!value) {
|
|
1159
|
+
return i18n.keyRequired;
|
|
1108
1160
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
}
|
|
1113
|
-
currentConfig.url = urlResponse.url;
|
|
1114
|
-
const savedConfig = configureApi(currentConfig);
|
|
1115
|
-
if (savedConfig) {
|
|
1116
|
-
console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
|
|
1117
|
-
console.log(ansis.gray(` ${i18n.apiConfigUrl}: ${savedConfig.url}`));
|
|
1118
|
-
}
|
|
1119
|
-
} else if (modifyResponse.item === "key") {
|
|
1120
|
-
const authType = currentConfig.authType || "auth_token";
|
|
1121
|
-
const keyMessage = authType === "auth_token" ? i18n.enterNewApiKey.replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.none) : i18n.enterNewApiKey.replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.none);
|
|
1122
|
-
const keyResponse = await prompts({
|
|
1123
|
-
type: "text",
|
|
1124
|
-
name: "key",
|
|
1125
|
-
message: keyMessage,
|
|
1126
|
-
validate: (value) => {
|
|
1127
|
-
if (!value) {
|
|
1128
|
-
return i18n.keyRequired;
|
|
1129
|
-
}
|
|
1130
|
-
const validation = validateApiKey(value, scriptLang);
|
|
1131
|
-
if (!validation.isValid) {
|
|
1132
|
-
return validation.error || i18n.invalidKeyFormat;
|
|
1133
|
-
}
|
|
1134
|
-
return true;
|
|
1161
|
+
const validation = validateApiKey(value, scriptLang);
|
|
1162
|
+
if (!validation.isValid) {
|
|
1163
|
+
return validation.error || i18n.invalidKeyFormat;
|
|
1135
1164
|
}
|
|
1136
|
-
|
|
1137
|
-
if (keyResponse.key === void 0) {
|
|
1138
|
-
continue;
|
|
1139
|
-
}
|
|
1140
|
-
currentConfig.key = keyResponse.key;
|
|
1141
|
-
const savedConfig = configureApi(currentConfig);
|
|
1142
|
-
if (savedConfig) {
|
|
1143
|
-
console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
|
|
1144
|
-
console.log(ansis.gray(` ${i18n.apiConfigKey}: ${formatApiKeyDisplay(savedConfig.key)}`));
|
|
1145
|
-
}
|
|
1146
|
-
} else if (modifyResponse.item === "authType") {
|
|
1147
|
-
const authResponse = await prompts({
|
|
1148
|
-
type: "select",
|
|
1149
|
-
name: "authType",
|
|
1150
|
-
message: i18n.selectNewAuthType.replace("{type}", currentConfig.authType || i18n.none),
|
|
1151
|
-
choices: [
|
|
1152
|
-
{ title: "Auth Token (OAuth)", value: "auth_token" },
|
|
1153
|
-
{ title: "API Key", value: "api_key" }
|
|
1154
|
-
],
|
|
1155
|
-
initial: currentConfig.authType === "api_key" ? 1 : 0
|
|
1156
|
-
});
|
|
1157
|
-
if (authResponse.authType === void 0) {
|
|
1158
|
-
continue;
|
|
1159
|
-
}
|
|
1160
|
-
currentConfig.authType = authResponse.authType;
|
|
1161
|
-
const savedConfig = configureApi(currentConfig);
|
|
1162
|
-
if (savedConfig) {
|
|
1163
|
-
console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
|
|
1164
|
-
console.log(ansis.gray(` ${i18n.apiConfigAuthType}: ${savedConfig.authType}`));
|
|
1165
|
+
return true;
|
|
1165
1166
|
}
|
|
1167
|
+
});
|
|
1168
|
+
if (key === void 0) {
|
|
1169
|
+
console.log(ansis.yellow(i18n.cancelled));
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
currentConfig.key = key;
|
|
1173
|
+
const savedConfig = configureApi(currentConfig);
|
|
1174
|
+
if (savedConfig) {
|
|
1175
|
+
console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
|
|
1176
|
+
console.log(ansis.gray(` ${i18n.apiConfigKey}: ${formatApiKeyDisplay(savedConfig.key)}`));
|
|
1166
1177
|
}
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1178
|
+
} else if (item === "authType") {
|
|
1179
|
+
const { authType } = await inquirer.prompt({
|
|
1180
|
+
type: "list",
|
|
1181
|
+
name: "authType",
|
|
1182
|
+
message: i18n.selectNewAuthType.replace("{type}", currentConfig.authType || i18n.none),
|
|
1183
|
+
choices: [
|
|
1184
|
+
{ name: "Auth Token (OAuth)", value: "auth_token" },
|
|
1185
|
+
{ name: "API Key", value: "api_key" }
|
|
1186
|
+
],
|
|
1187
|
+
default: currentConfig.authType === "api_key" ? 1 : 0
|
|
1172
1188
|
});
|
|
1173
|
-
if (
|
|
1174
|
-
|
|
1189
|
+
if (authType === void 0) {
|
|
1190
|
+
console.log(ansis.yellow(i18n.cancelled));
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
currentConfig.authType = authType;
|
|
1194
|
+
const savedConfig = configureApi(currentConfig);
|
|
1195
|
+
if (savedConfig) {
|
|
1196
|
+
console.log(ansis.green(`\u2714 ${i18n.modificationSaved}`));
|
|
1197
|
+
console.log(ansis.gray(` ${i18n.apiConfigAuthType}: ${savedConfig.authType}`));
|
|
1175
1198
|
}
|
|
1176
1199
|
}
|
|
1177
1200
|
}
|
|
@@ -1196,6 +1219,12 @@ function getPlatform() {
|
|
|
1196
1219
|
if (p === "darwin") return "macos";
|
|
1197
1220
|
return "linux";
|
|
1198
1221
|
}
|
|
1222
|
+
function isTermux() {
|
|
1223
|
+
return !!(process.env.PREFIX && process.env.PREFIX.includes("com.termux")) || !!process.env.TERMUX_VERSION || existsSync("/data/data/com.termux/files/usr");
|
|
1224
|
+
}
|
|
1225
|
+
function getTermuxPrefix() {
|
|
1226
|
+
return process.env.PREFIX || "/data/data/com.termux/files/usr";
|
|
1227
|
+
}
|
|
1199
1228
|
function isWindows() {
|
|
1200
1229
|
return getPlatform() === "windows";
|
|
1201
1230
|
}
|
|
@@ -1209,10 +1238,38 @@ async function commandExists(command) {
|
|
|
1209
1238
|
try {
|
|
1210
1239
|
const cmd = getPlatform() === "windows" ? "where" : "which";
|
|
1211
1240
|
const res = await exec(cmd, [command]);
|
|
1212
|
-
|
|
1241
|
+
if (res.exitCode === 0) {
|
|
1242
|
+
return true;
|
|
1243
|
+
}
|
|
1213
1244
|
} catch {
|
|
1214
|
-
return false;
|
|
1215
1245
|
}
|
|
1246
|
+
if (isTermux()) {
|
|
1247
|
+
const termuxPrefix = getTermuxPrefix();
|
|
1248
|
+
const possiblePaths = [
|
|
1249
|
+
`${termuxPrefix}/bin/${command}`,
|
|
1250
|
+
`${termuxPrefix}/usr/bin/${command}`,
|
|
1251
|
+
`/data/data/com.termux/files/usr/bin/${command}`
|
|
1252
|
+
];
|
|
1253
|
+
for (const path of possiblePaths) {
|
|
1254
|
+
if (existsSync(path)) {
|
|
1255
|
+
return true;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
if (getPlatform() !== "windows") {
|
|
1260
|
+
const commonPaths = [
|
|
1261
|
+
`/usr/local/bin/${command}`,
|
|
1262
|
+
`/usr/bin/${command}`,
|
|
1263
|
+
`/bin/${command}`,
|
|
1264
|
+
`${process.env.HOME}/.local/bin/${command}`
|
|
1265
|
+
];
|
|
1266
|
+
for (const path of commonPaths) {
|
|
1267
|
+
if (existsSync(path)) {
|
|
1268
|
+
return true;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
return false;
|
|
1216
1273
|
}
|
|
1217
1274
|
|
|
1218
1275
|
async function isClaudeCodeInstalled() {
|
|
@@ -1220,15 +1277,28 @@ async function isClaudeCodeInstalled() {
|
|
|
1220
1277
|
}
|
|
1221
1278
|
async function installClaudeCode(lang) {
|
|
1222
1279
|
const i18n = I18N[lang];
|
|
1280
|
+
if (isTermux()) {
|
|
1281
|
+
console.log(ansis.yellow(`\u2139 ${i18n.termuxDetected}`));
|
|
1282
|
+
const termuxPrefix = getTermuxPrefix();
|
|
1283
|
+
console.log(ansis.gray(i18n.termuxPathInfo.replace("{path}", termuxPrefix)));
|
|
1284
|
+
console.log(ansis.gray(`Node.js: ${termuxPrefix}/bin/node`));
|
|
1285
|
+
console.log(ansis.gray(`npm: ${termuxPrefix}/bin/npm`));
|
|
1286
|
+
}
|
|
1223
1287
|
console.log(i18n.installing);
|
|
1224
1288
|
try {
|
|
1225
|
-
if (!await commandExists("npm")) {
|
|
1226
|
-
throw new Error(i18n.npmNotFound);
|
|
1227
|
-
}
|
|
1228
1289
|
await exec("npm", ["install", "-g", "@anthropic-ai/claude-code"]);
|
|
1229
1290
|
console.log(`\u2714 ${i18n.installSuccess}`);
|
|
1291
|
+
if (isTermux()) {
|
|
1292
|
+
console.log(ansis.gray(`
|
|
1293
|
+
Claude Code installed to: ${getTermuxPrefix()}/bin/claude`));
|
|
1294
|
+
}
|
|
1230
1295
|
} catch (error) {
|
|
1231
1296
|
console.error(`\u2716 ${i18n.installFailed}`);
|
|
1297
|
+
if (isTermux()) {
|
|
1298
|
+
console.error(ansis.yellow(`
|
|
1299
|
+
${i18n.termuxInstallHint}
|
|
1300
|
+
`));
|
|
1301
|
+
}
|
|
1232
1302
|
throw error;
|
|
1233
1303
|
}
|
|
1234
1304
|
}
|
|
@@ -1312,30 +1382,33 @@ async function selectAiOutputLanguage(scriptLang, defaultLang) {
|
|
|
1312
1382
|
value: key
|
|
1313
1383
|
}));
|
|
1314
1384
|
const defaultChoice = defaultLang || (scriptLang === "zh-CN" ? "zh-CN" : "en");
|
|
1315
|
-
const
|
|
1316
|
-
type: "
|
|
1385
|
+
const { lang } = await inquirer.prompt({
|
|
1386
|
+
type: "list",
|
|
1317
1387
|
name: "lang",
|
|
1318
1388
|
message: i18n.selectAiOutputLang,
|
|
1319
|
-
choices: aiLangChoices
|
|
1320
|
-
|
|
1389
|
+
choices: aiLangChoices.map((choice) => ({
|
|
1390
|
+
name: choice.title,
|
|
1391
|
+
value: choice.value
|
|
1392
|
+
})),
|
|
1393
|
+
default: defaultChoice
|
|
1321
1394
|
});
|
|
1322
|
-
if (!
|
|
1395
|
+
if (!lang) {
|
|
1323
1396
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1324
1397
|
process.exit(0);
|
|
1325
1398
|
}
|
|
1326
|
-
let aiOutputLang =
|
|
1399
|
+
let aiOutputLang = lang;
|
|
1327
1400
|
if (aiOutputLang === "custom") {
|
|
1328
|
-
const
|
|
1329
|
-
type: "
|
|
1401
|
+
const { customLang } = await inquirer.prompt({
|
|
1402
|
+
type: "input",
|
|
1330
1403
|
name: "customLang",
|
|
1331
1404
|
message: i18n.enterCustomLanguage,
|
|
1332
1405
|
validate: (value) => !!value || i18n.languageRequired
|
|
1333
1406
|
});
|
|
1334
|
-
if (!
|
|
1407
|
+
if (!customLang) {
|
|
1335
1408
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1336
1409
|
process.exit(0);
|
|
1337
1410
|
}
|
|
1338
|
-
return
|
|
1411
|
+
return customLang;
|
|
1339
1412
|
}
|
|
1340
1413
|
return aiOutputLang;
|
|
1341
1414
|
}
|
|
@@ -1347,20 +1420,20 @@ async function selectScriptLanguage(currentLang) {
|
|
|
1347
1420
|
if (currentLang) {
|
|
1348
1421
|
return currentLang;
|
|
1349
1422
|
}
|
|
1350
|
-
const
|
|
1351
|
-
type: "
|
|
1423
|
+
const { lang } = await inquirer.prompt({
|
|
1424
|
+
type: "list",
|
|
1352
1425
|
name: "lang",
|
|
1353
1426
|
message: "Select ZCF display language / \u9009\u62E9ZCF\u663E\u793A\u8BED\u8A00",
|
|
1354
1427
|
choices: SUPPORTED_LANGS.map((l) => ({
|
|
1355
|
-
|
|
1428
|
+
name: LANG_LABELS[l],
|
|
1356
1429
|
value: l
|
|
1357
1430
|
}))
|
|
1358
1431
|
});
|
|
1359
|
-
if (!
|
|
1432
|
+
if (!lang) {
|
|
1360
1433
|
console.log(ansis.yellow("Operation cancelled / \u64CD\u4F5C\u5DF2\u53D6\u6D88"));
|
|
1361
1434
|
process.exit(0);
|
|
1362
1435
|
}
|
|
1363
|
-
const scriptLang =
|
|
1436
|
+
const scriptLang = lang;
|
|
1364
1437
|
updateZcfConfig({
|
|
1365
1438
|
version,
|
|
1366
1439
|
preferredLang: scriptLang
|
|
@@ -1379,6 +1452,26 @@ async function resolveAiOutputLanguage(scriptLang, commandLineOption, savedConfi
|
|
|
1379
1452
|
return await selectAiOutputLanguage(scriptLang, scriptLang);
|
|
1380
1453
|
}
|
|
1381
1454
|
|
|
1455
|
+
async function selectMcpServices(scriptLang) {
|
|
1456
|
+
const i18n = I18N[scriptLang];
|
|
1457
|
+
const choices = MCP_SERVICES.map((service) => ({
|
|
1458
|
+
name: `${service.name[scriptLang]} - ${ansis.gray(service.description[scriptLang])}`,
|
|
1459
|
+
value: service.id,
|
|
1460
|
+
selected: false
|
|
1461
|
+
}));
|
|
1462
|
+
const { services } = await inquirer.prompt({
|
|
1463
|
+
type: "checkbox",
|
|
1464
|
+
name: "services",
|
|
1465
|
+
message: i18n.selectMcpServices,
|
|
1466
|
+
choices
|
|
1467
|
+
});
|
|
1468
|
+
if (services === void 0) {
|
|
1469
|
+
console.log(ansis.yellow(i18n.cancelled));
|
|
1470
|
+
return void 0;
|
|
1471
|
+
}
|
|
1472
|
+
return services;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1382
1475
|
async function init(options = {}) {
|
|
1383
1476
|
try {
|
|
1384
1477
|
if (!options.skipBanner) {
|
|
@@ -1386,38 +1479,43 @@ async function init(options = {}) {
|
|
|
1386
1479
|
}
|
|
1387
1480
|
const scriptLang = await selectScriptLanguage(options.lang);
|
|
1388
1481
|
const i18n = I18N[scriptLang];
|
|
1482
|
+
if (isTermux()) {
|
|
1483
|
+
console.log(ansis.yellow(`
|
|
1484
|
+
\u2139 ${i18n.termuxDetected}`));
|
|
1485
|
+
console.log(ansis.gray(i18n.termuxEnvironmentInfo));
|
|
1486
|
+
}
|
|
1389
1487
|
let configLang = options.configLang;
|
|
1390
1488
|
if (!configLang) {
|
|
1391
|
-
const
|
|
1392
|
-
type: "
|
|
1489
|
+
const { lang } = await inquirer.prompt({
|
|
1490
|
+
type: "list",
|
|
1393
1491
|
name: "lang",
|
|
1394
1492
|
message: i18n.selectConfigLang,
|
|
1395
1493
|
choices: SUPPORTED_LANGS.map((l) => ({
|
|
1396
|
-
|
|
1494
|
+
name: `${LANG_LABELS[l]} - ${i18n.configLangHint[l]}`,
|
|
1397
1495
|
value: l
|
|
1398
1496
|
}))
|
|
1399
1497
|
});
|
|
1400
|
-
if (!
|
|
1498
|
+
if (!lang) {
|
|
1401
1499
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1402
1500
|
process.exit(0);
|
|
1403
1501
|
}
|
|
1404
|
-
configLang =
|
|
1502
|
+
configLang = lang;
|
|
1405
1503
|
}
|
|
1406
1504
|
const zcfConfig = readZcfConfig();
|
|
1407
1505
|
const aiOutputLang = await resolveAiOutputLanguage(scriptLang, options.aiOutputLang, zcfConfig);
|
|
1408
1506
|
const installed = await isClaudeCodeInstalled();
|
|
1409
1507
|
if (!installed) {
|
|
1410
|
-
const
|
|
1508
|
+
const { shouldInstall } = await inquirer.prompt({
|
|
1411
1509
|
type: "confirm",
|
|
1412
1510
|
name: "shouldInstall",
|
|
1413
1511
|
message: i18n.installPrompt,
|
|
1414
|
-
|
|
1512
|
+
default: true
|
|
1415
1513
|
});
|
|
1416
|
-
if (
|
|
1514
|
+
if (shouldInstall === void 0) {
|
|
1417
1515
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1418
1516
|
process.exit(0);
|
|
1419
1517
|
}
|
|
1420
|
-
if (
|
|
1518
|
+
if (shouldInstall) {
|
|
1421
1519
|
await installClaudeCode(scriptLang);
|
|
1422
1520
|
} else {
|
|
1423
1521
|
console.log(ansis.yellow(i18n.skip));
|
|
@@ -1426,36 +1524,32 @@ async function init(options = {}) {
|
|
|
1426
1524
|
console.log(ansis.green(`\u2714 ${i18n.installSuccess}`));
|
|
1427
1525
|
}
|
|
1428
1526
|
ensureClaudeDir();
|
|
1429
|
-
let onlyUpdateDocs = false;
|
|
1430
1527
|
let action = "new";
|
|
1431
1528
|
if (existsSync(SETTINGS_FILE) && !options.force) {
|
|
1432
|
-
const
|
|
1433
|
-
type: "
|
|
1529
|
+
const { action: userAction } = await inquirer.prompt({
|
|
1530
|
+
type: "list",
|
|
1434
1531
|
name: "action",
|
|
1435
1532
|
message: i18n.existingConfig,
|
|
1436
1533
|
choices: [
|
|
1437
|
-
{
|
|
1438
|
-
{
|
|
1439
|
-
{
|
|
1440
|
-
{
|
|
1534
|
+
{ name: i18n.backupAndOverwrite, value: "backup" },
|
|
1535
|
+
{ name: i18n.updateDocsOnly, value: "docs-only" },
|
|
1536
|
+
{ name: i18n.mergeConfig, value: "merge" },
|
|
1537
|
+
{ name: i18n.skip, value: "skip" }
|
|
1441
1538
|
]
|
|
1442
1539
|
});
|
|
1443
|
-
if (!
|
|
1540
|
+
if (!userAction) {
|
|
1444
1541
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1445
1542
|
process.exit(0);
|
|
1446
1543
|
}
|
|
1447
|
-
action =
|
|
1544
|
+
action = userAction;
|
|
1448
1545
|
if (action === "skip") {
|
|
1449
1546
|
console.log(ansis.yellow(i18n.skip));
|
|
1450
1547
|
return;
|
|
1451
1548
|
}
|
|
1452
|
-
if (action === "docs-only") {
|
|
1453
|
-
onlyUpdateDocs = true;
|
|
1454
|
-
}
|
|
1455
1549
|
}
|
|
1456
1550
|
let apiConfig = null;
|
|
1457
1551
|
const isNewInstall = !existsSync(SETTINGS_FILE);
|
|
1458
|
-
if (
|
|
1552
|
+
if (action !== "docs-only" && (isNewInstall || ["backup", "merge"].includes(action))) {
|
|
1459
1553
|
const existingApiConfig = getExistingApiConfig();
|
|
1460
1554
|
if (existingApiConfig) {
|
|
1461
1555
|
console.log("\n" + ansis.blue(`\u2139 ${i18n.existingApiConfig}`));
|
|
@@ -1467,84 +1561,74 @@ async function init(options = {}) {
|
|
|
1467
1561
|
);
|
|
1468
1562
|
console.log(ansis.gray(` ${i18n.apiConfigAuthType}: ${existingApiConfig.authType || i18n.notConfigured}
|
|
1469
1563
|
`));
|
|
1470
|
-
const
|
|
1471
|
-
type: "
|
|
1564
|
+
const { action: apiAction } = await inquirer.prompt({
|
|
1565
|
+
type: "list",
|
|
1472
1566
|
name: "action",
|
|
1473
1567
|
message: i18n.selectApiAction,
|
|
1474
1568
|
choices: [
|
|
1475
|
-
{
|
|
1476
|
-
{
|
|
1477
|
-
{
|
|
1478
|
-
{
|
|
1569
|
+
{ name: i18n.keepExistingConfig, value: "keep" },
|
|
1570
|
+
{ name: i18n.modifyAllConfig, value: "modify-all" },
|
|
1571
|
+
{ name: i18n.modifyPartialConfig, value: "modify-partial" },
|
|
1572
|
+
{ name: i18n.skipApi, value: "skip" }
|
|
1479
1573
|
]
|
|
1480
1574
|
});
|
|
1481
|
-
if (!
|
|
1575
|
+
if (!apiAction) {
|
|
1482
1576
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1483
1577
|
process.exit(0);
|
|
1484
1578
|
}
|
|
1485
|
-
if (
|
|
1579
|
+
if (apiAction === "keep" || apiAction === "skip") {
|
|
1486
1580
|
apiConfig = null;
|
|
1487
|
-
} else if (
|
|
1581
|
+
} else if (apiAction === "modify-partial") {
|
|
1488
1582
|
await modifyApiConfigPartially(existingApiConfig, i18n, scriptLang);
|
|
1489
1583
|
apiConfig = null;
|
|
1490
|
-
} else if (
|
|
1584
|
+
} else if (apiAction === "modify-all") {
|
|
1491
1585
|
apiConfig = await configureApiCompletely(i18n, scriptLang);
|
|
1492
1586
|
}
|
|
1493
1587
|
} else {
|
|
1494
|
-
const
|
|
1495
|
-
type: "
|
|
1588
|
+
const { apiChoice } = await inquirer.prompt({
|
|
1589
|
+
type: "list",
|
|
1496
1590
|
name: "apiChoice",
|
|
1497
1591
|
message: i18n.configureApi,
|
|
1498
1592
|
choices: [
|
|
1499
1593
|
{
|
|
1500
|
-
|
|
1594
|
+
name: `${i18n.useAuthToken} - ${ansis.gray(i18n.authTokenDesc)}`,
|
|
1501
1595
|
value: "auth_token",
|
|
1502
|
-
|
|
1596
|
+
short: i18n.useAuthToken
|
|
1503
1597
|
},
|
|
1504
1598
|
{
|
|
1505
|
-
|
|
1599
|
+
name: `${i18n.useApiKey} - ${ansis.gray(i18n.apiKeyDesc)}`,
|
|
1506
1600
|
value: "api_key",
|
|
1507
|
-
|
|
1601
|
+
short: i18n.useApiKey
|
|
1508
1602
|
},
|
|
1509
1603
|
{
|
|
1510
|
-
|
|
1604
|
+
name: i18n.skipApi,
|
|
1511
1605
|
value: "skip"
|
|
1512
1606
|
}
|
|
1513
1607
|
]
|
|
1514
1608
|
});
|
|
1515
|
-
if (!
|
|
1609
|
+
if (!apiChoice) {
|
|
1516
1610
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1517
1611
|
process.exit(0);
|
|
1518
1612
|
}
|
|
1519
|
-
if (
|
|
1520
|
-
apiConfig = await configureApiCompletely(i18n, scriptLang,
|
|
1613
|
+
if (apiChoice !== "skip") {
|
|
1614
|
+
apiConfig = await configureApiCompletely(i18n, scriptLang, apiChoice);
|
|
1521
1615
|
}
|
|
1522
1616
|
}
|
|
1523
1617
|
}
|
|
1524
|
-
if (
|
|
1525
|
-
const backupDir = backupExistingConfig();
|
|
1526
|
-
if (backupDir) {
|
|
1527
|
-
console.log(ansis.gray(`\u2714 ${i18n.backupSuccess}: ${backupDir}`));
|
|
1528
|
-
}
|
|
1529
|
-
copyConfigFiles(configLang, false);
|
|
1530
|
-
} else if (action === "docs-only") {
|
|
1618
|
+
if (["backup", "docs-only", "merge"].includes(action)) {
|
|
1531
1619
|
const backupDir = backupExistingConfig();
|
|
1532
1620
|
if (backupDir) {
|
|
1533
1621
|
console.log(ansis.gray(`\u2714 ${i18n.backupSuccess}: ${backupDir}`));
|
|
1534
1622
|
}
|
|
1623
|
+
}
|
|
1624
|
+
if (action === "docs-only") {
|
|
1535
1625
|
copyConfigFiles(configLang, true);
|
|
1536
|
-
} else if (
|
|
1537
|
-
const backupDir = backupExistingConfig();
|
|
1538
|
-
if (backupDir) {
|
|
1539
|
-
console.log(ansis.gray(`\u2714 ${i18n.backupSuccess}: ${backupDir}`));
|
|
1540
|
-
}
|
|
1541
|
-
copyConfigFiles(configLang, false);
|
|
1542
|
-
} else if (action === "new") {
|
|
1626
|
+
} else if (["backup", "merge", "new"].includes(action)) {
|
|
1543
1627
|
copyConfigFiles(configLang, false);
|
|
1544
1628
|
}
|
|
1545
1629
|
applyAiLanguageDirective(aiOutputLang);
|
|
1546
1630
|
await configureAiPersonality(scriptLang);
|
|
1547
|
-
if (apiConfig &&
|
|
1631
|
+
if (apiConfig && action !== "docs-only") {
|
|
1548
1632
|
const configuredApi = configureApi(apiConfig);
|
|
1549
1633
|
if (configuredApi) {
|
|
1550
1634
|
console.log(ansis.green(`\u2714 ${i18n.apiConfigSuccess}`));
|
|
@@ -1557,18 +1641,18 @@ async function init(options = {}) {
|
|
|
1557
1641
|
}
|
|
1558
1642
|
}
|
|
1559
1643
|
}
|
|
1560
|
-
if (
|
|
1561
|
-
const
|
|
1644
|
+
if (action !== "docs-only") {
|
|
1645
|
+
const { shouldConfigureMcp } = await inquirer.prompt({
|
|
1562
1646
|
type: "confirm",
|
|
1563
1647
|
name: "shouldConfigureMcp",
|
|
1564
1648
|
message: i18n.configureMcp,
|
|
1565
|
-
|
|
1649
|
+
default: true
|
|
1566
1650
|
});
|
|
1567
|
-
if (
|
|
1651
|
+
if (shouldConfigureMcp === void 0) {
|
|
1568
1652
|
console.log(ansis.yellow(i18n.cancelled));
|
|
1569
1653
|
process.exit(0);
|
|
1570
1654
|
}
|
|
1571
|
-
if (
|
|
1655
|
+
if (shouldConfigureMcp) {
|
|
1572
1656
|
if (isWindows()) {
|
|
1573
1657
|
console.log(
|
|
1574
1658
|
ansis.blue(
|
|
@@ -1576,34 +1660,10 @@ async function init(options = {}) {
|
|
|
1576
1660
|
)
|
|
1577
1661
|
);
|
|
1578
1662
|
}
|
|
1579
|
-
const
|
|
1580
|
-
|
|
1581
|
-
title: ansis.bold(i18n.allServices),
|
|
1582
|
-
value: "ALL",
|
|
1583
|
-
selected: false
|
|
1584
|
-
},
|
|
1585
|
-
...MCP_SERVICES.map((service) => ({
|
|
1586
|
-
title: `${service.name[scriptLang]} - ${ansis.gray(service.description[scriptLang])}`,
|
|
1587
|
-
value: service.id,
|
|
1588
|
-
selected: false
|
|
1589
|
-
}))
|
|
1590
|
-
];
|
|
1591
|
-
const selectedResponse = await prompts({
|
|
1592
|
-
type: "multiselect",
|
|
1593
|
-
name: "services",
|
|
1594
|
-
message: i18n.selectMcpServices,
|
|
1595
|
-
choices,
|
|
1596
|
-
instructions: false,
|
|
1597
|
-
hint: i18n.spaceToSelectReturn
|
|
1598
|
-
});
|
|
1599
|
-
if (selectedResponse.services === void 0) {
|
|
1600
|
-
console.log(ansis.yellow(i18n.cancelled));
|
|
1663
|
+
const selectedServices = await selectMcpServices(scriptLang);
|
|
1664
|
+
if (selectedServices === void 0) {
|
|
1601
1665
|
process.exit(0);
|
|
1602
1666
|
}
|
|
1603
|
-
let selectedServices = selectedResponse.services || [];
|
|
1604
|
-
if (selectedServices.includes("ALL")) {
|
|
1605
|
-
selectedServices = MCP_SERVICES.map((s) => s.id);
|
|
1606
|
-
}
|
|
1607
1667
|
if (selectedServices.length > 0) {
|
|
1608
1668
|
const mcpBackupPath = backupMcpConfig();
|
|
1609
1669
|
if (mcpBackupPath) {
|
|
@@ -1615,18 +1675,18 @@ async function init(options = {}) {
|
|
|
1615
1675
|
if (!service) continue;
|
|
1616
1676
|
let config = service.config;
|
|
1617
1677
|
if (service.requiresApiKey) {
|
|
1618
|
-
const
|
|
1619
|
-
type: "
|
|
1678
|
+
const { apiKey } = await inquirer.prompt({
|
|
1679
|
+
type: "input",
|
|
1620
1680
|
name: "apiKey",
|
|
1621
1681
|
message: service.apiKeyPrompt[scriptLang],
|
|
1622
1682
|
validate: (value) => !!value || i18n.keyRequired
|
|
1623
1683
|
});
|
|
1624
|
-
if (
|
|
1684
|
+
if (apiKey === void 0) {
|
|
1625
1685
|
console.log(ansis.yellow(`${i18n.skip}: ${service.name[scriptLang]}`));
|
|
1626
1686
|
continue;
|
|
1627
1687
|
}
|
|
1628
|
-
if (
|
|
1629
|
-
config = buildMcpServerConfig(service.config,
|
|
1688
|
+
if (apiKey) {
|
|
1689
|
+
config = buildMcpServerConfig(service.config, apiKey, service.apiKeyPlaceholder);
|
|
1630
1690
|
} else {
|
|
1631
1691
|
continue;
|
|
1632
1692
|
}
|
|
@@ -1653,9 +1713,10 @@ async function init(options = {}) {
|
|
|
1653
1713
|
console.log(ansis.green(`\u2714 ${i18n.configSuccess} ${CLAUDE_DIR}`));
|
|
1654
1714
|
console.log("\n" + ansis.cyan(i18n.complete));
|
|
1655
1715
|
} catch (error) {
|
|
1656
|
-
|
|
1657
|
-
|
|
1716
|
+
if (!handleExitPromptError(error)) {
|
|
1717
|
+
handleGeneralError(error, options.lang);
|
|
1718
|
+
}
|
|
1658
1719
|
}
|
|
1659
1720
|
}
|
|
1660
1721
|
|
|
1661
|
-
export { AI_OUTPUT_LANGUAGES as A,
|
|
1722
|
+
export { AI_OUTPUT_LANGUAGES as A, readZcfConfig as B, CLAUDE_DIR as C, resolveAiOutputLanguage as D, configureAiPersonality as E, isWindows as F, selectMcpServices as G, formatApiKeyDisplay as H, I18N as I, modifyApiConfigPartially as J, validateApiKey as K, LANG_LABELS as L, MCP_SERVICES as M, displayBanner as N, selectScriptLanguage as O, updatePromptOnly as P, version as Q, handleExitPromptError as R, SETTINGS_FILE as S, handleGeneralError as T, displayBannerWithInfo as U, ZCF_CONFIG_FILE as Z, CLAUDE_MD_FILE as a, ClAUDE_CONFIG_FILE as b, commandExists as c, SUPPORTED_LANGS as d, isClaudeCodeInstalled as e, installClaudeCode as f, getPlatform as g, ensureClaudeDir as h, init as i, backupExistingConfig as j, copyConfigFiles as k, configureApi as l, mergeConfigs as m, mergeSettingsFile as n, getExistingApiConfig as o, applyAiLanguageDirective as p, getMcpConfigPath as q, readMcpConfig as r, backupMcpConfig as s, mergeMcpServers as t, updateDefaultModel as u, buildMcpServerConfig as v, writeMcpConfig as w, fixWindowsMcpConfig as x, addCompletedOnboarding as y, updateZcfConfig as z };
|