@vibeapi/api-helper 0.0.114 → 0.0.116
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/lib/auto-update.d.ts +4 -2
- package/dist/lib/auto-update.js +1 -1
- package/dist/lib/tool-manager.js +1 -1
- package/dist/lib/tool-upgrade.d.ts +18 -4
- package/dist/lib/tool-upgrade.js +1 -1
- package/dist/locales/en_US.json +3 -1
- package/dist/locales/zh_CN.json +3 -1
- package/package.json +1 -1
|
@@ -32,8 +32,10 @@ export declare function resolveNpmGlobalPrefix(root: string): string | null;
|
|
|
32
32
|
export declare function shouldSkipStartupUpdate(args: string[], env?: NodeJS.ProcessEnv): boolean;
|
|
33
33
|
/**
|
|
34
34
|
* npm.cmd / pnpm.cmd only start through a shell on Windows: Node ≥ 18.20.2 / 20.12.2 refuses to spawn
|
|
35
|
-
* .cmd files directly (spawnSync EINVAL). The command goes as one
|
|
36
|
-
*
|
|
35
|
+
* .cmd files directly (spawnSync EINVAL). The command goes as one string, since args plus `shell: true`
|
|
36
|
+
* is deprecated (DEP0190). Args are quoted (the npm prefix can contain spaces) but the command name is
|
|
37
|
+
* not: cmd.exe gives a quoted batch name found via PATH the wrong %~dp0, and npm.cmd then looks for
|
|
38
|
+
* npm-cli.js under the current directory (MODULE_NOT_FOUND, seen on Windows 11 with Node 24.11.1).
|
|
37
39
|
*/
|
|
38
40
|
export declare function windowsShellCommand(command: string, args: string[]): string;
|
|
39
41
|
export declare function runStartupUpdate(args: string[], options?: StartupUpdateOptions): Promise<StartupUpdateResult>;
|
package/dist/lib/auto-update.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{chmodSync as e,existsSync as t,mkdirSync as r,readFileSync as n,renameSync as o,writeFileSync as s}from"fs";import{homedir as a}from"os";import{dirname as l,join as i,sep as u}from"path";import{spawnSync as c}from"child_process";import p from"chalk";import{checkForUpdate as d,compareSemver as m,readLocalPackage as f,UPDATE_SOURCES as _}from"../commands/update.js";import{i18n as h}from"./i18n.js";import{isColorEnabled as g}from"./runtime-options.js";import{logger as x}from"../utils/logger.js";import{isHelpRequest as v}from"./cli-help.js";import{brand as y,brandEnvName as S}from"./brand.js";export const UPDATE_CHECK_INTERVAL_MS=216e5;export const INSTALL_RETRY_INTERVAL_MS=36e5;export const INSTALL_TIMEOUT_MS=45e3;function k(e,t){return g()?e(t):t}export function resolveUpdateCachePath(e=process.env){const t=e[S("CONFIG_DIR")]?.trim();if(t)return i(t,"update-state.json");const r=e[S("TEST_HOME")]?.trim();return i(r||a(),y().configDirName,"update-state.json")}export function isGlobalPackageInstall(e){return e.split(u).includes("node_modules")}export function isNpxExecution(e=process.env){return"exec"===e.npm_command||"npx"===e.npm_lifecycle_event}export function isPnpmGlobalInstall(e){return e.includes(`${u}.pnpm${u}`)||e.includes(`${u}pnpm${u}global${u}`)}export function resolveNpmGlobalPrefix(e){const t=`${u}node_modules${u}`,r=e.indexOf(t);if(r<0)return null;const n=e.slice(0,r);return n.endsWith(`${u}lib`)?l(n):n}export function shouldSkipStartupUpdate(e,t=process.env){return"1"===t[S("SKIP_AUTO_UPDATE")]||"1"===t[S("DISABLE_AUTO_UPDATE")]||(!(!["--json","--non-interactive","--dry-run","--help","-h","--version","-v"].some(t=>e.includes(t))&&!v(e))||e.includes("update")||e.includes("completion"))}function A(t,n,a,i,u){try{r(l(t),{recursive:!0,mode:448});const c=`${t}.tmp-${process.pid}`,p={package_name:n,checked_at:a,latest:i.latest,source:i.source,registry:i.registry,errors:i.errors,...void 0===u?{}:{install_attempted_at:u,install_attempted_version:i.latest||void 0}};s(c,JSON.stringify(p),{encoding:"utf-8",mode:384}),o(c,t),e(t,384)}catch(e){x.warn("Failed to persist update check cache:",e)}}export function windowsShellCommand(e,t){return[e,...t
|
|
1
|
+
import{chmodSync as e,existsSync as t,mkdirSync as r,readFileSync as n,renameSync as o,writeFileSync as s}from"fs";import{homedir as a}from"os";import{dirname as l,join as i,sep as u}from"path";import{spawnSync as c}from"child_process";import p from"chalk";import{checkForUpdate as d,compareSemver as m,readLocalPackage as f,UPDATE_SOURCES as _}from"../commands/update.js";import{i18n as h}from"./i18n.js";import{isColorEnabled as g}from"./runtime-options.js";import{logger as x}from"../utils/logger.js";import{isHelpRequest as v}from"./cli-help.js";import{brand as y,brandEnvName as S}from"./brand.js";export const UPDATE_CHECK_INTERVAL_MS=216e5;export const INSTALL_RETRY_INTERVAL_MS=36e5;export const INSTALL_TIMEOUT_MS=45e3;function k(e,t){return g()?e(t):t}export function resolveUpdateCachePath(e=process.env){const t=e[S("CONFIG_DIR")]?.trim();if(t)return i(t,"update-state.json");const r=e[S("TEST_HOME")]?.trim();return i(r||a(),y().configDirName,"update-state.json")}export function isGlobalPackageInstall(e){return e.split(u).includes("node_modules")}export function isNpxExecution(e=process.env){return"exec"===e.npm_command||"npx"===e.npm_lifecycle_event}export function isPnpmGlobalInstall(e){return e.includes(`${u}.pnpm${u}`)||e.includes(`${u}pnpm${u}global${u}`)}export function resolveNpmGlobalPrefix(e){const t=`${u}node_modules${u}`,r=e.indexOf(t);if(r<0)return null;const n=e.slice(0,r);return n.endsWith(`${u}lib`)?l(n):n}export function shouldSkipStartupUpdate(e,t=process.env){return"1"===t[S("SKIP_AUTO_UPDATE")]||"1"===t[S("DISABLE_AUTO_UPDATE")]||(!(!["--json","--non-interactive","--dry-run","--help","-h","--version","-v"].some(t=>e.includes(t))&&!v(e))||e.includes("update")||e.includes("completion"))}function A(t,n,a,i,u){try{r(l(t),{recursive:!0,mode:448});const c=`${t}.tmp-${process.pid}`,p={package_name:n,checked_at:a,latest:i.latest,source:i.source,registry:i.registry,errors:i.errors,...void 0===u?{}:{install_attempted_at:u,install_attempted_version:i.latest||void 0}};s(c,JSON.stringify(p),{encoding:"utf-8",mode:384}),o(c,t),e(t,384)}catch(e){x.warn("Failed to persist update check cache:",e)}}export function windowsShellCommand(e,t){return[e,...t.map(e=>`"${e}"`)].join(" ")}const P=(e,t)=>{const r={stdio:"inherit",timeout:45e3,killSignal:"SIGTERM"};return"win32"===process.platform?c(windowsShellCommand(e,t),{...r,shell:!0}):c(e,t,r)},$=(e,t)=>c(process.execPath,[process.argv[1],...e],{stdio:"inherit",env:t});export async function runStartupUpdate(e,r={}){const o=r.env||process.env,s=r.localPackage||f(),a=r.globalInstall??isGlobalPackageInstall(s.root),l=r.npx??isNpxExecution(o);if(!a||l||shouldSkipStartupUpdate(e,o))return{status:"skipped",handled:!1,source:null};const i=r.now??Date.now(),u=r.cachePath||resolveUpdateCachePath(o),c=function(e,r,o){try{if(!t(e))return null;const s=JSON.parse(n(e,"utf-8"));if(s.package_name!==r.name||!Number.isFinite(s.checked_at))return null;const a=s.latest?216e5:6e5;return o-s.checked_at>=a?null:{result:{current:r.version,latest:s.latest,up_to_date:s.latest?m(r.version,s.latest)>=0:null,source:s.source,registry:s.registry,errors:Array.isArray(s.errors)?s.errors:[],error:s.latest?null:(s.errors||[]).map(e=>`${e.source}: ${e.error}`).join("; ")||"unknown"},installAttemptedAt:s.latest&&s.install_attempted_version===s.latest&&Number.isFinite(s.install_attempted_at)?s.install_attempted_at:null}}catch{return null}}(u,s,i);let g=c?.result,x=c?.installAttemptedAt||null;if(g||(g=await d({localPackage:s,fetchFn:r.fetchFn}),A(u,s.name,i,g),x=null),!g.latest)return{status:"unavailable",handled:!1,source:null};if(g.up_to_date)return{status:"current",handled:!1,source:g.source};if(null!==x&&i-x<36e5)return{status:"update_failed",handled:!1,source:g.source};const v=r.output||console.log,y=r.errorOutput||console.error,T=r.installRunner||P,b=isPnpmGlobalInstall(s.root),w=b?"win32"===process.platform?"pnpm.cmd":"pnpm":"win32"===process.platform?"npm.cmd":"npm",I=b?null:resolveNpmGlobalPrefix(s.root);v(k(p.cyan,h.t("update.auto_installing",{version:g.latest})));let E=null,N="unknown";for(const e of _.map(e=>e.registry)){const t=T(w,b?["add","--global",`${s.name}@${g.latest}`,"--registry",e]:["install","--global",...I?["--prefix",I]:[],`${s.name}@${g.latest}`,"--registry",e,"--no-audit","--no-fund","--fetch-timeout=15000","--fetch-retries=1","--fetch-retry-mintimeout=1000","--fetch-retry-maxtimeout=3000"]);if(0===t.status){E=e;break}N=t.error?.message||`exit ${t.status??"unknown"}`}if(!E)return A(u,s.name,i,g,i),y(k(p.yellow,h.t("update.auto_failed",{error:N}))),{status:"update_failed",handled:!1,source:g.source};v(k(p.green,h.t("update.auto_installed",{version:g.latest})));const U=(r.reexecRunner||$)(e,{...o,[S("SKIP_AUTO_UPDATE")]:"1"});return U.error?(y(k(p.yellow,h.t("update.reexec_failed",{error:U.error.message}))),{status:"update_failed",handled:!1,source:g.source}):(process.exitCode=U.status??1,{status:"reexecuted",handled:!0,source:g.source})}
|
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 $,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();
|
|
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(await _(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();
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import { type ToolInstallSpec } from './tools/tool-installs.js';
|
|
2
|
+
/** How the last runCommand ended (for the support events and the fallback message). */
|
|
3
|
+
export type RunOutcome = 'ok' | 'fail' | 'timeout' | 'stalled';
|
|
4
|
+
export interface RunLimits {
|
|
5
|
+
/** Stop after this long in total. */
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
/** Stop once the command has printed nothing for this long (download progress counts as output). */
|
|
8
|
+
idleMs?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Runs a command with its output passed through to the terminal, stopping it once it goes quiet
|
|
12
|
+
* for `idleMs`: a slow network keeps printing download progress and gets all the time it needs,
|
|
13
|
+
* one that can't connect prints nothing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function runWatched(command: string, args: string[], limits: RunLimits): Promise<RunOutcome>;
|
|
2
16
|
/** Tests replace the process runner. */
|
|
3
|
-
export declare function setUpgradeRunnerForTests(fake: (command: string, args: string[],
|
|
17
|
+
export declare function setUpgradeRunnerForTests(fake: (command: string, args: string[], limits?: RunLimits) => boolean | RunOutcome | Promise<boolean | RunOutcome>): void;
|
|
4
18
|
/**
|
|
5
19
|
* Fresh install / last-resort fallback: our install script when the tool has one, else npm
|
|
6
|
-
* from npmmirror. A script that fails or
|
|
7
|
-
*
|
|
20
|
+
* from npmmirror. A script that fails or stalls falls back to npm when the tool is on npm
|
|
21
|
+
* (it reaches npmmirror through npm's own proxy settings, which often work where
|
|
8
22
|
* PowerShell / curl don't).
|
|
9
23
|
*/
|
|
10
|
-
export declare function mirrorInstall(spec: ToolInstallSpec): boolean
|
|
24
|
+
export declare function mirrorInstall(spec: ToolInstallSpec): Promise<boolean>;
|
|
11
25
|
/**
|
|
12
26
|
* `vibecli upgrade <tool>`: upgrade the copy PATH runs the way it was installed
|
|
13
27
|
* (vendor updater / npm via npmmirror / Homebrew). When the vendor updater
|
package/dist/lib/tool-upgrade.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawnSync as
|
|
1
|
+
import{spawn as t,spawnSync as e}from"child_process";import{rmSync as o}from"fs";import{join as r}from"path";import n from"chalk";import i from"inquirer";import{i18n as a}from"./i18n.js";import{logger as s}from"../utils/logger.js";import{compareVersions as l,getToolMinVersion as c}from"./model-registry.js";import{getAdapter as p}from"./tools/registry.js";import{findInstalls as u,forgetInstalls as m,installLabel as d,npmMirrorInstallCommand as g,npmUninstallCommand as f}from"./tools/tool-installs.js";import{toolHome as w}from"./tools/types.js";import{isNonInteractive as y,shouldAutoConfirm as h}from"./runtime-options.js";import{track as _}from"./telemetry.js";let v="ok",k=async(t,o,r={})=>(console.log(n.gray("$ ")+[t,...o].join(" ")),v=r.idleMs?await runWatched(t,o,r):function(t,o,r){const n=b(t)?e($(t,o),{stdio:"inherit",shell:!0,timeout:r}):e(t,o,{stdio:"inherit",timeout:r});return n.error&&s.logError(`upgrade: ${t}`,n.error),"ETIMEDOUT"===n.error?.code?"timeout":0===n.status?"ok":"fail"}(t,o,r.timeoutMs),"ok"===v);const b=t=>"win32"===process.platform&&!/\.exe$/i.test(t),$=(t,e)=>[t,...e].map(t=>/\s/.test(t)?`"${t}"`:t).join(" ");export function runWatched(e,o,r){return new Promise(n=>{const i=b(e)?t($(e,o),{stdio:["inherit","pipe","pipe"],shell:!0}):t(e,o,{stdio:["inherit","pipe","pipe"]});let a;const l=t=>{a=t,i.kill()};let c;const p=()=>{clearTimeout(c),r.idleMs&&(c=setTimeout(()=>l("stalled"),r.idleMs))},u=r.timeoutMs?setTimeout(()=>l("timeout"),r.timeoutMs):void 0;p(),i.stdout?.on("data",t=>{process.stdout.write(t),p()}),i.stderr?.on("data",t=>{process.stderr.write(t),p()});const m=t=>{clearTimeout(c),clearTimeout(u),n(t)};i.on("error",t=>{s.logError(`upgrade: ${e}`,t),m(a??"fail")}),i.on("close",t=>{a&&process.stdout.write("\n"),m(a??(0===t?"ok":"fail"))})})}export function setUpgradeRunnerForTests(t){k=async(e,o,r)=>{const n=await t(e,o,r);return v="string"==typeof n?n:n?"ok":"fail","ok"===v}}const T={ok:"install.script_failed_npm",fail:"install.script_failed_npm",stalled:"install.script_stalled_npm",timeout:"install.script_timeout_npm"};export async function mirrorInstall(t){if(!t.mirrorScript)return j(t);console.log(n.gray(a.t("install.downloading")));const e=`install-script:${t.command}`,o=Date.now();_(e,"start");const r={idleMs:18e4,timeoutMs:36e5},i="win32"===process.platform?await k("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",`irm ${t.mirrorScript.ps1} -TimeoutSec 30 | iex`],r):await k("sh",["-c",`script=$(curl -fsSL --connect-timeout 15 --max-time 60 ${t.mirrorScript.sh}) && printf '%s\\n' "$script" | sh`],r),s=v;return _(e,"stalled"===s?"timeout":s,{duration_ms:Date.now()-o,..."stalled"===s||"timeout"===s?{detail:{reason:s}}:{}}),i||!t.npmPackage?i:(console.log(n.yellow(" ! "+a.t(T[s],{minutes:String(3)}))),_(e,"fallback"),j(t))}async function j(t){const[e,...o]=g(t).split(" "),r=`install-npm:${t.command}`,i=Date.now();_(r,"start");const s=await k(e,o);return _(r,s?"ok":"fail",{duration_ms:Date.now()-i}),s||"win32"===process.platform||console.log(n.yellow(" ! "+a.t("upgrade.npm_permission",{command:g(t)}))),s}async function M(t,e){switch(e.kind){case"npm":t.npmPackage&&await k("npm",["uninstall","-g",t.npmPackage]);break;case"brew":t.brew&&await k("brew",["uninstall",t.brew]);break;case"native":try{o(e.path,{force:!0});for(const e of t.native?.dataDirs??[])o(r(w(),...e),{recursive:!0,force:!0})}catch(t){s.logError("upgrade: remove native copy",t)}break;default:return!1}return m(),!u(t).some(t=>t.path===e.path)}function D(t,e){switch(e.kind){case"npm":return f(t);case"brew":return`brew uninstall ${t.brew}`;case"native":return a.t("upgrade.delete_paths",{paths:[e.path,...(t.native?.dataDirs??[]).map(t=>r(w(),...t))].join("、")});default:return a.t("upgrade.delete_paths",{paths:e.path})}}export async function upgradeTool(t){const e=Date.now();_(`upgrade:${t}`,"start");try{const o=await async function(t){const e=p(t),o=e?.installSpec;if(!e||!o)throw new Error(a.t("upgrade.unsupported",{tool:t}));const r=e.displayName;m();const g=u(o);if(console.log(n.bold(`\n${r}`)),0===g.length)console.log(a.t("upgrade.not_installed_installing",{tool:r})),await mirrorInstall(o);else{const t=g[0];console.log(n.gray(" "+a.t("upgrade.current",{copy:d(t)})));const e=await async function(t,e){switch(e.kind){case"native":return k(e.path,t.native?.updateArgs??["update"],{timeoutMs:t.native?.updateTimeoutMs});case"npm":return j(t);case"brew":return!!t.brew&&k("brew",["upgrade",t.brew]);default:return!1}}(o,t);e||"other"!==t.kind?e||"npm"===t.kind||"native"===t.kind&&await async function(t){const e=t.native?.mirrorUpdate;if(!e)return!1;console.log(n.yellow(" ! "+a.t("upgrade.native_mirror_trying")));try{const{version:t,manifestVerified:o}=await e();return console.log(n.green(" √ "+a.t(o?"upgrade.native_mirror_done_verified":"upgrade.native_mirror_done",{version:t}))),!0}catch(t){return s.logError("upgrade: native mirror",t),console.log(n.yellow(" ! "+a.t("upgrade.native_mirror_failed",{reason:t instanceof Error?t.message:String(t)}))),!1}}(o)||(console.log(n.yellow(" ! "+a.t("upgrade.fallback_mirror"))),await mirrorInstall(o)):console.log(n.yellow(" ! "+a.t("upgrade.unknown_install",{path:t.path})))}m(),await async function(t,e){const o=u(t);if(o.length<2)return;const r=function(t){return t.reduce((t,e)=>e.version&&(!t.version||l(e.version,t.version)>0)?e:t)}(o),s=o.filter(t=>t!==r);console.log(n.yellow(" ! "+a.t("upgrade.duplicates",{tool:e,keep:d(r),others:s.map(d).join("、")})));let c=h();c||y()||!process.stdin.isTTY||(c=(await i.prompt([{type:"confirm",name:"remove",message:a.t("upgrade.confirm_remove"),default:!0}])).remove);for(const e of s)c&&await M(t,e)?console.log(n.green(" √ "+a.t("upgrade.removed",{copy:d(e)}))):console.log(n.yellow(" ! "+a.t("upgrade.remove_by_hand",{how:D(t,e)})))}(o,r),m();const f=u(o)[0];if(!f)return console.log(n.red(" × "+a.t("upgrade.still_missing",{tool:r}))),!1;const w=c(t);if(w&&f.version&&l(f.version,w)<0){console.log(n.yellow(" ! "+a.t("upgrade.still_old",{copy:d(f),min:w})));for(const t of e.upgradeHints?.(w)??[])console.log(n.yellow(" ! "+t));return!1}return console.log(n.green(" √ "+a.t("upgrade.done",{copy:d(f)}))),!0}(t);return _(`upgrade:${t}`,o?"ok":"fail",{duration_ms:Date.now()-e}),o}catch(o){throw _(`upgrade:${t}`,"fail",{duration_ms:Date.now()-e,error:o}),o}}
|
package/dist/locales/en_US.json
CHANGED
|
@@ -476,7 +476,9 @@
|
|
|
476
476
|
"verified_success": "Found {{tool}}, continuing",
|
|
477
477
|
"install_failed_detail": "Installation did not finish; see the output above or {{cli}} logs tail",
|
|
478
478
|
"downloading": "Downloading and installing (tens of MB up to about 130 MB); usually done within a minute or two",
|
|
479
|
-
"script_failed_npm": "The install script did not finish
|
|
479
|
+
"script_failed_npm": "The install script did not finish; installing with npm from the China mirror instead",
|
|
480
|
+
"script_stalled_npm": "The install script made no progress for {{minutes}} minutes (the download server is unreachable); installing with npm from the China mirror instead",
|
|
481
|
+
"script_timeout_npm": "The install script was still running after an hour; installing with npm from the China mirror instead",
|
|
480
482
|
"manual_command": "{{tool}} was not installed; when the network is better, run: {{command}}",
|
|
481
483
|
"manual_npm": "or install with npm: {{command}}"
|
|
482
484
|
},
|
package/dist/locales/zh_CN.json
CHANGED
|
@@ -476,7 +476,9 @@
|
|
|
476
476
|
"verified_success": "已找到 {{tool}},继续配置",
|
|
477
477
|
"install_failed_detail": "安装没有完成,详情见上面的输出或 {{cli}} logs tail",
|
|
478
478
|
"downloading": "正在下载安装,大约几十到一百多 MB,网络正常时一两分钟内完成",
|
|
479
|
-
"script_failed_npm": "
|
|
479
|
+
"script_failed_npm": "安装脚本没能完成,改用 npm 从国内镜像安装",
|
|
480
|
+
"script_stalled_npm": "安装脚本 {{minutes}} 分钟没有任何进展,网络连不上下载地址,改用 npm 从国内镜像安装",
|
|
481
|
+
"script_timeout_npm": "安装脚本运行 1 小时仍未完成,改用 npm 从国内镜像安装",
|
|
480
482
|
"manual_command": "{{tool}} 没装上,网络好的时候可以手动运行:{{command}}",
|
|
481
483
|
"manual_npm": "或者用 npm 安装:{{command}}"
|
|
482
484
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeapi/api-helper",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.116",
|
|
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",
|