ccjk 10.0.0 → 10.2.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 (113) hide show
  1. package/dist/chunks/agent-teams.mjs +1 -1
  2. package/dist/chunks/agent.mjs +1 -1
  3. package/dist/chunks/agents.mjs +1 -1
  4. package/dist/chunks/api-providers.mjs +1 -1
  5. package/dist/chunks/api.mjs +3 -3
  6. package/dist/chunks/auto-bootstrap.mjs +1 -1
  7. package/dist/chunks/auto-updater.mjs +1 -1
  8. package/dist/{shared/ccjk.Br91zBIG.mjs → chunks/banner.mjs} +52 -3
  9. package/dist/chunks/boost.mjs +2 -2
  10. package/dist/chunks/ccjk-agents.mjs +1 -1
  11. package/dist/chunks/ccjk-all.mjs +1 -1
  12. package/dist/chunks/ccjk-config.mjs +1 -1
  13. package/dist/chunks/ccjk-hooks.mjs +1 -1
  14. package/dist/chunks/ccjk-mcp.mjs +2 -2
  15. package/dist/chunks/ccjk-setup.mjs +1 -1
  16. package/dist/chunks/ccjk-skills.mjs +1 -1
  17. package/dist/chunks/ccr.mjs +10 -10
  18. package/dist/chunks/ccu.mjs +1 -1
  19. package/dist/chunks/check-updates.mjs +3 -3
  20. package/dist/chunks/claude-code-config-manager.mjs +7 -7
  21. package/dist/chunks/claude-code-incremental-manager.mjs +2 -2
  22. package/dist/chunks/claude-config.mjs +3 -3
  23. package/dist/chunks/claude-wrapper.mjs +2 -2
  24. package/dist/chunks/codex-config-switch.mjs +2 -2
  25. package/dist/chunks/codex-provider-manager.mjs +2 -2
  26. package/dist/chunks/codex-uninstaller.mjs +2 -2
  27. package/dist/chunks/codex.mjs +5 -5
  28. package/dist/chunks/commands.mjs +88 -391
  29. package/dist/chunks/commands2.mjs +391 -88
  30. package/dist/chunks/completion.mjs +1 -1
  31. package/dist/chunks/config-consolidator.mjs +2 -2
  32. package/dist/chunks/config-switch.mjs +3 -3
  33. package/dist/chunks/config.mjs +5 -5
  34. package/dist/chunks/config2.mjs +410 -400
  35. package/dist/chunks/config3.mjs +400 -410
  36. package/dist/chunks/constants.mjs +1 -1
  37. package/dist/chunks/context.mjs +283 -1
  38. package/dist/chunks/dashboard.mjs +365 -0
  39. package/dist/chunks/doctor.mjs +4 -4
  40. package/dist/chunks/features.mjs +11 -11
  41. package/dist/chunks/fs-operations.mjs +1 -1
  42. package/dist/chunks/health-alerts.mjs +304 -0
  43. package/dist/chunks/health-check.mjs +532 -0
  44. package/dist/chunks/index.mjs +10 -177
  45. package/dist/chunks/index2.mjs +168 -1162
  46. package/dist/chunks/index3.mjs +1076 -910
  47. package/dist/chunks/index4.mjs +947 -137
  48. package/dist/chunks/index5.mjs +167 -635
  49. package/dist/chunks/index6.mjs +663 -0
  50. package/dist/chunks/init.mjs +19 -19
  51. package/dist/chunks/installer.mjs +649 -147
  52. package/dist/chunks/installer2.mjs +147 -649
  53. package/dist/chunks/interview.mjs +2 -2
  54. package/dist/chunks/marketplace.mjs +1 -1
  55. package/dist/chunks/mcp.mjs +4 -4
  56. package/dist/chunks/menu.mjs +16 -9
  57. package/dist/chunks/metrics-display.mjs +152 -0
  58. package/dist/chunks/migrator.mjs +1 -1
  59. package/dist/chunks/monitor.mjs +2 -2
  60. package/dist/chunks/notification.mjs +1 -1
  61. package/dist/chunks/onboarding.mjs +2 -2
  62. package/dist/chunks/package.mjs +1 -1
  63. package/dist/chunks/permission-manager.mjs +2 -2
  64. package/dist/chunks/permissions.mjs +1 -1
  65. package/dist/chunks/persistence-manager.mjs +781 -0
  66. package/dist/chunks/persistence.mjs +667 -0
  67. package/dist/chunks/platform.mjs +1 -1
  68. package/dist/chunks/plugin.mjs +1 -1
  69. package/dist/chunks/prompts.mjs +1 -1
  70. package/dist/chunks/providers.mjs +1 -1
  71. package/dist/chunks/quick-actions.mjs +321 -0
  72. package/dist/chunks/quick-setup.mjs +8 -8
  73. package/dist/chunks/sessions.mjs +1 -1
  74. package/dist/chunks/silent-updater.mjs +1 -1
  75. package/dist/chunks/simple-config.mjs +2 -2
  76. package/dist/chunks/skill.mjs +1 -1
  77. package/dist/chunks/skills-sync.mjs +1 -1
  78. package/dist/chunks/skills.mjs +1 -1
  79. package/dist/chunks/slash-commands.mjs +208 -0
  80. package/dist/chunks/smart-defaults.mjs +1 -1
  81. package/dist/chunks/startup.mjs +1 -1
  82. package/dist/chunks/stats.mjs +1 -1
  83. package/dist/chunks/status.mjs +31 -2
  84. package/dist/chunks/team.mjs +1 -1
  85. package/dist/chunks/thinking.mjs +2 -2
  86. package/dist/chunks/uninstall.mjs +5 -5
  87. package/dist/chunks/update.mjs +7 -7
  88. package/dist/chunks/upgrade-manager.mjs +2 -2
  89. package/dist/chunks/version-checker.mjs +3 -3
  90. package/dist/chunks/vim.mjs +1 -1
  91. package/dist/cli.mjs +191 -21
  92. package/dist/i18n/locales/en/cli.json +14 -1
  93. package/dist/i18n/locales/en/common.json +27 -0
  94. package/dist/i18n/locales/en/context.json +54 -1
  95. package/dist/i18n/locales/en/dashboard.json +78 -0
  96. package/dist/i18n/locales/en/persistence.json +127 -0
  97. package/dist/i18n/locales/en/quick-actions.json +78 -0
  98. package/dist/i18n/locales/zh-CN/cli.json +14 -1
  99. package/dist/i18n/locales/zh-CN/common.json +27 -0
  100. package/dist/i18n/locales/zh-CN/context.json +54 -1
  101. package/dist/i18n/locales/zh-CN/dashboard.json +78 -0
  102. package/dist/i18n/locales/zh-CN/persistence.json +127 -0
  103. package/dist/i18n/locales/zh-CN/quick-actions.json +78 -0
  104. package/dist/index.mjs +2 -2
  105. package/dist/shared/{ccjk.DE91nClQ.mjs → ccjk.BKoi8-Hy.mjs} +1 -1
  106. package/dist/shared/{ccjk.Dpw86UX0.mjs → ccjk.CxtuJxaS.mjs} +1 -1
  107. package/dist/shared/{ccjk.ClzTOz9n.mjs → ccjk.DB2UYcq0.mjs} +5 -5
  108. package/dist/shared/{ccjk.Bndhan7G.mjs → ccjk.DfwJOEok.mjs} +1 -1
  109. package/dist/shared/{ccjk.DvIrK0wz.mjs → ccjk.DrMygfCF.mjs} +1 -1
  110. package/dist/shared/ccjk.DtMBiwVG.mjs +599 -0
  111. package/dist/shared/{ccjk.CmsW23FN.mjs → ccjk.IbImMVWM.mjs} +3 -3
  112. package/package.json +19 -19
  113. package/dist/shared/ccjk.OYWY25_l.mjs +0 -239
