ccjk 1.3.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.
Files changed (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +455 -0
  3. package/README.ko.md +455 -0
  4. package/README.md +550 -0
  5. package/README.zh-CN.md +488 -0
  6. package/bin/ccjk.mjs +2 -0
  7. package/dist/chunks/api-providers.mjs +89 -0
  8. package/dist/chunks/claude-code-config-manager.mjs +733 -0
  9. package/dist/chunks/claude-code-incremental-manager.mjs +603 -0
  10. package/dist/chunks/codex-config-switch.mjs +427 -0
  11. package/dist/chunks/codex-provider-manager.mjs +232 -0
  12. package/dist/chunks/codex-uninstaller.mjs +404 -0
  13. package/dist/chunks/commands.mjs +120 -0
  14. package/dist/chunks/features.mjs +642 -0
  15. package/dist/chunks/simple-config.mjs +10445 -0
  16. package/dist/cli.d.mts +1 -0
  17. package/dist/cli.d.ts +1 -0
  18. package/dist/cli.mjs +5972 -0
  19. package/dist/i18n/locales/en/api.json +63 -0
  20. package/dist/i18n/locales/en/ccjk.json +276 -0
  21. package/dist/i18n/locales/en/ccr.json +65 -0
  22. package/dist/i18n/locales/en/cli.json +57 -0
  23. package/dist/i18n/locales/en/codex.json +124 -0
  24. package/dist/i18n/locales/en/cometix.json +29 -0
  25. package/dist/i18n/locales/en/common.json +20 -0
  26. package/dist/i18n/locales/en/configuration.json +77 -0
  27. package/dist/i18n/locales/en/errors.json +26 -0
  28. package/dist/i18n/locales/en/installation.json +80 -0
  29. package/dist/i18n/locales/en/interview.json +104 -0
  30. package/dist/i18n/locales/en/language.json +19 -0
  31. package/dist/i18n/locales/en/mcp.json +38 -0
  32. package/dist/i18n/locales/en/menu.json +51 -0
  33. package/dist/i18n/locales/en/multi-config.json +79 -0
  34. package/dist/i18n/locales/en/shencha.json +14 -0
  35. package/dist/i18n/locales/en/team.json +7 -0
  36. package/dist/i18n/locales/en/tools.json +42 -0
  37. package/dist/i18n/locales/en/uninstall.json +56 -0
  38. package/dist/i18n/locales/en/updater.json +25 -0
  39. package/dist/i18n/locales/en/workflow.json +25 -0
  40. package/dist/i18n/locales/zh-CN/api.json +63 -0
  41. package/dist/i18n/locales/zh-CN/ccjk.json +276 -0
  42. package/dist/i18n/locales/zh-CN/ccr.json +65 -0
  43. package/dist/i18n/locales/zh-CN/cli.json +57 -0
  44. package/dist/i18n/locales/zh-CN/codex.json +124 -0
  45. package/dist/i18n/locales/zh-CN/cometix.json +29 -0
  46. package/dist/i18n/locales/zh-CN/common.json +20 -0
  47. package/dist/i18n/locales/zh-CN/configuration.json +77 -0
  48. package/dist/i18n/locales/zh-CN/errors.json +26 -0
  49. package/dist/i18n/locales/zh-CN/installation.json +80 -0
  50. package/dist/i18n/locales/zh-CN/interview.json +104 -0
  51. package/dist/i18n/locales/zh-CN/language.json +19 -0
  52. package/dist/i18n/locales/zh-CN/mcp.json +38 -0
  53. package/dist/i18n/locales/zh-CN/menu.json +51 -0
  54. package/dist/i18n/locales/zh-CN/multi-config.json +79 -0
  55. package/dist/i18n/locales/zh-CN/shencha.json +14 -0
  56. package/dist/i18n/locales/zh-CN/team.json +7 -0
  57. package/dist/i18n/locales/zh-CN/tools.json +42 -0
  58. package/dist/i18n/locales/zh-CN/uninstall.json +56 -0
  59. package/dist/i18n/locales/zh-CN/updater.json +25 -0
  60. package/dist/i18n/locales/zh-CN/workflow.json +25 -0
  61. package/dist/index.d.mts +2644 -0
  62. package/dist/index.d.ts +2644 -0
  63. package/dist/index.mjs +1706 -0
  64. package/package.json +157 -0
  65. package/templates/CLAUDE.md +219 -0
  66. package/templates/claude-code/CLAUDE.md +250 -0
  67. package/templates/claude-code/common/settings.json +38 -0
  68. package/templates/claude-code/en/workflow/bmad/commands/bmad-init.md +165 -0
  69. package/templates/claude-code/en/workflow/common/agents/get-current-datetime.md +29 -0
  70. package/templates/claude-code/en/workflow/common/agents/init-architect.md +114 -0
  71. package/templates/claude-code/en/workflow/common/commands/init-project.md +53 -0
  72. package/templates/claude-code/en/workflow/plan/agents/planner.md +116 -0
  73. package/templates/claude-code/en/workflow/plan/agents/ui-ux-designer.md +91 -0
  74. package/templates/claude-code/en/workflow/plan/commands/feat.md +105 -0
  75. package/templates/claude-code/zh-CN/workflow/bmad/commands/bmad-init.md +172 -0
  76. package/templates/claude-code/zh-CN/workflow/common/agents/get-current-datetime.md +29 -0
  77. package/templates/claude-code/zh-CN/workflow/common/agents/init-architect.md +114 -0
  78. package/templates/claude-code/zh-CN/workflow/common/commands/init-project.md +53 -0
  79. package/templates/claude-code/zh-CN/workflow/plan/agents/planner.md +116 -0
  80. package/templates/claude-code/zh-CN/workflow/plan/agents/ui-ux-designer.md +91 -0
  81. package/templates/claude-code/zh-CN/workflow/plan/commands/feat.md +105 -0
  82. package/templates/codex/common/config.toml +0 -0
  83. package/templates/common/output-styles/en/casual-friendly.md +97 -0
  84. package/templates/common/output-styles/en/engineer-professional.md +88 -0
  85. package/templates/common/output-styles/en/expert-concise.md +93 -0
  86. package/templates/common/output-styles/en/laowang-engineer.md +127 -0
  87. package/templates/common/output-styles/en/nekomata-engineer.md +120 -0
  88. package/templates/common/output-styles/en/ojousama-engineer.md +121 -0
  89. package/templates/common/output-styles/en/teaching-mode.md +102 -0
  90. package/templates/common/output-styles/en/technical-precise.md +101 -0
  91. package/templates/common/output-styles/zh-CN/engineer-professional.md +89 -0
  92. package/templates/common/output-styles/zh-CN/laowang-engineer.md +127 -0
  93. package/templates/common/output-styles/zh-CN/nekomata-engineer.md +120 -0
  94. package/templates/common/output-styles/zh-CN/ojousama-engineer.md +121 -0
  95. package/templates/common/workflow/git/en/git-cleanBranches.md +102 -0
  96. package/templates/common/workflow/git/en/git-commit.md +205 -0
  97. package/templates/common/workflow/git/en/git-rollback.md +90 -0
  98. package/templates/common/workflow/git/en/git-worktree.md +276 -0
  99. package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +102 -0
  100. package/templates/common/workflow/git/zh-CN/git-commit.md +205 -0
  101. package/templates/common/workflow/git/zh-CN/git-rollback.md +90 -0
  102. package/templates/common/workflow/git/zh-CN/git-worktree.md +276 -0
  103. package/templates/common/workflow/interview/en/interview.md +212 -0
  104. package/templates/common/workflow/interview/zh-CN/interview.md +212 -0
  105. package/templates/common/workflow/sixStep/en/workflow.md +251 -0
  106. package/templates/common/workflow/sixStep/zh-CN/workflow.md +215 -0
  107. package/templates/industry/devops/en/ci-cd-pipeline.md +410 -0
  108. package/templates/industry/web-dev/en/api-design.md +299 -0
  109. package/templates/industry/web-dev/en/react-nextjs-setup.md +236 -0
@@ -0,0 +1,642 @@
1
+ import ansis from 'ansis';
2
+ import inquirer from 'inquirer';
3
+ import { cj as i18n, co as ensureI18nInitialized, Y as SUPPORTED_LANGS, cz as addNumbersToChoices, _ as LANG_LABELS, cG as updateZcfConfig, cP as changeLanguage, cF as readZcfConfig, ct as promptBoolean, p as openSettingsJson, o as importRecommendedPermissions, n as importRecommendedEnv, bp as applyAiLanguageDirective, cY as configureOutputStyle, bn as getExistingModelConfig, bk as updateCustomModel, bl as updateDefaultModel, cZ as isWindows, ah as readMcpConfig, am as fixWindowsMcpConfig, ai as writeMcpConfig, c_ as selectMcpServices, aj as backupMcpConfig, c$ as getMcpServices, al as buildMcpServerConfig, ak as mergeMcpServers, cq as isCcrInstalled, cr as installCcr, d0 as setupCcrConfiguration, bo as getExistingApiConfig, br as promptApiConfigurationAction, d1 as modifyApiConfigPartially, cQ as validateApiKey, bi as configureApi, d2 as formatApiKeyDisplay, bq as switchToOfficialLogin } from './simple-config.mjs';
4
+ import 'node:fs';
5
+ import 'node:process';
6
+ import 'pathe';
7
+ import 'smol-toml';
8
+ import 'dayjs';
9
+ import 'node:child_process';
10
+ import 'node:os';
11
+ import 'node:util';
12
+ import 'node:url';
13
+ import 'inquirer-toggle';
14
+ import 'ora';
15
+ import 'tinyexec';
16
+ import 'semver';
17
+ import 'node:fs/promises';
18
+ import 'fs-extra';
19
+ import 'trash';
20
+ import 'i18next';
21
+ import 'i18next-fs-backend';
22
+
23
+ async function handleCancellation() {
24
+ ensureI18nInitialized();
25
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
26
+ }
27
+ async function handleOfficialLoginMode() {
28
+ ensureI18nInitialized();
29
+ const success = switchToOfficialLogin();
30
+ if (success) {
31
+ console.log(ansis.green(`\u2714 ${i18n.t("api:officialLoginConfigured")}`));
32
+ } else {
33
+ console.log(ansis.red(i18n.t("api:officialLoginFailed")));
34
+ }
35
+ }
36
+ async function handleCustomApiMode() {
37
+ ensureI18nInitialized();
38
+ const zcfConfig = readZcfConfig();
39
+ const codeToolType = zcfConfig?.codeToolType || "claude-code";
40
+ if (codeToolType === "claude-code") {
41
+ const { configureIncrementalManagement } = await import('./claude-code-incremental-manager.mjs');
42
+ await configureIncrementalManagement();
43
+ return;
44
+ }
45
+ const existingConfig = getExistingApiConfig();
46
+ if (existingConfig) {
47
+ const configAction = await promptApiConfigurationAction();
48
+ if (configAction === "keep-existing") {
49
+ console.log(ansis.green(`\u2714 ${i18n.t("api:keepExistingConfig")}`));
50
+ return;
51
+ } else if (configAction === "modify-partial") {
52
+ await modifyApiConfigPartially(existingConfig);
53
+ return;
54
+ }
55
+ }
56
+ const { apiChoice } = await inquirer.prompt({
57
+ type: "list",
58
+ name: "apiChoice",
59
+ message: i18n.t("api:configureApi"),
60
+ choices: addNumbersToChoices([
61
+ {
62
+ name: `${i18n.t("api:useAuthToken")} - ${ansis.gray(i18n.t("api:authTokenDesc"))}`,
63
+ value: "auth_token",
64
+ short: i18n.t("api:useAuthToken")
65
+ },
66
+ {
67
+ name: `${i18n.t("api:useApiKey")} - ${ansis.gray(i18n.t("api:apiKeyDesc"))}`,
68
+ value: "api_key",
69
+ short: i18n.t("api:useApiKey")
70
+ },
71
+ { name: i18n.t("api:skipApi"), value: "skip" }
72
+ ])
73
+ });
74
+ if (!apiChoice || apiChoice === "skip") {
75
+ await handleCancellation();
76
+ return;
77
+ }
78
+ const { url } = await inquirer.prompt({
79
+ type: "input",
80
+ name: "url",
81
+ message: `${i18n.t("api:enterApiUrl")}${i18n.t("common:emptyToSkip")}`,
82
+ validate: (value) => {
83
+ if (!value) {
84
+ return true;
85
+ }
86
+ try {
87
+ void new URL(value);
88
+ return true;
89
+ } catch {
90
+ return i18n.t("api:invalidUrl");
91
+ }
92
+ }
93
+ });
94
+ if (url === void 0 || !url) {
95
+ await handleCancellation();
96
+ return;
97
+ }
98
+ const keyMessage = apiChoice === "auth_token" ? `${i18n.t("api:enterAuthToken")}${i18n.t("common:emptyToSkip")}` : `${i18n.t("api:enterApiKey")}${i18n.t("common:emptyToSkip")}`;
99
+ const { key } = await inquirer.prompt({
100
+ type: "input",
101
+ name: "key",
102
+ message: keyMessage,
103
+ validate: (value) => {
104
+ if (!value) {
105
+ return true;
106
+ }
107
+ const validation = validateApiKey(value);
108
+ if (!validation.isValid) {
109
+ return validation.error || i18n.t("api:invalidKeyFormat");
110
+ }
111
+ return true;
112
+ }
113
+ });
114
+ if (key === void 0 || !key) {
115
+ await handleCancellation();
116
+ return;
117
+ }
118
+ const apiConfig = { url, key, authType: apiChoice };
119
+ const configuredApi = configureApi(apiConfig);
120
+ if (configuredApi) {
121
+ console.log(ansis.green(`\u2714 ${i18n.t("api:apiConfigSuccess")}`));
122
+ console.log(ansis.gray(` URL: ${configuredApi.url}`));
123
+ console.log(ansis.gray(` Key: ${formatApiKeyDisplay(configuredApi.key)}`));
124
+ }
125
+ }
126
+ async function handleCcrProxyMode() {
127
+ ensureI18nInitialized();
128
+ const ccrStatus = await isCcrInstalled();
129
+ if (!ccrStatus.hasCorrectPackage) {
130
+ await installCcr();
131
+ } else {
132
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrAlreadyInstalled")}`));
133
+ }
134
+ const ccrConfigured = await setupCcrConfiguration();
135
+ if (ccrConfigured) {
136
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrSetupComplete")}`));
137
+ }
138
+ }
139
+ async function handleSwitchConfigMode() {
140
+ ensureI18nInitialized();
141
+ const { configSwitchCommand } = await import('../cli.mjs').then(function (n) { return n.c; });
142
+ await configSwitchCommand({ codeType: "claude-code" });
143
+ }
144
+ async function configureApiFeature() {
145
+ ensureI18nInitialized();
146
+ const { mode } = await inquirer.prompt({
147
+ type: "list",
148
+ name: "mode",
149
+ message: i18n.t("api:apiModePrompt"),
150
+ choices: addNumbersToChoices([
151
+ { name: i18n.t("api:apiModeOfficial"), value: "official" },
152
+ { name: i18n.t("api:apiModeCustom"), value: "custom" },
153
+ { name: i18n.t("api:apiModeCcr"), value: "ccr" },
154
+ { name: i18n.t("api:apiModeSwitch"), value: "switch" },
155
+ { name: i18n.t("api:apiModeSkip"), value: "skip" }
156
+ ])
157
+ });
158
+ if (!mode || mode === "skip") {
159
+ await handleCancellation();
160
+ return;
161
+ }
162
+ switch (mode) {
163
+ case "official":
164
+ await handleOfficialLoginMode();
165
+ break;
166
+ case "custom":
167
+ await handleCustomApiMode();
168
+ break;
169
+ case "ccr":
170
+ await handleCcrProxyMode();
171
+ break;
172
+ case "switch":
173
+ await handleSwitchConfigMode();
174
+ break;
175
+ default:
176
+ await handleCancellation();
177
+ break;
178
+ }
179
+ }
180
+ async function configureMcpFeature() {
181
+ ensureI18nInitialized();
182
+ if (isWindows()) {
183
+ const fixWindows = await promptBoolean({
184
+ message: i18n.t("configuration:fixWindowsMcp") || "Fix Windows MCP configuration?",
185
+ defaultValue: true
186
+ });
187
+ if (fixWindows) {
188
+ const existingConfig = readMcpConfig() || { mcpServers: {} };
189
+ const fixedConfig = fixWindowsMcpConfig(existingConfig);
190
+ writeMcpConfig(fixedConfig);
191
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:windowsMcpConfigFixed")}`));
192
+ }
193
+ }
194
+ const selectedServices = await selectMcpServices();
195
+ if (!selectedServices) {
196
+ return;
197
+ }
198
+ if (selectedServices.length > 0) {
199
+ const mcpBackupPath = backupMcpConfig();
200
+ if (mcpBackupPath) {
201
+ console.log(ansis.gray(`\u2714 ${i18n.t("mcp:mcpBackupSuccess")}: ${mcpBackupPath}`));
202
+ }
203
+ const newServers = {};
204
+ for (const serviceId of selectedServices) {
205
+ const service = (await getMcpServices()).find((s) => s.id === serviceId);
206
+ if (!service)
207
+ continue;
208
+ let config = service.config;
209
+ if (service.requiresApiKey) {
210
+ const { apiKey } = await inquirer.prompt({
211
+ type: "input",
212
+ name: "apiKey",
213
+ message: service.apiKeyPrompt,
214
+ validate: async (value) => !!value || i18n.t("api:keyRequired")
215
+ });
216
+ if (apiKey) {
217
+ config = buildMcpServerConfig(service.config, apiKey, service.apiKeyPlaceholder, service.apiKeyEnvVar);
218
+ } else {
219
+ continue;
220
+ }
221
+ }
222
+ newServers[service.id] = config;
223
+ }
224
+ const existingConfig = readMcpConfig();
225
+ let mergedConfig = mergeMcpServers(existingConfig, newServers);
226
+ mergedConfig = fixWindowsMcpConfig(mergedConfig);
227
+ writeMcpConfig(mergedConfig);
228
+ console.log(ansis.green(`\u2714 ${i18n.t("mcp:mcpConfigSuccess")}`));
229
+ }
230
+ }
231
+ async function configureDefaultModelFeature() {
232
+ ensureI18nInitialized();
233
+ const existingModel = getExistingModelConfig();
234
+ if (existingModel) {
235
+ console.log(`
236
+ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingModelConfig") || "Existing model configuration"}`)}`);
237
+ const modelDisplay = existingModel === "default" ? i18n.t("configuration:defaultModelOption") || "Default (Let Claude Code choose)" : existingModel.charAt(0).toUpperCase() + existingModel.slice(1);
238
+ console.log(ansis.gray(` ${i18n.t("configuration:currentModel") || "Current model"}: ${modelDisplay}
239
+ `));
240
+ const modify = await promptBoolean({
241
+ message: i18n.t("configuration:modifyModel") || "Modify model configuration?",
242
+ defaultValue: false
243
+ });
244
+ if (!modify) {
245
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:keepModel") || "Keeping existing model configuration"}`));
246
+ return;
247
+ }
248
+ }
249
+ const { model } = await inquirer.prompt({
250
+ type: "list",
251
+ name: "model",
252
+ message: i18n.t("configuration:selectDefaultModel") || "Select default model",
253
+ choices: addNumbersToChoices([
254
+ {
255
+ name: i18n.t("configuration:defaultModelOption") || "Default - Let Claude Code choose",
256
+ value: "default"
257
+ },
258
+ {
259
+ name: i18n.t("configuration:opusModelOption") || "Opus - Only use opus, high token consumption, use with caution",
260
+ value: "opus"
261
+ },
262
+ {
263
+ name: i18n.t("configuration:sonnet1mModelOption") || "Sonnet 1M - 1M context version",
264
+ value: "sonnet[1m]"
265
+ },
266
+ {
267
+ name: i18n.t("configuration:customModelOption") || "Custom - Specify custom model names",
268
+ value: "custom"
269
+ }
270
+ ]),
271
+ default: existingModel ? ["default", "opus", "sonnet[1m]", "custom"].indexOf(existingModel) : 0
272
+ });
273
+ if (!model) {
274
+ await handleCancellation();
275
+ return;
276
+ }
277
+ if (model === "custom") {
278
+ const { primaryModel, haikuModel, sonnetModel, opusModel } = await promptCustomModels();
279
+ if (!primaryModel.trim() && !haikuModel.trim() && !sonnetModel.trim() && !opusModel.trim()) {
280
+ console.log(ansis.yellow(`\u26A0 ${i18n.t("configuration:customModelSkipped") || "Custom model configuration skipped"}`));
281
+ return;
282
+ }
283
+ updateCustomModel(primaryModel, haikuModel, sonnetModel, opusModel);
284
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:customModelConfigured") || "Custom model configuration completed"}`));
285
+ return;
286
+ }
287
+ updateDefaultModel(model);
288
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:modelConfigured") || "Default model configured"}`));
289
+ }
290
+ async function promptCustomModels(defaultPrimaryModel, defaultHaikuModel, defaultSonnetModel, defaultOpusModel) {
291
+ const { primaryModel } = await inquirer.prompt({
292
+ type: "input",
293
+ name: "primaryModel",
294
+ message: `${i18n.t("configuration:enterPrimaryModel")}${i18n.t("common:emptyToSkip")}`,
295
+ default: defaultPrimaryModel || ""
296
+ });
297
+ const { haikuModel } = await inquirer.prompt({
298
+ type: "input",
299
+ name: "haikuModel",
300
+ message: `${i18n.t("configuration:enterHaikuModel")}${i18n.t("common:emptyToSkip")}`,
301
+ default: defaultHaikuModel || ""
302
+ });
303
+ const { sonnetModel } = await inquirer.prompt({
304
+ type: "input",
305
+ name: "sonnetModel",
306
+ message: `${i18n.t("configuration:enterSonnetModel")}${i18n.t("common:emptyToSkip")}`,
307
+ default: defaultSonnetModel || ""
308
+ });
309
+ const { opusModel } = await inquirer.prompt({
310
+ type: "input",
311
+ name: "opusModel",
312
+ message: `${i18n.t("configuration:enterOpusModel")}${i18n.t("common:emptyToSkip")}`,
313
+ default: defaultOpusModel || ""
314
+ });
315
+ return { primaryModel, haikuModel, sonnetModel, opusModel };
316
+ }
317
+ async function configureAiMemoryFeature() {
318
+ ensureI18nInitialized();
319
+ const { option } = await inquirer.prompt({
320
+ type: "list",
321
+ name: "option",
322
+ message: i18n.t("configuration:selectMemoryOption") || "Select configuration option",
323
+ choices: addNumbersToChoices([
324
+ {
325
+ name: i18n.t("configuration:configureAiLanguage") || "Configure AI output language",
326
+ value: "language"
327
+ },
328
+ {
329
+ name: i18n.t("configuration:configureOutputStyle") || "Configure global AI output style",
330
+ value: "outputStyle"
331
+ }
332
+ ])
333
+ });
334
+ if (!option) {
335
+ return;
336
+ }
337
+ if (option === "language") {
338
+ const zcfConfig = readZcfConfig();
339
+ const existingLang = zcfConfig?.aiOutputLang;
340
+ if (existingLang) {
341
+ console.log(
342
+ `
343
+ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existing AI output language configuration"}`)}`
344
+ );
345
+ console.log(ansis.gray(` ${i18n.t("configuration:currentLanguage") || "Current language"}: ${existingLang}
346
+ `));
347
+ const modify = await promptBoolean({
348
+ message: i18n.t("configuration:modifyLanguage") || "Modify AI output language?",
349
+ defaultValue: false
350
+ });
351
+ if (!modify) {
352
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:keepLanguage") || "Keeping existing language configuration"}`));
353
+ return;
354
+ }
355
+ }
356
+ const { selectAiOutputLanguage } = await import('./simple-config.mjs').then(function (n) { return n.d9; });
357
+ const aiOutputLang = await selectAiOutputLanguage();
358
+ applyAiLanguageDirective(aiOutputLang);
359
+ updateZcfConfig({ aiOutputLang });
360
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:aiLanguageConfigured") || "AI output language configured"}`));
361
+ } else if (option === "outputStyle") {
362
+ await configureOutputStyle();
363
+ }
364
+ }
365
+ async function changeScriptLanguageFeature(currentLang) {
366
+ ensureI18nInitialized();
367
+ const { lang } = await inquirer.prompt({
368
+ type: "list",
369
+ name: "lang",
370
+ message: i18n.t("language:selectScriptLang"),
371
+ choices: addNumbersToChoices(
372
+ SUPPORTED_LANGS.map((l) => ({
373
+ name: LANG_LABELS[l],
374
+ value: l
375
+ }))
376
+ ),
377
+ default: SUPPORTED_LANGS.indexOf(currentLang)
378
+ });
379
+ if (!lang) {
380
+ return currentLang;
381
+ }
382
+ updateZcfConfig({ preferredLang: lang });
383
+ await changeLanguage(lang);
384
+ console.log(ansis.green(`\u2714 ${i18n.t("language:languageChanged") || "Language changed"}`));
385
+ return lang;
386
+ }
387
+ async function configureCodexDefaultModelFeature() {
388
+ ensureI18nInitialized();
389
+ const { readCodexConfig } = await import('./simple-config.mjs').then(function (n) { return n.da; });
390
+ const existingConfig = readCodexConfig();
391
+ const currentModel = existingConfig?.model;
392
+ if (currentModel) {
393
+ console.log(`
394
+ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingModelConfig") || "Existing model configuration"}`)}`);
395
+ const modelDisplay = currentModel === "gpt-5-codex" ? "GPT-5-Codex" : currentModel === "gpt-5" ? "GPT-5" : currentModel.charAt(0).toUpperCase() + currentModel.slice(1);
396
+ console.log(ansis.gray(` ${i18n.t("configuration:currentModel") || "Current model"}: ${modelDisplay}
397
+ `));
398
+ const modify = await promptBoolean({
399
+ message: i18n.t("configuration:modifyModel") || "Modify model configuration?",
400
+ defaultValue: false
401
+ });
402
+ if (!modify) {
403
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:keepModel") || "Keeping existing model configuration"}`));
404
+ return;
405
+ }
406
+ }
407
+ const { model } = await inquirer.prompt({
408
+ type: "list",
409
+ name: "model",
410
+ message: i18n.t("configuration:selectDefaultModel") || "Select default model",
411
+ choices: addNumbersToChoices([
412
+ {
413
+ name: i18n.t("configuration:codexModelOptions.gpt5"),
414
+ value: "gpt-5"
415
+ },
416
+ {
417
+ name: i18n.t("configuration:codexModelOptions.gpt5Codex"),
418
+ value: "gpt-5-codex"
419
+ },
420
+ {
421
+ name: i18n.t("configuration:codexModelOptions.custom"),
422
+ value: "custom"
423
+ }
424
+ ]),
425
+ default: currentModel ? ["gpt-5", "gpt-5-codex", "custom"].indexOf(currentModel) : 1
426
+ // Default to gpt-5-codex
427
+ });
428
+ if (!model) {
429
+ await handleCancellation();
430
+ return;
431
+ }
432
+ if (model === "custom") {
433
+ const { customModel } = await inquirer.prompt({
434
+ type: "input",
435
+ name: "customModel",
436
+ message: `${i18n.t("configuration:enterCustomModel")}${i18n.t("common:emptyToSkip")}`,
437
+ default: ""
438
+ });
439
+ if (!customModel.trim()) {
440
+ console.log(ansis.yellow(`\u26A0 ${i18n.t("configuration:customModelSkipped") || "Custom model configuration skipped"}`));
441
+ return;
442
+ }
443
+ await updateCodexModelProvider(customModel.trim());
444
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:customModelConfigured") || "Custom model configuration completed"}`));
445
+ return;
446
+ }
447
+ await updateCodexModelProvider(model);
448
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:modelConfigured") || "Default model configured"}`));
449
+ }
450
+ async function configureCodexAiMemoryFeature() {
451
+ ensureI18nInitialized();
452
+ const { option } = await inquirer.prompt({
453
+ type: "list",
454
+ name: "option",
455
+ message: i18n.t("configuration:selectMemoryOption") || "Select configuration option",
456
+ choices: addNumbersToChoices([
457
+ {
458
+ name: i18n.t("configuration:configureAiLanguage") || "Configure AI output language",
459
+ value: "language"
460
+ },
461
+ {
462
+ name: i18n.t("configuration:configureSystemPromptStyle") || "Configure global AI system prompt style",
463
+ value: "systemPrompt"
464
+ }
465
+ ])
466
+ });
467
+ if (!option) {
468
+ return;
469
+ }
470
+ if (option === "language") {
471
+ const zcfConfig = readZcfConfig();
472
+ const existingLang = zcfConfig?.aiOutputLang;
473
+ if (existingLang) {
474
+ console.log(
475
+ `
476
+ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existing AI output language configuration"}`)}`
477
+ );
478
+ console.log(ansis.gray(` ${i18n.t("configuration:currentLanguage") || "Current language"}: ${existingLang}
479
+ `));
480
+ const modify = await promptBoolean({
481
+ message: i18n.t("configuration:modifyLanguage") || "Modify AI output language?",
482
+ defaultValue: false
483
+ });
484
+ if (!modify) {
485
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:keepLanguage") || "Keeping existing language configuration"}`));
486
+ await ensureLanguageDirectiveInAgents(existingLang);
487
+ return;
488
+ }
489
+ }
490
+ const { selectAiOutputLanguage } = await import('./simple-config.mjs').then(function (n) { return n.d9; });
491
+ const aiOutputLang = await selectAiOutputLanguage();
492
+ await updateCodexLanguageDirective(aiOutputLang);
493
+ updateZcfConfig({ aiOutputLang });
494
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:aiLanguageConfigured") || "AI output language configured"}`));
495
+ } else if (option === "systemPrompt") {
496
+ const zcfConfig = readZcfConfig();
497
+ const currentLang = zcfConfig?.aiOutputLang || "English";
498
+ const { runCodexSystemPromptSelection } = await import('./simple-config.mjs').then(function (n) { return n.da; });
499
+ await runCodexSystemPromptSelection();
500
+ await ensureLanguageDirectiveInAgents(currentLang);
501
+ console.log(ansis.green(`\u2714 ${i18n.t("configuration:systemPromptConfigured")}`));
502
+ }
503
+ }
504
+ async function updateCodexModelProvider(modelProvider) {
505
+ const { readCodexConfig, writeCodexConfig, backupCodexConfig, getBackupMessage } = await import('./simple-config.mjs').then(function (n) { return n.da; });
506
+ const backupPath = backupCodexConfig();
507
+ if (backupPath) {
508
+ console.log(ansis.gray(getBackupMessage(backupPath)));
509
+ }
510
+ const existingConfig = readCodexConfig();
511
+ const updatedConfig = {
512
+ ...existingConfig,
513
+ model: modelProvider,
514
+ // Set the model field
515
+ modelProvider: existingConfig?.modelProvider || null,
516
+ // Preserve existing API provider
517
+ providers: existingConfig?.providers || [],
518
+ mcpServices: existingConfig?.mcpServices || [],
519
+ managed: true,
520
+ otherConfig: existingConfig?.otherConfig || [],
521
+ modelProviderCommented: existingConfig?.modelProviderCommented
522
+ };
523
+ writeCodexConfig(updatedConfig);
524
+ }
525
+ async function ensureLanguageDirectiveInAgents(aiOutputLang) {
526
+ const { readFile, writeFile, exists } = await import('./simple-config.mjs').then(function (n) { return n.d4; });
527
+ const { homedir } = await import('node:os');
528
+ const { join } = await import('pathe');
529
+ const CODEX_AGENTS_FILE = join(homedir(), ".codex", "AGENTS.md");
530
+ if (!exists(CODEX_AGENTS_FILE)) {
531
+ console.log(ansis.yellow(i18n.t("codex:agentsFileNotFound")));
532
+ return;
533
+ }
534
+ const content = readFile(CODEX_AGENTS_FILE);
535
+ const languageLabels = {
536
+ "Chinese": "Chinese-simplified",
537
+ "English": "English",
538
+ "zh-CN": "Chinese-simplified",
539
+ "en": "English"
540
+ };
541
+ const langLabel = languageLabels[aiOutputLang] || aiOutputLang;
542
+ const hasLanguageDirective = /\*\*Most Important:\s*Always respond in [^*]+\*\*/i.test(content);
543
+ if (!hasLanguageDirective) {
544
+ const { backupCodexAgents, getBackupMessage } = await import('./simple-config.mjs').then(function (n) { return n.da; });
545
+ const backupPath = backupCodexAgents();
546
+ if (backupPath) {
547
+ console.log(ansis.gray(getBackupMessage(backupPath)));
548
+ }
549
+ let updatedContent = content;
550
+ if (!updatedContent.endsWith("\n")) {
551
+ updatedContent += "\n";
552
+ }
553
+ updatedContent += `
554
+ **Most Important:Always respond in ${langLabel}**
555
+ `;
556
+ writeFile(CODEX_AGENTS_FILE, updatedContent);
557
+ console.log(ansis.gray(` ${i18n.t("configuration:addedLanguageDirective")}: ${langLabel}`));
558
+ }
559
+ }
560
+ async function updateCodexLanguageDirective(aiOutputLang) {
561
+ const { readFile, writeFile, exists } = await import('./simple-config.mjs').then(function (n) { return n.d4; });
562
+ const { backupCodexAgents, getBackupMessage } = await import('./simple-config.mjs').then(function (n) { return n.da; });
563
+ const { homedir } = await import('node:os');
564
+ const { join } = await import('pathe');
565
+ const CODEX_AGENTS_FILE = join(homedir(), ".codex", "AGENTS.md");
566
+ if (!exists(CODEX_AGENTS_FILE)) {
567
+ console.log(ansis.yellow(i18n.t("codex:agentsFileNotFound")));
568
+ return;
569
+ }
570
+ const backupPath = backupCodexAgents();
571
+ if (backupPath) {
572
+ console.log(ansis.gray(getBackupMessage(backupPath)));
573
+ }
574
+ let content = readFile(CODEX_AGENTS_FILE);
575
+ const languageLabels = {
576
+ "Chinese": "Chinese-simplified",
577
+ "English": "English",
578
+ "zh-CN": "Chinese-simplified",
579
+ "en": "English"
580
+ };
581
+ const langLabel = languageLabels[aiOutputLang] || aiOutputLang;
582
+ content = content.replace(/\*\*Most Important:\s*Always respond in [^*]+\*\*\s*/g, "");
583
+ if (!content.endsWith("\n")) {
584
+ content += "\n";
585
+ }
586
+ content += `
587
+ **Most Important:Always respond in ${langLabel}**
588
+ `;
589
+ writeFile(CODEX_AGENTS_FILE, content);
590
+ }
591
+ async function configureEnvPermissionFeature() {
592
+ ensureI18nInitialized();
593
+ const { choice } = await inquirer.prompt({
594
+ type: "list",
595
+ name: "choice",
596
+ message: i18n.t("configuration:selectEnvPermissionOption") || "Select option",
597
+ choices: addNumbersToChoices([
598
+ {
599
+ name: `${i18n.t("configuration:importRecommendedEnv") || "Import environment"} ${ansis.gray(
600
+ `- ${i18n.t("configuration:importRecommendedEnvDesc") || "Import env settings"}`
601
+ )}`,
602
+ value: "env"
603
+ },
604
+ {
605
+ name: `${i18n.t("configuration:importRecommendedPermissions") || "Import permissions"} ${ansis.gray(
606
+ `- ${i18n.t("configuration:importRecommendedPermissionsDesc") || "Import permission settings"}`
607
+ )}`,
608
+ value: "permissions"
609
+ },
610
+ {
611
+ name: `${i18n.t("configuration:openSettingsJson") || "Open settings"} ${ansis.gray(
612
+ `- ${i18n.t("configuration:openSettingsJsonDesc") || "View settings file"}`
613
+ )}`,
614
+ value: "open"
615
+ }
616
+ ])
617
+ });
618
+ if (!choice) {
619
+ await handleCancellation();
620
+ return;
621
+ }
622
+ try {
623
+ switch (choice) {
624
+ case "env":
625
+ await importRecommendedEnv();
626
+ console.log(ansis.green(`\u2705 ${i18n.t("configuration:envImportSuccess")}`));
627
+ break;
628
+ case "permissions":
629
+ await importRecommendedPermissions();
630
+ console.log(ansis.green(`\u2705 ${i18n.t("configuration:permissionsImportSuccess") || "Permissions imported"}`));
631
+ break;
632
+ case "open":
633
+ console.log(ansis.cyan(i18n.t("configuration:openingSettingsJson") || "Opening settings.json..."));
634
+ await openSettingsJson();
635
+ break;
636
+ }
637
+ } catch (error) {
638
+ console.error(ansis.red(`${i18n.t("common:error")}: ${error.message}`));
639
+ }
640
+ }
641
+
642
+ export { changeScriptLanguageFeature, configureAiMemoryFeature, configureApiFeature, configureCodexAiMemoryFeature, configureCodexDefaultModelFeature, configureDefaultModelFeature, configureEnvPermissionFeature, configureMcpFeature, promptCustomModels };