@vibeapi/api-helper 0.0.105 → 0.0.107
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/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 a}from"../lib/config.js";import{confirmAction as s,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 _(a,f,d){if(!l[a])return void console.log(e.red(i.t("config.unknown_tool",{tool:a})));const g=(f[0]||"").toLowerCase();if("backups"!==g&&"list-backups"!==g){if("restore"===g){if(!await s({message:i.t("config.confirm_restore",{tool:l[a].displayName}),defaultValue:!1}))return;return void p(a,"restore")}if("remove"===g||"unload"===g){const o=l[a].displayName;return void await c({description:i.t("config.remove_dry_run",{tool:o}),json:{action:"remove",tool:a},apply:async()=>{if(!await s({message:i.t("config.confirm_remove",{tool:o,name:a}),defaultValue:!0}))return;const t=n.unloadPrivateConfig(a);console.log(e.green(i.t("config.remove_done",{tool:o}))),t.forEach(o=>console.log(e.yellow(" ! "+o.text)))}})}if("clear-model"===g||"clear-models"===g){const o=l[a].displayName;return n.supportsClearPinnedModels(a)?void await c({description:i.t("config.clear_model_dry_run",{tool:o}),json:{action:"clear_model",tool:a},apply:async()=>{const t=await n.clearPinnedModels(a);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(a)){if(d.nonInteractive)return void console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[a].displayName})));console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[a].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(a)}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(a);if(!o)return void console.log(e.red(i.t("wizard.api_key_required")));if(d.force&&!d.nonInteractive&&!await s({message:i.t("config.confirm_force",{tool:l[a].displayName}),defaultValue:!1}))return;return await n.applyPrivateConfig(a,o,r.getModelsForTool(a),{force:d.force}),d.force&&console.log(e.yellow(i.t("config.force_done",{tool:l[a].displayName}))),void n.printApplied(a)}await t.showToolMenu(a)}else p(a,"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===a&&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 s({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",a=(o.length>=4?o[3]:o[2]||"").trim();return l[t]?a&&g.test(n)?(r.setToolModel(t,{[n]:a}),void console.log(e.green(i.t("config.tool_model_set",{tool:t,slot:n,model:a})))):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 s({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 a}from"../lib/config.js";import{confirmAction as s,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.reopen_hint",{tool:l[o].displayName})))):console.log(e.yellow(i.t("config.restore_no_backup",{tool:l[o].displayName})))}async function _(a,f,d){if(!l[a])return void console.log(e.red(i.t("config.unknown_tool",{tool:a})));const g=(f[0]||"").toLowerCase();if("backups"!==g&&"list-backups"!==g){if("restore"===g){if(!await s({message:i.t("config.confirm_restore",{tool:l[a].displayName}),defaultValue:!1}))return;return void p(a,"restore")}if("remove"===g||"unload"===g){const o=l[a].displayName;return void await c({description:i.t("config.remove_dry_run",{tool:o}),json:{action:"remove",tool:a},apply:async()=>{if(!await s({message:i.t("config.confirm_remove",{tool:o,name:a}),defaultValue:!0}))return;const t=n.unloadPrivateConfig(a);console.log(e.green(i.t("config.remove_done",{tool:o}))),t.forEach(o=>console.log(e.yellow(" ! "+o.text)))}})}if("clear-model"===g||"clear-models"===g){const o=l[a].displayName;return n.supportsClearPinnedModels(a)?void await c({description:i.t("config.clear_model_dry_run",{tool:o}),json:{action:"clear_model",tool:a},apply:async()=>{const t=await n.clearPinnedModels(a);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(a)){if(d.nonInteractive)return void console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[a].displayName})));console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[a].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(a)}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(a);if(!o)return void console.log(e.red(i.t("wizard.api_key_required")));if(d.force&&!d.nonInteractive&&!await s({message:i.t("config.confirm_force",{tool:l[a].displayName}),defaultValue:!1}))return;return await n.applyPrivateConfig(a,o,r.getModelsForTool(a),{force:d.force}),d.force&&console.log(e.yellow(i.t("config.force_done",{tool:l[a].displayName}))),void n.printApplied(a)}await t.showToolMenu(a)}else p(a,"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===a&&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 s({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",a=(o.length>=4?o[3]:o[2]||"").trim();return l[t]?a&&g.test(n)?(r.setToolModel(t,{[n]:a}),void console.log(e.green(i.t("config.tool_model_set",{tool:t,slot:n,model:a})))):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 s({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)}
|
package/dist/lib/tool-manager.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{execSync as
|
|
1
|
+
import{execSync as t,spawnSync as o}from"child_process";import{i18n as n}from"./i18n.js";import e from"inquirer";import r from"chalk";import{logger as i}from"../utils/logger.js";import{configManager as s}from"./config.js";import{getAdapter as l,listAdapters as a,TOOL_ADAPTERS as c}from"./tools/registry.js";import{backupBeforeWrite as d,listBackups as p,restoreBackup as u}from"./tools/backup.js";import{existsSync as f,rmSync as m}from"fs";import{join as g}from"path";import{toolHome as h}from"./tools/types.js";import{stringWidth as w}from"../utils/string-width.js";import{resolveModelCatalog as P}from"./model-catalog.js";import{compareVersions as y,getToolMinVersion as T}from"./model-registry.js";import{findInstalls as k,forgetInstalls as $,installLabel as C,mirrorInstallCommand as E}from"./tools/tool-installs.js";import{CLI_NAME as v}from"./brand.js";export{y as compareVersions};function O(t){const o=c[t];return{name:o.name,command:o.command,installCommand:o.installCommand,configPath:o.configPath,displayName:o.displayName,...o.hidden?{hidden:!0}:{},...o.isInstalled?{gui:!0}:{}}}function S(){const t=new Set;for(const o of s.listProfiles()){const n=s.getProfile(o);for(const o of[n.api_key,...Object.values(n.tool_api_keys??{})])o?.trim()&&t.add(o.trim())}return[...t]}export const SUPPORTED_TOOLS=Object.fromEntries(Object.keys(c).map(t=>[t,O(t)]));export class ToolManager{static instance;constructor(){}static getInstance(){return ToolManager.instance||(ToolManager.instance=new ToolManager),ToolManager.instance}isToolInstalled(t){if(!SUPPORTED_TOOLS[t])return!1;const o=l(t);if(o?.isInstalled)try{return o.isInstalled()}catch{return!1}return this.isOnPath(t)||null!==this.nativeLauncher(t)}isOnPath(o){const n=SUPPORTED_TOOLS[o];if(!n)return!1;try{const o="win32"===process.platform?`where ${n.command}`:`which ${n.command}`;return t(o,{stdio:"pipe"}),!0}catch{return!1}}nativeLauncher(t){const o=l(t),n=o?.installSpec?.native?.binDir;if(!o||!n)return null;const e="win32"===process.platform?`${o.command}.exe`:o.command,r=g(h(),...n,e);return f(r)?r:null}async installTool(o){const i=SUPPORTED_TOOLS[o];if(!i)throw new Error(`Unknown tool: ${o}`);const s=l(o)?.installSpec,a=s?E(s):i.installCommand;console.log(r.gray("$ ")+r.white(a));try{return t(a,{stdio:"inherit"}),$(),void console.log(r.green("√ "+n.t("wizard.tool_installed")))}catch(t){if(console.log(r.red("× "+n.t("wizard.install_failed"))),!/EACCES|EPERM|permission denied/i.test(`${t?.message??""}${t?.stderr??""}`)&&243!==t?.status&&!a.startsWith("npm "))throw new Error(`Failed to install ${i.displayName}: ${t}`);console.log(r.yellow(" ! "+("win32"===process.platform?n.t("install.permission_windows",{command:a}):n.t("install.permission_unix",{command:a}))))}const{action:c}=await e.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"===c)throw new Error(n.t("install.user_cancelled"));if($(),!this.isToolInstalled(o))throw console.log(r.red("× "+n.t("install.still_not_installed",{tool:i.displayName}))),new Error(`${i.displayName} is not installed`);console.log(r.green("√ "+n.t("install.verified_success",{tool:i.displayName})))}getToolConfig(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);try{return o.getConfig()}catch(o){return i.warn(`Failed to read config for ${t}:`,o),i.logError(`ToolManager.getToolConfig(${t})`,o),null}}updateToolConfig(t,o){const n=l(t);if(!n)throw new Error(`Unknown tool: ${t}`);if(!n.updateConfig)throw new Error(`Tool ${t} does not support raw config updates`);n.updateConfig(o)}forceResetConfig(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);const n=o.forceResetPaths?o.forceResetPaths():this.backupPathsFor(o),e=[];for(const t of n)f(t)&&(d(t),m(t,{force:!0}),e.push(t));return e}loadPrivateConfig(t,o,n,e,r={}){const i=l(t);if(!i)throw new Error(`Unknown tool: ${t}`);r.force&&this.forceResetConfig(t),i.loadPrivateConfig({apiKey:o,baseUrl:s.getBaseUrl(),models:n,settings:s.getToolSettings(t),...e?{catalog:e}:{}})}async applyPrivateConfig(t,o,n,e={}){const r=l(t);if(!r)throw new Error(`Unknown tool: ${t}`);const i=r.wantsModelCatalog?await P(o):null;e.force?this.loadPrivateConfig(t,o,n,i??void 0,{force:!0}):i?this.loadPrivateConfig(t,o,n,i):this.loadPrivateConfig(t,o,n)}applyNotes(t){const o=l(t);if(!o)return[];const e=[];try{o.applyNotes&&e.push(...o.applyNotes())}catch(o){i.logError(`ToolManager.applyNotes(${t})`,o)}const r=this.outdatedVersion(t);if(r){e.push({kind:"action",text:n.t("tools.version_outdated",{current:r.current,min:r.min,upgrade:o.installSpec?`${v} upgrade ${t}`:o.upgradeCommand||o.installCommand})});for(const t of o.upgradeHints?.(r.min)??[])e.push({kind:"action",text:t})}const s=o.installSpec?k(o.installSpec):[];return s.length>1&&e.push({kind:"action",text:n.t("upgrade.duplicates_note",{count:String(s.length),active:C(s[0]),others:s.slice(1).map(C).join("、"),tool:t})}),e}printApplied(t,o=16){const n=SUPPORTED_TOOLS[t]?.displayName??t,e=this.applyNotes(t);for(const t of e.filter(t=>"detail"===t.kind))i.record(`${n}: ${t.text}`);const s=e.filter(t=>"summary"===t.kind).map(t=>t.text).join(";"),l=" ".repeat(Math.max(1,o-w(n)));console.log(r.green("√ "+n)+(s?l+s:""));for(const t of e.filter(t=>"action"===t.kind))console.log(r.yellow(" ! "+t.text))}installedVersion(t){const n=l(t);if(!n)return null;if(n.installSpec)return k(n.installSpec)[0]?.version??null;if(n.installedVersion)try{return n.installedVersion()}catch(o){return i.logError(`ToolManager.installedVersion(${t})`,o),null}if(n.isInstalled)return null;try{const t={encoding:"utf-8",timeout:1e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]},e=`${("win32"===process.platform?o(`${n.command} --version`,{...t,shell:!0}):o(n.command,["--version"],t)).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return e?e[0]:null}catch{return null}}outdatedVersion(t){const o=T(t);if(!o)return null;const n=this.installedVersion(t);return n&&y(n,o)<0?{current:n,min:o}:null}unloadPrivateConfig(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);o.unloadPrivateConfig({savedKeys:S()});let e=[];try{e=o.unloadNotes?.()??[]}catch(o){i.logError(`ToolManager.unloadNotes(${t})`,o)}return e.length>0?e:[{kind:"action",text:n.t("config.reopen_hint",{tool:o.displayName})}]}async clearPinnedModels(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);if(s.setToolModel(t,null),!o.clearPinnedModels)return[];const n=s.getApiKeyForTool(t),e=o.wantsModelCatalog&&n?await P(n):null;return o.clearPinnedModels(e??void 0)}supportsClearPinnedModels(t){return Boolean(l(t)?.clearPinnedModels)}detectCurrentConfig(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);return o.detectCurrentConfig()}backupPathsFor(t){return t.backupPaths?t.backupPaths():[t.configPath]}listToolBackups(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);return this.backupPathsFor(o).map(t=>({file:t,backups:p(t)}))}restorePrivateConfig(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);return this.backupPathsFor(o).map(t=>({file:t,result:u(t)}))}getInstalledTools(){return Object.keys(SUPPORTED_TOOLS).filter(t=>this.isToolInstalled(t))}getSupportedTools(){return a().filter(t=>!t.hidden).map(t=>O(t.name))}isGitInstalled(){try{const o="win32"===process.platform?"where git":"which git";return t(o,{stdio:"pipe"}),!0}catch{return!1}}}export const toolManager=ToolManager.getInstance();
|
package/dist/lib/tools/codex.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as e,readFileSync as t,rmSync as o}from"fs";import{join as n}from"path";import*as r from"@iarna/toml";import{logger as i}from"../../utils/logger.js";import{i18n as l}from"../i18n.js";import{backupBeforeWrite as a,atomicWriteFile as s}from"./backup.js";import{pickModel as d,toolHome as c,withV1 as m}from"./types.js";import{getToolDefaultModel as u}from"../model-registry.js";import{buildCodexCatalog as p,codexCatalogPath as _,loadBundledCodexModels as g,loadPreviousCodexModels as f,previousGatewayModelIds as x}from"./codex-catalog.js";import{gatewayModelSpecs as y,modelFamily as h}from"../gateway-models.js";import{mirrorInstallCommand as k,brandInstallScripts as b}from"./tool-installs.js";const j=()=>n(c(),".codex"),w=()=>n(j(),"config.toml"),O=()=>n(j(),"auth.json"),v="OPENAI_API_KEY",C="custom",M=1e6,E=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function N(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function S(e,t){return N(e[t])||(e[t]={}),e[t]}function A(){if(!e(w()))return{};const o=t(w(),"utf-8");if(!o.trim())return{};try{const e=r.parse(o);if(!N(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function P(){if(!e(O()))return{};try{const e=JSON.parse(t(O(),"utf-8"));return N(e)?e:{}}catch{return{}}}let T=null;function I(e){const t=e.profiles;if(N(t)){for(const[e,o]of Object.entries(t))N(o)&&2===Object.keys(o).length&&o.model_provider===C&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let L=null;function D(o,n,r){const l=!1!==n.settings?.one_million_context;!function(e){e.model_context_window===M&&delete e.model_context_window,e.model_auto_compact_token_limit===E&&delete e.model_auto_compact_token_limit}(o);const d=g()??f();if(!d)return i.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),L="skipped",o.model_catalog_json===_()&&delete o.model_catalog_json,void(l&&(o.model_context_window=M,o.model_auto_compact_token_limit=E));const c=n.catalog,m=p({bundled:d,specs:y("codex",c?.clientModels),...c?{keyModels:c.models}:{},gatewayAvailable:c?.models??x(),oneMillion:l,selectedModel:r,..."gateway"===c?.oneMillionSource?{claudeOneMillion:c.oneMillion}:{}});L={listed:m.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))};const u=JSON.stringify(m,null,2)+"\n",h=_();e(h)&&t(h,"utf-8")===u||(a(h),s(h,u)),o.model_catalog_json=h}export function setCodexOneMillionContext(e,t){const o=A(),n=r.stringify(o),i="string"==typeof o.model?o.model:u("codex");D(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},i);const l=r.stringify(o);l!==n&&(a(w()),s(w(),l))}const J={command:"codex",npmPackage:"@openai/codex",native:{binDir:"win32"===process.platform?["AppData","Local","Programs","OpenAI","Codex","bin"]:[".local","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".codex","packages","standalone"]]},mirrorScript:b("codex"),brew:"codex"};export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:k(J),installSpec:J,configPath:w(),wantsModelCatalog:!0,listedModels(){if(A().model_catalog_json!==_())return null;try{return(JSON.parse(t(_(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){A().model_catalog_json===_()&&setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog)},applyNotes(){if("skipped"===L)return[{kind:"action",text:l.t("tools.codex.catalog_skipped")}];if(!L)return[];const e=new Map;for(const t of L.listed)e.set(h(t.id),(e.get(h(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${l.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:l.t("tools.codex.catalog_written",{count:String(L.listed.length),breakdown:t})},{kind:"detail",text:L.listed.map(e=>e.name).join(", ")}]},loadPrivateConfig(e){const t=u("codex"),o=d(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,i=m(e.baseUrl),l=A();l.model=n,l.model_provider=C,l.model_reasoning_effort="high",D(l,e,n);const c=S(l,"model_providers"),p=N(c[C])?{...c[C]}:{};delete p.env_key;const{experimental_bearer_token:_,...g}=p;c[C]={...g,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:i},I(l),S(S(l,"tui"),"model_availability_nux")[n]=4;const f=S(l,"features");f.goals=!0,f.js_repl=!1,a(w()),s(w(),r.stringify(l)),function(e){const t=e.trim();if(!t)return;const o={...P(),auth_mode:"apikey",[v]:t};a(O()),s(O(),JSON.stringify(o,null,2)+"\n")}(e.apiKey)},unloadPrivateConfig(t){if(T=function(e){const t=P(),n="string"==typeof t[v]?t[v].trim():"";if(!n)return N(t.tokens)?"chatgpt":null;if(!e.includes(n))return"other_key";const{[v]:r,auth_mode:i,...l}=t;return a(O()),N(l.tokens)?(s(O(),JSON.stringify({...l,auth_mode:"chatgpt"},null,2)+"\n"),"chatgpt"):(o(O(),{force:!0}),"signed_out")}(t?.savedKeys??[]),!e(w()))return;let n;try{n=A()}catch(e){return void i.logError("codexAdapter.unloadPrivateConfig",e)}const l=n.model_providers;N(l)&&(delete l[C],0===Object.keys(l).length&&delete n.model_providers),n.model_provider===C&&delete n.model_provider,n.model_catalog_json===_()&&delete n.model_catalog_json,I(n),a(w()),s(w(),r.stringify(n))},unloadNotes(){switch(T){case"chatgpt":return[{kind:"action",text:l.t("tools.codex.unload_chatgpt_restored")}];case"other_key":return[{kind:"action",text:l.t("tools.codex.unload_other_key")}];default:return[{kind:"action",text:l.t("tools.codex.unload_sign_in")}]}},detectCurrentConfig(){const e=P()[v];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return A()}catch(e){return i.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[w(),O(),_()]};export function codexAuthProblem(){try{const e=A(),t=e.model_providers?.[C];if(e.model_provider!==C||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=P();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
|
|
1
|
+
import{existsSync as e,readFileSync as t,rmSync as o}from"fs";import{join as n}from"path";import*as r from"@iarna/toml";import{logger as i}from"../../utils/logger.js";import{i18n as l}from"../i18n.js";import{backupBeforeWrite as a,atomicWriteFile as s}from"./backup.js";import{pickModel as d,toolHome as c,withV1 as m}from"./types.js";import{getToolDefaultModel as u}from"../model-registry.js";import{buildCodexCatalog as p,codexCatalogPath as _,loadBundledCodexModels as g,loadPreviousCodexModels as f,previousGatewayModelIds as x}from"./codex-catalog.js";import{gatewayModelSpecs as y,modelFamily as h}from"../gateway-models.js";import{mirrorInstallCommand as k,brandInstallScripts as b}from"./tool-installs.js";const j=()=>n(c(),".codex"),w=()=>n(j(),"config.toml"),O=()=>n(j(),"auth.json"),v="OPENAI_API_KEY",C="custom",M=1e6,E=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function N(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function S(e,t){return N(e[t])||(e[t]={}),e[t]}function A(){if(!e(w()))return{};const o=t(w(),"utf-8");if(!o.trim())return{};try{const e=r.parse(o);if(!N(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function P(){if(!e(O()))return{};try{const e=JSON.parse(t(O(),"utf-8"));return N(e)?e:{}}catch{return{}}}let T=null;function I(e){const t=e.profiles;if(N(t)){for(const[e,o]of Object.entries(t))N(o)&&2===Object.keys(o).length&&o.model_provider===C&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let L=null;function D(o,n,r){const l=!1!==n.settings?.one_million_context;!function(e){e.model_context_window===M&&delete e.model_context_window,e.model_auto_compact_token_limit===E&&delete e.model_auto_compact_token_limit}(o);const d=g()??f();if(!d)return i.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),L="skipped",o.model_catalog_json===_()&&delete o.model_catalog_json,void(l&&(o.model_context_window=M,o.model_auto_compact_token_limit=E));const c=n.catalog,m=p({bundled:d,specs:y("codex",c?.clientModels),...c?{keyModels:c.models}:{},gatewayAvailable:c?.models??x(),oneMillion:l,selectedModel:r,..."gateway"===c?.oneMillionSource?{claudeOneMillion:c.oneMillion}:{}});L={listed:m.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))};const u=JSON.stringify(m,null,2)+"\n",h=_();e(h)&&t(h,"utf-8")===u||(a(h),s(h,u)),o.model_catalog_json=h}export function setCodexOneMillionContext(e,t){const o=A(),n=r.stringify(o),i="string"==typeof o.model?o.model:u("codex");D(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},i);const l=r.stringify(o);l!==n&&(a(w()),s(w(),l))}const J={command:"codex",npmPackage:"@openai/codex",native:{binDir:"win32"===process.platform?["AppData","Local","Programs","OpenAI","Codex","bin"]:[".local","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".codex","packages","standalone"]]},mirrorScript:b("codex"),brew:"codex"};export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:k(J),installSpec:J,configPath:w(),wantsModelCatalog:!0,listedModels(){if(A().model_catalog_json!==_())return null;try{return(JSON.parse(t(_(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){A().model_catalog_json===_()&&setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog)},applyNotes(){if("skipped"===L)return[{kind:"action",text:l.t("tools.codex.catalog_skipped")}];if(!L)return[];const e=new Map;for(const t of L.listed)e.set(h(t.id),(e.get(h(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${l.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:l.t("tools.codex.catalog_written",{count:String(L.listed.length),breakdown:t})},{kind:"detail",text:L.listed.map(e=>e.name).join(", ")}]},loadPrivateConfig(e){const t=u("codex"),o=d(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,i=m(e.baseUrl),l=A();l.model=n,l.model_provider=C,l.model_reasoning_effort="high",D(l,e,n);const c=S(l,"model_providers"),p=N(c[C])?{...c[C]}:{};delete p.env_key;const{experimental_bearer_token:_,...g}=p;c[C]={...g,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:i},I(l),S(S(l,"tui"),"model_availability_nux")[n]=4;const f=S(l,"features");f.goals=!0,f.js_repl=!1,a(w()),s(w(),r.stringify(l)),function(e){const t=e.trim();if(!t)return;const o={...P(),auth_mode:"apikey",[v]:t};a(O()),s(O(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},unloadPrivateConfig(t){if(T=function(e){const t=P(),n="string"==typeof t[v]?t[v].trim():"";if(!n)return N(t.tokens)?"chatgpt":null;if(!e.includes(n))return"other_key";const{[v]:r,auth_mode:i,...l}=t;return a(O()),N(l.tokens)?(s(O(),JSON.stringify({...l,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(o(O(),{force:!0}),"signed_out")}(t?.savedKeys??[]),!e(w()))return;let n;try{n=A()}catch(e){return void i.logError("codexAdapter.unloadPrivateConfig",e)}const l=n.model_providers;N(l)&&(delete l[C],0===Object.keys(l).length&&delete n.model_providers),n.model_provider===C&&delete n.model_provider,n.model_catalog_json===_()&&delete n.model_catalog_json,I(n),a(w()),s(w(),r.stringify(n))},unloadNotes(){switch(T){case"chatgpt":return[{kind:"action",text:l.t("tools.codex.unload_chatgpt_restored")}];case"other_key":return[{kind:"action",text:l.t("tools.codex.unload_other_key")}];default:return[{kind:"action",text:l.t("tools.codex.unload_sign_in")}]}},detectCurrentConfig(){const e=P()[v];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return A()}catch(e){return i.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[w(),O(),_()]};export function codexAuthProblem(){try{const e=A(),t=e.model_providers?.[C];if(e.model_provider!==C||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=P();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
|
package/dist/lib/wizard.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export declare class Wizard {
|
|
|
15
15
|
* 一个都没配置时退回通用提示(不再写死 Claude Code)。
|
|
16
16
|
*/
|
|
17
17
|
private printGoodbye;
|
|
18
|
+
/** Installed where this terminal's PATH doesn't reach yet (fresh install): say how to pick it up. */
|
|
19
|
+
private printPathReloadHint;
|
|
18
20
|
runFirstTimeSetup(): Promise<void>;
|
|
19
21
|
configLanguage(): Promise<void>;
|
|
20
22
|
private buildPresetChoices;
|
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{postApplyPrompts as d}from"./post-apply.js";import{i18n as p,detectSystemLang as m}from"./i18n.js";import{createBorderLine as u,createContentLine as _}from"../utils/string-width.js";import{validateApiKey as g,fetchModels as w}from"./api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as f}from"./tools/codex.js";import{CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as y}from"./tools/claude-desktop.js";import{addressesWithCurrent as h,ensureReachableGatewayAddress as z,fastestIndex as v,probeAll as k,probeSummary as x,reasonText as b,savedApiKey as S,switchGatewayAddress as C}from"../commands/base.js";import{readFileSync as M}from"fs";import{dirname as T,join as A}from"path";import{fileURLToPath as K}from"url";import{brand as N}from"./brand.js";const B=T(K(import.meta.url)),W=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(W.bold("\n"+u("╔","╗","═",this.BOX_WIDTH))),console.log(W.bold(_(e,"║","║",this.BOX_WIDTH,"center"))),console.log(W.bold(u("╚","╝","═",this.BOX_WIDTH))),console.log("")}showOperationHints(){const e=[t.gray(p.t("wizard.hint_navigate")),t.gray(p.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=p.t("wizard.banner_subtitle"),a=_(t,"║","║",e,"center"),o=_("","║","║",e,"center"),i=_(`${N().productName} v${function(){try{return JSON.parse(M(A(B,"..","..","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=>_(s+t,"║","║",e,"left")),c=[u("╔","╗","═",e),o,...l,o,i,a,u("╚","╝","═",e)];console.log(W.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)}catch{return!1}});let a;if(e.length>0){const t=e.map(e=>e.command).join(" / ");a=p.t("wizard.goodbye_message_tools",{commands:t}),e.some(e=>"claude-code"===e.name)&&(a+=" "+p.t("wizard.goodbye_claude_hint"))}else a=p.t("wizard.goodbye_message");console.log(t.green("\n👋 "+a))}async runFirstTimeSetup(){const e="zh_CN"===m();e&&(o.setLang("zh_CN"),p.setLocale("zh_CN")),this.resetScreen(),console.log(W.bold("\n"+p.t("wizard.welcome"))),console.log(t.gray(p.t("wizard.privacy_note")+"\n")),e?console.log(t.gray(p.t("wizard.lang_auto_zh")+"\n")):await this.configLanguage(),await z(),await this.configApiKey()&&await this.selectAndConfigureTool(!0)}async configLanguage(){for(;;){this.resetScreen(),this.createBox(p.t("wizard.select_language"));const a=p.getLocale(),{language:i}=await this.promptWithHints([{type:"list",name:"language",message:"✨ "+p.t("wizard.select_language"),choices:[{name:"[EN] English"+("en_US"===a?t.green(" ✓ ("+p.t("wizard.current_active")+")"):""),value:"en_US"},{name:"[CN] 中文"+("zh_CN"===a?t.green(" ✓ ("+p.t("wizard.current_active")+")"):""),value:"zh_CN"},new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:"back"},{name:"x "+p.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 p.setLocale(i)}}buildPresetChoices(){const a=n(),o=a.filter(e=>e.recommended),i=a.filter(e=>!e.recommended),r=e=>({name:(p.t(e.name)!==e.name?p.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")("── "+p.t("wizard.recommended")+" ──"))),s.push(...o.map(r))),i.length>0&&(s.push(new e.Separator(t.gray("── "+p.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:p.t("wizard.custom_model_mode"),choices:[{name:p.t("wizard.custom_model_single"),value:"single"},{name:p.t("wizard.custom_model_per_role"),value:"per_role"}]}]);if("single"===n){const{customModel:t}=await e.prompt([{type:"input",name:"customModel",message:p.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:p.t("wizard.model_haiku"),default:a.haiku},{type:"input",name:"sonnet",message:p.t("wizard.model_sonnet"),default:a.sonnet},{type:"input",name:"opus",message:p.t("wizard.model_opus"),default:a.opus},{type:"input",name:"reasoning",message:p.t("wizard.model_reasoning"),default:a.reasoning}]);o.setModels(t)}console.log(t.green("\n✓ "+p.t("wizard.models_saved")))}async configModels(a){const i=o.getApiKey();if(await this.validatedKeyForConfiguration(i))for(;;){this.resetScreen(),this.createBox(p.t("wizard.config_models"));const i=[...this.buildPresetChoices()];i.push(new e.Separator),i.push({name:"✏️ "+p.t("wizard.custom_model_input"),value:{type:"custom_input"}}),i.push(new e.Separator),i.push({name:"<- "+p.t("wizard.nav_return"),value:{type:"back"}}),i.push({name:"x "+p.t("wizard.nav_exit"),value:{type:"exit"}});const{modelChoice:n}=await this.promptWithHints([{type:"list",name:"modelChoice",message:p.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✓ "+p.t("wizard.models_saved"))),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}}}else await e.prompt([{type:"input",name:"continue",message:p.t("wizard.press_enter")}])}async promptLoadAfterModelConfig(){const{shouldLoad:t}=await e.prompt([{type:"list",name:"shouldLoad",message:p.t("wizard.load_config_now"),choices:[{name:p.t("wizard.load_config_yes"),value:!0},{name:p.t("wizard.load_config_later"),value:!1}]}]);t&&await this.selectAndConfigureTool()}async configBaseUrl(){const i=o.getBaseUrl(),n=h(),r=a(p.t("wizard.base_testing")).start(),s=await k(n,{apiKey:S(),samples:3});r.stop();const l=v(s),c=n.map((e,a)=>{const o=e.url===i?t.cyan(` ← ${p.t("base.current_mark")}`):"";return{name:`${e.url} ${t.gray(e.label)} ${x(s[a],a===l)}${o}`,value:e.url}});c.push(new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:"__back__"});const{url:d}=await this.promptWithHints([{type:"list",name:"url",message:p.t("wizard.base_select"),choices:c,default:i}]);if("__back__"===d)return;const m=s[n.findIndex(e=>e.url===d)];m.ok?await C(d):console.log(t.red(p.t("base.unreachable",{url:d,reason:b(m)}))),await e.prompt([{type:"input",name:"continue",message:p.t("wizard.press_enter")}])}async configApiKey(){for(;;){this.resetScreen(),this.createBox(p.t("wizard.input_api_key")),console.log(t.gray("\n💡 "+p.t("wizard.api_key_input_hint"))),console.log(t.gray(" "+p.t("wizard.api_key_get_hint",{url:N().links.tokenPage}))),console.log();const{apiKey:i}=await e.prompt([{type:"password",name:"apiKey",message:p.t("wizard.input_your_api_key"),mask:"*"}]);if(!i||""===i.trim()){const{action:t}=await e.prompt([{type:"list",name:"action",message:p.t("wizard.select_action"),choices:[{name:p.t("wizard.retry_input"),value:"retry"},{name:"<- "+p.t("wizard.nav_return"),value:"back"}]}]);if("back"===t)return!1;continue}const n=a(p.t("wizard.validating_api_key")).start(),r=await g(i.trim());if(n.stop(),r.valid)return o.setApiKey(i.trim()),this.validatedApiKeys.add(i.trim()),console.log(t.green("\n✓ "+p.t("wizard.api_key_valid"))),!0;{this.validatedApiKeys.delete(i.trim()),"invalid_api_key"===r.error?console.log(t.red("\n✗ "+p.t("wizard.api_key_invalid"))):console.log(t.red("\n✗ "+p.t("wizard.api_key_network_error")));const{action:a}=await e.prompt([{type:"list",name:"action",message:p.t("wizard.select_action"),choices:[{name:p.t("wizard.retry_input"),value:"retry"},{name:"<- "+p.t("wizard.nav_return"),value:"back"}]}]);if("back"===a)return!1}}}async selectAndConfigureTool(t=!1){for(;;){this.resetScreen(),this.createBox(p.t("wizard.select_tool"));const a=l.getSupportedTools().map(e=>({name:e.displayName,value:e.name})),{tool:o}=await this.promptWithHints([{type:"list",name:"tool",message:"🛠️ "+p.t("wizard.select_tool"),choices:[...a,new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:"back"},{name:"x "+p.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===o)this.printGoodbye(),process.exit(0);else if("back"===o)return;await this.configureTool(o,t)}}async configureTool(a,o=!1){const i=c[a];if(i){if(!l.isToolInstalled(a)){console.log(t.yellow("\n"+p.t("wizard.tool_not_installed",{tool:i.displayName})));const{install:o}=await e.prompt([{type:"confirm",name:"install",message:p.t("wizard.install_tool_confirm"),default:!0}]);if(!o)return;try{await l.installTool(a)}catch{return void console.log(t.red(p.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+" "+p.t("wizard.menu_title"));const o=[{name:"📥 "+p.t("wizard.action_load_config",{tool:a.displayName}),value:"load"},{name:"📤 "+p.t("wizard.action_unload_config",{tool:a.displayName}),value:"unload"}];l.supportsClearPinnedModels(t)&&o.push({name:"🧹 "+p.t("wizard.action_clear_model",{tool:a.displayName}),value:"clear-model"}),o.push({name:"🧨 "+p.t("wizard.action_force_config",{tool:a.displayName}),value:"force"},{name:"↩️ "+p.t("wizard.action_restore_config",{tool:a.displayName}),value:"restore"},new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:"back"},{name:"x "+p.t("wizard.nav_exit"),value:"exit"});const{action:i}=await this.promptWithHints([{type:"list",name:"action",message:"⚙️ "+p.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):"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"+p.t("wizard.api_key_required"))),console.log(t.yellow(p.t("wizard.please_config_api_key_first"))),null;if(this.validatedApiKeys.has(o))return o;const i=a(p.t("wizard.validating_api_key")).start(),n=await g(o);if(n.valid)return this.validatedApiKeys.add(o),i.succeed(p.t("wizard.api_key_valid")),o;this.validatedApiKeys.delete(o);const r="invalid_api_key"===n.error?p.t("wizard.api_key_invalid"):p.t("wizard.api_key_network_error");return i.fail(r),console.log(t.red("\n"+p.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:p.t("wizard.press_enter")}]),!1;const d="claude-code"===i,m=s(i),u=d||!m?p.t("wizard.model_builtin_default"):m;this.resetScreen(),this.createBox(n.displayName+" · "+p.t("wizard.config_models"));const _=[{name:"✅ "+p.t("wizard.use_default_model",{model:u}),value:{type:"default"}},{name:"🌐 "+p.t("wizard.fetch_models_from_api"),value:{type:"fetch"}},...this.buildPresetChoices(),new e.Separator,{name:"✏️ "+p.t("wizard.input_custom_model"),value:{type:"custom"}},new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:{type:"back"}}],{choice:g}=await this.promptWithHints([{type:"list",name:"choice",message:p.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:p.t("wizard.input_custom_model"),default:!d&&m?m:void 0}]),a=(t||"").trim();o.setToolModel(i,a?this.singleModelOverride(a):null)}else if("fetch"===g.type){const n=a(p.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:p.t("wizard.select_fetched_model"),pageSize:20,choices:[...r.models,new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:"__back__"}]}]);if("__back__"===t)return!1;s=t}else{console.log(t.yellow("\n"+p.t("wizard.fetch_models_failed")));const{model:a}=await e.prompt([{type:"input",name:"model",message:p.t("wizard.input_custom_model"),default:!d&&m?m:void 0}]);s=(a||"").trim()}o.setToolModel(i,s?this.singleModelOverride(s):null)}if("codex"===i){const t=o.getToolSetting(i,f),{enableOneMillionContext:a}=await e.prompt([{type:"confirm",name:"enableOneMillionContext",message:p.t("wizard.codex_enable_1m_context"),default:!1!==t}]);o.setToolSetting(i,f,Boolean(a))}if("claude-desktop"===i){const t=o.getToolSetting(i,y),{hideOfficialLogin:a}=await e.prompt([{type:"confirm",name:"hideOfficialLogin",message:p.t("wizard.desktop_hide_official_login"),default:!1!==t}]);o.setToolSetting(i,y,Boolean(a))}return console.log(t.green("\n✓ "+p.t("wizard.models_saved"))),d&&console.log(t.gray("💡 "+p.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:p.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:p.t("wizard.press_enter")}]);const m=a(p.t("wizard.loading_config")).start();try{await l.applyPrivateConfig(i,s,r,n),m.stop(),l.printApplied(i),await d([i]),n.force&&console.log(t.yellow(p.t("config.force_done",{tool:c[i]?.displayName||i})));const a=c[i]?.command;a&&console.log(t.green("\n"+p.t("wizard.run_tool_hint",{command:a})));const{nextAction:o}=await e.prompt([{type:"list",name:"nextAction",message:p.t("wizard.what_next"),choices:[{name:p.t("wizard.exit_and_start"),value:"exit"},{name:p.t("wizard.continue_config"),value:"continue"}]}]);"exit"===o&&(this.printGoodbye(),process.exit(0))}catch(a){m.fail(p.t("wizard.config_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:p.t("wizard.press_enter")}])}}async clearPinnedModels(a){const o=c[a]?.displayName||a,{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:p.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"+p.t("config.clear_model_none",{tool:o}))):(console.log(t.green("\n✓ "+p.t("config.clear_model_done",{tool:o}))),e.forEach(e=>console.log(t.gray(` - ${e}`))),console.log(t.gray(p.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:p.t("wizard.press_enter")}])}}async unloadConfig(o){const{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:p.t("wizard.confirm_unload_config",{tool:c[o]?.displayName||o}),default:!1}]);if(!i)return;const n=a(p.t("wizard.unloading_config")).start();try{const a=l.unloadPrivateConfig(o);n.succeed(p.t("wizard.config_unloaded")),a.forEach(e=>console.log(t.yellow(" ! "+e.text)));const{nextAction:i}=await e.prompt([{type:"list",name:"nextAction",message:p.t("wizard.what_next"),choices:[{name:p.t("wizard.exit_and_start"),value:"exit"},{name:p.t("wizard.continue_config"),value:"continue"}]}]);"exit"===i&&(this.printGoodbye(),process.exit(0))}catch(a){n.fail(p.t("wizard.config_unload_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:p.t("wizard.press_enter")}])}}async restoreConfig(o){const i=c[o]?.displayName||o,{confirm:n}=await e.prompt([{type:"confirm",name:"confirm",message:p.t("wizard.confirm_restore_config",{tool:i}),default:!1}]);if(!n)return;const r=a(p.t("wizard.restoring_config")).start();try{const e=l.restorePrivateConfig(o).filter(e=>e.result.restored);0===e.length?r.warn(p.t("wizard.restore_no_backup")):(r.succeed(p.t("wizard.config_restored",{tool:i})),e.forEach(e=>console.log(t.gray(` ${e.file} ← ${e.result.from}`))))}catch(e){r.fail(p.t("wizard.config_restore_failed")),console.log(t.red(e instanceof Error?e.message:String(e)))}await e.prompt([{type:"input",name:"continue",message:p.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(W("── "+p.t("wizard.select_tool")+" ──")),...n,new e.Separator(t.gray("── "+p.t("wizard.settings")+" ──")),{name:"🔑 "+p.t("wizard.menu_change_api_key"),value:{type:"apikey"}},{name:"🔗 "+p.t("wizard.menu_base_url",{url:o.getBaseUrl()}),value:{type:"base"}},{name:"🌐 "+p.t("wizard.menu_config_language"),value:{type:"language"}},new e.Separator,{name:"x "+p.t("wizard.nav_exit"),value:{type:"exit"}}],{action:s}=await this.promptWithHints([{type:"list",name:"action",message:"🛠️ "+p.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{postApplyPrompts as d}from"./post-apply.js";import{i18n as p,detectSystemLang as m}from"./i18n.js";import{createBorderLine as u,createContentLine as _}from"../utils/string-width.js";import{validateApiKey as g,fetchModels as w}from"./api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as f}from"./tools/codex.js";import{CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as y}from"./tools/claude-desktop.js";import{addressesWithCurrent as h,ensureReachableGatewayAddress as z,fastestIndex as v,probeAll as k,probeSummary as x,reasonText as b,savedApiKey as S,switchGatewayAddress as C}from"../commands/base.js";import{readFileSync as M}from"fs";import{dirname as T,join as A}from"path";import{fileURLToPath as K}from"url";import{brand as N}from"./brand.js";const B=T(K(import.meta.url)),H=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(H.bold("\n"+u("╔","╗","═",this.BOX_WIDTH))),console.log(H.bold(_(e,"║","║",this.BOX_WIDTH,"center"))),console.log(H.bold(u("╚","╝","═",this.BOX_WIDTH))),console.log("")}showOperationHints(){const e=[t.gray(p.t("wizard.hint_navigate")),t.gray(p.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=p.t("wizard.banner_subtitle"),a=_(t,"║","║",e,"center"),o=_("","║","║",e,"center"),i=_(`${N().productName} v${function(){try{return JSON.parse(M(A(B,"..","..","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=>_(s+t,"║","║",e,"left")),c=[u("╔","╗","═",e),o,...l,o,i,a,u("╚","╝","═",e)];console.log(H.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=p.t("wizard.goodbye_message_tools",{commands:t}),e.some(e=>"claude-code"===e.name)&&(a+=" "+p.t("wizard.goodbye_claude_hint"))}else a=p.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(" ! "+p.t("win32"===process.platform?"setup.path_reload_windows":"setup.path_reload",{commands:o})))}async runFirstTimeSetup(){const e="zh_CN"===m();e&&(o.setLang("zh_CN"),p.setLocale("zh_CN")),this.resetScreen(),console.log(H.bold("\n"+p.t("wizard.welcome"))),console.log(t.gray(p.t("wizard.privacy_note")+"\n")),e?console.log(t.gray(p.t("wizard.lang_auto_zh")+"\n")):await this.configLanguage(),await z(),await this.configApiKey()&&await this.selectAndConfigureTool(!0)}async configLanguage(){for(;;){this.resetScreen(),this.createBox(p.t("wizard.select_language"));const a=p.getLocale(),{language:i}=await this.promptWithHints([{type:"list",name:"language",message:"✨ "+p.t("wizard.select_language"),choices:[{name:"[EN] English"+("en_US"===a?t.green(" ✓ ("+p.t("wizard.current_active")+")"):""),value:"en_US"},{name:"[CN] 中文"+("zh_CN"===a?t.green(" ✓ ("+p.t("wizard.current_active")+")"):""),value:"zh_CN"},new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:"back"},{name:"x "+p.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 p.setLocale(i)}}buildPresetChoices(){const a=n(),o=a.filter(e=>e.recommended),i=a.filter(e=>!e.recommended),r=e=>({name:(p.t(e.name)!==e.name?p.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")("── "+p.t("wizard.recommended")+" ──"))),s.push(...o.map(r))),i.length>0&&(s.push(new e.Separator(t.gray("── "+p.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:p.t("wizard.custom_model_mode"),choices:[{name:p.t("wizard.custom_model_single"),value:"single"},{name:p.t("wizard.custom_model_per_role"),value:"per_role"}]}]);if("single"===n){const{customModel:t}=await e.prompt([{type:"input",name:"customModel",message:p.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:p.t("wizard.model_haiku"),default:a.haiku},{type:"input",name:"sonnet",message:p.t("wizard.model_sonnet"),default:a.sonnet},{type:"input",name:"opus",message:p.t("wizard.model_opus"),default:a.opus},{type:"input",name:"reasoning",message:p.t("wizard.model_reasoning"),default:a.reasoning}]);o.setModels(t)}console.log(t.green("\n✓ "+p.t("wizard.models_saved")))}async configModels(a){const i=o.getApiKey();if(await this.validatedKeyForConfiguration(i))for(;;){this.resetScreen(),this.createBox(p.t("wizard.config_models"));const i=[...this.buildPresetChoices()];i.push(new e.Separator),i.push({name:"✏️ "+p.t("wizard.custom_model_input"),value:{type:"custom_input"}}),i.push(new e.Separator),i.push({name:"<- "+p.t("wizard.nav_return"),value:{type:"back"}}),i.push({name:"x "+p.t("wizard.nav_exit"),value:{type:"exit"}});const{modelChoice:n}=await this.promptWithHints([{type:"list",name:"modelChoice",message:p.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✓ "+p.t("wizard.models_saved"))),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}}}else await e.prompt([{type:"input",name:"continue",message:p.t("wizard.press_enter")}])}async promptLoadAfterModelConfig(){const{shouldLoad:t}=await e.prompt([{type:"list",name:"shouldLoad",message:p.t("wizard.load_config_now"),choices:[{name:p.t("wizard.load_config_yes"),value:!0},{name:p.t("wizard.load_config_later"),value:!1}]}]);t&&await this.selectAndConfigureTool()}async configBaseUrl(){const i=o.getBaseUrl(),n=h(),r=a(p.t("wizard.base_testing")).start(),s=await k(n,{apiKey:S(),samples:3});r.stop();const l=v(s),c=n.map((e,a)=>{const o=e.url===i?t.cyan(` ← ${p.t("base.current_mark")}`):"";return{name:`${e.url} ${t.gray(e.label)} ${x(s[a],a===l)}${o}`,value:e.url}});c.push(new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:"__back__"});const{url:d}=await this.promptWithHints([{type:"list",name:"url",message:p.t("wizard.base_select"),choices:c,default:i}]);if("__back__"===d)return;const m=s[n.findIndex(e=>e.url===d)];m.ok?await C(d):console.log(t.red(p.t("base.unreachable",{url:d,reason:b(m)}))),await e.prompt([{type:"input",name:"continue",message:p.t("wizard.press_enter")}])}async configApiKey(){for(;;){this.resetScreen(),this.createBox(p.t("wizard.input_api_key")),console.log(t.gray("\n💡 "+p.t("wizard.api_key_input_hint"))),console.log(t.gray(" "+p.t("wizard.api_key_get_hint",{url:N().links.tokenPage}))),console.log();const{apiKey:i}=await e.prompt([{type:"password",name:"apiKey",message:p.t("wizard.input_your_api_key"),mask:"*"}]);if(!i||""===i.trim()){const{action:t}=await e.prompt([{type:"list",name:"action",message:p.t("wizard.select_action"),choices:[{name:p.t("wizard.retry_input"),value:"retry"},{name:"<- "+p.t("wizard.nav_return"),value:"back"}]}]);if("back"===t)return!1;continue}const n=a(p.t("wizard.validating_api_key")).start(),r=await g(i.trim());if(n.stop(),r.valid)return o.setApiKey(i.trim()),this.validatedApiKeys.add(i.trim()),console.log(t.green("\n✓ "+p.t("wizard.api_key_valid"))),!0;{this.validatedApiKeys.delete(i.trim()),"invalid_api_key"===r.error?console.log(t.red("\n✗ "+p.t("wizard.api_key_invalid"))):console.log(t.red("\n✗ "+p.t("wizard.api_key_network_error")));const{action:a}=await e.prompt([{type:"list",name:"action",message:p.t("wizard.select_action"),choices:[{name:p.t("wizard.retry_input"),value:"retry"},{name:"<- "+p.t("wizard.nav_return"),value:"back"}]}]);if("back"===a)return!1}}}async selectAndConfigureTool(t=!1){for(;;){this.resetScreen(),this.createBox(p.t("wizard.select_tool"));const a=l.getSupportedTools().map(e=>({name:e.displayName,value:e.name})),{tool:o}=await this.promptWithHints([{type:"list",name:"tool",message:"🛠️ "+p.t("wizard.select_tool"),choices:[...a,new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:"back"},{name:"x "+p.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===o)this.printGoodbye(),process.exit(0);else if("back"===o)return;await this.configureTool(o,t)}}async configureTool(a,o=!1){const i=c[a];if(i){if(!l.isToolInstalled(a)){console.log(t.yellow("\n"+p.t("wizard.tool_not_installed",{tool:i.displayName})));const{install:o}=await e.prompt([{type:"confirm",name:"install",message:p.t("wizard.install_tool_confirm"),default:!0}]);if(!o)return;try{await l.installTool(a)}catch{return void console.log(t.red(p.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+" "+p.t("wizard.menu_title"));const o=[{name:"📥 "+p.t("wizard.action_load_config",{tool:a.displayName}),value:"load"},{name:"📤 "+p.t("wizard.action_unload_config",{tool:a.displayName}),value:"unload"}];l.supportsClearPinnedModels(t)&&o.push({name:"🧹 "+p.t("wizard.action_clear_model",{tool:a.displayName}),value:"clear-model"}),o.push({name:"🧨 "+p.t("wizard.action_force_config",{tool:a.displayName}),value:"force"},{name:"↩️ "+p.t("wizard.action_restore_config",{tool:a.displayName}),value:"restore"},new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:"back"},{name:"x "+p.t("wizard.nav_exit"),value:"exit"});const{action:i}=await this.promptWithHints([{type:"list",name:"action",message:"⚙️ "+p.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):"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"+p.t("wizard.api_key_required"))),console.log(t.yellow(p.t("wizard.please_config_api_key_first"))),null;if(this.validatedApiKeys.has(o))return o;const i=a(p.t("wizard.validating_api_key")).start(),n=await g(o);if(n.valid)return this.validatedApiKeys.add(o),i.succeed(p.t("wizard.api_key_valid")),o;this.validatedApiKeys.delete(o);const r="invalid_api_key"===n.error?p.t("wizard.api_key_invalid"):p.t("wizard.api_key_network_error");return i.fail(r),console.log(t.red("\n"+p.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:p.t("wizard.press_enter")}]),!1;const d="claude-code"===i,m=s(i),u=d||!m?p.t("wizard.model_builtin_default"):m;this.resetScreen(),this.createBox(n.displayName+" · "+p.t("wizard.config_models"));const _=[{name:"✅ "+p.t("wizard.use_default_model",{model:u}),value:{type:"default"}},{name:"🌐 "+p.t("wizard.fetch_models_from_api"),value:{type:"fetch"}},...this.buildPresetChoices(),new e.Separator,{name:"✏️ "+p.t("wizard.input_custom_model"),value:{type:"custom"}},new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:{type:"back"}}],{choice:g}=await this.promptWithHints([{type:"list",name:"choice",message:p.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:p.t("wizard.input_custom_model"),default:!d&&m?m:void 0}]),a=(t||"").trim();o.setToolModel(i,a?this.singleModelOverride(a):null)}else if("fetch"===g.type){const n=a(p.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:p.t("wizard.select_fetched_model"),pageSize:20,choices:[...r.models,new e.Separator,{name:"<- "+p.t("wizard.nav_return"),value:"__back__"}]}]);if("__back__"===t)return!1;s=t}else{console.log(t.yellow("\n"+p.t("wizard.fetch_models_failed")));const{model:a}=await e.prompt([{type:"input",name:"model",message:p.t("wizard.input_custom_model"),default:!d&&m?m:void 0}]);s=(a||"").trim()}o.setToolModel(i,s?this.singleModelOverride(s):null)}if("codex"===i){const t=o.getToolSetting(i,f),{enableOneMillionContext:a}=await e.prompt([{type:"confirm",name:"enableOneMillionContext",message:p.t("wizard.codex_enable_1m_context"),default:!1!==t}]);o.setToolSetting(i,f,Boolean(a))}if("claude-desktop"===i){const t=o.getToolSetting(i,y),{hideOfficialLogin:a}=await e.prompt([{type:"confirm",name:"hideOfficialLogin",message:p.t("wizard.desktop_hide_official_login"),default:!1!==t}]);o.setToolSetting(i,y,Boolean(a))}return console.log(t.green("\n✓ "+p.t("wizard.models_saved"))),d&&console.log(t.gray("💡 "+p.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:p.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:p.t("wizard.press_enter")}]);const m=a(p.t("wizard.loading_config")).start();try{await l.applyPrivateConfig(i,s,r,n),m.stop(),l.printApplied(i),await d([i]),n.force&&console.log(t.yellow(p.t("config.force_done",{tool:c[i]?.displayName||i})));const a=c[i];a&&!a.gui&&(console.log(t.green("\n"+p.t("wizard.run_tool_hint",{command:a.command}))),this.printPathReloadHint([i]));const{nextAction:o}=await e.prompt([{type:"list",name:"nextAction",message:p.t("wizard.what_next"),choices:[{name:p.t("wizard.exit_and_start"),value:"exit"},{name:p.t("wizard.continue_config"),value:"continue"}]}]);"exit"===o&&(this.printGoodbye(),process.exit(0))}catch(a){m.fail(p.t("wizard.config_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:p.t("wizard.press_enter")}])}}async clearPinnedModels(a){const o=c[a]?.displayName||a,{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:p.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"+p.t("config.clear_model_none",{tool:o}))):(console.log(t.green("\n✓ "+p.t("config.clear_model_done",{tool:o}))),e.forEach(e=>console.log(t.gray(` - ${e}`))),console.log(t.gray(p.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:p.t("wizard.press_enter")}])}}async unloadConfig(o){const{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:p.t("wizard.confirm_unload_config",{tool:c[o]?.displayName||o}),default:!1}]);if(!i)return;const n=a(p.t("wizard.unloading_config")).start();try{const a=l.unloadPrivateConfig(o);n.succeed(p.t("wizard.config_unloaded")),a.forEach(e=>console.log(t.yellow(" ! "+e.text)));const{nextAction:i}=await e.prompt([{type:"list",name:"nextAction",message:p.t("wizard.what_next"),choices:[{name:p.t("wizard.nav_exit"),value:"exit"},{name:p.t("wizard.continue_config"),value:"continue"}]}]);"exit"===i&&(this.printGoodbye(),process.exit(0))}catch(a){n.fail(p.t("wizard.config_unload_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:p.t("wizard.press_enter")}])}}async restoreConfig(o){const i=c[o]?.displayName||o,{confirm:n}=await e.prompt([{type:"confirm",name:"confirm",message:p.t("wizard.confirm_restore_config",{tool:i}),default:!1}]);if(!n)return;const r=a(p.t("wizard.restoring_config")).start();try{const e=l.restorePrivateConfig(o).filter(e=>e.result.restored);0===e.length?r.warn(p.t("wizard.restore_no_backup")):(r.succeed(p.t("wizard.config_restored",{tool:i})),e.forEach(e=>console.log(t.gray(` ${e.file} ← ${e.result.from}`))),console.log(t.yellow(" ! "+p.t("config.reopen_hint",{tool:i}))))}catch(e){r.fail(p.t("wizard.config_restore_failed")),console.log(t.red(e instanceof Error?e.message:String(e)))}await e.prompt([{type:"input",name:"continue",message:p.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(H("── "+p.t("wizard.select_tool")+" ──")),...n,new e.Separator(t.gray("── "+p.t("wizard.settings")+" ──")),{name:"🔑 "+p.t("wizard.menu_change_api_key"),value:{type:"apikey"}},{name:"🔗 "+p.t("wizard.menu_base_url",{url:o.getBaseUrl()}),value:{type:"base"}},{name:"🌐 "+p.t("wizard.menu_config_language"),value:{type:"language"}},new e.Separator,{name:"x "+p.t("wizard.nav_exit"),value:{type:"exit"}}],{action:s}=await this.promptWithHints([{type:"list",name:"action",message:"🛠️ "+p.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
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"menu_config_tool": "Coding Tool Configuration (Apply API to Claude Code/Codex and more)",
|
|
91
91
|
"menu_exit": "Exit",
|
|
92
92
|
"select_operation": "Select operation:",
|
|
93
|
-
"goodbye_message": "Goodbye!
|
|
93
|
+
"goodbye_message": "Goodbye! No tool is configured yet; when you need one, run {{cli}} setup --key <your key>",
|
|
94
94
|
"lang_auto_zh": "Detected a Chinese system locale; using the Chinese interface automatically (switch anytime via the main menu or {{cli}} lang set).",
|
|
95
95
|
"goodbye_message_tools": "Goodbye! Type {{commands}} in your terminal to start coding!",
|
|
96
96
|
"goodbye_claude_hint": "You can also install the Claude extension in VSCode to use Claude Code.",
|
|
@@ -290,7 +290,8 @@
|
|
|
290
290
|
"force_done": "Reset {{tool}}'s config files (originals snapshotted; undo with `{{cli}} config {{tool}} restore`)",
|
|
291
291
|
"confirm_remove": "Remove the {{brand}} configuration from {{tool}}? (The current state is backed up first; {{cli}} config {{name}} restore brings it back)",
|
|
292
292
|
"remove_dry_run": "Would remove the {{brand}} provider, key and model settings from {{tool}}, keeping everything else",
|
|
293
|
-
"remove_done": "Removed the {{brand}} configuration from {{tool}}"
|
|
293
|
+
"remove_done": "Removed the {{brand}} configuration from {{tool}}",
|
|
294
|
+
"reopen_hint": "Quit {{tool}} completely and reopen it if it is already running"
|
|
294
295
|
},
|
|
295
296
|
"logs": {
|
|
296
297
|
"directory": "Logs directory: {{dir}}",
|
package/dist/locales/zh_CN.json
CHANGED
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"menu_config_tool": "编码工具配置 (将 API 应用到 Claude Code/Codex 等)",
|
|
91
91
|
"menu_exit": "退出",
|
|
92
92
|
"select_operation": "请选择操作:",
|
|
93
|
-
"goodbye_message": "
|
|
93
|
+
"goodbye_message": "再见!还没有配置好的工具,需要时运行 {{cli}} setup --key <你的 Key>",
|
|
94
94
|
"lang_auto_zh": "检测到系统语言为中文,已自动使用中文界面(主菜单或 {{cli}} lang set 可随时切换)。",
|
|
95
95
|
"goodbye_message_tools": "再见! 终端输入 {{commands}} 即可开始编码!",
|
|
96
96
|
"goodbye_claude_hint": "也可以在 VSCode 安装 Claude 插件使用 Claude Code。",
|
|
@@ -290,7 +290,8 @@
|
|
|
290
290
|
"force_done": "已重置 {{tool}} 的配置文件(原文件已快照,`{{cli}} config {{tool}} restore` 可撤销)",
|
|
291
291
|
"confirm_remove": "确定从 {{tool}} 移除 {{brand}} 的配置吗?(当前状态会先自动备份,可用 {{cli}} config {{name}} restore 还原)",
|
|
292
292
|
"remove_dry_run": "将从 {{tool}} 移除 {{brand}} 的服务商、Key 和模型设置,其它设置保留",
|
|
293
|
-
"remove_done": "已从 {{tool}} 移除 {{brand}} 的配置"
|
|
293
|
+
"remove_done": "已从 {{tool}} 移除 {{brand}} 的配置",
|
|
294
|
+
"reopen_hint": "已经打开的 {{tool}} 要完全退出后重新打开才会生效"
|
|
294
295
|
},
|
|
295
296
|
"logs": {
|
|
296
297
|
"directory": "日志目录: {{dir}}",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeapi/api-helper",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.107",
|
|
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",
|