@@ -1,455 +1,465 @@
1
- import { existsSync, readFileSync, writeFileSync } from 'node:fs';
1
+ import { exec } from 'node:child_process';
2
+ import { existsSync, copyFileSync, mkdirSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
2
4
  import process__default from 'node:process';
5
+ import { promisify } from 'node:util';
3
6
  import ansis from 'ansis';
7
+ import dayjs from 'dayjs';
4
8
  import inquirer from 'inquirer';
5
- import { getApiProviderPresets } from './api-providers.mjs';
9
+ import { join } from 'pathe';
6
10
  import { SETTINGS_FILE } from './constants.mjs';
7
- import { i18n } from './index.mjs';
11
+ import { ensureI18nInitialized, i18n } from './index2.mjs';
12
+ import { s as setPrimaryApiKey, c as addCompletedOnboarding } from './claude-config.mjs';
8
13
  import { b as backupExistingConfig } from './config.mjs';
9
- import 'node:os';
10
- import 'pathe';
14
+ import { readJsonConfig, writeJsonConfig } from './json-config.mjs';
15
+ import { p as promptBoolean } from '../shared/ccjk.DHbrGcgg.mjs';
11
16
  import 'node:url';
12
17
  import 'i18next';
13
18
  import 'i18next-fs-backend';
14
- import 'dayjs';
15
- import './claude-config.mjs';
16
- import './json-config.mjs';
19
+ import './platform.mjs';
20
+ import 'tinyexec';
17
21
  import './fs-operations.mjs';
18
22
  import 'node:crypto';
19
23
  import 'node:fs/promises';
20
- import './platform.mjs';
21
- import 'tinyexec';
24
+ import 'inquirer-toggle';
22
25
 
23
- async function getConfig(key, options = {}) {
24
- const isZh = i18n.language === "zh-CN";
25
- try {
26
- const config = readClaudeConfig();
27
- if (!config) {
28
- console.log(ansis.yellow(isZh ? "\u26A0\uFE0F \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728" : "\u26A0\uFE0F Configuration file not found"));
29
- console.log(ansis.dim(isZh ? '\u8FD0\u884C "ccjk init" \u521D\u59CB\u5316\u914D\u7F6E' : 'Run "ccjk init" to initialize configuration'));
30
- console.log("");
31
- return;
32
- }
33
- const value = getNestedValue(config, key);
34
- if (value === void 0) {
35
- console.log(ansis.yellow(isZh ? `\u26A0\uFE0F \u914D\u7F6E\u9879 "${key}" \u4E0D\u5B58\u5728` : `\u26A0\uFE0F Configuration key "${key}" not found`));
36
- console.log("");
37
- return;
38
- }
39
- if (options.json) {
40
- console.log(JSON.stringify(value, null, 2));
41
- } else {
42
- console.log("");
43
- console.log(ansis.bold.cyan(isZh ? `\u{1F4CB} \u914D\u7F6E\u9879: ${key}` : `\u{1F4CB} Configuration: ${key}`));
44
- console.log(ansis.dim("\u2500".repeat(60)));
45
- console.log("");
46
- displayValue(value, 0);
47
- console.log("");
48
- }
49
- } catch (error) {
50
- console.error(ansis.red(isZh ? "\u274C \u8BFB\u53D6\u914D\u7F6E\u5931\u8D25" : "\u274C Failed to read configuration"));
51
- if (error instanceof Error) {
52
- console.error(ansis.dim(error.message));
53
- }
54
- console.log("");
55
- }
56
- }
57
- async function setConfig(key, value, _options = {}) {
58
- const isZh = i18n.language === "zh-CN";
59
- try {
60
- const config = readClaudeConfig();
61
- if (!config) {
62
- console.log(ansis.yellow(isZh ? "\u26A0\uFE0F \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728" : "\u26A0\uFE0F Configuration file not found"));
63
- console.log(ansis.dim(isZh ? '\u8FD0\u884C "ccjk init" \u521D\u59CB\u5316\u914D\u7F6E' : 'Run "ccjk init" to initialize configuration'));
64
- console.log("");
65
- return;
66
- }
67
- const backupPath = backupExistingConfig();
68
- if (backupPath) {
69
- console.log(ansis.dim(isZh ? `\u{1F4E6} \u5DF2\u5907\u4EFD\u914D\u7F6E\u5230: ${backupPath}` : `\u{1F4E6} Configuration backed up to: ${backupPath}`));
70
- }
71
- let parsedValue = value;
72
- try {
73
- parsedValue = JSON.parse(value);
74
- } catch {
75
- }
76
- setNestedValue(config, key, parsedValue);
77
- writeClaudeConfig(config);
78
- console.log("");
79
- console.log(ansis.green(isZh ? `\u2705 \u914D\u7F6E\u9879 "${key}" \u5DF2\u66F4\u65B0` : `\u2705 Configuration "${key}" updated`));
80
- console.log("");
81
- console.log(ansis.bold(isZh ? "\u65B0\u503C:" : "New value:"));
82
- displayValue(parsedValue, 0);
83
- console.log("");
84
- } catch (error) {
85
- console.error(ansis.red(isZh ? "\u274C \u8BBE\u7F6E\u914D\u7F6E\u5931\u8D25" : "\u274C Failed to set configuration"));
86
- if (error instanceof Error) {
87
- console.error(ansis.dim(error.message));
88
- }
89
- console.log("");
90
- }
91
- }
92
- async function listConfig(options = {}) {
93
- const isZh = i18n.language === "zh-CN";
94
- try {
95
- const config = readClaudeConfig();
96
- if (!config) {
97
- console.log(ansis.yellow(isZh ? "\u26A0\uFE0F \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728" : "\u26A0\uFE0F Configuration file not found"));
98
- console.log(ansis.dim(isZh ? '\u8FD0\u884C "ccjk init" \u521D\u59CB\u5316\u914D\u7F6E' : 'Run "ccjk init" to initialize configuration'));
99
- console.log("");
100
- return;
101
- }
102
- if (options.json) {
103
- console.log(JSON.stringify(config, null, 2));
104
- return;
105
- }
106
- console.log("");
107
- console.log(ansis.bold.cyan(isZh ? "\u{1F4CB} Claude Code \u914D\u7F6E" : "\u{1F4CB} Claude Code Configuration"));
108
- console.log(ansis.dim("\u2500".repeat(60)));
109
- console.log("");
110
- displayConfigSection(isZh ? "API \u914D\u7F6E" : "API Configuration", {
111
- baseUrl: config.baseUrl,
112
- apiKey: config.apiKey ? "***" : void 0,
113
- authToken: config.authToken ? "***" : void 0,
114
- model: config.model,
115
- fastModel: config.fastModel
116
- }, isZh);
117
- if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {
118
- displayConfigSection(isZh ? "MCP \u670D\u52A1" : "MCP Services", {
119
- count: Object.keys(config.mcpServers).length,
120
- services: Object.keys(config.mcpServers)
121
- }, isZh);
122
- }
123
- if (config.customInstructions) {
124
- displayConfigSection(isZh ? "\u81EA\u5B9A\u4E49\u6307\u4EE4" : "Custom Instructions", {
125
- length: config.customInstructions.length,
126
- preview: `${config.customInstructions.substring(0, 100)}...`
127
- }, isZh);
128
- }
129
- console.log("");
130
- console.log(ansis.dim("\u2500".repeat(60)));
131
- console.log(ansis.dim(isZh ? `\u914D\u7F6E\u6587\u4EF6: ${SETTINGS_FILE}` : `Config file: ${SETTINGS_FILE}`));
132
- console.log("");
133
- } catch (error) {
134
- console.error(ansis.red(isZh ? "\u274C \u8BFB\u53D6\u914D\u7F6E\u5931\u8D25" : "\u274C Failed to read configuration"));
135
- if (error instanceof Error) {
136
- console.error(ansis.dim(error.message));
137
- }
138
- console.log("");
139
- }
140
- }
141
- async function resetConfig(_options = {}) {
142
- const isZh = i18n.language === "zh-CN";
26
+ const PROVIDER_PRESETS_URL = "https://pub-0dc3e1677e894f07bbea11b17a29e032.r2.dev/providers.json";
27
+ async function fetchProviderPresets() {
143
28
  try {
144
- const config = readClaudeConfig();
145
- if (!config) {
146
- console.log(ansis.yellow(isZh ? "\u26A0\uFE0F \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728" : "\u26A0\uFE0F Configuration file not found"));
147
- console.log("");
148
- return;
149
- }
150
- const { confirm } = await inquirer.prompt({
151
- type: "confirm",
152
- name: "confirm",
153
- message: isZh ? "\u786E\u5B9A\u8981\u91CD\u7F6E\u914D\u7F6E\u5417\uFF1F\u8FD9\u5C06\u5220\u9664\u6240\u6709\u81EA\u5B9A\u4E49\u8BBE\u7F6E\u3002" : "Are you sure you want to reset configuration? This will remove all custom settings.",
154
- default: false
29
+ const controller = new AbortController();
30
+ const timeoutId = setTimeout(() => controller.abort(), 5e3);
31
+ const response = await fetch(PROVIDER_PRESETS_URL, {
32
+ signal: controller.signal
155
33
  });
156
- if (!confirm) {
157
- console.log(ansis.yellow(isZh ? "\u5DF2\u53D6\u6D88" : "Cancelled"));
158
- console.log("");
159
- return;
160
- }
161
- const backupPath = backupExistingConfig();
162
- if (backupPath) {
163
- console.log(ansis.dim(isZh ? `\u{1F4E6} \u5DF2\u5907\u4EFD\u914D\u7F6E\u5230: ${backupPath}` : `\u{1F4E6} Configuration backed up to: ${backupPath}`));
164
- }
165
- const minimalConfig = {
166
- completedOnboarding: true
167
- };
168
- writeClaudeConfig(minimalConfig);
169
- console.log("");
170
- console.log(ansis.green(isZh ? "\u2705 \u914D\u7F6E\u5DF2\u91CD\u7F6E" : "\u2705 Configuration reset"));
171
- console.log(ansis.dim(isZh ? '\u8FD0\u884C "ccjk init" \u91CD\u65B0\u914D\u7F6E' : 'Run "ccjk init" to reconfigure'));
172
- console.log("");
173
- } catch (error) {
174
- console.error(ansis.red(isZh ? "\u274C \u91CD\u7F6E\u914D\u7F6E\u5931\u8D25" : "\u274C Failed to reset configuration"));
175
- if (error instanceof Error) {
176
- console.error(ansis.dim(error.message));
177
- }
178
- console.log("");
179
- }
180
- }
181
- async function setProvider(providerId, options = {}) {
182
- const isZh = i18n.language === "zh-CN";
183
- const codeType = options.codeType || "claude-code";
184
- try {
185
- const providers = await getApiProviderPresets(codeType);
186
- const provider = providers.find((p) => p.id === providerId);
187
- if (!provider) {
188
- console.log(ansis.yellow(isZh ? `\u26A0\uFE0F \u4F9B\u5E94\u5546 "${providerId}" \u4E0D\u5B58\u5728` : `\u26A0\uFE0F Provider "${providerId}" not found`));
189
- console.log("");
190
- console.log(ansis.dim(isZh ? "\u53EF\u7528\u7684\u4F9B\u5E94\u5546:" : "Available providers:"));
191
- for (const p of providers) {
192
- console.log(` - ${p.id} (${p.name})`);
34
+ clearTimeout(timeoutId);
35
+ if (!response.ok) {
36
+ throw new Error(`HTTP error! status: ${response.status}`);
37
+ }
38
+ const data = await response.json();
39
+ const presets = [];
40
+ if (Array.isArray(data)) {
41
+ for (const provider of data) {
42
+ if (provider && typeof provider === "object") {
43
+ presets.push({
44
+ name: provider.name || "",
45
+ provider: provider.name || "",
46
+ baseURL: provider.api_base_url || provider.baseURL || provider.url,
47
+ requiresApiKey: provider.api_key === "" || provider.requiresApiKey !== false,
48
+ models: provider.models || [],
49
+ description: provider.description || provider.name || "",
50
+ transformer: provider.transformer
51
+ });
52
+ }
193
53
  }
194
- console.log("");
195
- return;
196
- }
197
- const config = readClaudeConfig();
198
- if (!config) {
199
- console.log(ansis.yellow(isZh ? "\u26A0\uFE0F \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728" : "\u26A0\uFE0F Configuration file not found"));
200
- console.log(ansis.dim(isZh ? '\u8FD0\u884C "ccjk init" \u521D\u59CB\u5316\u914D\u7F6E' : 'Run "ccjk init" to initialize configuration'));
201
- console.log("");
202
- return;
203
- }
204
- const backupPath = backupExistingConfig();
205
- if (backupPath) {
206
- console.log(ansis.dim(isZh ? `\u{1F4E6} \u5DF2\u5907\u4EFD\u914D\u7F6E\u5230: ${backupPath}` : `\u{1F4E6} Configuration backed up to: ${backupPath}`));
207
- }
208
- if (codeType === "claude-code" && provider.claudeCode) {
209
- config.baseUrl = provider.claudeCode.baseUrl;
210
- if (provider.claudeCode.defaultModels && provider.claudeCode.defaultModels.length > 0) {
211
- config.model = provider.claudeCode.defaultModels[0];
212
- if (provider.claudeCode.defaultModels.length > 1) {
213
- config.fastModel = provider.claudeCode.defaultModels[1];
54
+ } else if (data && typeof data === "object") {
55
+ for (const [key, value] of Object.entries(data)) {
56
+ if (typeof value === "object" && value !== null) {
57
+ const provider = value;
58
+ presets.push({
59
+ name: provider.name || key,
60
+ provider: key,
61
+ baseURL: provider.api_base_url || provider.baseURL || provider.url,
62
+ requiresApiKey: provider.api_key === "" || provider.requiresApiKey !== false,
63
+ models: provider.models || [],
64
+ description: provider.description || "",
65
+ transformer: provider.transformer
66
+ });
214
67
  }
215
68
  }
216
69
  }
217
- writeClaudeConfig(config);
218
- console.log("");
219
- console.log(ansis.green(isZh ? `\u2705 \u5DF2\u5207\u6362\u5230\u4F9B\u5E94\u5546: ${provider.name}` : `\u2705 Switched to provider: ${provider.name}`));
220
- console.log("");
221
- console.log(ansis.bold(isZh ? "\u914D\u7F6E\u8BE6\u60C5:" : "Configuration details:"));
222
- console.log(` ${ansis.green(isZh ? "\u4F9B\u5E94\u5546" : "Provider")}: ${provider.name}`);
223
- console.log(` ${ansis.green(isZh ? "\u63A5\u53E3\u5730\u5740" : "Base URL")}: ${config.baseUrl}`);
224
- if (config.model) {
225
- console.log(` ${ansis.green(isZh ? "\u4E3B\u6A21\u578B" : "Primary Model")}: ${config.model}`);
226
- }
227
- if (config.fastModel) {
228
- console.log(` ${ansis.green(isZh ? "\u5FEB\u901F\u6A21\u578B" : "Fast Model")}: ${config.fastModel}`);
229
- }
230
- console.log("");
231
- console.log(ansis.dim(isZh ? "\u{1F4A1} \u63D0\u793A: \u8BF7\u786E\u4FDD\u5DF2\u8BBE\u7F6E\u6B63\u786E\u7684 API \u5BC6\u94A5\u6216\u8BA4\u8BC1\u4EE4\u724C" : "\u{1F4A1} Tip: Make sure to set the correct API key or auth token"));
232
- console.log("");
233
- } catch (error) {
234
- console.error(ansis.red(isZh ? "\u274C \u8BBE\u7F6E\u4F9B\u5E94\u5546\u5931\u8D25" : "\u274C Failed to set provider"));
235
- if (error instanceof Error) {
236
- console.error(ansis.dim(error.message));
237
- }
238
- console.log("");
70
+ return presets;
71
+ } catch {
72
+ return getFallbackPresets();
239
73
  }
240
74
  }
241
- async function configCommand(action, args, options = {}) {
242
- switch (action) {
243
- case "get":
244
- if (args.length === 0) {
245
- const isZh = i18n.language === "zh-CN";
246
- console.log(ansis.yellow(isZh ? "\u26A0\uFE0F \u8BF7\u6307\u5B9A\u914D\u7F6E\u9879" : "\u26A0\uFE0F Please specify a configuration key"));
247
- console.log(ansis.dim(isZh ? "\u7528\u6CD5: ccjk config get <key>" : "Usage: ccjk config get <key>"));
248
- console.log("");
249
- return;
75
+ function getFallbackPresets() {
76
+ return [
77
+ {
78
+ name: "dashscope",
79
+ provider: "dashscope",
80
+ baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
81
+ requiresApiKey: true,
82
+ models: ["qwen3-coder-plus"],
83
+ description: "Alibaba DashScope",
84
+ transformer: {
85
+ "use": [["maxtoken", { max_tokens: 65536 }]],
86
+ "qwen3-coder-plus": {
87
+ use: ["enhancetool"]
88
+ }
89
+ }
90
+ },
91
+ {
92
+ name: "deepseek",
93
+ provider: "deepseek",
94
+ baseURL: "https://api.deepseek.com/chat/completions",
95
+ requiresApiKey: true,
96
+ models: ["deepseek-chat", "deepseek-reasoner"],
97
+ description: "DeepSeek AI models",
98
+ transformer: {
99
+ "use": ["deepseek"],
100
+ "deepseek-chat": {
101
+ use: ["tooluse"]
102
+ }
103
+ }
104
+ },
105
+ {
106
+ name: "gemini",
107
+ provider: "gemini",
108
+ baseURL: "https://generativelanguage.googleapis.com/v1beta/models/",
109
+ requiresApiKey: true,
110
+ models: ["gemini-2.5-flash", "gemini-2.5-pro"],
111
+ description: "Google Gemini models",
112
+ transformer: {
113
+ use: ["gemini"]
250
114
  }
251
- await getConfig(args[0], options);
252
- break;
253
- case "set":
254
- if (args.length < 2) {
255
- const isZh = i18n.language === "zh-CN";
256
- console.log(ansis.yellow(isZh ? "\u26A0\uFE0F \u8BF7\u6307\u5B9A\u914D\u7F6E\u9879\u548C\u503C" : "\u26A0\uFE0F Please specify key and value"));
257
- console.log(ansis.dim(isZh ? "\u7528\u6CD5: ccjk config set <key> <value>" : "Usage: ccjk config set <key> <value>"));
258
- console.log("");
259
- return;
115
+ },
116
+ {
117
+ name: "modelscope",
118
+ provider: "modelscope",
119
+ baseURL: "https://api-inference.modelscope.cn/v1/chat/completions",
120
+ requiresApiKey: true,
121
+ models: ["Qwen/Qwen3-Coder-480B-A35B-Instruct", "Qwen/Qwen3-235B-A22B-Thinking-2507", "ZhipuAI/GLM-4.5"],
122
+ description: "ModelScope AI models",
123
+ transformer: {
124
+ "use": [["maxtoken", { max_tokens: 65536 }]],
125
+ "Qwen/Qwen3-Coder-480B-A35B-Instruct": {
126
+ use: ["enhancetool"]
127
+ },
128
+ "Qwen/Qwen3-235B-A22B-Thinking-2507": {
129
+ use: ["reasoning"]
130
+ }
131
+ }
132
+ },
133
+ {
134
+ name: "openrouter",
135
+ provider: "openrouter",
136
+ baseURL: "https://openrouter.ai/api/v1/chat/completions",
137
+ requiresApiKey: true,
138
+ models: [
139
+ "google/gemini-2.5-pro-preview",
140
+ "anthropic/claude-sonnet-4",
141
+ "anthropic/claude-3.5-sonnet",
142
+ "anthropic/claude-3.7-sonnet:thinking"
143
+ ],
144
+ description: "OpenRouter API",
145
+ transformer: {
146
+ use: ["openrouter"]
260
147
  }
261
- await setConfig(args[0], args.slice(1).join(" "), options);
262
- break;
263
- case "list":
264
- case "ls":
265
- await listConfig(options);
266
- break;
267
- case "reset":
268
- await resetConfig(options);
269
- break;
270
- case "provider":
271
- if (args.length === 0) {
272
- const isZh = i18n.language === "zh-CN";
273
- console.log(ansis.yellow(isZh ? "\u26A0\uFE0F \u8BF7\u6307\u5B9A\u4F9B\u5E94\u5546 ID" : "\u26A0\uFE0F Please specify provider ID"));
274
- console.log(ansis.dim(isZh ? "\u7528\u6CD5: ccjk config provider <id>" : "Usage: ccjk config provider <id>"));
275
- console.log("");
276
- return;
148
+ },
149
+ {
150
+ name: "siliconflow",
151
+ provider: "siliconflow",
152
+ baseURL: "https://api.siliconflow.cn/v1/chat/completions",
153
+ requiresApiKey: true,
154
+ models: ["moonshotai/Kimi-K2-Instruct"],
155
+ description: "SiliconFlow AI",
156
+ transformer: {
157
+ use: [["maxtoken", { max_tokens: 16384 }]]
158
+ }
159
+ },
160
+ {
161
+ name: "volcengine",
162
+ provider: "volcengine",
163
+ baseURL: "https://ark.cn-beijing.volces.com/api/v3/chat/completions",
164
+ requiresApiKey: true,
165
+ models: ["deepseek-v3-250324", "deepseek-r1-250528"],
166
+ description: "Volcengine AI",
167
+ transformer: {
168
+ use: ["deepseek"]
277
169
  }
278
- await setProvider(args[0], options);
279
- break;
280
- default: {
281
- const isZh = i18n.language === "zh-CN";
282
- console.log("");
283
- console.log(ansis.bold.cyan(isZh ? "\u2699\uFE0F \u914D\u7F6E\u7BA1\u7406\u547D\u4EE4" : "\u2699\uFE0F Configuration Management Commands"));
284
- console.log("");
285
- console.log(` ${ansis.green("ccjk config get <key>")} ${isZh ? "\u83B7\u53D6\u914D\u7F6E\u9879" : "Get configuration value"}`);
286
- console.log(` ${ansis.green("ccjk config set <key> <value>")} ${isZh ? "\u8BBE\u7F6E\u914D\u7F6E\u9879" : "Set configuration value"}`);
287
- console.log(` ${ansis.green("ccjk config list")} ${isZh ? "\u5217\u51FA\u6240\u6709\u914D\u7F6E" : "List all configuration"}`);
288
- console.log(` ${ansis.green("ccjk config reset")} ${isZh ? "\u91CD\u7F6E\u914D\u7F6E" : "Reset configuration"}`);
289
- console.log(` ${ansis.green("ccjk config provider <id>")} ${isZh ? "\u5207\u6362\u4F9B\u5E94\u5546" : "Switch provider"}`);
290
- console.log("");
291
- console.log(ansis.bold(isZh ? "\u9009\u9879" : "Options"));
292
- console.log(` ${ansis.green("--code-type, -T")} <type> ${isZh ? "\u4EE3\u7801\u5DE5\u5177\u7C7B\u578B (claude-code, codex)" : "Code tool type (claude-code, codex)"}`);
293
- console.log(` ${ansis.green("--json, -j")} ${isZh ? "JSON \u683C\u5F0F\u8F93\u51FA" : "JSON format output"}`);
294
- console.log("");
295
- console.log(ansis.bold(isZh ? "\u793A\u4F8B" : "Examples"));
296
- console.log(` ${ansis.dim("ccjk config get baseUrl")}`);
297
- console.log(` ${ansis.dim('ccjk config set model "claude-3-5-sonnet-20241022"')}`);
298
- console.log(` ${ansis.dim("ccjk config provider glm")}`);
299
- console.log("");
300
170
  }
301
- }
171
+ ];
302
172
  }
303
- function getClaudeConfigPath() {
304
- return SETTINGS_FILE;
173
+
174
+ const execAsync = promisify(exec);
175
+ const CCR_CONFIG_DIR = join(homedir(), ".claude-code-router");
176
+ const CCR_CONFIG_FILE = join(CCR_CONFIG_DIR, "config.json");
177
+ const CCR_BACKUP_DIR = CCR_CONFIG_DIR;
178
+ function ensureCcrConfigDir() {
179
+ if (!existsSync(CCR_CONFIG_DIR)) {
180
+ mkdirSync(CCR_CONFIG_DIR, { recursive: true });
181
+ }
305
182
  }
306
- function readClaudeConfig() {
307
- if (!existsSync(SETTINGS_FILE)) {
183
+ async function backupCcrConfig() {
184
+ ensureI18nInitialized();
185
+ try {
186
+ if (!existsSync(CCR_CONFIG_FILE)) {
187
+ return null;
188
+ }
189
+ const timestamp = `${dayjs().format("YYYY-MM-DDTHH-mm-ss-SSS")}Z`;
190
+ const backupFileName = `config.json.${timestamp}.bak`;
191
+ const backupPath = join(CCR_BACKUP_DIR, backupFileName);
192
+ console.log(ansis.green(`${i18n.t("ccr:backupCcrConfig")}`));
193
+ copyFileSync(CCR_CONFIG_FILE, backupPath);
194
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrBackupSuccess").replace("{path}", backupPath)}`));
195
+ return backupPath;
196
+ } catch (error) {
197
+ console.error(ansis.red(`${i18n.t("ccr:ccrBackupFailed")}:`), error.message);
308
198
  return null;
309
199
  }
310
- try {
311
- const content = readFileSync(SETTINGS_FILE, "utf-8");
312
- return JSON.parse(content);
313
- } catch {
200
+ }
201
+ function readCcrConfig() {
202
+ if (!existsSync(CCR_CONFIG_FILE)) {
314
203
  return null;
315
204
  }
205
+ return readJsonConfig(CCR_CONFIG_FILE);
316
206
  }
317
- function writeClaudeConfig(config) {
318
- writeFileSync(SETTINGS_FILE, JSON.stringify(config, null, 2), "utf-8");
207
+ function writeCcrConfig(config) {
208
+ ensureCcrConfigDir();
209
+ writeJsonConfig(CCR_CONFIG_FILE, config);
319
210
  }
320
- function getNestedValue(obj, path) {
321
- const keys = path.split(".");
322
- let current = obj;
323
- for (const key of keys) {
324
- if (current === null || current === void 0) {
325
- return void 0;
326
- }
327
- current = current[key];
211
+ async function configureCcrProxy(ccrConfig) {
212
+ const settings = readJsonConfig(SETTINGS_FILE) || {};
213
+ const host = ccrConfig.HOST || "127.0.0.1";
214
+ const port = ccrConfig.PORT || 3456;
215
+ const apiKey = ccrConfig.APIKEY || "sk-ccjk-x-ccr";
216
+ if (!settings.env) {
217
+ settings.env = {};
218
+ }
219
+ delete settings.env.ANTHROPIC_AUTH_TOKEN;
220
+ settings.env.ANTHROPIC_BASE_URL = `http://${host}:${port}`;
221
+ settings.env.ANTHROPIC_API_KEY = apiKey;
222
+ writeJsonConfig(SETTINGS_FILE, settings);
223
+ try {
224
+ setPrimaryApiKey();
225
+ } catch (error) {
226
+ ensureI18nInitialized();
227
+ console.error(i18n.t("mcp:primaryApiKeySetFailed"), error);
328
228
  }
329
- return current;
330
229
  }
331
- function setNestedValue(obj, path, value) {
332
- const keys = path.split(".");
333
- let current = obj;
334
- for (let i = 0; i < keys.length - 1; i++) {
335
- const key = keys[i];
336
- if (!(key in current) || typeof current[key] !== "object") {
337
- current[key] = {};
230
+ async function selectCcrPreset() {
231
+ ensureI18nInitialized();
232
+ console.log(ansis.green(`${i18n.t("ccr:fetchingPresets")}`));
233
+ const presets = await fetchProviderPresets();
234
+ if (!presets || presets.length === 0) {
235
+ console.log(ansis.yellow(`${i18n.t("ccr:noPresetsAvailable")}`));
236
+ return null;
237
+ }
238
+ try {
239
+ const choices = [
240
+ {
241
+ name: `1. ${i18n.t("ccr:skipOption")}`,
242
+ value: "skip"
243
+ },
244
+ ...presets.map((p, index) => ({
245
+ name: `${index + 2}. ${p.name}`,
246
+ value: p
247
+ }))
248
+ ];
249
+ const { preset } = await inquirer.prompt({
250
+ type: "list",
251
+ name: "preset",
252
+ message: i18n.t("ccr:selectCcrPreset"),
253
+ choices
254
+ });
255
+ return preset;
256
+ } catch (error) {
257
+ if (error.name === "ExitPromptError") {
258
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
259
+ return null;
338
260
  }
339
- current = current[key];
261
+ throw error;
340
262
  }
341
- current[keys[keys.length - 1]] = value;
342
263
  }
343
- function displayValue(value, indent) {
344
- const prefix = " ".repeat(indent);
345
- if (value === null) {
346
- console.log(`${prefix}${ansis.dim("null")}`);
347
- } else if (typeof value === "boolean") {
348
- console.log(`${prefix}${ansis.green(value.toString())}`);
349
- } else if (typeof value === "number") {
350
- console.log(`${prefix}${ansis.yellow(value.toString())}`);
351
- } else if (typeof value === "string") {
352
- console.log(`${prefix}${ansis.green(value)}`);
353
- } else if (Array.isArray(value)) {
354
- console.log(`${prefix}${ansis.dim("[")}`);
355
- for (const item of value) {
356
- displayValue(item, indent + 1);
357
- }
358
- console.log(`${prefix}${ansis.dim("]")}`);
359
- } else if (typeof value === "object") {
360
- for (const [key, val] of Object.entries(value)) {
361
- console.log(`${prefix}${ansis.bold(key)}:`);
362
- displayValue(val, indent + 1);
264
+ async function configureCcrWithPreset(preset) {
265
+ ensureI18nInitialized();
266
+ const provider = {
267
+ name: preset.name,
268
+ // Use the original name from JSON
269
+ api_base_url: preset.baseURL || "",
270
+ api_key: "",
271
+ models: preset.models
272
+ };
273
+ if (preset.transformer) {
274
+ provider.transformer = preset.transformer;
275
+ }
276
+ if (preset.requiresApiKey) {
277
+ try {
278
+ const { apiKey } = await inquirer.prompt({
279
+ type: "input",
280
+ name: "apiKey",
281
+ message: i18n.t("ccr:enterApiKeyForProvider").replace("{provider}", preset.name),
282
+ validate: async (value) => !!value || i18n.t("api:keyRequired")
283
+ });
284
+ provider.api_key = apiKey;
285
+ } catch (error) {
286
+ if (error.name === "ExitPromptError") {
287
+ throw error;
288
+ }
289
+ throw error;
363
290
  }
364
291
  } else {
365
- console.log(`${prefix}${value}`);
292
+ provider.api_key = "sk-free";
366
293
  }
367
- }
368
- function displayConfigSection(title, data, _isZh) {
369
- console.log(ansis.bold(title));
370
- console.log("");
371
- for (const [key, value] of Object.entries(data)) {
372
- if (value !== void 0) {
373
- if (Array.isArray(value)) {
374
- console.log(` ${ansis.green(key)}: ${value.join(", ")}`);
375
- } else {
376
- console.log(` ${ansis.green(key)}: ${value}`);
294
+ let defaultModel = preset.models[0];
295
+ if (preset.models.length > 1) {
296
+ try {
297
+ const { model } = await inquirer.prompt({
298
+ type: "list",
299
+ name: "model",
300
+ message: i18n.t("ccr:selectDefaultModelForProvider").replace("{provider}", preset.name),
301
+ choices: preset.models.map((m, index) => ({
302
+ name: `${index + 1}. ${m}`,
303
+ value: m
304
+ }))
305
+ });
306
+ defaultModel = model;
307
+ } catch (error) {
308
+ if (error.name === "ExitPromptError") {
309
+ throw error;
377
310
  }
311
+ throw error;
378
312
  }
379
313
  }
380
- console.log("");
314
+ const router = {
315
+ default: `${preset.name},${defaultModel}`,
316
+ // Use the original name
317
+ background: `${preset.name},${defaultModel}`,
318
+ think: `${preset.name},${defaultModel}`,
319
+ longContext: `${preset.name},${defaultModel}`,
320
+ longContextThreshold: 6e4,
321
+ webSearch: `${preset.name},${defaultModel}`
322
+ };
323
+ const config = {
324
+ LOG: true,
325
+ CLAUDE_PATH: "",
326
+ HOST: "127.0.0.1",
327
+ PORT: 3456,
328
+ APIKEY: "sk-ccjk-x-ccr",
329
+ API_TIMEOUT_MS: "600000",
330
+ PROXY_URL: "",
331
+ transformers: [],
332
+ Providers: [provider],
333
+ Router: router
334
+ };
335
+ return config;
381
336
  }
382
- async function unsetConfig(key, _options = {}) {
383
- const isZh = i18n.language === "zh-CN";
384
- if (!key) {
385
- console.log(ansis.yellow(isZh ? "\u26A0\uFE0F \u8BF7\u6307\u5B9A\u914D\u7F6E\u9879" : "\u26A0\uFE0F Please specify a configuration key"));
386
- return;
387
- }
388
- const config = readClaudeConfig();
389
- const keys = key.split(".");
390
- let current = config;
391
- for (let i = 0; i < keys.length - 1; i++) {
392
- if (current[keys[i]] === void 0) {
393
- console.log(ansis.yellow(isZh ? `\u26A0\uFE0F \u914D\u7F6E\u9879 "${key}" \u4E0D\u5B58\u5728` : `\u26A0\uFE0F Configuration key "${key}" does not exist`));
394
- return;
337
+ async function restartAndCheckCcrStatus() {
338
+ ensureI18nInitialized();
339
+ try {
340
+ console.log(ansis.green(`${i18n.t("ccr:restartingCcr")}`));
341
+ await execAsync("ccr restart");
342
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrRestartSuccess")}`));
343
+ console.log(ansis.green(`${i18n.t("ccr:checkingCcrStatus")}`));
344
+ const { stdout } = await execAsync("ccr status");
345
+ console.log(ansis.gray(stdout));
346
+ } catch (error) {
347
+ console.error(ansis.red(`${i18n.t("ccr:ccrRestartFailed")}:`), error.message || error);
348
+ if (process__default.env.DEBUG) {
349
+ console.error("Full error:", error);
395
350
  }
396
- current = current[keys[i]];
397
351
  }
398
- const lastKey = keys[keys.length - 1];
399
- if (current[lastKey] === void 0) {
400
- console.log(ansis.yellow(isZh ? `\u26A0\uFE0F \u914D\u7F6E\u9879 "${key}" \u4E0D\u5B58\u5728` : `\u26A0\uFE0F Configuration key "${key}" does not exist`));
401
- return;
352
+ }
353
+ async function showConfigurationTips(apiKey) {
354
+ ensureI18nInitialized();
355
+ console.log(ansis.bold.cyan(`
356
+ \u{1F4CC} ${i18n.t("ccr:configTips")}:`));
357
+ console.log(ansis.green(` \u2022 ${i18n.t("ccr:advancedConfigTip")}`));
358
+ console.log(ansis.green(` \u2022 ${i18n.t("ccr:manualConfigTip")}`));
359
+ console.log(ansis.bold.yellow(` \u2022 ${i18n.t("ccr:useClaudeCommand")}`));
360
+ if (apiKey) {
361
+ console.log(ansis.bold.green(` \u2022 ${i18n.t("ccr:ccrUiApiKey") || "CCR UI API Key"}: ${apiKey}`));
362
+ console.log(ansis.gray(` ${i18n.t("ccr:ccrUiApiKeyHint") || "Use this API key to login to CCR UI"}`));
402
363
  }
403
- delete current[lastKey];
404
- writeClaudeConfig(config);
405
- console.log(ansis.green(isZh ? `\u2705 \u5DF2\u5220\u9664\u914D\u7F6E\u9879: ${key}` : `\u2705 Removed configuration: ${key}`));
364
+ console.log("");
406
365
  }
407
- async function editConfig(_options = {}) {
408
- const isZh = i18n.language === "zh-CN";
409
- const configPath = getClaudeConfigPath();
410
- const editor = process__default.env.EDITOR || process__default.env.VISUAL || "vi";
411
- console.log(ansis.green(isZh ? `\u{1F4DD} \u6B63\u5728\u6253\u5F00\u914D\u7F6E\u6587\u4EF6: ${configPath}` : `\u{1F4DD} Opening config file: ${configPath}`));
412
- const { spawn } = await import('node:child_process');
413
- const child = spawn(editor, [configPath], { stdio: "inherit" });
414
- child.on("exit", (code) => {
415
- if (code === 0) {
416
- console.log(ansis.green(isZh ? "\u2705 \u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58" : "\u2705 Config file saved"));
417
- }
418
- });
366
+ function createDefaultCcrConfig() {
367
+ return {
368
+ LOG: false,
369
+ CLAUDE_PATH: "",
370
+ HOST: "127.0.0.1",
371
+ PORT: 3456,
372
+ APIKEY: "sk-ccjk-x-ccr",
373
+ API_TIMEOUT_MS: "600000",
374
+ PROXY_URL: "",
375
+ transformers: [],
376
+ Providers: [],
377
+ // Empty providers array - user configures in UI
378
+ Router: {}
379
+ // Empty router configuration - user configures in UI
380
+ };
419
381
  }
420
- async function validateConfig(_options = {}) {
421
- const isZh = i18n.language === "zh-CN";
422
- console.log(ansis.green(isZh ? "\u{1F50D} \u6B63\u5728\u9A8C\u8BC1\u914D\u7F6E..." : "\u{1F50D} Validating configuration..."));
423
- console.log("");
424
- const config = readClaudeConfig();
425
- const errors = [];
426
- const warnings = [];
427
- if (!config.apiKey) {
428
- errors.push(isZh ? "apiKey \u672A\u8BBE\u7F6E" : "apiKey is not set");
429
- }
430
- if (!config.baseUrl) {
431
- warnings.push(isZh ? "baseUrl \u672A\u8BBE\u7F6E\uFF0C\u5C06\u4F7F\u7528\u9ED8\u8BA4\u503C" : "baseUrl is not set, will use default");
432
- }
433
- if (config.model && typeof config.model !== "string") {
434
- errors.push(isZh ? "model \u683C\u5F0F\u65E0\u6548" : "model format is invalid");
435
- }
436
- if (errors.length === 0 && warnings.length === 0) {
437
- console.log(ansis.green(isZh ? "\u2705 \u914D\u7F6E\u9A8C\u8BC1\u901A\u8FC7" : "\u2705 Configuration is valid"));
438
- } else {
439
- if (errors.length > 0) {
440
- console.log(ansis.red(isZh ? "\u274C \u9519\u8BEF:" : "\u274C Errors:"));
441
- for (const error of errors) {
442
- console.log(ansis.red(` \u2022 ${error}`));
382
+ async function setupCcrConfiguration() {
383
+ ensureI18nInitialized();
384
+ try {
385
+ const existingConfig = readCcrConfig();
386
+ if (existingConfig) {
387
+ console.log(ansis.green(`\u2139 ${i18n.t("ccr:existingCcrConfig")}`));
388
+ let shouldBackupAndReconfigure = false;
389
+ try {
390
+ shouldBackupAndReconfigure = await promptBoolean({
391
+ message: i18n.t("ccr:overwriteCcrConfig"),
392
+ defaultValue: false
393
+ });
394
+ } catch (error) {
395
+ if (error.name === "ExitPromptError") {
396
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
397
+ return false;
398
+ }
399
+ throw error;
443
400
  }
444
- console.log("");
445
- }
446
- if (warnings.length > 0) {
447
- console.log(ansis.yellow(isZh ? "\u26A0\uFE0F \u8B66\u544A:" : "\u26A0\uFE0F Warnings:"));
448
- for (const warning of warnings) {
449
- console.log(ansis.yellow(` \u2022 ${warning}`));
401
+ if (!shouldBackupAndReconfigure) {
402
+ console.log(ansis.yellow(`${i18n.t("ccr:keepingExistingConfig")}`));
403
+ await configureCcrProxy(existingConfig);
404
+ try {
405
+ const { manageApiKeyApproval } = await import('./claude-config.mjs').then(function (n) { return n.h; });
406
+ const apiKey = existingConfig.APIKEY || "sk-ccjk-x-ccr";
407
+ manageApiKeyApproval(apiKey);
408
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:apiKeyApprovalSuccess")}`));
409
+ } catch (error) {
410
+ console.error(ansis.red(`${i18n.t("ccr:apiKeyApprovalFailed")}:`), error);
411
+ }
412
+ return true;
450
413
  }
414
+ backupCcrConfig();
451
415
  }
416
+ const preset = await selectCcrPreset();
417
+ if (!preset) {
418
+ return false;
419
+ }
420
+ let config;
421
+ if (preset === "skip") {
422
+ console.log(ansis.yellow(`${i18n.t("ccr:skipConfiguring")}`));
423
+ config = createDefaultCcrConfig();
424
+ } else {
425
+ config = await configureCcrWithPreset(preset);
426
+ }
427
+ writeCcrConfig(config);
428
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrConfigSuccess")}`));
429
+ await configureCcrProxy(config);
430
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:proxyConfigSuccess")}`));
431
+ await restartAndCheckCcrStatus();
432
+ await showConfigurationTips(config.APIKEY);
433
+ try {
434
+ addCompletedOnboarding();
435
+ } catch (error) {
436
+ console.error(ansis.red(i18n.t("errors:failedToSetOnboarding")), error);
437
+ }
438
+ try {
439
+ const { manageApiKeyApproval } = await import('./claude-config.mjs').then(function (n) { return n.h; });
440
+ const apiKey = config.APIKEY || "sk-ccjk-x-ccr";
441
+ manageApiKeyApproval(apiKey);
442
+ console.log(ansis.green(`\u2714 ${i18n.t("ccr:apiKeyApprovalSuccess")}`));
443
+ } catch (error) {
444
+ console.error(ansis.red(`${i18n.t("ccr:apiKeyApprovalFailed")}:`), error);
445
+ }
446
+ return true;
447
+ } catch (error) {
448
+ if (error.name === "ExitPromptError") {
449
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
450
+ return false;
451
+ }
452
+ console.error(ansis.red(`${i18n.t("ccr:ccrConfigFailed")}:`), error);
453
+ return false;
454
+ }
455
+ }
456
+ async function configureCcrFeature() {
457
+ ensureI18nInitialized();
458
+ const backupDir = backupExistingConfig();
459
+ if (backupDir) {
460
+ console.log(ansis.gray(`\u2714 ${i18n.t("configuration:backupSuccess")}: ${backupDir}`));
452
461
  }
462
+ await setupCcrConfiguration();
453
463
  }
454
464
 
455
- export { configCommand, editConfig, getConfig, listConfig, resetConfig, setConfig, setProvider, unsetConfig, validateConfig };
465
+ export { backupCcrConfig, configureCcrFeature, configureCcrProxy, configureCcrWithPreset, createDefaultCcrConfig, ensureCcrConfigDir, readCcrConfig, restartAndCheckCcrStatus, selectCcrPreset, setupCcrConfiguration, showConfigurationTips, writeCcrConfig };