@vibeapi/api-helper 0.0.147 → 0.0.148
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/brand.json +2 -1
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/setup.d.ts +4 -3
- package/dist/commands/setup.js +1 -1
- package/dist/commands/upgrade.d.ts +4 -2
- package/dist/commands/upgrade.js +1 -1
- package/dist/lib/app-update.d.ts +26 -6
- package/dist/lib/app-update.js +1 -1
- package/dist/lib/brand.d.ts +2 -0
- package/dist/lib/codex-sessions.js +1 -1
- package/dist/lib/i18n.js +1 -1
- package/dist/lib/post-apply.js +1 -1
- package/dist/lib/powershell-env.d.ts +12 -0
- package/dist/lib/powershell-env.js +1 -0
- package/dist/lib/program.js +1 -1
- package/dist/lib/tool-upgrade.js +1 -1
- package/dist/lib/tools/chatgpt-desktop.d.ts +32 -0
- package/dist/lib/tools/chatgpt-desktop.js +1 -0
- package/dist/lib/tools/claude-desktop-app.d.ts +17 -58
- package/dist/lib/tools/claude-desktop-app.js +1 -1
- package/dist/lib/tools/claude-desktop-cli.js +1 -1
- package/dist/lib/tools/claude-desktop.js +1 -1
- package/dist/lib/tools/codex.js +1 -1
- package/dist/lib/tools/desktop-app-installer.d.ts +102 -0
- package/dist/lib/tools/desktop-app-installer.js +1 -0
- package/dist/lib/tools/desktop-process.js +1 -1
- package/dist/lib/tools/elevated-reg.js +1 -1
- package/dist/lib/tools/types.d.ts +24 -0
- package/dist/lib/windows-env.js +1 -1
- package/dist/lib/wizard.js +1 -1
- package/dist/locales/en_US.json +33 -12
- package/dist/locales/zh_CN.json +33 -12
- package/package.json +1 -1
package/dist/lib/wizard.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"inquirer";import t from"chalk";import a from"ora";import{configManager as o,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{confirmWritePlan as d}from"./write-plan.js";import{postApplyPrompts as p}from"./post-apply.js";import{appStatus as m,appStatusText as u,appTools as _,cachedAppStatus as g,upgradeApp as w}from"./app-update.js";import{i18n as f,detectSystemLang as y}from"./i18n.js";import{createBorderLine as h,createContentLine as z}from"../utils/string-width.js";import{validateApiKey as v,fetchModels as k}from"./api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as x}from"./tools/codex.js";import{CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as b}from"./tools/claude-desktop.js";import{addressesWithCurrent as S,ensureReachableGatewayAddress as C,fastestIndex as M,probeAll as T,probeSummary as A,reasonText as N,savedApiKey as K,switchGatewayAddress as B}from"../commands/base.js";import{readFileSync as P}from"fs";import{dirname as j,join as H}from"path";import{fileURLToPath as O}from"url";import{brand as W}from"./brand.js";const L=j(O(import.meta.url)),F=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(F.bold("\n"+h("╔","╗","═",this.BOX_WIDTH))),console.log(F.bold(z(e,"║","║",this.BOX_WIDTH,"center"))),console.log(F.bold(h("╚","╝","═",this.BOX_WIDTH))),console.log("")}showOperationHints(){const e=[t.gray(f.t("wizard.hint_navigate")),t.gray(f.t("wizard.hint_confirm"))];console.log(t.gray("💡 ")+e.join(t.gray(" | "))+"\n")}async promptWithHints(t){this.showOperationHints();const a=t.map(e=>"list"!==e.type||e.pageSize?e:{...e,pageSize:20});return e.prompt(a)}printBanner(){const e=60,t=f.t("wizard.banner_subtitle"),a=z(t,"║","║",e,"center"),o=z("","║","║",e,"center"),i=z(`${W().productName} v${function(){try{return JSON.parse(P(H(L,"..","..","package.json"),"utf-8")).version}catch{return"0.0.0"}}()}`,"║","║",e,"center"),n=[String.raw`__ ___ _ ____ _ ___ `,String.raw`\ \ / (_) |__ ___ / ___| | |_ _|`,String.raw` \ \ / /| | '_ \ / _ \ | | | | | `,String.raw` \ V / | | |_) | __/ |___| |___ | | `,String.raw` \_/ |_|_.__/ \___|\____|_____|___|`],r=Math.max(...n.map(e=>e.length)),s=" ".repeat(Math.floor((58-r)/2)),l=n.map(t=>z(s+t,"║","║",e,"left")),c=[h("╔","╗","═",e),o,...l,o,i,a,h("╚","╝","═",e)];console.log(F.bold("\n"+c.join("\n")))}resetScreen(){console.clear(),this.printBanner()}printGoodbye(){const e=l.getSupportedTools().filter(e=>{if(e.gui)return!1;try{return Boolean(l.detectCurrentConfig(e.name).apiKey)&&l.isToolInstalled(e.name)}catch{return!1}});let a;if(e.length>0){const t=e.map(e=>e.command).join(" / ");a=f.t("wizard.goodbye_message_tools",{commands:t}),e.some(e=>"claude-code"===e.name)&&(a+=" "+f.t("wizard.goodbye_claude_hint"))}else a=f.t("wizard.goodbye_message");console.log(t.green("\n👋 "+a)),this.printPathReloadHint(e.map(e=>e.name))}printPathReloadHint(e){const a=e.filter(e=>!l.isOnPath(e));if(0===a.length)return;const o=a.map(e=>c[e].command).join(" / ");console.log(t.yellow(" ! "+f.t("win32"===process.platform?"setup.path_reload_windows":"setup.path_reload",{commands:o})))}async runFirstTimeSetup(){const e="zh_CN"===y();e&&(o.setLang("zh_CN"),f.setLocale("zh_CN")),this.resetScreen(),console.log(F.bold("\n"+f.t("wizard.welcome"))),console.log(t.gray(f.t("wizard.privacy_note")+"\n")),e?console.log(t.gray(f.t("wizard.lang_auto_zh")+"\n")):await this.configLanguage(),await C(),await this.configApiKey()&&await this.selectAndConfigureTool(!0)}async configLanguage(){for(;;){this.resetScreen(),this.createBox(f.t("wizard.select_language"));const a=f.getLocale(),{language:i}=await this.promptWithHints([{type:"list",name:"language",message:"✨ "+f.t("wizard.select_language"),choices:[{name:"[EN] English"+("en_US"===a?t.green(" ✓ ("+f.t("wizard.current_active")+")"):""),value:"en_US"},{name:"[CN] 中文"+("zh_CN"===a?t.green(" ✓ ("+f.t("wizard.current_active")+")"):""),value:"zh_CN"},new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:"back"},{name:"x "+f.t("wizard.nav_exit"),value:"exit"}],default:"zh_CN"}]);if("exit"===i)this.printGoodbye(),process.exit(0);else if("back"===i)return;return o.setLang(i),void f.setLocale(i)}}buildPresetChoices(){const a=n(),o=a.filter(e=>e.recommended),i=a.filter(e=>!e.recommended),r=e=>({name:(f.t(e.name)!==e.name?f.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 o.length>0&&(s.push(new e.Separator(t.hex("#FF8700")("── "+f.t("wizard.recommended")+" ──"))),s.push(...o.map(r))),i.length>0&&(s.push(new e.Separator(t.gray("── "+f.t("wizard.other_models")+" ──"))),s.push(...i.map(r))),s}async handleCustomModelInput(){const a=o.getModels(),{customMode:n}=await e.prompt([{type:"list",name:"customMode",message:f.t("wizard.custom_model_mode"),choices:[{name:f.t("wizard.custom_model_single"),value:"single"},{name:f.t("wizard.custom_model_per_role"),value:"per_role"}]}]);if("single"===n){const{customModel:t}=await e.prompt([{type:"input",name:"customModel",message:f.t("wizard.input_custom_model"),default:i.sonnet}]);o.setModels({haiku:t,sonnet:t,opus:t,reasoning:t})}else{const t=await e.prompt([{type:"input",name:"haiku",message:f.t("wizard.model_haiku"),default:a.haiku},{type:"input",name:"sonnet",message:f.t("wizard.model_sonnet"),default:a.sonnet},{type:"input",name:"opus",message:f.t("wizard.model_opus"),default:a.opus},{type:"input",name:"reasoning",message:f.t("wizard.model_reasoning"),default:a.reasoning}]);o.setModels(t)}console.log(t.green("\n✓ "+f.t("wizard.models_saved")))}async configModels(a){const i=o.getApiKey();if(await this.validatedKeyForConfiguration(i))for(;;){this.resetScreen(),this.createBox(f.t("wizard.config_models"));const i=[...this.buildPresetChoices()];i.push(new e.Separator),i.push({name:"✏️ "+f.t("wizard.custom_model_input"),value:{type:"custom_input"}}),i.push(new e.Separator),i.push({name:"<- "+f.t("wizard.nav_return"),value:{type:"back"}}),i.push({name:"x "+f.t("wizard.nav_exit"),value:{type:"exit"}});const{modelChoice:n}=await this.promptWithHints([{type:"list",name:"modelChoice",message:f.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(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig());if("preset"===n.type){const e=r(n.preset);return o.setModels(e),console.log(t.green("\n✓ "+f.t("wizard.models_saved"))),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}}}else await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}async promptLoadAfterModelConfig(){const{shouldLoad:t}=await e.prompt([{type:"list",name:"shouldLoad",message:f.t("wizard.load_config_now"),choices:[{name:f.t("wizard.load_config_yes"),value:!0},{name:f.t("wizard.load_config_later"),value:!1}]}]);t&&await this.selectAndConfigureTool()}async configBaseUrl(){const i=o.getBaseUrl(),n=S(),r=a(f.t("wizard.base_testing")).start(),s=await T(n,{apiKey:K(),samples:3});r.stop();const l=M(s),c=n.map((e,a)=>{const o=e.url===i?t.cyan(` ← ${f.t("base.current_mark")}`):"";return{name:`${e.url} ${t.gray(e.label)} ${A(s[a],a===l)}${o}`,value:e.url}});c.push(new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:"__back__"});const{url:d}=await this.promptWithHints([{type:"list",name:"url",message:f.t("wizard.base_select"),choices:c,default:i}]);if("__back__"===d)return;const p=s[n.findIndex(e=>e.url===d)];p.ok?await B(d):console.log(t.red(f.t("base.unreachable",{url:d,reason:N(p)}))),await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}async configApiKey(){for(;;){this.resetScreen(),this.createBox(f.t("wizard.input_api_key")),console.log(t.gray("\n💡 "+f.t("wizard.api_key_input_hint"))),console.log(t.gray(" "+f.t("wizard.api_key_get_hint",{url:W().links.tokenPage}))),console.log();const{apiKey:i}=await e.prompt([{type:"password",name:"apiKey",message:f.t("wizard.input_your_api_key"),mask:"*"}]);if(!i||""===i.trim()){const{action:t}=await e.prompt([{type:"list",name:"action",message:f.t("wizard.select_action"),choices:[{name:f.t("wizard.retry_input"),value:"retry"},{name:"<- "+f.t("wizard.nav_return"),value:"back"}]}]);if("back"===t)return!1;continue}const n=a(f.t("wizard.validating_api_key")).start(),r=await v(i.trim());if(n.stop(),r.valid)return o.setApiKey(i.trim()),this.validatedApiKeys.add(i.trim()),console.log(t.green("\n✓ "+f.t("wizard.api_key_valid"))),!0;{this.validatedApiKeys.delete(i.trim()),"invalid_api_key"===r.error?console.log(t.red("\n✗ "+f.t("wizard.api_key_invalid"))):console.log(t.red("\n✗ "+f.t("wizard.api_key_network_error")));const{action:a}=await e.prompt([{type:"list",name:"action",message:f.t("wizard.select_action"),choices:[{name:f.t("wizard.retry_input"),value:"retry"},{name:"<- "+f.t("wizard.nav_return"),value:"back"}]}]);if("back"===a)return!1}}}async selectAndConfigureTool(a=!1){for(const e of _())await m(e).catch(()=>{});for(;;){this.resetScreen(),this.createBox(f.t("wizard.select_tool"));const o=l.getSupportedTools().map(e=>{const a=_().includes(e.name)?g(e.name):null;return{name:e.displayName+(a?.outdated?t.yellow(" "+u(a)):""),value:e.name}}),{tool:i}=await this.promptWithHints([{type:"list",name:"tool",message:"🛠️ "+f.t("wizard.select_tool"),choices:[...o,new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:"back"},{name:"x "+f.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===i)this.printGoodbye(),process.exit(0);else if("back"===i)return;await this.configureTool(i,a)}}async configureTool(a,o=!1){const i=c[a];if(i){if(!l.isToolInstalled(a)){console.log(t.yellow("\n"+f.t("wizard.tool_not_installed",{tool:i.displayName})));const{install:o}=await e.prompt([{type:"confirm",name:"install",message:f.t("wizard.install_tool_confirm"),default:!0}]);if(!o)return;try{await l.installTool(a)}catch{return void console.log(t.red(f.t("wizard.install_failed")))}}o?await this.configureToolModel(a)&&await this.loadConfig(a):await this.showToolMenu(a)}}async showToolMenu(t){for(;;){this.resetScreen();const a=c[t];if(!a)return;this.createBox(a.displayName+" "+f.t("wizard.menu_title"));const o=[{name:"📥 "+f.t("wizard.action_load_config",{tool:a.displayName}),value:"load"},{name:"📤 "+f.t("wizard.action_unload_config",{tool:a.displayName}),value:"unload"}];l.supportsClearPinnedModels(t)&&o.push({name:"🧹 "+f.t("wizard.action_clear_model",{tool:a.displayName}),value:"clear-model"});const i=_().includes(t)?g(t):null;if(i&&!i.blocker&&i.latest&&(i.outdated||!i.installed)){const e=i.installed?f.t("wizard.action_upgrade_app",{tool:a.displayName,current:i.current??"?",latest:i.latest}):f.t("wizard.action_install_app",{tool:a.displayName,latest:i.latest});o.unshift({name:"↑ "+e,value:"upgrade-app"})}o.push({name:"🧨 "+f.t("wizard.action_force_config",{tool:a.displayName}),value:"force"},{name:"↩️ "+f.t("wizard.action_restore_config",{tool:a.displayName}),value:"restore"},new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:"back"},{name:"x "+f.t("wizard.nav_exit"),value:"exit"});const{action:n}=await this.promptWithHints([{type:"list",name:"action",message:"⚙️ "+f.t("wizard.select_action"),choices:o}]);if("exit"===n)this.printGoodbye(),process.exit(0);else{if("back"===n)return;"load"===n?await this.configureToolModel(t)&&await this.loadConfig(t):"force"===n?await this.forceConfig(t):"unload"===n?await this.unloadConfig(t):"upgrade-app"===n?(await w(t,{install:!0}),await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])):"clear-model"===n?await this.clearPinnedModels(t):"restore"===n&&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!!o.getApiKey()?.trim()||o.listToolApiKeys().some(e=>Boolean(o.getApiKeyForTool(e)?.trim()))}async validatedKeyForConfiguration(e){const o=e?.trim();if(!o)return console.log(t.red("\n"+f.t("wizard.api_key_required"))),console.log(t.yellow(f.t("wizard.please_config_api_key_first"))),null;if(this.validatedApiKeys.has(o))return o;const i=a(f.t("wizard.validating_api_key")).start(),n=await v(o);if(n.valid)return this.validatedApiKeys.add(o),i.succeed(f.t("wizard.api_key_valid")),o;this.validatedApiKeys.delete(o);const r="invalid_api_key"===n.error?f.t("wizard.api_key_invalid"):f.t("wizard.api_key_network_error");return i.fail(r),console.log(t.red("\n"+f.t("wizard.please_reconfig_api_key"))),null}async configureToolModel(i){const n=c[i];if(!n)return!1;const l=await this.validatedKeyForConfiguration(o.getApiKeyForTool(i));if(!l)return await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}]),!1;const d="claude-code"===i,p=d||"claude-desktop"===i||"agy"===i,m=s(i),u=p||!m?f.t("wizard.model_builtin_default"):m;this.resetScreen(),this.createBox(n.displayName+" · "+f.t("wizard.config_models"));const _=[{name:"✅ "+f.t("wizard.use_default_model",{model:u}),value:{type:"default"}},{name:"🌐 "+f.t("wizard.fetch_models_from_api"),value:{type:"fetch"}},...this.buildPresetChoices(),new e.Separator,{name:"✏️ "+f.t("wizard.input_custom_model"),value:{type:"custom"}},new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:{type:"back"}}],{choice:g}=await this.promptWithHints([{type:"list",name:"choice",message:f.t("wizard.select_tool_model",{tool:n.displayName}),choices:_}]);if("back"===g.type)return!1;if("default"===g.type)o.setToolModel(i,null);else if("preset"===g.type)o.setToolModel(i,r(g.preset));else if("custom"===g.type){const{model:t}=await e.prompt([{type:"input",name:"model",message:f.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]),a=(t||"").trim();o.setToolModel(i,a?this.singleModelOverride(a):null)}else if("fetch"===g.type){const n=a(f.t("wizard.fetching_models")).start(),r=await k(l);let s;if(n.stop(),r.ok&&r.models.length>0){const{model:t}=await e.prompt([{type:"list",name:"model",message:f.t("wizard.select_fetched_model"),pageSize:20,choices:[...r.models,new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:"__back__"}]}]);if("__back__"===t)return!1;s=t}else{console.log(t.yellow("\n"+f.t("wizard.fetch_models_failed")));const{model:a}=await e.prompt([{type:"input",name:"model",message:f.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]);s=(a||"").trim()}o.setToolModel(i,s?this.singleModelOverride(s):null)}if("codex"===i){const t=o.getToolSetting(i,x),{enableOneMillionContext:a}=await e.prompt([{type:"confirm",name:"enableOneMillionContext",message:f.t("wizard.codex_enable_1m_context"),default:!1!==t}]);o.setToolSetting(i,x,Boolean(a))}if("claude-desktop"===i){const t=o.getToolSetting(i,b),{hideOfficialLogin:a}=await e.prompt([{type:"confirm",name:"hideOfficialLogin",message:f.t("wizard.desktop_hide_official_login"),default:!1!==t}]);o.setToolSetting(i,b,Boolean(a))}return console.log(t.green("\n✓ "+f.t("wizard.models_saved"))),d&&console.log(t.gray("💡 "+f.t("wizard.claude_model_hint"))),!0}async forceConfig(t){const a=c[t]?.displayName||t,{confirm:o}=await e.prompt([{type:"confirm",name:"confirm",message:f.t("config.confirm_force",{tool:a}),default:!1}]);o&&await this.loadConfig(t,{force:!0})}async loadConfig(i,n={}){const r=o.getModelsForTool(i),s=await this.validatedKeyForConfiguration(o.getApiKeyForTool(i));if(!s)return void await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}]);if(!n.force&&!await d([i]))return;const m=a(f.t("wizard.loading_config")).start();try{await l.applyPrivateConfig(i,s,r,n),m.stop(),l.printApplied(i),await p([i],{apps:{install:!1}}),n.force&&console.log(t.yellow(f.t("config.force_done",{tool:c[i]?.displayName||i,name:i})));const a=c[i];a&&!a.gui&&(l.isOnPath(i)&&console.log(t.green("\n"+f.t("wizard.run_tool_hint",{command:a.command}))),this.printPathReloadHint([i]));const{nextAction:o}=await e.prompt([{type:"list",name:"nextAction",message:f.t("wizard.what_next"),choices:[{name:f.t("wizard.exit_and_start"),value:"exit"},{name:f.t("wizard.continue_config"),value:"continue"}]}]);"exit"===o&&(this.printGoodbye(),process.exit(0))}catch(a){m.fail(f.t("wizard.config_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}}async clearPinnedModels(a){const o=c[a]?.displayName||a,{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:f.t("wizard.confirm_clear_model",{tool:o}),default:!1}]);if(i){try{const e=await l.clearPinnedModels(a);0===e.length?console.log(t.yellow("\n"+f.t("config.clear_model_none",{tool:o}))):(console.log(t.green("\n✓ "+f.t("config.clear_model_done",{tool:o}))),e.forEach(e=>console.log(t.gray(` - ${e}`))),console.log(t.gray(f.t("config.clear_model_restart_hint",{tool:o}))))}catch(e){console.log(t.red("\n"+(e instanceof Error?e.message:String(e))))}await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}}async unloadConfig(o){const{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:f.t("wizard.confirm_unload_config",{tool:c[o]?.displayName||o}),default:!1}]);if(!i)return;const n=a(f.t("wizard.unloading_config")).start();try{const a=l.holdsOurConfig(o),i=l.unloadPrivateConfig(o);if(!a)return void n.info(f.t("config.remove_nothing",{tool:c[o]?.displayName||o}));n.succeed(f.t("wizard.config_unloaded")),i.forEach(e=>console.log(t.yellow(" ! "+e.text)));const{nextAction:r}=await e.prompt([{type:"list",name:"nextAction",message:f.t("wizard.what_next"),choices:[{name:f.t("wizard.nav_exit"),value:"exit"},{name:f.t("wizard.continue_config"),value:"continue"}]}]);"exit"===r&&(this.printGoodbye(),process.exit(0))}catch(a){n.fail(f.t("wizard.config_unload_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}}async restoreConfig(o){const i=c[o]?.displayName||o,{confirm:n}=await e.prompt([{type:"confirm",name:"confirm",message:f.t("wizard.confirm_restore_config",{tool:i}),default:!1}]);if(!n)return;const r=a(f.t("wizard.restoring_config")).start();try{const e=l.restorePrivateConfig(o).filter(e=>e.result.restored);0===e.length?r.warn(f.t("wizard.restore_no_backup")):(r.succeed(f.t("wizard.config_restored",{tool:i})),e.forEach(e=>console.log(t.gray(` ${e.file} ← ${e.result.from}`))),console.log(t.yellow(" ! "+f.t("config.reopen_hint",{tool:i}))))}catch(e){r.fail(f.t("wizard.config_restore_failed")),console.log(t.red(e instanceof Error?e.message:String(e)))}await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}async run(){await this.showMainMenu()}async showMainMenu(){if(this.hasConfiguredApiKey())for(;;){this.resetScreen();const a=o.getApiKey()||"",i=a.length>4?"sk-****"+a.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(F("── "+f.t("wizard.select_tool")+" ──")),...n,new e.Separator(t.gray("── "+f.t("wizard.settings")+" ──")),{name:"🔑 "+f.t("wizard.menu_change_api_key"),value:{type:"apikey"}},{name:"🔗 "+f.t("wizard.menu_base_url",{url:o.getBaseUrl()}),value:{type:"base"}},{name:"🌐 "+f.t("wizard.menu_config_language"),value:{type:"language"}},new e.Separator,{name:"x "+f.t("wizard.nav_exit"),value:{type:"exit"}}],{action:s}=await this.promptWithHints([{type:"list",name:"action",message:"🛠️ "+f.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():"base"===s.type?await this.configBaseUrl():"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 a from"ora";import{configManager as o,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{confirmWritePlan as d}from"./write-plan.js";import{postApplyPrompts as p}from"./post-apply.js";import{appStatus as m,appStatusText as u,appTools as _,appsForTools as g,cachedAppStatus as w,upgradeApp as f}from"./app-update.js";import{i18n as y,detectSystemLang as h}from"./i18n.js";import{createBorderLine as z,createContentLine as v}from"../utils/string-width.js";import{validateApiKey as k,fetchModels as x}from"./api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as b}from"./tools/codex.js";import{CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as S}from"./tools/claude-desktop.js";import{addressesWithCurrent as C,ensureReachableGatewayAddress as M,fastestIndex as T,probeAll as A,probeSummary as K,reasonText as N,savedApiKey as B,switchGatewayAddress as P}from"../commands/base.js";import{readFileSync as W}from"fs";import{dirname as j,join as H}from"path";import{fileURLToPath as O}from"url";import{brand as L}from"./brand.js";const $=j(O(import.meta.url)),F=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(F.bold("\n"+z("╔","╗","═",this.BOX_WIDTH))),console.log(F.bold(v(e,"║","║",this.BOX_WIDTH,"center"))),console.log(F.bold(z("╚","╝","═",this.BOX_WIDTH))),console.log("")}showOperationHints(){const e=[t.gray(y.t("wizard.hint_navigate")),t.gray(y.t("wizard.hint_confirm"))];console.log(t.gray("💡 ")+e.join(t.gray(" | "))+"\n")}async promptWithHints(t){this.showOperationHints();const a=t.map(e=>"list"!==e.type||e.pageSize?e:{...e,pageSize:20});return e.prompt(a)}printBanner(){const e=60,t=y.t("wizard.banner_subtitle"),a=v(t,"║","║",e,"center"),o=v("","║","║",e,"center"),i=v(`${L().productName} v${function(){try{return JSON.parse(W(H($,"..","..","package.json"),"utf-8")).version}catch{return"0.0.0"}}()}`,"║","║",e,"center"),n=[String.raw`__ ___ _ ____ _ ___ `,String.raw`\ \ / (_) |__ ___ / ___| | |_ _|`,String.raw` \ \ / /| | '_ \ / _ \ | | | | | `,String.raw` \ V / | | |_) | __/ |___| |___ | | `,String.raw` \_/ |_|_.__/ \___|\____|_____|___|`],r=Math.max(...n.map(e=>e.length)),s=" ".repeat(Math.floor((58-r)/2)),l=n.map(t=>v(s+t,"║","║",e,"left")),c=[z("╔","╗","═",e),o,...l,o,i,a,z("╚","╝","═",e)];console.log(F.bold("\n"+c.join("\n")))}resetScreen(){console.clear(),this.printBanner()}printGoodbye(){const e=l.getSupportedTools().filter(e=>{if(e.gui)return!1;try{return Boolean(l.detectCurrentConfig(e.name).apiKey)&&l.isToolInstalled(e.name)}catch{return!1}});let a;if(e.length>0){const t=e.map(e=>e.command).join(" / ");a=y.t("wizard.goodbye_message_tools",{commands:t}),e.some(e=>"claude-code"===e.name)&&(a+=" "+y.t("wizard.goodbye_claude_hint"))}else a=y.t("wizard.goodbye_message");console.log(t.green("\n👋 "+a)),this.printPathReloadHint(e.map(e=>e.name))}printPathReloadHint(e){const a=e.filter(e=>!l.isOnPath(e));if(0===a.length)return;const o=a.map(e=>c[e].command).join(" / ");console.log(t.yellow(" ! "+y.t("win32"===process.platform?"setup.path_reload_windows":"setup.path_reload",{commands:o})))}async runFirstTimeSetup(){const e="zh_CN"===h();e&&(o.setLang("zh_CN"),y.setLocale("zh_CN")),this.resetScreen(),console.log(F.bold("\n"+y.t("wizard.welcome"))),console.log(t.gray(y.t("wizard.privacy_note")+"\n")),e?console.log(t.gray(y.t("wizard.lang_auto_zh")+"\n")):await this.configLanguage(),await M(),await this.configApiKey()&&await this.selectAndConfigureTool(!0)}async configLanguage(){for(;;){this.resetScreen(),this.createBox(y.t("wizard.select_language"));const a=y.getLocale(),{language:i}=await this.promptWithHints([{type:"list",name:"language",message:"✨ "+y.t("wizard.select_language"),choices:[{name:"[EN] English"+("en_US"===a?t.green(" ✓ ("+y.t("wizard.current_active")+")"):""),value:"en_US"},{name:"[CN] 中文"+("zh_CN"===a?t.green(" ✓ ("+y.t("wizard.current_active")+")"):""),value:"zh_CN"},new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:"back"},{name:"x "+y.t("wizard.nav_exit"),value:"exit"}],default:"zh_CN"}]);if("exit"===i)this.printGoodbye(),process.exit(0);else if("back"===i)return;return o.setLang(i),void y.setLocale(i)}}buildPresetChoices(){const a=n(),o=a.filter(e=>e.recommended),i=a.filter(e=>!e.recommended),r=e=>({name:(y.t(e.name)!==e.name?y.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 o.length>0&&(s.push(new e.Separator(t.hex("#FF8700")("── "+y.t("wizard.recommended")+" ──"))),s.push(...o.map(r))),i.length>0&&(s.push(new e.Separator(t.gray("── "+y.t("wizard.other_models")+" ──"))),s.push(...i.map(r))),s}async handleCustomModelInput(){const a=o.getModels(),{customMode:n}=await e.prompt([{type:"list",name:"customMode",message:y.t("wizard.custom_model_mode"),choices:[{name:y.t("wizard.custom_model_single"),value:"single"},{name:y.t("wizard.custom_model_per_role"),value:"per_role"}]}]);if("single"===n){const{customModel:t}=await e.prompt([{type:"input",name:"customModel",message:y.t("wizard.input_custom_model"),default:i.sonnet}]);o.setModels({haiku:t,sonnet:t,opus:t,reasoning:t})}else{const t=await e.prompt([{type:"input",name:"haiku",message:y.t("wizard.model_haiku"),default:a.haiku},{type:"input",name:"sonnet",message:y.t("wizard.model_sonnet"),default:a.sonnet},{type:"input",name:"opus",message:y.t("wizard.model_opus"),default:a.opus},{type:"input",name:"reasoning",message:y.t("wizard.model_reasoning"),default:a.reasoning}]);o.setModels(t)}console.log(t.green("\n✓ "+y.t("wizard.models_saved")))}async configModels(a){const i=o.getApiKey();if(await this.validatedKeyForConfiguration(i))for(;;){this.resetScreen(),this.createBox(y.t("wizard.config_models"));const i=[...this.buildPresetChoices()];i.push(new e.Separator),i.push({name:"✏️ "+y.t("wizard.custom_model_input"),value:{type:"custom_input"}}),i.push(new e.Separator),i.push({name:"<- "+y.t("wizard.nav_return"),value:{type:"back"}}),i.push({name:"x "+y.t("wizard.nav_exit"),value:{type:"exit"}});const{modelChoice:n}=await this.promptWithHints([{type:"list",name:"modelChoice",message:y.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(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig());if("preset"===n.type){const e=r(n.preset);return o.setModels(e),console.log(t.green("\n✓ "+y.t("wizard.models_saved"))),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}}}else await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}async promptLoadAfterModelConfig(){const{shouldLoad:t}=await e.prompt([{type:"list",name:"shouldLoad",message:y.t("wizard.load_config_now"),choices:[{name:y.t("wizard.load_config_yes"),value:!0},{name:y.t("wizard.load_config_later"),value:!1}]}]);t&&await this.selectAndConfigureTool()}async configBaseUrl(){const i=o.getBaseUrl(),n=C(),r=a(y.t("wizard.base_testing")).start(),s=await A(n,{apiKey:B(),samples:3});r.stop();const l=T(s),c=n.map((e,a)=>{const o=e.url===i?t.cyan(` ← ${y.t("base.current_mark")}`):"";return{name:`${e.url} ${t.gray(e.label)} ${K(s[a],a===l)}${o}`,value:e.url}});c.push(new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:"__back__"});const{url:d}=await this.promptWithHints([{type:"list",name:"url",message:y.t("wizard.base_select"),choices:c,default:i}]);if("__back__"===d)return;const p=s[n.findIndex(e=>e.url===d)];p.ok?await P(d):console.log(t.red(y.t("base.unreachable",{url:d,reason:N(p)}))),await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}async configApiKey(){for(;;){this.resetScreen(),this.createBox(y.t("wizard.input_api_key")),console.log(t.gray("\n💡 "+y.t("wizard.api_key_input_hint"))),console.log(t.gray(" "+y.t("wizard.api_key_get_hint",{url:L().links.tokenPage}))),console.log();const{apiKey:i}=await e.prompt([{type:"password",name:"apiKey",message:y.t("wizard.input_your_api_key"),mask:"*"}]);if(!i||""===i.trim()){const{action:t}=await e.prompt([{type:"list",name:"action",message:y.t("wizard.select_action"),choices:[{name:y.t("wizard.retry_input"),value:"retry"},{name:"<- "+y.t("wizard.nav_return"),value:"back"}]}]);if("back"===t)return!1;continue}const n=a(y.t("wizard.validating_api_key")).start(),r=await k(i.trim());if(n.stop(),r.valid)return o.setApiKey(i.trim()),this.validatedApiKeys.add(i.trim()),console.log(t.green("\n✓ "+y.t("wizard.api_key_valid"))),!0;{this.validatedApiKeys.delete(i.trim()),"invalid_api_key"===r.error?console.log(t.red("\n✗ "+y.t("wizard.api_key_invalid"))):console.log(t.red("\n✗ "+y.t("wizard.api_key_network_error")));const{action:a}=await e.prompt([{type:"list",name:"action",message:y.t("wizard.select_action"),choices:[{name:y.t("wizard.retry_input"),value:"retry"},{name:"<- "+y.t("wizard.nav_return"),value:"back"}]}]);if("back"===a)return!1}}}async selectAndConfigureTool(a=!1){for(const e of _())await m(e).catch(()=>{});for(;;){this.resetScreen(),this.createBox(y.t("wizard.select_tool"));const o=l.getSupportedTools().map(e=>{const a=g([e.name]).map(e=>w(e)).find(e=>e.outdated);return{name:e.displayName+(a?t.yellow(" "+(a.tool===e.name?"":`${a.name} `)+u(a)):""),value:e.name}}),{tool:i}=await this.promptWithHints([{type:"list",name:"tool",message:"🛠️ "+y.t("wizard.select_tool"),choices:[...o,new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:"back"},{name:"x "+y.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===i)this.printGoodbye(),process.exit(0);else if("back"===i)return;await this.configureTool(i,a)}}async configureTool(a,o=!1){const i=c[a];if(i){if(!l.isToolInstalled(a)){console.log(t.yellow("\n"+y.t("wizard.tool_not_installed",{tool:i.displayName})));const{install:o}=await e.prompt([{type:"confirm",name:"install",message:y.t("wizard.install_tool_confirm"),default:!0}]);if(!o)return;try{await l.installTool(a)}catch{return void console.log(t.red(y.t("wizard.install_failed")))}}o?await this.configureToolModel(a)&&await this.loadConfig(a):await this.showToolMenu(a)}}async showToolMenu(t){for(;;){this.resetScreen();const a=c[t];if(!a)return;this.createBox(a.displayName+" "+y.t("wizard.menu_title"));const o=[{name:"📥 "+y.t("wizard.action_load_config",{tool:a.displayName}),value:"load"},{name:"📤 "+y.t("wizard.action_unload_config",{tool:a.displayName}),value:"unload"}];l.supportsClearPinnedModels(t)&&o.push({name:"🧹 "+y.t("wizard.action_clear_model",{tool:a.displayName}),value:"clear-model"});for(const e of g([t]).map(e=>w(e)).reverse()){if(e.blocker||!e.latest||!e.outdated&&e.installed)continue;const t=e.installed?y.t("wizard.action_upgrade_app",{tool:e.name,current:e.current??"?",latest:e.latest}):y.t("wizard.action_install_app",{tool:e.name,latest:e.latest});o.unshift({name:"↑ "+t,value:`upgrade-app:${e.tool}`})}o.push({name:"🧨 "+y.t("wizard.action_force_config",{tool:a.displayName}),value:"force"},{name:"↩️ "+y.t("wizard.action_restore_config",{tool:a.displayName}),value:"restore"},new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:"back"},{name:"x "+y.t("wizard.nav_exit"),value:"exit"});const{action:i}=await this.promptWithHints([{type:"list",name:"action",message:"⚙️ "+y.t("wizard.select_action"),choices:o}]);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):"string"==typeof i&&i.startsWith("upgrade-app:")?(await f(i.slice(12),{install:!0}),await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])):"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!!o.getApiKey()?.trim()||o.listToolApiKeys().some(e=>Boolean(o.getApiKeyForTool(e)?.trim()))}async validatedKeyForConfiguration(e){const o=e?.trim();if(!o)return console.log(t.red("\n"+y.t("wizard.api_key_required"))),console.log(t.yellow(y.t("wizard.please_config_api_key_first"))),null;if(this.validatedApiKeys.has(o))return o;const i=a(y.t("wizard.validating_api_key")).start(),n=await k(o);if(n.valid)return this.validatedApiKeys.add(o),i.succeed(y.t("wizard.api_key_valid")),o;this.validatedApiKeys.delete(o);const r="invalid_api_key"===n.error?y.t("wizard.api_key_invalid"):y.t("wizard.api_key_network_error");return i.fail(r),console.log(t.red("\n"+y.t("wizard.please_reconfig_api_key"))),null}async configureToolModel(i){const n=c[i];if(!n)return!1;const l=await this.validatedKeyForConfiguration(o.getApiKeyForTool(i));if(!l)return await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}]),!1;const d="claude-code"===i,p=d||"claude-desktop"===i||"agy"===i,m=s(i),u=p||!m?y.t("wizard.model_builtin_default"):m;this.resetScreen(),this.createBox(n.displayName+" · "+y.t("wizard.config_models"));const _=[{name:"✅ "+y.t("wizard.use_default_model",{model:u}),value:{type:"default"}},{name:"🌐 "+y.t("wizard.fetch_models_from_api"),value:{type:"fetch"}},...this.buildPresetChoices(),new e.Separator,{name:"✏️ "+y.t("wizard.input_custom_model"),value:{type:"custom"}},new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:{type:"back"}}],{choice:g}=await this.promptWithHints([{type:"list",name:"choice",message:y.t("wizard.select_tool_model",{tool:n.displayName}),choices:_}]);if("back"===g.type)return!1;if("default"===g.type)o.setToolModel(i,null);else if("preset"===g.type)o.setToolModel(i,r(g.preset));else if("custom"===g.type){const{model:t}=await e.prompt([{type:"input",name:"model",message:y.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]),a=(t||"").trim();o.setToolModel(i,a?this.singleModelOverride(a):null)}else if("fetch"===g.type){const n=a(y.t("wizard.fetching_models")).start(),r=await x(l);let s;if(n.stop(),r.ok&&r.models.length>0){const{model:t}=await e.prompt([{type:"list",name:"model",message:y.t("wizard.select_fetched_model"),pageSize:20,choices:[...r.models,new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:"__back__"}]}]);if("__back__"===t)return!1;s=t}else{console.log(t.yellow("\n"+y.t("wizard.fetch_models_failed")));const{model:a}=await e.prompt([{type:"input",name:"model",message:y.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]);s=(a||"").trim()}o.setToolModel(i,s?this.singleModelOverride(s):null)}if("codex"===i){const t=o.getToolSetting(i,b),{enableOneMillionContext:a}=await e.prompt([{type:"confirm",name:"enableOneMillionContext",message:y.t("wizard.codex_enable_1m_context"),default:!1!==t}]);o.setToolSetting(i,b,Boolean(a))}if("claude-desktop"===i){const t=o.getToolSetting(i,S),{hideOfficialLogin:a}=await e.prompt([{type:"confirm",name:"hideOfficialLogin",message:y.t("wizard.desktop_hide_official_login"),default:!1!==t}]);o.setToolSetting(i,S,Boolean(a))}return console.log(t.green("\n✓ "+y.t("wizard.models_saved"))),d&&console.log(t.gray("💡 "+y.t("wizard.claude_model_hint"))),!0}async forceConfig(t){const a=c[t]?.displayName||t,{confirm:o}=await e.prompt([{type:"confirm",name:"confirm",message:y.t("config.confirm_force",{tool:a}),default:!1}]);o&&await this.loadConfig(t,{force:!0})}async loadConfig(i,n={}){const r=o.getModelsForTool(i),s=await this.validatedKeyForConfiguration(o.getApiKeyForTool(i));if(!s)return void await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}]);if(!n.force&&!await d([i]))return;const m=a(y.t("wizard.loading_config")).start();try{await l.applyPrivateConfig(i,s,r,n),m.stop(),l.printApplied(i),await p([i],{apps:{install:!1}}),n.force&&console.log(t.yellow(y.t("config.force_done",{tool:c[i]?.displayName||i,name:i})));const a=c[i];a&&!a.gui&&(l.isOnPath(i)&&console.log(t.green("\n"+y.t("wizard.run_tool_hint",{command:a.command}))),this.printPathReloadHint([i]));const{nextAction:o}=await e.prompt([{type:"list",name:"nextAction",message:y.t("wizard.what_next"),choices:[{name:y.t("wizard.exit_and_start"),value:"exit"},{name:y.t("wizard.continue_config"),value:"continue"}]}]);"exit"===o&&(this.printGoodbye(),process.exit(0))}catch(a){m.fail(y.t("wizard.config_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}}async clearPinnedModels(a){const o=c[a]?.displayName||a,{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:y.t("wizard.confirm_clear_model",{tool:o}),default:!1}]);if(i){try{const e=await l.clearPinnedModels(a);0===e.length?console.log(t.yellow("\n"+y.t("config.clear_model_none",{tool:o}))):(console.log(t.green("\n✓ "+y.t("config.clear_model_done",{tool:o}))),e.forEach(e=>console.log(t.gray(` - ${e}`))),console.log(t.gray(y.t("config.clear_model_restart_hint",{tool:o}))))}catch(e){console.log(t.red("\n"+(e instanceof Error?e.message:String(e))))}await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}}async unloadConfig(o){const{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:y.t("wizard.confirm_unload_config",{tool:c[o]?.displayName||o}),default:!1}]);if(!i)return;const n=a(y.t("wizard.unloading_config")).start();try{const a=l.holdsOurConfig(o),i=l.unloadPrivateConfig(o);if(!a)return void n.info(y.t("config.remove_nothing",{tool:c[o]?.displayName||o}));n.succeed(y.t("wizard.config_unloaded")),i.forEach(e=>console.log(t.yellow(" ! "+e.text)));const{nextAction:r}=await e.prompt([{type:"list",name:"nextAction",message:y.t("wizard.what_next"),choices:[{name:y.t("wizard.nav_exit"),value:"exit"},{name:y.t("wizard.continue_config"),value:"continue"}]}]);"exit"===r&&(this.printGoodbye(),process.exit(0))}catch(a){n.fail(y.t("wizard.config_unload_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}}async restoreConfig(o){const i=c[o]?.displayName||o,{confirm:n}=await e.prompt([{type:"confirm",name:"confirm",message:y.t("wizard.confirm_restore_config",{tool:i}),default:!1}]);if(!n)return;const r=a(y.t("wizard.restoring_config")).start();try{const e=l.restorePrivateConfig(o).filter(e=>e.result.restored);0===e.length?r.warn(y.t("wizard.restore_no_backup")):(r.succeed(y.t("wizard.config_restored",{tool:i})),e.forEach(e=>console.log(t.gray(` ${e.file} ← ${e.result.from}`))),console.log(t.yellow(" ! "+y.t("config.reopen_hint",{tool:i}))))}catch(e){r.fail(y.t("wizard.config_restore_failed")),console.log(t.red(e instanceof Error?e.message:String(e)))}await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}async run(){await this.showMainMenu()}async showMainMenu(){if(this.hasConfiguredApiKey())for(;;){this.resetScreen();const a=o.getApiKey()||"",i=a.length>4?"sk-****"+a.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(F("── "+y.t("wizard.select_tool")+" ──")),...n,new e.Separator(t.gray("── "+y.t("wizard.settings")+" ──")),{name:"🔑 "+y.t("wizard.menu_change_api_key"),value:{type:"apikey"}},{name:"🔗 "+y.t("wizard.menu_base_url",{url:o.getBaseUrl()}),value:{type:"base"}},{name:"🌐 "+y.t("wizard.menu_config_language"),value:{type:"language"}},new e.Separator,{name:"x "+y.t("wizard.nav_exit"),value:{type:"exit"}}],{action:s}=await this.promptWithHints([{type:"list",name:"action",message:"🛠️ "+y.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():"base"===s.type?await this.configBaseUrl():"language"===s.type&&await this.configLanguage()}else await this.runFirstTimeSetup()}}export const wizard=Wizard.getInstance();
|
package/dist/locales/en_US.json
CHANGED
|
@@ -366,7 +366,7 @@
|
|
|
366
366
|
"gui_preconfigured": "{{tool}} is not installed yet; its config is written already, so it works once you install and open it (download: {{install}})",
|
|
367
367
|
"validate_failed": "Couldn't validate the API key for {{label}}: {{reason}}",
|
|
368
368
|
"skip_no_claude_desktop": "This API key has no Claude model group; skipped Claude Code and Claude Desktop",
|
|
369
|
-
"install_app_confirm": "Install {{tools}}? (about
|
|
369
|
+
"install_app_confirm": "Install {{tools}}? (about {{size}} MB from the download site)",
|
|
370
370
|
"install_app_hint": "{{tool}} isn't installed: run {{command}} to install it (its config is ready, so it works once opened)"
|
|
371
371
|
},
|
|
372
372
|
"tools": {
|
|
@@ -852,21 +852,25 @@
|
|
|
852
852
|
}
|
|
853
853
|
},
|
|
854
854
|
"upgrade": {
|
|
855
|
-
"summary": "Upgrade Claude Code, Codex, Claude Desktop and other coding tools",
|
|
856
|
-
"description": "Upgrades each copy the way it was installed: native installs use the tool's own updater, npm installs are reinstalled from the China mirror (npmmirror), Homebrew installs use brew upgrade; if a native or Homebrew upgrade doesn't work, {{brand}}'s install script is used (programs from the China mirror). A named tool that is not installed yet is installed with that script.\nClaude Desktop (macOS / Windows) older than the download site's build
|
|
855
|
+
"summary": "Upgrade Claude Code, Codex, Claude Desktop, ChatGPT and other coding tools",
|
|
856
|
+
"description": "Upgrades each copy the way it was installed: native installs use the tool's own updater, npm installs are reinstalled from the China mirror (npmmirror), Homebrew installs use brew upgrade; if a native or Homebrew upgrade doesn't work, {{brand}}'s install script is used (programs from the China mirror). A named tool that is not installed yet is installed with that script.\nClaude Desktop and ChatGPT (with Codex inside; macOS / Windows) older than the download site's build are upgraded from the official installer there, after checking its checksum and the vendor's (Anthropic / OpenAI) signature; their own auto-update stays on, {{cli}} only steps in when they fall behind. A running app is only closed after a yes at a terminal; with --yes or without a terminal it is left running and only a hint is printed. Add --force to reinstall one that is already the latest. ChatGPT for Mac needs Apple silicon.\nWith no tool named, upgrades every installed one.\nTo update {{product}} itself, use {{cli}} update.",
|
|
857
857
|
"arg": {
|
|
858
|
-
"tools": "claude-code, codex, grok, agy, claude-desktop; one or more"
|
|
858
|
+
"tools": "claude-code, codex, grok, agy, claude-desktop, chatgpt; one or more"
|
|
859
859
|
},
|
|
860
860
|
"ex": {
|
|
861
861
|
"all": "Upgrade every installed tool",
|
|
862
862
|
"one": "Upgrade only Claude Code",
|
|
863
863
|
"many": "Upgrade Codex and Antigravity CLI",
|
|
864
|
-
"desktop": "Install Claude Desktop, or upgrade it to the download site's latest build"
|
|
864
|
+
"desktop": "Install Claude Desktop, or upgrade it to the download site's latest build",
|
|
865
|
+
"force": "Reinstall ChatGPT even though it is the latest (when the app is broken)"
|
|
865
866
|
},
|
|
866
867
|
"when": "When {{cli}} doctor reports an old version, or the tool's own updater doesn't finish.",
|
|
867
868
|
"needs": "Without tool names, only installed tools are upgraded",
|
|
868
869
|
"alt": {
|
|
869
870
|
"update": "Update {{product}} itself"
|
|
871
|
+
},
|
|
872
|
+
"opt": {
|
|
873
|
+
"force": "Download and reinstall desktop apps (claude-desktop, chatgpt) even when already the latest"
|
|
870
874
|
}
|
|
871
875
|
},
|
|
872
876
|
"refresh": {
|
|
@@ -1061,8 +1065,8 @@
|
|
|
1061
1065
|
"not_installed": "not installed; the download site has {{latest}}",
|
|
1062
1066
|
"outdated": "{{current}} installed, {{latest}} available",
|
|
1063
1067
|
"up_to_date": "{{current}} (latest)",
|
|
1064
|
-
"downloading": "Downloading {{tool}} {{version}} from the download site (about
|
|
1065
|
-
"verifying": "Checking the checksum and
|
|
1068
|
+
"downloading": "Downloading {{tool}} {{version}} from the download site (about {{size}} MB)…",
|
|
1069
|
+
"verifying": "Checking the checksum and {{vendor}}'s signature…",
|
|
1066
1070
|
"installing": "Installing…",
|
|
1067
1071
|
"already_latest": "{{tool}} is up to date ({{current}})",
|
|
1068
1072
|
"latest_unknown": "Couldn't look up the latest {{tool}}: {{reason}}",
|
|
@@ -1074,9 +1078,9 @@
|
|
|
1074
1078
|
"installed": "Installed {{tool}} {{version}}",
|
|
1075
1079
|
"upgrade_failed": "Couldn't upgrade {{tool}}: {{reason}}. {{current}} still works; fix the cause, then run {{command}}",
|
|
1076
1080
|
"install_failed": "Couldn't install {{tool}}: {{reason}}. Fix the cause, then run {{command}}",
|
|
1077
|
-
"blocked_unsupported_platform": "On this computer, install {{tool}} from
|
|
1078
|
-
"blocked_no_mirror": "Install {{tool}} from
|
|
1079
|
-
"blocked_classic_install": "This computer has the classic installer build of {{tool}}, which {{cli}} doesn't replace: check for updates in {{tool}}, or uninstall it and run {{
|
|
1081
|
+
"blocked_unsupported_platform": "On this computer, install {{tool}} from {{url}}",
|
|
1082
|
+
"blocked_no_mirror": "Install {{tool}} from {{url}}",
|
|
1083
|
+
"blocked_classic_install": "This computer has the classic installer build of {{tool}}, which {{cli}} doesn't replace: check for updates in {{tool}}, or uninstall it and run {{command}} to get the current build",
|
|
1080
1084
|
"reason_unsupported_platform": "there is no installer for this system",
|
|
1081
1085
|
"reason_no_mirror": "no download site is configured",
|
|
1082
1086
|
"reason_classic_install": "the classic installer build is installed",
|
|
@@ -1084,11 +1088,28 @@
|
|
|
1084
1088
|
"error_download": "download failed ({{reason}})",
|
|
1085
1089
|
"error_no_checksum": "the download site has no checksum for {{file}}",
|
|
1086
1090
|
"error_checksum": "{{file}} has the wrong checksum (expected {{expected}}…, got {{actual}}…); the download was deleted",
|
|
1087
|
-
"error_signature": "the package
|
|
1091
|
+
"error_signature": "the package's signature is wrong or broken ({{reason}}); nothing was installed",
|
|
1088
1092
|
"error_mount": "couldn't open the package ({{reason}})",
|
|
1089
1093
|
"error_bad_package": "the package has no {{reason}}",
|
|
1090
1094
|
"error_no_permission": "no permission to write {{path}}: run as an administrator, or give {{path}} to this user",
|
|
1091
1095
|
"error_copy": "copying the app failed ({{reason}})",
|
|
1092
|
-
"error_install": "the system installer failed ({{reason}})"
|
|
1096
|
+
"error_install": "the system installer failed ({{reason}})",
|
|
1097
|
+
"blocked_unsupported_arch": "{{tool}} is only built for Apple silicon Macs; this Mac can't run it",
|
|
1098
|
+
"reason_unsupported_arch": "there is no installer for this chip",
|
|
1099
|
+
"reason_unknown": "reason unknown",
|
|
1100
|
+
"blocked_other_app": "The ChatGPT.app in Applications is another app (the earlier ChatGPT without Codex), which {{cli}} doesn't replace: remove or rename it, then run {{command}}",
|
|
1101
|
+
"reason_other_app": "another app with the same name is in the way",
|
|
1102
|
+
"blocked_root": "Don't install {{tool}} with sudo: the app would belong to root and its own updates would fail. Run {{command}} as your usual account",
|
|
1103
|
+
"blocked_system_account": "This is the system account (SYSTEM); {{tool}} would be installed for no real user. Sign in as the account that uses it and run {{command}}",
|
|
1104
|
+
"reason_root": "it can't be installed with sudo",
|
|
1105
|
+
"reason_system_account": "this is the system account (SYSTEM)",
|
|
1106
|
+
"error_app_management": "macOS doesn't let this terminal replace {{path}}: allow it under System Settings → Privacy & Security → App Management, or check for updates in the app",
|
|
1107
|
+
"upgrade_offer": "Upgrade {{tool}} from {{current}} to {{latest}}?",
|
|
1108
|
+
"upgrade_hint": "{{tool}} is at {{current}}, {{latest}} is available: run {{command}}",
|
|
1109
|
+
"reinstalling": "Reinstalling {{tool}} {{latest}} (--force; current {{current}})",
|
|
1110
|
+
"reinstalled": "Reinstalled {{tool}} {{version}}",
|
|
1111
|
+
"force_hint": "To reinstall it, run {{command}} --force",
|
|
1112
|
+
"blocked_remote_session": "This is a remote (SSH) session, where Windows doesn't allow installing {{tool}}: run {{command}} in a terminal on this computer",
|
|
1113
|
+
"reason_remote_session": "Windows apps can't be installed from a remote (SSH) session"
|
|
1093
1114
|
}
|
|
1094
1115
|
}
|
package/dist/locales/zh_CN.json
CHANGED
|
@@ -366,7 +366,7 @@
|
|
|
366
366
|
"gui_preconfigured": "{{tool}} 还没有安装,已提前写好配置,安装后打开即可使用(下载:{{install}})",
|
|
367
367
|
"validate_failed": "无法验证 {{label}} 的令牌:{{reason}}",
|
|
368
368
|
"skip_no_claude_desktop": "这个令牌没有开通 Claude 模型分组,已跳过 Claude Code 和 Claude Desktop",
|
|
369
|
-
"install_app_confirm": "安装 {{tools}}?(从高速下载站下载约
|
|
369
|
+
"install_app_confirm": "安装 {{tools}}?(从高速下载站下载约 {{size}} MB)",
|
|
370
370
|
"install_app_hint": "没装 {{tool}}:要安装就运行 {{command}}(已写好配置,装好打开就能用)"
|
|
371
371
|
},
|
|
372
372
|
"tools": {
|
|
@@ -852,21 +852,25 @@
|
|
|
852
852
|
}
|
|
853
853
|
},
|
|
854
854
|
"upgrade": {
|
|
855
|
-
"summary": "升级 Claude Code、Codex、Claude Desktop 等编码工具",
|
|
856
|
-
"description": "按每份工具当初的安装方式升级:原生安装用工具自带的更新,npm 安装从国内镜像(npmmirror)重新安装,Homebrew 安装用 brew upgrade;原生或 Homebrew 方式无法升级时,改用 {{brand}} 一键安装脚本(程序取自国内镜像)。指定了但还没有安装的工具,也用这个脚本安装。\nClaude Desktop
|
|
855
|
+
"summary": "升级 Claude Code、Codex、Claude Desktop、ChatGPT 等编码工具",
|
|
856
|
+
"description": "按每份工具当初的安装方式升级:原生安装用工具自带的更新,npm 安装从国内镜像(npmmirror)重新安装,Homebrew 安装用 brew upgrade;原生或 Homebrew 方式无法升级时,改用 {{brand}} 一键安装脚本(程序取自国内镜像)。指定了但还没有安装的工具,也用这个脚本安装。\nClaude Desktop 和 ChatGPT(内含 Codex;macOS / Windows)比高速下载站上的版本旧时,从高速下载站下载官方安装包,核对校验值和厂商(Anthropic / OpenAI)的签名后安装;它们自带的自动更新照常开着,{{cli}} 只在没跟上时补上。应用正在运行时,在终端里问过才关掉它升级,带 --yes 或没有终端时只提示、不关。已是最新时加 --force 重新安装。ChatGPT 的 Mac 版只支持 Apple 芯片。\n不填工具名则升级已安装的全部工具。\n升级 {{product}} 本身请用 {{cli}} update。",
|
|
857
857
|
"arg": {
|
|
858
|
-
"tools": "claude-code、codex、grok、agy、claude-desktop,可以填写多个"
|
|
858
|
+
"tools": "claude-code、codex、grok、agy、claude-desktop、chatgpt,可以填写多个"
|
|
859
859
|
},
|
|
860
860
|
"ex": {
|
|
861
861
|
"all": "升级已安装的全部工具",
|
|
862
862
|
"one": "只升级 Claude Code",
|
|
863
863
|
"many": "升级 Codex 和 Antigravity CLI",
|
|
864
|
-
"desktop": "安装 Claude Desktop,或升到高速下载站上的最新版"
|
|
864
|
+
"desktop": "安装 Claude Desktop,或升到高速下载站上的最新版",
|
|
865
|
+
"force": "ChatGPT 已是最新也重新安装一遍(应用损坏时)"
|
|
865
866
|
},
|
|
866
867
|
"when": "{{cli}} doctor 提示版本过低,或工具自带的更新无法完成时。",
|
|
867
868
|
"needs": "不填工具名时,只升级已经安装的工具",
|
|
868
869
|
"alt": {
|
|
869
870
|
"update": "升级 {{product}} 本身"
|
|
871
|
+
},
|
|
872
|
+
"opt": {
|
|
873
|
+
"force": "桌面应用(claude-desktop、chatgpt)已是最新也重新下载安装"
|
|
870
874
|
}
|
|
871
875
|
},
|
|
872
876
|
"refresh": {
|
|
@@ -1061,8 +1065,8 @@
|
|
|
1061
1065
|
"not_installed": "没有安装,高速下载站上最新是 {{latest}}",
|
|
1062
1066
|
"outdated": "当前 {{current}},可升到 {{latest}}",
|
|
1063
1067
|
"up_to_date": "{{current}}(已是最新)",
|
|
1064
|
-
"downloading": "正在从高速下载站下载 {{tool}} {{version}}(约
|
|
1065
|
-
"verifying": "正在核对校验值和
|
|
1068
|
+
"downloading": "正在从高速下载站下载 {{tool}} {{version}}(约 {{size}} MB)…",
|
|
1069
|
+
"verifying": "正在核对校验值和 {{vendor}} 的签名…",
|
|
1066
1070
|
"installing": "正在安装…",
|
|
1067
1071
|
"already_latest": "{{tool}} 已是最新({{current}})",
|
|
1068
1072
|
"latest_unknown": "无法查到 {{tool}} 的最新版本:{{reason}}",
|
|
@@ -1074,9 +1078,9 @@
|
|
|
1074
1078
|
"installed": "已安装 {{tool}} {{version}}",
|
|
1075
1079
|
"upgrade_failed": "无法升级 {{tool}}:{{reason}}。当前的 {{current}} 照常可用;排除原因后运行 {{command}}",
|
|
1076
1080
|
"install_failed": "无法安装 {{tool}}:{{reason}}。排除原因后运行 {{command}}",
|
|
1077
|
-
"blocked_unsupported_platform": "这台电脑的 {{tool}} 要从官网下载安装:
|
|
1078
|
-
"blocked_no_mirror": "{{tool}} 要从官网下载安装:
|
|
1079
|
-
"blocked_classic_install": "这台电脑装的是旧式安装版 {{tool}},{{cli}} 不替换它:在 {{tool}} 里检查更新,或卸载后运行 {{
|
|
1081
|
+
"blocked_unsupported_platform": "这台电脑的 {{tool}} 要从官网下载安装:{{url}}",
|
|
1082
|
+
"blocked_no_mirror": "{{tool}} 要从官网下载安装:{{url}}",
|
|
1083
|
+
"blocked_classic_install": "这台电脑装的是旧式安装版 {{tool}},{{cli}} 不替换它:在 {{tool}} 里检查更新,或卸载后运行 {{command}} 装新版",
|
|
1080
1084
|
"reason_unsupported_platform": "这个系统没有可用的安装包",
|
|
1081
1085
|
"reason_no_mirror": "没有配置高速下载站",
|
|
1082
1086
|
"reason_classic_install": "装的是旧式安装版",
|
|
@@ -1084,11 +1088,28 @@
|
|
|
1084
1088
|
"error_download": "下载失败({{reason}})",
|
|
1085
1089
|
"error_no_checksum": "高速下载站上没有 {{file}} 的校验值",
|
|
1086
1090
|
"error_checksum": "{{file}} 的校验值不对(应为 {{expected}}…,实际 {{actual}}…),下载的文件已删除",
|
|
1087
|
-
"error_signature": "
|
|
1091
|
+
"error_signature": "安装包的签名不对或已损坏({{reason}}),没有安装",
|
|
1088
1092
|
"error_mount": "无法打开安装包({{reason}})",
|
|
1089
1093
|
"error_bad_package": "安装包里缺少 {{reason}}",
|
|
1090
1094
|
"error_no_permission": "没有权限写入 {{path}}:用管理员账号运行,或把 {{path}} 交给当前用户",
|
|
1091
1095
|
"error_copy": "复制应用失败({{reason}})",
|
|
1092
|
-
"error_install": "系统安装失败({{reason}})"
|
|
1096
|
+
"error_install": "系统安装失败({{reason}})",
|
|
1097
|
+
"blocked_unsupported_arch": "{{tool}} 只有 Apple 芯片的 Mac 版,这台 Mac 装不了",
|
|
1098
|
+
"reason_unsupported_arch": "官方没有这种芯片的安装包",
|
|
1099
|
+
"reason_unknown": "原因不明",
|
|
1100
|
+
"blocked_other_app": "“应用程序”里的 ChatGPT.app 是另一个应用(不含 Codex 的旧版 ChatGPT),{{cli}} 不替换它:删掉或改名后运行 {{command}}",
|
|
1101
|
+
"reason_other_app": "同名的另一个应用已经在那里",
|
|
1102
|
+
"blocked_root": "不要用 sudo 安装 {{tool}}:装出来的应用归 root 所有,它自己的更新会失败。用平常的账号运行 {{command}}",
|
|
1103
|
+
"blocked_system_account": "当前是系统账号(SYSTEM),{{tool}} 会装给不存在的用户:登录要用它的账号后运行 {{command}}",
|
|
1104
|
+
"reason_root": "不能用 sudo 安装",
|
|
1105
|
+
"reason_system_account": "当前是系统账号(SYSTEM)",
|
|
1106
|
+
"error_app_management": "macOS 不允许这个终端替换 {{path}}:在「系统设置 → 隐私与安全性 → App 管理」里打开当前终端,或在应用里检查更新",
|
|
1107
|
+
"upgrade_offer": "把 {{tool}} 从 {{current}} 升到 {{latest}}?",
|
|
1108
|
+
"upgrade_hint": "{{tool}} 当前 {{current}},可升到 {{latest}}:运行 {{command}}",
|
|
1109
|
+
"reinstalling": "按 --force 重新安装 {{tool}} {{latest}}(当前 {{current}})",
|
|
1110
|
+
"reinstalled": "已重新安装 {{tool}} {{version}}",
|
|
1111
|
+
"force_hint": "要重新安装就运行 {{command}} --force",
|
|
1112
|
+
"blocked_remote_session": "这是远程(SSH)登录的会话,Windows 不允许在这里安装 {{tool}}:在这台电脑本机的终端里运行 {{command}}",
|
|
1113
|
+
"reason_remote_session": "远程(SSH)会话里不能安装 Windows 应用"
|
|
1093
1114
|
}
|
|
1094
1115
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeapi/api-helper",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.148",
|
|
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",
|