zcf 2.7.1 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -16
- package/bin/zcf.mjs +1 -1
- package/dist/cli.mjs +413 -127
- package/dist/index.d.mts +15 -238
- package/dist/index.d.ts +15 -238
- package/dist/index.mjs +4 -1
- package/dist/shared/{zcf.CZ3RjfyP.mjs → zcf.CLtDS8Pu.mjs} +1073 -341
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,82 +1,126 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import cac from 'cac';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
|
-
import {
|
|
4
|
+
import { H as getTranslation, Z as ZCF_CONFIG_FILE, h as SUPPORTED_LANGS, J as addNumbersToChoices, j as LANG_LABELS, K as updateZcfConfig, o as openSettingsJson, b as importRecommendedPermissions, a as importRecommendedEnv, N as readZcfConfig, O as resolveAiOutputLanguage, w as applyAiLanguageDirective, P as configureAiPersonality, u as updateDefaultModel, Q as isWindows, y as readMcpConfig, F as fixWindowsMcpConfig, z as writeMcpConfig, R as selectMcpServices, B as backupMcpConfig, M as MCP_SERVICES, E as buildMcpServerConfig, D as mergeMcpServers, v as getExistingApiConfig, T as formatApiKeyDisplay, G as addCompletedOnboarding, U as modifyApiConfigPartially, V as isCcrInstalled, W as installCcr, X as setupCcrConfiguration, Y as validateApiKey, r as configureApi, _ as readZcfConfigAsync, I as I18N, $ as readCcrConfig, a0 as configureCcrFeature, a1 as handleExitPromptError, a2 as handleGeneralError, a3 as displayBanner, a4 as selectScriptLanguage, a5 as updatePromptOnly, a6 as selectAndInstallWorkflows, a7 as version, a8 as displayBannerWithInfo, i as init } from './shared/zcf.CLtDS8Pu.mjs';
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
6
|
import { existsSync, unlinkSync } from 'node:fs';
|
|
7
7
|
import { x } from 'tinyexec';
|
|
8
|
+
import { homedir } from 'node:os';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { exec } from 'child_process';
|
|
11
|
+
import { promisify } from 'util';
|
|
8
12
|
import 'pathe';
|
|
9
13
|
import 'dayjs';
|
|
10
14
|
import 'node:url';
|
|
11
15
|
import 'node:fs/promises';
|
|
12
|
-
import 'node:
|
|
16
|
+
import 'node:child_process';
|
|
17
|
+
import 'node:util';
|
|
13
18
|
|
|
14
19
|
function handleCancellation(scriptLang) {
|
|
15
|
-
|
|
20
|
+
const i18n = getTranslation(scriptLang);
|
|
21
|
+
console.log(ansis.yellow(i18n.common.cancelled));
|
|
16
22
|
}
|
|
17
23
|
async function configureApiFeature(scriptLang) {
|
|
18
|
-
const i18n =
|
|
24
|
+
const i18n = getTranslation(scriptLang);
|
|
19
25
|
const existingApiConfig = getExistingApiConfig();
|
|
20
26
|
if (existingApiConfig) {
|
|
21
|
-
console.log("\n" + ansis.blue(`\u2139 ${i18n.existingApiConfig}`));
|
|
22
|
-
console.log(ansis.gray(` ${i18n.apiConfigUrl}: ${existingApiConfig.url || i18n.notConfigured}`));
|
|
23
|
-
console.log(ansis.gray(` ${i18n.apiConfigKey}: ${existingApiConfig.key ? formatApiKeyDisplay(existingApiConfig.key) : i18n.notConfigured}`));
|
|
24
|
-
console.log(ansis.gray(` ${i18n.apiConfigAuthType}: ${existingApiConfig.authType || i18n.notConfigured}
|
|
27
|
+
console.log("\n" + ansis.blue(`\u2139 ${i18n.api.existingApiConfig}`));
|
|
28
|
+
console.log(ansis.gray(` ${i18n.api.apiConfigUrl}: ${existingApiConfig.url || i18n.common.notConfigured}`));
|
|
29
|
+
console.log(ansis.gray(` ${i18n.api.apiConfigKey}: ${existingApiConfig.key ? formatApiKeyDisplay(existingApiConfig.key) : i18n.common.notConfigured}`));
|
|
30
|
+
console.log(ansis.gray(` ${i18n.api.apiConfigAuthType}: ${existingApiConfig.authType || i18n.common.notConfigured}
|
|
25
31
|
`));
|
|
26
32
|
const { action } = await inquirer.prompt({
|
|
27
33
|
type: "list",
|
|
28
34
|
name: "action",
|
|
29
|
-
message: i18n.selectApiAction,
|
|
30
|
-
choices: [
|
|
31
|
-
{ name: i18n.keepExistingConfig, value: "keep" },
|
|
32
|
-
{ name: i18n.modifyAllConfig, value: "modify-all" },
|
|
33
|
-
{ name: i18n.modifyPartialConfig, value: "modify-partial" }
|
|
34
|
-
|
|
35
|
+
message: i18n.api.selectApiAction,
|
|
36
|
+
choices: addNumbersToChoices([
|
|
37
|
+
{ name: i18n.api.keepExistingConfig, value: "keep" },
|
|
38
|
+
{ name: i18n.api.modifyAllConfig, value: "modify-all" },
|
|
39
|
+
{ name: i18n.api.modifyPartialConfig, value: "modify-partial" },
|
|
40
|
+
{ name: i18n.api.useCcrProxy, value: "use-ccr" }
|
|
41
|
+
])
|
|
35
42
|
});
|
|
36
43
|
if (!action) {
|
|
37
44
|
handleCancellation(scriptLang);
|
|
38
45
|
return;
|
|
39
46
|
}
|
|
40
47
|
if (action === "keep") {
|
|
41
|
-
console.log(ansis.green(`\u2714 ${i18n.keepExistingConfig}`));
|
|
48
|
+
console.log(ansis.green(`\u2714 ${i18n.api.keepExistingConfig}`));
|
|
49
|
+
try {
|
|
50
|
+
addCompletedOnboarding();
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error(ansis.red(i18n.configuration.failedToSetOnboarding), error);
|
|
53
|
+
}
|
|
42
54
|
return;
|
|
43
55
|
} else if (action === "modify-partial") {
|
|
44
56
|
await modifyApiConfigPartially(existingApiConfig, i18n, scriptLang);
|
|
45
57
|
return;
|
|
58
|
+
} else if (action === "use-ccr") {
|
|
59
|
+
const ccrInstalled = await isCcrInstalled();
|
|
60
|
+
if (!ccrInstalled) {
|
|
61
|
+
console.log(ansis.yellow(`${i18n.ccr.installingCcr}`));
|
|
62
|
+
await installCcr(scriptLang);
|
|
63
|
+
} else {
|
|
64
|
+
console.log(ansis.green(`\u2714 ${i18n.ccr.ccrAlreadyInstalled}`));
|
|
65
|
+
}
|
|
66
|
+
const ccrConfigured = await setupCcrConfiguration(scriptLang);
|
|
67
|
+
if (ccrConfigured) {
|
|
68
|
+
console.log(ansis.green(`\u2714 ${i18n.ccr.ccrSetupComplete}`));
|
|
69
|
+
}
|
|
70
|
+
return;
|
|
46
71
|
}
|
|
47
72
|
}
|
|
48
73
|
const { apiChoice } = await inquirer.prompt({
|
|
49
74
|
type: "list",
|
|
50
75
|
name: "apiChoice",
|
|
51
|
-
message: i18n.configureApi,
|
|
52
|
-
choices: [
|
|
76
|
+
message: i18n.api.configureApi,
|
|
77
|
+
choices: addNumbersToChoices([
|
|
53
78
|
{
|
|
54
|
-
name: `${i18n.useAuthToken} - ${ansis.gray(i18n.authTokenDesc)}`,
|
|
79
|
+
name: `${i18n.api.useAuthToken} - ${ansis.gray(i18n.api.authTokenDesc)}`,
|
|
55
80
|
value: "auth_token",
|
|
56
|
-
short: i18n.useAuthToken
|
|
81
|
+
short: i18n.api.useAuthToken
|
|
57
82
|
},
|
|
58
83
|
{
|
|
59
|
-
name: `${i18n.useApiKey} - ${ansis.gray(i18n.apiKeyDesc)}`,
|
|
84
|
+
name: `${i18n.api.useApiKey} - ${ansis.gray(i18n.api.apiKeyDesc)}`,
|
|
60
85
|
value: "api_key",
|
|
61
|
-
short: i18n.useApiKey
|
|
86
|
+
short: i18n.api.useApiKey
|
|
62
87
|
},
|
|
63
|
-
{
|
|
64
|
-
|
|
88
|
+
{
|
|
89
|
+
name: `${i18n.api.useCcrProxy} - ${ansis.gray(i18n.api.ccrProxyDesc)}`,
|
|
90
|
+
value: "ccr_proxy",
|
|
91
|
+
short: i18n.api.useCcrProxy
|
|
92
|
+
},
|
|
93
|
+
{ name: i18n.api.skipApi, value: "skip" }
|
|
94
|
+
])
|
|
65
95
|
});
|
|
66
96
|
if (!apiChoice || apiChoice === "skip") {
|
|
67
97
|
return;
|
|
68
98
|
}
|
|
99
|
+
if (apiChoice === "ccr_proxy") {
|
|
100
|
+
const ccrInstalled = await isCcrInstalled();
|
|
101
|
+
if (!ccrInstalled) {
|
|
102
|
+
console.log(ansis.yellow(`${i18n.ccr.installingCcr}`));
|
|
103
|
+
await installCcr(scriptLang);
|
|
104
|
+
} else {
|
|
105
|
+
console.log(ansis.green(`\u2714 ${i18n.ccr.ccrAlreadyInstalled}`));
|
|
106
|
+
}
|
|
107
|
+
const ccrConfigured = await setupCcrConfiguration(scriptLang);
|
|
108
|
+
if (ccrConfigured) {
|
|
109
|
+
console.log(ansis.green(`\u2714 ${i18n.ccr.ccrSetupComplete}`));
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
69
113
|
const { url } = await inquirer.prompt({
|
|
70
114
|
type: "input",
|
|
71
115
|
name: "url",
|
|
72
|
-
message: i18n.enterApiUrl,
|
|
116
|
+
message: i18n.api.enterApiUrl,
|
|
73
117
|
validate: (value) => {
|
|
74
|
-
if (!value) return i18n.urlRequired;
|
|
118
|
+
if (!value) return i18n.api.urlRequired;
|
|
75
119
|
try {
|
|
76
120
|
new URL(value);
|
|
77
121
|
return true;
|
|
78
122
|
} catch {
|
|
79
|
-
return i18n.invalidUrl;
|
|
123
|
+
return i18n.api.invalidUrl;
|
|
80
124
|
}
|
|
81
125
|
}
|
|
82
126
|
});
|
|
@@ -84,18 +128,18 @@ async function configureApiFeature(scriptLang) {
|
|
|
84
128
|
handleCancellation(scriptLang);
|
|
85
129
|
return;
|
|
86
130
|
}
|
|
87
|
-
const keyMessage = apiChoice === "auth_token" ? i18n.enterAuthToken : i18n.enterApiKey;
|
|
131
|
+
const keyMessage = apiChoice === "auth_token" ? i18n.api.enterAuthToken : i18n.api.enterApiKey;
|
|
88
132
|
const { key } = await inquirer.prompt({
|
|
89
133
|
type: "input",
|
|
90
134
|
name: "key",
|
|
91
135
|
message: keyMessage,
|
|
92
136
|
validate: (value) => {
|
|
93
137
|
if (!value) {
|
|
94
|
-
return i18n.keyRequired;
|
|
138
|
+
return i18n.api.keyRequired;
|
|
95
139
|
}
|
|
96
140
|
const validation = validateApiKey(value, scriptLang);
|
|
97
141
|
if (!validation.isValid) {
|
|
98
|
-
return validation.error || i18n.invalidKeyFormat;
|
|
142
|
+
return validation.error || i18n.api.invalidKeyFormat;
|
|
99
143
|
}
|
|
100
144
|
return true;
|
|
101
145
|
}
|
|
@@ -107,25 +151,25 @@ async function configureApiFeature(scriptLang) {
|
|
|
107
151
|
const apiConfig = { url, key, authType: apiChoice };
|
|
108
152
|
const configuredApi = configureApi(apiConfig);
|
|
109
153
|
if (configuredApi) {
|
|
110
|
-
console.log(ansis.green(`\u2714 ${i18n.apiConfigSuccess}`));
|
|
154
|
+
console.log(ansis.green(`\u2714 ${i18n.api.apiConfigSuccess}`));
|
|
111
155
|
console.log(ansis.gray(` URL: ${configuredApi.url}`));
|
|
112
156
|
console.log(ansis.gray(` Key: ${formatApiKeyDisplay(configuredApi.key)}`));
|
|
113
157
|
}
|
|
114
158
|
}
|
|
115
159
|
async function configureMcpFeature(scriptLang) {
|
|
116
|
-
const i18n =
|
|
160
|
+
const i18n = getTranslation(scriptLang);
|
|
117
161
|
if (isWindows()) {
|
|
118
162
|
const { fixWindows } = await inquirer.prompt({
|
|
119
163
|
type: "confirm",
|
|
120
164
|
name: "fixWindows",
|
|
121
|
-
message: i18n.fixWindowsMcp || "Fix Windows MCP configuration?",
|
|
165
|
+
message: i18n.configuration.fixWindowsMcp || "Fix Windows MCP configuration?",
|
|
122
166
|
default: true
|
|
123
167
|
});
|
|
124
168
|
if (fixWindows) {
|
|
125
169
|
const existingConfig = readMcpConfig() || { mcpServers: {} };
|
|
126
170
|
const fixedConfig = fixWindowsMcpConfig(existingConfig);
|
|
127
171
|
writeMcpConfig(fixedConfig);
|
|
128
|
-
console.log(ansis.green(`\u2714
|
|
172
|
+
console.log(ansis.green(`\u2714 Windows MCP configuration fixed`));
|
|
129
173
|
}
|
|
130
174
|
}
|
|
131
175
|
const selectedServices = await selectMcpServices(scriptLang);
|
|
@@ -135,7 +179,7 @@ async function configureMcpFeature(scriptLang) {
|
|
|
135
179
|
if (selectedServices.length > 0) {
|
|
136
180
|
const mcpBackupPath = backupMcpConfig();
|
|
137
181
|
if (mcpBackupPath) {
|
|
138
|
-
console.log(ansis.gray(`\u2714 ${i18n.mcpBackupSuccess}: ${mcpBackupPath}`));
|
|
182
|
+
console.log(ansis.gray(`\u2714 ${i18n.mcp.mcpBackupSuccess}: ${mcpBackupPath}`));
|
|
139
183
|
}
|
|
140
184
|
const newServers = {};
|
|
141
185
|
for (const serviceId of selectedServices) {
|
|
@@ -147,7 +191,7 @@ async function configureMcpFeature(scriptLang) {
|
|
|
147
191
|
type: "input",
|
|
148
192
|
name: "apiKey",
|
|
149
193
|
message: service.apiKeyPrompt[scriptLang],
|
|
150
|
-
validate: (value) => !!value || i18n.keyRequired
|
|
194
|
+
validate: (value) => !!value || i18n.api.keyRequired
|
|
151
195
|
});
|
|
152
196
|
if (apiKey) {
|
|
153
197
|
config = buildMcpServerConfig(service.config, apiKey, service.apiKeyPlaceholder, service.apiKeyEnvVar);
|
|
@@ -161,43 +205,42 @@ async function configureMcpFeature(scriptLang) {
|
|
|
161
205
|
let mergedConfig = mergeMcpServers(existingConfig, newServers);
|
|
162
206
|
mergedConfig = fixWindowsMcpConfig(mergedConfig);
|
|
163
207
|
writeMcpConfig(mergedConfig);
|
|
164
|
-
console.log(ansis.green(`\u2714 ${i18n.mcpConfigSuccess}`));
|
|
208
|
+
console.log(ansis.green(`\u2714 ${i18n.mcp.mcpConfigSuccess}`));
|
|
165
209
|
}
|
|
166
210
|
}
|
|
167
211
|
async function configureDefaultModelFeature(scriptLang) {
|
|
168
|
-
const i18n = I18N[scriptLang];
|
|
169
212
|
const { model } = await inquirer.prompt({
|
|
170
213
|
type: "list",
|
|
171
214
|
name: "model",
|
|
172
|
-
message:
|
|
173
|
-
choices: [
|
|
215
|
+
message: "Select default model",
|
|
216
|
+
choices: addNumbersToChoices([
|
|
174
217
|
{ name: "Opus", value: "opus" },
|
|
175
218
|
{ name: "Sonnet", value: "sonnet" }
|
|
176
|
-
]
|
|
219
|
+
])
|
|
177
220
|
});
|
|
178
221
|
if (!model) {
|
|
179
222
|
handleCancellation(scriptLang);
|
|
180
223
|
return;
|
|
181
224
|
}
|
|
182
225
|
updateDefaultModel(model);
|
|
183
|
-
console.log(ansis.green(`\u2714
|
|
226
|
+
console.log(ansis.green(`\u2714 Default model configured`));
|
|
184
227
|
}
|
|
185
228
|
async function configureAiMemoryFeature(scriptLang) {
|
|
186
|
-
const i18n =
|
|
229
|
+
const i18n = getTranslation(scriptLang);
|
|
187
230
|
const { option } = await inquirer.prompt({
|
|
188
231
|
type: "list",
|
|
189
232
|
name: "option",
|
|
190
|
-
message:
|
|
191
|
-
choices: [
|
|
233
|
+
message: "Select configuration option",
|
|
234
|
+
choices: addNumbersToChoices([
|
|
192
235
|
{
|
|
193
|
-
name: i18n.configureAiLanguage || "Configure AI output language",
|
|
236
|
+
name: i18n.configuration.configureAiLanguage || "Configure AI output language",
|
|
194
237
|
value: "language"
|
|
195
238
|
},
|
|
196
239
|
{
|
|
197
|
-
name: i18n.configureAiPersonality || "Configure AI personality",
|
|
240
|
+
name: i18n.configuration.configureAiPersonality || "Configure AI personality",
|
|
198
241
|
value: "personality"
|
|
199
242
|
}
|
|
200
|
-
]
|
|
243
|
+
])
|
|
201
244
|
});
|
|
202
245
|
if (!option) {
|
|
203
246
|
return;
|
|
@@ -207,17 +250,17 @@ async function configureAiMemoryFeature(scriptLang) {
|
|
|
207
250
|
const aiOutputLang = await resolveAiOutputLanguage(scriptLang, void 0, zcfConfig);
|
|
208
251
|
applyAiLanguageDirective(aiOutputLang);
|
|
209
252
|
updateZcfConfig({ aiOutputLang });
|
|
210
|
-
console.log(ansis.green(`\u2714 ${i18n.aiLanguageConfigured || "AI output language configured"}`));
|
|
253
|
+
console.log(ansis.green(`\u2714 ${i18n.configuration.aiLanguageConfigured || "AI output language configured"}`));
|
|
211
254
|
} else {
|
|
212
255
|
await configureAiPersonality(scriptLang);
|
|
213
256
|
}
|
|
214
257
|
}
|
|
215
258
|
async function clearZcfCacheFeature(scriptLang) {
|
|
216
|
-
const i18n =
|
|
259
|
+
const i18n = getTranslation(scriptLang);
|
|
217
260
|
const { confirm } = await inquirer.prompt({
|
|
218
261
|
type: "confirm",
|
|
219
262
|
name: "confirm",
|
|
220
|
-
message: i18n.confirmClearCache || "Clear all ZCF preferences cache?",
|
|
263
|
+
message: i18n.configuration.confirmClearCache || "Clear all ZCF preferences cache?",
|
|
221
264
|
default: false
|
|
222
265
|
});
|
|
223
266
|
if (!confirm) {
|
|
@@ -226,50 +269,51 @@ async function clearZcfCacheFeature(scriptLang) {
|
|
|
226
269
|
}
|
|
227
270
|
if (existsSync(ZCF_CONFIG_FILE)) {
|
|
228
271
|
unlinkSync(ZCF_CONFIG_FILE);
|
|
229
|
-
console.log(ansis.green(`\u2714 ${i18n.cacheCleared || "ZCF cache cleared"}`));
|
|
272
|
+
console.log(ansis.green(`\u2714 ${i18n.configuration.cacheCleared || "ZCF cache cleared"}`));
|
|
230
273
|
} else {
|
|
231
|
-
console.log(ansis.yellow(
|
|
274
|
+
console.log(ansis.yellow("No cache found"));
|
|
232
275
|
}
|
|
233
276
|
}
|
|
234
277
|
async function changeScriptLanguageFeature(currentLang) {
|
|
235
|
-
const i18n =
|
|
278
|
+
const i18n = getTranslation(currentLang);
|
|
236
279
|
const { lang } = await inquirer.prompt({
|
|
237
280
|
type: "list",
|
|
238
281
|
name: "lang",
|
|
239
|
-
message: i18n.selectScriptLang,
|
|
240
|
-
choices: SUPPORTED_LANGS.map((l) => ({
|
|
282
|
+
message: i18n.language.selectScriptLang,
|
|
283
|
+
choices: addNumbersToChoices(SUPPORTED_LANGS.map((l) => ({
|
|
241
284
|
name: LANG_LABELS[l],
|
|
242
285
|
value: l
|
|
243
|
-
})),
|
|
286
|
+
}))),
|
|
244
287
|
default: SUPPORTED_LANGS.indexOf(currentLang)
|
|
245
288
|
});
|
|
246
289
|
if (!lang) {
|
|
247
290
|
return currentLang;
|
|
248
291
|
}
|
|
249
292
|
updateZcfConfig({ preferredLang: lang });
|
|
250
|
-
|
|
293
|
+
const newI18n = getTranslation(lang);
|
|
294
|
+
console.log(ansis.green(`\u2714 ${newI18n.language.languageChanged || "Language changed"}`));
|
|
251
295
|
return lang;
|
|
252
296
|
}
|
|
253
297
|
async function configureEnvPermissionFeature(scriptLang) {
|
|
254
|
-
const i18n =
|
|
298
|
+
const i18n = getTranslation(scriptLang);
|
|
255
299
|
const { choice } = await inquirer.prompt({
|
|
256
300
|
type: "list",
|
|
257
301
|
name: "choice",
|
|
258
|
-
message: i18n.selectEnvPermissionOption,
|
|
259
|
-
choices: [
|
|
302
|
+
message: i18n.configuration?.selectEnvPermissionOption || "Select option",
|
|
303
|
+
choices: addNumbersToChoices([
|
|
260
304
|
{
|
|
261
|
-
name: `${i18n.importRecommendedEnv} ${ansis.gray("- " + i18n.importRecommendedEnvDesc)}`,
|
|
305
|
+
name: `${i18n.configuration?.importRecommendedEnv || "Import environment"} ${ansis.gray("- " + (i18n.configuration?.importRecommendedEnvDesc || "Import env settings"))}`,
|
|
262
306
|
value: "env"
|
|
263
307
|
},
|
|
264
308
|
{
|
|
265
|
-
name: `${i18n.importRecommendedPermissions} ${ansis.gray("- " + i18n.importRecommendedPermissionsDesc)}`,
|
|
309
|
+
name: `${i18n.configuration?.importRecommendedPermissions || "Import permissions"} ${ansis.gray("- " + (i18n.configuration?.importRecommendedPermissionsDesc || "Import permission settings"))}`,
|
|
266
310
|
value: "permissions"
|
|
267
311
|
},
|
|
268
312
|
{
|
|
269
|
-
name: `${i18n.openSettingsJson} ${ansis.gray("- " + i18n.openSettingsJsonDesc)}`,
|
|
313
|
+
name: `${i18n.configuration?.openSettingsJson || "Open settings"} ${ansis.gray("- " + (i18n.configuration?.openSettingsJsonDesc || "View settings file"))}`,
|
|
270
314
|
value: "open"
|
|
271
315
|
}
|
|
272
|
-
]
|
|
316
|
+
])
|
|
273
317
|
});
|
|
274
318
|
if (!choice) {
|
|
275
319
|
handleCancellation(scriptLang);
|
|
@@ -279,32 +323,37 @@ async function configureEnvPermissionFeature(scriptLang) {
|
|
|
279
323
|
switch (choice) {
|
|
280
324
|
case "env":
|
|
281
325
|
await importRecommendedEnv();
|
|
282
|
-
console.log(ansis.green(`\u2705 ${i18n.envImportSuccess}`));
|
|
326
|
+
console.log(ansis.green(`\u2705 ${i18n.configuration.envImportSuccess}`));
|
|
283
327
|
break;
|
|
284
328
|
case "permissions":
|
|
285
329
|
await importRecommendedPermissions();
|
|
286
|
-
console.log(ansis.green(`\u2705 ${i18n.permissionsImportSuccess}`));
|
|
330
|
+
console.log(ansis.green(`\u2705 ${i18n.configuration?.permissionsImportSuccess || "Permissions imported"}`));
|
|
287
331
|
break;
|
|
288
332
|
case "open":
|
|
289
|
-
console.log(ansis.cyan(i18n.openingSettingsJson));
|
|
333
|
+
console.log(ansis.cyan(i18n.configuration?.openingSettingsJson || "Opening settings.json..."));
|
|
290
334
|
await openSettingsJson();
|
|
291
335
|
break;
|
|
292
336
|
}
|
|
293
337
|
} catch (error) {
|
|
294
|
-
console.error(ansis.red(`${i18n.error}: ${error.message}`));
|
|
338
|
+
console.error(ansis.red(`${i18n.common.error}: ${error.message}`));
|
|
295
339
|
}
|
|
296
340
|
}
|
|
297
341
|
|
|
298
342
|
async function executeCcusage(args = []) {
|
|
299
343
|
try {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
344
|
+
let lang = "en";
|
|
345
|
+
try {
|
|
346
|
+
const zcfConfig = await readZcfConfigAsync();
|
|
347
|
+
const rawLang = zcfConfig?.preferredLang || "en";
|
|
348
|
+
lang = getValidLanguage(rawLang);
|
|
349
|
+
} catch {
|
|
350
|
+
lang = "en";
|
|
351
|
+
}
|
|
303
352
|
const i18n = I18N[lang];
|
|
304
353
|
const command = "npx";
|
|
305
|
-
const commandArgs = ["ccusage@latest", ...args];
|
|
306
|
-
console.log(ansis.cyan(i18n.runningCcusage));
|
|
307
|
-
console.log(ansis.gray(`$ npx ccusage@latest ${args.join(" ")}`));
|
|
354
|
+
const commandArgs = ["ccusage@latest", ...args || []];
|
|
355
|
+
console.log(ansis.cyan(i18n.tools.runningCcusage));
|
|
356
|
+
console.log(ansis.gray(`$ npx ccusage@latest ${(args || []).join(" ")}`));
|
|
308
357
|
console.log("");
|
|
309
358
|
await x(command, commandArgs, {
|
|
310
359
|
nodeOptions: {
|
|
@@ -312,14 +361,19 @@ async function executeCcusage(args = []) {
|
|
|
312
361
|
}
|
|
313
362
|
});
|
|
314
363
|
} catch (error) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
364
|
+
let lang = "en";
|
|
365
|
+
try {
|
|
366
|
+
const zcfConfig = await readZcfConfigAsync();
|
|
367
|
+
const rawLang = zcfConfig?.preferredLang || "en";
|
|
368
|
+
lang = getValidLanguage(rawLang);
|
|
369
|
+
} catch {
|
|
370
|
+
lang = "en";
|
|
371
|
+
}
|
|
318
372
|
const i18n = I18N[lang];
|
|
319
|
-
console.error(ansis.red(i18n.ccusageFailed));
|
|
320
|
-
console.error(ansis.yellow(i18n.checkNetworkConnection));
|
|
373
|
+
console.error(ansis.red(i18n.tools.ccusageFailed));
|
|
374
|
+
console.error(ansis.yellow(i18n.tools.checkNetworkConnection));
|
|
321
375
|
if (process.env.DEBUG) {
|
|
322
|
-
console.error(ansis.gray(i18n.errorDetails), error);
|
|
376
|
+
console.error(ansis.gray(i18n.tools.errorDetails), error);
|
|
323
377
|
}
|
|
324
378
|
if (process.env.NODE_ENV !== "test") {
|
|
325
379
|
process.exit(1);
|
|
@@ -328,29 +382,228 @@ async function executeCcusage(args = []) {
|
|
|
328
382
|
}
|
|
329
383
|
}
|
|
330
384
|
|
|
385
|
+
const execAsync = promisify(exec);
|
|
386
|
+
async function runCcrUi(scriptLang, apiKey) {
|
|
387
|
+
const i18n = I18N[scriptLang];
|
|
388
|
+
console.log(ansis.cyan(`
|
|
389
|
+
\u{1F5A5}\uFE0F ${i18n.ccr.startingCcrUi}`));
|
|
390
|
+
if (apiKey) {
|
|
391
|
+
console.log(ansis.bold.green(`
|
|
392
|
+
\u{1F511} ${i18n.ccr.ccrUiApiKey || "CCR UI API Key"}: ${apiKey}`));
|
|
393
|
+
console.log(ansis.gray(` ${i18n.ccr.ccrUiApiKeyHint || "Use this API key to login to CCR UI"}
|
|
394
|
+
`));
|
|
395
|
+
}
|
|
396
|
+
try {
|
|
397
|
+
const { stdout, stderr } = await execAsync("ccr ui");
|
|
398
|
+
if (stdout) console.log(stdout);
|
|
399
|
+
if (stderr) console.error(ansis.yellow(stderr));
|
|
400
|
+
console.log(ansis.green(`\u2714 ${i18n.ccr.ccrUiStarted}`));
|
|
401
|
+
} catch (error) {
|
|
402
|
+
console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
|
|
403
|
+
throw error;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
async function runCcrStatus(scriptLang) {
|
|
407
|
+
const i18n = I18N[scriptLang];
|
|
408
|
+
console.log(ansis.cyan(`
|
|
409
|
+
\u{1F4CA} ${i18n.ccr.checkingCcrStatus}`));
|
|
410
|
+
try {
|
|
411
|
+
const { stdout, stderr } = await execAsync("ccr status");
|
|
412
|
+
if (stdout) {
|
|
413
|
+
console.log("\n" + ansis.bold(i18n.ccr.ccrStatusTitle));
|
|
414
|
+
console.log(stdout);
|
|
415
|
+
}
|
|
416
|
+
if (stderr) console.error(ansis.yellow(stderr));
|
|
417
|
+
} catch (error) {
|
|
418
|
+
console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
|
|
419
|
+
throw error;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
async function runCcrRestart(scriptLang) {
|
|
423
|
+
const i18n = I18N[scriptLang];
|
|
424
|
+
console.log(ansis.cyan(`
|
|
425
|
+
\u{1F504} ${i18n.ccr.restartingCcr}`));
|
|
426
|
+
try {
|
|
427
|
+
const { stdout, stderr } = await execAsync("ccr restart");
|
|
428
|
+
if (stdout) console.log(stdout);
|
|
429
|
+
if (stderr) console.error(ansis.yellow(stderr));
|
|
430
|
+
console.log(ansis.green(`\u2714 ${i18n.ccr.ccrRestarted}`));
|
|
431
|
+
} catch (error) {
|
|
432
|
+
console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
|
|
433
|
+
throw error;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
async function runCcrStart(scriptLang) {
|
|
437
|
+
const i18n = I18N[scriptLang];
|
|
438
|
+
console.log(ansis.cyan(`
|
|
439
|
+
\u25B6\uFE0F ${i18n.ccr.startingCcr}`));
|
|
440
|
+
try {
|
|
441
|
+
const { stdout, stderr } = await execAsync("ccr start");
|
|
442
|
+
if (stdout) console.log(stdout);
|
|
443
|
+
if (stderr) console.error(ansis.yellow(stderr));
|
|
444
|
+
console.log(ansis.green(`\u2714 ${i18n.ccr.ccrStarted}`));
|
|
445
|
+
} catch (error) {
|
|
446
|
+
console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
|
|
447
|
+
throw error;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
async function runCcrStop(scriptLang) {
|
|
451
|
+
const i18n = I18N[scriptLang];
|
|
452
|
+
console.log(ansis.cyan(`
|
|
453
|
+
\u23F9\uFE0F ${i18n.ccr.stoppingCcr}`));
|
|
454
|
+
try {
|
|
455
|
+
const { stdout, stderr } = await execAsync("ccr stop");
|
|
456
|
+
if (stdout) console.log(stdout);
|
|
457
|
+
if (stderr) console.error(ansis.yellow(stderr));
|
|
458
|
+
console.log(ansis.green(`\u2714 ${i18n.ccr.ccrStopped}`));
|
|
459
|
+
} catch (error) {
|
|
460
|
+
console.error(ansis.red(`\u2716 ${i18n.ccr.ccrCommandFailed}: ${error instanceof Error ? error.message : String(error)}`));
|
|
461
|
+
throw error;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function isCcrConfigured() {
|
|
466
|
+
const CCR_CONFIG_FILE = join(homedir(), ".claude-code-router", "config.json");
|
|
467
|
+
if (!existsSync(CCR_CONFIG_FILE)) {
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
const config = readCcrConfig();
|
|
471
|
+
return config !== null && config.Providers && config.Providers.length > 0;
|
|
472
|
+
}
|
|
473
|
+
async function showCcrMenu(scriptLang) {
|
|
474
|
+
try {
|
|
475
|
+
const i18n = I18N[scriptLang];
|
|
476
|
+
console.log("\n" + ansis.cyan("\u2550".repeat(50)));
|
|
477
|
+
console.log(ansis.bold.cyan(` ${i18n.ccr.ccrMenuTitle}`));
|
|
478
|
+
console.log(ansis.cyan("\u2550".repeat(50)) + "\n");
|
|
479
|
+
console.log(` ${ansis.cyan("1.")} ${i18n.ccr.ccrMenuOptions.initCcr} ${ansis.gray("- " + i18n.ccr.ccrMenuDescriptions.initCcr)}`);
|
|
480
|
+
console.log(` ${ansis.cyan("2.")} ${i18n.ccr.ccrMenuOptions.startUi} ${ansis.gray("- " + i18n.ccr.ccrMenuDescriptions.startUi)}`);
|
|
481
|
+
console.log(` ${ansis.cyan("3.")} ${i18n.ccr.ccrMenuOptions.checkStatus} ${ansis.gray("- " + i18n.ccr.ccrMenuDescriptions.checkStatus)}`);
|
|
482
|
+
console.log(` ${ansis.cyan("4.")} ${i18n.ccr.ccrMenuOptions.restart} ${ansis.gray("- " + i18n.ccr.ccrMenuDescriptions.restart)}`);
|
|
483
|
+
console.log(` ${ansis.cyan("5.")} ${i18n.ccr.ccrMenuOptions.start} ${ansis.gray("- " + i18n.ccr.ccrMenuDescriptions.start)}`);
|
|
484
|
+
console.log(` ${ansis.cyan("6.")} ${i18n.ccr.ccrMenuOptions.stop} ${ansis.gray("- " + i18n.ccr.ccrMenuDescriptions.stop)}`);
|
|
485
|
+
console.log(` ${ansis.yellow("0.")} ${i18n.ccr.ccrMenuOptions.back}`);
|
|
486
|
+
console.log("");
|
|
487
|
+
const { choice } = await inquirer.prompt({
|
|
488
|
+
type: "input",
|
|
489
|
+
name: "choice",
|
|
490
|
+
message: i18n.common.enterChoice,
|
|
491
|
+
validate: (value) => {
|
|
492
|
+
const valid = ["1", "2", "3", "4", "5", "6", "0"];
|
|
493
|
+
return valid.includes(value) || i18n.common.invalidChoice;
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
switch (choice) {
|
|
497
|
+
case "1":
|
|
498
|
+
const ccrInstalled = await isCcrInstalled();
|
|
499
|
+
if (!ccrInstalled) {
|
|
500
|
+
console.log(ansis.yellow(`${i18n.ccr.installingCcr}`));
|
|
501
|
+
await installCcr(scriptLang);
|
|
502
|
+
} else {
|
|
503
|
+
console.log(ansis.green(`\u2714 ${i18n.ccr.ccrAlreadyInstalled}`));
|
|
504
|
+
}
|
|
505
|
+
await configureCcrFeature(scriptLang);
|
|
506
|
+
console.log(ansis.green(`
|
|
507
|
+
\u2714 ${i18n.ccr.ccrSetupComplete}`));
|
|
508
|
+
break;
|
|
509
|
+
case "2":
|
|
510
|
+
if (!isCcrConfigured()) {
|
|
511
|
+
console.log(ansis.yellow(`
|
|
512
|
+
\u26A0\uFE0F ${i18n.ccr.ccrNotConfigured || "CCR is not configured yet. Please initialize CCR first."}`));
|
|
513
|
+
console.log(ansis.cyan(` ${i18n.ccr.pleaseInitFirst || "Please select option 1 to initialize CCR."}
|
|
514
|
+
`));
|
|
515
|
+
} else {
|
|
516
|
+
const config = readCcrConfig();
|
|
517
|
+
await runCcrUi(scriptLang, config?.APIKEY);
|
|
518
|
+
}
|
|
519
|
+
break;
|
|
520
|
+
case "3":
|
|
521
|
+
if (!isCcrConfigured()) {
|
|
522
|
+
console.log(ansis.yellow(`
|
|
523
|
+
\u26A0\uFE0F ${i18n.ccr.ccrNotConfigured || "CCR is not configured yet. Please initialize CCR first."}`));
|
|
524
|
+
console.log(ansis.cyan(` ${i18n.ccr.pleaseInitFirst || "Please select option 1 to initialize CCR."}
|
|
525
|
+
`));
|
|
526
|
+
} else {
|
|
527
|
+
await runCcrStatus(scriptLang);
|
|
528
|
+
}
|
|
529
|
+
break;
|
|
530
|
+
case "4":
|
|
531
|
+
if (!isCcrConfigured()) {
|
|
532
|
+
console.log(ansis.yellow(`
|
|
533
|
+
\u26A0\uFE0F ${i18n.ccr.ccrNotConfigured || "CCR is not configured yet. Please initialize CCR first."}`));
|
|
534
|
+
console.log(ansis.cyan(` ${i18n.ccr.pleaseInitFirst || "Please select option 1 to initialize CCR."}
|
|
535
|
+
`));
|
|
536
|
+
} else {
|
|
537
|
+
await runCcrRestart(scriptLang);
|
|
538
|
+
}
|
|
539
|
+
break;
|
|
540
|
+
case "5":
|
|
541
|
+
if (!isCcrConfigured()) {
|
|
542
|
+
console.log(ansis.yellow(`
|
|
543
|
+
\u26A0\uFE0F ${i18n.ccr.ccrNotConfigured || "CCR is not configured yet. Please initialize CCR first."}`));
|
|
544
|
+
console.log(ansis.cyan(` ${i18n.ccr.pleaseInitFirst || "Please select option 1 to initialize CCR."}
|
|
545
|
+
`));
|
|
546
|
+
} else {
|
|
547
|
+
await runCcrStart(scriptLang);
|
|
548
|
+
}
|
|
549
|
+
break;
|
|
550
|
+
case "6":
|
|
551
|
+
if (!isCcrConfigured()) {
|
|
552
|
+
console.log(ansis.yellow(`
|
|
553
|
+
\u26A0\uFE0F ${i18n.ccr.ccrNotConfigured || "CCR is not configured yet. Please initialize CCR first."}`));
|
|
554
|
+
console.log(ansis.cyan(` ${i18n.ccr.pleaseInitFirst || "Please select option 1 to initialize CCR."}
|
|
555
|
+
`));
|
|
556
|
+
} else {
|
|
557
|
+
await runCcrStop(scriptLang);
|
|
558
|
+
}
|
|
559
|
+
break;
|
|
560
|
+
case "0":
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
if (choice !== "0") {
|
|
564
|
+
console.log("\n" + ansis.dim("\u2500".repeat(50)) + "\n");
|
|
565
|
+
const { continueInCcr } = await inquirer.prompt({
|
|
566
|
+
type: "confirm",
|
|
567
|
+
name: "continueInCcr",
|
|
568
|
+
message: i18n.common.returnToMenu || "Return to CCR menu?",
|
|
569
|
+
default: true
|
|
570
|
+
});
|
|
571
|
+
if (continueInCcr) {
|
|
572
|
+
return await showCcrMenu(scriptLang);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return false;
|
|
576
|
+
} catch (error) {
|
|
577
|
+
if (!handleExitPromptError(error)) {
|
|
578
|
+
handleGeneralError(error, scriptLang);
|
|
579
|
+
}
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
331
584
|
function getValidLanguage(lang) {
|
|
332
585
|
return lang && lang in I18N ? lang : "en";
|
|
333
586
|
}
|
|
334
587
|
async function runCcusageFeature(scriptLang) {
|
|
335
588
|
const validLang = getValidLanguage(scriptLang);
|
|
336
|
-
const i18n =
|
|
589
|
+
const i18n = getTranslation(validLang);
|
|
337
590
|
console.log("");
|
|
338
|
-
console.log(ansis.cyan(i18n.menuOptions.ccusage));
|
|
339
|
-
console.log(ansis.gray(`${i18n.ccusageDescription} - https://github.com/ryoppippi/ccusage`));
|
|
591
|
+
console.log(ansis.cyan(i18n.menu.menuOptions.ccusage));
|
|
592
|
+
console.log(ansis.gray(`${i18n.tools.ccusageDescription} - https://github.com/ryoppippi/ccusage`));
|
|
340
593
|
console.log("");
|
|
341
594
|
const choices = [
|
|
342
|
-
{ name: i18n.ccusageModes.daily, value: "daily" },
|
|
343
|
-
{ name: i18n.ccusageModes.monthly, value: "monthly" },
|
|
344
|
-
{ name: i18n.ccusageModes.session, value: "session" },
|
|
345
|
-
{ name: i18n.ccusageModes.blocks, value: "blocks" },
|
|
346
|
-
{ name: i18n.ccusageModes.custom, value: "custom" },
|
|
347
|
-
{ name: i18n.back, value: "back" }
|
|
595
|
+
{ name: i18n.tools.ccusageModes.daily, value: "daily" },
|
|
596
|
+
{ name: i18n.tools.ccusageModes.monthly, value: "monthly" },
|
|
597
|
+
{ name: i18n.tools.ccusageModes.session, value: "session" },
|
|
598
|
+
{ name: i18n.tools.ccusageModes.blocks, value: "blocks" },
|
|
599
|
+
{ name: i18n.tools.ccusageModes.custom, value: "custom" },
|
|
600
|
+
{ name: i18n.common.back, value: "back" }
|
|
348
601
|
];
|
|
349
602
|
const { mode } = await inquirer.prompt({
|
|
350
603
|
type: "list",
|
|
351
604
|
name: "mode",
|
|
352
|
-
message: i18n.selectAnalysisMode,
|
|
353
|
-
choices
|
|
605
|
+
message: i18n.tools.selectAnalysisMode,
|
|
606
|
+
choices: addNumbersToChoices(choices)
|
|
354
607
|
});
|
|
355
608
|
if (mode === "back") {
|
|
356
609
|
return;
|
|
@@ -360,7 +613,7 @@ async function runCcusageFeature(scriptLang) {
|
|
|
360
613
|
const { customArgs } = await inquirer.prompt({
|
|
361
614
|
type: "input",
|
|
362
615
|
name: "customArgs",
|
|
363
|
-
message: i18n.enterCustomArgs,
|
|
616
|
+
message: i18n.tools.enterCustomArgs,
|
|
364
617
|
default: ""
|
|
365
618
|
});
|
|
366
619
|
if (customArgs === null || customArgs === void 0 || customArgs === "") {
|
|
@@ -391,9 +644,13 @@ async function runCcusageFeature(scriptLang) {
|
|
|
391
644
|
await inquirer.prompt({
|
|
392
645
|
type: "input",
|
|
393
646
|
name: "continue",
|
|
394
|
-
message: ansis.gray(i18n.pressEnterToContinue)
|
|
647
|
+
message: ansis.gray(i18n.tools.pressEnterToContinue)
|
|
395
648
|
});
|
|
396
649
|
}
|
|
650
|
+
async function runCcrMenuFeature(scriptLang) {
|
|
651
|
+
const validLang = getValidLanguage(scriptLang);
|
|
652
|
+
await showCcrMenu(validLang);
|
|
653
|
+
}
|
|
397
654
|
|
|
398
655
|
async function update(options = {}) {
|
|
399
656
|
try {
|
|
@@ -408,21 +665,21 @@ async function update(options = {}) {
|
|
|
408
665
|
const { lang } = await inquirer.prompt({
|
|
409
666
|
type: "list",
|
|
410
667
|
name: "lang",
|
|
411
|
-
message: i18n.updateConfigLangPrompt,
|
|
412
|
-
choices: SUPPORTED_LANGS.map((l) => ({
|
|
413
|
-
name: `${LANG_LABELS[l]} - ${i18n.configLangHint[l]}`,
|
|
668
|
+
message: i18n.language.updateConfigLangPrompt,
|
|
669
|
+
choices: addNumbersToChoices(SUPPORTED_LANGS.map((l) => ({
|
|
670
|
+
name: `${LANG_LABELS[l]} - ${i18n.language.configLangHint[l]}`,
|
|
414
671
|
value: l
|
|
415
|
-
}))
|
|
672
|
+
})))
|
|
416
673
|
});
|
|
417
674
|
if (!lang) {
|
|
418
|
-
console.log(ansis.yellow(i18n.cancelled));
|
|
675
|
+
console.log(ansis.yellow(i18n.common.cancelled));
|
|
419
676
|
process.exit(0);
|
|
420
677
|
}
|
|
421
678
|
configLang = lang;
|
|
422
679
|
}
|
|
423
680
|
const aiOutputLang = await resolveAiOutputLanguage(scriptLang, options.aiOutputLang, zcfConfig);
|
|
424
681
|
console.log(ansis.cyan(`
|
|
425
|
-
${i18n.updatingPrompts}
|
|
682
|
+
${i18n.workflow.updatingPrompts}
|
|
426
683
|
`));
|
|
427
684
|
await updatePromptOnly(configLang, scriptLang, aiOutputLang);
|
|
428
685
|
await selectAndInstallWorkflows(configLang, scriptLang);
|
|
@@ -446,69 +703,72 @@ async function showMainMenu() {
|
|
|
446
703
|
let exitMenu = false;
|
|
447
704
|
while (!exitMenu) {
|
|
448
705
|
const i18n = I18N[scriptLang];
|
|
449
|
-
console.log(ansis.cyan(i18n.selectFunction));
|
|
706
|
+
console.log(ansis.cyan(i18n.menu.selectFunction));
|
|
450
707
|
console.log(" -------- Claude Code --------");
|
|
451
708
|
console.log(
|
|
452
|
-
` ${ansis.cyan("1.")} ${i18n.menuOptions.fullInit} ${ansis.gray("- " + i18n.menuDescriptions.fullInit)}`
|
|
709
|
+
` ${ansis.cyan("1.")} ${i18n.menu.menuOptions.fullInit} ${ansis.gray("- " + i18n.menu.menuDescriptions.fullInit)}`
|
|
453
710
|
);
|
|
454
711
|
console.log(
|
|
455
|
-
` ${ansis.cyan("2.")} ${i18n.menuOptions.importWorkflow} ${ansis.gray(
|
|
456
|
-
"- " + i18n.menuDescriptions.importWorkflow
|
|
712
|
+
` ${ansis.cyan("2.")} ${i18n.menu.menuOptions.importWorkflow} ${ansis.gray(
|
|
713
|
+
"- " + i18n.menu.menuDescriptions.importWorkflow
|
|
457
714
|
)}`
|
|
458
715
|
);
|
|
459
716
|
console.log(
|
|
460
|
-
` ${ansis.cyan("3.")} ${i18n.menuOptions.
|
|
461
|
-
"- " + i18n.menuDescriptions.
|
|
717
|
+
` ${ansis.cyan("3.")} ${i18n.menu.menuOptions.configureApiOrCcr} ${ansis.gray(
|
|
718
|
+
"- " + i18n.menu.menuDescriptions.configureApiOrCcr
|
|
462
719
|
)}`
|
|
463
720
|
);
|
|
464
721
|
console.log(
|
|
465
|
-
` ${ansis.cyan("4.")} ${i18n.menuOptions.configureMcp} ${ansis.gray(
|
|
466
|
-
"- " + i18n.menuDescriptions.configureMcp
|
|
722
|
+
` ${ansis.cyan("4.")} ${i18n.menu.menuOptions.configureMcp} ${ansis.gray(
|
|
723
|
+
"- " + i18n.menu.menuDescriptions.configureMcp
|
|
467
724
|
)}`
|
|
468
725
|
);
|
|
469
726
|
console.log(
|
|
470
|
-
` ${ansis.cyan("5.")} ${i18n.menuOptions.configureModel} ${ansis.gray(
|
|
471
|
-
"- " + i18n.menuDescriptions.configureModel
|
|
727
|
+
` ${ansis.cyan("5.")} ${i18n.menu.menuOptions.configureModel} ${ansis.gray(
|
|
728
|
+
"- " + i18n.menu.menuDescriptions.configureModel
|
|
472
729
|
)}`
|
|
473
730
|
);
|
|
474
731
|
console.log(
|
|
475
|
-
` ${ansis.cyan("6.")} ${i18n.menuOptions.configureAiMemory} ${ansis.gray(
|
|
476
|
-
"- " + i18n.menuDescriptions.configureAiMemory
|
|
732
|
+
` ${ansis.cyan("6.")} ${i18n.menu.menuOptions.configureAiMemory} ${ansis.gray(
|
|
733
|
+
"- " + i18n.menu.menuDescriptions.configureAiMemory
|
|
477
734
|
)}`
|
|
478
735
|
);
|
|
479
736
|
console.log(
|
|
480
|
-
` ${ansis.cyan("7.")} ${i18n.menuOptions.configureEnvPermission} ${ansis.gray(
|
|
481
|
-
"- " + i18n.menuDescriptions.configureEnvPermission
|
|
737
|
+
` ${ansis.cyan("7.")} ${i18n.menu.menuOptions.configureEnvPermission} ${ansis.gray(
|
|
738
|
+
"- " + i18n.menu.menuDescriptions.configureEnvPermission
|
|
482
739
|
)}`
|
|
483
740
|
);
|
|
484
741
|
console.log("");
|
|
485
|
-
console.log(` --------- ${i18n.menuSections.otherTools} ----------`);
|
|
742
|
+
console.log(` --------- ${i18n.menu.menuSections.otherTools} ----------`);
|
|
486
743
|
console.log(
|
|
487
|
-
` ${ansis.cyan("
|
|
744
|
+
` ${ansis.cyan("R.")} ${i18n.menu.menuOptions.ccrManagement} ${ansis.gray("- " + i18n.menu.menuDescriptions.ccrManagement)}`
|
|
745
|
+
);
|
|
746
|
+
console.log(
|
|
747
|
+
` ${ansis.cyan("U.")} ${i18n.menu.menuOptions.ccusage} ${ansis.gray("- " + i18n.menu.menuDescriptions.ccusage)}`
|
|
488
748
|
);
|
|
489
749
|
console.log("");
|
|
490
750
|
console.log(" ------------ ZCF ------------");
|
|
491
751
|
console.log(
|
|
492
|
-
` ${ansis.cyan("0.")} ${i18n.menuOptions.changeLanguage} ${ansis.gray(
|
|
493
|
-
"- " + i18n.menuDescriptions.changeLanguage
|
|
752
|
+
` ${ansis.cyan("0.")} ${i18n.menu.menuOptions.changeLanguage} ${ansis.gray(
|
|
753
|
+
"- " + i18n.menu.menuDescriptions.changeLanguage
|
|
494
754
|
)}`
|
|
495
755
|
);
|
|
496
756
|
console.log(
|
|
497
|
-
` ${ansis.cyan("-.")} ${i18n.menuOptions.clearCache} ${ansis.gray("- " + i18n.menuDescriptions.clearCache)}`
|
|
757
|
+
` ${ansis.cyan("-.")} ${i18n.menu.menuOptions.clearCache} ${ansis.gray("- " + i18n.menu.menuDescriptions.clearCache)}`
|
|
498
758
|
);
|
|
499
|
-
console.log(` ${ansis.red("Q.")} ${ansis.red(i18n.menuOptions.exit)}`);
|
|
759
|
+
console.log(` ${ansis.red("Q.")} ${ansis.red(i18n.menu.menuOptions.exit)}`);
|
|
500
760
|
console.log("");
|
|
501
761
|
const { choice } = await inquirer.prompt({
|
|
502
762
|
type: "input",
|
|
503
763
|
name: "choice",
|
|
504
|
-
message: i18n.enterChoice,
|
|
764
|
+
message: i18n.common.enterChoice,
|
|
505
765
|
validate: (value) => {
|
|
506
|
-
const valid = ["1", "2", "3", "4", "5", "6", "7", "u", "U", "0", "-", "q", "Q"];
|
|
507
|
-
return valid.includes(value) || i18n.invalidChoice;
|
|
766
|
+
const valid = ["1", "2", "3", "4", "5", "6", "7", "r", "R", "u", "U", "0", "-", "q", "Q"];
|
|
767
|
+
return valid.includes(value) || i18n.common.invalidChoice;
|
|
508
768
|
}
|
|
509
769
|
});
|
|
510
770
|
if (!choice) {
|
|
511
|
-
console.log(ansis.yellow(i18n.cancelled));
|
|
771
|
+
console.log(ansis.yellow(i18n.common.cancelled));
|
|
512
772
|
exitMenu = true;
|
|
513
773
|
break;
|
|
514
774
|
}
|
|
@@ -534,6 +794,10 @@ async function showMainMenu() {
|
|
|
534
794
|
case "7":
|
|
535
795
|
await configureEnvPermissionFeature(scriptLang);
|
|
536
796
|
break;
|
|
797
|
+
case "r":
|
|
798
|
+
case "R":
|
|
799
|
+
await runCcrMenuFeature(scriptLang);
|
|
800
|
+
break;
|
|
537
801
|
case "u":
|
|
538
802
|
case "U":
|
|
539
803
|
await runCcusageFeature(scriptLang);
|
|
@@ -549,11 +813,11 @@ async function showMainMenu() {
|
|
|
549
813
|
break;
|
|
550
814
|
case "q":
|
|
551
815
|
exitMenu = true;
|
|
552
|
-
console.log(ansis.cyan(i18n.goodbye));
|
|
816
|
+
console.log(ansis.cyan(i18n.common.goodbye));
|
|
553
817
|
break;
|
|
554
818
|
}
|
|
555
819
|
if (!exitMenu && choice.toLowerCase() !== "q") {
|
|
556
|
-
if (choice === "0" || choice === "-" || choice.toLowerCase() === "u") {
|
|
820
|
+
if (choice === "0" || choice === "-" || choice.toLowerCase() === "u" || choice.toLowerCase() === "r") {
|
|
557
821
|
console.log("\n" + ansis.dim("\u2500".repeat(50)) + "\n");
|
|
558
822
|
continue;
|
|
559
823
|
}
|
|
@@ -561,12 +825,12 @@ async function showMainMenu() {
|
|
|
561
825
|
const { continue: shouldContinue } = await inquirer.prompt({
|
|
562
826
|
type: "confirm",
|
|
563
827
|
name: "continue",
|
|
564
|
-
message: i18n.returnToMenu,
|
|
828
|
+
message: i18n.common.returnToMenu,
|
|
565
829
|
default: true
|
|
566
830
|
});
|
|
567
831
|
if (!shouldContinue) {
|
|
568
832
|
exitMenu = true;
|
|
569
|
-
console.log(ansis.cyan(i18n.goodbye));
|
|
833
|
+
console.log(ansis.cyan(i18n.common.goodbye));
|
|
570
834
|
}
|
|
571
835
|
}
|
|
572
836
|
}
|
|
@@ -577,6 +841,24 @@ async function showMainMenu() {
|
|
|
577
841
|
}
|
|
578
842
|
}
|
|
579
843
|
|
|
844
|
+
async function ccr(options = {}) {
|
|
845
|
+
try {
|
|
846
|
+
if (!options.skipBanner) {
|
|
847
|
+
displayBannerWithInfo();
|
|
848
|
+
}
|
|
849
|
+
const zcfConfig = await readZcfConfigAsync();
|
|
850
|
+
const scriptLang = options.lang || zcfConfig?.preferredLang || await selectScriptLanguage();
|
|
851
|
+
const continueInCcr = await showCcrMenu(scriptLang);
|
|
852
|
+
if (!continueInCcr && !options.skipBanner) {
|
|
853
|
+
await showMainMenu();
|
|
854
|
+
}
|
|
855
|
+
} catch (error) {
|
|
856
|
+
if (!handleExitPromptError(error)) {
|
|
857
|
+
handleGeneralError(error, options.lang);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
580
862
|
function setupCommands(cli) {
|
|
581
863
|
cli.command("[lang]", "Show interactive menu (default)").option("--init", "Run full initialization directly").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--force, -f", "Force overwrite existing configuration").action(async (lang, options) => {
|
|
582
864
|
await handleDefaultCommand(lang, options);
|
|
@@ -587,6 +869,9 @@ function setupCommands(cli) {
|
|
|
587
869
|
cli.command("update", "Update Claude Code prompts only").alias("u").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").action(async (options) => {
|
|
588
870
|
await handleUpdateCommand(options);
|
|
589
871
|
});
|
|
872
|
+
cli.command("ccr", "Configure Claude Code Router for model proxy").option("--lang, -l <lang>", "Display language (zh-CN, en)").action(async (options) => {
|
|
873
|
+
await ccr({ lang: options.lang });
|
|
874
|
+
});
|
|
590
875
|
cli.command("ccu [...args]", "Run Claude Code usage analysis tool").allowUnknownOptions().action(async (args) => {
|
|
591
876
|
await executeCcusage(args);
|
|
592
877
|
});
|
|
@@ -628,6 +913,7 @@ function customizeHelp(sections) {
|
|
|
628
913
|
"i"
|
|
629
914
|
)} Initialize Claude Code configuration / \u521D\u59CB\u5316 Claude Code \u914D\u7F6E`,
|
|
630
915
|
` ${ansis.cyan("zcf update")} | ${ansis.cyan("u")} Update workflow-related md files / \u4EC5\u66F4\u65B0\u5DE5\u4F5C\u6D41\u76F8\u5173md`,
|
|
916
|
+
` ${ansis.cyan("zcf ccr")} Configure Claude Code Router / \u914D\u7F6E\u6A21\u578B\u4EE3\u7406`,
|
|
631
917
|
` ${ansis.cyan("zcf ccu")} [args] Run Claude Code usage analysis / \u8FD0\u884C Claude Code \u7528\u91CF\u5206\u6790`,
|
|
632
918
|
"",
|
|
633
919
|
ansis.gray(" Shortcuts / \u5FEB\u6377\u65B9\u5F0F:"),
|