@vibeapi/api-helper 0.0.131 → 0.0.133

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import{Command as e,Option as o}from"commander";import{readFileSync as s}from"fs";import{join as t,dirname as n}from"path";import{fileURLToPath as a}from"url";import{i18n as i}from"./i18n.js";import{wizard as r}from"./wizard.js";import{SUPPORTED_TOOLS as c}from"./tool-manager.js";import{DEFAULT_BASE_URL as l}from"./config.js";import{attachCommandHelp as p,helpConfiguration as m}from"./cli-help.js";import{langCommand as u,authCommand as d,doctorCommand as f,configCommand as g,statusCommand as x,refreshCommand as h}from"../commands/index.js";import{logsCommand as y}from"../commands/logs.js";import{completionCommand as $}from"../commands/completion.js";import{benchCommand as b}from"../commands/bench.js";import{updateCommand as k}from"../commands/update.js";import{upgradeCommand as _}from"../commands/upgrade.js";import{codexSessionsCommand as w}from"../commands/codex-sessions.js";import{sessionsExportCommand as v,sessionsListCommand as j,sessionsResumeCommand as O,sessionsShowCommand as S}from"../commands/sessions.js";import{setupCommand as A,DEDICATED_KEYS as E}from"../commands/setup.js";import{baseCommand as G}from"../commands/base.js";import{usageError as z}from"./errors.js";import{brand as C,brandEnv as R,CLI_NAME as B}from"./brand.js";const L=(C().gatewayAddresses[1]??C().gatewayAddresses[0]).url,N=(C().gatewayAddresses[2]??C().gatewayAddresses[0]).url;function P(e,o){return i.t(`help.${e}`,o)}function T(e,o){return{command:e,note:P(o)}}function U(e){const o=P(e);return o===`help.${e}`?"":o}function H(e,o=[]){return{when:U(`${e}.when`),prerequisites:U(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>T(e,o))}}function K(e){return e.helpCommand("help [command]",P("help_command"))}export function buildProgram(){const C=new e;C.name(`${B}`).summary(P("root.summary")).description(P("root.description")).configureHelp(m()).allowExcessArguments(!0).optionsGroup(P("group.global_options")).helpOption("-h, --help",P("global.help")).version(function(){try{const e=n(a(import.meta.url));return JSON.parse(s(t(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",P("global.version")).option("--base <url>",P("global.base")).option("--non-interactive",P("global.non_interactive")).option("--json",P("global.json")).option("-y, --yes",P("global.yes")).option("--dry-run",P("global.dry_run")).option("--no-color",P("global.no_color")),C.configureOutput({writeErr:()=>{},outputError:()=>{}}),C.showSuggestionAfterError(),C.exitOverride(e=>{throw e}),C.commandsGroup(P("group.configure"));const U=C.command("setup").summary(P("setup.summary")).description(P("setup.description")).option("--key <key>",P("setup.opt.key"));for(const e of E){const s=new o(`--${e.option} <key>`,P(`setup.opt.${e.option}`));e.hidden&&s.hideHelp(),U.addOption(s)}U.option("--1m",P("setup.opt.one_m")).option("--no-1m",P("setup.opt.no_one_m")).option("--claude-official <on|off>",P("setup.opt.claude_official")).option("--desktop-registry <on|off>",P("setup.opt.desktop_registry")).option("--force",P("setup.opt.force")).option("--install",P("setup.opt.install")).option("--no-install",P("setup.opt.no_install")).option("--all",P("setup.opt.all")).action(async e=>{e.key||E.some(o=>e[o.option])||(e.key=R("SETUP_KEY")?.trim()||void 0,e.fromInstaller=Boolean(e.key));const o=Boolean(e.key||E.some(o=>e[o.option])),s=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,t=i.t("errors.key_placeholder");if(!o&&!s)throw z(i.t("setup.usage"),`${B} setup --key ${t}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw z(i.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),`${B} setup --claude-official on|off`,"invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw z(i.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),`${B} setup --desktop-registry on|off`,"invalid_value");await A({key:e.key,...Object.fromEntries(E.map(o=>[o.option,e[o.option]])),all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,desktopRegistry:e.desktopRegistry,force:e.force,install:e.install})}),p(U,{...H("setup",[[`${B} init`,"setup.alt.init"],[`${B} config <tool>`,"setup.alt.config"],[`${B} auth <key>`,"setup.alt.auth"]]),sections:[{title:P("setup.autodetect_title"),rows:[["Claude",P("setup.autodetect.claude")],["GPT",P("setup.autodetect.gpt")],["Grok",P("setup.autodetect.grok")],["Gemini",P("setup.autodetect.gemini")]]}],examples:[T(`${B} setup --key sk-xxx`,"setup.ex.key"),T(`${B} setup --install --key sk-xxx`,"setup.ex.install"),T(`${B} setup --claudekey sk-a --codexkey sk-b --agykey sk-g`,"setup.ex.split"),T(`${B} setup --force --key sk-xxx`,"setup.ex.force"),T(`${B} setup --base ${L} --key sk-xxx`,"setup.ex.base")]});const M=C.command("init").summary(P("init.summary")).description(P("init.description")).action(async()=>{await r.runFirstTimeSetup()});p(M,{...H("init",[[`${B} setup --key <key>`,"init.alt.setup"],[`${B}`,"init.alt.menu"]]),examples:[T(`${B} init`,"init.ex.run"),T(`${B} init --base ${L}`,"init.ex.base"),T(`${B}`,"init.ex.menu")]});const q=C.command("auth").summary(P("auth.summary")).description(P("auth.description")).argument("[token]",P("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});K(q);const D=q.command("revoke").description(P("auth.revoke")).action(async()=>{await d(["revoke"])});p(D,{examples:[T(`${B} auth revoke`,"auth.ex.revoke_ask"),T(`${B} auth revoke --yes`,"auth.ex.revoke")]});const F=q.command("reload <tool>").description(P("auth.reload")).action(async e=>{await d(["reload",e])});p(F,{examples:[T(`${B} auth reload claude-code`,"auth.ex.reload"),T(`${B} auth reload claude-code --json`,"auth.ex.reload_json")]}),p(q,{...H("auth",[[`${B} setup --key <key>`,"auth.alt.setup"]]),examples:[T(`${B} auth`,"auth.ex.prompt"),T(`${B} auth sk-xxx --non-interactive`,"auth.ex.save"),T(`${B} auth revoke --yes`,"auth.ex.revoke"),T(`${B} auth reload claude-code`,"auth.ex.reload")]});const I=C.command("config").summary(P("config.summary")).description(P("config.description")).argument("[args...]",P("config.arg.args")).option("-f, --force",P("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await g(o.force?[...e,"--force"]:e)});p(I,{...H("config",[[`${B} setup --force --key <key>`,"config.alt.setup"],[`${B} status`,"config.alt.status"]]),sections:[{title:P("config.subcommands_title"),rows:[["<tool>",P("config.sub.tool")],["<tool> --force",P("config.sub.tool_force")],["<tool> --non-interactive",P("config.sub.tool_non_interactive")],["<tool> remove",P("config.sub.tool_remove")],["<tool> restore",P("config.sub.tool_restore")],["<tool> backups",P("config.sub.tool_backups")],["<tool> clear-model",P("config.sub.tool_clear_model")],["tool-model list",P("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",P("config.sub.tool_model_set")],["tool-model clear <tool>",P("config.sub.tool_model_clear")],["profile list",P("config.sub.profile_list")],["profile create <name>",P("config.sub.profile_create")],["profile use <name>",P("config.sub.profile_use")],["profile delete <name>",P("config.sub.profile_delete")],["preset list",P("config.sub.preset_list")],["preset save <name>",P("config.sub.preset_save")],["preset use <name>",P("config.sub.preset_use")],["preset delete <name>",P("config.sub.preset_delete")],["backup list",P("config.sub.backup_list")],["backup create [label]",P("config.sub.backup_create")],["backup restore <name>",P("config.sub.backup_restore")]]},{title:P("config.tools_title"),rows:Object.values(c).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[T(`${B} config codex`,"config.ex.menu"),T(`${B} config claude-code --force`,"config.ex.force"),T(`${B} config tool-model set codex gpt-6-astra`,"config.ex.tool_model"),T(`${B} config profile create work`,"config.ex.profile"),T(`${B} config codex remove`,"config.ex.remove")]});const J=C.command("base").summary(P("base.summary")).description(P("base.description")).argument("[target]",P("base.arg.target")).action(async e=>{await G(e)});p(J,{...H("base",[[`${B} doctor`,"base.alt.doctor"],[`${B} bench`,"base.alt.bench"]]),sections:[{title:P("base.targets_title"),rows:[[P("base.target.none_term"),P("base.target.none")],[P("base.target.index_term"),P("base.target.index")],[P("base.target.url_term"),P("base.target.url")],["auto",P("base.target.auto")],["default",P("base.target.default",{url:l})]]}],examples:[T(`${B} base`,"base.ex.list"),T(`${B} base auto`,"base.ex.auto"),T(`${B} base 2`,"base.ex.index"),T(`${B} base ${L}`,"base.ex.url"),T(`${B} base default`,"base.ex.default")]}),C.commandsGroup(P("group.diagnose"));const Y=C.command("status").summary(P("status.summary")).description(P("status.description")).action(async()=>{await x()});p(Y,{...H("status",[[`${B} doctor`,"status.alt.doctor"]]),examples:[T(`${B} status`,"status.ex.show"),T(`${B} status --json`,"status.ex.json")]});const Q=C.command("doctor").summary(P("doctor.summary")).description(P("doctor.description")).option("--deep",P("doctor.opt.deep")).option("--report",P("doctor.opt.report")).action(async e=>{await f({deep:e.deep,report:e.report})});p(Q,{...H("doctor",[[`${B} base auto`,"doctor.alt.base"],[`${B} logs tail`,"doctor.alt.logs"]]),examples:[T(`${B} doctor`,"doctor.ex.run"),T(`${B} doctor --deep`,"doctor.ex.deep"),T(`${B} doctor --report`,"doctor.ex.report")]});const V=C.command("bench").summary(P("bench.summary")).description(P("bench.description")).option("--samples <n>",P("bench.opt.samples"),"5").option("--stream",P("bench.opt.stream")).option("--model <model>",P("bench.opt.model")).action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),e.stream&&o.push("--stream"),e.model&&o.push("--model",e.model),await b(o)});p(V,{...H("bench",[[`${B} base`,"bench.alt.base"]]),examples:[T(`${B} bench`,"bench.ex.run"),T(`${B} bench --samples 3`,"bench.ex.samples"),T(`${B} bench --stream`,"bench.ex.stream"),T(`${B} bench --stream --model gpt-6-astra`,"bench.ex.stream_model"),T(`${B} bench --json`,"bench.ex.json")]});const W=C.command("logs").summary(P("logs.summary")).description(P("logs.description")).argument("[action]",P("logs.arg.action")).argument("[file]",P("logs.arg.file")).action(async(e,o)=>{const s=[];e&&s.push(e),o&&s.push(o),await y(s)});p(W,{...H("logs",[[`${B} doctor`,"logs.alt.doctor"]]),sections:[{title:P("logs.actions_title"),rows:[["list",P("logs.action.list")],["tail [file]",P("logs.action.tail")],["path",P("logs.action.path")]]}],examples:[T(`${B} logs`,"logs.ex.list"),T(`${B} logs tail`,"logs.ex.tail"),T(`${B} logs path`,"logs.ex.path")]}),C.commandsGroup(P("group.maintain"));const X=C.command("upgrade").summary(P("upgrade.summary")).description(P("upgrade.description")).argument("[tools...]",P("upgrade.arg.tools")).action(async(e=[])=>{await _(e)});p(X,{...H("upgrade",[[`${B} update`,"upgrade.alt.update"]]),examples:[T(`${B} upgrade`,"upgrade.ex.all"),T(`${B} upgrade claude-code`,"upgrade.ex.one"),T(`${B} upgrade codex agy`,"upgrade.ex.many")]});const Z=C.command("refresh").summary(P("refresh.summary")).description(P("refresh.description")).action(async()=>{await h()});p(Z,{...H("refresh",[[`${B} setup --key ${i.t("errors.key_placeholder")}`,"refresh.alt.setup"]]),examples:[T(`${B} refresh`,"refresh.ex.run"),T(`${B} refresh --base ${N}`,"refresh.ex.base")]});const ee=C.command("update").summary(P("update.summary")).description(P("update.description")).action(async()=>{await k()});p(ee,{...H("update",[[`${B} upgrade`,"update.alt.upgrade"]]),examples:[T(`${B} update`,"update.ex.check"),T(`${B} update --json`,"update.ex.json")]});const oe=C.command("codex").summary(P("codex.summary")).description(P("codex.description"));K(oe);const se=oe.command("sessions").summary(P("codex_sessions.summary")).description(P("codex_sessions.description")).option("--to <provider>",P("codex_sessions.opt.to")).option("--undo <dir>",P("codex_sessions.opt.undo")).action(async e=>{await w(e)});p(oe,{...H("codex"),examples:[T(`${B} codex sessions`,"codex_sessions.ex.move"),T(`${B} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]}),p(se,{...H("codex_sessions",[[`${B} codex sessions --undo <dir>`,"codex_sessions.alt.undo"]]),examples:[T(`${B} codex sessions`,"codex_sessions.ex.move"),T(`${B} codex sessions --to custom`,"codex_sessions.ex.to"),T(`${B} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]});const te=C.command("sessions").summary(P("sessions.summary")).description(P("sessions.description"));K(te);const ne=te.command("list",{isDefault:!0}).description(P("sessions.list")).option("--tool <tool>",P("sessions.opt.tool")).option("--dir <path>",P("sessions.opt.dir")).option("--here",P("sessions.opt.here")).option("-n, --limit <count>",P("sessions.opt.limit")).option("--all",P("sessions.opt.all")).action(async e=>{await j(e)}),ae=te.command("show <id>").description(P("sessions.show")).option("-m, --messages <count>",P("sessions.opt.messages")).action(async(e,o)=>{await S(e,o)}),ie=te.command("resume <id>").description(P("sessions.resume")).option("--run",P("sessions.opt.run")).action(async(e,o)=>{await O(e,o)}),re=te.command("export <ids...>").description(P("sessions.export")).option("-o, --output <dir>",P("sessions.opt.output")).option("--tools",P("sessions.opt.tools")).action(async(e,o)=>{await v(e,o)});p(ne,{examples:[T(`${B} sessions list`,"sessions.ex.list"),T(`${B} sessions list --tool codex`,"sessions.ex.codex"),T(`${B} sessions list --here --all`,"sessions.ex.here"),T(`${B} sessions list --json`,"sessions.ex.json")]}),p(ae,{examples:[T(`${B} sessions show 01a0f5fe`,"sessions.ex.show"),T(`${B} sessions show 01a0f5fe -m 20`,"sessions.ex.show_more")]}),p(ie,{examples:[T(`${B} sessions resume 01a0f5fe`,"sessions.ex.resume_print"),T(`${B} sessions resume 01a0f5fe --run`,"sessions.ex.resume")]}),p(re,{examples:[T(`${B} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export"),T(`${B} sessions export 01a0f5fe -o ./sessions --tools`,"sessions.ex.export_tools")]}),p(te,{...H("sessions",[[`${B} codex sessions`,"sessions.alt.codex_sessions"]]),examples:[T(`${B} sessions`,"sessions.ex.list"),T(`${B} sessions --tool codex --here`,"sessions.ex.here"),T(`${B} sessions show 01a0f5fe`,"sessions.ex.show"),T(`${B} sessions resume 01a0f5fe --run`,"sessions.ex.resume"),T(`${B} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export")]});const ce=C.command("lang").summary(P("lang.summary")).description(P("lang.description"));K(ce);const le=ce.command("show").description(P("lang.show")).action(async()=>{await u(["show"])}),pe=ce.command("set <locale>").description(P("lang.set")).action(async e=>{await u(["set",e])}),me=[T(`${B} lang show`,"lang.ex.show"),T(`${B} lang set en_US`,"lang.ex.set_en"),T(`${B} lang set zh_CN`,"lang.ex.set_zh")];p(ce,{...H("lang",[[`${B} enter lang`,"lang.alt.enter"]]),examples:me}),p(le,{examples:[me[0],T(`${B} lang show --json`,"lang.ex.show_json")]}),p(pe,{examples:me.slice(1)});const ue=C.command("completion").summary(P("completion.summary")).description(P("completion.description")).argument("<shell>",P("completion.arg.shell")).action(async e=>{await $([e])});p(ue,{...H("completion"),examples:[T(`${B} completion bash > ~/.${B}-completion.bash`,"completion.ex.bash"),T(`${B} completion zsh > ~/.${B}-completion.zsh`,"completion.ex.zsh"),T(`${B} completion fish > ~/.config/fish/completions/${B}.fish`,"completion.ex.fish")]});const de=C.command("enter").summary(P("enter.summary")).description(P("enter.description")).argument("[option]",P("enter.arg.option")).action(async e=>{if(e)switch(e){case"lang":case"language":await r.configLanguage();break;case"apikey":case"api-key":await r.configApiKey();break;case"models":await r.configModels();break;default:await g([e])}else await r.run()});p(de,{...H("enter",[[`${B}`,"enter.alt.menu"],[`${B} config <tool>`,"enter.alt.config"]]),sections:[{title:P("enter.options_title"),rows:[[P("enter.option.none_term"),P("enter.option.none")],["lang",P("enter.option.lang")],["apikey",P("enter.option.apikey")],["models",P("enter.option.models")],["<tool>",P("enter.option.tool")]]}],examples:[T(`${B} enter`,"enter.ex.menu"),T(`${B} enter models`,"enter.ex.models"),T(`${B} enter codex`,"enter.ex.tool")]}),K(C),C.action(async()=>{await r.run()}),p(C,{examples:[T(`${B}`,"root.ex.menu"),T(`${B} setup --key sk-xxx`,"root.ex.setup"),T(`${B} doctor`,"root.ex.doctor"),T(`${B} base auto`,"root.ex.base"),T(`${B} config codex`,"root.ex.config")]});const fe=e=>{for(const o of e.commands)o.helpOption("-h, --help",P("global.help")),fe(o)};return fe(C),C}
1
+ import{Command as e,Option as o}from"commander";import{readFileSync as s}from"fs";import{join as t,dirname as n}from"path";import{fileURLToPath as a}from"url";import{i18n as i}from"./i18n.js";import{wizard as r}from"./wizard.js";import{SUPPORTED_TOOLS as c}from"./tool-manager.js";import{DEFAULT_BASE_URL as l}from"./config.js";import{attachCommandHelp as p,helpConfiguration as m}from"./cli-help.js";import{langCommand as u,authCommand as d,doctorCommand as f,configCommand as g,statusCommand as x,refreshCommand as h}from"../commands/index.js";import{logsCommand as y}from"../commands/logs.js";import{completionCommand as $}from"../commands/completion.js";import{benchCommand as b}from"../commands/bench.js";import{updateCommand as k}from"../commands/update.js";import{upgradeCommand as _}from"../commands/upgrade.js";import{codexSessionsCommand as w}from"../commands/codex-sessions.js";import{sessionsExportCommand as v,sessionsListCommand as j,sessionsResumeCommand as O,sessionsShowCommand as S}from"../commands/sessions.js";import{setupCommand as A,DEDICATED_KEYS as E}from"../commands/setup.js";import{baseCommand as G}from"../commands/base.js";import{usageError as z}from"./errors.js";import{brand as C,brandEnv as R,CLI_NAME as B}from"./brand.js";const I=(C().gatewayAddresses[1]??C().gatewayAddresses[0]).url,L=(C().gatewayAddresses[2]??C().gatewayAddresses[0]).url;function N(e,o){return i.t(`help.${e}`,o)}function P(e,o){return{command:e,note:N(o)}}function T(e){const o=N(e);return o===`help.${e}`?"":o}function U(e,o=[]){return{when:T(`${e}.when`),prerequisites:T(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>P(e,o))}}function H(e){return e.helpCommand("help [command]",N("help_command"))}export function buildProgram(){const C=new e;C.name(`${B}`).summary(N("root.summary")).description(N("root.description")).configureHelp(m()).allowExcessArguments(!0).optionsGroup(N("group.global_options")).helpOption("-h, --help",N("global.help")).version(function(){try{const e=n(a(import.meta.url));return JSON.parse(s(t(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",N("global.version")).option("--base <url>",N("global.base")).option("--non-interactive",N("global.non_interactive")).option("--json",N("global.json")).option("-y, --yes",N("global.yes")).option("--dry-run",N("global.dry_run")).option("--no-color",N("global.no_color")),C.configureOutput({writeErr:()=>{},outputError:()=>{}}),C.showSuggestionAfterError(),C.exitOverride(e=>{throw e}),C.commandsGroup(N("group.configure"));const T=C.command("setup").summary(N("setup.summary")).description(N("setup.description")).option("--key <key>",N("setup.opt.key"));for(const e of E){const s=new o(`--${e.option} <key>`,N(`setup.opt.${e.option}`));e.hidden&&s.hideHelp(),T.addOption(s)}T.option("--1m",N("setup.opt.one_m")).option("--no-1m",N("setup.opt.no_one_m")).option("--claude-official <on|off>",N("setup.opt.claude_official")).option("--desktop-registry <on|off>",N("setup.opt.desktop_registry")).option("--force",N("setup.opt.force")).option("--install",N("setup.opt.install")).option("--no-install",N("setup.opt.no_install")).option("--all",N("setup.opt.all")).action(async e=>{e.key||E.some(o=>e[o.option])||(e.key=R("SETUP_KEY")?.trim()||void 0,e.fromInstaller=Boolean(e.key));const o=Boolean(e.key||E.some(o=>e[o.option])),s=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,t=i.t("errors.key_placeholder");if(!o&&!s)throw z(i.t("setup.usage"),`${B} setup --key ${t}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw z(i.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),`${B} setup --claude-official on|off`,"invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw z(i.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),`${B} setup --desktop-registry on|off`,"invalid_value");await A({key:e.key,...Object.fromEntries(E.map(o=>[o.option,e[o.option]])),all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,desktopRegistry:e.desktopRegistry,force:e.force,install:e.install,fromInstaller:e.fromInstaller})}),p(T,{...U("setup",[[`${B} init`,"setup.alt.init"],[`${B} config <tool>`,"setup.alt.config"],[`${B} auth <key>`,"setup.alt.auth"]]),sections:[{title:N("setup.autodetect_title"),rows:[["Claude",N("setup.autodetect.claude")],["GPT",N("setup.autodetect.gpt")],["Grok",N("setup.autodetect.grok")],["Gemini",N("setup.autodetect.gemini")]]}],examples:[P(`${B} setup --key sk-xxx`,"setup.ex.key"),P(`${B} setup --install --key sk-xxx`,"setup.ex.install"),P(`${B} setup --claudekey sk-a --codexkey sk-b --agykey sk-g`,"setup.ex.split"),P(`${B} setup --force --key sk-xxx`,"setup.ex.force"),P(`${B} setup --base ${I} --key sk-xxx`,"setup.ex.base")]});const K=C.command("init").summary(N("init.summary")).description(N("init.description")).action(async()=>{await r.runFirstTimeSetup()});p(K,{...U("init",[[`${B} setup --key <key>`,"init.alt.setup"],[`${B}`,"init.alt.menu"]]),examples:[P(`${B} init`,"init.ex.run"),P(`${B} init --base ${I}`,"init.ex.base"),P(`${B}`,"init.ex.menu")]});const M=C.command("auth").summary(N("auth.summary")).description(N("auth.description")).argument("[token]",N("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});H(M);const q=M.command("revoke").description(N("auth.revoke")).action(async()=>{await d(["revoke"])});p(q,{examples:[P(`${B} auth revoke`,"auth.ex.revoke_ask"),P(`${B} auth revoke --yes`,"auth.ex.revoke")]});const D=M.command("reload <tool>").description(N("auth.reload")).action(async e=>{await d(["reload",e])});p(D,{examples:[P(`${B} auth reload claude-code`,"auth.ex.reload"),P(`${B} auth reload claude-code --json`,"auth.ex.reload_json")]}),p(M,{...U("auth",[[`${B} setup --key <key>`,"auth.alt.setup"]]),examples:[P(`${B} auth`,"auth.ex.prompt"),P(`${B} auth sk-xxx --non-interactive`,"auth.ex.save"),P(`${B} auth revoke --yes`,"auth.ex.revoke"),P(`${B} auth reload claude-code`,"auth.ex.reload")]});const F=C.command("config").summary(N("config.summary")).description(N("config.description")).argument("[args...]",N("config.arg.args")).option("-f, --force",N("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await g(o.force?[...e,"--force"]:e)});p(F,{...U("config",[[`${B} setup --force --key <key>`,"config.alt.setup"],[`${B} status`,"config.alt.status"]]),sections:[{title:N("config.subcommands_title"),rows:[["<tool>",N("config.sub.tool")],["<tool> --force",N("config.sub.tool_force")],["<tool> --non-interactive",N("config.sub.tool_non_interactive")],["<tool> remove",N("config.sub.tool_remove")],["<tool> restore",N("config.sub.tool_restore")],["<tool> backups",N("config.sub.tool_backups")],["<tool> clear-model",N("config.sub.tool_clear_model")],["tool-model list",N("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",N("config.sub.tool_model_set")],["tool-model clear <tool>",N("config.sub.tool_model_clear")],["profile list",N("config.sub.profile_list")],["profile create <name>",N("config.sub.profile_create")],["profile use <name>",N("config.sub.profile_use")],["profile delete <name>",N("config.sub.profile_delete")],["preset list",N("config.sub.preset_list")],["preset save <name>",N("config.sub.preset_save")],["preset use <name>",N("config.sub.preset_use")],["preset delete <name>",N("config.sub.preset_delete")],["backup list",N("config.sub.backup_list")],["backup create [label]",N("config.sub.backup_create")],["backup restore <name>",N("config.sub.backup_restore")]]},{title:N("config.tools_title"),rows:Object.values(c).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[P(`${B} config codex`,"config.ex.menu"),P(`${B} config claude-code --force`,"config.ex.force"),P(`${B} config tool-model set codex gpt-6-astra`,"config.ex.tool_model"),P(`${B} config profile create work`,"config.ex.profile"),P(`${B} config codex remove`,"config.ex.remove")]});const J=C.command("base").summary(N("base.summary")).description(N("base.description")).argument("[target]",N("base.arg.target")).action(async e=>{await G(e)});p(J,{...U("base",[[`${B} doctor`,"base.alt.doctor"],[`${B} bench`,"base.alt.bench"]]),sections:[{title:N("base.targets_title"),rows:[[N("base.target.none_term"),N("base.target.none")],[N("base.target.index_term"),N("base.target.index")],[N("base.target.url_term"),N("base.target.url")],["auto",N("base.target.auto")],["default",N("base.target.default",{url:l})]]}],examples:[P(`${B} base`,"base.ex.list"),P(`${B} base auto`,"base.ex.auto"),P(`${B} base 2`,"base.ex.index"),P(`${B} base ${I}`,"base.ex.url"),P(`${B} base default`,"base.ex.default")]}),C.commandsGroup(N("group.diagnose"));const Y=C.command("status").summary(N("status.summary")).description(N("status.description")).action(async()=>{await x()});p(Y,{...U("status",[[`${B} doctor`,"status.alt.doctor"]]),examples:[P(`${B} status`,"status.ex.show"),P(`${B} status --json`,"status.ex.json")]});const Q=C.command("doctor").summary(N("doctor.summary")).description(N("doctor.description")).option("--deep",N("doctor.opt.deep")).option("--report",N("doctor.opt.report")).action(async e=>{await f({deep:e.deep,report:e.report})});p(Q,{...U("doctor",[[`${B} base auto`,"doctor.alt.base"],[`${B} logs tail`,"doctor.alt.logs"]]),examples:[P(`${B} doctor`,"doctor.ex.run"),P(`${B} doctor --deep`,"doctor.ex.deep"),P(`${B} doctor --report`,"doctor.ex.report")]});const V=C.command("bench").summary(N("bench.summary")).description(N("bench.description")).option("--samples <n>",N("bench.opt.samples"),"5").option("--stream",N("bench.opt.stream")).option("--model <model>",N("bench.opt.model")).action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),e.stream&&o.push("--stream"),e.model&&o.push("--model",e.model),await b(o)});p(V,{...U("bench",[[`${B} base`,"bench.alt.base"]]),examples:[P(`${B} bench`,"bench.ex.run"),P(`${B} bench --samples 3`,"bench.ex.samples"),P(`${B} bench --stream`,"bench.ex.stream"),P(`${B} bench --stream --model gpt-6-astra`,"bench.ex.stream_model"),P(`${B} bench --json`,"bench.ex.json")]});const W=C.command("logs").summary(N("logs.summary")).description(N("logs.description")).argument("[action]",N("logs.arg.action")).argument("[file]",N("logs.arg.file")).action(async(e,o)=>{const s=[];e&&s.push(e),o&&s.push(o),await y(s)});p(W,{...U("logs",[[`${B} doctor`,"logs.alt.doctor"]]),sections:[{title:N("logs.actions_title"),rows:[["list",N("logs.action.list")],["tail [file]",N("logs.action.tail")],["path",N("logs.action.path")]]}],examples:[P(`${B} logs`,"logs.ex.list"),P(`${B} logs tail`,"logs.ex.tail"),P(`${B} logs path`,"logs.ex.path")]}),C.commandsGroup(N("group.maintain"));const X=C.command("upgrade").summary(N("upgrade.summary")).description(N("upgrade.description")).argument("[tools...]",N("upgrade.arg.tools")).action(async(e=[])=>{await _(e)});p(X,{...U("upgrade",[[`${B} update`,"upgrade.alt.update"]]),examples:[P(`${B} upgrade`,"upgrade.ex.all"),P(`${B} upgrade claude-code`,"upgrade.ex.one"),P(`${B} upgrade codex agy`,"upgrade.ex.many")]});const Z=C.command("refresh").summary(N("refresh.summary")).description(N("refresh.description")).action(async()=>{await h()});p(Z,{...U("refresh",[[`${B} setup --key ${i.t("errors.key_placeholder")}`,"refresh.alt.setup"]]),examples:[P(`${B} refresh`,"refresh.ex.run"),P(`${B} refresh --base ${L}`,"refresh.ex.base")]});const ee=C.command("update").summary(N("update.summary")).description(N("update.description")).action(async()=>{await k()});p(ee,{...U("update",[[`${B} upgrade`,"update.alt.upgrade"]]),examples:[P(`${B} update`,"update.ex.check"),P(`${B} update --json`,"update.ex.json")]});const oe=C.command("codex").summary(N("codex.summary")).description(N("codex.description"));H(oe);const se=oe.command("sessions").summary(N("codex_sessions.summary")).description(N("codex_sessions.description")).option("--to <provider>",N("codex_sessions.opt.to")).option("--undo <dir>",N("codex_sessions.opt.undo")).action(async e=>{await w(e)});p(oe,{...U("codex"),examples:[P(`${B} codex sessions`,"codex_sessions.ex.move"),P(`${B} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]}),p(se,{...U("codex_sessions",[[`${B} codex sessions --undo <dir>`,"codex_sessions.alt.undo"]]),examples:[P(`${B} codex sessions`,"codex_sessions.ex.move"),P(`${B} codex sessions --to custom`,"codex_sessions.ex.to"),P(`${B} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]});const te=C.command("sessions").summary(N("sessions.summary")).description(N("sessions.description"));H(te);const ne=te.command("list",{isDefault:!0}).description(N("sessions.list")).option("--tool <tool>",N("sessions.opt.tool")).option("--dir <path>",N("sessions.opt.dir")).option("--here",N("sessions.opt.here")).option("-n, --limit <count>",N("sessions.opt.limit")).option("--all",N("sessions.opt.all")).action(async e=>{await j(e)}),ae=te.command("show <id>").description(N("sessions.show")).option("-m, --messages <count>",N("sessions.opt.messages")).action(async(e,o)=>{await S(e,o)}),ie=te.command("resume <id>").description(N("sessions.resume")).option("--run",N("sessions.opt.run")).action(async(e,o)=>{await O(e,o)}),re=te.command("export <ids...>").description(N("sessions.export")).option("-o, --output <dir>",N("sessions.opt.output")).option("--tools",N("sessions.opt.tools")).action(async(e,o)=>{await v(e,o)});p(ne,{examples:[P(`${B} sessions list`,"sessions.ex.list"),P(`${B} sessions list --tool codex`,"sessions.ex.codex"),P(`${B} sessions list --here --all`,"sessions.ex.here"),P(`${B} sessions list --json`,"sessions.ex.json")]}),p(ae,{examples:[P(`${B} sessions show 01a0f5fe`,"sessions.ex.show"),P(`${B} sessions show 01a0f5fe -m 20`,"sessions.ex.show_more")]}),p(ie,{examples:[P(`${B} sessions resume 01a0f5fe`,"sessions.ex.resume_print"),P(`${B} sessions resume 01a0f5fe --run`,"sessions.ex.resume")]}),p(re,{examples:[P(`${B} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export"),P(`${B} sessions export 01a0f5fe -o ./sessions --tools`,"sessions.ex.export_tools")]}),p(te,{...U("sessions",[[`${B} codex sessions`,"sessions.alt.codex_sessions"]]),examples:[P(`${B} sessions`,"sessions.ex.list"),P(`${B} sessions --tool codex --here`,"sessions.ex.here"),P(`${B} sessions show 01a0f5fe`,"sessions.ex.show"),P(`${B} sessions resume 01a0f5fe --run`,"sessions.ex.resume"),P(`${B} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export")]});const ce=C.command("lang").summary(N("lang.summary")).description(N("lang.description"));H(ce);const le=ce.command("show").description(N("lang.show")).action(async()=>{await u(["show"])}),pe=ce.command("set <locale>").description(N("lang.set")).action(async e=>{await u(["set",e])}),me=[P(`${B} lang show`,"lang.ex.show"),P(`${B} lang set en_US`,"lang.ex.set_en"),P(`${B} lang set zh_CN`,"lang.ex.set_zh")];p(ce,{...U("lang",[[`${B} enter lang`,"lang.alt.enter"]]),examples:me}),p(le,{examples:[me[0],P(`${B} lang show --json`,"lang.ex.show_json")]}),p(pe,{examples:me.slice(1)});const ue=C.command("completion").summary(N("completion.summary")).description(N("completion.description")).argument("<shell>",N("completion.arg.shell")).action(async e=>{await $([e])});p(ue,{...U("completion"),examples:[P(`${B} completion bash > ~/.${B}-completion.bash`,"completion.ex.bash"),P(`${B} completion zsh > ~/.${B}-completion.zsh`,"completion.ex.zsh"),P(`${B} completion fish > ~/.config/fish/completions/${B}.fish`,"completion.ex.fish")]});const de=C.command("enter").summary(N("enter.summary")).description(N("enter.description")).argument("[option]",N("enter.arg.option")).action(async e=>{if(e)switch(e){case"lang":case"language":await r.configLanguage();break;case"apikey":case"api-key":await r.configApiKey();break;case"models":await r.configModels();break;default:await g([e])}else await r.run()});p(de,{...U("enter",[[`${B}`,"enter.alt.menu"],[`${B} config <tool>`,"enter.alt.config"]]),sections:[{title:N("enter.options_title"),rows:[[N("enter.option.none_term"),N("enter.option.none")],["lang",N("enter.option.lang")],["apikey",N("enter.option.apikey")],["models",N("enter.option.models")],["<tool>",N("enter.option.tool")]]}],examples:[P(`${B} enter`,"enter.ex.menu"),P(`${B} enter models`,"enter.ex.models"),P(`${B} enter codex`,"enter.ex.tool")]}),H(C),C.action(async()=>{await r.run()}),p(C,{examples:[P(`${B}`,"root.ex.menu"),P(`${B} setup --key sk-xxx`,"root.ex.setup"),P(`${B} doctor`,"root.ex.doctor"),P(`${B} base auto`,"root.ex.base"),P(`${B} config codex`,"root.ex.config")]});const fe=e=>{for(const o of e.commands)o.helpOption("-h, --help",N("global.help")),fe(o)};return fe(C),C}
@@ -1 +1 @@
1
- import{chmodSync as t,existsSync as r,readFileSync as e}from"fs";import{join as n}from"path";import{i18n as o}from"../i18n.js";import{prettyModelName as i}from"../gateway-models.js";import{getAgyRules as a}from"../model-registry.js";import{logger as l}from"../../utils/logger.js";import{readPersistentEnvFile as s,removePersistentEnv as c,writePersistentEnv as u}from"../persistent-env.js";import{backupBeforeWrite as p,atomicWriteFile as g}from"./backup.js";import{findInstalls as d,mirrorInstallCommand as m}from"./tool-installs.js";import{toolHome as y}from"./types.js";import{brand as f,PROVIDER_KEY as v}from"../brand.js";const A="agy",_="AGY_LLM_GATEWAY_MODELS",h=["GEMINI_API_KEY","GOOGLE_GEMINI_BASE_URL","AGY_LLM_GATEWAY_URL","AGY_LLM_GATEWAY_API_KEY"],E="gemini",j=()=>n(y(),".gemini","antigravity-cli"),b=()=>n(j(),"settings.json"),w=()=>n(j(),`${v}.env`),I=()=>n(y(),".antigravity","settings.json"),K=f().installMirror?.agy,P={command:"agy",native:{binDir:"win32"===process.platform?["AppData","Local","agy","bin"]:[".local","bin"],updateArgs:["update"],dataDirs:[]},...K?{mirrorScript:{sh:`${K}/install.sh`,ps1:`${K}/install.ps1`}}:{}};function M(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function G(t,n){if(!r(t))return{};const o=e(t,"utf-8");if(!o.trim())return{};try{const t=JSON.parse(o);if(!M(t))throw new Error(`${n} root must be an object`);return t}catch(t){throw new Error(`Existing ${n} cannot be parsed, back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}const L=()=>G(b(),"~/.gemini/antigravity-cli/settings.json"),C=()=>G(I(),"~/.antigravity/settings.json");function N(r,e,n){p(r),g(r,JSON.stringify(e,null,2)+"\n",n),void 0!==n&&t(r,n)}function S(t){return(t||"").replace(/\/+$/,"").replace(/\/v1(beta)?$/,"")}function Y(t){const r=a().gatewayModels,e=t?r.filter(r=>t.models.includes(r)):[];return e.length>0?e:r}const $=t=>i(t.replace(/-preview$/,""));function k(t){const r=t.gateway;return M(r)&&!0===r.enabled&&"string"==typeof r.apiKey&&r.apiKey.trim()&&"string"==typeof r.url?{url:r.url,apiKey:r.apiKey}:null}function O(t){const r=t.models;return M(r)&&Array.isArray(r.list)?r.list.map(t=>M(t)&&"string"==typeof t.modelId?t.modelId:"").filter(Boolean):[]}function x(){try{if(L().modelProvider!==E)return null}catch{return null}const t=s(w()),r=t.GEMINI_API_KEY;return r&&r.trim()?{apiKey:r,url:t.GOOGLE_GEMINI_BASE_URL??""}:null}function U(t,r,e){const n=L(),o=C();o.gateway={...M(o.gateway)?o.gateway:{},enabled:!0,url:r,apiKey:t,wireProtocol:"genai"},o.models={...M(o.models)?o.models:{},defaultModelId:e[0],list:e.map(t=>({modelId:t,displayName:$(t),supportsThinking:!0}))},N(I(),o,384),h.some(t=>void 0!==s(w())[t])&&c(A,w(),h);const i=u(A,w(),{[_]:e.join(",")}).rcFiles;for(const t of h)delete process.env[t];return n.modelProvider===E&&(delete n.modelProvider,N(b(),n)),i}let D=null,R=null;export const antigravityAdapter={name:"agy",displayName:"Antigravity CLI",command:"agy",installCommand:m(P),installSpec:P,configPath:I(),wantsModelCatalog:!0,loadPrivateConfig(t){L(),C();const r=Y(t.catalog);D=U(t.apiKey,S(t.baseUrl),r),R=r},unloadPrivateConfig(){try{const t=C();k(t)&&(delete t.gateway,delete t.models,N(I(),t,384))}catch(t){l.logError("antigravityAdapter.unloadPrivateConfig",t)}try{const t=L();t.modelProvider===E&&(delete t.modelProvider,N(b(),t))}catch(t){l.logError("antigravityAdapter.unloadPrivateConfig",t)}c(A,w(),[_,...h])},detectCurrentConfig(){try{const t=k(C());if(t)return{apiKey:t.apiKey}}catch{return{apiKey:null}}return{apiKey:x()?.apiKey??null}},listedModels(){try{const t=C();if(k(t))return O(t)}catch{return null}return x()?[]:null},refreshModelMenu(t){const r=C(),e=k(r)??x();if(!e)return;const n=Y(t.catalog),o=e.url||S(t.baseUrl);null!==k(r)&&O(r).join(",")===n.join(",")&&s(w())[_]===n.join(",")&&null===x()||U(e.apiKey,o,n)},getConfig(){try{return C()}catch(t){return l.logError("antigravityAdapter.getConfig",t),null}},applyNotes(){const t=[];if(R&&R.length>0){const r=R.map($);t.push({kind:"summary",text:o.t("tools.agy.menu_written",{count:String(r.length),list:r.join(o.t("tools.grok.list_separator")),default:r[0]})})}return null===D||0===d(P).length||t.push({kind:"action",text:o.t("tools.agy.effort_after_reopen")}),t},backupPaths:()=>[I(),b(),w()],forceResetPaths:()=>[w()]};
1
+ import{chmodSync as t,existsSync as r,readFileSync as e}from"fs";import{join as n}from"path";import{i18n as o}from"../i18n.js";import{prettyModelName as i}from"../gateway-models.js";import{getAgyRules as a}from"../model-registry.js";import{logger as l}from"../../utils/logger.js";import{readPersistentEnvFile as s,removePersistentEnv as c,writePersistentEnv as u}from"../persistent-env.js";import{backupBeforeWrite as p,atomicWriteFile as g}from"./backup.js";import{findInstalls as d,mirrorInstallCommand as m}from"./tool-installs.js";import{toolHome as y}from"./types.js";import{brand as f,PROVIDER_KEY as v}from"../brand.js";const A="agy",_="AGY_LLM_GATEWAY_MODELS",h=["GEMINI_API_KEY","GOOGLE_GEMINI_BASE_URL","AGY_LLM_GATEWAY_URL","AGY_LLM_GATEWAY_API_KEY"],E="gemini",j=()=>n(y(),".gemini","antigravity-cli"),b=()=>n(j(),"settings.json"),w=()=>n(j(),`${v}.env`),I=()=>n(y(),".antigravity","settings.json"),K=f().installMirror?.agy,P={command:"agy",native:{binDir:"win32"===process.platform?["AppData","Local","agy","bin"]:[".local","bin"],updateArgs:["update"],dataDirs:[]},...K?{mirrorScript:{sh:`${K}/install.sh`,ps1:`${K}/install.ps1`}}:{}};function M(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function G(t,n){if(!r(t))return{};const o=e(t,"utf-8");if(!o.trim())return{};try{const t=JSON.parse(o);if(!M(t))throw new Error(`${n} root must be an object`);return t}catch(t){throw new Error(`Existing ${n} cannot be parsed; back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}const L=()=>G(b(),"~/.gemini/antigravity-cli/settings.json"),C=()=>G(I(),"~/.antigravity/settings.json");function N(r,e,n){p(r),g(r,JSON.stringify(e,null,2)+"\n",n),void 0!==n&&t(r,n)}function S(t){return(t||"").replace(/\/+$/,"").replace(/\/v1(beta)?$/,"")}function Y(t){const r=a().gatewayModels,e=t?r.filter(r=>t.models.includes(r)):[];return e.length>0?e:r}const $=t=>i(t.replace(/-preview$/,""));function k(t){const r=t.gateway;return M(r)&&!0===r.enabled&&"string"==typeof r.apiKey&&r.apiKey.trim()&&"string"==typeof r.url?{url:r.url,apiKey:r.apiKey}:null}function O(t){const r=t.models;return M(r)&&Array.isArray(r.list)?r.list.map(t=>M(t)&&"string"==typeof t.modelId?t.modelId:"").filter(Boolean):[]}function x(){try{if(L().modelProvider!==E)return null}catch{return null}const t=s(w()),r=t.GEMINI_API_KEY;return r&&r.trim()?{apiKey:r,url:t.GOOGLE_GEMINI_BASE_URL??""}:null}function U(t,r,e){const n=L(),o=C();o.gateway={...M(o.gateway)?o.gateway:{},enabled:!0,url:r,apiKey:t,wireProtocol:"genai"},o.models={...M(o.models)?o.models:{},defaultModelId:e[0],list:e.map(t=>({modelId:t,displayName:$(t),supportsThinking:!0}))},N(I(),o,384),h.some(t=>void 0!==s(w())[t])&&c(A,w(),h);const i=u(A,w(),{[_]:e.join(",")}).rcFiles;for(const t of h)delete process.env[t];return n.modelProvider===E&&(delete n.modelProvider,N(b(),n)),i}let D=null,R=null;export const antigravityAdapter={name:"agy",displayName:"Antigravity CLI",command:"agy",installCommand:m(P),installSpec:P,configPath:I(),wantsModelCatalog:!0,loadPrivateConfig(t){L(),C();const r=Y(t.catalog);D=U(t.apiKey,S(t.baseUrl),r),R=r},unloadPrivateConfig(){try{const t=C();k(t)&&(delete t.gateway,delete t.models,N(I(),t,384))}catch(t){l.logError("antigravityAdapter.unloadPrivateConfig",t)}try{const t=L();t.modelProvider===E&&(delete t.modelProvider,N(b(),t))}catch(t){l.logError("antigravityAdapter.unloadPrivateConfig",t)}c(A,w(),[_,...h])},detectCurrentConfig(){try{const t=k(C());if(t)return{apiKey:t.apiKey}}catch{return{apiKey:null}}return{apiKey:x()?.apiKey??null}},listedModels(){try{const t=C();if(k(t))return O(t)}catch{return null}return x()?[]:null},refreshModelMenu(t){const r=C(),e=k(r)??x();if(!e)return;const n=Y(t.catalog),o=e.url||S(t.baseUrl);null!==k(r)&&O(r).join(",")===n.join(",")&&s(w())[_]===n.join(",")&&null===x()||U(e.apiKey,o,n)},getConfig(){try{return C()}catch(t){return l.logError("antigravityAdapter.getConfig",t),null}},applyNotes(){const t=[];if(R&&R.length>0){const r=R.map($);t.push({kind:"summary",text:o.t("tools.agy.menu_written",{count:String(r.length),list:r.join(o.t("tools.grok.list_separator")),default:r[0]})})}return null===D||0===d(P).length||t.push({kind:"action",text:o.t("tools.agy.effort_after_reopen")}),t},backupPaths:()=>[I(),b(),w()],forceResetPaths:()=>[w()]};
@@ -1 +1 @@
1
- import{existsSync as r,readFileSync as o}from"fs";import{join as t}from"path";import*as e from"@iarna/toml";import{logger as i}from"../../utils/logger.js";import{BRAND_NAME as n}from"../brand.js";import{backupBeforeWrite as a,atomicWriteFile as d}from"./backup.js";import{pickModel as m,toolHome as s,withV1 as p}from"./types.js";import{getToolDefaultModel as l}from"../model-registry.js";const c=()=>t(t(s(),".atomcode"),"config.toml"),f=n;function u(r){return!!r&&"object"==typeof r&&!Array.isArray(r)}function g(){if(!r(c()))return{};const t=o(c(),"utf-8");if(!t.trim())return{};try{const r=e.parse(t);if(!u(r))throw new Error("config.toml root must be a TOML table");return r}catch(r){throw new Error(`Existing ~/.atomcode/config.toml cannot be parsed, back it up and fix it first: ${r instanceof Error?r.message:String(r)}`)}}export const atomcodeAdapter={name:"atomcode",displayName:"AtomCode",command:"atomcode",installCommand:"npm install -g atomcode",hidden:!0,configPath:c(),loadPrivateConfig(r){const o=g(),t=u(o.providers)?o.providers:o.providers={},i=u(t[f])?{...t[f]}:{};t[f]={...i,type:"openai",base_url:p(r.baseUrl),context_window:2e5,api_key:r.apiKey,model:m(r.models,l("atomcode"))},o.default_provider=f,a(c()),d(c(),e.stringify(o))},unloadPrivateConfig(){if(!r(c()))return;let o;try{o=g()}catch(r){return void i.logError("atomcodeAdapter.unloadPrivateConfig",r)}u(o.providers)&&(delete o.providers[f],0===Object.keys(o.providers).length&&delete o.providers),o.default_provider===f&&delete o.default_provider,a(c()),d(c(),e.stringify(o))},detectCurrentConfig(){try{const r=g(),o=u(r.providers)?r.providers[f]:null,t=u(o)?o.api_key:null;return{apiKey:"string"==typeof t&&t.trim()?t:null}}catch{return{apiKey:null}}},getConfig(){try{return g()}catch(r){return i.logError("atomcodeAdapter.getConfig",r),null}}};
1
+ import{existsSync as r,readFileSync as o}from"fs";import{join as t}from"path";import*as e from"@iarna/toml";import{logger as i}from"../../utils/logger.js";import{BRAND_NAME as n}from"../brand.js";import{backupBeforeWrite as a,atomicWriteFile as d}from"./backup.js";import{pickModel as m,toolHome as s,withV1 as p}from"./types.js";import{getToolDefaultModel as l}from"../model-registry.js";const c=()=>t(t(s(),".atomcode"),"config.toml"),f=n;function u(r){return!!r&&"object"==typeof r&&!Array.isArray(r)}function g(){if(!r(c()))return{};const t=o(c(),"utf-8");if(!t.trim())return{};try{const r=e.parse(t);if(!u(r))throw new Error("config.toml root must be a TOML table");return r}catch(r){throw new Error(`Existing ~/.atomcode/config.toml cannot be parsed; back it up and fix it first: ${r instanceof Error?r.message:String(r)}`)}}export const atomcodeAdapter={name:"atomcode",displayName:"AtomCode",command:"atomcode",installCommand:"npm install -g atomcode",hidden:!0,configPath:c(),loadPrivateConfig(r){const o=g(),t=u(o.providers)?o.providers:o.providers={},i=u(t[f])?{...t[f]}:{};t[f]={...i,type:"openai",base_url:p(r.baseUrl),context_window:2e5,api_key:r.apiKey,model:m(r.models,l("atomcode"))},o.default_provider=f,a(c()),d(c(),e.stringify(o))},unloadPrivateConfig(){if(!r(c()))return;let o;try{o=g()}catch(r){return void i.logError("atomcodeAdapter.unloadPrivateConfig",r)}u(o.providers)&&(delete o.providers[f],0===Object.keys(o.providers).length&&delete o.providers),o.default_provider===f&&delete o.default_provider,a(c()),d(c(),e.stringify(o))},detectCurrentConfig(){try{const r=g(),o=u(r.providers)?r.providers[f]:null,t=u(o)?o.api_key:null;return{apiKey:"string"==typeof t&&t.trim()?t:null}}catch{return{apiKey:null}}},getConfig(){try{return g()}catch(r){return i.logError("atomcodeAdapter.getConfig",r),null}}};
@@ -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 p from"chalk";import{logger as u}from"../../utils/logger.js";import{track as f}from"../telemetry.js";import{ensureDesktopCli as m}from"./claude-desktop-cli.js";import{i18n as g}from"../i18n.js";import{BRAND_NAME as y,brand as h,brandEnv as k,CLI_NAME as _}from"../brand.js";import{backupBeforeWrite as D,atomicWriteFile as b}from"./backup.js";import{toolHome as A}from"./types.js";import{canRestartDesktop as C,isDesktopRunning as w,restartDesktop as E,WINDOWS_PACKAGE_FAMILIES as M}from"./desktop-process.js";import{setUserRegistryElevated as v}from"./elevated-reg.js";import{UserActionNeeded as O}from"./types.js";import{baseModelId as x,isClaudeModel as S}from"../model-catalog.js";import{getDefaultModels as P}from"../model-registry.js";import{claudeFormat as j,nestedClaudeProjectFiles as L}from"../sessions/formats.js";const I=y;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const T=/^[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=A(),n=Boolean(k("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 M.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 R=()=>a(claudeDesktopUserDataDir(),"configLibrary"),G=()=>a(R(),"_meta.json"),N=e=>a(R(),`${e}.json`),U=()=>a(claudeDesktopUserDataDir(),"claude_desktop_config.json");function K(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 F(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),D(n),b(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){u.logError("claude-desktop.writeJson.chmod",e)}}function H(){const e=K(G());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 B(e){return e?.entries.find(e=>e.name===I&&T.test(e.id))}const V={opus:0,fable:1,sonnet:2,haiku:3};function W(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=W(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function J(e){return W(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>x(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(S)){i=[...new Set(t.models.filter(S).map(x))];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=x(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const a=e=>V[J(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=W(e),s=W(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,d=new Set(Object.values(P()).map(e=>x(e||"")));for(const e of n){const t=J(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=J(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 z=null,Z=null,q=null,X=null,Y=null;function Q(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 ee={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,banner:{enabled:!1}};function te(e){return Object.fromEntries(Object.entries(ee).filter(([t])=>!e(t)))}const oe="SOFTWARE\\Policies\\Claude",ne=`HKCU\\${oe}`,re="HKLM\\SOFTWARE\\Policies\\Claude",se=`${_}-claude-policy.reg`,ie=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let ae=ie;export function setRegRunnerForTests(e){ae=e??ie}function le(){return"win32"===process.platform}function ce(e){let t;try{t=ae(["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 de(){if(null===ce(ne))return;const e=a(claudeDesktopUserDataDir(),se);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),D(e),ae(["export",ne,e,"/y"])}catch(e){u.logError("claude-desktop.snapshotPolicy",e)}}function pe(e){de();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)];ae(["add",ne,"/v",t,"/t",e,"/d",n,"/f"])}}function ue(e){const t=ce(ne);if(!t)return;de();let o=t.size;for(const n of e)t.has(n)&&(ae(["delete",ne,"/v",n,"/f"]),o-=1);o<=0&&ae(["delete",ne,"/f"])}const fe=[...Object.keys(Q({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(ee)];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 ce(re)?re:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return u.logError("claude-desktop.detectManagedConfig",e),null}}function me(){const e=A();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"),...M.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))}const ge=/\d+\.\d+\.\d+/;function ye(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}function he(){if("darwin"===process.platform){for(const e of["/Applications/Claude.app",a(A(),"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?ge.exec(n[1])?.[0]:void 0;if(s)return s}return null}if("win32"===process.platform){const e=a(process.env.LOCALAPPDATA||a(A(),"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 ye(t)}const o=M.map(e=>`'${e}'`).join(",");return ye(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=>ge.exec(e)?.[0]??[]))}if("linux"===process.platform)try{const e=c("dpkg-query",["-W","-f=${Version}","claude-desktop"],{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]});return ge.exec(e)?.[0]??null}catch{return null}return null}const ke="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",_e="darwin"!==process.platform&&"win32"!==process.platform||!h().installMirror?.claudeDesktop?"https://claude.ai/download":h().installMirror.claudeDesktop,De="darwin"===process.platform?`open ${_e}`:"win32"===process.platform?`start ${_e}`:`xdg-open ${_e}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:ke,installCommand:De,configPath:G(),sessions:{format:j,files:()=>L(a(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:me,installedVersion:he,prepareRuntime:async function(){if(!["win32","darwin","linux"].includes(process.platform)||!me())return[];const e=Date.now();try{const t=await m({userDataDir:claudeDesktopUserDataDir(),onDownload:e=>console.log(p.gray(" "+g.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?he():null,mirrorRepo:h().installMirror?.claudeDesktop?.replace(/\/-\/releases\/latest\/?$/,"")??null});return f("desktop-code-cli","skipped"===t.status?"skip":"ok",{duration_ms:Date.now()-e,detail:{...t}}),"installed"!==t.status?[]:[{kind:"summary",text:g.t("tools.claude_desktop.code_cli_installed",{version:t.version})}]}catch(t){return u.logError("claude-desktop.prepareCodeTabCli",t),f("desktop-code-cli","fail",{duration_ms:Date.now()-e,error:t}),[{kind:"action",text:g.t("tools.claude_desktop.code_cli_failed",{reason:t instanceof Error?t.message:String(t)})}]}},runningApp:C()?{isRunning:w,restart:E}:void 0,wantsModelCatalog:!0,loadPrivateConfig(e){const o=H()??{appliedId:"",entries:[]};let n=B(o);n||(n={id:l(),name:I},o.entries.push(n));const r=Q(e);Z=!0===r.disableDeploymentModeChooser,z={models:r.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const s=K(N(n.id))??{};F(N(n.id),{...te(e=>e in s),...s,...r}),o.appliedId=n.id,F(G(),o);const i=K(U())??{};if("3p"!==i.deploymentMode&&F(U(),{...i,deploymentMode:"3p"}),X=null,Y=null,q=null,le()){const o=ce(ne),n=fe.filter(e=>o?.has(e)),s={...te(e=>o?.has(e)??!1),...r},i=!0===e.settings?.force_registry,l=!i&&function(){const e=!Boolean(k("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:a(A(),"AppData","Local");return!!t(a(e,"AnthropicClaude"))||M.some(o=>t(a(e,"Packages",o,"LocalCache","Local","Claude-3p")))}();try{l?ue(fe):pe(s),q=l?"removed":"written"}catch(e){u.logError("claude-desktop.policy",e),X=e instanceof Error?e.message.trim():String(e),(n.length>0||i)&&(Y=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=Y;return e?{prompt:g.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!v(oe,e.values,e.deleteKey))return!1;const t=ce(ne),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(Y=null,X=null),o}}:null},unloadPrivateConfig(){if(le())try{ue(fe)}catch(e){u.logError("claude-desktop.removePolicy",e)}const e=H(),t=B(e);if(!e||!t)return;D(N(t.id)),s(N(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(D(G()),s(G(),{force:!0})):F(G(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=H(),t=B(e);if(!t||e?.appliedId!==t.id)return null;const o=K(N(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=H(),o=B(t);if(!o||t?.appliedId!==o.id)return;const n=K(N(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog);if(JSON.stringify(n.inferenceModels)!==JSON.stringify(r)){if(le()&&ce(ne)?.has("inferenceModels"))try{pe({inferenceModels:r})}catch(e){throw u.logError("claude-desktop.refreshModelMenu registry",e),new O(g.t("tools.claude_desktop.refresh_needs_admin"))}F(N(o.id),{...n,inferenceModels:r})}},detectCurrentConfig(){try{if(le()){const e=ce(ne)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=B(H());if(!e)return{apiKey:null};const t=K(N(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return u.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=H(),t=B(e);return{meta:e,applied:t?K(N(t.id)):null,desktop:K(U()),...le()?{policy:Object.fromEntries(ce(ne)??[])}:{}}}catch(e){return u.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;le()&&ce(ne)?.has("inferenceModels")&&(de(),ae(["delete",ne,"/v","inferenceModels","/f"]),e=!0);const t=B(H()),o=t?K(N(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;F(N(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(z&&z.models.length>0){const{models:t,source:o,groups:n}=z;e.push({kind:"summary",text:g.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:g.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!==Z&&e.push({kind:"detail",text:g.t(Z?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),C()&&!w()||e.push({kind:"action",text:g.t("tools.claude_desktop.restart_hint")}),Y?(e.push({kind:"action",text:g.t(`tools.claude_desktop.policy_stale_${Y.action}`)}),e.push({kind:"detail",text:X??""})):X?(e.push({kind:"detail",text:g.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:X})):le()&&q&&e.push({kind:"detail",text:g.t(`tools.claude_desktop.registry_${q}`,{key:ne})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:g.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[G(),U()];try{const t=B(H());t&&e.push(N(t.id))}catch{}return e},backupPaths(){const e=[G(),U()];le()&&e.push(a(claudeDesktopUserDataDir(),se));try{const t=B(H());t&&e.push(N(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 p from"chalk";import{logger as u}from"../../utils/logger.js";import{track as f}from"../telemetry.js";import{ensureDesktopCli as m}from"./claude-desktop-cli.js";import{i18n as g}from"../i18n.js";import{BRAND_NAME as y,brand as h,brandEnv as k,CLI_NAME as _}from"../brand.js";import{backupBeforeWrite as D,atomicWriteFile as b}from"./backup.js";import{toolHome as A}from"./types.js";import{canRestartDesktop as C,isDesktopRunning as w,restartDesktop as E,WINDOWS_PACKAGE_FAMILIES as M}from"./desktop-process.js";import{setUserRegistryElevated as v}from"./elevated-reg.js";import{UserActionNeeded as O}from"./types.js";import{baseModelId as x,isClaudeModel as S}from"../model-catalog.js";import{getDefaultModels as P}from"../model-registry.js";import{claudeFormat as j,nestedClaudeProjectFiles as L}from"../sessions/formats.js";const I=y;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const T=/^[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=A(),n=Boolean(k("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 M.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 R=()=>a(claudeDesktopUserDataDir(),"configLibrary"),G=()=>a(R(),"_meta.json"),N=e=>a(R(),`${e}.json`),U=()=>a(claudeDesktopUserDataDir(),"claude_desktop_config.json");function K(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 F(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),D(n),b(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){u.logError("claude-desktop.writeJson.chmod",e)}}function H(){const e=K(G());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 B(e){return e?.entries.find(e=>e.name===I&&T.test(e.id))}const V={opus:0,fable:1,sonnet:2,haiku:3};function W(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=W(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function J(e){return W(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>x(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(S)){i=[...new Set(t.models.filter(S).map(x))];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=x(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const a=e=>V[J(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=W(e),s=W(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,d=new Set(Object.values(P()).map(e=>x(e||"")));for(const e of n){const t=J(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=J(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 z=null,Z=null,q=null,X=null,Y=null;function Q(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 ee={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,banner:{enabled:!1}};function te(e){return Object.fromEntries(Object.entries(ee).filter(([t])=>!e(t)))}const oe="SOFTWARE\\Policies\\Claude",ne=`HKCU\\${oe}`,re="HKLM\\SOFTWARE\\Policies\\Claude",se=`${_}-claude-policy.reg`,ie=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let ae=ie;export function setRegRunnerForTests(e){ae=e??ie}function le(){return"win32"===process.platform}function ce(e){let t;try{t=ae(["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 de(){if(null===ce(ne))return;const e=a(claudeDesktopUserDataDir(),se);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),D(e),ae(["export",ne,e,"/y"])}catch(e){u.logError("claude-desktop.snapshotPolicy",e)}}function pe(e){de();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)];ae(["add",ne,"/v",t,"/t",e,"/d",n,"/f"])}}function ue(e){const t=ce(ne);if(!t)return;de();let o=t.size;for(const n of e)t.has(n)&&(ae(["delete",ne,"/v",n,"/f"]),o-=1);o<=0&&ae(["delete",ne,"/f"])}const fe=[...Object.keys(Q({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(ee)];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 ce(re)?re:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return u.logError("claude-desktop.detectManagedConfig",e),null}}function me(){const e=A();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"),...M.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))}const ge=/\d+\.\d+\.\d+/;function ye(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}function he(){if("darwin"===process.platform){for(const e of["/Applications/Claude.app",a(A(),"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?ge.exec(n[1])?.[0]:void 0;if(s)return s}return null}if("win32"===process.platform){const e=a(process.env.LOCALAPPDATA||a(A(),"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 ye(t)}const o=M.map(e=>`'${e}'`).join(",");return ye(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=>ge.exec(e)?.[0]??[]))}if("linux"===process.platform)try{const e=c("dpkg-query",["-W","-f=${Version}","claude-desktop"],{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]});return ge.exec(e)?.[0]??null}catch{return null}return null}const ke="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",_e="darwin"!==process.platform&&"win32"!==process.platform||!h().installMirror?.claudeDesktop?"https://claude.ai/download":h().installMirror.claudeDesktop,De="darwin"===process.platform?`open ${_e}`:"win32"===process.platform?`start ${_e}`:`xdg-open ${_e}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:ke,installCommand:De,configPath:G(),sessions:{format:j,files:()=>L(a(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:me,installedVersion:he,prepareRuntime:async function(){if(!["win32","darwin","linux"].includes(process.platform)||!me())return[];const e=Date.now();try{const t=await m({userDataDir:claudeDesktopUserDataDir(),onDownload:e=>console.log(p.gray(" "+g.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?he():null,mirrorRepo:h().installMirror?.claudeDesktop?.replace(/\/-\/releases\/latest\/?$/,"")??null});return f("desktop-code-cli","skipped"===t.status?"skip":"ok",{duration_ms:Date.now()-e,detail:{...t}}),"installed"!==t.status?[]:[{kind:"summary",text:g.t("tools.claude_desktop.code_cli_installed",{version:t.version})}]}catch(t){return u.logError("claude-desktop.prepareCodeTabCli",t),f("desktop-code-cli","fail",{duration_ms:Date.now()-e,error:t}),[{kind:"action",text:g.t("tools.claude_desktop.code_cli_failed",{reason:t instanceof Error?t.message:String(t)})}]}},runningApp:C()?{isRunning:w,restart:E}:void 0,wantsModelCatalog:!0,loadPrivateConfig(e){const o=H()??{appliedId:"",entries:[]};let n=B(o);n||(n={id:l(),name:I},o.entries.push(n));const r=Q(e);Z=!0===r.disableDeploymentModeChooser,z={models:r.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const s=K(N(n.id))??{};F(N(n.id),{...te(e=>e in s),...s,...r}),o.appliedId=n.id,F(G(),o);const i=K(U())??{};if("3p"!==i.deploymentMode&&F(U(),{...i,deploymentMode:"3p"}),X=null,Y=null,q=null,le()){const o=ce(ne),n=fe.filter(e=>o?.has(e)),s={...te(e=>o?.has(e)??!1),...r},i=!0===e.settings?.force_registry,l=!i&&function(){const e=!Boolean(k("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:a(A(),"AppData","Local");return!!t(a(e,"AnthropicClaude"))||M.some(o=>t(a(e,"Packages",o,"LocalCache","Local","Claude-3p")))}();try{l?ue(fe):pe(s),q=l?"removed":"written"}catch(e){u.logError("claude-desktop.policy",e),X=e instanceof Error?e.message.trim():String(e),(n.length>0||i)&&(Y=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=Y;return e?{prompt:g.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!v(oe,e.values,e.deleteKey))return!1;const t=ce(ne),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(Y=null,X=null),o}}:null},unloadPrivateConfig(){if(le())try{ue(fe)}catch(e){u.logError("claude-desktop.removePolicy",e)}const e=H(),t=B(e);if(!e||!t)return;D(N(t.id)),s(N(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(D(G()),s(G(),{force:!0})):F(G(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=H(),t=B(e);if(!t||e?.appliedId!==t.id)return null;const o=K(N(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=H(),o=B(t);if(!o||t?.appliedId!==o.id)return;const n=K(N(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog);if(JSON.stringify(n.inferenceModels)!==JSON.stringify(r)){if(le()&&ce(ne)?.has("inferenceModels"))try{pe({inferenceModels:r})}catch(e){throw u.logError("claude-desktop.refreshModelMenu registry",e),new O(g.t("tools.claude_desktop.refresh_needs_admin"))}F(N(o.id),{...n,inferenceModels:r})}},detectCurrentConfig(){try{if(le()){const e=ce(ne)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=B(H());if(!e)return{apiKey:null};const t=K(N(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return u.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=H(),t=B(e);return{meta:e,applied:t?K(N(t.id)):null,desktop:K(U()),...le()?{policy:Object.fromEntries(ce(ne)??[])}:{}}}catch(e){return u.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;le()&&ce(ne)?.has("inferenceModels")&&(de(),ae(["delete",ne,"/v","inferenceModels","/f"]),e=!0);const t=B(H()),o=t?K(N(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;F(N(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(z&&z.models.length>0){const{models:t,source:o,groups:n}=z;e.push({kind:"summary",text:g.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:g.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!==Z&&e.push({kind:"detail",text:g.t(Z?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),C()&&!w()||e.push({kind:"action",text:g.t("tools.claude_desktop.restart_hint")}),Y?(e.push({kind:"action",text:g.t(`tools.claude_desktop.policy_stale_${Y.action}`)}),e.push({kind:"detail",text:X??""})):X?(e.push({kind:"detail",text:g.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:X})):le()&&q&&e.push({kind:"detail",text:g.t(`tools.claude_desktop.registry_${q}`,{key:ne})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:g.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[G(),U()];try{const t=B(H());t&&e.push(N(t.id))}catch{}return e},backupPaths(){const e=[G(),U()];le()&&e.push(a(claudeDesktopUserDataDir(),se));try{const t=B(H());t&&e.push(N(t.id))}catch{}return e}};
@@ -1 +1 @@
1
- import{createHash as e}from"crypto";import{existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as i,statSync as s,writeFileSync as l}from"fs";import{join as a}from"path";import*as c from"@iarna/toml";import{logger as d}from"../../utils/logger.js";import{i18n as u}from"../i18n.js";import{backupBeforeWrite as m,atomicWriteFile as p}from"./backup.js";import{codexHome as f,pickModel as g,toolHome as _,withV1 as x}from"./types.js";import{moveSessionsToProvider as h,NO_STATE_DB as y,runningCodexPids as k}from"../codex-sessions.js";import{codexFormat as b,codexRolloutFiles as v}from"../sessions/formats.js";import{getToolDefaultModel as j}from"../model-registry.js";import{configManager as w}from"../config.js";import{maskHome as C,track as O}from"../telemetry.js";import{buildCodexCatalog as S,catalogRejections as M,codexCatalogPath as A,fillFromOlderEntries as E,installedCodexBinaries as N,loadBundledCodexModels as P,loadPreviousCodexModels as T,previousGatewayModelIds as D}from"./codex-catalog.js";import{gatewayModelSpecs as I,modelFamily as L}from"../gateway-models.js";import{findInstalls as $,mirrorInstallCommand as J,brandInstallScripts as G}from"./tool-installs.js";const R=()=>f(),K=()=>a(R(),"config.toml"),X="sessions_move_declined",B=["browser_use","browser_use_external","computer_use"];function W(e){const t=e.features;if(!Q(t)||!B.every(e=>!1===t[e]))return!1;for(const e of B)delete t[e];return!0}export function codexWorkModeOn(){try{const e=Z();return e.model_provider===Y&&Q(e.desktop)&&"STEPS_PROSE"===e.desktop.conversationDetailMode}catch{return!1}}function q(){try{if(Q(Z().desktop))return!0}catch{}if("darwin"===process.platform)return["/Applications",a(_(),"Applications")].some(e=>["ChatGPT.app","Codex.app"].some(o=>t(a(e,o))));if("win32"===process.platform){const e=a(process.env.LOCALAPPDATA||a(_(),"AppData","Local"),"Packages");try{return n(e).some(e=>/^OpenAI\.(Codex|ChatGPT)/i.test(e))}catch{return!1}}return t("/usr/lib/chatgpt/ChatGPT")}export function codexConfigPath(){return K()}const U=()=>a(R(),"auth.json"),z="OPENAI_API_KEY",Y="custom",F=1e6,H=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function Q(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function V(e,t){return Q(e[t])||(e[t]={}),e[t]}function Z(){if(!t(K()))return{};const e=r(K(),"utf-8");if(!e.trim())return{};try{const t=c.parse(e);if(!Q(t))throw new Error("config.toml root must be a TOML table");return t}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 ee(){if(!t(U()))return{};try{const e=JSON.parse(r(U(),"utf-8"));return Q(e)?e:{}}catch{return{}}}let te=null;function oe(e){const t=e.profiles;if(Q(t)){for(const[e,o]of Object.entries(t))Q(o)&&2===Object.keys(o).length&&o.model_provider===Y&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let ne=null;const re=()=>a(w.getConfigDir(),"codex-catalog-check.json");function ie(e){const o=A();t(o)&&r(o,"utf-8")===e||(m(o),p(o,e))}function se(t,n){if(0===n.length)return[];const i=function(t,o){const n=e("sha256").update(t);for(const e of o)try{const t=s(e);n.update(`\0${e}\0${t.size}\0${t.mtimeMs}`)}catch{n.update(`\0${e}`)}return n.digest("hex")}(t,n);if(function(e){try{return JSON.parse(r(re(),"utf-8")).signature===e}catch{return!1}}(i))return[];const a=M(A(),n);return 0===a.length&&function(e){try{o(w.getConfigDir(),{recursive:!0}),l(re(),JSON.stringify({signature:e})+"\n")}catch(e){d.logError("codexAdapter.rememberAccepted",e)}}(i),a}function le(e,t,o){const n=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===F&&delete e.model_context_window,e.model_auto_compact_token_limit===H&&delete e.model_auto_compact_token_limit}(e);const r=()=>{e.model_catalog_json===A()&&delete e.model_catalog_json,n&&(e.model_context_window=F,e.model_auto_compact_token_limit=H)},s=P()??T();if(!s)return d.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),ne="skipped",void r();const l=t.catalog,a=e=>S({bundled:e,specs:I("codex",l?.clientModels),...l?{keyModels:l.models}:{},gatewayAvailable:l?.models??D(),oneMillion:n,selectedModel:o,..."gateway"===l?.oneMillionSource?{claudeOneMillion:l.oneMillion}:{}}),c=e=>JSON.stringify(e,null,2)+"\n";let u=a(s);ie(c(u));const m=N(),p=se(c(u),m);if(p.length>0){const e=Date.now();let t=!1;for(const e of p){const o=P(e.bin);if(o){for(const e of[{models:E(u.models,o)},{models:E(a(o).models,o)}])if(ie(c(e)),0===se(c(e),m).length){u=e,t=!0;break}if(t)break}}if(O("codex-catalog",t?"fallback":"fail",{duration_ms:Date.now()-e,error:p[0].error,detail:{rejected_by:p.map(e=>({version:e.version,path:C(e.bin)}))}}),!t)return ne={rejectedBy:p[0]},i(A(),{force:!0}),void r()}ne={listed:u.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))},e.model_catalog_json=A()}export function codexCatalogRejection(){let e;try{e=Z()}catch{return null}return e.model_catalog_json===A()&&t(A())?M(A())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=Z(),n=c.stringify(o),r="string"==typeof o.model?o.model:j("codex");le(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=c.stringify(o);i!==n&&(m(K()),p(K(),i))}const ae={command:"codex",npmPackage:"@openai/codex",native:{binDir:"win32"===process.platform?["AppData","Local","Programs","OpenAI","Codex","bin"]:[".local","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".codex","packages","standalone"]]},mirrorScript:G("codex"),brew:"codex"};export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:J(ae),installSpec:ae,configPath:K(),sessions:{format:b,files:()=>[...v(a(f(),"sessions")),...v(a(f(),"archived_sessions"))],resumeCommand:e=>({command:"codex",args:["resume",e]})},wantsModelCatalog:!0,listedModels(){if(Z().model_catalog_json!==A())return null;try{return(JSON.parse(r(A(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){if(Z().model_catalog_json!==A())return;setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog);const t=Z();W(t)&&(m(K()),p(K(),c.stringify(t)))},async followUp(){if(Z().model_provider!==Y)return null;const e=await h(Y,{dryRun:!0}),t=Math.max(e.moved.length,e.dbRows);if(0===t)return null;const o=w.getToolSettings("codex")[X];if("number"==typeof o&&t<=o)return null;const n={count:String(t)};return k().length>0?{hint:u.t("tools.codex.sessions_hidden_running",n)}:{prompt:u.t("tools.codex.sessions_offer",n),hint:u.t("tools.codex.sessions_hidden",n),async run(){const e=await h(Y),t=[...new Set(e.moved.map(e=>e.from))].join("、")||"-",o=String(Math.max(e.moved.length,e.dbRows)),n=[{kind:"summary",text:u.t("codex_sessions.moved",{count:o,from:t,target:Y})},{kind:"summary",text:u.t("codex_sessions.backup",{dir:e.backupDir??""})}];return e.dbSkipped&&e.dbSkipped!==y&&n.push({kind:"action",text:u.t("codex_sessions.db_skipped",{reason:e.dbSkipped})}),n},decline(){w.setToolSetting("codex",X,t)}}},applyNotes(){if("skipped"===ne)return 0===$(ae).length?[]:[{kind:"action",text:u.t("tools.codex.catalog_skipped")}];if(!ne)return[];if("rejectedBy"in ne){const{bin:e,version:t}=ne.rejectedBy;return[{kind:"action",text:u.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of ne.listed)e.set(L(t.id),(e.get(L(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${u.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:u.t("tools.codex.catalog_written",{count:String(ne.listed.length),breakdown:t})},{kind:"detail",text:ne.listed.map(e=>e.name).join(", ")},...codexWorkModeOn()||q()?[{kind:"action",text:u.t(codexWorkModeOn()?"tools.codex.work_mode_on":"tools.codex.work_mode_hint")}]:[]]},loadPrivateConfig(e){const t=j("codex"),o=g(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,r=x(e.baseUrl),i=Z();i.model=n,i.model_provider=Y,i.model_reasoning_effort="high",le(i,e,n);const s=V(i,"model_providers"),l=Q(s[Y])?{...s[Y]}:{};delete l.env_key;const{experimental_bearer_token:a,...d}=l;s[Y]={...d,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:r},oe(i),V(V(i,"tui"),"model_availability_nux")[n]=4;const u=V(i,"features");u.goals=!0,u.js_repl=!1,W(i),m(K()),p(K(),c.stringify(i)),function(e){const t=e.trim();if(!t)return;const o={...ee(),auth_mode:"apikey",[z]:t};m(U()),p(U(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},holdsOurConfig(e){const t=ee()[z];return"string"==typeof t&&e.includes(t.trim())},unloadPrivateConfig(e){if(te=function(e){const t=ee(),o="string"==typeof t[z]?t[z].trim():"";if(!o)return Q(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[z]:n,auth_mode:r,...s}=t;return m(U()),Q(s.tokens)?(p(U(),JSON.stringify({...s,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(i(U(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(K()))return;let o;try{o=Z()}catch(e){return void d.logError("codexAdapter.unloadPrivateConfig",e)}const n=o.model_providers;Q(n)&&(delete n[Y],0===Object.keys(n).length&&delete o.model_providers),o.model_provider===Y&&delete o.model_provider,o.model_catalog_json===A()&&delete o.model_catalog_json,W(o),oe(o),m(K()),p(K(),c.stringify(o))},unloadNotes(){switch(te){case"chatgpt":return[{kind:"action",text:u.t("tools.codex.unload_chatgpt_restored")}];case"other_key":return[{kind:"action",text:u.t("tools.codex.unload_other_key")}];default:return[{kind:"action",text:u.t("tools.codex.unload_sign_in")}]}},detectCurrentConfig(){const e=ee()[z];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return Z()}catch(e){return d.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[K(),U(),A()]};export function codexAuthProblem(){try{const e=Z(),t=e.model_providers?.[Y];if(e.model_provider!==Y||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=ee();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
1
+ import{createHash as e}from"crypto";import{existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as i,statSync as s,writeFileSync as l}from"fs";import{join as a}from"path";import*as c from"@iarna/toml";import{logger as d}from"../../utils/logger.js";import{i18n as u}from"../i18n.js";import{backupBeforeWrite as m,atomicWriteFile as p}from"./backup.js";import{codexHome as f,pickModel as g,toolHome as _,withV1 as x}from"./types.js";import{moveSessionsToProvider as h,NO_STATE_DB as y,runningCodexPids as k}from"../codex-sessions.js";import{codexFormat as b,codexRolloutFiles as v}from"../sessions/formats.js";import{getToolDefaultModel as j}from"../model-registry.js";import{configManager as w}from"../config.js";import{maskHome as C,track as O}from"../telemetry.js";import{buildCodexCatalog as S,catalogRejections as M,codexCatalogPath as A,fillFromOlderEntries as E,installedCodexBinaries as N,loadBundledCodexModels as P,loadPreviousCodexModels as T,previousGatewayModelIds as D}from"./codex-catalog.js";import{gatewayModelSpecs as I,modelFamily as L}from"../gateway-models.js";import{findInstalls as $,mirrorInstallCommand as J,brandInstallScripts as G}from"./tool-installs.js";const R=()=>f(),K=()=>a(R(),"config.toml"),X="sessions_move_declined",B=["browser_use","browser_use_external","computer_use"];function W(e){const t=e.features;if(!Q(t)||!B.every(e=>!1===t[e]))return!1;for(const e of B)delete t[e];return!0}export function codexWorkModeOn(){try{const e=Z();return e.model_provider===Y&&Q(e.desktop)&&"STEPS_PROSE"===e.desktop.conversationDetailMode}catch{return!1}}function q(){try{if(Q(Z().desktop))return!0}catch{}if("darwin"===process.platform)return["/Applications",a(_(),"Applications")].some(e=>["ChatGPT.app","Codex.app"].some(o=>t(a(e,o))));if("win32"===process.platform){const e=a(process.env.LOCALAPPDATA||a(_(),"AppData","Local"),"Packages");try{return n(e).some(e=>/^OpenAI\.(Codex|ChatGPT)/i.test(e))}catch{return!1}}return t("/usr/lib/chatgpt/ChatGPT")}export function codexConfigPath(){return K()}const U=()=>a(R(),"auth.json"),z="OPENAI_API_KEY",Y="custom",F=1e6,H=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function Q(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function V(e,t){return Q(e[t])||(e[t]={}),e[t]}function Z(){if(!t(K()))return{};const e=r(K(),"utf-8");if(!e.trim())return{};try{const t=c.parse(e);if(!Q(t))throw new Error("config.toml root must be a TOML table");return t}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 ee(){if(!t(U()))return{};try{const e=JSON.parse(r(U(),"utf-8"));return Q(e)?e:{}}catch{return{}}}let te=null;function oe(e){const t=e.profiles;if(Q(t)){for(const[e,o]of Object.entries(t))Q(o)&&2===Object.keys(o).length&&o.model_provider===Y&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let ne=null;const re=()=>a(w.getConfigDir(),"codex-catalog-check.json");function ie(e){const o=A();t(o)&&r(o,"utf-8")===e||(m(o),p(o,e))}function se(t,n){if(0===n.length)return[];const i=function(t,o){const n=e("sha256").update(t);for(const e of o)try{const t=s(e);n.update(`\0${e}\0${t.size}\0${t.mtimeMs}`)}catch{n.update(`\0${e}`)}return n.digest("hex")}(t,n);if(function(e){try{return JSON.parse(r(re(),"utf-8")).signature===e}catch{return!1}}(i))return[];const a=M(A(),n);return 0===a.length&&function(e){try{o(w.getConfigDir(),{recursive:!0}),l(re(),JSON.stringify({signature:e})+"\n")}catch(e){d.logError("codexAdapter.rememberAccepted",e)}}(i),a}function le(e,t,o){const n=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===F&&delete e.model_context_window,e.model_auto_compact_token_limit===H&&delete e.model_auto_compact_token_limit}(e);const r=()=>{e.model_catalog_json===A()&&delete e.model_catalog_json,n&&(e.model_context_window=F,e.model_auto_compact_token_limit=H)},s=P()??T();if(!s)return d.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),ne="skipped",void r();const l=t.catalog,a=e=>S({bundled:e,specs:I("codex",l?.clientModels),...l?{keyModels:l.models}:{},gatewayAvailable:l?.models??D(),oneMillion:n,selectedModel:o,..."gateway"===l?.oneMillionSource?{claudeOneMillion:l.oneMillion}:{}}),c=e=>JSON.stringify(e,null,2)+"\n";let u=a(s);ie(c(u));const m=N(),p=se(c(u),m);if(p.length>0){const e=Date.now();let t=!1;for(const e of p){const o=P(e.bin);if(o){for(const e of[{models:E(u.models,o)},{models:E(a(o).models,o)}])if(ie(c(e)),0===se(c(e),m).length){u=e,t=!0;break}if(t)break}}if(O("codex-catalog",t?"fallback":"fail",{duration_ms:Date.now()-e,error:p[0].error,detail:{rejected_by:p.map(e=>({version:e.version,path:C(e.bin)}))}}),!t)return ne={rejectedBy:p[0]},i(A(),{force:!0}),void r()}ne={listed:u.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))},e.model_catalog_json=A()}export function codexCatalogRejection(){let e;try{e=Z()}catch{return null}return e.model_catalog_json===A()&&t(A())?M(A())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=Z(),n=c.stringify(o),r="string"==typeof o.model?o.model:j("codex");le(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=c.stringify(o);i!==n&&(m(K()),p(K(),i))}const ae={command:"codex",npmPackage:"@openai/codex",native:{binDir:"win32"===process.platform?["AppData","Local","Programs","OpenAI","Codex","bin"]:[".local","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".codex","packages","standalone"]]},mirrorScript:G("codex"),brew:"codex"};export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:J(ae),installSpec:ae,configPath:K(),sessions:{format:b,files:()=>[...v(a(f(),"sessions")),...v(a(f(),"archived_sessions"))],resumeCommand:e=>({command:"codex",args:["resume",e]})},wantsModelCatalog:!0,listedModels(){if(Z().model_catalog_json!==A())return null;try{return(JSON.parse(r(A(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){if(Z().model_catalog_json!==A())return;setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog);const t=Z();W(t)&&(m(K()),p(K(),c.stringify(t)))},async followUp(){if(Z().model_provider!==Y)return null;const e=await h(Y,{dryRun:!0}),t=Math.max(e.moved.length,e.dbRows);if(0===t)return null;const o=w.getToolSettings("codex")[X];if("number"==typeof o&&t<=o)return null;const n={count:String(t)};return k().length>0?{hint:u.t("tools.codex.sessions_hidden_running",n)}:{prompt:u.t("tools.codex.sessions_offer",n),hint:u.t("tools.codex.sessions_hidden",n),async run(){const e=await h(Y),t=[...new Set(e.moved.map(e=>e.from))].join("、")||"-",o=String(Math.max(e.moved.length,e.dbRows)),n=[{kind:"summary",text:u.t("codex_sessions.moved",{count:o,from:t,target:Y})},{kind:"summary",text:u.t("codex_sessions.backup",{dir:e.backupDir??""})}];return e.dbSkipped&&e.dbSkipped!==y&&n.push({kind:"action",text:u.t("codex_sessions.db_skipped",{reason:e.dbSkipped})}),n},decline(){w.setToolSetting("codex",X,t)}}},applyNotes(){if("skipped"===ne)return 0===$(ae).length?[]:[{kind:"action",text:u.t("tools.codex.catalog_skipped")}];if(!ne)return[];if("rejectedBy"in ne){const{bin:e,version:t}=ne.rejectedBy;return[{kind:"action",text:u.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of ne.listed)e.set(L(t.id),(e.get(L(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${u.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:u.t("tools.codex.catalog_written",{count:String(ne.listed.length),breakdown:t})},{kind:"detail",text:ne.listed.map(e=>e.name).join(", ")},...codexWorkModeOn()||q()?[{kind:"action",text:u.t(codexWorkModeOn()?"tools.codex.work_mode_on":"tools.codex.work_mode_hint")}]:[]]},loadPrivateConfig(e){const t=j("codex"),o=g(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,r=x(e.baseUrl),i=Z();i.model=n,i.model_provider=Y,i.model_reasoning_effort="high",le(i,e,n);const s=V(i,"model_providers"),l=Q(s[Y])?{...s[Y]}:{};delete l.env_key;const{experimental_bearer_token:a,...d}=l;s[Y]={...d,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:r},oe(i),V(V(i,"tui"),"model_availability_nux")[n]=4;const u=V(i,"features");u.goals=!0,u.js_repl=!1,W(i),m(K()),p(K(),c.stringify(i)),function(e){const t=e.trim();if(!t)return;const o={...ee(),auth_mode:"apikey",[z]:t};m(U()),p(U(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},holdsOurConfig(e){const t=ee()[z];return"string"==typeof t&&e.includes(t.trim())},unloadPrivateConfig(e){if(te=function(e){const t=ee(),o="string"==typeof t[z]?t[z].trim():"";if(!o)return Q(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[z]:n,auth_mode:r,...s}=t;return m(U()),Q(s.tokens)?(p(U(),JSON.stringify({...s,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(i(U(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(K()))return;let o;try{o=Z()}catch(e){return void d.logError("codexAdapter.unloadPrivateConfig",e)}const n=o.model_providers;Q(n)&&(delete n[Y],0===Object.keys(n).length&&delete o.model_providers),o.model_provider===Y&&delete o.model_provider,o.model_catalog_json===A()&&delete o.model_catalog_json,W(o),oe(o),m(K()),p(K(),c.stringify(o))},unloadNotes(){switch(te){case"chatgpt":return[{kind:"action",text:u.t("tools.codex.unload_chatgpt_restored")}];case"other_key":return[{kind:"action",text:u.t("tools.codex.unload_other_key")}];default:return[{kind:"action",text:u.t("tools.codex.unload_sign_in")}]}},detectCurrentConfig(){const e=ee()[z];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return Z()}catch(e){return d.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[K(),U(),A()]};export function codexAuthProblem(){try{const e=Z(),t=e.model_providers?.[Y];if(e.model_provider!==Y||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=ee();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
@@ -1 +1 @@
1
- import{existsSync as e,readFileSync as t}from"fs";import{join as o}from"path";import*as r from"@iarna/toml";import{logger as n}from"../../utils/logger.js";import{PROVIDER_KEY as i}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as l}from"./backup.js";import{pickModel as d,toolHome as a,withV1 as m}from"./types.js";import{i18n as f}from"../i18n.js";import{getToolDefaultModel as g}from"../model-registry.js";import{gatewayModelSpecs as u,modelBlurb as c,modelFamily as p,prettyModelName as y}from"../gateway-models.js";import{brandInstallScripts as k,mirrorInstallCommand as b}from"./tool-installs.js";import{OFFICIAL_PLUGINS as h}from"./claude-plugins.js";const j=()=>o(o(a(),".grok"),"config.toml"),_=i,w=`${i}-`,A=["low","medium","high","xhigh"];let v=null;const C=e=>`${w}${e}`,x=e=>e===_||e.startsWith(w),M={command:"grok",npmPackage:"@xai-official/grok",mirrorScript:k("grok"),native:{binDir:[".grok","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".grok","downloads"]]}};function S(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function E(e,t){return S(e[t])||(e[t]={}),e[t]}function O(){if(!e(j()))return{};const o=t(j(),"utf-8");if(!o.trim())return{};try{const e=r.parse(o);if(!S(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.grok/config.toml cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function P(e){return S(e.model)?Object.entries(e.model).filter(e=>x(e[0])&&S(e[1])):[]}function N(e,t){let o=u("grok",e.catalog?.clientModels);if(e.catalog){const t=new Set(e.catalog.models);o=o.filter(e=>t.has(e.id))}return o.some(e=>e.id===t)?o:[{id:t},...o]}function $(e,t,o){E(e,"endpoints").models_base_url=m(t.baseUrl);const r=E(e,"model"),n=new Map(P(e));for(const e of n.keys())delete r[e];for(const e of o){const o=C(e.id),i={...n.get(o)??{},name:e.name??y(e.id),model:e.id,base_url:m(t.baseUrl),api_key:t.apiKey,context_window:e.contextWindow??5e5,api_backend:"responses",reasoning_summary:"concise"};"grok"===p(e.id)&&(i.supports_reasoning_effort=!0,i.reasoning_efforts=A);const s=c(e.description);s?i.description=s:delete i.description,r[o]=i}}export const grokAdapter={name:"grok",displayName:"Grok Build",command:"grok",installCommand:b(M),installSpec:M,configPath:j(),wantsModelCatalog:!0,loadPrivateConfig(e){const t=O(),o=d(e.models,g("grok")),n=N(e,o);$(t,e,n);const i=e=>e.name??y(e.id);v={names:n.map(i),defaultName:i(n.find(e=>e.id===o))},E(t,"models").default=C(o),function(e){const t=E(e,"plugins"),o=e=>Array.isArray(e)?e.map(String):[],r=o(t.enabled),n=o(t.disabled),i=h.filter(e=>!r.includes(e)&&!n.includes(e));i.length>0&&(t.disabled=[...n,...i])}(t),s(j()),l(j(),r.stringify(t))},unloadPrivateConfig(){if(!e(j()))return;let t;try{t=O()}catch(e){return void n.logError("grokAdapter.unloadPrivateConfig",e)}if(S(t.model)){for(const[e]of P(t))delete t.model[e];0===Object.keys(t.model).length&&delete t.model}S(t.models)&&"string"==typeof t.models.default&&x(t.models.default)&&(delete t.models.default,0===Object.keys(t.models).length&&delete t.models),S(t.endpoints)&&(delete t.endpoints.models_base_url,0===Object.keys(t.endpoints).length&&delete t.endpoints),function(e){if(!S(e.plugins)||!Array.isArray(e.plugins.disabled))return;const t=e.plugins.disabled.filter(e=>!h.includes(e));t.length>0?e.plugins.disabled=t:delete e.plugins.disabled,0===Object.keys(e.plugins).length&&delete e.plugins}(t),s(j()),l(j(),r.stringify(t))},detectCurrentConfig(){try{const e=O(),t=P(e),o=S(e.models)?e.models.default:void 0,r=t.find(([e])=>e===o)?.[1]??t[0]?.[1],n=r?r.api_key:null;return{apiKey:"string"==typeof n&&n.trim()?n:null}}catch{return{apiKey:null}}},listedModels(){try{const e=P(O());return e.length>0?e.map(([,e])=>String(e.model)):null}catch{return null}},refreshModelMenu(e){const t=O(),o=E(t,"models"),n="string"==typeof o.default?o.default:void 0,i=n?P(t).find(([e])=>e===n)?.[1].model:void 0,a="string"==typeof i&&n!==_&&e.catalog.models.includes(i)?i:d(e.models,g("grok")),m=r.stringify(t);$(t,e,N(e,a)),(void 0===n||x(n))&&(o.default=C(a)),r.stringify(t)!==m&&(s(j()),l(j(),r.stringify(t)))},applyNotes:()=>v?[{kind:"summary",text:f.t("tools.grok.menu_written",{count:String(v.names.length),list:v.names.join(f.t("tools.grok.list_separator")),default:v.defaultName})}]:[],getConfig(){try{return O()}catch(e){return n.logError("grokAdapter.getConfig",e),null}}};
1
+ import{existsSync as e,readFileSync as t}from"fs";import{join as o}from"path";import*as r from"@iarna/toml";import{logger as n}from"../../utils/logger.js";import{PROVIDER_KEY as i}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as l}from"./backup.js";import{pickModel as d,toolHome as a,withV1 as m}from"./types.js";import{i18n as f}from"../i18n.js";import{getToolDefaultModel as g}from"../model-registry.js";import{gatewayModelSpecs as u,modelBlurb as c,modelFamily as p,prettyModelName as y}from"../gateway-models.js";import{brandInstallScripts as k,mirrorInstallCommand as b}from"./tool-installs.js";import{OFFICIAL_PLUGINS as h}from"./claude-plugins.js";const j=()=>o(o(a(),".grok"),"config.toml"),_=i,w=`${i}-`,A=["low","medium","high","xhigh"];let v=null;const C=e=>`${w}${e}`,x=e=>e===_||e.startsWith(w),M={command:"grok",npmPackage:"@xai-official/grok",mirrorScript:k("grok"),native:{binDir:[".grok","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".grok","downloads"]]}};function S(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function E(e,t){return S(e[t])||(e[t]={}),e[t]}function O(){if(!e(j()))return{};const o=t(j(),"utf-8");if(!o.trim())return{};try{const e=r.parse(o);if(!S(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.grok/config.toml cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function P(e){return S(e.model)?Object.entries(e.model).filter(e=>x(e[0])&&S(e[1])):[]}function N(e,t){let o=u("grok",e.catalog?.clientModels);if(e.catalog){const t=new Set(e.catalog.models);o=o.filter(e=>t.has(e.id))}return o.some(e=>e.id===t)?o:[{id:t},...o]}function $(e,t,o){E(e,"endpoints").models_base_url=m(t.baseUrl);const r=E(e,"model"),n=new Map(P(e));for(const e of n.keys())delete r[e];for(const e of o){const o=C(e.id),i={...n.get(o)??{},name:e.name??y(e.id),model:e.id,base_url:m(t.baseUrl),api_key:t.apiKey,context_window:e.contextWindow??5e5,api_backend:"responses",reasoning_summary:"concise"};"grok"===p(e.id)&&(i.supports_reasoning_effort=!0,i.reasoning_efforts=A);const s=c(e.description);s?i.description=s:delete i.description,r[o]=i}}export const grokAdapter={name:"grok",displayName:"Grok Build",command:"grok",installCommand:b(M),installSpec:M,configPath:j(),wantsModelCatalog:!0,loadPrivateConfig(e){const t=O(),o=d(e.models,g("grok")),n=N(e,o);$(t,e,n);const i=e=>e.name??y(e.id);v={names:n.map(i),defaultName:i(n.find(e=>e.id===o))},E(t,"models").default=C(o),function(e){const t=E(e,"plugins"),o=e=>Array.isArray(e)?e.map(String):[],r=o(t.enabled),n=o(t.disabled),i=h.filter(e=>!r.includes(e)&&!n.includes(e));i.length>0&&(t.disabled=[...n,...i])}(t),s(j()),l(j(),r.stringify(t))},unloadPrivateConfig(){if(!e(j()))return;let t;try{t=O()}catch(e){return void n.logError("grokAdapter.unloadPrivateConfig",e)}if(S(t.model)){for(const[e]of P(t))delete t.model[e];0===Object.keys(t.model).length&&delete t.model}S(t.models)&&"string"==typeof t.models.default&&x(t.models.default)&&(delete t.models.default,0===Object.keys(t.models).length&&delete t.models),S(t.endpoints)&&(delete t.endpoints.models_base_url,0===Object.keys(t.endpoints).length&&delete t.endpoints),function(e){if(!S(e.plugins)||!Array.isArray(e.plugins.disabled))return;const t=e.plugins.disabled.filter(e=>!h.includes(e));t.length>0?e.plugins.disabled=t:delete e.plugins.disabled,0===Object.keys(e.plugins).length&&delete e.plugins}(t),s(j()),l(j(),r.stringify(t))},detectCurrentConfig(){try{const e=O(),t=P(e),o=S(e.models)?e.models.default:void 0,r=t.find(([e])=>e===o)?.[1]??t[0]?.[1],n=r?r.api_key:null;return{apiKey:"string"==typeof n&&n.trim()?n:null}}catch{return{apiKey:null}}},listedModels(){try{const e=P(O());return e.length>0?e.map(([,e])=>String(e.model)):null}catch{return null}},refreshModelMenu(e){const t=O(),o=E(t,"models"),n="string"==typeof o.default?o.default:void 0,i=n?P(t).find(([e])=>e===n)?.[1].model:void 0,a="string"==typeof i&&n!==_&&e.catalog.models.includes(i)?i:d(e.models,g("grok")),m=r.stringify(t);$(t,e,N(e,a)),(void 0===n||x(n))&&(o.default=C(a)),r.stringify(t)!==m&&(s(j()),l(j(),r.stringify(t)))},applyNotes:()=>v?[{kind:"summary",text:f.t("tools.grok.menu_written",{count:String(v.names.length),list:v.names.join(f.t("tools.grok.list_separator")),default:v.defaultName})}]:[],getConfig(){try{return O()}catch(e){return n.logError("grokAdapter.getConfig",e),null}}};
@@ -1 +1 @@
1
- import{existsSync as t,readFileSync as e}from"fs";import{join as r}from"path";import*as n from"js-yaml";import{logger as i}from"../../utils/logger.js";import{API_KEY_ENV as o}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as m}from"./backup.js";import{pickModel as l,toolHome as a,withV1 as c}from"./types.js";import{getToolDefaultModel as f}from"../model-registry.js";const d=()=>r(a(),".hermes"),u=()=>r(d(),"config.yaml"),p=()=>r(d(),".env");function h(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function g(){if(!t(u()))return{};const r=e(u(),"utf-8");if(!r.trim())return{};const i=n.load(r);if(!h(i))throw new Error("config.yaml root must be a YAML mapping");return i}export const hermesAdapter={name:"hermes",displayName:"Hermes",command:"hermes",installCommand:"npm install -g hermes-cli",hidden:!0,configPath:u(),loadPrivateConfig(r){let i;try{i=g()}catch(t){throw new Error(`Existing ~/.hermes/config.yaml cannot be parsed, back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}const a=h(i.model)?i.model:i.model={};a.provider="custom",a.base_url=c(r.baseUrl),a.default=l(r.models,f("hermes")),s(u()),m(u(),n.dump(i,{indent:2,lineWidth:-1,noRefs:!0,sortKeys:!1}));const d=t(p())?e(p(),"utf-8"):"";s(p()),m(p(),function(t,e,r){const n=(t||"").split(/\r?\n/),i=`${e}=${r}`;let o=!1;const s=n.map(t=>{const r=t.trim();if(!r||r.startsWith("#"))return t;const n=r.indexOf("=");return n<=0?t:r.slice(0,n).trim()===e?(o=!0,i):t});if(!o){if(!(t||"").trim())return i+"\n";s.length&&""!==s[s.length-1]&&s.push(""),s.push(i)}const m=s.join("\n");return m.endsWith("\n")?m:m+"\n"}(d,o,r.apiKey))},unloadPrivateConfig(){if(t(u()))try{const t=g();h(t.model)&&(delete t.model.provider,delete t.model.base_url,delete t.model.default,0===Object.keys(t.model).length&&delete t.model),s(u()),m(u(),n.dump(t,{indent:2,lineWidth:-1,noRefs:!0,sortKeys:!1}))}catch(t){i.logError("hermesAdapter.unloadPrivateConfig",t)}t(p())&&(s(p()),m(p(),function(t,e){const r=(t||"").split(/\r?\n/).filter(t=>{const r=t.trim();if(!r||r.startsWith("#"))return!0;const n=r.indexOf("=");return n<=0||r.slice(0,n).trim()!==e}).join("\n");return r.endsWith("\n")||""===r?r:r+"\n"}(e(p(),"utf-8"),o)))},detectCurrentConfig(){const r=function(){if(!t(p()))return{};const r={};for(const t of e(p(),"utf-8").split(/\r?\n/)){const e=t.trim();if(!e||e.startsWith("#"))continue;const n=e.indexOf("=");if(n<=0)continue;const i=e.slice(0,n).trim();let o=e.slice(n+1).trim();(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),r[i]=o}return r}()[o];return{apiKey:r&&r.trim()?r:null}},getConfig(){try{return g()}catch(t){return i.logError("hermesAdapter.getConfig",t),null}},backupPaths:()=>[u(),p()]};
1
+ import{existsSync as t,readFileSync as e}from"fs";import{join as r}from"path";import*as n from"js-yaml";import{logger as i}from"../../utils/logger.js";import{API_KEY_ENV as o}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as m}from"./backup.js";import{pickModel as l,toolHome as a,withV1 as c}from"./types.js";import{getToolDefaultModel as f}from"../model-registry.js";const d=()=>r(a(),".hermes"),u=()=>r(d(),"config.yaml"),p=()=>r(d(),".env");function h(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function g(){if(!t(u()))return{};const r=e(u(),"utf-8");if(!r.trim())return{};const i=n.load(r);if(!h(i))throw new Error("config.yaml root must be a YAML mapping");return i}export const hermesAdapter={name:"hermes",displayName:"Hermes",command:"hermes",installCommand:"npm install -g hermes-cli",hidden:!0,configPath:u(),loadPrivateConfig(r){let i;try{i=g()}catch(t){throw new Error(`Existing ~/.hermes/config.yaml cannot be parsed; back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}const a=h(i.model)?i.model:i.model={};a.provider="custom",a.base_url=c(r.baseUrl),a.default=l(r.models,f("hermes")),s(u()),m(u(),n.dump(i,{indent:2,lineWidth:-1,noRefs:!0,sortKeys:!1}));const d=t(p())?e(p(),"utf-8"):"";s(p()),m(p(),function(t,e,r){const n=(t||"").split(/\r?\n/),i=`${e}=${r}`;let o=!1;const s=n.map(t=>{const r=t.trim();if(!r||r.startsWith("#"))return t;const n=r.indexOf("=");return n<=0?t:r.slice(0,n).trim()===e?(o=!0,i):t});if(!o){if(!(t||"").trim())return i+"\n";s.length&&""!==s[s.length-1]&&s.push(""),s.push(i)}const m=s.join("\n");return m.endsWith("\n")?m:m+"\n"}(d,o,r.apiKey))},unloadPrivateConfig(){if(t(u()))try{const t=g();h(t.model)&&(delete t.model.provider,delete t.model.base_url,delete t.model.default,0===Object.keys(t.model).length&&delete t.model),s(u()),m(u(),n.dump(t,{indent:2,lineWidth:-1,noRefs:!0,sortKeys:!1}))}catch(t){i.logError("hermesAdapter.unloadPrivateConfig",t)}t(p())&&(s(p()),m(p(),function(t,e){const r=(t||"").split(/\r?\n/).filter(t=>{const r=t.trim();if(!r||r.startsWith("#"))return!0;const n=r.indexOf("=");return n<=0||r.slice(0,n).trim()!==e}).join("\n");return r.endsWith("\n")||""===r?r:r+"\n"}(e(p(),"utf-8"),o)))},detectCurrentConfig(){const r=function(){if(!t(p()))return{};const r={};for(const t of e(p(),"utf-8").split(/\r?\n/)){const e=t.trim();if(!e||e.startsWith("#"))continue;const n=e.indexOf("=");if(n<=0)continue;const i=e.slice(0,n).trim();let o=e.slice(n+1).trim();(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),r[i]=o}return r}()[o];return{apiKey:r&&r.trim()?r:null}},getConfig(){try{return g()}catch(t){return i.logError("hermesAdapter.getConfig",t),null}},backupPaths:()=>[u(),p()]};
@@ -1 +1 @@
1
- import{existsSync as e,readFileSync as r}from"fs";import{join as o}from"path";import{logger as t}from"../../utils/logger.js";import{PROVIDER_KEY as n}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as l}from"./backup.js";import{pickModel as a,toolHome as i,withV1 as d}from"./types.js";import{getToolDefaultModel as m}from"../model-registry.js";const p=()=>o(o(i(),".openclaw"),"openclaw.json");function c(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function f(){if(!e(p()))return{};const o=r(p(),"utf-8");if(!o.trim())return{};const t=JSON.parse(o);if(!c(t))throw new Error("openclaw.json root must be a JSON object");return t}export const openclawAdapter={name:"openclaw",displayName:"OpenClaw",command:"openclaw",installCommand:"npm install -g openclaw",hidden:!0,configPath:p(),loadPrivateConfig(e){let r;try{r=f()}catch(e){throw new Error(`Existing ~/.openclaw/openclaw.json cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}const o=c(r.models)?r.models:r.models={};o.mode||(o.mode="merge");const t=c(o.providers)?o.providers:o.providers={},i=c(t[n])?{...t[n]}:{},u=a(e.models,m("openclaw"))||function(e){const r=c(e.agents)?e.agents:{},o=c(r.defaults)?r.defaults:{},t=c(o.model)?o.model:{},s=`${n}/`;if("string"==typeof t.primary&&t.primary.startsWith(s))return t.primary.slice(s.length);const l=c(e.models)?e.models:{},a=(c(l.providers)?l.providers:{})[n],i=c(a)?a:null;return i&&Array.isArray(i.models)&&c(i.models[0])&&"string"==typeof i.models[0].id?i.models[0].id:""}(r);t[n]={...i,baseUrl:d(e.baseUrl),api:"openai-completions",apiKey:e.apiKey,models:[{id:u,name:u}]};const y=c(r.agents)?r.agents:r.agents={},g=c(y.defaults)?y.defaults:y.defaults={},w=c(g.model)?g.model:g.model={},h=`${n}/${u}`;w.primary=h;const v=c(g.models)?g.models:g.models={};Object.prototype.hasOwnProperty.call(v,h)||(v[h]={}),s(p()),l(p(),JSON.stringify(r,null,2))},unloadPrivateConfig(){if(!e(p()))return;let r;try{r=f()}catch(e){return void t.logError("openclawAdapter.unloadPrivateConfig",e)}const o=c(r.models)?r.models:null;o&&c(o.providers)&&delete o.providers[n];const a=c(r.agents)?r.agents:null,i=a&&c(a.defaults)?a.defaults:null,d=i&&c(i.model)?i.model:null,m=`${n}/`;if(d&&"string"==typeof d.primary&&d.primary.startsWith(m)&&delete d.primary,i&&c(i.models))for(const e of Object.keys(i.models))e.startsWith(m)&&delete i.models[e];s(p()),l(p(),JSON.stringify(r,null,2))},detectCurrentConfig(){try{const e=f(),r=c(e.models)?e.models:{},o=(c(r.providers)?r.providers:{})[n],t=c(o)?o:null,s=t&&"string"==typeof t.apiKey?t.apiKey:null;return{apiKey:s&&s.trim()?s:null}}catch{return{apiKey:null}}},getConfig(){try{return f()}catch(e){return t.logError("openclawAdapter.getConfig",e),null}}};
1
+ import{existsSync as e,readFileSync as r}from"fs";import{join as o}from"path";import{logger as t}from"../../utils/logger.js";import{PROVIDER_KEY as n}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as l}from"./backup.js";import{pickModel as a,toolHome as i,withV1 as d}from"./types.js";import{getToolDefaultModel as m}from"../model-registry.js";const p=()=>o(o(i(),".openclaw"),"openclaw.json");function c(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function f(){if(!e(p()))return{};const o=r(p(),"utf-8");if(!o.trim())return{};const t=JSON.parse(o);if(!c(t))throw new Error("openclaw.json root must be a JSON object");return t}export const openclawAdapter={name:"openclaw",displayName:"OpenClaw",command:"openclaw",installCommand:"npm install -g openclaw",hidden:!0,configPath:p(),loadPrivateConfig(e){let r;try{r=f()}catch(e){throw new Error(`Existing ~/.openclaw/openclaw.json cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}const o=c(r.models)?r.models:r.models={};o.mode||(o.mode="merge");const t=c(o.providers)?o.providers:o.providers={},i=c(t[n])?{...t[n]}:{},u=a(e.models,m("openclaw"))||function(e){const r=c(e.agents)?e.agents:{},o=c(r.defaults)?r.defaults:{},t=c(o.model)?o.model:{},s=`${n}/`;if("string"==typeof t.primary&&t.primary.startsWith(s))return t.primary.slice(s.length);const l=c(e.models)?e.models:{},a=(c(l.providers)?l.providers:{})[n],i=c(a)?a:null;return i&&Array.isArray(i.models)&&c(i.models[0])&&"string"==typeof i.models[0].id?i.models[0].id:""}(r);t[n]={...i,baseUrl:d(e.baseUrl),api:"openai-completions",apiKey:e.apiKey,models:[{id:u,name:u}]};const y=c(r.agents)?r.agents:r.agents={},g=c(y.defaults)?y.defaults:y.defaults={},w=c(g.model)?g.model:g.model={},h=`${n}/${u}`;w.primary=h;const v=c(g.models)?g.models:g.models={};Object.prototype.hasOwnProperty.call(v,h)||(v[h]={}),s(p()),l(p(),JSON.stringify(r,null,2))},unloadPrivateConfig(){if(!e(p()))return;let r;try{r=f()}catch(e){return void t.logError("openclawAdapter.unloadPrivateConfig",e)}const o=c(r.models)?r.models:null;o&&c(o.providers)&&delete o.providers[n];const a=c(r.agents)?r.agents:null,i=a&&c(a.defaults)?a.defaults:null,d=i&&c(i.model)?i.model:null,m=`${n}/`;if(d&&"string"==typeof d.primary&&d.primary.startsWith(m)&&delete d.primary,i&&c(i.models))for(const e of Object.keys(i.models))e.startsWith(m)&&delete i.models[e];s(p()),l(p(),JSON.stringify(r,null,2))},detectCurrentConfig(){try{const e=f(),r=c(e.models)?e.models:{},o=(c(r.providers)?r.providers:{})[n],t=c(o)?o:null,s=t&&"string"==typeof t.apiKey?t.apiKey:null;return{apiKey:s&&s.trim()?s:null}}catch{return{apiKey:null}}},getConfig(){try{return f()}catch(e){return t.logError("openclawAdapter.getConfig",e),null}}};
@@ -1 +1 @@
1
- import{spawnSync as r}from"child_process";import{existsSync as t,realpathSync as n,statSync as o}from"fs";import{delimiter as e,dirname as s,isAbsolute as i,join as c}from"path";import{i18n as a}from"../i18n.js";import{toolHome as m}from"./types.js";import{brand as p}from"../brand.js";export const NPM_MIRROR="https://registry.npmmirror.com";export function brandInstallScripts(r){const t=p().installMirror?.scripts;return t?{sh:`${t}/${r}.sh`,ps1:`${t}/${r}.ps1`}:void 0}export function npmMirrorInstallCommand(r){return`npm install -g ${r.npmPackage}@latest --registry=${NPM_MIRROR}`}export function mirrorInstallCommand(r){return r.mirrorScript?"win32"===process.platform?`powershell -NoProfile -ExecutionPolicy Bypass -Command "irm ${r.mirrorScript.ps1} | iex"`:`curl -fsSL ${r.mirrorScript.sh} | sh`:r.npmPackage?npmMirrorInstallCommand(r):""}export function npmUninstallCommand(r){return`npm uninstall -g ${r.npmPackage}`}export function installLabel(r){return`${a.t(`upgrade.kind.${r.kind}`)} ${r.version??"?"} (${r.path})`}let l=t=>{const n={encoding:"utf-8",timeout:1e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]};return`${(/\.cmd$/i.test(t)?r(`"${t}" --version`,{...n,shell:!0}):r(t,["--version"],n)).stdout??""}`};const u=new Map;export function setVersionRunnerForTests(r){l=r,u.clear()}export function forgetInstalls(){u.clear()}function f(r){try{return o(r).isFile()}catch{return!1}}function d(r,o){if(r.native&&(e=s(o),i=c(m(),...r.native.binDir),"win32"===process.platform?e.toLowerCase()===i.toLowerCase():e===i))return"native";var e,i;const a=r.npmPackage?c("node_modules",...r.npmPackage.split("/")):null;if(a&&t(c(s(o),a)))return"npm";let p=o;try{p=n(o)}catch{return"other"}return a&&p.includes(a)?"npm":/[\\/](Cellar|Caskroom)[\\/]/.test(p)?"brew":"other"}export function findInstalls(r){const t=u.get(r.command);if(t)return t;const o="win32"===process.platform?[`${r.command}.exe`,`${r.command}.cmd`]:[r.command],s=new Set,a=[];for(const t of(process.env.PATH??"").split(e))if(t&&i(t))for(const e of o){const o=c(t,e);if(!f(o))continue;let i=o;try{i=n(o)}catch{}const m="win32"===process.platform?i.toLowerCase():i;if(s.has(m))continue;s.add(m);const p=l(o).match(/(\d+)\.(\d+)\.(\d+)/);a.push({path:o,kind:d(r,o),version:p?p[0]:null})}return u.set(r.command,a),a}
1
+ import{spawnSync as r}from"child_process";import{existsSync as t,realpathSync as n,statSync as o}from"fs";import{delimiter as e,dirname as s,isAbsolute as i,join as a}from"path";import{i18n as p}from"../i18n.js";import{toolHome as c}from"./types.js";import{brand as m}from"../brand.js";export const NPM_MIRROR="https://registry.npmmirror.com";export function brandInstallScripts(r){const t=m().installMirror?.scripts;return t?{sh:`${t}/${r}.sh`,ps1:`${t}/${r}.ps1`}:void 0}export function npmMirrorInstallCommand(r){return`npm install -g ${r.npmPackage}@latest --registry=${NPM_MIRROR}`}export function mirrorInstallCommand(r){return r.mirrorScript?"win32"===process.platform?`powershell -NoProfile -ExecutionPolicy Bypass -Command "irm ${r.mirrorScript.ps1} | iex"`:`curl -fsSL ${r.mirrorScript.sh} | sh`:r.npmPackage?npmMirrorInstallCommand(r):""}export function npmUninstallCommand(r){return`npm uninstall -g ${r.npmPackage}`}export function installLabel(r){return p.t("upgrade.install_label",{kind:p.t(`upgrade.kind.${r.kind}`),version:r.version??"?",path:r.path})}let l=t=>{const n={encoding:"utf-8",timeout:1e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]};return`${(/\.cmd$/i.test(t)?r(`"${t}" --version`,{...n,shell:!0}):r(t,["--version"],n)).stdout??""}`};const u=new Map;export function setVersionRunnerForTests(r){l=r,u.clear()}export function forgetInstalls(){u.clear()}function d(r){try{return o(r).isFile()}catch{return!1}}function f(r,o){if(r.native&&(e=s(o),i=a(c(),...r.native.binDir),"win32"===process.platform?e.toLowerCase()===i.toLowerCase():e===i))return"native";var e,i;const p=r.npmPackage?a("node_modules",...r.npmPackage.split("/")):null;if(p&&t(a(s(o),p)))return"npm";let m=o;try{m=n(o)}catch{return"other"}return p&&m.includes(p)?"npm":/[\\/](Cellar|Caskroom)[\\/]/.test(m)?"brew":"other"}export function findInstalls(r){const t=u.get(r.command);if(t)return t;const o="win32"===process.platform?[`${r.command}.exe`,`${r.command}.cmd`]:[r.command],s=new Set,p=[];for(const t of(process.env.PATH??"").split(e))if(t&&i(t))for(const e of o){const o=a(t,e);if(!d(o))continue;let i=o;try{i=n(o)}catch{}const c="win32"===process.platform?i.toLowerCase():i;if(s.has(c))continue;s.add(c);const m=l(o).match(/(\d+)\.(\d+)\.(\d+)/);p.push({path:o,kind:f(r,o),version:m?m[0]:null})}return u.set(r.command,p),p}