ccjk 2.4.3 → 2.5.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.
Files changed (53) hide show
  1. package/dist/chunks/api-providers.mjs +73 -1
  2. package/dist/chunks/ccjk-config.mjs +13 -77
  3. package/dist/chunks/ccr.mjs +9 -4
  4. package/dist/chunks/check-updates.mjs +4 -2
  5. package/dist/chunks/claude-code-config-manager.mjs +9 -15
  6. package/dist/chunks/claude-code-incremental-manager.mjs +5 -8
  7. package/dist/chunks/codex.mjs +10 -569
  8. package/dist/chunks/config-switch.mjs +7 -5
  9. package/dist/chunks/config.mjs +573 -0
  10. package/dist/chunks/config2.mjs +451 -0
  11. package/dist/chunks/doctor.mjs +89 -1
  12. package/dist/chunks/features.mjs +13 -10
  13. package/dist/chunks/index.mjs +10 -1164
  14. package/dist/chunks/index2.mjs +8 -2
  15. package/dist/chunks/init.mjs +14 -11
  16. package/dist/chunks/json-config.mjs +59 -0
  17. package/dist/chunks/mcp-server.mjs +776 -0
  18. package/dist/chunks/mcp.mjs +10 -8
  19. package/dist/chunks/menu.mjs +5 -5
  20. package/dist/chunks/package.mjs +1 -1
  21. package/dist/chunks/permissions.mjs +420 -0
  22. package/dist/chunks/prompts.mjs +2 -1
  23. package/dist/chunks/providers.mjs +261 -0
  24. package/dist/chunks/session.mjs +484 -41
  25. package/dist/chunks/skills.mjs +553 -0
  26. package/dist/chunks/stats.mjs +411 -0
  27. package/dist/chunks/uninstall.mjs +4 -3
  28. package/dist/chunks/update.mjs +6 -3
  29. package/dist/chunks/workflows2.mjs +140 -0
  30. package/dist/cli.mjs +316 -10
  31. package/dist/i18n/locales/en/hooks.json +47 -0
  32. package/dist/i18n/locales/en/mcp.json +55 -0
  33. package/dist/i18n/locales/en/permissions.json +43 -0
  34. package/dist/i18n/locales/en/sandbox.json +44 -0
  35. package/dist/i18n/locales/en/skills.json +89 -129
  36. package/dist/i18n/locales/en/stats.json +20 -0
  37. package/dist/i18n/locales/zh-CN/hooks.json +47 -0
  38. package/dist/i18n/locales/zh-CN/mcp.json +55 -0
  39. package/dist/i18n/locales/zh-CN/permissions.json +43 -0
  40. package/dist/i18n/locales/zh-CN/sandbox.json +44 -0
  41. package/dist/i18n/locales/zh-CN/skills.json +88 -128
  42. package/dist/i18n/locales/zh-CN/stats.json +20 -0
  43. package/dist/index.mjs +12 -8
  44. package/dist/shared/ccjk.B-lZxV2u.mjs +1162 -0
  45. package/dist/shared/{ccjk.CURU8gbR.mjs → ccjk.CUdzQluX.mjs} +1 -1
  46. package/dist/shared/{ccjk.ByTIGCUC.mjs → ccjk.Dut3wyoP.mjs} +1 -1
  47. package/dist/shared/ccjk.J8YiPsOw.mjs +259 -0
  48. package/dist/shared/{ccjk.CGTmRqsu.mjs → ccjk.rLRHmcqD.mjs} +5 -134
  49. package/dist/shared/{ccjk.QbS8EAOd.mjs → ccjk.uVUeWAt8.mjs} +2 -1
  50. package/package.json +1 -1
  51. package/templates/common/skills/code-review.md +343 -0
  52. package/templates/common/skills/summarize.md +312 -0
  53. package/templates/common/skills/translate.md +202 -0
