cc-cast 1.3.7 → 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 CHANGED
@@ -1,1060 +1,35 @@
1
1
  #!/usr/bin/env node
2
- import { Command } from "commander";
3
- import chalk from "chalk";
4
- import { readRc, writeRc, getStore, isCcSwitchGuiRunning } from "./utils.js";
5
- import { ccSwitchExists } from "./store/cc-switch.js";
6
- import { readClaudeSettings, applyProfile } from "./claude.js";
7
- import { createInterface } from "readline";
8
- import { spawnSync } from "child_process";
9
- import { writeFileSync, readFileSync, unlinkSync, existsSync } from "fs";
10
- import { tmpdir, homedir } from "os";
11
- import { join, dirname } from "path";
12
- import { fileURLToPath } from "url";
13
- import { t, setLocale, getLocale } from "./i18n/index.js";
14
- import Enquirer from "enquirer";
15
- const Select = Enquirer.Select;
16
- function createSelect(options) {
17
- const prompt = new Select(options);
18
- prompt.prefix = async () => "";
19
- prompt.separator = async () => "";
20
- prompt.cancel = async function (err) {
21
- this.state.cancelled = true;
22
- this.state.submitted = true;
23
- this.clear(this.state.size);
24
- this.stdout.write("\u001b[?25h");
25
- if (typeof this.stop === "function")
26
- this.stop();
27
- this.emit("cancel", err);
28
- };
29
- prompt.choiceMessage = function (choice, i) {
30
- const hasColor = (s) => /\x1b\[\d+m/.test(String(s));
31
- let message = this.resolve(choice.message, this.state, choice, i);
32
- if (choice.role === "heading" && !hasColor(message)) {
33
- message = this.styles.strong(message);
34
- }
35
- if (this.index === i && !hasColor(message)) {
36
- message = this.styles.primary(message);
37
- }
38
- return this.resolve(message, this.state, choice, i);
39
- };
40
- return prompt;
41
- }
42
- const __dirname = dirname(fileURLToPath(import.meta.url));
43
- const packageJsonPath = join(__dirname, "..", "package.json");
44
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
45
- const program = new Command();
46
- program
47
- .name("ccc")
48
- .description(t("program.description"))
49
- .version(packageJson.version);
50
- // Helper: prompt user for input, optionally pre-filling the input field
51
- function ask(question, prefill) {
52
- const rl = createInterface({ input: process.stdin, output: process.stdout });
53
- return new Promise((resolve) => {
54
- rl.question(question, (answer) => {
55
- rl.close();
56
- resolve(answer.trim());
57
- });
58
- if (prefill) {
59
- rl.line = prefill;
60
- rl.cursor = prefill.length;
61
- rl._refreshLine();
62
- }
63
- });
64
- }
65
- // Helper: ensure store ready
66
- function ensureStore() {
67
- return getStore();
68
- }
69
- // Helper: print current active configuration
70
- function printCurrent() {
71
- const store = ensureStore();
72
- const currentName = store.getCurrent();
73
- if (!currentName) {
74
- console.log(chalk.yellow(t("current.none")));
75
- console.log(chalk.gray(`\n${t("current.settings_header")}`));
76
- const settings = readClaudeSettings();
77
- const env = (settings.env || {});
78
- console.log(formatEnv(env));
79
- return;
80
- }
81
- const profile = store.get(currentName);
82
- if (!profile) {
83
- console.log(chalk.yellow(t("current.not_exist", { name: currentName })));
84
- return;
85
- }
86
- console.log(`\n${t("current.header", { name: chalk.green.bold(profile.name) })}\n`);
87
- const env = (profile.settingsConfig.env || {});
88
- console.log(formatEnv(env));
89
- if (profile.settingsConfig.model) {
90
- console.log(` ${chalk.gray("model")}: ${profile.settingsConfig.model}`);
91
- }
92
- console.log();
93
- }
94
- // Helper: format env for display
95
- function formatEnv(env) {
96
- const lines = [];
97
- const order = [
98
- "ANTHROPIC_BASE_URL",
99
- "ANTHROPIC_MODEL",
100
- "ANTHROPIC_DEFAULT_OPUS_MODEL",
101
- "ANTHROPIC_DEFAULT_SONNET_MODEL",
102
- "ANTHROPIC_DEFAULT_HAIKU_MODEL",
103
- ];
104
- for (const key of order) {
105
- if (key in env) {
106
- lines.push(` ${chalk.gray(key)}: ${env[key]}`);
107
- }
108
- }
109
- // Show remaining keys (skip token for security)
110
- for (const [key, val] of Object.entries(env)) {
111
- if (!order.includes(key) && key !== "ANTHROPIC_AUTH_TOKEN") {
112
- lines.push(` ${chalk.gray(key)}: ${val}`);
113
- }
114
- }
115
- if ("ANTHROPIC_AUTH_TOKEN" in env) {
116
- const token = env["ANTHROPIC_AUTH_TOKEN"];
117
- const masked = token.slice(0, 8) + "..." + token.slice(-4);
118
- lines.push(` ${chalk.gray("ANTHROPIC_AUTH_TOKEN")}: ${masked}`);
119
- }
120
- return lines.join("\n");
121
- }
122
- // Helper: Levenshtein distance
123
- function levenshtein(a, b) {
124
- const la = a.length, lb = b.length;
125
- const dp = Array.from({ length: la + 1 }, (_, i) => Array.from({ length: lb + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)));
126
- for (let i = 1; i <= la; i++) {
127
- for (let j = 1; j <= lb; j++) {
128
- dp[i][j] = a[i - 1] === b[j - 1]
129
- ? dp[i - 1][j - 1]
130
- : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
131
- }
132
- }
133
- return dp[la][lb];
134
- }
135
- // Helper: find suggestions for a mistyped name
136
- function findSuggestions(input, names) {
137
- const lower = input.toLowerCase();
138
- // 1. exact case-insensitive match
139
- const exact = names.find((n) => n.toLowerCase() === lower);
140
- if (exact)
141
- return [exact];
142
- // 2. substring match (input is part of name, or name is part of input)
143
- const substring = names.filter((n) => n.toLowerCase().includes(lower) || lower.includes(n.toLowerCase()));
144
- if (substring.length > 0)
145
- return substring;
146
- // 3. Levenshtein distance <= 3
147
- const fuzzy = names
148
- .map((n) => ({ name: n, dist: levenshtein(lower, n.toLowerCase()) }))
149
- .filter((x) => x.dist <= 3)
150
- .sort((a, b) => a.dist - b.dist)
151
- .map((x) => x.name);
152
- return fuzzy;
153
- }
154
- // Helper: get alias target if exists
155
- function getAliasTarget(input) {
156
- const rc = readRc();
157
- return rc?.aliases?.[input];
158
- }
159
- // Helper: resolve name with alias conflict handling, returns profile or null
160
- async function resolveProfile(store, input) {
161
- const aliasTarget = getAliasTarget(input);
162
- const directProfile = store.get(input);
163
- // Both alias and config name exist → ask
164
- if (aliasTarget && directProfile && aliasTarget !== input) {
165
- console.log(chalk.yellow(t("alias.conflict", { name: input, target: aliasTarget })));
166
- console.log(` ${chalk.cyan("1)")} ${t("alias.conflict_alias", { target: aliasTarget })}`);
167
- console.log(` ${chalk.cyan("2)")} ${t("alias.conflict_config", { name: input })}`);
168
- const choice = await ask(t("alias.choose_conflict"));
169
- if (choice === "1") {
170
- const profile = store.get(aliasTarget);
171
- if (!profile) {
172
- console.log(chalk.red(t("error.alias_target_missing", { alias: input, target: aliasTarget })));
173
- return null;
174
- }
175
- return profile;
176
- }
177
- return directProfile;
178
- }
179
- // Alias exists → resolve
180
- if (aliasTarget) {
181
- const profile = store.get(aliasTarget);
182
- if (profile)
183
- return profile;
184
- console.log(chalk.red(t("error.alias_target_missing", { alias: input, target: aliasTarget })));
185
- return null;
186
- }
187
- // Direct match
188
- if (directProfile)
189
- return directProfile;
190
- // Fuzzy matching
191
- const allNames = store.list().map((p) => p.name);
192
- const suggestions = findSuggestions(input, allNames);
193
- console.log(chalk.red(t("error.not_found", { name: input })));
194
- if (suggestions.length === 1) {
195
- console.log(chalk.yellow(t("suggest.did_you_mean", { name: chalk.bold(suggestions[0]) })));
196
- }
197
- else if (suggestions.length > 1) {
198
- console.log(chalk.yellow(t("suggest.did_you_mean_header")));
199
- for (const s of suggestions) {
200
- console.log(` - ${chalk.bold(s)}`);
201
- }
202
- }
203
- else {
204
- console.log(chalk.gray(t("suggest.use_list")));
205
- }
206
- return null;
207
- }
208
- // cc-castinit
209
- program
210
- .command("init")
211
- .description(t("init.description"))
212
- .action(async () => {
213
- const rc = readRc();
214
- writeRc({ aliases: rc?.aliases, locale: rc?.locale });
215
- console.log(chalk.green(t("init.done")));
216
- if (ccSwitchExists()) {
217
- console.log(chalk.green(t("init.cc_switch_mode")));
218
- // If standalone config.json has profiles, offer to migrate them into cc-switch DB
219
- const { StandaloneStore } = await import("./store/standalone.js");
220
- const standaloneStore = new StandaloneStore();
221
- const standaloneProfiles = standaloneStore.list();
222
- if (standaloneProfiles.length > 0) {
223
- const migrate = await ask(t("init.cc_switch_migrate"));
224
- if (migrate.toLowerCase() !== "n") {
225
- const { CcSwitchStore } = await import("./store/cc-switch.js");
226
- const ccStore = new CcSwitchStore();
227
- const standaloneCurrent = standaloneStore.getCurrent();
228
- for (const profile of standaloneProfiles) {
229
- ccStore.save(profile.name, profile.settingsConfig);
230
- }
231
- if (standaloneCurrent) {
232
- ccStore.setCurrent(standaloneCurrent);
233
- }
234
- console.log(chalk.green(t("init.cc_switch_migrate_done", { count: String(standaloneProfiles.length) })));
235
- ccStore.close();
236
- }
237
- }
238
- }
239
- });
240
- // cc-castsync
241
- program
242
- .command("sync")
243
- .description(t("sync.description"))
244
- .action(async () => {
245
- if (!ccSwitchExists()) {
246
- console.log(chalk.red(t("sync.no_cc_switch")));
247
- return;
248
- }
249
- const { CcSwitchStore } = await import("./store/cc-switch.js");
250
- const { StandaloneStore } = await import("./store/standalone.js");
251
- const ccStore = new CcSwitchStore();
252
- const standaloneStore = new StandaloneStore();
253
- const profiles = ccStore.list();
254
- if (profiles.length === 0) {
255
- console.log(chalk.yellow(t("sync.empty")));
256
- ccStore.close();
257
- return;
258
- }
259
- for (const profile of profiles) {
260
- standaloneStore.save(profile.name, profile.settingsConfig);
261
- }
262
- const current = ccStore.getCurrent();
263
- if (current) {
264
- standaloneStore.setCurrent(current);
265
- }
266
- console.log(chalk.green(t("sync.done", { count: String(profiles.length) })));
267
- if (current) {
268
- console.log(chalk.gray(t("sync.current", { name: current })));
269
- }
270
- else {
271
- console.log(chalk.gray(t("sync.no_current")));
272
- }
273
- ccStore.close();
274
- });
275
- // cc-castclear
276
- program
277
- .command("clear")
278
- .description(t("clear.description"))
279
- .action(async () => {
280
- const confirm = await ask(t("clear.confirm"));
281
- if (confirm.toLowerCase() !== "y") {
282
- console.log(chalk.gray(t("clear.cancelled")));
283
- return;
284
- }
285
- const rcPath = join(homedir(), ".cc-cast", "rc.json");
286
- const configPath = join(homedir(), ".cc-cast", "config.json");
287
- if (existsSync(configPath)) {
288
- unlinkSync(configPath);
289
- console.log(chalk.green(t("clear.removed", { path: configPath })));
290
- }
291
- if (existsSync(rcPath)) {
292
- unlinkSync(rcPath);
293
- console.log(chalk.green(t("clear.removed", { path: rcPath })));
294
- }
295
- console.log(chalk.green(t("clear.done")));
296
- });
297
- // cc-castimport
298
- program
299
- .command("import [file]")
300
- .description(t("import.description"))
301
- .action(async (file) => {
302
- const store = ensureStore();
303
- let jsonContent;
304
- if (file) {
305
- // Read from file
306
- if (!existsSync(file)) {
307
- console.log(chalk.red(t("import.file_not_found", { file })));
308
- return;
309
- }
310
- jsonContent = readFileSync(file, "utf-8");
311
- }
312
- else {
313
- // Read from stdin
314
- console.log(chalk.gray(t("import.paste_hint")));
315
- const chunks = [];
316
- process.stdin.setEncoding("utf-8");
317
- for await (const chunk of process.stdin) {
318
- chunks.push(Buffer.from(chunk));
319
- }
320
- jsonContent = Buffer.concat(chunks).toString("utf-8");
321
- }
322
- let configs;
323
- try {
324
- configs = JSON.parse(jsonContent);
325
- }
326
- catch {
327
- console.log(chalk.red(t("import.json_parse_error")));
328
- return;
329
- }
330
- if (typeof configs !== "object" || configs === null || Object.keys(configs).length === 0) {
331
- console.log(chalk.red(t("import.invalid_format")));
332
- return;
333
- }
334
- let count = 0;
335
- for (const [name, settingsConfig] of Object.entries(configs)) {
336
- store.save(name, settingsConfig);
337
- count++;
338
- }
339
- console.log(chalk.green(t("import.done", { count: String(count) })));
340
- });
341
- // cc-castlist
342
- program
343
- .command("list")
344
- .alias("ls")
345
- .description(t("list.description"))
346
- .action(async () => {
347
- const store = ensureStore();
348
- const profiles = store.list();
349
- const current = store.getCurrent();
350
- if (profiles.length === 0) {
351
- console.log(chalk.yellow(t("list.empty")));
352
- return;
353
- }
354
- // Helper: apply selected profile
355
- const switchTo = (name) => {
356
- if (name === current)
357
- return;
358
- const profile = store.get(name);
359
- store.setCurrent(profile.name);
360
- console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
361
- if (isCcSwitchGuiRunning()) {
362
- console.log(chalk.yellow(t("use.cc_switch_running")));
363
- }
364
- else {
365
- applyProfile(profile.name, profile.settingsConfig);
366
- const env = (profile.settingsConfig.env || {});
367
- const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
368
- console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
369
- console.log(chalk.gray(` ${t("use.restart")}`));
370
- }
371
- };
372
- const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
373
- if (isInteractive) {
374
- const options = profiles.map((p) => {
375
- const isCurrent = p.name === current;
376
- const env = (p.settingsConfig.env || {});
377
- const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
378
- const baseUrl = env["ANTHROPIC_BASE_URL"] || "default";
379
- const tag = isCurrent ? ` ${t("list.current_marker")}` : "";
380
- return {
381
- label: `${p.name}${tag}`,
382
- hint: `${t("common.model")}: ${model} ${t("common.source")}: ${baseUrl}`,
383
- value: p.name,
384
- };
385
- });
386
- const initial = profiles.findIndex((p) => p.name === current);
387
- const prompt = createSelect({
388
- message: "",
389
- choices: options.map((o) => ({ name: o.value, message: o.label })),
390
- initial: initial >= 0 ? initial : 0,
391
- pointer: "●",
392
- styles: { em: (k) => k, strong: (k) => k },
393
- });
394
- try {
395
- const value = await prompt.run();
396
- switchTo(value);
397
- }
398
- catch {
399
- console.log(chalk.gray(t("common.cancelled")));
400
- return;
401
- }
402
- }
403
- else {
404
- // Fallback: numbered list + type to select
405
- console.log(chalk.bold(`\n${t("list.header")}\n`));
406
- profiles.forEach((p, i) => {
407
- const isCurrent = p.name === current;
408
- const marker = isCurrent ? chalk.green("● ") : " ";
409
- const name = isCurrent ? chalk.green.bold(p.name) : p.name;
410
- const env = (p.settingsConfig.env || {});
411
- const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
412
- const baseUrl = env["ANTHROPIC_BASE_URL"] || "default";
413
- console.log(`${marker}${chalk.gray(`${i + 1}.`)} ${name}`);
414
- console.log(` ${t("common.model")}: ${chalk.cyan(model)} ${t("common.source")}: ${chalk.gray(baseUrl)}`);
415
- });
416
- console.log();
417
- const input = await ask(t("list.choose_number"));
418
- if (!input)
419
- return;
420
- const idx = parseInt(input, 10) - 1;
421
- if (isNaN(idx) || idx < 0 || idx >= profiles.length) {
422
- console.log(chalk.red(t("error.invalid_choice")));
423
- return;
424
- }
425
- switchTo(profiles[idx].name);
426
- }
427
- });
428
- // cc-castcurrent
429
- program
430
- .command("current")
431
- .description(t("current.description"))
432
- .action(() => {
433
- printCurrent();
434
- });
435
- // cc-castuse [name]
436
- program
437
- .command("use [name]")
438
- .description(t("use.description"))
439
- .action(async (name) => {
440
- const store = ensureStore();
441
- if (!name) {
442
- // No argument: behave like `ls`
443
- await program.commands.find((c) => c.name() === "list").parseAsync([]);
444
- return;
445
- }
446
- const profile = await resolveProfile(store, name);
447
- if (!profile)
448
- return;
449
- store.setCurrent(profile.name);
450
- console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
451
- if (isCcSwitchGuiRunning()) {
452
- console.log(chalk.yellow(t("use.cc_switch_running")));
453
- }
454
- else {
455
- applyProfile(profile.name, profile.settingsConfig);
456
- const env = (profile.settingsConfig.env || {});
457
- const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
458
- console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
459
- console.log(chalk.gray(` ${t("use.restart")}`));
460
- }
461
- });
462
- // cc-castsave <name>
463
- program
464
- .command("save <name>")
465
- .description(t("save.description"))
466
- .action((name) => {
467
- const store = ensureStore();
468
- const existing = store.get(name);
469
- if (existing) {
470
- console.log(chalk.yellow(t("save.overwrite", { name })));
471
- }
472
- const settings = readClaudeSettings();
473
- const settingsConfig = {};
474
- if (settings.env)
475
- settingsConfig.env = settings.env;
476
- if (settings.model)
477
- settingsConfig.model = settings.model;
478
- if (settings.hooks)
479
- settingsConfig.hooks = settings.hooks;
480
- if (settings.statusLine)
481
- settingsConfig.statusLine = settings.statusLine;
482
- store.save(name, settingsConfig);
483
- store.setCurrent(name);
484
- console.log(chalk.green(t("save.done", { name })));
485
- });
486
- // Helper: open editor with content, return parsed JSON or null
487
- function openEditor(name, content) {
488
- const tmpFile = join(tmpdir(), `cc-cast-${name}-${Date.now()}.json`);
489
- writeFileSync(tmpFile, JSON.stringify(content, null, 2));
490
- const editor = process.env.EDITOR || "vi";
491
- const result = spawnSync(editor, [tmpFile], { stdio: "inherit" });
492
- let parsed = null;
493
- if (result.status === 0) {
494
- try {
495
- parsed = JSON.parse(readFileSync(tmpFile, "utf-8"));
496
- }
497
- catch {
498
- console.log(chalk.red(t("add.json_parse_error")));
499
- }
500
- }
501
- try {
502
- unlinkSync(tmpFile);
503
- }
504
- catch { /* ignore */ }
505
- return parsed;
506
- }
507
- // Helper: save and optionally switch after add
508
- async function saveAndSwitch(store, name, settingsConfig) {
509
- store.save(name, settingsConfig);
510
- console.log(chalk.green(t("add.done", { name })));
511
- const switchChoice = await ask(t("add.switch_confirm"));
512
- if (switchChoice.toLowerCase() !== "n") {
513
- store.setCurrent(name);
514
- console.log(chalk.green(t("use.done", { name: chalk.bold(name) })));
515
- if (isCcSwitchGuiRunning()) {
516
- console.log(chalk.yellow(t("use.cc_switch_running")));
517
- }
518
- else {
519
- applyProfile(name, settingsConfig);
520
- console.log(chalk.gray(` ${t("use.restart")}`));
521
- }
522
- }
523
- }
524
- const BUILTIN_BASE_URLS = {
525
- kimi: "https://api.moonshot.cn/v1",
526
- "kimi-coding": "https://api.kimi.com/coding/",
527
- openrouter: "https://openrouter.ai/api/v1",
528
- deepseek: "https://api.deepseek.com",
529
- zenmux: "https://zenmux.ai/api/anthropic",
530
- fusecode: "https://www.fusecode.cc",
531
- };
532
- function getKnownBaseUrl(name) {
533
- return BUILTIN_BASE_URLS[name.toLowerCase()];
534
- }
535
- // cc-castadd
536
- program
537
- .command("add")
538
- .alias("new")
539
- .description(t("add.description"))
540
- .action(async () => {
541
- const store = ensureStore();
542
- // 1. Ask name first
543
- const name = await ask(t("add.prompt_name"));
544
- if (!name) {
545
- console.log(chalk.red(t("add.name_required")));
546
- return;
547
- }
548
- // Check if exists
549
- const existing = store.get(name);
550
- if (existing) {
551
- const overwrite = await ask(t("add.already_exists", { name }));
552
- if (overwrite.toLowerCase() !== "y") {
553
- console.log(chalk.gray(t("add.cancelled")));
554
- return;
555
- }
556
- }
557
- // 2. Choose mode
558
- console.log(`\n${chalk.bold(t("add.mode_select"))}\n`);
559
- console.log(` ${chalk.cyan("1)")} ${t("add.mode_interactive")}`);
560
- console.log(` ${chalk.cyan("2)")} ${t("add.mode_json")}\n`);
561
- const mode = await ask(t("add.mode_choose"));
562
- if (mode === "2") {
563
- // JSON mode: open editor with template
564
- const template = {
565
- env: {
566
- ANTHROPIC_BASE_URL: getKnownBaseUrl(name) ?? "",
567
- ANTHROPIC_AUTH_TOKEN: "",
568
- ANTHROPIC_MODEL: "",
569
- ANTHROPIC_DEFAULT_OPUS_MODEL: "",
570
- ANTHROPIC_DEFAULT_SONNET_MODEL: "",
571
- ANTHROPIC_DEFAULT_HAIKU_MODEL: "",
572
- },
573
- };
574
- console.log(chalk.gray(t("add.json_template_hint")));
575
- const edited = openEditor(name, template);
576
- if (!edited)
577
- return;
578
- await saveAndSwitch(store, name, edited);
579
- return;
580
- }
581
- // Interactive mode with step-based back support
582
- const defaultBaseUrl = getKnownBaseUrl(name);
583
- const steps = [
584
- { key: "ANTHROPIC_BASE_URL", prompt: t("add.prompt_base_url"), required: true, defaultValue: defaultBaseUrl },
585
- { key: "ANTHROPIC_AUTH_TOKEN", prompt: t("add.prompt_auth_token"), required: true },
586
- { key: "ANTHROPIC_MODEL", prompt: t("add.prompt_model"), required: false },
587
- { key: "ANTHROPIC_DEFAULT_OPUS_MODEL", prompt: t("add.prompt_default_opus"), required: false },
588
- { key: "ANTHROPIC_DEFAULT_SONNET_MODEL", prompt: t("add.prompt_default_sonnet"), required: false },
589
- { key: "ANTHROPIC_DEFAULT_HAIKU_MODEL", prompt: t("add.prompt_default_haiku"), required: false },
590
- ];
591
- console.log(chalk.gray(t("add.back_hint")));
592
- const values = {};
593
- let i = 0;
594
- while (i < steps.length) {
595
- const step = steps[i];
596
- const promptText = step.defaultValue
597
- ? `${step.prompt}(${chalk.gray(step.defaultValue)}): `
598
- : step.prompt;
599
- const input = await ask(promptText, step.defaultValue);
600
- if (input === "<") {
601
- if (i > 0)
602
- i--;
603
- continue;
604
- }
605
- const value = input || step.defaultValue || "";
606
- if (step.required && !value) {
607
- console.log(chalk.red(t("add.field_required", { field: step.key })));
608
- continue;
609
- }
610
- if (value)
611
- values[step.key] = value;
612
- else
613
- delete values[step.key];
614
- i++;
615
- }
616
- // Build config
617
- const env = {};
618
- for (const [k, v] of Object.entries(values)) {
619
- env[k] = v;
620
- }
621
- let settingsConfig = { env };
622
- // Preview + optional edit
623
- console.log(`\n${chalk.bold(t("add.preview_header"))}\n`);
624
- console.log(JSON.stringify(settingsConfig, null, 2));
625
- console.log();
626
- const editChoice = await ask(t("add.edit_confirm"));
627
- if (editChoice.toLowerCase() === "y") {
628
- const edited = openEditor(name, settingsConfig);
629
- if (edited)
630
- settingsConfig = edited;
631
- }
632
- await saveAndSwitch(store, name, settingsConfig);
633
- });
634
- // cc-castshow [name]
635
- program
636
- .command("show [name]")
637
- .description(t("show.description"))
638
- .action(async (name) => {
639
- const store = ensureStore();
640
- if (!name) {
641
- // Show all configurations
642
- const profiles = store.list();
643
- if (profiles.length === 0) {
644
- console.log(chalk.yellow(t("list.empty")));
645
- return;
646
- }
647
- console.log(chalk.bold(`\n${t("show.all_header")}\n`));
648
- const allConfigs = {};
649
- for (const profile of profiles) {
650
- allConfigs[profile.name] = profile.settingsConfig;
651
- }
652
- console.log(JSON.stringify(allConfigs, null, 2));
653
- return;
654
- }
655
- const profile = await resolveProfile(store, name);
656
- if (!profile)
657
- return;
658
- console.log(`\n${chalk.bold(profile.name)}\n`);
659
- const env = (profile.settingsConfig.env || {});
660
- console.log(formatEnv(env));
661
- if (profile.settingsConfig.model) {
662
- console.log(` ${chalk.gray("model")}: ${profile.settingsConfig.model}`);
663
- }
664
- console.log();
665
- });
666
- // cc-castmodify [name]
667
- program
668
- .command("modify [name]")
669
- .alias("edit")
670
- .description(t("modify.description"))
671
- .action(async (name) => {
672
- const store = ensureStore();
673
- const profiles = store.list();
674
- const current = store.getCurrent();
675
- // 1. Select profile
676
- if (!name) {
677
- if (profiles.length === 0) {
678
- console.log(chalk.yellow(t("list.empty")));
679
- return;
680
- }
681
- const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
682
- if (isInteractive) {
683
- const options = profiles.map((p) => {
684
- const isCurrent = p.name === current;
685
- const env = (p.settingsConfig.env || {});
686
- const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
687
- const tag = isCurrent ? ` ${t("list.current_marker")}` : "";
688
- return {
689
- label: `${p.name}${tag}`,
690
- hint: `${t("common.model")}: ${model}`,
691
- value: p.name,
692
- };
693
- });
694
- const prompt = createSelect({
695
- message: "",
696
- choices: options.map((o) => ({ name: o.value, message: o.label, hint: o.hint })),
697
- pointer: "●",
698
- styles: { em: (k) => k, strong: (k) => k },
699
- });
700
- try {
701
- name = await prompt.run();
702
- }
703
- catch {
704
- console.log(chalk.gray(t("common.cancelled")));
705
- return;
706
- }
707
- }
708
- else {
709
- console.log(chalk.bold(`\n${t("list.header")}\n`));
710
- profiles.forEach((p, i) => {
711
- const isCurrent = p.name === current;
712
- const marker = isCurrent ? chalk.green("● ") : " ";
713
- const label = isCurrent ? chalk.green.bold(p.name) : p.name;
714
- const env = (p.settingsConfig.env || {});
715
- const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
716
- console.log(`${marker}${chalk.gray(`${i + 1}.`)} ${label}`);
717
- console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
718
- });
719
- console.log();
720
- const input = await ask(t("list.choose_number"));
721
- if (!input)
722
- return;
723
- const idx = parseInt(input, 10) - 1;
724
- if (isNaN(idx) || idx < 0 || idx >= profiles.length) {
725
- console.log(chalk.red(t("error.invalid_choice")));
726
- return;
727
- }
728
- name = profiles[idx].name;
729
- }
730
- }
731
- const profile = await resolveProfile(store, name);
732
- if (!profile)
733
- return;
734
- const currentEnv = (profile.settingsConfig.env || {});
735
- // 2. Choose mode
736
- console.log(`\n${chalk.bold(t("add.mode_select"))}\n`);
737
- console.log(` ${chalk.cyan("1)")} ${t("add.mode_interactive")}`);
738
- console.log(` ${chalk.cyan("2)")} ${t("add.mode_json")}\n`);
739
- const mode = await ask(t("add.mode_choose"));
740
- let settingsConfig;
741
- if (mode === "2") {
742
- // JSON mode
743
- const edited = openEditor(profile.name, profile.settingsConfig);
744
- if (!edited)
745
- return;
746
- settingsConfig = edited;
747
- }
748
- else {
749
- const steps = [
750
- { key: "ANTHROPIC_BASE_URL", prompt: "ANTHROPIC_BASE_URL", required: true },
751
- { key: "ANTHROPIC_AUTH_TOKEN", prompt: "ANTHROPIC_AUTH_TOKEN", required: true },
752
- { key: "ANTHROPIC_MODEL", prompt: "ANTHROPIC_MODEL", required: false },
753
- { key: "ANTHROPIC_DEFAULT_OPUS_MODEL", prompt: "ANTHROPIC_DEFAULT_OPUS_MODEL", required: false },
754
- { key: "ANTHROPIC_DEFAULT_SONNET_MODEL", prompt: "ANTHROPIC_DEFAULT_SONNET_MODEL", required: false },
755
- { key: "ANTHROPIC_DEFAULT_HAIKU_MODEL", prompt: "ANTHROPIC_DEFAULT_HAIKU_MODEL", required: false },
756
- ];
757
- console.log(chalk.gray(t("add.back_hint")));
758
- const values = { ...currentEnv };
759
- let i = 0;
760
- while (i < steps.length) {
761
- const step = steps[i];
762
- const cur = currentEnv[step.key]
763
- || (step.key === "ANTHROPIC_BASE_URL" ? (getKnownBaseUrl(profile.name) ?? "") : "");
764
- const hint = cur ? `(${chalk.gray(cur)})` : "";
765
- const input = await ask(`${step.prompt}${hint}: `, cur || undefined);
766
- if (input === "<") {
767
- if (i > 0)
768
- i--;
769
- continue;
770
- }
771
- if (input) {
772
- values[step.key] = input;
773
- }
774
- else if (step.required && !cur) {
775
- console.log(chalk.red(t("add.field_required", { field: step.key })));
776
- continue;
777
- }
778
- // empty input + has current value → keep current (already in values)
779
- i++;
780
- }
781
- const env = {};
782
- for (const [k, v] of Object.entries(values)) {
783
- if (v)
784
- env[k] = v;
785
- }
786
- settingsConfig = { ...profile.settingsConfig, env };
787
- }
788
- // 3. Preview
789
- console.log(`\n${chalk.bold(t("add.preview_header"))}\n`);
790
- console.log(JSON.stringify(settingsConfig, null, 2));
791
- console.log();
792
- // 4. Optional editor (only for step mode)
793
- if (mode !== "2") {
794
- const editChoice = await ask(t("add.edit_confirm"));
795
- if (editChoice.toLowerCase() === "y") {
796
- const edited = openEditor(profile.name, settingsConfig);
797
- if (edited)
798
- settingsConfig = edited;
799
- }
800
- }
801
- // 5. Save
802
- store.save(profile.name, settingsConfig);
803
- console.log(chalk.green(t("modify.done", { name: profile.name })));
804
- // 6. Switch if not current
805
- if (profile.name !== current) {
806
- const switchChoice = await ask(t("add.switch_confirm"));
807
- if (switchChoice.toLowerCase() !== "n") {
808
- store.setCurrent(profile.name);
809
- console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
810
- if (isCcSwitchGuiRunning()) {
811
- console.log(chalk.yellow(t("use.cc_switch_running")));
812
- }
813
- else {
814
- applyProfile(profile.name, settingsConfig);
815
- console.log(chalk.gray(` ${t("use.restart")}`));
816
- }
817
- }
818
- }
819
- else {
820
- applyProfile(profile.name, settingsConfig);
821
- console.log(chalk.gray(` ${t("use.restart")}`));
822
- }
823
- });
824
- // cc-castremove [name]
825
- program
826
- .command("remove [name]")
827
- .alias("rm")
828
- .description(t("remove.description"))
829
- .action(async (name) => {
830
- const store = ensureStore();
831
- const profiles = store.list();
832
- const current = store.getCurrent();
833
- if (!name) {
834
- if (profiles.length === 0) {
835
- console.log(chalk.yellow(t("list.empty")));
836
- return;
837
- }
838
- const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
839
- if (isInteractive) {
840
- const options = profiles.map((p) => {
841
- const isCurrent = p.name === current;
842
- const env = (p.settingsConfig.env || {});
843
- const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
844
- const tag = isCurrent ? ` ${t("list.current_marker")}` : "";
845
- return {
846
- label: `${p.name}${tag}`,
847
- hint: `${t("common.model")}: ${model}`,
848
- value: p.name,
849
- };
850
- });
851
- const prompt = createSelect({
852
- message: "",
853
- choices: options.map((o) => ({ name: o.value, message: o.label, hint: o.hint })),
854
- pointer: "●",
855
- styles: { em: (k) => k, strong: (k) => k },
856
- });
857
- try {
858
- name = await prompt.run();
859
- }
860
- catch {
861
- console.log(chalk.gray(t("common.cancelled")));
862
- return;
863
- }
864
- }
865
- else {
866
- console.log(chalk.bold(`\n${t("list.header")}\n`));
867
- profiles.forEach((p, i) => {
868
- const isCurrent = p.name === current;
869
- const marker = isCurrent ? chalk.green("● ") : " ";
870
- const label = isCurrent ? chalk.green.bold(p.name) : p.name;
871
- const env = (p.settingsConfig.env || {});
872
- const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
873
- console.log(`${marker}${chalk.gray(`${i + 1}.`)} ${label}`);
874
- console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
875
- });
876
- console.log();
877
- const input = await ask(t("list.choose_number"));
878
- if (!input)
879
- return;
880
- const idx = parseInt(input, 10) - 1;
881
- if (isNaN(idx) || idx < 0 || idx >= profiles.length) {
882
- console.log(chalk.red(t("error.invalid_choice")));
883
- return;
884
- }
885
- name = profiles[idx].name;
886
- }
887
- }
888
- // Check if name is an alias
889
- const aliasTarget = getAliasTarget(name);
890
- if (aliasTarget) {
891
- console.log(chalk.yellow(t("alias.is_alias", { name, target: aliasTarget })));
892
- console.log(`\n${t("alias.rm_which")}\n`);
893
- console.log(` ${chalk.cyan("1)")} ${t("alias.rm_alias", { name })}`);
894
- console.log(` ${chalk.cyan("2)")} ${t("alias.rm_config", { target: aliasTarget })}`);
895
- const choice = await ask(t("alias.rm_choose"));
896
- if (choice === "1") {
897
- const rc = readRc();
898
- delete rc.aliases[name];
899
- writeRc(rc);
900
- console.log(chalk.green(t("alias.rm_done", { short: name })));
901
- return;
902
- }
903
- // choice === "2" → delete the config
904
- name = aliasTarget;
905
- }
906
- const profile = await resolveProfile(store, name);
907
- if (!profile)
908
- return;
909
- const confirm = await ask(t("remove.confirm", { name: profile.name }));
910
- if (confirm.toLowerCase() !== "y")
911
- return;
912
- store.remove(profile.name);
913
- console.log(chalk.green(t("remove.done", { name: profile.name })));
914
- });
915
- // cc-castalias
916
- const aliasCmd = program
917
- .command("alias")
918
- .description(t("alias.description"));
919
- aliasCmd
920
- .command("set <short> <name>")
921
- .description(t("alias.set_description"))
922
- .action((short, name) => {
923
- const store = ensureStore();
924
- if (!store.get(name)) {
925
- const allNames = store.list().map((p) => p.name);
926
- const suggestions = findSuggestions(name, allNames);
927
- console.log(chalk.red(t("error.not_found", { name })));
928
- if (suggestions.length > 0) {
929
- console.log(chalk.yellow(t("suggest.did_you_mean", { name: suggestions.join(", ") })));
930
- }
931
- return;
932
- }
933
- const rc = readRc();
934
- rc.aliases = rc.aliases || {};
935
- rc.aliases[short] = name;
936
- writeRc(rc);
937
- console.log(chalk.green(t("alias.set_done", { short: chalk.bold(short), name })));
938
- });
939
- aliasCmd
940
- .command("rm <short>")
941
- .description(t("alias.rm_description"))
942
- .action((short) => {
943
- const rc = readRc();
944
- if (!rc?.aliases?.[short]) {
945
- console.log(chalk.red(t("alias.rm_not_found", { short })));
946
- return;
947
- }
948
- delete rc.aliases[short];
949
- writeRc(rc);
950
- console.log(chalk.green(t("alias.rm_done", { short })));
951
- });
952
- aliasCmd
953
- .command("list")
954
- .alias("ls")
955
- .description(t("alias.list_description"))
956
- .action(() => {
957
- const rc = readRc();
958
- const aliases = rc?.aliases || {};
959
- const entries = Object.entries(aliases);
960
- if (entries.length === 0) {
961
- console.log(chalk.yellow(t("alias.list_empty")));
962
- return;
963
- }
964
- console.log(chalk.bold(`\n${t("alias.list_header")}\n`));
965
- for (const [short, name] of entries) {
966
- console.log(` ${chalk.cyan.bold(short)} → ${name}`);
967
- }
968
- console.log();
969
- });
970
- // Default: cc-cast alias (no subcommand) → show list
971
- aliasCmd.action(() => {
972
- aliasCmd.commands.find((c) => c.name() === "list").parseAsync([]);
973
- });
974
- // cc-castlocale
975
- const localeCmd = program
976
- .command("locale")
977
- .description(t("locale.description"));
978
- localeCmd
979
- .command("set <lang>")
980
- .description(t("locale.set_description"))
981
- .action((lang) => {
982
- if (lang !== "zh" && lang !== "en") {
983
- console.log(chalk.red(t("locale.set_invalid", { locale: lang })));
984
- return;
985
- }
986
- switchLocale(lang);
987
- });
988
- const SUPPORTED_LOCALES = [
989
- { code: "zh", label: "中文" },
990
- { code: "en", label: "English" },
991
- ];
992
- const switchLocale = (code) => {
993
- const rc = readRc();
994
- rc.locale = code;
995
- writeRc(rc);
996
- setLocale(code);
997
- console.log(chalk.green(t("locale.set_done", { locale: code })));
998
- };
999
- localeCmd
1000
- .command("list")
1001
- .alias("ls")
1002
- .description(t("locale.list_description"))
1003
- .action(async () => {
1004
- const rc = readRc();
1005
- const current = rc?.locale || getLocale();
1006
- const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
1007
- if (isInteractive) {
1008
- const options = SUPPORTED_LOCALES.map(({ code, label }) => {
1009
- const isCurrent = code === current;
1010
- const tag = isCurrent ? ` ${t("locale.list_current_marker")}` : "";
1011
- return { label: `${code} - ${label}${tag}`, value: code };
1012
- });
1013
- const initialIdx = options.findIndex((o) => o.value === current);
1014
- const prompt = createSelect({
1015
- message: "",
1016
- choices: options.map((o) => ({ name: o.value, message: o.label })),
1017
- initial: initialIdx >= 0 ? initialIdx : 0,
1018
- pointer: "●",
1019
- styles: { em: (k) => k, strong: (k) => k },
1020
- });
1021
- try {
1022
- const value = await prompt.run();
1023
- if (value === current)
1024
- return;
1025
- switchLocale(value);
1026
- }
1027
- catch {
1028
- console.log(chalk.gray(t("common.cancelled")));
1029
- return;
1030
- }
1031
- }
1032
- else {
1033
- console.log(chalk.bold(`\n${t("locale.list_header")}\n`));
1034
- SUPPORTED_LOCALES.forEach(({ code, label }, i) => {
1035
- const isCurrent = code === current;
1036
- const marker = isCurrent ? chalk.green("● ") : " ";
1037
- const name = isCurrent ? chalk.green.bold(`${code} - ${label}`) : `${code} - ${label}`;
1038
- const tag = isCurrent ? chalk.gray(` ${t("locale.list_current_marker")}`) : "";
1039
- console.log(`${marker}${chalk.gray(`${i + 1}.`)} ${name}${tag}`);
1040
- });
1041
- console.log();
1042
- const input = await ask(t("locale.choose_number"));
1043
- if (!input)
1044
- return;
1045
- const idx = parseInt(input, 10) - 1;
1046
- if (isNaN(idx) || idx < 0 || idx >= SUPPORTED_LOCALES.length) {
1047
- console.log(chalk.red(t("error.invalid_choice")));
1048
- return;
1049
- }
1050
- const selected = SUPPORTED_LOCALES[idx].code;
1051
- if (selected === current)
1052
- return;
1053
- switchLocale(selected);
1054
- }
1055
- });
1056
- // Default: cc-cast locale (no subcommand) → show list
1057
- localeCmd.action(() => {
1058
- localeCmd.commands.find((c) => c.name() === "list").parseAsync([]);
1059
- });
1060
- 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();