@vibeapi/api-helper 0.0.109 → 0.0.110
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/README.md +1 -0
- package/dist/cli.js +1 -1
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.js +1 -1
- package/dist/lib/api-validator.js +1 -1
- package/dist/lib/client-config.d.ts +1 -1
- package/dist/lib/command.js +1 -1
- package/dist/lib/program.js +1 -1
- package/dist/lib/telemetry.d.ts +55 -0
- package/dist/lib/telemetry.js +1 -0
- package/dist/lib/tool-manager.d.ts +2 -0
- package/dist/lib/tool-manager.js +1 -1
- package/dist/lib/tool-upgrade.js +1 -1
- package/dist/locales/en_US.json +9 -3
- package/dist/locales/zh_CN.json +9 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -108,6 +108,7 @@ vibecli config <tool> remove # 移除 VibeAPI 写入的配置(Codex
|
|
|
108
108
|
vibecli config tool-model set codex gpt-6-astra # 单独给某工具指定模型
|
|
109
109
|
vibecli config profile use work # 切换 profile
|
|
110
110
|
vibecli doctor # 健康巡检(--deep 实发一条请求)
|
|
111
|
+
vibecli doctor --report # 巡检后上传诊断信息,得到诊断码发给客服
|
|
111
112
|
vibecli upgrade # 升级 Claude Code / Codex / agy,官方渠道连不上自动改走国内镜像
|
|
112
113
|
vibecli codex sessions # 换过登录方式后 Codex 旧会话不显示时,让它们重新出现(先退出 Codex)
|
|
113
114
|
vibecli setup --desktop-registry on # Windows:桌面端不认本地配置时,强制写注册表(会请求一次管理员确认)
|
package/dist/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
if(Number(process.versions.node.split(".")[0])<20){const{brand:
|
|
2
|
+
if(Number(process.versions.node.split(".")[0])<20){const{brand:e}=await import("./lib/brand.js"),r=e().productName;console.error(`${r} 需要 Node.js 20 或更高版本,当前是 v${process.versions.node}。\n请安装 Node.js LTS(国内镜像:https://registry.npmmirror.com/binary.html?path=node/ ,或用 nvm install --lts),装好后重开终端再运行。\n${r} needs Node.js 20 or later (found v${process.versions.node}); install the LTS release and open a new terminal.`),process.exit(1)}const{Command:e}=await import("./lib/command.js"),{logger:r}=await import("./utils/logger.js"),{reportCliError:o}=await import("./lib/errors.js"),{telemetryPending:s}=await import("./lib/telemetry.js");try{await(new e).execute(process.argv.slice(2))}catch(e){r.logError("CLI",e),o(e)}s()&&process.exit();export{};
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{refreshClientConfig as
|
|
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{toolManager as d}from"../lib/tool-manager.js";import{i18n as p}from"../lib/i18n.js";import{validateApiKey as u}from"../lib/api-validator.js";import{getAdapter as m}from"../lib/tools/registry.js";import{findInstalls as f,installLabel as g}from"../lib/tools/tool-installs.js";import{detectManagedOverrides as _}from"../lib/tools/claude-managed.js";import{codexAuthProblem as h}from"../lib/tools/codex.js";import{claudeAccountLoginPresent as y}from"../lib/tools/claude-code.js";import{toolHome as v}from"../lib/tools/types.js";import{gatewayAddresses as w,probeGatewayAddress as j}from"../lib/gateway-addresses.js";import{listAdapters as k}from"../lib/tools/registry.js";import{logger as b}from"../utils/logger.js";import{maskSecrets as $,uploadReport as x}from"../lib/telemetry.js";import{CLI_NAME as T}from"../lib/brand.js";const A=["HTTPS_PROXY","https_proxy","HTTP_PROXY","http_proxy","ALL_PROXY","all_proxy"];function P(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 R(){const o=b.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 $(t.slice(-15e4))}function O(){const o={};for(const t of A){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(p.t("doctor.checking")).start(),i=[],b=Number(process.versions.node.split(".")[0]);i.push({name:"Node.js",status:b>=20?"pass":"fail",message:`v${process.versions.node}`}),n.text=p.t("doctor.check_proxy"),i.push(await async function(){const o=p.t("doctor.proxy"),t=new Map;for(const o of A){const e=process.env[o]?.trim();e&&!t.has(e)&&t.set(e,o)}if(0===t.size)return{name:o,status:"pass",message:p.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 P(t.hostname,r)||e.push(`${s}=${o}`)}return 0===e.length?{name:o,status:"pass",message:[...t.keys()].join(", ")}:{name:o,status:"fail",message:p.t("doctor.proxy_dead",{proxies:e.join(", ")})}}()),n.text=p.t("doctor.check_api_key_network");const $=l.getApiKey(),N=p.t("doctor.api_key_network");if($){const o=await u($);o.valid?i.push({name:N,status:"pass"}):"invalid_api_key"===o.error?i.push({name:N,status:"fail",message:p.t("doctor.api_key_invalid")}):(i.push({name:N,status:"fail",message:`${p.t("doctor.network_error")}: ${o.message??o.error}`}),n.text=p.t("doctor.check_other_addresses"),i.push(await async function(){const o=p.t("doctor.other_addresses"),t=l.getBaseUrl(),e=w().filter(o=>o.url!==t),s=l.getApiKey(),r=await Promise.all(e.map(o=>j(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:p.t("doctor.other_addresses_none")}:{name:o,status:"warn",message:p.t("doctor.other_addresses_found",{urls:n.join(", ")})}}()))}else i.push({name:N,status:"fail",message:p.t("doctor.api_key_missing")});n.text=p.t("doctor.check_client_config");const H=await o();i.push({name:p.t("doctor.client_config"),status:"cloud"===H.source||"cache"===H.source&&!H.problem?"pass":"warn",message:[H.source?p.t(`refresh.source.${H.source}`):p.t("refresh.source.none"),H.revision?p.t("doctor.client_config_revision",{revision:H.revision}):"",H.problem??""].filter(Boolean).join(" · ")}),n.text=p.t("doctor.check_tools");const S=d.getInstalledTools();i.push({name:p.t("doctor.installed_tools"),status:S.length>0?"pass":"warn",message:S.length>0?S.map(o=>m(o)?.displayName??o).join(", "):p.t("doctor.no_tools_installed")}),i.push(...function(){const o=[];for(const t of d.getInstalledTools()){const e=m(t);if(!e?.installSpec)continue;const s=f(e.installSpec);if(0===s.length)continue;const r=[],n=d.outdatedVersion(t);n&&r.push(p.t("doctor.tool_outdated",{min:n.min})),s.length>1&&r.push(p.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?[p.t("doctor.run_upgrade",{tool:t})]:[]].join("\n ")})}return o}());const C=function(){if(!d.isToolInstalled("claude-code"))return null;const o=p.t("doctor.claude_config"),t=_();if(t.length>0){const e=t.map(o=>`${o.source}: ${o.keys.join(", ")}`).join("; ");return{name:o,status:"fail",message:p.t("doctor.claude_managed",{detail:e})}}let e={};try{e=JSON.parse(a(c(v(),".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:p.t("doctor.claude_config_changed")}:{name:o,status:"pass"}:{name:o,status:"warn",message:p.t("doctor.claude_not_configured")}}();C&&i.push(C),S.includes("claude-code")&&y()&&i.push({name:p.t("doctor.claude_login"),status:"pass",message:p.t("tools.claude_code.account_login_overridden")});const I=S.includes("codex")?h():null;S.includes("codex")&&i.push({name:p.t("doctor.codex_auth"),status:I?"fail":"pass",message:I?p.t(`doctor.codex_${I}`):void 0}),"win32"===process.platform&&S.includes("claude-code")&&!process.env.CLAUDE_CODE_GIT_BASH_PATH&&i.push({name:"Git for Windows",status:d.isGitInstalled()?"pass":"warn",message:d.isGitInstalled()?void 0:p.t("tools.claude_code.no_git_bash")}),r.deep&&S.includes("claude-code")&&(n.text=p.t("doctor.check_claude_request"),i.push(function(){const o=p.t("doctor.claude_request"),t=f(m("claude-code").installSpec)[0];if(!t)return{name:o,status:"warn",message:p.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:p.t("doctor.claude_request_failed",{reason:i})}}())),n.stop(),console.log("\n"+t.bold(p.t("doctor.results_title"))+"\n");const L={pass:t.green("√"),warn:t.yellow("!"),fail:t.red("×")};for(const o of i)console.log(`${L[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(p.t("doctor.all_good"))),!r.deep&&S.includes("claude-code")&&console.log(t.gray("\n"+p.t("doctor.deep_hint"))),r.report){const o=e(p.t("doctor.report_uploading")).start(),t=await x(function(o,t){const e={};for(const o of k()){if(o.hidden)continue;let t=null;try{t=d.detectCurrentConfig(o.name).apiKey?"has_key":"no_key"}catch{t="unreadable"}e[o.name]={installed:d.isToolInstalled(o.name),version:d.installedVersion(o.name),copies:o.installSpec?f(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:O()},log:R()}}(i,{source:H.source??void 0,revision:H.revision,problem:H.problem}));t?o.succeed(p.t("doctor.report_done",{code:t})):o.fail(p.t("doctor.report_failed",{cli:T}))}else i.some(o=>"fail"===o.status)&&console.log(t.gray("\n"+p.t("doctor.report_hint",{cli:T})));i.some(o=>"fail"===o.status)&&(process.exitCode=1)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{KEY_INFO_PATH as e}from"./gateway-protocol.js";import{logger as r}from"../utils/logger.js";import{configManager as t}from"./config.js";import{i18n as o}from"./i18n.js";import{rememberPublishedAddresses as a}from"./gateway-addresses.js";import{eligibleLists as n}from"./client-config.js";import{
|
|
1
|
+
import{KEY_INFO_PATH as e}from"./gateway-protocol.js";import{logger as r}from"../utils/logger.js";import{configManager as t}from"./config.js";import{i18n as o}from"./i18n.js";import{rememberPublishedAddresses as a}from"./gateway-addresses.js";import{eligibleLists as n}from"./client-config.js";import{track as s}from"./telemetry.js";import{refreshClientConfig as i}from"./client-config-sync.js";const l=e=>new Promise(r=>setTimeout(r,e));async function c(e,r,a){const n=`${t.getBaseUrl()}/v1/models`,s=new AbortController,i=setTimeout(()=>s.abort(),r);try{const r=await a(n,{method:"GET",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},signal:s.signal});if(401===r.status)return{valid:!1,error:"invalid_api_key",message:"API Key is invalid or expired"};if(r.ok){try{const e=await r.json();if(e&&"list"===e.object)return{valid:!0}}catch{return{valid:!0}}return{valid:!0}}return{valid:!1,error:"unknown_error",message:`HTTP ${r.status}: ${r.statusText}`}}catch(e){return e instanceof Error&&"AbortError"===e.name?{valid:!1,error:"network_error",message:"Request timeout"}:function(e){const r=e?.cause?.code;return"string"==typeof r&&u.has(r)}(e)?{valid:!1,error:"network_error",message:o.t("messages.certificate_intercepted",{url:n})}:{valid:!1,error:"network_error",message:e instanceof Error?e.message:"Network connection failed"}}finally{clearTimeout(i)}}const u=new Set(["DEPTH_ZERO_SELF_SIGNED_CERT","SELF_SIGNED_CERT_IN_CHAIN","UNABLE_TO_VERIFY_LEAF_SIGNATURE","UNABLE_TO_GET_ISSUER_CERT_LOCALLY","CERT_UNTRUSTED","ERR_TLS_CERT_ALTNAME_INVALID"]);export async function fetchModels(e,o={}){const{timeoutMs:a=3e4,fetchFn:n=fetch}=o,s=`${t.getBaseUrl()}/v1/models`,i=new AbortController,l=setTimeout(()=>i.abort(),a);try{const r=await n(s,{method:"GET",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},signal:i.signal});if(!r.ok)return{ok:!1,models:[],error:`HTTP ${r.status}`};const t=await r.json();return{ok:!0,models:(Array.isArray(t?.data)?t.data:[]).map(e=>"string"==typeof e?e:e?.id).filter(e=>"string"==typeof e&&e.trim().length>0).map(e=>e.trim())}}catch(e){return r.logError("fetchModels",e),{ok:!1,models:[],error:e instanceof Error?e.message:"network error"}}finally{clearTimeout(l)}}function f(e){return e.filter(e=>!!e&&"object"==typeof e&&"string"==typeof e.name).map(e=>({name:e.name.trim(),..."string"==typeof e.labelOverride?{labelOverride:e.labelOverride}:{},..."boolean"==typeof e.supports1m?{supports1m:e.supports1m}:{}})).filter(e=>e.name.length>0)}export async function fetchGatewayStatus(e={}){const{timeoutMs:o=15e3,fetchFn:n=fetch}=e,s=`${t.getBaseUrl()}/api/status`,i=new AbortController,l=setTimeout(()=>i.abort(),o);try{const e=await n(s,{method:"GET",signal:i.signal});if(!e.ok)return{ok:!1,claudeDesktopGroupModels:{},error:`HTTP ${e.status}`};const r=await e.json();a(r?.data,t.getBaseUrl());let o=r?.data?.claude_desktop_group_models;if("string"==typeof o)try{o=JSON.parse(o)}catch{o=void 0}const l={};if(o&&"object"==typeof o&&!Array.isArray(o))for(const[e,r]of Object.entries(o))Array.isArray(r)&&(l[e]=f(r));return{ok:!0,claudeDesktopGroupModels:l}}catch(e){return r.logError("fetchGatewayStatus",e),{ok:!1,claudeDesktopGroupModels:{},error:e instanceof Error?e.message:"network error"}}finally{clearTimeout(l)}}export async function fetchKeyGroupInfo(o,a={}){const{timeoutMs:n=1e4,fetchFn:s=fetch}=a,i=`${t.getBaseUrl()}${e}`,l=new AbortController,c=setTimeout(()=>l.abort(),n);try{const e=await s(i,{method:"GET",headers:{Authorization:`Bearer ${o}`},signal:l.signal});if(!e.ok)return null;const r=await e.json(),t=r?.data;if(!t||"string"!=typeof t.group||!Array.isArray(t.claude_desktop_models))return null;const a=Array.isArray(t.groups)?t.groups.filter(e=>"string"==typeof e&&!!e):[];return{group:t.group,groups:a.length>0?a:[t.group],claudeDesktopModels:f(t.claude_desktop_models)}}catch(e){return r.logError("fetchKeyGroupInfo",e),null}finally{clearTimeout(c)}}export async function fetchClientModelConfig(e={}){const r=await i(e);return r.config?n(r.config.models):null}export async function validateApiKey(e,t={}){const o=Date.now(),a=await async function(e,t){const{timeoutMs:o=3e4,retries:a=2,backoffMs:n=500,fetchFn:s=fetch,sleepFn:i=l}=t;let u={valid:!1,error:"network_error",message:"Network connection failed"};for(let t=0;t<=a;t++){const l=await c(e,o,s);if(l.valid||"invalid_api_key"===l.error)return l.valid||r.logError("validateApiKey",new Error(l.message||"invalid_api_key")),l;u=l,t<a&&await i(n*Math.pow(2,t))}return r.logError("validateApiKey",new Error(u.message||"network_error")),u}(e,t);return s("validate-key",a.valid?"ok":"fail",{duration_ms:Date.now()-o,...a.valid?{}:{error:a.message??a.error,detail:{reason:a.error}}}),a}
|
|
@@ -88,7 +88,7 @@ export declare function currentClientConfig(): {
|
|
|
88
88
|
/** Tests pin the client version and install id. */
|
|
89
89
|
export declare function setClientIdentityForTests(version: string | null, installId: string | null): void;
|
|
90
90
|
export declare const clientVersion: () => string;
|
|
91
|
-
/** Stable random id per install
|
|
91
|
+
/** Stable random id per install: rollout buckets, and support telling one machine's events apart (see telemetry.ts). */
|
|
92
92
|
export declare function installId(): string;
|
|
93
93
|
/** 0–99, stable per install and model. */
|
|
94
94
|
export declare function rolloutBucket(modelId: string): number;
|
package/dist/lib/command.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i18n as n,detectSystemLang as
|
|
1
|
+
import{i18n as n,detectSystemLang as o}from"./i18n.js";import{configManager as r}from"./config.js";import{runModelRefresh as e}from"./model-refresh.js";import{refreshClientConfig as t}from"./client-config-sync.js";import{normalizeBaseUrl as s}from"./gateway-addresses.js";import i from"chalk";import{setRuntimeOptions as a,detectColorPreferenceFromEnv as m,isColorEnabled as c,isJsonMode as l}from"./runtime-options.js";import{cleanupAnthropicEnvVars as g,machineEnvVarsLeft as d}from"./env-cleanup.js";import{runStartupUpdate as f}from"./auto-update.js";import{buildProgram as u}from"./program.js";import{firstCommandWord as p,isHelpRequest as h,renderHelpTopic as w}from"./cli-help.js";import{reportCliError as y,usageError as v,CliError as _}from"./errors.js";import{CLI_NAME as j}from"./brand.js";import{flushTelemetry as k,installClientHeaders as C,setTelemetryCommand as x,track as A}from"./telemetry.js";export{buildProgram}from"./program.js";const b=new Set(["setup","init","auth","enter","config"]);export class Command{program;configuring=!1;constructor(){const e=r.isLangChosen()?r.getLang():o();n.loadFromConfig(e),this.program=u()}cleanupLeakedEnvVars(){const o=g();if(0===o.length||l())return;const r=n.t("messages.env_vars_cleared",{vars:o.join(", ")});console.log(c()?i.yellow(r):r);const e=d();if(e.length>0){const o=n.t("messages.env_vars_machine_left",{vars:e.join(", ")});console.log(c()?i.yellow(o):o)}}preflightArgs(n){const o=o=>n.includes(o),e=!o("--no-color")&&m();if(a({nonInteractive:o("--non-interactive"),json:o("--json"),yes:o("--yes")||o("-y"),dryRun:o("--dry-run"),color:e}),e||(i.level=0),this.configuring=!1,h(n))return;let t;for(let o=0;o<n.length;o+=1){const r=n[o];"--base"===r&&n[o+1]?(t=n[o+1],o+=1):r.startsWith("--base=")&&(t=r.slice(7))}const c=p(n),l=void 0===c&&!["--version","-v"].some(o);this.configuring=l||void 0!==c&&b.has(c),t&&r.setBaseUrl(s(t)??t,this.configuring)}async execute(n){const o=Date.now();let r=!1;try{if(this.preflightArgs(n),C(),h(n)||["--version","-v"].some(o=>n.includes(o))||(x(p(n)??"wizard"),A("command","start",{detail:{args:n.filter(n=>n.startsWith("-")&&!/key/i.test(n))}}),r=!0),"help"===n[0]&&n[1]){const o=w(n[1]);if(o)return void process.stdout.write(o)}if(this.rejectUnknownCommand(n),!h(n)){if(this.configuring&&this.cleanupLeakedEnvVars(),(await f(n)).handled)return;this.configuring&&await t({timeoutMs:5e3}),await e(n)}if(await this.program.parseAsync(n,{from:"user"}),r){const n=Boolean(process.exitCode)&&0!==process.exitCode;A("command",n?"fail":"ok",{duration_ms:Date.now()-o,...n?{detail:{exit_code:process.exitCode}}:{}})}}catch(e){if("commander.helpDisplayed"===e?.code||"commander.version"===e?.code)return;const t=this.normalizeCommanderError(e,n),s=y(t);if(r){const n=t instanceof _?`${t.type}${t.subtype?"/"+t.subtype:""}`:void 0;A("command",130===s?"cancel":"fail",{duration_ms:Date.now()-o,error:t,detail:{exit_code:s,...n?{type:n}:{}}})}}finally{r&&await k()}}rejectUnknownCommand(o){const r=p(o);if(!r||"help"===r)return;if(this.program.commands.some(n=>n.name()===r))return;const e=this.suggestCommand(r),t=e?n.t("cli.unknown_hint_suggestion",{command:e}):n.t("cli.unknown_hint");throw v(n.t("cli.error_unknown",{command:r}),t,"unknown_command")}suggestCommand(n){const o=(n,o)=>{const r=Array.from({length:o.length+1},(n,o)=>o);for(let e=1;e<=n.length;e+=1){let t=r[0];r[0]=e;for(let s=1;s<=o.length;s+=1){const i=r[s];r[s]=Math.min(r[s]+1,r[s-1]+1,t+(n[e-1]===o[s-1]?0:1)),t=i}}return r[o.length]};return this.program.commands.map(n=>n.name()).map(r=>({name:r,score:o(n,r)})).filter(({score:o})=>o<=Math.max(2,Math.floor(n.length/2))).sort((n,o)=>n.score-o.score)[0]?.name}normalizeCommanderError(o,r){if(o instanceof _)return o;const e=o?.code,t=o instanceof Error?o.message:String(o);if("commander.unknownOption"===e||"commander.missingArgument"===e||"commander.missingMandatoryOption"===e||"commander.invalidArgument"===e){const o=p(r)??j,s=/'([^']+)'/.exec(t)?.[1]??"",i="commander.unknownOption"===e?"cli.err_unknown_option":"commander.missingArgument"===e?"cli.err_missing_argument":"commander.missingMandatoryOption"===e?"cli.err_missing_option":null,a=i&&s?n.t(i,{name:s}):t.replace(/^error:\s*/,"");return v(a,n.t("cli.unknown_option_hint",{command:o}),e)}return o}getProgram(){return this.program}}
|
package/dist/lib/program.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Command as e,Option as o}from"commander";import{readFileSync as t}from"fs";import{join as s,dirname as a}from"path";import{fileURLToPath as n}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 g,configCommand as f,statusCommand as x,refreshCommand as y}from"../commands/index.js";import{logsCommand as h}from"../commands/logs.js";import{completionCommand as b}from"../commands/completion.js";import{benchCommand as $}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{setupCommand as v,DEDICATED_KEYS as j}from"../commands/setup.js";import{baseCommand as O}from"../commands/base.js";import{usageError as S}from"./errors.js";import{brand as z,brandEnv as A,CLI_NAME as C}from"./brand.js";const E=(z().gatewayAddresses[1]??z().gatewayAddresses[0]).url,G=(z().gatewayAddresses[2]??z().gatewayAddresses[0]).url;function R(e,o){return i.t(`help.${e}`,o)}function K(e,o){return{command:e,note:R(o)}}function L(e){const o=R(e);return o===`help.${e}`?"":o}function N(e,o=[]){return{when:L(`${e}.when`),prerequisites:L(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>K(e,o))}}function P(e){return e.helpCommand("help [command]",R("help_command"))}export function buildProgram(){const z=new e;z.name(`${C}`).summary(R("root.summary")).description(R("root.description")).configureHelp(m()).allowExcessArguments(!0).optionsGroup(R("group.global_options")).helpOption("-h, --help",R("global.help")).version(function(){try{const e=a(n(import.meta.url));return JSON.parse(t(s(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",R("global.version")).option("--base <url>",R("global.base")).option("--non-interactive",R("global.non_interactive")).option("--json",R("global.json")).option("-y, --yes",R("global.yes")).option("--dry-run",R("global.dry_run")).option("--no-color",R("global.no_color")),z.configureOutput({writeErr:()=>{},outputError:()=>{}}),z.showSuggestionAfterError(),z.exitOverride(e=>{throw e}),z.commandsGroup(R("group.configure"));const L=z.command("setup").summary(R("setup.summary")).description(R("setup.description")).option("--key <key>",R("setup.opt.key"));for(const e of j){const t=new o(`--${e.option} <key>`,R(`setup.opt.${e.option}`));e.hidden&&t.hideHelp(),L.addOption(t)}L.option("--1m",R("setup.opt.one_m")).option("--no-1m",R("setup.opt.no_one_m")).option("--claude-official <on|off>",R("setup.opt.claude_official")).option("--desktop-registry <on|off>",R("setup.opt.desktop_registry")).option("--force",R("setup.opt.force")).option("--install",R("setup.opt.install")).option("--no-install",R("setup.opt.no_install")).option("--all",R("setup.opt.all")).action(async e=>{e.key||j.some(o=>e[o.option])||(e.key=A("SETUP_KEY")?.trim()||void 0);const o=Boolean(e.key||j.some(o=>e[o.option])),t=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,s="zh_CN"===i.getLocale()?"<你的 Key>":"<your key>";if(!o&&!t)throw S(i.t("setup.usage"),`${C} setup --key ${s}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw S(i.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),`${C} setup --claude-official on|off`,"invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw S(i.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),`${C} setup --desktop-registry on|off`,"invalid_value");await v({key:e.key,...Object.fromEntries(j.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})}),p(L,{...N("setup",[[`${C} init`,"setup.alt.init"],[`${C} config <tool>`,"setup.alt.config"],[`${C} auth <key>`,"setup.alt.auth"]]),sections:[{title:R("setup.autodetect_title"),rows:[["Claude",R("setup.autodetect.claude")],["GPT",R("setup.autodetect.gpt")],["Grok",R("setup.autodetect.grok")],["Gemini",R("setup.autodetect.gemini")]]}],examples:[K(`${C} setup --key sk-xxx`,"setup.ex.key"),K(`${C} setup --install --key sk-xxx`,"setup.ex.install"),K(`${C} setup --claudekey sk-a --codexkey sk-b --agykey sk-g`,"setup.ex.split"),K(`${C} setup --force --key sk-xxx`,"setup.ex.force"),K(`${C} setup --base ${E} --key sk-xxx`,"setup.ex.base")]});const T=z.command("init").summary(R("init.summary")).description(R("init.description")).action(async()=>{await r.runFirstTimeSetup()});p(T,{...N("init",[[`${C} setup --key <key>`,"init.alt.setup"],[`${C}`,"init.alt.menu"]]),examples:[K(`${C} init`,"init.ex.run"),K(`${C} init --base ${E}`,"init.ex.base"),K(`${C}`,"init.ex.menu")]});const U=z.command("auth").summary(R("auth.summary")).description(R("auth.description")).argument("[token]",R("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});P(U);const B=U.command("revoke").description(R("auth.revoke")).action(async()=>{await d(["revoke"])});p(B,{examples:[K(`${C} auth revoke`,"auth.ex.revoke_ask"),K(`${C} auth revoke --yes`,"auth.ex.revoke")]});const H=U.command("reload <tool>").description(R("auth.reload")).action(async e=>{await d(["reload",e])});p(H,{examples:[K(`${C} auth reload claude-code`,"auth.ex.reload"),K(`${C} auth reload claude-code --json`,"auth.ex.reload_json")]}),p(U,{...N("auth",[[`${C} setup --key <key>`,"auth.alt.setup"]]),examples:[K(`${C} auth`,"auth.ex.prompt"),K(`${C} auth sk-xxx --non-interactive`,"auth.ex.save"),K(`${C} auth revoke --yes`,"auth.ex.revoke"),K(`${C} auth reload claude-code`,"auth.ex.reload")]});const M=z.command("config").summary(R("config.summary")).description(R("config.description")).argument("[args...]",R("config.arg.args")).option("-f, --force",R("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await f(o.force?[...e,"--force"]:e)});p(M,{...N("config",[[`${C} setup --force --key <key>`,"config.alt.setup"],[`${C} status`,"config.alt.status"]]),sections:[{title:R("config.subcommands_title"),rows:[["<tool>",R("config.sub.tool")],["<tool> --force",R("config.sub.tool_force")],["<tool> --non-interactive",R("config.sub.tool_non_interactive")],["<tool> remove",R("config.sub.tool_remove")],["<tool> restore",R("config.sub.tool_restore")],["<tool> backups",R("config.sub.tool_backups")],["<tool> clear-model",R("config.sub.tool_clear_model")],["tool-model list",R("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",R("config.sub.tool_model_set")],["tool-model clear <tool>",R("config.sub.tool_model_clear")],["profile list",R("config.sub.profile_list")],["profile create <name>",R("config.sub.profile_create")],["profile use <name>",R("config.sub.profile_use")],["profile delete <name>",R("config.sub.profile_delete")],["preset list",R("config.sub.preset_list")],["preset save <name>",R("config.sub.preset_save")],["preset use <name>",R("config.sub.preset_use")],["preset delete <name>",R("config.sub.preset_delete")],["backup list",R("config.sub.backup_list")],["backup create [label]",R("config.sub.backup_create")],["backup restore <name>",R("config.sub.backup_restore")]]},{title:R("config.tools_title"),rows:Object.values(c).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[K(`${C} config codex`,"config.ex.menu"),K(`${C} config claude-code --force`,"config.ex.force"),K(`${C} config tool-model set codex gpt-6-astra`,"config.ex.tool_model"),K(`${C} config profile create work`,"config.ex.profile"),K(`${C} config codex remove`,"config.ex.remove")]});const q=z.command("base").summary(R("base.summary")).description(R("base.description")).argument("[target]",R("base.arg.target")).action(async e=>{await O(e)});p(q,{...N("base",[[`${C} doctor`,"base.alt.doctor"],[`${C} bench`,"base.alt.bench"]]),sections:[{title:R("base.targets_title"),rows:[[R("base.target.none_term"),R("base.target.none")],[R("base.target.index_term"),R("base.target.index")],[R("base.target.url_term"),R("base.target.url")],["auto",R("base.target.auto")],["default",R("base.target.default",{url:l})]]}],examples:[K(`${C} base`,"base.ex.list"),K(`${C} base auto`,"base.ex.auto"),K(`${C} base 2`,"base.ex.index"),K(`${C} base ${E}`,"base.ex.url"),K(`${C} base default`,"base.ex.default")]}),z.commandsGroup(R("group.diagnose"));const F=z.command("status").summary(R("status.summary")).description(R("status.description")).action(async()=>{await x()});p(F,{...N("status",[[`${C} doctor`,"status.alt.doctor"]]),examples:[K(`${C} status`,"status.ex.show"),K(`${C} status --json`,"status.ex.json")]});const J=z.command("doctor").summary(R("doctor.summary")).description(R("doctor.description")).option("--deep",R("doctor.opt.deep")).action(async e=>{await g({deep:e.deep})});p(J,{...N("doctor",[[`${C} base auto`,"doctor.alt.base"],[`${C} logs tail`,"doctor.alt.logs"]]),examples:[K(`${C} doctor`,"doctor.ex.run"),K(`${C} doctor --deep`,"doctor.ex.deep")]});const Y=z.command("bench").summary(R("bench.summary")).description(R("bench.description")).option("--samples <n>",R("bench.opt.samples"),"5").action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),await $(o)});p(Y,{...N("bench",[[`${C} base`,"bench.alt.base"]]),examples:[K(`${C} bench`,"bench.ex.run"),K(`${C} bench --samples 3`,"bench.ex.samples"),K(`${C} bench --json`,"bench.ex.json")]});const D=z.command("logs").summary(R("logs.summary")).description(R("logs.description")).argument("[action]",R("logs.arg.action")).argument("[file]",R("logs.arg.file")).action(async(e,o)=>{const t=[];e&&t.push(e),o&&t.push(o),await h(t)});p(D,{...N("logs",[[`${C} doctor`,"logs.alt.doctor"]]),sections:[{title:R("logs.actions_title"),rows:[["list",R("logs.action.list")],["tail [file]",R("logs.action.tail")],["path",R("logs.action.path")]]}],examples:[K(`${C} logs`,"logs.ex.list"),K(`${C} logs tail`,"logs.ex.tail"),K(`${C} logs path`,"logs.ex.path")]}),z.commandsGroup(R("group.maintain"));const I=z.command("upgrade").summary(R("upgrade.summary")).description(R("upgrade.description")).argument("[tools...]",R("upgrade.arg.tools")).action(async(e=[])=>{await _(e)});p(I,{...N("upgrade",[[`${C} update`,"upgrade.alt.update"]]),examples:[K(`${C} upgrade`,"upgrade.ex.all"),K(`${C} upgrade claude-code`,"upgrade.ex.one"),K(`${C} upgrade codex agy`,"upgrade.ex.many")]});const Q=z.command("refresh").summary(R("refresh.summary")).description(R("refresh.description")).action(async()=>{await y()});p(Q,{...N("refresh",[[`${C} setup --key <你的 Key>`,"refresh.alt.setup"]]),examples:[K(`${C} refresh`,"refresh.ex.run"),K(`${C} refresh --base ${G}`,"refresh.ex.base")]});const V=z.command("update").summary(R("update.summary")).description(R("update.description")).action(async()=>{await k()});p(V,{...N("update",[[`${C} upgrade`,"update.alt.upgrade"]]),examples:[K(`${C} update`,"update.ex.check"),K(`${C} update --json`,"update.ex.json")]});const W=z.command("codex").summary(R("codex.summary")).description(R("codex.description"));P(W);const X=W.command("sessions").summary(R("codex_sessions.summary")).description(R("codex_sessions.description")).option("--to <provider>",R("codex_sessions.opt.to")).option("--undo <dir>",R("codex_sessions.opt.undo")).action(async e=>{await w(e)});p(W,{...N("codex"),examples:[K(`${C} codex sessions`,"codex_sessions.ex.move"),K(`${C} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]}),p(X,{...N("codex_sessions",[[`${C} codex sessions --undo <dir>`,"codex_sessions.alt.undo"]]),examples:[K(`${C} codex sessions`,"codex_sessions.ex.move"),K(`${C} codex sessions --to custom`,"codex_sessions.ex.to"),K(`${C} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]});const Z=z.command("lang").summary(R("lang.summary")).description(R("lang.description"));P(Z);const ee=Z.command("show").description(R("lang.show")).action(async()=>{await u(["show"])}),oe=Z.command("set <locale>").description(R("lang.set")).action(async e=>{await u(["set",e])}),te=[K(`${C} lang show`,"lang.ex.show"),K(`${C} lang set en_US`,"lang.ex.set_en"),K(`${C} lang set zh_CN`,"lang.ex.set_zh")];p(Z,{...N("lang",[[`${C} enter lang`,"lang.alt.enter"]]),examples:te}),p(ee,{examples:[te[0],K(`${C} lang show --json`,"lang.ex.show_json")]}),p(oe,{examples:te.slice(1)});const se=z.command("completion").summary(R("completion.summary")).description(R("completion.description")).argument("<shell>",R("completion.arg.shell")).action(async e=>{await b([e])});p(se,{...N("completion"),examples:[K(`${C} completion bash > ~/.${C}-completion.bash`,"completion.ex.bash"),K(`${C} completion zsh > ~/.${C}-completion.zsh`,"completion.ex.zsh"),K(`${C} completion fish > ~/.config/fish/completions/${C}.fish`,"completion.ex.fish")]});const ae=z.command("enter").summary(R("enter.summary")).description(R("enter.description")).argument("[option]",R("enter.arg.option")).action(async e=>{if(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 f([e])}else await r.run()});p(ae,{...N("enter",[[`${C}`,"enter.alt.menu"],[`${C} config <tool>`,"enter.alt.config"]]),sections:[{title:R("enter.options_title"),rows:[[R("enter.option.none_term"),R("enter.option.none")],["lang",R("enter.option.lang")],["apikey",R("enter.option.apikey")],["models",R("enter.option.models")],["<tool>",R("enter.option.tool")]]}],examples:[K(`${C} enter`,"enter.ex.menu"),K(`${C} enter models`,"enter.ex.models"),K(`${C} enter codex`,"enter.ex.tool")]}),P(z),z.action(async()=>{await r.run()}),p(z,{examples:[K(`${C}`,"root.ex.menu"),K(`${C} setup --key sk-xxx`,"root.ex.setup"),K(`${C} doctor`,"root.ex.doctor"),K(`${C} base auto`,"root.ex.base"),K(`${C} config codex`,"root.ex.config")]});const ne=e=>{for(const o of e.commands)o.helpOption("-h, --help",R("global.help")),ne(o)};return ne(z),z}
|
|
1
|
+
import{Command as e,Option as o}from"commander";import{readFileSync as t}from"fs";import{join as s,dirname as a}from"path";import{fileURLToPath as n}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 g,configCommand as f,statusCommand as x,refreshCommand as y}from"../commands/index.js";import{logsCommand as h}from"../commands/logs.js";import{completionCommand as b}from"../commands/completion.js";import{benchCommand as $}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{setupCommand as v,DEDICATED_KEYS as j}from"../commands/setup.js";import{baseCommand as O}from"../commands/base.js";import{usageError as S}from"./errors.js";import{brand as z,brandEnv as A,CLI_NAME as C}from"./brand.js";const E=(z().gatewayAddresses[1]??z().gatewayAddresses[0]).url,G=(z().gatewayAddresses[2]??z().gatewayAddresses[0]).url;function R(e,o){return i.t(`help.${e}`,o)}function K(e,o){return{command:e,note:R(o)}}function L(e){const o=R(e);return o===`help.${e}`?"":o}function N(e,o=[]){return{when:L(`${e}.when`),prerequisites:L(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>K(e,o))}}function P(e){return e.helpCommand("help [command]",R("help_command"))}export function buildProgram(){const z=new e;z.name(`${C}`).summary(R("root.summary")).description(R("root.description")).configureHelp(m()).allowExcessArguments(!0).optionsGroup(R("group.global_options")).helpOption("-h, --help",R("global.help")).version(function(){try{const e=a(n(import.meta.url));return JSON.parse(t(s(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",R("global.version")).option("--base <url>",R("global.base")).option("--non-interactive",R("global.non_interactive")).option("--json",R("global.json")).option("-y, --yes",R("global.yes")).option("--dry-run",R("global.dry_run")).option("--no-color",R("global.no_color")),z.configureOutput({writeErr:()=>{},outputError:()=>{}}),z.showSuggestionAfterError(),z.exitOverride(e=>{throw e}),z.commandsGroup(R("group.configure"));const L=z.command("setup").summary(R("setup.summary")).description(R("setup.description")).option("--key <key>",R("setup.opt.key"));for(const e of j){const t=new o(`--${e.option} <key>`,R(`setup.opt.${e.option}`));e.hidden&&t.hideHelp(),L.addOption(t)}L.option("--1m",R("setup.opt.one_m")).option("--no-1m",R("setup.opt.no_one_m")).option("--claude-official <on|off>",R("setup.opt.claude_official")).option("--desktop-registry <on|off>",R("setup.opt.desktop_registry")).option("--force",R("setup.opt.force")).option("--install",R("setup.opt.install")).option("--no-install",R("setup.opt.no_install")).option("--all",R("setup.opt.all")).action(async e=>{e.key||j.some(o=>e[o.option])||(e.key=A("SETUP_KEY")?.trim()||void 0);const o=Boolean(e.key||j.some(o=>e[o.option])),t=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,s="zh_CN"===i.getLocale()?"<你的 Key>":"<your key>";if(!o&&!t)throw S(i.t("setup.usage"),`${C} setup --key ${s}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw S(i.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),`${C} setup --claude-official on|off`,"invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw S(i.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),`${C} setup --desktop-registry on|off`,"invalid_value");await v({key:e.key,...Object.fromEntries(j.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})}),p(L,{...N("setup",[[`${C} init`,"setup.alt.init"],[`${C} config <tool>`,"setup.alt.config"],[`${C} auth <key>`,"setup.alt.auth"]]),sections:[{title:R("setup.autodetect_title"),rows:[["Claude",R("setup.autodetect.claude")],["GPT",R("setup.autodetect.gpt")],["Grok",R("setup.autodetect.grok")],["Gemini",R("setup.autodetect.gemini")]]}],examples:[K(`${C} setup --key sk-xxx`,"setup.ex.key"),K(`${C} setup --install --key sk-xxx`,"setup.ex.install"),K(`${C} setup --claudekey sk-a --codexkey sk-b --agykey sk-g`,"setup.ex.split"),K(`${C} setup --force --key sk-xxx`,"setup.ex.force"),K(`${C} setup --base ${E} --key sk-xxx`,"setup.ex.base")]});const T=z.command("init").summary(R("init.summary")).description(R("init.description")).action(async()=>{await r.runFirstTimeSetup()});p(T,{...N("init",[[`${C} setup --key <key>`,"init.alt.setup"],[`${C}`,"init.alt.menu"]]),examples:[K(`${C} init`,"init.ex.run"),K(`${C} init --base ${E}`,"init.ex.base"),K(`${C}`,"init.ex.menu")]});const U=z.command("auth").summary(R("auth.summary")).description(R("auth.description")).argument("[token]",R("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});P(U);const B=U.command("revoke").description(R("auth.revoke")).action(async()=>{await d(["revoke"])});p(B,{examples:[K(`${C} auth revoke`,"auth.ex.revoke_ask"),K(`${C} auth revoke --yes`,"auth.ex.revoke")]});const H=U.command("reload <tool>").description(R("auth.reload")).action(async e=>{await d(["reload",e])});p(H,{examples:[K(`${C} auth reload claude-code`,"auth.ex.reload"),K(`${C} auth reload claude-code --json`,"auth.ex.reload_json")]}),p(U,{...N("auth",[[`${C} setup --key <key>`,"auth.alt.setup"]]),examples:[K(`${C} auth`,"auth.ex.prompt"),K(`${C} auth sk-xxx --non-interactive`,"auth.ex.save"),K(`${C} auth revoke --yes`,"auth.ex.revoke"),K(`${C} auth reload claude-code`,"auth.ex.reload")]});const M=z.command("config").summary(R("config.summary")).description(R("config.description")).argument("[args...]",R("config.arg.args")).option("-f, --force",R("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await f(o.force?[...e,"--force"]:e)});p(M,{...N("config",[[`${C} setup --force --key <key>`,"config.alt.setup"],[`${C} status`,"config.alt.status"]]),sections:[{title:R("config.subcommands_title"),rows:[["<tool>",R("config.sub.tool")],["<tool> --force",R("config.sub.tool_force")],["<tool> --non-interactive",R("config.sub.tool_non_interactive")],["<tool> remove",R("config.sub.tool_remove")],["<tool> restore",R("config.sub.tool_restore")],["<tool> backups",R("config.sub.tool_backups")],["<tool> clear-model",R("config.sub.tool_clear_model")],["tool-model list",R("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",R("config.sub.tool_model_set")],["tool-model clear <tool>",R("config.sub.tool_model_clear")],["profile list",R("config.sub.profile_list")],["profile create <name>",R("config.sub.profile_create")],["profile use <name>",R("config.sub.profile_use")],["profile delete <name>",R("config.sub.profile_delete")],["preset list",R("config.sub.preset_list")],["preset save <name>",R("config.sub.preset_save")],["preset use <name>",R("config.sub.preset_use")],["preset delete <name>",R("config.sub.preset_delete")],["backup list",R("config.sub.backup_list")],["backup create [label]",R("config.sub.backup_create")],["backup restore <name>",R("config.sub.backup_restore")]]},{title:R("config.tools_title"),rows:Object.values(c).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[K(`${C} config codex`,"config.ex.menu"),K(`${C} config claude-code --force`,"config.ex.force"),K(`${C} config tool-model set codex gpt-6-astra`,"config.ex.tool_model"),K(`${C} config profile create work`,"config.ex.profile"),K(`${C} config codex remove`,"config.ex.remove")]});const q=z.command("base").summary(R("base.summary")).description(R("base.description")).argument("[target]",R("base.arg.target")).action(async e=>{await O(e)});p(q,{...N("base",[[`${C} doctor`,"base.alt.doctor"],[`${C} bench`,"base.alt.bench"]]),sections:[{title:R("base.targets_title"),rows:[[R("base.target.none_term"),R("base.target.none")],[R("base.target.index_term"),R("base.target.index")],[R("base.target.url_term"),R("base.target.url")],["auto",R("base.target.auto")],["default",R("base.target.default",{url:l})]]}],examples:[K(`${C} base`,"base.ex.list"),K(`${C} base auto`,"base.ex.auto"),K(`${C} base 2`,"base.ex.index"),K(`${C} base ${E}`,"base.ex.url"),K(`${C} base default`,"base.ex.default")]}),z.commandsGroup(R("group.diagnose"));const F=z.command("status").summary(R("status.summary")).description(R("status.description")).action(async()=>{await x()});p(F,{...N("status",[[`${C} doctor`,"status.alt.doctor"]]),examples:[K(`${C} status`,"status.ex.show"),K(`${C} status --json`,"status.ex.json")]});const J=z.command("doctor").summary(R("doctor.summary")).description(R("doctor.description")).option("--deep",R("doctor.opt.deep")).option("--report",R("doctor.opt.report")).action(async e=>{await g({deep:e.deep,report:e.report})});p(J,{...N("doctor",[[`${C} base auto`,"doctor.alt.base"],[`${C} logs tail`,"doctor.alt.logs"]]),examples:[K(`${C} doctor`,"doctor.ex.run"),K(`${C} doctor --deep`,"doctor.ex.deep"),K(`${C} doctor --report`,"doctor.ex.report")]});const Y=z.command("bench").summary(R("bench.summary")).description(R("bench.description")).option("--samples <n>",R("bench.opt.samples"),"5").action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),await $(o)});p(Y,{...N("bench",[[`${C} base`,"bench.alt.base"]]),examples:[K(`${C} bench`,"bench.ex.run"),K(`${C} bench --samples 3`,"bench.ex.samples"),K(`${C} bench --json`,"bench.ex.json")]});const D=z.command("logs").summary(R("logs.summary")).description(R("logs.description")).argument("[action]",R("logs.arg.action")).argument("[file]",R("logs.arg.file")).action(async(e,o)=>{const t=[];e&&t.push(e),o&&t.push(o),await h(t)});p(D,{...N("logs",[[`${C} doctor`,"logs.alt.doctor"]]),sections:[{title:R("logs.actions_title"),rows:[["list",R("logs.action.list")],["tail [file]",R("logs.action.tail")],["path",R("logs.action.path")]]}],examples:[K(`${C} logs`,"logs.ex.list"),K(`${C} logs tail`,"logs.ex.tail"),K(`${C} logs path`,"logs.ex.path")]}),z.commandsGroup(R("group.maintain"));const I=z.command("upgrade").summary(R("upgrade.summary")).description(R("upgrade.description")).argument("[tools...]",R("upgrade.arg.tools")).action(async(e=[])=>{await _(e)});p(I,{...N("upgrade",[[`${C} update`,"upgrade.alt.update"]]),examples:[K(`${C} upgrade`,"upgrade.ex.all"),K(`${C} upgrade claude-code`,"upgrade.ex.one"),K(`${C} upgrade codex agy`,"upgrade.ex.many")]});const Q=z.command("refresh").summary(R("refresh.summary")).description(R("refresh.description")).action(async()=>{await y()});p(Q,{...N("refresh",[[`${C} setup --key <你的 Key>`,"refresh.alt.setup"]]),examples:[K(`${C} refresh`,"refresh.ex.run"),K(`${C} refresh --base ${G}`,"refresh.ex.base")]});const V=z.command("update").summary(R("update.summary")).description(R("update.description")).action(async()=>{await k()});p(V,{...N("update",[[`${C} upgrade`,"update.alt.upgrade"]]),examples:[K(`${C} update`,"update.ex.check"),K(`${C} update --json`,"update.ex.json")]});const W=z.command("codex").summary(R("codex.summary")).description(R("codex.description"));P(W);const X=W.command("sessions").summary(R("codex_sessions.summary")).description(R("codex_sessions.description")).option("--to <provider>",R("codex_sessions.opt.to")).option("--undo <dir>",R("codex_sessions.opt.undo")).action(async e=>{await w(e)});p(W,{...N("codex"),examples:[K(`${C} codex sessions`,"codex_sessions.ex.move"),K(`${C} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]}),p(X,{...N("codex_sessions",[[`${C} codex sessions --undo <dir>`,"codex_sessions.alt.undo"]]),examples:[K(`${C} codex sessions`,"codex_sessions.ex.move"),K(`${C} codex sessions --to custom`,"codex_sessions.ex.to"),K(`${C} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]});const Z=z.command("lang").summary(R("lang.summary")).description(R("lang.description"));P(Z);const ee=Z.command("show").description(R("lang.show")).action(async()=>{await u(["show"])}),oe=Z.command("set <locale>").description(R("lang.set")).action(async e=>{await u(["set",e])}),te=[K(`${C} lang show`,"lang.ex.show"),K(`${C} lang set en_US`,"lang.ex.set_en"),K(`${C} lang set zh_CN`,"lang.ex.set_zh")];p(Z,{...N("lang",[[`${C} enter lang`,"lang.alt.enter"]]),examples:te}),p(ee,{examples:[te[0],K(`${C} lang show --json`,"lang.ex.show_json")]}),p(oe,{examples:te.slice(1)});const se=z.command("completion").summary(R("completion.summary")).description(R("completion.description")).argument("<shell>",R("completion.arg.shell")).action(async e=>{await b([e])});p(se,{...N("completion"),examples:[K(`${C} completion bash > ~/.${C}-completion.bash`,"completion.ex.bash"),K(`${C} completion zsh > ~/.${C}-completion.zsh`,"completion.ex.zsh"),K(`${C} completion fish > ~/.config/fish/completions/${C}.fish`,"completion.ex.fish")]});const ae=z.command("enter").summary(R("enter.summary")).description(R("enter.description")).argument("[option]",R("enter.arg.option")).action(async e=>{if(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 f([e])}else await r.run()});p(ae,{...N("enter",[[`${C}`,"enter.alt.menu"],[`${C} config <tool>`,"enter.alt.config"]]),sections:[{title:R("enter.options_title"),rows:[[R("enter.option.none_term"),R("enter.option.none")],["lang",R("enter.option.lang")],["apikey",R("enter.option.apikey")],["models",R("enter.option.models")],["<tool>",R("enter.option.tool")]]}],examples:[K(`${C} enter`,"enter.ex.menu"),K(`${C} enter models`,"enter.ex.models"),K(`${C} enter codex`,"enter.ex.tool")]}),P(z),z.action(async()=>{await r.run()}),p(z,{examples:[K(`${C}`,"root.ex.menu"),K(`${C} setup --key sk-xxx`,"root.ex.setup"),K(`${C} doctor`,"root.ex.doctor"),K(`${C} base auto`,"root.ex.base"),K(`${C} config codex`,"root.ex.config")]});const ne=e=>{for(const o of e.commands)o.helpOption("-h, --help",R("global.help")),ne(o)};return ne(z),z}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step events and diagnostic reports for customer support, sent to the gateway the user is
|
|
3
|
+
* configured against (`/api/platform/vibecode/telemetry` and `/report` on new-api). Support
|
|
4
|
+
* looks them up by user, install id or diagnostic code in the admin console.
|
|
5
|
+
*
|
|
6
|
+
* Sent: CLI version, OS / arch / Node version, the install id, the command and step names,
|
|
7
|
+
* status, duration and error messages. Never sent: conversation content, file contents,
|
|
8
|
+
* the API key itself (it only authenticates the request, as any gateway call does).
|
|
9
|
+
* `<PREFIX>_TELEMETRY=0` turns events and the user agent's install id off.
|
|
10
|
+
*
|
|
11
|
+
* Everything here is best effort: a few seconds at most, never an error for the user.
|
|
12
|
+
*/
|
|
13
|
+
export type StepStatus = 'start' | 'ok' | 'fail' | 'timeout' | 'fallback' | 'cancel' | 'skip';
|
|
14
|
+
export interface TelemetryEvent {
|
|
15
|
+
ts: number;
|
|
16
|
+
session: string;
|
|
17
|
+
command: string;
|
|
18
|
+
step: string;
|
|
19
|
+
status: StepStatus;
|
|
20
|
+
duration_ms?: number;
|
|
21
|
+
error?: string;
|
|
22
|
+
detail?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/** Off with `<PREFIX>_TELEMETRY=0` (also `false` / `off`), and always under the test runner. */
|
|
25
|
+
export declare function telemetryEnabled(): boolean;
|
|
26
|
+
/** Tests capture what would be sent. */
|
|
27
|
+
export declare function setTelemetrySenderForTests(fake: ((path: string, body: unknown, timeoutMs: number) => Promise<unknown>) | null): void;
|
|
28
|
+
/** Who is calling, for every request to the gateway. */
|
|
29
|
+
export declare function clientHeaders(): Record<string, string>;
|
|
30
|
+
/**
|
|
31
|
+
* Adds clientHeaders() to every request this process makes to a gateway address (built-in,
|
|
32
|
+
* published or the current one); requests elsewhere (npmmirror, GitHub …) are left as they are.
|
|
33
|
+
* Done once at startup instead of at each call site, which also take injected fetches in tests.
|
|
34
|
+
*/
|
|
35
|
+
export declare function installClientHeaders(): void;
|
|
36
|
+
/** Whether sends are still running (the CLI exits without waiting out their timeout). */
|
|
37
|
+
export declare function telemetryPending(): boolean;
|
|
38
|
+
/** API keys anywhere in a text (error messages, logs) become `sk-…abcd`. */
|
|
39
|
+
export declare function maskSecrets(text: string): string;
|
|
40
|
+
/** The command this process runs (`setup`, `config`, … or `wizard`), recorded with every event. */
|
|
41
|
+
export declare function setTelemetryCommand(name: string): void;
|
|
42
|
+
export declare function track(step: string, status: StepStatus, extra?: {
|
|
43
|
+
duration_ms?: number;
|
|
44
|
+
error?: unknown;
|
|
45
|
+
detail?: Record<string, unknown>;
|
|
46
|
+
}): void;
|
|
47
|
+
/** Runs one step and records its start, then ok / fail with the duration. */
|
|
48
|
+
export declare function trackStep<T>(step: string, run: () => Promise<T> | T, detail?: Record<string, unknown>): Promise<T>;
|
|
49
|
+
/** Sends what is queued and waits for it, at most `timeoutMs`; called before the process exits. */
|
|
50
|
+
export declare function flushTelemetry(timeoutMs?: number): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Uploads a diagnostic report (the user asked for it, so `<PREFIX>_TELEMETRY=0` doesn't apply);
|
|
53
|
+
* resolves to the code support looks it up by, or null when it didn't go through.
|
|
54
|
+
*/
|
|
55
|
+
export declare function uploadReport(report: Record<string, unknown>): Promise<string | null>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{randomUUID as e}from"crypto";import{arch as t,release as r}from"os";import{brand as n,brandEnv as o,CLI_NAME as s}from"./brand.js";import{clientVersion as a,installId as i}from"./client-config.js";import{configManager as c}from"./config.js";import{gatewayAddresses as l}from"./gateway-addresses.js";const u=e();let d="wizard",f=[];const m=new Set;let p=null,h=b;export function telemetryEnabled(){if(process.env.VITEST&&!g)return!1;const e=o("TELEMETRY")?.trim().toLowerCase();return!("0"===e||"false"===e||"off"===e)}let g=!1;export function setTelemetrySenderForTests(e){h=e??b,g=null!==e,f=[]}export function clientHeaders(){const e=`${s}/${a()} (${process.platform} ${r()}; ${t()}) node/${process.versions.node}`;return telemetryEnabled()?{"User-Agent":e,"X-VibeCLI-Install-Id":i()}:{"User-Agent":e}}export function installClientHeaders(){const e=globalThis.fetch;if(!e||e.vibecliHeaders)return;const t=(t,r)=>{try{const n=new URL("string"==typeof t||t instanceof URL?t.toString():t.url);if(new Set([c.getBaseUrl(),...l().map(e=>e.url)].map(e=>new URL(e).host)).has(n.host)){const n=new Headers(r?.headers??(t instanceof Request?t.headers:void 0));for(const[e,t]of Object.entries(clientHeaders()))n.has(e)||n.set(e,t);return e(t,{...r,headers:n})}}catch{}return e(t,r)};t.vibecliHeaders=!0,globalThis.fetch=t}export function telemetryPending(){return m.size>0}function y(){return{install_id:i(),cli_version:a(),brand:n().id,os:process.platform,os_release:r(),arch:t(),node_version:process.versions.node}}export function maskSecrets(e){return e.replace(/\b(sk-[A-Za-z0-9_-]{2})[A-Za-z0-9_-]{8,}([A-Za-z0-9_-]{4})\b/g,"$1…$2").replace(/(Bearer\s+)[A-Za-z0-9._~+/=-]{8,}/gi,"$1…")}export function setTelemetryCommand(e){d=e}export function track(e,t,r={}){if(!telemetryEnabled())return;const n=void 0===r.error?void 0:maskSecrets(r.error instanceof Error?r.error.message:String(r.error)).slice(0,2e3);f.push({ts:Date.now(),session:u,command:d,step:e,status:t,...void 0!==r.duration_ms?{duration_ms:Math.round(r.duration_ms)}:{},...n?{error:n}:{},...r.detail?{detail:r.detail}:{}}),"start"===t?w():p||(p=setTimeout(w,500),p.unref())}export async function trackStep(e,t,r){const n=Date.now();track(e,"start",r?{detail:r}:{});try{const r=await t();return track(e,"ok",{duration_ms:Date.now()-n}),r}catch(t){throw track(e,"fail",{duration_ms:Date.now()-n,error:t}),t}}function w(){if(p&&(clearTimeout(p),p=null),0===f.length)return;const e=f.splice(0,50),t=h("/api/platform/vibecode/telemetry",{...y(),events:e},3e3).then(()=>{},()=>{}).finally(()=>m.delete(t));m.add(t),f.length>0&&w()}export async function flushTelemetry(e=1500){w(),0!==m.size&&await Promise.race([Promise.allSettled([...m]),new Promise(t=>setTimeout(t,e).unref())])}export async function uploadReport(e){try{const t=await h("/api/platform/vibecode/report",{...y(),report:e},2e4),r=t?.data?.code;return"string"==typeof r&&r?r:null}catch{return null}}async function b(e,t,r){const n=c.getApiKey()?.trim(),o=await fetch(new URL(e,c.getBaseUrl()).toString(),{method:"POST",headers:{"Content-Type":"application/json",...clientHeaders(),...n?{Authorization:`Bearer ${n}`}:{}},body:JSON.stringify(t),signal:AbortSignal.timeout(r)});if(!o.ok)throw new Error(`HTTP ${o.status}`);return o.json().catch(()=>null)}
|
|
@@ -41,6 +41,7 @@ export declare class ToolManager {
|
|
|
41
41
|
*/
|
|
42
42
|
nativeLauncher(toolName: string): string | null;
|
|
43
43
|
installTool(toolName: string): Promise<void>;
|
|
44
|
+
private installToolNow;
|
|
44
45
|
getToolConfig(toolName: string): any;
|
|
45
46
|
updateToolConfig(toolName: string, config: any): void;
|
|
46
47
|
/**
|
|
@@ -63,6 +64,7 @@ export declare class ToolManager {
|
|
|
63
64
|
applyPrivateConfig(toolName: string, apiKey: string, models: VibecliModels, options?: {
|
|
64
65
|
force?: boolean;
|
|
65
66
|
}): Promise<void>;
|
|
67
|
+
private applyPrivateConfigNow;
|
|
66
68
|
/** Post-apply follow-ups the adapter wants shown to the user (may be empty). */
|
|
67
69
|
applyNotes(toolName: string): ApplyNote[];
|
|
68
70
|
/**
|
package/dist/lib/tool-manager.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{execSync as o,spawnSync as t}from"child_process";import{i18n as n}from"./i18n.js";import e from"inquirer";import r from"chalk";import{logger as l}from"../utils/logger.js";import{configManager as i}from"./config.js";import{getAdapter as s,listAdapters as a,TOOL_ADAPTERS as c}from"./tools/registry.js";import{backupBeforeWrite as d,listBackups as p,restoreBackup as m}from"./tools/backup.js";import{existsSync as u,rmSync as f}from"fs";import{join as g}from"path";import{toolHome as h}from"./tools/types.js";import{stringWidth as w}from"../utils/string-width.js";import{resolveModelCatalog as y}from"./model-catalog.js";import{compareVersions as P,getToolMinVersion as T}from"./model-registry.js";import{findInstalls as
|
|
1
|
+
import{execSync as o,spawnSync as t}from"child_process";import{i18n as n}from"./i18n.js";import e from"inquirer";import r from"chalk";import{logger as l}from"../utils/logger.js";import{configManager as i}from"./config.js";import{getAdapter as s,listAdapters as a,TOOL_ADAPTERS as c}from"./tools/registry.js";import{backupBeforeWrite as d,listBackups as p,restoreBackup as m}from"./tools/backup.js";import{existsSync as u,rmSync as f}from"fs";import{join as g}from"path";import{toolHome as h}from"./tools/types.js";import{stringWidth as w}from"../utils/string-width.js";import{resolveModelCatalog as y}from"./model-catalog.js";import{compareVersions as P,getToolMinVersion as T}from"./model-registry.js";import{findInstalls as $,forgetInstalls as k,installLabel as C,mirrorInstallCommand as v,npmMirrorInstallCommand as E}from"./tools/tool-installs.js";import{mirrorInstall as _}from"./tool-upgrade.js";import{CLI_NAME as S}from"./brand.js";import{track as O,trackStep as M}from"./telemetry.js";export{P as compareVersions};function N(o){const t=c[o];return{name:t.name,command:t.command,installCommand:t.installCommand,configPath:t.configPath,displayName:t.displayName,...t.hidden?{hidden:!0}:{},...t.isInstalled?{gui:!0}:{}}}function j(){const o=new Set;for(const t of i.listProfiles()){const n=i.getProfile(t);for(const t of[n.api_key,...Object.values(n.tool_api_keys??{})])t?.trim()&&o.add(t.trim())}return[...o]}export const SUPPORTED_TOOLS=Object.fromEntries(Object.keys(c).map(o=>[o,N(o)]));export class ToolManager{static instance;constructor(){}static getInstance(){return ToolManager.instance||(ToolManager.instance=new ToolManager),ToolManager.instance}isToolInstalled(o){if(!SUPPORTED_TOOLS[o])return!1;const t=s(o);if(t?.isInstalled)try{return t.isInstalled()}catch{return!1}return this.isOnPath(o)||null!==this.nativeLauncher(o)}isOnPath(t){const n=SUPPORTED_TOOLS[t];if(!n)return!1;try{const t="win32"===process.platform?`where ${n.command}`:`which ${n.command}`;return o(t,{stdio:"pipe"}),!0}catch{return!1}}nativeLauncher(o){const t=s(o),n=t?.installSpec?.native?.binDir;if(!t||!n)return null;const e="win32"===process.platform?`${t.command}.exe`:t.command,r=g(h(),...n,e);return u(r)?r:null}async installTool(o){return M(`install:${o}`,()=>this.installToolNow(o))}async installToolNow(t){const l=SUPPORTED_TOOLS[t];if(!l)throw new Error(`Unknown tool: ${t}`);const i=s(t)?.installSpec;if(i&&(i.mirrorScript||i.npmPackage)){const o=v(i);if(_(i)&&(k(),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:l.displayName,command:o}))),i.mirrorScript&&i.npmPackage&&console.log(r.yellow(" ! "+n.t("install.manual_npm",{command:E(i)}))),new Error(`Failed to install ${l.displayName}`)}const a=l.installCommand;console.log(r.gray("$ ")+r.white(a));try{return o(a,{stdio:"inherit"}),k(),void console.log(r.green("√ "+n.t("wizard.tool_installed")))}catch(o){if(console.log(r.red("× "+n.t("wizard.install_failed"))),!/EACCES|EPERM|permission denied/i.test(`${o?.message??""}${o?.stderr??""}`)&&243!==o?.status&&!a.startsWith("npm "))throw new Error(`Failed to install ${l.displayName}: ${o}`);console.log(r.yellow(" ! "+("win32"===process.platform?n.t("install.permission_windows",{command:a}):n.t("install.permission_unix",{command:a}))))}const{action:c}=await e.prompt([{type:"list",name:"action",message:n.t("install.what_next"),choices:[{name:n.t("install.installed_continue"),value:"continue"},{name:n.t("install.cancel_install"),value:"cancel"}]}]);if("cancel"===c)throw new Error(n.t("install.user_cancelled"));if(k(),!this.isToolInstalled(t))throw console.log(r.red("× "+n.t("install.still_not_installed",{tool:l.displayName}))),new Error(`${l.displayName} is not installed`);console.log(r.green("√ "+n.t("install.verified_success",{tool:l.displayName})))}getToolConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);try{return t.getConfig()}catch(t){return l.warn(`Failed to read config for ${o}:`,t),l.logError(`ToolManager.getToolConfig(${o})`,t),null}}updateToolConfig(o,t){const n=s(o);if(!n)throw new Error(`Unknown tool: ${o}`);if(!n.updateConfig)throw new Error(`Tool ${o} does not support raw config updates`);n.updateConfig(t)}forceResetConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);const n=t.forceResetPaths?t.forceResetPaths():this.backupPathsFor(t),e=[];for(const o of n)u(o)&&(d(o),f(o,{force:!0}),e.push(o));return e}loadPrivateConfig(o,t,n,e,r={}){const l=s(o);if(!l)throw new Error(`Unknown tool: ${o}`);r.force&&this.forceResetConfig(o),l.loadPrivateConfig({apiKey:t,baseUrl:i.getBaseUrl(),models:n,settings:i.getToolSettings(o),...e?{catalog:e}:{}})}async applyPrivateConfig(o,t,n,e={}){const r=this.installedVersion(o);return M(`apply:${o}`,()=>this.applyPrivateConfigNow(o,t,n,e),{...r?{tool_version:r}:{},...e.force?{force:!0}:{}})}async applyPrivateConfigNow(o,t,n,e){const r=s(o);if(!r)throw new Error(`Unknown tool: ${o}`);const l=r.wantsModelCatalog?await y(t):null;e.force?this.loadPrivateConfig(o,t,n,l??void 0,{force:!0}):l?this.loadPrivateConfig(o,t,n,l):this.loadPrivateConfig(o,t,n)}applyNotes(o){const t=s(o);if(!t)return[];const e=[];try{t.applyNotes&&e.push(...t.applyNotes())}catch(t){l.logError(`ToolManager.applyNotes(${o})`,t)}const r=this.outdatedVersion(o);if(r){e.push({kind:"action",text:n.t("tools.version_outdated",{current:r.current,min:r.min,upgrade:t.installSpec?`${S} upgrade ${o}`:t.upgradeCommand||t.installCommand})});for(const o of t.upgradeHints?.(r.min)??[])e.push({kind:"action",text:o})}const i=t.installSpec?$(t.installSpec):[];return i.length>1&&e.push({kind:"action",text:n.t("upgrade.duplicates_note",{count:String(i.length),active:C(i[0]),others:i.slice(1).map(C).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))l.record(`${n}: ${o.text}`);const i=e.filter(o=>"summary"===o.kind).map(o=>o.text).join(";"),s=" ".repeat(Math.max(1,t-w(n)));console.log(r.green("√ "+n)+(i?s+i:""));for(const o of e.filter(o=>"action"===o.kind))console.log(r.yellow(" ! "+o.text))}installedVersion(o){const n=s(o);if(!n)return null;if(n.installSpec)return $(n.installSpec)[0]?.version??null;if(n.installedVersion)try{return n.installedVersion()}catch(t){return l.logError(`ToolManager.installedVersion(${o})`,t),null}if(n.isInstalled)return null;try{const o={encoding:"utf-8",timeout:1e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]},e=`${("win32"===process.platform?t(`${n.command} --version`,{...o,shell:!0}):t(n.command,["--version"],o)).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return e?e[0]:null}catch{return null}}outdatedVersion(o){const t=T(o);if(!t)return null;const n=this.installedVersion(o);return n&&P(n,t)<0?{current:n,min:t}:null}unloadPrivateConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);try{t.unloadPrivateConfig({savedKeys:j()}),O(`remove:${o}`,"ok")}catch(t){throw O(`remove:${o}`,"fail",{error:t}),t}let e=[];try{e=t.unloadNotes?.()??[]}catch(t){l.logError(`ToolManager.unloadNotes(${o})`,t)}return e.length>0?e:[{kind:"action",text:n.t("config.reopen_hint",{tool:t.displayName})}]}async clearPinnedModels(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);if(i.setToolModel(o,null),!t.clearPinnedModels)return[];const n=i.getApiKeyForTool(o),e=t.wantsModelCatalog&&n?await y(n):null;return t.clearPinnedModels(e??void 0)}supportsClearPinnedModels(o){return Boolean(s(o)?.clearPinnedModels)}detectCurrentConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);return t.detectCurrentConfig()}backupPathsFor(o){return o.backupPaths?o.backupPaths():[o.configPath]}listToolBackups(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(t).map(o=>({file:o,backups:p(o)}))}restorePrivateConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(t).map(o=>({file:o,result:m(o)}))}getInstalledTools(){return Object.keys(SUPPORTED_TOOLS).filter(o=>this.isToolInstalled(o))}getSupportedTools(){return a().filter(o=>!o.hidden).map(o=>N(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();
|
package/dist/lib/tool-upgrade.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawnSync as r}from"child_process";import{rmSync as
|
|
1
|
+
import{spawnSync as r}from"child_process";import{rmSync as o}from"fs";import{join as e}from"path";import t from"chalk";import n from"inquirer";import{i18n as i}from"./i18n.js";import{logger as a}from"../utils/logger.js";import{compareVersions as s,getToolMinVersion as l}from"./model-registry.js";import{getAdapter as c}from"./tools/registry.js";import{findInstalls as p,forgetInstalls as m,installLabel as u,npmMirrorInstallCommand as d,npmUninstallCommand as g}from"./tools/tool-installs.js";import{toolHome as f}from"./tools/types.js";import{isNonInteractive as w,shouldAutoConfirm as h}from"./runtime-options.js";import{track as y}from"./telemetry.js";let v=!1,_=(o,e,n)=>{v=!1,console.log(t.gray("$ ")+[o,...e].join(" "));const i="win32"!==process.platform||/\.exe$/i.test(o)?r(o,e,{stdio:"inherit",timeout:n}):r([o,...e].map(r=>/\s/.test(r)?`"${r}"`:r).join(" "),{stdio:"inherit",shell:!0,timeout:n});return i.error&&a.logError(`upgrade: ${o}`,i.error),v="ETIMEDOUT"===i.error?.code,0===i.status};export function setUpgradeRunnerForTests(r){_=r}const k=3e5;export function mirrorInstall(r){if(!r.mirrorScript)return b(r);console.log(t.gray(i.t("install.downloading")));const o=`install-script:${r.command}`,e=Date.now();y(o,"start");const n="win32"===process.platform?_("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",`irm ${r.mirrorScript.ps1} -TimeoutSec 30 | iex`],k):_("sh",["-c",`script=$(curl -fsSL --connect-timeout 15 --max-time 60 ${r.mirrorScript.sh}) && printf '%s\\n' "$script" | sh`],k);return y(o,n?"ok":v?"timeout":"fail",{duration_ms:Date.now()-e}),n||!r.npmPackage?n:(console.log(t.yellow(" ! "+i.t("install.script_failed_npm"))),y(o,"fallback"),b(r))}function b(r){const[o,...e]=d(r).split(" "),n=`install-npm:${r.command}`,a=Date.now();y(n,"start");const s=_(o,e);return y(n,s?"ok":"fail",{duration_ms:Date.now()-a}),s||"win32"===process.platform||console.log(t.yellow(" ! "+i.t("upgrade.npm_permission",{command:d(r)}))),s}function $(r,t){switch(t.kind){case"npm":r.npmPackage&&_("npm",["uninstall","-g",r.npmPackage]);break;case"brew":r.brew&&_("brew",["uninstall",r.brew]);break;case"native":try{o(t.path,{force:!0});for(const t of r.native?.dataDirs??[])o(e(f(),...t),{recursive:!0,force:!0})}catch(r){a.logError("upgrade: remove native copy",r)}break;default:return!1}return m(),!p(r).some(r=>r.path===t.path)}function j(r,o){switch(o.kind){case"npm":return g(r);case"brew":return`brew uninstall ${r.brew}`;case"native":return i.t("upgrade.delete_paths",{paths:[o.path,...(r.native?.dataDirs??[]).map(r=>e(f(),...r))].join("、")});default:return i.t("upgrade.delete_paths",{paths:o.path})}}export async function upgradeTool(r){const o=Date.now();y(`upgrade:${r}`,"start");try{const e=await async function(r){const o=c(r),e=o?.installSpec;if(!o||!e)throw new Error(i.t("upgrade.unsupported",{tool:r}));const d=o.displayName;m();const g=p(e);if(console.log(t.bold(`\n${d}`)),0===g.length)console.log(i.t("upgrade.not_installed_installing",{tool:d})),mirrorInstall(e);else{const r=g[0];console.log(t.gray(" "+i.t("upgrade.current",{copy:u(r)})));const o=function(r,o){switch(o.kind){case"native":return _(o.path,r.native?.updateArgs??["update"],r.native?.updateTimeoutMs);case"npm":return b(r);case"brew":return!!r.brew&&_("brew",["upgrade",r.brew]);default:return!1}}(e,r);o||"other"!==r.kind?o||"npm"===r.kind||"native"===r.kind&&await async function(r){const o=r.native?.mirrorUpdate;if(!o)return!1;console.log(t.yellow(" ! "+i.t("upgrade.native_mirror_trying")));try{const{version:r,manifestVerified:e}=await o();return console.log(t.green(" √ "+i.t(e?"upgrade.native_mirror_done_verified":"upgrade.native_mirror_done",{version:r}))),!0}catch(r){return a.logError("upgrade: native mirror",r),console.log(t.yellow(" ! "+i.t("upgrade.native_mirror_failed",{reason:r instanceof Error?r.message:String(r)}))),!1}}(e)||(console.log(t.yellow(" ! "+i.t("upgrade.fallback_mirror"))),mirrorInstall(e)):console.log(t.yellow(" ! "+i.t("upgrade.unknown_install",{path:r.path})))}m(),await async function(r,o){const e=p(r);if(e.length<2)return;const a=function(r){return r.reduce((r,o)=>o.version&&(!r.version||s(o.version,r.version)>0)?o:r)}(e),l=e.filter(r=>r!==a);console.log(t.yellow(" ! "+i.t("upgrade.duplicates",{tool:o,keep:u(a),others:l.map(u).join("、")})));let c=h();c||w()||!process.stdin.isTTY||(c=(await n.prompt([{type:"confirm",name:"remove",message:i.t("upgrade.confirm_remove"),default:!0}])).remove);for(const o of l)c&&$(r,o)?console.log(t.green(" √ "+i.t("upgrade.removed",{copy:u(o)}))):console.log(t.yellow(" ! "+i.t("upgrade.remove_by_hand",{how:j(r,o)})))}(e,d),m();const f=p(e)[0];if(!f)return console.log(t.red(" × "+i.t("upgrade.still_missing",{tool:d}))),!1;const y=l(r);if(y&&f.version&&s(f.version,y)<0){console.log(t.yellow(" ! "+i.t("upgrade.still_old",{copy:u(f),min:y})));for(const r of o.upgradeHints?.(y)??[])console.log(t.yellow(" ! "+r));return!1}return console.log(t.green(" √ "+i.t("upgrade.done",{copy:u(f)}))),!0}(r);return y(`upgrade:${r}`,e?"ok":"fail",{duration_ms:Date.now()-o}),e}catch(e){throw y(`upgrade:${r}`,"fail",{duration_ms:Date.now()-o,error:e}),e}}
|
package/dist/locales/en_US.json
CHANGED
|
@@ -211,7 +211,11 @@
|
|
|
211
211
|
"other_addresses_none": "None of the other gateway addresses can be reached either; check your network or proxy",
|
|
212
212
|
"check_client_config": "Checking the gateway model config...",
|
|
213
213
|
"client_config": "Gateway model config",
|
|
214
|
-
"client_config_revision": "revision {{revision}}"
|
|
214
|
+
"client_config_revision": "revision {{revision}}",
|
|
215
|
+
"report_uploading": "Uploading diagnostics…",
|
|
216
|
+
"report_done": "Diagnostic code: {{code}} (give it to support; they can see these results and recent run history with it)",
|
|
217
|
+
"report_failed": "The diagnostics were not uploaded; send support a screenshot of the results above, and run {{cli}} doctor --report again once the network is back",
|
|
218
|
+
"report_hint": "When you need help from support, run {{cli}} doctor --report and give them the diagnostic code"
|
|
215
219
|
},
|
|
216
220
|
"preset": {
|
|
217
221
|
"claude_mix": "Claude Mix",
|
|
@@ -742,11 +746,13 @@
|
|
|
742
746
|
"summary": "Find configuration and network problems",
|
|
743
747
|
"description": "Checks the key, network, proxy, installed tools and their configs, and says how to fix what it finds.",
|
|
744
748
|
"opt": {
|
|
745
|
-
"deep": "Also send one real request through Claude Code (uses a little quota)"
|
|
749
|
+
"deep": "Also send one real request through Claude Code (uses a little quota)",
|
|
750
|
+
"report": "After the checks, upload diagnostics (results, tool versions, settings and recent run history; no keys or conversations) and get a code for support"
|
|
746
751
|
},
|
|
747
752
|
"ex": {
|
|
748
753
|
"run": "Run the checks",
|
|
749
|
-
"deep": "Include a real Claude Code request"
|
|
754
|
+
"deep": "Include a real Claude Code request",
|
|
755
|
+
"report": "Upload diagnostics and get a code for support"
|
|
750
756
|
},
|
|
751
757
|
"when": "When a tool fails (401, cannot connect, model not found) and you do not know why.",
|
|
752
758
|
"alt": {
|
package/dist/locales/zh_CN.json
CHANGED
|
@@ -211,7 +211,11 @@
|
|
|
211
211
|
"other_addresses_none": "其他接入地址也都连不上,请检查网络或代理",
|
|
212
212
|
"check_client_config": "正在检查网关模型配置...",
|
|
213
213
|
"client_config": "网关模型配置",
|
|
214
|
-
"client_config_revision": "修订 {{revision}}"
|
|
214
|
+
"client_config_revision": "修订 {{revision}}",
|
|
215
|
+
"report_uploading": "正在上传诊断信息…",
|
|
216
|
+
"report_done": "诊断码:{{code}}(把它发给客服,客服就能看到这次检查的结果和最近的运行记录)",
|
|
217
|
+
"report_failed": "诊断信息没有上传成功;可以截图上面的结果发给客服,网络恢复后再运行 {{cli}} doctor --report",
|
|
218
|
+
"report_hint": "需要客服帮忙时运行 {{cli}} doctor --report,把得到的诊断码发给客服"
|
|
215
219
|
},
|
|
216
220
|
"preset": {
|
|
217
221
|
"claude_mix": "Claude 混合",
|
|
@@ -742,11 +746,13 @@
|
|
|
742
746
|
"summary": "检查配置和网络问题",
|
|
743
747
|
"description": "检查 Key、网络、代理、已安装的工具和它们的配置,并给出处理办法。",
|
|
744
748
|
"opt": {
|
|
745
|
-
"deep": "再用 Claude Code 真实发一条请求(消耗少量额度)"
|
|
749
|
+
"deep": "再用 Claude Code 真实发一条请求(消耗少量额度)",
|
|
750
|
+
"report": "检查后上传诊断信息(检查结果、工具版本、设置和最近的运行记录,不含 Key 和对话内容),得到一个诊断码发给客服"
|
|
746
751
|
},
|
|
747
752
|
"ex": {
|
|
748
753
|
"run": "做一次检查",
|
|
749
|
-
"deep": "连 Claude Code 实际请求一起检查"
|
|
754
|
+
"deep": "连 Claude Code 实际请求一起检查",
|
|
755
|
+
"report": "上传诊断信息,得到诊断码发给客服"
|
|
750
756
|
},
|
|
751
757
|
"when": "工具报错(401、连不上、找不到模型)又不知道原因时。",
|
|
752
758
|
"alt": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeapi/api-helper",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.110",
|
|
4
4
|
"description": "CLI tool for managing AI coding assistants (Claude Code, Codex, OpenClaw, Hermes, AtomCode, Grok Build) with one unified config",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|