@marsapi/cli 0.0.147 → 0.0.148

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{spawn as t,spawnSync as e}from"child_process";import{rmSync as o}from"fs";import{join as r}from"path";import n from"chalk";import i from"inquirer";import{i18n as a}from"./i18n.js";import{logger as s}from"../utils/logger.js";import{compareVersions as l,getToolMinVersion as c}from"./model-registry.js";import{getAdapter as p}from"./tools/registry.js";import{findInstalls as u,forgetInstalls as m,installLabel as d,npmMirrorInstallCommand as g,npmMirrorVersion as f,npmUninstallCommand as w}from"./tools/tool-installs.js";import{toolHome as y}from"./tools/types.js";import{isNonInteractive as h,shouldAutoConfirm as _}from"./runtime-options.js";import{track as v}from"./telemetry.js";let k="ok",b=async(t,o,r={})=>(console.log(n.gray("$ ")+[t,...o].join(" ")),k=r.idleMs?await runWatched(t,o,r):function(t,o,r){const n=$(t)?e(T(t,o),{stdio:"inherit",shell:!0,timeout:r}):e(t,o,{stdio:"inherit",timeout:r});return n.error&&s.logError(`upgrade: ${t}`,n.error),"ETIMEDOUT"===n.error?.code?"timeout":0===n.status?"ok":"fail"}(t,o,r.timeoutMs),"ok"===k);const $=t=>"win32"===process.platform&&!/\.exe$/i.test(t),T=(t,e)=>[t,...e].map(t=>/\s/.test(t)?`"${t}"`:t).join(" ");export function runWatched(e,o,r){return new Promise(n=>{const i=$(e)?t(T(e,o),{stdio:["inherit","pipe","pipe"],shell:!0}):t(e,o,{stdio:["inherit","pipe","pipe"]});let a;const l=t=>{a=t,i.kill()};let c;const p=()=>{clearTimeout(c),r.idleMs&&(c=setTimeout(()=>l("stalled"),r.idleMs))},u=r.timeoutMs?setTimeout(()=>l("timeout"),r.timeoutMs):void 0;p(),i.stdout?.on("data",t=>{process.stdout.write(t),p()}),i.stderr?.on("data",t=>{process.stderr.write(t),p()});const m=t=>{clearTimeout(c),clearTimeout(u),n(t)};i.on("error",t=>{s.logError(`upgrade: ${e}`,t),m(a??"fail")}),i.on("close",t=>{a&&process.stdout.write("\n"),m(a??(0===t?"ok":"fail"))})})}export function setUpgradeRunnerForTests(t){b=async(e,o,r)=>{const n=await t(e,o,r);return k="string"==typeof n?n:n?"ok":"fail","ok"===k}}const j={ok:"install.script_failed_npm",fail:"install.script_failed_npm",stalled:"install.script_stalled_npm",timeout:"install.script_timeout_npm"};export async function mirrorInstall(t){if(!t.mirrorScript)return M(t);console.log(n.gray(a.t("install.downloading")));const e=`install-script:${t.command}`,o=Date.now();v(e,"start");const r={idleMs:18e4,timeoutMs:36e5},i="win32"===process.platform?await b("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",`irm ${t.mirrorScript.ps1} -TimeoutSec 30 | iex`],r):await b("sh",["-c",`script=$(curl -fsSL --connect-timeout 15 --max-time 60 ${t.mirrorScript.sh}) && printf '%s\\n' "$script" | sh`],r),s=k;return v(e,"stalled"===s?"timeout":s,{duration_ms:Date.now()-o,..."stalled"===s||"timeout"===s?{detail:{reason:s}}:{}}),i||!t.npmPackage?i:(console.log(n.yellow(" ! "+a.t(j[s],{minutes:String(3)}))),v(e,"fallback"),M(t))}async function M(t){const e=g(t,await f(t)),[o,...r]=e.split(" "),i=`install-npm:${t.command}`,s=Date.now();v(i,"start");const l=await b(o,r);return v(i,l?"ok":"fail",{duration_ms:Date.now()-s}),l||"win32"===process.platform||console.log(n.yellow(" ! "+a.t("upgrade.npm_permission",{command:e}))),l}async function D(t,e){switch(e.kind){case"npm":t.npmPackage&&await b("npm",["uninstall","-g",t.npmPackage]);break;case"brew":t.brew&&await b("brew",["uninstall",t.brew]);break;case"native":try{o(e.path,{force:!0});for(const e of t.native?.dataDirs??[])o(r(y(),...e),{recursive:!0,force:!0})}catch(t){s.logError("upgrade: remove native copy",t)}break;default:return!1}return m(),!u(t).some(t=>t.path===e.path)}function x(t,e){switch(e.kind){case"npm":return w(t);case"brew":return`brew uninstall ${t.brew}`;case"native":return a.t("upgrade.delete_paths",{paths:[e.path,...(t.native?.dataDirs??[]).map(t=>r(y(),...t))].join("、")});default:return a.t("upgrade.delete_paths",{paths:e.path})}}export async function upgradeTool(t){const e=Date.now();v(`upgrade:${t}`,"start");try{const o=await async function(t){const e=p(t),o=e?.installSpec;if(!e||!o)throw new Error(a.t("upgrade.unsupported",{tool:t}));const r=e.displayName;m();const g=u(o);if(console.log(n.bold(`\n${r}`)),0===g.length)console.log(a.t("upgrade.not_installed_installing",{tool:r})),await mirrorInstall(o);else{const t=g[0];console.log(n.gray(" "+a.t("upgrade.current",{copy:d(t)})));const e=await async function(t,e){switch(e.kind){case"native":return b(e.path,t.native?.updateArgs??["update"],{timeoutMs:t.native?.updateTimeoutMs});case"npm":return M(t);case"brew":return!!t.brew&&b("brew",["upgrade",t.brew]);default:return!1}}(o,t);e||"other"!==t.kind?e||"npm"===t.kind||"native"===t.kind&&await async function(t){const e=t.native?.mirrorUpdate;if(!e)return!1;console.log(n.yellow(" ! "+a.t("upgrade.native_mirror_trying")));try{const{version:t,manifestVerified:o}=await e();return console.log(n.green(" √ "+a.t(o?"upgrade.native_mirror_done_verified":"upgrade.native_mirror_done",{version:t}))),!0}catch(t){return s.logError("upgrade: native mirror",t),console.log(n.yellow(" ! "+a.t("upgrade.native_mirror_failed",{reason:t instanceof Error?t.message:String(t)}))),!1}}(o)||(console.log(n.yellow(" ! "+a.t("upgrade.fallback_mirror"))),await mirrorInstall(o)):console.log(n.yellow(" ! "+a.t("upgrade.unknown_install",{path:t.path})))}m(),await async function(t,e){const o=u(t);if(o.length<2)return;const r=function(t){return t.reduce((t,e)=>e.version&&(!t.version||l(e.version,t.version)>0)?e:t)}(o),s=o.filter(t=>t!==r);console.log(n.yellow(" ! "+a.t("upgrade.duplicates",{tool:e,keep:d(r),others:s.map(d).join("、")})));let c=_();c||h()||!process.stdin.isTTY||(c=(await i.prompt([{type:"confirm",name:"remove",message:a.t("upgrade.confirm_remove"),default:!0}])).remove);for(const e of s)c&&await D(t,e)?console.log(n.green(" √ "+a.t("upgrade.removed",{copy:d(e)}))):console.log(n.yellow(" ! "+a.t("upgrade.remove_by_hand",{how:x(t,e)})))}(o,r),m();const f=u(o)[0];if(!f)return console.log(n.red(" × "+a.t("upgrade.still_missing",{tool:r}))),!1;const w=c(t);if(w&&f.version&&l(f.version,w)<0){console.log(n.yellow(" ! "+a.t("upgrade.still_old",{copy:d(f),min:w})));for(const t of e.upgradeHints?.(w)??[])console.log(n.yellow(" ! "+t));return!1}return console.log(n.green(" √ "+a.t("upgrade.done",{copy:d(f)}))),!0}(t);return v(`upgrade:${t}`,o?"ok":"fail",{duration_ms:Date.now()-e}),o}catch(o){throw v(`upgrade:${t}`,"fail",{duration_ms:Date.now()-e,error:o}),o}}
1
+ import{spawn as t,spawnSync as e}from"child_process";import{rmSync as o}from"fs";import{join as r}from"path";import n from"chalk";import i from"inquirer";import{i18n as s}from"./i18n.js";import{logger as a}from"../utils/logger.js";import{compareVersions as l,getToolMinVersion as c}from"./model-registry.js";import{getAdapter as p}from"./tools/registry.js";import{findInstalls as u,forgetInstalls as m,installLabel as d,npmMirrorInstallCommand as g,npmMirrorVersion as f,npmUninstallCommand as w}from"./tools/tool-installs.js";import{toolHome as h}from"./tools/types.js";import{isNonInteractive as y,shouldAutoConfirm as v}from"./runtime-options.js";import{track as _}from"./telemetry.js";import{isWindowsPowerShell as k,powerShellEnv as b}from"./powershell-env.js";let $="ok",j=async(t,o,r={})=>(console.log(n.gray("$ ")+[t,...o].join(" ")),$=r.idleMs?await runWatched(t,o,r):function(t,o,r){const n=T(t)?e(D(t,o),{stdio:"inherit",shell:!0,timeout:r}):e(t,o,{stdio:"inherit",timeout:r,env:M(t)});return n.error&&a.logError(`upgrade: ${t}`,n.error),"ETIMEDOUT"===n.error?.code?"timeout":0===n.status?"ok":"fail"}(t,o,r.timeoutMs),"ok"===$);const T=t=>"win32"===process.platform&&!/\.exe$/i.test(t),M=t=>k(t)?b():process.env,D=(t,e)=>[t,...e].map(t=>/\s/.test(t)?`"${t}"`:t).join(" ");export function runWatched(e,o,r){return new Promise(n=>{const i=T(e)?t(D(e,o),{stdio:["inherit","pipe","pipe"],shell:!0}):t(e,o,{stdio:["inherit","pipe","pipe"],env:M(e)});let s;const l=t=>{s=t,i.kill()};let c;const p=()=>{clearTimeout(c),r.idleMs&&(c=setTimeout(()=>l("stalled"),r.idleMs))},u=r.timeoutMs?setTimeout(()=>l("timeout"),r.timeoutMs):void 0;p(),i.stdout?.on("data",t=>{process.stdout.write(t),p()}),i.stderr?.on("data",t=>{process.stderr.write(t),p()});const m=t=>{clearTimeout(c),clearTimeout(u),n(t)};i.on("error",t=>{a.logError(`upgrade: ${e}`,t),m(s??"fail")}),i.on("close",t=>{s&&process.stdout.write("\n"),m(s??(0===t?"ok":"fail"))})})}export function setUpgradeRunnerForTests(t){j=async(e,o,r)=>{const n=await t(e,o,r);return $="string"==typeof n?n:n?"ok":"fail","ok"===$}}const x={ok:"install.script_failed_npm",fail:"install.script_failed_npm",stalled:"install.script_stalled_npm",timeout:"install.script_timeout_npm"};export async function mirrorInstall(t){if(!t.mirrorScript)return E(t);console.log(n.gray(s.t("install.downloading")));const e=`install-script:${t.command}`,o=Date.now();_(e,"start");const r={idleMs:18e4,timeoutMs:36e5},i="win32"===process.platform?await j("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",`irm ${t.mirrorScript.ps1} -TimeoutSec 30 | iex`],r):await j("sh",["-c",`script=$(curl -fsSL --connect-timeout 15 --max-time 60 ${t.mirrorScript.sh}) && printf '%s\\n' "$script" | sh`],r),a=$;return _(e,"stalled"===a?"timeout":a,{duration_ms:Date.now()-o,..."stalled"===a||"timeout"===a?{detail:{reason:a}}:{}}),i||!t.npmPackage?i:(console.log(n.yellow(" ! "+s.t(x[a],{minutes:String(3)}))),_(e,"fallback"),E(t))}async function E(t){const e=g(t,await f(t)),[o,...r]=e.split(" "),i=`install-npm:${t.command}`,a=Date.now();_(i,"start");const l=await j(o,r);return _(i,l?"ok":"fail",{duration_ms:Date.now()-a}),l||"win32"===process.platform||console.log(n.yellow(" ! "+s.t("upgrade.npm_permission",{command:e}))),l}async function S(t,e){switch(e.kind){case"npm":t.npmPackage&&await j("npm",["uninstall","-g",t.npmPackage]);break;case"brew":t.brew&&await j("brew",["uninstall",t.brew]);break;case"native":try{o(e.path,{force:!0});for(const e of t.native?.dataDirs??[])o(r(h(),...e),{recursive:!0,force:!0})}catch(t){a.logError("upgrade: remove native copy",t)}break;default:return!1}return m(),!u(t).some(t=>t.path===e.path)}function P(t,e){switch(e.kind){case"npm":return w(t);case"brew":return`brew uninstall ${t.brew}`;case"native":return s.t("upgrade.delete_paths",{paths:[e.path,...(t.native?.dataDirs??[]).map(t=>r(h(),...t))].join("、")});default:return s.t("upgrade.delete_paths",{paths:e.path})}}export async function upgradeTool(t){const e=Date.now();_(`upgrade:${t}`,"start");try{const o=await async function(t){const e=p(t),o=e?.installSpec;if(!e||!o)throw new Error(s.t("upgrade.unsupported",{tool:t}));const r=e.displayName;m();const g=u(o);if(console.log(n.bold(`\n${r}`)),0===g.length)console.log(s.t("upgrade.not_installed_installing",{tool:r})),await mirrorInstall(o);else{const t=g[0];console.log(n.gray(" "+s.t("upgrade.current",{copy:d(t)})));const e=await async function(t,e){switch(e.kind){case"native":return j(e.path,t.native?.updateArgs??["update"],{timeoutMs:t.native?.updateTimeoutMs});case"npm":return E(t);case"brew":return!!t.brew&&j("brew",["upgrade",t.brew]);default:return!1}}(o,t);e||"other"!==t.kind?e||"npm"===t.kind||"native"===t.kind&&await async function(t){const e=t.native?.mirrorUpdate;if(!e)return!1;console.log(n.yellow(" ! "+s.t("upgrade.native_mirror_trying")));try{const{version:t,manifestVerified:o}=await e();return console.log(n.green(" √ "+s.t(o?"upgrade.native_mirror_done_verified":"upgrade.native_mirror_done",{version:t}))),!0}catch(t){return a.logError("upgrade: native mirror",t),console.log(n.yellow(" ! "+s.t("upgrade.native_mirror_failed",{reason:t instanceof Error?t.message:String(t)}))),!1}}(o)||(console.log(n.yellow(" ! "+s.t("upgrade.fallback_mirror"))),await mirrorInstall(o)):console.log(n.yellow(" ! "+s.t("upgrade.unknown_install",{path:t.path})))}m(),await async function(t,e){const o=u(t);if(o.length<2)return;const r=function(t){return t.reduce((t,e)=>e.version&&(!t.version||l(e.version,t.version)>0)?e:t)}(o),a=o.filter(t=>t!==r);console.log(n.yellow(" ! "+s.t("upgrade.duplicates",{tool:e,keep:d(r),others:a.map(d).join("、")})));let c=v();c||y()||!process.stdin.isTTY||(c=(await i.prompt([{type:"confirm",name:"remove",message:s.t("upgrade.confirm_remove"),default:!0}])).remove);for(const e of a)c&&await S(t,e)?console.log(n.green(" √ "+s.t("upgrade.removed",{copy:d(e)}))):console.log(n.yellow(" ! "+s.t("upgrade.remove_by_hand",{how:P(t,e)})))}(o,r),m();const f=u(o)[0];if(!f)return console.log(n.red(" × "+s.t("upgrade.still_missing",{tool:r}))),!1;const w=c(t);if(w&&f.version&&l(f.version,w)<0){console.log(n.yellow(" ! "+s.t("upgrade.still_old",{copy:d(f),min:w})));for(const t of e.upgradeHints?.(w)??[])console.log(n.yellow(" ! "+t));return!1}return console.log(n.green(" √ "+s.t("upgrade.done",{copy:d(f)}))),!0}(t);return _(`upgrade:${t}`,o?"ok":"fail",{duration_ms:Date.now()-e}),o}catch(o){throw _(`upgrade:${t}`,"fail",{duration_ms:Date.now()-e,error:o}),o}}
@@ -0,0 +1 @@
1
+ import{spawnSync as t}from"child_process";import{logger as n}from"../../utils/logger.js";import{brand as e}from"../brand.js";import{powerShellEnv as o}from"../powershell-env.js";import{existsSync as r}from"fs";import{join as i}from"path";import{appPlatform as a,createDesktopAppInstaller as s,isArm64Machine as p,macAppVersion as l,macBundleId as c}from"./desktop-app-installer.js";import{toolHome as u}from"./types.js";export const OPENAI_TEAM_ID="2DC432GLL2";const d="com.openai.codex";export const CHATGPT_PACKAGE_FAMILY="OpenAI.Codex_2p2nqsd0c76g0";const g=s({id:"chatgpt-desktop",mirror:()=>e().installMirror?.chatgptDesktop,asset:(t,n)=>"darwin"===t?n?"ChatGPT-mac-arm64.dmg":null:"win32"===t?n?"ChatGPT-win-arm64.msix":"ChatGPT-win-x64.msix":null,versionFile:(t,n)=>"win32"===t?`version-win-${n?"arm64":"x64"}.txt`:"version.txt",macApp:{source:"ChatGPT.app",installedNames:["ChatGPT.app","Codex.app"],bundleId:d,teamId:"2DC432GLL2"},windows:{signer:new RegExp("^CN=50BDFD77-8903-4850-9FFE-6E8522F64D5B$"),packageFilter:`$_.PackageFamilyName -eq '${CHATGPT_PACKAGE_FAMILY}'`},extraBlocker:t=>"darwin"===t&&!g.installedMacApp()&&["/Applications",i(u(),"Applications")].some(t=>{const n=i(t,"ChatGPT.app");return r(i(n,"Contents","Info.plist"))&&c(n)!==d})?"other_app":null});export const chatgptInstaller=g;let h=(e,r,i=3e4)=>{const a=t(e,r,{encoding:"utf-8",timeout:i,windowsHide:!0,stdio:["ignore","pipe","pipe"],env:o()});return a.error&&n.logError(`chatgpt-desktop: ${e}`,a.error),{status:a.status,stdout:`${a.stdout??""}`}};export function setChatgptProcessRunnerForTests(t){h=t}function m(t,n){return h("powershell.exe",["-NoProfile","-NonInteractive","-Command",t],n)}const C=t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),w="Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Path -like '*\\WindowsApps\\OpenAI.Codex_*\\app\\ChatGPT.exe' }";function A(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}export function isChatgptRunning(){if("darwin"===a()){const t=g.installedMacApp();return Boolean(t)&&0===h("pgrep",["-f",`^${C(t)}/Contents/MacOS/`]).status}return"win32"===a()&&Number(m(`@(${w}).Count`).stdout.trim())>0}export function quitChatgpt(){if("darwin"===a()){const t=g.installedMacApp();h("osascript",["-e",`tell application id "${d}" to quit`]);for(let t=0;t<30&&isChatgptRunning();t++)A(500);t&&isChatgptRunning()&&h("pkill",["-f",`^${C(t)}/Contents/MacOS/`]),A(1e3)}else{if("win32"!==a())return!1;m([`$p = @(${w})`,"$p | ForEach-Object { [void]$_.CloseMainWindow() }","Start-Sleep -Seconds 3",`@(${w}) | Stop-Process -Force -ErrorAction SilentlyContinue`,"Start-Sleep -Seconds 1"].join("\n"),6e4)}return!isChatgptRunning()}export function launchChatgpt(){if("darwin"===a()){const t=g.installedMacApp();if(!t)return!1;h("open",[t])}else{if("win32"!==a())return!1;m(`Start-Process 'shell:AppsFolder\\${CHATGPT_PACKAGE_FAMILY}!App'`,6e4)}for(let t=0;t<20;t++){if(isChatgptRunning())return!0;A(500)}return!1}export const chatgptDesktopApp={name:"chatgpt",displayName:"ChatGPT",installedVersion:function(){if("darwin"===a()){const t=g.installedMacApp();return t?l(t):null}return"win32"===a()?g.windowsPackageVersion():null},runningApp:{isRunning:isChatgptRunning,quit:quitChatgpt,launch:launchChatgpt},appInstaller:{vendor:"OpenAI",sizeMb:()=>"darwin"===a()?800:p()?1050:1e3,downloadPage:"https://chatgpt.com/download",blocker:g.blocker,latestVersion:()=>g.latestVersion(),installedPath:()=>"darwin"===a()?g.installedMacApp():"win32"!==a()?null:g.windowsPackageVersion()?"MSIX":null,install:t=>g.install(t)}};
@@ -1 +1 @@
1
- import{spawnSync as t}from"child_process";import{createHash as e}from"crypto";import{accessSync as o,constants as r,createReadStream as s,createWriteStream as n,existsSync as a,mkdirSync as i,mkdtempSync as c,readFileSync as p,renameSync as u,rmSync as l}from"fs";import{tmpdir as d}from"os";import{dirname as f,join as m}from"path";import{Readable as g,Transform as h}from"stream";import{pipeline as w}from"stream/promises";import{logger as k}from"../../utils/logger.js";import{brand as $}from"../brand.js";import{i18n as A}from"../i18n.js";import{WINDOWS_PACKAGE_FAMILIES as x}from"./desktop-process.js";import{toolHome as y}from"./types.js";export const ANTHROPIC_TEAM_ID="Q6L2SF6YDW";const S=/(^|,\s*)O="?Anthropic, PBC"?(,|$)/;let v=(e,o,r={})=>{const s=t(e,o,{encoding:"utf-8",timeout:r.timeout??12e4,windowsHide:!0,input:r.input,stdio:[void 0===r.input?"ignore":"pipe","pipe","pipe"],maxBuffer:16777216});return s.error&&k.logError(`claude-desktop-app: ${e}`,s.error),{status:s.status,stdout:`${s.stdout??""}`,stderr:`${s.stderr??""}`}},C=(...t)=>fetch(...t),E=null;export function setDesktopAppDepsForTests(t){void 0!==t.run&&(v=t.run??v),void 0!==t.fetch&&(C=t.fetch??((...t)=>fetch(...t))),void 0!==t.platform&&(E=t.platform)}function P(){return E??process.platform}export function desktopMirrorRepo(){return $().installMirror?.claudeDesktop?.replace(/\/-\/releases\/latest\/?$/,"")??null}export function desktopAssetName(){return"darwin"===P()?"Claude-mac-universal.dmg":"win32"===P()?"arm64"===process.arch||"ARM64"===process.env.PROCESSOR_ARCHITECTURE||"ARM64"===process.env.PROCESSOR_ARCHITEW6432?"Claude-win-arm64.msix":"Claude-win-x64.msix":null}export function desktopInstallBlocker(){return desktopAssetName()?desktopMirrorRepo()?"win32"===P()&&function(){const t=process.env.LOCALAPPDATA||m(y(),"AppData","Local");return a(m(t,"AnthropicClaude","Update.exe"))}()?"classic_install":null:"no_mirror":"unsupported_platform"}async function _(t,e){const o=await C(t,{signal:AbortSignal.timeout(e)});if(!o.ok)throw new Error(`${t}: HTTP ${o.status}`);return(await o.text()).trim()}export async function fetchLatestDesktopVersion(t=8e3){const e=desktopMirrorRepo();if(!e)throw new Error("no mirror");const o=await _(`${e}/-/releases/latest/download/version.txt`,t);if(!/^\d+\.\d+\.\d+$/.test(o))throw new Error(`unexpected version.txt: ${o.slice(0,40)}`);return o}export function parseSha256Sums(t){const e=new Map;for(const o of t.split(/\r?\n/)){const t=/^([0-9a-f]{64})\s+\*?(\S.*)$/i.exec(o.trim());t&&e.set(t[2].trim(),t[1].toLowerCase())}return e}export class DesktopInstallError extends Error{constructor(t){super(t),this.name="DesktopInstallError"}}const b=(t,e={})=>{throw new DesktopInstallError(A.t(`app_update.error_${t}`,e))};export function verifyMacApp(t){const e=v("codesign",["--verify","--deep","--strict",t],{timeout:6e5});0!==e.status&&b("signature",{reason:(e.stderr||e.stdout).trim().split("\n")[0]||`codesign ${e.status}`});const o=v("codesign",["-dv",t]),r=`${o.stdout}\n${o.stderr}`,s=/^TeamIdentifier=(\S+)/m.exec(r)?.[1],n=/^Identifier=(\S+)/m.exec(r)?.[1];"Q6L2SF6YDW"===s&&"com.anthropic.claudefordesktop"===n||b("signature",{reason:`TeamIdentifier=${s??"?"} Identifier=${n??"?"}`});const a=v("spctl",["-a","-t","exec","-vv",t],{timeout:3e5});0!==a.status&&b("signature",{reason:(a.stderr||a.stdout).trim().split("\n")[0]||`spctl ${a.status}`})}function I(t){try{return o(t,r.W_OK),!0}catch{return!1}}export function installedMacApp(){for(const t of["/Applications/Claude.app",m(y(),"Applications","Claude.app")])if(a(m(t,"Contents","Info.plist")))return t;return null}const M=t=>`'${t.replace(/'/g,"''")}'`;function T(t,e=12e4){return v("powershell.exe",["-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command",t],{timeout:e})}export function verifyWindowsPackage(t){const e=T(`$s = Get-AuthenticodeSignature -LiteralPath ${M(t)}; [pscustomobject]@{ status = [string]$s.Status; subject = [string]$s.SignerCertificate.Subject } | ConvertTo-Json -Compress`);let o={};try{o=JSON.parse(e.stdout.trim()||"{}")}catch{}"Valid"===o.status&&S.test(o.subject??"")||b("signature",{reason:`${o.status??e.stderr.trim().split("\n")[0]??"?"} ${o.subject??""}`.trim()})}export async function installLatestDesktop(t={}){const o=desktopInstallBlocker();o&&b("blocked",{reason:A.t(`app_update.reason_${o}`)});const r=desktopMirrorRepo(),$=desktopAssetName();let S;try{S=await fetchLatestDesktopVersion(15e3)}catch(t){b("download",{reason:t instanceof Error?t.message:String(t)})}const E=`${r}/-/releases/download/v${S}`;let D;try{D=parseSha256Sums(await _(`${E}/SHA256SUMS`,15e3)).get($)}catch(t){k.logError("claude-desktop-app: SHA256SUMS",t)}D||b("no_checksum",{file:$});const R=c(m(d(),"claude-desktop-"));try{const o=m(R,$);t.downloading?.(S),await async function(t,e,o){let r;try{r=await C(t,{signal:AbortSignal.timeout(18e5)})}catch(t){b("download",{reason:t instanceof Error?t.message:String(t)})}r.ok&&r.body||b("download",{reason:`HTTP ${r.status}`});const s=Number(r.headers.get("content-length"))||0;let a=0,i=-1;const c=new h({transform(t,e,r){a+=t.length;const n=s?Math.floor(100*a/s):-1;n>=0&&n!==i&&(i=n,o?.(n)),r(null,t)}});try{await w(g.fromWeb(r.body),c,n(e))}catch(t){l(e,{force:!0}),b("download",{reason:t instanceof Error?t.message:String(t)})}}(`${E}/${$}`,o,t.percent),t.verifying?.();const r=await async function(t){const o=e("sha256");for await(const e of s(t))o.update(e);return o.digest("hex")}(o);return r!==D&&b("checksum",{file:$,expected:D.slice(0,12),actual:r.slice(0,12)}),t.installing?.(),"darwin"===P()?await async function(t,e){const o=m(e,"mnt");i(o,{recursive:!0});const r=v("hdiutil",["attach","-nobrowse","-readonly","-noautoopen","-mountpoint",o,t],{timeout:3e5,input:"Y\n"});0!==r.status&&b("mount",{reason:(r.stderr||r.stdout).trim().split("\n").pop()??""});let s=null;try{const t=m(o,"Claude.app");a(t)||b("bad_package",{reason:"Claude.app"});const e=installedMacApp();let r=e;if(!r){const t=m(y(),"Applications"),e=I("/Applications")?"/Applications":t;i(e,{recursive:!0}),r=m(e,"Claude.app")}const n=f(r);(!I(n)||e&&!I(e))&&b("no_permission",{path:r}),s=m(n,`.Claude.app.${process.pid}.new`),l(s,{recursive:!0,force:!0});const c=v("ditto",[t,s],{timeout:9e5});0!==c.status&&b("copy",{reason:(c.stderr||c.stdout).trim().split("\n")[0]??""}),verifyMacApp(s);const d=function(t){try{const e=p(m(t,"Contents","Info.plist"),"utf-8");return/<key>CFBundleShortVersionString<\/key>\s*<string>(\d+\.\d+\.\d+)[^<]*<\/string>/.exec(e)?.[1]??null}catch{return null}}(s);d||b("bad_package",{reason:"Info.plist"});const g=m(n,`.Claude.app.${process.pid}.old`);e&&u(e,g);try{u(s,r)}catch(t){throw e&&u(g,e),t}return s=null,l(g,{recursive:!0,force:!0}),{version:d,location:r}}finally{s&&l(s,{recursive:!0,force:!0}),v("hdiutil",["detach",o,"-force"],{timeout:6e4})}}(o,R):function(t){verifyWindowsPackage(t);const e=T(`$ErrorActionPreference = 'Stop'; Add-AppxPackage -Path ${M(t)}`,9e5);0!==e.status&&b("install",{reason:(e.stderr||e.stdout).trim().split(/\r?\n/).filter(Boolean)[0]??`Add-AppxPackage ${e.status}`});const o=function(){const t=T(`Get-AppxPackage | Where-Object { @(${x.map(M).join(",")}) -contains $_.PackageFamilyName } | ForEach-Object { $_.Version.ToString() }`,3e4);return/\d+\.\d+\.\d+/.exec(t.stdout)?.[0]??null}();return o||b("install",{reason:"Get-AppxPackage"}),{version:o,location:"MSIX"}}(o)}finally{l(R,{recursive:!0,force:!0})}}
1
+ import{existsSync as e}from"fs";import{join as t}from"path";import{brand as s}from"../brand.js";import{WINDOWS_PACKAGE_FAMILIES as o}from"./desktop-process.js";import{createDesktopAppInstaller as r}from"./desktop-app-installer.js";import{toolHome as a}from"./types.js";export const ANTHROPIC_TEAM_ID="Q6L2SF6YDW";export{DesktopInstallError,parseSha256Sums,setDesktopAppDepsForTests}from"./desktop-app-installer.js";const p=r({id:"claude-desktop",mirror:()=>s().installMirror?.claudeDesktop,asset:(e,t)=>"darwin"===e?"Claude-mac-universal.dmg":"win32"===e?t?"Claude-win-arm64.msix":"Claude-win-x64.msix":null,versionFile:()=>"version.txt",releaseTag:e=>`v${e}`,macApp:{source:"Claude.app",installedNames:["Claude.app"],bundleId:"com.anthropic.claudefordesktop",teamId:"Q6L2SF6YDW"},windows:{signer:/(^|,\s*)O="?Anthropic, PBC"?(,|$)/,packageFilter:`@(${o.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName`},extraBlocker:s=>"win32"===s&&function(){const s=process.env.LOCALAPPDATA||t(a(),"AppData","Local");return e(t(s,"AnthropicClaude","Update.exe"))}()?"classic_install":null});export const desktopMirrorRepo=p.mirrorRepo;export const desktopAssetName=p.assetName;export const desktopInstallBlocker=p.blocker;export const fetchLatestDesktopVersion=(e=8e3)=>p.latestVersion(e);export const installedMacApp=p.installedMacApp;export const verifyMacApp=p.verifyMacApp;export const verifyWindowsPackage=p.verifyWindowsPackage;export function installLatestDesktop(e={}){return p.install(e)}
@@ -1 +1 @@
1
- import{execFileSync as e}from"child_process";import{createHash as t}from"crypto";import{createReadStream as r,createWriteStream as s,existsSync as o,readdirSync as n,readFileSync as i}from"fs";import{copyFile as a,mkdir as l,readFile as c,rename as u,rm as f,writeFile as p}from"fs/promises";import{isAbsolute as d,join as m,normalize as h,sep as w}from"path";import{Readable as g,Writable as b}from"stream";import{pipeline as D}from"stream/promises";import*as y from"zlib";import{logger as v}from"../../utils/logger.js";import{brandEnv as k}from"../brand.js";import{downloadNativeBinary as $,nativeLayout as C,nativePlatformKey as x}from"./claude-native-mirror.js";import{WINDOWS_PACKAGE_FAMILIES as N}from"./desktop-process.js";import{toolHome as A}from"./types.js";export function readDesktopCliPin(e,t,r=!1){const s=e.indexOf('claude-code-releases","sdkWrapperVersion"');if(s<0)return null;const o=e.lastIndexOf("JSON.parse('",s),n=e.indexOf("')",s);if(o<0||n<0)return null;try{const s=JSON.parse(e.subarray(o+12,n).toString("utf-8")),i="string"==typeof s.version?s.version:"",a=s.manifest?.platforms?.[t],l=r?a?.bundle?.checksum:a?.checksum;return/^\d+\.\d+\.\d+$/.test(i)&&"string"==typeof l&&/^[0-9a-f]{64}$/.test(l)?{version:i,checksum:l}:null}catch{return null}}function P(){const t=m(process.env.LOCALAPPDATA||"","AnthropicClaude");if(process.env.LOCALAPPDATA&&o(t)){const e=n(t).filter(e=>/^app-\d+\.\d+\.\d+$/.test(e)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}));for(const r of e){const e=m(t,r,"resources","app.asar");if(o(e))return e}}try{const t=e("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${N.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName } | ForEach-Object { $_.InstallLocation }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]});for(const e of t.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)){const t=m(e,"app","resources","app.asar");if(o(t))return t}}catch(e){v.logError("claude-desktop-cli.windowsAsarPath",e)}return null}function L(){if(k("TEST_HOME")?.trim())return null;for(const e of["/usr/lib/claude-desktop","/opt/Claude"]){const t=m(e,"resources","app.asar");if(o(t))return t}return null}function O(){for(const e of["/Applications/Claude.app",m(A(),"Applications","Claude.app")]){const t=m(e,"Contents","Resources","app.asar");if(o(t))return t}return null}export function installedDesktopAsarPath(){return"win32"===process.platform?P():"darwin"===process.platform?O():"linux"===process.platform?L():null}class E extends b{dest;buffer=Buffer.alloc(0);remaining=0;padding=0;file=null;longName=null;collectingLongName=null;constructor(e){super(),this.dest=e}_write(e,t,r){this.buffer=this.buffer.length?Buffer.concat([this.buffer,e]):e,this.drain().then(()=>r()).catch(r)}_final(e){this.remaining>0?e(new Error("archive ends inside an entry")):e()}target(e){const t=h(e);if(!t||d(t)||".."===t||t.startsWith(`..${w}`))throw new Error(`unsafe path in archive: ${e}`);return m(this.dest,t)}async closeFile(){const e=this.file;this.file=null,e&&await new Promise((t,r)=>e.end(e=>e?r(e):t()))}async drain(){for(;;){if(this.remaining>0){if(0===this.buffer.length)return;const e=this.buffer.subarray(0,Math.min(this.remaining,this.buffer.length));this.buffer=this.buffer.subarray(e.length),this.remaining-=e.length,this.collectingLongName?this.collectingLongName.push(e):this.file&&!this.file.write(e)&&await new Promise(e=>this.file.once("drain",()=>e())),0===this.remaining&&(this.collectingLongName&&(this.longName=Buffer.concat(this.collectingLongName).toString("utf-8").replace(/\0.*$/s,""),this.collectingLongName=null),await this.closeFile());continue}if(this.padding>0){if(this.buffer.length<this.padding)return;this.buffer=this.buffer.subarray(this.padding),this.padding=0}if(this.buffer.length<512)return;const e=this.buffer.subarray(0,512);if(this.buffer=this.buffer.subarray(512),e.every(e=>0===e))continue;const t=(t,r)=>e.subarray(t,t+r).toString("utf-8").replace(/\0.*$/s,""),r=t(345,155);let o=r?`${r}/${t(0,100)}`:t(0,100);null!==this.longName&&(o=this.longName,this.longName=null);const n=parseInt(t(124,12).trim()||"0",8),i=511&parseInt(t(100,8).trim()||"644",8),a=t(156,1)||"0";if(this.remaining=n,this.padding=(512-n%512)%512,"L"===a)this.collectingLongName=[];else if("x"===a||"g"===a);else if("5"===a)await l(this.target(o),{recursive:!0});else{if("0"!==a)throw new Error(`unexpected entry type ${a} in archive: ${o}`);{const e=this.target(o);await l(m(e,".."),{recursive:!0}),this.file=s(e,{mode:i||420}),0===n&&await this.closeFile()}}}}}export async function installDesktopCli(e){const s=readDesktopCliPin(e.asar,e.platformKey,e.bundle);if(!s)return{status:"skipped",reason:"unknown app layout"};if(e.bundle&&!e.download)return{status:"skipped",reason:"no bundle mirror"};const n=e.platformKey.startsWith("win32")?"claude.exe":"claude",i=m(e.userDataDir,"claude-code",s.version),d=m(i,s.checksum.slice(0,12)),h=e.bundle?m(d,"claude.app","Contents","MacOS","claude"):m(d,n),w=m(d,".verified");try{if(o(h)&&(await c(w,"utf-8")).trim()===s.checksum)return{status:"present",version:s.version}}catch{}await l(i,{recursive:!0});const g=m(i,`.partial-${s.checksum.slice(0,12)}`),v=`${g}.download`;try{await f(w,{force:!0}),await f(g,{recursive:!0,force:!0});let n="mirror";if(e.bundle){if(e.onDownload?.(s.version),await e.download(s.version,v),await async function(e,s,o){const n=t("sha256");if(await D(r(e),new b({write(e,t,r){n.update(e),r()}})),n.digest("hex")!==s)throw new Error("downloaded bundle does not match the app's checksum");const i=y.createZstdDecompress;if(!i)throw new Error(`Node ${process.version} cannot decompress zstd (needs 22.15 or newer)`);await D(r(e),i(),new E(o))}(v,s.checksum,g),!o(m(g,"claude.app","Contents","MacOS","claude")))throw new Error("bundle has no claude.app");await f(d,{recursive:!0,force:!0}),await u(g,d)}else{const t=e.localVersionsDir?m(e.localVersionsDir,s.version):null;if(t&&o(t))await a(t,g),n="local";else{e.onDownload?.(s.version);const t=e.download??((t,r)=>$(e.platformKey,t,r));await t(s.version,g)}await l(d,{recursive:!0}),await u(g,h)}return await p(w,s.checksum),{status:"installed",version:s.version,source:n}}finally{await f(g,{recursive:!0,force:!0}),await f(v,{force:!0}),await f(`${g}.download`,{force:!0})}}let S=(...e)=>fetch(...e);export function setDesktopCliFetchForTests(e){S=e}export async function ensureDesktopCli(e){const t=x();if(!t)return{status:"skipped",reason:"unsupported architecture"};if("win32"===process.platform){const r=P();return r?installDesktopCli({userDataDir:e.userDataDir,asar:i(r),platformKey:t,localVersionsDir:C().versionsDir,onDownload:e.onDownload}):{status:"skipped",reason:"app.asar not found"}}if("darwin"===process.platform){const r=O();if(!r)return{status:"skipped",reason:"app.asar not found"};const{mirrorRepo:o,desktopVersion:n}=e;return installDesktopCli({userDataDir:e.userDataDir,asar:i(r),platformKey:t,bundle:!0,onDownload:e.onDownload,download:o&&n?(e,r)=>async function(e,t){const r=await S(e,{signal:AbortSignal.timeout(9e5)});if(!r.ok||!r.body)throw new Error(`${e}: HTTP ${r.status}`);await D(g.fromWeb(r.body),s(t))}(`${o}/-/releases/download/v${n}/claude-code-${e}-${t}.app.tar.zst`,r):void 0})}if("linux"===process.platform){const r=L();return r?installDesktopCli({userDataDir:e.userDataDir,asar:i(r),platformKey:t.replace(/-musl$/,""),localVersionsDir:t.endsWith("-musl")?void 0:C().versionsDir,onDownload:e.onDownload}):{status:"skipped",reason:"app.asar not found"}}return{status:"skipped",reason:"unsupported platform"}}
1
+ import{execFileSync as e}from"child_process";import{createHash as r}from"crypto";import{createReadStream as t,createWriteStream as s,existsSync as o,readdirSync as n,readFileSync as i}from"fs";import{copyFile as a,mkdir as l,readFile as c,rename as u,rm as p,writeFile as f}from"fs/promises";import{isAbsolute as d,join as m,normalize as h,sep as w}from"path";import{Readable as g,Writable as b}from"stream";import{pipeline as D}from"stream/promises";import*as v from"zlib";import{logger as y}from"../../utils/logger.js";import{brandEnv as k}from"../brand.js";import{downloadNativeBinary as $,nativeLayout as C,nativePlatformKey as x}from"./claude-native-mirror.js";import{WINDOWS_PACKAGE_FAMILIES as N}from"./desktop-process.js";import{toolHome as A}from"./types.js";import{powerShellEnv as P}from"../powershell-env.js";export function readDesktopCliPin(e,r,t=!1){const s=e.indexOf('claude-code-releases","sdkWrapperVersion"');if(s<0)return null;const o=e.lastIndexOf("JSON.parse('",s),n=e.indexOf("')",s);if(o<0||n<0)return null;try{const s=JSON.parse(e.subarray(o+12,n).toString("utf-8")),i="string"==typeof s.version?s.version:"",a=s.manifest?.platforms?.[r],l=t?a?.bundle?.checksum:a?.checksum;return/^\d+\.\d+\.\d+$/.test(i)&&"string"==typeof l&&/^[0-9a-f]{64}$/.test(l)?{version:i,checksum:l}:null}catch{return null}}function L(){const r=m(process.env.LOCALAPPDATA||"","AnthropicClaude");if(process.env.LOCALAPPDATA&&o(r)){const e=n(r).filter(e=>/^app-\d+\.\d+\.\d+$/.test(e)).sort((e,r)=>r.localeCompare(e,void 0,{numeric:!0}));for(const t of e){const e=m(r,t,"resources","app.asar");if(o(e))return e}}try{const r=e("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${N.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName } | ForEach-Object { $_.InstallLocation }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"],env:P()});for(const e of r.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)){const r=m(e,"app","resources","app.asar");if(o(r))return r}}catch(e){y.logError("claude-desktop-cli.windowsAsarPath",e)}return null}function O(){if(k("TEST_HOME")?.trim())return null;for(const e of["/usr/lib/claude-desktop","/opt/Claude"]){const r=m(e,"resources","app.asar");if(o(r))return r}return null}function E(){for(const e of["/Applications/Claude.app",m(A(),"Applications","Claude.app")]){const r=m(e,"Contents","Resources","app.asar");if(o(r))return r}return null}export function installedDesktopAsarPath(){return"win32"===process.platform?L():"darwin"===process.platform?E():"linux"===process.platform?O():null}class j extends b{dest;buffer=Buffer.alloc(0);remaining=0;padding=0;file=null;longName=null;collectingLongName=null;constructor(e){super(),this.dest=e}_write(e,r,t){this.buffer=this.buffer.length?Buffer.concat([this.buffer,e]):e,this.drain().then(()=>t()).catch(t)}_final(e){this.remaining>0?e(new Error("archive ends inside an entry")):e()}target(e){const r=h(e);if(!r||d(r)||".."===r||r.startsWith(`..${w}`))throw new Error(`unsafe path in archive: ${e}`);return m(this.dest,r)}async closeFile(){const e=this.file;this.file=null,e&&await new Promise((r,t)=>e.end(e=>e?t(e):r()))}async drain(){for(;;){if(this.remaining>0){if(0===this.buffer.length)return;const e=this.buffer.subarray(0,Math.min(this.remaining,this.buffer.length));this.buffer=this.buffer.subarray(e.length),this.remaining-=e.length,this.collectingLongName?this.collectingLongName.push(e):this.file&&!this.file.write(e)&&await new Promise(e=>this.file.once("drain",()=>e())),0===this.remaining&&(this.collectingLongName&&(this.longName=Buffer.concat(this.collectingLongName).toString("utf-8").replace(/\0.*$/s,""),this.collectingLongName=null),await this.closeFile());continue}if(this.padding>0){if(this.buffer.length<this.padding)return;this.buffer=this.buffer.subarray(this.padding),this.padding=0}if(this.buffer.length<512)return;const e=this.buffer.subarray(0,512);if(this.buffer=this.buffer.subarray(512),e.every(e=>0===e))continue;const r=(r,t)=>e.subarray(r,r+t).toString("utf-8").replace(/\0.*$/s,""),t=r(345,155);let o=t?`${t}/${r(0,100)}`:r(0,100);null!==this.longName&&(o=this.longName,this.longName=null);const n=parseInt(r(124,12).trim()||"0",8),i=511&parseInt(r(100,8).trim()||"644",8),a=r(156,1)||"0";if(this.remaining=n,this.padding=(512-n%512)%512,"L"===a)this.collectingLongName=[];else if("x"===a||"g"===a);else if("5"===a)await l(this.target(o),{recursive:!0});else{if("0"!==a)throw new Error(`unexpected entry type ${a} in archive: ${o}`);{const e=this.target(o);await l(m(e,".."),{recursive:!0}),this.file=s(e,{mode:i||420}),0===n&&await this.closeFile()}}}}}export async function installDesktopCli(e){const s=readDesktopCliPin(e.asar,e.platformKey,e.bundle);if(!s)return{status:"skipped",reason:"unknown app layout"};if(e.bundle&&!e.download)return{status:"skipped",reason:"no bundle mirror"};const n=e.platformKey.startsWith("win32")?"claude.exe":"claude",i=m(e.userDataDir,"claude-code",s.version),d=m(i,s.checksum.slice(0,12)),h=e.bundle?m(d,"claude.app","Contents","MacOS","claude"):m(d,n),w=m(d,".verified");try{if(o(h)&&(await c(w,"utf-8")).trim()===s.checksum)return{status:"present",version:s.version}}catch{}await l(i,{recursive:!0});const g=m(i,`.partial-${s.checksum.slice(0,12)}`),y=`${g}.download`;try{await p(w,{force:!0}),await p(g,{recursive:!0,force:!0});let n="mirror";if(e.bundle){if(e.onDownload?.(s.version),await e.download(s.version,y),await async function(e,s,o){const n=r("sha256");if(await D(t(e),new b({write(e,r,t){n.update(e),t()}})),n.digest("hex")!==s)throw new Error("downloaded bundle does not match the app's checksum");const i=v.createZstdDecompress;if(!i)throw new Error(`Node ${process.version} cannot decompress zstd (needs 22.15 or newer)`);await D(t(e),i(),new j(o))}(y,s.checksum,g),!o(m(g,"claude.app","Contents","MacOS","claude")))throw new Error("bundle has no claude.app");await p(d,{recursive:!0,force:!0}),await u(g,d)}else{const r=e.localVersionsDir?m(e.localVersionsDir,s.version):null;if(r&&o(r))await a(r,g),n="local";else{e.onDownload?.(s.version);const r=e.download??((r,t)=>$(e.platformKey,r,t));await r(s.version,g)}await l(d,{recursive:!0}),await u(g,h)}return await f(w,s.checksum),{status:"installed",version:s.version,source:n}}finally{await p(g,{recursive:!0,force:!0}),await p(y,{force:!0}),await p(`${g}.download`,{force:!0})}}let S=(...e)=>fetch(...e);export function setDesktopCliFetchForTests(e){S=e}export async function ensureDesktopCli(e){const r=x();if(!r)return{status:"skipped",reason:"unsupported architecture"};if("win32"===process.platform){const t=L();return t?installDesktopCli({userDataDir:e.userDataDir,asar:i(t),platformKey:r,localVersionsDir:C().versionsDir,onDownload:e.onDownload}):{status:"skipped",reason:"app.asar not found"}}if("darwin"===process.platform){const t=E();if(!t)return{status:"skipped",reason:"app.asar not found"};const{mirrorRepo:o,desktopVersion:n}=e;return installDesktopCli({userDataDir:e.userDataDir,asar:i(t),platformKey:r,bundle:!0,onDownload:e.onDownload,download:o&&n?(e,t)=>async function(e,r){const t=await S(e,{signal:AbortSignal.timeout(9e5)});if(!t.ok||!t.body)throw new Error(`${e}: HTTP ${t.status}`);await D(g.fromWeb(t.body),s(r))}(`${o}/-/releases/download/v${n}/claude-code-${e}-${r}.app.tar.zst`,t):void 0})}if("linux"===process.platform){const t=O();return t?installDesktopCli({userDataDir:e.userDataDir,asar:i(t),platformKey:r.replace(/-musl$/,""),localVersionsDir:r.endsWith("-musl")?void 0:C().versionsDir,onDownload:e.onDownload}):{status:"skipped",reason:"app.asar not found"}}return{status:"skipped",reason:"unsupported platform"}}
@@ -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 l}from"path";import{randomUUID as a}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,installedDesktopAsarPath as g}from"./claude-desktop-cli.js";import{i18n as y}from"../i18n.js";import{BRAND_NAME as h,brand as k,brandEnv as _,CLI_NAME as b}from"../brand.js";import{backupBeforeWrite as D,atomicWriteFile as A}from"./backup.js";import{toolHome as w}from"./types.js";import{canRestartDesktop as C,isDesktopRunning as E,launchDesktop as v,quitDesktop as M,restartDesktop as O,WINDOWS_PACKAGE_FAMILIES as S}from"./desktop-process.js";import{desktopInstallBlocker as x,fetchLatestDesktopVersion as P,installedMacApp as j,installLatestDesktop as I}from"./claude-desktop-app.js";import{setUserRegistryElevated as L}from"./elevated-reg.js";import{UserActionNeeded as T}from"./types.js";import{baseModelId as $,isClaudeModel as N}from"../model-catalog.js";import{getDefaultModels as R}from"../model-registry.js";import{claudeFormat as G,nestedClaudeProjectFiles as K}from"../sessions/formats.js";const U=h;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const F=/^[a-f0-9-]{36}$/;function H(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=w(),n=Boolean(_("TEST_HOME")?.trim());switch(process.platform){case"darwin":return l(o,"Library","Application Support","Claude-3p");case"win32":{const e=!n&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(o,"AppData","Local");return S.map(t=>l(e,"Packages",t,"LocalCache","Local","Claude-3p")).find(e=>t(e))??l(e,"Claude-3p")}default:{const e=!n&&process.env.XDG_CONFIG_HOME?process.env.XDG_CONFIG_HOME:l(o,".config");return l(e,"Claude-3p")}}}const J=()=>l(claudeDesktopUserDataDir(),"configLibrary"),V=()=>l(J(),"_meta.json"),B=e=>l(J(),`${e}.json`),W=()=>l(claudeDesktopUserDataDir(),"claude_desktop_config.json");function z(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return H(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 q(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),D(n),A(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){u.logError("claude-desktop.writeJson.chmod",e)}}function X(){const e=z(V());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>H(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function Z(e){return e?.entries.find(e=>e.name===U&&F.test(e.id))}const Y={opus:0,fable:1,sonnet:2,haiku:3};function Q(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=Q(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function ee(e){return Q(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>$(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(N)){i=[...new Set(t.models.filter(N).map($))];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=$(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const l=e=>Y[ee(e)??""]??9;i.sort((e,t)=>{if(e===o)return-1;if(t===o)return 1;const n=l(e)-l(t);if(0!==n)return n;const r=Q(e),s=Q(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 a=new Set,c=new Map,d=new Set(Object.values(R()).map(e=>$(e||"")));for(const e of n){const t=ee(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=ee(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||a.has(t)||(o.isFamilyDefault=!0,a.add(t))}return o})}let te=null,oe=null,ne=null,re=null,se=null;function ie(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 le={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}},ae=()=>{if(_("TEST_HOME")?.trim())return null;const e=g();return e?r(e):null};let ce=ae,de=null;export function setDesktopAsarForTests(e){ce=void 0===e?ae:()=>e,de=null}function pe(){if(de)return de;let e=null;try{e=ce()}catch(e){u.logError("claude-desktop.unsupportedDefaults",e)}return de=new Set(e?Object.keys(le).filter(t=>!e.includes(t)):[]),de}function ue(e){const t=pe();return Object.fromEntries(Object.entries(le).filter(([o])=>!e(o)&&!t.has(o)))}function fe(e){const t={...ue(t=>t in e),...e};for(const e of pe())e in t&&JSON.stringify(t[e])===JSON.stringify(le[e])&&delete t[e];return t}const me="SOFTWARE\\Policies\\Claude",ge=`HKCU\\${me}`,ye="HKLM\\SOFTWARE\\Policies\\Claude",he=`${b}-claude-policy.reg`,ke=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let _e=ke;export function setRegRunnerForTests(e){_e=e??ke}function be(){return"win32"===process.platform}function De(e){let t;try{t=_e(["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 Ae(){if(null===De(ge))return;const e=l(claudeDesktopUserDataDir(),he);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),D(e),_e(["export",ge,e,"/y"])}catch(e){u.logError("claude-desktop.snapshotPolicy",e)}}function we(e){Ae();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)];_e(["add",ge,"/v",t,"/t",e,"/d",n,"/f"])}}function Ce(e){const t=De(ge);if(!t)return;Ae();let o=t.size;for(const n of e)t.has(n)&&(_e(["delete",ge,"/v",n,"/f"]),o-=1);o<=0&&_e(["delete",ge,"/f"])}function Ee(){const e=!Boolean(_("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(w(),"AppData","Local");return!!t(l(e,"AnthropicClaude"))||S.some(o=>t(l(e,"Packages",o,"LocalCache","Local","Claude-3p")))}const ve=[...Object.keys(ie({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(le)];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 De(ye)?ye: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=w();let o;switch(process.platform){case"darwin":o=["/Applications/Claude.app",l(e,"Applications","Claude.app")];break;case"win32":{const t=process.env.LOCALAPPDATA||l(e,"AppData","Local");o=[l(t,"AnthropicClaude"),l(t,"Programs","Claude"),...S.map(e=>l(t,"Packages",e))];break}default:o=["/usr/lib/claude-desktop","/opt/Claude","/usr/bin/claude-desktop",l(e,".local","bin","claude-desktop")]}return o.push(claudeDesktopUserDataDir(),l(claudeDesktopUserDataDir(),"..","Claude")),o.some(e=>t(e))}const Oe=/\d+\.\d+\.\d+/;function Se(e){const t=e=>e.split(".").map(Number);return e.sort((e,o)=>{const[n,r]=[t(e),t(o)];for(let e=0;e<3;e++)if(n[e]!==r[e])return r[e]-n[e];return 0})[0]??null}function xe(){if("darwin"===process.platform){for(const e of["/Applications/Claude.app",l(w(),"Applications","Claude.app")]){const o=l(e,"Contents","Info.plist");if(!t(o))continue;const n=/<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/.exec(r(o,"utf-8")),s=n?Oe.exec(n[1])?.[0]:void 0;if(s)return s}return null}if("win32"===process.platform){const e=l(process.env.LOCALAPPDATA||l(w(),"AppData","Local"),"AnthropicClaude");if(t(e)){const t=n(e).map(e=>/^app-(\d+\.\d+\.\d+)$/.exec(e)?.[1]).filter(e=>!!e);if(t.length>0)return Se(t)}const o=S.map(e=>`'${e}'`).join(",");return Se(c("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${o}) -contains $_.PackageFamilyName } | ForEach-Object { $_.Version.ToString() }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).flatMap(e=>Oe.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 Oe.exec(e)?.[0]??null}catch{return null}return null}const Pe="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",je="darwin"!==process.platform&&"win32"!==process.platform||!k().installMirror?.claudeDesktop?"https://claude.ai/download":k().installMirror.claudeDesktop,Ie="darwin"===process.platform?`open ${je}`:"win32"===process.platform?`start ${je}`:`xdg-open ${je}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:Pe,installCommand:Ie,configPath:V(),sessions:{format:G,files:()=>K(l(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:Me,installedVersion:xe,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(" "+y.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?xe():null,mirrorRepo:k().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:y.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:y.t("tools.claude_desktop.code_cli_failed",{reason:t instanceof Error?t.message:String(t)})}]}},runningApp:C()?{isRunning:E,restart:O,quit:M,launch:v}:void 0,appInstaller:{blocker:x,latestVersion:()=>P(),installedPath(){if("darwin"===process.platform)return j();if("win32"!==process.platform)return null;try{return xe()?"MSIX":null}catch(e){return u.logError("claude-desktop.installedPath",e),null}},install:e=>I(e)},wantsModelCatalog:!0,loadPrivateConfig(e){const t=X()??{appliedId:"",entries:[]};let o=Z(t);o||(o={id:a(),name:U},t.entries.push(o));const n=ie(e);oe=!0===n.disableDeploymentModeChooser,te={models:n.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const r=z(B(o.id))??{};q(B(o.id),{...fe(r),...n}),t.appliedId=o.id,q(V(),t);const s=z(W())??{};if("3p"!==s.deploymentMode&&q(W(),{...s,deploymentMode:"3p"}),re=null,se=null,ne=null,be()){const t=De(ge),o=ve.filter(e=>t?.has(e)),r={...ue(e=>t?.has(e)??!1),...n},s=!0===e.settings?.force_registry,i=!s&&Ee();try{i?Ce(ve):we(r),ne=i?"removed":"written"}catch(e){u.logError("claude-desktop.policy",e),re=e instanceof Error?e.message.trim():String(e),(o.length>0||s)&&(se=i?{action:"remove",values:Object.fromEntries(o.map(e=>[e,null])),deleteKey:o.length===t.size}:{action:"write",values:r,deleteKey:!1})}}},pendingElevation(){const e=se;return e?{prompt:y.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!L(me,e.values,e.deleteKey))return!1;const t=De(ge),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(se=null,re=null),o}}:null},unloadPrivateConfig(){if(be())try{Ce(ve)}catch(e){u.logError("claude-desktop.removePolicy",e)}const e=X(),t=Z(e);if(!e||!t)return;D(B(t.id)),s(B(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(D(V()),s(V(),{force:!0})):q(V(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=X(),t=Z(e);if(!t||e?.appliedId!==t.id)return null;const o=z(B(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=X(),o=Z(t);if(!o||t?.appliedId!==o.id)return;const n=z(B(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog),s=JSON.stringify(n.inferenceModels)!==JSON.stringify(r),i={...fe(n),inferenceModels:r},l=JSON.stringify(i)!==JSON.stringify(n);se=null;const a=be()?De(ge):null;if(!a?.has("inferenceModels"))return void(l&&q(B(o.id),i));const c=ve.filter(e=>a.has(e)),d=!0!==e.settings?.force_registry&&Ee();if(l&&q(B(o.id),i),d||s)try{d?Ce(ve):we({inferenceModels:r})}catch(e){throw u.logError("claude-desktop.refreshModelMenu registry",e),se=d?{action:"remove",values:Object.fromEntries(c.map(e=>[e,null])),deleteKey:c.length===a.size}:{action:"write",values:{inferenceModels:r},deleteKey:!1},new T(y.t("tools.claude_desktop.refresh_needs_admin"))}},detectCurrentConfig(){try{if(be()){const e=De(ge)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=Z(X());if(!e)return{apiKey:null};const t=z(B(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=X(),t=Z(e);return{meta:e,applied:t?z(B(t.id)):null,desktop:z(W()),...be()?{policy:Object.fromEntries(De(ge)??[])}:{}}}catch(e){return u.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;be()&&De(ge)?.has("inferenceModels")&&(Ae(),_e(["delete",ge,"/v","inferenceModels","/f"]),e=!0);const t=Z(X()),o=t?z(B(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;q(B(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(te&&te.models.length>0){const{models:t,source:o,groups:n}=te;e.push({kind:"summary",text:y.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:y.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!==oe&&e.push({kind:"detail",text:y.t(oe?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),C()&&!E()||e.push({kind:"action",text:y.t("tools.claude_desktop.restart_hint")}),se?(e.push({kind:"action",text:y.t(`tools.claude_desktop.policy_stale_${se.action}`)}),e.push({kind:"detail",text:re??""})):re?(e.push({kind:"detail",text:y.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:re})):be()&&ne&&e.push({kind:"detail",text:y.t(`tools.claude_desktop.registry_${ne}`,{key:ge})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:y.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[V(),W()];try{const t=Z(X());t&&e.push(B(t.id))}catch{}return e},backupPaths(){const e=[V(),W()];be()&&e.push(l(claudeDesktopUserDataDir(),he));try{const t=Z(X());t&&e.push(B(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 l}from"path";import{randomUUID as a}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,installedDesktopAsarPath as g}from"./claude-desktop-cli.js";import{i18n as y}from"../i18n.js";import{BRAND_NAME as h,brand as k,brandEnv as _,CLI_NAME as b}from"../brand.js";import{backupBeforeWrite as D,atomicWriteFile as w}from"./backup.js";import{toolHome as A}from"./types.js";import{canRestartDesktop as C,isDesktopRunning as E,launchDesktop as v,quitDesktop as M,restartDesktop as O,WINDOWS_PACKAGE_FAMILIES as S}from"./desktop-process.js";import{desktopInstallBlocker as x,fetchLatestDesktopVersion as P,installedMacApp as j,installLatestDesktop as I}from"./claude-desktop-app.js";import{setUserRegistryElevated as L}from"./elevated-reg.js";import{UserActionNeeded as T}from"./types.js";import{baseModelId as $,isClaudeModel as N}from"../model-catalog.js";import{getDefaultModels as R}from"../model-registry.js";import{claudeFormat as G,nestedClaudeProjectFiles as K}from"../sessions/formats.js";import{powerShellEnv as U}from"../powershell-env.js";const F=h;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const H=/^[a-f0-9-]{36}$/;function J(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(_("TEST_HOME")?.trim());switch(process.platform){case"darwin":return l(o,"Library","Application Support","Claude-3p");case"win32":{const e=!n&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(o,"AppData","Local");return S.map(t=>l(e,"Packages",t,"LocalCache","Local","Claude-3p")).find(e=>t(e))??l(e,"Claude-3p")}default:{const e=!n&&process.env.XDG_CONFIG_HOME?process.env.XDG_CONFIG_HOME:l(o,".config");return l(e,"Claude-3p")}}}const V=()=>l(claudeDesktopUserDataDir(),"configLibrary"),B=()=>l(V(),"_meta.json"),W=e=>l(V(),`${e}.json`),z=()=>l(claudeDesktopUserDataDir(),"claude_desktop_config.json");function q(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return J(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 X(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),D(n),w(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){u.logError("claude-desktop.writeJson.chmod",e)}}function Z(){const e=q(B());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>J(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function Y(e){return e?.entries.find(e=>e.name===F&&H.test(e.id))}const Q={opus:0,fable:1,sonnet:2,haiku:3};function ee(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=ee(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function te(e){return ee(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>$(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(N)){i=[...new Set(t.models.filter(N).map($))];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=$(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const l=e=>Q[te(e)??""]??9;i.sort((e,t)=>{if(e===o)return-1;if(t===o)return 1;const n=l(e)-l(t);if(0!==n)return n;const r=ee(e),s=ee(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 a=new Set,c=new Map,d=new Set(Object.values(R()).map(e=>$(e||"")));for(const e of n){const t=te(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=te(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||a.has(t)||(o.isFamilyDefault=!0,a.add(t))}return o})}let oe=null,ne=null,re=null,se=null,ie=null;function le(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 ae={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}},ce=()=>{if(_("TEST_HOME")?.trim())return null;const e=g();return e?r(e):null};let de=ce,pe=null;export function setDesktopAsarForTests(e){de=void 0===e?ce:()=>e,pe=null}function ue(){if(pe)return pe;let e=null;try{e=de()}catch(e){u.logError("claude-desktop.unsupportedDefaults",e)}return pe=new Set(e?Object.keys(ae).filter(t=>!e.includes(t)):[]),pe}function fe(e){const t=ue();return Object.fromEntries(Object.entries(ae).filter(([o])=>!e(o)&&!t.has(o)))}function me(e){const t={...fe(t=>t in e),...e};for(const e of ue())e in t&&JSON.stringify(t[e])===JSON.stringify(ae[e])&&delete t[e];return t}const ge="SOFTWARE\\Policies\\Claude",ye=`HKCU\\${ge}`,he="HKLM\\SOFTWARE\\Policies\\Claude",ke=`${b}-claude-policy.reg`,_e=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let be=_e;export function setRegRunnerForTests(e){be=e??_e}function De(){return"win32"===process.platform}function we(e){let t;try{t=be(["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 Ae(){if(null===we(ye))return;const e=l(claudeDesktopUserDataDir(),ke);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),D(e),be(["export",ye,e,"/y"])}catch(e){u.logError("claude-desktop.snapshotPolicy",e)}}function Ce(e){Ae();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)];be(["add",ye,"/v",t,"/t",e,"/d",n,"/f"])}}function Ee(e){const t=we(ye);if(!t)return;Ae();let o=t.size;for(const n of e)t.has(n)&&(be(["delete",ye,"/v",n,"/f"]),o-=1);o<=0&&be(["delete",ye,"/f"])}function ve(){const e=!Boolean(_("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:l(A(),"AppData","Local");return!!t(l(e,"AnthropicClaude"))||S.some(o=>t(l(e,"Packages",o,"LocalCache","Local","Claude-3p")))}const Me=[...Object.keys(le({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(ae)];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 we(he)?he: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 Oe(){const e=A();let o;switch(process.platform){case"darwin":o=["/Applications/Claude.app",l(e,"Applications","Claude.app")];break;case"win32":{const t=process.env.LOCALAPPDATA||l(e,"AppData","Local");o=[l(t,"AnthropicClaude"),l(t,"Programs","Claude"),...S.map(e=>l(t,"Packages",e))];break}default:o=["/usr/lib/claude-desktop","/opt/Claude","/usr/bin/claude-desktop",l(e,".local","bin","claude-desktop")]}return o.push(claudeDesktopUserDataDir(),l(claudeDesktopUserDataDir(),"..","Claude")),o.some(e=>t(e))}const Se=/\d+\.\d+\.\d+/;function xe(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 Pe(){if("darwin"===process.platform){for(const e of["/Applications/Claude.app",l(A(),"Applications","Claude.app")]){const o=l(e,"Contents","Info.plist");if(!t(o))continue;const n=/<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/.exec(r(o,"utf-8")),s=n?Se.exec(n[1])?.[0]:void 0;if(s)return s}return null}if("win32"===process.platform){const e=l(process.env.LOCALAPPDATA||l(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 xe(t)}const o=S.map(e=>`'${e}'`).join(",");return xe(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"],env:U()}).split(/\r?\n/).flatMap(e=>Se.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 Se.exec(e)?.[0]??null}catch{return null}return null}const je="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",Ie="darwin"!==process.platform&&"win32"!==process.platform||!k().installMirror?.claudeDesktop?"https://claude.ai/download":k().installMirror.claudeDesktop,Le="darwin"===process.platform?`open ${Ie}`:"win32"===process.platform?`start ${Ie}`:`xdg-open ${Ie}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:je,installCommand:Le,configPath:B(),sessions:{format:G,files:()=>K(l(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:Oe,installedVersion:Pe,prepareRuntime:async function(){if(!["win32","darwin","linux"].includes(process.platform)||!Oe())return[];const e=Date.now();try{const t=await m({userDataDir:claudeDesktopUserDataDir(),onDownload:e=>console.log(p.gray(" "+y.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?Pe():null,mirrorRepo:k().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:y.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:y.t("tools.claude_desktop.code_cli_failed",{reason:t instanceof Error?t.message:String(t)})}]}},runningApp:C()?{isRunning:E,restart:O,quit:M,launch:v}:void 0,appInstaller:{vendor:"Anthropic",sizeMb:()=>300,downloadPage:"https://claude.ai/download",blocker:x,latestVersion:()=>P(),installedPath(){if("darwin"===process.platform)return j();if("win32"!==process.platform)return null;try{return Pe()?"MSIX":null}catch(e){return u.logError("claude-desktop.installedPath",e),null}},install:e=>I(e)},wantsModelCatalog:!0,loadPrivateConfig(e){const t=Z()??{appliedId:"",entries:[]};let o=Y(t);o||(o={id:a(),name:F},t.entries.push(o));const n=le(e);ne=!0===n.disableDeploymentModeChooser,oe={models:n.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const r=q(W(o.id))??{};X(W(o.id),{...me(r),...n}),t.appliedId=o.id,X(B(),t);const s=q(z())??{};if("3p"!==s.deploymentMode&&X(z(),{...s,deploymentMode:"3p"}),se=null,ie=null,re=null,De()){const t=we(ye),o=Me.filter(e=>t?.has(e)),r={...fe(e=>t?.has(e)??!1),...n},s=!0===e.settings?.force_registry,i=!s&&ve();try{i?Ee(Me):Ce(r),re=i?"removed":"written"}catch(e){u.logError("claude-desktop.policy",e),se=e instanceof Error?e.message.trim():String(e),(o.length>0||s)&&(ie=i?{action:"remove",values:Object.fromEntries(o.map(e=>[e,null])),deleteKey:o.length===t.size}:{action:"write",values:r,deleteKey:!1})}}},pendingElevation(){const e=ie;return e?{prompt:y.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!L(ge,e.values,e.deleteKey))return!1;const t=we(ye),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(ie=null,se=null),o}}:null},unloadPrivateConfig(){if(De())try{Ee(Me)}catch(e){u.logError("claude-desktop.removePolicy",e)}const e=Z(),t=Y(e);if(!e||!t)return;D(W(t.id)),s(W(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(D(B()),s(B(),{force:!0})):X(B(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=Z(),t=Y(e);if(!t||e?.appliedId!==t.id)return null;const o=q(W(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=Z(),o=Y(t);if(!o||t?.appliedId!==o.id)return;const n=q(W(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog),s=JSON.stringify(n.inferenceModels)!==JSON.stringify(r),i={...me(n),inferenceModels:r},l=JSON.stringify(i)!==JSON.stringify(n);ie=null;const a=De()?we(ye):null;if(!a?.has("inferenceModels"))return void(l&&X(W(o.id),i));const c=Me.filter(e=>a.has(e)),d=!0!==e.settings?.force_registry&&ve();if(l&&X(W(o.id),i),d||s)try{d?Ee(Me):Ce({inferenceModels:r})}catch(e){throw u.logError("claude-desktop.refreshModelMenu registry",e),ie=d?{action:"remove",values:Object.fromEntries(c.map(e=>[e,null])),deleteKey:c.length===a.size}:{action:"write",values:{inferenceModels:r},deleteKey:!1},new T(y.t("tools.claude_desktop.refresh_needs_admin"))}},detectCurrentConfig(){try{if(De()){const e=we(ye)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=Y(Z());if(!e)return{apiKey:null};const t=q(W(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=Z(),t=Y(e);return{meta:e,applied:t?q(W(t.id)):null,desktop:q(z()),...De()?{policy:Object.fromEntries(we(ye)??[])}:{}}}catch(e){return u.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;De()&&we(ye)?.has("inferenceModels")&&(Ae(),be(["delete",ye,"/v","inferenceModels","/f"]),e=!0);const t=Y(Z()),o=t?q(W(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;X(W(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(oe&&oe.models.length>0){const{models:t,source:o,groups:n}=oe;e.push({kind:"summary",text:y.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:y.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!==ne&&e.push({kind:"detail",text:y.t(ne?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),C()&&!E()||e.push({kind:"action",text:y.t("tools.claude_desktop.restart_hint")}),ie?(e.push({kind:"action",text:y.t(`tools.claude_desktop.policy_stale_${ie.action}`)}),e.push({kind:"detail",text:se??""})):se?(e.push({kind:"detail",text:y.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:se})):De()&&re&&e.push({kind:"detail",text:y.t(`tools.claude_desktop.registry_${re}`,{key:ye})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:y.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[B(),z()];try{const t=Y(Z());t&&e.push(W(t.id))}catch{}return e},backupPaths(){const e=[B(),z()];De()&&e.push(l(claudeDesktopUserDataDir(),ke));try{const t=Y(Z());t&&e.push(W(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 a}from"fs";import{join as l}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 _,toolHome as g,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 w}from"../model-registry.js";import{configManager as j}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=()=>l(R(),"config.toml"),X="sessions_move_declined",B=["browser_use","browser_use_external","computer_use"];function U(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 W(){try{if(Q(Z().desktop))return!0}catch{}if("darwin"===process.platform)return["/Applications",l(g(),"Applications")].some(e=>["ChatGPT.app","Codex.app"].some(o=>t(l(e,o))));if("win32"===process.platform){const e=l(process.env.LOCALAPPDATA||l(g(),"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 q=()=>l(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(q()))return{};try{const e=JSON.parse(r(q(),"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=()=>l(j.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 l=M(A(),n);return 0===l.length&&function(e){try{o(j.getConfigDir(),{recursive:!0}),a(re(),JSON.stringify({signature:e})+"\n")}catch(e){d.logError("codexAdapter.rememberAccepted",e)}}(i),l}function ae(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 a=t.catalog,l=e=>S({bundled:e,specs:I("codex",a?.clientModels),...a?{keyModels:a.models}:{},gatewayAvailable:a?.models??D(),oneMillion:n,selectedModel:o,..."gateway"===a?.oneMillionSource?{claudeOneMillion:a.oneMillion}:{}}),c=e=>JSON.stringify(e,null,2)+"\n";let u=l(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(l(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:w("codex");ae(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=c.stringify(o);i!==n&&(m(K()),p(K(),i))}const le={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(le),installSpec:le,configPath:K(),sessions:{format:b,files:()=>[...v(l(f(),"sessions")),...v(l(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(),o=function(e,t){const o=Q(e.model_providers)?e.model_providers[Y]:void 0;return!(!Q(o)||o.base_url!==t||!0===o.supports_standalone_web_search||(o.supports_standalone_web_search=!0,0))}(t,x(e.baseUrl));(U(t)||o)&&(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=j.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(){j.setToolSetting("codex",X,t)}}},applyNotes(){if("skipped"===ne)return 0===$(le).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()||W()?[{kind:"action",text:u.t(codexWorkModeOn()?"tools.codex.work_mode_on":"tools.codex.work_mode_hint")}]:[]]},loadPrivateConfig(e){const t=w("codex"),o=_(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",ae(i,e,n);const s=V(i,"model_providers"),a=Q(s[Y])?{...s[Y]}:{};delete a.env_key;const{experimental_bearer_token:l,...d}=a;s[Y]={...d,name:"custom",wire_api:"responses",requires_openai_auth:!0,supports_standalone_web_search:!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,U(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(q()),p(q(),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(q()),Q(s.tokens)?(p(q(),JSON.stringify({...s,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(i(q(),{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,U(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(),q(),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 a}from"fs";import{join as l}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 _,toolHome as g,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 w}from"../model-registry.js";import{configManager as j}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";import{chatgptDesktopApp as R}from"./chatgpt-desktop.js";const K=()=>f(),X=()=>l(K(),"config.toml"),B="sessions_move_declined",U=["browser_use","browser_use_external","computer_use"];function W(e){const t=e.features;if(!V(t)||!U.every(e=>!1===t[e]))return!1;for(const e of U)delete t[e];return!0}export function codexWorkModeOn(){try{const e=ee();return e.model_provider===F&&V(e.desktop)&&"STEPS_PROSE"===e.desktop.conversationDetailMode}catch{return!1}}function q(){try{if(V(ee().desktop))return!0}catch{}if("darwin"===process.platform)return["/Applications",l(g(),"Applications")].some(e=>["ChatGPT.app","Codex.app"].some(o=>t(l(e,o))));if("win32"===process.platform){const e=l(process.env.LOCALAPPDATA||l(g(),"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 X()}const z=()=>l(K(),"auth.json"),Y="OPENAI_API_KEY",F="custom",H=1e6,Q=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function V(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function Z(e,t){return V(e[t])||(e[t]={}),e[t]}function ee(){if(!t(X()))return{};const e=r(X(),"utf-8");if(!e.trim())return{};try{const t=c.parse(e);if(!V(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 te(){if(!t(z()))return{};try{const e=JSON.parse(r(z(),"utf-8"));return V(e)?e:{}}catch{return{}}}let oe=null;function ne(e){const t=e.profiles;if(V(t)){for(const[e,o]of Object.entries(t))V(o)&&2===Object.keys(o).length&&o.model_provider===F&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let re=null;const ie=()=>l(j.getConfigDir(),"codex-catalog-check.json");function se(e){const o=A();t(o)&&r(o,"utf-8")===e||(m(o),p(o,e))}function ae(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(ie(),"utf-8")).signature===e}catch{return!1}}(i))return[];const l=M(A(),n);return 0===l.length&&function(e){try{o(j.getConfigDir(),{recursive:!0}),a(ie(),JSON.stringify({signature:e})+"\n")}catch(e){d.logError("codexAdapter.rememberAccepted",e)}}(i),l}function le(e,t,o){const n=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===H&&delete e.model_context_window,e.model_auto_compact_token_limit===Q&&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=H,e.model_auto_compact_token_limit=Q)},s=P()??T();if(!s)return d.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),re="skipped",void r();const a=t.catalog,l=e=>S({bundled:e,specs:I("codex",a?.clientModels),...a?{keyModels:a.models}:{},gatewayAvailable:a?.models??D(),oneMillion:n,selectedModel:o,..."gateway"===a?.oneMillionSource?{claudeOneMillion:a.oneMillion}:{}}),c=e=>JSON.stringify(e,null,2)+"\n";let u=l(s);se(c(u));const m=N(),p=ae(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(l(o).models,o)}])if(se(c(e)),0===ae(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 re={rejectedBy:p[0]},i(A(),{force:!0}),void r()}re={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=ee()}catch{return null}return e.model_catalog_json===A()&&t(A())?M(A())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=ee(),n=c.stringify(o),r="string"==typeof o.model?o.model:w("codex");le(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=c.stringify(o);i!==n&&(m(X()),p(X(),i))}const ce={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",companionApps:[R],displayName:"Codex",command:"codex",installCommand:J(ce),installSpec:ce,configPath:X(),sessions:{format:b,files:()=>[...v(l(f(),"sessions")),...v(l(f(),"archived_sessions"))],resumeCommand:e=>({command:"codex",args:["resume",e]})},wantsModelCatalog:!0,listedModels(){if(ee().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(ee().model_catalog_json!==A())return;setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog);const t=ee(),o=function(e,t){const o=V(e.model_providers)?e.model_providers[F]:void 0;return!(!V(o)||o.base_url!==t||!0===o.supports_standalone_web_search||(o.supports_standalone_web_search=!0,0))}(t,x(e.baseUrl));(W(t)||o)&&(m(X()),p(X(),c.stringify(t)))},async followUp(){if(ee().model_provider!==F)return null;const e=await h(F,{dryRun:!0}),t=Math.max(e.moved.length,e.dbRows);if(0===t)return null;const o=j.getToolSettings("codex")[B];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(F),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:F})},{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(){j.setToolSetting("codex",B,t)}}},applyNotes(){if("skipped"===re)return 0===$(ce).length?[]:[{kind:"action",text:u.t("tools.codex.catalog_skipped")}];if(!re)return[];if("rejectedBy"in re){const{bin:e,version:t}=re.rejectedBy;return[{kind:"action",text:u.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of re.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(re.listed.length),breakdown:t})},{kind:"detail",text:re.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=w("codex"),o=_(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,r=x(e.baseUrl),i=ee();i.model=n,i.model_provider=F,i.model_reasoning_effort="high",le(i,e,n);const s=Z(i,"model_providers"),a=V(s[F])?{...s[F]}:{};delete a.env_key;const{experimental_bearer_token:l,...d}=a;s[F]={...d,name:"custom",wire_api:"responses",requires_openai_auth:!0,supports_standalone_web_search:!0,base_url:r},ne(i),Z(Z(i,"tui"),"model_availability_nux")[n]=4;const u=Z(i,"features");u.goals=!0,u.js_repl=!1,W(i),m(X()),p(X(),c.stringify(i)),function(e){const t=e.trim();if(!t)return;const o={...te(),auth_mode:"apikey",[Y]:t};m(z()),p(z(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},holdsOurConfig(e){const t=te()[Y];return"string"==typeof t&&e.includes(t.trim())},unloadPrivateConfig(e){if(oe=function(e){const t=te(),o="string"==typeof t[Y]?t[Y].trim():"";if(!o)return V(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[Y]:n,auth_mode:r,...s}=t;return m(z()),V(s.tokens)?(p(z(),JSON.stringify({...s,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(i(z(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(X()))return;let o;try{o=ee()}catch(e){return void d.logError("codexAdapter.unloadPrivateConfig",e)}const n=o.model_providers;V(n)&&(delete n[F],0===Object.keys(n).length&&delete o.model_providers),o.model_provider===F&&delete o.model_provider,o.model_catalog_json===A()&&delete o.model_catalog_json,W(o),ne(o),m(X()),p(X(),c.stringify(o))},unloadNotes(){switch(oe){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=te()[Y];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return ee()}catch(e){return d.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[X(),z(),A()]};export function codexAuthProblem(){try{const e=ee(),t=e.model_providers?.[F];if(e.model_provider!==F||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=te();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
@@ -0,0 +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 +1 @@
1
- import{spawnSync as e}from"child_process";import{logger as t}from"../../utils/logger.js";export const WINDOWS_PACKAGE_FAMILIES=["Claude_pzs8sxrjxfjjc","AnthropicPBC.Claude_fnn82j28hfe8t"];const r="Get-Process -Name claude -ErrorAction SilentlyContinue | Where-Object { $_.Path -and ($_.Path -like '*\\AnthropicClaude\\*' -or $_.Path -like '*\\Programs\\Claude\\*' -or $_.Path -like '*\\WindowsApps\\*Claude*') }";let o=(r,o,s=3e4)=>{const n=e(r,o,{encoding:"utf-8",timeout:s,windowsHide:!0,stdio:["ignore","pipe","pipe"]});return n.error&&t.logError(`desktop-process: ${r}`,n.error),{status:n.status,stdout:`${n.stdout??""}`}};export function setDesktopProcessRunnerForTests(e){o=e}function s(e,t){return o("powershell.exe",["-NoProfile","-NonInteractive","-Command",e],t)}function n(e){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e)}export function isDesktopRunning(){return"darwin"===process.platform?0===o("pgrep",["-x","Claude"]).status:"win32"===process.platform&&Number(s(`@(${r}).Count`).stdout.trim())>0}export function canRestartDesktop(){return"darwin"===process.platform||"win32"===process.platform}export function quitDesktop(){if("darwin"===process.platform){o("osascript",["-e",'quit app "Claude"']);for(let e=0;e<30&&isDesktopRunning();e++)n(500);isDesktopRunning()&&o("pkill",["-x","Claude"]),n(1e3)}else{if("win32"!==process.platform)return!1;s([`$p = @(${r})`,"$p | ForEach-Object { [void]$_.CloseMainWindow() }","Start-Sleep -Seconds 3","$p | Where-Object { -not $_.HasExited } | Stop-Process -Force -ErrorAction SilentlyContinue","Start-Sleep -Seconds 1"].join("\n"),6e4)}return!isDesktopRunning()}export function launchDesktop(){if("darwin"===process.platform)o("open",["-a","Claude"]);else{if("win32"!==process.platform)return!1;s(["$squirrel = Join-Path $env:LOCALAPPDATA 'AnthropicClaude\\claude.exe'","$programs = Join-Path $env:LOCALAPPDATA 'Programs\\Claude\\Claude.exe'","if (Test-Path $squirrel) { Start-Process $squirrel }","elseif (Test-Path $programs) { Start-Process $programs }",`else { $pkg = Get-AppxPackage | Where-Object { @(${WINDOWS_PACKAGE_FAMILIES.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName } | Select-Object -First 1`," if ($pkg) { $id = (Get-AppxPackageManifest $pkg).Package.Applications.Application.Id | Select-Object -First 1",' Start-Process "shell:AppsFolder\\$($pkg.PackageFamilyName)!$id" } }'].join("\n"),6e4)}for(let e=0;e<20;e++){if(isDesktopRunning())return!0;n(500)}return!1}export function restartDesktop(){return!!canRestartDesktop()&&(quitDesktop(),launchDesktop())}
1
+ import{spawnSync as e}from"child_process";import{logger as t}from"../../utils/logger.js";import{powerShellEnv as r}from"../powershell-env.js";export const WINDOWS_PACKAGE_FAMILIES=["Claude_pzs8sxrjxfjjc","AnthropicPBC.Claude_fnn82j28hfe8t"];const o="Get-Process -Name claude -ErrorAction SilentlyContinue | Where-Object { $_.Path -and ($_.Path -like '*\\AnthropicClaude\\*' -or $_.Path -like '*\\Programs\\Claude\\*' -or $_.Path -like '*\\WindowsApps\\*Claude*') }";let s=(o,s,n=3e4)=>{const i=e(o,s,{encoding:"utf-8",timeout:n,windowsHide:!0,stdio:["ignore","pipe","pipe"],env:r()});return i.error&&t.logError(`desktop-process: ${o}`,i.error),{status:i.status,stdout:`${i.stdout??""}`}};export function setDesktopProcessRunnerForTests(e){s=e}function n(e,t){return s("powershell.exe",["-NoProfile","-NonInteractive","-Command",e],t)}function i(e){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e)}export function isDesktopRunning(){return"darwin"===process.platform?0===s("pgrep",["-x","Claude"]).status:"win32"===process.platform&&Number(n(`@(${o}).Count`).stdout.trim())>0}export function canRestartDesktop(){return"darwin"===process.platform||"win32"===process.platform}export function quitDesktop(){if("darwin"===process.platform){s("osascript",["-e",'quit app "Claude"']);for(let e=0;e<30&&isDesktopRunning();e++)i(500);isDesktopRunning()&&s("pkill",["-x","Claude"]),i(1e3)}else{if("win32"!==process.platform)return!1;n([`$p = @(${o})`,"$p | ForEach-Object { [void]$_.CloseMainWindow() }","Start-Sleep -Seconds 3","$p | Where-Object { -not $_.HasExited } | Stop-Process -Force -ErrorAction SilentlyContinue","Start-Sleep -Seconds 1"].join("\n"),6e4)}return!isDesktopRunning()}export function launchDesktop(){if("darwin"===process.platform)s("open",["-a","Claude"]);else{if("win32"!==process.platform)return!1;n(["$squirrel = Join-Path $env:LOCALAPPDATA 'AnthropicClaude\\claude.exe'","$programs = Join-Path $env:LOCALAPPDATA 'Programs\\Claude\\Claude.exe'","if (Test-Path $squirrel) { Start-Process $squirrel }","elseif (Test-Path $programs) { Start-Process $programs }",`else { $pkg = Get-AppxPackage | Where-Object { @(${WINDOWS_PACKAGE_FAMILIES.map(e=>`'${e}'`).join(",")}) -contains $_.PackageFamilyName } | Select-Object -First 1`," if ($pkg) { $id = (Get-AppxPackageManifest $pkg).Package.Applications.Application.Id | Select-Object -First 1",' Start-Process "shell:AppsFolder\\$($pkg.PackageFamilyName)!$id" } }'].join("\n"),6e4)}for(let e=0;e<20;e++){if(isDesktopRunning())return!0;i(500)}return!1}export function restartDesktop(){return!!canRestartDesktop()&&(quitDesktop(),launchDesktop())}
@@ -1 +1 @@
1
- import{spawnSync as r}from"child_process";import{mkdtempSync as e,rmSync as t,writeFileSync as o}from"fs";import{tmpdir as n}from"os";import{join as i}from"path";import{logger as s}from"../../utils/logger.js";import{CLI_NAME as u}from"../brand.js";function f(r){return`"${r.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}export function buildRegFile(r,e,t,o=!1){const n=`HKEY_USERS\\${r}\\${e}`;return o?`Windows Registry Editor Version 5.00\r\n\r\n[-${n}]\r\n`:`Windows Registry Editor Version 5.00\r\n\r\n[${n}]\r\n${Object.entries(t).map(([r,e])=>`${f(r)}=${null===e?"-":function(r){return"boolean"==typeof r?"dword:"+(r?"00000001":"00000000"):"number"==typeof r?`dword:${(r>>>0).toString(16).padStart(8,"0")}`:f("string"==typeof r?r:JSON.stringify(r))}(e)}`).join("\r\n")}\r\n`}let d=()=>{const e=r("whoami",["/user","/fo","csv","/nh"],{encoding:"utf-8",windowsHide:!0});return/"(S-1-[\d-]+)"/.exec(`${e.stdout??""}`)?.[1]??null},l=e=>{const t=r("powershell.exe",["-NoProfile","-NonInteractive","-Command",`$p = Start-Process -FilePath 'reg.exe' -ArgumentList @('import', '"${e}"') -Verb RunAs -Wait -PassThru -WindowStyle Hidden; exit $p.ExitCode`],{encoding:"utf-8",windowsHide:!0,timeout:3e5});return 0!==t.status&&s.logError("elevatedImport",new Error(`${t.stderr??""}`.trim()||`exit ${t.status}`)),0===t.status};export function setElevationForTests(r,e){d=r,l=e}export function setUserRegistryElevated(r,s,f=!1){const c=d();if(!c)return!1;const m=e(i(n(),`${u}-reg-`)),a=i(m,`${u}.reg`);try{return o(a,Buffer.concat([Buffer.from([255,254]),Buffer.from(buildRegFile(c,r,s,f),"utf16le")])),l(a)}finally{t(m,{recursive:!0,force:!0})}}
1
+ import{spawnSync as r}from"child_process";import{mkdtempSync as e,rmSync as t,writeFileSync as o}from"fs";import{tmpdir as n}from"os";import{join as i}from"path";import{logger as s}from"../../utils/logger.js";import{CLI_NAME as u}from"../brand.js";import{powerShellEnv as f}from"../powershell-env.js";function d(r){return`"${r.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}export function buildRegFile(r,e,t,o=!1){const n=`HKEY_USERS\\${r}\\${e}`;return o?`Windows Registry Editor Version 5.00\r\n\r\n[-${n}]\r\n`:`Windows Registry Editor Version 5.00\r\n\r\n[${n}]\r\n${Object.entries(t).map(([r,e])=>`${d(r)}=${null===e?"-":function(r){return"boolean"==typeof r?"dword:"+(r?"00000001":"00000000"):"number"==typeof r?`dword:${(r>>>0).toString(16).padStart(8,"0")}`:d("string"==typeof r?r:JSON.stringify(r))}(e)}`).join("\r\n")}\r\n`}let l=()=>{const e=r("whoami",["/user","/fo","csv","/nh"],{encoding:"utf-8",windowsHide:!0});return/"(S-1-[\d-]+)"/.exec(`${e.stdout??""}`)?.[1]??null},m=e=>{const t=r("powershell.exe",["-NoProfile","-NonInteractive","-Command",`$p = Start-Process -FilePath 'reg.exe' -ArgumentList @('import', '"${e}"') -Verb RunAs -Wait -PassThru -WindowStyle Hidden; exit $p.ExitCode`],{encoding:"utf-8",windowsHide:!0,timeout:3e5,env:f()});return 0!==t.status&&s.logError("elevatedImport",new Error(`${t.stderr??""}`.trim()||`exit ${t.status}`)),0===t.status};export function setElevationForTests(r,e){l=r,m=e}export function setUserRegistryElevated(r,s,f=!1){const d=l();if(!d)return!1;const c=e(i(n(),`${u}-reg-`)),p=i(c,`${u}.reg`);try{return o(p,Buffer.concat([Buffer.from([255,254]),Buffer.from(buildRegFile(d,r,s,f),"utf16le")])),m(p)}finally{t(c,{recursive:!0,force:!0})}}
@@ -1 +1 @@
1
- import{execFileSync as e,spawn as r}from"child_process";import{logger as n}from"../utils/logger.js";import{brandEnvName as t}from"./brand.js";const o={user:"HKCU\\Environment",machine:"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"},s=r=>e("reg.exe",r,{encoding:"utf-8",windowsHide:!0,timeout:15e3,stdio:["ignore","pipe","pipe"]}),i=()=>{const e=r("powershell.exe",["-NoProfile","-NonInteractive","-Command",`[Environment]::SetEnvironmentVariable('${t("ENV_REFRESH")}',$null,'User')`],{detached:!0,stdio:"ignore",windowsHide:!0});e.on("error",e=>n.logError("windowsEnv.broadcast",e)),e.unref()};let a=s,d=i;export function setWindowsEnvRunnersForTests(e,r){a=e??s,d=e?r??(()=>{}):i}export function readWindowsEnv(e,r){let n;try{n=a(["query",o[e],"/v",r])}catch{return}const t=n.match(new RegExp(String.raw`^\s*${r}\s+REG_(?:EXPAND_)?SZ\s+(.*?)\r?$`,"im"));return t?t[1]:void 0}export function addUserPathDir(e){let r="REG_EXPAND_SZ",n="";try{const e=a(["query",o.user,"/v","Path"]).match(/^\s*Path\s+(REG_(?:EXPAND_)?SZ)\s+(.*?)\r?$/im);e&&([,r,n]=e)}catch{}const t=e=>(e=>e.replace(/%([^%]+)%/g,(e,r)=>process.env[r]??e))(e).replace(/[\\/]+$/,"").toLowerCase();return!n.split(";").some(r=>r&&t(r)===t(e))&&(a(["add",o.user,"/v","Path","/t",r,"/d",n?`${n.replace(/;+$/,"")};${e}`:e,"/f"]),!0)}export function setUserEnv(e,r){a(["add",o.user,"/v",e,"/t","REG_SZ","/d",r,"/f"])}export function deleteWindowsEnv(e,r){a(["delete",o[e],"/v",r,"/f"])}export function broadcastEnvChange(){d()}
1
+ import{execFileSync as e,spawn as r}from"child_process";import{logger as n}from"../utils/logger.js";import{brandEnvName as t}from"./brand.js";import{powerShellEnv as o}from"./powershell-env.js";const s={user:"HKCU\\Environment",machine:"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"},i=r=>e("reg.exe",r,{encoding:"utf-8",windowsHide:!0,timeout:15e3,stdio:["ignore","pipe","pipe"]}),a=()=>{const e=r("powershell.exe",["-NoProfile","-NonInteractive","-Command",`[Environment]::SetEnvironmentVariable('${t("ENV_REFRESH")}',$null,'User')`],{detached:!0,stdio:"ignore",windowsHide:!0,env:o()});e.on("error",e=>n.logError("windowsEnv.broadcast",e)),e.unref()};let d=i,c=a;export function setWindowsEnvRunnersForTests(e,r){d=e??i,c=e?r??(()=>{}):a}export function readWindowsEnv(e,r){let n;try{n=d(["query",s[e],"/v",r])}catch{return}const t=n.match(new RegExp(String.raw`^\s*${r}\s+REG_(?:EXPAND_)?SZ\s+(.*?)\r?$`,"im"));return t?t[1]:void 0}export function addUserPathDir(e){let r="REG_EXPAND_SZ",n="";try{const e=d(["query",s.user,"/v","Path"]).match(/^\s*Path\s+(REG_(?:EXPAND_)?SZ)\s+(.*?)\r?$/im);e&&([,r,n]=e)}catch{}const t=e=>(e=>e.replace(/%([^%]+)%/g,(e,r)=>process.env[r]??e))(e).replace(/[\\/]+$/,"").toLowerCase();return!n.split(";").some(r=>r&&t(r)===t(e))&&(d(["add",s.user,"/v","Path","/t",r,"/d",n?`${n.replace(/;+$/,"")};${e}`:e,"/f"]),!0)}export function setUserEnv(e,r){d(["add",s.user,"/v",e,"/t","REG_SZ","/d",r,"/f"])}export function deleteWindowsEnv(e,r){d(["delete",s[e],"/v",r,"/f"])}export function broadcastEnvChange(){c()}
@@ -1 +1 @@
1
- import e from"inquirer";import t from"chalk";import a from"ora";import{configManager as o,DEFAULT_MODELS as i}from"./config.js";import{getPresets as n,resolvePreset as r,getToolDefaultModel as s}from"./model-registry.js";import{toolManager as l,SUPPORTED_TOOLS as c}from"./tool-manager.js";import{confirmWritePlan as d}from"./write-plan.js";import{postApplyPrompts as p}from"./post-apply.js";import{appStatus as m,appStatusText as u,appTools as _,cachedAppStatus as g,upgradeApp as w}from"./app-update.js";import{i18n as f,detectSystemLang as y}from"./i18n.js";import{createBorderLine as h,createContentLine as z}from"../utils/string-width.js";import{validateApiKey as v,fetchModels as k}from"./api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as x}from"./tools/codex.js";import{CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as b}from"./tools/claude-desktop.js";import{addressesWithCurrent as S,ensureReachableGatewayAddress as C,fastestIndex as M,probeAll as T,probeSummary as A,reasonText as N,savedApiKey as K,switchGatewayAddress as B}from"../commands/base.js";import{readFileSync as P}from"fs";import{dirname as j,join as H}from"path";import{fileURLToPath as O}from"url";import{brand as W}from"./brand.js";const L=j(O(import.meta.url)),F=t.hex("#FF8700");export class Wizard{static instance;BOX_WIDTH=63;validatedApiKeys=new Set;constructor(){}static getInstance(){return Wizard.instance||(Wizard.instance=new Wizard),Wizard.instance}createBox(e){console.log(F.bold("\n"+h("╔","╗","═",this.BOX_WIDTH))),console.log(F.bold(z(e,"║","║",this.BOX_WIDTH,"center"))),console.log(F.bold(h("╚","╝","═",this.BOX_WIDTH))),console.log("")}showOperationHints(){const e=[t.gray(f.t("wizard.hint_navigate")),t.gray(f.t("wizard.hint_confirm"))];console.log(t.gray("💡 ")+e.join(t.gray(" | "))+"\n")}async promptWithHints(t){this.showOperationHints();const a=t.map(e=>"list"!==e.type||e.pageSize?e:{...e,pageSize:20});return e.prompt(a)}printBanner(){const e=60,t=f.t("wizard.banner_subtitle"),a=z(t,"║","║",e,"center"),o=z("","║","║",e,"center"),i=z(`${W().productName} v${function(){try{return JSON.parse(P(H(L,"..","..","package.json"),"utf-8")).version}catch{return"0.0.0"}}()}`,"║","║",e,"center"),n=[String.raw`__ ___ _ ____ _ ___ `,String.raw`\ \ / (_) |__ ___ / ___| | |_ _|`,String.raw` \ \ / /| | '_ \ / _ \ | | | | | `,String.raw` \ V / | | |_) | __/ |___| |___ | | `,String.raw` \_/ |_|_.__/ \___|\____|_____|___|`],r=Math.max(...n.map(e=>e.length)),s=" ".repeat(Math.floor((58-r)/2)),l=n.map(t=>z(s+t,"║","║",e,"left")),c=[h("╔","╗","═",e),o,...l,o,i,a,h("╚","╝","═",e)];console.log(F.bold("\n"+c.join("\n")))}resetScreen(){console.clear(),this.printBanner()}printGoodbye(){const e=l.getSupportedTools().filter(e=>{if(e.gui)return!1;try{return Boolean(l.detectCurrentConfig(e.name).apiKey)&&l.isToolInstalled(e.name)}catch{return!1}});let a;if(e.length>0){const t=e.map(e=>e.command).join(" / ");a=f.t("wizard.goodbye_message_tools",{commands:t}),e.some(e=>"claude-code"===e.name)&&(a+=" "+f.t("wizard.goodbye_claude_hint"))}else a=f.t("wizard.goodbye_message");console.log(t.green("\n👋 "+a)),this.printPathReloadHint(e.map(e=>e.name))}printPathReloadHint(e){const a=e.filter(e=>!l.isOnPath(e));if(0===a.length)return;const o=a.map(e=>c[e].command).join(" / ");console.log(t.yellow(" ! "+f.t("win32"===process.platform?"setup.path_reload_windows":"setup.path_reload",{commands:o})))}async runFirstTimeSetup(){const e="zh_CN"===y();e&&(o.setLang("zh_CN"),f.setLocale("zh_CN")),this.resetScreen(),console.log(F.bold("\n"+f.t("wizard.welcome"))),console.log(t.gray(f.t("wizard.privacy_note")+"\n")),e?console.log(t.gray(f.t("wizard.lang_auto_zh")+"\n")):await this.configLanguage(),await C(),await this.configApiKey()&&await this.selectAndConfigureTool(!0)}async configLanguage(){for(;;){this.resetScreen(),this.createBox(f.t("wizard.select_language"));const a=f.getLocale(),{language:i}=await this.promptWithHints([{type:"list",name:"language",message:"✨ "+f.t("wizard.select_language"),choices:[{name:"[EN] English"+("en_US"===a?t.green(" ✓ ("+f.t("wizard.current_active")+")"):""),value:"en_US"},{name:"[CN] 中文"+("zh_CN"===a?t.green(" ✓ ("+f.t("wizard.current_active")+")"):""),value:"zh_CN"},new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:"back"},{name:"x "+f.t("wizard.nav_exit"),value:"exit"}],default:"zh_CN"}]);if("exit"===i)this.printGoodbye(),process.exit(0);else if("back"===i)return;return o.setLang(i),void f.setLocale(i)}}buildPresetChoices(){const a=n(),o=a.filter(e=>e.recommended),i=a.filter(e=>!e.recommended),r=e=>({name:(f.t(e.name)!==e.name?f.t(e.name):e.name)+(e.models?t.gray(` [H:${e.models.haiku} S:${e.models.sonnet} O:${e.models.opus}]`):""),value:{type:"preset",preset:e}}),s=[];return o.length>0&&(s.push(new e.Separator(t.hex("#FF8700")("── "+f.t("wizard.recommended")+" ──"))),s.push(...o.map(r))),i.length>0&&(s.push(new e.Separator(t.gray("── "+f.t("wizard.other_models")+" ──"))),s.push(...i.map(r))),s}async handleCustomModelInput(){const a=o.getModels(),{customMode:n}=await e.prompt([{type:"list",name:"customMode",message:f.t("wizard.custom_model_mode"),choices:[{name:f.t("wizard.custom_model_single"),value:"single"},{name:f.t("wizard.custom_model_per_role"),value:"per_role"}]}]);if("single"===n){const{customModel:t}=await e.prompt([{type:"input",name:"customModel",message:f.t("wizard.input_custom_model"),default:i.sonnet}]);o.setModels({haiku:t,sonnet:t,opus:t,reasoning:t})}else{const t=await e.prompt([{type:"input",name:"haiku",message:f.t("wizard.model_haiku"),default:a.haiku},{type:"input",name:"sonnet",message:f.t("wizard.model_sonnet"),default:a.sonnet},{type:"input",name:"opus",message:f.t("wizard.model_opus"),default:a.opus},{type:"input",name:"reasoning",message:f.t("wizard.model_reasoning"),default:a.reasoning}]);o.setModels(t)}console.log(t.green("\n✓ "+f.t("wizard.models_saved")))}async configModels(a){const i=o.getApiKey();if(await this.validatedKeyForConfiguration(i))for(;;){this.resetScreen(),this.createBox(f.t("wizard.config_models"));const i=[...this.buildPresetChoices()];i.push(new e.Separator),i.push({name:"✏️ "+f.t("wizard.custom_model_input"),value:{type:"custom_input"}}),i.push(new e.Separator),i.push({name:"<- "+f.t("wizard.nav_return"),value:{type:"back"}}),i.push({name:"x "+f.t("wizard.nav_exit"),value:{type:"exit"}});const{modelChoice:n}=await this.promptWithHints([{type:"list",name:"modelChoice",message:f.t("wizard.select_model_config"),choices:i}]);if("exit"===n.type)this.printGoodbye(),process.exit(0);else{if("back"===n.type)return;if("custom_input"===n.type)return await this.handleCustomModelInput(),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig());if("preset"===n.type){const e=r(n.preset);return o.setModels(e),console.log(t.green("\n✓ "+f.t("wizard.models_saved"))),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}}}else await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}async promptLoadAfterModelConfig(){const{shouldLoad:t}=await e.prompt([{type:"list",name:"shouldLoad",message:f.t("wizard.load_config_now"),choices:[{name:f.t("wizard.load_config_yes"),value:!0},{name:f.t("wizard.load_config_later"),value:!1}]}]);t&&await this.selectAndConfigureTool()}async configBaseUrl(){const i=o.getBaseUrl(),n=S(),r=a(f.t("wizard.base_testing")).start(),s=await T(n,{apiKey:K(),samples:3});r.stop();const l=M(s),c=n.map((e,a)=>{const o=e.url===i?t.cyan(` ← ${f.t("base.current_mark")}`):"";return{name:`${e.url} ${t.gray(e.label)} ${A(s[a],a===l)}${o}`,value:e.url}});c.push(new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:"__back__"});const{url:d}=await this.promptWithHints([{type:"list",name:"url",message:f.t("wizard.base_select"),choices:c,default:i}]);if("__back__"===d)return;const p=s[n.findIndex(e=>e.url===d)];p.ok?await B(d):console.log(t.red(f.t("base.unreachable",{url:d,reason:N(p)}))),await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}async configApiKey(){for(;;){this.resetScreen(),this.createBox(f.t("wizard.input_api_key")),console.log(t.gray("\n💡 "+f.t("wizard.api_key_input_hint"))),console.log(t.gray(" "+f.t("wizard.api_key_get_hint",{url:W().links.tokenPage}))),console.log();const{apiKey:i}=await e.prompt([{type:"password",name:"apiKey",message:f.t("wizard.input_your_api_key"),mask:"*"}]);if(!i||""===i.trim()){const{action:t}=await e.prompt([{type:"list",name:"action",message:f.t("wizard.select_action"),choices:[{name:f.t("wizard.retry_input"),value:"retry"},{name:"<- "+f.t("wizard.nav_return"),value:"back"}]}]);if("back"===t)return!1;continue}const n=a(f.t("wizard.validating_api_key")).start(),r=await v(i.trim());if(n.stop(),r.valid)return o.setApiKey(i.trim()),this.validatedApiKeys.add(i.trim()),console.log(t.green("\n✓ "+f.t("wizard.api_key_valid"))),!0;{this.validatedApiKeys.delete(i.trim()),"invalid_api_key"===r.error?console.log(t.red("\n✗ "+f.t("wizard.api_key_invalid"))):console.log(t.red("\n✗ "+f.t("wizard.api_key_network_error")));const{action:a}=await e.prompt([{type:"list",name:"action",message:f.t("wizard.select_action"),choices:[{name:f.t("wizard.retry_input"),value:"retry"},{name:"<- "+f.t("wizard.nav_return"),value:"back"}]}]);if("back"===a)return!1}}}async selectAndConfigureTool(a=!1){for(const e of _())await m(e).catch(()=>{});for(;;){this.resetScreen(),this.createBox(f.t("wizard.select_tool"));const o=l.getSupportedTools().map(e=>{const a=_().includes(e.name)?g(e.name):null;return{name:e.displayName+(a?.outdated?t.yellow(" "+u(a)):""),value:e.name}}),{tool:i}=await this.promptWithHints([{type:"list",name:"tool",message:"🛠️ "+f.t("wizard.select_tool"),choices:[...o,new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:"back"},{name:"x "+f.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===i)this.printGoodbye(),process.exit(0);else if("back"===i)return;await this.configureTool(i,a)}}async configureTool(a,o=!1){const i=c[a];if(i){if(!l.isToolInstalled(a)){console.log(t.yellow("\n"+f.t("wizard.tool_not_installed",{tool:i.displayName})));const{install:o}=await e.prompt([{type:"confirm",name:"install",message:f.t("wizard.install_tool_confirm"),default:!0}]);if(!o)return;try{await l.installTool(a)}catch{return void console.log(t.red(f.t("wizard.install_failed")))}}o?await this.configureToolModel(a)&&await this.loadConfig(a):await this.showToolMenu(a)}}async showToolMenu(t){for(;;){this.resetScreen();const a=c[t];if(!a)return;this.createBox(a.displayName+" "+f.t("wizard.menu_title"));const o=[{name:"📥 "+f.t("wizard.action_load_config",{tool:a.displayName}),value:"load"},{name:"📤 "+f.t("wizard.action_unload_config",{tool:a.displayName}),value:"unload"}];l.supportsClearPinnedModels(t)&&o.push({name:"🧹 "+f.t("wizard.action_clear_model",{tool:a.displayName}),value:"clear-model"});const i=_().includes(t)?g(t):null;if(i&&!i.blocker&&i.latest&&(i.outdated||!i.installed)){const e=i.installed?f.t("wizard.action_upgrade_app",{tool:a.displayName,current:i.current??"?",latest:i.latest}):f.t("wizard.action_install_app",{tool:a.displayName,latest:i.latest});o.unshift({name:"↑ "+e,value:"upgrade-app"})}o.push({name:"🧨 "+f.t("wizard.action_force_config",{tool:a.displayName}),value:"force"},{name:"↩️ "+f.t("wizard.action_restore_config",{tool:a.displayName}),value:"restore"},new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:"back"},{name:"x "+f.t("wizard.nav_exit"),value:"exit"});const{action:n}=await this.promptWithHints([{type:"list",name:"action",message:"⚙️ "+f.t("wizard.select_action"),choices:o}]);if("exit"===n)this.printGoodbye(),process.exit(0);else{if("back"===n)return;"load"===n?await this.configureToolModel(t)&&await this.loadConfig(t):"force"===n?await this.forceConfig(t):"unload"===n?await this.unloadConfig(t):"upgrade-app"===n?(await w(t,{install:!0}),await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])):"clear-model"===n?await this.clearPinnedModels(t):"restore"===n&&await this.restoreConfig(t)}}}singleModelOverride(e){const t=e.trim();return/claude/i.test(t)?{opus:t}:{haiku:t,sonnet:t,opus:t,reasoning:t}}hasConfiguredApiKey(){return!!o.getApiKey()?.trim()||o.listToolApiKeys().some(e=>Boolean(o.getApiKeyForTool(e)?.trim()))}async validatedKeyForConfiguration(e){const o=e?.trim();if(!o)return console.log(t.red("\n"+f.t("wizard.api_key_required"))),console.log(t.yellow(f.t("wizard.please_config_api_key_first"))),null;if(this.validatedApiKeys.has(o))return o;const i=a(f.t("wizard.validating_api_key")).start(),n=await v(o);if(n.valid)return this.validatedApiKeys.add(o),i.succeed(f.t("wizard.api_key_valid")),o;this.validatedApiKeys.delete(o);const r="invalid_api_key"===n.error?f.t("wizard.api_key_invalid"):f.t("wizard.api_key_network_error");return i.fail(r),console.log(t.red("\n"+f.t("wizard.please_reconfig_api_key"))),null}async configureToolModel(i){const n=c[i];if(!n)return!1;const l=await this.validatedKeyForConfiguration(o.getApiKeyForTool(i));if(!l)return await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}]),!1;const d="claude-code"===i,p=d||"claude-desktop"===i||"agy"===i,m=s(i),u=p||!m?f.t("wizard.model_builtin_default"):m;this.resetScreen(),this.createBox(n.displayName+" · "+f.t("wizard.config_models"));const _=[{name:"✅ "+f.t("wizard.use_default_model",{model:u}),value:{type:"default"}},{name:"🌐 "+f.t("wizard.fetch_models_from_api"),value:{type:"fetch"}},...this.buildPresetChoices(),new e.Separator,{name:"✏️ "+f.t("wizard.input_custom_model"),value:{type:"custom"}},new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:{type:"back"}}],{choice:g}=await this.promptWithHints([{type:"list",name:"choice",message:f.t("wizard.select_tool_model",{tool:n.displayName}),choices:_}]);if("back"===g.type)return!1;if("default"===g.type)o.setToolModel(i,null);else if("preset"===g.type)o.setToolModel(i,r(g.preset));else if("custom"===g.type){const{model:t}=await e.prompt([{type:"input",name:"model",message:f.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]),a=(t||"").trim();o.setToolModel(i,a?this.singleModelOverride(a):null)}else if("fetch"===g.type){const n=a(f.t("wizard.fetching_models")).start(),r=await k(l);let s;if(n.stop(),r.ok&&r.models.length>0){const{model:t}=await e.prompt([{type:"list",name:"model",message:f.t("wizard.select_fetched_model"),pageSize:20,choices:[...r.models,new e.Separator,{name:"<- "+f.t("wizard.nav_return"),value:"__back__"}]}]);if("__back__"===t)return!1;s=t}else{console.log(t.yellow("\n"+f.t("wizard.fetch_models_failed")));const{model:a}=await e.prompt([{type:"input",name:"model",message:f.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]);s=(a||"").trim()}o.setToolModel(i,s?this.singleModelOverride(s):null)}if("codex"===i){const t=o.getToolSetting(i,x),{enableOneMillionContext:a}=await e.prompt([{type:"confirm",name:"enableOneMillionContext",message:f.t("wizard.codex_enable_1m_context"),default:!1!==t}]);o.setToolSetting(i,x,Boolean(a))}if("claude-desktop"===i){const t=o.getToolSetting(i,b),{hideOfficialLogin:a}=await e.prompt([{type:"confirm",name:"hideOfficialLogin",message:f.t("wizard.desktop_hide_official_login"),default:!1!==t}]);o.setToolSetting(i,b,Boolean(a))}return console.log(t.green("\n✓ "+f.t("wizard.models_saved"))),d&&console.log(t.gray("💡 "+f.t("wizard.claude_model_hint"))),!0}async forceConfig(t){const a=c[t]?.displayName||t,{confirm:o}=await e.prompt([{type:"confirm",name:"confirm",message:f.t("config.confirm_force",{tool:a}),default:!1}]);o&&await this.loadConfig(t,{force:!0})}async loadConfig(i,n={}){const r=o.getModelsForTool(i),s=await this.validatedKeyForConfiguration(o.getApiKeyForTool(i));if(!s)return void await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}]);if(!n.force&&!await d([i]))return;const m=a(f.t("wizard.loading_config")).start();try{await l.applyPrivateConfig(i,s,r,n),m.stop(),l.printApplied(i),await p([i],{apps:{install:!1}}),n.force&&console.log(t.yellow(f.t("config.force_done",{tool:c[i]?.displayName||i,name:i})));const a=c[i];a&&!a.gui&&(l.isOnPath(i)&&console.log(t.green("\n"+f.t("wizard.run_tool_hint",{command:a.command}))),this.printPathReloadHint([i]));const{nextAction:o}=await e.prompt([{type:"list",name:"nextAction",message:f.t("wizard.what_next"),choices:[{name:f.t("wizard.exit_and_start"),value:"exit"},{name:f.t("wizard.continue_config"),value:"continue"}]}]);"exit"===o&&(this.printGoodbye(),process.exit(0))}catch(a){m.fail(f.t("wizard.config_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}}async clearPinnedModels(a){const o=c[a]?.displayName||a,{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:f.t("wizard.confirm_clear_model",{tool:o}),default:!1}]);if(i){try{const e=await l.clearPinnedModels(a);0===e.length?console.log(t.yellow("\n"+f.t("config.clear_model_none",{tool:o}))):(console.log(t.green("\n✓ "+f.t("config.clear_model_done",{tool:o}))),e.forEach(e=>console.log(t.gray(` - ${e}`))),console.log(t.gray(f.t("config.clear_model_restart_hint",{tool:o}))))}catch(e){console.log(t.red("\n"+(e instanceof Error?e.message:String(e))))}await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}}async unloadConfig(o){const{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:f.t("wizard.confirm_unload_config",{tool:c[o]?.displayName||o}),default:!1}]);if(!i)return;const n=a(f.t("wizard.unloading_config")).start();try{const a=l.holdsOurConfig(o),i=l.unloadPrivateConfig(o);if(!a)return void n.info(f.t("config.remove_nothing",{tool:c[o]?.displayName||o}));n.succeed(f.t("wizard.config_unloaded")),i.forEach(e=>console.log(t.yellow(" ! "+e.text)));const{nextAction:r}=await e.prompt([{type:"list",name:"nextAction",message:f.t("wizard.what_next"),choices:[{name:f.t("wizard.nav_exit"),value:"exit"},{name:f.t("wizard.continue_config"),value:"continue"}]}]);"exit"===r&&(this.printGoodbye(),process.exit(0))}catch(a){n.fail(f.t("wizard.config_unload_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}}async restoreConfig(o){const i=c[o]?.displayName||o,{confirm:n}=await e.prompt([{type:"confirm",name:"confirm",message:f.t("wizard.confirm_restore_config",{tool:i}),default:!1}]);if(!n)return;const r=a(f.t("wizard.restoring_config")).start();try{const e=l.restorePrivateConfig(o).filter(e=>e.result.restored);0===e.length?r.warn(f.t("wizard.restore_no_backup")):(r.succeed(f.t("wizard.config_restored",{tool:i})),e.forEach(e=>console.log(t.gray(` ${e.file} ← ${e.result.from}`))),console.log(t.yellow(" ! "+f.t("config.reopen_hint",{tool:i}))))}catch(e){r.fail(f.t("wizard.config_restore_failed")),console.log(t.red(e instanceof Error?e.message:String(e)))}await e.prompt([{type:"input",name:"continue",message:f.t("wizard.press_enter")}])}async run(){await this.showMainMenu()}async showMainMenu(){if(this.hasConfiguredApiKey())for(;;){this.resetScreen();const a=o.getApiKey()||"",i=a.length>4?"sk-****"+a.slice(-4):"****";console.log(t.gray(` 🔑 API Key: ${i}`)+t.green(" ✓")),console.log("");const n=l.getSupportedTools().map(e=>({name:"🛠️ "+e.displayName,value:{type:"tool",tool:e.name}})),r=[new e.Separator(F("── "+f.t("wizard.select_tool")+" ──")),...n,new e.Separator(t.gray("── "+f.t("wizard.settings")+" ──")),{name:"🔑 "+f.t("wizard.menu_change_api_key"),value:{type:"apikey"}},{name:"🔗 "+f.t("wizard.menu_base_url",{url:o.getBaseUrl()}),value:{type:"base"}},{name:"🌐 "+f.t("wizard.menu_config_language"),value:{type:"language"}},new e.Separator,{name:"x "+f.t("wizard.nav_exit"),value:{type:"exit"}}],{action:s}=await this.promptWithHints([{type:"list",name:"action",message:"🛠️ "+f.t("wizard.select_tool"),choices:r}]);"exit"===s.type?(this.printGoodbye(),process.exit(0)):"tool"===s.type?await this.configureTool(s.tool):"apikey"===s.type?await this.configApiKey():"base"===s.type?await this.configBaseUrl():"language"===s.type&&await this.configLanguage()}else await this.runFirstTimeSetup()}}export const wizard=Wizard.getInstance();
1
+ import e from"inquirer";import t from"chalk";import a from"ora";import{configManager as o,DEFAULT_MODELS as i}from"./config.js";import{getPresets as n,resolvePreset as r,getToolDefaultModel as s}from"./model-registry.js";import{toolManager as l,SUPPORTED_TOOLS as c}from"./tool-manager.js";import{confirmWritePlan as d}from"./write-plan.js";import{postApplyPrompts as p}from"./post-apply.js";import{appStatus as m,appStatusText as u,appTools as _,appsForTools as g,cachedAppStatus as w,upgradeApp as f}from"./app-update.js";import{i18n as y,detectSystemLang as h}from"./i18n.js";import{createBorderLine as z,createContentLine as v}from"../utils/string-width.js";import{validateApiKey as k,fetchModels as x}from"./api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as b}from"./tools/codex.js";import{CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as S}from"./tools/claude-desktop.js";import{addressesWithCurrent as C,ensureReachableGatewayAddress as M,fastestIndex as T,probeAll as A,probeSummary as K,reasonText as N,savedApiKey as B,switchGatewayAddress as P}from"../commands/base.js";import{readFileSync as W}from"fs";import{dirname as j,join as H}from"path";import{fileURLToPath as O}from"url";import{brand as L}from"./brand.js";const $=j(O(import.meta.url)),F=t.hex("#FF8700");export class Wizard{static instance;BOX_WIDTH=63;validatedApiKeys=new Set;constructor(){}static getInstance(){return Wizard.instance||(Wizard.instance=new Wizard),Wizard.instance}createBox(e){console.log(F.bold("\n"+z("╔","╗","═",this.BOX_WIDTH))),console.log(F.bold(v(e,"║","║",this.BOX_WIDTH,"center"))),console.log(F.bold(z("╚","╝","═",this.BOX_WIDTH))),console.log("")}showOperationHints(){const e=[t.gray(y.t("wizard.hint_navigate")),t.gray(y.t("wizard.hint_confirm"))];console.log(t.gray("💡 ")+e.join(t.gray(" | "))+"\n")}async promptWithHints(t){this.showOperationHints();const a=t.map(e=>"list"!==e.type||e.pageSize?e:{...e,pageSize:20});return e.prompt(a)}printBanner(){const e=60,t=y.t("wizard.banner_subtitle"),a=v(t,"║","║",e,"center"),o=v("","║","║",e,"center"),i=v(`${L().productName} v${function(){try{return JSON.parse(W(H($,"..","..","package.json"),"utf-8")).version}catch{return"0.0.0"}}()}`,"║","║",e,"center"),n=[String.raw`__ ___ _ ____ _ ___ `,String.raw`\ \ / (_) |__ ___ / ___| | |_ _|`,String.raw` \ \ / /| | '_ \ / _ \ | | | | | `,String.raw` \ V / | | |_) | __/ |___| |___ | | `,String.raw` \_/ |_|_.__/ \___|\____|_____|___|`],r=Math.max(...n.map(e=>e.length)),s=" ".repeat(Math.floor((58-r)/2)),l=n.map(t=>v(s+t,"║","║",e,"left")),c=[z("╔","╗","═",e),o,...l,o,i,a,z("╚","╝","═",e)];console.log(F.bold("\n"+c.join("\n")))}resetScreen(){console.clear(),this.printBanner()}printGoodbye(){const e=l.getSupportedTools().filter(e=>{if(e.gui)return!1;try{return Boolean(l.detectCurrentConfig(e.name).apiKey)&&l.isToolInstalled(e.name)}catch{return!1}});let a;if(e.length>0){const t=e.map(e=>e.command).join(" / ");a=y.t("wizard.goodbye_message_tools",{commands:t}),e.some(e=>"claude-code"===e.name)&&(a+=" "+y.t("wizard.goodbye_claude_hint"))}else a=y.t("wizard.goodbye_message");console.log(t.green("\n👋 "+a)),this.printPathReloadHint(e.map(e=>e.name))}printPathReloadHint(e){const a=e.filter(e=>!l.isOnPath(e));if(0===a.length)return;const o=a.map(e=>c[e].command).join(" / ");console.log(t.yellow(" ! "+y.t("win32"===process.platform?"setup.path_reload_windows":"setup.path_reload",{commands:o})))}async runFirstTimeSetup(){const e="zh_CN"===h();e&&(o.setLang("zh_CN"),y.setLocale("zh_CN")),this.resetScreen(),console.log(F.bold("\n"+y.t("wizard.welcome"))),console.log(t.gray(y.t("wizard.privacy_note")+"\n")),e?console.log(t.gray(y.t("wizard.lang_auto_zh")+"\n")):await this.configLanguage(),await M(),await this.configApiKey()&&await this.selectAndConfigureTool(!0)}async configLanguage(){for(;;){this.resetScreen(),this.createBox(y.t("wizard.select_language"));const a=y.getLocale(),{language:i}=await this.promptWithHints([{type:"list",name:"language",message:"✨ "+y.t("wizard.select_language"),choices:[{name:"[EN] English"+("en_US"===a?t.green(" ✓ ("+y.t("wizard.current_active")+")"):""),value:"en_US"},{name:"[CN] 中文"+("zh_CN"===a?t.green(" ✓ ("+y.t("wizard.current_active")+")"):""),value:"zh_CN"},new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:"back"},{name:"x "+y.t("wizard.nav_exit"),value:"exit"}],default:"zh_CN"}]);if("exit"===i)this.printGoodbye(),process.exit(0);else if("back"===i)return;return o.setLang(i),void y.setLocale(i)}}buildPresetChoices(){const a=n(),o=a.filter(e=>e.recommended),i=a.filter(e=>!e.recommended),r=e=>({name:(y.t(e.name)!==e.name?y.t(e.name):e.name)+(e.models?t.gray(` [H:${e.models.haiku} S:${e.models.sonnet} O:${e.models.opus}]`):""),value:{type:"preset",preset:e}}),s=[];return o.length>0&&(s.push(new e.Separator(t.hex("#FF8700")("── "+y.t("wizard.recommended")+" ──"))),s.push(...o.map(r))),i.length>0&&(s.push(new e.Separator(t.gray("── "+y.t("wizard.other_models")+" ──"))),s.push(...i.map(r))),s}async handleCustomModelInput(){const a=o.getModels(),{customMode:n}=await e.prompt([{type:"list",name:"customMode",message:y.t("wizard.custom_model_mode"),choices:[{name:y.t("wizard.custom_model_single"),value:"single"},{name:y.t("wizard.custom_model_per_role"),value:"per_role"}]}]);if("single"===n){const{customModel:t}=await e.prompt([{type:"input",name:"customModel",message:y.t("wizard.input_custom_model"),default:i.sonnet}]);o.setModels({haiku:t,sonnet:t,opus:t,reasoning:t})}else{const t=await e.prompt([{type:"input",name:"haiku",message:y.t("wizard.model_haiku"),default:a.haiku},{type:"input",name:"sonnet",message:y.t("wizard.model_sonnet"),default:a.sonnet},{type:"input",name:"opus",message:y.t("wizard.model_opus"),default:a.opus},{type:"input",name:"reasoning",message:y.t("wizard.model_reasoning"),default:a.reasoning}]);o.setModels(t)}console.log(t.green("\n✓ "+y.t("wizard.models_saved")))}async configModels(a){const i=o.getApiKey();if(await this.validatedKeyForConfiguration(i))for(;;){this.resetScreen(),this.createBox(y.t("wizard.config_models"));const i=[...this.buildPresetChoices()];i.push(new e.Separator),i.push({name:"✏️ "+y.t("wizard.custom_model_input"),value:{type:"custom_input"}}),i.push(new e.Separator),i.push({name:"<- "+y.t("wizard.nav_return"),value:{type:"back"}}),i.push({name:"x "+y.t("wizard.nav_exit"),value:{type:"exit"}});const{modelChoice:n}=await this.promptWithHints([{type:"list",name:"modelChoice",message:y.t("wizard.select_model_config"),choices:i}]);if("exit"===n.type)this.printGoodbye(),process.exit(0);else{if("back"===n.type)return;if("custom_input"===n.type)return await this.handleCustomModelInput(),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig());if("preset"===n.type){const e=r(n.preset);return o.setModels(e),console.log(t.green("\n✓ "+y.t("wizard.models_saved"))),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}}}else await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}async promptLoadAfterModelConfig(){const{shouldLoad:t}=await e.prompt([{type:"list",name:"shouldLoad",message:y.t("wizard.load_config_now"),choices:[{name:y.t("wizard.load_config_yes"),value:!0},{name:y.t("wizard.load_config_later"),value:!1}]}]);t&&await this.selectAndConfigureTool()}async configBaseUrl(){const i=o.getBaseUrl(),n=C(),r=a(y.t("wizard.base_testing")).start(),s=await A(n,{apiKey:B(),samples:3});r.stop();const l=T(s),c=n.map((e,a)=>{const o=e.url===i?t.cyan(` ← ${y.t("base.current_mark")}`):"";return{name:`${e.url} ${t.gray(e.label)} ${K(s[a],a===l)}${o}`,value:e.url}});c.push(new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:"__back__"});const{url:d}=await this.promptWithHints([{type:"list",name:"url",message:y.t("wizard.base_select"),choices:c,default:i}]);if("__back__"===d)return;const p=s[n.findIndex(e=>e.url===d)];p.ok?await P(d):console.log(t.red(y.t("base.unreachable",{url:d,reason:N(p)}))),await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}async configApiKey(){for(;;){this.resetScreen(),this.createBox(y.t("wizard.input_api_key")),console.log(t.gray("\n💡 "+y.t("wizard.api_key_input_hint"))),console.log(t.gray(" "+y.t("wizard.api_key_get_hint",{url:L().links.tokenPage}))),console.log();const{apiKey:i}=await e.prompt([{type:"password",name:"apiKey",message:y.t("wizard.input_your_api_key"),mask:"*"}]);if(!i||""===i.trim()){const{action:t}=await e.prompt([{type:"list",name:"action",message:y.t("wizard.select_action"),choices:[{name:y.t("wizard.retry_input"),value:"retry"},{name:"<- "+y.t("wizard.nav_return"),value:"back"}]}]);if("back"===t)return!1;continue}const n=a(y.t("wizard.validating_api_key")).start(),r=await k(i.trim());if(n.stop(),r.valid)return o.setApiKey(i.trim()),this.validatedApiKeys.add(i.trim()),console.log(t.green("\n✓ "+y.t("wizard.api_key_valid"))),!0;{this.validatedApiKeys.delete(i.trim()),"invalid_api_key"===r.error?console.log(t.red("\n✗ "+y.t("wizard.api_key_invalid"))):console.log(t.red("\n✗ "+y.t("wizard.api_key_network_error")));const{action:a}=await e.prompt([{type:"list",name:"action",message:y.t("wizard.select_action"),choices:[{name:y.t("wizard.retry_input"),value:"retry"},{name:"<- "+y.t("wizard.nav_return"),value:"back"}]}]);if("back"===a)return!1}}}async selectAndConfigureTool(a=!1){for(const e of _())await m(e).catch(()=>{});for(;;){this.resetScreen(),this.createBox(y.t("wizard.select_tool"));const o=l.getSupportedTools().map(e=>{const a=g([e.name]).map(e=>w(e)).find(e=>e.outdated);return{name:e.displayName+(a?t.yellow(" "+(a.tool===e.name?"":`${a.name} `)+u(a)):""),value:e.name}}),{tool:i}=await this.promptWithHints([{type:"list",name:"tool",message:"🛠️ "+y.t("wizard.select_tool"),choices:[...o,new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:"back"},{name:"x "+y.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===i)this.printGoodbye(),process.exit(0);else if("back"===i)return;await this.configureTool(i,a)}}async configureTool(a,o=!1){const i=c[a];if(i){if(!l.isToolInstalled(a)){console.log(t.yellow("\n"+y.t("wizard.tool_not_installed",{tool:i.displayName})));const{install:o}=await e.prompt([{type:"confirm",name:"install",message:y.t("wizard.install_tool_confirm"),default:!0}]);if(!o)return;try{await l.installTool(a)}catch{return void console.log(t.red(y.t("wizard.install_failed")))}}o?await this.configureToolModel(a)&&await this.loadConfig(a):await this.showToolMenu(a)}}async showToolMenu(t){for(;;){this.resetScreen();const a=c[t];if(!a)return;this.createBox(a.displayName+" "+y.t("wizard.menu_title"));const o=[{name:"📥 "+y.t("wizard.action_load_config",{tool:a.displayName}),value:"load"},{name:"📤 "+y.t("wizard.action_unload_config",{tool:a.displayName}),value:"unload"}];l.supportsClearPinnedModels(t)&&o.push({name:"🧹 "+y.t("wizard.action_clear_model",{tool:a.displayName}),value:"clear-model"});for(const e of g([t]).map(e=>w(e)).reverse()){if(e.blocker||!e.latest||!e.outdated&&e.installed)continue;const t=e.installed?y.t("wizard.action_upgrade_app",{tool:e.name,current:e.current??"?",latest:e.latest}):y.t("wizard.action_install_app",{tool:e.name,latest:e.latest});o.unshift({name:"↑ "+t,value:`upgrade-app:${e.tool}`})}o.push({name:"🧨 "+y.t("wizard.action_force_config",{tool:a.displayName}),value:"force"},{name:"↩️ "+y.t("wizard.action_restore_config",{tool:a.displayName}),value:"restore"},new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:"back"},{name:"x "+y.t("wizard.nav_exit"),value:"exit"});const{action:i}=await this.promptWithHints([{type:"list",name:"action",message:"⚙️ "+y.t("wizard.select_action"),choices:o}]);if("exit"===i)this.printGoodbye(),process.exit(0);else{if("back"===i)return;"load"===i?await this.configureToolModel(t)&&await this.loadConfig(t):"force"===i?await this.forceConfig(t):"unload"===i?await this.unloadConfig(t):"string"==typeof i&&i.startsWith("upgrade-app:")?(await f(i.slice(12),{install:!0}),await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])):"clear-model"===i?await this.clearPinnedModels(t):"restore"===i&&await this.restoreConfig(t)}}}singleModelOverride(e){const t=e.trim();return/claude/i.test(t)?{opus:t}:{haiku:t,sonnet:t,opus:t,reasoning:t}}hasConfiguredApiKey(){return!!o.getApiKey()?.trim()||o.listToolApiKeys().some(e=>Boolean(o.getApiKeyForTool(e)?.trim()))}async validatedKeyForConfiguration(e){const o=e?.trim();if(!o)return console.log(t.red("\n"+y.t("wizard.api_key_required"))),console.log(t.yellow(y.t("wizard.please_config_api_key_first"))),null;if(this.validatedApiKeys.has(o))return o;const i=a(y.t("wizard.validating_api_key")).start(),n=await k(o);if(n.valid)return this.validatedApiKeys.add(o),i.succeed(y.t("wizard.api_key_valid")),o;this.validatedApiKeys.delete(o);const r="invalid_api_key"===n.error?y.t("wizard.api_key_invalid"):y.t("wizard.api_key_network_error");return i.fail(r),console.log(t.red("\n"+y.t("wizard.please_reconfig_api_key"))),null}async configureToolModel(i){const n=c[i];if(!n)return!1;const l=await this.validatedKeyForConfiguration(o.getApiKeyForTool(i));if(!l)return await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}]),!1;const d="claude-code"===i,p=d||"claude-desktop"===i||"agy"===i,m=s(i),u=p||!m?y.t("wizard.model_builtin_default"):m;this.resetScreen(),this.createBox(n.displayName+" · "+y.t("wizard.config_models"));const _=[{name:"✅ "+y.t("wizard.use_default_model",{model:u}),value:{type:"default"}},{name:"🌐 "+y.t("wizard.fetch_models_from_api"),value:{type:"fetch"}},...this.buildPresetChoices(),new e.Separator,{name:"✏️ "+y.t("wizard.input_custom_model"),value:{type:"custom"}},new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:{type:"back"}}],{choice:g}=await this.promptWithHints([{type:"list",name:"choice",message:y.t("wizard.select_tool_model",{tool:n.displayName}),choices:_}]);if("back"===g.type)return!1;if("default"===g.type)o.setToolModel(i,null);else if("preset"===g.type)o.setToolModel(i,r(g.preset));else if("custom"===g.type){const{model:t}=await e.prompt([{type:"input",name:"model",message:y.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]),a=(t||"").trim();o.setToolModel(i,a?this.singleModelOverride(a):null)}else if("fetch"===g.type){const n=a(y.t("wizard.fetching_models")).start(),r=await x(l);let s;if(n.stop(),r.ok&&r.models.length>0){const{model:t}=await e.prompt([{type:"list",name:"model",message:y.t("wizard.select_fetched_model"),pageSize:20,choices:[...r.models,new e.Separator,{name:"<- "+y.t("wizard.nav_return"),value:"__back__"}]}]);if("__back__"===t)return!1;s=t}else{console.log(t.yellow("\n"+y.t("wizard.fetch_models_failed")));const{model:a}=await e.prompt([{type:"input",name:"model",message:y.t("wizard.input_custom_model"),default:!p&&m?m:void 0}]);s=(a||"").trim()}o.setToolModel(i,s?this.singleModelOverride(s):null)}if("codex"===i){const t=o.getToolSetting(i,b),{enableOneMillionContext:a}=await e.prompt([{type:"confirm",name:"enableOneMillionContext",message:y.t("wizard.codex_enable_1m_context"),default:!1!==t}]);o.setToolSetting(i,b,Boolean(a))}if("claude-desktop"===i){const t=o.getToolSetting(i,S),{hideOfficialLogin:a}=await e.prompt([{type:"confirm",name:"hideOfficialLogin",message:y.t("wizard.desktop_hide_official_login"),default:!1!==t}]);o.setToolSetting(i,S,Boolean(a))}return console.log(t.green("\n✓ "+y.t("wizard.models_saved"))),d&&console.log(t.gray("💡 "+y.t("wizard.claude_model_hint"))),!0}async forceConfig(t){const a=c[t]?.displayName||t,{confirm:o}=await e.prompt([{type:"confirm",name:"confirm",message:y.t("config.confirm_force",{tool:a}),default:!1}]);o&&await this.loadConfig(t,{force:!0})}async loadConfig(i,n={}){const r=o.getModelsForTool(i),s=await this.validatedKeyForConfiguration(o.getApiKeyForTool(i));if(!s)return void await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}]);if(!n.force&&!await d([i]))return;const m=a(y.t("wizard.loading_config")).start();try{await l.applyPrivateConfig(i,s,r,n),m.stop(),l.printApplied(i),await p([i],{apps:{install:!1}}),n.force&&console.log(t.yellow(y.t("config.force_done",{tool:c[i]?.displayName||i,name:i})));const a=c[i];a&&!a.gui&&(l.isOnPath(i)&&console.log(t.green("\n"+y.t("wizard.run_tool_hint",{command:a.command}))),this.printPathReloadHint([i]));const{nextAction:o}=await e.prompt([{type:"list",name:"nextAction",message:y.t("wizard.what_next"),choices:[{name:y.t("wizard.exit_and_start"),value:"exit"},{name:y.t("wizard.continue_config"),value:"continue"}]}]);"exit"===o&&(this.printGoodbye(),process.exit(0))}catch(a){m.fail(y.t("wizard.config_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}}async clearPinnedModels(a){const o=c[a]?.displayName||a,{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:y.t("wizard.confirm_clear_model",{tool:o}),default:!1}]);if(i){try{const e=await l.clearPinnedModels(a);0===e.length?console.log(t.yellow("\n"+y.t("config.clear_model_none",{tool:o}))):(console.log(t.green("\n✓ "+y.t("config.clear_model_done",{tool:o}))),e.forEach(e=>console.log(t.gray(` - ${e}`))),console.log(t.gray(y.t("config.clear_model_restart_hint",{tool:o}))))}catch(e){console.log(t.red("\n"+(e instanceof Error?e.message:String(e))))}await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}}async unloadConfig(o){const{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:y.t("wizard.confirm_unload_config",{tool:c[o]?.displayName||o}),default:!1}]);if(!i)return;const n=a(y.t("wizard.unloading_config")).start();try{const a=l.holdsOurConfig(o),i=l.unloadPrivateConfig(o);if(!a)return void n.info(y.t("config.remove_nothing",{tool:c[o]?.displayName||o}));n.succeed(y.t("wizard.config_unloaded")),i.forEach(e=>console.log(t.yellow(" ! "+e.text)));const{nextAction:r}=await e.prompt([{type:"list",name:"nextAction",message:y.t("wizard.what_next"),choices:[{name:y.t("wizard.nav_exit"),value:"exit"},{name:y.t("wizard.continue_config"),value:"continue"}]}]);"exit"===r&&(this.printGoodbye(),process.exit(0))}catch(a){n.fail(y.t("wizard.config_unload_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}}async restoreConfig(o){const i=c[o]?.displayName||o,{confirm:n}=await e.prompt([{type:"confirm",name:"confirm",message:y.t("wizard.confirm_restore_config",{tool:i}),default:!1}]);if(!n)return;const r=a(y.t("wizard.restoring_config")).start();try{const e=l.restorePrivateConfig(o).filter(e=>e.result.restored);0===e.length?r.warn(y.t("wizard.restore_no_backup")):(r.succeed(y.t("wizard.config_restored",{tool:i})),e.forEach(e=>console.log(t.gray(` ${e.file} ← ${e.result.from}`))),console.log(t.yellow(" ! "+y.t("config.reopen_hint",{tool:i}))))}catch(e){r.fail(y.t("wizard.config_restore_failed")),console.log(t.red(e instanceof Error?e.message:String(e)))}await e.prompt([{type:"input",name:"continue",message:y.t("wizard.press_enter")}])}async run(){await this.showMainMenu()}async showMainMenu(){if(this.hasConfiguredApiKey())for(;;){this.resetScreen();const a=o.getApiKey()||"",i=a.length>4?"sk-****"+a.slice(-4):"****";console.log(t.gray(` 🔑 API Key: ${i}`)+t.green(" ✓")),console.log("");const n=l.getSupportedTools().map(e=>({name:"🛠️ "+e.displayName,value:{type:"tool",tool:e.name}})),r=[new e.Separator(F("── "+y.t("wizard.select_tool")+" ──")),...n,new e.Separator(t.gray("── "+y.t("wizard.settings")+" ──")),{name:"🔑 "+y.t("wizard.menu_change_api_key"),value:{type:"apikey"}},{name:"🔗 "+y.t("wizard.menu_base_url",{url:o.getBaseUrl()}),value:{type:"base"}},{name:"🌐 "+y.t("wizard.menu_config_language"),value:{type:"language"}},new e.Separator,{name:"x "+y.t("wizard.nav_exit"),value:{type:"exit"}}],{action:s}=await this.promptWithHints([{type:"list",name:"action",message:"🛠️ "+y.t("wizard.select_tool"),choices:r}]);"exit"===s.type?(this.printGoodbye(),process.exit(0)):"tool"===s.type?await this.configureTool(s.tool):"apikey"===s.type?await this.configApiKey():"base"===s.type?await this.configBaseUrl():"language"===s.type&&await this.configLanguage()}else await this.runFirstTimeSetup()}}export const wizard=Wizard.getInstance();