@vibeapi/cli 0.0.61 → 0.0.62

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.
@@ -40,6 +40,8 @@ export interface SetupCommandOptions {
40
40
  claudeOfficial?: string;
41
41
  /** Replace each tool's config files wholesale (snapshotted first) instead of merging. */
42
42
  force?: boolean;
43
+ /** Windows: `on` = always put Claude Desktop's config in the registry policy (for when the local file is ignored); `off` = back to automatic. */
44
+ desktopRegistry?: string;
43
45
  }
44
46
  /** `--claude-official on|off` (also true/false, show/hide, 1/0, yes/no); undefined when unrecognized. */
45
47
  export declare function parseOnOff(raw: string | undefined): boolean | undefined;
@@ -1 +1 @@
1
- import e from"chalk";import{getAdapter as o}from"../lib/tools/registry.js";import{postApplyPrompts as t}from"../lib/post-apply.js";import{i18n as s}from"../lib/i18n.js";import{configManager as l}from"../lib/config.js";import{toolManager as a,SUPPORTED_TOOLS as i}from"../lib/tool-manager.js";import{validateApiKey as n,fetchModels as d}from"../lib/api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as r,setCodexOneMillionContext as p}from"../lib/tools/codex.js";import{resolveModelCatalog as c}from"../lib/model-catalog.js";import{CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as u}from"../lib/tools/claude-desktop.js";async function f(e){const o=await d(e);if(!o.ok)return{hasClaude:!0,hasGpt:!0,hasGrok:!0,probed:!1};const t=o.models.map(e=>e.toLowerCase());return{hasClaude:t.some(e=>e.includes("claude")),hasGpt:t.some(e=>e.startsWith("gpt")||e.includes("gpt-")||/^o\d/.test(e)),hasGrok:t.some(e=>e.includes("grok")),probed:!0}}function m(e,o){return"claude"===o?e.hasClaude:"gpt"===o?e.hasGpt:e.hasGrok}export function parseOnOff(e){const o=(e??"").trim().toLowerCase();return!!["on","true","show","1","yes","y"].includes(o)||!["off","false","hide","0","no","n"].includes(o)&&void 0}function g(o){console.log(e.green(o))}function y(o){console.log(e.yellow(o))}function k(o){console.error(e.red(o))}async function _(o,t){console.log(e.gray(s.t("setup.validating",{label:o})));const l=await n(t);return!!l.valid||(k(s.t("setup.invalid_key",{label:o,reason:l.message||l.error||"invalid"})),!1)}async function b(o,t,n,d,p){const c=i[o];try{"codex"===o&&void 0!==n&&l.setToolSetting("codex",r,n),"claude-desktop"===o&&void 0!==d&&l.setToolSetting("claude-desktop",u,!d),await a.applyPrivateConfig(o,t,l.getModelsForTool(o),{force:p})}catch(e){const o=(e instanceof Error?e.message:String(e)).replace(/\s+/g," ").trim();return k("× "+s.t("setup.apply_failed",{tool:c.displayName,reason:o})),!1}return a.printApplied(o),p&&console.log(e.gray(" "+s.t("config.force_done",{tool:c.displayName}))),"codex"===o&&void 0!==n&&console.log(e.gray(" "+s.t(n?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))),a.isToolInstalled(o)||console.log(e.yellow(" ! "+s.t("setup.install_hint",{tool:c.displayName,install:c.installCommand}))),!0}export async function setupCommand(e){const n=e.key?.trim(),d=e.claudekey?.trim(),u=e.codexkey?.trim(),h=e.grokkey?.trim(),x=e.desktopkey?.trim(),v=void 0!==e.oneMillion,C=void 0!==e.claudeOfficial;let w;if(C&&(w=parseOnOff(e.claudeOfficial),void 0===w))return k(s.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)})),void(process.exitCode=1);const K=Boolean(n||d||u||h||x);if(!K&&(v||C)){if(v){const o=l.getApiKeyForTool("codex");if(o)try{const t=!0===e.oneMillion;l.setToolSetting("codex",r,t);const a=await c(o);p(t,a??void 0),g(s.t(t?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))}catch(e){k(s.t("setup.apply_failed",{tool:i.codex.displayName,reason:e instanceof Error?e.message:String(e)})),process.exitCode=1}else k(s.t("setup.codex_1m_missing_key")),process.exitCode=1}if(C){const o=l.getApiKeyForTool("claude-desktop");o?await b("claude-desktop",o,void 0,w,e.force)||(process.exitCode=1):(k(s.t("setup.desktop_official_login_missing_key")),process.exitCode=1)}return}if(!K)return k(s.t("setup.usage")),void(process.exitCode=1);let j=0,G=0;const M=new Set,S=[];d&&S.push({tool:"claude-code",label:"--claudekey",apiKey:d,need:"claude"}),u&&S.push({tool:"codex",label:"--codexkey",apiKey:u,need:"gpt"}),h&&S.push({tool:"grok",label:"--grokkey",apiKey:h,need:"grok"}),x&&S.push({tool:"claude-desktop",label:"--desktopkey",apiKey:x,need:"claude"});for(const o of S){if(!await _(o.label,o.apiKey)){G+=1;continue}const t=await f(o.apiKey);!t.probed||m(t,o.need)?(t.probed||y(s.t("setup.probe_failed",{label:o.label})),l.setToolApiKey(o.tool,o.apiKey),await b(o.tool,o.apiKey,e.oneMillion,w,e.force)?(j+=1,M.add(o.tool)):G+=1):(k(s.t(`setup.key_no_${o.need}`,{label:o.label,tool:i[o.tool].displayName})),G+=1)}if(n){if(!await _("--key",n))return void(process.exitCode=1);l.setApiKey(n);const o=await f(n);if(o.probed||y(s.t("setup.probe_failed",{label:"--key"})),o.probed&&!o.hasClaude&&!o.hasGpt&&!o.hasGrok)return k(s.t("setup.key_no_family")),void(process.exitCode=1);const t=[{tool:"claude-code",capable:o.hasClaude,skipMsg:s.t("setup.skip_no_claude")},{tool:"codex",capable:o.hasGpt,skipMsg:s.t("setup.skip_no_gpt")},{tool:"grok",capable:o.hasGrok,skipMsg:s.t("setup.skip_no_grok")},{tool:"claude-desktop",capable:o.hasClaude&&a.isToolInstalled("claude-desktop"),skipMsg:s.t("setup.skip_desktop_not_installed"),quiet:!o.hasClaude}];for(const o of t)M.has(o.tool)||(o.capable?await b(o.tool,n,e.oneMillion,w,e.force)?(j+=1,M.add(o.tool)):G+=1:o.quiet||y(o.skipMsg))}if(j>0){const e=[...M].filter(e=>!o(e)?.isInstalled).map(e=>i[e]?.command).filter(Boolean).join(" / "),t=s.t("setup.done",{count:String(j)});g("\n"+(e?`${t}${s.t("setup.done_commands",{commands:e})}`:t))}G>0&&k(s.t("setup.failed_summary",{count:String(G)})),await t([...M]),(G>0||0===j)&&(process.exitCode=1)}
1
+ import e from"chalk";import{getAdapter as o}from"../lib/tools/registry.js";import{postApplyPrompts as t}from"../lib/post-apply.js";import{i18n as s}from"../lib/i18n.js";import{configManager as i}from"../lib/config.js";import{toolManager as l,SUPPORTED_TOOLS as a}from"../lib/tool-manager.js";import{validateApiKey as d,fetchModels as n}from"../lib/api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as r,setCodexOneMillionContext as p}from"../lib/tools/codex.js";import{resolveModelCatalog as c}from"../lib/model-catalog.js";import{CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING as u,CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as f}from"../lib/tools/claude-desktop.js";async function g(e){const o=await n(e);if(!o.ok)return{hasClaude:!0,hasGpt:!0,hasGrok:!0,probed:!1};const t=o.models.map(e=>e.toLowerCase());return{hasClaude:t.some(e=>e.includes("claude")),hasGpt:t.some(e=>e.startsWith("gpt")||e.includes("gpt-")||/^o\d/.test(e)),hasGrok:t.some(e=>e.includes("grok")),probed:!0}}function m(e,o){return"claude"===o?e.hasClaude:"gpt"===o?e.hasGpt:e.hasGrok}export function parseOnOff(e){const o=(e??"").trim().toLowerCase();return!!["on","true","show","1","yes","y"].includes(o)||!["off","false","hide","0","no","n"].includes(o)&&void 0}function k(o){console.log(e.green(o))}function y(o){console.log(e.yellow(o))}function _(o){console.error(e.red(o))}async function b(o,t){console.log(e.gray(s.t("setup.validating",{label:o})));const i=await d(t);return!!i.valid||(_(s.t("setup.invalid_key",{label:o,reason:i.message||i.error||"invalid"})),!1)}async function h(o,t,d={}){const{oneMillion:n,officialLogin:p,desktopRegistry:c,force:g}=d,m=a[o];try{"claude-desktop"===o&&void 0!==c&&i.setToolSetting("claude-desktop",u,c),"codex"===o&&void 0!==n&&i.setToolSetting("codex",r,n),"claude-desktop"===o&&void 0!==p&&i.setToolSetting("claude-desktop",f,!p),await l.applyPrivateConfig(o,t,i.getModelsForTool(o),{force:g})}catch(e){const o=(e instanceof Error?e.message:String(e)).replace(/\s+/g," ").trim();return _("× "+s.t("setup.apply_failed",{tool:m.displayName,reason:o})),!1}return l.printApplied(o),g&&console.log(e.gray(" "+s.t("config.force_done",{tool:m.displayName}))),"codex"===o&&void 0!==n&&console.log(e.gray(" "+s.t(n?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))),l.isToolInstalled(o)||console.log(e.yellow(" ! "+s.t("setup.install_hint",{tool:m.displayName,install:m.installCommand}))),!0}export async function setupCommand(e){const d=e.key?.trim(),n=e.claudekey?.trim(),u=e.codexkey?.trim(),f=e.grokkey?.trim(),x=e.desktopkey?.trim(),v=void 0!==e.oneMillion,C=void 0!==e.claudeOfficial;let w;if(C&&(w=parseOnOff(e.claudeOfficial),void 0===w))return _(s.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)})),void(process.exitCode=1);const K=void 0!==e.desktopRegistry;let M;if(K&&(M=parseOnOff(e.desktopRegistry),void 0===M))return _(s.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)})),void(process.exitCode=1);const S=C||K,j=Boolean(d||n||u||f||x),G={oneMillion:e.oneMillion,officialLogin:w,desktopRegistry:M,force:e.force};if(!j&&(v||S)){if(v){const o=i.getApiKeyForTool("codex");if(o)try{const t=!0===e.oneMillion;i.setToolSetting("codex",r,t);const l=await c(o);p(t,l??void 0),k(s.t(t?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))}catch(e){_(s.t("setup.apply_failed",{tool:a.codex.displayName,reason:e instanceof Error?e.message:String(e)})),process.exitCode=1}else _(s.t("setup.codex_1m_missing_key")),process.exitCode=1}if(S){const e=i.getApiKeyForTool("claude-desktop");e?await h("claude-desktop",e,{...G,oneMillion:void 0})?await t(["claude-desktop"]):process.exitCode=1:(_(s.t("setup.desktop_official_login_missing_key")),process.exitCode=1)}return}if(!j)return _(s.t("setup.usage")),void(process.exitCode=1);let T=0,O=0;const A=new Set,N=[];n&&N.push({tool:"claude-code",label:"--claudekey",apiKey:n,need:"claude"}),u&&N.push({tool:"codex",label:"--codexkey",apiKey:u,need:"gpt"}),f&&N.push({tool:"grok",label:"--grokkey",apiKey:f,need:"grok"}),x&&N.push({tool:"claude-desktop",label:"--desktopkey",apiKey:x,need:"claude"});for(const e of N){if(!await b(e.label,e.apiKey)){O+=1;continue}const o=await g(e.apiKey);!o.probed||m(o,e.need)?(o.probed||y(s.t("setup.probe_failed",{label:e.label})),i.setToolApiKey(e.tool,e.apiKey),await h(e.tool,e.apiKey,G)?(T+=1,A.add(e.tool)):O+=1):(_(s.t(`setup.key_no_${e.need}`,{label:e.label,tool:a[e.tool].displayName})),O+=1)}if(d){if(!await b("--key",d))return void(process.exitCode=1);i.setApiKey(d);const e=await g(d);if(e.probed||y(s.t("setup.probe_failed",{label:"--key"})),e.probed&&!e.hasClaude&&!e.hasGpt&&!e.hasGrok)return _(s.t("setup.key_no_family")),void(process.exitCode=1);const o=[{tool:"claude-code",capable:e.hasClaude,skipMsg:s.t("setup.skip_no_claude")},{tool:"codex",capable:e.hasGpt,skipMsg:s.t("setup.skip_no_gpt")},{tool:"grok",capable:e.hasGrok,skipMsg:s.t("setup.skip_no_grok")},{tool:"claude-desktop",capable:e.hasClaude&&l.isToolInstalled("claude-desktop"),skipMsg:s.t("setup.skip_desktop_not_installed"),quiet:!e.hasClaude}];for(const e of o)A.has(e.tool)||(e.capable?await h(e.tool,d,G)?(T+=1,A.add(e.tool)):O+=1:e.quiet||y(e.skipMsg))}if(T>0){const e=[...A].filter(e=>!o(e)?.isInstalled).map(e=>a[e]?.command).filter(Boolean).join(" / "),t=s.t("setup.done",{count:String(T)});k("\n"+(e?`${t}${s.t("setup.done_commands",{commands:e})}`:t))}O>0&&_(s.t("setup.failed_summary",{count:String(O)})),await t([...A]),(O>0||0===T)&&(process.exitCode=1)}
@@ -1 +1 @@
1
- import{Command as e}from"commander";import{i18n as o,detectSystemLang as a}from"./i18n.js";import{configManager as t}from"./config.js";import{wizard as i}from"./wizard.js";import{langCommand as n,authCommand as s,doctorCommand as r,configCommand as c,statusCommand as m}from"../commands/index.js";import{logsCommand as l}from"../commands/logs.js";import{completionCommand as p}from"../commands/completion.js";import{benchCommand as d}from"../commands/bench.js";import{updateCommand as g}from"../commands/update.js";import{runModelRefresh as u}from"./model-refresh.js";import{upgradeCommand as f}from"../commands/upgrade.js";import{setupCommand as h}from"../commands/setup.js";import y from"chalk";import{readFileSync as k}from"fs";import{join as b,dirname as v}from"path";import{fileURLToPath as w}from"url";import{setRuntimeOptions as $,detectColorPreferenceFromEnv as C,isColorEnabled as x,isJsonMode as j}from"./runtime-options.js";import{cleanupAnthropicEnvVars as A,machineEnvVarsLeft as I}from"./env-cleanup.js";import{runStartupUpdate as P}from"./auto-update.js";export class Command{program;constructor(){const i=t.isLangChosen()?t.getLang():a();o.loadFromConfig(i),this.program=new e,this.setupProgram()}getVersion(){try{const e=w(import.meta.url),o=v(e),a=b(o,"../../package.json");return JSON.parse(k(a,"utf-8")).version}catch{return"1.0.0"}}setupProgram(){this.program.name("vibecli").description(o.t("cli.title")).version(this.getVersion(),"-v, --version",o.t("commands.version")).helpOption("-h, --help",o.t("commands.help")).option("--base <url>","Custom API base URL").option("--non-interactive","Disable interactive prompts (CI mode)").option("--json","Emit machine-readable JSON output where applicable").option("--yes, -y","Auto-confirm prompts that have a default action").option("--dry-run","Show planned changes without writing anywhere").option("--no-color","Disable colored output"),this.program.command("setup").description(o.t("commands.setup")).option("--key <key>","API key for all capable tools (capability auto-detected)").option("--claudekey <key>","Dedicated API key for Claude Code").option("--codexkey <key>","Dedicated API key for Codex").option("--grokkey <key>","Dedicated API key for Grok Build").option("--desktopkey <key>","Dedicated API key for Claude Desktop (3p mode)").option("--1m","Enable the 1M context window for Codex").option("--no-1m","Disable the 1M context window for Codex").option("--claude-official <on|off>","Claude Desktop: show (on) or hide (off, default) the official Claude.ai sign-in entry").option("--force","Replace each tool's config files wholesale (snapshotted first) instead of merging — repairs hand-broken configs").option("--all","Configure every tool the key can serve (default behavior)").action(async e=>{await h({key:e.key,claudekey:e.claudekey,codexkey:e.codexkey,grokkey:e.grokkey,desktopkey:e.desktopkey,all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,force:e.force})}),this.program.command("init").description(o.t("commands.init")).action(async()=>{await this.handleInitCommand()});const e=this.program.command("lang").description(o.t("commands.lang"));e.command("show").description(o.t("lang.show_usage")).action(async()=>{await n(["show"])}),e.command("set <locale>").description(o.t("lang.set_usage")).action(async e=>{await n(["set",e])});const a=this.program.command("auth").description(o.t("commands.auth"));a.argument("[token]","API token").action(async e=>{const o=[];e&&o.push(e),await s(o)}),a.command("revoke").description("Revoke saved API key").action(async()=>{await s(["revoke"])}),a.command("reload <tool>").description("Reload plan configuration to the specified tool (e.g., claude)").action(async e=>{await s(["reload",e])}),this.program.command("doctor").description(o.t("commands.doctor")).option("--deep","Also send one real Claude Code request through the written config").action(async e=>{await r({deep:e.deep})}),this.program.command("status").description(o.t("commands.status")).action(async()=>{await m()}),this.program.command("logs").description("Inspect vibecli log files").argument("[action]","list|tail|path").argument("[file]","specific log file when using tail").action(async(e,o)=>{const a=[];e&&a.push(e),o&&a.push(o),await l(a)}),this.program.command("completion <shell>").description("Print shell completion script (bash|zsh|fish)").action(async e=>{await p([e])}),this.program.command("update").description("Check for a newer version across CNB and npm mirrors").action(async()=>{await g()}),this.program.command("upgrade [tools...]").description(o.t("commands.upgrade")).action(async(e=[])=>{await f(e)}),this.program.command("bench").description("Benchmark the configured API endpoint").option("--samples <n>","number of samples to send","5").action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),await d(o)}),this.program.command("config").description("Manage profiles, presets, backups, and per-tool config").argument("[args...]","Subcommand and arguments").allowUnknownOption(!0).action(async e=>{await c(e||[])}),this.program.command("enter [option]").description(o.t("commands.enter")).action(async e=>{if(e)switch(e){case"lang":case"language":await i.configLanguage();break;case"apikey":case"api-key":await i.configApiKey();break;case"models":await i.configModels();break;default:{const o=[e];await c(o);break}}else await i.run()}),this.program.action(async()=>{await i.run()}),this.program.configureHelp({sortSubcommands:!0,subcommandTerm:e=>e.name()+" "+e.usage()}),this.program.addHelpText("after",`\n${y.bold(o.t("cli.examples"))}:\n ${y.gray("$ vibecli # Interactive main menu")}\n ${y.gray("$ vibecli init # Run first-time setup wizard")}\n ${y.gray("$ vibecli setup --key sk-xxx # One-shot setup (auto-detect capable tools)")}\n ${y.gray("$ vibecli setup --claudekey sk-a --codexkey sk-b --grokkey sk-c")}\n ${y.gray("$ vibecli setup --desktopkey sk-d --claude-official off # Claude Desktop, hide Claude.ai login")}\n ${y.gray("$ vibecli setup --key sk-xxx --force # Replace broken tool configs with the recommended ones")}\n ${y.gray("$ vibecli config codex --force # Same, for one tool")}\n ${y.gray("$ vibecli status --json # Machine-readable status")}\n ${y.gray("$ vibecli config profile list")}\n ${y.gray("$ vibecli config profile create work")}\n ${y.gray("$ vibecli config profile use work")}\n ${y.gray("$ vibecli config preset save fast")}\n ${y.gray("$ vibecli config backup create snapshot")}\n ${y.gray("$ vibecli auth <token> --non-interactive")}\n ${y.gray("$ vibecli auth revoke --yes")}\n ${y.gray("$ vibecli logs path")}\n ${y.gray("$ vibecli completion bash")}\n ${y.gray("$ vibecli bench --samples 3")}\n ${y.gray("$ vibecli update")}\n ${y.gray("$ vibecli upgrade claude-code")}\n ${y.gray('$ vibecli --base "https://custom.api.com" init # Custom base URL')}\n`)}async handleInitCommand(){await i.runFirstTimeSetup()}cleanupLeakedEnvVars(){const e=A();if(0===e.length||j())return;const a=o.t("messages.env_vars_cleared",{vars:e.join(", ")});console.log(x()?y.yellow(a):a);const t=I();if(t.length>0){const e=o.t("messages.env_vars_machine_left",{vars:t.join(", ")});console.log(x()?y.yellow(e):e)}}preflightArgs(e){const o=o=>e.includes(o),a=!o("--no-color")&&C();let i;$({nonInteractive:o("--non-interactive"),json:o("--json"),yes:o("--yes")||o("-y"),dryRun:o("--dry-run"),color:a}),a||(y.level=0);for(let o=0;o<e.length;o+=1){const a=e[o];if("--base"===a&&e[o+1]){i=e[o+1];break}if(a.startsWith("--base=")){i=a.slice(7);break}}i&&t.setBaseUrl(i)}async execute(e){try{if(this.preflightArgs(e),this.cleanupLeakedEnvVars(),(await P(e)).handled)return;await u(e),await this.program.parseAsync(e,{from:"user"})}catch(e){if(e instanceof Error){const a=x()?y.red:e=>e;console.error(a(o.t("cli.error_general")),e.message)}process.exit(1)}}getProgram(){return this.program}}
1
+ import{Command as e}from"commander";import{i18n as o,detectSystemLang as a}from"./i18n.js";import{configManager as t}from"./config.js";import{wizard as i}from"./wizard.js";import{langCommand as n,authCommand as s,doctorCommand as r,configCommand as c,statusCommand as m}from"../commands/index.js";import{logsCommand as l}from"../commands/logs.js";import{completionCommand as p}from"../commands/completion.js";import{benchCommand as d}from"../commands/bench.js";import{updateCommand as g}from"../commands/update.js";import{runModelRefresh as u}from"./model-refresh.js";import{upgradeCommand as f}from"../commands/upgrade.js";import{setupCommand as h}from"../commands/setup.js";import y from"chalk";import{readFileSync as k}from"fs";import{join as b,dirname as w}from"path";import{fileURLToPath as v}from"url";import{setRuntimeOptions as $,detectColorPreferenceFromEnv as C,isColorEnabled as x,isJsonMode as j}from"./runtime-options.js";import{cleanupAnthropicEnvVars as A,machineEnvVarsLeft as I}from"./env-cleanup.js";import{runStartupUpdate as P}from"./auto-update.js";export class Command{program;constructor(){const i=t.isLangChosen()?t.getLang():a();o.loadFromConfig(i),this.program=new e,this.setupProgram()}getVersion(){try{const e=v(import.meta.url),o=w(e),a=b(o,"../../package.json");return JSON.parse(k(a,"utf-8")).version}catch{return"1.0.0"}}setupProgram(){this.program.name("vibecli").description(o.t("cli.title")).version(this.getVersion(),"-v, --version",o.t("commands.version")).helpOption("-h, --help",o.t("commands.help")).option("--base <url>","Custom API base URL").option("--non-interactive","Disable interactive prompts (CI mode)").option("--json","Emit machine-readable JSON output where applicable").option("--yes, -y","Auto-confirm prompts that have a default action").option("--dry-run","Show planned changes without writing anywhere").option("--no-color","Disable colored output"),this.program.command("setup").description(o.t("commands.setup")).option("--key <key>","API key for all capable tools (capability auto-detected)").option("--claudekey <key>","Dedicated API key for Claude Code").option("--codexkey <key>","Dedicated API key for Codex").option("--grokkey <key>","Dedicated API key for Grok Build").option("--desktopkey <key>","Dedicated API key for Claude Desktop (3p mode)").option("--1m","Enable the 1M context window for Codex").option("--no-1m","Disable the 1M context window for Codex").option("--claude-official <on|off>","Claude Desktop: show (on) or hide (off, default) the official Claude.ai sign-in entry").option("--desktop-registry <on|off>","Windows Claude Desktop: always write the config to the registry policy (on, asks for admin once if needed) or decide automatically (off)").option("--force","Replace each tool's config files wholesale (snapshotted first) instead of merging — repairs hand-broken configs").option("--all","Configure every tool the key can serve (default behavior)").action(async e=>{await h({key:e.key,claudekey:e.claudekey,codexkey:e.codexkey,grokkey:e.grokkey,desktopkey:e.desktopkey,all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,desktopRegistry:e.desktopRegistry,force:e.force})}),this.program.command("init").description(o.t("commands.init")).action(async()=>{await this.handleInitCommand()});const e=this.program.command("lang").description(o.t("commands.lang"));e.command("show").description(o.t("lang.show_usage")).action(async()=>{await n(["show"])}),e.command("set <locale>").description(o.t("lang.set_usage")).action(async e=>{await n(["set",e])});const a=this.program.command("auth").description(o.t("commands.auth"));a.argument("[token]","API token").action(async e=>{const o=[];e&&o.push(e),await s(o)}),a.command("revoke").description("Revoke saved API key").action(async()=>{await s(["revoke"])}),a.command("reload <tool>").description("Reload plan configuration to the specified tool (e.g., claude)").action(async e=>{await s(["reload",e])}),this.program.command("doctor").description(o.t("commands.doctor")).option("--deep","Also send one real Claude Code request through the written config").action(async e=>{await r({deep:e.deep})}),this.program.command("status").description(o.t("commands.status")).action(async()=>{await m()}),this.program.command("logs").description("Inspect vibecli log files").argument("[action]","list|tail|path").argument("[file]","specific log file when using tail").action(async(e,o)=>{const a=[];e&&a.push(e),o&&a.push(o),await l(a)}),this.program.command("completion <shell>").description("Print shell completion script (bash|zsh|fish)").action(async e=>{await p([e])}),this.program.command("update").description("Check for a newer version across CNB and npm mirrors").action(async()=>{await g()}),this.program.command("upgrade [tools...]").description(o.t("commands.upgrade")).action(async(e=[])=>{await f(e)}),this.program.command("bench").description("Benchmark the configured API endpoint").option("--samples <n>","number of samples to send","5").action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),await d(o)}),this.program.command("config").description("Manage profiles, presets, backups, and per-tool config").argument("[args...]","Subcommand and arguments").allowUnknownOption(!0).action(async e=>{await c(e||[])}),this.program.command("enter [option]").description(o.t("commands.enter")).action(async e=>{if(e)switch(e){case"lang":case"language":await i.configLanguage();break;case"apikey":case"api-key":await i.configApiKey();break;case"models":await i.configModels();break;default:{const o=[e];await c(o);break}}else await i.run()}),this.program.action(async()=>{await i.run()}),this.program.configureHelp({sortSubcommands:!0,subcommandTerm:e=>e.name()+" "+e.usage()}),this.program.addHelpText("after",`\n${y.bold(o.t("cli.examples"))}:\n ${y.gray("$ vibecli # Interactive main menu")}\n ${y.gray("$ vibecli init # Run first-time setup wizard")}\n ${y.gray("$ vibecli setup --key sk-xxx # One-shot setup (auto-detect capable tools)")}\n ${y.gray("$ vibecli setup --claudekey sk-a --codexkey sk-b --grokkey sk-c")}\n ${y.gray("$ vibecli setup --desktopkey sk-d --claude-official off # Claude Desktop, hide Claude.ai login")}\n ${y.gray("$ vibecli setup --key sk-xxx --force # Replace broken tool configs with the recommended ones")}\n ${y.gray("$ vibecli config codex --force # Same, for one tool")}\n ${y.gray("$ vibecli status --json # Machine-readable status")}\n ${y.gray("$ vibecli config profile list")}\n ${y.gray("$ vibecli config profile create work")}\n ${y.gray("$ vibecli config profile use work")}\n ${y.gray("$ vibecli config preset save fast")}\n ${y.gray("$ vibecli config backup create snapshot")}\n ${y.gray("$ vibecli auth <token> --non-interactive")}\n ${y.gray("$ vibecli auth revoke --yes")}\n ${y.gray("$ vibecli logs path")}\n ${y.gray("$ vibecli completion bash")}\n ${y.gray("$ vibecli bench --samples 3")}\n ${y.gray("$ vibecli update")}\n ${y.gray("$ vibecli upgrade claude-code")}\n ${y.gray('$ vibecli --base "https://custom.api.com" init # Custom base URL')}\n`)}async handleInitCommand(){await i.runFirstTimeSetup()}cleanupLeakedEnvVars(){const e=A();if(0===e.length||j())return;const a=o.t("messages.env_vars_cleared",{vars:e.join(", ")});console.log(x()?y.yellow(a):a);const t=I();if(t.length>0){const e=o.t("messages.env_vars_machine_left",{vars:t.join(", ")});console.log(x()?y.yellow(e):e)}}preflightArgs(e){const o=o=>e.includes(o),a=!o("--no-color")&&C();let i;$({nonInteractive:o("--non-interactive"),json:o("--json"),yes:o("--yes")||o("-y"),dryRun:o("--dry-run"),color:a}),a||(y.level=0);for(let o=0;o<e.length;o+=1){const a=e[o];if("--base"===a&&e[o+1]){i=e[o+1];break}if(a.startsWith("--base=")){i=a.slice(7);break}}i&&t.setBaseUrl(i)}async execute(e){try{if(this.preflightArgs(e),this.cleanupLeakedEnvVars(),(await P(e)).handled)return;await u(e),await this.program.parseAsync(e,{from:"user"})}catch(e){if(e instanceof Error){const a=x()?y.red:e=>e;console.error(a(o.t("cli.error_general")),e.message)}process.exit(1)}}getProgram(){return this.program}}
@@ -8,6 +8,8 @@ import { type ModelCatalog } from '../model-catalog.js';
8
8
  * the app is gateway-only; `false` leaves the chooser visible.
