@vibeapi/cli 0.0.51 → 0.0.52
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/tool-manager.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{execSync as o,spawnSync as
|
|
1
|
+
import{execSync as o,spawnSync as n}from"child_process";import{i18n as t}from"./i18n.js";import l from"inquirer";import e from"chalk";import s from"terminal-link";import i from"ora";import{logger as r}from"../utils/logger.js";import{configManager as a}from"./config.js";import{getAdapter as c,listAdapters as d,TOOL_ADAPTERS as u}from"./tools/registry.js";import{backupBeforeWrite as g,listBackups as m,restoreBackup as p}from"./tools/backup.js";import{existsSync as f,rmSync as w}from"fs";import{resolveModelCatalog as h}from"./model-catalog.js";import{getToolMinVersion as _}from"./model-registry.js";function y(o){const n=u[o];return{name:n.name,command:n.command,installCommand:n.installCommand,configPath:n.configPath,displayName:n.displayName,...n.hidden?{hidden:!0}:{}}}export const SUPPORTED_TOOLS=Object.fromEntries(Object.keys(u).map(o=>[o,y(o)]));export class ToolManager{static instance;constructor(){}static getInstance(){return ToolManager.instance||(ToolManager.instance=new ToolManager),ToolManager.instance}isToolInstalled(n){const t=SUPPORTED_TOOLS[n];if(!t)return!1;const l=c(n);if(l?.isInstalled)try{return l.isInstalled()}catch{return!1}try{const n="win32"===process.platform?`where ${t.command}`:`which ${t.command}`;return o(n,{stdio:"pipe"}),!0}catch{return!1}}async installTool(n){const a=SUPPORTED_TOOLS[n];if(!a)throw new Error(`Unknown tool: ${n}`);const c=i(t.t("wizard.installing_tool")).start();try{c.info(e.gray("$ ")+e.white(a.installCommand)),c.stop(),o(a.installCommand,{stdio:"inherit"}),c.succeed(t.t("wizard.tool_installed"))}catch(i){c.fail(t.t("wizard.install_failed"));const d=(i.message||"")+(i.stderr?.toString()||"")+(i.stdout?.toString()||"");if(!(d.includes("EACCES")||d.includes("permission denied")||d.includes("EPERM")||243===i.status))throw new Error(`Failed to install ${a.displayName}: ${i}`);if(console.log("\n⚠️ "+t.t("install.permission_detected")+"\n"),"win32"===process.platform)try{const n=a.installCommand.replace("npm install -g","npm install -g --force");return console.log("🔧 "+t.t("install.trying_solution",{num:"1",desc:t.t("install.using_force")})),console.log(e.gray("$ ")+e.white(n)),o(n,{stdio:"inherit"}),void console.log("\n✅ "+t.t("install.permission_fixed"))}catch(o){r.warn("Retry install failed:",o),console.log("\n❌ "+t.t("install.auto_fix_failed")),console.log(e.yellow("\n📌 "+t.t("install.windows_solutions"))),console.log(""),console.log(e.cyan.bold(t.t("install.windows_solution_1_title"))),console.log(e.gray(" "+t.t("install.windows_solution_1_step1"))),console.log(e.gray(" "+t.t("install.windows_solution_1_step2"))),console.log(e.gray(" "+t.t("install.windows_solution_1_step3"))),console.log(e.white(` ${a.installCommand}`)),console.log(""),console.log(e.cyan.bold(t.t("install.windows_solution_2_title"))),console.log(e.gray(" "+t.t("install.windows_solution_2_command"))),console.log(e.white(` ${a.installCommand.replace("npm install -g","npm install -g --prefix=%APPDATA%\\npm")}`)),console.log("");const{action:s}=await l.prompt([{type:"list",name:"action",message:t.t("install.what_next"),choices:[{name:t.t("install.installed_continue"),value:"continue"},{name:t.t("install.cancel_install"),value:"cancel"}]}]);if("cancel"===s)throw new Error(t.t("install.user_cancelled"));if(!this.isToolInstalled(n))throw console.log(e.red("\n❌ "+t.t("install.still_not_installed",{tool:a.displayName}))),new Error(`${a.displayName} is not installed`);return void console.log(e.green("\n✅ "+t.t("install.verified_success",{tool:a.displayName})))}console.log(e.yellow("\n📌 "+t.t("install.unix_solutions"))),console.log(""),console.log(e.cyan.bold(t.t("install.unix_solution_1_title"))),console.log(e.gray(" "+t.t("install.unix_solution_1_desc"))),console.log(e.white(` sudo ${a.installCommand}`)),console.log("");const u="https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally",g=s(u,u,{fallback:()=>u});console.log(e.cyan.bold(t.t("install.unix_solution_2_title"))),console.log(e.gray(" "+t.t("install.unix_solution_2_desc"))),console.log(e.blue(" 📖 "+t.t("install.npm_docs_link")+": ")+g),console.log("");const{action:m}=await l.prompt([{type:"list",name:"action",message:t.t("install.what_next"),choices:[{name:t.t("install.installed_continue"),value:"continue"},{name:t.t("install.cancel_install"),value:"cancel"}]}]);if("cancel"===m)throw new Error(t.t("install.user_cancelled"));if(!this.isToolInstalled(n))throw console.log(e.red("\n❌ "+t.t("install.still_not_installed",{tool:a.displayName}))),new Error(`${a.displayName} is not installed`);console.log(e.green("\n✅ "+t.t("install.verified_success",{tool:a.displayName})))}}getToolConfig(o){const n=c(o);if(!n)throw new Error(`Unknown tool: ${o}`);try{return n.getConfig()}catch(n){return r.warn(`Failed to read config for ${o}:`,n),r.logError(`ToolManager.getToolConfig(${o})`,n),null}}updateToolConfig(o,n){const t=c(o);if(!t)throw new Error(`Unknown tool: ${o}`);if(!t.updateConfig)throw new Error(`Tool ${o} does not support raw config updates`);t.updateConfig(n)}forceResetConfig(o){const n=c(o);if(!n)throw new Error(`Unknown tool: ${o}`);const t=n.forceResetPaths?n.forceResetPaths():this.backupPathsFor(n),l=[];for(const o of t)f(o)&&(g(o),w(o,{force:!0}),l.push(o));return l}loadPrivateConfig(o,n,t,l,e={}){const s=c(o);if(!s)throw new Error(`Unknown tool: ${o}`);e.force&&this.forceResetConfig(o),s.loadPrivateConfig({apiKey:n,baseUrl:a.getBaseUrl(),models:t,settings:a.getToolSettings(o),...l?{catalog:l}:{}})}async applyPrivateConfig(o,n,t,l={}){const e=c(o);if(!e)throw new Error(`Unknown tool: ${o}`);const s=e.wantsModelCatalog?await h(n):null;l.force?this.loadPrivateConfig(o,n,t,s??void 0,{force:!0}):s?this.loadPrivateConfig(o,n,t,s):this.loadPrivateConfig(o,n,t)}applyNotes(o){const n=c(o);if(!n)return[];const l=[];try{n.applyNotes&&l.push(...n.applyNotes())}catch(n){r.logError(`ToolManager.applyNotes(${o})`,n)}const e=this.outdatedVersion(o);return e&&l.push(t.t("tools.version_outdated",{tool:n.displayName,current:e.current,min:e.min,upgrade:n.upgradeCommand||n.installCommand})),l}installedVersion(o){const t=c(o);if(!t)return null;if(t.installedVersion)try{return t.installedVersion()}catch(n){return r.logError(`ToolManager.installedVersion(${o})`,n),null}if(t.isInstalled)return null;try{const o=`${n(t.command,["--version"],{encoding:"utf-8",timeout:1e4,windowsHide:!0,shell:"win32"===process.platform,stdio:["ignore","pipe","pipe"]}).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return o?o[0]:null}catch{return null}}outdatedVersion(o){const n=_(o);if(!n)return null;const t=this.installedVersion(o);return t&&compareVersions(t,n)<0?{current:t,min:n}:null}unloadPrivateConfig(o){const n=c(o);if(!n)throw new Error(`Unknown tool: ${o}`);n.unloadPrivateConfig()}async clearPinnedModels(o){const n=c(o);if(!n)throw new Error(`Unknown tool: ${o}`);if(a.setToolModel(o,null),!n.clearPinnedModels)return[];const t=a.getApiKeyForTool(o),l=n.wantsModelCatalog&&t?await h(t):null;return n.clearPinnedModels(l??void 0)}supportsClearPinnedModels(o){return Boolean(c(o)?.clearPinnedModels)}detectCurrentConfig(o){const n=c(o);if(!n)throw new Error(`Unknown tool: ${o}`);return n.detectCurrentConfig()}backupPathsFor(o){return o.backupPaths?o.backupPaths():[o.configPath]}listToolBackups(o){const n=c(o);if(!n)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(n).map(o=>({file:o,backups:m(o)}))}restorePrivateConfig(o){const n=c(o);if(!n)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(n).map(o=>({file:o,result:p(o)}))}getInstalledTools(){return Object.keys(SUPPORTED_TOOLS).filter(o=>this.isToolInstalled(o))}getSupportedTools(){return d().filter(o=>!o.hidden).map(o=>y(o.name))}isGitInstalled(){try{const n="win32"===process.platform?"where git":"which git";return o(n,{stdio:"pipe"}),!0}catch{return!1}}}export function compareVersions(o,n){const t=o.split(".").map(o=>parseInt(o,10)||0),l=n.split(".").map(o=>parseInt(o,10)||0);for(let o=0;o<Math.max(t.length,l.length);o++){const n=(t[o]??0)-(l[o]??0);if(0!==n)return n}return 0}export const toolManager=ToolManager.getInstance();
|
|
@@ -13,6 +13,8 @@ export interface InferenceModel {
|
|
|
13
13
|
name: string;
|
|
14
14
|
labelOverride: string;
|
|
15
15
|
supports1m?: boolean;
|
|
16
|
+
/** With `supports1m`: show one option that requests 1M instead of two. */
|
|
17
|
+
prefer1m?: boolean;
|
|
16
18
|
anthropicFamilyTier?: string;
|
|
17
19
|
isFamilyDefault?: boolean;
|
|
18
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{chmodSync as e,existsSync as t,mkdirSync as o,readFileSync as n,rmSync as r}from"fs";import{dirname as s}from"path";import{join as i}from"path";import{randomUUID as a}from"crypto";import{execFileSync as l}from"child_process";import{userInfo as c}from"os";import{logger as d}from"../../utils/logger.js";import{i18n as p}from"../i18n.js";import{BRAND_NAME as u}from"../brand.js";import{backupBeforeWrite as f,atomicWriteFile as m}from"./backup.js";import{toolHome as g}from"./types.js";import{baseModelId as y,isClaudeModel as h}from"../model-catalog.js";const C=u;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";const k=["Claude_pzs8sxrjxfjjc","AnthropicPBC.Claude_fnn82j28hfe8t"],_=/^[a-f0-9-]{36}$/;function b(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}export function claudeDesktopUserDataDir(){const e=process.env.CLAUDE_USER_DATA_DIR?.trim();if(e)return e;const o=g(),n=Boolean(process.env.VIBECLI_TEST_HOME?.trim());switch(process.platform){case"darwin":return i(o,"Library","Application Support","Claude-3p");case"win32":{const e=!n&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:i(o,"AppData","Local");return k.map(t=>i(e,"Packages",t,"LocalCache","Local","Claude-3p")).find(e=>t(e))??i(e,"Claude-3p")}default:{const e=!n&&process.env.XDG_CONFIG_HOME?process.env.XDG_CONFIG_HOME:i(o,".config");return i(e,"Claude-3p")}}}const D=()=>i(claudeDesktopUserDataDir(),"configLibrary"),A=()=>i(D(),"_meta.json"),w=e=>i(D(),`${e}.json`),M=()=>i(claudeDesktopUserDataDir(),"claude_desktop_config.json");function E(e){if(!t(e))return null;const o=n(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return b(e)?e:null}catch(t){throw new Error(`Existing ${e} cannot be parsed, back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}function v(n,r){const i=s(n);t(i)||o(i,{recursive:!0,mode:448}),f(n),m(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){d.logError("claude-desktop.writeJson.chmod",e)}}function I(){const e=E(A());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>b(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function P(e){return e?.entries.find(e=>e.name===C&&_.test(e.id))}const S={opus:0,fable:1,sonnet:2,haiku:3};function L(e){let t=/^claude-(opus|sonnet|haiku|fable)-(\d+(?:-\d+)*)/i.exec(e);return t?{family:t[1].toLowerCase(),version:t[2].split("-").map(Number)}:(t=/^claude-(\d+(?:-\d+)*)-(opus|sonnet|haiku)/i.exec(e),t?{family:t[2].toLowerCase(),version:t[1].split("-").map(Number)}:null)}export function humanizeModelId(e){const t=L(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function O(e){return L(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>y(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(h)){i=[...new Set(t.models.filter(h).map(y))];for(const e of t.oneMillion)r.add(e)}else{i=[];for(const t of["opus","sonnet","haiku","reasoning"]){const o=(e[t]||"").trim(),n=y(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const a=e=>S[O(e)??""]??9;i.sort((e,t)=>{if(e===o)return-1;if(t===o)return 1;const n=a(e)-a(t);if(0!==n)return n;const r=L(e),s=L(t);return r&&s?function(e,t){const o=Math.max(e.length,t.length);for(let n=0;n<o;n++){const o=(t[n]??0)-(e[n]??0);if(0!==o)return o}return 0}(r.version,s.version):e.localeCompare(t)});const l=new Set,c=new Map;for(const e of n){const t=O(e);t&&i.includes(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=O(e),o={name:e,labelOverride:s[e]||humanizeModelId(e)};if(r.has(e)&&(o.supports1m=!0),t){o.anthropicFamilyTier=t;const n=c.get(t);n&&n!==e||l.has(t)||(o.isFamilyDefault=!0,l.add(t))}return o})}let j=null,x=null;function T(e){return{inferenceProvider:"gateway",inferenceCredentialKind:"static",inferenceGatewayBaseUrl:(e.baseUrl||"").trim().replace(/\/+$/,""),inferenceGatewayApiKey:e.apiKey,inferenceModels:buildInferenceModels(e.models,e.catalog),disableDeploymentModeChooser:!1!==e.settings?.hide_official_login,chatTabEnabled:!0,chatAdvancedFileAnalysisEnabled:!0,autoModeEnabled:!0,coworkEgressAllowedHosts:["*"],disableEssentialTelemetry:!0,disableNonessentialTelemetry:!0,disableNonessentialServices:!0}}const G="HKCU\\SOFTWARE\\Policies\\Claude",U="HKLM\\SOFTWARE\\Policies\\Claude",$="vibecli-claude-policy.reg",K=e=>l("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let N=K;export function setRegRunnerForTests(e){N=e??K}function R(){return"win32"===process.platform}function F(e){let t;try{t=N(["query",e])}catch{return null}const o=new Map;for(const e of t.split(/\r?\n/)){const t=/^\s{2,}(\S+)\s+(REG_[A-Z_]+)\s*(.*)$/.exec(e);t&&o.set(t[1],t[3])}return o}function H(){if(null===F(G))return;const e=i(claudeDesktopUserDataDir(),$);try{t(s(e))||o(s(e),{recursive:!0,mode:448}),f(e),N(["export",G,e,"/y"])}catch(e){d.logError("claude-desktop.snapshotPolicy",e)}}const B=Object.keys(T({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}}));export function detectManagedConfig(){try{if("darwin"===process.platform){let e="";try{e=c().username}catch{}return[e?`/Library/Managed Preferences/${e}/com.anthropic.claudefordesktop.plist`:"","/Library/Managed Preferences/com.anthropic.claudefordesktop.plist"].filter(Boolean).find(e=>t(e))??null}if("win32"===process.platform)return F(U)?U:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return d.logError("claude-desktop.detectManagedConfig",e),null}}const z="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",J="https://claude.ai/download",W="darwin"===process.platform?`open ${J}`:"win32"===process.platform?`start ${J}`:`xdg-open ${J}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:z,installCommand:W,configPath:A(),isInstalled:function(){const e=g();let o;switch(process.platform){case"darwin":o=["/Applications/Claude.app",i(e,"Applications","Claude.app")];break;case"win32":{const t=process.env.LOCALAPPDATA||i(e,"AppData","Local");o=[i(t,"AnthropicClaude"),i(t,"Programs","Claude"),...k.map(e=>i(t,"Packages",e))];break}default:o=["/usr/lib/claude-desktop","/opt/Claude","/usr/bin/claude-desktop",i(e,".local","bin","claude-desktop")]}return o.push(claudeDesktopUserDataDir(),i(claudeDesktopUserDataDir(),"..","Claude")),o.some(e=>t(e))},wantsModelCatalog:!0,loadPrivateConfig(e){const t=I()??{appliedId:"",entries:[]};let o=P(t);o||(o={id:a(),name:C},t.entries.push(o));const n=T(e);x=!0===n.disableDeploymentModeChooser,j={models:n.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const r=E(w(o.id))??{};v(w(o.id),{...r,...n}),t.appliedId=o.id,v(A(),t);const s=E(M())??{};"3p"!==s.deploymentMode&&v(M(),{...s,deploymentMode:"3p"}),R()&&function(e){H();for(const[t,o]of Object.entries(e)){const[e,n]="boolean"==typeof o?["REG_DWORD",o?"1":"0"]:"string"==typeof o?["REG_SZ",o]:["REG_SZ",JSON.stringify(o)];N(["add",G,"/v",t,"/t",e,"/d",n,"/f"])}}(n)},unloadPrivateConfig(){R()&&function(e){const t=F(G);if(!t)return;H();let o=t.size;for(const n of e)t.has(n)&&(N(["delete",G,"/v",n,"/f"]),o-=1);o<=0&&N(["delete",G,"/f"])}(B);const e=I(),t=P(e);if(!e||!t)return;f(w(t.id)),r(w(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(f(A()),r(A(),{force:!0})):v(A(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},detectCurrentConfig(){try{if(R()){const e=F(G)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=P(I());if(!e)return{apiKey:null};const t=E(w(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return d.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=I(),t=P(e);return{meta:e,applied:t?E(w(t.id)):null,desktop:E(M()),...R()?{policy:Object.fromEntries(F(G)??[])}:{}}}catch(e){return d.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;R()&&F(G)?.has("inferenceModels")&&(H(),N(["delete",G,"/v","inferenceModels","/f"]),e=!0);const t=P(I()),o=t?E(w(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;v(w(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(j){const t=j.models.map(e=>`${e.labelOverride}${e.supports1m?" (1M)":""}`).join(", ");e.push(p.t(`tools.claude_desktop.models_written_${j.source}`,{count:String(j.models.length),list:t,groups:j.groups.join(" / ")}))}null!==x&&e.push(p.t(x?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")),e.push(p.t("tools.claude_desktop.restart_hint")),R()&&e.push(p.t("tools.claude_desktop.registry_written",{key:G}));const t=detectManagedConfig();return t&&e.push(p.t("tools.claude_desktop.managed_conflict",{path:t})),e},forceResetPaths(){const e=[A(),M()];try{const t=P(I());t&&e.push(w(t.id))}catch{}return e},backupPaths(){const e=[A(),M()];R()&&e.push(i(claudeDesktopUserDataDir(),$));try{const t=P(I());t&&e.push(w(t.id))}catch{}return e}};
|
|
1
|
+
import{chmodSync as e,existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as s}from"fs";import{dirname as i}from"path";import{join as a}from"path";import{randomUUID as l}from"crypto";import{execFileSync as c}from"child_process";import{userInfo as p}from"os";import{logger as d}from"../../utils/logger.js";import{i18n as u}from"../i18n.js";import{BRAND_NAME as f}from"../brand.js";import{backupBeforeWrite as m,atomicWriteFile as g}from"./backup.js";import{toolHome as h}from"./types.js";import{baseModelId as y,isClaudeModel as b}from"../model-catalog.js";const C=f;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";const k=["Claude_pzs8sxrjxfjjc","AnthropicPBC.Claude_fnn82j28hfe8t"],A=/^[a-f0-9-]{36}$/;function _(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}export function claudeDesktopUserDataDir(){const e=process.env.CLAUDE_USER_DATA_DIR?.trim();if(e)return e;const o=h(),n=Boolean(process.env.VIBECLI_TEST_HOME?.trim());switch(process.platform){case"darwin":return a(o,"Library","Application Support","Claude-3p");case"win32":{const e=!n&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:a(o,"AppData","Local");return k.map(t=>a(e,"Packages",t,"LocalCache","Local","Claude-3p")).find(e=>t(e))??a(e,"Claude-3p")}default:{const e=!n&&process.env.XDG_CONFIG_HOME?process.env.XDG_CONFIG_HOME:a(o,".config");return a(e,"Claude-3p")}}}const D=()=>a(claudeDesktopUserDataDir(),"configLibrary"),w=()=>a(D(),"_meta.json"),E=e=>a(D(),`${e}.json`),M=()=>a(claudeDesktopUserDataDir(),"claude_desktop_config.json");function v(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return _(e)?e:null}catch(t){throw new Error(`Existing ${e} cannot be parsed, back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}function P(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),m(n),g(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){d.logError("claude-desktop.writeJson.chmod",e)}}function O(){const e=v(w());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>_(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function S(e){return e?.entries.find(e=>e.name===C&&A.test(e.id))}const j={opus:0,fable:1,sonnet:2,haiku:3};function I(e){let t=/^claude-(opus|sonnet|haiku|fable)-(\d+(?:-\d+)*)/i.exec(e);return t?{family:t[1].toLowerCase(),version:t[2].split("-").map(Number)}:(t=/^claude-(\d+(?:-\d+)*)-(opus|sonnet|haiku)/i.exec(e),t?{family:t[2].toLowerCase(),version:t[1].split("-").map(Number)}:null)}export function humanizeModelId(e){const t=I(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function x(e){return I(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>y(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(b)){i=[...new Set(t.models.filter(b).map(y))];for(const e of t.oneMillion)r.add(e)}else{i=[];for(const t of["opus","sonnet","haiku","reasoning"]){const o=(e[t]||"").trim(),n=y(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const a=e=>j[x(e)??""]??9;i.sort((e,t)=>{if(e===o)return-1;if(t===o)return 1;const n=a(e)-a(t);if(0!==n)return n;const r=I(e),s=I(t);return r&&s?function(e,t){const o=Math.max(e.length,t.length);for(let n=0;n<o;n++){const o=(t[n]??0)-(e[n]??0);if(0!==o)return o}return 0}(r.version,s.version):e.localeCompare(t)});const l=new Set,c=new Map;for(const e of n){const t=x(e);t&&i.includes(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=x(e),o={name:e,labelOverride:s[e]||humanizeModelId(e)};if(r.has(e)&&(o.supports1m=!0,o.prefer1m=!0),t){o.anthropicFamilyTier=t;const n=c.get(t);n&&n!==e||l.has(t)||(o.isFamilyDefault=!0,l.add(t))}return o})}let L=null,T=null;function $(e){return{inferenceProvider:"gateway",inferenceCredentialKind:"static",inferenceGatewayBaseUrl:(e.baseUrl||"").trim().replace(/\/+$/,""),inferenceGatewayApiKey:e.apiKey,inferenceModels:buildInferenceModels(e.models,e.catalog),disableDeploymentModeChooser:!1!==e.settings?.hide_official_login,chatTabEnabled:!0,chatAdvancedFileAnalysisEnabled:!0,autoModeEnabled:!0,coworkEgressAllowedHosts:["*"],disableEssentialTelemetry:!0,disableNonessentialTelemetry:!0,disableNonessentialServices:!1}}const G={modelPrefer1mContext:!0,skipWebFetchPreflight:!0,toolSearchEnabled:!0,builtinBrowserEnabled:!0,isDesktopExtensionEnabled:!0,sshHostAllowlist:["*"],claudeAiImport:{enabled:!0,automatic3pImport:!0,exportEnabled:!0},coworkVmIpv6Enabled:!0,mcpToolTimeoutSec:3600,updateViaUpdatesHost:!0};function N(e){return Object.fromEntries(Object.entries(G).filter(([t])=>!e(t)))}const U="HKCU\\SOFTWARE\\Policies\\Claude",F="HKLM\\SOFTWARE\\Policies\\Claude",R="vibecli-claude-policy.reg",K=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let H=K;export function setRegRunnerForTests(e){H=e??K}function B(){return"win32"===process.platform}function V(e){let t;try{t=H(["query",e])}catch{return null}const o=new Map;for(const e of t.split(/\r?\n/)){const t=/^\s{2,}(\S+)\s+(REG_[A-Z_]+)\s*(.*)$/.exec(e);t&&o.set(t[1],t[3])}return o}function W(){if(null===V(U))return;const e=a(claudeDesktopUserDataDir(),R);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),m(e),H(["export",U,e,"/y"])}catch(e){d.logError("claude-desktop.snapshotPolicy",e)}}const z=[...Object.keys($({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(G)];export function detectManagedConfig(){try{if("darwin"===process.platform){let e="";try{e=p().username}catch{}return[e?`/Library/Managed Preferences/${e}/com.anthropic.claudefordesktop.plist`:"","/Library/Managed Preferences/com.anthropic.claudefordesktop.plist"].filter(Boolean).find(e=>t(e))??null}if("win32"===process.platform)return V(F)?F:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return d.logError("claude-desktop.detectManagedConfig",e),null}}const J=/\d+\.\d+\.\d+/;function Z(e){const t=e=>e.split(".").map(Number);return e.sort((e,o)=>{const[n,r]=[t(e),t(o)];for(let e=0;e<3;e++)if(n[e]!==r[e])return r[e]-n[e];return 0})[0]??null}const X="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",q="darwin"===process.platform||"win32"===process.platform?"https://cnb.cool/vibeapi/claude-desktop/-/releases/latest":"https://claude.ai/download",Q="darwin"===process.platform?`open ${q}`:"win32"===process.platform?`start ${q}`:`xdg-open ${q}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:X,installCommand:Q,configPath:w(),isInstalled:function(){const e=h();let o;switch(process.platform){case"darwin":o=["/Applications/Claude.app",a(e,"Applications","Claude.app")];break;case"win32":{const t=process.env.LOCALAPPDATA||a(e,"AppData","Local");o=[a(t,"AnthropicClaude"),a(t,"Programs","Claude"),...k.map(e=>a(t,"Packages",e))];break}default:o=["/usr/lib/claude-desktop","/opt/Claude","/usr/bin/claude-desktop",a(e,".local","bin","claude-desktop")]}return o.push(claudeDesktopUserDataDir(),a(claudeDesktopUserDataDir(),"..","Claude")),o.some(e=>t(e))},installedVersion:function(){if("darwin"===process.platform){for(const e of["/Applications/Claude.app",a(h(),"Applications","Claude.app")]){const o=a(e,"Contents","Info.plist");if(!t(o))continue;const n=/<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/.exec(r(o,"utf-8")),s=n?J.exec(n[1])?.[0]:void 0;if(s)return s}return null}if("win32"===process.platform){const e=a(process.env.LOCALAPPDATA||a(h(),"AppData","Local"),"AnthropicClaude");if(t(e)){const t=n(e).map(e=>/^app-(\d+\.\d+\.\d+)$/.exec(e)?.[1]).filter(e=>!!e);if(t.length>0)return Z(t)}const o=k.map(e=>`'${e}'`).join(",");return Z(c("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${o}) -contains $_.PackageFamilyName } | ForEach-Object { $_.Version.ToString() }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).flatMap(e=>J.exec(e)?.[0]??[]))}return null},wantsModelCatalog:!0,loadPrivateConfig(e){const t=O()??{appliedId:"",entries:[]};let o=S(t);o||(o={id:l(),name:C},t.entries.push(o));const n=$(e);T=!0===n.disableDeploymentModeChooser,L={models:n.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const r=v(E(o.id))??{};P(E(o.id),{...N(e=>e in r),...r,...n}),t.appliedId=o.id,P(w(),t);const s=v(M())??{};if("3p"!==s.deploymentMode&&P(M(),{...s,deploymentMode:"3p"}),B()){const e=V(U);!function(e){W();for(const[t,o]of Object.entries(e)){const[e,n]="boolean"==typeof o?["REG_DWORD",o?"1":"0"]:"number"==typeof o?["REG_DWORD",String(o)]:"string"==typeof o?["REG_SZ",o]:["REG_SZ",JSON.stringify(o)];H(["add",U,"/v",t,"/t",e,"/d",n,"/f"])}}({...N(t=>e?.has(t)??!1),...n})}},unloadPrivateConfig(){B()&&function(e){const t=V(U);if(!t)return;W();let o=t.size;for(const n of e)t.has(n)&&(H(["delete",U,"/v",n,"/f"]),o-=1);o<=0&&H(["delete",U,"/f"])}(z);const e=O(),t=S(e);if(!e||!t)return;m(E(t.id)),s(E(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(m(w()),s(w(),{force:!0})):P(w(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},detectCurrentConfig(){try{if(B()){const e=V(U)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=S(O());if(!e)return{apiKey:null};const t=v(E(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return d.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=O(),t=S(e);return{meta:e,applied:t?v(E(t.id)):null,desktop:v(M()),...B()?{policy:Object.fromEntries(V(U)??[])}:{}}}catch(e){return d.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;B()&&V(U)?.has("inferenceModels")&&(W(),H(["delete",U,"/v","inferenceModels","/f"]),e=!0);const t=S(O()),o=t?v(E(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;P(E(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(L){const t=L.models.map(e=>`${e.labelOverride}${e.supports1m?" (1M)":""}`).join(", ");e.push(u.t(`tools.claude_desktop.models_written_${L.source}`,{count:String(L.models.length),list:t,groups:L.groups.join(" / ")}))}null!==T&&e.push(u.t(T?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")),e.push(u.t("tools.claude_desktop.restart_hint")),B()&&e.push(u.t("tools.claude_desktop.registry_written",{key:U}));const t=detectManagedConfig();return t&&e.push(u.t("tools.claude_desktop.managed_conflict",{path:t})),e},forceResetPaths(){const e=[w(),M()];try{const t=S(O());t&&e.push(E(t.id))}catch{}return e},backupPaths(){const e=[w(),M()];B()&&e.push(a(claudeDesktopUserDataDir(),R));try{const t=S(O());t&&e.push(E(t.id))}catch{}return e}};
|
|
@@ -40,6 +40,11 @@ export interface ToolAdapter {
|
|
|
40
40
|
installCommand: string;
|
|
41
41
|
/** Shell command that upgrades an installed copy; defaults to `installCommand`. */
|
|
42
42
|
upgradeCommand?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Installed version as `x.y.z`, for tools without a `--version` CLI (GUI
|
|
45
|
+
* apps); null when unknown. Checked against `models.json` → `toolMinVersions`.
|
|
46
|
+
*/
|
|
47
|
+
installedVersion?(): string | null;
|
|
43
48
|
/** Primary config file path (informational; used for status/doctor output). */
|
|
44
49
|
configPath: string;
|
|
45
50
|
/** Hidden tools are still usable by id but omitted from menus. */
|
package/dist/models.json
CHANGED
package/models.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeapi/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.52",
|
|
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",
|