cc-cast 1.3.8 → 1.3.9
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/dist/index.js +34 -1062
- package/package.json +4 -3
- package/dist/claude.js +0 -27
- package/dist/i18n/en.js +0 -139
- package/dist/i18n/index.js +0 -36
- package/dist/i18n/zh.js +0 -139
- package/dist/store/cc-switch.js +0 -114
- package/dist/store/interface.js +0 -1
- package/dist/store/standalone.js +0 -65
- package/dist/types.js +0 -1
- package/dist/utils.js +0 -42
package/dist/index.js
CHANGED
|
@@ -1,1063 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command } from "commander";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (this.index === i && !hasColor(message)) {
|
|
37
|
-
message = this.styles.primary(message);
|
|
38
|
-
}
|
|
39
|
-
return this.resolve(message, this.state, choice, i);
|
|
40
|
-
};
|
|
41
|
-
return prompt;
|
|
42
|
-
}
|
|
43
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
44
|
-
const packageJsonPath = join(__dirname, "..", "package.json");
|
|
45
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
46
|
-
const notifier = updateNotifier({ pkg: packageJson, updateCheckInterval: 1000 * 60 * 60 * 24 });
|
|
47
|
-
notifier.notify({ isGlobal: true, defer: true });
|
|
48
|
-
const program = new Command();
|
|
49
|
-
program
|
|
50
|
-
.name("ccc")
|
|
51
|
-
.description(t("program.description"))
|
|
52
|
-
.version(packageJson.version);
|
|
53
|
-
// Helper: prompt user for input, optionally pre-filling the input field
|
|
54
|
-
function ask(question, prefill) {
|
|
55
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
56
|
-
return new Promise((resolve) => {
|
|
57
|
-
rl.question(question, (answer) => {
|
|
58
|
-
rl.close();
|
|
59
|
-
resolve(answer.trim());
|
|
60
|
-
});
|
|
61
|
-
if (prefill) {
|
|
62
|
-
rl.line = prefill;
|
|
63
|
-
rl.cursor = prefill.length;
|
|
64
|
-
rl._refreshLine();
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
// Helper: ensure store ready
|
|
69
|
-
function ensureStore() {
|
|
70
|
-
return getStore();
|
|
71
|
-
}
|
|
72
|
-
// Helper: print current active configuration
|
|
73
|
-
function printCurrent() {
|
|
74
|
-
const store = ensureStore();
|
|
75
|
-
const currentName = store.getCurrent();
|
|
76
|
-
if (!currentName) {
|
|
77
|
-
console.log(chalk.yellow(t("current.none")));
|
|
78
|
-
console.log(chalk.gray(`\n${t("current.settings_header")}`));
|
|
79
|
-
const settings = readClaudeSettings();
|
|
80
|
-
const env = (settings.env || {});
|
|
81
|
-
console.log(formatEnv(env));
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const profile = store.get(currentName);
|
|
85
|
-
if (!profile) {
|
|
86
|
-
console.log(chalk.yellow(t("current.not_exist", { name: currentName })));
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
console.log(`\n${t("current.header", { name: chalk.green.bold(profile.name) })}\n`);
|
|
90
|
-
const env = (profile.settingsConfig.env || {});
|
|
91
|
-
console.log(formatEnv(env));
|
|
92
|
-
if (profile.settingsConfig.model) {
|
|
93
|
-
console.log(` ${chalk.gray("model")}: ${profile.settingsConfig.model}`);
|
|
94
|
-
}
|
|
95
|
-
console.log();
|
|
96
|
-
}
|
|
97
|
-
// Helper: format env for display
|
|
98
|
-
function formatEnv(env) {
|
|
99
|
-
const lines = [];
|
|
100
|
-
const order = [
|
|
101
|
-
"ANTHROPIC_BASE_URL",
|
|
102
|
-
"ANTHROPIC_MODEL",
|
|
103
|
-
"ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
104
|
-
"ANTHROPIC_DEFAULT_SONNET_MODEL",
|
|
105
|
-
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
|
|
106
|
-
];
|
|
107
|
-
for (const key of order) {
|
|
108
|
-
if (key in env) {
|
|
109
|
-
lines.push(` ${chalk.gray(key)}: ${env[key]}`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// Show remaining keys (skip token for security)
|
|
113
|
-
for (const [key, val] of Object.entries(env)) {
|
|
114
|
-
if (!order.includes(key) && key !== "ANTHROPIC_AUTH_TOKEN") {
|
|
115
|
-
lines.push(` ${chalk.gray(key)}: ${val}`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if ("ANTHROPIC_AUTH_TOKEN" in env) {
|
|
119
|
-
const token = env["ANTHROPIC_AUTH_TOKEN"];
|
|
120
|
-
const masked = token.slice(0, 8) + "..." + token.slice(-4);
|
|
121
|
-
lines.push(` ${chalk.gray("ANTHROPIC_AUTH_TOKEN")}: ${masked}`);
|
|
122
|
-
}
|
|
123
|
-
return lines.join("\n");
|
|
124
|
-
}
|
|
125
|
-
// Helper: Levenshtein distance
|
|
126
|
-
function levenshtein(a, b) {
|
|
127
|
-
const la = a.length, lb = b.length;
|
|
128
|
-
const dp = Array.from({ length: la + 1 }, (_, i) => Array.from({ length: lb + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)));
|
|
129
|
-
for (let i = 1; i <= la; i++) {
|
|
130
|
-
for (let j = 1; j <= lb; j++) {
|
|
131
|
-
dp[i][j] = a[i - 1] === b[j - 1]
|
|
132
|
-
? dp[i - 1][j - 1]
|
|
133
|
-
: 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return dp[la][lb];
|
|
137
|
-
}
|
|
138
|
-
// Helper: find suggestions for a mistyped name
|
|
139
|
-
function findSuggestions(input, names) {
|
|
140
|
-
const lower = input.toLowerCase();
|
|
141
|
-
// 1. exact case-insensitive match
|
|
142
|
-
const exact = names.find((n) => n.toLowerCase() === lower);
|
|
143
|
-
if (exact)
|
|
144
|
-
return [exact];
|
|
145
|
-
// 2. substring match (input is part of name, or name is part of input)
|
|
146
|
-
const substring = names.filter((n) => n.toLowerCase().includes(lower) || lower.includes(n.toLowerCase()));
|
|
147
|
-
if (substring.length > 0)
|
|
148
|
-
return substring;
|
|
149
|
-
// 3. Levenshtein distance <= 3
|
|
150
|
-
const fuzzy = names
|
|
151
|
-
.map((n) => ({ name: n, dist: levenshtein(lower, n.toLowerCase()) }))
|
|
152
|
-
.filter((x) => x.dist <= 3)
|
|
153
|
-
.sort((a, b) => a.dist - b.dist)
|
|
154
|
-
.map((x) => x.name);
|
|
155
|
-
return fuzzy;
|
|
156
|
-
}
|
|
157
|
-
// Helper: get alias target if exists
|
|
158
|
-
function getAliasTarget(input) {
|
|
159
|
-
const rc = readRc();
|
|
160
|
-
return rc?.aliases?.[input];
|
|
161
|
-
}
|
|
162
|
-
// Helper: resolve name with alias conflict handling, returns profile or null
|
|
163
|
-
async function resolveProfile(store, input) {
|
|
164
|
-
const aliasTarget = getAliasTarget(input);
|
|
165
|
-
const directProfile = store.get(input);
|
|
166
|
-
// Both alias and config name exist → ask
|
|
167
|
-
if (aliasTarget && directProfile && aliasTarget !== input) {
|
|
168
|
-
console.log(chalk.yellow(t("alias.conflict", { name: input, target: aliasTarget })));
|
|
169
|
-
console.log(` ${chalk.cyan("1)")} ${t("alias.conflict_alias", { target: aliasTarget })}`);
|
|
170
|
-
console.log(` ${chalk.cyan("2)")} ${t("alias.conflict_config", { name: input })}`);
|
|
171
|
-
const choice = await ask(t("alias.choose_conflict"));
|
|
172
|
-
if (choice === "1") {
|
|
173
|
-
const profile = store.get(aliasTarget);
|
|
174
|
-
if (!profile) {
|
|
175
|
-
console.log(chalk.red(t("error.alias_target_missing", { alias: input, target: aliasTarget })));
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
return profile;
|
|
179
|
-
}
|
|
180
|
-
return directProfile;
|
|
181
|
-
}
|
|
182
|
-
// Alias exists → resolve
|
|
183
|
-
if (aliasTarget) {
|
|
184
|
-
const profile = store.get(aliasTarget);
|
|
185
|
-
if (profile)
|
|
186
|
-
return profile;
|
|
187
|
-
console.log(chalk.red(t("error.alias_target_missing", { alias: input, target: aliasTarget })));
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
// Direct match
|
|
191
|
-
if (directProfile)
|
|
192
|
-
return directProfile;
|
|
193
|
-
// Fuzzy matching
|
|
194
|
-
const allNames = store.list().map((p) => p.name);
|
|
195
|
-
const suggestions = findSuggestions(input, allNames);
|
|
196
|
-
console.log(chalk.red(t("error.not_found", { name: input })));
|
|
197
|
-
if (suggestions.length === 1) {
|
|
198
|
-
console.log(chalk.yellow(t("suggest.did_you_mean", { name: chalk.bold(suggestions[0]) })));
|
|
199
|
-
}
|
|
200
|
-
else if (suggestions.length > 1) {
|
|
201
|
-
console.log(chalk.yellow(t("suggest.did_you_mean_header")));
|
|
202
|
-
for (const s of suggestions) {
|
|
203
|
-
console.log(` - ${chalk.bold(s)}`);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
console.log(chalk.gray(t("suggest.use_list")));
|
|
208
|
-
}
|
|
209
|
-
return null;
|
|
210
|
-
}
|
|
211
|
-
// cc-castinit
|
|
212
|
-
program
|
|
213
|
-
.command("init")
|
|
214
|
-
.description(t("init.description"))
|
|
215
|
-
.action(async () => {
|
|
216
|
-
const rc = readRc();
|
|
217
|
-
writeRc({ aliases: rc?.aliases, locale: rc?.locale });
|
|
218
|
-
console.log(chalk.green(t("init.done")));
|
|
219
|
-
if (ccSwitchExists()) {
|
|
220
|
-
console.log(chalk.green(t("init.cc_switch_mode")));
|
|
221
|
-
// If standalone config.json has profiles, offer to migrate them into cc-switch DB
|
|
222
|
-
const { StandaloneStore } = await import("./store/standalone.js");
|
|
223
|
-
const standaloneStore = new StandaloneStore();
|
|
224
|
-
const standaloneProfiles = standaloneStore.list();
|
|
225
|
-
if (standaloneProfiles.length > 0) {
|
|
226
|
-
const migrate = await ask(t("init.cc_switch_migrate"));
|
|
227
|
-
if (migrate.toLowerCase() !== "n") {
|
|
228
|
-
const { CcSwitchStore } = await import("./store/cc-switch.js");
|
|
229
|
-
const ccStore = new CcSwitchStore();
|
|
230
|
-
const standaloneCurrent = standaloneStore.getCurrent();
|
|
231
|
-
for (const profile of standaloneProfiles) {
|
|
232
|
-
ccStore.save(profile.name, profile.settingsConfig);
|
|
233
|
-
}
|
|
234
|
-
if (standaloneCurrent) {
|
|
235
|
-
ccStore.setCurrent(standaloneCurrent);
|
|
236
|
-
}
|
|
237
|
-
console.log(chalk.green(t("init.cc_switch_migrate_done", { count: String(standaloneProfiles.length) })));
|
|
238
|
-
ccStore.close();
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
// cc-castsync
|
|
244
|
-
program
|
|
245
|
-
.command("sync")
|
|
246
|
-
.description(t("sync.description"))
|
|
247
|
-
.action(async () => {
|
|
248
|
-
if (!ccSwitchExists()) {
|
|
249
|
-
console.log(chalk.red(t("sync.no_cc_switch")));
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
const { CcSwitchStore } = await import("./store/cc-switch.js");
|
|
253
|
-
const { StandaloneStore } = await import("./store/standalone.js");
|
|
254
|
-
const ccStore = new CcSwitchStore();
|
|
255
|
-
const standaloneStore = new StandaloneStore();
|
|
256
|
-
const profiles = ccStore.list();
|
|
257
|
-
if (profiles.length === 0) {
|
|
258
|
-
console.log(chalk.yellow(t("sync.empty")));
|
|
259
|
-
ccStore.close();
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
for (const profile of profiles) {
|
|
263
|
-
standaloneStore.save(profile.name, profile.settingsConfig);
|
|
264
|
-
}
|
|
265
|
-
const current = ccStore.getCurrent();
|
|
266
|
-
if (current) {
|
|
267
|
-
standaloneStore.setCurrent(current);
|
|
268
|
-
}
|
|
269
|
-
console.log(chalk.green(t("sync.done", { count: String(profiles.length) })));
|
|
270
|
-
if (current) {
|
|
271
|
-
console.log(chalk.gray(t("sync.current", { name: current })));
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
console.log(chalk.gray(t("sync.no_current")));
|
|
275
|
-
}
|
|
276
|
-
ccStore.close();
|
|
277
|
-
});
|
|
278
|
-
// cc-castclear
|
|
279
|
-
program
|
|
280
|
-
.command("clear")
|
|
281
|
-
.description(t("clear.description"))
|
|
282
|
-
.action(async () => {
|
|
283
|
-
const confirm = await ask(t("clear.confirm"));
|
|
284
|
-
if (confirm.toLowerCase() !== "y") {
|
|
285
|
-
console.log(chalk.gray(t("clear.cancelled")));
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
const rcPath = join(homedir(), ".cc-cast", "rc.json");
|
|
289
|
-
const configPath = join(homedir(), ".cc-cast", "config.json");
|
|
290
|
-
if (existsSync(configPath)) {
|
|
291
|
-
unlinkSync(configPath);
|
|
292
|
-
console.log(chalk.green(t("clear.removed", { path: configPath })));
|
|
293
|
-
}
|
|
294
|
-
if (existsSync(rcPath)) {
|
|
295
|
-
unlinkSync(rcPath);
|
|
296
|
-
console.log(chalk.green(t("clear.removed", { path: rcPath })));
|
|
297
|
-
}
|
|
298
|
-
console.log(chalk.green(t("clear.done")));
|
|
299
|
-
});
|
|
300
|
-
// cc-castimport
|
|
301
|
-
program
|
|
302
|
-
.command("import [file]")
|
|
303
|
-
.description(t("import.description"))
|
|
304
|
-
.action(async (file) => {
|
|
305
|
-
const store = ensureStore();
|
|
306
|
-
let jsonContent;
|
|
307
|
-
if (file) {
|
|
308
|
-
// Read from file
|
|
309
|
-
if (!existsSync(file)) {
|
|
310
|
-
console.log(chalk.red(t("import.file_not_found", { file })));
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
jsonContent = readFileSync(file, "utf-8");
|
|
314
|
-
}
|
|
315
|
-
else {
|
|
316
|
-
// Read from stdin
|
|
317
|
-
console.log(chalk.gray(t("import.paste_hint")));
|
|
318
|
-
const chunks = [];
|
|
319
|
-
process.stdin.setEncoding("utf-8");
|
|
320
|
-
for await (const chunk of process.stdin) {
|
|
321
|
-
chunks.push(Buffer.from(chunk));
|
|
322
|
-
}
|
|
323
|
-
jsonContent = Buffer.concat(chunks).toString("utf-8");
|
|
324
|
-
}
|
|
325
|
-
let configs;
|
|
326
|
-
try {
|
|
327
|
-
configs = JSON.parse(jsonContent);
|
|
328
|
-
}
|
|
329
|
-
catch {
|
|
330
|
-
console.log(chalk.red(t("import.json_parse_error")));
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
if (typeof configs !== "object" || configs === null || Object.keys(configs).length === 0) {
|
|
334
|
-
console.log(chalk.red(t("import.invalid_format")));
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
let count = 0;
|
|
338
|
-
for (const [name, settingsConfig] of Object.entries(configs)) {
|
|
339
|
-
store.save(name, settingsConfig);
|
|
340
|
-
count++;
|
|
341
|
-
}
|
|
342
|
-
console.log(chalk.green(t("import.done", { count: String(count) })));
|
|
343
|
-
});
|
|
344
|
-
// cc-castlist
|
|
345
|
-
program
|
|
346
|
-
.command("list")
|
|
347
|
-
.alias("ls")
|
|
348
|
-
.description(t("list.description"))
|
|
349
|
-
.action(async () => {
|
|
350
|
-
const store = ensureStore();
|
|
351
|
-
const profiles = store.list();
|
|
352
|
-
const current = store.getCurrent();
|
|
353
|
-
if (profiles.length === 0) {
|
|
354
|
-
console.log(chalk.yellow(t("list.empty")));
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
// Helper: apply selected profile
|
|
358
|
-
const switchTo = (name) => {
|
|
359
|
-
if (name === current)
|
|
360
|
-
return;
|
|
361
|
-
const profile = store.get(name);
|
|
362
|
-
store.setCurrent(profile.name);
|
|
363
|
-
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
364
|
-
if (isCcSwitchGuiRunning()) {
|
|
365
|
-
console.log(chalk.yellow(t("use.cc_switch_running")));
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
applyProfile(profile.name, profile.settingsConfig);
|
|
369
|
-
const env = (profile.settingsConfig.env || {});
|
|
370
|
-
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
371
|
-
console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
|
|
372
|
-
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
373
|
-
}
|
|
374
|
-
};
|
|
375
|
-
const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
|
|
376
|
-
if (isInteractive) {
|
|
377
|
-
const options = profiles.map((p) => {
|
|
378
|
-
const isCurrent = p.name === current;
|
|
379
|
-
const env = (p.settingsConfig.env || {});
|
|
380
|
-
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
381
|
-
const baseUrl = env["ANTHROPIC_BASE_URL"] || "default";
|
|
382
|
-
const tag = isCurrent ? ` ${t("list.current_marker")}` : "";
|
|
383
|
-
return {
|
|
384
|
-
label: `${p.name}${tag}`,
|
|
385
|
-
hint: `${t("common.model")}: ${model} ${t("common.source")}: ${baseUrl}`,
|
|
386
|
-
value: p.name,
|
|
387
|
-
};
|
|
388
|
-
});
|
|
389
|
-
const initial = profiles.findIndex((p) => p.name === current);
|
|
390
|
-
const prompt = createSelect({
|
|
391
|
-
message: "",
|
|
392
|
-
choices: options.map((o) => ({ name: o.value, message: o.label })),
|
|
393
|
-
initial: initial >= 0 ? initial : 0,
|
|
394
|
-
pointer: "●",
|
|
395
|
-
styles: { em: (k) => k, strong: (k) => k },
|
|
396
|
-
});
|
|
397
|
-
try {
|
|
398
|
-
const value = await prompt.run();
|
|
399
|
-
switchTo(value);
|
|
400
|
-
}
|
|
401
|
-
catch {
|
|
402
|
-
console.log(chalk.gray(t("common.cancelled")));
|
|
403
|
-
return;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
else {
|
|
407
|
-
// Fallback: numbered list + type to select
|
|
408
|
-
console.log(chalk.bold(`\n${t("list.header")}\n`));
|
|
409
|
-
profiles.forEach((p, i) => {
|
|
410
|
-
const isCurrent = p.name === current;
|
|
411
|
-
const marker = isCurrent ? chalk.green("● ") : " ";
|
|
412
|
-
const name = isCurrent ? chalk.green.bold(p.name) : p.name;
|
|
413
|
-
const env = (p.settingsConfig.env || {});
|
|
414
|
-
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
415
|
-
const baseUrl = env["ANTHROPIC_BASE_URL"] || "default";
|
|
416
|
-
console.log(`${marker}${chalk.gray(`${i + 1}.`)} ${name}`);
|
|
417
|
-
console.log(` ${t("common.model")}: ${chalk.cyan(model)} ${t("common.source")}: ${chalk.gray(baseUrl)}`);
|
|
418
|
-
});
|
|
419
|
-
console.log();
|
|
420
|
-
const input = await ask(t("list.choose_number"));
|
|
421
|
-
if (!input)
|
|
422
|
-
return;
|
|
423
|
-
const idx = parseInt(input, 10) - 1;
|
|
424
|
-
if (isNaN(idx) || idx < 0 || idx >= profiles.length) {
|
|
425
|
-
console.log(chalk.red(t("error.invalid_choice")));
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
switchTo(profiles[idx].name);
|
|
429
|
-
}
|
|
430
|
-
});
|
|
431
|
-
// cc-castcurrent
|
|
432
|
-
program
|
|
433
|
-
.command("current")
|
|
434
|
-
.description(t("current.description"))
|
|
435
|
-
.action(() => {
|
|
436
|
-
printCurrent();
|
|
437
|
-
});
|
|
438
|
-
// cc-castuse [name]
|
|
439
|
-
program
|
|
440
|
-
.command("use [name]")
|
|
441
|
-
.description(t("use.description"))
|
|
442
|
-
.action(async (name) => {
|
|
443
|
-
const store = ensureStore();
|
|
444
|
-
if (!name) {
|
|
445
|
-
// No argument: behave like `ls`
|
|
446
|
-
await program.commands.find((c) => c.name() === "list").parseAsync([]);
|
|
447
|
-
return;
|
|
448
|
-
}
|
|
449
|
-
const profile = await resolveProfile(store, name);
|
|
450
|
-
if (!profile)
|
|
451
|
-
return;
|
|
452
|
-
store.setCurrent(profile.name);
|
|
453
|
-
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
454
|
-
if (isCcSwitchGuiRunning()) {
|
|
455
|
-
console.log(chalk.yellow(t("use.cc_switch_running")));
|
|
456
|
-
}
|
|
457
|
-
else {
|
|
458
|
-
applyProfile(profile.name, profile.settingsConfig);
|
|
459
|
-
const env = (profile.settingsConfig.env || {});
|
|
460
|
-
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
461
|
-
console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
|
|
462
|
-
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
// cc-castsave <name>
|
|
466
|
-
program
|
|
467
|
-
.command("save <name>")
|
|
468
|
-
.description(t("save.description"))
|
|
469
|
-
.action((name) => {
|
|
470
|
-
const store = ensureStore();
|
|
471
|
-
const existing = store.get(name);
|
|
472
|
-
if (existing) {
|
|
473
|
-
console.log(chalk.yellow(t("save.overwrite", { name })));
|
|
474
|
-
}
|
|
475
|
-
const settings = readClaudeSettings();
|
|
476
|
-
const settingsConfig = {};
|
|
477
|
-
if (settings.env)
|
|
478
|
-
settingsConfig.env = settings.env;
|
|
479
|
-
if (settings.model)
|
|
480
|
-
settingsConfig.model = settings.model;
|
|
481
|
-
if (settings.hooks)
|
|
482
|
-
settingsConfig.hooks = settings.hooks;
|
|
483
|
-
if (settings.statusLine)
|
|
484
|
-
settingsConfig.statusLine = settings.statusLine;
|
|
485
|
-
store.save(name, settingsConfig);
|
|
486
|
-
store.setCurrent(name);
|
|
487
|
-
console.log(chalk.green(t("save.done", { name })));
|
|
488
|
-
});
|
|
489
|
-
// Helper: open editor with content, return parsed JSON or null
|
|
490
|
-
function openEditor(name, content) {
|
|
491
|
-
const tmpFile = join(tmpdir(), `cc-cast-${name}-${Date.now()}.json`);
|
|
492
|
-
writeFileSync(tmpFile, JSON.stringify(content, null, 2));
|
|
493
|
-
const editor = process.env.EDITOR || "vi";
|
|
494
|
-
const result = spawnSync(editor, [tmpFile], { stdio: "inherit" });
|
|
495
|
-
let parsed = null;
|
|
496
|
-
if (result.status === 0) {
|
|
497
|
-
try {
|
|
498
|
-
parsed = JSON.parse(readFileSync(tmpFile, "utf-8"));
|
|
499
|
-
}
|
|
500
|
-
catch {
|
|
501
|
-
console.log(chalk.red(t("add.json_parse_error")));
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
try {
|
|
505
|
-
unlinkSync(tmpFile);
|
|
506
|
-
}
|
|
507
|
-
catch { /* ignore */ }
|
|
508
|
-
return parsed;
|
|
509
|
-
}
|
|
510
|
-
// Helper: save and optionally switch after add
|
|
511
|
-
async function saveAndSwitch(store, name, settingsConfig) {
|
|
512
|
-
store.save(name, settingsConfig);
|
|
513
|
-
console.log(chalk.green(t("add.done", { name })));
|
|
514
|
-
const switchChoice = await ask(t("add.switch_confirm"));
|
|
515
|
-
if (switchChoice.toLowerCase() !== "n") {
|
|
516
|
-
store.setCurrent(name);
|
|
517
|
-
console.log(chalk.green(t("use.done", { name: chalk.bold(name) })));
|
|
518
|
-
if (isCcSwitchGuiRunning()) {
|
|
519
|
-
console.log(chalk.yellow(t("use.cc_switch_running")));
|
|
520
|
-
}
|
|
521
|
-
else {
|
|
522
|
-
applyProfile(name, settingsConfig);
|
|
523
|
-
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
const BUILTIN_BASE_URLS = {
|
|
528
|
-
kimi: "https://api.moonshot.cn/v1",
|
|
529
|
-
"kimi-coding": "https://api.kimi.com/coding/",
|
|
530
|
-
openrouter: "https://openrouter.ai/api/v1",
|
|
531
|
-
deepseek: "https://api.deepseek.com",
|
|
532
|
-
zenmux: "https://zenmux.ai/api/anthropic",
|
|
533
|
-
fusecode: "https://www.fusecode.cc",
|
|
534
|
-
};
|
|
535
|
-
function getKnownBaseUrl(name) {
|
|
536
|
-
return BUILTIN_BASE_URLS[name.toLowerCase()];
|
|
537
|
-
}
|
|
538
|
-
// cc-castadd
|
|
539
|
-
program
|
|
540
|
-
.command("add")
|
|
541
|
-
.alias("new")
|
|
542
|
-
.description(t("add.description"))
|
|
543
|
-
.action(async () => {
|
|
544
|
-
const store = ensureStore();
|
|
545
|
-
// 1. Ask name first
|
|
546
|
-
const name = await ask(t("add.prompt_name"));
|
|
547
|
-
if (!name) {
|
|
548
|
-
console.log(chalk.red(t("add.name_required")));
|
|
549
|
-
return;
|
|
550
|
-
}
|
|
551
|
-
// Check if exists
|
|
552
|
-
const existing = store.get(name);
|
|
553
|
-
if (existing) {
|
|
554
|
-
const overwrite = await ask(t("add.already_exists", { name }));
|
|
555
|
-
if (overwrite.toLowerCase() !== "y") {
|
|
556
|
-
console.log(chalk.gray(t("add.cancelled")));
|
|
557
|
-
return;
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
// 2. Choose mode
|
|
561
|
-
console.log(`\n${chalk.bold(t("add.mode_select"))}\n`);
|
|
562
|
-
console.log(` ${chalk.cyan("1)")} ${t("add.mode_interactive")}`);
|
|
563
|
-
console.log(` ${chalk.cyan("2)")} ${t("add.mode_json")}\n`);
|
|
564
|
-
const mode = await ask(t("add.mode_choose"));
|
|
565
|
-
if (mode === "2") {
|
|
566
|
-
// JSON mode: open editor with template
|
|
567
|
-
const template = {
|
|
568
|
-
env: {
|
|
569
|
-
ANTHROPIC_BASE_URL: getKnownBaseUrl(name) ?? "",
|
|
570
|
-
ANTHROPIC_AUTH_TOKEN: "",
|
|
571
|
-
ANTHROPIC_MODEL: "",
|
|
572
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL: "",
|
|
573
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL: "",
|
|
574
|
-
ANTHROPIC_DEFAULT_HAIKU_MODEL: "",
|
|
575
|
-
},
|
|
576
|
-
};
|
|
577
|
-
console.log(chalk.gray(t("add.json_template_hint")));
|
|
578
|
-
const edited = openEditor(name, template);
|
|
579
|
-
if (!edited)
|
|
580
|
-
return;
|
|
581
|
-
await saveAndSwitch(store, name, edited);
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
// Interactive mode with step-based back support
|
|
585
|
-
const defaultBaseUrl = getKnownBaseUrl(name);
|
|
586
|
-
const steps = [
|
|
587
|
-
{ key: "ANTHROPIC_BASE_URL", prompt: t("add.prompt_base_url"), required: true, defaultValue: defaultBaseUrl },
|
|
588
|
-
{ key: "ANTHROPIC_AUTH_TOKEN", prompt: t("add.prompt_auth_token"), required: true },
|
|
589
|
-
{ key: "ANTHROPIC_MODEL", prompt: t("add.prompt_model"), required: false },
|
|
590
|
-
{ key: "ANTHROPIC_DEFAULT_OPUS_MODEL", prompt: t("add.prompt_default_opus"), required: false },
|
|
591
|
-
{ key: "ANTHROPIC_DEFAULT_SONNET_MODEL", prompt: t("add.prompt_default_sonnet"), required: false },
|
|
592
|
-
{ key: "ANTHROPIC_DEFAULT_HAIKU_MODEL", prompt: t("add.prompt_default_haiku"), required: false },
|
|
593
|
-
];
|
|
594
|
-
console.log(chalk.gray(t("add.back_hint")));
|
|
595
|
-
const values = {};
|
|
596
|
-
let i = 0;
|
|
597
|
-
while (i < steps.length) {
|
|
598
|
-
const step = steps[i];
|
|
599
|
-
const promptText = step.defaultValue
|
|
600
|
-
? `${step.prompt}(${chalk.gray(step.defaultValue)}): `
|
|
601
|
-
: step.prompt;
|
|
602
|
-
const input = await ask(promptText, step.defaultValue);
|
|
603
|
-
if (input === "<") {
|
|
604
|
-
if (i > 0)
|
|
605
|
-
i--;
|
|
606
|
-
continue;
|
|
607
|
-
}
|
|
608
|
-
const value = input || step.defaultValue || "";
|
|
609
|
-
if (step.required && !value) {
|
|
610
|
-
console.log(chalk.red(t("add.field_required", { field: step.key })));
|
|
611
|
-
continue;
|
|
612
|
-
}
|
|
613
|
-
if (value)
|
|
614
|
-
values[step.key] = value;
|
|
615
|
-
else
|
|
616
|
-
delete values[step.key];
|
|
617
|
-
i++;
|
|
618
|
-
}
|
|
619
|
-
// Build config
|
|
620
|
-
const env = {};
|
|
621
|
-
for (const [k, v] of Object.entries(values)) {
|
|
622
|
-
env[k] = v;
|
|
623
|
-
}
|
|
624
|
-
let settingsConfig = { env };
|
|
625
|
-
// Preview + optional edit
|
|
626
|
-
console.log(`\n${chalk.bold(t("add.preview_header"))}\n`);
|
|
627
|
-
console.log(JSON.stringify(settingsConfig, null, 2));
|
|
628
|
-
console.log();
|
|
629
|
-
const editChoice = await ask(t("add.edit_confirm"));
|
|
630
|
-
if (editChoice.toLowerCase() === "y") {
|
|
631
|
-
const edited = openEditor(name, settingsConfig);
|
|
632
|
-
if (edited)
|
|
633
|
-
settingsConfig = edited;
|
|
634
|
-
}
|
|
635
|
-
await saveAndSwitch(store, name, settingsConfig);
|
|
636
|
-
});
|
|
637
|
-
// cc-castshow [name]
|
|
638
|
-
program
|
|
639
|
-
.command("show [name]")
|
|
640
|
-
.description(t("show.description"))
|
|
641
|
-
.action(async (name) => {
|
|
642
|
-
const store = ensureStore();
|
|
643
|
-
if (!name) {
|
|
644
|
-
// Show all configurations
|
|
645
|
-
const profiles = store.list();
|
|
646
|
-
if (profiles.length === 0) {
|
|
647
|
-
console.log(chalk.yellow(t("list.empty")));
|
|
648
|
-
return;
|
|
649
|
-
}
|
|
650
|
-
console.log(chalk.bold(`\n${t("show.all_header")}\n`));
|
|
651
|
-
const allConfigs = {};
|
|
652
|
-
for (const profile of profiles) {
|
|
653
|
-
allConfigs[profile.name] = profile.settingsConfig;
|
|
654
|
-
}
|
|
655
|
-
console.log(JSON.stringify(allConfigs, null, 2));
|
|
656
|
-
return;
|
|
657
|
-
}
|
|
658
|
-
const profile = await resolveProfile(store, name);
|
|
659
|
-
if (!profile)
|
|
660
|
-
return;
|
|
661
|
-
console.log(`\n${chalk.bold(profile.name)}\n`);
|
|
662
|
-
const env = (profile.settingsConfig.env || {});
|
|
663
|
-
console.log(formatEnv(env));
|
|
664
|
-
if (profile.settingsConfig.model) {
|
|
665
|
-
console.log(` ${chalk.gray("model")}: ${profile.settingsConfig.model}`);
|
|
666
|
-
}
|
|
667
|
-
console.log();
|
|
668
|
-
});
|
|
669
|
-
// cc-castmodify [name]
|
|
670
|
-
program
|
|
671
|
-
.command("modify [name]")
|
|
672
|
-
.alias("edit")
|
|
673
|
-
.description(t("modify.description"))
|
|
674
|
-
.action(async (name) => {
|
|
675
|
-
const store = ensureStore();
|
|
676
|
-
const profiles = store.list();
|
|
677
|
-
const current = store.getCurrent();
|
|
678
|
-
// 1. Select profile
|
|
679
|
-
if (!name) {
|
|
680
|
-
if (profiles.length === 0) {
|
|
681
|
-
console.log(chalk.yellow(t("list.empty")));
|
|
682
|
-
return;
|
|
683
|
-
}
|
|
684
|
-
const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
|
|
685
|
-
if (isInteractive) {
|
|
686
|
-
const options = profiles.map((p) => {
|
|
687
|
-
const isCurrent = p.name === current;
|
|
688
|
-
const env = (p.settingsConfig.env || {});
|
|
689
|
-
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
690
|
-
const tag = isCurrent ? ` ${t("list.current_marker")}` : "";
|
|
691
|
-
return {
|
|
692
|
-
label: `${p.name}${tag}`,
|
|
693
|
-
hint: `${t("common.model")}: ${model}`,
|
|
694
|
-
value: p.name,
|
|
695
|
-
};
|
|
696
|
-
});
|
|
697
|
-
const prompt = createSelect({
|
|
698
|
-
message: "",
|
|
699
|
-
choices: options.map((o) => ({ name: o.value, message: o.label, hint: o.hint })),
|
|
700
|
-
pointer: "●",
|
|
701
|
-
styles: { em: (k) => k, strong: (k) => k },
|
|
702
|
-
});
|
|
703
|
-
try {
|
|
704
|
-
name = await prompt.run();
|
|
705
|
-
}
|
|
706
|
-
catch {
|
|
707
|
-
console.log(chalk.gray(t("common.cancelled")));
|
|
708
|
-
return;
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
else {
|
|
712
|
-
console.log(chalk.bold(`\n${t("list.header")}\n`));
|
|
713
|
-
profiles.forEach((p, i) => {
|
|
714
|
-
const isCurrent = p.name === current;
|
|
715
|
-
const marker = isCurrent ? chalk.green("● ") : " ";
|
|
716
|
-
const label = isCurrent ? chalk.green.bold(p.name) : p.name;
|
|
717
|
-
const env = (p.settingsConfig.env || {});
|
|
718
|
-
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
719
|
-
console.log(`${marker}${chalk.gray(`${i + 1}.`)} ${label}`);
|
|
720
|
-
console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
|
|
721
|
-
});
|
|
722
|
-
console.log();
|
|
723
|
-
const input = await ask(t("list.choose_number"));
|
|
724
|
-
if (!input)
|
|
725
|
-
return;
|
|
726
|
-
const idx = parseInt(input, 10) - 1;
|
|
727
|
-
if (isNaN(idx) || idx < 0 || idx >= profiles.length) {
|
|
728
|
-
console.log(chalk.red(t("error.invalid_choice")));
|
|
729
|
-
return;
|
|
730
|
-
}
|
|
731
|
-
name = profiles[idx].name;
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
const profile = await resolveProfile(store, name);
|
|
735
|
-
if (!profile)
|
|
736
|
-
return;
|
|
737
|
-
const currentEnv = (profile.settingsConfig.env || {});
|
|
738
|
-
// 2. Choose mode
|
|
739
|
-
console.log(`\n${chalk.bold(t("add.mode_select"))}\n`);
|
|
740
|
-
console.log(` ${chalk.cyan("1)")} ${t("add.mode_interactive")}`);
|
|
741
|
-
console.log(` ${chalk.cyan("2)")} ${t("add.mode_json")}\n`);
|
|
742
|
-
const mode = await ask(t("add.mode_choose"));
|
|
743
|
-
let settingsConfig;
|
|
744
|
-
if (mode === "2") {
|
|
745
|
-
// JSON mode
|
|
746
|
-
const edited = openEditor(profile.name, profile.settingsConfig);
|
|
747
|
-
if (!edited)
|
|
748
|
-
return;
|
|
749
|
-
settingsConfig = edited;
|
|
750
|
-
}
|
|
751
|
-
else {
|
|
752
|
-
const steps = [
|
|
753
|
-
{ key: "ANTHROPIC_BASE_URL", prompt: "ANTHROPIC_BASE_URL", required: true },
|
|
754
|
-
{ key: "ANTHROPIC_AUTH_TOKEN", prompt: "ANTHROPIC_AUTH_TOKEN", required: true },
|
|
755
|
-
{ key: "ANTHROPIC_MODEL", prompt: "ANTHROPIC_MODEL", required: false },
|
|
756
|
-
{ key: "ANTHROPIC_DEFAULT_OPUS_MODEL", prompt: "ANTHROPIC_DEFAULT_OPUS_MODEL", required: false },
|
|
757
|
-
{ key: "ANTHROPIC_DEFAULT_SONNET_MODEL", prompt: "ANTHROPIC_DEFAULT_SONNET_MODEL", required: false },
|
|
758
|
-
{ key: "ANTHROPIC_DEFAULT_HAIKU_MODEL", prompt: "ANTHROPIC_DEFAULT_HAIKU_MODEL", required: false },
|
|
759
|
-
];
|
|
760
|
-
console.log(chalk.gray(t("add.back_hint")));
|
|
761
|
-
const values = { ...currentEnv };
|
|
762
|
-
let i = 0;
|
|
763
|
-
while (i < steps.length) {
|
|
764
|
-
const step = steps[i];
|
|
765
|
-
const cur = currentEnv[step.key]
|
|
766
|
-
|| (step.key === "ANTHROPIC_BASE_URL" ? (getKnownBaseUrl(profile.name) ?? "") : "");
|
|
767
|
-
const hint = cur ? `(${chalk.gray(cur)})` : "";
|
|
768
|
-
const input = await ask(`${step.prompt}${hint}: `, cur || undefined);
|
|
769
|
-
if (input === "<") {
|
|
770
|
-
if (i > 0)
|
|
771
|
-
i--;
|
|
772
|
-
continue;
|
|
773
|
-
}
|
|
774
|
-
if (input) {
|
|
775
|
-
values[step.key] = input;
|
|
776
|
-
}
|
|
777
|
-
else if (step.required && !cur) {
|
|
778
|
-
console.log(chalk.red(t("add.field_required", { field: step.key })));
|
|
779
|
-
continue;
|
|
780
|
-
}
|
|
781
|
-
// empty input + has current value → keep current (already in values)
|
|
782
|
-
i++;
|
|
783
|
-
}
|
|
784
|
-
const env = {};
|
|
785
|
-
for (const [k, v] of Object.entries(values)) {
|
|
786
|
-
if (v)
|
|
787
|
-
env[k] = v;
|
|
788
|
-
}
|
|
789
|
-
settingsConfig = { ...profile.settingsConfig, env };
|
|
790
|
-
}
|
|
791
|
-
// 3. Preview
|
|
792
|
-
console.log(`\n${chalk.bold(t("add.preview_header"))}\n`);
|
|
793
|
-
console.log(JSON.stringify(settingsConfig, null, 2));
|
|
794
|
-
console.log();
|
|
795
|
-
// 4. Optional editor (only for step mode)
|
|
796
|
-
if (mode !== "2") {
|
|
797
|
-
const editChoice = await ask(t("add.edit_confirm"));
|
|
798
|
-
if (editChoice.toLowerCase() === "y") {
|
|
799
|
-
const edited = openEditor(profile.name, settingsConfig);
|
|
800
|
-
if (edited)
|
|
801
|
-
settingsConfig = edited;
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
// 5. Save
|
|
805
|
-
store.save(profile.name, settingsConfig);
|
|
806
|
-
console.log(chalk.green(t("modify.done", { name: profile.name })));
|
|
807
|
-
// 6. Switch if not current
|
|
808
|
-
if (profile.name !== current) {
|
|
809
|
-
const switchChoice = await ask(t("add.switch_confirm"));
|
|
810
|
-
if (switchChoice.toLowerCase() !== "n") {
|
|
811
|
-
store.setCurrent(profile.name);
|
|
812
|
-
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
813
|
-
if (isCcSwitchGuiRunning()) {
|
|
814
|
-
console.log(chalk.yellow(t("use.cc_switch_running")));
|
|
815
|
-
}
|
|
816
|
-
else {
|
|
817
|
-
applyProfile(profile.name, settingsConfig);
|
|
818
|
-
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
else {
|
|
823
|
-
applyProfile(profile.name, settingsConfig);
|
|
824
|
-
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
825
|
-
}
|
|
826
|
-
});
|
|
827
|
-
// cc-castremove [name]
|
|
828
|
-
program
|
|
829
|
-
.command("remove [name]")
|
|
830
|
-
.alias("rm")
|
|
831
|
-
.description(t("remove.description"))
|
|
832
|
-
.action(async (name) => {
|
|
833
|
-
const store = ensureStore();
|
|
834
|
-
const profiles = store.list();
|
|
835
|
-
const current = store.getCurrent();
|
|
836
|
-
if (!name) {
|
|
837
|
-
if (profiles.length === 0) {
|
|
838
|
-
console.log(chalk.yellow(t("list.empty")));
|
|
839
|
-
return;
|
|
840
|
-
}
|
|
841
|
-
const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
|
|
842
|
-
if (isInteractive) {
|
|
843
|
-
const options = profiles.map((p) => {
|
|
844
|
-
const isCurrent = p.name === current;
|
|
845
|
-
const env = (p.settingsConfig.env || {});
|
|
846
|
-
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
847
|
-
const tag = isCurrent ? ` ${t("list.current_marker")}` : "";
|
|
848
|
-
return {
|
|
849
|
-
label: `${p.name}${tag}`,
|
|
850
|
-
hint: `${t("common.model")}: ${model}`,
|
|
851
|
-
value: p.name,
|
|
852
|
-
};
|
|
853
|
-
});
|
|
854
|
-
const prompt = createSelect({
|
|
855
|
-
message: "",
|
|
856
|
-
choices: options.map((o) => ({ name: o.value, message: o.label, hint: o.hint })),
|
|
857
|
-
pointer: "●",
|
|
858
|
-
styles: { em: (k) => k, strong: (k) => k },
|
|
859
|
-
});
|
|
860
|
-
try {
|
|
861
|
-
name = await prompt.run();
|
|
862
|
-
}
|
|
863
|
-
catch {
|
|
864
|
-
console.log(chalk.gray(t("common.cancelled")));
|
|
865
|
-
return;
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
else {
|
|
869
|
-
console.log(chalk.bold(`\n${t("list.header")}\n`));
|
|
870
|
-
profiles.forEach((p, i) => {
|
|
871
|
-
const isCurrent = p.name === current;
|
|
872
|
-
const marker = isCurrent ? chalk.green("● ") : " ";
|
|
873
|
-
const label = isCurrent ? chalk.green.bold(p.name) : p.name;
|
|
874
|
-
const env = (p.settingsConfig.env || {});
|
|
875
|
-
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
876
|
-
console.log(`${marker}${chalk.gray(`${i + 1}.`)} ${label}`);
|
|
877
|
-
console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
|
|
878
|
-
});
|
|
879
|
-
console.log();
|
|
880
|
-
const input = await ask(t("list.choose_number"));
|
|
881
|
-
if (!input)
|
|
882
|
-
return;
|
|
883
|
-
const idx = parseInt(input, 10) - 1;
|
|
884
|
-
if (isNaN(idx) || idx < 0 || idx >= profiles.length) {
|
|
885
|
-
console.log(chalk.red(t("error.invalid_choice")));
|
|
886
|
-
return;
|
|
887
|
-
}
|
|
888
|
-
name = profiles[idx].name;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
// Check if name is an alias
|
|
892
|
-
const aliasTarget = getAliasTarget(name);
|
|
893
|
-
if (aliasTarget) {
|
|
894
|
-
console.log(chalk.yellow(t("alias.is_alias", { name, target: aliasTarget })));
|
|
895
|
-
console.log(`\n${t("alias.rm_which")}\n`);
|
|
896
|
-
console.log(` ${chalk.cyan("1)")} ${t("alias.rm_alias", { name })}`);
|
|
897
|
-
console.log(` ${chalk.cyan("2)")} ${t("alias.rm_config", { target: aliasTarget })}`);
|
|
898
|
-
const choice = await ask(t("alias.rm_choose"));
|
|
899
|
-
if (choice === "1") {
|
|
900
|
-
const rc = readRc();
|
|
901
|
-
delete rc.aliases[name];
|
|
902
|
-
writeRc(rc);
|
|
903
|
-
console.log(chalk.green(t("alias.rm_done", { short: name })));
|
|
904
|
-
return;
|
|
905
|
-
}
|
|
906
|
-
// choice === "2" → delete the config
|
|
907
|
-
name = aliasTarget;
|
|
908
|
-
}
|
|
909
|
-
const profile = await resolveProfile(store, name);
|
|
910
|
-
if (!profile)
|
|
911
|
-
return;
|
|
912
|
-
const confirm = await ask(t("remove.confirm", { name: profile.name }));
|
|
913
|
-
if (confirm.toLowerCase() !== "y")
|
|
914
|
-
return;
|
|
915
|
-
store.remove(profile.name);
|
|
916
|
-
console.log(chalk.green(t("remove.done", { name: profile.name })));
|
|
917
|
-
});
|
|
918
|
-
// cc-castalias
|
|
919
|
-
const aliasCmd = program
|
|
920
|
-
.command("alias")
|
|
921
|
-
.description(t("alias.description"));
|
|
922
|
-
aliasCmd
|
|
923
|
-
.command("set <short> <name>")
|
|
924
|
-
.description(t("alias.set_description"))
|
|
925
|
-
.action((short, name) => {
|
|
926
|
-
const store = ensureStore();
|
|
927
|
-
if (!store.get(name)) {
|
|
928
|
-
const allNames = store.list().map((p) => p.name);
|
|
929
|
-
const suggestions = findSuggestions(name, allNames);
|
|
930
|
-
console.log(chalk.red(t("error.not_found", { name })));
|
|
931
|
-
if (suggestions.length > 0) {
|
|
932
|
-
console.log(chalk.yellow(t("suggest.did_you_mean", { name: suggestions.join(", ") })));
|
|
933
|
-
}
|
|
934
|
-
return;
|
|
935
|
-
}
|
|
936
|
-
const rc = readRc();
|
|
937
|
-
rc.aliases = rc.aliases || {};
|
|
938
|
-
rc.aliases[short] = name;
|
|
939
|
-
writeRc(rc);
|
|
940
|
-
console.log(chalk.green(t("alias.set_done", { short: chalk.bold(short), name })));
|
|
941
|
-
});
|
|
942
|
-
aliasCmd
|
|
943
|
-
.command("rm <short>")
|
|
944
|
-
.description(t("alias.rm_description"))
|
|
945
|
-
.action((short) => {
|
|
946
|
-
const rc = readRc();
|
|
947
|
-
if (!rc?.aliases?.[short]) {
|
|
948
|
-
console.log(chalk.red(t("alias.rm_not_found", { short })));
|
|
949
|
-
return;
|
|
950
|
-
}
|
|
951
|
-
delete rc.aliases[short];
|
|
952
|
-
writeRc(rc);
|
|
953
|
-
console.log(chalk.green(t("alias.rm_done", { short })));
|
|
954
|
-
});
|
|
955
|
-
aliasCmd
|
|
956
|
-
.command("list")
|
|
957
|
-
.alias("ls")
|
|
958
|
-
.description(t("alias.list_description"))
|
|
959
|
-
.action(() => {
|
|
960
|
-
const rc = readRc();
|
|
961
|
-
const aliases = rc?.aliases || {};
|
|
962
|
-
const entries = Object.entries(aliases);
|
|
963
|
-
if (entries.length === 0) {
|
|
964
|
-
console.log(chalk.yellow(t("alias.list_empty")));
|
|
965
|
-
return;
|
|
966
|
-
}
|
|
967
|
-
console.log(chalk.bold(`\n${t("alias.list_header")}\n`));
|
|
968
|
-
for (const [short, name] of entries) {
|
|
969
|
-
console.log(` ${chalk.cyan.bold(short)} → ${name}`);
|
|
970
|
-
}
|
|
971
|
-
console.log();
|
|
972
|
-
});
|
|
973
|
-
// Default: cc-cast alias (no subcommand) → show list
|
|
974
|
-
aliasCmd.action(() => {
|
|
975
|
-
aliasCmd.commands.find((c) => c.name() === "list").parseAsync([]);
|
|
976
|
-
});
|
|
977
|
-
// cc-castlocale
|
|
978
|
-
const localeCmd = program
|
|
979
|
-
.command("locale")
|
|
980
|
-
.description(t("locale.description"));
|
|
981
|
-
localeCmd
|
|
982
|
-
.command("set <lang>")
|
|
983
|
-
.description(t("locale.set_description"))
|
|
984
|
-
.action((lang) => {
|
|
985
|
-
if (lang !== "zh" && lang !== "en") {
|
|
986
|
-
console.log(chalk.red(t("locale.set_invalid", { locale: lang })));
|
|
987
|
-
return;
|
|
988
|
-
}
|
|
989
|
-
switchLocale(lang);
|
|
990
|
-
});
|
|
991
|
-
const SUPPORTED_LOCALES = [
|
|
992
|
-
{ code: "zh", label: "中文" },
|
|
993
|
-
{ code: "en", label: "English" },
|
|
994
|
-
];
|
|
995
|
-
const switchLocale = (code) => {
|
|
996
|
-
const rc = readRc();
|
|
997
|
-
rc.locale = code;
|
|
998
|
-
writeRc(rc);
|
|
999
|
-
setLocale(code);
|
|
1000
|
-
console.log(chalk.green(t("locale.set_done", { locale: code })));
|
|
1001
|
-
};
|
|
1002
|
-
localeCmd
|
|
1003
|
-
.command("list")
|
|
1004
|
-
.alias("ls")
|
|
1005
|
-
.description(t("locale.list_description"))
|
|
1006
|
-
.action(async () => {
|
|
1007
|
-
const rc = readRc();
|
|
1008
|
-
const current = rc?.locale || getLocale();
|
|
1009
|
-
const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
|
|
1010
|
-
if (isInteractive) {
|
|
1011
|
-
const options = SUPPORTED_LOCALES.map(({ code, label }) => {
|
|
1012
|
-
const isCurrent = code === current;
|
|
1013
|
-
const tag = isCurrent ? ` ${t("locale.list_current_marker")}` : "";
|
|
1014
|
-
return { label: `${code} - ${label}${tag}`, value: code };
|
|
1015
|
-
});
|
|
1016
|
-
const initialIdx = options.findIndex((o) => o.value === current);
|
|
1017
|
-
const prompt = createSelect({
|
|
1018
|
-
message: "",
|
|
1019
|
-
choices: options.map((o) => ({ name: o.value, message: o.label })),
|
|
1020
|
-
initial: initialIdx >= 0 ? initialIdx : 0,
|
|
1021
|
-
pointer: "●",
|
|
1022
|
-
styles: { em: (k) => k, strong: (k) => k },
|
|
1023
|
-
});
|
|
1024
|
-
try {
|
|
1025
|
-
const value = await prompt.run();
|
|
1026
|
-
if (value === current)
|
|
1027
|
-
return;
|
|
1028
|
-
switchLocale(value);
|
|
1029
|
-
}
|
|
1030
|
-
catch {
|
|
1031
|
-
console.log(chalk.gray(t("common.cancelled")));
|
|
1032
|
-
return;
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
else {
|
|
1036
|
-
console.log(chalk.bold(`\n${t("locale.list_header")}\n`));
|
|
1037
|
-
SUPPORTED_LOCALES.forEach(({ code, label }, i) => {
|
|
1038
|
-
const isCurrent = code === current;
|
|
1039
|
-
const marker = isCurrent ? chalk.green("● ") : " ";
|
|
1040
|
-
const name = isCurrent ? chalk.green.bold(`${code} - ${label}`) : `${code} - ${label}`;
|
|
1041
|
-
const tag = isCurrent ? chalk.gray(` ${t("locale.list_current_marker")}`) : "";
|
|
1042
|
-
console.log(`${marker}${chalk.gray(`${i + 1}.`)} ${name}${tag}`);
|
|
1043
|
-
});
|
|
1044
|
-
console.log();
|
|
1045
|
-
const input = await ask(t("locale.choose_number"));
|
|
1046
|
-
if (!input)
|
|
1047
|
-
return;
|
|
1048
|
-
const idx = parseInt(input, 10) - 1;
|
|
1049
|
-
if (isNaN(idx) || idx < 0 || idx >= SUPPORTED_LOCALES.length) {
|
|
1050
|
-
console.log(chalk.red(t("error.invalid_choice")));
|
|
1051
|
-
return;
|
|
1052
|
-
}
|
|
1053
|
-
const selected = SUPPORTED_LOCALES[idx].code;
|
|
1054
|
-
if (selected === current)
|
|
1055
|
-
return;
|
|
1056
|
-
switchLocale(selected);
|
|
1057
|
-
}
|
|
1058
|
-
});
|
|
1059
|
-
// Default: cc-cast locale (no subcommand) → show list
|
|
1060
|
-
localeCmd.action(() => {
|
|
1061
|
-
localeCmd.commands.find((c) => c.name() === "list").parseAsync([]);
|
|
1062
|
-
});
|
|
1063
|
-
program.parse();
|
|
2
|
+
var Le=Object.defineProperty;var S=(s,n)=>()=>(s&&(n=s(s=0)),n);var le=(s,n)=>{for(var t in n)Le(s,t,{get:n[t],enumerable:!0})};var be,de,ge=S(()=>{"use strict";be={"program.description":"Claude Code Model Switcher - \u5FEB\u901F\u5207\u6362 Claude Code \u81EA\u5B9A\u4E49\u6A21\u578B\u914D\u7F6E","common.not_init":"\u5C1A\u672A\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u8FD0\u884C: cc-cast init","common.model":"\u6A21\u578B","common.model_default":"\u9ED8\u8BA4","common.source":"\u6765\u6E90","common.cancelled":"\u5DF2\u53D6\u6D88","error.not_found":'\u914D\u7F6E "{name}" \u4E0D\u5B58\u5728',"error.alias_target_missing":'\u522B\u540D "{alias}" \u6307\u5411 "{target}"\uFF0C\u4F46\u8BE5\u914D\u7F6E\u4E0D\u5B58\u5728',"error.invalid_choice":"\u65E0\u6548\u9009\u62E9","suggest.did_you_mean":"\u4F60\u662F\u4E0D\u662F\u60F3\u8BF4: {name}?","suggest.did_you_mean_header":"\u4F60\u662F\u4E0D\u662F\u60F3\u8BF4:","suggest.use_list":"\u4F7F\u7528 cc-cast list \u67E5\u770B\u6240\u6709\u53EF\u7528\u914D\u7F6E","init.description":"\u521D\u59CB\u5316 cc-cast","init.cc_switch_found":"\u68C0\u6D4B\u5230 cc-switch \u5DF2\u5B89\u88C5\uFF0C\u662F\u5426\u4ECE\u4E2D\u5BFC\u5165\u914D\u7F6E\uFF1F(Y/n) ","init.cc_switch_mode":"\u2713 \u68C0\u6D4B\u5230 cc-switch\uFF0Ccc-cast \u5C06\u76F4\u63A5\u4F7F\u7528 cc-switch \u914D\u7F6E\u5E93","init.cc_switch_migrate":"\u53D1\u73B0 cc-cast \u72EC\u7ACB\u914D\u7F6E\uFF0C\u662F\u5426\u5C06\u5176\u8FC1\u79FB\u81F3 cc-switch\uFF1F(Y/n) ","init.cc_switch_migrate_done":"\u2713 \u5DF2\u8FC1\u79FB {count} \u4E2A\u914D\u7F6E\u81F3 cc-switch","init.done":"\u2713 \u521D\u59CB\u5316\u5B8C\u6210","list.description":"\u5217\u51FA\u5E76\u9009\u62E9\u914D\u7F6E\u65B9\u6848","list.empty":"\u6682\u65E0\u914D\u7F6E\u65B9\u6848\u3002\u4F7F\u7528 cc-cast save <name> \u4FDD\u5B58\u5F53\u524D\u914D\u7F6E","list.header":"\u53EF\u7528\u914D\u7F6E:","list.select":"\u9009\u62E9\u914D\u7F6E:","list.current_marker":"(\u5F53\u524D)","list.choose_number":"\u8F93\u5165\u5E8F\u53F7\u5207\u6362 (\u56DE\u8F66\u8DF3\u8FC7): ","current.description":"\u663E\u793A\u5F53\u524D\u751F\u6548\u7684\u914D\u7F6E","current.none":"\u5F53\u524D\u65E0\u6FC0\u6D3B\u914D\u7F6E","current.settings_header":"\u5F53\u524D settings.json:","current.not_exist":'\u5F53\u524D\u914D\u7F6E "{name}" \u5DF2\u4E0D\u5B58\u5728',"current.header":"\u5F53\u524D\u914D\u7F6E: {name}","use.description":"\u5207\u6362\u5230\u6307\u5B9A\u914D\u7F6E\u65B9\u6848","use.done":"\u2713 \u5DF2\u5207\u6362\u5230 {name}","use.restart":"\u91CD\u542F Claude Code \u751F\u6548","use.cc_switch_running":"\u68C0\u6D4B\u5230 cc-switch GUI \u6B63\u5728\u8FD0\u884C\uFF0C\u4E3A\u907F\u514D\u914D\u7F6E\u51B2\u7A81\uFF0C\u4EC5\u66F4\u65B0\u4E86\u5F53\u524D\u914D\u7F6E\u6807\u8BB0\u3002\u8BF7\u5728 cc-switch GUI \u4E2D\u624B\u52A8\u5207\u6362\uFF0C\u6216\u9000\u51FA GUI \u540E\u91CD\u8BD5\u3002","save.description":"\u4ECE\u5F53\u524D settings.json \u4FDD\u5B58\u4E3A\u65B0\u914D\u7F6E","save.overwrite":'\u914D\u7F6E "{name}" \u5DF2\u5B58\u5728\uFF0C\u5C06\u8986\u76D6',"save.done":'\u2713 \u5DF2\u4FDD\u5B58\u5F53\u524D\u914D\u7F6E\u4E3A "{name}"',"show.description":"\u67E5\u770B\u914D\u7F6E\u8BE6\u60C5\uFF08\u4E0D\u6307\u5B9A\u5219\u663E\u793A\u5F53\u524D\uFF09","show.no_current":"\u5F53\u524D\u65E0\u6FC0\u6D3B\u914D\u7F6E\uFF0C\u8BF7\u6307\u5B9A\u540D\u79F0: cc-cast show <name>","show.all_header":"\u6240\u6709\u914D\u7F6E:","remove.description":"\u5220\u9664\u914D\u7F6E\u65B9\u6848","remove.select":"\u9009\u62E9\u8981\u5220\u9664\u7684\u914D\u7F6E:","remove.confirm":'\u786E\u8BA4\u5220\u9664 "{name}"\uFF1F(y/N) ',"remove.done":'\u2713 \u5DF2\u5220\u9664 "{name}"',"alias.description":"\u7BA1\u7406\u522B\u540D","alias.set_description":"\u8BBE\u7F6E\u522B\u540D\uFF0C\u5982: cc-cast alias set or openrouter-opus4.6","alias.set_done":"\u2713 \u522B\u540D\u5DF2\u8BBE\u7F6E: {short} \u2192 {name}","alias.rm_description":"\u5220\u9664\u522B\u540D","alias.rm_not_found":'\u522B\u540D "{short}" \u4E0D\u5B58\u5728',"alias.rm_done":'\u2713 \u5DF2\u5220\u9664\u522B\u540D "{short}"',"alias.list_description":"\u5217\u51FA\u6240\u6709\u522B\u540D","alias.list_empty":"\u6682\u65E0\u522B\u540D\u3002\u4F7F\u7528 cc-cast alias set <short> <name> \u6DFB\u52A0","alias.list_header":"\u522B\u540D\u5217\u8868:","locale.description":"\u7BA1\u7406\u754C\u9762\u8BED\u8A00","locale.current":"\u5F53\u524D\u8BED\u8A00: {locale}","locale.set_description":"\u8BBE\u7F6E\u8BED\u8A00 (zh/en)","locale.set_done":"\u2713 \u8BED\u8A00\u5DF2\u8BBE\u7F6E\u4E3A {locale}","locale.set_invalid":"\u4E0D\u652F\u6301\u7684\u8BED\u8A00: {locale}\uFF0C\u53EF\u9009: zh, en","locale.list_description":"\u5217\u51FA\u5E76\u9009\u62E9\u8BED\u8A00","locale.list_header":"\u652F\u6301\u7684\u8BED\u8A00:","locale.list_current_marker":"(\u5F53\u524D)","locale.select":"\u9009\u62E9\u8BED\u8A00:","locale.choose_number":"\u8F93\u5165\u5E8F\u53F7\u5207\u6362 (\u56DE\u8F66\u8DF3\u8FC7): ","add.description":"\u4EA4\u4E92\u5F0F\u6DFB\u52A0\u65B0\u914D\u7F6E","add.prompt_name":"\u4F9B\u5E94\u5546\u540D\u79F0 (\u5982 OpenRouter): ","add.prompt_base_url":"ANTHROPIC_BASE_URL: ","add.prompt_auth_token":"ANTHROPIC_AUTH_TOKEN: ","add.prompt_model":"ANTHROPIC_MODEL: ","add.prompt_default_opus":"ANTHROPIC_DEFAULT_OPUS_MODEL (\u56DE\u8F66\u8DF3\u8FC7): ","add.prompt_default_sonnet":"ANTHROPIC_DEFAULT_SONNET_MODEL (\u56DE\u8F66\u8DF3\u8FC7): ","add.prompt_default_haiku":"ANTHROPIC_DEFAULT_HAIKU_MODEL (\u56DE\u8F66\u8DF3\u8FC7): ","add.mode_select":"\u9009\u62E9\u6DFB\u52A0\u65B9\u5F0F:","add.mode_interactive":"\u9010\u6B65\u586B\u5199","add.mode_json":"\u76F4\u63A5\u7F16\u5199 JSON","add.mode_choose":"\u8BF7\u9009\u62E9 (1/2): ","add.json_template_hint":"\u8BF7\u5728\u7F16\u8F91\u5668\u4E2D\u586B\u5199\u914D\u7F6E\uFF0C\u4FDD\u5B58\u5E76\u9000\u51FA","add.json_parse_error":"JSON \u89E3\u6790\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u683C\u5F0F","add.back_hint":"\u8F93\u5165 < \u8FD4\u56DE\u4E0A\u4E00\u6B65","add.name_required":"\u4F9B\u5E94\u5546\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A","add.field_required":"{field} \u4E0D\u80FD\u4E3A\u7A7A","add.already_exists":'\u914D\u7F6E "{name}" \u5DF2\u5B58\u5728\uFF0C\u662F\u5426\u8986\u76D6\uFF1F(y/N) ',"add.edit_confirm":"\u662F\u5426\u5728\u7F16\u8F91\u5668\u4E2D\u7F16\u8F91\u914D\u7F6E\uFF1F(y/N) ","add.preview_header":"\u914D\u7F6E\u9884\u89C8:","add.done":'\u2713 \u5DF2\u4FDD\u5B58\u914D\u7F6E "{name}"',"add.switch_confirm":"\u662F\u5426\u7ACB\u5373\u5207\u6362\u5230\u6B64\u914D\u7F6E\uFF1F(Y/n) ","add.cancelled":"\u5DF2\u53D6\u6D88","modify.description":"\u4FEE\u6539\u5DF2\u6709\u914D\u7F6E","modify.select":"\u9009\u62E9\u8981\u4FEE\u6539\u7684\u914D\u7F6E:","modify.done":'\u2713 \u5DF2\u66F4\u65B0\u914D\u7F6E "{name}"',"modify.no_change":"\u672A\u505A\u4EFB\u4F55\u4FEE\u6539","alias.is_alias":'"{name}" \u662F\u522B\u540D\uFF0C\u6307\u5411 "{target}"',"alias.conflict":'"{name}" \u540C\u65F6\u662F\u522B\u540D\uFF08\u2192 {target}\uFF09\u548C\u914D\u7F6E\u540D\uFF0C\u4F7F\u7528\u54EA\u4E2A\uFF1F',"alias.conflict_alias":"\u522B\u540D\uFF08\u2192 {target}\uFF09","alias.conflict_config":"\u914D\u7F6E {name}","alias.choose_conflict":"\u8BF7\u9009\u62E9 (1/2): ","alias.rm_which":"\u8981\u5220\u9664\u54EA\u4E2A\uFF1F","alias.rm_alias":"\u522B\u540D {name}","alias.rm_config":"\u914D\u7F6E {target}","alias.rm_choose":"\u8BF7\u9009\u62E9 (1/2): ","sync.description":"\u4ECE cc-switch \u540C\u6B65\u914D\u7F6E","sync.no_cc_switch":"\u672A\u68C0\u6D4B\u5230 cc-switch \u6570\u636E\u5E93","sync.empty":"cc-switch \u4E2D\u6CA1\u6709\u627E\u5230 Claude \u914D\u7F6E","sync.done":"\u2713 \u5DF2\u540C\u6B65 {count} \u4E2A\u914D\u7F6E","sync.current":"\u5F53\u524D\u6FC0\u6D3B: {name}","sync.no_current":"\u5F53\u524D\u65E0\u6FC0\u6D3B\u914D\u7F6E","clear.description":"\u6E05\u7406 cc-cast \u6570\u636E\u6587\u4EF6","clear.confirm":"\u786E\u8BA4\u5220\u9664\u6240\u6709 cc-cast \u6570\u636E\u6587\u4EF6\uFF1F(y/N) ","clear.cancelled":"\u5DF2\u53D6\u6D88\u6E05\u7406","clear.removed":"\u2713 \u5DF2\u5220\u9664 {path}","clear.done":"\u2713 \u6E05\u7406\u5B8C\u6210","import.description":"\u4ECE JSON \u5BFC\u5165\u914D\u7F6E\uFF08\u6587\u4EF6\u6216\u7C98\u8D34\uFF09","import.paste_hint":"\u7C98\u8D34 JSON\uFF0C\u6309 Ctrl+D\uFF08\u6216 Windows \u7684 Ctrl+Z\uFF09\u7ED3\u675F:","import.file_not_found":"\u6587\u4EF6\u4E0D\u5B58\u5728: {file}","import.json_parse_error":"JSON \u683C\u5F0F\u65E0\u6548","import.invalid_format":"\u683C\u5F0F\u9519\u8BEF: \u5E94\u4E3A\u4EE5\u914D\u7F6E\u540D\u79F0\u4E3A\u952E\u7684\u5BF9\u8C61","import.done":"\u2713 \u5DF2\u5BFC\u5165 {count} \u4E2A\u914D\u7F6E","store.db_not_found":"cc-switch \u6570\u636E\u5E93\u4E0D\u5B58\u5728: {path}"},de=be});var Ie,me,ue=S(()=>{"use strict";Ie={"program.description":"Claude Code Model Switcher - Quickly switch Claude Code custom model configurations","common.not_init":"Not initialized yet. Run: cc-cast init","common.model":"Model","common.model_default":"default","common.source":"Source","common.cancelled":"cancelled","error.not_found":'Configuration "{name}" not found',"error.alias_target_missing":'Alias "{alias}" points to "{target}", but it does not exist',"error.invalid_choice":"Invalid choice","suggest.did_you_mean":"Did you mean: {name}?","suggest.did_you_mean_header":"Did you mean:","suggest.use_list":"Use cc-cast list to see all available configurations","init.description":"Initialize cc-cast","init.cc_switch_found":"cc-switch detected. Import configurations from it? (Y/n) ","init.cc_switch_mode":"\u2713 cc-switch detected \u2014 cc-cast will use cc-switch's configuration store directly","init.cc_switch_migrate":"Standalone cc-cast configurations found. Migrate them to cc-switch? (Y/n) ","init.cc_switch_migrate_done":"\u2713 Migrated {count} configurations to cc-switch","init.done":"\u2713 Initialized","list.description":"List and select configurations","list.empty":"No configurations yet. Use cc-cast save <name> to save current config","list.header":"Available configurations:","list.select":"Select configuration:","list.current_marker":"(current)","list.choose_number":"Enter number to switch (Enter to skip): ","current.description":"Show the currently active configuration","current.none":"No active configuration","current.settings_header":"Current settings.json:","current.not_exist":'Current configuration "{name}" no longer exists',"current.header":"Current configuration: {name}","use.description":"Switch to a specified configuration","use.done":"\u2713 Switched to {name}","use.restart":"Restart Claude Code to apply","use.cc_switch_running":"cc-switch GUI is running. To avoid config conflicts, only the active marker was updated. Please switch manually in cc-switch GUI, or quit GUI and try again.","save.description":"Save current settings.json as a new configuration","save.overwrite":'Configuration "{name}" already exists, will overwrite',"save.done":'\u2713 Saved current configuration as "{name}"',"show.description":"View configuration details (defaults to current)","show.no_current":"No active configuration. Specify a name: cc-cast show <name>","show.all_header":"All configurations:","remove.description":"Delete a configuration","remove.select":"Select configuration to delete:","remove.confirm":'Delete "{name}"? (y/N) ',"remove.done":'\u2713 Deleted "{name}"',"alias.description":"Manage aliases","alias.set_description":"Set alias, e.g.: cc-cast alias set or openrouter-opus4.6","alias.set_done":"\u2713 Alias set: {short} \u2192 {name}","alias.rm_description":"Remove an alias","alias.rm_not_found":'Alias "{short}" not found',"alias.rm_done":'\u2713 Removed alias "{short}"',"alias.list_description":"List all aliases","alias.list_empty":"No aliases yet. Use cc-cast alias set <short> <name> to add one","alias.list_header":"Aliases:","locale.description":"Manage interface language","locale.current":"Current language: {locale}","locale.set_description":"Set language (zh/en)","locale.set_done":"\u2713 Language set to {locale}","locale.set_invalid":"Unsupported language: {locale}. Available: zh, en","locale.list_description":"List and select language","locale.list_header":"Supported languages:","locale.list_current_marker":"(current)","locale.select":"Select language:","locale.choose_number":"Enter number to switch (Enter to skip): ","add.description":"Interactively add a new configuration","add.prompt_name":"Provider name (e.g. OpenRouter): ","add.prompt_base_url":"ANTHROPIC_BASE_URL: ","add.prompt_auth_token":"ANTHROPIC_AUTH_TOKEN: ","add.prompt_model":"ANTHROPIC_MODEL: ","add.prompt_default_opus":"ANTHROPIC_DEFAULT_OPUS_MODEL (press Enter to skip): ","add.prompt_default_sonnet":"ANTHROPIC_DEFAULT_SONNET_MODEL (press Enter to skip): ","add.prompt_default_haiku":"ANTHROPIC_DEFAULT_HAIKU_MODEL (press Enter to skip): ","add.mode_select":"Choose how to add:","add.mode_interactive":"Step by step","add.mode_json":"Write JSON directly","add.mode_choose":"Choose (1/2): ","add.json_template_hint":"Fill in the configuration in editor, save and exit","add.json_parse_error":"JSON parse error, please check format","add.back_hint":"Type < to go back","add.name_required":"Provider name cannot be empty","add.field_required":"{field} cannot be empty","add.already_exists":'Configuration "{name}" already exists. Overwrite? (y/N) ',"add.edit_confirm":"Edit configuration in editor? (y/N) ","add.preview_header":"Configuration preview:","add.done":'\u2713 Saved configuration "{name}"',"add.switch_confirm":"Switch to this configuration now? (Y/n) ","add.cancelled":"Cancelled","modify.description":"Modify an existing configuration","modify.select":"Select configuration to modify:","modify.done":'\u2713 Updated configuration "{name}"',"modify.no_change":"No changes made","alias.is_alias":'"{name}" is an alias for "{target}"',"alias.conflict":'"{name}" is both an alias (\u2192 {target}) and a config name. Which one?',"alias.conflict_alias":"Alias (\u2192 {target})","alias.conflict_config":"Config {name}","alias.choose_conflict":"Choose (1/2): ","alias.rm_which":"Which one to delete?","alias.rm_alias":"Alias {name}","alias.rm_config":"Config {target}","alias.rm_choose":"Choose (1/2): ","sync.description":"Sync configurations from cc-switch","sync.no_cc_switch":"cc-switch database not detected","sync.empty":"No Claude configurations found in cc-switch","sync.done":"\u2713 Synced {count} configurations","sync.current":"Active: {name}","sync.no_current":"No active configuration","clear.description":"Clean up cc-cast data files","clear.confirm":"Delete all cc-cast data files? (y/N) ","clear.cancelled":"Cancelled","clear.removed":"\u2713 Deleted {path}","clear.done":"\u2713 Cleanup complete","import.description":"Import configurations from JSON (file or stdin)","import.paste_hint":"Paste JSON and press Ctrl+D (or Ctrl+Z on Windows) to finish:","import.file_not_found":"File not found: {file}","import.json_parse_error":"Invalid JSON format","import.invalid_format":"Invalid format: expected object with configuration names as keys","import.done":"\u2713 Imported {count} configurations","store.db_not_found":"cc-switch database not found: {path}"},me=Ie});function $e(){let s=w();return s?.locale&&s.locale in z?s.locale:((process.env.LC_ALL||process.env.LANG||"").startsWith("en"),"en")}function B(){return k||(k=$e()),k}function fe(s){k=s}function e(s,n){let t=B(),r=z[t][s]??z.en[s]??s;if(n)for(let[c,a]of Object.entries(n))r=r.replace(new RegExp(`\\{${c}\\}`,"g"),a);return r}var z,k,P=S(()=>{"use strict";ge();ue();W();z={zh:de,en:me}});var Z={};le(Z,{StandaloneStore:()=>R});import{homedir as ke}from"os";import{join as pe}from"path";import{existsSync as _e,readFileSync as Pe,writeFileSync as De,mkdirSync as He}from"fs";function Ue(){_e(G)||He(G,{recursive:!0})}function T(){return _e(V)?JSON.parse(Pe(V,"utf-8")):{profiles:{}}}function Y(s){Ue(),De(V,JSON.stringify(s,null,2))}var G,V,R,D=S(()=>{"use strict";P();G=pe(ke(),".cc-cast"),V=pe(G,"config.json");R=class{list(){let n=T();return Object.entries(n.profiles).map(([t,r])=>({id:t,name:t,settingsConfig:r}))}get(n){let r=T().profiles[n];if(r)return{id:n,name:n,settingsConfig:r}}save(n,t){let r=T();r.profiles[n]=t,Y(r)}remove(n){let t=T();return n in t.profiles?(delete t.profiles[n],t.current===n&&(t.current=void 0),Y(t),!0):!1}getCurrent(){return T().current}setCurrent(n){let t=T();if(!(n in t.profiles))throw new Error(e("error.not_found",{name:n}));t.current=n,Y(t)}}});var Q={};le(Q,{CcSwitchStore:()=>L,ccSwitchExists:()=>E});import xe from"better-sqlite3";import{homedir as ye}from"os";import{join as we}from"path";import{existsSync as H,readFileSync as he,writeFileSync as Me}from"fs";function E(){return H(U)}var U,A,L,b=S(()=>{"use strict";P();U=we(ye(),".cc-switch","cc-switch.db"),A=we(ye(),".cc-switch","settings.json");L=class{db;constructor(){if(!H(U))throw new Error(e("store.db_not_found",{path:U}));this.db=new xe(U)}list(){return this.db.prepare("SELECT id, name, settings_config FROM providers WHERE app_type = 'claude' ORDER BY sort_index").all().map(t=>({id:t.id,name:t.name,settingsConfig:JSON.parse(t.settings_config)}))}get(n){let t=this.db.prepare("SELECT id, name, settings_config FROM providers WHERE app_type = 'claude' AND name = ?").get(n);if(t)return{id:t.id,name:t.name,settingsConfig:JSON.parse(t.settings_config)}}save(n,t){if(this.get(n))this.db.prepare("UPDATE providers SET settings_config = ? WHERE app_type = 'claude' AND name = ?").run(JSON.stringify(t),n);else{let a=(this.db.prepare("SELECT COALESCE(MAX(sort_index), -1) as max_sort FROM providers WHERE app_type = 'claude'").get()?.max_sort??-1)+1,i=crypto.randomUUID();this.db.prepare(`INSERT INTO providers (
|
|
3
|
+
id, app_type, name, settings_config, website_url, category,
|
|
4
|
+
created_at, sort_index, notes, icon, icon_color, meta, is_current, in_failover_queue
|
|
5
|
+
) VALUES (?, 'claude', ?, ?, NULL, NULL, ?, ?, NULL, NULL, NULL, '{}', 0, 0)`).run(i,n,JSON.stringify(t),Date.now(),a)}}remove(n){return this.db.prepare("DELETE FROM providers WHERE app_type = 'claude' AND name = ?").run(n).changes>0}getCurrent(){let n=this.db.prepare("SELECT name FROM providers WHERE app_type = 'claude' AND is_current = 1 LIMIT 1").get();if(n)return n.name;if(H(A))try{let r=JSON.parse(he(A,"utf-8")).currentProviderClaude;return r?this.db.prepare("SELECT name FROM providers WHERE app_type = 'claude' AND id = ?").get(r)?.name:void 0}catch{return}}setCurrent(n){let t=this.get(n);if(!t)throw new Error(e("error.not_found",{name:n}));this.db.transaction(()=>{this.db.prepare("UPDATE providers SET is_current = 0 WHERE app_type = 'claude'").run(),this.db.prepare("UPDATE providers SET is_current = 1 WHERE app_type = 'claude' AND id = ?").run(t.id)})();let c=H(A)?JSON.parse(he(A,"utf-8")):{};c.currentProviderClaude=t.id,Me(A,JSON.stringify(c,null,2))}close(){this.db.close()}}});import{homedir as je}from"os";import{join as Ce}from"path";import{existsSync as ve,readFileSync as Fe,writeFileSync as Je,mkdirSync as qe}from"fs";import{spawnSync as Ke}from"child_process";function w(){if(!ve(ee))return O({}),{};try{return JSON.parse(Fe(ee,"utf-8"))}catch{return O({}),{}}}function O(s){ve(X)||qe(X,{recursive:!0}),Je(ee,JSON.stringify(s,null,2))}function Oe(){return E()?new L:new R}function I(){try{let s=Ke("pgrep",["-f","cc-switch"],{encoding:"utf-8"});return s.status===0&&(s.stdout?.trim().length??0)>0}catch{return!1}}var X,ee,W=S(()=>{"use strict";D();b();X=Ce(je(),".cc-cast"),ee=Ce(X,"rc.json")});W();b();import{Command as Ve}from"commander";import o from"chalk";import{homedir as ze}from"os";import{join as Be}from"path";import{existsSync as We,readFileSync as Ye,writeFileSync as Ge}from"fs";var ne=Be(ze(),".claude","settings.json");function x(){return We(ne)?JSON.parse(Ye(ne,"utf-8")):{}}function N(s,n){let t=x(),r={},c=["language","permissions"];for(let i of c)i in t&&(r[i]=t[i]);let a={...t,...r,...n};Ge(ne,JSON.stringify(a,null,2))}P();import{createInterface as Ze}from"readline";import{spawnSync as Qe}from"child_process";import{writeFileSync as Xe,readFileSync as ce,unlinkSync as te,existsSync as oe}from"fs";import{tmpdir as en,homedir as Se}from"os";import{join as j,dirname as nn}from"path";import{fileURLToPath as tn}from"url";import on from"enquirer";import sn from"update-notifier";var rn=on.Select;function q(s){let n=new rn(s);return n.prefix=async()=>"",n.separator=async()=>"",n.cancel=async function(t){this.state.cancelled=!0,this.state.submitted=!0,this.clear(this.state.size),this.stdout.write("\x1B[?25h"),typeof this.stop=="function"&&this.stop(),this.emit("cancel",t)},n.choiceMessage=function(t,r){let c=i=>/\x1b\[\d+m/.test(String(i)),a=this.resolve(t.message,this.state,t,r);return t.role==="heading"&&!c(a)&&(a=this.styles.strong(a)),this.index===r&&!c(a)&&(a=this.styles.primary(a)),this.resolve(a,this.state,t,r)},n}var cn=nn(tn(import.meta.url)),an=j(cn,"..","package.json"),Ee=JSON.parse(ce(an,"utf-8")),ln=sn({pkg:Ee,updateCheckInterval:1e3*60*60*24});ln.notify({isGlobal:!0,defer:!0});var h=new Ve;h.name("ccc").description(e("program.description")).version(Ee.version);function _(s,n){let t=Ze({input:process.stdin,output:process.stdout});return new Promise(r=>{t.question(s,c=>{t.close(),r(c.trim())}),n&&(t.line=n,t.cursor=n.length,t._refreshLine())})}function C(){return Oe()}function dn(){let s=C(),n=s.getCurrent();if(!n){console.log(o.yellow(e("current.none"))),console.log(o.gray(`
|
|
6
|
+
${e("current.settings_header")}`));let a=x().env||{};console.log(se(a));return}let t=s.get(n);if(!t){console.log(o.yellow(e("current.not_exist",{name:n})));return}console.log(`
|
|
7
|
+
${e("current.header",{name:o.green.bold(t.name)})}
|
|
8
|
+
`);let r=t.settingsConfig.env||{};console.log(se(r)),t.settingsConfig.model&&console.log(` ${o.gray("model")}: ${t.settingsConfig.model}`),console.log()}function se(s){let n=[],t=["ANTHROPIC_BASE_URL","ANTHROPIC_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL"];for(let r of t)r in s&&n.push(` ${o.gray(r)}: ${s[r]}`);for(let[r,c]of Object.entries(s))!t.includes(r)&&r!=="ANTHROPIC_AUTH_TOKEN"&&n.push(` ${o.gray(r)}: ${c}`);if("ANTHROPIC_AUTH_TOKEN"in s){let r=s.ANTHROPIC_AUTH_TOKEN,c=r.slice(0,8)+"..."+r.slice(-4);n.push(` ${o.gray("ANTHROPIC_AUTH_TOKEN")}: ${c}`)}return n.join(`
|
|
9
|
+
`)}function gn(s,n){let t=s.length,r=n.length,c=Array.from({length:t+1},(a,i)=>Array.from({length:r+1},(g,d)=>i===0?d:d===0?i:0));for(let a=1;a<=t;a++)for(let i=1;i<=r;i++)c[a][i]=s[a-1]===n[i-1]?c[a-1][i-1]:1+Math.min(c[a-1][i],c[a][i-1],c[a-1][i-1]);return c[t][r]}function Ne(s,n){let t=s.toLowerCase(),r=n.find(i=>i.toLowerCase()===t);if(r)return[r];let c=n.filter(i=>i.toLowerCase().includes(t)||t.includes(i.toLowerCase()));return c.length>0?c:n.map(i=>({name:i,dist:gn(t,i.toLowerCase())})).filter(i=>i.dist<=3).sort((i,g)=>i.dist-g.dist).map(i=>i.name)}function Re(s){return w()?.aliases?.[s]}async function K(s,n){let t=Re(n),r=s.get(n);if(t&&r&&t!==n){if(console.log(o.yellow(e("alias.conflict",{name:n,target:t}))),console.log(` ${o.cyan("1)")} ${e("alias.conflict_alias",{target:t})}`),console.log(` ${o.cyan("2)")} ${e("alias.conflict_config",{name:n})}`),await _(e("alias.choose_conflict"))==="1"){let g=s.get(t);return g||(console.log(o.red(e("error.alias_target_missing",{alias:n,target:t}))),null)}return r}if(t){let i=s.get(t);return i||(console.log(o.red(e("error.alias_target_missing",{alias:n,target:t}))),null)}if(r)return r;let c=s.list().map(i=>i.name),a=Ne(n,c);if(console.log(o.red(e("error.not_found",{name:n}))),a.length===1)console.log(o.yellow(e("suggest.did_you_mean",{name:o.bold(a[0])})));else if(a.length>1){console.log(o.yellow(e("suggest.did_you_mean_header")));for(let i of a)console.log(` - ${o.bold(i)}`)}else console.log(o.gray(e("suggest.use_list")));return null}h.command("init").description(e("init.description")).action(async()=>{let s=w();if(O({aliases:s?.aliases,locale:s?.locale}),console.log(o.green(e("init.done"))),E()){console.log(o.green(e("init.cc_switch_mode")));let{StandaloneStore:n}=await Promise.resolve().then(()=>(D(),Z)),t=new n,r=t.list();if(r.length>0&&(await _(e("init.cc_switch_migrate"))).toLowerCase()!=="n"){let{CcSwitchStore:a}=await Promise.resolve().then(()=>(b(),Q)),i=new a,g=t.getCurrent();for(let d of r)i.save(d.name,d.settingsConfig);g&&i.setCurrent(g),console.log(o.green(e("init.cc_switch_migrate_done",{count:String(r.length)}))),i.close()}}});h.command("sync").description(e("sync.description")).action(async()=>{if(!E()){console.log(o.red(e("sync.no_cc_switch")));return}let{CcSwitchStore:s}=await Promise.resolve().then(()=>(b(),Q)),{StandaloneStore:n}=await Promise.resolve().then(()=>(D(),Z)),t=new s,r=new n,c=t.list();if(c.length===0){console.log(o.yellow(e("sync.empty"))),t.close();return}for(let i of c)r.save(i.name,i.settingsConfig);let a=t.getCurrent();a&&r.setCurrent(a),console.log(o.green(e("sync.done",{count:String(c.length)}))),console.log(a?o.gray(e("sync.current",{name:a})):o.gray(e("sync.no_current"))),t.close()});h.command("clear").description(e("clear.description")).action(async()=>{if((await _(e("clear.confirm"))).toLowerCase()!=="y"){console.log(o.gray(e("clear.cancelled")));return}let n=j(Se(),".cc-cast","rc.json"),t=j(Se(),".cc-cast","config.json");oe(t)&&(te(t),console.log(o.green(e("clear.removed",{path:t})))),oe(n)&&(te(n),console.log(o.green(e("clear.removed",{path:n})))),console.log(o.green(e("clear.done")))});h.command("import [file]").description(e("import.description")).action(async s=>{let n=C(),t;if(s){if(!oe(s)){console.log(o.red(e("import.file_not_found",{file:s})));return}t=ce(s,"utf-8")}else{console.log(o.gray(e("import.paste_hint")));let a=[];process.stdin.setEncoding("utf-8");for await(let i of process.stdin)a.push(Buffer.from(i));t=Buffer.concat(a).toString("utf-8")}let r;try{r=JSON.parse(t)}catch{console.log(o.red(e("import.json_parse_error")));return}if(typeof r!="object"||r===null||Object.keys(r).length===0){console.log(o.red(e("import.invalid_format")));return}let c=0;for(let[a,i]of Object.entries(r))n.save(a,i),c++;console.log(o.green(e("import.done",{count:String(c)})))});h.command("list").alias("ls").description(e("list.description")).action(async()=>{let s=C(),n=s.list(),t=s.getCurrent();if(n.length===0){console.log(o.yellow(e("list.empty")));return}let r=a=>{if(a===t)return;let i=s.get(a);if(s.setCurrent(i.name),console.log(o.green(e("use.done",{name:o.bold(i.name)}))),I())console.log(o.yellow(e("use.cc_switch_running")));else{N(i.name,i.settingsConfig);let d=(i.settingsConfig.env||{}).ANTHROPIC_MODEL||e("common.model_default");console.log(` ${e("common.model")}: ${o.cyan(d)}`),console.log(o.gray(` ${e("use.restart")}`))}};if(process.stdin.isTTY&&process.stdout.isTTY){let a=n.map(d=>{let u=d.name===t,m=d.settingsConfig.env||{},l=m.ANTHROPIC_MODEL||e("common.model_default"),f=m.ANTHROPIC_BASE_URL||"default",p=u?` ${e("list.current_marker")}`:"";return{label:`${d.name}${p}`,hint:`${e("common.model")}: ${l} ${e("common.source")}: ${f}`,value:d.name}}),i=n.findIndex(d=>d.name===t),g=q({message:"",choices:a.map(d=>({name:d.value,message:d.label})),initial:i>=0?i:0,pointer:"\u25CF",styles:{em:d=>d,strong:d=>d}});try{let d=await g.run();r(d)}catch{console.log(o.gray(e("common.cancelled")));return}}else{console.log(o.bold(`
|
|
10
|
+
${e("list.header")}
|
|
11
|
+
`)),n.forEach((g,d)=>{let u=g.name===t,m=u?o.green("\u25CF "):" ",l=u?o.green.bold(g.name):g.name,f=g.settingsConfig.env||{},p=f.ANTHROPIC_MODEL||e("common.model_default"),y=f.ANTHROPIC_BASE_URL||"default";console.log(`${m}${o.gray(`${d+1}.`)} ${l}`),console.log(` ${e("common.model")}: ${o.cyan(p)} ${e("common.source")}: ${o.gray(y)}`)}),console.log();let a=await _(e("list.choose_number"));if(!a)return;let i=parseInt(a,10)-1;if(isNaN(i)||i<0||i>=n.length){console.log(o.red(e("error.invalid_choice")));return}r(n[i].name)}});h.command("current").description(e("current.description")).action(()=>{dn()});h.command("use [name]").description(e("use.description")).action(async s=>{let n=C();if(!s){await h.commands.find(r=>r.name()==="list").parseAsync([]);return}let t=await K(n,s);if(t)if(n.setCurrent(t.name),console.log(o.green(e("use.done",{name:o.bold(t.name)}))),I())console.log(o.yellow(e("use.cc_switch_running")));else{N(t.name,t.settingsConfig);let c=(t.settingsConfig.env||{}).ANTHROPIC_MODEL||e("common.model_default");console.log(` ${e("common.model")}: ${o.cyan(c)}`),console.log(o.gray(` ${e("use.restart")}`))}});h.command("save <name>").description(e("save.description")).action(s=>{let n=C();n.get(s)&&console.log(o.yellow(e("save.overwrite",{name:s})));let r=x(),c={};r.env&&(c.env=r.env),r.model&&(c.model=r.model),r.hooks&&(c.hooks=r.hooks),r.statusLine&&(c.statusLine=r.statusLine),n.save(s,c),n.setCurrent(s),console.log(o.green(e("save.done",{name:s})))});function F(s,n){let t=j(en(),`cc-cast-${s}-${Date.now()}.json`);Xe(t,JSON.stringify(n,null,2));let r=process.env.EDITOR||"vi",c=Qe(r,[t],{stdio:"inherit"}),a=null;if(c.status===0)try{a=JSON.parse(ce(t,"utf-8"))}catch{console.log(o.red(e("add.json_parse_error")))}try{te(t)}catch{}return a}async function Te(s,n,t){s.save(n,t),console.log(o.green(e("add.done",{name:n}))),(await _(e("add.switch_confirm"))).toLowerCase()!=="n"&&(s.setCurrent(n),console.log(o.green(e("use.done",{name:o.bold(n)}))),I()?console.log(o.yellow(e("use.cc_switch_running"))):(N(n,t),console.log(o.gray(` ${e("use.restart")}`))))}var mn={kimi:"https://api.moonshot.cn/v1","kimi-coding":"https://api.kimi.com/coding/",openrouter:"https://openrouter.ai/api/v1",deepseek:"https://api.deepseek.com",zenmux:"https://zenmux.ai/api/anthropic",fusecode:"https://www.fusecode.cc"};function re(s){return mn[s.toLowerCase()]}h.command("add").alias("new").description(e("add.description")).action(async()=>{let s=C(),n=await _(e("add.prompt_name"));if(!n){console.log(o.red(e("add.name_required")));return}if(s.get(n)&&(await _(e("add.already_exists",{name:n}))).toLowerCase()!=="y"){console.log(o.gray(e("add.cancelled")));return}if(console.log(`
|
|
12
|
+
${o.bold(e("add.mode_select"))}
|
|
13
|
+
`),console.log(` ${o.cyan("1)")} ${e("add.mode_interactive")}`),console.log(` ${o.cyan("2)")} ${e("add.mode_json")}
|
|
14
|
+
`),await _(e("add.mode_choose"))==="2"){let l={env:{ANTHROPIC_BASE_URL:re(n)??"",ANTHROPIC_AUTH_TOKEN:"",ANTHROPIC_MODEL:"",ANTHROPIC_DEFAULT_OPUS_MODEL:"",ANTHROPIC_DEFAULT_SONNET_MODEL:"",ANTHROPIC_DEFAULT_HAIKU_MODEL:""}};console.log(o.gray(e("add.json_template_hint")));let f=F(n,l);if(!f)return;await Te(s,n,f);return}let c=re(n),a=[{key:"ANTHROPIC_BASE_URL",prompt:e("add.prompt_base_url"),required:!0,defaultValue:c},{key:"ANTHROPIC_AUTH_TOKEN",prompt:e("add.prompt_auth_token"),required:!0},{key:"ANTHROPIC_MODEL",prompt:e("add.prompt_model"),required:!1},{key:"ANTHROPIC_DEFAULT_OPUS_MODEL",prompt:e("add.prompt_default_opus"),required:!1},{key:"ANTHROPIC_DEFAULT_SONNET_MODEL",prompt:e("add.prompt_default_sonnet"),required:!1},{key:"ANTHROPIC_DEFAULT_HAIKU_MODEL",prompt:e("add.prompt_default_haiku"),required:!1}];console.log(o.gray(e("add.back_hint")));let i={},g=0;for(;g<a.length;){let l=a[g],f=l.defaultValue?`${l.prompt}(${o.gray(l.defaultValue)}): `:l.prompt,p=await _(f,l.defaultValue);if(p==="<"){g>0&&g--;continue}let y=p||l.defaultValue||"";if(l.required&&!y){console.log(o.red(e("add.field_required",{field:l.key})));continue}y?i[l.key]=y:delete i[l.key],g++}let d={};for(let[l,f]of Object.entries(i))d[l]=f;let u={env:d};if(console.log(`
|
|
15
|
+
${o.bold(e("add.preview_header"))}
|
|
16
|
+
`),console.log(JSON.stringify(u,null,2)),console.log(),(await _(e("add.edit_confirm"))).toLowerCase()==="y"){let l=F(n,u);l&&(u=l)}await Te(s,n,u)});h.command("show [name]").description(e("show.description")).action(async s=>{let n=C();if(!s){let c=n.list();if(c.length===0){console.log(o.yellow(e("list.empty")));return}console.log(o.bold(`
|
|
17
|
+
${e("show.all_header")}
|
|
18
|
+
`));let a={};for(let i of c)a[i.name]=i.settingsConfig;console.log(JSON.stringify(a,null,2));return}let t=await K(n,s);if(!t)return;console.log(`
|
|
19
|
+
${o.bold(t.name)}
|
|
20
|
+
`);let r=t.settingsConfig.env||{};console.log(se(r)),t.settingsConfig.model&&console.log(` ${o.gray("model")}: ${t.settingsConfig.model}`),console.log()});h.command("modify [name]").alias("edit").description(e("modify.description")).action(async s=>{let n=C(),t=n.list(),r=n.getCurrent();if(!s){if(t.length===0){console.log(o.yellow(e("list.empty")));return}if(process.stdin.isTTY&&process.stdout.isTTY){let u=t.map(l=>{let f=l.name===r,y=(l.settingsConfig.env||{}).ANTHROPIC_MODEL||e("common.model_default"),v=f?` ${e("list.current_marker")}`:"";return{label:`${l.name}${v}`,hint:`${e("common.model")}: ${y}`,value:l.name}}),m=q({message:"",choices:u.map(l=>({name:l.value,message:l.label,hint:l.hint})),pointer:"\u25CF",styles:{em:l=>l,strong:l=>l}});try{s=await m.run()}catch{console.log(o.gray(e("common.cancelled")));return}}else{console.log(o.bold(`
|
|
21
|
+
${e("list.header")}
|
|
22
|
+
`)),t.forEach((l,f)=>{let p=l.name===r,y=p?o.green("\u25CF "):" ",v=p?o.green.bold(l.name):l.name,Ae=(l.settingsConfig.env||{}).ANTHROPIC_MODEL||e("common.model_default");console.log(`${y}${o.gray(`${f+1}.`)} ${v}`),console.log(` ${e("common.model")}: ${o.cyan(Ae)}`)}),console.log();let u=await _(e("list.choose_number"));if(!u)return;let m=parseInt(u,10)-1;if(isNaN(m)||m<0||m>=t.length){console.log(o.red(e("error.invalid_choice")));return}s=t[m].name}}let c=await K(n,s);if(!c)return;let a=c.settingsConfig.env||{};console.log(`
|
|
23
|
+
${o.bold(e("add.mode_select"))}
|
|
24
|
+
`),console.log(` ${o.cyan("1)")} ${e("add.mode_interactive")}`),console.log(` ${o.cyan("2)")} ${e("add.mode_json")}
|
|
25
|
+
`);let i=await _(e("add.mode_choose")),g;if(i==="2"){let d=F(c.name,c.settingsConfig);if(!d)return;g=d}else{let d=[{key:"ANTHROPIC_BASE_URL",prompt:"ANTHROPIC_BASE_URL",required:!0},{key:"ANTHROPIC_AUTH_TOKEN",prompt:"ANTHROPIC_AUTH_TOKEN",required:!0},{key:"ANTHROPIC_MODEL",prompt:"ANTHROPIC_MODEL",required:!1},{key:"ANTHROPIC_DEFAULT_OPUS_MODEL",prompt:"ANTHROPIC_DEFAULT_OPUS_MODEL",required:!1},{key:"ANTHROPIC_DEFAULT_SONNET_MODEL",prompt:"ANTHROPIC_DEFAULT_SONNET_MODEL",required:!1},{key:"ANTHROPIC_DEFAULT_HAIKU_MODEL",prompt:"ANTHROPIC_DEFAULT_HAIKU_MODEL",required:!1}];console.log(o.gray(e("add.back_hint")));let u={...a},m=0;for(;m<d.length;){let f=d[m],p=a[f.key]||(f.key==="ANTHROPIC_BASE_URL"?re(c.name)??"":""),y=p?`(${o.gray(p)})`:"",v=await _(`${f.prompt}${y}: `,p||void 0);if(v==="<"){m>0&&m--;continue}if(v)u[f.key]=v;else if(f.required&&!p){console.log(o.red(e("add.field_required",{field:f.key})));continue}m++}let l={};for(let[f,p]of Object.entries(u))p&&(l[f]=p);g={...c.settingsConfig,env:l}}if(console.log(`
|
|
26
|
+
${o.bold(e("add.preview_header"))}
|
|
27
|
+
`),console.log(JSON.stringify(g,null,2)),console.log(),i!=="2"&&(await _(e("add.edit_confirm"))).toLowerCase()==="y"){let u=F(c.name,g);u&&(g=u)}n.save(c.name,g),console.log(o.green(e("modify.done",{name:c.name}))),c.name!==r?(await _(e("add.switch_confirm"))).toLowerCase()!=="n"&&(n.setCurrent(c.name),console.log(o.green(e("use.done",{name:o.bold(c.name)}))),I()?console.log(o.yellow(e("use.cc_switch_running"))):(N(c.name,g),console.log(o.gray(` ${e("use.restart")}`)))):(N(c.name,g),console.log(o.gray(` ${e("use.restart")}`)))});h.command("remove [name]").alias("rm").description(e("remove.description")).action(async s=>{let n=C(),t=n.list(),r=n.getCurrent();if(!s){if(t.length===0){console.log(o.yellow(e("list.empty")));return}if(process.stdin.isTTY&&process.stdout.isTTY){let d=t.map(m=>{let l=m.name===r,p=(m.settingsConfig.env||{}).ANTHROPIC_MODEL||e("common.model_default"),y=l?` ${e("list.current_marker")}`:"";return{label:`${m.name}${y}`,hint:`${e("common.model")}: ${p}`,value:m.name}}),u=q({message:"",choices:d.map(m=>({name:m.value,message:m.label,hint:m.hint})),pointer:"\u25CF",styles:{em:m=>m,strong:m=>m}});try{s=await u.run()}catch{console.log(o.gray(e("common.cancelled")));return}}else{console.log(o.bold(`
|
|
28
|
+
${e("list.header")}
|
|
29
|
+
`)),t.forEach((m,l)=>{let f=m.name===r,p=f?o.green("\u25CF "):" ",y=f?o.green.bold(m.name):m.name,ae=(m.settingsConfig.env||{}).ANTHROPIC_MODEL||e("common.model_default");console.log(`${p}${o.gray(`${l+1}.`)} ${y}`),console.log(` ${e("common.model")}: ${o.cyan(ae)}`)}),console.log();let d=await _(e("list.choose_number"));if(!d)return;let u=parseInt(d,10)-1;if(isNaN(u)||u<0||u>=t.length){console.log(o.red(e("error.invalid_choice")));return}s=t[u].name}}let c=Re(s);if(c){if(console.log(o.yellow(e("alias.is_alias",{name:s,target:c}))),console.log(`
|
|
30
|
+
${e("alias.rm_which")}
|
|
31
|
+
`),console.log(` ${o.cyan("1)")} ${e("alias.rm_alias",{name:s})}`),console.log(` ${o.cyan("2)")} ${e("alias.rm_config",{target:c})}`),await _(e("alias.rm_choose"))==="1"){let d=w();delete d.aliases[s],O(d),console.log(o.green(e("alias.rm_done",{short:s})));return}s=c}let a=await K(n,s);!a||(await _(e("remove.confirm",{name:a.name}))).toLowerCase()!=="y"||(n.remove(a.name),console.log(o.green(e("remove.done",{name:a.name}))))});var $=h.command("alias").description(e("alias.description"));$.command("set <short> <name>").description(e("alias.set_description")).action((s,n)=>{let t=C();if(!t.get(n)){let c=t.list().map(i=>i.name),a=Ne(n,c);console.log(o.red(e("error.not_found",{name:n}))),a.length>0&&console.log(o.yellow(e("suggest.did_you_mean",{name:a.join(", ")})));return}let r=w();r.aliases=r.aliases||{},r.aliases[s]=n,O(r),console.log(o.green(e("alias.set_done",{short:o.bold(s),name:n})))});$.command("rm <short>").description(e("alias.rm_description")).action(s=>{let n=w();if(!n?.aliases?.[s]){console.log(o.red(e("alias.rm_not_found",{short:s})));return}delete n.aliases[s],O(n),console.log(o.green(e("alias.rm_done",{short:s})))});$.command("list").alias("ls").description(e("alias.list_description")).action(()=>{let n=w()?.aliases||{},t=Object.entries(n);if(t.length===0){console.log(o.yellow(e("alias.list_empty")));return}console.log(o.bold(`
|
|
32
|
+
${e("alias.list_header")}
|
|
33
|
+
`));for(let[r,c]of t)console.log(` ${o.cyan.bold(r)} \u2192 ${c}`);console.log()});$.action(()=>{$.commands.find(s=>s.name()==="list").parseAsync([])});var J=h.command("locale").description(e("locale.description"));J.command("set <lang>").description(e("locale.set_description")).action(s=>{if(s!=="zh"&&s!=="en"){console.log(o.red(e("locale.set_invalid",{locale:s})));return}ie(s)});var M=[{code:"zh",label:"\u4E2D\u6587"},{code:"en",label:"English"}],ie=s=>{let n=w();n.locale=s,O(n),fe(s),console.log(o.green(e("locale.set_done",{locale:s})))};J.command("list").alias("ls").description(e("locale.list_description")).action(async()=>{let n=w()?.locale||B();if(process.stdin.isTTY&&process.stdout.isTTY){let r=M.map(({code:i,label:g})=>{let u=i===n?` ${e("locale.list_current_marker")}`:"";return{label:`${i} - ${g}${u}`,value:i}}),c=r.findIndex(i=>i.value===n),a=q({message:"",choices:r.map(i=>({name:i.value,message:i.label})),initial:c>=0?c:0,pointer:"\u25CF",styles:{em:i=>i,strong:i=>i}});try{let i=await a.run();if(i===n)return;ie(i)}catch{console.log(o.gray(e("common.cancelled")));return}}else{console.log(o.bold(`
|
|
34
|
+
${e("locale.list_header")}
|
|
35
|
+
`)),M.forEach(({code:i,label:g},d)=>{let u=i===n,m=u?o.green("\u25CF "):" ",l=u?o.green.bold(`${i} - ${g}`):`${i} - ${g}`,f=u?o.gray(` ${e("locale.list_current_marker")}`):"";console.log(`${m}${o.gray(`${d+1}.`)} ${l}${f}`)}),console.log();let r=await _(e("locale.choose_number"));if(!r)return;let c=parseInt(r,10)-1;if(isNaN(c)||c<0||c>=M.length){console.log(o.red(e("error.invalid_choice")));return}let a=M[c].code;if(a===n)return;ie(a)}});J.action(()=>{J.commands.find(s=>s.name()==="list").parseAsync([])});h.parse();
|