9
9
  */
10
10
  export declare const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING = "hide_official_login";
11
+ /** Windows: always write the HKCU policy (the user found the local library ignored), never remove it. */
12
+ export declare const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING = "force_registry";
11
13
  /** One model as advertised to Claude Desktop's picker (`inferenceModels[]`). */
12
14
  export interface InferenceModel {
13
15
  name: string;
@@ -1 +1 @@
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 d}from"os";import{logger as p}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{canRestartDesktop as y,isDesktopRunning as k,restartDesktop as b,WINDOWS_PACKAGE_FAMILIES as A}from"./desktop-process.js";import{setUserRegistryElevated as C}from"./elevated-reg.js";import{UserActionNeeded as _}from"./types.js";import{baseModelId as E,isClaudeModel as D}from"../model-catalog.js";const v=f;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";const w=/^[a-f0-9-]{36}$/;function M(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 A.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 O=()=>a(claudeDesktopUserDataDir(),"configLibrary"),P=()=>a(O(),"_meta.json"),S=e=>a(O(),`${e}.json`),x=()=>a(claudeDesktopUserDataDir(),"claude_desktop_config.json");function L(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return M(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 I(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){p.logError("claude-desktop.writeJson.chmod",e)}}function j(){const e=L(P());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>M(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function T(e){return e?.entries.find(e=>e.name===v&&w.test(e.id))}const $={opus:0,fable:1,sonnet:2,haiku:3};function N(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=N(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function G(e){return N(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>E(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(D)){i=[...new Set(t.models.filter(D).map(E))];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=E(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const a=e=>$[G(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=N(e),s=N(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=G(e);t&&i.includes(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=G(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 K=null,U=null,R=null,F=null;function H(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 B={defaultModelEffort:"medium",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 V(e){return Object.fromEntries(Object.entries(B).filter(([t])=>!e(t)))}const J="SOFTWARE\\Policies\\Claude",W=`HKCU\\${J}`,z="HKLM\\SOFTWARE\\Policies\\Claude",Z="vibecli-claude-policy.reg",X=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let q=X;export function setRegRunnerForTests(e){q=e??X}function Q(){return"win32"===process.platform}function Y(e){let t;try{t=q(["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 ee(){if(null===Y(W))return;const e=a(claudeDesktopUserDataDir(),Z);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),m(e),q(["export",W,e,"/y"])}catch(e){p.logError("claude-desktop.snapshotPolicy",e)}}function te(e){ee();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)];q(["add",W,"/v",t,"/t",e,"/d",n,"/f"])}}function oe(e){const t=Y(W);if(!t)return;ee();let o=t.size;for(const n of e)t.has(n)&&(q(["delete",W,"/v",n,"/f"]),o-=1);o<=0&&q(["delete",W,"/f"])}const ne=[...Object.keys(H({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(B),"banner"];export function detectManagedConfig(){try{if("darwin"===process.platform){let e="";try{e=d().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 Y(z)?z:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return p.logError("claude-desktop.detectManagedConfig",e),null}}const re=/\d+\.\d+\.\d+/;function se(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 ie="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",ae="darwin"===process.platform||"win32"===process.platform?"https://cnb.cool/vibeapi/claude-desktop/-/releases/latest":"https://claude.ai/download",le="darwin"===process.platform?`open ${ae}`:"win32"===process.platform?`start ${ae}`:`xdg-open ${ae}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:ie,installCommand:le,configPath:P(),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"),...A.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?re.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 se(t)}const o=A.map(e=>`'${e}'`).join(",");return se(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=>re.exec(e)?.[0]??[]))}return null},runningApp:y()?{isRunning:k,restart:b}:void 0,wantsModelCatalog:!0,loadPrivateConfig(e){const o=j()??{appliedId:"",entries:[]};let n=T(o);n||(n={id:l(),name:v},o.entries.push(n));const r=H(e);U=!0===r.disableDeploymentModeChooser,K={models:r.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const s=L(S(n.id))??{};I(S(n.id),{...V(e=>e in s),...s,...r}),o.appliedId=n.id,I(P(),o);const i=L(x())??{};if("3p"!==i.deploymentMode&&I(x(),{...i,deploymentMode:"3p"}),R=null,F=null,Q()){const e=Y(W),o=ne.filter(t=>e?.has(t)),n={...V(t=>e?.has(t)??!1),...r},s=function(){const e=!Boolean(process.env.VIBECLI_TEST_HOME?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:a(h(),"AppData","Local");return!!t(a(e,"AnthropicClaude"))||A.some(o=>t(a(e,"Packages",o,"LocalCache","Local","Claude-3p")))}();try{s?oe(ne):te(n)}catch(t){p.logError("claude-desktop.policy",t),R=t instanceof Error?t.message.trim():String(t),o.length>0&&(F=s?{action:"remove",values:Object.fromEntries(o.map(e=>[e,null])),deleteKey:o.length===e.size}:{action:"write",values:n,deleteKey:!1})}}},pendingElevation(){const e=F;return e?{prompt:u.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!C(J,e.values,e.deleteKey))return!1;const t=Y(W),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(F=null,R=null),o}}:null},unloadPrivateConfig(){if(Q())try{oe(ne)}catch(e){p.logError("claude-desktop.removePolicy",e)}const e=j(),t=T(e);if(!e||!t)return;m(S(t.id)),s(S(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(m(P()),s(P(),{force:!0})):I(P(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=j(),t=T(e);if(!t||e?.appliedId!==t.id)return null;const o=L(S(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=j(),o=T(t);if(!o||t?.appliedId!==o.id)return;const n=L(S(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog);if(JSON.stringify(n.inferenceModels)!==JSON.stringify(r)){if(Q()&&Y(W)?.has("inferenceModels"))try{te({inferenceModels:r})}catch(e){throw p.logError("claude-desktop.refreshModelMenu registry",e),new _(u.t("tools.claude_desktop.refresh_needs_admin"))}I(S(o.id),{...n,inferenceModels:r})}},detectCurrentConfig(){try{if(Q()){const e=Y(W)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=T(j());if(!e)return{apiKey:null};const t=L(S(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return p.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=j(),t=T(e);return{meta:e,applied:t?L(S(t.id)):null,desktop:L(x()),...Q()?{policy:Object.fromEntries(Y(W)??[])}:{}}}catch(e){return p.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;Q()&&Y(W)?.has("inferenceModels")&&(ee(),q(["delete",W,"/v","inferenceModels","/f"]),e=!0);const t=T(j()),o=t?L(S(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;I(S(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(K&&K.models.length>0){const{models:t,source:o,groups:n}=K;e.push({kind:"summary",text:u.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:u.t(`tools.claude_desktop.models_written_${o}`,{count:String(t.length),list:t.map(e=>`${e.labelOverride}${e.supports1m?" (1M)":""}`).join(", "),groups:n.join(" / ")})})}null!==U&&e.push({kind:"detail",text:u.t(U?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),y()&&!k()||e.push({kind:"action",text:u.t("tools.claude_desktop.restart_hint")}),F?(e.push({kind:"action",text:u.t(`tools.claude_desktop.policy_stale_${F.action}`)}),e.push({kind:"detail",text:R??""})):R?(e.push({kind:"detail",text:u.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:R})):Q()&&e.push({kind:"detail",text:u.t("tools.claude_desktop.registry_written",{key:W})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:u.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[P(),x()];try{const t=T(j());t&&e.push(S(t.id))}catch{}return e},backupPaths(){const e=[P(),x()];Q()&&e.push(a(claudeDesktopUserDataDir(),Z));try{const t=T(j());t&&e.push(S(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 d}from"os";import{logger as p}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{canRestartDesktop as y,isDesktopRunning as k,restartDesktop as b,WINDOWS_PACKAGE_FAMILIES as _}from"./desktop-process.js";import{setUserRegistryElevated as A}from"./elevated-reg.js";import{UserActionNeeded as C}from"./types.js";import{baseModelId as E,isClaudeModel as D}from"../model-catalog.js";const v=f;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const w=/^[a-f0-9-]{36}$/;function M(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 _.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 O=()=>a(claudeDesktopUserDataDir(),"configLibrary"),S=()=>a(O(),"_meta.json"),P=e=>a(O(),`${e}.json`),x=()=>a(claudeDesktopUserDataDir(),"claude_desktop_config.json");function I(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return M(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 L(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){p.logError("claude-desktop.writeJson.chmod",e)}}function j(){const e=I(S());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>M(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function T(e){return e?.entries.find(e=>e.name===v&&w.test(e.id))}const $={opus:0,fable:1,sonnet:2,haiku:3};function G(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=G(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function N(e){return G(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>E(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(D)){i=[...new Set(t.models.filter(D).map(E))];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=E(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const a=e=>$[N(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=G(e),s=G(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=N(e);t&&i.includes(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=N(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 R=null,K=null,U=null,F=null;function H(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 B={defaultModelEffort:"medium",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 V(e){return Object.fromEntries(Object.entries(B).filter(([t])=>!e(t)))}const J="SOFTWARE\\Policies\\Claude",W=`HKCU\\${J}`,z="HKLM\\SOFTWARE\\Policies\\Claude",Z="vibecli-claude-policy.reg",X=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let q=X;export function setRegRunnerForTests(e){q=e??X}function Y(){return"win32"===process.platform}function Q(e){let t;try{t=q(["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 ee(){if(null===Q(W))return;const e=a(claudeDesktopUserDataDir(),Z);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),m(e),q(["export",W,e,"/y"])}catch(e){p.logError("claude-desktop.snapshotPolicy",e)}}function te(e){ee();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)];q(["add",W,"/v",t,"/t",e,"/d",n,"/f"])}}function oe(e){const t=Q(W);if(!t)return;ee();let o=t.size;for(const n of e)t.has(n)&&(q(["delete",W,"/v",n,"/f"]),o-=1);o<=0&&q(["delete",W,"/f"])}const ne=[...Object.keys(H({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(B),"banner"];export function detectManagedConfig(){try{if("darwin"===process.platform){let e="";try{e=d().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 Q(z)?z:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return p.logError("claude-desktop.detectManagedConfig",e),null}}const re=/\d+\.\d+\.\d+/;function se(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 ie="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",ae="darwin"===process.platform||"win32"===process.platform?"https://cnb.cool/vibeapi/claude-desktop/-/releases/latest":"https://claude.ai/download",le="darwin"===process.platform?`open ${ae}`:"win32"===process.platform?`start ${ae}`:`xdg-open ${ae}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:ie,installCommand:le,configPath:S(),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"),..._.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?re.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 se(t)}const o=_.map(e=>`'${e}'`).join(",");return se(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=>re.exec(e)?.[0]??[]))}return null},runningApp:y()?{isRunning:k,restart:b}:void 0,wantsModelCatalog:!0,loadPrivateConfig(e){const o=j()??{appliedId:"",entries:[]};let n=T(o);n||(n={id:l(),name:v},o.entries.push(n));const r=H(e);K=!0===r.disableDeploymentModeChooser,R={models:r.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const s=I(P(n.id))??{};L(P(n.id),{...V(e=>e in s),...s,...r}),o.appliedId=n.id,L(S(),o);const i=I(x())??{};if("3p"!==i.deploymentMode&&L(x(),{...i,deploymentMode:"3p"}),U=null,F=null,Y()){const o=Q(W),n=ne.filter(e=>o?.has(e)),s={...V(e=>o?.has(e)??!1),...r},i=!0===e.settings?.force_registry,l=!i&&function(){const e=!Boolean(process.env.VIBECLI_TEST_HOME?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:a(h(),"AppData","Local");return!!t(a(e,"AnthropicClaude"))||_.some(o=>t(a(e,"Packages",o,"LocalCache","Local","Claude-3p")))}();try{l?oe(ne):te(s)}catch(e){p.logError("claude-desktop.policy",e),U=e instanceof Error?e.message.trim():String(e),(n.length>0||i)&&(F=l?{action:"remove",values:Object.fromEntries(n.map(e=>[e,null])),deleteKey:n.length===o.size}:{action:"write",values:s,deleteKey:!1})}}},pendingElevation(){const e=F;return e?{prompt:u.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!A(J,e.values,e.deleteKey))return!1;const t=Q(W),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(F=null,U=null),o}}:null},unloadPrivateConfig(){if(Y())try{oe(ne)}catch(e){p.logError("claude-desktop.removePolicy",e)}const e=j(),t=T(e);if(!e||!t)return;m(P(t.id)),s(P(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(m(S()),s(S(),{force:!0})):L(S(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=j(),t=T(e);if(!t||e?.appliedId!==t.id)return null;const o=I(P(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=j(),o=T(t);if(!o||t?.appliedId!==o.id)return;const n=I(P(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog);if(JSON.stringify(n.inferenceModels)!==JSON.stringify(r)){if(Y()&&Q(W)?.has("inferenceModels"))try{te({inferenceModels:r})}catch(e){throw p.logError("claude-desktop.refreshModelMenu registry",e),new C(u.t("tools.claude_desktop.refresh_needs_admin"))}L(P(o.id),{...n,inferenceModels:r})}},detectCurrentConfig(){try{if(Y()){const e=Q(W)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=T(j());if(!e)return{apiKey:null};const t=I(P(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return p.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=j(),t=T(e);return{meta:e,applied:t?I(P(t.id)):null,desktop:I(x()),...Y()?{policy:Object.fromEntries(Q(W)??[])}:{}}}catch(e){return p.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;Y()&&Q(W)?.has("inferenceModels")&&(ee(),q(["delete",W,"/v","inferenceModels","/f"]),e=!0);const t=T(j()),o=t?I(P(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;L(P(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(R&&R.models.length>0){const{models:t,source:o,groups:n}=R;e.push({kind:"summary",text:u.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:u.t(`tools.claude_desktop.models_written_${o}`,{count:String(t.length),list:t.map(e=>`${e.labelOverride}${e.supports1m?" (1M)":""}`).join(", "),groups:n.join(" / ")})})}null!==K&&e.push({kind:"detail",text:u.t(K?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),y()&&!k()||e.push({kind:"action",text:u.t("tools.claude_desktop.restart_hint")}),F?(e.push({kind:"action",text:u.t(`tools.claude_desktop.policy_stale_${F.action}`)}),e.push({kind:"detail",text:U??""})):U?(e.push({kind:"detail",text:u.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:U})):Y()&&e.push({kind:"detail",text:u.t("tools.claude_desktop.registry_written",{key:W})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:u.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[S(),x()];try{const t=T(j());t&&e.push(P(t.id))}catch{}return e},backupPaths(){const e=[S(),x()];Y()&&e.push(a(claudeDesktopUserDataDir(),Z));try{const t=T(j());t&&e.push(P(t.id))}catch{}return e}};
@@ -1 +1 @@
1
- import{existsSync as e,readFileSync as o}from"fs";import{join as t}from"path";import*as n from"@iarna/toml";import{logger as i}from"../../utils/logger.js";import{i18n as r}from"../i18n.js";import{backupBeforeWrite as l,atomicWriteFile as a}from"./backup.js";import{pickModel as s,toolHome as d,withV1 as c}from"./types.js";import{getToolDefaultModel as m}from"../model-registry.js";import{buildCodexCatalog as u,codexCatalogPath as p,loadBundledCodexModels as g,loadPreviousCodexModels as _,previousGatewayModelIds as f}from"./codex-catalog.js";import{gatewayModelSpecs as x,modelFamily as y}from"../gateway-models.js";const w=()=>t(d(),".codex"),C=()=>t(w(),"config.toml"),h=()=>t(w(),"auth.json"),j="OPENAI_API_KEY",k="custom",b=1e6,E=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function M(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function O(e,o){return M(e[o])||(e[o]={}),e[o]}function v(){if(!e(C()))return{};const t=o(C(),"utf-8");if(!t.trim())return{};try{const e=n.parse(t);if(!M(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function N(){if(!e(h()))return{};try{const e=JSON.parse(o(h(),"utf-8"));return M(e)?e:{}}catch{return{}}}let S=null;function A(t,n,r){const s=!1!==n.settings?.one_million_context;!function(e){e.model_context_window===b&&delete e.model_context_window,e.model_auto_compact_token_limit===E&&delete e.model_auto_compact_token_limit}(t);const d=g()??_();if(!d)return i.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),S="skipped",t.model_catalog_json===p()&&delete t.model_catalog_json,void(s&&(t.model_context_window=b,t.model_auto_compact_token_limit=E));const c=n.catalog,m=u({bundled:d,specs:x("codex",c?.clientModels),...c?{keyModels:c.models}:{},gatewayAvailable:c?.models??f(),oneMillion:s,selectedModel:r,..."gateway"===c?.oneMillionSource?{claudeOneMillion:c.oneMillion}:{}});S={listed:m.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))};const y=JSON.stringify(m,null,2)+"\n",w=p();e(w)&&o(w,"utf-8")===y||(l(w),a(w,y)),t.model_catalog_json=w}export function setCodexOneMillionContext(e,o){const t=v(),i=n.stringify(t),r="string"==typeof t.model?t.model:m("codex");A(t,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:o},r);const s=n.stringify(t);s!==i&&(l(C()),a(C(),s))}export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:"npm install -g @openai/codex",upgradeCommand:"npm install -g @openai/codex@latest",installSpec:{command:"codex",npmPackage:"@openai/codex",brew:"codex"},configPath:C(),wantsModelCatalog:!0,listedModels(){if(v().model_catalog_json!==p())return null;try{return(JSON.parse(o(p(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){v().model_catalog_json===p()&&setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog)},applyNotes(){if("skipped"===S)return[{kind:"action",text:r.t("tools.codex.catalog_skipped")}];if(!S)return[];const e=new Map;for(const o of S.listed)e.set(y(o.id),(e.get(y(o.id))??0)+1);const o=["gpt","claude","other","grok"].filter(o=>e.has(o)).map(o=>`${r.t(`tools.model_family.${o}`)} ${e.get(o)}`).join(" · ");return[{kind:"summary",text:r.t("tools.codex.catalog_written",{count:String(S.listed.length),breakdown:o})},{kind:"detail",text:S.listed.map(e=>e.name).join(", ")}]},loadPrivateConfig(e){const o=m("codex"),t=s(e.models,o),i=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(t)?o:t,r=c(e.baseUrl),d=v();d.model=i,d.model_provider=k,d.model_reasoning_effort="xhigh",A(d,e,i);const u=O(d,"model_providers"),p=M(u[k])?{...u[k]}:{};delete p.env_key,u[k]={...p,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:r};const g=O(d,"profiles"),_=M(g[i])?{...g[i]}:{};g[i]={..._,model_provider:k,model:i},O(O(d,"tui"),"model_availability_nux")[i]=4;const f=O(d,"features");f.goals=!0,f.js_repl=!1,l(C()),a(C(),n.stringify(d)),function(e){const o=e.trim();if(!o)return;const t={...N(),auth_mode:"apikey",[j]:o};l(h()),a(h(),JSON.stringify(t,null,2)+"\n")}(e.apiKey)},unloadPrivateConfig(){if(!e(C()))return;let o;try{o=v()}catch(e){return void i.logError("codexAdapter.unloadPrivateConfig",e)}const t=o.model_providers;M(t)&&(delete t[k],0===Object.keys(t).length&&delete o.model_providers),o.model_provider===k&&delete o.model_provider,o.model_catalog_json===p()&&delete o.model_catalog_json,l(C()),a(C(),n.stringify(o))},detectCurrentConfig(){const e=N()[j];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return v()}catch(e){return i.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[C(),h(),p()]};
1
+ import{existsSync as e,readFileSync as o}from"fs";import{join as t}from"path";import*as n from"@iarna/toml";import{logger as i}from"../../utils/logger.js";import{i18n as r}from"../i18n.js";import{backupBeforeWrite as l,atomicWriteFile as a}from"./backup.js";import{pickModel as s,toolHome as d,withV1 as c}from"./types.js";import{getToolDefaultModel as m}from"../model-registry.js";import{buildCodexCatalog as u,codexCatalogPath as p,loadBundledCodexModels as g,loadPreviousCodexModels as _,previousGatewayModelIds as f}from"./codex-catalog.js";import{gatewayModelSpecs as x,modelFamily as y}from"../gateway-models.js";const w=()=>t(d(),".codex"),C=()=>t(w(),"config.toml"),h=()=>t(w(),"auth.json"),j="OPENAI_API_KEY",k="custom",b=1e6,E=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function M(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function O(e,o){return M(e[o])||(e[o]={}),e[o]}function v(){if(!e(C()))return{};const t=o(C(),"utf-8");if(!t.trim())return{};try{const e=n.parse(t);if(!M(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function N(){if(!e(h()))return{};try{const e=JSON.parse(o(h(),"utf-8"));return M(e)?e:{}}catch{return{}}}let S=null;function A(t,n,r){const s=!1!==n.settings?.one_million_context;!function(e){e.model_context_window===b&&delete e.model_context_window,e.model_auto_compact_token_limit===E&&delete e.model_auto_compact_token_limit}(t);const d=g()??_();if(!d)return i.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),S="skipped",t.model_catalog_json===p()&&delete t.model_catalog_json,void(s&&(t.model_context_window=b,t.model_auto_compact_token_limit=E));const c=n.catalog,m=u({bundled:d,specs:x("codex",c?.clientModels),...c?{keyModels:c.models}:{},gatewayAvailable:c?.models??f(),oneMillion:s,selectedModel:r,..."gateway"===c?.oneMillionSource?{claudeOneMillion:c.oneMillion}:{}});S={listed:m.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))};const y=JSON.stringify(m,null,2)+"\n",w=p();e(w)&&o(w,"utf-8")===y||(l(w),a(w,y)),t.model_catalog_json=w}export function setCodexOneMillionContext(e,o){const t=v(),i=n.stringify(t),r="string"==typeof t.model?t.model:m("codex");A(t,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:o},r);const s=n.stringify(t);s!==i&&(l(C()),a(C(),s))}export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:"npm install -g @openai/codex",upgradeCommand:"npm install -g @openai/codex@latest",installSpec:{command:"codex",npmPackage:"@openai/codex",brew:"codex"},configPath:C(),wantsModelCatalog:!0,listedModels(){if(v().model_catalog_json!==p())return null;try{return(JSON.parse(o(p(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){v().model_catalog_json===p()&&setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog)},applyNotes(){if("skipped"===S)return[{kind:"action",text:r.t("tools.codex.catalog_skipped")}];if(!S)return[];const e=new Map;for(const o of S.listed)e.set(y(o.id),(e.get(y(o.id))??0)+1);const o=["gpt","claude","other","grok"].filter(o=>e.has(o)).map(o=>`${r.t(`tools.model_family.${o}`)} ${e.get(o)}`).join(" · ");return[{kind:"summary",text:r.t("tools.codex.catalog_written",{count:String(S.listed.length),breakdown:o})},{kind:"detail",text:S.listed.map(e=>e.name).join(", ")}]},loadPrivateConfig(e){const o=m("codex"),t=s(e.models,o),i=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(t)?o:t,r=c(e.baseUrl),d=v();d.model=i,d.model_provider=k,d.model_reasoning_effort="high",A(d,e,i);const u=O(d,"model_providers"),p=M(u[k])?{...u[k]}:{};delete p.env_key,u[k]={...p,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:r};const g=O(d,"profiles"),_=M(g[i])?{...g[i]}:{};g[i]={..._,model_provider:k,model:i},O(O(d,"tui"),"model_availability_nux")[i]=4;const f=O(d,"features");f.goals=!0,f.js_repl=!1,l(C()),a(C(),n.stringify(d)),function(e){const o=e.trim();if(!o)return;const t={...N(),auth_mode:"apikey",[j]:o};l(h()),a(h(),JSON.stringify(t,null,2)+"\n")}(e.apiKey)},unloadPrivateConfig(){if(!e(C()))return;let o;try{o=v()}catch(e){return void i.logError("codexAdapter.unloadPrivateConfig",e)}const t=o.model_providers;M(t)&&(delete t[k],0===Object.keys(t).length&&delete o.model_providers),o.model_provider===k&&delete o.model_provider,o.model_catalog_json===p()&&delete o.model_catalog_json,l(C()),a(C(),n.stringify(o))},detectCurrentConfig(){const e=N()[j];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return v()}catch(e){return i.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[C(),h(),p()]};
@@ -357,7 +357,8 @@
357
357
  "restart_failed": "Could not restart {{tool}}; quit it completely and open it again",
358
358
  "elevation_running": "Click Yes in the Windows prompt…",
359
359
  "elevation_done": "{{tool}} registry updated",
360
- "elevation_failed": "Could not update {{tool}}'s registry (prompt declined, or this account is not an administrator): open PowerShell as administrator and run vibecli setup"
360
+ "elevation_failed": "Could not update {{tool}}'s registry (prompt declined, or this account is not an administrator): open PowerShell as administrator and run vibecli setup",
361
+ "desktop_registry_invalid": "--desktop-registry takes on or off, got {{value}}"
361
362
  },
362
363
  "tools": {
363
364
  "version_outdated": "version {{current}} is too old (needs {{min}} or later); upgrade with {{upgrade}}",
@@ -357,7 +357,8 @@
357
357
  "restart_failed": "{{tool}} 没能自动重启,请完全退出后手动打开",
358
358
  "elevation_running": "请在弹出的系统窗口里点「是」…",
359
359
  "elevation_done": "{{tool}} 的注册表已更新",
360
- "elevation_failed": "没能更新 {{tool}} 的注册表(系统确认被取消,或这个账号不是管理员):用管理员身份打开 PowerShell 再运行 vibecli setup"
360
+ "elevation_failed": "没能更新 {{tool}} 的注册表(系统确认被取消,或这个账号不是管理员):用管理员身份打开 PowerShell 再运行 vibecli setup",
361
+ "desktop_registry_invalid": "--desktop-registry 只接受 on 或 off,收到的是 {{value}}"
361
362
  },
362
363
  "tools": {
363
364
  "version_outdated": "版本 {{current}} 过旧,需要 {{min}} 及以上,运行 {{upgrade}} 升级",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeapi/cli",
3
- "version": "0.0.61",
3
+ "version": "0.0.62",
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",