@vibeapi/cli 0.0.150 → 0.0.151

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/components.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": 1,
3
- "about": "Components VibeCLI installs and upgrades (vibecli list / install / upgrade). Read by src/lib/components.ts and by scripts/gen-components-doc.mjs (docs, the install scripts' README). {scripts} = the brand's installMirror.scripts, {agy} = installMirror.agy, {devtools} = the neutral CNB mirror of fnm / uv / Git for Windows.",
3
+ "about": "Components the CLI installs and upgrades (its list / install / upgrade commands). Read by src/lib/components.ts and by scripts/gen-components-doc.mjs (docs, the install scripts' README). {scripts} = the brand's installMirror.scripts, {agy} = installMirror.agy, {devtools} = the neutral CNB mirror of fnm / uv / Git for Windows.",
4
4
  "devtools": "https://cnb.cool/lib/devtools/-/releases/latest/download",
5
5
  "components": [
6
6
  {
@@ -1 +1 @@
1
- import o from"inquirer";import e from"chalk";import{wizard as t}from"../lib/wizard.js";import{toolManager as n,SUPPORTED_TOOLS as l}from"../lib/tool-manager.js";import{i18n as i}from"../lib/i18n.js";import{configManager as r,DEFAULT_PROFILE_NAME as a}from"../lib/config.js";import{confirmAction as s,applyOrDryRun as c,requireTerminal as d}from"../lib/confirm.js";import{canPrompt as f,isDryRun as g,isNonInteractive as p,shouldAutoConfirm as m}from"../lib/runtime-options.js";const _=/^[a-zA-Z0-9._-]+$/;function u(o,e){const t=(o||"").trim();if(!t||!_.test(t))throw new Error(i.t(`config.${e}_invalid_name`,{name:t||"<empty>"}));return t}function y(o,t){console.log("\n"+e.bold(o)),0!==t.length?t.forEach(o=>console.log(" "+o)):console.log(e.gray(" ("+i.t("config.empty_list")+")"))}function v(o,t){if("backups"===t){const t=n.listToolBackups(o).flatMap(o=>{const t=o.file.replace(/^.*[/\\]/,"");return o.backups.length?o.backups.map(o=>`${e.cyan(t)} ${e.gray(o.name.split(".bak-")[1]||o.name)}`):[`${e.cyan(t)} ${e.gray("("+i.t("config.empty_list")+")")}`]});return void y(i.t("config.tool_backups_title",{tool:l[o].displayName}),t)}const r=n.restorePrivateConfig(o).filter(o=>o.result.restored);0!==r.length?(console.log(e.green(i.t("config.config_restored",{tool:l[o].displayName}))),r.forEach(o=>console.log(e.gray(` ${o.file} ← ${o.result.from}`))),console.log(e.yellow(" ! "+i.t("config.reopen_hint",{tool:l[o].displayName})))):console.log(e.yellow(i.t("config.restore_no_backup",{tool:l[o].displayName})))}async function w(a,p,m){if(!l[a])return void console.log(e.red(i.t("config.unknown_tool",{tool:a})));const _=(p[0]||"").toLowerCase();if("backups"!==_&&"list-backups"!==_)if("restore"!==_){if("remove"===_||"unload"===_){const o=l[a].displayName;return void await c({description:i.t("config.remove_dry_run",{tool:o}),json:{action:"remove",tool:a},apply:async()=>{if(!await s({message:i.t("config.confirm_remove",{tool:o,name:a}),defaultValue:!0}))return;const t=n.holdsOurConfig(a),l=n.unloadPrivateConfig(a);t?(console.log(e.green(i.t("config.remove_done",{tool:o}))),l.forEach(o=>console.log(e.yellow(" ! "+o.text)))):console.log(e.gray(i.t("config.remove_nothing",{tool:o})))}})}if("clear-model"===_||"clear-models"===_){const o=l[a].displayName;return n.supportsClearPinnedModels(a)?void await c({description:i.t("config.clear_model_dry_run",{tool:o}),json:{action:"clear_model",tool:a},apply:async()=>{const t=await n.clearPinnedModels(a);0!==t.length?(console.log(e.green(i.t("config.clear_model_done",{tool:o}))),t.forEach(o=>console.log(e.gray(` - ${o}`))),console.log(e.gray(i.t("config.clear_model_restart_hint",{tool:o})))):console.log(e.yellow(i.t("config.clear_model_none",{tool:o})))}}):void console.log(e.yellow(i.t("config.clear_model_unsupported",{tool:o})))}if(g())await c({description:i.t("config.tool_apply_dry_run",{tool:l[a].displayName}),json:{action:"apply",tool:a,force:Boolean(m.force)},apply:()=>{}});else{if(!n.isToolInstalled(a)){if(m.nonInteractive)return void console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[a].displayName})));if(console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[a].displayName}))),!f())return;const{shouldInstall:t}=await o.prompt([{type:"confirm",name:"shouldInstall",message:i.t("wizard.install_tool_confirm"),default:!0}]);if(!t)return void console.log(e.yellow(i.t("wizard.install_skipped")));try{await n.installTool(a)}catch(o){return console.error(e.red(i.t("install.install_failed_detail"))),void(o instanceof Error&&o.message&&console.error(e.gray(o.message)))}}if(m.nonInteractive||m.force){const o=r.getApiKeyForTool(a);if(!o)return void console.log(e.red(i.t("auth.reload_missing_config")));if(m.force&&!m.nonInteractive&&!await s({message:i.t("config.confirm_force",{tool:l[a].displayName}),defaultValue:!1}))return;return await n.applyPrivateConfig(a,o,r.getModelsForTool(a),{force:m.force,takeOver:!0}),m.force&&console.log(e.yellow(i.t("config.force_done",{tool:l[a].displayName,name:a}))),void n.printApplied(a)}d(),await t.showToolMenu(a)}}else await c({description:i.t("config.tool_restore_dry_run",{tool:l[a].displayName}),json:{action:"tool_restore",tool:a},apply:async()=>{await s({message:i.t("config.confirm_restore",{tool:l[a].displayName}),defaultValue:!1})&&v(a,"restore")}});else v(a,"backups")}export async function configCommand(t){const{positional:n,options:d}=function(o){const e=[],t={};(p()||m())&&(t.nonInteractive=!0);for(const n of o)"--non-interactive"===n||"-y"===n?t.nonInteractive=!0:"--force"===n||"-f"===n?t.force=!0:e.push(n);return{positional:e,options:t}}(t),g=n[0],v=n.slice(1);if(g){switch(g){case"profile":return void await async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=r.getActiveProfileName(),t=r.listProfiles().map(t=>{const n=t===o;return`${n?e.green("●"):e.gray("○")} ${t}${n?e.gray(" ("+i.t("config.profile_active_label")+")"):""}`});return void y(i.t("config.profile_list_title"),t)}if("create"===t){const o=u(n,"profile");return r.listProfiles().includes(o)?void console.log(e.yellow(i.t("config.profile_exists",{name:o}))):void await c({description:i.t("config.profile_create_dry_run",{name:o}),json:{action:"profile_create",name:o},apply:()=>{r.createProfile(o),console.log(e.green(i.t("config.profile_created",{name:o})))}})}if("use"===t){const o=u(n,"profile");return void await c({description:i.t("config.profile_use_dry_run",{name:o}),json:{action:"profile_use",name:o},apply:()=>{r.setActiveProfile(o),console.log(e.green(i.t("config.profile_activated",{name:o})))}})}if("delete"===t||"remove"===t){const o=u(n,"profile");return o===a&&1===r.listProfiles().length?void console.log(e.yellow(i.t("config.profile_cannot_delete_last"))):void await c({description:i.t("config.profile_delete_dry_run",{name:o}),json:{action:"profile_delete",name:o},apply:async()=>{await s({message:i.t("config.profile_delete_confirm",{name:o}),defaultValue:!1})?(r.deleteProfile(o),console.log(e.green(i.t("config.profile_deleted",{name:o})))):console.log(e.yellow(i.t("config.profile_delete_aborted")))}})}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"preset":return void await async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=Object.entries(r.getCustomPresets()).map(([o,t])=>`${e.cyan(o)} ${e.gray(`H:${t.models.haiku} S:${t.models.sonnet} O:${t.models.opus}`)}`);return void y(i.t("config.preset_list_title"),o)}if("save"===t){const o=u(n,"preset");return void await c({description:i.t("config.preset_save_dry_run",{name:o}),json:{action:"preset_save",name:o},apply:()=>{r.saveCustomPreset(o,r.getModels()),console.log(e.green(i.t("config.preset_saved",{name:o})))}})}if("use"===t||"apply"===t){const o=u(n,"preset"),t=r.getCustomPresets()[o];return t?void await c({description:i.t("config.preset_use_dry_run",{name:o}),json:{action:"preset_use",name:o},apply:()=>{r.setModels(t.models),console.log(e.green(i.t("config.preset_applied",{name:o})))}}):void console.log(e.red(i.t("config.preset_not_found",{name:o})))}if("delete"===t||"remove"===t){const o=u(n,"preset");return void await c({description:i.t("config.preset_delete_dry_run",{name:o}),json:{action:"preset_delete",name:o},apply:()=>{r.deleteCustomPreset(o),console.log(e.green(i.t("config.preset_deleted",{name:o})))}})}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"tool-model":return void await async function(o){const t=o[0];if(!t||"list"===t){const o=r.getProfile().tool_models||{},t=Object.entries(o).map(([o,t])=>{const n=Object.entries(t).map(([o,e])=>`${o}=${e}`).join(" ");return`${e.cyan(o)} ${e.gray(n)}`});return void y(i.t("config.tool_model_list_title"),t)}if("set"===t){const t=(o[1]||"").trim(),n=o.length>=4?(o[2]||"").trim():"opus",a=(o.length>=4?o[3]:o[2]||"").trim();return l[t]?a&&_.test(n)?void await c({description:i.t("config.tool_model_set_dry_run",{tool:t,slot:n,model:a}),json:{action:"tool_model_set",tool:t,slot:n,model:a},apply:()=>{r.setToolModel(t,{[n]:a}),console.log(e.green(i.t("config.tool_model_set",{tool:t,slot:n,model:a})))}}):void console.log(e.red(i.t("config.tool_model_usage"))):void console.log(e.red(t?i.t("config.unknown_tool",{tool:t}):i.t("config.tool_model_usage")))}if("clear"===t||"remove"===t){const t=(o[1]||"").trim();return l[t]?void await c({description:i.t("config.tool_model_clear_dry_run",{tool:t}),json:{action:"tool_model_clear",tool:t},apply:()=>{r.setToolModel(t,null),console.log(e.green(i.t("config.tool_model_cleared",{tool:t})))}}):void console.log(e.red(t?i.t("config.unknown_tool",{tool:t}):i.t("config.tool_model_usage")))}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"backup":return void await function(o){return async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=r.listBackups().map(o=>{const t=new Date(o.mtimeMs).toISOString();return`${e.cyan(o.name)} ${e.gray(t)}`});return void y(i.t("config.backup_list_title"),o)}if("create"!==t&&"snapshot"!==t)return"restore"===t?n?void await c({description:i.t("config.backup_restore_dry_run",{name:n}),json:{action:"backup_restore",name:n},apply:async()=>{await s({message:i.t("config.backup_restore_confirm",{name:n}),defaultValue:!1})?(r.restoreBackup(n),console.log(e.green(i.t("config.backup_restored",{name:n})))):console.log(e.yellow(i.t("config.backup_restore_aborted")))}}):void console.log(e.red(i.t("config.backup_restore_missing_name"))):void console.log(e.red(i.t("config.unknown_action",{action:t})));await c({description:i.t("config.backup_create_dry_run"),json:{action:"backup_create",name:n??null},apply:()=>{const o=r.createBackup(n);console.log(e.green(i.t("config.backup_created",{path:o})))}})}(o)}(v)}"claude-code"!==g&&"claude-code"!==v[0]?l[g]?await w(g,v,d):(console.error(e.red(i.t("config.unknown_command",{command:g}))),console.log(e.gray(i.t("config.usage_hint"))),Object.values(l).filter(o=>!o.hidden).forEach(o=>{console.log(e.gray(` - ${o.name}: ${o.displayName}`))})):await w("claude-code",v,d)}else await async function(t){if(t.nonInteractive||!f())return void console.log(e.red(i.t("config.requires_argument")));const{selectedTool:n}=await o.prompt([{type:"list",name:"selectedTool",message:i.t("wizard.select_tool"),choices:Object.values(l).filter(o=>!o.hidden).map(o=>({name:`${o.displayName} (${o.name})`,value:o.name}))}]);await w(n,[],t)}(d)}
1
+ import o from"inquirer";import e from"chalk";import{wizard as t}from"../lib/wizard.js";import{runFollowUps as n}from"../lib/post-apply.js";import{toolManager as l,SUPPORTED_TOOLS as i}from"../lib/tool-manager.js";import{i18n as r}from"../lib/i18n.js";import{configManager as a,DEFAULT_PROFILE_NAME as s}from"../lib/config.js";import{confirmAction as c,applyOrDryRun as d,requireTerminal as f}from"../lib/confirm.js";import{canPrompt as g,isDryRun as p,isNonInteractive as m,shouldAutoConfirm as _}from"../lib/runtime-options.js";const u=/^[a-zA-Z0-9._-]+$/;function y(o,e){const t=(o||"").trim();if(!t||!u.test(t))throw new Error(r.t(`config.${e}_invalid_name`,{name:t||"<empty>"}));return t}function v(o,t){console.log("\n"+e.bold(o)),0!==t.length?t.forEach(o=>console.log(" "+o)):console.log(e.gray(" ("+r.t("config.empty_list")+")"))}function w(o,t){if("backups"===t){const t=l.listToolBackups(o).flatMap(o=>{const t=o.file.replace(/^.*[/\\]/,"");return o.backups.length?o.backups.map(o=>`${e.cyan(t)} ${e.gray(o.name.split(".bak-")[1]||o.name)}`):[`${e.cyan(t)} ${e.gray("("+r.t("config.empty_list")+")")}`]});return void v(r.t("config.tool_backups_title",{tool:i[o].displayName}),t)}const n=l.restorePrivateConfig(o).filter(o=>o.result.restored);0!==n.length?(console.log(e.green(r.t("config.config_restored",{tool:i[o].displayName}))),n.forEach(o=>console.log(e.gray(` ${o.file} ← ${o.result.from}`))),console.log(e.yellow(" ! "+r.t("config.reopen_hint",{tool:i[o].displayName})))):console.log(e.yellow(r.t("config.restore_no_backup",{tool:i[o].displayName})))}async function b(s,m,_){if(!i[s])return void console.log(e.red(r.t("config.unknown_tool",{tool:s})));const u=(m[0]||"").toLowerCase();if("backups"!==u&&"list-backups"!==u)if("restore"!==u){if("remove"===u||"unload"===u){const o=i[s].displayName;return void await d({description:r.t("config.remove_dry_run",{tool:o}),json:{action:"remove",tool:s},apply:async()=>{if(!await c({message:r.t("config.confirm_remove",{tool:o,name:s}),defaultValue:!0}))return;const t=l.holdsOurConfig(s),n=l.unloadPrivateConfig(s);t?(console.log(e.green(r.t("config.remove_done",{tool:o}))),n.forEach(o=>console.log(e.yellow(" ! "+o.text)))):console.log(e.gray(r.t("config.remove_nothing",{tool:o})))}})}if("clear-model"===u||"clear-models"===u){const o=i[s].displayName;return l.supportsClearPinnedModels(s)?void await d({description:r.t("config.clear_model_dry_run",{tool:o}),json:{action:"clear_model",tool:s},apply:async()=>{const t=await l.clearPinnedModels(s);0!==t.length?(console.log(e.green(r.t("config.clear_model_done",{tool:o}))),t.forEach(o=>console.log(e.gray(` - ${o}`))),console.log(e.gray(r.t("config.clear_model_restart_hint",{tool:o})))):console.log(e.yellow(r.t("config.clear_model_none",{tool:o})))}}):void console.log(e.yellow(r.t("config.clear_model_unsupported",{tool:o})))}if(p())await d({description:r.t("config.tool_apply_dry_run",{tool:i[s].displayName}),json:{action:"apply",tool:s,force:Boolean(_.force)},apply:()=>{}});else{if(!l.isToolInstalled(s)){if(_.nonInteractive)return void console.log(e.yellow(r.t("wizard.tool_not_installed",{tool:i[s].displayName})));if(console.log(e.yellow(r.t("wizard.tool_not_installed",{tool:i[s].displayName}))),!g())return;const{shouldInstall:t}=await o.prompt([{type:"confirm",name:"shouldInstall",message:r.t("wizard.install_tool_confirm"),default:!0}]);if(!t)return void console.log(e.yellow(r.t("wizard.install_skipped")));try{await l.installTool(s)}catch(o){return console.error(e.red(r.t("install.install_failed_detail"))),void(o instanceof Error&&o.message&&console.error(e.gray(o.message)))}}if(_.nonInteractive||_.force){const o=a.getApiKeyForTool(s);if(!o)return void console.log(e.red(r.t("auth.reload_missing_config")));if(_.force&&!_.nonInteractive&&!await c({message:r.t("config.confirm_force",{tool:i[s].displayName}),defaultValue:!1}))return;return await l.applyPrivateConfig(s,o,a.getModelsForTool(s),{force:_.force,takeOver:!0}),_.force&&console.log(e.yellow(r.t("config.force_done",{tool:i[s].displayName,name:s}))),l.printApplied(s),void await n([s])}f(),await t.showToolMenu(s)}}else await d({description:r.t("config.tool_restore_dry_run",{tool:i[s].displayName}),json:{action:"tool_restore",tool:s},apply:async()=>{await c({message:r.t("config.confirm_restore",{tool:i[s].displayName}),defaultValue:!1})&&w(s,"restore")}});else w(s,"backups")}export async function configCommand(t){const{positional:n,options:l}=function(o){const e=[],t={};(m()||_())&&(t.nonInteractive=!0);for(const n of o)"--non-interactive"===n||"-y"===n?t.nonInteractive=!0:"--force"===n||"-f"===n?t.force=!0:e.push(n);return{positional:e,options:t}}(t),f=n[0],p=n.slice(1);if(f){switch(f){case"profile":return void await async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=a.getActiveProfileName(),t=a.listProfiles().map(t=>{const n=t===o;return`${n?e.green("●"):e.gray("○")} ${t}${n?e.gray(" ("+r.t("config.profile_active_label")+")"):""}`});return void v(r.t("config.profile_list_title"),t)}if("create"===t){const o=y(n,"profile");return a.listProfiles().includes(o)?void console.log(e.yellow(r.t("config.profile_exists",{name:o}))):void await d({description:r.t("config.profile_create_dry_run",{name:o}),json:{action:"profile_create",name:o},apply:()=>{a.createProfile(o),console.log(e.green(r.t("config.profile_created",{name:o})))}})}if("use"===t){const o=y(n,"profile");return void await d({description:r.t("config.profile_use_dry_run",{name:o}),json:{action:"profile_use",name:o},apply:()=>{a.setActiveProfile(o),console.log(e.green(r.t("config.profile_activated",{name:o})))}})}if("delete"===t||"remove"===t){const o=y(n,"profile");return o===s&&1===a.listProfiles().length?void console.log(e.yellow(r.t("config.profile_cannot_delete_last"))):void await d({description:r.t("config.profile_delete_dry_run",{name:o}),json:{action:"profile_delete",name:o},apply:async()=>{await c({message:r.t("config.profile_delete_confirm",{name:o}),defaultValue:!1})?(a.deleteProfile(o),console.log(e.green(r.t("config.profile_deleted",{name:o})))):console.log(e.yellow(r.t("config.profile_delete_aborted")))}})}console.log(e.red(r.t("config.unknown_action",{action:t})))}(p);case"preset":return void await async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=Object.entries(a.getCustomPresets()).map(([o,t])=>`${e.cyan(o)} ${e.gray(`H:${t.models.haiku} S:${t.models.sonnet} O:${t.models.opus}`)}`);return void v(r.t("config.preset_list_title"),o)}if("save"===t){const o=y(n,"preset");return void await d({description:r.t("config.preset_save_dry_run",{name:o}),json:{action:"preset_save",name:o},apply:()=>{a.saveCustomPreset(o,a.getModels()),console.log(e.green(r.t("config.preset_saved",{name:o})))}})}if("use"===t||"apply"===t){const o=y(n,"preset"),t=a.getCustomPresets()[o];return t?void await d({description:r.t("config.preset_use_dry_run",{name:o}),json:{action:"preset_use",name:o},apply:()=>{a.setModels(t.models),console.log(e.green(r.t("config.preset_applied",{name:o})))}}):void console.log(e.red(r.t("config.preset_not_found",{name:o})))}if("delete"===t||"remove"===t){const o=y(n,"preset");return void await d({description:r.t("config.preset_delete_dry_run",{name:o}),json:{action:"preset_delete",name:o},apply:()=>{a.deleteCustomPreset(o),console.log(e.green(r.t("config.preset_deleted",{name:o})))}})}console.log(e.red(r.t("config.unknown_action",{action:t})))}(p);case"tool-model":return void await async function(o){const t=o[0];if(!t||"list"===t){const o=a.getProfile().tool_models||{},t=Object.entries(o).map(([o,t])=>{const n=Object.entries(t).map(([o,e])=>`${o}=${e}`).join(" ");return`${e.cyan(o)} ${e.gray(n)}`});return void v(r.t("config.tool_model_list_title"),t)}if("set"===t){const t=(o[1]||"").trim(),n=o.length>=4?(o[2]||"").trim():"opus",l=(o.length>=4?o[3]:o[2]||"").trim();return i[t]?l&&u.test(n)?void await d({description:r.t("config.tool_model_set_dry_run",{tool:t,slot:n,model:l}),json:{action:"tool_model_set",tool:t,slot:n,model:l},apply:()=>{a.setToolModel(t,{[n]:l}),console.log(e.green(r.t("config.tool_model_set",{tool:t,slot:n,model:l})))}}):void console.log(e.red(r.t("config.tool_model_usage"))):void console.log(e.red(t?r.t("config.unknown_tool",{tool:t}):r.t("config.tool_model_usage")))}if("clear"===t||"remove"===t){const t=(o[1]||"").trim();return i[t]?void await d({description:r.t("config.tool_model_clear_dry_run",{tool:t}),json:{action:"tool_model_clear",tool:t},apply:()=>{a.setToolModel(t,null),console.log(e.green(r.t("config.tool_model_cleared",{tool:t})))}}):void console.log(e.red(t?r.t("config.unknown_tool",{tool:t}):r.t("config.tool_model_usage")))}console.log(e.red(r.t("config.unknown_action",{action:t})))}(p);case"backup":return void await function(o){return async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=a.listBackups().map(o=>{const t=new Date(o.mtimeMs).toISOString();return`${e.cyan(o.name)} ${e.gray(t)}`});return void v(r.t("config.backup_list_title"),o)}if("create"!==t&&"snapshot"!==t)return"restore"===t?n?void await d({description:r.t("config.backup_restore_dry_run",{name:n}),json:{action:"backup_restore",name:n},apply:async()=>{await c({message:r.t("config.backup_restore_confirm",{name:n}),defaultValue:!1})?(a.restoreBackup(n),console.log(e.green(r.t("config.backup_restored",{name:n})))):console.log(e.yellow(r.t("config.backup_restore_aborted")))}}):void console.log(e.red(r.t("config.backup_restore_missing_name"))):void console.log(e.red(r.t("config.unknown_action",{action:t})));await d({description:r.t("config.backup_create_dry_run"),json:{action:"backup_create",name:n??null},apply:()=>{const o=a.createBackup(n);console.log(e.green(r.t("config.backup_created",{path:o})))}})}(o)}(p)}"claude-code"!==f&&"claude-code"!==p[0]?i[f]?await b(f,p,l):(console.error(e.red(r.t("config.unknown_command",{command:f}))),console.log(e.gray(r.t("config.usage_hint"))),Object.values(i).filter(o=>!o.hidden).forEach(o=>{console.log(e.gray(` - ${o.name}: ${o.displayName}`))})):await b("claude-code",p,l)}else await async function(t){if(t.nonInteractive||!g())return void console.log(e.red(r.t("config.requires_argument")));const{selectedTool:n}=await o.prompt([{type:"list",name:"selectedTool",message:r.t("wizard.select_tool"),choices:Object.values(i).filter(o=>!o.hidden).map(o=>({name:`${o.displayName} (${o.name})`,value:o.name}))}]);await b(n,[],t)}(l)}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": 1,
3
- "about": "Components VibeCLI installs and upgrades (vibecli list / install / upgrade). Read by src/lib/components.ts and by scripts/gen-components-doc.mjs (docs, the install scripts' README). {scripts} = the brand's installMirror.scripts, {agy} = installMirror.agy, {devtools} = the neutral CNB mirror of fnm / uv / Git for Windows.",
3
+ "about": "Components the CLI installs and upgrades (its list / install / upgrade commands). Read by src/lib/components.ts and by scripts/gen-components-doc.mjs (docs, the install scripts' README). {scripts} = the brand's installMirror.scripts, {agy} = installMirror.agy, {devtools} = the neutral CNB mirror of fnm / uv / Git for Windows.",
4
4
  "devtools": "https://cnb.cool/lib/devtools/-/releases/latest/download",
