cc-cast 1.3.9 → 1.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/assets/icon.png +0 -0
- package/dist/i18n/zh.d.ts +2 -1
- package/dist/index.js +33 -32
- package/dist/utils.d.ts +2 -0
- package/package.json +1 -1
- package/src/claude.ts +51 -3
- package/src/i18n/en.ts +2 -1
- package/src/i18n/zh.ts +2 -1
- package/src/index.ts +44 -32
- package/src/utils.ts +39 -0
package/README.md
CHANGED
package/README.zh-CN.md
CHANGED
package/assets/icon.png
ADDED
|
Binary file
|
package/dist/i18n/zh.d.ts
CHANGED
|
@@ -31,7 +31,8 @@ declare const zh: {
|
|
|
31
31
|
readonly "use.description": "切换到指定配置方案";
|
|
32
32
|
readonly "use.done": "✓ 已切换到 {name}";
|
|
33
33
|
readonly "use.restart": "重启 Claude Code 生效";
|
|
34
|
-
readonly "use.
|
|
34
|
+
readonly "use.cc_switch_restarting": "检测到 cc-switch GUI,正在重启以同步配置...";
|
|
35
|
+
readonly "use.cc_switch_relaunch_manual": "无法自动重启 cc-switch,请手动打开。";
|
|
35
36
|
readonly "save.description": "从当前 settings.json 保存为新配置";
|
|
36
37
|
readonly "save.overwrite": "配置 \"{name}\" 已存在,将覆盖";
|
|
37
38
|
readonly "save.done": "✓ 已保存当前配置为 \"{name}\"";
|
package/dist/index.js
CHANGED
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
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 (
|
|
2
|
+
var He=Object.defineProperty;var O=(o,e)=>()=>(o&&(e=o(o=0)),e);var ue=(o,e)=>{for(var t in e)He(o,t,{get:e[t],enumerable:!0})};var Ue,me,fe=O(()=>{"use strict";Ue={"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_restarting":"\u68C0\u6D4B\u5230 cc-switch GUI\uFF0C\u6B63\u5728\u91CD\u542F\u4EE5\u540C\u6B65\u914D\u7F6E...","use.cc_switch_relaunch_manual":"\u65E0\u6CD5\u81EA\u52A8\u91CD\u542F cc-switch\uFF0C\u8BF7\u624B\u52A8\u6253\u5F00\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}"},me=Ue});var xe,pe,_e=O(()=>{"use strict";xe={"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_restarting":"cc-switch GUI detected, restarting to sync config...","use.cc_switch_relaunch_manual":"Could not auto-restart cc-switch. Please reopen it manually.","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}"},pe=xe});function Me(){let o=w();return o?.locale&&o.locale in B?o.locale:((process.env.LC_ALL||process.env.LANG||"").startsWith("en"),"en")}function W(){return P||(P=Me()),P}function he(o){P=o}function n(o,e){let t=W(),s=B[t][o]??B.en[o]??o;if(e)for(let[c,a]of Object.entries(e))s=s.replace(new RegExp(`\\{${c}\\}`,"g"),a);return s}var B,P,D=O(()=>{"use strict";fe();_e();Y();B={zh:me,en:pe}});var Q={};ue(Q,{StandaloneStore:()=>A});import{homedir as je}from"os";import{join as ye}from"path";import{existsSync as we,readFileSync as Fe,writeFileSync as Je,mkdirSync as ze}from"fs";function qe(){we(V)||ze(V,{recursive:!0})}function T(){return we(Z)?JSON.parse(Fe(Z,"utf-8")):{profiles:{}}}function G(o){qe(),Je(Z,JSON.stringify(o,null,2))}var V,Z,A,H=O(()=>{"use strict";D();V=ye(je(),".cc-cast"),Z=ye(V,"config.json");A=class{list(){let e=T();return Object.entries(e.profiles).map(([t,s])=>({id:t,name:t,settingsConfig:s}))}get(e){let s=T().profiles[e];if(s)return{id:e,name:e,settingsConfig:s}}save(e,t){let s=T();s.profiles[e]=t,G(s)}remove(e){let t=T();return e in t.profiles?(delete t.profiles[e],t.current===e&&(t.current=void 0),G(t),!0):!1}getCurrent(){return T().current}setCurrent(e){let t=T();if(!(e in t.profiles))throw new Error(n("error.not_found",{name:e}));t.current=e,G(t)}}});var X={};ue(X,{CcSwitchStore:()=>b,ccSwitchExists:()=>R});import Ke from"better-sqlite3";import{homedir as ve}from"os";import{join as Se}from"path";import{existsSync as U,readFileSync as Ce,writeFileSync as Be}from"fs";function R(){return U(x)}var x,L,b,$=O(()=>{"use strict";D();x=Se(ve(),".cc-switch","cc-switch.db"),L=Se(ve(),".cc-switch","settings.json");b=class{db;constructor(){if(!U(x))throw new Error(n("store.db_not_found",{path:x}));this.db=new Ke(x)}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(e){let t=this.db.prepare("SELECT id, name, settings_config FROM providers WHERE app_type = 'claude' AND name = ?").get(e);if(t)return{id:t.id,name:t.name,settingsConfig:JSON.parse(t.settings_config)}}save(e,t){if(this.get(e))this.db.prepare("UPDATE providers SET settings_config = ? WHERE app_type = 'claude' AND name = ?").run(JSON.stringify(t),e);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
3
|
id, app_type, name, settings_config, website_url, category,
|
|
4
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,
|
|
6
|
-
|
|
7
|
-
${
|
|
8
|
-
|
|
9
|
-
`)
|
|
10
|
-
${e("list.
|
|
11
|
-
|
|
12
|
-
${o.bold(e("add.
|
|
13
|
-
|
|
14
|
-
`),
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
${e("list.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
`)
|
|
26
|
-
${
|
|
27
|
-
|
|
28
|
-
${e("list.
|
|
29
|
-
|
|
30
|
-
${
|
|
31
|
-
|
|
32
|
-
${e("alias.
|
|
33
|
-
|
|
34
|
-
${e("locale.
|
|
35
|
-
|
|
5
|
+
) VALUES (?, 'claude', ?, ?, NULL, NULL, ?, ?, NULL, NULL, NULL, '{}', 0, 0)`).run(i,e,JSON.stringify(t),Date.now(),a)}}remove(e){return this.db.prepare("DELETE FROM providers WHERE app_type = 'claude' AND name = ?").run(e).changes>0}getCurrent(){let e=this.db.prepare("SELECT name FROM providers WHERE app_type = 'claude' AND is_current = 1 LIMIT 1").get();if(e)return e.name;if(U(L))try{let s=JSON.parse(Ce(L,"utf-8")).currentProviderClaude;return s?this.db.prepare("SELECT name FROM providers WHERE app_type = 'claude' AND id = ?").get(s)?.name:void 0}catch{return}}setCurrent(e){let t=this.get(e);if(!t)throw new Error(n("error.not_found",{name:e}));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=U(L)?JSON.parse(Ce(L,"utf-8")):{};c.currentProviderClaude=t.id,Be(L,JSON.stringify(c,null,2))}close(){this.db.close()}}});import{homedir as We}from"os";import{join as Oe}from"path";import{existsSync as Te,readFileSync as Ye,writeFileSync as Ge,mkdirSync as Ve}from"fs";import{spawnSync as E}from"child_process";function w(){if(!Te(ne))return S({}),{};try{return JSON.parse(Ye(ne,"utf-8"))}catch{return S({}),{}}}function S(o){Te(ee)||Ve(ee,{recursive:!0}),Ge(ne,JSON.stringify(o,null,2))}function Re(){return R()?new b:new A}function Ee(){try{let o=E("pgrep",["-f","cc-switch"],{encoding:"utf-8"});return o.status===0&&(o.stdout?.trim().length??0)>0}catch{return!1}}function Ne(){try{let o=null;if(process.platform==="darwin"){let e=E("pgrep",["-f","cc-switch"],{encoding:"utf-8"});if(e.status===0){let t=e.stdout.trim().split(`
|
|
6
|
+
`);for(let s of t){let i=E("ps",["-p",s,"-o","args="],{encoding:"utf-8"}).stdout.trim().match(/^(.+?\.app)\b/);if(i){o=i[1];break}}}}return E("pkill",["-f","cc-switch"]),E("sleep",["0.5"]),o}catch{return null}}function Ae(o){try{E("open",["-g",o],{encoding:"utf-8"})}catch{}}var ee,ne,Y=O(()=>{"use strict";H();$();ee=Oe(We(),".cc-cast"),ne=Oe(ee,"rc.json")});Y();$();import{Command as on}from"commander";import r from"chalk";import{homedir as Ze}from"os";import{join as Qe}from"path";import{existsSync as te,readFileSync as Xe,writeFileSync as en,renameSync as nn,unlinkSync as Le}from"fs";var N=Qe(Ze(),".claude","settings.json");function M(){return te(N)?JSON.parse(Xe(N,"utf-8")):{}}function oe(o){if(o===null||typeof o!="object")return o;if(Array.isArray(o))return o.map(oe);let e={},t=Object.keys(o).sort();for(let s of t)e[s]=oe(o[s]);return e}function tn(o){let e={...o};return delete e.currentProviderClaude,delete e.api_format,delete e.apiFormat,delete e.openrouter_compat_mode,delete e.openrouterCompatMode,e}function re(o,e){let t=M(),s={},c=["language","permissions"];for(let l of c)l in t&&(s[l]=t[l]);let a={...t,...s,...e};a=tn(a);let i=oe(a),d=`${N}.tmp.${Date.now()}`;try{en(d,JSON.stringify(i,null,2)),process.platform==="win32"&&te(N)&&Le(N),nn(d,N)}catch(l){if(te(d))try{Le(d)}catch{}throw l}}D();import{createInterface as rn}from"readline";import{spawnSync as sn}from"child_process";import{writeFileSync as cn,readFileSync as de,unlinkSync as se,existsSync as ie}from"fs";import{tmpdir as an,homedir as be}from"os";import{join as F,dirname as ln}from"path";import{fileURLToPath as dn}from"url";import gn from"enquirer";import un from"update-notifier";var mn=gn.Select;function q(o){let e=new mn(o);return e.prefix=async()=>"",e.separator=async()=>"",e.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)},e.choiceMessage=function(t,s){let c=i=>/\x1b\[\d+m/.test(String(i)),a=this.resolve(t.message,this.state,t,s);return t.role==="heading"&&!c(a)&&(a=this.styles.strong(a)),this.index===s&&!c(a)&&(a=this.styles.primary(a)),this.resolve(a,this.state,t,s)},e}var fn=ln(dn(import.meta.url)),pn=F(fn,"..","package.json"),ke=JSON.parse(de(pn,"utf-8")),_n=un({pkg:ke,updateCheckInterval:1e3*60*60*24});_n.notify({isGlobal:!0,defer:!0});var h=new on;h.name("ccc").description(n("program.description")).version(ke.version);function _(o,e){let t=rn({input:process.stdin,output:process.stdout});return new Promise(s=>{t.question(o,c=>{t.close(),s(c.trim())}),e&&(t.line=e,t.cursor=e.length,t._refreshLine())})}function C(){return Re()}function k(o,e){if(Ee()){console.log(r.gray(n("use.cc_switch_restarting")));let t=Ne();re(o,e),t?Ae(t):console.log(r.yellow(n("use.cc_switch_relaunch_manual")))}else re(o,e)}function hn(){let o=C(),e=o.getCurrent();if(!e){console.log(r.yellow(n("current.none"))),console.log(r.gray(`
|
|
7
|
+
${n("current.settings_header")}`));let a=M().env||{};console.log(ce(a));return}let t=o.get(e);if(!t){console.log(r.yellow(n("current.not_exist",{name:e})));return}console.log(`
|
|
8
|
+
${n("current.header",{name:r.green.bold(t.name)})}
|
|
9
|
+
`);let s=t.settingsConfig.env||{};console.log(ce(s)),t.settingsConfig.model&&console.log(` ${r.gray("model")}: ${t.settingsConfig.model}`),console.log()}function ce(o){let e=[],t=["ANTHROPIC_BASE_URL","ANTHROPIC_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL"];for(let s of t)s in o&&e.push(` ${r.gray(s)}: ${o[s]}`);for(let[s,c]of Object.entries(o))!t.includes(s)&&s!=="ANTHROPIC_AUTH_TOKEN"&&e.push(` ${r.gray(s)}: ${c}`);if("ANTHROPIC_AUTH_TOKEN"in o){let s=o.ANTHROPIC_AUTH_TOKEN,c=s.slice(0,8)+"..."+s.slice(-4);e.push(` ${r.gray("ANTHROPIC_AUTH_TOKEN")}: ${c}`)}return e.join(`
|
|
10
|
+
`)}function yn(o,e){let t=o.length,s=e.length,c=Array.from({length:t+1},(a,i)=>Array.from({length:s+1},(d,l)=>i===0?l:l===0?i:0));for(let a=1;a<=t;a++)for(let i=1;i<=s;i++)c[a][i]=o[a-1]===e[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][s]}function Ie(o,e){let t=o.toLowerCase(),s=e.find(i=>i.toLowerCase()===t);if(s)return[s];let c=e.filter(i=>i.toLowerCase().includes(t)||t.includes(i.toLowerCase()));return c.length>0?c:e.map(i=>({name:i,dist:yn(t,i.toLowerCase())})).filter(i=>i.dist<=3).sort((i,d)=>i.dist-d.dist).map(i=>i.name)}function Pe(o){return w()?.aliases?.[o]}async function K(o,e){let t=Pe(e),s=o.get(e);if(t&&s&&t!==e){if(console.log(r.yellow(n("alias.conflict",{name:e,target:t}))),console.log(` ${r.cyan("1)")} ${n("alias.conflict_alias",{target:t})}`),console.log(` ${r.cyan("2)")} ${n("alias.conflict_config",{name:e})}`),await _(n("alias.choose_conflict"))==="1"){let l=o.get(t);return l||(console.log(r.red(n("error.alias_target_missing",{alias:e,target:t}))),null)}return s}if(t){let d=o.get(t);return d||(console.log(r.red(n("error.alias_target_missing",{alias:e,target:t}))),null)}if(s)return s;let c=e.replace(/[-_]/g," ");if(c!==e){let d=o.get(c);if(d)return d}let a=o.list().map(d=>d.name),i=Ie(e,a);if(i.length===1){let d=o.get(i[0]);if(d)return d}if(console.log(r.red(n("error.not_found",{name:e}))),i.length===1)console.log(r.yellow(n("suggest.did_you_mean",{name:r.bold(i[0])})));else if(i.length>1){console.log(r.yellow(n("suggest.did_you_mean_header")));for(let d of i)console.log(` - ${r.bold(d)}`)}else console.log(r.gray(n("suggest.use_list")));return null}h.command("init").description(n("init.description")).action(async()=>{let o=w();if(S({aliases:o?.aliases,locale:o?.locale}),console.log(r.green(n("init.done"))),R()){console.log(r.green(n("init.cc_switch_mode")));let{StandaloneStore:e}=await Promise.resolve().then(()=>(H(),Q)),t=new e,s=t.list();if(s.length>0&&(await _(n("init.cc_switch_migrate"))).toLowerCase()!=="n"){let{CcSwitchStore:a}=await Promise.resolve().then(()=>($(),X)),i=new a,d=t.getCurrent();for(let l of s)i.save(l.name,l.settingsConfig);d&&i.setCurrent(d),console.log(r.green(n("init.cc_switch_migrate_done",{count:String(s.length)}))),i.close()}}});h.command("sync").description(n("sync.description")).action(async()=>{if(!R()){console.log(r.red(n("sync.no_cc_switch")));return}let{CcSwitchStore:o}=await Promise.resolve().then(()=>($(),X)),{StandaloneStore:e}=await Promise.resolve().then(()=>(H(),Q)),t=new o,s=new e,c=t.list();if(c.length===0){console.log(r.yellow(n("sync.empty"))),t.close();return}for(let i of c)s.save(i.name,i.settingsConfig);let a=t.getCurrent();a&&s.setCurrent(a),console.log(r.green(n("sync.done",{count:String(c.length)}))),console.log(a?r.gray(n("sync.current",{name:a})):r.gray(n("sync.no_current"))),t.close()});h.command("clear").description(n("clear.description")).action(async()=>{if((await _(n("clear.confirm"))).toLowerCase()!=="y"){console.log(r.gray(n("clear.cancelled")));return}let e=F(be(),".cc-cast","rc.json"),t=F(be(),".cc-cast","config.json");ie(t)&&(se(t),console.log(r.green(n("clear.removed",{path:t})))),ie(e)&&(se(e),console.log(r.green(n("clear.removed",{path:e})))),console.log(r.green(n("clear.done")))});h.command("import [file]").description(n("import.description")).action(async o=>{let e=C(),t;if(o){if(!ie(o)){console.log(r.red(n("import.file_not_found",{file:o})));return}t=de(o,"utf-8")}else{console.log(r.gray(n("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 s;try{s=JSON.parse(t)}catch{console.log(r.red(n("import.json_parse_error")));return}if(typeof s!="object"||s===null||Object.keys(s).length===0){console.log(r.red(n("import.invalid_format")));return}let c=0;for(let[a,i]of Object.entries(s))e.save(a,i),c++;console.log(r.green(n("import.done",{count:String(c)})))});h.command("list").alias("ls").description(n("list.description")).action(async()=>{let o=C(),e=o.list(),t=o.getCurrent();if(e.length===0){console.log(r.yellow(n("list.empty")));return}let s=a=>{if(a===t)return;let i=o.get(a);o.setCurrent(i.name),console.log(r.green(n("use.done",{name:r.bold(i.name)}))),k(i.name,i.settingsConfig);let l=(i.settingsConfig.env||{}).ANTHROPIC_MODEL||n("common.model_default");console.log(` ${n("common.model")}: ${r.cyan(l)}`),console.log(r.gray(` ${n("use.restart")}`))};if(process.stdin.isTTY&&process.stdout.isTTY){let a=e.map(l=>{let m=l.name===t,u=l.settingsConfig.env||{},g=u.ANTHROPIC_MODEL||n("common.model_default"),f=u.ANTHROPIC_BASE_URL||"default",p=m?` ${n("list.current_marker")}`:"";return{label:`${l.name}${p}`,hint:`${n("common.model")}: ${g} ${n("common.source")}: ${f}`,value:l.name}}),i=e.findIndex(l=>l.name===t),d=q({message:"",choices:a.map(l=>({name:l.value,message:l.label})),initial:i>=0?i:0,pointer:"\u25CF",styles:{em:l=>l,strong:l=>l}});try{let l=await d.run();s(l)}catch{console.log(r.gray(n("common.cancelled")));return}}else{console.log(r.bold(`
|
|
11
|
+
${n("list.header")}
|
|
12
|
+
`)),e.forEach((d,l)=>{let m=d.name===t,u=m?r.green("\u25CF "):" ",g=m?r.green.bold(d.name):d.name,f=d.settingsConfig.env||{},p=f.ANTHROPIC_MODEL||n("common.model_default"),y=f.ANTHROPIC_BASE_URL||"default";console.log(`${u}${r.gray(`${l+1}.`)} ${g}`),console.log(` ${n("common.model")}: ${r.cyan(p)} ${n("common.source")}: ${r.gray(y)}`)}),console.log();let a=await _(n("list.choose_number"));if(!a)return;let i=parseInt(a,10)-1;if(isNaN(i)||i<0||i>=e.length){console.log(r.red(n("error.invalid_choice")));return}s(e[i].name)}});h.command("current").description(n("current.description")).action(()=>{hn()});h.command("use [name]").description(n("use.description")).action(async o=>{let e=C();if(!o){await h.commands.find(a=>a.name()==="list").parseAsync([]);return}let t=await K(e,o);if(!t)return;e.setCurrent(t.name),console.log(r.green(n("use.done",{name:r.bold(t.name)}))),k(t.name,t.settingsConfig);let c=(t.settingsConfig.env||{}).ANTHROPIC_MODEL||n("common.model_default");console.log(` ${n("common.model")}: ${r.cyan(c)}`),console.log(r.gray(` ${n("use.restart")}`))});h.command("save <name>").description(n("save.description")).action(o=>{let e=C();e.get(o)&&console.log(r.yellow(n("save.overwrite",{name:o})));let s=M(),c={};s.env&&(c.env=s.env),s.model&&(c.model=s.model),s.hooks&&(c.hooks=s.hooks),s.statusLine&&(c.statusLine=s.statusLine),e.save(o,c),e.setCurrent(o),console.log(r.green(n("save.done",{name:o})))});function J(o,e){let t=F(an(),`cc-cast-${o}-${Date.now()}.json`);cn(t,JSON.stringify(e,null,2));let s=process.env.EDITOR||"vi",c=sn(s,[t],{stdio:"inherit"}),a=null;if(c.status===0)try{a=JSON.parse(de(t,"utf-8"))}catch{console.log(r.red(n("add.json_parse_error")))}try{se(t)}catch{}return a}async function $e(o,e,t){o.save(e,t),console.log(r.green(n("add.done",{name:e}))),(await _(n("add.switch_confirm"))).toLowerCase()!=="n"&&(o.setCurrent(e),console.log(r.green(n("use.done",{name:r.bold(e)}))),k(e,t),console.log(r.gray(` ${n("use.restart")}`)))}var wn={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 ae(o){return wn[o.toLowerCase()]}h.command("add").alias("new").description(n("add.description")).action(async()=>{let o=C(),e=await _(n("add.prompt_name"));if(!e){console.log(r.red(n("add.name_required")));return}if(o.get(e)&&(await _(n("add.already_exists",{name:e}))).toLowerCase()!=="y"){console.log(r.gray(n("add.cancelled")));return}if(console.log(`
|
|
13
|
+
${r.bold(n("add.mode_select"))}
|
|
14
|
+
`),console.log(` ${r.cyan("1)")} ${n("add.mode_interactive")}`),console.log(` ${r.cyan("2)")} ${n("add.mode_json")}
|
|
15
|
+
`),await _(n("add.mode_choose"))==="2"){let g={env:{ANTHROPIC_BASE_URL:ae(e)??"",ANTHROPIC_AUTH_TOKEN:"",ANTHROPIC_MODEL:"",ANTHROPIC_DEFAULT_OPUS_MODEL:"",ANTHROPIC_DEFAULT_SONNET_MODEL:"",ANTHROPIC_DEFAULT_HAIKU_MODEL:""}};console.log(r.gray(n("add.json_template_hint")));let f=J(e,g);if(!f)return;await $e(o,e,f);return}let c=ae(e),a=[{key:"ANTHROPIC_BASE_URL",prompt:n("add.prompt_base_url"),required:!0,defaultValue:c},{key:"ANTHROPIC_AUTH_TOKEN",prompt:n("add.prompt_auth_token"),required:!0},{key:"ANTHROPIC_MODEL",prompt:n("add.prompt_model"),required:!1},{key:"ANTHROPIC_DEFAULT_OPUS_MODEL",prompt:n("add.prompt_default_opus"),required:!1},{key:"ANTHROPIC_DEFAULT_SONNET_MODEL",prompt:n("add.prompt_default_sonnet"),required:!1},{key:"ANTHROPIC_DEFAULT_HAIKU_MODEL",prompt:n("add.prompt_default_haiku"),required:!1}];console.log(r.gray(n("add.back_hint")));let i={},d=0;for(;d<a.length;){let g=a[d],f=g.defaultValue?`${g.prompt}(${r.gray(g.defaultValue)}): `:g.prompt,p=await _(f,g.defaultValue);if(p==="<"){d>0&&d--;continue}let y=p||g.defaultValue||"";if(g.required&&!y){console.log(r.red(n("add.field_required",{field:g.key})));continue}y?i[g.key]=y:delete i[g.key],d++}let l={};for(let[g,f]of Object.entries(i))l[g]=f;let m={env:l};if(console.log(`
|
|
16
|
+
${r.bold(n("add.preview_header"))}
|
|
17
|
+
`),console.log(JSON.stringify(m,null,2)),console.log(),(await _(n("add.edit_confirm"))).toLowerCase()==="y"){let g=J(e,m);g&&(m=g)}await $e(o,e,m)});h.command("show [name]").description(n("show.description")).action(async o=>{let e=C();if(!o){let c=e.list();if(c.length===0){console.log(r.yellow(n("list.empty")));return}console.log(r.bold(`
|
|
18
|
+
${n("show.all_header")}
|
|
19
|
+
`));let a={};for(let i of c)a[i.name]=i.settingsConfig;console.log(JSON.stringify(a,null,2));return}let t=await K(e,o);if(!t)return;console.log(`
|
|
20
|
+
${r.bold(t.name)}
|
|
21
|
+
`);let s=t.settingsConfig.env||{};console.log(ce(s)),t.settingsConfig.model&&console.log(` ${r.gray("model")}: ${t.settingsConfig.model}`),console.log()});h.command("modify [name]").alias("edit").description(n("modify.description")).action(async o=>{let e=C(),t=e.list(),s=e.getCurrent();if(!o){if(t.length===0){console.log(r.yellow(n("list.empty")));return}if(process.stdin.isTTY&&process.stdout.isTTY){let m=t.map(g=>{let f=g.name===s,y=(g.settingsConfig.env||{}).ANTHROPIC_MODEL||n("common.model_default"),v=f?` ${n("list.current_marker")}`:"";return{label:`${g.name}${v}`,hint:`${n("common.model")}: ${y}`,value:g.name}}),u=q({message:"",choices:m.map(g=>({name:g.value,message:g.label,hint:g.hint})),pointer:"\u25CF",styles:{em:g=>g,strong:g=>g}});try{o=await u.run()}catch{console.log(r.gray(n("common.cancelled")));return}}else{console.log(r.bold(`
|
|
22
|
+
${n("list.header")}
|
|
23
|
+
`)),t.forEach((g,f)=>{let p=g.name===s,y=p?r.green("\u25CF "):" ",v=p?r.green.bold(g.name):g.name,De=(g.settingsConfig.env||{}).ANTHROPIC_MODEL||n("common.model_default");console.log(`${y}${r.gray(`${f+1}.`)} ${v}`),console.log(` ${n("common.model")}: ${r.cyan(De)}`)}),console.log();let m=await _(n("list.choose_number"));if(!m)return;let u=parseInt(m,10)-1;if(isNaN(u)||u<0||u>=t.length){console.log(r.red(n("error.invalid_choice")));return}o=t[u].name}}let c=await K(e,o);if(!c)return;let a=c.settingsConfig.env||{};console.log(`
|
|
24
|
+
${r.bold(n("add.mode_select"))}
|
|
25
|
+
`),console.log(` ${r.cyan("1)")} ${n("add.mode_interactive")}`),console.log(` ${r.cyan("2)")} ${n("add.mode_json")}
|
|
26
|
+
`);let i=await _(n("add.mode_choose")),d;if(i==="2"){let l=J(c.name,c.settingsConfig);if(!l)return;d=l}else{let l=[{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(r.gray(n("add.back_hint")));let m={...a},u=0;for(;u<l.length;){let f=l[u],p=a[f.key]||(f.key==="ANTHROPIC_BASE_URL"?ae(c.name)??"":""),y=p?`(${r.gray(p)})`:"",v=await _(`${f.prompt}${y}: `,p||void 0);if(v==="<"){u>0&&u--;continue}if(v)m[f.key]=v;else if(f.required&&!p){console.log(r.red(n("add.field_required",{field:f.key})));continue}u++}let g={};for(let[f,p]of Object.entries(m))p&&(g[f]=p);d={...c.settingsConfig,env:g}}if(console.log(`
|
|
27
|
+
${r.bold(n("add.preview_header"))}
|
|
28
|
+
`),console.log(JSON.stringify(d,null,2)),console.log(),i!=="2"&&(await _(n("add.edit_confirm"))).toLowerCase()==="y"){let m=J(c.name,d);m&&(d=m)}e.save(c.name,d),console.log(r.green(n("modify.done",{name:c.name}))),c.name!==s?(await _(n("add.switch_confirm"))).toLowerCase()!=="n"&&(e.setCurrent(c.name),console.log(r.green(n("use.done",{name:r.bold(c.name)}))),k(c.name,d),console.log(r.gray(` ${n("use.restart")}`))):(k(c.name,d),console.log(r.gray(` ${n("use.restart")}`)))});h.command("remove [name]").alias("rm").description(n("remove.description")).action(async o=>{let e=C(),t=e.list(),s=e.getCurrent();if(!o){if(t.length===0){console.log(r.yellow(n("list.empty")));return}if(process.stdin.isTTY&&process.stdout.isTTY){let l=t.map(u=>{let g=u.name===s,p=(u.settingsConfig.env||{}).ANTHROPIC_MODEL||n("common.model_default"),y=g?` ${n("list.current_marker")}`:"";return{label:`${u.name}${y}`,hint:`${n("common.model")}: ${p}`,value:u.name}}),m=q({message:"",choices:l.map(u=>({name:u.value,message:u.label,hint:u.hint})),pointer:"\u25CF",styles:{em:u=>u,strong:u=>u}});try{o=await m.run()}catch{console.log(r.gray(n("common.cancelled")));return}}else{console.log(r.bold(`
|
|
29
|
+
${n("list.header")}
|
|
30
|
+
`)),t.forEach((u,g)=>{let f=u.name===s,p=f?r.green("\u25CF "):" ",y=f?r.green.bold(u.name):u.name,ge=(u.settingsConfig.env||{}).ANTHROPIC_MODEL||n("common.model_default");console.log(`${p}${r.gray(`${g+1}.`)} ${y}`),console.log(` ${n("common.model")}: ${r.cyan(ge)}`)}),console.log();let l=await _(n("list.choose_number"));if(!l)return;let m=parseInt(l,10)-1;if(isNaN(m)||m<0||m>=t.length){console.log(r.red(n("error.invalid_choice")));return}o=t[m].name}}let c=Pe(o);if(c){if(console.log(r.yellow(n("alias.is_alias",{name:o,target:c}))),console.log(`
|
|
31
|
+
${n("alias.rm_which")}
|
|
32
|
+
`),console.log(` ${r.cyan("1)")} ${n("alias.rm_alias",{name:o})}`),console.log(` ${r.cyan("2)")} ${n("alias.rm_config",{target:c})}`),await _(n("alias.rm_choose"))==="1"){let l=w();delete l.aliases[o],S(l),console.log(r.green(n("alias.rm_done",{short:o})));return}o=c}let a=await K(e,o);!a||(await _(n("remove.confirm",{name:a.name}))).toLowerCase()!=="y"||(e.remove(a.name),console.log(r.green(n("remove.done",{name:a.name}))))});var I=h.command("alias").description(n("alias.description"));I.command("set <short> <name>").description(n("alias.set_description")).action((o,e)=>{let t=C();if(!t.get(e)){let c=t.list().map(i=>i.name),a=Ie(e,c);console.log(r.red(n("error.not_found",{name:e}))),a.length>0&&console.log(r.yellow(n("suggest.did_you_mean",{name:a.join(", ")})));return}let s=w();s.aliases=s.aliases||{},s.aliases[o]=e,S(s),console.log(r.green(n("alias.set_done",{short:r.bold(o),name:e})))});I.command("rm <short>").description(n("alias.rm_description")).action(o=>{let e=w();if(!e?.aliases?.[o]){console.log(r.red(n("alias.rm_not_found",{short:o})));return}delete e.aliases[o],S(e),console.log(r.green(n("alias.rm_done",{short:o})))});I.command("list").alias("ls").description(n("alias.list_description")).action(()=>{let e=w()?.aliases||{},t=Object.entries(e);if(t.length===0){console.log(r.yellow(n("alias.list_empty")));return}console.log(r.bold(`
|
|
33
|
+
${n("alias.list_header")}
|
|
34
|
+
`));for(let[s,c]of t)console.log(` ${r.cyan.bold(s)} \u2192 ${c}`);console.log()});I.action(()=>{I.commands.find(o=>o.name()==="list").parseAsync([])});var z=h.command("locale").description(n("locale.description"));z.command("set <lang>").description(n("locale.set_description")).action(o=>{if(o!=="zh"&&o!=="en"){console.log(r.red(n("locale.set_invalid",{locale:o})));return}le(o)});var j=[{code:"zh",label:"\u4E2D\u6587"},{code:"en",label:"English"}],le=o=>{let e=w();e.locale=o,S(e),he(o),console.log(r.green(n("locale.set_done",{locale:o})))};z.command("list").alias("ls").description(n("locale.list_description")).action(async()=>{let e=w()?.locale||W();if(process.stdin.isTTY&&process.stdout.isTTY){let s=j.map(({code:i,label:d})=>{let m=i===e?` ${n("locale.list_current_marker")}`:"";return{label:`${i} - ${d}${m}`,value:i}}),c=s.findIndex(i=>i.value===e),a=q({message:"",choices:s.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===e)return;le(i)}catch{console.log(r.gray(n("common.cancelled")));return}}else{console.log(r.bold(`
|
|
35
|
+
${n("locale.list_header")}
|
|
36
|
+
`)),j.forEach(({code:i,label:d},l)=>{let m=i===e,u=m?r.green("\u25CF "):" ",g=m?r.green.bold(`${i} - ${d}`):`${i} - ${d}`,f=m?r.gray(` ${n("locale.list_current_marker")}`):"";console.log(`${u}${r.gray(`${l+1}.`)} ${g}${f}`)}),console.log();let s=await _(n("locale.choose_number"));if(!s)return;let c=parseInt(s,10)-1;if(isNaN(c)||c<0||c>=j.length){console.log(r.red(n("error.invalid_choice")));return}let a=j[c].code;if(a===e)return;le(a)}});z.action(()=>{z.commands.find(o=>o.name()==="list").parseAsync([])});h.parse();
|
package/dist/utils.d.ts
CHANGED
|
@@ -4,3 +4,5 @@ export declare function readRc(): RcConfig;
|
|
|
4
4
|
export declare function writeRc(rc: RcConfig): void;
|
|
5
5
|
export declare function getStore(): DataStore;
|
|
6
6
|
export declare function isCcSwitchGuiRunning(): boolean;
|
|
7
|
+
export declare function stopCcSwitchGui(): string | null;
|
|
8
|
+
export declare function launchCcSwitchGui(appPath: string): void;
|
package/package.json
CHANGED
package/src/claude.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { homedir } from "os";
|
|
2
2
|
import { join } from "path";
|
|
3
|
-
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, renameSync, unlinkSync } from "fs";
|
|
4
4
|
|
|
5
5
|
const SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
|
|
6
6
|
|
|
@@ -9,6 +9,32 @@ export function readClaudeSettings(): Record<string, unknown> {
|
|
|
9
9
|
return JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
// Recursively sort object keys for deterministic serialization (matches cc-switch behavior)
|
|
13
|
+
function sortKeys(obj: unknown): unknown {
|
|
14
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
15
|
+
if (Array.isArray(obj)) return obj.map(sortKeys);
|
|
16
|
+
|
|
17
|
+
const sorted: Record<string, unknown> = {};
|
|
18
|
+
const keys = Object.keys(obj as Record<string, unknown>).sort();
|
|
19
|
+
for (const key of keys) {
|
|
20
|
+
sorted[key] = sortKeys((obj as Record<string, unknown>)[key]);
|
|
21
|
+
}
|
|
22
|
+
return sorted;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Sanitize settings before writing (remove cc-switch internal fields)
|
|
26
|
+
function sanitizeSettings(settings: Record<string, unknown>): Record<string, unknown> {
|
|
27
|
+
const sanitized = { ...settings };
|
|
28
|
+
// cc-switch meta field
|
|
29
|
+
delete sanitized.currentProviderClaude;
|
|
30
|
+
// cc-switch internal-only fields (matches sanitize_claude_settings_for_live in cc-switch)
|
|
31
|
+
delete sanitized.api_format;
|
|
32
|
+
delete sanitized.apiFormat;
|
|
33
|
+
delete sanitized.openrouter_compat_mode;
|
|
34
|
+
delete sanitized.openrouterCompatMode;
|
|
35
|
+
return sanitized;
|
|
36
|
+
}
|
|
37
|
+
|
|
12
38
|
export function applyProfile(_name: string, settingsConfig: Record<string, unknown>): void {
|
|
13
39
|
const current = readClaudeSettings();
|
|
14
40
|
|
|
@@ -23,8 +49,30 @@ export function applyProfile(_name: string, settingsConfig: Record<string, unkno
|
|
|
23
49
|
|
|
24
50
|
// Merge instead of replace: keep any top-level keys from the existing file
|
|
25
51
|
// that the profile does not explicitly set (e.g. common snippets from cc-switch)
|
|
26
|
-
|
|
27
|
-
|
|
52
|
+
let merged = { ...current, ...preserved, ...settingsConfig };
|
|
53
|
+
|
|
54
|
+
// Sanitize and sort keys to match cc-switch behavior
|
|
55
|
+
merged = sanitizeSettings(merged);
|
|
56
|
+
const sorted = sortKeys(merged) as Record<string, unknown>;
|
|
57
|
+
|
|
58
|
+
// Atomic write: write to temp file, then rename (matches cc-switch's atomic_write)
|
|
59
|
+
const tmpPath = `${SETTINGS_PATH}.tmp.${Date.now()}`;
|
|
60
|
+
try {
|
|
61
|
+
writeFileSync(tmpPath, JSON.stringify(sorted, null, 2));
|
|
62
|
+
|
|
63
|
+
// On Windows, remove target first if it exists
|
|
64
|
+
if (process.platform === "win32" && existsSync(SETTINGS_PATH)) {
|
|
65
|
+
unlinkSync(SETTINGS_PATH);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
renameSync(tmpPath, SETTINGS_PATH);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
// Clean up temp file on error
|
|
71
|
+
if (existsSync(tmpPath)) {
|
|
72
|
+
try { unlinkSync(tmpPath); } catch { /* ignore */ }
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
28
76
|
}
|
|
29
77
|
|
|
30
78
|
export function getSettingsPath(): string {
|
package/src/i18n/en.ts
CHANGED
|
@@ -48,7 +48,8 @@ const en: Record<TranslationKey, string> = {
|
|
|
48
48
|
"use.description": "Switch to a specified configuration",
|
|
49
49
|
"use.done": "✓ Switched to {name}",
|
|
50
50
|
"use.restart": "Restart Claude Code to apply",
|
|
51
|
-
"use.
|
|
51
|
+
"use.cc_switch_restarting": "cc-switch GUI detected, restarting to sync config...",
|
|
52
|
+
"use.cc_switch_relaunch_manual": "Could not auto-restart cc-switch. Please reopen it manually.",
|
|
52
53
|
|
|
53
54
|
// save
|
|
54
55
|
"save.description": "Save current settings.json as a new configuration",
|
package/src/i18n/zh.ts
CHANGED
|
@@ -46,7 +46,8 @@ const zh = {
|
|
|
46
46
|
"use.description": "切换到指定配置方案",
|
|
47
47
|
"use.done": "✓ 已切换到 {name}",
|
|
48
48
|
"use.restart": "重启 Claude Code 生效",
|
|
49
|
-
"use.
|
|
49
|
+
"use.cc_switch_restarting": "检测到 cc-switch GUI,正在重启以同步配置...",
|
|
50
|
+
"use.cc_switch_relaunch_manual": "无法自动重启 cc-switch,请手动打开。",
|
|
50
51
|
|
|
51
52
|
// save
|
|
52
53
|
"save.description": "从当前 settings.json 保存为新配置",
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import chalk from "chalk";
|
|
5
|
-
import { readRc, writeRc, getStore, isCcSwitchGuiRunning } from "./utils.js";
|
|
5
|
+
import { readRc, writeRc, getStore, isCcSwitchGuiRunning, stopCcSwitchGui, launchCcSwitchGui } from "./utils.js";
|
|
6
6
|
import { ccSwitchExists } from "./store/cc-switch.js";
|
|
7
7
|
import { readClaudeSettings, applyProfile } from "./claude.js";
|
|
8
8
|
import { createInterface } from "readline";
|
|
@@ -77,6 +77,22 @@ function ensureStore() {
|
|
|
77
77
|
return getStore();
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
// Helper: apply profile with cc-switch GUI restart if needed
|
|
81
|
+
function applySafely(name: string, settingsConfig: Record<string, unknown>): void {
|
|
82
|
+
if (isCcSwitchGuiRunning()) {
|
|
83
|
+
console.log(chalk.gray(t("use.cc_switch_restarting")));
|
|
84
|
+
const appPath = stopCcSwitchGui();
|
|
85
|
+
applyProfile(name, settingsConfig);
|
|
86
|
+
if (appPath) {
|
|
87
|
+
launchCcSwitchGui(appPath);
|
|
88
|
+
} else {
|
|
89
|
+
console.log(chalk.yellow(t("use.cc_switch_relaunch_manual")));
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
applyProfile(name, settingsConfig);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
80
96
|
// Helper: print current active configuration
|
|
81
97
|
function printCurrent(): void {
|
|
82
98
|
const store = ensureStore();
|
|
@@ -214,10 +230,22 @@ async function resolveProfile(store: ReturnType<typeof ensureStore>, input: stri
|
|
|
214
230
|
// Direct match
|
|
215
231
|
if (directProfile) return directProfile;
|
|
216
232
|
|
|
233
|
+
// Normalized match (hyphens/underscores → spaces)
|
|
234
|
+
const normalizedInput = input.replace(/[-_]/g, " ");
|
|
235
|
+
if (normalizedInput !== input) {
|
|
236
|
+
const normalizedProfile = store.get(normalizedInput);
|
|
237
|
+
if (normalizedProfile) return normalizedProfile;
|
|
238
|
+
}
|
|
239
|
+
|
|
217
240
|
// Fuzzy matching
|
|
218
241
|
const allNames = store.list().map((p) => p.name);
|
|
219
242
|
const suggestions = findSuggestions(input, allNames);
|
|
220
243
|
|
|
244
|
+
if (suggestions.length === 1) {
|
|
245
|
+
const profile = store.get(suggestions[0]);
|
|
246
|
+
if (profile) return profile;
|
|
247
|
+
}
|
|
248
|
+
|
|
221
249
|
console.log(chalk.red(t("error.not_found", { name: input })));
|
|
222
250
|
if (suggestions.length === 1) {
|
|
223
251
|
console.log(chalk.yellow(t("suggest.did_you_mean", { name: chalk.bold(suggestions[0]) })));
|
|
@@ -403,15 +431,11 @@ program
|
|
|
403
431
|
const profile = store.get(name)!;
|
|
404
432
|
store.setCurrent(profile.name);
|
|
405
433
|
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
412
|
-
console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
|
|
413
|
-
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
414
|
-
}
|
|
434
|
+
applySafely(profile.name, profile.settingsConfig);
|
|
435
|
+
const env = (profile.settingsConfig.env || {}) as Record<string, string>;
|
|
436
|
+
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
437
|
+
console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
|
|
438
|
+
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
415
439
|
};
|
|
416
440
|
|
|
417
441
|
const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
|
|
@@ -496,15 +520,11 @@ program
|
|
|
496
520
|
|
|
497
521
|
store.setCurrent(profile.name);
|
|
498
522
|
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
505
|
-
console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
|
|
506
|
-
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
507
|
-
}
|
|
523
|
+
applySafely(profile.name, profile.settingsConfig);
|
|
524
|
+
const env = (profile.settingsConfig.env || {}) as Record<string, string>;
|
|
525
|
+
const model = env["ANTHROPIC_MODEL"] || t("common.model_default");
|
|
526
|
+
console.log(` ${t("common.model")}: ${chalk.cyan(model)}`);
|
|
527
|
+
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
508
528
|
});
|
|
509
529
|
|
|
510
530
|
// cc-castsave <name>
|
|
@@ -562,12 +582,8 @@ async function saveAndSwitch(store: ReturnType<typeof ensureStore>, name: string
|
|
|
562
582
|
if (switchChoice.toLowerCase() !== "n") {
|
|
563
583
|
store.setCurrent(name);
|
|
564
584
|
console.log(chalk.green(t("use.done", { name: chalk.bold(name) })));
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
} else {
|
|
568
|
-
applyProfile(name, settingsConfig);
|
|
569
|
-
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
570
|
-
}
|
|
585
|
+
applySafely(name, settingsConfig);
|
|
586
|
+
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
571
587
|
}
|
|
572
588
|
}
|
|
573
589
|
|
|
@@ -886,15 +902,11 @@ program
|
|
|
886
902
|
if (switchChoice.toLowerCase() !== "n") {
|
|
887
903
|
store.setCurrent(profile.name);
|
|
888
904
|
console.log(chalk.green(t("use.done", { name: chalk.bold(profile.name) })));
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
} else {
|
|
892
|
-
applyProfile(profile.name, settingsConfig);
|
|
893
|
-
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
894
|
-
}
|
|
905
|
+
applySafely(profile.name, settingsConfig);
|
|
906
|
+
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
895
907
|
}
|
|
896
908
|
} else {
|
|
897
|
-
|
|
909
|
+
applySafely(profile.name, settingsConfig);
|
|
898
910
|
console.log(chalk.gray(` ${t("use.restart")}`));
|
|
899
911
|
}
|
|
900
912
|
});
|
package/src/utils.ts
CHANGED
|
@@ -45,3 +45,42 @@ export function isCcSwitchGuiRunning(): boolean {
|
|
|
45
45
|
return false;
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
|
|
49
|
+
// Kill cc-switch GUI and return the .app path for relaunch (macOS only).
|
|
50
|
+
// Returns null on Linux/other or if the app path can't be determined.
|
|
51
|
+
export function stopCcSwitchGui(): string | null {
|
|
52
|
+
try {
|
|
53
|
+
let appPath: string | null = null;
|
|
54
|
+
|
|
55
|
+
if (process.platform === "darwin") {
|
|
56
|
+
const pgrepResult = spawnSync("pgrep", ["-f", "cc-switch"], { encoding: "utf-8" });
|
|
57
|
+
if (pgrepResult.status === 0) {
|
|
58
|
+
const pids = pgrepResult.stdout.trim().split("\n");
|
|
59
|
+
for (const pid of pids) {
|
|
60
|
+
const psResult = spawnSync("ps", ["-p", pid, "-o", "args="], { encoding: "utf-8" });
|
|
61
|
+
const args = psResult.stdout.trim();
|
|
62
|
+
const match = args.match(/^(.+?\.app)\b/);
|
|
63
|
+
if (match) {
|
|
64
|
+
appPath = match[1];
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
spawnSync("pkill", ["-f", "cc-switch"]);
|
|
72
|
+
spawnSync("sleep", ["0.5"]);
|
|
73
|
+
|
|
74
|
+
return appPath;
|
|
75
|
+
} catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function launchCcSwitchGui(appPath: string): void {
|
|
81
|
+
try {
|
|
82
|
+
spawnSync("open", ["-g", appPath], { encoding: "utf-8" });
|
|
83
|
+
} catch {
|
|
84
|
+
// ignore
|
|
85
|
+
}
|
|
86
|
+
}
|