@@ -0,0 +1,573 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import ansis from 'ansis';
3
+ import dayjs from 'dayjs';
4
+ import inquirer from 'inquirer';
5
+ import { join, dirname } from 'pathe';
6
+ import { CLAUDE_VSC_CONFIG_FILE, CLAUDE_DIR, ClAUDE_CONFIG_FILE, SETTINGS_FILE, AI_OUTPUT_LANGUAGES } from './constants.mjs';
7
+ import { ensureI18nInitialized, i18n } from './index2.mjs';
8
+ import { readJsonConfig, writeJsonConfig, backupJsonConfig } from './json-config.mjs';
9
+ import { isWindows, getMcpCommand } from './platform.mjs';
10
+ import { ensureDir, exists, copyDir, writeFileAtomic, copyFile } from './fs-operations.mjs';
11
+
12
+ function mergeArraysUnique(arr1, arr2) {
13
+ const combined = [...arr1 || [], ...arr2 || []];
14
+ return [...new Set(combined)];
15
+ }
16
+ function isPlainObject(value) {
17
+ return value !== null && typeof value === "object" && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]";
18
+ }
19
+ function deepMerge(target, source, options = {}) {
20
+ const { mergeArrays = false, arrayMergeStrategy = "replace" } = options;
21
+ const result = { ...target };
22
+ for (const key in source) {
23
+ const sourceValue = source[key];
24
+ const targetValue = result[key];
25
+ if (sourceValue === void 0) {
26
+ continue;
27
+ }
28
+ if (isPlainObject(sourceValue) && isPlainObject(targetValue)) {
29
+ result[key] = deepMerge(targetValue, sourceValue, options);
30
+ } else if (Array.isArray(sourceValue)) {
31
+ if (!mergeArrays || !Array.isArray(targetValue)) {
32
+ result[key] = sourceValue;
33
+ } else {
34
+ switch (arrayMergeStrategy) {
35
+ case "concat":
36
+ result[key] = [...targetValue, ...sourceValue];
37
+ break;
38
+ case "unique":
39
+ result[key] = mergeArraysUnique(targetValue, sourceValue);
40
+ break;
41
+ case "replace":
42
+ default:
43
+ result[key] = sourceValue;
44
+ break;
45
+ }
46
+ }
47
+ } else {
48
+ result[key] = sourceValue;
49
+ }
50
+ }
51
+ return result;
52
+ }
53
+ function deepClone(obj) {
54
+ if (obj === null || typeof obj !== "object") {
55
+ return obj;
56
+ }
57
+ if (obj instanceof Date) {
58
+ return new Date(obj.getTime());
59
+ }
60
+ if (Array.isArray(obj)) {
61
+ return obj.map((item) => deepClone(item));
62
+ }
63
+ if (isPlainObject(obj)) {
64
+ const cloned = {};
65
+ for (const key in obj) {
66
+ cloned[key] = deepClone(obj[key]);
67
+ }
68
+ return cloned;
69
+ }
70
+ return obj;
71
+ }
72
+
73
+ function getMcpConfigPath() {
74
+ return ClAUDE_CONFIG_FILE;
75
+ }
76
+ function readMcpConfig() {
77
+ return readJsonConfig(ClAUDE_CONFIG_FILE);
78
+ }
79
+ function writeMcpConfig(config) {
80
+ writeJsonConfig(ClAUDE_CONFIG_FILE, config);
81
+ }
82
+ function backupMcpConfig() {
83
+ const backupBaseDir = join(CLAUDE_DIR, "backup");
84
+ return backupJsonConfig(ClAUDE_CONFIG_FILE, backupBaseDir);
85
+ }
86
+ function mergeMcpServers(existing, newServers) {
87
+ const config = existing || { mcpServers: {} };
88
+ if (!config.mcpServers) {
89
+ config.mcpServers = {};
90
+ }
91
+ Object.assign(config.mcpServers, newServers);
92
+ return config;
93
+ }
94
+ function applyPlatformCommand(config) {
95
+ if (isWindows() && config.command) {
96
+ const mcpCmd = getMcpCommand(config.command);
97
+ if (mcpCmd[0] === "cmd") {
98
+ config.command = mcpCmd[0];
99
+ config.args = [...mcpCmd.slice(1), ...config.args || []];
100
+ }
101
+ }
102
+ }
103
+ function buildMcpServerConfig(baseConfig, apiKey, placeholder = "YOUR_EXA_API_KEY", envVarName) {
104
+ const config = deepClone(baseConfig);
105
+ applyPlatformCommand(config);
106
+ if (!apiKey) {
107
+ return config;
108
+ }
109
+ if (envVarName && config.env) {
110
+ config.env[envVarName] = apiKey;
111
+ return config;
112
+ }
113
+ if (config.args) {
114
+ config.args = config.args.map((arg) => arg.replace(placeholder, apiKey));
115
+ }
116
+ if (config.url) {
117
+ config.url = config.url.replace(placeholder, apiKey);
118
+ }
119
+ return config;
120
+ }
121
+ function fixWindowsMcpConfig(config) {
122
+ if (!isWindows() || !config.mcpServers) {
123
+ return config;
124
+ }
125
+ const fixed = { ...config };
126
+ for (const [, serverConfig] of Object.entries(fixed.mcpServers)) {
127
+ if (serverConfig && typeof serverConfig === "object" && "command" in serverConfig) {
128
+ applyPlatformCommand(serverConfig);
129
+ }
130
+ }
131
+ return fixed;
132
+ }
133
+ function addCompletedOnboarding() {
134
+ try {
135
+ let config = readMcpConfig();
136
+ if (!config) {
137
+ config = { mcpServers: {} };
138
+ }
139
+ if (config.hasCompletedOnboarding === true) {
140
+ return;
141
+ }
142
+ config.hasCompletedOnboarding = true;
143
+ writeMcpConfig(config);
144
+ } catch (error) {
145
+ console.error("Failed to add onboarding flag", error);
146
+ throw error;
147
+ }
148
+ }
149
+ function ensureApiKeyApproved(config, apiKey) {
150
+ if (!apiKey || typeof apiKey !== "string" || apiKey.trim() === "") {
151
+ return config;
152
+ }
153
+ const truncatedApiKey = apiKey.substring(0, 20);
154
+ const updatedConfig = { ...config };
155
+ if (!updatedConfig.customApiKeyResponses) {
156
+ updatedConfig.customApiKeyResponses = {
157
+ approved: [],
158
+ rejected: []
159
+ };
160
+ }
161
+ if (!Array.isArray(updatedConfig.customApiKeyResponses.approved)) {
162
+ updatedConfig.customApiKeyResponses.approved = [];
163
+ }
164
+ if (!Array.isArray(updatedConfig.customApiKeyResponses.rejected)) {
165
+ updatedConfig.customApiKeyResponses.rejected = [];
166
+ }
167
+ const rejectedIndex = updatedConfig.customApiKeyResponses.rejected.indexOf(truncatedApiKey);
168
+ if (rejectedIndex > -1) {
169
+ updatedConfig.customApiKeyResponses.rejected.splice(rejectedIndex, 1);
170
+ }
171
+ if (!updatedConfig.customApiKeyResponses.approved.includes(truncatedApiKey)) {
172
+ updatedConfig.customApiKeyResponses.approved.push(truncatedApiKey);
173
+ }
174
+ return updatedConfig;
175
+ }
176
+ function removeApiKeyFromRejected(config, apiKey) {
177
+ if (!config.customApiKeyResponses || !Array.isArray(config.customApiKeyResponses.rejected)) {
178
+ return config;
179
+ }
180
+ const truncatedApiKey = apiKey.substring(0, 20);
181
+ const updatedConfig = { ...config };
182
+ if (updatedConfig.customApiKeyResponses) {
183
+ const rejectedIndex = updatedConfig.customApiKeyResponses.rejected.indexOf(truncatedApiKey);
184
+ if (rejectedIndex > -1) {
185
+ updatedConfig.customApiKeyResponses.rejected.splice(rejectedIndex, 1);
186
+ }
187
+ }
188
+ return updatedConfig;
189
+ }
190
+ function manageApiKeyApproval(apiKey) {
191
+ try {
192
+ let config = readMcpConfig();
193
+ if (!config) {
194
+ config = { mcpServers: {} };
195
+ }
196
+ const updatedConfig = ensureApiKeyApproved(config, apiKey);
197
+ writeMcpConfig(updatedConfig);
198
+ } catch (error) {
199
+ ensureI18nInitialized();
200
+ console.error(i18n.t("mcp:apiKeyApprovalFailed"), error);
201
+ }
202
+ }
203
+ function setPrimaryApiKey() {
204
+ try {
205
+ let config = readJsonConfig(CLAUDE_VSC_CONFIG_FILE);
206
+ if (!config) {
207
+ config = {};
208
+ }
209
+ config.primaryApiKey = "ccjk";
210
+ writeJsonConfig(CLAUDE_VSC_CONFIG_FILE, config);
211
+ } catch (error) {
212
+ ensureI18nInitialized();
213
+ console.error(i18n.t("mcp:primaryApiKeySetFailed"), error);
214
+ }
215
+ }
216
+
217
+ const claudeConfig = {
218
+ __proto__: null,
219
+ addCompletedOnboarding: addCompletedOnboarding,
220
+ backupMcpConfig: backupMcpConfig,
221
+ buildMcpServerConfig: buildMcpServerConfig,
222
+ ensureApiKeyApproved: ensureApiKeyApproved,
223
+ fixWindowsMcpConfig: fixWindowsMcpConfig,
224
+ getMcpConfigPath: getMcpConfigPath,
225
+ manageApiKeyApproval: manageApiKeyApproval,
226
+ mergeMcpServers: mergeMcpServers,
227
+ readMcpConfig: readMcpConfig,
228
+ removeApiKeyFromRejected: removeApiKeyFromRejected,
229
+ setPrimaryApiKey: setPrimaryApiKey,
230
+ writeMcpConfig: writeMcpConfig
231
+ };
232
+
233
+ const MODEL_ENV_KEYS = [
234
+ "ANTHROPIC_MODEL",
235
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL",
236
+ "ANTHROPIC_DEFAULT_SONNET_MODEL",
237
+ "ANTHROPIC_DEFAULT_OPUS_MODEL",
238
+ // Deprecated but still cleaned to avoid stale values
239
+ "ANTHROPIC_SMALL_FAST_MODEL"
240
+ ];
241
+ function clearModelEnv(env) {
242
+ for (const key of MODEL_ENV_KEYS) {
243
+ delete env[key];
244
+ }
245
+ }
246
+
247
+ function cleanupPermissions(templatePermissions, userPermissions) {
248
+ const templateSet = new Set(templatePermissions);
249
+ const cleanedPermissions = userPermissions.filter((permission) => {
250
+ if (["mcp__.*", "mcp__*", "mcp__(*)"].includes(permission)) {
251
+ return false;
252
+ }
253
+ for (const templatePerm of templatePermissions) {
254
+ if (permission === templatePerm) {
255
+ continue;
256
+ }
257
+ if (permission.startsWith(templatePerm)) {
258
+ return false;
259
+ }
260
+ }
261
+ return true;
262
+ });
263
+ const merged = [...templateSet];
264
+ for (const permission of cleanedPermissions) {
265
+ if (!templateSet.has(permission)) {
266
+ merged.push(permission);
267
+ }
268
+ }
269
+ return merged;
270
+ }
271
+ function mergeAndCleanPermissions(templatePermissions, userPermissions) {
272
+ const template = templatePermissions || [];
273
+ const user = userPermissions || [];
274
+ return cleanupPermissions(template, user);
275
+ }
276
+
277
+ function ensureClaudeDir() {
278
+ ensureDir(CLAUDE_DIR);
279
+ }
280
+ function backupExistingConfig() {
281
+ if (!exists(CLAUDE_DIR)) {
282
+ return null;
283
+ }
284
+ const timestamp = dayjs().format("YYYY-MM-DD_HH-mm-ss");
285
+ const backupBaseDir = join(CLAUDE_DIR, "backup");
286
+ const backupDir = join(backupBaseDir, `backup_${timestamp}`);
287
+ ensureDir(backupDir);
288
+ const filter = (path) => {
289
+ return !path.includes("/backup");
290
+ };
291
+ copyDir(CLAUDE_DIR, backupDir, { filter });
292
+ return backupDir;
293
+ }
294
+ function copyConfigFiles(onlyMd = false) {
295
+ const currentFilePath = fileURLToPath(import.meta.url);
296
+ const distDir = dirname(dirname(currentFilePath));
297
+ const rootDir = dirname(distDir);
298
+ const baseTemplateDir = join(rootDir, "templates", "claude-code");
299
+ if (!onlyMd) {
300
+ const baseSettingsPath = join(baseTemplateDir, "common", "settings.json");
301
+ const destSettingsPath = join(CLAUDE_DIR, "settings.json");
302
+ if (exists(baseSettingsPath)) {
303
+ mergeSettingsFile(baseSettingsPath, destSettingsPath);
304
+ }
305
+ }
306
+ }
307
+ function getDefaultSettings() {
308
+ try {
309
+ const currentFilePath = fileURLToPath(import.meta.url);
310
+ const distDir = dirname(dirname(currentFilePath));
311
+ const rootDir = dirname(distDir);
312
+ const templateSettingsPath = join(rootDir, "templates", "claude-code", "common", "settings.json");
313
+ return readJsonConfig(templateSettingsPath) || {};
314
+ } catch (error) {
315
+ console.error("Failed to read template settings", error);
316
+ return {};
317
+ }
318
+ }
319
+ function configureApi(apiConfig) {
320
+ if (!apiConfig)
321
+ return null;
322
+ let settings = getDefaultSettings();
323
+ const existingSettings = readJsonConfig(SETTINGS_FILE);
324
+ if (existingSettings) {
325
+ settings = deepMerge(settings, existingSettings);
326
+ }
327
+ if (!settings.env) {
328
+ settings.env = {};
329
+ }
330
+ if (apiConfig.authType === "api_key") {
331
+ settings.env.ANTHROPIC_API_KEY = apiConfig.key;
332
+ delete settings.env.ANTHROPIC_AUTH_TOKEN;
333
+ } else if (apiConfig.authType === "auth_token") {
334
+ settings.env.ANTHROPIC_AUTH_TOKEN = apiConfig.key;
335
+ delete settings.env.ANTHROPIC_API_KEY;
336
+ }
337
+ if (apiConfig.url) {
338
+ settings.env.ANTHROPIC_BASE_URL = apiConfig.url;
339
+ }
340
+ writeJsonConfig(SETTINGS_FILE, settings);
341
+ if (apiConfig.authType) {
342
+ try {
343
+ setPrimaryApiKey();
344
+ } catch (error) {
345
+ ensureI18nInitialized();
346
+ console.error(i18n.t("mcp:primaryApiKeySetFailed"), error);
347
+ }
348
+ }
349
+ try {
350
+ addCompletedOnboarding();
351
+ } catch (error) {
352
+ console.error("Failed to set onboarding flag", error);
353
+ }
354
+ return apiConfig;
355
+ }
356
+ function mergeConfigs(sourceFile, targetFile) {
357
+ if (!exists(sourceFile))
358
+ return;
359
+ const target = readJsonConfig(targetFile) || {};
360
+ const source = readJsonConfig(sourceFile) || {};
361
+ const merged = deepMerge(target, source);
362
+ writeJsonConfig(targetFile, merged);
363
+ }
364
+ function updateCustomModel(primaryModel, haikuModel, sonnetModel, opusModel) {
365
+ if (!primaryModel?.trim() && !haikuModel?.trim() && !sonnetModel?.trim() && !opusModel?.trim()) {
366
+ return;
367
+ }
368
+ let settings = getDefaultSettings();
369
+ const existingSettings = readJsonConfig(SETTINGS_FILE);
370
+ if (existingSettings) {
371
+ settings = existingSettings;
372
+ }
373
+ delete settings.model;
374
+ settings.env = settings.env || {};
375
+ clearModelEnv(settings.env);
376
+ if (primaryModel?.trim()) {
377
+ settings.env.ANTHROPIC_MODEL = primaryModel.trim();
378
+ }
379
+ if (haikuModel?.trim())
380
+ settings.env.ANTHROPIC_DEFAULT_HAIKU_MODEL = haikuModel.trim();
381
+ if (sonnetModel?.trim())
382
+ settings.env.ANTHROPIC_DEFAULT_SONNET_MODEL = sonnetModel.trim();
383
+ if (opusModel?.trim())
384
+ settings.env.ANTHROPIC_DEFAULT_OPUS_MODEL = opusModel.trim();
385
+ writeJsonConfig(SETTINGS_FILE, settings);
386
+ }
387
+ function updateDefaultModel(model) {
388
+ let settings = getDefaultSettings();
389
+ const existingSettings = readJsonConfig(SETTINGS_FILE);
390
+ if (existingSettings) {
391
+ settings = existingSettings;
392
+ }
393
+ if (!settings.env) {
394
+ settings.env = {};
395
+ }
396
+ if (model !== "custom") {
397
+ clearModelEnv(settings.env);
398
+ }
399
+ if (model === "default" || model === "custom") {
400
+ delete settings.model;
401
+ } else {
402
+ settings.model = model;
403
+ }
404
+ writeJsonConfig(SETTINGS_FILE, settings);
405
+ }
406
+ function mergeSettingsFile(templatePath, targetPath) {
407
+ try {
408
+ const templateSettings = readJsonConfig(templatePath);
409
+ if (!templateSettings) {
410
+ console.error("Failed to read template settings");
411
+ return;
412
+ }
413
+ if (!exists(targetPath)) {
414
+ writeJsonConfig(targetPath, templateSettings);
415
+ return;
416
+ }
417
+ const existingSettings = readJsonConfig(targetPath) || {};
418
+ const mergedEnv = {
419
+ ...templateSettings.env || {},
420
+ // Template env vars first
421
+ ...existingSettings.env || {}
422
+ // User's env vars override (preserving API keys, etc.)
423
+ };
424
+ const mergedSettings = deepMerge(templateSettings, existingSettings, {
425
+ mergeArrays: true,
426
+ arrayMergeStrategy: "unique"
427
+ });
428
+ mergedSettings.env = mergedEnv;
429
+ if (mergedSettings.permissions && mergedSettings.permissions.allow) {
430
+ mergedSettings.permissions.allow = mergeAndCleanPermissions(
431
+ templateSettings.permissions?.allow,
432
+ existingSettings.permissions?.allow
433
+ );
434
+ }
435
+ writeJsonConfig(targetPath, mergedSettings);
436
+ } catch (error) {
437
+ console.error("Failed to merge settings", error);
438
+ if (exists(targetPath)) {
439
+ console.log("Preserving existing settings");
440
+ } else {
441
+ copyFile(templatePath, targetPath);
442
+ }
443
+ }
444
+ }
445
+ function getExistingModelConfig() {
446
+ const settings = readJsonConfig(SETTINGS_FILE);
447
+ if (!settings) {
448
+ return null;
449
+ }
450
+ const hasModelEnv = MODEL_ENV_KEYS.some((key) => settings.env?.[key]);
451
+ if (hasModelEnv) {
452
+ return "custom";
453
+ }
454
+ if (!settings.model) {
455
+ return "default";
456
+ }
457
+ const validModels = ["opus", "sonnet", "sonnet[1m]"];
458
+ if (validModels.includes(settings.model)) {
459
+ return settings.model;
460
+ }
461
+ return "default";
462
+ }
463
+ function getExistingApiConfig() {
464
+ const settings = readJsonConfig(SETTINGS_FILE);
465
+ if (!settings || !settings.env) {
466
+ return null;
467
+ }
468
+ const { ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_BASE_URL } = settings.env;
469
+ if (!ANTHROPIC_BASE_URL && !ANTHROPIC_API_KEY && !ANTHROPIC_AUTH_TOKEN) {
470
+ return null;
471
+ }
472
+ let authType;
473
+ let key;
474
+ if (ANTHROPIC_AUTH_TOKEN) {
475
+ authType = "auth_token";
476
+ key = ANTHROPIC_AUTH_TOKEN;
477
+ } else if (ANTHROPIC_API_KEY) {
478
+ authType = "api_key";
479
+ key = ANTHROPIC_API_KEY;
480
+ }
481
+ return {
482
+ url: ANTHROPIC_BASE_URL || "",
483
+ key: key || "",
484
+ authType
485
+ };
486
+ }
487
+ function applyAiLanguageDirective(aiOutputLang) {
488
+ const claudeFile = join(CLAUDE_DIR, "CLAUDE.md");
489
+ let directive = "";
490
+ if (aiOutputLang === "custom") {
491
+ return;
492
+ } else if (AI_OUTPUT_LANGUAGES[aiOutputLang]) {
493
+ directive = AI_OUTPUT_LANGUAGES[aiOutputLang].directive;
494
+ } else {
495
+ directive = `Always respond in ${aiOutputLang}`;
496
+ }
497
+ writeFileAtomic(claudeFile, directive);
498
+ }
499
+ function switchToOfficialLogin() {
500
+ try {
501
+ ensureI18nInitialized();
502
+ const settings = readJsonConfig(SETTINGS_FILE) || {};
503
+ if (settings.env) {
504
+ delete settings.env.ANTHROPIC_BASE_URL;
505
+ delete settings.env.ANTHROPIC_AUTH_TOKEN;
506
+ delete settings.env.ANTHROPIC_API_KEY;
507
+ }
508
+ writeJsonConfig(SETTINGS_FILE, settings);
509
+ const vscConfig = readJsonConfig(CLAUDE_VSC_CONFIG_FILE);
510
+ if (vscConfig) {
511
+ delete vscConfig.primaryApiKey;
512
+ writeJsonConfig(CLAUDE_VSC_CONFIG_FILE, vscConfig);
513
+ }
514
+ console.log(i18n.t("api:officialLoginConfigured"));
515
+ return true;
516
+ } catch (error) {
517
+ ensureI18nInitialized();
518
+ console.error(i18n.t("api:officialLoginFailed"), error);
519
+ return false;
520
+ }
521
+ }
522
+ async function promptApiConfigurationAction() {
523
+ ensureI18nInitialized();
524
+ const existingConfig = getExistingApiConfig();
525
+ if (!existingConfig) {
526
+ return null;
527
+ }
528
+ console.log(`
529
+ ${ansis.blue(`\u2139 ${i18n.t("api:existingApiConfig")}`)}`);
530
+ console.log(ansis.gray(` ${i18n.t("api:apiConfigUrl")}: ${existingConfig.url || "N/A"}`));
531
+ console.log(ansis.gray(` ${i18n.t("api:apiConfigKey")}: ${existingConfig.key ? `***${existingConfig.key.slice(-4)}` : "N/A"}`));
532
+ console.log(ansis.gray(` ${i18n.t("api:apiConfigAuthType")}: ${existingConfig.authType || "N/A"}
533
+ `));
534
+ const { choice } = await inquirer.prompt({
535
+ type: "list",
536
+ name: "choice",
537
+ message: i18n.t("api:selectCustomConfigAction"),
538
+ choices: [
539
+ {
540
+ name: i18n.t("api:modifyPartialConfig"),
541
+ value: "modify-partial"
542
+ },
543
+ {
544
+ name: i18n.t("api:modifyAllConfig"),
545
+ value: "modify-all"
546
+ },
547
+ {
548
+ name: i18n.t("api:keepExistingConfig"),
549
+ value: "keep-existing"
550
+ }
551
+ ]
552
+ });
553
+ return choice || null;
554
+ }
555
+
556
+ const config = {
557
+ __proto__: null,
558
+ applyAiLanguageDirective: applyAiLanguageDirective,
559
+ backupExistingConfig: backupExistingConfig,
560
+ configureApi: configureApi,
561
+ copyConfigFiles: copyConfigFiles,
562
+ ensureClaudeDir: ensureClaudeDir,
563
+ getExistingApiConfig: getExistingApiConfig,
564
+ getExistingModelConfig: getExistingModelConfig,
565
+ mergeConfigs: mergeConfigs,
566
+ mergeSettingsFile: mergeSettingsFile,
567
+ promptApiConfigurationAction: promptApiConfigurationAction,
568
+ switchToOfficialLogin: switchToOfficialLogin,
569
+ updateCustomModel: updateCustomModel,
570
+ updateDefaultModel: updateDefaultModel
571
+ };
572
+
573
+ export { promptApiConfigurationAction as A, clearModelEnv as B, claudeConfig as C, config as D, mergeMcpServers as a, backupMcpConfig as b, cleanupPermissions as c, buildMcpServerConfig as d, addCompletedOnboarding as e, fixWindowsMcpConfig as f, getMcpConfigPath as g, ensureApiKeyApproved as h, removeApiKeyFromRejected as i, manageApiKeyApproval as j, ensureClaudeDir as k, backupExistingConfig as l, mergeAndCleanPermissions as m, copyConfigFiles as n, configureApi as o, mergeConfigs as p, updateDefaultModel as q, readMcpConfig as r, setPrimaryApiKey as s, mergeSettingsFile as t, updateCustomModel as u, getExistingModelConfig as v, writeMcpConfig as w, getExistingApiConfig as x, applyAiLanguageDirective as y, switchToOfficialLogin as z };