5
5
  "components": [
6
6
  {
@@ -1 +1 @@
1
- import t from"chalk";import e from"inquirer";import{existsSync as r,mkdirSync as n,readFileSync as a,writeFileSync as o}from"fs";import{join as l}from"path";import{CLI_NAME as p}from"./brand.js";import{configManager as i}from"./config.js";import{i18n as s}from"./i18n.js";import{canPrompt as u,hasExplicitYes as d,isJsonMode as c}from"./runtime-options.js";import{track as f}from"./telemetry.js";import{compareVersions as m}from"./model-registry.js";import{listAdapters as g}from"./tools/registry.js";import{logger as _}from"../utils/logger.js";function y(){return l(i.getConfigDir(),"app-releases.json")}function w(){try{if(!r(y()))return{};const t=JSON.parse(a(y(),"utf-8"));return t&&"object"==typeof t?t:{}}catch{return{}}}function h(t,e){try{n(i.getConfigDir(),{recursive:!0}),o(y(),JSON.stringify({...w(),[t]:e},null,2))}catch(t){_.logError("app-update.writeCache",t)}}function v(){return g().flatMap(t=>[...t.appInstaller?[{name:t.name,displayName:t.displayName,appInstaller:t.appInstaller,installedVersion:t.installedVersion,runningApp:t.runningApp,tool:t.name}]:[],...(t.companionApps??[]).map(e=>({...e,tool:t.name}))])}export function appTools(){return v().map(t=>t.name)}export function getApp(t){return v().find(e=>e.name===t)}export function appsForTools(t){return v().filter(e=>t.includes(e.tool)).map(t=>t.name)}function k(t){const e=getApp(t);if(!e)throw new Error(`no app installer for ${t}`);return e}function b(t,e,r){try{return e()}catch(e){return _.logError(`app-update.${t}`,e),r}}function q(t){const e=k(t),r=e.appInstaller,n=b("installedPath",()=>null!==r.installedPath(),!1);return{tool:t,name:e.displayName,installed:n,current:n?b("installedVersion",()=>e.installedVersion?.()??null,null):null,running:!!n&&b("isRunning",()=>e.runningApp?.isRunning()??!1,!1),blocker:b("blocker",()=>r.blocker(),"unsupported_platform")}}function x(t,e,r){const n=Boolean(t.installed&&t.current&&e&&m(t.current,e)<0);return{...t,latest:e,outdated:n,...r?{error:r}:{}}}export async function appLatest(t,e={}){const r=w()[t],n=r&&Date.now()-r.checked_at<(r.version?36e5:6e5);if(r&&n&&!e.refresh)return{version:r.version??null,...r.error?{error:r.error}:{}};try{const e=await k(t).appInstaller.latestVersion();return h(t,{version:e,checked_at:Date.now()}),{version:e}}catch(e){const n=e instanceof Error?e.message:String(e);return _.logError(`app-update.latest(${t})`,e),h(t,{error:n,checked_at:Date.now()}),{version:r?.version??null,error:n}}}export async function appStatus(t,e={}){const r=q(t);if(r.blocker&&"classic_install"!==r.blocker)return x(r,null);const{version:n,error:a}=await appLatest(t,e);return x(r,n,a)}export function appStatusWith(t,e){return x(q(t),e.version,e.error)}export function cachedAppStatus(t){const e=q(t);return x(e,e.blocker&&"classic_install"!==e.blocker?null:w()[t]?.version??null)}export function appStatusText(t){return t.installed?t.outdated?s.t("app_update.outdated",{current:t.current,latest:t.latest}):t.current&&t.latest?s.t("app_update.up_to_date",{current:t.current}):t.current??"":t.latest?s.t("app_update.not_installed",{latest:t.latest}):""}export function appUpgradeCommand(t){return`${p} upgrade ${t}`}function C(t){c()?process.stderr.write(t+"\n"):console.log(t)}async function S(t,r=!0){const{ok:n}=await e.prompt([{type:"confirm",name:"ok",message:t,default:r}]);return n}let U={totalMs:12e4,stepMs:1e3};export function setQuitWaitForTests(t){U=t}export async function upgradeApp(e,r={}){const n=Date.now(),a=await appStatus(e,{refresh:r.refresh??!0}),o=a.name,l=(t,r={})=>{const o={...a,result:t,upgraded:"upgraded"===t||"installed"===t,version_after:null,...r};return["up_to_date","unavailable","not_installed","offered"].includes(t)||f(`app-upgrade:${e}`,"failed"===t?"fail":"ok",{duration_ms:Date.now()-n,detail:{result:t,current:a.current,latest:a.latest,...r.reason?{reason:r.reason}:{}}}),o};if(a.blocker)return!r.quiet&&a.installed&&a.outdated&&C(t.yellow(" ! "+s.t("app_update.outdated",{current:a.current,latest:a.latest}))),r.quiet||C(t.yellow(" ! "+s.t(`app_update.blocked_${a.blocker}`,{tool:o,url:k(e).appInstaller.downloadPage,command:appUpgradeCommand(e)}))),l("unavailable",{reason:a.blocker});if(!a.latest)return r.quiet||C(t.yellow(" ! "+s.t("app_update.latest_unknown",{tool:o,reason:a.error??""}))),l("unavailable",{reason:a.error});if(!a.installed&&!r.install)return l("not_installed");const p=Boolean(r.force&&a.installed&&!a.outdated);if(a.installed&&!a.outdated&&!p)return r.quiet||(C(t.green(" √ "+s.t("app_update.already_latest",{tool:o,current:a.current??a.latest}))),C(t.gray(" "+s.t("app_update.force_hint",{command:appUpgradeCommand(e)})))),l("up_to_date");if(p?C(t.yellow(" ! "+s.t("app_update.reinstalling",{tool:o,latest:a.latest,current:a.current??"?"}))):!a.installed||r.askBeforeUpgrade&&!a.running||C(t.yellow(` ! ${o} `+appStatusText(a))),a.installed&&r.askBeforeUpgrade&&!a.running){if(!u()||d())return C(t.gray(" "+s.t("app_update.upgrade_hint",{tool:o,current:a.current??"?",latest:a.latest,command:appUpgradeCommand(e)}))),l("offered");if(!await S(s.t("app_update.upgrade_offer",{tool:o,current:a.current??"?",latest:a.latest})))return C(t.gray(" "+s.t("app_update.declined_hint",{command:appUpgradeCommand(e)}))),l("declined")}let i=!1;if(a.running){if(!u()||d())return C(t.yellow(" ! "+s.t("app_update.running_hint",{tool:o,command:appUpgradeCommand(e)}))),l("left_running");if(!await S(s.t("app_update.offer_quit",{tool:o,latest:a.latest})))return C(t.gray(" "+s.t("app_update.declined_hint",{command:appUpgradeCommand(e)}))),l("declined");const r=k(e).runningApp;if(r?.quit?.())i=!0;else{if(!r?.quitRefused?.()||!await async function(e,r){C(t.yellow(" ! "+s.t("app_update.quit_confirm_in_app",{tool:e,seconds:String(Math.round(U.totalMs/1e3))})));const n=Date.now()+U.totalMs;for(;Date.now()<n;)if(await new Promise(t=>setTimeout(t,U.stepMs)),!r.isRunning())return await new Promise(t=>setTimeout(t,Math.min(1e3,U.stepMs))),!0;return!1}(o,r)){const n=r?.quitRefused?.()?"app_update.quit_refused":"app_update.quit_failed";return C(t.yellow(" ! "+s.t(n,{tool:o,command:appUpgradeCommand(e)}))),l(r?.quitRefused?.()?"left_running":"failed",{reason:r?.quitRefused?.()?"quit_refused":"quit_failed"})}i=!0}}try{const{version:r}=await async function(e){const r=k(e).appInstaller,n=!c()&&Boolean(process.stdout.isTTY);let a=-1;try{return await r.install({downloading:n=>C(t.gray(" "+s.t("app_update.downloading",{tool:k(e).displayName,version:n,size:String(r.sizeMb())}))),percent:e=>{!n||e-a<5||(a=e,process.stdout.write(t.gray(`\r ${e}%`)),e>=100&&process.stdout.write("\n"))},verifying:()=>{n&&a>=0&&a<100&&process.stdout.write("\n"),a=100,C(t.gray(" "+s.t("app_update.verifying",{vendor:r.vendor})))},installing:()=>C(t.gray(" "+s.t("app_update.installing")))})}finally{n&&a>=0&&a<100&&process.stdout.write("\n")}}(e);return C(t.green(" √ "+(p?s.t("app_update.reinstalled",{tool:o,version:r}):a.installed?s.t("app_update.upgraded",{tool:o,from:a.current??"?",to:r}):s.t("app_update.installed",{tool:o,version:r})))),i&&!k(e).runningApp?.launch?.()&&C(t.yellow(" ! "+s.t("setup.reopen_hint",{tool:o}))),l(a.installed?"upgraded":"installed",{version_after:r,current:a.current})}catch(r){const n=r instanceof Error?r.message:String(r);return _.logError(`app-update.install(${e})`,r),C(t.yellow(" ! "+(a.installed?s.t("app_update.upgrade_failed",{tool:o,reason:n,current:a.current??"?",command:appUpgradeCommand(e)}):s.t("app_update.install_failed",{tool:o,reason:n,command:appUpgradeCommand(e)})))),i&&k(e).runningApp?.launch?.(),l("failed",{reason:n})}}
1
+ import t from"chalk";import e from"inquirer";import{existsSync as r,mkdirSync as n,readFileSync as a,writeFileSync as o}from"fs";import{join as p}from"path";import{CLI_NAME as l}from"./brand.js";import{configManager as i}from"./config.js";import{i18n as s}from"./i18n.js";import{canPrompt as u,hasExplicitYes as d,isJsonMode as c}from"./runtime-options.js";import{track as f}from"./telemetry.js";import{compareVersions as m}from"./model-registry.js";import{listAdapters as g}from"./tools/registry.js";import{logger as _}from"../utils/logger.js";function y(){return p(i.getConfigDir(),"app-releases.json")}function w(){try{if(!r(y()))return{};const t=JSON.parse(a(y(),"utf-8"));return t&&"object"==typeof t?t:{}}catch{return{}}}function h(t,e){try{n(i.getConfigDir(),{recursive:!0}),o(y(),JSON.stringify({...w(),[t]:e},null,2))}catch(t){_.logError("app-update.writeCache",t)}}function v(){return g().flatMap(t=>[...t.appInstaller?[{name:t.name,displayName:t.displayName,appInstaller:t.appInstaller,installedVersion:t.installedVersion,runningApp:t.runningApp,tool:t.name}]:[],...(t.companionApps??[]).map(e=>({...e,tool:t.name}))])}export function appTools(){return v().map(t=>t.name)}export function getApp(t){return v().find(e=>e.name===t)}export function appsForTools(t){return v().filter(e=>t.includes(e.tool)).map(t=>t.name)}function k(t){const e=getApp(t);if(!e)throw new Error(`no app installer for ${t}`);return e}function b(t,e,r){try{return e()}catch(e){return _.logError(`app-update.${t}`,e),r}}function q(t){const e=k(t),r=e.appInstaller,n=b("installedPath",()=>null!==r.installedPath(),!1);return{tool:t,name:e.displayName,installed:n,current:n?b("installedVersion",()=>e.installedVersion?.()??null,null):null,running:!!n&&b("isRunning",()=>e.runningApp?.isRunning()??!1,!1),blocker:b("blocker",()=>r.blocker(),"unsupported_platform")}}function x(t,e,r){const n=Boolean(t.installed&&t.current&&e&&m(t.current,e)<0);return{...t,latest:e,outdated:n,...r?{error:r}:{}}}export async function appLatest(t,e={}){const r=w()[t],n=r&&Date.now()-r.checked_at<(r.version?36e5:6e5);if(r&&n&&!e.refresh)return{version:r.version??null,...r.error?{error:r.error}:{}};try{const e=await k(t).appInstaller.latestVersion();return h(t,{version:e,checked_at:Date.now()}),{version:e}}catch(e){const n=e instanceof Error?e.message:String(e);return _.logError(`app-update.latest(${t})`,e),h(t,{error:n,checked_at:Date.now()}),{version:r?.version??null,error:n}}}export async function appStatus(t,e={}){const r=q(t);if(r.blocker&&"classic_install"!==r.blocker)return x(r,null);const{version:n,error:a}=await appLatest(t,e);return x(r,n,a)}export function appStatusWith(t,e){return x(q(t),e.version,e.error)}export function cachedAppStatus(t){const e=q(t);return x(e,e.blocker&&"classic_install"!==e.blocker?null:w()[t]?.version??null)}export function appStatusText(t){return t.installed?t.outdated?s.t("app_update.outdated",{current:t.current,latest:t.latest}):t.current&&t.latest?s.t("app_update.up_to_date",{current:t.current}):t.current??"":t.latest?s.t("app_update.not_installed",{latest:t.latest}):""}export function appUpgradeCommand(t){return`${l} upgrade ${t}`}function C(t){c()?process.stderr.write(t+"\n"):console.log(t)}async function S(t,r=!0){const{ok:n}=await e.prompt([{type:"confirm",name:"ok",message:t,default:r}]);return n}let U={totalMs:12e4,stepMs:1e3};export function setQuitWaitForTests(t){U=t}export async function upgradeApp(e,r={}){const n=Date.now(),a=await appStatus(e,{refresh:r.refresh??!0}),o=a.name,p=(t,r={})=>{const o={...a,result:t,upgraded:"upgraded"===t||"installed"===t,version_after:null,...r};return["up_to_date","unavailable","not_installed","offered"].includes(t)||f(`app-upgrade:${e}`,"failed"===t?"fail":"ok",{duration_ms:Date.now()-n,detail:{result:t,current:a.current,latest:a.latest,...r.reason?{reason:r.reason}:{}}}),o};if(a.blocker)return!r.quiet&&a.installed&&a.outdated&&C(t.yellow(" ! "+s.t("app_update.outdated",{current:a.current,latest:a.latest}))),r.quiet||C(t.yellow(" ! "+s.t(`app_update.blocked_${a.blocker}`,{tool:o,url:k(e).appInstaller.downloadPage,command:appUpgradeCommand(e)}))),p("unavailable",{reason:a.blocker});if(!a.latest)return r.quiet||C(t.yellow(" ! "+s.t("app_update.latest_unknown",{tool:o,reason:a.error??""}))),p("unavailable",{reason:a.error});if(!a.installed&&!r.install)return p("not_installed");const l=Boolean(r.force&&a.installed&&!a.outdated);if(a.installed&&!a.outdated&&!l)return r.quiet||(C(t.green(" √ "+s.t("app_update.already_latest",{tool:o,current:a.current??a.latest}))),C(t.gray(" "+s.t("app_update.force_hint",{command:appUpgradeCommand(e)})))),p("up_to_date");if(l?C(t.yellow(" ! "+s.t("app_update.reinstalling",{tool:o,latest:a.latest,current:a.current??"?"}))):!a.installed||r.askBeforeUpgrade&&!a.running||C(t.yellow(` ! ${o} `+appStatusText(a))),a.installed&&r.askBeforeUpgrade&&!a.running){if(!u()||d())return C(t.gray(" "+s.t("app_update.upgrade_hint",{tool:o,current:a.current??"?",latest:a.latest,command:appUpgradeCommand(e)}))),p("offered");if(!await S(s.t("app_update.upgrade_offer",{tool:o,current:a.current??"?",latest:a.latest})))return C(t.gray(" "+s.t("app_update.declined_hint",{command:appUpgradeCommand(e)}))),p("declined")}let i=!1;if(a.running){if(!u()||d())return C(t.yellow(" ! "+s.t("app_update.running_hint",{tool:o,command:appUpgradeCommand(e)}))),p("left_running");if(!await S(s.t("app_update.offer_quit",{tool:o,latest:a.latest})))return C(t.gray(" "+s.t("app_update.declined_hint",{command:appUpgradeCommand(e)}))),p("declined");const r=k(e).runningApp;if(r?.quit?.())i=!0;else{if(!r?.quitRefused?.()||!await async function(e,r){C(t.yellow(" ! "+s.t("app_update.quit_confirm_in_app",{tool:e,seconds:String(Math.round(U.totalMs/1e3))})));const n=Date.now()+U.totalMs;for(;Date.now()<n;)if(await new Promise(t=>setTimeout(t,U.stepMs)),!r.isRunning())return await new Promise(t=>setTimeout(t,Math.min(1e3,U.stepMs))),!0;return!1}(o,r)){const n=r?.quitRefused?.()?"app_update.quit_refused":"app_update.quit_failed";return C(t.yellow(" ! "+s.t(n,{tool:o,command:appUpgradeCommand(e)}))),p(r?.quitRefused?.()?"left_running":"failed",{reason:r?.quitRefused?.()?"quit_refused":"quit_failed"})}i=!0}}try{const{version:r}=await async function(e){const r=k(e).appInstaller,n=!c()&&Boolean(process.stdout.isTTY);let a=-1;try{return await r.install({downloading:n=>C(t.gray(" "+s.t("app_update.downloading",{tool:k(e).displayName,version:n,size:String(r.sizeMb())}))),percent:e=>{!n||e-a<5||(a=e,process.stdout.write(t.gray(`\r ${e}%`)),e>=100&&process.stdout.write("\n"))},verifying:()=>{n&&a>=0&&a<100&&process.stdout.write("\n"),a=100,C(t.gray(" "+s.t("app_update.verifying",{vendor:r.vendor})))},installing:()=>C(t.gray(" "+s.t("app_update.installing"))),elevate:async()=>!(!u()||!d()&&!await S(s.t("app_update.elevate_offer",{tool:k(e).displayName}))||(C(t.gray(" "+s.t("app_update.elevating"))),0))})}finally{n&&a>=0&&a<100&&process.stdout.write("\n")}}(e);return C(t.green(" √ "+(l?s.t("app_update.reinstalled",{tool:o,version:r}):a.installed?s.t("app_update.upgraded",{tool:o,from:a.current??"?",to:r}):s.t("app_update.installed",{tool:o,version:r})))),i&&!k(e).runningApp?.launch?.()&&C(t.yellow(" ! "+s.t("setup.reopen_hint",{tool:o}))),p(a.installed?"upgraded":"installed",{version_after:r,current:a.current})}catch(r){const n=r instanceof Error?r.message:String(r);return _.logError(`app-update.install(${e})`,r),C(t.yellow(" ! "+(a.installed?s.t("app_update.upgrade_failed",{tool:o,reason:n,current:a.current??"?",command:appUpgradeCommand(e)}):s.t("app_update.install_failed",{tool:o,reason:n,command:appUpgradeCommand(e)})))),i&&k(e).runningApp?.launch?.(),p("failed",{reason:n})}}
@@ -34,11 +34,17 @@ export interface EnvCleanupResult {
34
34
  /**
35
35
  * Removes ANTHROPIC_* settings that point at this gateway from shell profiles and the Windows
36
36
  * environment (they override the settings.json vibecli writes), after backing each one up.
37
- * Settings for another service are left alone and reported (new-api#174: a profile someone else
38
- * wrote is not ours to delete). Runs when Claude Code is configured, after the write plan was
37
+ * Settings for another service are left alone here (new-api#174: a profile someone else wrote is
38
+ * not ours to delete unasked); the Claude Code adapter's `followUp()` asks about them in a terminal
39
+ * (user, 11-03: default yes). Runs when Claude Code is configured, after the write plan was
39
40
  * confirmed; the plan lists the same sources (`envCleanupPlan`).
40
41
  */
41
42
  export declare function cleanupAnthropicEnvVars(): EnvCleanupResult;
43
+ /**
44
+ * Removes the ANTHROPIC_* settings of `sources` (each backed up first): shell / PowerShell profile
45
+ * lines, Windows user and system variables (system ones need an administrator, left in `machineLeft`).
46
+ */
47
+ export declare function removeEnvSources(sources: EnvSource[]): EnvCleanupResult;
42
48
  /** What the last `cleanupAnthropicEnvVars()` did, for the notes after Claude Code is configured. */
43
49
  export declare function lastEnvCleanup(): EnvCleanupResult;
44
50
  /** Shown in the write plan before Claude Code is configured: profiles whose ANTHROPIC_* lines go. */
@@ -1 +1 @@
1
- import{existsSync as o,mkdirSync as n,readFileSync as e,writeFileSync as r}from"fs";import{join as t}from"path";import{logger as s}from"../utils/logger.js";import{toolHome as c}from"./tools/types.js";import{backupBeforeWrite as i}from"./tools/backup.js";import{configManager as f,savedApiKeys as u}from"./config.js";import{isOurGatewayUrl as a}from"./gateway-addresses.js";import{broadcastEnvChange as l,deleteWindowsEnv as p,readWindowsEnv as m}from"./windows-env.js";export const ANTHROPIC_ENV_VARS=["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL","ANTHROPIC_MODEL","ANTHROPIC_REASONING_MODEL"];export function getShellRcFilePath(){if("win32"===process.platform)return null;const o=c();switch((process.env.SHELL||"").split("/").pop()||""){case"bash":return t(o,".bashrc");case"zsh":return t(o,".zshrc");case"fish":return t(o,".config","fish","config.fish");default:return t(o,".profile")}}function h(o){const n=o.trim().replace(/\s+#.*$/,""),e=n.match(/^(['"])(.*)\1$/);return e?e[2]:n}const E=o=>new RegExp(String.raw`^\s*export\s+${o}=(.*)$`,"gm"),v=o=>new RegExp(String.raw`^[ \t]*\$env:${o}[ \t]*=(.*)$`,"gim");function g(o){if(a(o.ANTHROPIC_BASE_URL))return!0;const n=u();return[o.ANTHROPIC_API_KEY,o.ANTHROPIC_AUTH_TOKEN].some(o=>Boolean(o)&&n.includes(o.trim()))}export function anthropicEnvSources(){const n=[],r=(r,t)=>{if(r&&o(r))try{const o=function(o,n){const e={};for(const r of ANTHROPIC_ENV_VARS)for(const t of o.matchAll(n(r)))e[r]=h(t[1]);return e}(e(r,"utf-8"),t);Object.keys(o).length>0&&n.push({kind:"file",location:r,vars:o,ours:g(o)})}catch(o){s.logError("envCleanup.read",o)}};if("win32"!==process.platform)return r(getShellRcFilePath(),E),n;for(const o of["user","machine"]){const e={};for(const n of ANTHROPIC_ENV_VARS){const r=m(o,n);void 0!==r&&(e[n]=r)}Object.keys(e).length>0&&n.push({kind:"user"===o?"windows-user":"windows-machine",location:"user"===o?"HKCU\\Environment":"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",vars:e,ours:g(e)})}for(const o of function(){const o=c(),n=[];for(const e of[t(o,"Documents"),t(o,"OneDrive","Documents"),t(o,"OneDrive","文档")])for(const o of["PowerShell","WindowsPowerShell"])n.push(t(e,o,"Microsoft.PowerShell_profile.ps1"),t(e,o,"profile.ps1"));return n}())r(o,v);return n}function O(o,n,t){const c=e(o,"utf-8");let f=c;for(const o of n)f=f.replace(new RegExp(t(o).source+String.raw`(\r?\n)?`,t(o).flags),"");return t===E&&(f=f.replace(/^\s*#\s*Claude Code environment variables\s*$\n?/gm,"")),f!==c&&(i(o),r(o,f,"utf-8"),s.debug(`Removed ${n.join(", ")} from ${o}`),!0)}function A(o,e){try{const s=t(f.getConfigDir(),"backups");n(s,{recursive:!0});const c=t(s,`windows-env-${o}-${(new Date).toISOString().replace(/[:.]/g,"-")}.json`);return r(c,JSON.stringify(e,null,2)+"\n",{mode:384}),c}catch(o){return s.logError("envCleanup.backupWindowsValues",o),null}}let _={removed:[],foreign:[],machineLeft:[]};export function cleanupAnthropicEnvVars(){const o={removed:[],foreign:[],machineLeft:[]};let n=!1;for(const e of anthropicEnvSources()){if(!e.ours){o.foreign.push(e);continue}const r=Object.keys(e.vars);try{if("file"===e.kind){O(e.location,r,e.location.endsWith(".ps1")?v:E)&&o.removed.push(e);continue}const t="windows-user"===e.kind?"user":"machine";A(t,e.vars);const c=[];for(const n of r)try{p(t,n),c.push(n)}catch(e){"machine"===t&&o.machineLeft.push(n),s.logError("envCleanup.deleteWindowsEnv",e)}c.length>0&&(n=!0,o.removed.push({...e,vars:Object.fromEntries(c.map(o=>[o,e.vars[o]]))}))}catch(o){s.logError("envCleanup.cleanupAnthropicEnvVars",o)}}n&&l();for(const n of o.removed)for(const[o,e]of Object.entries(n.vars))process.env[o]===e&&delete process.env[o];return _=o,o}export function lastEnvCleanup(){return _}export function envCleanupPlan(){return anthropicEnvSources().filter(o=>o.ours)}
1
+ import{existsSync as e,mkdirSync as o,readFileSync as r,writeFileSync as n}from"fs";import{join as t}from"path";import{logger as s}from"../utils/logger.js";import{toolHome as c}from"./tools/types.js";import{backupBeforeWrite as i}from"./tools/backup.js";import{configManager as u,savedApiKeys as f}from"./config.js";import{isOurGatewayUrl as l}from"./gateway-addresses.js";import{broadcastEnvChange as a,deleteWindowsEnv as p,readWindowsEnv as m}from"./windows-env.js";export const ANTHROPIC_ENV_VARS=["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL","ANTHROPIC_MODEL","ANTHROPIC_REASONING_MODEL"];export function getShellRcFilePath(){if("win32"===process.platform)return null;const e=c();switch((process.env.SHELL||"").split("/").pop()||""){case"bash":return t(e,".bashrc");case"zsh":return t(e,".zshrc");case"fish":return t(e,".config","fish","config.fish");default:return t(e,".profile")}}function h(e){const o=e.trim().replace(/\s+#.*$/,""),r=o.match(/^(['"])(.*)\1$/);return r?r[2]:o}const v=e=>new RegExp(String.raw`^\s*export\s+${e}=(.*)$`,"gm"),E=e=>new RegExp(String.raw`^[ \t]*\$env:${e}[ \t]*=(.*)$`,"gim");function g(e){if(l(e.ANTHROPIC_BASE_URL))return!0;const o=f();return[e.ANTHROPIC_API_KEY,e.ANTHROPIC_AUTH_TOKEN].some(e=>Boolean(e)&&o.includes(e.trim()))}export function anthropicEnvSources(){const o=[],n=(n,t)=>{if(n&&e(n))try{const e=function(e,o){const r={};for(const n of ANTHROPIC_ENV_VARS)for(const t of e.matchAll(o(n)))r[n]=h(t[1]);return r}(r(n,"utf-8"),t);Object.keys(e).length>0&&o.push({kind:"file",location:n,vars:e,ours:g(e)})}catch(e){s.logError("envCleanup.read",e)}};if("win32"!==process.platform)return n(getShellRcFilePath(),v),o;for(const e of["user","machine"]){const r={};for(const o of ANTHROPIC_ENV_VARS){const n=m(e,o);void 0!==n&&(r[o]=n)}Object.keys(r).length>0&&o.push({kind:"user"===e?"windows-user":"windows-machine",location:"user"===e?"HKCU\\Environment":"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",vars:r,ours:g(r)})}for(const e of function(){const e=c(),o=[];for(const r of[t(e,"Documents"),t(e,"OneDrive","Documents"),t(e,"OneDrive","文档")])for(const e of["PowerShell","WindowsPowerShell"])o.push(t(r,e,"Microsoft.PowerShell_profile.ps1"),t(r,e,"profile.ps1"));return o}())n(e,E);return o}function O(e,o,t){const c=r(e,"utf-8");let u=c;for(const e of o)u=u.replace(new RegExp(t(e).source+String.raw`(\r?\n)?`,t(e).flags),"");return t===v&&(u=u.replace(/^\s*#\s*Claude Code environment variables\s*$\n?/gm,"")),u!==c&&(i(e),n(e,u,"utf-8"),s.debug(`Removed ${o.join(", ")} from ${e}`),!0)}function _(e,r){try{const s=t(u.getConfigDir(),"backups");o(s,{recursive:!0});const c=t(s,`windows-env-${e}-${(new Date).toISOString().replace(/[:.]/g,"-")}.json`);return n(c,JSON.stringify(r,null,2)+"\n",{mode:384}),c}catch(e){return s.logError("envCleanup.backupWindowsValues",e),null}}let A={removed:[],foreign:[],machineLeft:[]};export function cleanupAnthropicEnvVars(){const e=anthropicEnvSources(),o=removeEnvSources(e.filter(e=>e.ours));return o.foreign=e.filter(e=>!e.ours),A=o,o}export function removeEnvSources(e){const o={removed:[],foreign:[],machineLeft:[]};let r=!1;for(const n of e){const e=Object.keys(n.vars);try{if("file"===n.kind){O(n.location,e,n.location.endsWith(".ps1")?E:v)&&o.removed.push(n);continue}const t="windows-user"===n.kind?"user":"machine";_(t,n.vars);const c=[];for(const r of e)try{p(t,r),c.push(r)}catch(e){"machine"===t&&o.machineLeft.push(r),s.logError("envCleanup.deleteWindowsEnv",e)}c.length>0&&(r=!0,o.removed.push({...n,vars:Object.fromEntries(c.map(e=>[e,n.vars[e]]))}))}catch(e){s.logError("envCleanup.removeEnvSources",e)}}r&&a();for(const e of o.removed)for(const[o,r]of Object.entries(e.vars))process.env[o]===r&&delete process.env[o];return o}export function lastEnvCleanup(){return A}export function envCleanupPlan(){return anthropicEnvSources().filter(e=>e.ours)}
@@ -3,6 +3,11 @@
3
3
  * UAC prompt each, asked in interactive terminals; `--yes` runs them without asking.
4
4
  */
5
5
  export declare function runPendingElevations(tools: string[]): Promise<void>;
6
+ /**
7
+ * The adapters' `followUp()` offers (Codex sessions, another service's ANTHROPIC_* variables): asked in a
8
+ * terminal with default yes, done under `--yes`, otherwise only the hint is printed. Also after `config <tool>`.
9
+ */
10
+ export declare function runFollowUps(tools: string[]): Promise<void>;
6
11
  /**
7
12
  * What setup and the wizard ask right after writing configs: UAC changes and
8
13
  * adapter follow-ups (non-interactive: only their hint), then upgrade tools too
@@ -1 +1 @@
1
- import o from"chalk";import t from"inquirer";import{i18n as n}from"./i18n.js";import{canPrompt as e,hasExplicitYes as r,shouldAutoConfirm as i}from"./runtime-options.js";import{toolManager as s}from"./tool-manager.js";import{getAdapter as a}from"./tools/registry.js";import{upgradeTool as l}from"./tool-upgrade.js";import{appsForTools as p,upgradeApp as f}from"./app-update.js";import{logger as c}from"../utils/logger.js";async function u(o){const{ok:n}=await t.prompt([{type:"confirm",name:"ok",message:o,default:!0}]);return n}export async function runPendingElevations(t){const r=e();for(const e of t){const t=a(e)?.pendingElevation?.();if(!t)continue;if(!(i()||r&&await u(t.prompt)))continue;const s=a(e)?.displayName??e;console.log(o.gray(" "+n.t("setup.elevation_running"))),console.log(t.run()?o.green(" √ "+n.t("setup.elevation_done",{tool:s})):o.yellow(" ! "+n.t("setup.elevation_failed",{tool:s})))}}export async function postApplyPrompts(t,i={}){const m=new Set;for(const o of i.apps?p(t):[])try{const t=await f(o,{install:i.apps.install,quiet:!0,askBeforeUpgrade:!0});t.upgraded&&t.running&&m.add(o)}catch(t){c.logError(`postApplyPrompts.upgradeApp(${o})`,t)}for(const n of t){const t=await(a(n)?.prepareRuntime?.())??[];for(const n of t)console.log("action"===n.kind?o.yellow(" ! "+n.text):o.green(" √ "+n.text))}await runPendingElevations(t);const g=e();for(const n of t){let t;try{t=await(a(n)?.followUp?.())}catch(o){c.logError(`postApplyPrompts.followUp(${n})`,o);continue}if(t)if("run"in t&&(r()||g))if(r()||await u(t.prompt))for(const n of await t.run())console.log("action"===n.kind?o.yellow(" ! "+n.text):o.green(" √ "+n.text));else t.decline();else console.log(o.yellow(" ! "+t.hint))}const d=r(),y=g||d?t.filter(o=>a(o)?.installSpec&&s.outdatedVersion(o)):[];if(y.length>0){const o=y.map(o=>a(o)?.displayName??o).join("、");if(d||await u(n.t("setup.offer_upgrade",{tools:o})))for(const o of y)await l(o)}for(const e of t){const t=a(e);if(m.has(e)||!t?.runningApp?.isRunning())continue;if(d||!g){console.log(o.yellow(" ! "+n.t("setup.reopen_hint",{tool:t.displayName})));continue}if(!await u(n.t("setup.offer_restart",{tool:t.displayName})))continue;const r=t.runningApp.restart();console.log(r?o.green(" √ "+n.t("setup.restarted",{tool:t.displayName})):o.yellow(" ! "+n.t("setup.restart_failed",{tool:t.displayName})))}}
1
+ import o from"chalk";import t from"inquirer";import{i18n as n}from"./i18n.js";import{canPrompt as e,hasExplicitYes as r,shouldAutoConfirm as i}from"./runtime-options.js";import{toolManager as s}from"./tool-manager.js";import{getAdapter as a}from"./tools/registry.js";import{upgradeTool as l}from"./tool-upgrade.js";import{appsForTools as p,upgradeApp as c}from"./app-update.js";import{logger as f}from"../utils/logger.js";async function u(o){const{ok:n}=await t.prompt([{type:"confirm",name:"ok",message:o,default:!0}]);return n}export async function runPendingElevations(t){const r=e();for(const e of t){const t=a(e)?.pendingElevation?.();if(!t)continue;if(!(i()||r&&await u(t.prompt)))continue;const s=a(e)?.displayName??e;console.log(o.gray(" "+n.t("setup.elevation_running"))),console.log(t.run()?o.green(" √ "+n.t("setup.elevation_done",{tool:s})):o.yellow(" ! "+n.t("setup.elevation_failed",{tool:s})))}}export async function runFollowUps(t){const n=e();for(const e of t){let t;try{t=await(a(e)?.followUp?.())}catch(o){f.logError(`postApplyPrompts.followUp(${e})`,o);continue}if(t)if("run"in t&&(r()||n))if(r()||await u(t.prompt))for(const n of await t.run())console.log("action"===n.kind?o.yellow(" ! "+n.text):o.green(" √ "+n.text));else t.decline();else console.log(o.yellow(" ! "+t.hint))}}export async function postApplyPrompts(t,i={}){const m=new Set;for(const o of i.apps?p(t):[])try{const t=await c(o,{install:i.apps.install,quiet:!0,askBeforeUpgrade:!0});t.upgraded&&t.running&&m.add(o)}catch(t){f.logError(`postApplyPrompts.upgradeApp(${o})`,t)}for(const n of t){const t=await(a(n)?.prepareRuntime?.())??[];for(const n of t)console.log("action"===n.kind?o.yellow(" ! "+n.text):o.green(" √ "+n.text))}await runPendingElevations(t),await runFollowUps(t);const g=e(),d=r(),y=g||d?t.filter(o=>a(o)?.installSpec&&s.outdatedVersion(o)):[];if(y.length>0){const o=y.map(o=>a(o)?.displayName??o).join("、");if(d||await u(n.t("setup.offer_upgrade",{tools:o})))for(const o of y)await l(o)}for(const e of t){const t=a(e);if(m.has(e)||!t?.runningApp?.isRunning())continue;if(d||!g){console.log(o.yellow(" ! "+n.t("setup.reopen_hint",{tool:t.displayName})));continue}if(!await u(n.t("setup.offer_restart",{tool:t.displayName})))continue;const r=t.runningApp.restart();console.log(r?o.green(" √ "+n.t("setup.restarted",{tool:t.displayName})):o.yellow(" ! "+n.t("setup.restart_failed",{tool:t.displayName})))}}
@@ -1 +1 @@
1
- import{join as e}from"path";import{applyGatewayModels as t,claudeCodeManager as o}from"../claude-code-manager.js";import{backupBeforeWrite as n}from"./backup.js";import{i18n as s}from"../i18n.js";import{baseModelId as a}from"../model-catalog.js";import{gatewayModelSpecs as r,prettyModelName as i,vendorNames as l}from"../gateway-models.js";import{toolHome as d}from"./types.js";import{gatewayAddresses as c,normalizeBaseUrl as u}from"../gateway-addresses.js";import{configManager as m,savedApiKeys as p}from"../config.js";import{envCleanupPlan as g,lastEnvCleanup as f}from"../env-cleanup.js";import{maskHome as _}from"../telemetry.js";import{spawnSync as h}from"child_process";import{existsSync as C,readFileSync as v}from"fs";import{detectManagedOverrides as j}from"./claude-managed.js";import{installOfficialPlugins as y}from"./claude-plugins.js";import{findInstalls as k,mirrorInstallCommand as A,brandInstallScripts as P}from"./tool-installs.js";import{updateNativeFromMirror as S}from"./claude-native-mirror.js";import{brandEnv as O}from"../brand.js";import{claudeFormat as x,claudeProjectFiles as T}from"../sessions/formats.js";const N=e(d(),".claude","settings.json"),b=e(d(),".claude.json");let H,R=null,U=()=>0===h("security",["find-generic-password","-s","Claude Code-credentials"],{stdio:"ignore"}).status;export function setClaudeKeychainProbeForTests(e){U=e}export function claudeAccountLoginPresent(){const t=process.env.CLAUDE_CONFIG_DIR?.trim()||e(d(),".claude");if(C(e(t,".credentials.json")))return!0;if("darwin"!==process.platform||O("TEST_HOME"))return!1;try{return U()}catch{return!1}}function w(){try{const t=JSON.parse(v(e(d(),".claude","settings.json"),"utf-8"));return"string"==typeof t.autoUpdatesChannel?t.autoUpdatesChannel:"latest"}catch{return"latest"}}function E(e){if(!e)return;const t=new Set(e.models);return r("claude-code",e.clientModels).filter(e=>t.has(e.id))}function L(){const e=o.getSettings().env?.ANTHROPIC_BASE_URL;return"string"==typeof e&&e.trim()?claudeCodeAdapter.holdsOurConfig(p())?null:e.trim():null}let I=null;const M={command:"claude",npmPackage:"@anthropic-ai/claude-code",native:{binDir:[".local","bin"],updateArgs:["update"],dataDirs:[[".local","share","claude"]],mirrorUpdate:()=>S(w())},mirrorScript:P("claude-code"),brew:"claude-code"};export const claudeCodeAdapter={name:"claude-code",displayName:"Claude Code",command:"claude",installCommand:A(M),upgradeCommand:"claude update",installSpec:M,upgradeHints:e=>"stable"===w()?[s.t("tools.claude_code.stable_channel",{min:e})]:[],configPath:N,sessions:{format:x,files:()=>T(e(process.env.CLAUDE_CONFIG_DIR?.trim()||e(d(),".claude"),"projects")),resumeCommand:e=>({command:"claude",args:["--resume",e]})},wantsModelCatalog:!0,loadPrivateConfig(t){I=L(),n(N),n(b),H=E(t.catalog),o.loadPrivateConfig(t.apiKey,t.models,t.catalog?.models,H);const s=e(d(),".local","bin","win32"===process.platform?"claude.exe":"claude"),a=k(claudeCodeAdapter.installSpec)[0]?.path??(C(s)?s:null);R=a?y(a):null},holdsOurConfig(e){const t=o.getSettings().env??{},n="string"==typeof t.ANTHROPIC_AUTH_TOKEN?t.ANTHROPIC_AUTH_TOKEN.trim():"",s="string"==typeof t.ANTHROPIC_BASE_URL?u(t.ANTHROPIC_BASE_URL):null;return!(!n||!e.includes(n))||null!==s&&(c().some(e=>e.url===s)||s===u(m.getBaseUrl()))},planNotes(){const e=[],t=L();t&&e.push(s.t("tools.claude_code.plan_replace_provider",{url:t}));for(const t of g())e.push(s.t("tools.claude_code.plan_env_remove",{location:_(t.location),vars:Object.keys(t.vars).join(", ")}));return e},unloadPrivateConfig(e){const t=o.getSettings().env??{};Boolean(t.ANTHROPIC_AUTH_TOKEN||t.ANTHROPIC_BASE_URL)&&!claudeCodeAdapter.holdsOurConfig(e?.savedKeys??[])||(n(N),o.unloadPrivateConfig())},detectCurrentConfig:()=>o.detectCurrentConfig(),getConfig:()=>({settings:o.getSettings(),mcp:o.getMCPConfig()}),updateConfig(e){const t=e||{};t.settings&&o.saveSettings(t.settings),t.mcp&&o.saveMCPConfig(t.mcp)},clearPinnedModels:e=>(n(N),o.clearPinnedModels(e?.models)),listedModels(){const e=o.getSettings().modelPicker;return Array.isArray(e?.options)?e.options.map(e=>a(String(e.model))):null},refreshModelMenu(e){const s=o.getSettings(),a=t(s,E(e.catalog));JSON.stringify(a)!==JSON.stringify(s)&&(n(N),o.saveSettings(a))},applyNotes(){const e=[];R?.installed.length&&(e.push({kind:"summary",text:s.t("tools.claude_code.plugins_installed",{count:String(R.installed.length)})}),e.push({kind:"detail",text:R.installed.join(", ")})),"git"===R?.skipped?e.push({kind:"action",text:s.t("tools.claude_code.plugins_need_git")}):("marketplace"===R?.skipped||R?.failed.length)&&e.push({kind:"action",text:s.t("tools.claude_code.plugins_failed")}),H&&H.length>0&&(e.push({kind:"summary",text:s.t("tools.claude_code.gateway_models",{count:String(H.length),vendors:l(H.map(e=>e.id)).join(" / ")})}),e.push({kind:"detail",text:H.map(e=>e.name||i(e.id)).join(", ")})),I&&e.push({kind:"summary",text:s.t("tools.claude_code.provider_replaced",{url:I})});const t=f();for(const o of t.removed)e.push({kind:"summary",text:s.t("tools.claude_code.env_removed",{location:_(o.location),vars:Object.keys(o.vars).join(", ")})});for(const o of t.foreign)e.push({kind:"action",text:s.t("tools.claude_code.env_foreign",{location:_(o.location),vars:Object.keys(o.vars).join(", ")})});t.machineLeft.length>0&&e.push({kind:"action",text:s.t("messages.env_vars_machine_left",{vars:t.machineLeft.join(", ")})});const n=o.getLastKept();n.length>0&&e.push({kind:"summary",text:s.t("tools.claude_code.kept_user_models",{values:n.join(", ")})}),"win32"!==process.platform||process.env.CLAUDE_CODE_GIT_BASH_PATH||0===h("where",["git"],{windowsHide:!0,stdio:"ignore"}).status||e.push({kind:"action",text:s.t("tools.claude_code.no_git_bash")}),claudeAccountLoginPresent()&&e.push({kind:"detail",text:s.t("tools.claude_code.account_login_overridden")});for(const t of j())e.push({kind:"action",text:s.t("tools.claude_code.managed_override",{source:t.source,keys:t.keys.join(", ")})});for(const t of o.getLastTierFallbacks())e.push({kind:"detail",text:s.t("tools.claude_code.tier_fallback",{tier:t.tier,from:t.from,to:t.to})});return e},backupPaths:()=>[N,b],forceResetPaths:()=>[N]};
1
+ import{join as e}from"path";import{applyGatewayModels as t,claudeCodeManager as o}from"../claude-code-manager.js";import{backupBeforeWrite as n}from"./backup.js";import{i18n as s}from"../i18n.js";import{baseModelId as a}from"../model-catalog.js";import{gatewayModelSpecs as r,prettyModelName as i,vendorNames as l}from"../gateway-models.js";import{toolHome as c}from"./types.js";import{gatewayAddresses as d,normalizeBaseUrl as u}from"../gateway-addresses.js";import{configManager as m,savedApiKeys as p}from"../config.js";import{envCleanupPlan as f,lastEnvCleanup as g,removeEnvSources as _}from"../env-cleanup.js";import{canPrompt as h,hasExplicitYes as v}from"../runtime-options.js";import{maskHome as C}from"../telemetry.js";import{spawnSync as j}from"child_process";import{existsSync as y,readFileSync as k}from"fs";import{detectManagedOverrides as A}from"./claude-managed.js";import{installOfficialPlugins as O}from"./claude-plugins.js";import{findInstalls as S,mirrorInstallCommand as P,brandInstallScripts as x}from"./tool-installs.js";import{updateNativeFromMirror as b}from"./claude-native-mirror.js";import{brandEnv as T}from"../brand.js";import{claudeFormat as N,claudeProjectFiles as w}from"../sessions/formats.js";const H=e(c(),".claude","settings.json"),L=e(c(),".claude.json");let U,R=null,E=()=>0===j("security",["find-generic-password","-s","Claude Code-credentials"],{stdio:"ignore"}).status;export function setClaudeKeychainProbeForTests(e){E=e}export function claudeAccountLoginPresent(){const t=process.env.CLAUDE_CONFIG_DIR?.trim()||e(c(),".claude");if(y(e(t,".credentials.json")))return!0;if("darwin"!==process.platform||T("TEST_HOME"))return!1;try{return E()}catch{return!1}}function I(){try{const t=JSON.parse(k(e(c(),".claude","settings.json"),"utf-8"));return"string"==typeof t.autoUpdatesChannel?t.autoUpdatesChannel:"latest"}catch{return"latest"}}function M(e){if(!e)return;const t=new Set(e.models);return r("claude-code",e.clientModels).filter(e=>t.has(e.id))}function D(){const e=o.getSettings().env?.ANTHROPIC_BASE_URL;return"string"==typeof e&&e.trim()?claudeCodeAdapter.holdsOurConfig(p())?null:e.trim():null}let B=null;const K={command:"claude",npmPackage:"@anthropic-ai/claude-code",native:{binDir:[".local","bin"],updateArgs:["update"],dataDirs:[[".local","share","claude"]],mirrorUpdate:()=>b(I())},mirrorScript:x("claude-code"),brew:"claude-code"};function F(){return h()&&!v()}export const claudeCodeAdapter={name:"claude-code",displayName:"Claude Code",command:"claude",installCommand:P(K),upgradeCommand:"claude update",installSpec:K,upgradeHints:e=>"stable"===I()?[s.t("tools.claude_code.stable_channel",{min:e})]:[],configPath:H,sessions:{format:N,files:()=>w(e(process.env.CLAUDE_CONFIG_DIR?.trim()||e(c(),".claude"),"projects")),resumeCommand:e=>({command:"claude",args:["--resume",e]})},wantsModelCatalog:!0,loadPrivateConfig(t){B=D(),n(H),n(L),U=M(t.catalog),o.loadPrivateConfig(t.apiKey,t.models,t.catalog?.models,U);const s=e(c(),".local","bin","win32"===process.platform?"claude.exe":"claude"),a=S(claudeCodeAdapter.installSpec)[0]?.path??(y(s)?s:null);R=a?O(a):null},holdsOurConfig(e){const t=o.getSettings().env??{},n="string"==typeof t.ANTHROPIC_AUTH_TOKEN?t.ANTHROPIC_AUTH_TOKEN.trim():"",s="string"==typeof t.ANTHROPIC_BASE_URL?u(t.ANTHROPIC_BASE_URL):null;return!(!n||!e.includes(n))||null!==s&&(d().some(e=>e.url===s)||s===u(m.getBaseUrl()))},planNotes(){const e=[],t=D();t&&e.push(s.t("tools.claude_code.plan_replace_provider",{url:t}));for(const t of f())e.push(s.t("tools.claude_code.plan_env_remove",{location:C(t.location),vars:Object.keys(t.vars).join(", ")}));return e},unloadPrivateConfig(e){const t=o.getSettings().env??{};Boolean(t.ANTHROPIC_AUTH_TOKEN||t.ANTHROPIC_BASE_URL)&&!claudeCodeAdapter.holdsOurConfig(e?.savedKeys??[])||(n(H),o.unloadPrivateConfig())},detectCurrentConfig:()=>o.detectCurrentConfig(),getConfig:()=>({settings:o.getSettings(),mcp:o.getMCPConfig()}),updateConfig(e){const t=e||{};t.settings&&o.saveSettings(t.settings),t.mcp&&o.saveMCPConfig(t.mcp)},clearPinnedModels:e=>(n(H),o.clearPinnedModels(e?.models)),listedModels(){const e=o.getSettings().modelPicker;return Array.isArray(e?.options)?e.options.map(e=>a(String(e.model))):null},refreshModelMenu(e){const s=o.getSettings(),a=t(s,M(e.catalog));JSON.stringify(a)!==JSON.stringify(s)&&(n(H),o.saveSettings(a))},async followUp(){const e=g().foreign;if(0===e.length||!F())return null;const t=e.map(e=>`${C(e.location)}(${Object.keys(e.vars).join(", ")})`).join("、");return{prompt:s.t("tools.claude_code.env_foreign_offer",{where:t}),hint:s.t("tools.claude_code.env_foreign",{location:e.map(e=>C(e.location)).join("、"),vars:[...new Set(e.flatMap(e=>Object.keys(e.vars)))].join(", ")}),async run(){const t=_(e),o=t.removed.map(e=>({kind:"summary",text:s.t("tools.claude_code.env_removed_foreign",{location:C(e.location),vars:Object.keys(e.vars).join(", ")})}));return t.machineLeft.length>0&&o.push({kind:"action",text:s.t("messages.env_vars_machine_left",{vars:t.machineLeft.join(", ")})}),o},decline(){}}},applyNotes(){const e=[];R?.installed.length&&(e.push({kind:"summary",text:s.t("tools.claude_code.plugins_installed",{count:String(R.installed.length)})}),e.push({kind:"detail",text:R.installed.join(", ")})),"git"===R?.skipped?e.push({kind:"action",text:s.t("tools.claude_code.plugins_need_git")}):("marketplace"===R?.skipped||R?.failed.length)&&e.push({kind:"action",text:s.t("tools.claude_code.plugins_failed")}),U&&U.length>0&&(e.push({kind:"summary",text:s.t("tools.claude_code.gateway_models",{count:String(U.length),vendors:l(U.map(e=>e.id)).join(" / ")})}),e.push({kind:"detail",text:U.map(e=>e.name||i(e.id)).join(", ")})),B&&e.push({kind:"summary",text:s.t("tools.claude_code.provider_replaced",{url:B})});const t=g();for(const o of t.removed)e.push({kind:"summary",text:s.t("tools.claude_code.env_removed",{location:C(o.location),vars:Object.keys(o.vars).join(", ")})});for(const o of t.foreign){const t={location:C(o.location),vars:Object.keys(o.vars).join(", ")};e.push(F()?{kind:"detail",text:s.t("tools.claude_code.env_foreign_found",t)}:{kind:"action",text:s.t("tools.claude_code.env_foreign",t)})}t.machineLeft.length>0&&e.push({kind:"action",text:s.t("messages.env_vars_machine_left",{vars:t.machineLeft.join(", ")})});const n=o.getLastKept();n.length>0&&e.push({kind:"summary",text:s.t("tools.claude_code.kept_user_models",{values:n.join(", ")})}),"win32"!==process.platform||process.env.CLAUDE_CODE_GIT_BASH_PATH||0===j("where",["git"],{windowsHide:!0,stdio:"ignore"}).status||e.push({kind:"action",text:s.t("tools.claude_code.no_git_bash")}),claudeAccountLoginPresent()&&e.push({kind:"detail",text:s.t("tools.claude_code.account_login_overridden")});for(const t of A())e.push({kind:"action",text:s.t("tools.claude_code.managed_override",{source:t.source,keys:t.keys.join(", ")})});for(const t of o.getLastTierFallbacks())e.push({kind:"detail",text:s.t("tools.claude_code.tier_fallback",{tier:t.tier,from:t.from,to:t.to})});return e},backupPaths:()=>[H,L],forceResetPaths:()=>[H]};
@@ -13,7 +13,9 @@
13
13
  * - macOS: the .dmg is attached read-only, the app copied with `ditto` next to the target and swapped in with
14
14
  * two renames (the old bundle stays until the new one is in place). A new install goes to /Applications, or
15
15
  * ~/Applications when /Applications isn't writable for this user. Write access is checked before downloading.
16
- * - Windows: `Add-AppxPackage` (per user, no administrator).
16
+ * - Windows: `Add-AppxPackage` (per user). Windows refuses some first installs without an administrator
17
+ * (0x80073D28, 11-03 a customer's fresh Claude Desktop install; upgrades of the same package worked without):
18
+ * then, if `progress.elevate()` agrees, the downloaded package is installed once more through one UAC prompt.
17
19
  * - Not as root (sudo) on macOS, not as SYSTEM on Windows: the app would belong to the wrong account. Not over
18
20
  * SSH on Windows: a network logon can't deploy MSIX packages.
19
21
  */
@@ -83,6 +85,8 @@ export interface DesktopInstallProgress {
83
85
  percent?(percent: number): void;
84
86
  verifying?(): void;
85
87
  installing?(): void;
88
+ /** Windows asked for an administrator: true = install through a UAC prompt (asked / announced by the caller). */
89
+ elevate?(): Promise<boolean>;
86
90
  }
87
91
  export interface DesktopAppInstaller {
88
92
  mirrorRepo(): string | null;
@@ -1 +1 @@
1
- import{spawnSync as t}from"child_process";import{createHash as e}from"crypto";import{accessSync as r,constants as o,createReadStream as n,createWriteStream as s,existsSync as a,mkdirSync as i,mkdtempSync as c,readFileSync as l,renameSync as p,rmSync as u}from"fs";import{cpus as d,tmpdir as f}from"os";import{basename as m,dirname as g,join as w}from"path";import{Readable as h,Transform as $}from"stream";import{pipeline as S}from"stream/promises";import{logger as A}from"../../utils/logger.js";import{i18n as x}from"../i18n.js";import{powerShellEnv as y}from"../powershell-env.js";import{toolHome as E}from"./types.js";const v=(e,r,o={})=>{const n=t(e,r,{encoding:"utf-8",timeout:o.timeout??12e4,windowsHide:!0,input:o.input,stdio:[void 0===o.input?"ignore":"pipe","pipe","pipe"],maxBuffer:16777216,env:y()});return n.error&&A.logError(`desktop-app: ${e}`,n.error),{status:n.status,stdout:`${n.stdout??""}`,stderr:`${n.stderr??""}`}};let _=v,I=(...t)=>fetch(...t),k=null,P=null,b=null,C=null;export function setDesktopAppDepsForTests(t){void 0!==t.run&&(_=t.run??v),void 0!==t.fetch&&(I=t.fetch??((...t)=>fetch(...t))),void 0!==t.platform&&(k=t.platform),void 0!==t.arm64&&(P=t.arm64),void 0!==t.privileged&&(b=t.privileged),void 0!==t.remote&&(C=t.remote)}export function appPlatform(){return k??process.platform}export function isArm64Machine(){return null!==P?P:"arm64"===process.arch||("win32"===appPlatform()?"ARM64"===process.env.PROCESSOR_ARCHITECTURE||"ARM64"===process.env.PROCESSOR_ARCHITEW6432:"darwin"===appPlatform()&&/\bApple\b/.test(d()[0]?.model??""))}export class DesktopInstallError extends Error{constructor(t){super(t),this.name="DesktopInstallError"}}export const fail=(t,e={})=>{const r={};for(const[t,o]of Object.entries(e))r[t]=o.trim()||x.t("app_update.reason_unknown");throw new DesktopInstallError(x.t(`app_update.error_${t}`,r))};export function parseSha256Sums(t){const e=new Map;for(const r of t.split(/\r?\n/)){const t=/^([0-9a-f]{64})\s+\*?(\S.*)$/i.exec(r.trim());t&&e.set(t[2].trim(),t[1].toLowerCase())}return e}async function T(t,e){const r=await I(t,{signal:AbortSignal.timeout(e)});if(!r.ok)throw new Error(`${t}: HTTP ${r.status}`);return(await r.text()).trim()}function M(t,e){try{const r=l(w(t,"Contents","Info.plist"),"utf-8");return new RegExp(`<key>${e}</key>\\s*<string>([^<]*)</string>`).exec(r)?.[1]??null}catch{return null}}export function macBundleId(t){return M(t,"CFBundleIdentifier")}export function macAppVersion(t){return/^\d+\.\d+\.\d+/.exec(M(t,"CFBundleShortVersionString")??"")?.[0]??null}function R(t){try{return r(t,o.W_OK),!0}catch{return!1}}const O=t=>`'${t.replace(/'/g,"''")}'`;function j(t,e=12e4){return _("powershell.exe",["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command","[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; "+t],{timeout:e})}export function powerShellError(t){return t.replace(/#< CLIXML/g,"").replace(/_x000D__x000A_/g,"\n").replace(/<\/S>/g,"\n").replace(/<[^>]+>/g,"").replace(/_x[0-9A-F]{4}_/g,"").replace(/&apos;/g,"'").replace(/&quot;/g,'"').replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").split(/\r?\n/).map(t=>t.trim()).find(t=>t&&!/^(At line|At char|所在位置|\+|~|CategoryInfo|FullyQualifiedErrorId)/i.test(t))??""}export function createDesktopAppInstaller(t){const r=()=>t.mirror()?.replace(/\/-\/releases\/latest\/?$/,"")??null,o=()=>t.asset(appPlatform(),isArm64Machine()),l=()=>{const e=appPlatform();return"darwin"!==e&&"win32"!==e?"unsupported_platform":o()?r()?"darwin"===e&&(b??0===process.getuid?.())?"root":"win32"===e&&(null!==b?b:/\\system32\\config\\systemprofile/i.test(process.env.USERPROFILE??"")||!0===process.env.USERNAME?.endsWith("$"))?"system_account":"win32"===e&&(null!==C?C:Boolean(process.env.SSH_CONNECTION||process.env.SSH_CLIENT))?"remote_session":t.extraBlocker?.(e)??null:"no_mirror":"darwin"===e?"unsupported_arch":"unsupported_platform"},d=async(e=8e3)=>{const o=r();if(!o)throw new Error("no mirror");const n=t.versionFile(appPlatform(),isArm64Machine()),s=await T(`${o}/-/releases/latest/download/${n}`,e),a=/^(\d+\.\d+\.\d+)(\.\d+)?$/.exec(s)?.[1];if(!a)throw new Error(`unexpected ${n}: ${s.slice(0,40)}`);return a},y=()=>{for(const e of["/Applications",w(E(),"Applications")])for(const r of t.macApp.installedNames){const o=w(e,r);if(!a(w(o,"Contents","Info.plist")))continue;const n=macBundleId(o);if(null===n||n===t.macApp.bundleId)return o}return null},v=e=>{const r=_("codesign",["--verify","--deep","--strict",e],{timeout:6e5});0!==r.status&&fail("signature",{reason:(r.stderr||r.stdout).trim().split("\n")[0]||`codesign ${r.status}`});const o=_("codesign",["-dv",e]),n=`${o.stdout}\n${o.stderr}`,s=/^TeamIdentifier=(\S+)/m.exec(n)?.[1],a=/^Identifier=(\S+)/m.exec(n)?.[1];s===t.macApp.teamId&&a===t.macApp.bundleId||fail("signature",{reason:`TeamIdentifier=${s??"?"} Identifier=${a??"?"}`});const i=_("spctl",["-a","-t","exec","-vv",e],{timeout:3e5});0!==i.status&&fail("signature",{reason:(i.stderr||i.stdout).trim().split("\n")[0]||`spctl ${i.status}`})},k=()=>{const e=y();let r=e;if(!r){const e=R("/Applications")?"/Applications":w(E(),"Applications");r=w(e,t.macApp.installedNames[0])}const o=g(r);return(a(o)&&!R(o)||e&&!R(e))&&fail("no_permission",{path:r}),{target:r,existing:e}},P=e=>{const r=j(`$s = Get-AuthenticodeSignature -LiteralPath ${O(e)}; [pscustomobject]@{ status = [string]$s.Status; subject = [string]$s.SignerCertificate.Subject } | ConvertTo-Json -Compress`);let o={};try{o=JSON.parse(r.stdout.trim()||"{}")}catch{}if("Valid"!==o.status||!t.windows.signer.test(o.subject??"")){const t=o.status?`${o.status} ${o.subject??""}`:powerShellError(r.stderr)||powerShellError(r.stdout.trim().startsWith("{")?"":r.stdout)||`exit ${r.status}`;fail("signature",{reason:t.trim()})}},M=()=>{const e=j(`Get-AppxPackage | Where-Object { ${t.windows.packageFilter} } | ForEach-Object { $_.Version.ToString() }`,3e4);return/\d+\.\d+\.\d+/.exec(e.stdout)?.[0]??null};return{mirrorRepo:r,assetName:o,blocker:l,latestVersion:d,installedMacApp:y,windowsPackageVersion:M,verifyMacApp:v,verifyWindowsPackage:P,install:async(y={})=>{const E=l();E&&fail("blocked",{reason:x.t(`app_update.reason_${E}`)});const b=r(),C=o();let R;try{R=await d(15e3)}catch(t){fail("download",{reason:t instanceof Error?t.message:String(t)})}const N=t.releaseTag?`${b}/-/releases/download/${t.releaseTag(R)}`:`${b}/-/releases/latest/download`;let F;try{F=parseSha256Sums(await T(`${N}/SHA256SUMS`,15e3)).get(C)}catch(e){A.logError(`${t.id}: SHA256SUMS`,e)}F||fail("no_checksum",{file:C}),"darwin"===appPlatform()&&k();const H=c(w(f(),`${t.id}-`));try{const r=w(H,C);y.downloading?.(R),await async function(t,e,r){let o;try{o=await I(t,{signal:AbortSignal.timeout(18e5)})}catch(t){fail("download",{reason:t instanceof Error?t.message:String(t)})}o.ok&&o.body||fail("download",{reason:`HTTP ${o.status}`});const n=Number(o.headers.get("content-length"))||0;let a=0,i=-1;const c=new $({transform(t,e,o){a+=t.length;const s=n?Math.floor(100*a/n):-1;s>=0&&s!==i&&(i=s,r?.(s)),o(null,t)}});try{await S(h.fromWeb(o.body),c,s(e))}catch(t){u(e,{force:!0}),fail("download",{reason:t instanceof Error?t.message:String(t)})}}(`${N}/${C}`,r,y.percent),y.verifying?.();const o=await async function(t){const r=e("sha256");for await(const e of n(t))r.update(e);return r.digest("hex")}(r);return o!==F&&fail("checksum",{file:C,expected:F.slice(0,12),actual:o.slice(0,12)}),y.installing?.(),"darwin"===appPlatform()?await(async(e,r)=>{const o=w(r,"mnt");i(o,{recursive:!0});const n=_("hdiutil",["attach","-nobrowse","-readonly","-noautoopen","-mountpoint",o,e],{timeout:3e5,input:"Y\n"});0!==n.status&&fail("mount",{reason:(n.stderr||n.stdout).trim().split("\n").pop()??""});let s=null;try{const e=w(o,t.macApp.source);a(e)||fail("bad_package",{reason:t.macApp.source});const{target:r,existing:n}=k(),c=g(r),l=m(r);i(c,{recursive:!0}),s=w(c,`.${l}.${process.pid}.new`),u(s,{recursive:!0,force:!0});const d=_("ditto",[e,s],{timeout:9e5});0!==d.status&&fail("copy",{reason:(d.stderr||d.stdout).trim().split("\n")[0]??""}),v(s);const f=macAppVersion(s);f||fail("bad_package",{reason:"Info.plist"});const h=w(c,`.${l}.${process.pid}.old`);try{n&&p(n,h)}catch(t){throw["EPERM","EACCES"].includes(t.code??"")&&fail("app_management",{path:n}),t}try{p(s,r)}catch(t){throw n&&p(h,n),t}return s=null,u(h,{recursive:!0,force:!0}),{version:f,location:r}}finally{s&&u(s,{recursive:!0,force:!0}),_("hdiutil",["detach",o,"-force"],{timeout:6e4})}})(r,H):(t=>{P(t);const e=j(`$ErrorActionPreference = 'Stop'; Add-AppxPackage -Path ${O(t)} -ForceApplicationShutdown`,9e5);0!==e.status&&fail("install",{reason:powerShellError(e.stderr)||powerShellError(e.stdout)||`Add-AppxPackage ${e.status}`});const r=M();return r||fail("install",{reason:"Get-AppxPackage"}),{version:r,location:"MSIX"}})(r)}finally{u(H,{recursive:!0,force:!0})}}}}
1
+ import{spawnSync as t}from"child_process";import{createHash as e}from"crypto";import{accessSync as r,constants as o,createReadStream as n,createWriteStream as s,existsSync as a,mkdirSync as i,mkdtempSync as c,readFileSync as l,renameSync as p,rmSync as u}from"fs";import{cpus as d,tmpdir as f}from"os";import{basename as m,dirname as g,join as h}from"path";import{Readable as w,Transform as $}from"stream";import{pipeline as S}from"stream/promises";import{logger as A}from"../../utils/logger.js";import{i18n as x}from"../i18n.js";import{powerShellEnv as E}from"../powershell-env.js";import{toolHome as y}from"./types.js";const v=(e,r,o={})=>{const n=t(e,r,{encoding:"utf-8",timeout:o.timeout??12e4,windowsHide:!0,input:o.input,stdio:[void 0===o.input?"ignore":"pipe","pipe","pipe"],maxBuffer:16777216,env:E()});return n.error&&A.logError(`desktop-app: ${e}`,n.error),{status:n.status,stdout:`${n.stdout??""}`,stderr:`${n.stderr??""}`}};let P=v,_=(...t)=>fetch(...t),I=null,k=null,b=null,C=null;export function setDesktopAppDepsForTests(t){void 0!==t.run&&(P=t.run??v),void 0!==t.fetch&&(_=t.fetch??((...t)=>fetch(...t))),void 0!==t.platform&&(I=t.platform),void 0!==t.arm64&&(k=t.arm64),void 0!==t.privileged&&(b=t.privileged),void 0!==t.remote&&(C=t.remote)}export function appPlatform(){return I??process.platform}export function isArm64Machine(){return null!==k?k:"arm64"===process.arch||("win32"===appPlatform()?"ARM64"===process.env.PROCESSOR_ARCHITECTURE||"ARM64"===process.env.PROCESSOR_ARCHITEW6432:"darwin"===appPlatform()&&/\bApple\b/.test(d()[0]?.model??""))}export class DesktopInstallError extends Error{constructor(t){super(t),this.name="DesktopInstallError"}}export const fail=(t,e={})=>{const r={};for(const[t,o]of Object.entries(e))r[t]=o.trim()||x.t("app_update.reason_unknown");throw new DesktopInstallError(x.t(`app_update.error_${t}`,r))};export function parseSha256Sums(t){const e=new Map;for(const r of t.split(/\r?\n/)){const t=/^([0-9a-f]{64})\s+\*?(\S.*)$/i.exec(r.trim());t&&e.set(t[2].trim(),t[1].toLowerCase())}return e}async function T(t,e){const r=await _(t,{signal:AbortSignal.timeout(e)});if(!r.ok)throw new Error(`${t}: HTTP ${r.status}`);return(await r.text()).trim()}function M(t,e){try{const r=l(h(t,"Contents","Info.plist"),"utf-8");return new RegExp(`<key>${e}</key>\\s*<string>([^<]*)</string>`).exec(r)?.[1]??null}catch{return null}}export function macBundleId(t){return M(t,"CFBundleIdentifier")}export function macAppVersion(t){return/^\d+\.\d+\.\d+/.exec(M(t,"CFBundleShortVersionString")??"")?.[0]??null}function R(t){try{return r(t,o.W_OK),!0}catch{return!1}}const F=t=>`'${t.replace(/'/g,"''")}'`;function O(t,e=12e4){return P("powershell.exe",["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command","[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; "+t],{timeout:e})}export function powerShellError(t){return t.replace(/#< CLIXML/g,"").replace(/_x000D__x000A_/g,"\n").replace(/<\/S>/g,"\n").replace(/<[^>]+>/g,"").replace(/_x[0-9A-F]{4}_/g,"").replace(/&apos;/g,"'").replace(/&quot;/g,'"').replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").split(/\r?\n/).map(t=>t.trim()).find(t=>t&&!/^(At line|At char|所在位置|\+|~|CategoryInfo|FullyQualifiedErrorId)/i.test(t))??""}export function createDesktopAppInstaller(t){const r=()=>t.mirror()?.replace(/\/-\/releases\/latest\/?$/,"")??null,o=()=>t.asset(appPlatform(),isArm64Machine()),d=()=>{const e=appPlatform();return"darwin"!==e&&"win32"!==e?"unsupported_platform":o()?r()?"darwin"===e&&(b??0===process.getuid?.())?"root":"win32"===e&&(null!==b?b:/\\system32\\config\\systemprofile/i.test(process.env.USERPROFILE??"")||!0===process.env.USERNAME?.endsWith("$"))?"system_account":"win32"===e&&(null!==C?C:Boolean(process.env.SSH_CONNECTION||process.env.SSH_CLIENT))?"remote_session":t.extraBlocker?.(e)??null:"no_mirror":"darwin"===e?"unsupported_arch":"unsupported_platform"},E=async(e=8e3)=>{const o=r();if(!o)throw new Error("no mirror");const n=t.versionFile(appPlatform(),isArm64Machine()),s=await T(`${o}/-/releases/latest/download/${n}`,e),a=/^(\d+\.\d+\.\d+)(\.\d+)?$/.exec(s)?.[1];if(!a)throw new Error(`unexpected ${n}: ${s.slice(0,40)}`);return a},v=()=>{for(const e of["/Applications",h(y(),"Applications")])for(const r of t.macApp.installedNames){const o=h(e,r);if(!a(h(o,"Contents","Info.plist")))continue;const n=macBundleId(o);if(null===n||n===t.macApp.bundleId)return o}return null},I=e=>{const r=P("codesign",["--verify","--deep","--strict",e],{timeout:6e5});0!==r.status&&fail("signature",{reason:(r.stderr||r.stdout).trim().split("\n")[0]||`codesign ${r.status}`});const o=P("codesign",["-dv",e]),n=`${o.stdout}\n${o.stderr}`,s=/^TeamIdentifier=(\S+)/m.exec(n)?.[1],a=/^Identifier=(\S+)/m.exec(n)?.[1];s===t.macApp.teamId&&a===t.macApp.bundleId||fail("signature",{reason:`TeamIdentifier=${s??"?"} Identifier=${a??"?"}`});const i=P("spctl",["-a","-t","exec","-vv",e],{timeout:3e5});0!==i.status&&fail("signature",{reason:(i.stderr||i.stdout).trim().split("\n")[0]||`spctl ${i.status}`})},k=()=>{const e=v();let r=e;if(!r){const e=R("/Applications")?"/Applications":h(y(),"Applications");r=h(e,t.macApp.installedNames[0])}const o=g(r);return(a(o)&&!R(o)||e&&!R(e))&&fail("no_permission",{path:r}),{target:r,existing:e}},M=e=>{const r=O(`$s = Get-AuthenticodeSignature -LiteralPath ${F(e)}; [pscustomobject]@{ status = [string]$s.Status; subject = [string]$s.SignerCertificate.Subject } | ConvertTo-Json -Compress`);let o={};try{o=JSON.parse(r.stdout.trim()||"{}")}catch{}if("Valid"!==o.status||!t.windows.signer.test(o.subject??"")){const t=o.status?`${o.status} ${o.subject??""}`:powerShellError(r.stderr)||powerShellError(r.stdout.trim().startsWith("{")?"":r.stdout)||`exit ${r.status}`;fail("signature",{reason:t.trim()})}},N=()=>{const e=O(`Get-AppxPackage | Where-Object { ${t.windows.packageFilter} } | ForEach-Object { $_.Version.ToString() }`,3e4);return/\d+\.\d+\.\d+/.exec(e.stdout)?.[0]??null};return{mirrorRepo:r,assetName:o,blocker:d,latestVersion:E,installedMacApp:v,windowsPackageVersion:N,verifyMacApp:I,verifyWindowsPackage:M,install:async(y={})=>{const v=d();v&&fail("blocked",{reason:x.t(`app_update.reason_${v}`)});const b=r(),C=o();let R;try{R=await E(15e3)}catch(t){fail("download",{reason:t instanceof Error?t.message:String(t)})}const j=t.releaseTag?`${b}/-/releases/download/${t.releaseTag(R)}`:`${b}/-/releases/latest/download`;let B;try{B=parseSha256Sums(await T(`${j}/SHA256SUMS`,15e3)).get(C)}catch(e){A.logError(`${t.id}: SHA256SUMS`,e)}B||fail("no_checksum",{file:C}),"darwin"===appPlatform()&&k();const H=c(h(f(),`${t.id}-`));try{const r=h(H,C);y.downloading?.(R),await async function(t,e,r){let o;try{o=await _(t,{signal:AbortSignal.timeout(18e5)})}catch(t){fail("download",{reason:t instanceof Error?t.message:String(t)})}o.ok&&o.body||fail("download",{reason:`HTTP ${o.status}`});const n=Number(o.headers.get("content-length"))||0;let a=0,i=-1;const c=new $({transform(t,e,o){a+=t.length;const s=n?Math.floor(100*a/n):-1;s>=0&&s!==i&&(i=s,r?.(s)),o(null,t)}});try{await S(w.fromWeb(o.body),c,s(e))}catch(t){u(e,{force:!0}),fail("download",{reason:t instanceof Error?t.message:String(t)})}}(`${j}/${C}`,r,y.percent),y.verifying?.();const o=await async function(t){const r=e("sha256");for await(const e of n(t))r.update(e);return r.digest("hex")}(r);return o!==B&&fail("checksum",{file:C,expected:B.slice(0,12),actual:o.slice(0,12)}),y.installing?.(),"darwin"===appPlatform()?await(async(e,r)=>{const o=h(r,"mnt");i(o,{recursive:!0});const n=P("hdiutil",["attach","-nobrowse","-readonly","-noautoopen","-mountpoint",o,e],{timeout:3e5,input:"Y\n"});0!==n.status&&fail("mount",{reason:(n.stderr||n.stdout).trim().split("\n").pop()??""});let s=null;try{const e=h(o,t.macApp.source);a(e)||fail("bad_package",{reason:t.macApp.source});const{target:r,existing:n}=k(),c=g(r),l=m(r);i(c,{recursive:!0}),s=h(c,`.${l}.${process.pid}.new`),u(s,{recursive:!0,force:!0});const d=P("ditto",[e,s],{timeout:9e5});0!==d.status&&fail("copy",{reason:(d.stderr||d.stdout).trim().split("\n")[0]??""}),I(s);const f=macAppVersion(s);f||fail("bad_package",{reason:"Info.plist"});const w=h(c,`.${l}.${process.pid}.old`);try{n&&p(n,w)}catch(t){throw["EPERM","EACCES"].includes(t.code??"")&&fail("app_management",{path:n}),t}try{p(s,r)}catch(t){throw n&&p(w,n),t}return s=null,u(w,{recursive:!0,force:!0}),{version:f,location:r}}finally{s&&u(s,{recursive:!0,force:!0}),P("hdiutil",["detach",o,"-force"],{timeout:6e4})}})(r,H):await(async(t,e)=>{M(t);const r=O(`$ErrorActionPreference = 'Stop'; Add-AppxPackage -Path ${F(t)} -ForceApplicationShutdown`,9e5);if(0!==r.status){const o=powerShellError(r.stderr)||powerShellError(r.stdout)||`Add-AppxPackage ${r.status}`;/0x80073D28/i.test(`${r.stderr}\n${r.stdout}`)||fail("install",{reason:o}),await(e.elevate?.())||fail("needs_admin");const n=(t=>{const e=h(g(t),"elevated-install.log"),r=`$ErrorActionPreference = 'Stop'; try { Add-AppxPackage -Path ${F(t)} -ForceApplicationShutdown; exit 0 } catch { [IO.File]::WriteAllText(${F(e)}, $_.Exception.Message, [Text.Encoding]::UTF8); exit 1 }`,o=O(`$ErrorActionPreference = 'Stop'; $p = Start-Process -FilePath 'powershell.exe' -ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-EncodedCommand', '${Buffer.from(r,"utf16le").toString("base64")}') -Verb RunAs -Wait -PassThru -WindowStyle Hidden; exit $p.ExitCode`,12e5);if(0===o.status)return null;let n="";try{n=l(e,"utf-8").trim()}catch{}return n||powerShellError(o.stderr)||powerShellError(o.stdout)||`exit ${o.status}`})(t);n&&fail("install",{reason:n}),N()||fail("other_account")}const o=N();return o||fail("install",{reason:"Get-AppxPackage"}),{version:o,location:"MSIX"}})(r,y)}finally{u(H,{recursive:!0,force:!0})}}}}
@@ -100,6 +100,8 @@ export interface AppInstaller {
100
100
  percent(percent: number): void;
101
101
  verifying(): void;
102
102
  installing(): void;
103
+ /** Windows wants an administrator for this install: true = go ahead with a UAC prompt. */
104
+ elevate?(): Promise<boolean>;
103
105
  }): Promise<{
104
106
  version: string;
105
107
  location: string;
@@ -427,6 +427,9 @@
427
427
  "plan_env_remove": "Remove {{vars}} pointing at this site from {{location}} (backed up first)",
428
428
  "env_removed": "Removed {{vars}} pointing at this site from {{location}}; new terminals pick this up (backed up)",
429
429
  "env_foreign": "{{vars}} in {{location}} point at another service and override Claude Code's settings; {{product}} left them alone. To use {{brand}}, remove them yourself and open a new terminal",
430
+ "env_foreign_found": "{{vars}} in {{location}} point at another service and override Claude Code's settings",
431
+ "env_foreign_offer": "Remove the environment variables pointing at another service, {{where}}? Claude Code uses {{brand}} only without them (they are backed up first)",
432
+ "env_removed_foreign": "Removed {{vars}} from {{location}} (backed up); open a new terminal for it to take effect",
430
433
  "plan_replace_provider": "Replace Claude Code's current endpoint {{url}} (not written by {{product}})",
431
434
  "provider_replaced": "Replaced the previous endpoint {{url}}; the old file is backed up",
432
435
  "gateway_models": "{{count}} more models added to /model ({{vendors}})",
@@ -1245,6 +1248,10 @@
1245
1248
  "reinstalled": "Reinstalled {{tool}} {{version}}",
1246
1249
  "force_hint": "To reinstall it, run {{command}} --force",
1247
1250
  "blocked_remote_session": "This is a remote (SSH) session, where Windows doesn't allow installing {{tool}}: run {{command}} in a terminal on this computer",
1248
- "reason_remote_session": "Windows apps can't be installed from a remote (SSH) session"
1251
+ "reason_remote_session": "Windows apps can't be installed from a remote (SSH) session",
1252
+ "error_needs_admin": "Windows requires administrator rights for this install (0x80073D28); right-click PowerShell, choose \"Run as administrator\" and run it there",
1253
+ "error_other_account": "the prompt was approved with another administrator account, so the app was installed for that account: approve with the current account (make it an administrator), or use the app from that account",
1254
+ "elevate_offer": "Windows requires administrator rights to install {{tool}}. Show the permission prompt now?",
1255
+ "elevating": "Requesting administrator rights: click Yes in the Windows prompt…"
1249
1256
  }
1250
1257
  }
@@ -427,6 +427,9 @@
427
427
  "plan_env_remove": "删除 {{location}} 里指向本站的 {{vars}}(先备份)",
428
428
  "env_removed": "已删除 {{location}} 里指向本站的 {{vars}},新开的终端生效(已备份)",
429
429
  "env_foreign": "{{location}} 里的 {{vars}} 指向别的服务,会盖过 Claude Code 的配置,{{product}} 没有改它;要用 {{brand}},请自己删掉后重新打开终端",
430
+ "env_foreign_found": "{{location}} 里的 {{vars}} 指向别的服务,会盖过 Claude Code 的配置",
431
+ "env_foreign_offer": "删掉指向别的服务的环境变量 {{where}}?删掉后 Claude Code 才会用 {{brand}}(会先备份)",
432
+ "env_removed_foreign": "已删除 {{location}} 里的 {{vars}}(已备份),重新打开终端后生效",
430
433
  "plan_replace_provider": "替换 Claude Code 现在的接入地址 {{url}}(不是 {{product}} 写的)",
431
434
  "provider_replaced": "已替换原来的接入地址 {{url}},修改前的文件已备份",
432
435
  "gateway_models": "/model 菜单新增 {{count}} 个其他模型({{vendors}})",
@@ -1245,6 +1248,10 @@
1245
1248
  "reinstalled": "已重新安装 {{tool}} {{version}}",
1246
1249
  "force_hint": "要重新安装就运行 {{command}} --force",
1247
1250
  "blocked_remote_session": "这是远程(SSH)登录的会话,Windows 不允许在这里安装 {{tool}}:在这台电脑本机的终端里运行 {{command}}",
1248
- "reason_remote_session": "远程(SSH)会话里不能安装 Windows 应用"
1251
+ "reason_remote_session": "远程(SSH)会话里不能安装 Windows 应用",
1252
+ "error_needs_admin": "Windows 要求用管理员权限安装(0x80073D28),先右键 PowerShell 选「以管理员身份运行」,在那个窗口里运行",
1253
+ "error_other_account": "授权时用的是另一个管理员账号,应用装给了那个账号:用当前账号授权(把当前账号设为管理员),或在那个账号下使用",
1254
+ "elevate_offer": "Windows 要求用管理员权限安装 {{tool}}。现在弹出授权窗口?",
1255
+ "elevating": "正在请求管理员权限:在弹出的 Windows 窗口里点「是」…"
1249
1256
  }
1250
1257
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeapi/cli",
3
- "version": "0.0.150",
3
+ "version": "0.0.151",
4
4
  "description": "CLI tool for managing AI coding assistants (Claude Code, Codex, OpenClaw, Hermes, AtomCode, Grok Build) with one unified config",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",