ccjk 10.1.0 → 10.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/chunks/agent-teams.mjs +1 -1
- package/dist/chunks/agent.mjs +1 -1
- package/dist/chunks/api-providers.mjs +1 -1
- package/dist/chunks/api.mjs +3 -3
- package/dist/chunks/auto-bootstrap.mjs +1 -1
- package/dist/chunks/auto-updater.mjs +1 -1
- package/dist/{shared/ccjk.Br91zBIG.mjs → chunks/banner.mjs} +52 -3
- package/dist/chunks/boost.mjs +2 -2
- package/dist/chunks/ccjk-agents.mjs +1 -1
- package/dist/chunks/ccjk-all.mjs +1 -1
- package/dist/chunks/ccjk-config.mjs +1 -1
- package/dist/chunks/ccjk-hooks.mjs +1 -1
- package/dist/chunks/ccjk-mcp.mjs +2 -2
- package/dist/chunks/ccjk-setup.mjs +1 -1
- package/dist/chunks/ccjk-skills.mjs +1 -1
- package/dist/chunks/ccr.mjs +11 -10
- package/dist/chunks/ccu.mjs +1 -1
- package/dist/chunks/check-updates.mjs +4 -3
- package/dist/chunks/claude-code-config-manager.mjs +8 -7
- package/dist/chunks/claude-code-incremental-manager.mjs +3 -2
- package/dist/chunks/claude-config.mjs +3 -3
- package/dist/chunks/claude-wrapper.mjs +2 -2
- package/dist/chunks/codex-config-switch.mjs +3 -2
- package/dist/chunks/codex-provider-manager.mjs +3 -2
- package/dist/chunks/codex-uninstaller.mjs +2 -2
- package/dist/chunks/codex.mjs +5 -5
- package/dist/chunks/commands.mjs +88 -391
- package/dist/chunks/commands2.mjs +391 -88
- package/dist/chunks/completion.mjs +1 -1
- package/dist/chunks/config-consolidator.mjs +2 -2
- package/dist/chunks/config-switch.mjs +4 -3
- package/dist/chunks/config.mjs +6 -98
- package/dist/chunks/config2.mjs +411 -400
- package/dist/chunks/config3.mjs +401 -410
- package/dist/chunks/constants.mjs +1 -1
- package/dist/chunks/context.mjs +283 -1
- package/dist/chunks/dashboard.mjs +365 -0
- package/dist/chunks/doctor.mjs +4 -4
- package/dist/chunks/features.mjs +12 -11
- package/dist/chunks/fs-operations.mjs +1 -1
- package/dist/chunks/health-alerts.mjs +304 -0
- package/dist/chunks/health-check.mjs +532 -0
- package/dist/chunks/index.mjs +10 -177
- package/dist/chunks/index2.mjs +168 -1162
- package/dist/chunks/index3.mjs +1076 -910
- package/dist/chunks/index4.mjs +947 -137
- package/dist/chunks/index5.mjs +167 -635
- package/dist/chunks/index6.mjs +663 -0
- package/dist/chunks/init.mjs +19 -19
- package/dist/chunks/installer.mjs +649 -147
- package/dist/chunks/installer2.mjs +147 -649
- package/dist/chunks/interview.mjs +2 -2
- package/dist/chunks/marketplace.mjs +1 -1
- package/dist/chunks/mcp.mjs +5 -4
- package/dist/chunks/menu.mjs +22 -9
- package/dist/chunks/metrics-display.mjs +152 -0
- package/dist/chunks/migrator.mjs +1 -1
- package/dist/chunks/monitor.mjs +2 -2
- package/dist/chunks/notification.mjs +1 -1
- package/dist/chunks/onboarding.mjs +2 -2
- package/dist/chunks/package.mjs +1 -1
- package/dist/chunks/permission-manager.mjs +2 -2
- package/dist/chunks/permissions.mjs +1 -1
- package/dist/chunks/persistence-manager.mjs +781 -0
- package/dist/chunks/persistence.mjs +667 -0
- package/dist/chunks/platform.mjs +1 -1
- package/dist/chunks/plugin.mjs +1 -1
- package/dist/chunks/prompts.mjs +1 -1
- package/dist/chunks/providers.mjs +1 -1
- package/dist/chunks/quick-actions.mjs +321 -0
- package/dist/chunks/quick-provider.mjs +2 -0
- package/dist/chunks/quick-setup.mjs +9 -8
- package/dist/chunks/silent-updater.mjs +1 -1
- package/dist/chunks/simple-config.mjs +3 -8
- package/dist/chunks/skill.mjs +1 -1
- package/dist/chunks/skills-sync.mjs +1 -1
- package/dist/chunks/skills.mjs +1 -1
- package/dist/chunks/slash-commands.mjs +208 -0
- package/dist/chunks/smart-defaults.mjs +1 -1
- package/dist/chunks/startup.mjs +1 -1
- package/dist/chunks/stats.mjs +1 -1
- package/dist/chunks/status.mjs +31 -2
- package/dist/chunks/team.mjs +1 -1
- package/dist/chunks/thinking.mjs +2 -2
- package/dist/chunks/uninstall.mjs +5 -5
- package/dist/chunks/update.mjs +8 -7
- package/dist/chunks/upgrade-manager.mjs +2 -2
- package/dist/chunks/version-checker.mjs +3 -3
- package/dist/chunks/vim.mjs +1 -1
- package/dist/chunks/zero-config.mjs +359 -0
- package/dist/cli.mjs +212 -21
- package/dist/i18n/locales/en/cli.json +14 -1
- package/dist/i18n/locales/en/common.json +27 -0
- package/dist/i18n/locales/en/configuration.json +33 -0
- package/dist/i18n/locales/en/context.json +54 -1
- package/dist/i18n/locales/en/dashboard.json +78 -0
- package/dist/i18n/locales/en/persistence.json +127 -0
- package/dist/i18n/locales/en/quick-actions.json +78 -0
- package/dist/i18n/locales/zh-CN/cli.json +14 -1
- package/dist/i18n/locales/zh-CN/common.json +27 -0
- package/dist/i18n/locales/zh-CN/configuration.json +33 -0
- package/dist/i18n/locales/zh-CN/context.json +54 -1
- package/dist/i18n/locales/zh-CN/dashboard.json +78 -0
- package/dist/i18n/locales/zh-CN/persistence.json +127 -0
- package/dist/i18n/locales/zh-CN/quick-actions.json +78 -0
- package/dist/index.mjs +3 -2
- package/dist/shared/{ccjk.DE91nClQ.mjs → ccjk.BKoi8-Hy.mjs} +1 -1
- package/dist/shared/ccjk.BiCrMV5O.mjs +94 -0
- package/dist/shared/{ccjk.Dpw86UX0.mjs → ccjk.CxtuJxaS.mjs} +1 -1
- package/dist/shared/{ccjk.ClzTOz9n.mjs → ccjk.DB2UYcq0.mjs} +5 -5
- package/dist/shared/{ccjk.CmsW23FN.mjs → ccjk.DVBW2wxp.mjs} +4 -3
- package/dist/shared/{ccjk.Bndhan7G.mjs → ccjk.DfwJOEok.mjs} +1 -1
- package/dist/shared/{ccjk.DvIrK0wz.mjs → ccjk.DrMygfCF.mjs} +1 -1
- package/package.json +19 -19
package/dist/chunks/config2.mjs
CHANGED
|
@@ -1,455 +1,466 @@
|
|
|
1
|
-
import {
|
|
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 {
|
|
9
|
+
import { join } from 'pathe';
|
|
6
10
|
import { SETTINGS_FILE } from './constants.mjs';
|
|
7
|
-
import { i18n } from './
|
|
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 '
|
|
10
|
-
import '
|
|
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 '
|
|
15
|
-
import '
|
|
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 '
|
|
21
|
-
import '
|
|
24
|
+
import '../shared/ccjk.BiCrMV5O.mjs';
|
|
25
|
+
import 'inquirer-toggle';
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
|
|
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";
|
|
27
|
+
const PROVIDER_PRESETS_URL = "https://pub-0dc3e1677e894f07bbea11b17a29e032.r2.dev/providers.json";
|
|
28
|
+
async function fetchProviderPresets() {
|
|
143
29
|
try {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
32
|
+
const response = await fetch(PROVIDER_PRESETS_URL, {
|
|
33
|
+
signal: controller.signal
|
|
155
34
|
});
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
if (
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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})`);
|
|
35
|
+
clearTimeout(timeoutId);
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
38
|
+
}
|
|
39
|
+
const data = await response.json();
|
|
40
|
+
const presets = [];
|
|
41
|
+
if (Array.isArray(data)) {
|
|
42
|
+
for (const provider of data) {
|
|
43
|
+
if (provider && typeof provider === "object") {
|
|
44
|
+
presets.push({
|
|
45
|
+
name: provider.name || "",
|
|
46
|
+
provider: provider.name || "",
|
|
47
|
+
baseURL: provider.api_base_url || provider.baseURL || provider.url,
|
|
48
|
+
requiresApiKey: provider.api_key === "" || provider.requiresApiKey !== false,
|
|
49
|
+
models: provider.models || [],
|
|
50
|
+
description: provider.description || provider.name || "",
|
|
51
|
+
transformer: provider.transformer
|
|
52
|
+
});
|
|
53
|
+
}
|
|
193
54
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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];
|
|
55
|
+
} else if (data && typeof data === "object") {
|
|
56
|
+
for (const [key, value] of Object.entries(data)) {
|
|
57
|
+
if (typeof value === "object" && value !== null) {
|
|
58
|
+
const provider = value;
|
|
59
|
+
presets.push({
|
|
60
|
+
name: provider.name || key,
|
|
61
|
+
provider: key,
|
|
62
|
+
baseURL: provider.api_base_url || provider.baseURL || provider.url,
|
|
63
|
+
requiresApiKey: provider.api_key === "" || provider.requiresApiKey !== false,
|
|
64
|
+
models: provider.models || [],
|
|
65
|
+
description: provider.description || "",
|
|
66
|
+
transformer: provider.transformer
|
|
67
|
+
});
|
|
214
68
|
}
|
|
215
69
|
}
|
|
216
70
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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("");
|
|
71
|
+
return presets;
|
|
72
|
+
} catch {
|
|
73
|
+
return getFallbackPresets();
|
|
239
74
|
}
|
|
240
75
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
76
|
+
function getFallbackPresets() {
|
|
77
|
+
return [
|
|
78
|
+
{
|
|
79
|
+
name: "dashscope",
|
|
80
|
+
provider: "dashscope",
|
|
81
|
+
baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
|
|
82
|
+
requiresApiKey: true,
|
|
83
|
+
models: ["qwen3-coder-plus"],
|
|
84
|
+
description: "Alibaba DashScope",
|
|
85
|
+
transformer: {
|
|
86
|
+
"use": [["maxtoken", { max_tokens: 65536 }]],
|
|
87
|
+
"qwen3-coder-plus": {
|
|
88
|
+
use: ["enhancetool"]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "deepseek",
|
|
94
|
+
provider: "deepseek",
|
|
95
|
+
baseURL: "https://api.deepseek.com/chat/completions",
|
|
96
|
+
requiresApiKey: true,
|
|
97
|
+
models: ["deepseek-chat", "deepseek-reasoner"],
|
|
98
|
+
description: "DeepSeek AI models",
|
|
99
|
+
transformer: {
|
|
100
|
+
"use": ["deepseek"],
|
|
101
|
+
"deepseek-chat": {
|
|
102
|
+
use: ["tooluse"]
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "gemini",
|
|
108
|
+
provider: "gemini",
|
|
109
|
+
baseURL: "https://generativelanguage.googleapis.com/v1beta/models/",
|
|
110
|
+
requiresApiKey: true,
|
|
111
|
+
models: ["gemini-2.5-flash", "gemini-2.5-pro"],
|
|
112
|
+
description: "Google Gemini models",
|
|
113
|
+
transformer: {
|
|
114
|
+
use: ["gemini"]
|
|
250
115
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: "modelscope",
|
|
119
|
+
provider: "modelscope",
|
|
120
|
+
baseURL: "https://api-inference.modelscope.cn/v1/chat/completions",
|
|
121
|
+
requiresApiKey: true,
|
|
122
|
+
models: ["Qwen/Qwen3-Coder-480B-A35B-Instruct", "Qwen/Qwen3-235B-A22B-Thinking-2507", "ZhipuAI/GLM-4.5"],
|
|
123
|
+
description: "ModelScope AI models",
|
|
124
|
+
transformer: {
|
|
125
|
+
"use": [["maxtoken", { max_tokens: 65536 }]],
|
|
126
|
+
"Qwen/Qwen3-Coder-480B-A35B-Instruct": {
|
|
127
|
+
use: ["enhancetool"]
|
|
128
|
+
},
|
|
129
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507": {
|
|
130
|
+
use: ["reasoning"]
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: "openrouter",
|
|
136
|
+
provider: "openrouter",
|
|
137
|
+
baseURL: "https://openrouter.ai/api/v1/chat/completions",
|
|
138
|
+
requiresApiKey: true,
|
|
139
|
+
models: [
|
|
140
|
+
"google/gemini-2.5-pro-preview",
|
|
141
|
+
"anthropic/claude-sonnet-4",
|
|
142
|
+
"anthropic/claude-3.5-sonnet",
|
|
143
|
+
"anthropic/claude-3.7-sonnet:thinking"
|
|
144
|
+
],
|
|
145
|
+
description: "OpenRouter API",
|
|
146
|
+
transformer: {
|
|
147
|
+
use: ["openrouter"]
|
|
260
148
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: "siliconflow",
|
|
152
|
+
provider: "siliconflow",
|
|
153
|
+
baseURL: "https://api.siliconflow.cn/v1/chat/completions",
|
|
154
|
+
requiresApiKey: true,
|
|
155
|
+
models: ["moonshotai/Kimi-K2-Instruct"],
|
|
156
|
+
description: "SiliconFlow AI",
|
|
157
|
+
transformer: {
|
|
158
|
+
use: [["maxtoken", { max_tokens: 16384 }]]
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: "volcengine",
|
|
163
|
+
provider: "volcengine",
|
|
164
|
+
baseURL: "https://ark.cn-beijing.volces.com/api/v3/chat/completions",
|
|
165
|
+
requiresApiKey: true,
|
|
166
|
+
models: ["deepseek-v3-250324", "deepseek-r1-250528"],
|
|
167
|
+
description: "Volcengine AI",
|
|
168
|
+
transformer: {
|
|
169
|
+
use: ["deepseek"]
|
|
277
170
|
}
|
|
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
171
|
}
|
|
301
|
-
|
|
172
|
+
];
|
|
302
173
|
}
|
|
303
|
-
|
|
304
|
-
|
|
174
|
+
|
|
175
|
+
const execAsync = promisify(exec);
|
|
176
|
+
const CCR_CONFIG_DIR = join(homedir(), ".claude-code-router");
|
|
177
|
+
const CCR_CONFIG_FILE = join(CCR_CONFIG_DIR, "config.json");
|
|
178
|
+
const CCR_BACKUP_DIR = CCR_CONFIG_DIR;
|
|
179
|
+
function ensureCcrConfigDir() {
|
|
180
|
+
if (!existsSync(CCR_CONFIG_DIR)) {
|
|
181
|
+
mkdirSync(CCR_CONFIG_DIR, { recursive: true });
|
|
182
|
+
}
|
|
305
183
|
}
|
|
306
|
-
function
|
|
307
|
-
|
|
184
|
+
async function backupCcrConfig() {
|
|
185
|
+
ensureI18nInitialized();
|
|
186
|
+
try {
|
|
187
|
+
if (!existsSync(CCR_CONFIG_FILE)) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
const timestamp = `${dayjs().format("YYYY-MM-DDTHH-mm-ss-SSS")}Z`;
|
|
191
|
+
const backupFileName = `config.json.${timestamp}.bak`;
|
|
192
|
+
const backupPath = join(CCR_BACKUP_DIR, backupFileName);
|
|
193
|
+
console.log(ansis.green(`${i18n.t("ccr:backupCcrConfig")}`));
|
|
194
|
+
copyFileSync(CCR_CONFIG_FILE, backupPath);
|
|
195
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrBackupSuccess").replace("{path}", backupPath)}`));
|
|
196
|
+
return backupPath;
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.error(ansis.red(`${i18n.t("ccr:ccrBackupFailed")}:`), error.message);
|
|
308
199
|
return null;
|
|
309
200
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
} catch {
|
|
201
|
+
}
|
|
202
|
+
function readCcrConfig() {
|
|
203
|
+
if (!existsSync(CCR_CONFIG_FILE)) {
|
|
314
204
|
return null;
|
|
315
205
|
}
|
|
206
|
+
return readJsonConfig(CCR_CONFIG_FILE);
|
|
316
207
|
}
|
|
317
|
-
function
|
|
318
|
-
|
|
208
|
+
function writeCcrConfig(config) {
|
|
209
|
+
ensureCcrConfigDir();
|
|
210
|
+
writeJsonConfig(CCR_CONFIG_FILE, config);
|
|
319
211
|
}
|
|
320
|
-
function
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
|
|
212
|
+
async function configureCcrProxy(ccrConfig) {
|
|
213
|
+
const settings = readJsonConfig(SETTINGS_FILE) || {};
|
|
214
|
+
const host = ccrConfig.HOST || "127.0.0.1";
|
|
215
|
+
const port = ccrConfig.PORT || 3456;
|
|
216
|
+
const apiKey = ccrConfig.APIKEY || "sk-ccjk-x-ccr";
|
|
217
|
+
if (!settings.env) {
|
|
218
|
+
settings.env = {};
|
|
219
|
+
}
|
|
220
|
+
delete settings.env.ANTHROPIC_AUTH_TOKEN;
|
|
221
|
+
settings.env.ANTHROPIC_BASE_URL = `http://${host}:${port}`;
|
|
222
|
+
settings.env.ANTHROPIC_API_KEY = apiKey;
|
|
223
|
+
writeJsonConfig(SETTINGS_FILE, settings);
|
|
224
|
+
try {
|
|
225
|
+
setPrimaryApiKey();
|
|
226
|
+
} catch (error) {
|
|
227
|
+
ensureI18nInitialized();
|
|
228
|
+
console.error(i18n.t("mcp:primaryApiKeySetFailed"), error);
|
|
328
229
|
}
|
|
329
|
-
return current;
|
|
330
230
|
}
|
|
331
|
-
function
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
231
|
+
async function selectCcrPreset() {
|
|
232
|
+
ensureI18nInitialized();
|
|
233
|
+
console.log(ansis.green(`${i18n.t("ccr:fetchingPresets")}`));
|
|
234
|
+
const presets = await fetchProviderPresets();
|
|
235
|
+
if (!presets || presets.length === 0) {
|
|
236
|
+
console.log(ansis.yellow(`${i18n.t("ccr:noPresetsAvailable")}`));
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
const choices = [
|
|
241
|
+
{
|
|
242
|
+
name: `1. ${i18n.t("ccr:skipOption")}`,
|
|
243
|
+
value: "skip"
|
|
244
|
+
},
|
|
245
|
+
...presets.map((p, index) => ({
|
|
246
|
+
name: `${index + 2}. ${p.name}`,
|
|
247
|
+
value: p
|
|
248
|
+
}))
|
|
249
|
+
];
|
|
250
|
+
const { preset } = await inquirer.prompt({
|
|
251
|
+
type: "list",
|
|
252
|
+
name: "preset",
|
|
253
|
+
message: i18n.t("ccr:selectCcrPreset"),
|
|
254
|
+
choices
|
|
255
|
+
});
|
|
256
|
+
return preset;
|
|
257
|
+
} catch (error) {
|
|
258
|
+
if (error.name === "ExitPromptError") {
|
|
259
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
260
|
+
return null;
|
|
338
261
|
}
|
|
339
|
-
|
|
262
|
+
throw error;
|
|
340
263
|
}
|
|
341
|
-
current[keys[keys.length - 1]] = value;
|
|
342
264
|
}
|
|
343
|
-
function
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
265
|
+
async function configureCcrWithPreset(preset) {
|
|
266
|
+
ensureI18nInitialized();
|
|
267
|
+
const provider = {
|
|
268
|
+
name: preset.name,
|
|
269
|
+
// Use the original name from JSON
|
|
270
|
+
api_base_url: preset.baseURL || "",
|
|
271
|
+
api_key: "",
|
|
272
|
+
models: preset.models
|
|
273
|
+
};
|
|
274
|
+
if (preset.transformer) {
|
|
275
|
+
provider.transformer = preset.transformer;
|
|
276
|
+
}
|
|
277
|
+
if (preset.requiresApiKey) {
|
|
278
|
+
try {
|
|
279
|
+
const { apiKey } = await inquirer.prompt({
|
|
280
|
+
type: "input",
|
|
281
|
+
name: "apiKey",
|
|
282
|
+
message: i18n.t("ccr:enterApiKeyForProvider").replace("{provider}", preset.name),
|
|
283
|
+
validate: async (value) => !!value || i18n.t("api:keyRequired")
|
|
284
|
+
});
|
|
285
|
+
provider.api_key = apiKey;
|
|
286
|
+
} catch (error) {
|
|
287
|
+
if (error.name === "ExitPromptError") {
|
|
288
|
+
throw error;
|
|
289
|
+
}
|
|
290
|
+
throw error;
|
|
363
291
|
}
|
|
364
292
|
} else {
|
|
365
|
-
|
|
293
|
+
provider.api_key = "sk-free";
|
|
366
294
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
295
|
+
let defaultModel = preset.models[0];
|
|
296
|
+
if (preset.models.length > 1) {
|
|
297
|
+
try {
|
|
298
|
+
const { model } = await inquirer.prompt({
|
|
299
|
+
type: "list",
|
|
300
|
+
name: "model",
|
|
301
|
+
message: i18n.t("ccr:selectDefaultModelForProvider").replace("{provider}", preset.name),
|
|
302
|
+
choices: preset.models.map((m, index) => ({
|
|
303
|
+
name: `${index + 1}. ${m}`,
|
|
304
|
+
value: m
|
|
305
|
+
}))
|
|
306
|
+
});
|
|
307
|
+
defaultModel = model;
|
|
308
|
+
} catch (error) {
|
|
309
|
+
if (error.name === "ExitPromptError") {
|
|
310
|
+
throw error;
|
|
377
311
|
}
|
|
312
|
+
throw error;
|
|
378
313
|
}
|
|
379
314
|
}
|
|
380
|
-
|
|
315
|
+
const router = {
|
|
316
|
+
default: `${preset.name},${defaultModel}`,
|
|
317
|
+
// Use the original name
|
|
318
|
+
background: `${preset.name},${defaultModel}`,
|
|
319
|
+
think: `${preset.name},${defaultModel}`,
|
|
320
|
+
longContext: `${preset.name},${defaultModel}`,
|
|
321
|
+
longContextThreshold: 6e4,
|
|
322
|
+
webSearch: `${preset.name},${defaultModel}`
|
|
323
|
+
};
|
|
324
|
+
const config = {
|
|
325
|
+
LOG: true,
|
|
326
|
+
CLAUDE_PATH: "",
|
|
327
|
+
HOST: "127.0.0.1",
|
|
328
|
+
PORT: 3456,
|
|
329
|
+
APIKEY: "sk-ccjk-x-ccr",
|
|
330
|
+
API_TIMEOUT_MS: "600000",
|
|
331
|
+
PROXY_URL: "",
|
|
332
|
+
transformers: [],
|
|
333
|
+
Providers: [provider],
|
|
334
|
+
Router: router
|
|
335
|
+
};
|
|
336
|
+
return config;
|
|
381
337
|
}
|
|
382
|
-
async function
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
console.log(ansis.
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
338
|
+
async function restartAndCheckCcrStatus() {
|
|
339
|
+
ensureI18nInitialized();
|
|
340
|
+
try {
|
|
341
|
+
console.log(ansis.green(`${i18n.t("ccr:restartingCcr")}`));
|
|
342
|
+
await execAsync("ccr restart");
|
|
343
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrRestartSuccess")}`));
|
|
344
|
+
console.log(ansis.green(`${i18n.t("ccr:checkingCcrStatus")}`));
|
|
345
|
+
const { stdout } = await execAsync("ccr status");
|
|
346
|
+
console.log(ansis.gray(stdout));
|
|
347
|
+
} catch (error) {
|
|
348
|
+
console.error(ansis.red(`${i18n.t("ccr:ccrRestartFailed")}:`), error.message || error);
|
|
349
|
+
if (process__default.env.DEBUG) {
|
|
350
|
+
console.error("Full error:", error);
|
|
395
351
|
}
|
|
396
|
-
current = current[keys[i]];
|
|
397
352
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
353
|
+
}
|
|
354
|
+
async function showConfigurationTips(apiKey) {
|
|
355
|
+
ensureI18nInitialized();
|
|
356
|
+
console.log(ansis.bold.cyan(`
|
|
357
|
+
\u{1F4CC} ${i18n.t("ccr:configTips")}:`));
|
|
358
|
+
console.log(ansis.green(` \u2022 ${i18n.t("ccr:advancedConfigTip")}`));
|
|
359
|
+
console.log(ansis.green(` \u2022 ${i18n.t("ccr:manualConfigTip")}`));
|
|
360
|
+
console.log(ansis.bold.yellow(` \u2022 ${i18n.t("ccr:useClaudeCommand")}`));
|
|
361
|
+
if (apiKey) {
|
|
362
|
+
console.log(ansis.bold.green(` \u2022 ${i18n.t("ccr:ccrUiApiKey") || "CCR UI API Key"}: ${apiKey}`));
|
|
363
|
+
console.log(ansis.gray(` ${i18n.t("ccr:ccrUiApiKeyHint") || "Use this API key to login to CCR UI"}`));
|
|
402
364
|
}
|
|
403
|
-
|
|
404
|
-
writeClaudeConfig(config);
|
|
405
|
-
console.log(ansis.green(isZh ? `\u2705 \u5DF2\u5220\u9664\u914D\u7F6E\u9879: ${key}` : `\u2705 Removed configuration: ${key}`));
|
|
365
|
+
console.log("");
|
|
406
366
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
367
|
+
function createDefaultCcrConfig() {
|
|
368
|
+
return {
|
|
369
|
+
LOG: false,
|
|
370
|
+
CLAUDE_PATH: "",
|
|
371
|
+
HOST: "127.0.0.1",
|
|
372
|
+
PORT: 3456,
|
|
373
|
+
APIKEY: "sk-ccjk-x-ccr",
|
|
374
|
+
API_TIMEOUT_MS: "600000",
|
|
375
|
+
PROXY_URL: "",
|
|
376
|
+
transformers: [],
|
|
377
|
+
Providers: [],
|
|
378
|
+
// Empty providers array - user configures in UI
|
|
379
|
+
Router: {}
|
|
380
|
+
// Empty router configuration - user configures in UI
|
|
381
|
+
};
|
|
419
382
|
}
|
|
420
|
-
async function
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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}`));
|
|
383
|
+
async function setupCcrConfiguration() {
|
|
384
|
+
ensureI18nInitialized();
|
|
385
|
+
try {
|
|
386
|
+
const existingConfig = readCcrConfig();
|
|
387
|
+
if (existingConfig) {
|
|
388
|
+
console.log(ansis.green(`\u2139 ${i18n.t("ccr:existingCcrConfig")}`));
|
|
389
|
+
let shouldBackupAndReconfigure = false;
|
|
390
|
+
try {
|
|
391
|
+
shouldBackupAndReconfigure = await promptBoolean({
|
|
392
|
+
message: i18n.t("ccr:overwriteCcrConfig"),
|
|
393
|
+
defaultValue: false
|
|
394
|
+
});
|
|
395
|
+
} catch (error) {
|
|
396
|
+
if (error.name === "ExitPromptError") {
|
|
397
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
throw error;
|
|
443
401
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
402
|
+
if (!shouldBackupAndReconfigure) {
|
|
403
|
+
console.log(ansis.yellow(`${i18n.t("ccr:keepingExistingConfig")}`));
|
|
404
|
+
await configureCcrProxy(existingConfig);
|
|
405
|
+
try {
|
|
406
|
+
const { manageApiKeyApproval } = await import('./claude-config.mjs').then(function (n) { return n.h; });
|
|
407
|
+
const apiKey = existingConfig.APIKEY || "sk-ccjk-x-ccr";
|
|
408
|
+
manageApiKeyApproval(apiKey);
|
|
409
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:apiKeyApprovalSuccess")}`));
|
|
410
|
+
} catch (error) {
|
|
411
|
+
console.error(ansis.red(`${i18n.t("ccr:apiKeyApprovalFailed")}:`), error);
|
|
412
|
+
}
|
|
413
|
+
return true;
|
|
450
414
|
}
|
|
415
|
+
backupCcrConfig();
|
|
451
416
|
}
|
|
417
|
+
const preset = await selectCcrPreset();
|
|
418
|
+
if (!preset) {
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
let config;
|
|
422
|
+
if (preset === "skip") {
|
|
423
|
+
console.log(ansis.yellow(`${i18n.t("ccr:skipConfiguring")}`));
|
|
424
|
+
config = createDefaultCcrConfig();
|
|
425
|
+
} else {
|
|
426
|
+
config = await configureCcrWithPreset(preset);
|
|
427
|
+
}
|
|
428
|
+
writeCcrConfig(config);
|
|
429
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrConfigSuccess")}`));
|
|
430
|
+
await configureCcrProxy(config);
|
|
431
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:proxyConfigSuccess")}`));
|
|
432
|
+
await restartAndCheckCcrStatus();
|
|
433
|
+
await showConfigurationTips(config.APIKEY);
|
|
434
|
+
try {
|
|
435
|
+
addCompletedOnboarding();
|
|
436
|
+
} catch (error) {
|
|
437
|
+
console.error(ansis.red(i18n.t("errors:failedToSetOnboarding")), error);
|
|
438
|
+
}
|
|
439
|
+
try {
|
|
440
|
+
const { manageApiKeyApproval } = await import('./claude-config.mjs').then(function (n) { return n.h; });
|
|
441
|
+
const apiKey = config.APIKEY || "sk-ccjk-x-ccr";
|
|
442
|
+
manageApiKeyApproval(apiKey);
|
|
443
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:apiKeyApprovalSuccess")}`));
|
|
444
|
+
} catch (error) {
|
|
445
|
+
console.error(ansis.red(`${i18n.t("ccr:apiKeyApprovalFailed")}:`), error);
|
|
446
|
+
}
|
|
447
|
+
return true;
|
|
448
|
+
} catch (error) {
|
|
449
|
+
if (error.name === "ExitPromptError") {
|
|
450
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
console.error(ansis.red(`${i18n.t("ccr:ccrConfigFailed")}:`), error);
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
async function configureCcrFeature() {
|
|
458
|
+
ensureI18nInitialized();
|
|
459
|
+
const backupDir = backupExistingConfig();
|
|
460
|
+
if (backupDir) {
|
|
461
|
+
console.log(ansis.gray(`\u2714 ${i18n.t("configuration:backupSuccess")}: ${backupDir}`));
|
|
452
462
|
}
|
|
463
|
+
await setupCcrConfiguration();
|
|
453
464
|
}
|
|
454
465
|
|
|
455
|
-
export {
|
|
466
|
+
export { backupCcrConfig, configureCcrFeature, configureCcrProxy, configureCcrWithPreset, createDefaultCcrConfig, ensureCcrConfigDir, readCcrConfig, restartAndCheckCcrStatus, selectCcrPreset, setupCcrConfiguration, showConfigurationTips, writeCcrConfig };
|