@vibeapi/api-helper 0.0.126 → 0.0.128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/auth.js +1 -1
- package/dist/commands/bench.js +1 -1
- package/dist/commands/completion.js +1 -1
- package/dist/commands/config.js +1 -1
- package/dist/commands/lang.js +1 -1
- package/dist/commands/logs.js +1 -1
- package/dist/lib/codex-sessions.d.ts +7 -0
- package/dist/lib/codex-sessions.js +1 -1
- package/dist/lib/errors.js +1 -1
- package/dist/lib/tool-manager.d.ts +2 -0
- package/dist/lib/tool-manager.js +1 -1
- package/dist/lib/tools/claude-code.js +1 -1
- package/dist/lib/tools/codex.js +1 -1
- package/dist/lib/tools/types.d.ts +6 -0
- package/dist/lib/wizard.js +1 -1
- package/dist/locales/en_US.json +3 -3
- package/dist/locales/zh_CN.json +3 -3
- package/package.json +1 -1
package/dist/commands/auth.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import e from"chalk";import o from"inquirer";import t from"ora";import{configManager as r}from"../lib/config.js";import{i18n as a}from"../lib/i18n.js";import{validateApiKey as i}from"../lib/api-validator.js";import{toolManager as n}from"../lib/tool-manager.js";import{isJsonMode as s,isNonInteractive as c,shouldAutoConfirm as d,emitJson as l,isColorEnabled as p}from"../lib/runtime-options.js";import{authenticationError as m,CliError as u,networkError as _,operationError as f,usageError as h}from"../lib/errors.js";import{CLI_NAME as k}from"../lib/brand.js";const w=["claude","claude-code","opencode"];function y(e){return p()?e:e=>e}function g(e,o=e=>e){s()||console.log(y(o)(e))}function v(e){return"invalid_api_key"===e.error?m(a.t("wizard.api_key_invalid"),a.t("errors.next_step",{command:`${k} auth ${a.t("errors.key_placeholder")}`}),"invalid_api_key"):_(a.t("wizard.api_key_network_error"),e.message??"",e.error??"network_error")}async function b(o){if(s()){const e=await i(o);if(!e.valid)throw v(e);return r.setApiKey(o),void l({ok:!0,action:"auth"})}const n=t(a.t("wizard.validating_api_key")).start(),c=await i(o);if(!c.valid)throw n.stop(),v(c);r.setApiKey(o),n.succeed(y(e.green)(a.t("auth.saved")))}export async function authCommand(t){0!==t.length?"revoke"!==t[0]?"reload"!==t[0]?await b(t[0]):await async function(o){const t=o.toLowerCase();if(!w.includes(t))throw h(a.t("auth.reload_tool_not_supported",{tool:o}),a.t("errors.next_step",{command:`${k} auth reload claude-code`}),"unsupported_tool");const i="opencode"===t?"opencode":"claude-code",c=r.getApiKeyForTool(i)||r.getApiKey();if(!c)throw h(a.t("bench.missing_api_key"),a.t("errors.next_step",{command:`${k} setup --key ${a.t("errors.key_placeholder")}`}),"missing_api_key");const d="opencode"===t?"OpenCode":"Claude Code";s()||g(a.t("auth.reloading",{tool:d}),e.blue);try{await n.applyPrivateConfig(i,c,r.getModelsForTool(i)),s()?l({ok:!0,action:"reload",tool:i}):g(a.t("auth.reloaded",{tool:d}),e.green)}catch(e){throw f(`${a.t("auth.reload_failed")} ${e instanceof Error?e.message:String(e)}`,a.t("errors.hint_logs"),"reload_failed")}}(t[1]||""):await async function(){if(!d()){const{confirm:e}=await o.prompt([{type:"confirm",name:"confirm",message:a.t("auth.revoke_confirm"),default:!1}]);if(!e)throw new u("cancelled",a.t("auth.not_revoked"),"","user_cancelled")}r.revokeApiKey(),s()?l({ok:!0,action:"revoke"}):g(a.t("auth.revoked"),e.green)}():await async function(){if(c())throw h(a.t("runtime.non_interactive_required_token"),a.t("errors.next_step",{command:`${k} auth ${a.t("errors.key_placeholder")}`}),"token_required");const{token:e}=await o.prompt([{type:"password",name:"token",message:a.t("auth.token_prompt"),validate:e=>!(!e||0===e.trim().length)||a.t("auth.token_required")}]);await b(e.trim())}()}
|
package/dist/commands/bench.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"chalk";import{configManager as o}from"../lib/config.js";import{savedApiKey as
|
|
1
|
+
import e from"chalk";import{configManager as o}from"../lib/config.js";import{savedApiKey as s}from"./base.js";import{i18n as r}from"../lib/i18n.js";import{isJsonMode as n,emitJson as t,isColorEnabled as l}from"../lib/runtime-options.js";import{usageError as m}from"../lib/errors.js";import{CLI_NAME as a}from"../lib/brand.js";function i(e){return l()?e:e=>e}export async function benchCommand(l,c=function(e){let o=5;for(let s=0;s<e.length;s+=1)if("--samples"===e[s]&&e[s+1]){const r=Number.parseInt(e[s+1],10);Number.isFinite(r)&&r>0&&r<=50&&(o=r)}return{samples:o}}(l)){const h=s();if(!h)throw m(r.t("bench.missing_api_key"),r.t("errors.next_step",{command:`${a} setup --key ${r.t("errors.key_placeholder")}`}),"missing_api_key");const p=c.fetchFn||fetch,g=o.getBaseUrl(),u=`${g}/v1/models`,b={samples:c.samples,errors:0,durations:[]};n()||console.log(i(e.gray)(r.t("bench.running")));for(let e=0;e<c.samples;e+=1){const e=Date.now();try{if(!(await p(u,{method:"GET",headers:{Authorization:`Bearer ${h}`,Accept:"application/json"}})).ok){b.errors+=1;continue}b.durations.push(Date.now()-e)}catch{b.errors+=1}}const f=function(e){const o=e.durations.slice().sort((e,o)=>e-o),s=o.reduce((e,o)=>e+o,0),r=0===o.length?0:o.length%2==0?(o[o.length/2-1]+o[o.length/2])/2:o[Math.floor(o.length/2)],n=0===o.length?0:s/o.length;return{samples:e.samples,completed:o.length,errors:e.errors,median_ms:Math.round(r),average_ms:Math.round(n),min_ms:o[0]||0,max_ms:o[o.length-1]||0}}(b),d=b.errors===c.samples;n()?t({ok:!d,base_url:g,...f}):(console.log("\n"+i(e.bold)(r.t("bench.result_title"))),console.log(` ${r.t("bench.samples")}: ${f.samples}`),console.log(` ${r.t("bench.median")}: ${f.median_ms}ms`),console.log(` ${r.t("bench.average")}: ${f.average_ms}ms`),console.log(` ${r.t("bench.min")}: ${f.min_ms}ms`),console.log(` ${r.t("bench.max")}: ${f.max_ms}ms`),console.log(` ${r.t("bench.errors")}: ${f.errors}`))}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i18n as n}from"../lib/i18n.js";import{isJsonMode as o,emitJson as e}from"../lib/runtime-options.js";import{CLI_NAME as s}from"../lib/brand.js";const
|
|
1
|
+
import{i18n as n}from"../lib/i18n.js";import{isJsonMode as o,emitJson as e}from"../lib/runtime-options.js";import{CLI_NAME as s}from"../lib/brand.js";import{usageError as c}from"../lib/errors.js";const t=s.replace(/-/g,"_"),i=["init","setup","lang","auth","doctor","status","logs","completion","update","upgrade","codex","bench","base","config","enter"],r=["profile","preset","backup","claude-code","codex"],m=["list","create","use","delete"],l=["list","save","use","delete"],a=["list","create","restore"],p=["revoke","reload"],u=["show","set"],$=["path","list","tail"],_=["bash","zsh","fish"],d=["--base","--non-interactive","--json","--yes","--dry-run","--no-color","--help","--version"];export async function completionCommand(h){const b=(h[0]||"").toLowerCase();if(!_.includes(b))throw c(n.t("completion.unsupported_shell",{shell:b}),n.t("errors.next_step",{command:`${s} completion bash`}),"unsupported_shell");const f="bash"===b?`# ${s} bash completion\n_${t}_completions() {\n local cur prev\n COMPREPLY=()\n cur="\${COMP_WORDS[COMP_CWORD]}"\n prev="\${COMP_WORDS[COMP_CWORD-1]}"\n\n case "\${prev}" in\n ${s})\n COMPREPLY=( $(compgen -W "${i.join(" ")} ${d.join(" ")}" -- "\${cur}") )\n return 0\n ;;\n config)\n COMPREPLY=( $(compgen -W "${r.join(" ")}" -- "\${cur}") )\n return 0\n ;;\n profile)\n COMPREPLY=( $(compgen -W "${m.join(" ")}" -- "\${cur}") )\n return 0\n ;;\n preset)\n COMPREPLY=( $(compgen -W "${l.join(" ")}" -- "\${cur}") )\n return 0\n ;;\n backup)\n COMPREPLY=( $(compgen -W "${a.join(" ")}" -- "\${cur}") )\n return 0\n ;;\n auth)\n COMPREPLY=( $(compgen -W "${p.join(" ")}" -- "\${cur}") )\n return 0\n ;;\n lang)\n COMPREPLY=( $(compgen -W "${u.join(" ")}" -- "\${cur}") )\n return 0\n ;;\n logs)\n COMPREPLY=( $(compgen -W "${$.join(" ")}" -- "\${cur}") )\n return 0\n ;;\n completion)\n COMPREPLY=( $(compgen -W "${_.join(" ")}" -- "\${cur}") )\n return 0\n ;;\n esac\n\n if [[ "\${cur}" == --* ]]; then\n COMPREPLY=( $(compgen -W "${d.join(" ")}" -- "\${cur}") )\n return 0\n fi\n}\ncomplete -F _${t}_completions ${s}\n`:"zsh"===b?`#compdef ${s}\n_${t}() {\n local -a commands subcommands\n local context state line\n\n _arguments -C \\\n '(-h --help)'{-h,--help}'[Show help]' \\\n '(-v --version)'{-v,--version}'[Show version]' \\\n '--base[Custom API base URL]:url:' \\\n '--non-interactive[Disable interactive prompts]' \\\n '--json[Emit JSON output]' \\\n '(-y --yes)'{-y,--yes}'[Auto-confirm prompts]' \\\n '--dry-run[Show planned changes without writing]' \\\n '--no-color[Disable colored output]' \\\n '1:command:->command' \\\n '*::arg:->args'\n\n case $state in\n command)\n commands=(\n${i.map(n=>` '${n}:${s} ${n}'`).join("\n")}\n )\n _describe 'command' commands\n ;;\n args)\n case $line[1] in\n config)\n subcommands=(${r.map(n=>`'${n}'`).join(" ")})\n _describe 'config sub' subcommands\n ;;\n auth) _values 'auth sub' ${p.join(" ")} ;;\n lang) _values 'lang sub' ${u.join(" ")} ;;\n logs) _values 'logs action' ${$.join(" ")} ;;\n completion) _values 'shell' ${_.join(" ")} ;;\n esac\n ;;\n esac\n}\ncompdef _${t} ${s}\n`:`# ${s} fish completion\ncomplete -c ${s} -n "__fish_use_subcommand" -a "${i.join(" ")}"\ncomplete -c ${s} -n "__fish_seen_subcommand_from config" -a "${r.join(" ")}"\ncomplete -c ${s} -n "__fish_seen_subcommand_from profile" -a "${m.join(" ")}"\ncomplete -c ${s} -n "__fish_seen_subcommand_from preset" -a "${l.join(" ")}"\ncomplete -c ${s} -n "__fish_seen_subcommand_from backup" -a "${a.join(" ")}"\ncomplete -c ${s} -n "__fish_seen_subcommand_from auth" -a "${p.join(" ")}"\ncomplete -c ${s} -n "__fish_seen_subcommand_from lang" -a "${u.join(" ")}"\ncomplete -c ${s} -n "__fish_seen_subcommand_from logs" -a "${$.join(" ")}"\ncomplete -c ${s} -n "__fish_seen_subcommand_from completion" -a "${_.join(" ")}"\ncomplete -c ${s} -l base -d 'Custom API base URL'\ncomplete -c ${s} -l non-interactive -d 'Disable interactive prompts'\ncomplete -c ${s} -l json -d 'Emit JSON output'\ncomplete -c ${s} -l yes -s y -d 'Auto-confirm prompts'\ncomplete -c ${s} -l dry-run -d 'Show planned changes without writing'\ncomplete -c ${s} -l no-color -d 'Disable colored output'\n`;o()?e({shell:b,script:f}):(console.log(f),"bash"===b?console.log("# "+n.t("completion.instructions_bash")):"zsh"===b?console.log("# "+n.t("completion.instructions_zsh")):console.log("# "+n.t("completion.instructions_fish")))}
|
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{isDryRun as d,isNonInteractive as f,shouldAutoConfirm as g}from"../lib/runtime-options.js";const p=/^[a-zA-Z0-9._-]+$/;function m(o,e){const t=(o||"").trim();if(!t||!p.test(t))throw new Error(i.t(`config.${e}_invalid_name`,{name:t||"<empty>"}));return t}function _(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 u(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 _(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 y(a,f,g){if(!l[a])return void console.log(e.red(i.t("config.unknown_tool",{tool:a})));const p=(f[0]||"").toLowerCase();if("backups"!==p&&"list-backups"!==p)if("restore"!==p){if("remove"===p||"unload"===p){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=Boolean(n.detectCurrentConfig(a).apiKey),l=n.unloadPrivateConfig(a);t?(console.log(e.green(i.t("config.remove_done",{tool:o}))),l.forEach(o=>console.log(e.yellow(" ! "+o.text)))):console.log(e.gray(i.t("config.remove_nothing",{tool:o})))}})}if("clear-model"===p||"clear-models"===p){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(d())await c({description:i.t("config.tool_apply_dry_run",{tool:l[a].displayName}),json:{action:"apply",tool:a,force:Boolean(g.force)},apply:()=>{}});else{if(!n.isToolInstalled(a)){if(g.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(g.nonInteractive||g.force){const o=r.getApiKeyForTool(a);if(!o)return void console.log(e.red(i.t("auth.reload_missing_config")));if(g.force&&!g.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:g.force}),g.force&&console.log(e.yellow(i.t("config.force_done",{tool:l[a].displayName,name:a}))),void n.printApplied(a)}await t.showToolMenu(a)}}else await c({description:i.t("config.tool_restore_dry_run",{tool:l[a].displayName}),json:{action:"tool_restore",tool:a},apply:async()=>{await s({message:i.t("config.confirm_restore",{tool:l[a].displayName}),defaultValue:!1})&&u(a,"restore")}});else u(a,"backups")}export async function configCommand(t){const{positional:n,options:d}=function(o){const e=[],t={};(f()||g())&&(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),u=n[0],v=n.slice(1);if(u){switch(u){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 _(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}))):void await c({description:i.t("config.profile_create_dry_run",{name:o}),json:{action:"profile_create",name:o},apply:()=>{r.createProfile(o),console.log(e.green(i.t("config.profile_created",{name:o})))}})}if("use"===t){const o=m(n,"profile");return void await c({description:i.t("config.profile_use_dry_run",{name:o}),json:{action:"profile_use",name:o},apply:()=>{r.setActiveProfile(o),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 await async 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 _(i.t("config.preset_list_title"),o)}if("save"===t){const o=m(n,"preset");return void await c({description:i.t("config.preset_save_dry_run",{name:o}),json:{action:"preset_save",name:o},apply:()=>{r.saveCustomPreset(o,r.getModels()),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?void await c({description:i.t("config.preset_use_dry_run",{name:o}),json:{action:"preset_use",name:o},apply:()=>{r.setModels(t.models),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 void await c({description:i.t("config.preset_delete_dry_run",{name:o}),json:{action:"preset_delete",name:o},apply:()=>{r.deleteCustomPreset(o),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 await async 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 _(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&&p.test(n)?void await c({description:i.t("config.tool_model_set_dry_run",{tool:t,slot:n,model:a}),json:{action:"tool_model_set",tool:t,slot:n,model:a},apply:()=>{r.setToolModel(t,{[n]:a}),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(t?i.t("config.unknown_tool",{tool:t}):i.t("config.tool_model_usage")))}if("clear"===t||"remove"===t){const t=(o[1]||"").trim();return l[t]?void await c({description:i.t("config.tool_model_clear_dry_run",{tool:t}),json:{action:"tool_model_clear",tool:t},apply:()=>{r.setToolModel(t,null),console.log(e.green(i.t("config.tool_model_cleared",{tool:t})))}}):void console.log(e.red(t?i.t("config.unknown_tool",{tool:t}):i.t("config.tool_model_usage")))}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 _(i.t("config.backup_list_title"),o)}if("create"!==t&&"snapshot"!==t)return"restore"===t?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"))):void console.log(e.red(i.t("config.unknown_action",{action:t})));await c({description:i.t("config.backup_create_dry_run"),json:{action:"backup_create",name:n??null},apply:()=>{const o=r.createBackup(n);console.log(e.green(i.t("config.backup_created",{path:o})))}})}(o)}(v)}"claude-code"!==u&&"claude-code"!==v[0]?l[u]?await y(u,v,d):(console.error(e.red(i.t("config.unknown_command",{command:u}))),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 y("claude-code",v,d)}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 y(n,[],t)}(d)}
|
|
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{isDryRun as d,isNonInteractive as f,shouldAutoConfirm as g}from"../lib/runtime-options.js";const p=/^[a-zA-Z0-9._-]+$/;function m(o,e){const t=(o||"").trim();if(!t||!p.test(t))throw new Error(i.t(`config.${e}_invalid_name`,{name:t||"<empty>"}));return t}function _(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 u(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 _(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 y(a,f,g){if(!l[a])return void console.log(e.red(i.t("config.unknown_tool",{tool:a})));const p=(f[0]||"").toLowerCase();if("backups"!==p&&"list-backups"!==p)if("restore"!==p){if("remove"===p||"unload"===p){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.holdsOurConfig(a),l=n.unloadPrivateConfig(a);t?(console.log(e.green(i.t("config.remove_done",{tool:o}))),l.forEach(o=>console.log(e.yellow(" ! "+o.text)))):console.log(e.gray(i.t("config.remove_nothing",{tool:o})))}})}if("clear-model"===p||"clear-models"===p){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(d())await c({description:i.t("config.tool_apply_dry_run",{tool:l[a].displayName}),json:{action:"apply",tool:a,force:Boolean(g.force)},apply:()=>{}});else{if(!n.isToolInstalled(a)){if(g.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(g.nonInteractive||g.force){const o=r.getApiKeyForTool(a);if(!o)return void console.log(e.red(i.t("auth.reload_missing_config")));if(g.force&&!g.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:g.force}),g.force&&console.log(e.yellow(i.t("config.force_done",{tool:l[a].displayName,name:a}))),void n.printApplied(a)}await t.showToolMenu(a)}}else await c({description:i.t("config.tool_restore_dry_run",{tool:l[a].displayName}),json:{action:"tool_restore",tool:a},apply:async()=>{await s({message:i.t("config.confirm_restore",{tool:l[a].displayName}),defaultValue:!1})&&u(a,"restore")}});else u(a,"backups")}export async function configCommand(t){const{positional:n,options:d}=function(o){const e=[],t={};(f()||g())&&(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),u=n[0],v=n.slice(1);if(u){switch(u){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 _(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}))):void await c({description:i.t("config.profile_create_dry_run",{name:o}),json:{action:"profile_create",name:o},apply:()=>{r.createProfile(o),console.log(e.green(i.t("config.profile_created",{name:o})))}})}if("use"===t){const o=m(n,"profile");return void await c({description:i.t("config.profile_use_dry_run",{name:o}),json:{action:"profile_use",name:o},apply:()=>{r.setActiveProfile(o),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 await async 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 _(i.t("config.preset_list_title"),o)}if("save"===t){const o=m(n,"preset");return void await c({description:i.t("config.preset_save_dry_run",{name:o}),json:{action:"preset_save",name:o},apply:()=>{r.saveCustomPreset(o,r.getModels()),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?void await c({description:i.t("config.preset_use_dry_run",{name:o}),json:{action:"preset_use",name:o},apply:()=>{r.setModels(t.models),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 void await c({description:i.t("config.preset_delete_dry_run",{name:o}),json:{action:"preset_delete",name:o},apply:()=>{r.deleteCustomPreset(o),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 await async 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 _(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&&p.test(n)?void await c({description:i.t("config.tool_model_set_dry_run",{tool:t,slot:n,model:a}),json:{action:"tool_model_set",tool:t,slot:n,model:a},apply:()=>{r.setToolModel(t,{[n]:a}),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(t?i.t("config.unknown_tool",{tool:t}):i.t("config.tool_model_usage")))}if("clear"===t||"remove"===t){const t=(o[1]||"").trim();return l[t]?void await c({description:i.t("config.tool_model_clear_dry_run",{tool:t}),json:{action:"tool_model_clear",tool:t},apply:()=>{r.setToolModel(t,null),console.log(e.green(i.t("config.tool_model_cleared",{tool:t})))}}):void console.log(e.red(t?i.t("config.unknown_tool",{tool:t}):i.t("config.tool_model_usage")))}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 _(i.t("config.backup_list_title"),o)}if("create"!==t&&"snapshot"!==t)return"restore"===t?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"))):void console.log(e.red(i.t("config.unknown_action",{action:t})));await c({description:i.t("config.backup_create_dry_run"),json:{action:"backup_create",name:n??null},apply:()=>{const o=r.createBackup(n);console.log(e.green(i.t("config.backup_created",{path:o})))}})}(o)}(v)}"claude-code"!==u&&"claude-code"!==v[0]?l[u]?await y(u,v,d):(console.error(e.red(i.t("config.unknown_command",{command:u}))),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 y("claude-code",v,d)}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 y(n,[],t)}(d)}
|
package/dist/commands/lang.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{configManager as o}from"../lib/config.js";import{i18n as n}from"../lib/i18n.js";import l from"chalk";import{isJsonMode as
|
|
1
|
+
import{configManager as o}from"../lib/config.js";import{i18n as n}from"../lib/i18n.js";import l from"chalk";import{isJsonMode as a,emitJson as t,isColorEnabled as e}from"../lib/runtime-options.js";import{usageError as i}from"../lib/errors.js";function r(o){return e()?o:o=>o}export async function langCommand(e){if(0===e.length||"show"===e[0]){const e=o.getLang(),i=n.getAvailableLocales();return a()?void t({current:e,available:i}):(console.log(`${n.t("lang.current")}: ${r(l.cyan)(e)}`),void console.log(`${n.t("lang.available")}: ${i.join(", ")}`))}if("set"===e[0]&&e.length>=2){const g=e[1],s=n.getAvailableLocales();if(!s.includes(g))throw i(n.t("lang.invalid",{lang:g}),`${n.t("lang.available")}: ${s.join(", ")}`,"invalid_locale");const c=o.getLang();return o.setLang(g),n.loadFromConfig(g),a()?void t({ok:!0,from:c,to:g}):void console.log(r(l.green)(n.t("lang.changed",{from:c,to:g})))}console.log(n.t("lang.show_usage")),console.log(n.t("lang.set_usage"))}
|
package/dist/commands/logs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import o from"chalk";import{readdirSync as t,statSync as i,readFileSync as n,existsSync as r}from"fs";import{join as e}from"path";import{logger as s}from"../utils/logger.js";import{i18n as l}from"../lib/i18n.js";import{isJsonMode as f,emitJson as
|
|
1
|
+
import o from"chalk";import{readdirSync as t,statSync as i,readFileSync as n,existsSync as r}from"fs";import{join as e}from"path";import{logger as s}from"../utils/logger.js";import{i18n as l}from"../lib/i18n.js";import{isJsonMode as f,emitJson as m,isColorEnabled as c}from"../lib/runtime-options.js";import{operationError as g,usageError as a}from"../lib/errors.js";import{CLI_NAME as u}from"../lib/brand.js";const p=/^\d{4}-\d{2}-\d{2}\.log$/;function d(o){return c()?o:o=>o}export async function logsCommand(c){const h=c[0]||"list",_=s.getLogDir();if("path"===h)return f()?void m({log_dir:_}):void console.log(l.t("logs.directory",{dir:_}));const b=function(){const o=s.getLogDir();return r(o)?t(o).filter(o=>p.test(o)).map(t=>{const n=e(o,t),r=i(n);return{name:t,path:n,size:r.size,mtimeMs:r.mtimeMs}}).sort((o,t)=>t.mtimeMs-o.mtimeMs):[]}();if("list"!==h){if("tail"===h){const o=c[1],t=o?b.find(t=>t.name===o):b[0];if(!t)throw g(o?l.t("logs.no_such_file",{file:o}):l.t("logs.no_files"),"","no_log_file");const e=function(o,t=16384){if(!r(o))return"";const e=i(o),s=n(o);if(e.size<=t)return s.toString("utf-8");let l=e.size-t;for(;l<e.size&&128==(192&s[l]);)l+=1;return s.subarray(l).toString("utf-8")}(t.path);return f()?void m({file:t.name,path:t.path,content:e}):void console.log(e)}throw a(l.t("config.unknown_action",{action:h}),l.t("errors.next_step",{command:`${u} logs --help`}),"unknown_action")}if(f())m({log_dir:_,files:b});else if(console.log("\n"+d(o.bold)(l.t("logs.files_title"))),0!==b.length)for(const t of b){const i=new Date(t.mtimeMs).toISOString();console.log(` ${d(o.cyan)(t.name)} ${d(o.gray)(`${t.size}B`)} ${d(o.gray)(i)}`)}else console.log(" "+d(o.gray)(l.t("logs.no_files")))}
|
|
@@ -29,6 +29,13 @@ export declare function currentCodexProvider(): string;
|
|
|
29
29
|
export declare function setCodexProcessCheckForTests(fake: () => number[]): void;
|
|
30
30
|
/** PIDs of this user's running Codex processes (CLI, desktop app, background app-server) on this CODEX_HOME; they would overwrite the edits. */
|
|
31
31
|
export declare function runningCodexPids(): number[];
|
|
32
|
+
/**
|
|
33
|
+
* Where Codex keeps `state_*.sqlite`: `sqlite_home` in config.toml, else the
|
|
34
|
+
* `CODEX_SQLITE_HOME` environment variable (relative to the current directory),
|
|
35
|
+
* else CODEX_HOME (codex-rs/core/src/config/mod.rs). Codex++ sets the variable
|
|
36
|
+
* for its extra instances.
|
|
37
|
+
*/
|
|
38
|
+
export declare function codexSqliteHome(): string;
|
|
32
39
|
/** `dbSkipped` when Codex has no state DB yet: nothing to update, not a problem to report. */
|
|
33
40
|
export declare const NO_STATE_DB = "no state DB";
|
|
34
41
|
/** Move every local session under `target`. `dryRun` only counts. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawnSync as e}from"child_process";import{closeSync as t,copyFileSync as r,createReadStream as o,createWriteStream as n,existsSync as s,mkdirSync as i,openSync as
|
|
1
|
+
import{spawnSync as e}from"child_process";import{closeSync as t,copyFileSync as r,createReadStream as o,createWriteStream as n,existsSync as s,mkdirSync as i,openSync as c,readFileSync as a,readSync as f,readdirSync as l,realpathSync as u,renameSync as p,statSync as d,utimesSync as m,writeFileSync as h}from"fs";import{join as g,resolve as y}from"path";import{pipeline as v}from"stream/promises";import*as S from"@iarna/toml";import{codexHome as b,toolHome as _}from"./tools/types.js";import{CLI_NAME as x}from"./brand.js";export{b as codexHome};export function currentCodexProvider(){try{const e=S.parse(a(g(b(),"config.toml"),"utf-8"));return"string"==typeof e.model_provider&&e.model_provider.trim()?e.model_provider.trim():"openai"}catch{return"openai"}}let E=()=>{if("win32"===process.platform)return`${e("powershell.exe",["-NoProfile","-NonInteractive","-Command","(Get-Process -Name codex -ErrorAction SilentlyContinue).Id"],{encoding:"utf-8",windowsHide:!0}).stdout??""}`.split(/\s+/).filter(Boolean).map(Number);const t=process.getuid?.(),r=`${e("pgrep",["-x","-i",...void 0===t?[]:["-u",String(t)],"codex"],{encoding:"utf-8"}).stdout??""}`.split(/\s+/).filter(Boolean).map(Number);if("linux"!==process.platform)return r;const o=O(b());return r.filter(e=>{let t;try{t=a(`/proc/${e}/environ`,"utf-8")}catch{return!0}const r=new Map(t.split("\0").map(e=>[e.slice(0,e.indexOf("=")),e.slice(e.indexOf("=")+1)])),n=r.get("CODEX_HOME")?.trim()||(r.get("HOME")?g(r.get("HOME"),".codex"):null);return null===n||O(n)===o})};function O(e){try{return u(e)}catch{return e}}export function setCodexProcessCheckForTests(e){E=e}export function runningCodexPids(){try{return E()}catch{return[]}}function w(e){const r=c(e,"r");try{const e=[],t=Buffer.alloc(65536);for(;;){const o=f(r,t,0,t.length,null);if(o<=0)break;const n=t.subarray(0,o).indexOf(10);if(n>=0){e.push(Buffer.from(t.subarray(0,n)));break}e.push(Buffer.from(t.subarray(0,o)))}return Buffer.concat(e).toString("utf-8")}finally{t(r)}}async function N(e,t,r){const{atime:s,mtime:i}=d(e),c=`${e}.${x}-tmp`,a=n(c);a.write(t),await v(o(e,{start:r}),a),p(c,e),m(e,s,i)}export function codexSqliteHome(){const e=b();try{const t=S.parse(a(g(e,"config.toml"),"utf-8")),r="string"==typeof t.sqlite_home?t.sqlite_home.trim():"";if(r)return"~"===r||r.startsWith("~/")?g(_(),r.slice(1)):y(e,r)}catch{}const t=process.env.CODEX_SQLITE_HOME?.trim();return t?y(t):e}async function T(e){try{return new((await import("node:sqlite")).DatabaseSync)(e)}catch(e){return`node:sqlite unavailable (Node ${process.versions.node}; needs 22.13+): ${e instanceof Error?e.message:String(e)}`}}export const NO_STATE_DB="no state DB";export async function moveSessionsToProvider(e,t={}){const o=function(){const e=[],t=r=>{if(s(r))for(const o of l(r,{withFileTypes:!0})){const n=g(r,o.name);o.isDirectory()?t(n):o.isFile()&&o.name.endsWith(".jsonl")&&e.push(n)}};return t(g(b(),"sessions")),t(g(b(),"archived_sessions")),e}(),n=[];for(const t of o){let r,o;try{r=w(t)}catch{continue}try{o=JSON.parse(r)}catch{continue}const s=o.payload?.model_provider;"session_meta"===o.type&&"string"==typeof s&&s!==e&&(o.payload.model_provider=e,n.push({file:t,from:s,line:JSON.stringify(o),length:Buffer.byteLength(r,"utf-8")}))}const c=function(){const e=codexSqliteHome();if(!s(e))return null;const t=l(e).map(e=>/^state_(\d+)\.sqlite$/.exec(e)).filter(e=>!!e).sort((e,t)=>Number(t[1])-Number(e[1]));return t.length>0?g(e,t[0][0]):null}();let a=c?null:NO_STATE_DB,f=[],u=null;if(c){const t=await T(c);"string"==typeof t?a=t:(u=t,f=u.prepare('SELECT id, model_provider AS "from" FROM threads WHERE model_provider <> ?').all(e).map(e=>({id:String(e.id),from:String(e.from)})))}const p={target:e,scanned:o.length,moved:n.map(({file:e,from:t})=>({file:e,from:t})),dbRows:f.length,dbSkipped:a,backupDir:null};if(t.dryRun||0===n.length&&0===f.length)return u?.close(),p;const d=g(b(),"backups",`${x}-sessions-${(new Date).toISOString().replace(/[:.]/g,"-")}`);if(i(d,{recursive:!0}),c)for(const e of["","-wal","-shm"])s(c+e)&&r(c+e,g(d,`state.sqlite${e}`));const m={target:e,moved:p.moved,threads:f,db:c};h(g(d,"manifest.json"),JSON.stringify(m,null,2)+"\n");for(const e of n)await N(e.file,e.line,e.length);return u&&(u.prepare("UPDATE threads SET model_provider = ? WHERE model_provider <> ?").run(e,e),u.close()),p.backupDir=d,p}export async function undoSessionMove(e){const t=JSON.parse(a(g(e,"manifest.json"),"utf-8"));let r=0;for(const{file:e,from:o}of t.moved){if(!s(e))continue;const t=w(e),n=JSON.parse(t);n.payload&&(n.payload.model_provider=o,await N(e,JSON.stringify(n),Buffer.byteLength(t,"utf-8")),r+=1)}let o=0;if(t.db&&s(t.db)&&t.threads.length>0){const e=await T(t.db);if("string"!=typeof e){const r=e.prepare("UPDATE threads SET model_provider = ? WHERE id = ?");for(const{id:e,from:n}of t.threads)o+=Number(r.run(n,e).changes);e.close()}}return{files:r,dbRows:o}}
|
package/dist/lib/errors.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import r from"chalk";import{i18n as e}from"./i18n.js";import{isColorEnabled as t,isJsonMode as o}from"./runtime-options.js";export const EXIT_CODES={operation:1,usage:2,authentication:3,network:4,internal:5,confirmation:10,cancelled:130};export class CliError extends Error{type;hint;subtype;constructor(r,e,t,o){super(e),this.name="CliError",this.type=r,this.hint=t,this.subtype=o}}export function exitCodeForError(r){return r instanceof CliError?EXIT_CODES[r.type]:EXIT_CODES.internal}export function asCliError(r){if(r instanceof CliError)return r;if("ExitPromptError"===r?.name)return new CliError("cancelled",e.t("errors.cancelled"),e.t("errors.cancel_hint"),"user_cancelled");const t=r instanceof Error?r.message:String(r);return new CliError("internal",t,e.t("errors.hint_logs"),"unexpected_error")}export function reportCliError(e){const n=asCliError(e),i={ok:!1,error:{type:n.type,message:n.message,hint:n.hint,...n.subtype?{subtype:n.subtype}:{}}};if(o())process.stderr.write(JSON.stringify(i)+"\n");else{const e=t()?r.red:r=>r;process.stderr.write(e(n.message)+"\n"+n.hint+"\n")}const s=exitCodeForError(n);return process.exitCode=s,s}export function usageError(r,e,t){return new CliError("usage",r,e,t)}export function operationError(r,e,t){return new CliError("operation",r,e,t)}export function authenticationError(r,e,t){return new CliError("authentication",r,e,t)}export function networkError(r,e,t){return new CliError("network",r,e,t)}
|
|
1
|
+
import r from"chalk";import{i18n as e}from"./i18n.js";import{isColorEnabled as t,isJsonMode as o}from"./runtime-options.js";export const EXIT_CODES={operation:1,usage:2,authentication:3,network:4,internal:5,confirmation:10,cancelled:130};export class CliError extends Error{type;hint;subtype;constructor(r,e,t,o){super(e),this.name="CliError",this.type=r,this.hint=t,this.subtype=o}}export function exitCodeForError(r){return r instanceof CliError?EXIT_CODES[r.type]:EXIT_CODES.internal}export function asCliError(r){if(r instanceof CliError)return r;if("ExitPromptError"===r?.name)return new CliError("cancelled",e.t("errors.cancelled"),e.t("errors.cancel_hint"),"user_cancelled");const t=r instanceof Error?r.message:String(r);return new CliError("internal",t,e.t("errors.hint_logs"),"unexpected_error")}export function reportCliError(e){const n=asCliError(e),i={ok:!1,error:{type:n.type,message:n.message,hint:n.hint,...n.subtype?{subtype:n.subtype}:{}}};if(o())process.stderr.write(JSON.stringify(i)+"\n");else{const e=t()?r.red:r=>r;process.stderr.write(e(n.message)+"\n"+(n.hint?n.hint+"\n":""))}const s=exitCodeForError(n);return process.exitCode=s,s}export function usageError(r,e,t){return new CliError("usage",r,e,t)}export function operationError(r,e,t){return new CliError("operation",r,e,t)}export function authenticationError(r,e,t){return new CliError("authentication",r,e,t)}export function networkError(r,e,t){return new CliError("network",r,e,t)}
|
|
@@ -96,6 +96,8 @@ export declare class ToolManager {
|
|
|
96
96
|
clearPinnedModels(toolName: string): Promise<string[]>;
|
|
97
97
|
/** Whether this tool supports clearing a pinned model. */
|
|
98
98
|
supportsClearPinnedModels(toolName: string): boolean;
|
|
99
|
+
/** The tool currently holds our provider settings (what `remove` would take out). */
|
|
100
|
+
holdsOurConfig(toolName: string): boolean;
|
|
99
101
|
detectCurrentConfig(toolName: string): {
|
|
100
102
|
apiKey: string | null;
|
|
101
103
|
};
|
package/dist/lib/tool-manager.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{execSync as o,spawnSync as t}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 l}from"./config.js";import{getAdapter as s,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 m,rmSync as f}from"fs";import{dirname as g,join as h}from"path";import{toolHome as w}from"./tools/types.js";import{stringWidth as y}from"../utils/string-width.js";import{resolveModelCatalog as P}from"./model-catalog.js";import{compareVersions as $,getToolMinVersion as T}from"./model-registry.js";import{findInstalls as
|
|
1
|
+
import{execSync as o,spawnSync as t}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 l}from"./config.js";import{getAdapter as s,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 m,rmSync as f}from"fs";import{dirname as g,join as h}from"path";import{toolHome as w}from"./tools/types.js";import{stringWidth as y}from"../utils/string-width.js";import{resolveModelCatalog as P}from"./model-catalog.js";import{compareVersions as $,getToolMinVersion as T}from"./model-registry.js";import{findInstalls as C,forgetInstalls as v,installLabel as k,mirrorInstallCommand as E,npmMirrorInstallCommand as O}from"./tools/tool-installs.js";import{mirrorInstall as _}from"./tool-upgrade.js";import{CLI_NAME as S}from"./brand.js";import{track as N,trackStep as M}from"./telemetry.js";import{addUserPathDir as j,broadcastEnvChange as U}from"./windows-env.js";export{$ as compareVersions};function b(o){const t=c[o];return{name:t.name,command:t.command,installCommand:t.installCommand,configPath:t.configPath,displayName:t.displayName,...t.hidden?{hidden:!0}:{},...t.isInstalled?{gui:!0}:{}}}function x(){const o=new Set;for(const t of l.listProfiles()){const n=l.getProfile(t);for(const t of[n.api_key,...Object.values(n.tool_api_keys??{})])t?.trim()&&o.add(t.trim())}return[...o]}export const SUPPORTED_TOOLS=Object.fromEntries(Object.keys(c).map(o=>[o,b(o)]));export class ToolManager{static instance;constructor(){}static getInstance(){return ToolManager.instance||(ToolManager.instance=new ToolManager),ToolManager.instance}isToolInstalled(o){if(!SUPPORTED_TOOLS[o])return!1;const t=s(o);if(t?.isInstalled)try{return t.isInstalled()}catch{return!1}return this.isOnPath(o)||null!==this.nativeLauncher(o)}isOnPath(t){const n=SUPPORTED_TOOLS[t];if(!n)return!1;try{const t="win32"===process.platform?`where ${n.command}`:`which ${n.command}`;return o(t,{stdio:"pipe"}),!0}catch{return!1}}nativeLauncher(o){const t=s(o),n=t?.installSpec?.native?.binDir;if(!t||!n)return null;const e="win32"===process.platform?`${t.command}.exe`:t.command,r=h(w(),...n,e);return m(r)?r:null}ensureNativeOnPath(o){if("win32"!==process.platform||this.isOnPath(o))return null;const t=this.nativeLauncher(o);if(!t)return null;const n=g(t);try{if(!j(n))return null}catch(t){return i.logError(`ensureNativeOnPath: ${o}`,t),null}return U(),process.env.Path=`${process.env.Path??""};${n}`,n}async installTool(o){return M(`install:${o}`,()=>this.installToolNow(o))}async installToolNow(t){const i=SUPPORTED_TOOLS[t];if(!i)throw new Error(`Unknown tool: ${t}`);const l=s(t)?.installSpec;if(l&&(l.mirrorScript||l.npmPackage)){const o=E(l);if(await _(l)&&(v(),this.isToolInstalled(t)))return void console.log(r.green("√ "+n.t("wizard.tool_installed")));throw console.log(r.red("× "+n.t("wizard.install_failed"))),console.log(r.yellow(" ! "+n.t("install.manual_command",{tool:i.displayName,command:o}))),l.mirrorScript&&l.npmPackage&&console.log(r.yellow(" ! "+n.t("install.manual_npm",{command:O(l)}))),new Error(`Failed to install ${i.displayName}`)}const a=i.installCommand;console.log(r.gray("$ ")+r.white(a));try{return o(a,{stdio:"inherit"}),v(),void console.log(r.green("√ "+n.t("wizard.tool_installed")))}catch(o){if(console.log(r.red("× "+n.t("wizard.install_failed"))),!/EACCES|EPERM|permission denied/i.test(`${o?.message??""}${o?.stderr??""}`)&&243!==o?.status&&!a.startsWith("npm "))throw new Error(`Failed to install ${i.displayName}: ${o}`);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(v(),!this.isToolInstalled(t))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(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);try{return t.getConfig()}catch(t){return i.warn(`Failed to read config for ${o}:`,t),i.logError(`ToolManager.getToolConfig(${o})`,t),null}}updateToolConfig(o,t){const n=s(o);if(!n)throw new Error(`Unknown tool: ${o}`);if(!n.updateConfig)throw new Error(`Tool ${o} does not support raw config updates`);n.updateConfig(t)}forceResetConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);const n=t.forceResetPaths?t.forceResetPaths():this.backupPathsFor(t),e=[];for(const o of n)m(o)&&(d(o),f(o,{force:!0}),e.push(o));return e}loadPrivateConfig(o,t,n,e,r={}){const i=s(o);if(!i)throw new Error(`Unknown tool: ${o}`);r.force&&this.forceResetConfig(o),i.loadPrivateConfig({apiKey:t,baseUrl:l.getBaseUrl(),models:n,settings:l.getToolSettings(o),...e?{catalog:e}:{}})}async applyPrivateConfig(o,t,n,e={}){const r=this.installedVersion(o);return M(`apply:${o}`,()=>this.applyPrivateConfigNow(o,t,n,e),{...r?{tool_version:r}:{},...e.force?{force:!0}:{}})}async applyPrivateConfigNow(o,t,n,e){const r=s(o);if(!r)throw new Error(`Unknown tool: ${o}`);const i=r.wantsModelCatalog?await P(t):null;e.force?this.loadPrivateConfig(o,t,n,i??void 0,{force:!0}):i?this.loadPrivateConfig(o,t,n,i):this.loadPrivateConfig(o,t,n)}applyNotes(o){const t=s(o);if(!t)return[];const e=[];try{t.applyNotes&&e.push(...t.applyNotes())}catch(t){i.logError(`ToolManager.applyNotes(${o})`,t)}const r=this.outdatedVersion(o);if(r){e.push({kind:"action",text:n.t("tools.version_outdated",{current:r.current,min:r.min,upgrade:t.installSpec?`${S} upgrade ${o}`:t.upgradeCommand||t.installCommand})});for(const o of t.upgradeHints?.(r.min)??[])e.push({kind:"action",text:o})}const l=t.installSpec?C(t.installSpec):[];return l.length>1&&e.push({kind:"action",text:n.t("upgrade.duplicates_note",{count:String(l.length),active:k(l[0]),others:l.slice(1).map(k).join("、"),tool:o})}),e}printApplied(o,t=16){const n=SUPPORTED_TOOLS[o]?.displayName??o,e=this.applyNotes(o);for(const o of e.filter(o=>"detail"===o.kind))i.record(`${n}: ${o.text}`);const l=e.filter(o=>"summary"===o.kind).map(o=>o.text).join(";"),s=" ".repeat(Math.max(1,t-y(n)));console.log(r.green("√ "+n)+(l?s+l:""));for(const o of e.filter(o=>"action"===o.kind))console.log(r.yellow(" ! "+o.text))}installedVersion(o){const n=s(o);if(!n)return null;if(n.installSpec)return C(n.installSpec)[0]?.version??null;if(n.installedVersion)try{return n.installedVersion()}catch(t){return i.logError(`ToolManager.installedVersion(${o})`,t),null}if(n.isInstalled)return null;try{const o={encoding:"utf-8",timeout:1e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]},e=`${("win32"===process.platform?t(`${n.command} --version`,{...o,shell:!0}):t(n.command,["--version"],o)).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return e?e[0]:null}catch{return null}}outdatedVersion(o){const t=T(o);if(!t)return null;const n=this.installedVersion(o);return n&&$(n,t)<0?{current:n,min:t}:null}unloadPrivateConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);try{t.unloadPrivateConfig({savedKeys:x()}),N(`remove:${o}`,"ok")}catch(t){throw N(`remove:${o}`,"fail",{error:t}),t}let e=[];try{e=t.unloadNotes?.()??[]}catch(t){i.logError(`ToolManager.unloadNotes(${o})`,t)}return e.length>0?e:[{kind:"action",text:n.t("config.reopen_hint",{tool:t.displayName})}]}async clearPinnedModels(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);if(l.setToolModel(o,null),!t.clearPinnedModels)return[];const n=l.getApiKeyForTool(o),e=t.wantsModelCatalog&&n?await P(n):null;return t.clearPinnedModels(e??void 0)}supportsClearPinnedModels(o){return Boolean(s(o)?.clearPinnedModels)}holdsOurConfig(o){const t=s(o);if(!t)return!1;const n=x();return t.holdsOurConfig?t.holdsOurConfig(n):Boolean(t.detectCurrentConfig().apiKey)}detectCurrentConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);return t.detectCurrentConfig()}backupPathsFor(o){return o.backupPaths?o.backupPaths():[o.configPath]}listToolBackups(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(t).map(o=>({file:o,backups:p(o)}))}restorePrivateConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(t).map(o=>({file:o,result:u(o)}))}getInstalledTools(){return Object.keys(SUPPORTED_TOOLS).filter(o=>this.isToolInstalled(o))}getSupportedTools(){return a().filter(o=>!o.hidden).map(o=>b(o.name))}isGitInstalled(){try{const t="win32"===process.platform?"where git":"which git";return o(t,{stdio:"pipe"}),!0}catch{return!1}}}export const toolManager=ToolManager.getInstance();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join as e}from"path";import{applyGatewayModels as t,claudeCodeManager as o}from"../claude-code-manager.js";import{backupBeforeWrite as n}from"./backup.js";import{i18n as
|
|
1
|
+
import{join as e}from"path";import{applyGatewayModels as t,claudeCodeManager as o}from"../claude-code-manager.js";import{backupBeforeWrite as n}from"./backup.js";import{i18n as s}from"../i18n.js";import{baseModelId as a}from"../model-catalog.js";import{gatewayModelSpecs as i,prettyModelName as r,vendorNames as l}from"../gateway-models.js";import{toolHome as d}from"./types.js";import{gatewayAddresses as c,normalizeBaseUrl as u}from"../gateway-addresses.js";import{configManager as p}from"../config.js";import{spawnSync as m}from"child_process";import{existsSync as g,readFileSync as f}from"fs";import{detectManagedOverrides as _}from"./claude-managed.js";import{installOfficialPlugins as C}from"./claude-plugins.js";import{findInstalls as h,mirrorInstallCommand as A,brandInstallScripts as y}from"./tool-installs.js";import{updateNativeFromMirror as P}from"./claude-native-mirror.js";import{brandEnv as S}from"../brand.js";const j=e(d(),".claude","settings.json"),k=e(d(),".claude.json");let T,v=null,O=()=>0===m("security",["find-generic-password","-s","Claude Code-credentials"],{stdio:"ignore"}).status;export function setClaudeKeychainProbeForTests(e){O=e}export function claudeAccountLoginPresent(){const t=process.env.CLAUDE_CONFIG_DIR?.trim()||e(d(),".claude");if(g(e(t,".credentials.json")))return!0;if("darwin"!==process.platform||S("TEST_HOME"))return!1;try{return O()}catch{return!1}}function N(){try{const t=JSON.parse(f(e(d(),".claude","settings.json"),"utf-8"));return"string"==typeof t.autoUpdatesChannel?t.autoUpdatesChannel:"latest"}catch{return"latest"}}function x(e){if(!e)return;const t=new Set(e.models);return i("claude-code",e.clientModels).filter(e=>t.has(e.id))}const H={command:"claude",npmPackage:"@anthropic-ai/claude-code",native:{binDir:[".local","bin"],updateArgs:["update"],dataDirs:[[".local","share","claude"]],mirrorUpdate:()=>P(N())},mirrorScript:y("claude-code"),brew:"claude-code"};export const claudeCodeAdapter={name:"claude-code",displayName:"Claude Code",command:"claude",installCommand:A(H),upgradeCommand:"claude update",installSpec:H,upgradeHints:e=>"stable"===N()?[s.t("tools.claude_code.stable_channel",{min:e})]:[],configPath:j,wantsModelCatalog:!0,loadPrivateConfig(t){n(j),n(k),T=x(t.catalog),o.loadPrivateConfig(t.apiKey,t.models,t.catalog?.models,T);const s=e(d(),".local","bin","win32"===process.platform?"claude.exe":"claude"),a=h(claudeCodeAdapter.installSpec)[0]?.path??(g(s)?s:null);v=a?C(a):null},holdsOurConfig(e){const t=o.getSettings().env??{},n="string"==typeof t.ANTHROPIC_AUTH_TOKEN?t.ANTHROPIC_AUTH_TOKEN.trim():"",s="string"==typeof t.ANTHROPIC_BASE_URL?u(t.ANTHROPIC_BASE_URL):null;return!(!n||!e.includes(n))||null!==s&&(c().some(e=>e.url===s)||s===u(p.getBaseUrl()))},unloadPrivateConfig(e){const t=o.getSettings().env??{};Boolean(t.ANTHROPIC_AUTH_TOKEN||t.ANTHROPIC_BASE_URL)&&!claudeCodeAdapter.holdsOurConfig(e?.savedKeys??[])||(n(j),o.unloadPrivateConfig())},detectCurrentConfig:()=>o.detectCurrentConfig(),getConfig:()=>({settings:o.getSettings(),mcp:o.getMCPConfig()}),updateConfig(e){const t=e||{};t.settings&&o.saveSettings(t.settings),t.mcp&&o.saveMCPConfig(t.mcp)},clearPinnedModels:e=>(n(j),o.clearPinnedModels(e?.models)),listedModels(){const e=o.getSettings().modelPicker;return Array.isArray(e?.options)?e.options.map(e=>a(String(e.model))):null},refreshModelMenu(e){const s=o.getSettings(),a=t(s,x(e.catalog));JSON.stringify(a)!==JSON.stringify(s)&&(n(j),o.saveSettings(a))},applyNotes(){const e=[];v?.installed.length&&(e.push({kind:"summary",text:s.t("tools.claude_code.plugins_installed",{count:String(v.installed.length)})}),e.push({kind:"detail",text:v.installed.join(", ")})),"git"===v?.skipped?e.push({kind:"action",text:s.t("tools.claude_code.plugins_need_git")}):("marketplace"===v?.skipped||v?.failed.length)&&e.push({kind:"action",text:s.t("tools.claude_code.plugins_failed")}),T&&T.length>0&&(e.push({kind:"summary",text:s.t("tools.claude_code.gateway_models",{count:String(T.length),vendors:l(T.map(e=>e.id)).join(" / ")})}),e.push({kind:"detail",text:T.map(e=>e.name||r(e.id)).join(", ")})),"win32"!==process.platform||process.env.CLAUDE_CODE_GIT_BASH_PATH||0===m("where",["git"],{windowsHide:!0,stdio:"ignore"}).status||e.push({kind:"action",text:s.t("tools.claude_code.no_git_bash")}),claudeAccountLoginPresent()&&e.push({kind:"detail",text:s.t("tools.claude_code.account_login_overridden")});for(const t of _())e.push({kind:"action",text:s.t("tools.claude_code.managed_override",{source:t.source,keys:t.keys.join(", ")})});for(const t of o.getLastTierFallbacks())e.push({kind:"detail",text:s.t("tools.claude_code.tier_fallback",{tier:t.tier,from:t.from,to:t.to})});return e},backupPaths:()=>[j,k],forceResetPaths:()=>[j]};
|
package/dist/lib/tools/codex.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash as e}from"crypto";import{existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as i,statSync as s,writeFileSync as l}from"fs";import{join as
|
|
1
|
+
import{createHash as e}from"crypto";import{existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as i,statSync as s,writeFileSync as l}from"fs";import{join as c}from"path";import*as a from"@iarna/toml";import{logger as d}from"../../utils/logger.js";import{i18n as u}from"../i18n.js";import{backupBeforeWrite as m,atomicWriteFile as p}from"./backup.js";import{codexHome as f,pickModel as g,toolHome as _,withV1 as x}from"./types.js";import{moveSessionsToProvider as h,NO_STATE_DB as y,runningCodexPids as k}from"../codex-sessions.js";import{getToolDefaultModel as b}from"../model-registry.js";import{configManager as v}from"../config.js";import{maskHome as w,track as j}from"../telemetry.js";import{buildCodexCatalog as C,catalogRejections as O,codexCatalogPath as S,fillFromOlderEntries as M,installedCodexBinaries as A,loadBundledCodexModels as E,loadPreviousCodexModels as N,previousGatewayModelIds as P}from"./codex-catalog.js";import{gatewayModelSpecs as T,modelFamily as D}from"../gateway-models.js";import{findInstalls as I,mirrorInstallCommand as L,brandInstallScripts as $}from"./tool-installs.js";const J=()=>f(),G=()=>c(J(),"config.toml"),R="sessions_move_declined",K=["browser_use","browser_use_external","computer_use"];function X(e){const t=e.features;if(!F(t)||!K.every(e=>!1===t[e]))return!1;for(const e of K)delete t[e];return!0}export function codexWorkModeOn(){try{const e=Q();return e.model_provider===U&&F(e.desktop)&&"STEPS_PROSE"===e.desktop.conversationDetailMode}catch{return!1}}function B(){try{if(F(Q().desktop))return!0}catch{}if("darwin"===process.platform)return["/Applications",c(_(),"Applications")].some(e=>["ChatGPT.app","Codex.app"].some(o=>t(c(e,o))));if("win32"===process.platform){const e=c(process.env.LOCALAPPDATA||c(_(),"AppData","Local"),"Packages");try{return n(e).some(e=>/^OpenAI\.(Codex|ChatGPT)/i.test(e))}catch{return!1}}return t("/usr/lib/chatgpt/ChatGPT")}export function codexConfigPath(){return G()}const W=()=>c(J(),"auth.json"),q="OPENAI_API_KEY",U="custom",z=1e6,Y=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function F(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function H(e,t){return F(e[t])||(e[t]={}),e[t]}function Q(){if(!t(G()))return{};const e=r(G(),"utf-8");if(!e.trim())return{};try{const t=a.parse(e);if(!F(t))throw new Error("config.toml root must be a TOML table");return t}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 V(){if(!t(W()))return{};try{const e=JSON.parse(r(W(),"utf-8"));return F(e)?e:{}}catch{return{}}}let Z=null;function ee(e){const t=e.profiles;if(F(t)){for(const[e,o]of Object.entries(t))F(o)&&2===Object.keys(o).length&&o.model_provider===U&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let te=null;const oe=()=>c(v.getConfigDir(),"codex-catalog-check.json");function ne(e){const o=S();t(o)&&r(o,"utf-8")===e||(m(o),p(o,e))}function re(t,n){if(0===n.length)return[];const i=function(t,o){const n=e("sha256").update(t);for(const e of o)try{const t=s(e);n.update(`\0${e}\0${t.size}\0${t.mtimeMs}`)}catch{n.update(`\0${e}`)}return n.digest("hex")}(t,n);if(function(e){try{return JSON.parse(r(oe(),"utf-8")).signature===e}catch{return!1}}(i))return[];const c=O(S(),n);return 0===c.length&&function(e){try{o(v.getConfigDir(),{recursive:!0}),l(oe(),JSON.stringify({signature:e})+"\n")}catch(e){d.logError("codexAdapter.rememberAccepted",e)}}(i),c}function ie(e,t,o){const n=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===z&&delete e.model_context_window,e.model_auto_compact_token_limit===Y&&delete e.model_auto_compact_token_limit}(e);const r=()=>{e.model_catalog_json===S()&&delete e.model_catalog_json,n&&(e.model_context_window=z,e.model_auto_compact_token_limit=Y)},s=E()??N();if(!s)return d.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),te="skipped",void r();const l=t.catalog,c=e=>C({bundled:e,specs:T("codex",l?.clientModels),...l?{keyModels:l.models}:{},gatewayAvailable:l?.models??P(),oneMillion:n,selectedModel:o,..."gateway"===l?.oneMillionSource?{claudeOneMillion:l.oneMillion}:{}}),a=e=>JSON.stringify(e,null,2)+"\n";let u=c(s);ne(a(u));const m=A(),p=re(a(u),m);if(p.length>0){const e=Date.now();let t=!1;for(const e of p){const o=E(e.bin);if(o){for(const e of[{models:M(u.models,o)},{models:M(c(o).models,o)}])if(ne(a(e)),0===re(a(e),m).length){u=e,t=!0;break}if(t)break}}if(j("codex-catalog",t?"fallback":"fail",{duration_ms:Date.now()-e,error:p[0].error,detail:{rejected_by:p.map(e=>({version:e.version,path:w(e.bin)}))}}),!t)return te={rejectedBy:p[0]},i(S(),{force:!0}),void r()}te={listed:u.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))},e.model_catalog_json=S()}export function codexCatalogRejection(){let e;try{e=Q()}catch{return null}return e.model_catalog_json===S()&&t(S())?O(S())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=Q(),n=a.stringify(o),r="string"==typeof o.model?o.model:b("codex");ie(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=a.stringify(o);i!==n&&(m(G()),p(G(),i))}const se={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:$("codex"),brew:"codex"};export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:L(se),installSpec:se,configPath:G(),wantsModelCatalog:!0,listedModels(){if(Q().model_catalog_json!==S())return null;try{return(JSON.parse(r(S(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){if(Q().model_catalog_json!==S())return;setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog);const t=Q();X(t)&&(m(G()),p(G(),a.stringify(t)))},async followUp(){if(Q().model_provider!==U)return null;const e=await h(U,{dryRun:!0}),t=Math.max(e.moved.length,e.dbRows);if(0===t)return null;const o=v.getToolSettings("codex")[R];if("number"==typeof o&&t<=o)return null;const n={count:String(t)};return k().length>0?{hint:u.t("tools.codex.sessions_hidden_running",n)}:{prompt:u.t("tools.codex.sessions_offer",n),hint:u.t("tools.codex.sessions_hidden",n),async run(){const e=await h(U),t=[...new Set(e.moved.map(e=>e.from))].join("、")||"-",o=String(Math.max(e.moved.length,e.dbRows)),n=[{kind:"summary",text:u.t("codex_sessions.moved",{count:o,from:t,target:U})},{kind:"summary",text:u.t("codex_sessions.backup",{dir:e.backupDir??""})}];return e.dbSkipped&&e.dbSkipped!==y&&n.push({kind:"action",text:u.t("codex_sessions.db_skipped",{reason:e.dbSkipped})}),n},decline(){v.setToolSetting("codex",R,t)}}},applyNotes(){if("skipped"===te)return 0===I(se).length?[]:[{kind:"action",text:u.t("tools.codex.catalog_skipped")}];if(!te)return[];if("rejectedBy"in te){const{bin:e,version:t}=te.rejectedBy;return[{kind:"action",text:u.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of te.listed)e.set(D(t.id),(e.get(D(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${u.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:u.t("tools.codex.catalog_written",{count:String(te.listed.length),breakdown:t})},{kind:"detail",text:te.listed.map(e=>e.name).join(", ")},...codexWorkModeOn()||B()?[{kind:"action",text:u.t(codexWorkModeOn()?"tools.codex.work_mode_on":"tools.codex.work_mode_hint")}]:[]]},loadPrivateConfig(e){const t=b("codex"),o=g(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,r=x(e.baseUrl),i=Q();i.model=n,i.model_provider=U,i.model_reasoning_effort="high",ie(i,e,n);const s=H(i,"model_providers"),l=F(s[U])?{...s[U]}:{};delete l.env_key;const{experimental_bearer_token:c,...d}=l;s[U]={...d,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:r},ee(i),H(H(i,"tui"),"model_availability_nux")[n]=4;const u=H(i,"features");u.goals=!0,u.js_repl=!1,X(i),m(G()),p(G(),a.stringify(i)),function(e){const t=e.trim();if(!t)return;const o={...V(),auth_mode:"apikey",[q]:t};m(W()),p(W(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},holdsOurConfig(e){const t=V()[q];return"string"==typeof t&&e.includes(t.trim())},unloadPrivateConfig(e){if(Z=function(e){const t=V(),o="string"==typeof t[q]?t[q].trim():"";if(!o)return F(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[q]:n,auth_mode:r,...s}=t;return m(W()),F(s.tokens)?(p(W(),JSON.stringify({...s,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(i(W(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(G()))return;let o;try{o=Q()}catch(e){return void d.logError("codexAdapter.unloadPrivateConfig",e)}const n=o.model_providers;F(n)&&(delete n[U],0===Object.keys(n).length&&delete o.model_providers),o.model_provider===U&&delete o.model_provider,o.model_catalog_json===S()&&delete o.model_catalog_json,X(o),ee(o),m(G()),p(G(),a.stringify(o))},unloadNotes(){switch(Z){case"chatgpt":return[{kind:"action",text:u.t("tools.codex.unload_chatgpt_restored")}];case"other_key":return[{kind:"action",text:u.t("tools.codex.unload_other_key")}];default:return[{kind:"action",text:u.t("tools.codex.unload_sign_in")}]}},detectCurrentConfig(){const e=V()[q];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return Q()}catch(e){return d.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[G(),W(),S()]};export function codexAuthProblem(){try{const e=Q(),t=e.model_providers?.[U];if(e.model_provider!==U||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=V();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
|
|
@@ -141,6 +141,12 @@ export interface ToolAdapter {
|
|
|
141
141
|
loadPrivateConfig(ctx: ToolApplyContext): void;
|
|
142
142
|
/** Remove this CLI's provider config from the tool, leaving other config intact. */
|
|
143
143
|
unloadPrivateConfig(ctx?: ToolUnloadContext): void;
|
|
144
|
+
/**
|
|
145
|
+
* The tool's current provider settings are ours, so removing them is right. Default: it
|
|
146
|
+
* has a key at all (most adapters only read it from an entry they named). Tools whose
|
|
147
|
+
* provider slot other software also writes (Codex auth.json, Claude Code env) check it.
|
|
148
|
+
*/
|
|
149
|
+
holdsOurConfig?(savedKeys: string[]): boolean;
|
|
144
150
|
/** Localized next steps after the last `unloadPrivateConfig` (e.g. how to sign in with the vendor's own account). */
|
|
145
151
|
unloadNotes?(): ApplyNote[];
|
|
146
152
|
/** Read back the api key currently configured for this tool, if any. */
|
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)),P=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(P.bold("\n"+u("╔","╗","═",this.BOX_WIDTH))),console.log(P.bold(_(e,"║","║",this.BOX_WIDTH,"center"))),console.log(P.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(P.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(P.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=d||"claude-desktop"===i||"agy"===i,u=s(i),_=m||!u?p.t("wizard.model_builtin_default"):u;this.resetScreen(),this.createBox(n.displayName+" · "+p.t("wizard.config_models"));const g=[{name:"✅ "+p.t("wizard.use_default_model",{model:_}),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:h}=await this.promptWithHints([{type:"list",name:"choice",message:p.t("wizard.select_tool_model",{tool:n.displayName}),choices:g}]);if("back"===h.type)return!1;if("default"===h.type)o.setToolModel(i,null);else if("preset"===h.type)o.setToolModel(i,r(h.preset));else if("custom"===h.type){const{model:t}=await e.prompt([{type:"input",name:"model",message:p.t("wizard.input_custom_model"),default:!m&&u?u:void 0}]),a=(t||"").trim();o.setToolModel(i,a?this.singleModelOverride(a):null)}else if("fetch"===h.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:!m&&u?u: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,name:i})));const a=c[i];a&&!a.gui&&(l.isOnPath(i)&&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=Boolean(l.detectCurrentConfig(o).apiKey),i=l.unloadPrivateConfig(o);if(!a)return void n.info(p.t("config.remove_nothing",{tool:c[o]?.displayName||o}));n.succeed(p.t("wizard.config_unloaded")),i.forEach(e=>console.log(t.yellow(" ! "+e.text)));const{nextAction:r}=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"===r&&(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(P("── "+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)),P=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(P.bold("\n"+u("╔","╗","═",this.BOX_WIDTH))),console.log(P.bold(_(e,"║","║",this.BOX_WIDTH,"center"))),console.log(P.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(P.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(P.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=d||"claude-desktop"===i||"agy"===i,u=s(i),_=m||!u?p.t("wizard.model_builtin_default"):u;this.resetScreen(),this.createBox(n.displayName+" · "+p.t("wizard.config_models"));const g=[{name:"✅ "+p.t("wizard.use_default_model",{model:_}),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:h}=await this.promptWithHints([{type:"list",name:"choice",message:p.t("wizard.select_tool_model",{tool:n.displayName}),choices:g}]);if("back"===h.type)return!1;if("default"===h.type)o.setToolModel(i,null);else if("preset"===h.type)o.setToolModel(i,r(h.preset));else if("custom"===h.type){const{model:t}=await e.prompt([{type:"input",name:"model",message:p.t("wizard.input_custom_model"),default:!m&&u?u:void 0}]),a=(t||"").trim();o.setToolModel(i,a?this.singleModelOverride(a):null)}else if("fetch"===h.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:!m&&u?u: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,name:i})));const a=c[i];a&&!a.gui&&(l.isOnPath(i)&&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.holdsOurConfig(o),i=l.unloadPrivateConfig(o);if(!a)return void n.info(p.t("config.remove_nothing",{tool:c[o]?.displayName||o}));n.succeed(p.t("wizard.config_unloaded")),i.forEach(e=>console.log(t.yellow(" ! "+e.text)));const{nextAction:r}=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"===r&&(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(P("── "+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
|
@@ -242,7 +242,7 @@
|
|
|
242
242
|
"confirm_force": "Reset {{tool}}? Its config files are snapshotted, deleted, and rewritten from the recommended configuration (fields you added by hand are lost; undo with restore)",
|
|
243
243
|
"force_done": "Reset {{tool}}'s config files (originals snapshotted; undo with `{{cli}} config {{name}} restore`)",
|
|
244
244
|
"confirm_remove": "Remove the {{brand}} configuration from {{tool}}? (The current state is backed up first; {{cli}} config {{name}} restore brings it back)",
|
|
245
|
-
"remove_dry_run": "Would remove
|
|
245
|
+
"remove_dry_run": "Would remove {{brand}}'s provider address, key and model settings from {{tool}} (settings written by others stay), keeping everything else",
|
|
246
246
|
"remove_done": "Removed the {{brand}} configuration from {{tool}}",
|
|
247
247
|
"reopen_hint": "Quit {{tool}} completely and reopen it if it is already running",
|
|
248
248
|
"remove_nothing": "{{tool}} has no {{brand}} configuration; nothing to remove"
|
|
@@ -268,7 +268,7 @@
|
|
|
268
268
|
"min": "min",
|
|
269
269
|
"max": "max",
|
|
270
270
|
"errors": "errors",
|
|
271
|
-
"missing_api_key": "No API key saved yet
|
|
271
|
+
"missing_api_key": "No API key saved yet"
|
|
272
272
|
},
|
|
273
273
|
"update": {
|
|
274
274
|
"checking": "Checking for updates...",
|
|
@@ -915,7 +915,7 @@
|
|
|
915
915
|
"help_topics": {
|
|
916
916
|
"exit_codes": {
|
|
917
917
|
"title": "Exit codes and error output",
|
|
918
|
-
"body": "Exit codes:\n 0 success\n 1 operation failed\n 2 usage or input error\n 3 authentication failed (invalid or rejected key)\n 4 network problem (DNS, certificate, timeout, or unreachable gateway)\n 5 internal error\n 130 cancelled by the user\n\nWith --json, successful output keeps its existing format.
|
|
918
|
+
"body": "Exit codes:\n 0 success\n 1 operation failed\n 2 usage or input error\n 3 authentication failed (invalid or rejected key)\n 4 network problem (DNS, certificate, timeout, or unreachable gateway)\n 5 internal error\n 130 cancelled by the user\n\nWith --json, successful output keeps its existing format. Failures write one JSON object to stderr:\n{\"ok\":false,\"error\":{\"type\":\"usage\",\"message\":\"…\",\"hint\":\"…\",\"subtype\":\"…\"}}"
|
|
919
919
|
},
|
|
920
920
|
"environment": {
|
|
921
921
|
"title": "Environment variables",
|
package/dist/locales/zh_CN.json
CHANGED
|
@@ -242,7 +242,7 @@
|
|
|
242
242
|
"confirm_force": "确认重置 {{tool}} 的配置吗?会先快照、再删掉它的配置文件,用推荐配置整份重写(您自行添加的字段会丢失,可用 restore 撤销)",
|
|
243
243
|
"force_done": "已重置 {{tool}} 的配置文件(原文件已快照,`{{cli}} config {{name}} restore` 可撤销)",
|
|
244
244
|
"confirm_remove": "确定从 {{tool}} 移除 {{brand}} 的配置吗?(当前状态会先自动备份,可用 {{cli}} config {{name}} restore 还原)",
|
|
245
|
-
"remove_dry_run": "将从 {{tool}}
|
|
245
|
+
"remove_dry_run": "将从 {{tool}} 移除 {{brand}} 的服务商地址、Key 和模型设置(别家写入的不动),其它设置保留",
|
|
246
246
|
"remove_done": "已从 {{tool}} 移除 {{brand}} 的配置",
|
|
247
247
|
"reopen_hint": "已经打开的 {{tool}} 要完全退出后重新打开才会生效",
|
|
248
248
|
"remove_nothing": "{{tool}} 里没有 {{brand}} 的配置,无需移除"
|
|
@@ -268,7 +268,7 @@
|
|
|
268
268
|
"min": "最小值",
|
|
269
269
|
"max": "最大值",
|
|
270
270
|
"errors": "错误",
|
|
271
|
-
"missing_api_key": "还没有保存 API Key
|
|
271
|
+
"missing_api_key": "还没有保存 API Key"
|
|
272
272
|
},
|
|
273
273
|
"update": {
|
|
274
274
|
"checking": "正在检查更新...",
|
|
@@ -915,7 +915,7 @@
|
|
|
915
915
|
"help_topics": {
|
|
916
916
|
"exit_codes": {
|
|
917
917
|
"title": "退出码与错误输出",
|
|
918
|
-
"body": "退出码:\n 0 成功\n 1 操作失败\n 2 用法或输入错误\n 3 认证失败(Key 无效或被拒绝)\n 4 网络问题(DNS、证书、超时或网关不可达)\n 5 内部错误\n 130 用户取消\n\n使用 --json
|
|
918
|
+
"body": "退出码:\n 0 成功\n 1 操作失败\n 2 用法或输入错误\n 3 认证失败(Key 无效或被拒绝)\n 4 网络问题(DNS、证书、超时或网关不可达)\n 5 内部错误\n 130 用户取消\n\n使用 --json 时,成功输出保持原格式;失败只在 stderr 输出一个 JSON 对象:\n{\"ok\":false,\"error\":{\"type\":\"usage\",\"message\":\"…\",\"hint\":\"…\",\"subtype\":\"…\"}}"
|
|
919
919
|
},
|
|
920
920
|
"environment": {
|
|
921
921
|
"title": "环境变量",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeapi/api-helper",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.128",
|
|
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",
|