@vibeapi/api-helper 0.0.146 → 0.0.148
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/brand.json +2 -1
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/setup.d.ts +7 -0
- package/dist/commands/setup.js +1 -1
- package/dist/commands/update.js +1 -1
- package/dist/commands/upgrade.d.ts +8 -2
- package/dist/commands/upgrade.js +1 -1
- package/dist/lib/app-update.d.ts +74 -0
- package/dist/lib/app-update.js +1 -0
- package/dist/lib/brand.d.ts +2 -0
- package/dist/lib/codex-sessions.js +1 -1
- package/dist/lib/i18n.js +1 -1
- package/dist/lib/post-apply.d.ts +5 -1
- package/dist/lib/post-apply.js +1 -1
- package/dist/lib/powershell-env.d.ts +12 -0
- package/dist/lib/powershell-env.js +1 -0
- package/dist/lib/program.js +1 -1
- package/dist/lib/tool-manager.js +1 -1
- package/dist/lib/tool-upgrade.js +1 -1
- package/dist/lib/tools/chatgpt-desktop.d.ts +32 -0
- package/dist/lib/tools/chatgpt-desktop.js +1 -0
- package/dist/lib/tools/claude-desktop-app.d.ts +31 -0
- package/dist/lib/tools/claude-desktop-app.js +1 -0
- package/dist/lib/tools/claude-desktop-cli.js +1 -1
- package/dist/lib/tools/claude-desktop.js +1 -1
- package/dist/lib/tools/codex.js +1 -1
- package/dist/lib/tools/desktop-app-installer.d.ts +102 -0
- package/dist/lib/tools/desktop-app-installer.js +1 -0
- package/dist/lib/tools/desktop-process.d.ts +4 -0
- package/dist/lib/tools/desktop-process.js +1 -1
- package/dist/lib/tools/elevated-reg.js +1 -1
- package/dist/lib/tools/types.d.ts +50 -0
- package/dist/lib/windows-env.js +1 -1
- package/dist/lib/wizard.js +1 -1
- package/dist/locales/en_US.json +69 -7
- package/dist/locales/zh_CN.json +69 -7
- package/package.json +1 -1
package/dist/brand.json
CHANGED
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"installMirror": {
|
|
43
43
|
"scripts": "https://cnb.cool/vibeapi/install/-/git/raw/main",
|
|
44
44
|
"agy": "https://cnb.cool/lib/agy/-/releases/latest/download",
|
|
45
|
-
"claudeDesktop": "https://cnb.cool/lib/claude-desktop/-/releases/latest"
|
|
45
|
+
"claudeDesktop": "https://cnb.cool/lib/claude-desktop/-/releases/latest",
|
|
46
|
+
"chatgptDesktop": "https://cnb.cool/lib/chatgpt-desktop/-/releases/latest"
|
|
46
47
|
},
|
|
47
48
|
"pluginMarketplaces": [
|
|
48
49
|
{
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{refreshClientConfig as o}from"../lib/client-config-sync.js";import t from"chalk";import e from"ora";import{spawnSync as s}from"child_process";import{existsSync as r,readdirSync as n,readFileSync as a}from"fs";import{connect as i}from"net";import{join as c}from"path";import{configManager as l}from"../lib/config.js";import{savedApiKey as d}from"./base.js";import{toolManager as p}from"../lib/tool-manager.js";import{i18n as u}from"../lib/i18n.js";import{validateApiKey as m}from"../lib/api-validator.js";import{getAdapter as f}from"../lib/tools/registry.js";import{findInstalls as _,installLabel as g}from"../lib/tools/tool-installs.js";import{detectManagedOverrides as h}from"../lib/tools/claude-managed.js";import{codexAuthProblem as y,codexCatalogRejection as k,codexConfigPath as w,codexWorkModeOn as b}from"../lib/tools/codex.js";import{claudeAccountLoginPresent as v}from"../lib/tools/claude-code.js";import{toolHome as j}from"../lib/tools/types.js";import{gatewayAddresses as x,probeGatewayAddress as $}from"../lib/gateway-addresses.js";import{listAdapters as T}from"../lib/tools/registry.js";import{logger as A}from"../utils/logger.js";import{maskHome as P,maskSecrets as R,uploadReport as N}from"../lib/telemetry.js";import{CLI_NAME as O}from"../lib/brand.js";import{balanceLookupEnabled as C,balanceNeedsAttention as I,balanceText as H,fetchKeyBalances as L}from"../lib/key-balance.js";const S=["HTTPS_PROXY","https_proxy","HTTP_PROXY","http_proxy","ALL_PROXY","all_proxy"];function U(o,t,e=3e3){return new Promise(s=>{const r=i({host:o,port:t}),n=o=>{r.destroy(),s(o)};r.setTimeout(e,()=>n(!1)),r.once("connect",()=>n(!0)),r.once("error",()=>n(!1))})}function E(){const o=A.getLogDir();if(!r(o))return"";const t=n(o).filter(o=>/^\d{4}-\d{2}-\d{2}\.log$/.test(o)).sort().slice(-2).map(t=>`== ${t}\n`+a(c(o,t),"utf-8")).join("\n");return R(t.slice(-15e4))}function K(){const o={};for(const t of S){const e=process.env[t]?.trim();if(e)try{const s=new URL(e.includes("://")?e:`http://${e}`);o[t]=`${s.protocol}//${s.host}`}catch{o[t]="(unparsable)"}}return o}export async function doctorCommand(r={}){const n=e(u.t("doctor.checking")).start(),i=[],A=Number(process.versions.node.split(".")[0]);i.push({name:"Node.js",status:A>=20?"pass":"fail",message:`v${process.versions.node}`}),n.text=u.t("doctor.check_proxy"),i.push(await async function(){const o=u.t("doctor.proxy"),t=new Map;for(const o of S){const e=process.env[o]?.trim();e&&!t.has(e)&&t.set(e,o)}if(0===t.size)return{name:o,status:"pass",message:u.t("doctor.proxy_none")};const e=[];for(const[o,s]of t){let t;try{t=new URL(o.includes("://")?o:`http://${o}`)}catch{e.push(`${s}=${o}`);continue}const r=Number(t.port)||("https:"===t.protocol?443:t.protocol.startsWith("socks")?1080:80);await U(t.hostname,r)||e.push(`${s}=${o}`)}return 0===e.length?{name:o,status:"pass",message:[...t.keys()].join(", ")}:{name:o,status:"fail",message:u.t("doctor.proxy_dead",{proxies:e.join(", ")})}}()),n.text=u.t("doctor.check_api_key_network");const R=d(),B=u.t("doctor.api_key_network");if(R){const o=await m(R);o.valid?(i.push({name:B,status:"pass"}),n.text=u.t("doctor.check_balance"),i.push(...await async function(o){if(!C())return[];const t=l.listToolApiKeys().map(o=>({tool:o,key:l.getApiKeyForTool(o)})).filter(t=>Boolean(t.key)&&t.key!==o),e=await L([o,...t.map(o=>o.key)]),s=[{name:u.t("doctor.balance"),key:o},...t.map(o=>({name:u.t("doctor.balance_tool",{tool:f(o.tool)?.displayName??o.tool}),key:o.key}))],r=[];for(const o of s){const t=e.get(o.key);t&&r.push({name:o.name,status:I(t)?"warn":"pass",message:H(t)})}return r}(R))):"invalid_api_key"===o.error?i.push({name:B,status:"fail",message:u.t("doctor.api_key_invalid")}):(i.push({name:B,status:"fail",message:`${u.t("doctor.network_error")}: ${o.message??o.error}`}),n.text=u.t("doctor.check_other_addresses"),i.push(await async function(){const o=u.t("doctor.other_addresses"),t=l.getBaseUrl(),e=x().filter(o=>o.url!==t),s=d(),r=await Promise.all(e.map(o=>$(o.url,{apiKey:s}))),n=e.filter((o,t)=>r[t].ok).map(o=>o.url);return 0===n.length?{name:o,status:"fail",message:u.t("doctor.other_addresses_none")}:{name:o,status:"warn",message:u.t("doctor.other_addresses_found",{urls:n.join(", ")})}}()))}else i.push({name:B,status:"fail",message:u.t("doctor.api_key_missing")});n.text=u.t("doctor.check_client_config");const G=await o();i.push({name:u.t("doctor.client_config"),status:"cloud"===G.source||"cache"===G.source&&!G.problem?"pass":"warn",message:[G.source?u.t(`refresh.source.${G.source}`):u.t("refresh.source.none"),G.revision?u.t("doctor.client_config_revision",{revision:G.revision}):"",G.problem??""].filter(Boolean).join(" · ")}),n.text=u.t("doctor.check_tools");const D=p.getInstalledTools();i.push({name:u.t("doctor.installed_tools"),status:D.length>0?"pass":"warn",message:D.length>0?D.map(o=>f(o)?.displayName??o).join(u.t("setup.list_separator")):u.t("doctor.no_tools_installed")}),i.push(...function(){const o=[];for(const t of p.getInstalledTools()){const e=f(t);if(!e?.installSpec)continue;const s=_(e.installSpec);if(0===s.length)continue;const r=[],n=p.outdatedVersion(t);n&&r.push(u.t("doctor.tool_outdated",{min:n.min})),s.length>1&&r.push(u.t("doctor.tool_duplicates",{others:s.slice(1).map(g).join("、")})),o.push({name:e.displayName,status:r.length>0?"warn":"pass",message:[g(s[0]),...r,...r.length>0?[u.t("doctor.run_upgrade",{tool:t})]:[]].join("\n ")})}return o}());const q=function(){if(!p.isToolInstalled("claude-code"))return null;const o=u.t("doctor.claude_config"),t=h();if(t.length>0){const e=t.map(o=>`${o.source}: ${o.keys.join(", ")}`).join("; ");return{name:o,status:"fail",message:u.t("doctor.claude_managed",{detail:e})}}let e={};try{e=JSON.parse(a(c(process.env.CLAUDE_CONFIG_DIR?.trim()||c(j(),".claude"),"settings.json"),"utf-8")).env??{}}catch{}const s=l.getApiKeyForTool("claude-code");return e.ANTHROPIC_AUTH_TOKEN&&e.ANTHROPIC_BASE_URL?e.ANTHROPIC_BASE_URL!==l.getBaseUrl()||s&&e.ANTHROPIC_AUTH_TOKEN!==s?{name:o,status:"warn",message:u.t("doctor.claude_config_changed")}:{name:o,status:"pass"}:{name:o,status:"warn",message:u.t("doctor.claude_not_configured")}}();q&&i.push(q),D.includes("claude-code")&&v()&&i.push({name:u.t("doctor.claude_login"),status:"pass",message:u.t("tools.claude_code.account_login_overridden")});const F=D.includes("codex")?y():null;if(D.includes("codex")&&i.push({name:u.t("doctor.codex_auth"),status:F?"fail":"pass",message:F?u.t(`doctor.codex_${F}`,{path:P(w())}):void 0}),D.includes("codex")){const o=k();i.push({name:u.t("doctor.codex_catalog"),status:o?"fail":"pass",message:o?u.t("doctor.codex_catalog_rejected",{path:o.bin,version:o.version??"?",error:o.error}):void 0})}D.includes("codex")&&b()&&i.push({name:u.t("doctor.codex_work_mode"),status:"warn",message:u.t("tools.codex.work_mode_on")}),"win32"===process.platform&&D.includes("claude-code")&&!process.env.CLAUDE_CODE_GIT_BASH_PATH&&i.push({name:"Git for Windows",status:p.isGitInstalled()?"pass":"warn",message:p.isGitInstalled()?void 0:u.t("tools.claude_code.no_git_bash")}),r.deep&&D.includes("claude-code")&&(n.text=u.t("doctor.check_claude_request"),i.push(function(){const o=u.t("doctor.claude_request"),t=_(f("claude-code").installSpec)[0];if(!t)return{name:o,status:"warn",message:u.t("doctor.claude_request_skipped")};const e={encoding:"utf-8",timeout:12e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]},r=["-p","Reply with the single word OK."],n=/\.cmd$/i.test(t.path)?s(`"${t.path}" ${r.map(o=>`"${o}"`).join(" ")}`,{...e,shell:!0}):s(t.path,r,e),a=`${n.stdout??""}`.trim();if(0===n.status&&a)return{name:o,status:"pass",message:a.slice(0,80)};const i=(`${n.stderr??""}`.trim()||a||n.error?.message||`exit ${n.status}`).slice(0,300);return{name:o,status:"fail",message:u.t("doctor.claude_request_failed",{reason:i})}}())),n.stop(),console.log("\n"+t.bold(u.t("doctor.results_title"))+"\n");const M={pass:t.green("√"),warn:t.yellow("!"),fail:t.red("×")};for(const o of i)console.log(`${M[o.status]} ${o.name}`),o.message&&console.log(t.gray(` ${o.message}`));if(i.every(o=>"pass"===o.status)&&console.log("\n"+t.green.bold(u.t("doctor.all_good"))),!r.deep&&D.includes("claude-code")&&console.log(t.gray("\n"+u.t("doctor.deep_hint"))),r.report){const o=e(u.t("doctor.report_uploading")).start(),t=await N(function(o,t){const e={};for(const o of T()){if(o.hidden)continue;let t=null;try{t=p.detectCurrentConfig(o.name).apiKey?"has_key":"no_key"}catch{t="unreadable"}e[o.name]={installed:p.isToolInstalled(o.name),version:p.installedVersion(o.name),copies:o.installSpec?_(o.installSpec).map(o=>({kind:o.kind,version:o.version,path:o.path})):void 0,config:t}}const s=l.getProfile();return{checks:o,tools:e,settings:{base_url:l.getBaseUrl(),profile:l.getActiveProfileName(),profiles:l.listProfiles().length,key_fingerprint:l.getApiKeyFingerprint()||null,tool_keys:Object.keys(s.tool_api_keys??{}),models:s.models,tool_models:s.tool_models??{},tool_settings:s.tool_settings??{},lang:l.getLang()},client_config:t,env:{shell:process.env.SHELL??process.env.ComSpec??null,term:process.env.TERM_PROGRAM??null,proxies:K()},log:E()}}(i,{source:G.source??void 0,revision:G.revision,problem:G.problem}));t?o.succeed(u.t("doctor.report_done",{code:t})):o.fail(u.t("doctor.report_failed",{cli:O}))}else i.some(o=>"fail"===o.status)&&console.log(t.gray("\n"+u.t("doctor.report_hint",{cli:O})));i.some(o=>"fail"===o.status)&&(process.exitCode=1)}
|
|
1
|
+
import{refreshClientConfig as o}from"../lib/client-config-sync.js";import t from"chalk";import e from"ora";import{spawnSync as s}from"child_process";import{existsSync as r,readdirSync as n,readFileSync as a}from"fs";import{connect as c}from"net";import{join as i}from"path";import{configManager as l}from"../lib/config.js";import{savedApiKey as d}from"./base.js";import{toolManager as p}from"../lib/tool-manager.js";import{i18n as u}from"../lib/i18n.js";import{validateApiKey as m}from"../lib/api-validator.js";import{getAdapter as f}from"../lib/tools/registry.js";import{findInstalls as _,installLabel as g}from"../lib/tools/tool-installs.js";import{detectManagedOverrides as h}from"../lib/tools/claude-managed.js";import{codexAuthProblem as y,codexCatalogRejection as k,codexConfigPath as w,codexWorkModeOn as b}from"../lib/tools/codex.js";import{claudeAccountLoginPresent as v}from"../lib/tools/claude-code.js";import{toolHome as j}from"../lib/tools/types.js";import{gatewayAddresses as x,probeGatewayAddress as $}from"../lib/gateway-addresses.js";import{listAdapters as T}from"../lib/tools/registry.js";import{logger as A}from"../utils/logger.js";import{maskHome as P,maskSecrets as R,uploadReport as N}from"../lib/telemetry.js";import{CLI_NAME as O}from"../lib/brand.js";import{appStatus as I,appStatusText as C,appTools as H,appUpgradeCommand as L,getApp as S}from"../lib/app-update.js";import{balanceLookupEnabled as U,balanceNeedsAttention as E,balanceText as K,fetchKeyBalances as B}from"../lib/key-balance.js";const G=["HTTPS_PROXY","https_proxy","HTTP_PROXY","http_proxy","ALL_PROXY","all_proxy"];function D(o,t,e=3e3){return new Promise(s=>{const r=c({host:o,port:t}),n=o=>{r.destroy(),s(o)};r.setTimeout(e,()=>n(!1)),r.once("connect",()=>n(!0)),r.once("error",()=>n(!1))})}function q(){const o=A.getLogDir();if(!r(o))return"";const t=n(o).filter(o=>/^\d{4}-\d{2}-\d{2}\.log$/.test(o)).sort().slice(-2).map(t=>`== ${t}\n`+a(i(o,t),"utf-8")).join("\n");return R(t.slice(-15e4))}function F(){const o={};for(const t of G){const e=process.env[t]?.trim();if(e)try{const s=new URL(e.includes("://")?e:`http://${e}`);o[t]=`${s.protocol}//${s.host}`}catch{o[t]="(unparsable)"}}return o}export async function doctorCommand(r={}){const n=e(u.t("doctor.checking")).start(),c=[],A=Number(process.versions.node.split(".")[0]);c.push({name:"Node.js",status:A>=20?"pass":"fail",message:`v${process.versions.node}`}),n.text=u.t("doctor.check_proxy"),c.push(await async function(){const o=u.t("doctor.proxy"),t=new Map;for(const o of G){const e=process.env[o]?.trim();e&&!t.has(e)&&t.set(e,o)}if(0===t.size)return{name:o,status:"pass",message:u.t("doctor.proxy_none")};const e=[];for(const[o,s]of t){let t;try{t=new URL(o.includes("://")?o:`http://${o}`)}catch{e.push(`${s}=${o}`);continue}const r=Number(t.port)||("https:"===t.protocol?443:t.protocol.startsWith("socks")?1080:80);await D(t.hostname,r)||e.push(`${s}=${o}`)}return 0===e.length?{name:o,status:"pass",message:[...t.keys()].join(", ")}:{name:o,status:"fail",message:u.t("doctor.proxy_dead",{proxies:e.join(", ")})}}()),n.text=u.t("doctor.check_api_key_network");const R=d(),M=u.t("doctor.api_key_network");if(R){const o=await m(R);o.valid?(c.push({name:M,status:"pass"}),n.text=u.t("doctor.check_balance"),c.push(...await async function(o){if(!U())return[];const t=l.listToolApiKeys().map(o=>({tool:o,key:l.getApiKeyForTool(o)})).filter(t=>Boolean(t.key)&&t.key!==o),e=await B([o,...t.map(o=>o.key)]),s=[{name:u.t("doctor.balance"),key:o},...t.map(o=>({name:u.t("doctor.balance_tool",{tool:f(o.tool)?.displayName??o.tool}),key:o.key}))],r=[];for(const o of s){const t=e.get(o.key);t&&r.push({name:o.name,status:E(t)?"warn":"pass",message:K(t)})}return r}(R))):"invalid_api_key"===o.error?c.push({name:M,status:"fail",message:u.t("doctor.api_key_invalid")}):(c.push({name:M,status:"fail",message:`${u.t("doctor.network_error")}: ${o.message??o.error}`}),n.text=u.t("doctor.check_other_addresses"),c.push(await async function(){const o=u.t("doctor.other_addresses"),t=l.getBaseUrl(),e=x().filter(o=>o.url!==t),s=d(),r=await Promise.all(e.map(o=>$(o.url,{apiKey:s}))),n=e.filter((o,t)=>r[t].ok).map(o=>o.url);return 0===n.length?{name:o,status:"fail",message:u.t("doctor.other_addresses_none")}:{name:o,status:"warn",message:u.t("doctor.other_addresses_found",{urls:n.join(", ")})}}()))}else c.push({name:M,status:"fail",message:u.t("doctor.api_key_missing")});n.text=u.t("doctor.check_client_config");const X=await o();c.push({name:u.t("doctor.client_config"),status:"cloud"===X.source||"cache"===X.source&&!X.problem?"pass":"warn",message:[X.source?u.t(`refresh.source.${X.source}`):u.t("refresh.source.none"),X.revision?u.t("doctor.client_config_revision",{revision:X.revision}):"",X.problem??""].filter(Boolean).join(" · ")}),n.text=u.t("doctor.check_tools");const Y=p.getInstalledTools();c.push({name:u.t("doctor.installed_tools"),status:Y.length>0?"pass":"warn",message:Y.length>0?Y.map(o=>f(o)?.displayName??o).join(u.t("setup.list_separator")):u.t("doctor.no_tools_installed")}),c.push(...function(){const o=[];for(const t of p.getInstalledTools()){const e=f(t);if(!e?.installSpec)continue;const s=_(e.installSpec);if(0===s.length)continue;const r=[],n=p.outdatedVersion(t);n&&r.push(u.t("doctor.tool_outdated",{min:n.min})),s.length>1&&r.push(u.t("doctor.tool_duplicates",{others:s.slice(1).map(g).join("、")})),o.push({name:e.displayName,status:r.length>0?"warn":"pass",message:[g(s[0]),...r,...r.length>0?[u.t("doctor.run_upgrade",{tool:t})]:[]].join("\n ")})}return o}()),c.push(...await async function(){const o=[];for(const t of H()){const e=await I(t,{refresh:!0});if(!e.installed||!e.current)continue;const s=u.t("doctor.app_version",{tool:e.name});if(e.outdated){const r=e.blocker?u.t(`app_update.blocked_${e.blocker}`,{tool:e.name,url:S(t)?.appInstaller.downloadPage??"",command:L(t)}):u.t("doctor.run_app_upgrade",{command:L(t)});o.push({name:s,status:"warn",message:`${C(e)}\n ${r}`})}else o.push({name:s,status:"pass",message:C(e)})}return o}());const V=function(){if(!p.isToolInstalled("claude-code"))return null;const o=u.t("doctor.claude_config"),t=h();if(t.length>0){const e=t.map(o=>`${o.source}: ${o.keys.join(", ")}`).join("; ");return{name:o,status:"fail",message:u.t("doctor.claude_managed",{detail:e})}}let e={};try{e=JSON.parse(a(i(process.env.CLAUDE_CONFIG_DIR?.trim()||i(j(),".claude"),"settings.json"),"utf-8")).env??{}}catch{}const s=l.getApiKeyForTool("claude-code");return e.ANTHROPIC_AUTH_TOKEN&&e.ANTHROPIC_BASE_URL?e.ANTHROPIC_BASE_URL!==l.getBaseUrl()||s&&e.ANTHROPIC_AUTH_TOKEN!==s?{name:o,status:"warn",message:u.t("doctor.claude_config_changed")}:{name:o,status:"pass"}:{name:o,status:"warn",message:u.t("doctor.claude_not_configured")}}();V&&c.push(V),Y.includes("claude-code")&&v()&&c.push({name:u.t("doctor.claude_login"),status:"pass",message:u.t("tools.claude_code.account_login_overridden")});const W=Y.includes("codex")?y():null;if(Y.includes("codex")&&c.push({name:u.t("doctor.codex_auth"),status:W?"fail":"pass",message:W?u.t(`doctor.codex_${W}`,{path:P(w())}):void 0}),Y.includes("codex")){const o=k();c.push({name:u.t("doctor.codex_catalog"),status:o?"fail":"pass",message:o?u.t("doctor.codex_catalog_rejected",{path:o.bin,version:o.version??"?",error:o.error}):void 0})}Y.includes("codex")&&b()&&c.push({name:u.t("doctor.codex_work_mode"),status:"warn",message:u.t("tools.codex.work_mode_on")}),"win32"===process.platform&&Y.includes("claude-code")&&!process.env.CLAUDE_CODE_GIT_BASH_PATH&&c.push({name:"Git for Windows",status:p.isGitInstalled()?"pass":"warn",message:p.isGitInstalled()?void 0:u.t("tools.claude_code.no_git_bash")}),r.deep&&Y.includes("claude-code")&&(n.text=u.t("doctor.check_claude_request"),c.push(function(){const o=u.t("doctor.claude_request"),t=_(f("claude-code").installSpec)[0];if(!t)return{name:o,status:"warn",message:u.t("doctor.claude_request_skipped")};const e={encoding:"utf-8",timeout:12e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]},r=["-p","Reply with the single word OK."],n=/\.cmd$/i.test(t.path)?s(`"${t.path}" ${r.map(o=>`"${o}"`).join(" ")}`,{...e,shell:!0}):s(t.path,r,e),a=`${n.stdout??""}`.trim();if(0===n.status&&a)return{name:o,status:"pass",message:a.slice(0,80)};const c=(`${n.stderr??""}`.trim()||a||n.error?.message||`exit ${n.status}`).slice(0,300);return{name:o,status:"fail",message:u.t("doctor.claude_request_failed",{reason:c})}}())),n.stop(),console.log("\n"+t.bold(u.t("doctor.results_title"))+"\n");const z={pass:t.green("√"),warn:t.yellow("!"),fail:t.red("×")};for(const o of c)console.log(`${z[o.status]} ${o.name}`),o.message&&console.log(t.gray(` ${o.message}`));if(c.every(o=>"pass"===o.status)&&console.log("\n"+t.green.bold(u.t("doctor.all_good"))),!r.deep&&Y.includes("claude-code")&&console.log(t.gray("\n"+u.t("doctor.deep_hint"))),r.report){const o=e(u.t("doctor.report_uploading")).start(),t=await N(function(o,t){const e={};for(const o of T()){if(o.hidden)continue;let t=null;try{t=p.detectCurrentConfig(o.name).apiKey?"has_key":"no_key"}catch{t="unreadable"}e[o.name]={installed:p.isToolInstalled(o.name),version:p.installedVersion(o.name),copies:o.installSpec?_(o.installSpec).map(o=>({kind:o.kind,version:o.version,path:o.path})):void 0,config:t}}const s=l.getProfile();return{checks:o,tools:e,settings:{base_url:l.getBaseUrl(),profile:l.getActiveProfileName(),profiles:l.listProfiles().length,key_fingerprint:l.getApiKeyFingerprint()||null,tool_keys:Object.keys(s.tool_api_keys??{}),models:s.models,tool_models:s.tool_models??{},tool_settings:s.tool_settings??{},lang:l.getLang()},client_config:t,env:{shell:process.env.SHELL??process.env.ComSpec??null,term:process.env.TERM_PROGRAM??null,proxies:F()},log:q()}}(c,{source:X.source??void 0,revision:X.revision,problem:X.problem}));t?o.succeed(u.t("doctor.report_done",{code:t})):o.fail(u.t("doctor.report_failed",{cli:O}))}else c.some(o=>"fail"===o.status)&&console.log(t.gray("\n"+u.t("doctor.report_hint",{cli:O})));c.some(o=>"fail"===o.status)&&(process.exitCode=1)}
|
package/dist/commands/setup.d.ts
CHANGED
|
@@ -91,4 +91,11 @@ export interface SetupCommandOptions extends Partial<Record<DedicatedKeyOption,
|
|
|
91
91
|
}
|
|
92
92
|
/** `--claude-official on|off` (also true/false, show/hide, 1/0, yes/no); undefined when unrecognized. */
|
|
93
93
|
export declare function parseOnOff(raw: string | undefined): boolean | undefined;
|
|
94
|
+
/**
|
|
95
|
+
* Desktop apps that go with the configured tools but aren't installed (Claude Desktop; ChatGPT, which runs Codex
|
|
96
|
+
* on the same config): installed from the download mirror like a missing CLI tool (user, 11-01: the one-line
|
|
97
|
+
* installer should bring them along): `--install`, `--yes` (one-line installers pass it) or yes at the prompt
|
|
98
|
+
* (default yes); `--no-install`, a no, `--non-interactive` / `--json` or no terminal only print the command.
|
|
99
|
+
*/
|
|
100
|
+
export declare function installMissingApps(tools: string[], install: boolean | undefined): Promise<boolean>;
|
|
94
101
|
export declare function setupCommand(options: SetupCommandOptions): Promise<void>;
|
package/dist/commands/setup.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import o from"chalk";import{getAdapter as e}from"../lib/tools/registry.js";import{postApplyPrompts as t}from"../lib/post-apply.js";import{ensureReachableGatewayAddress as i}from"./base.js";import{i18n as l}from"../lib/i18n.js";import{configManager as s}from"../lib/config.js";import{toolManager as a,SUPPORTED_TOOLS as n}from"../lib/tool-manager.js";import{validateApiKey as r,fetchModels as d}from"../lib/api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as p,setCodexOneMillionContext as c}from"../lib/tools/codex.js";import{resolveModelCatalog as u}from"../lib/model-catalog.js";import{CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING as f,CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as m}from"../lib/tools/claude-desktop.js";import{operationError as g,authenticationError as y,networkError as _,EXIT_CODES as k}from"../lib/errors.js";import{emitJson as h,isColorEnabled as b,isDryRun as w,isJsonMode as v,isNonInteractive as x,shouldAutoConfirm as C}from"../lib/runtime-options.js";import{join as j}from"path";import{confirmWritePlan as K,printWritePlan as $,toolWritePlan as T}from"../lib/write-plan.js";import G from"inquirer";import{logger as S}from"../utils/logger.js";import{forgetInstalls as M}from"../lib/tools/tool-installs.js";import{CLI_NAME as N,brandEnv as E}from"../lib/brand.js";export const DEDICATED_KEYS=[{option:"claudekey",tool:"claude-code",need:"claude"},{option:"codexkey",tool:"codex",need:"gpt"},{option:"grokkey",tool:"grok",need:"grok"},{option:"desktopkey",tool:"claude-desktop",need:"claude"},{option:"agykey",tool:"agy",need:"gemini"},{option:"openclawkey",tool:"openclaw",need:"any",hidden:!0},{option:"hermeskey",tool:"hermes",need:"any",hidden:!0},{option:"atomcodekey",tool:"atomcode",need:"any",hidden:!0}];async function I(o){const e=await d(o);if(!e.ok)return{hasClaude:!0,hasGpt:!0,hasGrok:!0,hasGemini:!0,probed:!1};const t=e.models.map(o=>o.toLowerCase());return{hasClaude:t.some(o=>o.includes("claude")),hasGpt:t.some(o=>o.startsWith("gpt")||o.includes("gpt-")||/^o\d/.test(o)),hasGrok:t.some(o=>o.includes("grok")),hasGemini:t.some(o=>o.startsWith("gemini")),probed:!0}}function O(o,e){switch(e){case"claude":return o.hasClaude;case"gpt":return o.hasGpt;case"grok":return o.hasGrok;case"gemini":return o.hasGemini;default:return!0}}export function parseOnOff(o){const e=(o??"").trim().toLowerCase();return!!["on","true","show","1","yes","y"].includes(e)||!["off","false","hide","0","no","n"].includes(e)&&void 0}function A(e){console.log(o.green(e))}function D(e){console.log(o.yellow(e))}function F(e){console.error(o.red(e))}let B=null;function L(o){const e={operation:1,authentication:2,network:3};(!B||e[o]>e[B])&&(B=o)}async function R(e,t){v()||console.log(o.gray(l.t("setup.validating",{label:e})));const i=await r(t);if(i.valid)return!0;const a=l.t("errors.key_placeholder"),n="--key"===e?`${N} setup --key ${a}`:`${N} setup ${e} ${a}`;let d;if("network_error"===i.error?(L("network"),d=_(l.t("setup.unreachable",{url:s.getBaseUrl(),reason:i.message||"network error"}),`${N} base auto`,"network_error")):"invalid_api_key"===i.error?(L("authentication"),d=y(l.t("setup.invalid_key",{label:e,reason:i.message||"invalid"}),n,"invalid_api_key")):(L("operation"),d=g(l.t("setup.validate_failed",{label:e,reason:i.message||i.error||"unknown"}),n,i.error)),v())throw d;return F(d.message),console.log(o.gray(l.t("errors.next_step",{command:d.hint}))),!1}async function P(t,i,r={}){const{oneMillion:d,officialLogin:c,desktopRegistry:u,force:y}=r,_=n[t];try{"claude-desktop"===t&&void 0!==u&&s.setToolSetting("claude-desktop",f,u),"codex"===t&&void 0!==d&&s.setToolSetting("codex",p,d),"claude-desktop"===t&&void 0!==c&&s.setToolSetting("claude-desktop",m,!c),await a.applyPrivateConfig(t,i,s.getModelsForTool(t),{force:y})}catch(o){if(v())throw g(o instanceof Error?o.message:String(o),`${N} setup --key ${l.t("errors.key_placeholder")}`,"config_write_failed");const e=(o instanceof Error?o.message:String(o)).replace(/\s+/g," ").trim();return F("× "+l.t("setup.apply_failed",{tool:_.displayName,reason:e})),!1}return a.printApplied(t),y&&console.log(o.gray(" "+l.t("config.force_done",{tool:_.displayName,name:t}))),"codex"===t&&void 0!==d&&console.log(o.gray(" "+l.t(d?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))),e(t)?.isInstalled&&!a.isToolInstalled(t)&&console.log(o.yellow(" ! "+l.t("setup.gui_preconfigured",{tool:_.displayName,install:_.installCommand}))),!0}function Y(o){return!e(o)?.isInstalled&&!a.isToolInstalled(o)}function q(o){D(l.t("setup.still_missing",{tools:o.map(o=>n[o].displayName).join(l.t("setup.list_separator")),commands:o.map(o=>`${N} config ${o} --yes`).join(l.t("setup.list_separator"))}))}function H(e,t,i=[]){const a=T(e),n=j(s.getConfigDir(),"config.yaml");if(v())h({dry_run:!0,tools:a,install_first:i,key_file:t?n:null});else{if(0===a.length&&0===i.length){const e=(b()?o.cyan:o=>o)(l.t("runtime.dry_run_label"));return void console.log(`${e} ${l.t("setup.dry_run_none")}`)}$(a,{label:l.t("runtime.dry_run_label"),keyFile:t?n:void 0,installFirst:i})}}function W(){return"darwin"===process.platform||"win32"===process.platform||a.isToolInstalled("claude-desktop")}export async function setupCommand(r){B=null;const d=r.key?.trim(),f=DEDICATED_KEYS.map(o=>({...o,apiKey:r[o.option]?.trim()})).filter(o=>Boolean(o.apiKey)),m=void 0!==r.oneMillion,g=void 0!==r.claudeOfficial;let y;if(g&&(y=parseOnOff(r.claudeOfficial),void 0===y))return F(l.t("setup.claude_official_invalid",{value:String(r.claudeOfficial)})),void(process.exitCode=1);const _=void 0!==r.desktopRegistry;let h;if(_&&(h=parseOnOff(r.desktopRegistry),void 0===h))return F(l.t("setup.desktop_registry_invalid",{value:String(r.desktopRegistry)})),void(process.exitCode=1);const b=g||_,$=Boolean(d||f.length>0),T={oneMillion:r.oneMillion,officialLogin:y,desktopRegistry:h,force:r.force};if(!$&&(m||b)&&w())return void H([...m?["codex"]:[],...b?["claude-desktop"]:[]],!1);if(!$&&(m||b)){if(m){const o=s.getApiKeyForTool("codex");if(o)try{const e=!0===r.oneMillion;s.setToolSetting("codex",p,e);const t=await u(o);c(e,t??void 0),A(l.t(e?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))}catch(o){F(l.t("setup.apply_failed",{tool:n.codex.displayName,reason:o instanceof Error?o.message:String(o)})),process.exitCode=1}else F(l.t("setup.codex_1m_missing_key")),process.exitCode=1}if(b){const o=s.getApiKeyForTool("claude-desktop");o?await P("claude-desktop",o,{...T,oneMillion:void 0})?await t(["claude-desktop"]):process.exitCode=1:(F(l.t("setup.desktop_official_login_missing_key")),process.exitCode=1)}return}if(!$)return F(l.t("setup.usage")),void(process.exitCode=1);const L=w();L||await i(d||f[0].apiKey);const U=[],z=[];let J,Q=0,V=0;const X=new Set,Z=f.map(o=>({tool:o.tool,label:`--${o.option}`,apiKey:o.apiKey,need:o.need}));for(const o of Z){if(!await R(o.label,o.apiKey)){V+=1;continue}const e=await I(o.apiKey);!e.probed||O(e,o.need)?(e.probed||D(l.t("setup.probe_failed",{label:o.label})),U.push({tool:o.tool,apiKey:o.apiKey,dedicated:!0}),X.add(o.tool)):(F(l.t(`setup.key_no_${o.need}`,{label:o.label,tool:n[o.tool].displayName})),V+=1)}const oo=!!d&&await R("--key",d);d&&!oo&&(J=k[B??"operation"]);const eo=d&&oo?await I(d):void 0;if(d&&eo&&!eo.probed&&D(l.t("setup.probe_failed",{label:"--key"})),!(d&&eo&&eo.probed)||eo.hasClaude||eo.hasGpt||eo.hasGrok||eo.hasGemini||(F(l.t("setup.key_no_family")),J=1),d&&eo&&void 0===J){const o=[{tool:"claude-code",capable:eo.hasClaude,skipMsg:l.t(W()?"setup.skip_no_claude_desktop":"setup.skip_no_claude")},{tool:"codex",capable:eo.hasGpt,skipMsg:l.t("setup.skip_no_gpt")},{tool:"grok",capable:eo.hasGrok,skipMsg:l.t("setup.skip_no_grok")},{tool:"claude-desktop",capable:eo.hasClaude&&W(),skipMsg:"",quiet:!0},{tool:"agy",capable:eo.hasGemini,skipMsg:l.t("setup.skip_no_gemini")}];for(const e of o)X.has(e.tool)||(e.capable?(U.push({tool:e.tool,apiKey:d,dedicated:!1}),X.add(e.tool)):e.quiet||D(e.skipMsg))}const to=Boolean(d&&oo&&void 0===J);if(L)return H(U.filter(o=>!Y(o.tool)).map(o=>o.tool),U.length>0,U.filter(o=>Y(o.tool)).map(o=>o.tool)),void((V>0||void 0!==J)&&(process.exitCode=J??k[B??"operation"]));const io=U.filter(o=>!Y(o.tool)),lo=to||U.some(o=>o.dedicated);if((U.length>0||lo)&&!r.fromInstaller&&!await K(io.map(o=>o.tool),{keyFile:lo?j(s.getConfigDir(),"config.yaml"):void 0,installFirst:U.filter(o=>Y(o.tool)).map(o=>o.tool)}))return void(process.exitCode=k.cancelled);to&&d&&s.setApiKey(d);for(const o of U)o.dedicated&&s.setToolApiKey(o.tool,o.apiKey),Y(o.tool)?z.push({tool:o.tool,apiKey:o.apiKey}):await P(o.tool,o.apiKey,T)?Q+=1:(V+=1,X.delete(o.tool));if(void 0!==J)return z.length>0&&q(z.map(o=>o.tool)),void(process.exitCode=J);let so=[];if(z.length>0){const e=await async function(e,t,i){const s=e.map(o=>o.tool);if(0===s.length)return{still:[],applied:[],failed:[]};const r=s.map(o=>n[o].displayName).join(l.t("setup.list_separator"));let d=t;if(void 0!==d||v()||(C()?d=!x():process.stdin.isTTY&&(console.log(""),d=(await G.prompt([{type:"confirm",name:"go",message:l.t("setup.install_confirm",{tools:r}),default:!0}])).go)),!d){console.log("");for(const e of s)console.log(o.yellow("! "+l.t("setup.install_hint",{tool:n[e].displayName,install:n[e].installCommand})));return v()||console.log(o.gray(l.t("setup.install_all_hint",{cli:N}))),{still:s,applied:[],failed:[]}}const p=[];for(const e of s){console.log(o.bold(`\n${n[e].displayName}`));try{await a.installTool(e)}catch(o){S.logError(`setup: install ${e}`,o)}M(),a.isToolInstalled(e)||p.push(e)}const c=s.filter(o=>!p.includes(o));c.length>0&&console.log("");const u=[],f=[];for(const{tool:o,apiKey:t}of e.filter(o=>c.includes(o.tool)))await P(o,t,i)?u.push(o):f.push(o);return{still:p,applied:u,failed:f}}(z,r.install,T);so=e.still,Q+=e.applied.length,V+=e.failed.length;for(const o of[...so,...e.failed])X.delete(o)}if(Q>0){const t=[...X].filter(o=>!e(o)?.isInstalled&&!so.includes(o)),i=t.map(o=>n[o]?.command).filter(Boolean).join(" / "),s=l.t("setup.done",{count:String(Q)});A("\n"+(i?`${s}${l.t("setup.done_commands",{commands:i})}`:s)),so.length>0&&q(so);for(const o of t){const e=a.ensureNativeOnPath(o);e&&A(l.t("setup.path_added",{tool:n[o].displayName,dir:e}))}const r=t.filter(o=>!a.isOnPath(o));if(r.length>0&&!v()&&"1"!==E("PATH_HINT_BY_CALLER")){const e=r.map(o=>n[o].command).join(" / ");console.log(o.yellow(" ! "+l.t("win32"===process.platform?"setup.path_reload_windows":"setup.path_reload",{commands:e})))}}0===Q&&so.length>0&&q(so),V>0&&(F(l.t("setup.failed_summary",{count:String(V)})),v()||console.error(`${N} setup --key ${l.t("errors.key_placeholder")}`)),await t([...X]),(V>0||0===Q&&0===so.length)&&(process.exitCode=k[B??"operation"])}
|
|
1
|
+
import o from"chalk";import{getAdapter as e}from"../lib/tools/registry.js";import{postApplyPrompts as t}from"../lib/post-apply.js";import{ensureReachableGatewayAddress as i}from"./base.js";import{i18n as l}from"../lib/i18n.js";import{configManager as s}from"../lib/config.js";import{toolManager as a,SUPPORTED_TOOLS as n}from"../lib/tool-manager.js";import{validateApiKey as r,fetchModels as p}from"../lib/api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as d,setCodexOneMillionContext as c}from"../lib/tools/codex.js";import{resolveModelCatalog as u}from"../lib/model-catalog.js";import{CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING as f,CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as m}from"../lib/tools/claude-desktop.js";import{operationError as g,authenticationError as y,networkError as _,EXIT_CODES as k}from"../lib/errors.js";import{canPrompt as h,emitJson as b,isColorEnabled as w,isDryRun as v,isJsonMode as x,isNonInteractive as C,shouldAutoConfirm as j}from"../lib/runtime-options.js";import{appsForTools as K,appUpgradeCommand as $,getApp as T}from"../lib/app-update.js";import{join as M}from"path";import{confirmWritePlan as G,printWritePlan as S,toolWritePlan as I}from"../lib/write-plan.js";import N from"inquirer";import{logger as E}from"../utils/logger.js";import{forgetInstalls as A}from"../lib/tools/tool-installs.js";import{CLI_NAME as O,brandEnv as B}from"../lib/brand.js";export const DEDICATED_KEYS=[{option:"claudekey",tool:"claude-code",need:"claude"},{option:"codexkey",tool:"codex",need:"gpt"},{option:"grokkey",tool:"grok",need:"grok"},{option:"desktopkey",tool:"claude-desktop",need:"claude"},{option:"agykey",tool:"agy",need:"gemini"},{option:"openclawkey",tool:"openclaw",need:"any",hidden:!0},{option:"hermeskey",tool:"hermes",need:"any",hidden:!0},{option:"atomcodekey",tool:"atomcode",need:"any",hidden:!0}];async function D(o){const e=await p(o);if(!e.ok)return{hasClaude:!0,hasGpt:!0,hasGrok:!0,hasGemini:!0,probed:!1};const t=e.models.map(o=>o.toLowerCase());return{hasClaude:t.some(o=>o.includes("claude")),hasGpt:t.some(o=>o.startsWith("gpt")||o.includes("gpt-")||/^o\d/.test(o)),hasGrok:t.some(o=>o.includes("grok")),hasGemini:t.some(o=>o.startsWith("gemini")),probed:!0}}function F(o,e){switch(e){case"claude":return o.hasClaude;case"gpt":return o.hasGpt;case"grok":return o.hasGrok;case"gemini":return o.hasGemini;default:return!0}}export function parseOnOff(o){const e=(o??"").trim().toLowerCase();return!!["on","true","show","1","yes","y"].includes(e)||!["off","false","hide","0","no","n"].includes(e)&&void 0}function L(e){console.log(o.green(e))}function R(e){console.log(o.yellow(e))}function P(e){console.error(o.red(e))}let Y=null;function q(o){const e={operation:1,authentication:2,network:3};(!Y||e[o]>e[Y])&&(Y=o)}async function z(e,t){x()||console.log(o.gray(l.t("setup.validating",{label:e})));const i=await r(t);if(i.valid)return!0;const a=l.t("errors.key_placeholder"),n="--key"===e?`${O} setup --key ${a}`:`${O} setup ${e} ${a}`;let p;if("network_error"===i.error?(q("network"),p=_(l.t("setup.unreachable",{url:s.getBaseUrl(),reason:i.message||"network error"}),`${O} base auto`,"network_error")):"invalid_api_key"===i.error?(q("authentication"),p=y(l.t("setup.invalid_key",{label:e,reason:i.message||"invalid"}),n,"invalid_api_key")):(q("operation"),p=g(l.t("setup.validate_failed",{label:e,reason:i.message||i.error||"unknown"}),n,i.error)),x())throw p;return P(p.message),console.log(o.gray(l.t("errors.next_step",{command:p.hint}))),!1}async function H(t,i,r={}){const{oneMillion:p,officialLogin:c,desktopRegistry:u,force:y}=r,_=n[t];try{"claude-desktop"===t&&void 0!==u&&s.setToolSetting("claude-desktop",f,u),"codex"===t&&void 0!==p&&s.setToolSetting("codex",d,p),"claude-desktop"===t&&void 0!==c&&s.setToolSetting("claude-desktop",m,!c),await a.applyPrivateConfig(t,i,s.getModelsForTool(t),{force:y})}catch(o){if(x())throw g(o instanceof Error?o.message:String(o),`${O} setup --key ${l.t("errors.key_placeholder")}`,"config_write_failed");const e=(o instanceof Error?o.message:String(o)).replace(/\s+/g," ").trim();return P("× "+l.t("setup.apply_failed",{tool:_.displayName,reason:e})),!1}return a.printApplied(t),y&&console.log(o.gray(" "+l.t("config.force_done",{tool:_.displayName,name:t}))),"codex"===t&&void 0!==p&&console.log(o.gray(" "+l.t(p?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))),e(t)?.isInstalled&&!a.isToolInstalled(t)&&console.log(o.yellow(" ! "+l.t("setup.gui_preconfigured",{tool:_.displayName,install:_.installCommand}))),!0}function W(o){return!e(o)?.isInstalled&&!a.isToolInstalled(o)}export async function installMissingApps(e,t){const i=K(e).filter(o=>{const e=T(o)?.appInstaller;try{return Boolean(e&&!e.blocker()&&!e.installedPath())}catch(e){return E.logError(`setup: app installed? ${o}`,e),!1}});if(0===i.length)return!1;const s=o=>T(o)?.displayName??o;let a=t;if(void 0===a&&!x())if(j())a=!C();else if(h()){const o=i.map(s).join(l.t("setup.list_separator")),e=i.reduce((o,e)=>o+(T(e)?.appInstaller.sizeMb()??0),0);console.log(""),a=(await N.prompt([{type:"confirm",name:"go",message:l.t("setup.install_app_confirm",{tools:o,size:String(e)}),default:!0}])).go}if(!a&&!x())for(const e of i)console.log(o.gray(l.t("setup.install_app_hint",{tool:s(e),command:$(e)})));return Boolean(a)}function U(o){R(l.t("setup.still_missing",{tools:o.map(o=>n[o].displayName).join(l.t("setup.list_separator")),commands:o.map(o=>`${O} config ${o} --yes`).join(l.t("setup.list_separator"))}))}function J(e,t,i=[]){const a=I(e),n=M(s.getConfigDir(),"config.yaml");if(x())b({dry_run:!0,tools:a,install_first:i,key_file:t?n:null});else{if(0===a.length&&0===i.length){const e=(w()?o.cyan:o=>o)(l.t("runtime.dry_run_label"));return void console.log(`${e} ${l.t("setup.dry_run_none")}`)}S(a,{label:l.t("runtime.dry_run_label"),keyFile:t?n:void 0,installFirst:i})}}function Q(){return"darwin"===process.platform||"win32"===process.platform||a.isToolInstalled("claude-desktop")}export async function setupCommand(r){Y=null;const p=r.key?.trim(),f=DEDICATED_KEYS.map(o=>({...o,apiKey:r[o.option]?.trim()})).filter(o=>Boolean(o.apiKey)),m=void 0!==r.oneMillion,g=void 0!==r.claudeOfficial;let y;if(g&&(y=parseOnOff(r.claudeOfficial),void 0===y))return P(l.t("setup.claude_official_invalid",{value:String(r.claudeOfficial)})),void(process.exitCode=1);const _=void 0!==r.desktopRegistry;let h;if(_&&(h=parseOnOff(r.desktopRegistry),void 0===h))return P(l.t("setup.desktop_registry_invalid",{value:String(r.desktopRegistry)})),void(process.exitCode=1);const b=g||_,w=Boolean(p||f.length>0),K={oneMillion:r.oneMillion,officialLogin:y,desktopRegistry:h,force:r.force};if(!w&&(m||b)&&v())return void J([...m?["codex"]:[],...b?["claude-desktop"]:[]],!1);if(!w&&(m||b)){if(m){const o=s.getApiKeyForTool("codex");if(o)try{const e=!0===r.oneMillion;s.setToolSetting("codex",d,e);const t=await u(o);c(e,t??void 0),L(l.t(e?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))}catch(o){P(l.t("setup.apply_failed",{tool:n.codex.displayName,reason:o instanceof Error?o.message:String(o)})),process.exitCode=1}else P(l.t("setup.codex_1m_missing_key")),process.exitCode=1}if(b){const o=s.getApiKeyForTool("claude-desktop");o?await H("claude-desktop",o,{...K,oneMillion:void 0})?await t(["claude-desktop"],{apps:{install:!1}}):process.exitCode=1:(P(l.t("setup.desktop_official_login_missing_key")),process.exitCode=1)}return}if(!w)return P(l.t("setup.usage")),void(process.exitCode=1);const $=v();$||await i(p||f[0].apiKey);const T=[],S=[];let I,q=0,V=0;const X=new Set,Z=f.map(o=>({tool:o.tool,label:`--${o.option}`,apiKey:o.apiKey,need:o.need}));for(const o of Z){if(!await z(o.label,o.apiKey)){V+=1;continue}const e=await D(o.apiKey);!e.probed||F(e,o.need)?(e.probed||R(l.t("setup.probe_failed",{label:o.label})),T.push({tool:o.tool,apiKey:o.apiKey,dedicated:!0}),X.add(o.tool)):(P(l.t(`setup.key_no_${o.need}`,{label:o.label,tool:n[o.tool].displayName})),V+=1)}const oo=!!p&&await z("--key",p);p&&!oo&&(I=k[Y??"operation"]);const eo=p&&oo?await D(p):void 0;if(p&&eo&&!eo.probed&&R(l.t("setup.probe_failed",{label:"--key"})),!(p&&eo&&eo.probed)||eo.hasClaude||eo.hasGpt||eo.hasGrok||eo.hasGemini||(P(l.t("setup.key_no_family")),I=1),p&&eo&&void 0===I){const o=[{tool:"claude-code",capable:eo.hasClaude,skipMsg:l.t(Q()?"setup.skip_no_claude_desktop":"setup.skip_no_claude")},{tool:"codex",capable:eo.hasGpt,skipMsg:l.t("setup.skip_no_gpt")},{tool:"grok",capable:eo.hasGrok,skipMsg:l.t("setup.skip_no_grok")},{tool:"claude-desktop",capable:eo.hasClaude&&Q(),skipMsg:"",quiet:!0},{tool:"agy",capable:eo.hasGemini,skipMsg:l.t("setup.skip_no_gemini")}];for(const e of o)X.has(e.tool)||(e.capable?(T.push({tool:e.tool,apiKey:p,dedicated:!1}),X.add(e.tool)):e.quiet||R(e.skipMsg))}const to=Boolean(p&&oo&&void 0===I);if($)return J(T.filter(o=>!W(o.tool)).map(o=>o.tool),T.length>0,T.filter(o=>W(o.tool)).map(o=>o.tool)),void((V>0||void 0!==I)&&(process.exitCode=I??k[Y??"operation"]));const io=T.filter(o=>!W(o.tool)),lo=to||T.some(o=>o.dedicated);if((T.length>0||lo)&&!r.fromInstaller&&!await G(io.map(o=>o.tool),{keyFile:lo?M(s.getConfigDir(),"config.yaml"):void 0,installFirst:T.filter(o=>W(o.tool)).map(o=>o.tool)}))return void(process.exitCode=k.cancelled);to&&p&&s.setApiKey(p);for(const o of T)o.dedicated&&s.setToolApiKey(o.tool,o.apiKey),W(o.tool)?S.push({tool:o.tool,apiKey:o.apiKey}):await H(o.tool,o.apiKey,K)?q+=1:(V+=1,X.delete(o.tool));if(void 0!==I)return S.length>0&&U(S.map(o=>o.tool)),void(process.exitCode=I);let so=[];if(S.length>0){const e=await async function(e,t,i){const s=e.map(o=>o.tool);if(0===s.length)return{still:[],applied:[],failed:[]};const r=s.map(o=>n[o].displayName).join(l.t("setup.list_separator"));let p=t;if(void 0!==p||x()||(j()?p=!C():process.stdin.isTTY&&(console.log(""),p=(await N.prompt([{type:"confirm",name:"go",message:l.t("setup.install_confirm",{tools:r}),default:!0}])).go)),!p){console.log("");for(const e of s)console.log(o.yellow("! "+l.t("setup.install_hint",{tool:n[e].displayName,install:n[e].installCommand})));return x()||console.log(o.gray(l.t("setup.install_all_hint",{cli:O}))),{still:s,applied:[],failed:[]}}const d=[];for(const e of s){console.log(o.bold(`\n${n[e].displayName}`));try{await a.installTool(e)}catch(o){E.logError(`setup: install ${e}`,o)}A(),a.isToolInstalled(e)||d.push(e)}const c=s.filter(o=>!d.includes(o));c.length>0&&console.log("");const u=[],f=[];for(const{tool:o,apiKey:t}of e.filter(o=>c.includes(o.tool)))await H(o,t,i)?u.push(o):f.push(o);return{still:d,applied:u,failed:f}}(S,r.install,K);so=e.still,q+=e.applied.length,V+=e.failed.length;for(const o of[...so,...e.failed])X.delete(o)}if(q>0){const t=[...X].filter(o=>!e(o)?.isInstalled&&!so.includes(o)),i=t.map(o=>n[o]?.command).filter(Boolean).join(" / "),s=l.t("setup.done",{count:String(q)});L("\n"+(i?`${s}${l.t("setup.done_commands",{commands:i})}`:s)),so.length>0&&U(so);for(const o of t){const e=a.ensureNativeOnPath(o);e&&L(l.t("setup.path_added",{tool:n[o].displayName,dir:e}))}const r=t.filter(o=>!a.isOnPath(o));if(r.length>0&&!x()&&"1"!==B("PATH_HINT_BY_CALLER")){const e=r.map(o=>n[o].command).join(" / ");console.log(o.yellow(" ! "+l.t("win32"===process.platform?"setup.path_reload_windows":"setup.path_reload",{commands:e})))}}0===q&&so.length>0&&U(so),V>0&&(P(l.t("setup.failed_summary",{count:String(V)})),x()||console.error(`${O} setup --key ${l.t("errors.key_placeholder")}`)),await t([...X],{apps:{install:await installMissingApps([...X],r.install)}}),(V>0||0===q&&0===so.length)&&(process.exitCode=k[Y??"operation"])}
|
package/dist/commands/update.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import t from"chalk";import{readFileSync as e}from"fs";import{join as r,dirname as o}from"path";import{fileURLToPath as n}from"url";import{i18n as a}from"../lib/i18n.js";import{isJsonMode as s,emitJson as c,isColorEnabled as i}from"../lib/runtime-options.js";import{brand as l}from"../lib/brand.js";import{appStatus as u,appStatusText as p,appTools as m,appUpgradeCommand as d}from"../lib/app-update.js";import{logger as g}from"../utils/logger.js";const f=l().packageName;export const UPDATE_TIMEOUT_MS=1500;const h=t=>{const e=t["dist-tags"];if(!e||"object"!=typeof e)return null;const r=e.latest;return"string"==typeof r?r:null};export const UPDATE_SOURCES=l().updateRegistries.map(({id:t,url:e})=>({id:t,registry:e,metadataUrl:t=>((t,e,r="")=>`${t}${encodeURIComponent(e)}${r}`)(e,t),readVersion:h}));function y(t){return i()?t:t=>t}export function readLocalPackage(){const t=n(import.meta.url),a=o(t),s=r(a,"..","..");try{const t=JSON.parse(e(r(s,"package.json"),"utf-8"));return{name:t.name||f,version:t.version||"0.0.0",root:s}}catch{return{name:f,version:"0.0.0",root:s}}}function w(t){const[e,...r]=t.split("-"),o=r.length?r.join("-").split("."):[];return{main:e.split(".").map(t=>Number.parseInt(t,10)||0),pre:o}}function k(t,e){const r=Number.parseInt(t,10),o=Number.parseInt(e,10),n=Number.isFinite(r)&&String(r)===t,a=Number.isFinite(o)&&String(o)===e;return n&&a?r-o:n?-1:a?1:t<e?-1:t>e?1:0}export function compareSemver(t,e){const r=w(t),o=w(e),n=Math.max(r.main.length,o.main.length);for(let t=0;t<n;t+=1){const e=(r.main[t]||0)-(o.main[t]||0);if(0!==e)return e}if(0===r.pre.length&&0===o.pre.length)return 0;if(0===r.pre.length)return 1;if(0===o.pre.length)return-1;const a=Math.max(r.pre.length,o.pre.length);for(let t=0;t<a;t+=1){const e=r.pre[t],n=o.pre[t];if(void 0===e)return-1;if(void 0===n)return 1;const a=k(e,n);if(0!==a)return a}return 0}async function b(t,e,r,o){const n=new AbortController,a=setTimeout(()=>n.abort(),o);try{const o=await r(t.metadataUrl(e),{headers:{Accept:"application/json"},signal:n.signal});if(!o.ok)throw new Error(`HTTP ${o.status}`);const a=await o.json(),s=t.readVersion(a);if(!s)throw new Error("invalid registry metadata");return s}catch(t){if(n.signal.aborted)throw new Error(`timeout after ${o}ms`);throw t}finally{clearTimeout(a)}}export async function checkForUpdate(t={}){const e=t.localPackage||readLocalPackage(),r=t.localVersion||e.version,o=t.packageName||e.name,n=t.fetchFn||fetch,a=t.timeoutMs||1500,s=t.sources||UPDATE_SOURCES,c=[];for(const t of s)try{const e=await b(t,o,n,a);return{current:r,latest:e,up_to_date:compareSemver(r,e)>=0,source:t.id,registry:t.registry,errors:c,error:null}}catch(e){c.push({source:t.id,error:e instanceof Error?e.message:String(e)})}return{current:r,latest:null,up_to_date:null,source:null,registry:null,errors:c,error:c.map(t=>`${t.source}: ${t.error}`).join("; ")||"unknown"}}function $(e){for(const r of e){const e=p(r);e&&(console.log(" "+y(r.outdated?t.yellow:t.cyan)(`${r.name}: ${e}`)),r.outdated&&console.log(" "+y(t.gray)(a.t("update.command_hint",{command:d(r.tool)}))))}}export async function updateCommand(e={}){const r=e.localPackage||readLocalPackage();s()||console.log(y(t.gray)(a.t("update.checking")));const o=await checkForUpdate({...e,localPackage:r}),n=await async function(){const t=[];for(const e of m())try{const r=await u(e);r.installed&&!r.blocker&&t.push(r)}catch(t){g.logError(`update: app status ${e}`,t)}return t}();if(s())c({...o,apps:n.map(t=>({tool:t.tool,installed:t.installed,current:t.current,latest:t.latest,outdated:t.outdated,upgraded:!1}))});else{if(console.log(` ${y(t.cyan)(a.t("update.current",{version:o.current}))}`),!o.latest)return console.log(" "+y(t.yellow)(a.t("update.fetch_failed",{error:o.error||"unknown"}))),void $(n);if(console.log(` ${y(t.cyan)(a.t("update.latest",{version:o.latest}))}`),console.log(` ${y(t.cyan)(a.t("update.source",{source:l().updateRegistries.find(t=>t.id===o.source)?.label??o.source??"unknown"}))}`),o.up_to_date)console.log(" "+y(t.green)(a.t("update.up_to_date")));else{const e="npm"===o.source?"":` --registry ${o.registry}`,n=`npm install -g ${r.name}@latest${e}`;console.log(" "+y(t.yellow)(a.t("update.available"))),console.log(" "+y(t.gray)(a.t("update.command_hint",{command:n})))}$(n)}}
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* `vibecli upgrade [tool...]`: no argument = every installed tool vibecli knows how to upgrade (CLIs with an
|
|
3
|
+
* `installSpec`, GUI apps with an `appInstaller` that this machine can serve). An app named explicitly is installed
|
|
4
|
+
* when missing; `--force` reinstalls an app that is already the latest. `--json` prints `{ tools: [...] }`: per app its current / latest version and whether it was upgraded.
|
|
5
|
+
*/
|
|
6
|
+
export declare function upgradeCommand(tools: string[], options?: {
|
|
7
|
+
force?: boolean;
|
|
8
|
+
}): Promise<void>;
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import o from"chalk";import{i18n as r}from"../lib/i18n.js";import{toolManager as
|
|
1
|
+
import o from"chalk";import{appTools as t,getApp as e,upgradeApp as l}from"../lib/app-update.js";import{i18n as r}from"../lib/i18n.js";import{emitJson as n,isJsonMode as i}from"../lib/runtime-options.js";import{toolManager as s}from"../lib/tool-manager.js";import{listAdapters as a}from"../lib/tools/registry.js";import{upgradeTool as p}from"../lib/tool-upgrade.js";export async function upgradeCommand(d,c={}){const u=t(),m=[...a().filter(o=>o.installSpec).map(o=>o.name),...u],f=d.length>0?d:m.filter(o=>u.includes(o)?(o=>{const t=e(o)?.appInstaller;return Boolean(t&&!t.blocker()&&t.installedPath())})(o):s.isToolInstalled(o)),g=f.filter(o=>!m.includes(o));if(g.length>0)return console.error(o.red(r.t("upgrade.unsupported",{tool:g.join(", ")}))),console.error(r.t("upgrade.supported",{tools:m.join(" / ")})),void(process.exitCode=1);if(0===f.length)return void(i()?n({tools:[]}):console.log(r.t("upgrade.nothing_installed",{tools:m.join(" / ")})));let j=0;const b=[];for(const t of f){if(u.includes(t)){const r=e(t)?.displayName??t;i()||console.log(o.bold(`\n${r}`));const n=await l(t,{install:!0,force:c.force}),s=["installed","upgraded","up_to_date","declined"].includes(n.result);s||(j+=1),b.push({...n,ok:s});continue}const r=await p(t);r||(j+=1),b.push({tool:t,ok:r})}i()&&n({tools:b}),j>0&&(process.exitCode=1)}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { AppInstaller, CompanionApp } from './tools/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Installing and upgrading GUI apps from the brand's download mirror: adapters with an `appInstaller` (Claude
|
|
4
|
+
* Desktop) and companion apps that run on a tool's config (ChatGPT for `codex`). The app's own updater stays on; vibecli only offers the mirror's build when the installed copy is
|
|
5
|
+
* older, since the vendor's update server is often unreachable from mainland China.
|
|
6
|
+
*
|
|
7
|
+
* A running app is never closed without someone at a terminal agreeing (user, 2026-10-31): with a terminal and
|
|
8
|
+
* no `--yes` the question is "quit it and upgrade?"; with `--yes`, without a terminal or after "no" it is left
|
|
9
|
+
* running and only the upgrade command is shown. A failed upgrade leaves the old copy in place and is reported,
|
|
10
|
+
* never thrown: the rest of setup goes on.
|
|
11
|
+
*/
|
|
12
|
+
export interface AppStatus {
|
|
13
|
+
tool: string;
|
|
14
|
+
name: string;
|
|
15
|
+
installed: boolean;
|
|
16
|
+
current: string | null;
|
|
17
|
+
latest: string | null;
|
|
18
|
+
outdated: boolean;
|
|
19
|
+
running: boolean;
|
|
20
|
+
/** Why vibecli can't install / upgrade it here (locale key suffix), null when it can. */
|
|
21
|
+
blocker: string | null;
|
|
22
|
+
/** The latest version couldn't be read (offline, mirror down). */
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
export type AppUpgradeOutcome = 'installed' | 'upgraded' | 'up_to_date' | 'not_installed' | 'left_running' | 'declined' | 'offered' | 'failed' | 'unavailable';
|
|
26
|
+
export interface AppUpgradeResult extends AppStatus {
|
|
27
|
+
result: AppUpgradeOutcome;
|
|
28
|
+
upgraded: boolean;
|
|
29
|
+
version_after: string | null;
|
|
30
|
+
reason?: string;
|
|
31
|
+
}
|
|
32
|
+
/** An app vibecli can install / upgrade, and the tool whose config it runs on. */
|
|
33
|
+
export interface AppEntry extends Omit<CompanionApp, 'installedVersion'> {
|
|
34
|
+
appInstaller: AppInstaller;
|
|
35
|
+
installedVersion?(): string | null;
|
|
36
|
+
/** The tool it belongs to: itself for an adapter's own app, `codex` for ChatGPT. */
|
|
37
|
+
tool: string;
|
|
38
|
+
}
|
|
39
|
+
/** Apps vibecli can install / upgrade (on any platform; `blocker()` says whether here). */
|
|
40
|
+
export declare function appTools(): string[];
|
|
41
|
+
/** The app with this id, undefined for anything else. */
|
|
42
|
+
export declare function getApp(name: string): AppEntry | undefined;
|
|
43
|
+
/** Apps that go with these configured tools (Claude Desktop with itself, ChatGPT with codex). */
|
|
44
|
+
export declare function appsForTools(tools: string[]): string[];
|
|
45
|
+
/** Installed / latest versions; the latest is read from the mirror at most once an hour unless `refresh`. */
|
|
46
|
+
export declare function appStatus(tool: string, options?: {
|
|
47
|
+
refresh?: boolean;
|
|
48
|
+
}): Promise<AppStatus>;
|
|
49
|
+
/** From the cache only (menus): no network. */
|
|
50
|
+
export declare function cachedAppStatus(tool: string): AppStatus;
|
|
51
|
+
/** "current x, y available" / "x (latest)" / "not installed"; empty when nothing is known. */
|
|
52
|
+
export declare function appStatusText(status: AppStatus): string;
|
|
53
|
+
export declare function appUpgradeCommand(tool: string): string;
|
|
54
|
+
export interface UpgradeAppOptions {
|
|
55
|
+
/** Install the app when it isn't installed (`vibecli upgrade`, setup after consent). */
|
|
56
|
+
install?: boolean;
|
|
57
|
+
/** Re-read the mirror's version instead of the hour-old cache. */
|
|
58
|
+
refresh?: boolean;
|
|
59
|
+
/** Say nothing when there is nothing to do (setup: only an outdated or missing app is worth a line). */
|
|
60
|
+
quiet?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* An installed copy is only upgraded after a yes at a terminal (setup, user 11-01: an app found installed is
|
|
63
|
+
* offered the upgrade, not overwritten); with `--yes` or without a terminal only the command is shown.
|
|
64
|
+
*/
|
|
65
|
+
askBeforeUpgrade?: boolean;
|
|
66
|
+
/** Reinstall even when the installed copy is already the latest (`vibecli upgrade <app> --force`). */
|
|
67
|
+
force?: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Bring the app to the mirror's latest version: install when missing (`install`), upgrade when older (after a yes
|
|
71
|
+
* with `askBeforeUpgrade`), reinstall with `force`. A running app is only quit after a yes at a terminal (and
|
|
72
|
+
* reopened afterwards); see the module comment.
|
|
73
|
+
*/
|
|
74
|
+
export declare function upgradeApp(tool: string, options?: UpgradeAppOptions): Promise<AppUpgradeResult>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import t from"chalk";import e from"inquirer";import{existsSync as r,mkdirSync as n,readFileSync as a,writeFileSync as o}from"fs";import{join as l}from"path";import{CLI_NAME as p}from"./brand.js";import{configManager as i}from"./config.js";import{i18n as s}from"./i18n.js";import{canPrompt as u,hasExplicitYes as d,isJsonMode as c}from"./runtime-options.js";import{track as f}from"./telemetry.js";import{compareVersions as m}from"./model-registry.js";import{listAdapters as g}from"./tools/registry.js";import{logger as _}from"../utils/logger.js";function y(){return l(i.getConfigDir(),"app-releases.json")}function w(){try{if(!r(y()))return{};const t=JSON.parse(a(y(),"utf-8"));return t&&"object"==typeof t?t:{}}catch{return{}}}function h(t,e){try{n(i.getConfigDir(),{recursive:!0}),o(y(),JSON.stringify({...w(),[t]:e},null,2))}catch(t){_.logError("app-update.writeCache",t)}}function k(){return g().flatMap(t=>[...t.appInstaller?[{name:t.name,displayName:t.displayName,appInstaller:t.appInstaller,installedVersion:t.installedVersion,runningApp:t.runningApp,tool:t.name}]:[],...(t.companionApps??[]).map(e=>({...e,tool:t.name}))])}export function appTools(){return k().map(t=>t.name)}export function getApp(t){return k().find(e=>e.name===t)}export function appsForTools(t){return k().filter(e=>t.includes(e.tool)).map(t=>t.name)}function v(t){const e=getApp(t);if(!e)throw new Error(`no app installer for ${t}`);return e}function b(t,e,r){try{return e()}catch(e){return _.logError(`app-update.${t}`,e),r}}function C(t){const e=v(t),r=e.appInstaller,n=b("installedPath",()=>null!==r.installedPath(),!1);return{tool:t,name:e.displayName,installed:n,current:n?b("installedVersion",()=>e.installedVersion?.()??null,null):null,running:!!n&&b("isRunning",()=>e.runningApp?.isRunning()??!1,!1),blocker:b("blocker",()=>r.blocker(),"unsupported_platform")}}function U(t,e,r){const n=Boolean(t.installed&&t.current&&e&&m(t.current,e)<0);return{...t,latest:e,outdated:n,...r?{error:r}:{}}}export async function appStatus(t,e={}){const r=C(t);if(r.blocker&&"classic_install"!==r.blocker)return U(r,null);const n=w()[t],a=n&&Date.now()-n.checked_at<(n.version?36e5:6e5);if(n&&a&&!e.refresh)return U(r,n.version??null,n.error);try{const e=await v(t).appInstaller.latestVersion();return h(t,{version:e,checked_at:Date.now()}),U(r,e)}catch(e){const a=e instanceof Error?e.message:String(e);return _.logError(`app-update.latest(${t})`,e),h(t,{error:a,checked_at:Date.now()}),U(r,n?.version??null,a)}}export function cachedAppStatus(t){const e=C(t);return U(e,e.blocker&&"classic_install"!==e.blocker?null:w()[t]?.version??null)}export function appStatusText(t){return t.installed?t.outdated?s.t("app_update.outdated",{current:t.current,latest:t.latest}):t.current&&t.latest?s.t("app_update.up_to_date",{current:t.current}):t.current??"":t.latest?s.t("app_update.not_installed",{latest:t.latest}):""}export function appUpgradeCommand(t){return`${p} upgrade ${t}`}function A(t){c()?process.stderr.write(t+"\n"):console.log(t)}async function j(t,r=!0){const{ok:n}=await e.prompt([{type:"confirm",name:"ok",message:t,default:r}]);return n}export async function upgradeApp(e,r={}){const n=Date.now(),a=await appStatus(e,{refresh:r.refresh??!0}),o=a.name,l=(t,r={})=>{const o={...a,result:t,upgraded:"upgraded"===t||"installed"===t,version_after:null,...r};return["up_to_date","unavailable","not_installed","offered"].includes(t)||f(`app-upgrade:${e}`,"failed"===t?"fail":"ok",{duration_ms:Date.now()-n,detail:{result:t,current:a.current,latest:a.latest,...r.reason?{reason:r.reason}:{}}}),o};if(a.blocker)return!r.quiet&&a.installed&&a.outdated&&A(t.yellow(" ! "+s.t("app_update.outdated",{current:a.current,latest:a.latest}))),r.quiet||A(t.yellow(" ! "+s.t(`app_update.blocked_${a.blocker}`,{tool:o,url:v(e).appInstaller.downloadPage,command:appUpgradeCommand(e)}))),l("unavailable",{reason:a.blocker});if(!a.latest)return r.quiet||A(t.yellow(" ! "+s.t("app_update.latest_unknown",{tool:o,reason:a.error??""}))),l("unavailable",{reason:a.error});if(!a.installed&&!r.install)return l("not_installed");const p=Boolean(r.force&&a.installed&&!a.outdated);if(a.installed&&!a.outdated&&!p)return r.quiet||(A(t.green(" √ "+s.t("app_update.already_latest",{tool:o,current:a.current??a.latest}))),A(t.gray(" "+s.t("app_update.force_hint",{command:appUpgradeCommand(e)})))),l("up_to_date");if(p?A(t.yellow(" ! "+s.t("app_update.reinstalling",{tool:o,latest:a.latest,current:a.current??"?"}))):!a.installed||r.askBeforeUpgrade&&!a.running||A(t.yellow(` ! ${o} `+appStatusText(a))),a.installed&&r.askBeforeUpgrade&&!a.running){if(!u()||d())return A(t.gray(" "+s.t("app_update.upgrade_hint",{tool:o,current:a.current??"?",latest:a.latest,command:appUpgradeCommand(e)}))),l("offered");if(!await j(s.t("app_update.upgrade_offer",{tool:o,current:a.current??"?",latest:a.latest})))return A(t.gray(" "+s.t("app_update.declined_hint",{command:appUpgradeCommand(e)}))),l("declined")}let i=!1;if(a.running){if(!u()||d())return A(t.yellow(" ! "+s.t("app_update.running_hint",{tool:o,command:appUpgradeCommand(e)}))),l("left_running");if(!await j(s.t("app_update.offer_quit",{tool:o,latest:a.latest})))return A(t.gray(" "+s.t("app_update.declined_hint",{command:appUpgradeCommand(e)}))),l("declined");const r=v(e).runningApp;if(!r?.quit?.())return A(t.yellow(" ! "+s.t("app_update.quit_failed",{tool:o,command:appUpgradeCommand(e)}))),l("failed",{reason:"quit_failed"});i=!0}try{const{version:r}=await async function(e){const r=v(e).appInstaller,n=!c()&&Boolean(process.stdout.isTTY);let a=-1;try{return await r.install({downloading:n=>A(t.gray(" "+s.t("app_update.downloading",{tool:v(e).displayName,version:n,size:String(r.sizeMb())}))),percent:e=>{!n||e-a<5||(a=e,process.stdout.write(t.gray(`\r ${e}%`)),e>=100&&process.stdout.write("\n"))},verifying:()=>{n&&a>=0&&a<100&&process.stdout.write("\n"),a=100,A(t.gray(" "+s.t("app_update.verifying",{vendor:r.vendor})))},installing:()=>A(t.gray(" "+s.t("app_update.installing")))})}finally{n&&a>=0&&a<100&&process.stdout.write("\n")}}(e);return A(t.green(" √ "+(p?s.t("app_update.reinstalled",{tool:o,version:r}):a.installed?s.t("app_update.upgraded",{tool:o,from:a.current??"?",to:r}):s.t("app_update.installed",{tool:o,version:r})))),i&&!v(e).runningApp?.launch?.()&&A(t.yellow(" ! "+s.t("setup.reopen_hint",{tool:o}))),l(a.installed?"upgraded":"installed",{version_after:r,current:a.current})}catch(r){const n=r instanceof Error?r.message:String(r);return _.logError(`app-update.install(${e})`,r),A(t.yellow(" ! "+(a.installed?s.t("app_update.upgrade_failed",{tool:o,reason:n,current:a.current??"?",command:appUpgradeCommand(e)}):s.t("app_update.install_failed",{tool:o,reason:n,command:appUpgradeCommand(e)})))),i&&v(e).runningApp?.launch?.(),l("failed",{reason:n})}}
|
package/dist/lib/brand.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ export interface Brand {
|
|
|
50
50
|
agy?: string;
|
|
51
51
|
/** Claude Desktop download page for macOS / Windows. */
|
|
52
52
|
claudeDesktop?: string;
|
|
53
|
+
/** ChatGPT desktop app (contains Codex) download page for macOS / Windows. */
|
|
54
|
+
chatgptDesktop?: string;
|
|
53
55
|
};
|
|
54
56
|
/** Claude Code plugin marketplaces tried before Anthropic's GitHub repo. */
|
|
55
57
|
pluginMarketplaces: BrandPluginMarketplace[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawnSync as t}from"child_process";import{closeSync as e,copyFileSync as o,createReadStream as r,createWriteStream as n,existsSync as s,mkdirSync as i,openSync as a,readFileSync as c,readSync as
|
|
1
|
+
import{spawnSync as t}from"child_process";import{closeSync as e,copyFileSync as o,createReadStream as r,createWriteStream as n,existsSync as s,mkdirSync as i,openSync as a,readFileSync as c,readSync as l,readdirSync as f,realpathSync as d,renameSync as p,statSync as u,utimesSync as m,writeFileSync as h}from"fs";import{basename as g,join as b,resolve as y}from"path";import{pipeline as S}from"stream/promises";import*as _ from"@iarna/toml";import{codexHome as v,toolHome as w}from"./tools/types.js";import{CLI_NAME as E}from"./brand.js";import{powerShellEnv as x}from"./powershell-env.js";export{v as codexHome};export function currentCodexProvider(){try{const t=_.parse(c(b(v(),"config.toml"),"utf-8"));return"string"==typeof t.model_provider&&t.model_provider.trim()?t.model_provider.trim():"openai"}catch{return"openai"}}let N=()=>{if("win32"===process.platform)return`${t("powershell.exe",["-NoProfile","-NonInteractive","-Command","(Get-Process -Name codex -ErrorAction SilentlyContinue).Id"],{encoding:"utf-8",windowsHide:!0,env:x()}).stdout??""}`.split(/\s+/).filter(Boolean).map(Number);const e=process.getuid?.(),o=`${t("pgrep",["-x","-i",...void 0===e?[]:["-u",String(e)],"codex"],{encoding:"utf-8"}).stdout??""}`.split(/\s+/).filter(Boolean).map(Number);if("linux"!==process.platform)return o;const r=O(v());return o.filter(t=>{let e;try{e=c(`/proc/${t}/environ`,"utf-8")}catch{return!0}const o=new Map(e.split("\0").map(t=>[t.slice(0,t.indexOf("=")),t.slice(t.indexOf("=")+1)])),n=o.get("CODEX_HOME")?.trim()||(o.get("HOME")?b(o.get("HOME"),".codex"):null);return null===n||O(n)===r})};function O(t){try{return d(t)}catch{return t}}export function setCodexProcessCheckForTests(t){N=t}export function runningCodexPids(){try{return N()}catch{return[]}}function $(t){const o=a(t,"r");try{const t=[],e=Buffer.alloc(65536);for(;;){const r=l(o,e,0,e.length,null);if(r<=0)break;const n=e.subarray(0,r).indexOf(10);if(n>=0){t.push(Buffer.from(e.subarray(0,n)));break}t.push(Buffer.from(e.subarray(0,r)))}return Buffer.concat(t).toString("utf-8")}finally{e(o)}}async function D(t,e,o){const{atime:s,mtime:i}=u(t),a=`${t}.${E}-tmp`,c=n(a);c.write(e),await S(r(t,{start:o}),c),p(a,t),m(t,s,i)}export function codexSqliteHome(){const t=v();try{const e=_.parse(c(b(t,"config.toml"),"utf-8")),o="string"==typeof e.sqlite_home?e.sqlite_home.trim():"";if(o)return"~"===o||o.startsWith("~/")?b(w(),o.slice(1)):y(t,o)}catch{}const e=process.env.CODEX_SQLITE_HOME?.trim();return e?y(e):t}function T(){const t=codexSqliteHome();if(!s(t))return null;const e=f(t).map(t=>/^state_(\d+)\.sqlite$/.exec(t)).filter(t=>!!t).sort((t,e)=>Number(e[1])-Number(t[1]));return e.length>0?b(t,e[0][0]):null}const A={threads:"id",local_thread_catalog:"thread_id"};function B(){const t=b(codexSqliteHome(),"sqlite");return s(t)?f(t).filter(t=>/\.(db|sqlite3?)$/.test(t)).map(e=>b(t,e)).sort():[]}function C(t,e,o){const r=function(t,e){return new Set(t.prepare(`PRAGMA table_info(${e})`).all().map(t=>String(t.name)))}(t,e),n=A[e];if(!r.has(n)||!r.has("model_provider"))return null;const s=r.has("host_id")?" AND host_id = 'local'":"";return t.prepare(`SELECT ${n} AS id, model_provider AS "from" FROM ${e} WHERE COALESCE(model_provider, '') NOT IN ('', ?)${s}`).all(o).map(t=>({id:String(t.id),from:String(t.from)}))}async function H(t){try{return new((await import("node:sqlite")).DatabaseSync)(t)}catch(t){return`node:sqlite unavailable (Node ${process.versions.node}; needs 22.13+): ${t instanceof Error?t.message:String(t)}`}}export const NO_STATE_DB="no state DB";export async function moveSessionsToProvider(t,e={}){const r=function(){const t=[],e=o=>{if(s(o))for(const r of f(o,{withFileTypes:!0})){const n=b(o,r.name);r.isDirectory()?e(n):r.isFile()&&r.name.endsWith(".jsonl")&&t.push(n)}};return e(b(v(),"sessions")),e(b(v(),"archived_sessions")),t}(),n=[];for(const e of r){let o,r;try{o=$(e)}catch{continue}try{r=JSON.parse(o)}catch{continue}const s=r.payload?.model_provider;"session_meta"===r.type&&"string"==typeof s&&s!==t&&(r.payload.model_provider=t,n.push({file:e,from:s,line:JSON.stringify(r),length:Buffer.byteLength(o,"utf-8")}))}const a=[T(),...B()].filter(t=>!!t);let c=a.length>0?null:NO_STATE_DB;const l=[];for(const e of a){const o=await H(e);if("string"==typeof o){c=o;break}const r=[];try{for(const n of Object.keys(A)){const s=C(o,n,t);s&&s.length>0&&r.push({db:e,table:n,rows:s})}}catch{}l.push({path:e,db:o,tables:r})}const d=l.flatMap(t=>t.tables),p=new Set(d.flatMap(t=>t.rows.map(t=>t.id))),u={target:t,scanned:r.length,moved:n.map(({file:t,from:e})=>({file:t,from:e})),dbRows:p.size,dbSkipped:c,backupDir:null},m=()=>l.forEach(t=>t.db.close());if(e.dryRun||0===n.length&&0===d.length)return m(),u;const y=b(v(),"backups",`${E}-sessions-${(new Date).toISOString().replace(/[:.]/g,"-")}`);i(y,{recursive:!0}),l.forEach(({path:t,tables:e},r)=>{if(0!==e.length)for(const e of["","-wal","-shm"])s(t+e)&&o(t+e,b(y,`${r}-${g(t)}${e}`))});const S={target:t,moved:u.moved,tables:d};h(b(y,"manifest.json"),JSON.stringify(S,null,2)+"\n");for(const t of n)await D(t.file,t.line,t.length);for(const{db:e,tables:o}of l)for(const{table:r,rows:n}of o){const o=e.prepare(`UPDATE ${r} SET model_provider = ? WHERE ${A[r]} = ? AND model_provider = ?`);for(const{id:e,from:r}of n)o.run(t,e,r)}return m(),u.backupDir=y,u}export async function undoSessionMove(t){const e=JSON.parse(c(b(t,"manifest.json"),"utf-8"));let o=0;for(const{file:t,from:r}of e.moved){if(!s(t))continue;const e=$(t),n=JSON.parse(e);n.payload&&(n.payload.model_provider=r,await D(t,JSON.stringify(n),Buffer.byteLength(e,"utf-8")),o+=1)}const r=e.tables??(e.db&&e.threads?[{db:e.db,table:"threads",rows:e.threads}]:[]),n=new Set;for(const{db:t,table:o,rows:i}of r){if(!s(t)||0===i.length||!A[o])continue;const r=await H(t);if("string"==typeof r)continue;const a=r.prepare(`UPDATE ${o} SET model_provider = ? WHERE ${A[o]} = ? AND model_provider = ?`);for(const{id:t,from:o}of i)Number(a.run(o,t,e.target).changes)>0&&n.add(t);r.close()}return{files:o,dbRows:n.size}}
|
package/dist/lib/i18n.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readFileSync as t,existsSync as e,readdirSync as s}from"fs";import{join as o,dirname as r}from"path";import{fileURLToPath as a}from"url";import{logger as n}from"../utils/logger.js";import{brandTokens as l}from"./brand.js";class c{static instance;currentLocale="en_US";translations=new Map;fallbackLocale="en_US";localesDir;constructor(){const t=a(import.meta.url),e=r(t);this.localesDir=o(e,"..","locales"),this.loadTranslations(),this.loadSavedLocale()}static getInstance(){return c.instance||(c.instance=new c),c.instance}loadTranslations(){try{if(!e(this.localesDir))return void n.warn(`Locales directory not found at ${this.localesDir}`);const r=s(this.localesDir).filter(t=>t.endsWith(".json"));if(0===r.length)return void n.warn("No locale files found in locales directory");for(const e of r){const s=e.replace(".json",""),r=o(this.localesDir,e);try{const e=t(r,"utf-8"),o=JSON.parse(e);this.translations.set(s,o)}catch(t){n.warn(`Failed to load locale file ${e}:`,t)}}const a=process.env.LANG||process.env.LC_ALL||process.env.LC_MESSAGES;if(a){const t=a.split(".")[0].replace("_","-");if(this.translations.has(t))this.currentLocale=t;else{const e=t.split("-")[0],s=Array.from(this.translations.keys()).find(t=>t.startsWith(e+"_"));s?this.currentLocale=s:"zh"===e?this.currentLocale="zh_CN":"en"===e&&(this.currentLocale="en_US")}}}catch(t){n.warn("Failed to load translations:",t)}}setLocale(t){this.translations.has(t)?(this.currentLocale=t,this.saveLocale()):n.warn(`Locale '${t}' not supported, falling back to '${this.currentLocale}'`)}getLocale(){return this.currentLocale}getAvailableLocales(){return Array.from(this.translations.keys())}translate(t,e){const s=t.split(".");let o=this.translations.get(this.currentLocale);for(const e of s){if(!o||"object"!=typeof o||!(e in o)){o=this.translations.get(this.fallbackLocale);for(const e of s){if(!o||"object"!=typeof o||!(e in o))return t;o=o[e]}break}o=o[e]}if("string"!=typeof o)return t;const r=l(this.currentLocale);return o=o.replace(/\{\{(\w+)\}\}/g,(t,e)=>r[e]??t),e?o.replace(/\{\{(\w+)\}\}/g,(t,s)=>e[s]
|
|
1
|
+
import{readFileSync as t,existsSync as e,readdirSync as s}from"fs";import{join as o,dirname as r}from"path";import{fileURLToPath as a}from"url";import{logger as n}from"../utils/logger.js";import{brandTokens as l}from"./brand.js";class c{static instance;currentLocale="en_US";translations=new Map;fallbackLocale="en_US";localesDir;constructor(){const t=a(import.meta.url),e=r(t);this.localesDir=o(e,"..","locales"),this.loadTranslations(),this.loadSavedLocale()}static getInstance(){return c.instance||(c.instance=new c),c.instance}loadTranslations(){try{if(!e(this.localesDir))return void n.warn(`Locales directory not found at ${this.localesDir}`);const r=s(this.localesDir).filter(t=>t.endsWith(".json"));if(0===r.length)return void n.warn("No locale files found in locales directory");for(const e of r){const s=e.replace(".json",""),r=o(this.localesDir,e);try{const e=t(r,"utf-8"),o=JSON.parse(e);this.translations.set(s,o)}catch(t){n.warn(`Failed to load locale file ${e}:`,t)}}const a=process.env.LANG||process.env.LC_ALL||process.env.LC_MESSAGES;if(a){const t=a.split(".")[0].replace("_","-");if(this.translations.has(t))this.currentLocale=t;else{const e=t.split("-")[0],s=Array.from(this.translations.keys()).find(t=>t.startsWith(e+"_"));s?this.currentLocale=s:"zh"===e?this.currentLocale="zh_CN":"en"===e&&(this.currentLocale="en_US")}}}catch(t){n.warn("Failed to load translations:",t)}}setLocale(t){this.translations.has(t)?(this.currentLocale=t,this.saveLocale()):n.warn(`Locale '${t}' not supported, falling back to '${this.currentLocale}'`)}getLocale(){return this.currentLocale}getAvailableLocales(){return Array.from(this.translations.keys())}translate(t,e){const s=t.split(".");let o=this.translations.get(this.currentLocale);for(const e of s){if(!o||"object"!=typeof o||!(e in o)){o=this.translations.get(this.fallbackLocale);for(const e of s){if(!o||"object"!=typeof o||!(e in o))return t;o=o[e]}break}o=o[e]}if("string"!=typeof o)return t;const r=l(this.currentLocale);return o=o.replace(/\{\{(\w+)\}\}/g,(t,e)=>r[e]??t),e?o.replace(/\{\{(\w+)\}\}/g,(t,s)=>e[s]??t):o}t(t,e){return this.translate(t,e)}saveLocale(){}loadSavedLocale(){}loadFromConfig(t){this.translations.has(t)&&(this.currentLocale=t)}}export function detectSystemLang(){const t=process.env.LC_ALL||process.env.LC_MESSAGES||process.env.LANG||process.env.LANGUAGE||"";let e="";try{e=Intl.DateTimeFormat().resolvedOptions().locale||""}catch{}return`${t} ${e}`.toLowerCase().split(/[\s:;,]+/).some(t=>"zh"===t||t.startsWith("zh-")||t.startsWith("zh_"))?"zh_CN":"en_US"}export{c as I18n};export const i18n=c.getInstance();
|
package/dist/lib/post-apply.d.ts
CHANGED
|
@@ -14,4 +14,8 @@ export declare function runPendingElevations(tools: string[]): Promise<void>;
|
|
|
14
14
|
* terminal says yes: with `--yes` or without a terminal it is left running and the
|
|
15
15
|
* last line says to reopen it (user, 10-31: a script must not close someone's app).
|
|
16
16
|
*/
|
|
17
|
-
export declare function postApplyPrompts(tools: string[]
|
|
17
|
+
export declare function postApplyPrompts(tools: string[], options?: {
|
|
18
|
+
apps?: {
|
|
19
|
+
install: boolean;
|
|
20
|
+
};
|
|
21
|
+
}): Promise<void>;
|
package/dist/lib/post-apply.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import o from"chalk";import t from"inquirer";import{i18n as n}from"./i18n.js";import{canPrompt as e,hasExplicitYes as
|
|
1
|
+
import o from"chalk";import t from"inquirer";import{i18n as n}from"./i18n.js";import{canPrompt as e,hasExplicitYes as r,shouldAutoConfirm as i}from"./runtime-options.js";import{toolManager as s}from"./tool-manager.js";import{getAdapter as a}from"./tools/registry.js";import{upgradeTool as l}from"./tool-upgrade.js";import{appsForTools as p,upgradeApp as f}from"./app-update.js";import{logger as c}from"../utils/logger.js";async function u(o){const{ok:n}=await t.prompt([{type:"confirm",name:"ok",message:o,default:!0}]);return n}export async function runPendingElevations(t){const r=e();for(const e of t){const t=a(e)?.pendingElevation?.();if(!t)continue;if(!(i()||r&&await u(t.prompt)))continue;const s=a(e)?.displayName??e;console.log(o.gray(" "+n.t("setup.elevation_running"))),console.log(t.run()?o.green(" √ "+n.t("setup.elevation_done",{tool:s})):o.yellow(" ! "+n.t("setup.elevation_failed",{tool:s})))}}export async function postApplyPrompts(t,i={}){const m=new Set;for(const o of i.apps?p(t):[])try{const t=await f(o,{install:i.apps.install,quiet:!0,askBeforeUpgrade:!0});t.upgraded&&t.running&&m.add(o)}catch(t){c.logError(`postApplyPrompts.upgradeApp(${o})`,t)}for(const n of t){const t=await(a(n)?.prepareRuntime?.())??[];for(const n of t)console.log("action"===n.kind?o.yellow(" ! "+n.text):o.green(" √ "+n.text))}await runPendingElevations(t);const g=e();for(const n of t){let t;try{t=await(a(n)?.followUp?.())}catch(o){c.logError(`postApplyPrompts.followUp(${n})`,o);continue}if(t)if("run"in t&&(r()||g))if(r()||await u(t.prompt))for(const n of await t.run())console.log("action"===n.kind?o.yellow(" ! "+n.text):o.green(" √ "+n.text));else t.decline();else console.log(o.yellow(" ! "+t.hint))}const d=r(),y=g||d?t.filter(o=>a(o)?.installSpec&&s.outdatedVersion(o)):[];if(y.length>0){const o=y.map(o=>a(o)?.displayName??o).join("、");if(d||await u(n.t("setup.offer_upgrade",{tools:o})))for(const o of y)await l(o)}for(const e of t){const t=a(e);if(m.has(e)||!t?.runningApp?.isRunning())continue;if(d||!g){console.log(o.yellow(" ! "+n.t("setup.reopen_hint",{tool:t.displayName})));continue}if(!await u(n.t("setup.offer_restart",{tool:t.displayName})))continue;const r=t.runningApp.restart();console.log(r?o.green(" √ "+n.t("setup.restarted",{tool:t.displayName})):o.yellow(" ! "+n.t("setup.restart_failed",{tool:t.displayName})))}}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment for a child `powershell.exe` (Windows PowerShell 5.1).
|
|
3
|
+
*
|
|
4
|
+
* Started from a PowerShell 7 terminal, node inherits pwsh 7's `PSModulePath` (`Documents\PowerShell\Modules`,
|
|
5
|
+
* `Program Files\PowerShell\Modules`, `…\pwsh\…\Modules`). 5.1 then finds PS7's copies of built-in modules first
|
|
6
|
+
* and can't load them: `Get-AuthenticodeSignature` fails with CouldNotAutoloadMatchingModule while the script still
|
|
7
|
+
* exits 0 (2026-11-01, user's Windows 11: Claude Desktop upgrade reported a bad signature). pwsh fixes the variable
|
|
8
|
+
* itself when it starts powershell.exe; node doesn't. Without the variable 5.1 computes its own default.
|
|
9
|
+
*/
|
|
10
|
+
export declare function powerShellEnv(base?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
11
|
+
/** Whether `command` starts Windows PowerShell (`powershell`, `powershell.exe`, with or without a path). */
|
|
12
|
+
export declare function isWindowsPowerShell(command: string): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function powerShellEnv(e=process.env){const o={};for(const[t,r]of Object.entries(e))"psmodulepath"!==t.toLowerCase()&&(o[t]=r);return o}export function isWindowsPowerShell(e){return/(^|[\\/])powershell(\.exe)?$/i.test(e.trim())}
|
package/dist/lib/program.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Command as e,Option as o}from"commander";import{readFileSync as s}from"fs";import{join as t,dirname as n}from"path";import{fileURLToPath as a}from"url";import{i18n as i}from"./i18n.js";import{wizard as r}from"./wizard.js";import{SUPPORTED_TOOLS as c}from"./tool-manager.js";import{DEFAULT_BASE_URL as l}from"./config.js";import{attachCommandHelp as p,helpConfiguration as m}from"./cli-help.js";import{langCommand as u,authCommand as d,doctorCommand as f,configCommand as g,statusCommand as x,refreshCommand as h}from"../commands/index.js";import{logsCommand as y}from"../commands/logs.js";import{completionCommand as $}from"../commands/completion.js";import{benchCommand as b}from"../commands/bench.js";import{updateCommand as k}from"../commands/update.js";import{upgradeCommand as _}from"../commands/upgrade.js";import{codexSessionsCommand as w}from"../commands/codex-sessions.js";import{sessionsExportCommand as v,sessionsListCommand as j,sessionsResumeCommand as O,sessionsShowCommand as S}from"../commands/sessions.js";import{setupCommand as A,DEDICATED_KEYS as E}from"../commands/setup.js";import{baseCommand as G}from"../commands/base.js";import{usageError as z}from"./errors.js";import{requireTerminal as C}from"./confirm.js";import{brand as R,brandEnv as B,CLI_NAME as I}from"./brand.js";const L=(R().gatewayAddresses[1]??R().gatewayAddresses[0]).url,N=(R().gatewayAddresses[2]??R().gatewayAddresses[0]).url;function P(e,o){return i.t(`help.${e}`,o)}function T(e,o){return{command:e,note:P(o)}}function U(e){const o=P(e);return o===`help.${e}`?"":o}function H(e,o=[]){return{when:U(`${e}.when`),prerequisites:U(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>T(e,o))}}function K(e){return e.helpCommand("help [command]",P("help_command"))}export function buildProgram(){const R=new e;R.name(`${I}`).summary(P("root.summary")).description(P("root.description")).configureHelp(m()).allowExcessArguments(!0).optionsGroup(P("group.global_options")).helpOption("-h, --help",P("global.help")).version(function(){try{const e=n(a(import.meta.url));return JSON.parse(s(t(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",P("global.version")).option("--base <url>",P("global.base")).option("--non-interactive",P("global.non_interactive")).option("--json",P("global.json")).option("-y, --yes",P("global.yes")).option("--dry-run",P("global.dry_run")).option("--no-color",P("global.no_color")),R.configureOutput({writeErr:()=>{},outputError:()=>{}}),R.showSuggestionAfterError(),R.exitOverride(e=>{throw e}),R.commandsGroup(P("group.configure"));const U=R.command("setup").summary(P("setup.summary")).description(P("setup.description")).option("--key <key>",P("setup.opt.key"));for(const e of E){const s=new o(`--${e.option} <key>`,P(`setup.opt.${e.option}`));e.hidden&&s.hideHelp(),U.addOption(s)}U.option("--1m",P("setup.opt.one_m")).option("--no-1m",P("setup.opt.no_one_m")).option("--claude-official <on|off>",P("setup.opt.claude_official")).option("--desktop-registry <on|off>",P("setup.opt.desktop_registry")).option("--force",P("setup.opt.force")).option("--install",P("setup.opt.install")).option("--no-install",P("setup.opt.no_install")).option("--all",P("setup.opt.all")).action(async e=>{e.key||E.some(o=>e[o.option])||(e.key=B("SETUP_KEY")?.trim()||void 0,e.fromInstaller=Boolean(e.key));const o=Boolean(e.key||E.some(o=>e[o.option])),s=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,t=i.t("errors.key_placeholder");if(!o&&!s)throw z(i.t("setup.usage"),`${I} setup --key ${t}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw z(i.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),`${I} setup --claude-official on|off`,"invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw z(i.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),`${I} setup --desktop-registry on|off`,"invalid_value");await A({key:e.key,...Object.fromEntries(E.map(o=>[o.option,e[o.option]])),all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,desktopRegistry:e.desktopRegistry,force:e.force,install:e.install,fromInstaller:e.fromInstaller})}),p(U,{...H("setup",[[`${I} init`,"setup.alt.init"],[`${I} config <tool>`,"setup.alt.config"],[`${I} auth <key>`,"setup.alt.auth"]]),sections:[{title:P("setup.autodetect_title"),rows:[["Claude",P("setup.autodetect.claude")],["GPT",P("setup.autodetect.gpt")],["Grok",P("setup.autodetect.grok")],["Gemini",P("setup.autodetect.gemini")]]}],examples:[T(`${I} setup --key sk-xxx`,"setup.ex.key"),T(`${I} setup --install --key sk-xxx`,"setup.ex.install"),T(`${I} setup --claudekey sk-a --codexkey sk-b --agykey sk-g`,"setup.ex.split"),T(`${I} setup --force --key sk-xxx`,"setup.ex.force"),T(`${I} setup --base ${L} --key sk-xxx`,"setup.ex.base")]});const M=R.command("init").summary(P("init.summary")).description(P("init.description")).action(async()=>{C(),await r.runFirstTimeSetup()});p(M,{...H("init",[[`${I} setup --key <key>`,"init.alt.setup"],[`${I}`,"init.alt.menu"]]),examples:[T(`${I} init`,"init.ex.run"),T(`${I} init --base ${L}`,"init.ex.base"),T(`${I}`,"init.ex.menu")]});const q=R.command("auth").summary(P("auth.summary")).description(P("auth.description")).argument("[token]",P("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});K(q);const D=q.command("revoke").description(P("auth.revoke")).action(async()=>{await d(["revoke"])});p(D,{examples:[T(`${I} auth revoke`,"auth.ex.revoke_ask"),T(`${I} auth revoke --yes`,"auth.ex.revoke")]});const F=q.command("reload <tool>").description(P("auth.reload")).action(async e=>{await d(["reload",e])});p(F,{examples:[T(`${I} auth reload claude-code`,"auth.ex.reload"),T(`${I} auth reload claude-code --json`,"auth.ex.reload_json")]}),p(q,{...H("auth",[[`${I} setup --key <key>`,"auth.alt.setup"]]),examples:[T(`${I} auth`,"auth.ex.prompt"),T(`${I} auth sk-xxx --non-interactive`,"auth.ex.save"),T(`${I} auth revoke --yes`,"auth.ex.revoke"),T(`${I} auth reload claude-code`,"auth.ex.reload")]});const J=R.command("config").summary(P("config.summary")).description(P("config.description")).argument("[args...]",P("config.arg.args")).option("-f, --force",P("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await g(o.force?[...e,"--force"]:e)});p(J,{...H("config",[[`${I} setup --force --key <key>`,"config.alt.setup"],[`${I} status`,"config.alt.status"]]),sections:[{title:P("config.subcommands_title"),rows:[["<tool>",P("config.sub.tool")],["<tool> --force",P("config.sub.tool_force")],["<tool> --non-interactive",P("config.sub.tool_non_interactive")],["<tool> remove",P("config.sub.tool_remove")],["<tool> restore",P("config.sub.tool_restore")],["<tool> backups",P("config.sub.tool_backups")],["<tool> clear-model",P("config.sub.tool_clear_model")],["tool-model list",P("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",P("config.sub.tool_model_set")],["tool-model clear <tool>",P("config.sub.tool_model_clear")],["profile list",P("config.sub.profile_list")],["profile create <name>",P("config.sub.profile_create")],["profile use <name>",P("config.sub.profile_use")],["profile delete <name>",P("config.sub.profile_delete")],["preset list",P("config.sub.preset_list")],["preset save <name>",P("config.sub.preset_save")],["preset use <name>",P("config.sub.preset_use")],["preset delete <name>",P("config.sub.preset_delete")],["backup list",P("config.sub.backup_list")],["backup create [label]",P("config.sub.backup_create")],["backup restore <name>",P("config.sub.backup_restore")]]},{title:P("config.tools_title"),rows:Object.values(c).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[T(`${I} config codex`,"config.ex.menu"),T(`${I} config claude-code --force`,"config.ex.force"),T(`${I} config tool-model set codex gpt-6-astra`,"config.ex.tool_model"),T(`${I} config profile create work`,"config.ex.profile"),T(`${I} config codex remove`,"config.ex.remove")]});const Y=R.command("base").summary(P("base.summary")).description(P("base.description")).argument("[target]",P("base.arg.target")).action(async e=>{await G(e)});p(Y,{...H("base",[[`${I} doctor`,"base.alt.doctor"],[`${I} bench`,"base.alt.bench"]]),sections:[{title:P("base.targets_title"),rows:[[P("base.target.none_term"),P("base.target.none")],[P("base.target.index_term"),P("base.target.index")],[P("base.target.url_term"),P("base.target.url")],["auto",P("base.target.auto")],["default",P("base.target.default",{url:l})]]}],examples:[T(`${I} base`,"base.ex.list"),T(`${I} base auto`,"base.ex.auto"),T(`${I} base 2`,"base.ex.index"),T(`${I} base ${L}`,"base.ex.url"),T(`${I} base default`,"base.ex.default")]}),R.commandsGroup(P("group.diagnose"));const Q=R.command("status").summary(P("status.summary")).description(P("status.description")).action(async()=>{await x()});p(Q,{...H("status",[[`${I} doctor`,"status.alt.doctor"]]),examples:[T(`${I} status`,"status.ex.show"),T(`${I} status --json`,"status.ex.json")]});const V=R.command("doctor").summary(P("doctor.summary")).description(P("doctor.description")).option("--deep",P("doctor.opt.deep")).option("--report",P("doctor.opt.report")).action(async e=>{await f({deep:e.deep,report:e.report})});p(V,{...H("doctor",[[`${I} base auto`,"doctor.alt.base"],[`${I} logs tail`,"doctor.alt.logs"]]),examples:[T(`${I} doctor`,"doctor.ex.run"),T(`${I} doctor --deep`,"doctor.ex.deep"),T(`${I} doctor --report`,"doctor.ex.report")]});const W=R.command("bench").summary(P("bench.summary")).description(P("bench.description")).option("--samples <n>",P("bench.opt.samples"),"5").option("--stream",P("bench.opt.stream")).option("--model <model>",P("bench.opt.model")).action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),e.stream&&o.push("--stream"),e.model&&o.push("--model",e.model),await b(o)});p(W,{...H("bench",[[`${I} base`,"bench.alt.base"]]),examples:[T(`${I} bench`,"bench.ex.run"),T(`${I} bench --samples 3`,"bench.ex.samples"),T(`${I} bench --stream`,"bench.ex.stream"),T(`${I} bench --stream --model gpt-6-astra`,"bench.ex.stream_model"),T(`${I} bench --json`,"bench.ex.json")]});const X=R.command("logs").summary(P("logs.summary")).description(P("logs.description")).argument("[action]",P("logs.arg.action")).argument("[file]",P("logs.arg.file")).action(async(e,o)=>{const s=[];e&&s.push(e),o&&s.push(o),await y(s)});p(X,{...H("logs",[[`${I} doctor`,"logs.alt.doctor"]]),sections:[{title:P("logs.actions_title"),rows:[["list",P("logs.action.list")],["tail [file]",P("logs.action.tail")],["path",P("logs.action.path")]]}],examples:[T(`${I} logs`,"logs.ex.list"),T(`${I} logs tail`,"logs.ex.tail"),T(`${I} logs path`,"logs.ex.path")]}),R.commandsGroup(P("group.maintain"));const Z=R.command("upgrade").summary(P("upgrade.summary")).description(P("upgrade.description")).argument("[tools...]",P("upgrade.arg.tools")).action(async(e=[])=>{await _(e)});p(Z,{...H("upgrade",[[`${I} update`,"upgrade.alt.update"]]),examples:[T(`${I} upgrade`,"upgrade.ex.all"),T(`${I} upgrade claude-code`,"upgrade.ex.one"),T(`${I} upgrade codex agy`,"upgrade.ex.many")]});const ee=R.command("refresh").summary(P("refresh.summary")).description(P("refresh.description")).action(async()=>{await h()});p(ee,{...H("refresh",[[`${I} setup --key ${i.t("errors.key_placeholder")}`,"refresh.alt.setup"]]),examples:[T(`${I} refresh`,"refresh.ex.run"),T(`${I} refresh --base ${N}`,"refresh.ex.base")]});const oe=R.command("update").summary(P("update.summary")).description(P("update.description")).action(async()=>{await k()});p(oe,{...H("update",[[`${I} upgrade`,"update.alt.upgrade"]]),examples:[T(`${I} update`,"update.ex.check"),T(`${I} update --json`,"update.ex.json")]});const se=R.command("codex").summary(P("codex.summary")).description(P("codex.description"));K(se);const te=se.command("sessions").summary(P("codex_sessions.summary")).description(P("codex_sessions.description")).option("--to <provider>",P("codex_sessions.opt.to")).option("--undo <dir>",P("codex_sessions.opt.undo")).action(async e=>{await w(e)});p(se,{...H("codex"),examples:[T(`${I} codex sessions`,"codex_sessions.ex.move"),T(`${I} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]}),p(te,{...H("codex_sessions",[[`${I} codex sessions --undo <dir>`,"codex_sessions.alt.undo"]]),examples:[T(`${I} codex sessions`,"codex_sessions.ex.move"),T(`${I} codex sessions --to custom`,"codex_sessions.ex.to"),T(`${I} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]});const ne=R.command("sessions").summary(P("sessions.summary")).description(P("sessions.description"));K(ne);const ae=ne.command("list",{isDefault:!0}).description(P("sessions.list")).option("--tool <tool>",P("sessions.opt.tool")).option("--dir <path>",P("sessions.opt.dir")).option("--here",P("sessions.opt.here")).option("-n, --limit <count>",P("sessions.opt.limit")).option("--all",P("sessions.opt.all")).action(async e=>{await j(e)}),ie=ne.command("show <id>").description(P("sessions.show")).option("-m, --messages <count>",P("sessions.opt.messages")).action(async(e,o)=>{await S(e,o)}),re=ne.command("resume <id>").description(P("sessions.resume")).option("--run",P("sessions.opt.run")).action(async(e,o)=>{await O(e,o)}),ce=ne.command("export <ids...>").description(P("sessions.export")).option("-o, --output <dir>",P("sessions.opt.output")).option("--tools",P("sessions.opt.tools")).action(async(e,o)=>{await v(e,o)});p(ae,{examples:[T(`${I} sessions list`,"sessions.ex.list"),T(`${I} sessions list --tool codex`,"sessions.ex.codex"),T(`${I} sessions list --here --all`,"sessions.ex.here"),T(`${I} sessions list --json`,"sessions.ex.json")]}),p(ie,{examples:[T(`${I} sessions show 01a0f5fe`,"sessions.ex.show"),T(`${I} sessions show 01a0f5fe -m 20`,"sessions.ex.show_more")]}),p(re,{examples:[T(`${I} sessions resume 01a0f5fe`,"sessions.ex.resume_print"),T(`${I} sessions resume 01a0f5fe --run`,"sessions.ex.resume")]}),p(ce,{examples:[T(`${I} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export"),T(`${I} sessions export 01a0f5fe -o ./sessions --tools`,"sessions.ex.export_tools")]}),p(ne,{...H("sessions",[[`${I} codex sessions`,"sessions.alt.codex_sessions"]]),examples:[T(`${I} sessions`,"sessions.ex.list"),T(`${I} sessions --tool codex --here`,"sessions.ex.here"),T(`${I} sessions show 01a0f5fe`,"sessions.ex.show"),T(`${I} sessions resume 01a0f5fe --run`,"sessions.ex.resume"),T(`${I} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export")]});const le=R.command("lang").summary(P("lang.summary")).description(P("lang.description"));K(le);const pe=le.command("show").description(P("lang.show")).action(async()=>{await u(["show"])}),me=le.command("set <locale>").description(P("lang.set")).action(async e=>{await u(["set",e])}),ue=[T(`${I} lang show`,"lang.ex.show"),T(`${I} lang set en_US`,"lang.ex.set_en"),T(`${I} lang set zh_CN`,"lang.ex.set_zh")];p(le,{...H("lang",[[`${I} enter lang`,"lang.alt.enter"]]),examples:ue}),p(pe,{examples:[ue[0],T(`${I} lang show --json`,"lang.ex.show_json")]}),p(me,{examples:ue.slice(1)});const de=R.command("completion").summary(P("completion.summary")).description(P("completion.description")).argument("<shell>",P("completion.arg.shell")).action(async e=>{await $([e])});p(de,{...H("completion"),examples:[T(`${I} completion bash > ~/.${I}-completion.bash`,"completion.ex.bash"),T(`${I} completion zsh > ~/.${I}-completion.zsh`,"completion.ex.zsh"),T(`${I} completion fish > ~/.config/fish/completions/${I}.fish`,"completion.ex.fish")]});const fe=R.command("enter").summary(P("enter.summary")).description(P("enter.description")).argument("[option]",P("enter.arg.option")).action(async e=>{if(e&&!["lang","language","apikey","api-key","models"].includes(e)||C(),e)switch(e){case"lang":case"language":await r.configLanguage();break;case"apikey":case"api-key":await r.configApiKey();break;case"models":await r.configModels();break;default:await g([e])}else await r.run()});p(fe,{...H("enter",[[`${I}`,"enter.alt.menu"],[`${I} config <tool>`,"enter.alt.config"]]),sections:[{title:P("enter.options_title"),rows:[[P("enter.option.none_term"),P("enter.option.none")],["lang",P("enter.option.lang")],["apikey",P("enter.option.apikey")],["models",P("enter.option.models")],["<tool>",P("enter.option.tool")]]}],examples:[T(`${I} enter`,"enter.ex.menu"),T(`${I} enter models`,"enter.ex.models"),T(`${I} enter codex`,"enter.ex.tool")]}),K(R),R.action(async()=>{C(),await r.run()}),p(R,{examples:[T(`${I}`,"root.ex.menu"),T(`${I} setup --key sk-xxx`,"root.ex.setup"),T(`${I} doctor`,"root.ex.doctor"),T(`${I} base auto`,"root.ex.base"),T(`${I} config codex`,"root.ex.config")]});const ge=e=>{for(const o of e.commands)o.helpOption("-h, --help",P("global.help")),ge(o)};return ge(R),R}
|
|
1
|
+
import{Command as e,Option as o}from"commander";import{readFileSync as s}from"fs";import{join as t,dirname as n}from"path";import{fileURLToPath as a}from"url";import{i18n as i}from"./i18n.js";import{wizard as r}from"./wizard.js";import{SUPPORTED_TOOLS as c}from"./tool-manager.js";import{DEFAULT_BASE_URL as l}from"./config.js";import{attachCommandHelp as p,helpConfiguration as m}from"./cli-help.js";import{langCommand as u,authCommand as d,doctorCommand as f,configCommand as g,statusCommand as x,refreshCommand as h}from"../commands/index.js";import{logsCommand as y}from"../commands/logs.js";import{completionCommand as $}from"../commands/completion.js";import{benchCommand as b}from"../commands/bench.js";import{updateCommand as k}from"../commands/update.js";import{upgradeCommand as _}from"../commands/upgrade.js";import{codexSessionsCommand as w}from"../commands/codex-sessions.js";import{sessionsExportCommand as v,sessionsListCommand as j,sessionsResumeCommand as O,sessionsShowCommand as S}from"../commands/sessions.js";import{setupCommand as A,DEDICATED_KEYS as E}from"../commands/setup.js";import{baseCommand as G}from"../commands/base.js";import{usageError as z}from"./errors.js";import{requireTerminal as C}from"./confirm.js";import{brand as R,brandEnv as B,CLI_NAME as I}from"./brand.js";const L=(R().gatewayAddresses[1]??R().gatewayAddresses[0]).url,N=(R().gatewayAddresses[2]??R().gatewayAddresses[0]).url;function P(e,o){return i.t(`help.${e}`,o)}function T(e,o){return{command:e,note:P(o)}}function U(e){const o=P(e);return o===`help.${e}`?"":o}function H(e,o=[]){return{when:U(`${e}.when`),prerequisites:U(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>T(e,o))}}function K(e){return e.helpCommand("help [command]",P("help_command"))}export function buildProgram(){const R=new e;R.name(`${I}`).summary(P("root.summary")).description(P("root.description")).configureHelp(m()).allowExcessArguments(!0).optionsGroup(P("group.global_options")).helpOption("-h, --help",P("global.help")).version(function(){try{const e=n(a(import.meta.url));return JSON.parse(s(t(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",P("global.version")).option("--base <url>",P("global.base")).option("--non-interactive",P("global.non_interactive")).option("--json",P("global.json")).option("-y, --yes",P("global.yes")).option("--dry-run",P("global.dry_run")).option("--no-color",P("global.no_color")),R.configureOutput({writeErr:()=>{},outputError:()=>{}}),R.showSuggestionAfterError(),R.exitOverride(e=>{throw e}),R.commandsGroup(P("group.configure"));const U=R.command("setup").summary(P("setup.summary")).description(P("setup.description")).option("--key <key>",P("setup.opt.key"));for(const e of E){const s=new o(`--${e.option} <key>`,P(`setup.opt.${e.option}`));e.hidden&&s.hideHelp(),U.addOption(s)}U.option("--1m",P("setup.opt.one_m")).option("--no-1m",P("setup.opt.no_one_m")).option("--claude-official <on|off>",P("setup.opt.claude_official")).option("--desktop-registry <on|off>",P("setup.opt.desktop_registry")).option("--force",P("setup.opt.force")).option("--install",P("setup.opt.install")).option("--no-install",P("setup.opt.no_install")).option("--all",P("setup.opt.all")).action(async e=>{e.key||E.some(o=>e[o.option])||(e.key=B("SETUP_KEY")?.trim()||void 0,e.fromInstaller=Boolean(e.key));const o=Boolean(e.key||E.some(o=>e[o.option])),s=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,t=i.t("errors.key_placeholder");if(!o&&!s)throw z(i.t("setup.usage"),`${I} setup --key ${t}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw z(i.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),`${I} setup --claude-official on|off`,"invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw z(i.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),`${I} setup --desktop-registry on|off`,"invalid_value");await A({key:e.key,...Object.fromEntries(E.map(o=>[o.option,e[o.option]])),all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,desktopRegistry:e.desktopRegistry,force:e.force,install:e.install,fromInstaller:e.fromInstaller})}),p(U,{...H("setup",[[`${I} init`,"setup.alt.init"],[`${I} config <tool>`,"setup.alt.config"],[`${I} auth <key>`,"setup.alt.auth"]]),sections:[{title:P("setup.autodetect_title"),rows:[["Claude",P("setup.autodetect.claude")],["GPT",P("setup.autodetect.gpt")],["Grok",P("setup.autodetect.grok")],["Gemini",P("setup.autodetect.gemini")]]}],examples:[T(`${I} setup --key sk-xxx`,"setup.ex.key"),T(`${I} setup --install --key sk-xxx`,"setup.ex.install"),T(`${I} setup --claudekey sk-a --codexkey sk-b --agykey sk-g`,"setup.ex.split"),T(`${I} setup --force --key sk-xxx`,"setup.ex.force"),T(`${I} setup --base ${L} --key sk-xxx`,"setup.ex.base")]});const M=R.command("init").summary(P("init.summary")).description(P("init.description")).action(async()=>{C(),await r.runFirstTimeSetup()});p(M,{...H("init",[[`${I} setup --key <key>`,"init.alt.setup"],[`${I}`,"init.alt.menu"]]),examples:[T(`${I} init`,"init.ex.run"),T(`${I} init --base ${L}`,"init.ex.base"),T(`${I}`,"init.ex.menu")]});const q=R.command("auth").summary(P("auth.summary")).description(P("auth.description")).argument("[token]",P("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});K(q);const D=q.command("revoke").description(P("auth.revoke")).action(async()=>{await d(["revoke"])});p(D,{examples:[T(`${I} auth revoke`,"auth.ex.revoke_ask"),T(`${I} auth revoke --yes`,"auth.ex.revoke")]});const F=q.command("reload <tool>").description(P("auth.reload")).action(async e=>{await d(["reload",e])});p(F,{examples:[T(`${I} auth reload claude-code`,"auth.ex.reload"),T(`${I} auth reload claude-code --json`,"auth.ex.reload_json")]}),p(q,{...H("auth",[[`${I} setup --key <key>`,"auth.alt.setup"]]),examples:[T(`${I} auth`,"auth.ex.prompt"),T(`${I} auth sk-xxx --non-interactive`,"auth.ex.save"),T(`${I} auth revoke --yes`,"auth.ex.revoke"),T(`${I} auth reload claude-code`,"auth.ex.reload")]});const J=R.command("config").summary(P("config.summary")).description(P("config.description")).argument("[args...]",P("config.arg.args")).option("-f, --force",P("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await g(o.force?[...e,"--force"]:e)});p(J,{...H("config",[[`${I} setup --force --key <key>`,"config.alt.setup"],[`${I} status`,"config.alt.status"]]),sections:[{title:P("config.subcommands_title"),rows:[["<tool>",P("config.sub.tool")],["<tool> --force",P("config.sub.tool_force")],["<tool> --non-interactive",P("config.sub.tool_non_interactive")],["<tool> remove",P("config.sub.tool_remove")],["<tool> restore",P("config.sub.tool_restore")],["<tool> backups",P("config.sub.tool_backups")],["<tool> clear-model",P("config.sub.tool_clear_model")],["tool-model list",P("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",P("config.sub.tool_model_set")],["tool-model clear <tool>",P("config.sub.tool_model_clear")],["profile list",P("config.sub.profile_list")],["profile create <name>",P("config.sub.profile_create")],["profile use <name>",P("config.sub.profile_use")],["profile delete <name>",P("config.sub.profile_delete")],["preset list",P("config.sub.preset_list")],["preset save <name>",P("config.sub.preset_save")],["preset use <name>",P("config.sub.preset_use")],["preset delete <name>",P("config.sub.preset_delete")],["backup list",P("config.sub.backup_list")],["backup create [label]",P("config.sub.backup_create")],["backup restore <name>",P("config.sub.backup_restore")]]},{title:P("config.tools_title"),rows:Object.values(c).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[T(`${I} config codex`,"config.ex.menu"),T(`${I} config claude-code --force`,"config.ex.force"),T(`${I} config tool-model set codex gpt-6-astra`,"config.ex.tool_model"),T(`${I} config profile create work`,"config.ex.profile"),T(`${I} config codex remove`,"config.ex.remove")]});const Y=R.command("base").summary(P("base.summary")).description(P("base.description")).argument("[target]",P("base.arg.target")).action(async e=>{await G(e)});p(Y,{...H("base",[[`${I} doctor`,"base.alt.doctor"],[`${I} bench`,"base.alt.bench"]]),sections:[{title:P("base.targets_title"),rows:[[P("base.target.none_term"),P("base.target.none")],[P("base.target.index_term"),P("base.target.index")],[P("base.target.url_term"),P("base.target.url")],["auto",P("base.target.auto")],["default",P("base.target.default",{url:l})]]}],examples:[T(`${I} base`,"base.ex.list"),T(`${I} base auto`,"base.ex.auto"),T(`${I} base 2`,"base.ex.index"),T(`${I} base ${L}`,"base.ex.url"),T(`${I} base default`,"base.ex.default")]}),R.commandsGroup(P("group.diagnose"));const Q=R.command("status").summary(P("status.summary")).description(P("status.description")).action(async()=>{await x()});p(Q,{...H("status",[[`${I} doctor`,"status.alt.doctor"]]),examples:[T(`${I} status`,"status.ex.show"),T(`${I} status --json`,"status.ex.json")]});const V=R.command("doctor").summary(P("doctor.summary")).description(P("doctor.description")).option("--deep",P("doctor.opt.deep")).option("--report",P("doctor.opt.report")).action(async e=>{await f({deep:e.deep,report:e.report})});p(V,{...H("doctor",[[`${I} base auto`,"doctor.alt.base"],[`${I} logs tail`,"doctor.alt.logs"]]),examples:[T(`${I} doctor`,"doctor.ex.run"),T(`${I} doctor --deep`,"doctor.ex.deep"),T(`${I} doctor --report`,"doctor.ex.report")]});const W=R.command("bench").summary(P("bench.summary")).description(P("bench.description")).option("--samples <n>",P("bench.opt.samples"),"5").option("--stream",P("bench.opt.stream")).option("--model <model>",P("bench.opt.model")).action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),e.stream&&o.push("--stream"),e.model&&o.push("--model",e.model),await b(o)});p(W,{...H("bench",[[`${I} base`,"bench.alt.base"]]),examples:[T(`${I} bench`,"bench.ex.run"),T(`${I} bench --samples 3`,"bench.ex.samples"),T(`${I} bench --stream`,"bench.ex.stream"),T(`${I} bench --stream --model gpt-6-astra`,"bench.ex.stream_model"),T(`${I} bench --json`,"bench.ex.json")]});const X=R.command("logs").summary(P("logs.summary")).description(P("logs.description")).argument("[action]",P("logs.arg.action")).argument("[file]",P("logs.arg.file")).action(async(e,o)=>{const s=[];e&&s.push(e),o&&s.push(o),await y(s)});p(X,{...H("logs",[[`${I} doctor`,"logs.alt.doctor"]]),sections:[{title:P("logs.actions_title"),rows:[["list",P("logs.action.list")],["tail [file]",P("logs.action.tail")],["path",P("logs.action.path")]]}],examples:[T(`${I} logs`,"logs.ex.list"),T(`${I} logs tail`,"logs.ex.tail"),T(`${I} logs path`,"logs.ex.path")]}),R.commandsGroup(P("group.maintain"));const Z=R.command("upgrade").summary(P("upgrade.summary")).description(P("upgrade.description")).argument("[tools...]",P("upgrade.arg.tools")).option("--force",P("upgrade.opt.force")).action(async(e=[],o={})=>{await _(e,{force:o.force})});p(Z,{...H("upgrade",[[`${I} update`,"upgrade.alt.update"]]),examples:[T(`${I} upgrade`,"upgrade.ex.all"),T(`${I} upgrade claude-code`,"upgrade.ex.one"),T(`${I} upgrade codex agy`,"upgrade.ex.many"),T(`${I} upgrade claude-desktop`,"upgrade.ex.desktop"),T(`${I} upgrade chatgpt --force`,"upgrade.ex.force")]});const ee=R.command("refresh").summary(P("refresh.summary")).description(P("refresh.description")).action(async()=>{await h()});p(ee,{...H("refresh",[[`${I} setup --key ${i.t("errors.key_placeholder")}`,"refresh.alt.setup"]]),examples:[T(`${I} refresh`,"refresh.ex.run"),T(`${I} refresh --base ${N}`,"refresh.ex.base")]});const oe=R.command("update").summary(P("update.summary")).description(P("update.description")).action(async()=>{await k()});p(oe,{...H("update",[[`${I} upgrade`,"update.alt.upgrade"]]),examples:[T(`${I} update`,"update.ex.check"),T(`${I} update --json`,"update.ex.json")]});const se=R.command("codex").summary(P("codex.summary")).description(P("codex.description"));K(se);const te=se.command("sessions").summary(P("codex_sessions.summary")).description(P("codex_sessions.description")).option("--to <provider>",P("codex_sessions.opt.to")).option("--undo <dir>",P("codex_sessions.opt.undo")).action(async e=>{await w(e)});p(se,{...H("codex"),examples:[T(`${I} codex sessions`,"codex_sessions.ex.move"),T(`${I} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]}),p(te,{...H("codex_sessions",[[`${I} codex sessions --undo <dir>`,"codex_sessions.alt.undo"]]),examples:[T(`${I} codex sessions`,"codex_sessions.ex.move"),T(`${I} codex sessions --to custom`,"codex_sessions.ex.to"),T(`${I} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]});const ne=R.command("sessions").summary(P("sessions.summary")).description(P("sessions.description"));K(ne);const ae=ne.command("list",{isDefault:!0}).description(P("sessions.list")).option("--tool <tool>",P("sessions.opt.tool")).option("--dir <path>",P("sessions.opt.dir")).option("--here",P("sessions.opt.here")).option("-n, --limit <count>",P("sessions.opt.limit")).option("--all",P("sessions.opt.all")).action(async e=>{await j(e)}),ie=ne.command("show <id>").description(P("sessions.show")).option("-m, --messages <count>",P("sessions.opt.messages")).action(async(e,o)=>{await S(e,o)}),re=ne.command("resume <id>").description(P("sessions.resume")).option("--run",P("sessions.opt.run")).action(async(e,o)=>{await O(e,o)}),ce=ne.command("export <ids...>").description(P("sessions.export")).option("-o, --output <dir>",P("sessions.opt.output")).option("--tools",P("sessions.opt.tools")).action(async(e,o)=>{await v(e,o)});p(ae,{examples:[T(`${I} sessions list`,"sessions.ex.list"),T(`${I} sessions list --tool codex`,"sessions.ex.codex"),T(`${I} sessions list --here --all`,"sessions.ex.here"),T(`${I} sessions list --json`,"sessions.ex.json")]}),p(ie,{examples:[T(`${I} sessions show 01a0f5fe`,"sessions.ex.show"),T(`${I} sessions show 01a0f5fe -m 20`,"sessions.ex.show_more")]}),p(re,{examples:[T(`${I} sessions resume 01a0f5fe`,"sessions.ex.resume_print"),T(`${I} sessions resume 01a0f5fe --run`,"sessions.ex.resume")]}),p(ce,{examples:[T(`${I} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export"),T(`${I} sessions export 01a0f5fe -o ./sessions --tools`,"sessions.ex.export_tools")]}),p(ne,{...H("sessions",[[`${I} codex sessions`,"sessions.alt.codex_sessions"]]),examples:[T(`${I} sessions`,"sessions.ex.list"),T(`${I} sessions --tool codex --here`,"sessions.ex.here"),T(`${I} sessions show 01a0f5fe`,"sessions.ex.show"),T(`${I} sessions resume 01a0f5fe --run`,"sessions.ex.resume"),T(`${I} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export")]});const le=R.command("lang").summary(P("lang.summary")).description(P("lang.description"));K(le);const pe=le.command("show").description(P("lang.show")).action(async()=>{await u(["show"])}),me=le.command("set <locale>").description(P("lang.set")).action(async e=>{await u(["set",e])}),ue=[T(`${I} lang show`,"lang.ex.show"),T(`${I} lang set en_US`,"lang.ex.set_en"),T(`${I} lang set zh_CN`,"lang.ex.set_zh")];p(le,{...H("lang",[[`${I} enter lang`,"lang.alt.enter"]]),examples:ue}),p(pe,{examples:[ue[0],T(`${I} lang show --json`,"lang.ex.show_json")]}),p(me,{examples:ue.slice(1)});const de=R.command("completion").summary(P("completion.summary")).description(P("completion.description")).argument("<shell>",P("completion.arg.shell")).action(async e=>{await $([e])});p(de,{...H("completion"),examples:[T(`${I} completion bash > ~/.${I}-completion.bash`,"completion.ex.bash"),T(`${I} completion zsh > ~/.${I}-completion.zsh`,"completion.ex.zsh"),T(`${I} completion fish > ~/.config/fish/completions/${I}.fish`,"completion.ex.fish")]});const fe=R.command("enter").summary(P("enter.summary")).description(P("enter.description")).argument("[option]",P("enter.arg.option")).action(async e=>{if(e&&!["lang","language","apikey","api-key","models"].includes(e)||C(),e)switch(e){case"lang":case"language":await r.configLanguage();break;case"apikey":case"api-key":await r.configApiKey();break;case"models":await r.configModels();break;default:await g([e])}else await r.run()});p(fe,{...H("enter",[[`${I}`,"enter.alt.menu"],[`${I} config <tool>`,"enter.alt.config"]]),sections:[{title:P("enter.options_title"),rows:[[P("enter.option.none_term"),P("enter.option.none")],["lang",P("enter.option.lang")],["apikey",P("enter.option.apikey")],["models",P("enter.option.models")],["<tool>",P("enter.option.tool")]]}],examples:[T(`${I} enter`,"enter.ex.menu"),T(`${I} enter models`,"enter.ex.models"),T(`${I} enter codex`,"enter.ex.tool")]}),K(R),R.action(async()=>{C(),await r.run()}),p(R,{examples:[T(`${I}`,"root.ex.menu"),T(`${I} setup --key sk-xxx`,"root.ex.setup"),T(`${I} doctor`,"root.ex.doctor"),T(`${I} base auto`,"root.ex.base"),T(`${I} config codex`,"root.ex.config")]});const ge=e=>{for(const o of e.commands)o.helpOption("-h, --help",P("global.help")),ge(o)};return ge(R),R}
|
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{canPrompt as i,shouldAutoConfirm as l}from"./runtime-options.js";import{logger as s}from"../utils/logger.js";import{configManager as a}from"./config.js";import{getAdapter as c,listAdapters as d,TOOL_ADAPTERS as p}from"./tools/registry.js";import{backupBeforeWrite as u,listBackups as m,restoreBackup as f}from"./tools/backup.js";import{existsSync as g,rmSync as h}from"fs";import{dirname as w,join as y}from"path";import{toolHome as P}from"./tools/types.js";import{stringWidth as $}from"../utils/string-width.js";import{resolveModelCatalog as T}from"./model-catalog.js";import{compareVersions 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{canPrompt as i,shouldAutoConfirm as l}from"./runtime-options.js";import{logger as s}from"../utils/logger.js";import{configManager as a}from"./config.js";import{getAdapter as c,listAdapters as d,TOOL_ADAPTERS as p}from"./tools/registry.js";import{backupBeforeWrite as u,listBackups as m,restoreBackup as f}from"./tools/backup.js";import{existsSync as g,rmSync as h}from"fs";import{dirname as w,join as y}from"path";import{toolHome as P}from"./tools/types.js";import{stringWidth as $}from"../utils/string-width.js";import{resolveModelCatalog as T}from"./model-catalog.js";import{compareVersions as v,getToolMinVersion as C}from"./model-registry.js";import{findInstalls as k,forgetInstalls as E,installLabel as O,mirrorInstallCommand as _,npmMirrorInstallCommand as S,npmMirrorVersion as N}from"./tools/tool-installs.js";import{mirrorInstall as j}from"./tool-upgrade.js";import{upgradeApp as M}from"./app-update.js";import{CLI_NAME as U}from"./brand.js";import{track as b,trackStep as x}from"./telemetry.js";import{addUserPathDir as I,broadcastEnvChange as R}from"./windows-env.js";export{v as compareVersions};function F(o){const t=p[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 L(){const o=new Set;for(const t of a.listProfiles()){const n=a.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(p).map(o=>[o,F(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=c(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=c(o),n=t?.installSpec?.native?.binDir;if(!t||!n)return null;const e="win32"===process.platform?`${t.command}.exe`:t.command,r=y(P(),...n,e);return g(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=w(t);try{if(!I(n))return null}catch(t){return s.logError(`ensureNativeOnPath: ${o}`,t),null}return R(),process.env.Path=`${process.env.Path??""};${n}`,n}async installTool(o){return x(`install:${o}`,()=>this.installToolNow(o))}async installToolNow(t){const s=SUPPORTED_TOOLS[t];if(!s)throw new Error(`Unknown tool: ${t}`);const a=c(t)?.appInstaller;if(a&&!a.blocker()){const o=await M(t,{install:!0});if("failed"===o.result||"unavailable"===o.result)throw new Error(`Failed to install ${s.displayName}`);return}const d=c(t)?.installSpec;if(d&&(d.mirrorScript||d.npmPackage)){const o=_(d);if(await j(d)&&(E(),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:s.displayName,command:o}))),d.mirrorScript&&d.npmPackage&&console.log(r.yellow(" ! "+n.t("install.manual_npm",{command:S(d,await N(d))}))),new Error(`Failed to install ${s.displayName}`)}const p=s.installCommand;console.log(r.gray("$ ")+r.white(p));try{return o(p,{stdio:"inherit"}),E(),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&&!p.startsWith("npm "))throw new Error(`Failed to install ${s.displayName}: ${o}`);console.log(r.yellow(" ! "+("win32"===process.platform?n.t("install.permission_windows",{command:p}):n.t("install.permission_unix",{command:p}))))}const{action:u}=!i()||l()?{action:"continue"}: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"===u)throw new Error(n.t("install.user_cancelled"));if(E(),!this.isToolInstalled(t))throw console.log(r.red("× "+n.t("install.still_not_installed",{tool:s.displayName}))),new Error(`${s.displayName} is not installed`);console.log(r.green("√ "+n.t("install.verified_success",{tool:s.displayName})))}getToolConfig(o){const t=c(o);if(!t)throw new Error(`Unknown tool: ${o}`);try{return t.getConfig()}catch(t){return s.warn(`Failed to read config for ${o}:`,t),s.logError(`ToolManager.getToolConfig(${o})`,t),null}}updateToolConfig(o,t){const n=c(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=c(o);if(!t)throw new Error(`Unknown tool: ${o}`);const n=t.forceResetPaths?t.forceResetPaths():this.backupPathsFor(t),e=[];for(const o of n)g(o)&&(u(o),h(o,{force:!0}),e.push(o));return e}loadPrivateConfig(o,t,n,e,r={}){const i=c(o);if(!i)throw new Error(`Unknown tool: ${o}`);r.force&&this.forceResetConfig(o),i.loadPrivateConfig({apiKey:t,baseUrl:a.getBaseUrl(),models:n,settings:a.getToolSettings(o),...e?{catalog:e}:{}})}async applyPrivateConfig(o,t,n,e={}){const r=this.installedVersion(o);return x(`apply:${o}`,()=>this.applyPrivateConfigNow(o,t,n,e),{...r?{tool_version:r}:{},...e.force?{force:!0}:{}})}async applyPrivateConfigNow(o,t,n,e){const r=c(o);if(!r)throw new Error(`Unknown tool: ${o}`);const i=r.wantsModelCatalog?await T(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=c(o);if(!t)return[];const e=[];try{t.applyNotes&&e.push(...t.applyNotes())}catch(t){s.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?`${U} upgrade ${o}`:t.upgradeCommand||t.installCommand})});for(const o of t.upgradeHints?.(r.min)??[])e.push({kind:"action",text:o})}const i=t.installSpec?k(t.installSpec):[];return i.length>1&&e.push({kind:"action",text:n.t("upgrade.duplicates_note",{count:String(i.length),active:O(i[0]),others:i.slice(1).map(O).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))s.record(`${n}: ${o.text}`);const i=e.filter(o=>"summary"===o.kind).map(o=>o.text).join(";"),l=" ".repeat(Math.max(1,t-$(n)));console.log(r.green("√ "+n)+(i?l+i:""));for(const o of e.filter(o=>"action"===o.kind))console.log(r.yellow(" ! "+o.text))}installedVersion(o){const n=c(o);if(!n)return null;if(n.installSpec)return k(n.installSpec)[0]?.version??null;if(n.installedVersion)try{return n.installedVersion()}catch(t){return s.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=C(o);if(!t)return null;const n=this.installedVersion(o);return n&&v(n,t)<0?{current:n,min:t}:null}unloadPrivateConfig(o){const t=c(o);if(!t)throw new Error(`Unknown tool: ${o}`);try{t.unloadPrivateConfig({savedKeys:L()}),b(`remove:${o}`,"ok")}catch(t){throw b(`remove:${o}`,"fail",{error:t}),t}let e=[];try{e=t.unloadNotes?.()??[]}catch(t){s.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=c(o);if(!t)throw new Error(`Unknown tool: ${o}`);if(a.setToolModel(o,null),!t.clearPinnedModels)return[];const n=a.getApiKeyForTool(o),e=t.wantsModelCatalog&&n?await T(n):null;return t.clearPinnedModels(e??void 0)}supportsClearPinnedModels(o){return Boolean(c(o)?.clearPinnedModels)}holdsOurConfig(o){const t=c(o);if(!t)return!1;const n=L();return t.holdsOurConfig?t.holdsOurConfig(n):Boolean(t.detectCurrentConfig().apiKey)}detectCurrentConfig(o){const t=c(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=c(o);if(!t)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(t).map(o=>({file:o,backups:m(o)}))}restorePrivateConfig(o){const t=c(o);if(!t)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(t).map(o=>({file:o,result:f(o)}))}getInstalledTools(){return Object.keys(SUPPORTED_TOOLS).filter(o=>this.isToolInstalled(o))}getSupportedTools(){return d().filter(o=>!o.hidden).map(o=>F(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();
|