@vibeapi/cli 0.0.46 → 0.0.50
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/commands/auth.js +1 -1
- package/dist/commands/config.js +1 -1
- package/dist/lib/claude-code-manager.d.ts +27 -4
- package/dist/lib/claude-code-manager.js +1 -1
- package/dist/lib/env-cleanup.d.ts +1 -1
- package/dist/lib/env-cleanup.js +1 -1
- package/dist/lib/model-registry.d.ts +11 -0
- package/dist/lib/model-registry.js +1 -1
- package/dist/lib/tool-manager.d.ts +1 -1
- package/dist/lib/tool-manager.js +1 -1
- package/dist/lib/tools/claude-code.js +1 -1
- package/dist/lib/tools/types.d.ts +3 -2
- package/dist/lib/wizard.js +1 -1
- package/dist/locales/en_US.json +3 -0
- package/dist/locales/zh_CN.json +3 -0
- package/dist/models.json +8 -0
- package/dist/settings-template.json +2 -1
- package/models.json +8 -0
- package/package.json +1 -1
- package/settings-template.json +2 -1
package/dist/commands/auth.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import o from"chalk";import e from"inquirer";import t from"ora";import{configManager as r}from"../lib/config.js";import{i18n as i}from"../lib/i18n.js";import{validateApiKey as a}from"../lib/api-validator.js";import{toolManager as n}from"../lib/tool-manager.js";import{isJsonMode as d,isNonInteractive as l,shouldAutoConfirm as c,emitJson as s,isColorEnabled as u}from"../lib/runtime-options.js";const p=["claude","claude-code","opencode"];function m(o){return u()?o:o=>o}function f(o,e=o=>o){d()||console.log(m(e)(o))}async function k(e){if(d()){const o=await a(e);return o.valid?(r.setApiKey(e),void s({ok:!0,action:"auth"})):void s({ok:!1,action:"auth",error:o.error||"invalid_api_key"})}const n=t(i.t("wizard.validating_api_key")).start(),l=await a(e);l.valid?(r.setApiKey(e),n.succeed(m(o.green)(i.t("auth.saved")))):"invalid_api_key"===l.error?n.fail(m(o.red)(i.t("wizard.api_key_invalid"))):n.fail(m(o.red)(i.t("wizard.api_key_network_error")))}export async function authCommand(t){0!==t.length?"revoke"!==t[0]?"reload"!==t[0]?await k(t[0]):await async function(e){const t=e.toLowerCase();if(!p.includes(t))return d()?void s({ok:!1,action:"reload",error:"unsupported_tool",tool:e}):void f(i.t("auth.reload_tool_not_supported",{tool:e}),o.red);const a=r.getApiKey();if(!a)return d()?void s({ok:!1,action:"reload",error:"missing_api_key",tool:e}):void f(i.t("auth.reload_missing_config"),o.red);const l="opencode"===t?"OpenCode":"Claude Code",c="opencode"===t?"opencode":"claude-code";d()||f(i.t("auth.reloading",{tool:l}),o.blue);try{n.
|
|
1
|
+
import o from"chalk";import e from"inquirer";import t from"ora";import{configManager as r}from"../lib/config.js";import{i18n as i}from"../lib/i18n.js";import{validateApiKey as a}from"../lib/api-validator.js";import{toolManager as n}from"../lib/tool-manager.js";import{isJsonMode as d,isNonInteractive as l,shouldAutoConfirm as c,emitJson as s,isColorEnabled as u}from"../lib/runtime-options.js";const p=["claude","claude-code","opencode"];function m(o){return u()?o:o=>o}function f(o,e=o=>o){d()||console.log(m(e)(o))}async function k(e){if(d()){const o=await a(e);return o.valid?(r.setApiKey(e),void s({ok:!0,action:"auth"})):void s({ok:!1,action:"auth",error:o.error||"invalid_api_key"})}const n=t(i.t("wizard.validating_api_key")).start(),l=await a(e);l.valid?(r.setApiKey(e),n.succeed(m(o.green)(i.t("auth.saved")))):"invalid_api_key"===l.error?n.fail(m(o.red)(i.t("wizard.api_key_invalid"))):n.fail(m(o.red)(i.t("wizard.api_key_network_error")))}export async function authCommand(t){0!==t.length?"revoke"!==t[0]?"reload"!==t[0]?await k(t[0]):await async function(e){const t=e.toLowerCase();if(!p.includes(t))return d()?void s({ok:!1,action:"reload",error:"unsupported_tool",tool:e}):void f(i.t("auth.reload_tool_not_supported",{tool:e}),o.red);const a=r.getApiKey();if(!a)return d()?void s({ok:!1,action:"reload",error:"missing_api_key",tool:e}):void f(i.t("auth.reload_missing_config"),o.red);const l="opencode"===t?"OpenCode":"Claude Code",c="opencode"===t?"opencode":"claude-code";d()||f(i.t("auth.reloading",{tool:l}),o.blue);try{await n.applyPrivateConfig(c,r.getApiKeyForTool(c)||a,r.getModelsForTool(c)),d()?s({ok:!0,action:"reload",tool:c}):f(i.t("auth.reloaded",{tool:l}),o.green)}catch(e){if(d())return void s({ok:!1,action:"reload",error:"reload_failed",message:e instanceof Error?e.message:String(e)});f(i.t("auth.reload_failed"),o.red),e instanceof Error&&f(e.message,o.red)}}(t[1]||""):await async function(){if(!c()){const{confirm:t}=await e.prompt([{type:"confirm",name:"confirm",message:i.t("auth.revoke_confirm"),default:!1}]);if(!t)return d()?void s({ok:!1,action:"revoke",cancelled:!0}):void f(i.t("auth.not_revoked"),o.yellow)}r.revokeApiKey(),d()?s({ok:!0,action:"revoke"}):f(i.t("auth.revoked"),o.green)}():await async function(){if(l())return d()?void s({ok:!1,action:"auth",error:"token_required"}):void f(i.t("runtime.non_interactive_required_token"),o.red);const{token:t}=await e.prompt([{type:"password",name:"token",message:i.t("auth.token_prompt"),validate:o=>!(!o||0===o.trim().length)||i.t("auth.token_required")}]);await k(t.trim())}()}
|
package/dist/commands/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import o from"inquirer";import e from"chalk";import{wizard as t}from"../lib/wizard.js";import{toolManager as n,SUPPORTED_TOOLS as l}from"../lib/tool-manager.js";import{i18n as i}from"../lib/i18n.js";import{configManager as r,DEFAULT_PROFILE_NAME as s}from"../lib/config.js";import{confirmAction as a,applyOrDryRun as c}from"../lib/confirm.js";import{isNonInteractive as f,shouldAutoConfirm as d}from"../lib/runtime-options.js";const g=/^[a-zA-Z0-9._-]+$/;function m(o,e){const t=(o||"").trim();if(!t||!g.test(t))throw new Error(i.t(`config.${e}_invalid_name`,{name:t||"<empty>"}));return t}function u(o,t){console.log("\n"+e.bold(o)),0!==t.length?t.forEach(o=>console.log(" "+o)):console.log(e.gray(" ("+i.t("config.empty_list")+")"))}function p(o,t){if("backups"===t){const t=n.listToolBackups(o).flatMap(o=>{const t=o.file.replace(/^.*[/\\]/,"");return o.backups.length?o.backups.map(o=>`${e.cyan(t)} ${e.gray(o.name.split(".bak-")[1]||o.name)}`):[`${e.cyan(t)} ${e.gray("("+i.t("config.empty_list")+")")}`]});return void u(i.t("config.tool_backups_title",{tool:l[o].displayName}),t)}const r=n.restorePrivateConfig(o).filter(o=>o.result.restored);0!==r.length?(console.log(e.green(i.t("config.config_restored",{tool:l[o].displayName}))),r.forEach(o=>console.log(e.gray(` ${o.file} ← ${o.result.from}`)))):console.log(e.yellow(i.t("config.restore_no_backup",{tool:l[o].displayName})))}async function _(s,f,d){if(!l[s])return void console.log(e.red(i.t("config.unknown_tool",{tool:s})));const g=(f[0]||"").toLowerCase();if("backups"!==g&&"list-backups"!==g){if("restore"===g){if(!await a({message:i.t("config.confirm_restore",{tool:l[s].displayName}),defaultValue:!1}))return;return void p(s,"restore")}if("clear-model"===g||"clear-models"===g){const o=l[s].displayName;return n.supportsClearPinnedModels(s)?void await c({description:i.t("config.clear_model_dry_run",{tool:o}),json:{action:"clear_model",tool:s},apply:async()=>{const t=n.clearPinnedModels(s);0!==t.length?(console.log(e.green(i.t("config.clear_model_done",{tool:o}))),t.forEach(o=>console.log(e.gray(` - ${o}`))),console.log(e.gray(i.t("config.clear_model_restart_hint",{tool:o})))):console.log(e.yellow(i.t("config.clear_model_none",{tool:o})))}}):void console.log(e.yellow(i.t("config.clear_model_unsupported",{tool:o})))}if(!n.isToolInstalled(s)){if(d.nonInteractive)return void console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[s].displayName})));console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[s].displayName})));const{shouldInstall:t}=await o.prompt([{type:"confirm",name:"shouldInstall",message:i.t("wizard.install_tool_confirm"),default:!0}]);if(!t)return void console.log(e.yellow(i.t("wizard.install_skipped")));try{await n.installTool(s)}catch(o){return console.error(e.red(i.t("install.install_failed_detail"))),void(o instanceof Error&&o.message&&console.error(e.gray(o.message)))}}if(d.nonInteractive||d.force){const o=r.getApiKeyForTool(s);if(!o)return void console.log(e.red(i.t("wizard.api_key_required")));if(d.force&&!d.nonInteractive&&!await a({message:i.t("config.confirm_force",{tool:l[s].displayName}),defaultValue:!1}))return;return await n.applyPrivateConfig(s,o,r.getModelsForTool(s),{force:d.force}),d.force&&console.log(e.yellow(i.t("config.force_done",{tool:l[s].displayName}))),console.log(e.green(i.t("config.tool_config_loaded",{tool:l[s].displayName}))),void n.applyNotes(s).forEach(o=>console.log(e.yellow(o)))}await t.showToolMenu(s)}else p(s,"backups")}export async function configCommand(t){const{positional:n,options:p}=function(o){const e=[],t={};(f()||d())&&(t.nonInteractive=!0);for(const n of o)"--non-interactive"===n||"-y"===n?t.nonInteractive=!0:"--force"===n||"-f"===n?t.force=!0:e.push(n);return{positional:e,options:t}}(t),y=n[0],v=n.slice(1);if(y){switch(y){case"profile":return void await async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=r.getActiveProfileName(),t=r.listProfiles().map(t=>{const n=t===o;return`${n?e.green("●"):e.gray("○")} ${t}${n?e.gray(" ("+i.t("config.profile_active_label")+")"):""}`});return void u(i.t("config.profile_list_title"),t)}if("create"===t){const o=m(n,"profile");return r.listProfiles().includes(o)?void console.log(e.yellow(i.t("config.profile_exists",{name:o}))):(r.createProfile(o),void console.log(e.green(i.t("config.profile_created",{name:o}))))}if("use"===t){const o=m(n,"profile");return r.setActiveProfile(o),void console.log(e.green(i.t("config.profile_activated",{name:o})))}if("delete"===t||"remove"===t){const o=m(n,"profile");return o===s&&1===r.listProfiles().length?void console.log(e.yellow(i.t("config.profile_cannot_delete_last"))):void await c({description:i.t("config.profile_delete_dry_run",{name:o}),json:{action:"profile_delete",name:o},apply:async()=>{await a({message:i.t("config.profile_delete_confirm",{name:o}),defaultValue:!1})?(r.deleteProfile(o),console.log(e.green(i.t("config.profile_deleted",{name:o})))):console.log(e.yellow(i.t("config.profile_delete_aborted")))}})}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"preset":return void function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=Object.entries(r.getCustomPresets()).map(([o,t])=>`${e.cyan(o)} ${e.gray(`H:${t.models.haiku} S:${t.models.sonnet} O:${t.models.opus}`)}`);return void u(i.t("config.preset_list_title"),o)}if("save"===t){const o=m(n,"preset");return r.saveCustomPreset(o,r.getModels()),void console.log(e.green(i.t("config.preset_saved",{name:o})))}if("use"===t||"apply"===t){const o=m(n,"preset"),t=r.getCustomPresets()[o];return t?(r.setModels(t.models),void console.log(e.green(i.t("config.preset_applied",{name:o})))):void console.log(e.red(i.t("config.preset_not_found",{name:o})))}if("delete"===t||"remove"===t){const o=m(n,"preset");return r.deleteCustomPreset(o),void console.log(e.green(i.t("config.preset_deleted",{name:o})))}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"tool-model":return void function(o){const t=o[0];if(!t||"list"===t){const o=r.getProfile().tool_models||{},t=Object.entries(o).map(([o,t])=>{const n=Object.entries(t).map(([o,e])=>`${o}=${e}`).join(" ");return`${e.cyan(o)} ${e.gray(n)}`});return void u(i.t("config.tool_model_list_title"),t)}if("set"===t){const t=(o[1]||"").trim(),n=o.length>=4?(o[2]||"").trim():"opus",s=(o.length>=4?o[3]:o[2]||"").trim();return l[t]?s&&g.test(n)?(r.setToolModel(t,{[n]:s}),void console.log(e.green(i.t("config.tool_model_set",{tool:t,slot:n,model:s})))):void console.log(e.red(i.t("config.tool_model_usage"))):void console.log(e.red(i.t("config.unknown_tool",{tool:t})))}if("clear"===t||"remove"===t){const t=(o[1]||"").trim();return l[t]?(r.setToolModel(t,null),void console.log(e.green(i.t("config.tool_model_cleared",{tool:t})))):void console.log(e.red(i.t("config.unknown_tool",{tool:t})))}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"backup":return void await function(o){return async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=r.listBackups().map(o=>{const t=new Date(o.mtimeMs).toISOString();return`${e.cyan(o.name)} ${e.gray(t)}`});return void u(i.t("config.backup_list_title"),o)}if("create"===t||"snapshot"===t){const o=r.createBackup(n);return void console.log(e.green(i.t("config.backup_created",{path:o})))}if("restore"===t)return n?void await c({description:i.t("config.backup_restore_dry_run",{name:n}),json:{action:"backup_restore",name:n},apply:async()=>{await a({message:i.t("config.backup_restore_confirm",{name:n}),defaultValue:!1})?(r.restoreBackup(n),console.log(e.green(i.t("config.backup_restored",{name:n})))):console.log(e.yellow(i.t("config.backup_restore_aborted")))}}):void console.log(e.red(i.t("config.backup_restore_missing_name")));console.log(e.red(i.t("config.unknown_action",{action:t})))}(o)}(v)}"claude-code"!==y&&"claude-code"!==v[0]?l[y]?await _(y,v,p):(console.error(e.red(i.t("config.unknown_command",{command:y}))),console.log(e.gray(i.t("config.usage_hint"))),Object.values(l).filter(o=>!o.hidden).forEach(o=>{console.log(e.gray(` - ${o.name}: ${o.displayName}`))})):await _("claude-code",v,p)}else await async function(t){if(t.nonInteractive)return void console.log(e.red(i.t("config.requires_argument")));const{selectedTool:n}=await o.prompt([{type:"list",name:"selectedTool",message:i.t("wizard.select_tool"),choices:Object.values(l).filter(o=>!o.hidden).map(o=>({name:`${o.displayName} (${o.name})`,value:o.name}))}]);await _(n,[],t)}(p)}
|
|
1
|
+
import o from"inquirer";import e from"chalk";import{wizard as t}from"../lib/wizard.js";import{toolManager as n,SUPPORTED_TOOLS as l}from"../lib/tool-manager.js";import{i18n as i}from"../lib/i18n.js";import{configManager as r,DEFAULT_PROFILE_NAME as s}from"../lib/config.js";import{confirmAction as a,applyOrDryRun as c}from"../lib/confirm.js";import{isNonInteractive as f,shouldAutoConfirm as d}from"../lib/runtime-options.js";const g=/^[a-zA-Z0-9._-]+$/;function m(o,e){const t=(o||"").trim();if(!t||!g.test(t))throw new Error(i.t(`config.${e}_invalid_name`,{name:t||"<empty>"}));return t}function u(o,t){console.log("\n"+e.bold(o)),0!==t.length?t.forEach(o=>console.log(" "+o)):console.log(e.gray(" ("+i.t("config.empty_list")+")"))}function p(o,t){if("backups"===t){const t=n.listToolBackups(o).flatMap(o=>{const t=o.file.replace(/^.*[/\\]/,"");return o.backups.length?o.backups.map(o=>`${e.cyan(t)} ${e.gray(o.name.split(".bak-")[1]||o.name)}`):[`${e.cyan(t)} ${e.gray("("+i.t("config.empty_list")+")")}`]});return void u(i.t("config.tool_backups_title",{tool:l[o].displayName}),t)}const r=n.restorePrivateConfig(o).filter(o=>o.result.restored);0!==r.length?(console.log(e.green(i.t("config.config_restored",{tool:l[o].displayName}))),r.forEach(o=>console.log(e.gray(` ${o.file} ← ${o.result.from}`)))):console.log(e.yellow(i.t("config.restore_no_backup",{tool:l[o].displayName})))}async function _(s,f,d){if(!l[s])return void console.log(e.red(i.t("config.unknown_tool",{tool:s})));const g=(f[0]||"").toLowerCase();if("backups"!==g&&"list-backups"!==g){if("restore"===g){if(!await a({message:i.t("config.confirm_restore",{tool:l[s].displayName}),defaultValue:!1}))return;return void p(s,"restore")}if("clear-model"===g||"clear-models"===g){const o=l[s].displayName;return n.supportsClearPinnedModels(s)?void await c({description:i.t("config.clear_model_dry_run",{tool:o}),json:{action:"clear_model",tool:s},apply:async()=>{const t=await n.clearPinnedModels(s);0!==t.length?(console.log(e.green(i.t("config.clear_model_done",{tool:o}))),t.forEach(o=>console.log(e.gray(` - ${o}`))),console.log(e.gray(i.t("config.clear_model_restart_hint",{tool:o})))):console.log(e.yellow(i.t("config.clear_model_none",{tool:o})))}}):void console.log(e.yellow(i.t("config.clear_model_unsupported",{tool:o})))}if(!n.isToolInstalled(s)){if(d.nonInteractive)return void console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[s].displayName})));console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[s].displayName})));const{shouldInstall:t}=await o.prompt([{type:"confirm",name:"shouldInstall",message:i.t("wizard.install_tool_confirm"),default:!0}]);if(!t)return void console.log(e.yellow(i.t("wizard.install_skipped")));try{await n.installTool(s)}catch(o){return console.error(e.red(i.t("install.install_failed_detail"))),void(o instanceof Error&&o.message&&console.error(e.gray(o.message)))}}if(d.nonInteractive||d.force){const o=r.getApiKeyForTool(s);if(!o)return void console.log(e.red(i.t("wizard.api_key_required")));if(d.force&&!d.nonInteractive&&!await a({message:i.t("config.confirm_force",{tool:l[s].displayName}),defaultValue:!1}))return;return await n.applyPrivateConfig(s,o,r.getModelsForTool(s),{force:d.force}),d.force&&console.log(e.yellow(i.t("config.force_done",{tool:l[s].displayName}))),console.log(e.green(i.t("config.tool_config_loaded",{tool:l[s].displayName}))),void n.applyNotes(s).forEach(o=>console.log(e.yellow(o)))}await t.showToolMenu(s)}else p(s,"backups")}export async function configCommand(t){const{positional:n,options:p}=function(o){const e=[],t={};(f()||d())&&(t.nonInteractive=!0);for(const n of o)"--non-interactive"===n||"-y"===n?t.nonInteractive=!0:"--force"===n||"-f"===n?t.force=!0:e.push(n);return{positional:e,options:t}}(t),y=n[0],v=n.slice(1);if(y){switch(y){case"profile":return void await async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=r.getActiveProfileName(),t=r.listProfiles().map(t=>{const n=t===o;return`${n?e.green("●"):e.gray("○")} ${t}${n?e.gray(" ("+i.t("config.profile_active_label")+")"):""}`});return void u(i.t("config.profile_list_title"),t)}if("create"===t){const o=m(n,"profile");return r.listProfiles().includes(o)?void console.log(e.yellow(i.t("config.profile_exists",{name:o}))):(r.createProfile(o),void console.log(e.green(i.t("config.profile_created",{name:o}))))}if("use"===t){const o=m(n,"profile");return r.setActiveProfile(o),void console.log(e.green(i.t("config.profile_activated",{name:o})))}if("delete"===t||"remove"===t){const o=m(n,"profile");return o===s&&1===r.listProfiles().length?void console.log(e.yellow(i.t("config.profile_cannot_delete_last"))):void await c({description:i.t("config.profile_delete_dry_run",{name:o}),json:{action:"profile_delete",name:o},apply:async()=>{await a({message:i.t("config.profile_delete_confirm",{name:o}),defaultValue:!1})?(r.deleteProfile(o),console.log(e.green(i.t("config.profile_deleted",{name:o})))):console.log(e.yellow(i.t("config.profile_delete_aborted")))}})}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"preset":return void function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=Object.entries(r.getCustomPresets()).map(([o,t])=>`${e.cyan(o)} ${e.gray(`H:${t.models.haiku} S:${t.models.sonnet} O:${t.models.opus}`)}`);return void u(i.t("config.preset_list_title"),o)}if("save"===t){const o=m(n,"preset");return r.saveCustomPreset(o,r.getModels()),void console.log(e.green(i.t("config.preset_saved",{name:o})))}if("use"===t||"apply"===t){const o=m(n,"preset"),t=r.getCustomPresets()[o];return t?(r.setModels(t.models),void console.log(e.green(i.t("config.preset_applied",{name:o})))):void console.log(e.red(i.t("config.preset_not_found",{name:o})))}if("delete"===t||"remove"===t){const o=m(n,"preset");return r.deleteCustomPreset(o),void console.log(e.green(i.t("config.preset_deleted",{name:o})))}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"tool-model":return void function(o){const t=o[0];if(!t||"list"===t){const o=r.getProfile().tool_models||{},t=Object.entries(o).map(([o,t])=>{const n=Object.entries(t).map(([o,e])=>`${o}=${e}`).join(" ");return`${e.cyan(o)} ${e.gray(n)}`});return void u(i.t("config.tool_model_list_title"),t)}if("set"===t){const t=(o[1]||"").trim(),n=o.length>=4?(o[2]||"").trim():"opus",s=(o.length>=4?o[3]:o[2]||"").trim();return l[t]?s&&g.test(n)?(r.setToolModel(t,{[n]:s}),void console.log(e.green(i.t("config.tool_model_set",{tool:t,slot:n,model:s})))):void console.log(e.red(i.t("config.tool_model_usage"))):void console.log(e.red(i.t("config.unknown_tool",{tool:t})))}if("clear"===t||"remove"===t){const t=(o[1]||"").trim();return l[t]?(r.setToolModel(t,null),void console.log(e.green(i.t("config.tool_model_cleared",{tool:t})))):void console.log(e.red(i.t("config.unknown_tool",{tool:t})))}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"backup":return void await function(o){return async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=r.listBackups().map(o=>{const t=new Date(o.mtimeMs).toISOString();return`${e.cyan(o.name)} ${e.gray(t)}`});return void u(i.t("config.backup_list_title"),o)}if("create"===t||"snapshot"===t){const o=r.createBackup(n);return void console.log(e.green(i.t("config.backup_created",{path:o})))}if("restore"===t)return n?void await c({description:i.t("config.backup_restore_dry_run",{name:n}),json:{action:"backup_restore",name:n},apply:async()=>{await a({message:i.t("config.backup_restore_confirm",{name:n}),defaultValue:!1})?(r.restoreBackup(n),console.log(e.green(i.t("config.backup_restored",{name:n})))):console.log(e.yellow(i.t("config.backup_restore_aborted")))}}):void console.log(e.red(i.t("config.backup_restore_missing_name")));console.log(e.red(i.t("config.unknown_action",{action:t})))}(o)}(v)}"claude-code"!==y&&"claude-code"!==v[0]?l[y]?await _(y,v,p):(console.error(e.red(i.t("config.unknown_command",{command:y}))),console.log(e.gray(i.t("config.usage_hint"))),Object.values(l).filter(o=>!o.hidden).forEach(o=>{console.log(e.gray(` - ${o.name}: ${o.displayName}`))})):await _("claude-code",v,p)}else await async function(t){if(t.nonInteractive)return void console.log(e.red(i.t("config.requires_argument")));const{selectedTool:n}=await o.prompt([{type:"list",name:"selectedTool",message:i.t("wizard.select_tool"),choices:Object.values(l).filter(o=>!o.hidden).map(o=>({name:`${o.displayName} (${o.name})`,value:o.name}))}]);await _(n,[],t)}(p)}
|
|
@@ -3,7 +3,22 @@ import { DEFAULT_MODELS } from './config.js';
|
|
|
3
3
|
* settings.json 里所有"钉死模型"的 env 变量。写入、卸载与 clearPinnedModels
|
|
4
4
|
* 共用这一份清单——新增模型槽时只改这里,避免某条路径漏清导致残留。
|
|
5
5
|
*/
|
|
6
|
-
export declare const MODEL_ENV_VARS: readonly ["ANTHROPIC_DEFAULT_HAIKU_MODEL", "ANTHROPIC_DEFAULT_SONNET_MODEL", "ANTHROPIC_DEFAULT_OPUS_MODEL", "ANTHROPIC_MODEL", "ANTHROPIC_REASONING_MODEL"];
|
|
6
|
+
export declare const MODEL_ENV_VARS: readonly ["ANTHROPIC_DEFAULT_HAIKU_MODEL", "ANTHROPIC_DEFAULT_SONNET_MODEL", "ANTHROPIC_DEFAULT_OPUS_MODEL", "ANTHROPIC_DEFAULT_FABLE_MODEL", "ANTHROPIC_MODEL", "ANTHROPIC_REASONING_MODEL"];
|
|
7
|
+
export interface TierFallback {
|
|
8
|
+
tier: string;
|
|
9
|
+
envVar: string;
|
|
10
|
+
/** Claude Code 该档位内置解析到的模型(Key 用不了)。 */
|
|
11
|
+
from: string;
|
|
12
|
+
/** 实际钉上的替代模型。 */
|
|
13
|
+
to: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Claude Code 的档位别名会解析成它内置的模型(如 opus → claude-opus-5-5),Key 所在
|
|
17
|
+
* 分组没有这个模型时请求直接失败。按 models.json 的 `claudeCode.tierChains` 找出第一个
|
|
18
|
+
* Key 能用的替代模型钉到对应 env。内置模型可用、链上没有可用模型、或拿不到模型列表
|
|
19
|
+
* (离线)时都不钉;只会钉链上的 Claude 模型,不会把 GPT 等其它模型配给 Claude Code。
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveTierFallbacks(available?: string[]): TierFallback[];
|
|
7
22
|
export interface ClaudeCodeSettingsConfig {
|
|
8
23
|
env?: {
|
|
9
24
|
ANTHROPIC_AUTH_TOKEN?: string;
|
|
@@ -11,10 +26,12 @@ export interface ClaudeCodeSettingsConfig {
|
|
|
11
26
|
ANTHROPIC_DEFAULT_HAIKU_MODEL?: string;
|
|
12
27
|
ANTHROPIC_DEFAULT_SONNET_MODEL?: string;
|
|
13
28
|
ANTHROPIC_DEFAULT_OPUS_MODEL?: string;
|
|
29
|
+
ANTHROPIC_DEFAULT_FABLE_MODEL?: string;
|
|
14
30
|
ANTHROPIC_MODEL?: string;
|
|
15
31
|
ANTHROPIC_REASONING_MODEL?: string;
|
|
16
32
|
API_TIMEOUT_MS?: string;
|
|
17
33
|
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC?: number;
|
|
34
|
+
CLAUDE_CODE_AUTO_MODE_SERVER?: string;
|
|
18
35
|
[key: string]: any;
|
|
19
36
|
};
|
|
20
37
|
[key: string]: any;
|
|
@@ -38,6 +55,7 @@ export declare class ClaudeCodeManager {
|
|
|
38
55
|
private static instance;
|
|
39
56
|
private settingsPath;
|
|
40
57
|
private mcpConfigPath;
|
|
58
|
+
private lastTierFallbacks;
|
|
41
59
|
private constructor();
|
|
42
60
|
static getInstance(): ClaudeCodeManager;
|
|
43
61
|
/**
|
|
@@ -63,8 +81,9 @@ export declare class ClaudeCodeManager {
|
|
|
63
81
|
saveMCPConfig(config: ClaudeCodeMCPConfig): void;
|
|
64
82
|
/**
|
|
65
83
|
* 加载私有 NewAPI 配置到 Claude Code
|
|
84
|
+
* @param availableModels Key 在网关 `/v1/models` 能看到的模型;缺省(离线)时不做档位回退
|
|
66
85
|
*/
|
|
67
|
-
loadPrivateConfig(apiKey: string, models: typeof DEFAULT_MODELS): void;
|
|
86
|
+
loadPrivateConfig(apiKey: string, models: typeof DEFAULT_MODELS, availableModels?: string[]): void;
|
|
68
87
|
/**
|
|
69
88
|
* 确保 .claude.json 中有 hasCompletedOnboarding: true
|
|
70
89
|
*/
|
|
@@ -76,10 +95,14 @@ export declare class ClaudeCodeManager {
|
|
|
76
95
|
/**
|
|
77
96
|
* 只摘掉钉死的模型(env 里的 ANTHROPIC_*_MODEL + 顶层 model),保留凭据与
|
|
78
97
|
* 用户的 hooks / MCP / 插件配置。用于把 Claude Code 交还给自带默认模型,
|
|
79
|
-
* 让 /model 列表恢复完整(新上线的模型不再被旧配置挡住)。
|
|
98
|
+
* 让 /model 列表恢复完整(新上线的模型不再被旧配置挡住)。Key 用不了的内置档位
|
|
99
|
+
* 模型仍按 {@link resolveTierFallbacks} 保留回退钉子,否则清完就不能用了。
|
|
100
|
+
* @param availableModels Key 在网关能看到的模型;缺省(离线)时不保留回退
|
|
80
101
|
* @returns 实际被清除的键名(未改动时为空数组)
|
|
81
102
|
*/
|
|
82
|
-
clearPinnedModels(): string[];
|
|
103
|
+
clearPinnedModels(availableModels?: string[]): string[];
|
|
104
|
+
/** 最近一次 loadPrivateConfig 实际写入的档位回退(用于应用后的提示)。 */
|
|
105
|
+
getLastTierFallbacks(): TierFallback[];
|
|
83
106
|
/**
|
|
84
107
|
* 检测当前 Claude Code 配置的 API Key
|
|
85
108
|
* @returns 包含 API Key 的对象
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as e,mkdirSync as t,readFileSync as n,writeFileSync as s,renameSync as o,unlinkSync as
|
|
1
|
+
import{existsSync as e,mkdirSync as t,readFileSync as n,writeFileSync as s,renameSync as o,unlinkSync as r}from"fs";import{join as i,dirname as a}from"path";import{homedir as l}from"os";import{logger as c}from"../utils/logger.js";import{configManager as g,DEFAULT_MODELS as C}from"./config.js";import{loadSettingsTemplate as O}from"./settings-template.js";import{cleanupAnthropicEnvVars as d}from"./env-cleanup.js";import{getClaudeCodeTierChains as h}from"./model-registry.js";import{baseModelId as _}from"./model-catalog.js";export const MODEL_ENV_VARS=["ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL","ANTHROPIC_MODEL","ANTHROPIC_REASONING_MODEL"];const E={opus:"ANTHROPIC_DEFAULT_OPUS_MODEL",sonnet:"ANTHROPIC_DEFAULT_SONNET_MODEL",haiku:"ANTHROPIC_DEFAULT_HAIKU_MODEL",fable:"ANTHROPIC_DEFAULT_FABLE_MODEL"};export function resolveTierFallbacks(e){if(!e||0===e.length)return[];const t=new Set(e.map(_)),n=[];for(const[e,s]of Object.entries(h())){const o=E[e],[r,...i]=s;if(!o||!r||t.has(r))continue;const a=i.find(e=>t.has(e));a&&n.push({tier:e,envVar:o,from:r,to:a})}return n}export class ClaudeCodeManager{static instance;settingsPath;mcpConfigPath;lastTierFallbacks=[];constructor(){this.settingsPath=i(l(),".claude","settings.json"),this.mcpConfigPath=i(l(),".claude.json")}static getInstance(){return ClaudeCodeManager.instance||(ClaudeCodeManager.instance=new ClaudeCodeManager),ClaudeCodeManager.instance}ensureConfigDir(n){const s=a(n);e(s)||t(s,{recursive:!0})}atomicWrite(t,n){const i=`${t}.tmp`;try{s(i,n,"utf-8"),o(i,t)}catch(t){if(e(i))try{r(i)}catch{}throw t}}getSettings(){try{if(e(this.settingsPath)){const e=n(this.settingsPath,"utf-8");return JSON.parse(e)}}catch(e){c.warn("Failed to read Claude Code settings:",e),c.logError("ClaudeCodeManager.getSettings",e)}return{}}saveSettings(e){try{this.ensureConfigDir(this.settingsPath),this.atomicWrite(this.settingsPath,JSON.stringify(e,null,2))}catch(e){throw new Error(`Failed to save Claude Code settings: ${e}`)}}getMCPConfig(){try{if(e(this.mcpConfigPath)){const e=n(this.mcpConfigPath,"utf-8");return JSON.parse(e)}}catch(e){c.warn("Failed to read Claude Code MCP config:",e),c.logError("ClaudeCodeManager.getMCPConfig",e)}return{}}saveMCPConfig(e){try{this.ensureConfigDir(this.mcpConfigPath),this.atomicWrite(this.mcpConfigPath,JSON.stringify(e,null,2))}catch(e){throw new Error(`Failed to save Claude Code MCP config: ${e}`)}}loadPrivateConfig(e,t,n){this.ensureOnboardingCompleted(),d();const s=O(),o=s.env||{},{env:r,...i}=s,a=this.getSettings(),{ANTHROPIC_API_KEY:l,...c}=a.env||{},h={...c};for(const e of MODEL_ENV_VARS)delete h[e];const _={},E=e=>{const n=(t[e]||"").trim();return n&&n!==C[e]?n:null},f=E("haiku"),u=E("sonnet"),m=E("opus"),T=new Set([f&&"haiku",u&&"sonnet",m&&"opus"].filter(Boolean));this.lastTierFallbacks=resolveTierFallbacks(n).filter(e=>!T.has(e.tier));for(const e of this.lastTierFallbacks)_[e.envVar]=e.to;f&&(_.ANTHROPIC_DEFAULT_HAIKU_MODEL=f),u&&(_.ANTHROPIC_DEFAULT_SONNET_MODEL=u),m&&(_.ANTHROPIC_DEFAULT_OPUS_MODEL=m,_.ANTHROPIC_MODEL=m);const A={...a};for(const[e,t]of Object.entries(i))e in A||(A[e]=t);A.showThinkingSummaries=!0;const P={...A,env:{...h,...Object.fromEntries(Object.entries(o).filter(([e])=>!(e in h))),ANTHROPIC_AUTH_TOKEN:e,ANTHROPIC_BASE_URL:g.getBaseUrl(),..._}};m?P.model=m:Object.prototype.hasOwnProperty.call(i,"model")?P.model=i.model:delete P.model,this.saveSettings(P)}ensureOnboardingCompleted(){try{const e=this.getMCPConfig();e.hasCompletedOnboarding||this.saveMCPConfig({...e,hasCompletedOnboarding:!0})}catch(e){c.warn("Failed to ensure onboarding completed:",e),c.logError("ClaudeCodeManager.ensureOnboardingCompleted",e)}}unloadPrivateConfig(){const e=this.getSettings();if(!e.env){if(void 0!==e.model){const{model:t,...n}=e;this.saveSettings(n)}return}const{ANTHROPIC_AUTH_TOKEN:t,ANTHROPIC_BASE_URL:n,API_TIMEOUT_MS:s,CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:o,CLAUDE_CODE_AUTO_MODE_SERVER:r,...i}=e.env,a={...i};for(const e of MODEL_ENV_VARS)delete a[e];const l={...e,env:a};delete l.model,l.env&&0===Object.keys(l.env).length&&delete l.env,this.saveSettings(l)}clearPinnedModels(e){const t=this.getSettings(),n=t.env,s=n?.ANTHROPIC_AUTH_TOKEN?Object.fromEntries(resolveTierFallbacks(e).map(e=>[e.envVar,e.to])):{},o=[];for(const e of MODEL_ENV_VARS)n&&e in n&&n[e]!==s[e]&&o.push(e);void 0!==t.model&&o.push("model");const r=Object.entries(s).some(([e,t])=>n?.[e]!==t);if(0===o.length&&!r)return[];const i={...t};if(delete i.model,n){const e={...n};for(const t of MODEL_ENV_VARS)delete e[t];Object.assign(e,s),0===Object.keys(e).length?delete i.env:i.env=e}return this.saveSettings(i),o}getLastTierFallbacks(){return[...this.lastTierFallbacks]}detectCurrentConfig(){try{const e=this.getSettings();return e.env&&e.env.ANTHROPIC_AUTH_TOKEN?{apiKey:e.env.ANTHROPIC_AUTH_TOKEN}:{apiKey:null}}catch{return{apiKey:null}}}getExperimentalFeature(e){const t=this.getSettings();return t.env?.[e]}setExperimentalFeature(e,t){const n=this.getSettings(),s=n.env||{},o={...n,env:{...s,[e]:t}};this.saveSettings(o)}removeExperimentalFeature(e){const t=this.getSettings();if(!t.env)return;const{[e]:n,...s}=t.env,o={...t,env:s};this.saveSettings(o)}}export const claudeCodeManager=ClaudeCodeManager.getInstance();
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 会盖住模型选择,让 /model 里选不到新模型。这里统一负责把它们清掉:
|
|
5
5
|
* CLI 启动时检测一次(见 command.ts),给 Claude Code 写配置前再兜底一次。
|
|
6
6
|
*/
|
|
7
|
-
export declare const ANTHROPIC_ENV_VARS: readonly ["ANTHROPIC_API_KEY", "ANTHROPIC_BASE_URL", "ANTHROPIC_DEFAULT_HAIKU_MODEL", "ANTHROPIC_DEFAULT_SONNET_MODEL", "ANTHROPIC_DEFAULT_OPUS_MODEL", "ANTHROPIC_MODEL", "ANTHROPIC_REASONING_MODEL"];
|
|
7
|
+
export declare const ANTHROPIC_ENV_VARS: readonly ["ANTHROPIC_API_KEY", "ANTHROPIC_BASE_URL", "ANTHROPIC_DEFAULT_HAIKU_MODEL", "ANTHROPIC_DEFAULT_SONNET_MODEL", "ANTHROPIC_DEFAULT_OPUS_MODEL", "ANTHROPIC_DEFAULT_FABLE_MODEL", "ANTHROPIC_MODEL", "ANTHROPIC_REASONING_MODEL"];
|
|
8
8
|
/**
|
|
9
9
|
* 获取当前 shell 的 rc 文件路径(Windows 不使用 rc 文件,返回 null)。
|
|
10
10
|
*/
|
package/dist/lib/env-cleanup.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as e,readFileSync as r,writeFileSync as n}from"fs";import{join as t}from"path";import{logger as o}from"../utils/logger.js";import{toolHome as s}from"./tools/types.js";export const ANTHROPIC_ENV_VARS=["ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_MODEL","ANTHROPIC_REASONING_MODEL"];export function getShellRcFilePath(){if("win32"===process.platform)return null;const e=s();switch((process.env.SHELL||"").split("/").pop()||""){case"bash":return t(e,".bashrc");case"zsh":return t(e,".zshrc");case"fish":return t(e,".config","fish","config.fish");default:return t(e,".profile")}}export function cleanupShellRcEnvVars(){if("win32"===process.platform)return!1;try{const t=getShellRcFilePath();if(!t||!e(t))return!1;let s=r(t,"utf-8");const l=s,c=[...ANTHROPIC_ENV_VARS.map(e=>new RegExp(String.raw`^\s*export\s+${e}=.*$`,"gm")),/^\s*#\s*Claude Code environment variables\s*$/gm];for(const e of c)s=s.replace(e,"");if(s!==l)return n(t,s,"utf-8"),o.info(`Cleaned up ANTHROPIC_* environment variables from ${t}`),!0}catch(e){o.warn("Failed to cleanup shell environment variables:",e),o.logError("envCleanup.cleanupShellRcEnvVars",e)}return!1}export function cleanupAnthropicEnvVars(){const e=ANTHROPIC_ENV_VARS.filter(e=>!!process.env[e]);if(0===e.length)return[];cleanupShellRcEnvVars();for(const r of e)delete process.env[r];return[...e]}
|
|
1
|
+
import{existsSync as e,readFileSync as r,writeFileSync as n}from"fs";import{join as t}from"path";import{logger as o}from"../utils/logger.js";import{toolHome as s}from"./tools/types.js";export const ANTHROPIC_ENV_VARS=["ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL","ANTHROPIC_MODEL","ANTHROPIC_REASONING_MODEL"];export function getShellRcFilePath(){if("win32"===process.platform)return null;const e=s();switch((process.env.SHELL||"").split("/").pop()||""){case"bash":return t(e,".bashrc");case"zsh":return t(e,".zshrc");case"fish":return t(e,".config","fish","config.fish");default:return t(e,".profile")}}export function cleanupShellRcEnvVars(){if("win32"===process.platform)return!1;try{const t=getShellRcFilePath();if(!t||!e(t))return!1;let s=r(t,"utf-8");const l=s,c=[...ANTHROPIC_ENV_VARS.map(e=>new RegExp(String.raw`^\s*export\s+${e}=.*$`,"gm")),/^\s*#\s*Claude Code environment variables\s*$/gm];for(const e of c)s=s.replace(e,"");if(s!==l)return n(t,s,"utf-8"),o.info(`Cleaned up ANTHROPIC_* environment variables from ${t}`),!0}catch(e){o.warn("Failed to cleanup shell environment variables:",e),o.logError("envCleanup.cleanupShellRcEnvVars",e)}return!1}export function cleanupAnthropicEnvVars(){const e=ANTHROPIC_ENV_VARS.filter(e=>!!process.env[e]);if(0===e.length)return[];cleanupShellRcEnvVars();for(const r of e)delete process.env[r];return[...e]}
|
|
@@ -25,6 +25,15 @@ export interface ClaudeDesktopRules {
|
|
|
25
25
|
models: string[];
|
|
26
26
|
}>;
|
|
27
27
|
}
|
|
28
|
+
/** Claude Code tier aliases (`opus` / `sonnet` / `haiku` / `fable`) and how they degrade. */
|
|
29
|
+
export interface ClaudeCodeRules {
|
|
30
|
+
/**
|
|
31
|
+
* Per tier: the model Claude Code's alias resolves to by default, then the
|
|
32
|
+
* replacements to pin (in order) when the key cannot reach it — mirrors
|
|
33
|
+
* Claude Code's own `fallback_3p` chain.
|
|
34
|
+
*/
|
|
35
|
+
tierChains: Record<string, string[]>;
|
|
36
|
+
}
|
|
28
37
|
export interface ModelRegistryData {
|
|
29
38
|
defaultModels: Models;
|
|
30
39
|
/** Default model for non-Claude tools (Codex/OpenCode/OpenClaw/Hermes/AtomCode/Grok). */
|
|
@@ -32,6 +41,7 @@ export interface ModelRegistryData {
|
|
|
32
41
|
/** Per-tool default model. Empty string (e.g. claude-code) means "use the tool's built-in default". */
|
|
33
42
|
toolDefaults?: Record<string, string>;
|
|
34
43
|
presets: ModelPreset[];
|
|
44
|
+
claudeCode?: Partial<ClaudeCodeRules>;
|
|
35
45
|
claudeDesktop?: Partial<ClaudeDesktopRules>;
|
|
36
46
|
}
|
|
37
47
|
export declare function getDefaultModels(): Models;
|
|
@@ -45,5 +55,6 @@ export declare function getDefaultToolModel(): string;
|
|
|
45
55
|
export declare function getToolDefaultModel(toolName: string): string;
|
|
46
56
|
export declare function getPresets(): ModelPreset[];
|
|
47
57
|
export declare function resolvePreset(preset: ModelPreset): Models;
|
|
58
|
+
export declare function getClaudeCodeTierChains(): Record<string, string[]>;
|
|
48
59
|
export declare function getClaudeDesktopRules(): ClaudeDesktopRules;
|
|
49
60
|
export declare function reloadRegistry(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dirname as o,join as e}from"path";import{fileURLToPath as t}from"url";import{existsSync as
|
|
1
|
+
import{dirname as o,join as e}from"path";import{fileURLToPath as t}from"url";import{existsSync as n,readFileSync as l}from"fs";const r=o(t(import.meta.url));let s=null;function u(){return s||(s=function(){const o=[e(r,"..","..","models.json"),e(r,"..","models.json"),e(r,"models.json")];for(const e of o)if(n(e))return JSON.parse(l(e,"utf-8"));throw new Error(`models.json not found, searched: ${o.join(", ")}`)}()),s}export function getDefaultModels(){return{...u().defaultModels}}export function getDefaultToolModel(){return u().defaultToolModel?.trim()||"gpt-5.5"}export function getToolDefaultModel(o){const e=u().toolDefaults;return e&&Object.prototype.hasOwnProperty.call(e,o)?(e[o]??"").trim():getDefaultToolModel()}export function getPresets(){return[...u().presets]}export function resolvePreset(o){return o.models?{...o.models}:o.model?{haiku:o.model,sonnet:o.model,opus:o.model,reasoning:o.model}:getDefaultModels()}export function getClaudeCodeTierChains(){const o=u().claudeCode?.tierChains??{};return Object.fromEntries(Object.entries(o).map(([o,e])=>[o,[...e]]))}export function getClaudeDesktopRules(){const o=u().claudeDesktop??{};return{oneMillionFallback:[...o.oneMillionFallback??[]],oneMillionExclusions:(o.oneMillionExclusions??[]).map(o=>({...o,models:[...o.models]}))}}export function reloadRegistry(){s=null}
|
|
@@ -58,7 +58,7 @@ export declare class ToolManager {
|
|
|
58
58
|
* CLI's own per-tool model override so a later re-apply doesn't pin it back.
|
|
59
59
|
* @returns the config keys cleared in the tool's own config file
|
|
60
60
|
*/
|
|
61
|
-
clearPinnedModels(toolName: string): string[]
|
|
61
|
+
clearPinnedModels(toolName: string): Promise<string[]>;
|
|
62
62
|
/** Whether this tool supports clearing a pinned model. */
|
|
63
63
|
supportsClearPinnedModels(toolName: string): boolean;
|
|
64
64
|
detectCurrentConfig(toolName: string): {
|
package/dist/lib/tool-manager.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{execSync as o}from"child_process";import{i18n as n}from"./i18n.js";import t from"inquirer";import l from"chalk";import e from"terminal-link";import s from"ora";import{logger as i}from"../utils/logger.js";import{configManager as
|
|
1
|
+
import{execSync as o}from"child_process";import{i18n as n}from"./i18n.js";import t from"inquirer";import l from"chalk";import e from"terminal-link";import s from"ora";import{logger as i}from"../utils/logger.js";import{configManager as a}from"./config.js";import{getAdapter as r,listAdapters as c,TOOL_ADAPTERS as d}from"./tools/registry.js";import{backupBeforeWrite as g,listBackups as m,restoreBackup as p}from"./tools/backup.js";import{existsSync as u,rmSync as f}from"fs";import{resolveModelCatalog as w}from"./model-catalog.js";function h(o){const n=d[o];return{name:n.name,command:n.command,installCommand:n.installCommand,configPath:n.configPath,displayName:n.displayName,...n.hidden?{hidden:!0}:{}}}export const SUPPORTED_TOOLS=Object.fromEntries(Object.keys(d).map(o=>[o,h(o)]));export class ToolManager{static instance;constructor(){}static getInstance(){return ToolManager.instance||(ToolManager.instance=new ToolManager),ToolManager.instance}isToolInstalled(n){const t=SUPPORTED_TOOLS[n];if(!t)return!1;const l=r(n);if(l?.isInstalled)try{return l.isInstalled()}catch{return!1}try{const n="win32"===process.platform?`where ${t.command}`:`which ${t.command}`;return o(n,{stdio:"pipe"}),!0}catch{return!1}}async installTool(a){const r=SUPPORTED_TOOLS[a];if(!r)throw new Error(`Unknown tool: ${a}`);const c=s(n.t("wizard.installing_tool")).start();try{c.info(l.gray("$ ")+l.white(r.installCommand)),c.stop(),o(r.installCommand,{stdio:"inherit"}),c.succeed(n.t("wizard.tool_installed"))}catch(s){c.fail(n.t("wizard.install_failed"));const d=(s.message||"")+(s.stderr?.toString()||"")+(s.stdout?.toString()||"");if(!(d.includes("EACCES")||d.includes("permission denied")||d.includes("EPERM")||243===s.status))throw new Error(`Failed to install ${r.displayName}: ${s}`);if(console.log("\n⚠️ "+n.t("install.permission_detected")+"\n"),"win32"===process.platform)try{const t=r.installCommand.replace("npm install -g","npm install -g --force");return console.log("🔧 "+n.t("install.trying_solution",{num:"1",desc:n.t("install.using_force")})),console.log(l.gray("$ ")+l.white(t)),o(t,{stdio:"inherit"}),void console.log("\n✅ "+n.t("install.permission_fixed"))}catch(o){i.warn("Retry install failed:",o),console.log("\n❌ "+n.t("install.auto_fix_failed")),console.log(l.yellow("\n📌 "+n.t("install.windows_solutions"))),console.log(""),console.log(l.cyan.bold(n.t("install.windows_solution_1_title"))),console.log(l.gray(" "+n.t("install.windows_solution_1_step1"))),console.log(l.gray(" "+n.t("install.windows_solution_1_step2"))),console.log(l.gray(" "+n.t("install.windows_solution_1_step3"))),console.log(l.white(` ${r.installCommand}`)),console.log(""),console.log(l.cyan.bold(n.t("install.windows_solution_2_title"))),console.log(l.gray(" "+n.t("install.windows_solution_2_command"))),console.log(l.white(` ${r.installCommand.replace("npm install -g","npm install -g --prefix=%APPDATA%\\npm")}`)),console.log("");const{action:e}=await t.prompt([{type:"list",name:"action",message:n.t("install.what_next"),choices:[{name:n.t("install.installed_continue"),value:"continue"},{name:n.t("install.cancel_install"),value:"cancel"}]}]);if("cancel"===e)throw new Error(n.t("install.user_cancelled"));if(!this.isToolInstalled(a))throw console.log(l.red("\n❌ "+n.t("install.still_not_installed",{tool:r.displayName}))),new Error(`${r.displayName} is not installed`);return void console.log(l.green("\n✅ "+n.t("install.verified_success",{tool:r.displayName})))}console.log(l.yellow("\n📌 "+n.t("install.unix_solutions"))),console.log(""),console.log(l.cyan.bold(n.t("install.unix_solution_1_title"))),console.log(l.gray(" "+n.t("install.unix_solution_1_desc"))),console.log(l.white(` sudo ${r.installCommand}`)),console.log("");const g="https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally",m=e(g,g,{fallback:()=>g});console.log(l.cyan.bold(n.t("install.unix_solution_2_title"))),console.log(l.gray(" "+n.t("install.unix_solution_2_desc"))),console.log(l.blue(" 📖 "+n.t("install.npm_docs_link")+": ")+m),console.log("");const{action:p}=await t.prompt([{type:"list",name:"action",message:n.t("install.what_next"),choices:[{name:n.t("install.installed_continue"),value:"continue"},{name:n.t("install.cancel_install"),value:"cancel"}]}]);if("cancel"===p)throw new Error(n.t("install.user_cancelled"));if(!this.isToolInstalled(a))throw console.log(l.red("\n❌ "+n.t("install.still_not_installed",{tool:r.displayName}))),new Error(`${r.displayName} is not installed`);console.log(l.green("\n✅ "+n.t("install.verified_success",{tool:r.displayName})))}}getToolConfig(o){const n=r(o);if(!n)throw new Error(`Unknown tool: ${o}`);try{return n.getConfig()}catch(n){return i.warn(`Failed to read config for ${o}:`,n),i.logError(`ToolManager.getToolConfig(${o})`,n),null}}updateToolConfig(o,n){const t=r(o);if(!t)throw new Error(`Unknown tool: ${o}`);if(!t.updateConfig)throw new Error(`Tool ${o} does not support raw config updates`);t.updateConfig(n)}forceResetConfig(o){const n=r(o);if(!n)throw new Error(`Unknown tool: ${o}`);const t=n.forceResetPaths?n.forceResetPaths():this.backupPathsFor(n),l=[];for(const o of t)u(o)&&(g(o),f(o,{force:!0}),l.push(o));return l}loadPrivateConfig(o,n,t,l,e={}){const s=r(o);if(!s)throw new Error(`Unknown tool: ${o}`);e.force&&this.forceResetConfig(o),s.loadPrivateConfig({apiKey:n,baseUrl:a.getBaseUrl(),models:t,settings:a.getToolSettings(o),...l?{catalog:l}:{}})}async applyPrivateConfig(o,n,t,l={}){const e=r(o);if(!e)throw new Error(`Unknown tool: ${o}`);const s=e.wantsModelCatalog?await w(n):null;l.force?this.loadPrivateConfig(o,n,t,s??void 0,{force:!0}):s?this.loadPrivateConfig(o,n,t,s):this.loadPrivateConfig(o,n,t)}applyNotes(o){const n=r(o);if(!n?.applyNotes)return[];try{return n.applyNotes()}catch(n){return i.logError(`ToolManager.applyNotes(${o})`,n),[]}}unloadPrivateConfig(o){const n=r(o);if(!n)throw new Error(`Unknown tool: ${o}`);n.unloadPrivateConfig()}async clearPinnedModels(o){const n=r(o);if(!n)throw new Error(`Unknown tool: ${o}`);if(a.setToolModel(o,null),!n.clearPinnedModels)return[];const t=a.getApiKeyForTool(o),l=n.wantsModelCatalog&&t?await w(t):null;return n.clearPinnedModels(l??void 0)}supportsClearPinnedModels(o){return Boolean(r(o)?.clearPinnedModels)}detectCurrentConfig(o){const n=r(o);if(!n)throw new Error(`Unknown tool: ${o}`);return n.detectCurrentConfig()}backupPathsFor(o){return o.backupPaths?o.backupPaths():[o.configPath]}listToolBackups(o){const n=r(o);if(!n)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(n).map(o=>({file:o,backups:m(o)}))}restorePrivateConfig(o){const n=r(o);if(!n)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(n).map(o=>({file:o,result:p(o)}))}getInstalledTools(){return Object.keys(SUPPORTED_TOOLS).filter(o=>this.isToolInstalled(o))}getSupportedTools(){return c().filter(o=>!o.hidden).map(o=>h(o.name))}isGitInstalled(){try{const n="win32"===process.platform?"where git":"which git";return o(n,{stdio:"pipe"}),!0}catch{return!1}}}export const toolManager=ToolManager.getInstance();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join as e}from"path";import{homedir as
|
|
1
|
+
import{join as e}from"path";import{homedir as o}from"os";import{claudeCodeManager as t}from"../claude-code-manager.js";import{backupBeforeWrite as a}from"./backup.js";import{i18n as n}from"../i18n.js";const i=e(o(),".claude","settings.json"),s=e(o(),".claude.json");export const claudeCodeAdapter={name:"claude-code",displayName:"Claude Code",command:"claude",installCommand:"npm install -g @anthropic-ai/claude-code",configPath:i,wantsModelCatalog:!0,loadPrivateConfig(e){a(i),a(s),t.loadPrivateConfig(e.apiKey,e.models,e.catalog?.models)},unloadPrivateConfig(){a(i),t.unloadPrivateConfig()},detectCurrentConfig:()=>t.detectCurrentConfig(),getConfig:()=>({settings:t.getSettings(),mcp:t.getMCPConfig()}),updateConfig(e){const o=e||{};o.settings&&t.saveSettings(o.settings),o.mcp&&t.saveMCPConfig(o.mcp)},clearPinnedModels:e=>(a(i),t.clearPinnedModels(e?.models)),applyNotes:()=>t.getLastTierFallbacks().map(e=>n.t("tools.claude_code.tier_fallback",{tier:e.tier,from:e.from,to:e.to})),backupPaths:()=>[i,s],forceResetPaths:()=>[i]};
|
|
@@ -73,10 +73,11 @@ export interface ToolAdapter {
|
|
|
73
73
|
/**
|
|
74
74
|
* Drop any pinned model selection while keeping credentials and the user's
|
|
75
75
|
* own config intact, handing the tool back to its built-in default model.
|
|
76
|
-
* Optional — only tools that can pin a model implement it.
|
|
76
|
+
* Optional — only tools that can pin a model implement it. Adapters with
|
|
77
|
+
* `wantsModelCatalog` also get the key's catalog (absent offline).
|
|
77
78
|
* @returns the config keys actually cleared (empty when nothing was pinned)
|
|
78
79
|
*/
|
|
79
|
-
clearPinnedModels?(): string[];
|
|
80
|
+
clearPinnedModels?(catalog?: ModelCatalog): string[];
|
|
80
81
|
/**
|
|
81
82
|
* Every file this adapter writes (and therefore snapshots) — used by restore.
|
|
82
83
|
* Defaults to `[configPath]` when omitted; multi-file tools (Codex auth.json,
|
package/dist/lib/wizard.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"inquirer";import t from"chalk";import o from"ora";import{configManager as a,DEFAULT_MODELS as i}from"./config.js";import{getPresets as n,resolvePreset as r,getToolDefaultModel as s}from"./model-registry.js";import{toolManager as l,SUPPORTED_TOOLS as c}from"./tool-manager.js";import{i18n as d,detectSystemLang as p}from"./i18n.js";import{createBorderLine as m,createContentLine as u}from"../utils/string-width.js";import{validateApiKey as g,fetchModels as w}from"./api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as _}from"./tools/codex.js";import{CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as f}from"./tools/claude-desktop.js";import{readFileSync as y}from"fs";import{dirname as h,join as z}from"path";import{fileURLToPath as v}from"url";const k=h(v(import.meta.url)),x=t.hex("#FF8700");export class Wizard{static instance;BOX_WIDTH=63;validatedApiKeys=new Set;constructor(){}static getInstance(){return Wizard.instance||(Wizard.instance=new Wizard),Wizard.instance}createBox(e){console.log(x.bold("\n"+m("╔","╗","═",this.BOX_WIDTH))),console.log(x.bold(u(e,"║","║",this.BOX_WIDTH,"center"))),console.log(x.bold(m("╚","╝","═",this.BOX_WIDTH))),console.log("")}showOperationHints(){const e=[t.gray(d.t("wizard.hint_navigate")),t.gray(d.t("wizard.hint_confirm"))];console.log(t.gray("💡 ")+e.join(t.gray(" | "))+"\n")}async promptWithHints(t){this.showOperationHints();const o=t.map(e=>"list"!==e.type||e.pageSize?e:{...e,pageSize:20});return e.prompt(o)}printBanner(){const e=65,t=d.t("wizard.banner_subtitle"),o=u(t,"║","║",e,"center"),a=u("","║","║",e,"center"),i=u(`API Helper v${function(){try{return JSON.parse(y(z(k,"..","..","package.json"),"utf-8")).version}catch{return"0.0.0"}}()}`,"║","║",e,"center"),n=[" ▄▀▄ █▀▄ █ █▄█ ██▀ █ █▀▄ ██▀ █▀▄ "," █▀█ █▀ █ █ █ █▄▄ █▄▄ █▀ █▄▄ █▀▄ "].map(t=>u(t,"║","║",e,"center")),r=[m("╔","╗","═",e),a,...n,a,i,o,m("╚","╝","═",e)];console.log(x.bold("\n"+r.join("\n")))}resetScreen(){console.clear(),this.printBanner()}printGoodbye(){const e=l.getSupportedTools().filter(e=>{try{return Boolean(l.detectCurrentConfig(e.name).apiKey)}catch{return!1}});let o;if(e.length>0){const t=e.map(e=>e.command).join(" / ");o=d.t("wizard.goodbye_message_tools",{commands:t}),e.some(e=>"claude-code"===e.name)&&(o+=" "+d.t("wizard.goodbye_claude_hint"))}else o=d.t("wizard.goodbye_message");console.log(t.green("\n👋 "+o))}async runFirstTimeSetup(){const e="zh_CN"===p();e&&(a.setLang("zh_CN"),d.setLocale("zh_CN")),this.resetScreen(),console.log(x.bold("\n"+d.t("wizard.welcome"))),console.log(t.gray(d.t("wizard.privacy_note")+"\n")),e?console.log(t.gray(d.t("wizard.lang_auto_zh")+"\n")):await this.configLanguage(),await this.configApiKey()&&await this.selectAndConfigureTool(!0)}async configLanguage(){for(;;){this.resetScreen(),this.createBox(d.t("wizard.select_language"));const o=d.getLocale(),{language:i}=await this.promptWithHints([{type:"list",name:"language",message:"✨ "+d.t("wizard.select_language"),choices:[{name:"[EN] English"+("en_US"===o?t.green(" ✓ ("+d.t("wizard.current_active")+")"):""),value:"en_US"},{name:"[CN] 中文"+("zh_CN"===o?t.green(" ✓ ("+d.t("wizard.current_active")+")"):""),value:"zh_CN"},new e.Separator,{name:"<- "+d.t("wizard.nav_return"),value:"back"},{name:"x "+d.t("wizard.nav_exit"),value:"exit"}],default:"zh_CN"}]);if("exit"===i)this.printGoodbye(),process.exit(0);else if("back"===i)return;return a.setLang(i),void d.setLocale(i)}}buildPresetChoices(){const o=n(),a=o.filter(e=>e.recommended),i=o.filter(e=>!e.recommended),r=e=>({name:(d.t(e.name)!==e.name?d.t(e.name):e.name)+(e.models?t.gray(` [H:${e.models.haiku} S:${e.models.sonnet} O:${e.models.opus}]`):""),value:{type:"preset",preset:e}}),s=[];return a.length>0&&(s.push(new e.Separator(t.hex("#FF8700")("── "+d.t("wizard.recommended")+" ──"))),s.push(...a.map(r))),i.length>0&&(s.push(new e.Separator(t.gray("── "+d.t("wizard.other_models")+" ──"))),s.push(...i.map(r))),s}async handleCustomModelInput(){const o=a.getModels(),{customMode:n}=await e.prompt([{type:"list",name:"customMode",message:d.t("wizard.custom_model_mode"),choices:[{name:d.t("wizard.custom_model_single"),value:"single"},{name:d.t("wizard.custom_model_per_role"),value:"per_role"}]}]);if("single"===n){const{customModel:t}=await e.prompt([{type:"input",name:"customModel",message:d.t("wizard.input_custom_model"),default:i.sonnet}]);a.setModels({haiku:t,sonnet:t,opus:t,reasoning:t})}else{const t=await e.prompt([{type:"input",name:"haiku",message:d.t("wizard.model_haiku"),default:o.haiku},{type:"input",name:"sonnet",message:d.t("wizard.model_sonnet"),default:o.sonnet},{type:"input",name:"opus",message:d.t("wizard.model_opus"),default:o.opus},{type:"input",name:"reasoning",message:d.t("wizard.model_reasoning"),default:o.reasoning}]);a.setModels(t)}console.log(t.green("\n✓ "+d.t("wizard.models_saved")))}async configModels(o){const i=a.getApiKey();if(await this.validatedKeyForConfiguration(i))for(;;){this.resetScreen(),this.createBox(d.t("wizard.config_models"));const i=[...this.buildPresetChoices()];i.push(new e.Separator),i.push({name:"✏️ "+d.t("wizard.custom_model_input"),value:{type:"custom_input"}}),i.push(new e.Separator),i.push({name:"<- "+d.t("wizard.nav_return"),value:{type:"back"}}),i.push({name:"x "+d.t("wizard.nav_exit"),value:{type:"exit"}});const{modelChoice:n}=await this.promptWithHints([{type:"list",name:"modelChoice",message:d.t("wizard.select_model_config"),choices:i}]);if("exit"===n.type)this.printGoodbye(),process.exit(0);else{if("back"===n.type)return;if("custom_input"===n.type)return await this.handleCustomModelInput(),void(o?.skipLoadPrompt||await this.promptLoadAfterModelConfig());if("preset"===n.type){const e=r(n.preset);return a.setModels(e),console.log(t.green("\n✓ "+d.t("wizard.models_saved"))),void(o?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}}}else await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}])}async promptLoadAfterModelConfig(){const{shouldLoad:t}=await e.prompt([{type:"list",name:"shouldLoad",message:d.t("wizard.load_config_now"),choices:[{name:d.t("wizard.load_config_yes"),value:!0},{name:d.t("wizard.load_config_later"),value:!1}]}]);t&&await this.selectAndConfigureTool()}async configApiKey(){for(;;){this.resetScreen(),this.createBox(d.t("wizard.input_api_key")),console.log(t.gray("\n💡 "+d.t("wizard.api_key_input_hint"))),console.log(t.gray(" "+d.t("wizard.api_key_get_hint",{url:"https://www.vibeapi.cn/console/token"}))),console.log();const{apiKey:i}=await e.prompt([{type:"password",name:"apiKey",message:d.t("wizard.input_your_api_key"),mask:"*"}]);if(!i||""===i.trim()){const{action:t}=await e.prompt([{type:"list",name:"action",message:d.t("wizard.select_action"),choices:[{name:d.t("wizard.retry_input"),value:"retry"},{name:"<- "+d.t("wizard.nav_return"),value:"back"}]}]);if("back"===t)return!1;continue}const n=o(d.t("wizard.validating_api_key")).start(),r=await g(i.trim());if(n.stop(),r.valid)return a.setApiKey(i.trim()),this.validatedApiKeys.add(i.trim()),console.log(t.green("\n✓ "+d.t("wizard.api_key_valid"))),!0;{this.validatedApiKeys.delete(i.trim()),"invalid_api_key"===r.error?console.log(t.red("\n✗ "+d.t("wizard.api_key_invalid"))):console.log(t.red("\n✗ "+d.t("wizard.api_key_network_error")));const{action:o}=await e.prompt([{type:"list",name:"action",message:d.t("wizard.select_action"),choices:[{name:d.t("wizard.retry_input"),value:"retry"},{name:"<- "+d.t("wizard.nav_return"),value:"back"}]}]);if("back"===o)return!1}}}async selectAndConfigureTool(t=!1){for(;;){this.resetScreen(),this.createBox(d.t("wizard.select_tool"));const o=l.getSupportedTools().map(e=>({name:e.displayName,value:e.name})),{tool:a}=await this.promptWithHints([{type:"list",name:"tool",message:"🛠️ "+d.t("wizard.select_tool"),choices:[...o,new e.Separator,{name:"<- "+d.t("wizard.nav_return"),value:"back"},{name:"x "+d.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===a)this.printGoodbye(),process.exit(0);else if("back"===a)return;await this.configureTool(a,t)}}async configureTool(o,a=!1){const i=c[o];if(i){if(!l.isToolInstalled(o)){console.log(t.yellow("\n"+d.t("wizard.tool_not_installed",{tool:i.displayName})));const{install:a}=await e.prompt([{type:"confirm",name:"install",message:d.t("wizard.install_tool_confirm"),default:!0}]);if(!a)return;try{await l.installTool(o)}catch{return void console.log(t.red(d.t("wizard.install_failed")))}}a?await this.configureToolModel(o)&&await this.loadConfig(o):await this.showToolMenu(o)}}async showToolMenu(t){for(;;){this.resetScreen();const o=c[t];if(!o)return;this.createBox(o.displayName+" "+d.t("wizard.menu_title"));const a=[{name:"📥 "+d.t("wizard.action_load_config",{tool:o.displayName}),value:"load"},{name:"📤 "+d.t("wizard.action_unload_config",{tool:o.displayName}),value:"unload"}];l.supportsClearPinnedModels(t)&&a.push({name:"🧹 "+d.t("wizard.action_clear_model",{tool:o.displayName}),value:"clear-model"}),a.push({name:"🧨 "+d.t("wizard.action_force_config",{tool:o.displayName}),value:"force"},{name:"↩️ "+d.t("wizard.action_restore_config",{tool:o.displayName}),value:"restore"},new e.Separator,{name:"<- "+d.t("wizard.nav_return"),value:"back"},{name:"x "+d.t("wizard.nav_exit"),value:"exit"});const{action:i}=await this.promptWithHints([{type:"list",name:"action",message:"⚙️ "+d.t("wizard.select_action"),choices:a}]);if("exit"===i)this.printGoodbye(),process.exit(0);else{if("back"===i)return;"load"===i?await this.configureToolModel(t)&&await this.loadConfig(t):"force"===i?await this.forceConfig(t):"unload"===i?await this.unloadConfig(t):"clear-model"===i?await this.clearPinnedModels(t):"restore"===i&&await this.restoreConfig(t)}}}singleModelOverride(e){const t=e.trim();return/claude/i.test(t)?{opus:t}:{haiku:t,sonnet:t,opus:t,reasoning:t}}hasConfiguredApiKey(){return!!a.getApiKey()?.trim()||a.listToolApiKeys().some(e=>Boolean(a.getApiKeyForTool(e)?.trim()))}async validatedKeyForConfiguration(e){const a=e?.trim();if(!a)return console.log(t.red("\n"+d.t("wizard.api_key_required"))),console.log(t.yellow(d.t("wizard.please_config_api_key_first"))),null;if(this.validatedApiKeys.has(a))return a;const i=o(d.t("wizard.validating_api_key")).start(),n=await g(a);if(n.valid)return this.validatedApiKeys.add(a),i.succeed(d.t("wizard.api_key_valid")),a;this.validatedApiKeys.delete(a);const r="invalid_api_key"===n.error?d.t("wizard.api_key_invalid"):d.t("wizard.api_key_network_error");return i.fail(r),console.log(t.red("\n"+d.t("wizard.please_reconfig_api_key"))),null}async configureToolModel(i){const n=c[i];if(!n)return!1;const l=await this.validatedKeyForConfiguration(a.getApiKeyForTool(i));if(!l)return await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}]),!1;const p="claude-code"===i,m=s(i),u=p||!m?d.t("wizard.model_builtin_default"):m;this.resetScreen(),this.createBox(n.displayName+" · "+d.t("wizard.config_models"));const g=[{name:"✅ "+d.t("wizard.use_default_model",{model:u}),value:{type:"default"}},{name:"🌐 "+d.t("wizard.fetch_models_from_api"),value:{type:"fetch"}},...this.buildPresetChoices(),new e.Separator,{name:"✏️ "+d.t("wizard.input_custom_model"),value:{type:"custom"}},new e.Separator,{name:"<- "+d.t("wizard.nav_return"),value:{type:"back"}}],{choice:y}=await this.promptWithHints([{type:"list",name:"choice",message:d.t("wizard.select_tool_model",{tool:n.displayName}),choices:g}]);if("back"===y.type)return!1;if("default"===y.type)a.setToolModel(i,null);else if("preset"===y.type)a.setToolModel(i,r(y.preset));else if("custom"===y.type){const{model:t}=await e.prompt([{type:"input",name:"model",message:d.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]),o=(t||"").trim();a.setToolModel(i,o?this.singleModelOverride(o):null)}else if("fetch"===y.type){const n=o(d.t("wizard.fetching_models")).start(),r=await w(l);let s;if(n.stop(),r.ok&&r.models.length>0){const{model:t}=await e.prompt([{type:"list",name:"model",message:d.t("wizard.select_fetched_model"),pageSize:20,choices:[...r.models,new e.Separator,{name:"<- "+d.t("wizard.nav_return"),value:"__back__"}]}]);if("__back__"===t)return!1;s=t}else{console.log(t.yellow("\n"+d.t("wizard.fetch_models_failed")));const{model:o}=await e.prompt([{type:"input",name:"model",message:d.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]);s=(o||"").trim()}a.setToolModel(i,s?this.singleModelOverride(s):null)}if("codex"===i){const t=a.getToolSetting(i,_),{enableOneMillionContext:o}=await e.prompt([{type:"confirm",name:"enableOneMillionContext",message:d.t("wizard.codex_enable_1m_context"),default:!1!==t}]);a.setToolSetting(i,_,Boolean(o))}if("claude-desktop"===i){const t=a.getToolSetting(i,f),{hideOfficialLogin:o}=await e.prompt([{type:"confirm",name:"hideOfficialLogin",message:d.t("wizard.desktop_hide_official_login"),default:!1!==t}]);a.setToolSetting(i,f,Boolean(o))}return console.log(t.green("\n✓ "+d.t("wizard.models_saved"))),p&&console.log(t.gray("💡 "+d.t("wizard.claude_model_hint"))),!0}async forceConfig(t){const o=c[t]?.displayName||t,{confirm:a}=await e.prompt([{type:"confirm",name:"confirm",message:d.t("config.confirm_force",{tool:o}),default:!1}]);a&&await this.loadConfig(t,{force:!0})}async loadConfig(i,n={}){const r=a.getModelsForTool(i),s=await this.validatedKeyForConfiguration(a.getApiKeyForTool(i));if(!s)return void await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}]);const p=o(d.t("wizard.loading_config")).start();try{await l.applyPrivateConfig(i,s,r,n),p.succeed(d.t("wizard.config_loaded",{tool:c[i]?.displayName||i})),n.force&&console.log(t.yellow(d.t("config.force_done",{tool:c[i]?.displayName||i})));const o=c[i]?.command;o&&console.log(t.green("\n"+d.t("wizard.run_tool_hint",{command:o})));for(const e of l.applyNotes(i))console.log(t.yellow("💡 "+e));const{nextAction:a}=await e.prompt([{type:"list",name:"nextAction",message:d.t("wizard.what_next"),choices:[{name:d.t("wizard.exit_and_start"),value:"exit"},{name:d.t("wizard.continue_config"),value:"continue"}]}]);"exit"===a&&(this.printGoodbye(),process.exit(0))}catch(o){p.fail(d.t("wizard.config_failed")),console.log(t.red(o instanceof Error?o.message:String(o))),await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}])}}async clearPinnedModels(o){const a=c[o]?.displayName||o,{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:d.t("wizard.confirm_clear_model",{tool:a}),default:!1}]);if(i){try{const e=l.clearPinnedModels(o);0===e.length?console.log(t.yellow("\n"+d.t("config.clear_model_none",{tool:a}))):(console.log(t.green("\n✓ "+d.t("config.clear_model_done",{tool:a}))),e.forEach(e=>console.log(t.gray(` - ${e}`))),console.log(t.gray(d.t("config.clear_model_restart_hint",{tool:a}))))}catch(e){console.log(t.red("\n"+(e instanceof Error?e.message:String(e))))}await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}])}}async unloadConfig(a){const{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:d.t("wizard.confirm_unload_config",{tool:c[a]?.displayName||a}),default:!1}]);if(!i)return;const n=o(d.t("wizard.unloading_config")).start();try{l.unloadPrivateConfig(a),n.succeed(d.t("wizard.config_unloaded"));const{nextAction:t}=await e.prompt([{type:"list",name:"nextAction",message:d.t("wizard.what_next"),choices:[{name:d.t("wizard.exit_and_start"),value:"exit"},{name:d.t("wizard.continue_config"),value:"continue"}]}]);"exit"===t&&(this.printGoodbye(),process.exit(0))}catch(o){n.fail(d.t("wizard.config_unload_failed")),console.log(t.red(o instanceof Error?o.message:String(o))),await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}])}}async restoreConfig(a){const i=c[a]?.displayName||a,{confirm:n}=await e.prompt([{type:"confirm",name:"confirm",message:d.t("wizard.confirm_restore_config",{tool:i}),default:!1}]);if(!n)return;const r=o(d.t("wizard.restoring_config")).start();try{const e=l.restorePrivateConfig(a).filter(e=>e.result.restored);0===e.length?r.warn(d.t("wizard.restore_no_backup")):(r.succeed(d.t("wizard.config_restored",{tool:i})),e.forEach(e=>console.log(t.gray(` ${e.file} ← ${e.result.from}`))))}catch(e){r.fail(d.t("wizard.config_restore_failed")),console.log(t.red(e instanceof Error?e.message:String(e)))}await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}])}async run(){await this.showMainMenu()}async showMainMenu(){if(this.hasConfiguredApiKey())for(;;){this.resetScreen();const o=a.getApiKey()||"",i=o.length>4?"sk-****"+o.slice(-4):"****";console.log(t.gray(` 🔑 API Key: ${i}`)+t.green(" ✓")),console.log("");const n=l.getSupportedTools().map(e=>({name:"🛠️ "+e.displayName,value:{type:"tool",tool:e.name}})),r=[new e.Separator(x("── "+d.t("wizard.select_tool")+" ──")),...n,new e.Separator(t.gray("── "+d.t("wizard.settings")+" ──")),{name:"🔑 "+d.t("wizard.menu_change_api_key"),value:{type:"apikey"}},{name:"🌐 "+d.t("wizard.menu_config_language"),value:{type:"language"}},new e.Separator,{name:"x "+d.t("wizard.nav_exit"),value:{type:"exit"}}],{action:s}=await this.promptWithHints([{type:"list",name:"action",message:"🛠️ "+d.t("wizard.select_tool"),choices:r}]);"exit"===s.type?(this.printGoodbye(),process.exit(0)):"tool"===s.type?await this.configureTool(s.tool):"apikey"===s.type?await this.configApiKey():"language"===s.type&&await this.configLanguage()}else await this.runFirstTimeSetup()}}export const wizard=Wizard.getInstance();
|
|
1
|
+
import e from"inquirer";import t from"chalk";import o from"ora";import{configManager as a,DEFAULT_MODELS as i}from"./config.js";import{getPresets as n,resolvePreset as r,getToolDefaultModel as s}from"./model-registry.js";import{toolManager as l,SUPPORTED_TOOLS as c}from"./tool-manager.js";import{i18n as d,detectSystemLang as p}from"./i18n.js";import{createBorderLine as m,createContentLine as u}from"../utils/string-width.js";import{validateApiKey as g,fetchModels as w}from"./api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as _}from"./tools/codex.js";import{CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as f}from"./tools/claude-desktop.js";import{readFileSync as y}from"fs";import{dirname as h,join as z}from"path";import{fileURLToPath as v}from"url";const k=h(v(import.meta.url)),x=t.hex("#FF8700");export class Wizard{static instance;BOX_WIDTH=63;validatedApiKeys=new Set;constructor(){}static getInstance(){return Wizard.instance||(Wizard.instance=new Wizard),Wizard.instance}createBox(e){console.log(x.bold("\n"+m("╔","╗","═",this.BOX_WIDTH))),console.log(x.bold(u(e,"║","║",this.BOX_WIDTH,"center"))),console.log(x.bold(m("╚","╝","═",this.BOX_WIDTH))),console.log("")}showOperationHints(){const e=[t.gray(d.t("wizard.hint_navigate")),t.gray(d.t("wizard.hint_confirm"))];console.log(t.gray("💡 ")+e.join(t.gray(" | "))+"\n")}async promptWithHints(t){this.showOperationHints();const o=t.map(e=>"list"!==e.type||e.pageSize?e:{...e,pageSize:20});return e.prompt(o)}printBanner(){const e=65,t=d.t("wizard.banner_subtitle"),o=u(t,"║","║",e,"center"),a=u("","║","║",e,"center"),i=u(`API Helper v${function(){try{return JSON.parse(y(z(k,"..","..","package.json"),"utf-8")).version}catch{return"0.0.0"}}()}`,"║","║",e,"center"),n=[" ▄▀▄ █▀▄ █ █▄█ ██▀ █ █▀▄ ██▀ █▀▄ "," █▀█ █▀ █ █ █ █▄▄ █▄▄ █▀ █▄▄ █▀▄ "].map(t=>u(t,"║","║",e,"center")),r=[m("╔","╗","═",e),a,...n,a,i,o,m("╚","╝","═",e)];console.log(x.bold("\n"+r.join("\n")))}resetScreen(){console.clear(),this.printBanner()}printGoodbye(){const e=l.getSupportedTools().filter(e=>{try{return Boolean(l.detectCurrentConfig(e.name).apiKey)}catch{return!1}});let o;if(e.length>0){const t=e.map(e=>e.command).join(" / ");o=d.t("wizard.goodbye_message_tools",{commands:t}),e.some(e=>"claude-code"===e.name)&&(o+=" "+d.t("wizard.goodbye_claude_hint"))}else o=d.t("wizard.goodbye_message");console.log(t.green("\n👋 "+o))}async runFirstTimeSetup(){const e="zh_CN"===p();e&&(a.setLang("zh_CN"),d.setLocale("zh_CN")),this.resetScreen(),console.log(x.bold("\n"+d.t("wizard.welcome"))),console.log(t.gray(d.t("wizard.privacy_note")+"\n")),e?console.log(t.gray(d.t("wizard.lang_auto_zh")+"\n")):await this.configLanguage(),await this.configApiKey()&&await this.selectAndConfigureTool(!0)}async configLanguage(){for(;;){this.resetScreen(),this.createBox(d.t("wizard.select_language"));const o=d.getLocale(),{language:i}=await this.promptWithHints([{type:"list",name:"language",message:"✨ "+d.t("wizard.select_language"),choices:[{name:"[EN] English"+("en_US"===o?t.green(" ✓ ("+d.t("wizard.current_active")+")"):""),value:"en_US"},{name:"[CN] 中文"+("zh_CN"===o?t.green(" ✓ ("+d.t("wizard.current_active")+")"):""),value:"zh_CN"},new e.Separator,{name:"<- "+d.t("wizard.nav_return"),value:"back"},{name:"x "+d.t("wizard.nav_exit"),value:"exit"}],default:"zh_CN"}]);if("exit"===i)this.printGoodbye(),process.exit(0);else if("back"===i)return;return a.setLang(i),void d.setLocale(i)}}buildPresetChoices(){const o=n(),a=o.filter(e=>e.recommended),i=o.filter(e=>!e.recommended),r=e=>({name:(d.t(e.name)!==e.name?d.t(e.name):e.name)+(e.models?t.gray(` [H:${e.models.haiku} S:${e.models.sonnet} O:${e.models.opus}]`):""),value:{type:"preset",preset:e}}),s=[];return a.length>0&&(s.push(new e.Separator(t.hex("#FF8700")("── "+d.t("wizard.recommended")+" ──"))),s.push(...a.map(r))),i.length>0&&(s.push(new e.Separator(t.gray("── "+d.t("wizard.other_models")+" ──"))),s.push(...i.map(r))),s}async handleCustomModelInput(){const o=a.getModels(),{customMode:n}=await e.prompt([{type:"list",name:"customMode",message:d.t("wizard.custom_model_mode"),choices:[{name:d.t("wizard.custom_model_single"),value:"single"},{name:d.t("wizard.custom_model_per_role"),value:"per_role"}]}]);if("single"===n){const{customModel:t}=await e.prompt([{type:"input",name:"customModel",message:d.t("wizard.input_custom_model"),default:i.sonnet}]);a.setModels({haiku:t,sonnet:t,opus:t,reasoning:t})}else{const t=await e.prompt([{type:"input",name:"haiku",message:d.t("wizard.model_haiku"),default:o.haiku},{type:"input",name:"sonnet",message:d.t("wizard.model_sonnet"),default:o.sonnet},{type:"input",name:"opus",message:d.t("wizard.model_opus"),default:o.opus},{type:"input",name:"reasoning",message:d.t("wizard.model_reasoning"),default:o.reasoning}]);a.setModels(t)}console.log(t.green("\n✓ "+d.t("wizard.models_saved")))}async configModels(o){const i=a.getApiKey();if(await this.validatedKeyForConfiguration(i))for(;;){this.resetScreen(),this.createBox(d.t("wizard.config_models"));const i=[...this.buildPresetChoices()];i.push(new e.Separator),i.push({name:"✏️ "+d.t("wizard.custom_model_input"),value:{type:"custom_input"}}),i.push(new e.Separator),i.push({name:"<- "+d.t("wizard.nav_return"),value:{type:"back"}}),i.push({name:"x "+d.t("wizard.nav_exit"),value:{type:"exit"}});const{modelChoice:n}=await this.promptWithHints([{type:"list",name:"modelChoice",message:d.t("wizard.select_model_config"),choices:i}]);if("exit"===n.type)this.printGoodbye(),process.exit(0);else{if("back"===n.type)return;if("custom_input"===n.type)return await this.handleCustomModelInput(),void(o?.skipLoadPrompt||await this.promptLoadAfterModelConfig());if("preset"===n.type){const e=r(n.preset);return a.setModels(e),console.log(t.green("\n✓ "+d.t("wizard.models_saved"))),void(o?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}}}else await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}])}async promptLoadAfterModelConfig(){const{shouldLoad:t}=await e.prompt([{type:"list",name:"shouldLoad",message:d.t("wizard.load_config_now"),choices:[{name:d.t("wizard.load_config_yes"),value:!0},{name:d.t("wizard.load_config_later"),value:!1}]}]);t&&await this.selectAndConfigureTool()}async configApiKey(){for(;;){this.resetScreen(),this.createBox(d.t("wizard.input_api_key")),console.log(t.gray("\n💡 "+d.t("wizard.api_key_input_hint"))),console.log(t.gray(" "+d.t("wizard.api_key_get_hint",{url:"https://www.vibeapi.cn/console/token"}))),console.log();const{apiKey:i}=await e.prompt([{type:"password",name:"apiKey",message:d.t("wizard.input_your_api_key"),mask:"*"}]);if(!i||""===i.trim()){const{action:t}=await e.prompt([{type:"list",name:"action",message:d.t("wizard.select_action"),choices:[{name:d.t("wizard.retry_input"),value:"retry"},{name:"<- "+d.t("wizard.nav_return"),value:"back"}]}]);if("back"===t)return!1;continue}const n=o(d.t("wizard.validating_api_key")).start(),r=await g(i.trim());if(n.stop(),r.valid)return a.setApiKey(i.trim()),this.validatedApiKeys.add(i.trim()),console.log(t.green("\n✓ "+d.t("wizard.api_key_valid"))),!0;{this.validatedApiKeys.delete(i.trim()),"invalid_api_key"===r.error?console.log(t.red("\n✗ "+d.t("wizard.api_key_invalid"))):console.log(t.red("\n✗ "+d.t("wizard.api_key_network_error")));const{action:o}=await e.prompt([{type:"list",name:"action",message:d.t("wizard.select_action"),choices:[{name:d.t("wizard.retry_input"),value:"retry"},{name:"<- "+d.t("wizard.nav_return"),value:"back"}]}]);if("back"===o)return!1}}}async selectAndConfigureTool(t=!1){for(;;){this.resetScreen(),this.createBox(d.t("wizard.select_tool"));const o=l.getSupportedTools().map(e=>({name:e.displayName,value:e.name})),{tool:a}=await this.promptWithHints([{type:"list",name:"tool",message:"🛠️ "+d.t("wizard.select_tool"),choices:[...o,new e.Separator,{name:"<- "+d.t("wizard.nav_return"),value:"back"},{name:"x "+d.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===a)this.printGoodbye(),process.exit(0);else if("back"===a)return;await this.configureTool(a,t)}}async configureTool(o,a=!1){const i=c[o];if(i){if(!l.isToolInstalled(o)){console.log(t.yellow("\n"+d.t("wizard.tool_not_installed",{tool:i.displayName})));const{install:a}=await e.prompt([{type:"confirm",name:"install",message:d.t("wizard.install_tool_confirm"),default:!0}]);if(!a)return;try{await l.installTool(o)}catch{return void console.log(t.red(d.t("wizard.install_failed")))}}a?await this.configureToolModel(o)&&await this.loadConfig(o):await this.showToolMenu(o)}}async showToolMenu(t){for(;;){this.resetScreen();const o=c[t];if(!o)return;this.createBox(o.displayName+" "+d.t("wizard.menu_title"));const a=[{name:"📥 "+d.t("wizard.action_load_config",{tool:o.displayName}),value:"load"},{name:"📤 "+d.t("wizard.action_unload_config",{tool:o.displayName}),value:"unload"}];l.supportsClearPinnedModels(t)&&a.push({name:"🧹 "+d.t("wizard.action_clear_model",{tool:o.displayName}),value:"clear-model"}),a.push({name:"🧨 "+d.t("wizard.action_force_config",{tool:o.displayName}),value:"force"},{name:"↩️ "+d.t("wizard.action_restore_config",{tool:o.displayName}),value:"restore"},new e.Separator,{name:"<- "+d.t("wizard.nav_return"),value:"back"},{name:"x "+d.t("wizard.nav_exit"),value:"exit"});const{action:i}=await this.promptWithHints([{type:"list",name:"action",message:"⚙️ "+d.t("wizard.select_action"),choices:a}]);if("exit"===i)this.printGoodbye(),process.exit(0);else{if("back"===i)return;"load"===i?await this.configureToolModel(t)&&await this.loadConfig(t):"force"===i?await this.forceConfig(t):"unload"===i?await this.unloadConfig(t):"clear-model"===i?await this.clearPinnedModels(t):"restore"===i&&await this.restoreConfig(t)}}}singleModelOverride(e){const t=e.trim();return/claude/i.test(t)?{opus:t}:{haiku:t,sonnet:t,opus:t,reasoning:t}}hasConfiguredApiKey(){return!!a.getApiKey()?.trim()||a.listToolApiKeys().some(e=>Boolean(a.getApiKeyForTool(e)?.trim()))}async validatedKeyForConfiguration(e){const a=e?.trim();if(!a)return console.log(t.red("\n"+d.t("wizard.api_key_required"))),console.log(t.yellow(d.t("wizard.please_config_api_key_first"))),null;if(this.validatedApiKeys.has(a))return a;const i=o(d.t("wizard.validating_api_key")).start(),n=await g(a);if(n.valid)return this.validatedApiKeys.add(a),i.succeed(d.t("wizard.api_key_valid")),a;this.validatedApiKeys.delete(a);const r="invalid_api_key"===n.error?d.t("wizard.api_key_invalid"):d.t("wizard.api_key_network_error");return i.fail(r),console.log(t.red("\n"+d.t("wizard.please_reconfig_api_key"))),null}async configureToolModel(i){const n=c[i];if(!n)return!1;const l=await this.validatedKeyForConfiguration(a.getApiKeyForTool(i));if(!l)return await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}]),!1;const p="claude-code"===i,m=s(i),u=p||!m?d.t("wizard.model_builtin_default"):m;this.resetScreen(),this.createBox(n.displayName+" · "+d.t("wizard.config_models"));const g=[{name:"✅ "+d.t("wizard.use_default_model",{model:u}),value:{type:"default"}},{name:"🌐 "+d.t("wizard.fetch_models_from_api"),value:{type:"fetch"}},...this.buildPresetChoices(),new e.Separator,{name:"✏️ "+d.t("wizard.input_custom_model"),value:{type:"custom"}},new e.Separator,{name:"<- "+d.t("wizard.nav_return"),value:{type:"back"}}],{choice:y}=await this.promptWithHints([{type:"list",name:"choice",message:d.t("wizard.select_tool_model",{tool:n.displayName}),choices:g}]);if("back"===y.type)return!1;if("default"===y.type)a.setToolModel(i,null);else if("preset"===y.type)a.setToolModel(i,r(y.preset));else if("custom"===y.type){const{model:t}=await e.prompt([{type:"input",name:"model",message:d.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]),o=(t||"").trim();a.setToolModel(i,o?this.singleModelOverride(o):null)}else if("fetch"===y.type){const n=o(d.t("wizard.fetching_models")).start(),r=await w(l);let s;if(n.stop(),r.ok&&r.models.length>0){const{model:t}=await e.prompt([{type:"list",name:"model",message:d.t("wizard.select_fetched_model"),pageSize:20,choices:[...r.models,new e.Separator,{name:"<- "+d.t("wizard.nav_return"),value:"__back__"}]}]);if("__back__"===t)return!1;s=t}else{console.log(t.yellow("\n"+d.t("wizard.fetch_models_failed")));const{model:o}=await e.prompt([{type:"input",name:"model",message:d.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]);s=(o||"").trim()}a.setToolModel(i,s?this.singleModelOverride(s):null)}if("codex"===i){const t=a.getToolSetting(i,_),{enableOneMillionContext:o}=await e.prompt([{type:"confirm",name:"enableOneMillionContext",message:d.t("wizard.codex_enable_1m_context"),default:!1!==t}]);a.setToolSetting(i,_,Boolean(o))}if("claude-desktop"===i){const t=a.getToolSetting(i,f),{hideOfficialLogin:o}=await e.prompt([{type:"confirm",name:"hideOfficialLogin",message:d.t("wizard.desktop_hide_official_login"),default:!1!==t}]);a.setToolSetting(i,f,Boolean(o))}return console.log(t.green("\n✓ "+d.t("wizard.models_saved"))),p&&console.log(t.gray("💡 "+d.t("wizard.claude_model_hint"))),!0}async forceConfig(t){const o=c[t]?.displayName||t,{confirm:a}=await e.prompt([{type:"confirm",name:"confirm",message:d.t("config.confirm_force",{tool:o}),default:!1}]);a&&await this.loadConfig(t,{force:!0})}async loadConfig(i,n={}){const r=a.getModelsForTool(i),s=await this.validatedKeyForConfiguration(a.getApiKeyForTool(i));if(!s)return void await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}]);const p=o(d.t("wizard.loading_config")).start();try{await l.applyPrivateConfig(i,s,r,n),p.succeed(d.t("wizard.config_loaded",{tool:c[i]?.displayName||i})),n.force&&console.log(t.yellow(d.t("config.force_done",{tool:c[i]?.displayName||i})));const o=c[i]?.command;o&&console.log(t.green("\n"+d.t("wizard.run_tool_hint",{command:o})));for(const e of l.applyNotes(i))console.log(t.yellow("💡 "+e));const{nextAction:a}=await e.prompt([{type:"list",name:"nextAction",message:d.t("wizard.what_next"),choices:[{name:d.t("wizard.exit_and_start"),value:"exit"},{name:d.t("wizard.continue_config"),value:"continue"}]}]);"exit"===a&&(this.printGoodbye(),process.exit(0))}catch(o){p.fail(d.t("wizard.config_failed")),console.log(t.red(o instanceof Error?o.message:String(o))),await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}])}}async clearPinnedModels(o){const a=c[o]?.displayName||o,{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:d.t("wizard.confirm_clear_model",{tool:a}),default:!1}]);if(i){try{const e=await l.clearPinnedModels(o);0===e.length?console.log(t.yellow("\n"+d.t("config.clear_model_none",{tool:a}))):(console.log(t.green("\n✓ "+d.t("config.clear_model_done",{tool:a}))),e.forEach(e=>console.log(t.gray(` - ${e}`))),console.log(t.gray(d.t("config.clear_model_restart_hint",{tool:a}))))}catch(e){console.log(t.red("\n"+(e instanceof Error?e.message:String(e))))}await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}])}}async unloadConfig(a){const{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:d.t("wizard.confirm_unload_config",{tool:c[a]?.displayName||a}),default:!1}]);if(!i)return;const n=o(d.t("wizard.unloading_config")).start();try{l.unloadPrivateConfig(a),n.succeed(d.t("wizard.config_unloaded"));const{nextAction:t}=await e.prompt([{type:"list",name:"nextAction",message:d.t("wizard.what_next"),choices:[{name:d.t("wizard.exit_and_start"),value:"exit"},{name:d.t("wizard.continue_config"),value:"continue"}]}]);"exit"===t&&(this.printGoodbye(),process.exit(0))}catch(o){n.fail(d.t("wizard.config_unload_failed")),console.log(t.red(o instanceof Error?o.message:String(o))),await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}])}}async restoreConfig(a){const i=c[a]?.displayName||a,{confirm:n}=await e.prompt([{type:"confirm",name:"confirm",message:d.t("wizard.confirm_restore_config",{tool:i}),default:!1}]);if(!n)return;const r=o(d.t("wizard.restoring_config")).start();try{const e=l.restorePrivateConfig(a).filter(e=>e.result.restored);0===e.length?r.warn(d.t("wizard.restore_no_backup")):(r.succeed(d.t("wizard.config_restored",{tool:i})),e.forEach(e=>console.log(t.gray(` ${e.file} ← ${e.result.from}`))))}catch(e){r.fail(d.t("wizard.config_restore_failed")),console.log(t.red(e instanceof Error?e.message:String(e)))}await e.prompt([{type:"input",name:"continue",message:d.t("wizard.press_enter")}])}async run(){await this.showMainMenu()}async showMainMenu(){if(this.hasConfiguredApiKey())for(;;){this.resetScreen();const o=a.getApiKey()||"",i=o.length>4?"sk-****"+o.slice(-4):"****";console.log(t.gray(` 🔑 API Key: ${i}`)+t.green(" ✓")),console.log("");const n=l.getSupportedTools().map(e=>({name:"🛠️ "+e.displayName,value:{type:"tool",tool:e.name}})),r=[new e.Separator(x("── "+d.t("wizard.select_tool")+" ──")),...n,new e.Separator(t.gray("── "+d.t("wizard.settings")+" ──")),{name:"🔑 "+d.t("wizard.menu_change_api_key"),value:{type:"apikey"}},{name:"🌐 "+d.t("wizard.menu_config_language"),value:{type:"language"}},new e.Separator,{name:"x "+d.t("wizard.nav_exit"),value:{type:"exit"}}],{action:s}=await this.promptWithHints([{type:"list",name:"action",message:"🛠️ "+d.t("wizard.select_tool"),choices:r}]);"exit"===s.type?(this.printGoodbye(),process.exit(0)):"tool"===s.type?await this.configureTool(s.tool):"apikey"===s.type?await this.configApiKey():"language"===s.type&&await this.configLanguage()}else await this.runFirstTimeSetup()}}export const wizard=Wizard.getInstance();
|
package/dist/locales/en_US.json
CHANGED
|
@@ -349,6 +349,9 @@
|
|
|
349
349
|
"models_written_slots": "Wrote {{count}} models (offline: from the profile's model slots, gateway model list not fetched): {{list}}",
|
|
350
350
|
"official_login_hidden": "The official Claude.ai sign-in entry is hidden; the desktop is gateway-only. Run vibecli setup --claude-official on to bring it back",
|
|
351
351
|
"official_login_shown": "The official Claude.ai sign-in entry stays visible, so users can switch between the gateway and their own account. Run vibecli setup --claude-official off to hide it"
|
|
352
|
+
},
|
|
353
|
+
"claude_code": {
|
|
354
|
+
"tier_fallback": "This key can't use Claude Code's default {{from}}; the {{tier}} alias now uses {{to}}"
|
|
352
355
|
}
|
|
353
356
|
}
|
|
354
357
|
}
|
package/dist/locales/zh_CN.json
CHANGED
|
@@ -349,6 +349,9 @@
|
|
|
349
349
|
"models_written_slots": "已写入 {{count}} 个模型(离线:按当前 profile 的模型槽位,未拉取网关模型列表):{{list}}",
|
|
350
350
|
"official_login_hidden": "官方登录(Claude.ai 账号)入口已隐藏,桌面端只走网关;要恢复运行 vibecli setup --claude-official on",
|
|
351
351
|
"official_login_shown": "官方登录(Claude.ai 账号)入口保持可见,用户可在网关与官方账号间切换;要隐藏运行 vibecli setup --claude-official off"
|
|
352
|
+
},
|
|
353
|
+
"claude_code": {
|
|
354
|
+
"tier_fallback": "当前 Key 用不了 Claude Code 默认的 {{from}},{{tier}} 档已改用 {{to}}"
|
|
352
355
|
}
|
|
353
356
|
}
|
|
354
357
|
}
|
package/dist/models.json
CHANGED
|
@@ -41,6 +41,14 @@
|
|
|
41
41
|
"model": "deepseek-v4-pro"
|
|
42
42
|
}
|
|
43
43
|
],
|
|
44
|
+
"claudeCode": {
|
|
45
|
+
"tierChains": {
|
|
46
|
+
"opus": ["claude-opus-5-5", "claude-opus-5", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-4-6"],
|
|
47
|
+
"sonnet": ["claude-sonnet-5", "claude-sonnet-4-6"],
|
|
48
|
+
"haiku": ["claude-haiku-4-5-20251001"],
|
|
49
|
+
"fable": ["claude-fable-5-1", "claude-fable-5", "claude-opus-5-5", "claude-opus-5", "claude-opus-4-8"]
|
|
50
|
+
}
|
|
51
|
+
},
|
|
44
52
|
"claudeDesktop": {
|
|
45
53
|
"oneMillionFallback": [
|
|
46
54
|
"claude-opus-4-8",
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
"ENABLE_TOOL_SEARCH": "true",
|
|
4
4
|
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
|
|
5
5
|
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
|
|
6
|
-
"API_TIMEOUT_MS": "3000000"
|
|
6
|
+
"API_TIMEOUT_MS": "3000000",
|
|
7
|
+
"CLAUDE_CODE_AUTO_MODE_SERVER": "0"
|
|
7
8
|
},
|
|
8
9
|
"attribution": {
|
|
9
10
|
"commit": "",
|
package/models.json
CHANGED
|
@@ -41,6 +41,14 @@
|
|
|
41
41
|
"model": "deepseek-v4-pro"
|
|
42
42
|
}
|
|
43
43
|
],
|
|
44
|
+
"claudeCode": {
|
|
45
|
+
"tierChains": {
|
|
46
|
+
"opus": ["claude-opus-5-5", "claude-opus-5", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-4-6"],
|
|
47
|
+
"sonnet": ["claude-sonnet-5", "claude-sonnet-4-6"],
|
|
48
|
+
"haiku": ["claude-haiku-4-5-20251001"],
|
|
49
|
+
"fable": ["claude-fable-5-1", "claude-fable-5", "claude-opus-5-5", "claude-opus-5", "claude-opus-4-8"]
|
|
50
|
+
}
|
|
51
|
+
},
|
|
44
52
|
"claudeDesktop": {
|
|
45
53
|
"oneMillionFallback": [
|
|
46
54
|
"claude-opus-4-8",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeapi/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.50",
|
|
4
4
|
"description": "CLI tool for managing AI coding assistants (Claude Code, Codex, OpenClaw, Hermes, AtomCode, Grok Build) with one unified config",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/settings-template.json
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
"ENABLE_TOOL_SEARCH": "true",
|
|
4
4
|
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
|
|
5
5
|
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
|
|
6
|
-
"API_TIMEOUT_MS": "3000000"
|
|
6
|
+
"API_TIMEOUT_MS": "3000000",
|
|
7
|
+
"CLAUDE_CODE_AUTO_MODE_SERVER": "0"
|
|
7
8
|
},
|
|
8
9
|
"attribution": {
|
|
9
10
|
"commit": "",
|