@vibeapi/api-helper 0.0.107 → 0.0.109

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.
@@ -1 +1 @@
1
- import{execSync as t,spawnSync as o}from"child_process";import{i18n as n}from"./i18n.js";import e from"inquirer";import r from"chalk";import{logger as i}from"../utils/logger.js";import{configManager as s}from"./config.js";import{getAdapter as l,listAdapters as a,TOOL_ADAPTERS as c}from"./tools/registry.js";import{backupBeforeWrite as d,listBackups as p,restoreBackup as u}from"./tools/backup.js";import{existsSync as f,rmSync as m}from"fs";import{join as g}from"path";import{toolHome as h}from"./tools/types.js";import{stringWidth as w}from"../utils/string-width.js";import{resolveModelCatalog as P}from"./model-catalog.js";import{compareVersions as y,getToolMinVersion as T}from"./model-registry.js";import{findInstalls as k,forgetInstalls as $,installLabel as C,mirrorInstallCommand as E}from"./tools/tool-installs.js";import{CLI_NAME as v}from"./brand.js";export{y as compareVersions};function O(t){const o=c[t];return{name:o.name,command:o.command,installCommand:o.installCommand,configPath:o.configPath,displayName:o.displayName,...o.hidden?{hidden:!0}:{},...o.isInstalled?{gui:!0}:{}}}function S(){const t=new Set;for(const o of s.listProfiles()){const n=s.getProfile(o);for(const o of[n.api_key,...Object.values(n.tool_api_keys??{})])o?.trim()&&t.add(o.trim())}return[...t]}export const SUPPORTED_TOOLS=Object.fromEntries(Object.keys(c).map(t=>[t,O(t)]));export class ToolManager{static instance;constructor(){}static getInstance(){return ToolManager.instance||(ToolManager.instance=new ToolManager),ToolManager.instance}isToolInstalled(t){if(!SUPPORTED_TOOLS[t])return!1;const o=l(t);if(o?.isInstalled)try{return o.isInstalled()}catch{return!1}return this.isOnPath(t)||null!==this.nativeLauncher(t)}isOnPath(o){const n=SUPPORTED_TOOLS[o];if(!n)return!1;try{const o="win32"===process.platform?`where ${n.command}`:`which ${n.command}`;return t(o,{stdio:"pipe"}),!0}catch{return!1}}nativeLauncher(t){const o=l(t),n=o?.installSpec?.native?.binDir;if(!o||!n)return null;const e="win32"===process.platform?`${o.command}.exe`:o.command,r=g(h(),...n,e);return f(r)?r:null}async installTool(o){const i=SUPPORTED_TOOLS[o];if(!i)throw new Error(`Unknown tool: ${o}`);const s=l(o)?.installSpec,a=s?E(s):i.installCommand;console.log(r.gray("$ ")+r.white(a));try{return t(a,{stdio:"inherit"}),$(),void console.log(r.green("√ "+n.t("wizard.tool_installed")))}catch(t){if(console.log(r.red("× "+n.t("wizard.install_failed"))),!/EACCES|EPERM|permission denied/i.test(`${t?.message??""}${t?.stderr??""}`)&&243!==t?.status&&!a.startsWith("npm "))throw new Error(`Failed to install ${i.displayName}: ${t}`);console.log(r.yellow(" ! "+("win32"===process.platform?n.t("install.permission_windows",{command:a}):n.t("install.permission_unix",{command:a}))))}const{action:c}=await e.prompt([{type:"list",name:"action",message:n.t("install.what_next"),choices:[{name:n.t("install.installed_continue"),value:"continue"},{name:n.t("install.cancel_install"),value:"cancel"}]}]);if("cancel"===c)throw new Error(n.t("install.user_cancelled"));if($(),!this.isToolInstalled(o))throw console.log(r.red("× "+n.t("install.still_not_installed",{tool:i.displayName}))),new Error(`${i.displayName} is not installed`);console.log(r.green("√ "+n.t("install.verified_success",{tool:i.displayName})))}getToolConfig(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);try{return o.getConfig()}catch(o){return i.warn(`Failed to read config for ${t}:`,o),i.logError(`ToolManager.getToolConfig(${t})`,o),null}}updateToolConfig(t,o){const n=l(t);if(!n)throw new Error(`Unknown tool: ${t}`);if(!n.updateConfig)throw new Error(`Tool ${t} does not support raw config updates`);n.updateConfig(o)}forceResetConfig(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);const n=o.forceResetPaths?o.forceResetPaths():this.backupPathsFor(o),e=[];for(const t of n)f(t)&&(d(t),m(t,{force:!0}),e.push(t));return e}loadPrivateConfig(t,o,n,e,r={}){const i=l(t);if(!i)throw new Error(`Unknown tool: ${t}`);r.force&&this.forceResetConfig(t),i.loadPrivateConfig({apiKey:o,baseUrl:s.getBaseUrl(),models:n,settings:s.getToolSettings(t),...e?{catalog:e}:{}})}async applyPrivateConfig(t,o,n,e={}){const r=l(t);if(!r)throw new Error(`Unknown tool: ${t}`);const i=r.wantsModelCatalog?await P(o):null;e.force?this.loadPrivateConfig(t,o,n,i??void 0,{force:!0}):i?this.loadPrivateConfig(t,o,n,i):this.loadPrivateConfig(t,o,n)}applyNotes(t){const o=l(t);if(!o)return[];const e=[];try{o.applyNotes&&e.push(...o.applyNotes())}catch(o){i.logError(`ToolManager.applyNotes(${t})`,o)}const r=this.outdatedVersion(t);if(r){e.push({kind:"action",text:n.t("tools.version_outdated",{current:r.current,min:r.min,upgrade:o.installSpec?`${v} upgrade ${t}`:o.upgradeCommand||o.installCommand})});for(const t of o.upgradeHints?.(r.min)??[])e.push({kind:"action",text:t})}const s=o.installSpec?k(o.installSpec):[];return s.length>1&&e.push({kind:"action",text:n.t("upgrade.duplicates_note",{count:String(s.length),active:C(s[0]),others:s.slice(1).map(C).join("、"),tool:t})}),e}printApplied(t,o=16){const n=SUPPORTED_TOOLS[t]?.displayName??t,e=this.applyNotes(t);for(const t of e.filter(t=>"detail"===t.kind))i.record(`${n}: ${t.text}`);const s=e.filter(t=>"summary"===t.kind).map(t=>t.text).join(";"),l=" ".repeat(Math.max(1,o-w(n)));console.log(r.green("√ "+n)+(s?l+s:""));for(const t of e.filter(t=>"action"===t.kind))console.log(r.yellow(" ! "+t.text))}installedVersion(t){const n=l(t);if(!n)return null;if(n.installSpec)return k(n.installSpec)[0]?.version??null;if(n.installedVersion)try{return n.installedVersion()}catch(o){return i.logError(`ToolManager.installedVersion(${t})`,o),null}if(n.isInstalled)return null;try{const t={encoding:"utf-8",timeout:1e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]},e=`${("win32"===process.platform?o(`${n.command} --version`,{...t,shell:!0}):o(n.command,["--version"],t)).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return e?e[0]:null}catch{return null}}outdatedVersion(t){const o=T(t);if(!o)return null;const n=this.installedVersion(t);return n&&y(n,o)<0?{current:n,min:o}:null}unloadPrivateConfig(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);o.unloadPrivateConfig({savedKeys:S()});let e=[];try{e=o.unloadNotes?.()??[]}catch(o){i.logError(`ToolManager.unloadNotes(${t})`,o)}return e.length>0?e:[{kind:"action",text:n.t("config.reopen_hint",{tool:o.displayName})}]}async clearPinnedModels(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);if(s.setToolModel(t,null),!o.clearPinnedModels)return[];const n=s.getApiKeyForTool(t),e=o.wantsModelCatalog&&n?await P(n):null;return o.clearPinnedModels(e??void 0)}supportsClearPinnedModels(t){return Boolean(l(t)?.clearPinnedModels)}detectCurrentConfig(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);return o.detectCurrentConfig()}backupPathsFor(t){return t.backupPaths?t.backupPaths():[t.configPath]}listToolBackups(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);return this.backupPathsFor(o).map(t=>({file:t,backups:p(t)}))}restorePrivateConfig(t){const o=l(t);if(!o)throw new Error(`Unknown tool: ${t}`);return this.backupPathsFor(o).map(t=>({file:t,result:u(t)}))}getInstalledTools(){return Object.keys(SUPPORTED_TOOLS).filter(t=>this.isToolInstalled(t))}getSupportedTools(){return a().filter(t=>!t.hidden).map(t=>O(t.name))}isGitInstalled(){try{const o="win32"===process.platform?"where git":"which git";return t(o,{stdio:"pipe"}),!0}catch{return!1}}}export const toolManager=ToolManager.getInstance();
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 k,forgetInstalls as $,installLabel as C,mirrorInstallCommand as E,npmMirrorInstallCommand as _}from"./tools/tool-installs.js";import{mirrorInstall as v}from"./tool-upgrade.js";import{CLI_NAME as S}from"./brand.js";export{P as compareVersions};function O(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 M(){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,O(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(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=E(i);if(v(i)&&($(),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:_(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"}),$(),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($(),!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=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?k(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 k(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}`);t.unloadPrivateConfig({savedKeys:M()});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=>O(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,5 +1,13 @@
1
+ import { type ToolInstallSpec } from './tools/tool-installs.js';
1
2
  /** Tests replace the process runner. */
2
3
  export declare function setUpgradeRunnerForTests(fake: (command: string, args: string[], timeoutMs?: number) => boolean): void;
4
+ /**
5
+ * Fresh install / last-resort fallback: our install script when the tool has one, else npm
6
+ * from npmmirror. A script that fails or runs out of time falls back to npm when the tool is
7
+ * on npm (it reaches npmmirror through npm's own proxy settings, which often work where
8
+ * PowerShell / curl don't).
9
+ */
10
+ export declare function mirrorInstall(spec: ToolInstallSpec): boolean;
3
11
  /**
4
12
  * `vibecli upgrade <tool>`: upgrade the copy PATH runs the way it was installed
5
13
  * (vendor updater / npm via npmmirror / Homebrew). When the vendor updater
@@ -1 +1 @@
1
- import{spawnSync as e}from"child_process";import{rmSync as r}from"fs";import{join as o}from"path";import t from"chalk";import n from"inquirer";import{i18n as i}from"./i18n.js";import{logger as s}from"../utils/logger.js";import{compareVersions as a,getToolMinVersion as l}from"./model-registry.js";import{getAdapter as p}from"./tools/registry.js";import{findInstalls as c,forgetInstalls as u,installLabel as m,mirrorInstallCommand as d,npmMirrorInstallCommand as g,npmUninstallCommand as f}from"./tools/tool-installs.js";import{toolHome as w}from"./tools/types.js";import{isNonInteractive as h,shouldAutoConfirm as v}from"./runtime-options.js";let y=(r,o,n)=>{console.log(t.gray("$ ")+[r,...o].join(" "));const i="win32"!==process.platform||/\.exe$/i.test(r)?e(r,o,{stdio:"inherit",timeout:n}):e([r,...o].map(e=>/\s/.test(e)?`"${e}"`:e).join(" "),{stdio:"inherit",shell:!0,timeout:n});return i.error&&s.logError(`upgrade: ${r}`,i.error),0===i.status};export function setUpgradeRunnerForTests(e){y=e}function _(e){return e.mirrorScript?"win32"===process.platform?y("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",`irm ${e.mirrorScript.ps1} | iex`]):y("sh",["-c",d(e)]):b(e)}function b(e){const[r,...o]=g(e).split(" "),n=y(r,o);return n||"win32"===process.platform||console.log(t.yellow(" ! "+i.t("upgrade.npm_permission",{command:g(e)}))),n}function k(e,t){switch(t.kind){case"npm":e.npmPackage&&y("npm",["uninstall","-g",e.npmPackage]);break;case"brew":e.brew&&y("brew",["uninstall",e.brew]);break;case"native":try{r(t.path,{force:!0});for(const t of e.native?.dataDirs??[])r(o(w(),...t),{recursive:!0,force:!0})}catch(e){s.logError("upgrade: remove native copy",e)}break;default:return!1}return u(),!c(e).some(e=>e.path===t.path)}function j(e,r){switch(r.kind){case"npm":return f(e);case"brew":return`brew uninstall ${e.brew}`;case"native":return i.t("upgrade.delete_paths",{paths:[r.path,...(e.native?.dataDirs??[]).map(e=>o(w(),...e))].join("、")});default:return i.t("upgrade.delete_paths",{paths:r.path})}}export async function upgradeTool(e){const r=p(e),o=r?.installSpec;if(!r||!o)throw new Error(i.t("upgrade.unsupported",{tool:e}));const d=r.displayName;u();const g=c(o);if(console.log(t.bold(`\n${d}`)),0===g.length)console.log(i.t("upgrade.not_installed_installing",{tool:d})),_(o);else{const e=g[0];console.log(t.gray(" "+i.t("upgrade.current",{copy:m(e)})));const r=function(e,r){switch(r.kind){case"native":return y(r.path,e.native?.updateArgs??["update"],e.native?.updateTimeoutMs);case"npm":return b(e);case"brew":return!!e.brew&&y("brew",["upgrade",e.brew]);default:return!1}}(o,e);r||"other"!==e.kind?r||"npm"===e.kind||"native"===e.kind&&await async function(e){const r=e.native?.mirrorUpdate;if(!r)return!1;console.log(t.yellow(" ! "+i.t("upgrade.native_mirror_trying")));try{const{version:e,manifestVerified:o}=await r();return console.log(t.green(" √ "+i.t(o?"upgrade.native_mirror_done_verified":"upgrade.native_mirror_done",{version:e}))),!0}catch(e){return s.logError("upgrade: native mirror",e),console.log(t.yellow(" ! "+i.t("upgrade.native_mirror_failed",{reason:e instanceof Error?e.message:String(e)}))),!1}}(o)||(console.log(t.yellow(" ! "+i.t("upgrade.fallback_mirror"))),_(o)):console.log(t.yellow(" ! "+i.t("upgrade.unknown_install",{path:e.path})))}u(),await async function(e,r){const o=c(e);if(o.length<2)return;const s=function(e){return e.reduce((e,r)=>r.version&&(!e.version||a(r.version,e.version)>0)?r:e)}(o),l=o.filter(e=>e!==s);console.log(t.yellow(" ! "+i.t("upgrade.duplicates",{tool:r,keep:m(s),others:l.map(m).join("、")})));let p=v();p||h()||!process.stdin.isTTY||(p=(await n.prompt([{type:"confirm",name:"remove",message:i.t("upgrade.confirm_remove"),default:!0}])).remove);for(const r of l)p&&k(e,r)?console.log(t.green(" √ "+i.t("upgrade.removed",{copy:m(r)}))):console.log(t.yellow(" ! "+i.t("upgrade.remove_by_hand",{how:j(e,r)})))}(o,d),u();const f=c(o)[0];if(!f)return console.log(t.red(" × "+i.t("upgrade.still_missing",{tool:d}))),!1;const w=l(e);if(w&&f.version&&a(f.version,w)<0){console.log(t.yellow(" ! "+i.t("upgrade.still_old",{copy:m(f),min:w})));for(const e of r.upgradeHints?.(w)??[])console.log(t.yellow(" ! "+e));return!1}return console.log(t.green(" √ "+i.t("upgrade.done",{copy:m(f)}))),!0}
1
+ import{spawnSync as r}from"child_process";import{rmSync as e}from"fs";import{join as o}from"path";import t from"chalk";import n from"inquirer";import{i18n as i}from"./i18n.js";import{logger as s}from"../utils/logger.js";import{compareVersions as a,getToolMinVersion as l}from"./model-registry.js";import{getAdapter as p}from"./tools/registry.js";import{findInstalls as c,forgetInstalls as u,installLabel as m,npmMirrorInstallCommand as g,npmUninstallCommand as d}from"./tools/tool-installs.js";import{toolHome as f}from"./tools/types.js";import{isNonInteractive as w,shouldAutoConfirm as h}from"./runtime-options.js";let y=(e,o,n)=>{console.log(t.gray("$ ")+[e,...o].join(" "));const i="win32"!==process.platform||/\.exe$/i.test(e)?r(e,o,{stdio:"inherit",timeout:n}):r([e,...o].map(r=>/\s/.test(r)?`"${r}"`:r).join(" "),{stdio:"inherit",shell:!0,timeout:n});return i.error&&s.logError(`upgrade: ${e}`,i.error),0===i.status};export function setUpgradeRunnerForTests(r){y=r}const v=3e5;export function mirrorInstall(r){if(!r.mirrorScript)return _(r);console.log(t.gray(i.t("install.downloading")));const e="win32"===process.platform?y("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",`irm ${r.mirrorScript.ps1} -TimeoutSec 30 | iex`],v):y("sh",["-c",`script=$(curl -fsSL --connect-timeout 15 --max-time 60 ${r.mirrorScript.sh}) && printf '%s\\n' "$script" | sh`],v);return e||!r.npmPackage?e:(console.log(t.yellow(" ! "+i.t("install.script_failed_npm"))),_(r))}function _(r){const[e,...o]=g(r).split(" "),n=y(e,o);return n||"win32"===process.platform||console.log(t.yellow(" ! "+i.t("upgrade.npm_permission",{command:g(r)}))),n}function b(r,t){switch(t.kind){case"npm":r.npmPackage&&y("npm",["uninstall","-g",r.npmPackage]);break;case"brew":r.brew&&y("brew",["uninstall",r.brew]);break;case"native":try{e(t.path,{force:!0});for(const t of r.native?.dataDirs??[])e(o(f(),...t),{recursive:!0,force:!0})}catch(r){s.logError("upgrade: remove native copy",r)}break;default:return!1}return u(),!c(r).some(r=>r.path===t.path)}function k(r,e){switch(e.kind){case"npm":return d(r);case"brew":return`brew uninstall ${r.brew}`;case"native":return i.t("upgrade.delete_paths",{paths:[e.path,...(r.native?.dataDirs??[]).map(r=>o(f(),...r))].join("、")});default:return i.t("upgrade.delete_paths",{paths:e.path})}}export async function upgradeTool(r){const e=p(r),o=e?.installSpec;if(!e||!o)throw new Error(i.t("upgrade.unsupported",{tool:r}));const g=e.displayName;u();const d=c(o);if(console.log(t.bold(`\n${g}`)),0===d.length)console.log(i.t("upgrade.not_installed_installing",{tool:g})),mirrorInstall(o);else{const r=d[0];console.log(t.gray(" "+i.t("upgrade.current",{copy:m(r)})));const e=function(r,e){switch(e.kind){case"native":return y(e.path,r.native?.updateArgs??["update"],r.native?.updateTimeoutMs);case"npm":return _(r);case"brew":return!!r.brew&&y("brew",["upgrade",r.brew]);default:return!1}}(o,r);e||"other"!==r.kind?e||"npm"===r.kind||"native"===r.kind&&await async function(r){const e=r.native?.mirrorUpdate;if(!e)return!1;console.log(t.yellow(" ! "+i.t("upgrade.native_mirror_trying")));try{const{version:r,manifestVerified:o}=await e();return console.log(t.green(" √ "+i.t(o?"upgrade.native_mirror_done_verified":"upgrade.native_mirror_done",{version:r}))),!0}catch(r){return s.logError("upgrade: native mirror",r),console.log(t.yellow(" ! "+i.t("upgrade.native_mirror_failed",{reason:r instanceof Error?r.message:String(r)}))),!1}}(o)||(console.log(t.yellow(" ! "+i.t("upgrade.fallback_mirror"))),mirrorInstall(o)):console.log(t.yellow(" ! "+i.t("upgrade.unknown_install",{path:r.path})))}u(),await async function(r,e){const o=c(r);if(o.length<2)return;const s=function(r){return r.reduce((r,e)=>e.version&&(!r.version||a(e.version,r.version)>0)?e:r)}(o),l=o.filter(r=>r!==s);console.log(t.yellow(" ! "+i.t("upgrade.duplicates",{tool:e,keep:m(s),others:l.map(m).join("、")})));let p=h();p||w()||!process.stdin.isTTY||(p=(await n.prompt([{type:"confirm",name:"remove",message:i.t("upgrade.confirm_remove"),default:!0}])).remove);for(const e of l)p&&b(r,e)?console.log(t.green(" √ "+i.t("upgrade.removed",{copy:m(e)}))):console.log(t.yellow(" ! "+i.t("upgrade.remove_by_hand",{how:k(r,e)})))}(o,g),u();const f=c(o)[0];if(!f)return console.log(t.red(" × "+i.t("upgrade.still_missing",{tool:g}))),!1;const v=l(r);if(v&&f.version&&a(f.version,v)<0){console.log(t.yellow(" ! "+i.t("upgrade.still_old",{copy:m(f),min:v})));for(const r of e.upgradeHints?.(v)??[])console.log(t.yellow(" ! "+r));return!1}return console.log(t.green(" √ "+i.t("upgrade.done",{copy:m(f)}))),!0}
@@ -467,7 +467,11 @@
467
467
  "user_cancelled": "Installation cancelled",
468
468
  "still_not_installed": "{{tool}} still not found; make sure it installed and open a new terminal",
469
469
  "verified_success": "Found {{tool}}, continuing",
470
- "install_failed_detail": "Installation did not finish; see the output above or {{cli}} logs tail"
470
+ "install_failed_detail": "Installation did not finish; see the output above or {{cli}} logs tail",
471
+ "downloading": "Downloading and installing (tens of MB up to about 130 MB); usually done within a minute or two",
472
+ "script_failed_npm": "The install script did not finish (network unreachable or over 5 minutes); installing with npm from the China mirror instead",
473
+ "manual_command": "{{tool}} was not installed; when the network is better, run: {{command}}",
474
+ "manual_npm": "or install with npm: {{command}}"
471
475
  },
472
476
  "model_refresh": {
473
477
  "changed": "{{tool}} model menu synced with {{brand}}: {{changes}}",
@@ -467,7 +467,11 @@
467
467
  "user_cancelled": "已取消安装",
468
468
  "still_not_installed": "还是没找到 {{tool}},请确认安装成功、重开终端后再试",
469
469
  "verified_success": "已找到 {{tool}},继续配置",
470
- "install_failed_detail": "安装没有完成,详情见上面的输出或 {{cli}} logs tail"
470
+ "install_failed_detail": "安装没有完成,详情见上面的输出或 {{cli}} logs tail",
471
+ "downloading": "正在下载安装,大约几十到一百多 MB,网络正常时一两分钟内完成",
472
+ "script_failed_npm": "安装脚本没能完成(网络连不上或超过 5 分钟),改用 npm 从国内镜像安装",
473
+ "manual_command": "{{tool}} 没装上,网络好的时候可以手动运行:{{command}}",
474
+ "manual_npm": "或者用 npm 安装:{{command}}"
471
475
  },
472
476
  "model_refresh": {
473
477
  "changed": "已按 {{brand}} 最新模型清单更新 {{tool}}:{{changes}}",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeapi/api-helper",
3
- "version": "0.0.107",
3
+ "version": "0.0.109",
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",