@xship/cli 0.0.0-stage → 0.0.134

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.
Files changed (93) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +68 -2
  3. package/THIRD_PARTY_NOTICES.md +10 -0
  4. package/client-config.snapshot.json +377 -0
  5. package/codex-base-instructions.md +277 -0
  6. package/dist/brand.json +45 -0
  7. package/dist/cli.js +2 -0
  8. package/dist/client-config.snapshot.json +377 -0
  9. package/dist/commands/auth.js +1 -0
  10. package/dist/commands/base.js +1 -0
  11. package/dist/commands/bench.js +1 -0
  12. package/dist/commands/codex-sessions.js +1 -0
  13. package/dist/commands/completion.js +1 -0
  14. package/dist/commands/config.js +1 -0
  15. package/dist/commands/doctor.js +1 -0
  16. package/dist/commands/index.js +1 -0
  17. package/dist/commands/lang.js +1 -0
  18. package/dist/commands/logs.js +1 -0
  19. package/dist/commands/refresh.js +1 -0
  20. package/dist/commands/sessions.js +1 -0
  21. package/dist/commands/setup.js +1 -0
  22. package/dist/commands/status.js +1 -0
  23. package/dist/commands/update.js +1 -0
  24. package/dist/commands/upgrade.js +1 -0
  25. package/dist/index.js +1 -0
  26. package/dist/lib/api-validator.js +1 -0
  27. package/dist/lib/auto-update.js +1 -0
  28. package/dist/lib/brand.js +1 -0
  29. package/dist/lib/claude-code-manager.js +1 -0
  30. package/dist/lib/cli-help.js +1 -0
  31. package/dist/lib/client-config-sync.js +1 -0
  32. package/dist/lib/client-config.js +1 -0
  33. package/dist/lib/codex-sessions.js +1 -0
  34. package/dist/lib/command-docs.js +1 -0
  35. package/dist/lib/command.js +1 -0
  36. package/dist/lib/config.js +1 -0
  37. package/dist/lib/confirm.js +1 -0
  38. package/dist/lib/dry-run.js +1 -0
  39. package/dist/lib/env-cleanup.js +1 -0
  40. package/dist/lib/errors.js +1 -0
  41. package/dist/lib/gateway-addresses.js +1 -0
  42. package/dist/lib/gateway-models.js +1 -0
  43. package/dist/lib/gateway-protocol.js +1 -0
  44. package/dist/lib/i18n.js +1 -0
  45. package/dist/lib/key-balance.js +1 -0
  46. package/dist/lib/model-catalog.js +1 -0
  47. package/dist/lib/model-refresh.js +1 -0
  48. package/dist/lib/model-registry.js +1 -0
  49. package/dist/lib/opencode-manager.js +1 -0
  50. package/dist/lib/persistent-env.js +1 -0
  51. package/dist/lib/post-apply.js +1 -0
  52. package/dist/lib/program.js +1 -0
  53. package/dist/lib/runtime-options.js +1 -0
  54. package/dist/lib/secret-store.js +1 -0
  55. package/dist/lib/sessions/formats.js +1 -0
  56. package/dist/lib/sessions/index.js +1 -0
  57. package/dist/lib/settings-template.js +1 -0
  58. package/dist/lib/stream-check.js +1 -0
  59. package/dist/lib/telemetry.js +1 -0
  60. package/dist/lib/tool-manager.js +1 -0
  61. package/dist/lib/tool-upgrade.js +1 -0
  62. package/dist/lib/tools/antigravity.js +1 -0
  63. package/dist/lib/tools/atomcode.js +1 -0
  64. package/dist/lib/tools/backup.js +1 -0
  65. package/dist/lib/tools/claude-code.js +1 -0
  66. package/dist/lib/tools/claude-desktop-cli.js +1 -0
  67. package/dist/lib/tools/claude-desktop.js +1 -0
  68. package/dist/lib/tools/claude-managed.js +1 -0
  69. package/dist/lib/tools/claude-native-mirror.js +1 -0
  70. package/dist/lib/tools/claude-plugins.js +1 -0
  71. package/dist/lib/tools/codex-catalog.js +1 -0
  72. package/dist/lib/tools/codex.js +1 -0
  73. package/dist/lib/tools/desktop-process.js +1 -0
  74. package/dist/lib/tools/elevated-reg.js +1 -0
  75. package/dist/lib/tools/grok.js +1 -0
  76. package/dist/lib/tools/hermes.js +1 -0
  77. package/dist/lib/tools/openclaw.js +1 -0
  78. package/dist/lib/tools/opencode.js +1 -0
  79. package/dist/lib/tools/registry.js +1 -0
  80. package/dist/lib/tools/tool-installs.js +1 -0
  81. package/dist/lib/tools/types.js +1 -0
  82. package/dist/lib/windows-env.js +1 -0
  83. package/dist/lib/wizard.js +1 -0
  84. package/dist/lib/write-plan.js +1 -0
  85. package/dist/locales/en_US.json +1051 -0
  86. package/dist/locales/zh_CN.json +1051 -0
  87. package/dist/models.json +301 -0
  88. package/dist/settings-template.json +18 -0
  89. package/dist/utils/logger.js +1 -0
  90. package/dist/utils/string-width.js +1 -0
  91. package/models.json +301 -0
  92. package/package.json +48 -4
  93. package/settings-template.json +18 -0
@@ -0,0 +1 @@
1
+ import{execFileSync as e}from"child_process";import{existsSync as o,readFileSync as t}from"fs";import{join as r}from"path";import{logger as s}from"../../utils/logger.js";import{MODEL_ENV_VARS as n}from"../claude-code-manager.js";const i=["apiKeyHelper","forceLoginMethod","model","availableModels"],c=["ANTHROPIC_BASE_URL","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_API_KEY",...n],a=["HKLM\\SOFTWARE\\Policies\\ClaudeCode","HKCU\\SOFTWARE\\Policies\\ClaudeCode"];let d=()=>"darwin"===process.platform?["/Library/Application Support/ClaudeCode/managed-settings.json"]:"win32"===process.platform?[r(process.env.ProgramFiles||"C:\\Program Files","ClaudeCode","managed-settings.json")]:["/etc/claude-code/managed-settings.json"],l=o=>{try{const t=e("reg.exe",["query",o,"/v","Settings"],{encoding:"utf-8",windowsHide:!0,timeout:1e4,stdio:["ignore","pipe","ignore"]});return/Settings\s+REG_\w+\s+(.*)/.exec(t)?.[1]?.trim()??null}catch{return null}};export function setManagedSourcesForTests(e,o){d=e,l=o}function p(e){let o;try{o=JSON.parse(e)}catch{return[]}const t=i.filter(e=>void 0!==o[e]),r=o.env;return r&&"object"==typeof r&&t.push(...c.filter(e=>void 0!==r[e]).map(e=>`env.${e}`)),t}export function detectManagedOverrides(){const e=[];try{for(const r of d()){if(!o(r))continue;const s=p(t(r,"utf-8"));s.length>0&&e.push({source:r,keys:s})}if("win32"===process.platform)for(const o of a){const t=l(o),r=t?p(t):[];r.length>0&&e.push({source:o,keys:r})}}catch(e){s.logError("claude-managed.detectManagedOverrides",e)}return e}
@@ -0,0 +1 @@
1
+ import{createHash as t,randomBytes as r}from"crypto";import{createReadStream as i,createWriteStream as a}from"fs";import{chmod as e,copyFile as n,lstat as s,mkdir as o,readlink as c,rename as f,rm as h,symlink as u}from"fs/promises";import{dirname as l,join as w,resolve as d}from"path";import{pipeline as p}from"stream/promises";import{Readable as m,Transform as g,Writable as y}from"stream";import{createGunzip as b}from"zlib";import{toolHome as $}from"./types.js";export const NPM_MIRROR="https://registry.npmmirror.com";let v=(...t)=>fetch(...t);export function setNativeMirrorFetchForTests(t){v=t}export function nativePlatformKey(){const t="x64"===process.arch||"arm64"===process.arch?process.arch:null;if(!t)return null;if("darwin"===process.platform||"win32"===process.platform)return`${process.platform}-${t}`;if("linux"!==process.platform)return null;const r=process.report?.getReport()?.header;return r?.glibcVersionRuntime?`linux-${t}`:`linux-${t}-musl`}export function nativeLayout(){const t=$(),r=process.env.XDG_DATA_HOME?.trim()||w(t,".local","share");return{versionsDir:w(r,"claude","versions"),launcher:w(t,".local","bin","win32"===process.platform?"claude.exe":"claude")}}async function x(t,r){const i=await v(t,{signal:AbortSignal.timeout(r)});if(!i.ok)throw new Error(`${t}: HTTP ${i.status}`);return await i.json()}class E extends y{names;outPath;buffer=Buffer.alloc(0);remaining=0;padding=0;writing=null;found=!1;constructor(t,r){super(),this.names=t,this.outPath=r}_write(t,r,i){this.buffer=this.buffer.length?Buffer.concat([this.buffer,t]):t,this.drain().then(()=>i()).catch(i)}_final(t){this.writing?this.writing.end(()=>t()):t()}async drain(){for(;;){if(this.remaining>0){if(0===this.buffer.length)return;const t=Math.min(this.remaining,this.buffer.length),r=this.buffer.subarray(0,t);if(this.buffer=this.buffer.subarray(t),this.remaining-=t,this.writing&&!this.writing.write(r)&&await new Promise(t=>this.writing.once("drain",()=>t())),0===this.remaining&&this.writing){const t=this.writing;this.writing=null,await new Promise((r,i)=>t.end(t=>t?i(t):r()))}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 t=this.buffer.subarray(0,512);if(this.buffer=this.buffer.subarray(512),t.every(t=>0===t))continue;const r=(r,i)=>t.subarray(r,r+i).toString("utf-8").replace(/\0.*$/s,""),i=r(345,155),e=i?`${i}/${r(0,100)}`:r(0,100),n=parseInt(r(124,12).trim()||"0",8),s=r(156,1)||"0";if(this.remaining=n,this.padding=(512-n%512)%512,("0"===s||""===s)&&this.names.includes(e)&&!this.found&&(this.found=!0,this.writing=a(this.outPath,{mode:493}),0===n)){const t=this.writing;this.writing=null,await new Promise(r=>t.end(()=>r()))}}}}export async function updateNativeFromMirror(a){const e=nativePlatformKey();if(!e)throw new Error(`no native Claude Code build for ${process.platform}-${process.arch}`);const{versionsDir:m,launcher:g}=nativeLayout();if("win32"!==process.platform&&!await async function(t,r){try{return!!(await s(t)).isSymbolicLink()&&d(l(t),await c(t)).startsWith(d(r)+"/")}catch{return!0}}(g,m))throw new Error(`${g} was not created by the native installer; not replacing it`);const y=await x(`${NPM_MIRROR}/@anthropic-ai/claude-code`,2e4),b=y["dist-tags"]?.[a]??y["dist-tags"]?.latest;if(!b||!/^\d+\.\d+\.\d+$/.test(b))throw new Error("npmmirror returned no usable version");await o(m,{recursive:!0});const $=w(m,`${b}.tmp.${process.pid}.${Date.now()}`);try{await downloadNativeBinary(e,b,$);let a=!1;try{const r=await x(`https://downloads.claude.ai/claude-code-releases/${b}/manifest.json`,8e3),n=r.platforms?.[e]?.checksum;if(n){if(await async function(r){const a=t("sha256");return await p(i(r),a),a.digest("hex")}($)!==n)throw new Error("binary does not match Anthropic's release checksum");a=!0}}catch(t){if(t instanceof Error&&t.message.includes("release checksum"))throw t}const c=w(m,b);return await f($,c),await async function(t,i){await o(l(i),{recursive:!0});const a=`${process.pid}.${Date.now()}`;if("win32"!==process.platform){const r=`${i}.tmp.${a}`;await u(t,r);try{await f(r,i)}catch(t){throw await h(r,{force:!0}),t}return}const e=`${i}.new.${a}.${r(4).toString("hex")}`;await n(t,e);let c=null;try{await s(i),c=`${i}.old.${Date.now()}.${process.pid}`,await f(i,c)}catch(t){if("ENOENT"!==t.code)throw await h(e,{force:!0}),t}try{await f(e,i)}catch(t){throw c&&await f(c,i).catch(()=>{}),await h(e,{force:!0}),t}}(c,g),{version:b,manifestVerified:a}}finally{await h($,{force:!0})}}export async function downloadNativeBinary(r,n,s){const o=await x(`${NPM_MIRROR}/@anthropic-ai/claude-code-${r}/${n}`,2e4),c=o.dist?.tarball,f=o.dist?.integrity;if(!c||!f?.startsWith("sha512-"))throw new Error("npmmirror returned no tarball or integrity");const u=`${s}.download`;try{const r=await v(c,{signal:AbortSignal.timeout(9e5)});if(!r.ok||!r.body)throw new Error(`${c}: HTTP ${r.status}`);const n=t("sha512"),o=new g({transform(t,r,i){n.update(t),i(null,t)}});if(await p(m.fromWeb(r.body),o,a(u)),`sha512-${n.digest("base64")}`!==f)throw new Error("downloaded package does not match its sha512 integrity");const h=new E(["package/claude","package/claude.exe"],s);if(await p(i(u),b(),h),!h.found)throw new Error("package has no claude binary");await e(s,493)}finally{await h(u,{force:!0})}}
@@ -0,0 +1 @@
1
+ import{spawnSync as e}from"child_process";import{existsSync as t,readFileSync as i}from"fs";import{join as o}from"path";import{logger as s}from"../../utils/logger.js";import{configManager as n}from"../config.js";import{toolHome as r}from"./types.js";import{brandEnv as l,brand as a}from"../brand.js";export const PLUGIN_SOURCES=[...a().pluginMarketplaces,{name:"claude-plugins-official",add:"anthropics/claude-plugins-official",probe:"https://github.com/anthropics/claude-plugins-official.git"}];export const OFFICIAL_PLUGINS=["code-review","feature-dev","frontend-design","pr-review-toolkit","commit-commands","security-guidance","code-simplifier","skill-creator","claude-md-management","claude-code-setup"];const d="official_plugins_offered";let p=(t,i)=>{const n=e(t,i,{env:l("TEST_HOME")?{...process.env,CLAUDE_CONFIG_DIR:o(r(),".claude")}:process.env,encoding:"utf-8",timeout:12e4,windowsHide:!0,stdio:["ignore","pipe","pipe"],shell:"win32"===process.platform&&/\.cmd$/i.test(t)});return 0!==n.status&&s.logError(`claude ${i.join(" ")}`,new Error(`${n.stderr??""}${n.stdout??""}`.trim())),0===n.status},c=t=>0===e("git",["ls-remote","--heads",t],{timeout:8e3,windowsHide:!0,stdio:"ignore"}).status;export function setClaudePluginRunnerForTests(e){p=e}export function setPluginSourceProbeForTests(e){c=e}export function installOfficialPlugins(s){if("1"===l("SKIP_CLAUDE_PLUGINS"))return{installed:[],failed:[],skipped:"disabled"};const a=n.getToolSetting("claude-code",d),u=new Set("string"==typeof a?a.split(",").filter(Boolean):[]),f=function(){try{const e=JSON.parse(i(o(r(),".claude","plugins","installed_plugins.json"),"utf-8"));return new Set(Object.keys(e.plugins??{}).map(e=>e.replace(/@[^@]*$/,"")))}catch{return new Set}}(),m=e=>f.has(e),g=OFFICIAL_PLUGINS.filter(e=>!u.has(e)&&!m(e));if(0===g.length)return{installed:[],failed:[],skipped:null};if("darwin"===process.platform&&0!==e("xcode-select",["-p"],{stdio:"ignore"}).status&&!["/opt/homebrew/bin/git","/usr/local/bin/git"].some(e=>t(e))||0!==e("git",["--version"],{timeout:8e3,windowsHide:!0,stdio:"ignore"}).status)return{installed:[],failed:[],skipped:"git"};const S=PLUGIN_SOURCES.find(e=>c(e.probe));if(!S)return{installed:[],failed:[],skipped:"marketplace"};p(s,["plugin","marketplace","add",S.add]);const h={installed:[],failed:[],skipped:null,source:S.name};for(const e of g)p(s,["plugin","install",`${e}@${S.name}`])?(h.installed.push(e),u.add(e)):h.failed.push(e);for(const e of OFFICIAL_PLUGINS)m(e)&&u.add(e);return n.setToolSetting("claude-code",d,[...u].join(",")),h}
@@ -0,0 +1 @@
1
+ import{spawnSync as t}from"child_process";import{existsSync as o,mkdtempSync as e,readFileSync as n,realpathSync as s,rmSync as r,statSync as i,writeFileSync as c}from"fs";import{tmpdir as l}from"os";import{delimiter as a,dirname as u,isAbsolute as d,join as p}from"path";import*as f from"@iarna/toml";import{fileURLToPath as m}from"url";import{logger as _}from"../../utils/logger.js";import{getCodexRules as x,compareVersions as g}from"../model-registry.js";import{autoCompactTokens as w,modelBlurb as h,prettyModelName as y}from"../gateway-models.js";import{codexHome as b,toolHome as C}from"./types.js";import{brandEnv as v,CLI_NAME as M,PROVIDER_KEY as A}from"../brand.js";const j=u(m(import.meta.url));export const CODEX_CATALOG_FILE=`${A}-model-catalog.json`;export const codexCatalogPath=()=>p(b(),CODEX_CATALOG_FILE);function O(){const t=v("CODEX_BIN");if(void 0!==t)return t.trim()?[t.trim()]:[];const o=["codex"];if("win32"===process.platform){const t=process.env.LOCALAPPDATA||p(C(),"AppData","Local");o.push(p(t,"Programs","OpenAI","Codex","bin","codex.exe"))}else o.push(p(C(),".local","bin","codex"));if("darwin"===process.platform)for(const t of["/Applications",p(C(),"Applications")])o.push(p(t,"ChatGPT.app/Contents/Resources/codex-cli/bin/codex")),o.push(p(t,"Codex.app/Contents/Resources/codex"));return o}function $(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function E(t){try{const o=JSON.parse(t),e=$(o)&&Array.isArray(o.models)?o.models.filter($):[];return e.length>0?e:null}catch{return null}}function k(o,e,n){const s={encoding:"utf-8",timeout:2e4,maxBuffer:67108864,windowsHide:!0,stdio:["ignore","pipe","pipe"],...n?{env:n}:{}};return"win32"!==process.platform||"codex"!==o&&!/\.cmd$/i.test(o)?t(o,e,s):t(["codex"===o?"codex":`"${o}"`,...e].join(" "),{...s,shell:!0})}function P(t){const o=k(t,["debug","models","--bundled"]);if(0===o.status&&o.stdout){const t=E(o.stdout);if(t)return t}return(o.error||0!==o.status)&&_.logError("loadBundledCodexModels",o.error??new Error(`${t} exited ${o.status}`)),null}export function loadBundledCodexModels(t){if(t)return P(t);for(const t of O()){if("codex"!==t&&!o(t))continue;const e=P(t);if(e)return e}return null}function B(t){try{return i(t).isFile()}catch{return!1}}export function installedCodexBinaries(){const t=[],o=O();if(o.includes("codex")){const o="win32"===process.platform?["codex.exe","codex.cmd"]:["codex"];for(const e of(process.env.PATH??"").split(a))if(e&&d(e))for(const n of o)t.push(p(e,n))}t.push(...o.filter(t=>"codex"!==t));const e=new Set,n=[];for(const o of t){if(!B(o))continue;let t=o;try{t=s(o)}catch{}const r="win32"===process.platform?t.toLowerCase():t;e.has(r)||(e.add(r),n.push(o))}return n}export function codexBinaryVersion(t){const o=`${k(t,["--version"]).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return o?o[0]:null}export function catalogRejections(t,o=installedCodexBinaries()){if(0===o.length)return[];const n=e(p(l(),`${M}-codex-`)),s=[];try{c(p(n,"config.toml"),f.stringify({model_catalog_json:t}));for(const t of o){const o=k(t,["debug","models"],{...process.env,CODEX_HOME:n});if(0===o.status)continue;const e=`${o.stderr??""}\n${o.stdout??""}`,r=e.split(/\r?\n/).find(t=>t.includes("model_catalog_json"));r?s.push({bin:t,version:codexBinaryVersion(t),error:r.trim()}):_.logError("catalogRejections",o.error??new Error(`${t} exited ${o.status}: ${e.trim().slice(0,500)}`))}}finally{r(n,{recursive:!0,force:!0})}return s}export function loadPreviousCodexModels(){const t=L()?.filter(t=>!S(t));return t&&t.length>0?t:null}export function previousGatewayModelIds(){return(L()??[]).filter(S).map(t=>String(t.slug))}function L(){return o(codexCatalogPath())?E(n(codexCatalogPath(),"utf-8")):null}function S(t){return"number"==typeof t.priority&&t.priority>=1e3}let T=null;function D(){if(null!==T)return T;const t=[p(j,"..","..","..","codex-base-instructions.md"),p(j,"..","..","codex-base-instructions.md"),p(j,"codex-base-instructions.md")],e=t.find(t=>o(t));if(!e)throw new Error(`codex-base-instructions.md not found, searched: ${t.join(", ")}`);return T=n(e,"utf-8"),T}function F(t){return"number"==typeof t&&Number.isFinite(t)&&t>0?t:void 0}function I(t,o,e,n){const s=e?t:Math.min(t,o);return{window:s,compact:w(s,n)}}function W(t,o,e,n){const{standardContextWindow:s}=x();let r=F(t.contextWindow)??s;n&&t.id.startsWith("claude-")&&(r=n.has(t.id)?Math.max(r,1e6):Math.min(r,2e5));const{window:i,compact:c}=I(r,s,e,F(t.autoCompactTokens));return{slug:t.id,display_name:t.name||y(t.id),description:h(t.description,{millionContext:i>=1e6})??null,supported_reasoning_levels:[],shell_type:"unified_exec",visibility:"list",supported_in_api:!0,priority:o,additional_speed_tiers:[],service_tiers:[],availability_nux:null,upgrade:null,model_messages:{instructions_template:D()},base_instructions:D(),supports_reasoning_summaries:!0,supports_parallel_tool_calls:!1,prefer_websockets:!1,include_skills_usage_instructions:!1,include_plugin_usage_instructions:!1,include_apps_usage_instructions:!1,default_reasoning_summary:"auto",support_verbosity:!1,default_verbosity:null,apply_patch_tool_type:null,web_search_tool_type:"text",truncation_policy:{mode:"bytes",limit:1e4},supports_image_detail_original:!1,context_window:i,max_context_window:i,auto_compact_token_limit:c,effective_context_window_percent:95,experimental_supported_tools:[],input_modalities:["text","image"],supports_search_tool:!1,supports_experimental_context:!1,use_responses_lite:!1,supports_reasoning_effort_updates:!1,node_repl_auto_review_required:!1,node_repl_disabled:!1}}const G={supports_parallel_tool_calls:!0,supports_reasoning_summaries:!0};export function fillFromOlderEntries(t,o){const e=new Map(o.map(t=>[t.slug,t])),n=new Map;for(const t of o)for(const[o,e]of Object.entries(t))n.has(o)||n.set(o,e);return t.map(t=>{const o=e.get(t.slug),s={...t};for(const[t,e]of n)t in s||(s[t]=o&&t in o?o[t]:e);return s})}function R(t,o,e){if("list"!==(t=function(t){const o=Object.keys(G).filter(o=>!(o in t));return 0===o.length?t:{...t,...Object.fromEntries(o.map(t=>[t,G[t]]))}}(t)).visibility)return t;const n=F(t.context_window);if(!n)return t;const s=F(t.max_context_window)??n,r=e?Math.min(F(o?.contextWindow)??s,s):n,{window:i,compact:c}=I(r,n,!0,F(o?.autoCompactTokens));return{...t,context_window:i,auto_compact_token_limit:c}}export function buildCodexCatalog(t){const{bundled:o,specs:e,oneMillion:n,selectedModel:s}=t,r=t.claudeOneMillion?new Set(t.claudeOneMillion):void 0,i=t.keyModels?new Set(t.keyModels):null,c=new Set(t.gatewayAvailable),l=t=>!i||i.has(t)||t===s,a=t=>c.has(t)||t===s,u=new Map(e.map(t=>[t.id,t])),d=[],p=new Set;for(const t of o){const o="string"==typeof t.slug?t.slug:"";o&&!p.has(o)&&("list"!==t.visibility||l(o))&&(p.add(o),d.push(R(t,u.get(o),n)))}const f=[...e];s&&!u.has(s)&&f.push({id:s});const m=function(t){const o=new Map;for(const e of t){const t=/^claude-([a-z]+)-(.+)$/.exec(e);if(!t)continue;const n=t[2].split("-").filter(t=>/^\d{1,2}$/.test(t)).join("."),s=o.get(t[1]);(!s||g(n,s.version)>0)&&o.set(t[1],{id:e,version:n})}return new Set([...o.values()].map(t=>t.id))}(f.map(t=>t.id).filter(a));for(const t of f)!p.has(t.id)&&a(t.id)&&(t.id.startsWith("claude-")&&!m.has(t.id)&&t.id!==s||(p.add(t.id),d.push(W(t,1e3+d.length,n,r))));return{models:d}}
@@ -0,0 +1 @@
1
+ import{createHash as e}from"crypto";import{existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as i,statSync as s,writeFileSync as l}from"fs";import{join as a}from"path";import*as c from"@iarna/toml";import{logger as d}from"../../utils/logger.js";import{i18n as u}from"../i18n.js";import{backupBeforeWrite as m,atomicWriteFile as p}from"./backup.js";import{codexHome as f,pickModel as g,toolHome as _,withV1 as x}from"./types.js";import{moveSessionsToProvider as h,NO_STATE_DB as y,runningCodexPids as k}from"../codex-sessions.js";import{codexFormat as b,codexRolloutFiles as v}from"../sessions/formats.js";import{getToolDefaultModel as j}from"../model-registry.js";import{configManager as w}from"../config.js";import{maskHome as C,track as O}from"../telemetry.js";import{buildCodexCatalog as S,catalogRejections as M,codexCatalogPath as A,fillFromOlderEntries as E,installedCodexBinaries as N,loadBundledCodexModels as P,loadPreviousCodexModels as T,previousGatewayModelIds as D}from"./codex-catalog.js";import{gatewayModelSpecs as I,modelFamily as L}from"../gateway-models.js";import{findInstalls as $,mirrorInstallCommand as J,brandInstallScripts as G}from"./tool-installs.js";const R=()=>f(),K=()=>a(R(),"config.toml"),X="sessions_move_declined",B=["browser_use","browser_use_external","computer_use"];function W(e){const t=e.features;if(!Q(t)||!B.every(e=>!1===t[e]))return!1;for(const e of B)delete t[e];return!0}export function codexWorkModeOn(){try{const e=Z();return e.model_provider===Y&&Q(e.desktop)&&"STEPS_PROSE"===e.desktop.conversationDetailMode}catch{return!1}}function q(){try{if(Q(Z().desktop))return!0}catch{}if("darwin"===process.platform)return["/Applications",a(_(),"Applications")].some(e=>["ChatGPT.app","Codex.app"].some(o=>t(a(e,o))));if("win32"===process.platform){const e=a(process.env.LOCALAPPDATA||a(_(),"AppData","Local"),"Packages");try{return n(e).some(e=>/^OpenAI\.(Codex|ChatGPT)/i.test(e))}catch{return!1}}return t("/usr/lib/chatgpt/ChatGPT")}export function codexConfigPath(){return K()}const U=()=>a(R(),"auth.json"),z="OPENAI_API_KEY",Y="custom",F=1e6,H=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function Q(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function V(e,t){return Q(e[t])||(e[t]={}),e[t]}function Z(){if(!t(K()))return{};const e=r(K(),"utf-8");if(!e.trim())return{};try{const t=c.parse(e);if(!Q(t))throw new Error("config.toml root must be a TOML table");return t}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function ee(){if(!t(U()))return{};try{const e=JSON.parse(r(U(),"utf-8"));return Q(e)?e:{}}catch{return{}}}let te=null;function oe(e){const t=e.profiles;if(Q(t)){for(const[e,o]of Object.entries(t))Q(o)&&2===Object.keys(o).length&&o.model_provider===Y&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let ne=null;const re=()=>a(w.getConfigDir(),"codex-catalog-check.json");function ie(e){const o=A();t(o)&&r(o,"utf-8")===e||(m(o),p(o,e))}function se(t,n){if(0===n.length)return[];const i=function(t,o){const n=e("sha256").update(t);for(const e of o)try{const t=s(e);n.update(`\0${e}\0${t.size}\0${t.mtimeMs}`)}catch{n.update(`\0${e}`)}return n.digest("hex")}(t,n);if(function(e){try{return JSON.parse(r(re(),"utf-8")).signature===e}catch{return!1}}(i))return[];const a=M(A(),n);return 0===a.length&&function(e){try{o(w.getConfigDir(),{recursive:!0}),l(re(),JSON.stringify({signature:e})+"\n")}catch(e){d.logError("codexAdapter.rememberAccepted",e)}}(i),a}function le(e,t,o){const n=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===F&&delete e.model_context_window,e.model_auto_compact_token_limit===H&&delete e.model_auto_compact_token_limit}(e);const r=()=>{e.model_catalog_json===A()&&delete e.model_catalog_json,n&&(e.model_context_window=F,e.model_auto_compact_token_limit=H)},s=P()??T();if(!s)return d.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),ne="skipped",void r();const l=t.catalog,a=e=>S({bundled:e,specs:I("codex",l?.clientModels),...l?{keyModels:l.models}:{},gatewayAvailable:l?.models??D(),oneMillion:n,selectedModel:o,..."gateway"===l?.oneMillionSource?{claudeOneMillion:l.oneMillion}:{}}),c=e=>JSON.stringify(e,null,2)+"\n";let u=a(s);ie(c(u));const m=N(),p=se(c(u),m);if(p.length>0){const e=Date.now();let t=!1;for(const e of p){const o=P(e.bin);if(o){for(const e of[{models:E(u.models,o)},{models:E(a(o).models,o)}])if(ie(c(e)),0===se(c(e),m).length){u=e,t=!0;break}if(t)break}}if(O("codex-catalog",t?"fallback":"fail",{duration_ms:Date.now()-e,error:p[0].error,detail:{rejected_by:p.map(e=>({version:e.version,path:C(e.bin)}))}}),!t)return ne={rejectedBy:p[0]},i(A(),{force:!0}),void r()}ne={listed:u.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))},e.model_catalog_json=A()}export function codexCatalogRejection(){let e;try{e=Z()}catch{return null}return e.model_catalog_json===A()&&t(A())?M(A())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=Z(),n=c.stringify(o),r="string"==typeof o.model?o.model:j("codex");le(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=c.stringify(o);i!==n&&(m(K()),p(K(),i))}const ae={command:"codex",npmPackage:"@openai/codex",native:{binDir:"win32"===process.platform?["AppData","Local","Programs","OpenAI","Codex","bin"]:[".local","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".codex","packages","standalone"]]},mirrorScript:G("codex"),brew:"codex"};export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:J(ae),installSpec:ae,configPath:K(),sessions:{format:b,files:()=>[...v(a(f(),"sessions")),...v(a(f(),"archived_sessions"))],resumeCommand:e=>({command:"codex",args:["resume",e]})},wantsModelCatalog:!0,listedModels(){if(Z().model_catalog_json!==A())return null;try{return(JSON.parse(r(A(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){if(Z().model_catalog_json!==A())return;setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog);const t=Z();W(t)&&(m(K()),p(K(),c.stringify(t)))},async followUp(){if(Z().model_provider!==Y)return null;const e=await h(Y,{dryRun:!0}),t=Math.max(e.moved.length,e.dbRows);if(0===t)return null;const o=w.getToolSettings("codex")[X];if("number"==typeof o&&t<=o)return null;const n={count:String(t)};return k().length>0?{hint:u.t("tools.codex.sessions_hidden_running",n)}:{prompt:u.t("tools.codex.sessions_offer",n),hint:u.t("tools.codex.sessions_hidden",n),async run(){const e=await h(Y),t=[...new Set(e.moved.map(e=>e.from))].join("、")||"-",o=String(Math.max(e.moved.length,e.dbRows)),n=[{kind:"summary",text:u.t("codex_sessions.moved",{count:o,from:t,target:Y})},{kind:"summary",text:u.t("codex_sessions.backup",{dir:e.backupDir??""})}];return e.dbSkipped&&e.dbSkipped!==y&&n.push({kind:"action",text:u.t("codex_sessions.db_skipped",{reason:e.dbSkipped})}),n},decline(){w.setToolSetting("codex",X,t)}}},applyNotes(){if("skipped"===ne)return 0===$(ae).length?[]:[{kind:"action",text:u.t("tools.codex.catalog_skipped")}];if(!ne)return[];if("rejectedBy"in ne){const{bin:e,version:t}=ne.rejectedBy;return[{kind:"action",text:u.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of ne.listed)e.set(L(t.id),(e.get(L(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${u.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:u.t("tools.codex.catalog_written",{count:String(ne.listed.length),breakdown:t})},{kind:"detail",text:ne.listed.map(e=>e.name).join(", ")},...codexWorkModeOn()||q()?[{kind:"action",text:u.t(codexWorkModeOn()?"tools.codex.work_mode_on":"tools.codex.work_mode_hint")}]:[]]},loadPrivateConfig(e){const t=j("codex"),o=g(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,r=x(e.baseUrl),i=Z();i.model=n,i.model_provider=Y,i.model_reasoning_effort="high",le(i,e,n);const s=V(i,"model_providers"),l=Q(s[Y])?{...s[Y]}:{};delete l.env_key;const{experimental_bearer_token:a,...d}=l;s[Y]={...d,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:r},oe(i),V(V(i,"tui"),"model_availability_nux")[n]=4;const u=V(i,"features");u.goals=!0,u.js_repl=!1,W(i),m(K()),p(K(),c.stringify(i)),function(e){const t=e.trim();if(!t)return;const o={...ee(),auth_mode:"apikey",[z]:t};m(U()),p(U(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},holdsOurConfig(e){const t=ee()[z];return"string"==typeof t&&e.includes(t.trim())},unloadPrivateConfig(e){if(te=function(e){const t=ee(),o="string"==typeof t[z]?t[z].trim():"";if(!o)return Q(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[z]:n,auth_mode:r,...s}=t;return m(U()),Q(s.tokens)?(p(U(),JSON.stringify({...s,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(i(U(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(K()))return;let o;try{o=Z()}catch(e){return void d.logError("codexAdapter.unloadPrivateConfig",e)}const n=o.model_providers;Q(n)&&(delete n[Y],0===Object.keys(n).length&&delete o.model_providers),o.model_provider===Y&&delete o.model_provider,o.model_catalog_json===A()&&delete o.model_catalog_json,W(o),oe(o),m(K()),p(K(),c.stringify(o))},unloadNotes(){switch(te){case"chatgpt":return[{kind:"action",text:u.t("tools.codex.unload_chatgpt_restored")}];case"other_key":return[{kind:"action",text:u.t("tools.codex.unload_other_key")}];default:return[{kind:"action",text:u.t("tools.codex.unload_sign_in")}]}},detectCurrentConfig(){const e=ee()[z];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return Z()}catch(e){return d.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[K(),U(),A()]};export function codexAuthProblem(){try{const e=Z(),t=e.model_providers?.[Y];if(e.model_provider!==Y||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=ee();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
@@ -0,0 +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 restartDesktop(){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),o("open",["-a","Claude"])}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","$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}
@@ -0,0 +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})}}
@@ -0,0 +1 @@
1
+ import{existsSync as e,readFileSync as t}from"fs";import{join as o}from"path";import*as r from"@iarna/toml";import{logger as n}from"../../utils/logger.js";import{PROVIDER_KEY as i}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as l}from"./backup.js";import{pickModel as d,toolHome as a,withV1 as m}from"./types.js";import{i18n as f}from"../i18n.js";import{getToolDefaultModel as g}from"../model-registry.js";import{gatewayModelSpecs as u,modelBlurb as c,modelFamily as p,prettyModelName as y}from"../gateway-models.js";import{brandInstallScripts as k,mirrorInstallCommand as b}from"./tool-installs.js";import{OFFICIAL_PLUGINS as h}from"./claude-plugins.js";const j=()=>o(o(a(),".grok"),"config.toml"),_=i,w=`${i}-`,A=["low","medium","high","xhigh"];let v=null;const C=e=>`${w}${e}`,x=e=>e===_||e.startsWith(w),M={command:"grok",npmPackage:"@xai-official/grok",mirrorScript:k("grok"),native:{binDir:[".grok","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".grok","downloads"]]}};function S(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function E(e,t){return S(e[t])||(e[t]={}),e[t]}function O(){if(!e(j()))return{};const o=t(j(),"utf-8");if(!o.trim())return{};try{const e=r.parse(o);if(!S(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.grok/config.toml cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function P(e){return S(e.model)?Object.entries(e.model).filter(e=>x(e[0])&&S(e[1])):[]}function N(e,t){let o=u("grok",e.catalog?.clientModels);if(e.catalog){const t=new Set(e.catalog.models);o=o.filter(e=>t.has(e.id))}return o.some(e=>e.id===t)?o:[{id:t},...o]}function $(e,t,o){E(e,"endpoints").models_base_url=m(t.baseUrl);const r=E(e,"model"),n=new Map(P(e));for(const e of n.keys())delete r[e];for(const e of o){const o=C(e.id),i={...n.get(o)??{},name:e.name??y(e.id),model:e.id,base_url:m(t.baseUrl),api_key:t.apiKey,context_window:e.contextWindow??5e5,api_backend:"responses",reasoning_summary:"concise"};"grok"===p(e.id)&&(i.supports_reasoning_effort=!0,i.reasoning_efforts=A);const s=c(e.description);s?i.description=s:delete i.description,r[o]=i}}export const grokAdapter={name:"grok",displayName:"Grok Build",command:"grok",installCommand:b(M),installSpec:M,configPath:j(),wantsModelCatalog:!0,loadPrivateConfig(e){const t=O(),o=d(e.models,g("grok")),n=N(e,o);$(t,e,n);const i=e=>e.name??y(e.id);v={names:n.map(i),defaultName:i(n.find(e=>e.id===o))},E(t,"models").default=C(o),function(e){const t=E(e,"plugins"),o=e=>Array.isArray(e)?e.map(String):[],r=o(t.enabled),n=o(t.disabled),i=h.filter(e=>!r.includes(e)&&!n.includes(e));i.length>0&&(t.disabled=[...n,...i])}(t),s(j()),l(j(),r.stringify(t))},unloadPrivateConfig(){if(!e(j()))return;let t;try{t=O()}catch(e){return void n.logError("grokAdapter.unloadPrivateConfig",e)}if(S(t.model)){for(const[e]of P(t))delete t.model[e];0===Object.keys(t.model).length&&delete t.model}S(t.models)&&"string"==typeof t.models.default&&x(t.models.default)&&(delete t.models.default,0===Object.keys(t.models).length&&delete t.models),S(t.endpoints)&&(delete t.endpoints.models_base_url,0===Object.keys(t.endpoints).length&&delete t.endpoints),function(e){if(!S(e.plugins)||!Array.isArray(e.plugins.disabled))return;const t=e.plugins.disabled.filter(e=>!h.includes(e));t.length>0?e.plugins.disabled=t:delete e.plugins.disabled,0===Object.keys(e.plugins).length&&delete e.plugins}(t),s(j()),l(j(),r.stringify(t))},detectCurrentConfig(){try{const e=O(),t=P(e),o=S(e.models)?e.models.default:void 0,r=t.find(([e])=>e===o)?.[1]??t[0]?.[1],n=r?r.api_key:null;return{apiKey:"string"==typeof n&&n.trim()?n:null}}catch{return{apiKey:null}}},listedModels(){try{const e=P(O());return e.length>0?e.map(([,e])=>String(e.model)):null}catch{return null}},refreshModelMenu(e){const t=O(),o=E(t,"models"),n="string"==typeof o.default?o.default:void 0,i=n?P(t).find(([e])=>e===n)?.[1].model:void 0,a="string"==typeof i&&n!==_&&e.catalog.models.includes(i)?i:d(e.models,g("grok")),m=r.stringify(t);$(t,e,N(e,a)),(void 0===n||x(n))&&(o.default=C(a)),r.stringify(t)!==m&&(s(j()),l(j(),r.stringify(t)))},applyNotes:()=>v?[{kind:"summary",text:f.t("tools.grok.menu_written",{count:String(v.names.length),list:v.names.join(f.t("tools.grok.list_separator")),default:v.defaultName})}]:[],getConfig(){try{return O()}catch(e){return n.logError("grokAdapter.getConfig",e),null}}};
@@ -0,0 +1 @@
1
+ import{existsSync as t,readFileSync as e}from"fs";import{join as r}from"path";import*as n from"js-yaml";import{logger as i}from"../../utils/logger.js";import{API_KEY_ENV as o}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as m}from"./backup.js";import{pickModel as l,toolHome as a,withV1 as c}from"./types.js";import{getToolDefaultModel as f}from"../model-registry.js";const d=()=>r(a(),".hermes"),u=()=>r(d(),"config.yaml"),p=()=>r(d(),".env");function h(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function g(){if(!t(u()))return{};const r=e(u(),"utf-8");if(!r.trim())return{};const i=n.load(r);if(!h(i))throw new Error("config.yaml root must be a YAML mapping");return i}export const hermesAdapter={name:"hermes",displayName:"Hermes",command:"hermes",installCommand:"npm install -g hermes-cli",hidden:!0,configPath:u(),loadPrivateConfig(r){let i;try{i=g()}catch(t){throw new Error(`Existing ~/.hermes/config.yaml cannot be parsed; back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}const a=h(i.model)?i.model:i.model={};a.provider="custom",a.base_url=c(r.baseUrl),a.default=l(r.models,f("hermes")),s(u()),m(u(),n.dump(i,{indent:2,lineWidth:-1,noRefs:!0,sortKeys:!1}));const d=t(p())?e(p(),"utf-8"):"";s(p()),m(p(),function(t,e,r){const n=(t||"").split(/\r?\n/),i=`${e}=${r}`;let o=!1;const s=n.map(t=>{const r=t.trim();if(!r||r.startsWith("#"))return t;const n=r.indexOf("=");return n<=0?t:r.slice(0,n).trim()===e?(o=!0,i):t});if(!o){if(!(t||"").trim())return i+"\n";s.length&&""!==s[s.length-1]&&s.push(""),s.push(i)}const m=s.join("\n");return m.endsWith("\n")?m:m+"\n"}(d,o,r.apiKey))},unloadPrivateConfig(){if(t(u()))try{const t=g();h(t.model)&&(delete t.model.provider,delete t.model.base_url,delete t.model.default,0===Object.keys(t.model).length&&delete t.model),s(u()),m(u(),n.dump(t,{indent:2,lineWidth:-1,noRefs:!0,sortKeys:!1}))}catch(t){i.logError("hermesAdapter.unloadPrivateConfig",t)}t(p())&&(s(p()),m(p(),function(t,e){const r=(t||"").split(/\r?\n/).filter(t=>{const r=t.trim();if(!r||r.startsWith("#"))return!0;const n=r.indexOf("=");return n<=0||r.slice(0,n).trim()!==e}).join("\n");return r.endsWith("\n")||""===r?r:r+"\n"}(e(p(),"utf-8"),o)))},detectCurrentConfig(){const r=function(){if(!t(p()))return{};const r={};for(const t of e(p(),"utf-8").split(/\r?\n/)){const e=t.trim();if(!e||e.startsWith("#"))continue;const n=e.indexOf("=");if(n<=0)continue;const i=e.slice(0,n).trim();let o=e.slice(n+1).trim();(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),r[i]=o}return r}()[o];return{apiKey:r&&r.trim()?r:null}},getConfig(){try{return g()}catch(t){return i.logError("hermesAdapter.getConfig",t),null}},backupPaths:()=>[u(),p()]};
@@ -0,0 +1 @@
1
+ import{existsSync as e,readFileSync as r}from"fs";import{join as o}from"path";import{logger as t}from"../../utils/logger.js";import{PROVIDER_KEY as n}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as l}from"./backup.js";import{pickModel as a,toolHome as i,withV1 as d}from"./types.js";import{getToolDefaultModel as m}from"../model-registry.js";const p=()=>o(o(i(),".openclaw"),"openclaw.json");function c(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function f(){if(!e(p()))return{};const o=r(p(),"utf-8");if(!o.trim())return{};const t=JSON.parse(o);if(!c(t))throw new Error("openclaw.json root must be a JSON object");return t}export const openclawAdapter={name:"openclaw",displayName:"OpenClaw",command:"openclaw",installCommand:"npm install -g openclaw",hidden:!0,configPath:p(),loadPrivateConfig(e){let r;try{r=f()}catch(e){throw new Error(`Existing ~/.openclaw/openclaw.json cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}const o=c(r.models)?r.models:r.models={};o.mode||(o.mode="merge");const t=c(o.providers)?o.providers:o.providers={},i=c(t[n])?{...t[n]}:{},u=a(e.models,m("openclaw"))||function(e){const r=c(e.agents)?e.agents:{},o=c(r.defaults)?r.defaults:{},t=c(o.model)?o.model:{},s=`${n}/`;if("string"==typeof t.primary&&t.primary.startsWith(s))return t.primary.slice(s.length);const l=c(e.models)?e.models:{},a=(c(l.providers)?l.providers:{})[n],i=c(a)?a:null;return i&&Array.isArray(i.models)&&c(i.models[0])&&"string"==typeof i.models[0].id?i.models[0].id:""}(r);t[n]={...i,baseUrl:d(e.baseUrl),api:"openai-completions",apiKey:e.apiKey,models:[{id:u,name:u}]};const y=c(r.agents)?r.agents:r.agents={},g=c(y.defaults)?y.defaults:y.defaults={},w=c(g.model)?g.model:g.model={},h=`${n}/${u}`;w.primary=h;const v=c(g.models)?g.models:g.models={};Object.prototype.hasOwnProperty.call(v,h)||(v[h]={}),s(p()),l(p(),JSON.stringify(r,null,2))},unloadPrivateConfig(){if(!e(p()))return;let r;try{r=f()}catch(e){return void t.logError("openclawAdapter.unloadPrivateConfig",e)}const o=c(r.models)?r.models:null;o&&c(o.providers)&&delete o.providers[n];const a=c(r.agents)?r.agents:null,i=a&&c(a.defaults)?a.defaults:null,d=i&&c(i.model)?i.model:null,m=`${n}/`;if(d&&"string"==typeof d.primary&&d.primary.startsWith(m)&&delete d.primary,i&&c(i.models))for(const e of Object.keys(i.models))e.startsWith(m)&&delete i.models[e];s(p()),l(p(),JSON.stringify(r,null,2))},detectCurrentConfig(){try{const e=f(),r=c(e.models)?e.models:{},o=(c(r.providers)?r.providers:{})[n],t=c(o)?o:null,s=t&&"string"==typeof t.apiKey?t.apiKey:null;return{apiKey:s&&s.trim()?s:null}}catch{return{apiKey:null}}},getConfig(){try{return f()}catch(e){return t.logError("openclawAdapter.getConfig",e),null}}};
@@ -0,0 +1 @@
1
+ import{join as o}from"path";import{openCodeManager as e}from"../opencode-manager.js";import{backupBeforeWrite as n}from"./backup.js";import{pickModel as t,toolHome as i}from"./types.js";import{getToolDefaultModel as a}from"../model-registry.js";const d=()=>o(i(),".config","opencode","opencode.json");export const opencodeAdapter={name:"opencode",displayName:"OpenCode",command:"opencode",installCommand:"npm install -g opencode-ai",get configPath(){return d()},hidden:!0,loadPrivateConfig(o){n(d());const i=t(o.models,a("opencode"));e.loadPrivateConfig(o.apiKey,{...o.models,opus:i,haiku:i})},unloadPrivateConfig(){n(d()),e.unloadPrivateConfig()},detectCurrentConfig:()=>e.detectCurrentConfig(),getConfig:()=>e.getConfig(),updateConfig(o){e.saveConfig(o)}};
@@ -0,0 +1 @@
1
+ import{claudeCodeAdapter as o}from"./claude-code.js";import{opencodeAdapter as r}from"./opencode.js";import{codexAdapter as t}from"./codex.js";import{openclawAdapter as m}from"./openclaw.js";import{hermesAdapter as e}from"./hermes.js";import{atomcodeAdapter as p}from"./atomcode.js";import{grokAdapter as s}from"./grok.js";import{claudeDesktopAdapter as i}from"./claude-desktop.js";import{antigravityAdapter as n}from"./antigravity.js";const c=[o,r,t,m,e,p,s,i,n];export const TOOL_ADAPTERS=Object.fromEntries(c.map(o=>[o.name,o]));export function getAdapter(o){return TOOL_ADAPTERS[o]}export function listAdapters(){return[...c]}
@@ -0,0 +1 @@
1
+ import{spawnSync as r}from"child_process";import{existsSync as t,realpathSync as n,statSync as o}from"fs";import{delimiter as e,dirname as s,isAbsolute as i,join as a}from"path";import{i18n as p}from"../i18n.js";import{toolHome as c}from"./types.js";import{brand as m}from"../brand.js";export const NPM_MIRROR="https://registry.npmmirror.com";export function brandInstallScripts(r){const t=m().installMirror?.scripts;return t?{sh:`${t}/${r}.sh`,ps1:`${t}/${r}.ps1`}:void 0}export function npmMirrorInstallCommand(r){return`npm install -g ${r.npmPackage}@latest --registry=${NPM_MIRROR}`}export function mirrorInstallCommand(r){return r.mirrorScript?"win32"===process.platform?`powershell -NoProfile -ExecutionPolicy Bypass -Command "irm ${r.mirrorScript.ps1} | iex"`:`curl -fsSL ${r.mirrorScript.sh} | sh`:r.npmPackage?npmMirrorInstallCommand(r):""}export function npmUninstallCommand(r){return`npm uninstall -g ${r.npmPackage}`}export function installLabel(r){return p.t("upgrade.install_label",{kind:p.t(`upgrade.kind.${r.kind}`),version:r.version??"?",path:r.path})}let l=t=>{const n={encoding:"utf-8",timeout:1e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]};return`${(/\.cmd$/i.test(t)?r(`"${t}" --version`,{...n,shell:!0}):r(t,["--version"],n)).stdout??""}`};const u=new Map;export function setVersionRunnerForTests(r){l=r,u.clear()}export function forgetInstalls(){u.clear()}function d(r){try{return o(r).isFile()}catch{return!1}}function f(r,o){if(r.native&&(e=s(o),i=a(c(),...r.native.binDir),"win32"===process.platform?e.toLowerCase()===i.toLowerCase():e===i))return"native";var e,i;const p=r.npmPackage?a("node_modules",...r.npmPackage.split("/")):null;if(p&&t(a(s(o),p)))return"npm";let m=o;try{m=n(o)}catch{return"other"}return p&&m.includes(p)?"npm":/[\\/](Cellar|Caskroom)[\\/]/.test(m)?"brew":"other"}export function findInstalls(r){const t=u.get(r.command);if(t)return t;const o="win32"===process.platform?[`${r.command}.exe`,`${r.command}.cmd`]:[r.command],s=new Set,p=[];for(const t of(process.env.PATH??"").split(e))if(t&&i(t))for(const e of o){const o=a(t,e);if(!d(o))continue;let i=o;try{i=n(o)}catch{}const c="win32"===process.platform?i.toLowerCase():i;if(s.has(c))continue;s.add(c);const m=l(o).match(/(\d+)\.(\d+)\.(\d+)/);p.push({path:o,kind:f(r,o),version:m?m[0]:null})}return u.set(r.command,p),p}
@@ -0,0 +1 @@
1
+ import{homedir as o}from"os";import{join as r}from"path";import{getDefaultModels as e}from"../model-registry.js";import{brandEnv as t}from"../brand.js";export function toolHome(){const r=t("TEST_HOME");return r&&r.trim()?r.trim():o()}export function codexHome(){return process.env.CODEX_HOME?.trim()||r(toolHome(),".codex")}export function primaryModel(o){return o.opus||o.sonnet||o.reasoning||o.haiku}export function pickModel(o,r){const t=primaryModel(o);return t&&t!==e().opus?t:r}export function withV1(o){const r=(o||"").replace(/\/+$/,"");return/\/v\d+$/.test(r)?r:`${r}/v1`}export class UserActionNeeded extends Error{constructor(o){super(o),this.name="UserActionNeeded"}}
@@ -0,0 +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()}
@@ -0,0 +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{i18n as m,detectSystemLang as u}from"./i18n.js";import{createBorderLine as _,createContentLine as g}from"../utils/string-width.js";import{validateApiKey as w,fetchModels as f}from"./api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as y}from"./tools/codex.js";import{CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as h}from"./tools/claude-desktop.js";import{addressesWithCurrent as z,ensureReachableGatewayAddress as v,fastestIndex as k,probeAll as x,probeSummary as b,reasonText as S,savedApiKey as C,switchGatewayAddress as M}from"../commands/base.js";import{readFileSync as T}from"fs";import{dirname as A,join as K}from"path";import{fileURLToPath as N}from"url";import{brand as B}from"./brand.js";const P=A(N(import.meta.url)),H=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(H.bold("\n"+_("╔","╗","═",this.BOX_WIDTH))),console.log(H.bold(g(e,"║","║",this.BOX_WIDTH,"center"))),console.log(H.bold(_("╚","╝","═",this.BOX_WIDTH))),console.log("")}showOperationHints(){const e=[t.gray(m.t("wizard.hint_navigate")),t.gray(m.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=m.t("wizard.banner_subtitle"),a=g(t,"║","║",e,"center"),o=g("","║","║",e,"center"),i=g(`${B().productName} v${function(){try{return JSON.parse(T(K(P,"..","..","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=>g(s+t,"║","║",e,"left")),c=[_("╔","╗","═",e),o,...l,o,i,a,_("╚","╝","═",e)];console.log(H.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=m.t("wizard.goodbye_message_tools",{commands:t}),e.some(e=>"claude-code"===e.name)&&(a+=" "+m.t("wizard.goodbye_claude_hint"))}else a=m.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(" ! "+m.t("win32"===process.platform?"setup.path_reload_windows":"setup.path_reload",{commands:o})))}async runFirstTimeSetup(){const e="zh_CN"===u();e&&(o.setLang("zh_CN"),m.setLocale("zh_CN")),this.resetScreen(),console.log(H.bold("\n"+m.t("wizard.welcome"))),console.log(t.gray(m.t("wizard.privacy_note")+"\n")),e?console.log(t.gray(m.t("wizard.lang_auto_zh")+"\n")):await this.configLanguage(),await v(),await this.configApiKey()&&await this.selectAndConfigureTool(!0)}async configLanguage(){for(;;){this.resetScreen(),this.createBox(m.t("wizard.select_language"));const a=m.getLocale(),{language:i}=await this.promptWithHints([{type:"list",name:"language",message:"✨ "+m.t("wizard.select_language"),choices:[{name:"[EN] English"+("en_US"===a?t.green(" ✓ ("+m.t("wizard.current_active")+")"):""),value:"en_US"},{name:"[CN] 中文"+("zh_CN"===a?t.green(" ✓ ("+m.t("wizard.current_active")+")"):""),value:"zh_CN"},new e.Separator,{name:"<- "+m.t("wizard.nav_return"),value:"back"},{name:"x "+m.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 m.setLocale(i)}}buildPresetChoices(){const a=n(),o=a.filter(e=>e.recommended),i=a.filter(e=>!e.recommended),r=e=>({name:(m.t(e.name)!==e.name?m.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")("── "+m.t("wizard.recommended")+" ──"))),s.push(...o.map(r))),i.length>0&&(s.push(new e.Separator(t.gray("── "+m.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:m.t("wizard.custom_model_mode"),choices:[{name:m.t("wizard.custom_model_single"),value:"single"},{name:m.t("wizard.custom_model_per_role"),value:"per_role"}]}]);if("single"===n){const{customModel:t}=await e.prompt([{type:"input",name:"customModel",message:m.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:m.t("wizard.model_haiku"),default:a.haiku},{type:"input",name:"sonnet",message:m.t("wizard.model_sonnet"),default:a.sonnet},{type:"input",name:"opus",message:m.t("wizard.model_opus"),default:a.opus},{type:"input",name:"reasoning",message:m.t("wizard.model_reasoning"),default:a.reasoning}]);o.setModels(t)}console.log(t.green("\n✓ "+m.t("wizard.models_saved")))}async configModels(a){const i=o.getApiKey();if(await this.validatedKeyForConfiguration(i))for(;;){this.resetScreen(),this.createBox(m.t("wizard.config_models"));const i=[...this.buildPresetChoices()];i.push(new e.Separator),i.push({name:"✏️ "+m.t("wizard.custom_model_input"),value:{type:"custom_input"}}),i.push(new e.Separator),i.push({name:"<- "+m.t("wizard.nav_return"),value:{type:"back"}}),i.push({name:"x "+m.t("wizard.nav_exit"),value:{type:"exit"}});const{modelChoice:n}=await this.promptWithHints([{type:"list",name:"modelChoice",message:m.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✓ "+m.t("wizard.models_saved"))),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}}}else await e.prompt([{type:"input",name:"continue",message:m.t("wizard.press_enter")}])}async promptLoadAfterModelConfig(){const{shouldLoad:t}=await e.prompt([{type:"list",name:"shouldLoad",message:m.t("wizard.load_config_now"),choices:[{name:m.t("wizard.load_config_yes"),value:!0},{name:m.t("wizard.load_config_later"),value:!1}]}]);t&&await this.selectAndConfigureTool()}async configBaseUrl(){const i=o.getBaseUrl(),n=z(),r=a(m.t("wizard.base_testing")).start(),s=await x(n,{apiKey:C(),samples:3});r.stop();const l=k(s),c=n.map((e,a)=>{const o=e.url===i?t.cyan(` ← ${m.t("base.current_mark")}`):"";return{name:`${e.url} ${t.gray(e.label)} ${b(s[a],a===l)}${o}`,value:e.url}});c.push(new e.Separator,{name:"<- "+m.t("wizard.nav_return"),value:"__back__"});const{url:d}=await this.promptWithHints([{type:"list",name:"url",message:m.t("wizard.base_select"),choices:c,default:i}]);if("__back__"===d)return;const p=s[n.findIndex(e=>e.url===d)];p.ok?await M(d):console.log(t.red(m.t("base.unreachable",{url:d,reason:S(p)}))),await e.prompt([{type:"input",name:"continue",message:m.t("wizard.press_enter")}])}async configApiKey(){for(;;){this.resetScreen(),this.createBox(m.t("wizard.input_api_key")),console.log(t.gray("\n💡 "+m.t("wizard.api_key_input_hint"))),console.log(t.gray(" "+m.t("wizard.api_key_get_hint",{url:B().links.tokenPage}))),console.log();const{apiKey:i}=await e.prompt([{type:"password",name:"apiKey",message:m.t("wizard.input_your_api_key"),mask:"*"}]);if(!i||""===i.trim()){const{action:t}=await e.prompt([{type:"list",name:"action",message:m.t("wizard.select_action"),choices:[{name:m.t("wizard.retry_input"),value:"retry"},{name:"<- "+m.t("wizard.nav_return"),value:"back"}]}]);if("back"===t)return!1;continue}const n=a(m.t("wizard.validating_api_key")).start(),r=await w(i.trim());if(n.stop(),r.valid)return o.setApiKey(i.trim()),this.validatedApiKeys.add(i.trim()),console.log(t.green("\n✓ "+m.t("wizard.api_key_valid"))),!0;{this.validatedApiKeys.delete(i.trim()),"invalid_api_key"===r.error?console.log(t.red("\n✗ "+m.t("wizard.api_key_invalid"))):console.log(t.red("\n✗ "+m.t("wizard.api_key_network_error")));const{action:a}=await e.prompt([{type:"list",name:"action",message:m.t("wizard.select_action"),choices:[{name:m.t("wizard.retry_input"),value:"retry"},{name:"<- "+m.t("wizard.nav_return"),value:"back"}]}]);if("back"===a)return!1}}}async selectAndConfigureTool(t=!1){for(;;){this.resetScreen(),this.createBox(m.t("wizard.select_tool"));const a=l.getSupportedTools().map(e=>({name:e.displayName,value:e.name})),{tool:o}=await this.promptWithHints([{type:"list",name:"tool",message:"🛠️ "+m.t("wizard.select_tool"),choices:[...a,new e.Separator,{name:"<- "+m.t("wizard.nav_return"),value:"back"},{name:"x "+m.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===o)this.printGoodbye(),process.exit(0);else if("back"===o)return;await this.configureTool(o,t)}}async configureTool(a,o=!1){const i=c[a];if(i){if(!l.isToolInstalled(a)){console.log(t.yellow("\n"+m.t("wizard.tool_not_installed",{tool:i.displayName})));const{install:o}=await e.prompt([{type:"confirm",name:"install",message:m.t("wizard.install_tool_confirm"),default:!0}]);if(!o)return;try{await l.installTool(a)}catch{return void console.log(t.red(m.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+" "+m.t("wizard.menu_title"));const o=[{name:"📥 "+m.t("wizard.action_load_config",{tool:a.displayName}),value:"load"},{name:"📤 "+m.t("wizard.action_unload_config",{tool:a.displayName}),value:"unload"}];l.supportsClearPinnedModels(t)&&o.push({name:"🧹 "+m.t("wizard.action_clear_model",{tool:a.displayName}),value:"clear-model"}),o.push({name:"🧨 "+m.t("wizard.action_force_config",{tool:a.displayName}),value:"force"},{name:"↩️ "+m.t("wizard.action_restore_config",{tool:a.displayName}),value:"restore"},new e.Separator,{name:"<- "+m.t("wizard.nav_return"),value:"back"},{name:"x "+m.t("wizard.nav_exit"),value:"exit"});const{action:i}=await this.promptWithHints([{type:"list",name:"action",message:"⚙️ "+m.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):"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"+m.t("wizard.api_key_required"))),console.log(t.yellow(m.t("wizard.please_config_api_key_first"))),null;if(this.validatedApiKeys.has(o))return o;const i=a(m.t("wizard.validating_api_key")).start(),n=await w(o);if(n.valid)return this.validatedApiKeys.add(o),i.succeed(m.t("wizard.api_key_valid")),o;this.validatedApiKeys.delete(o);const r="invalid_api_key"===n.error?m.t("wizard.api_key_invalid"):m.t("wizard.api_key_network_error");return i.fail(r),console.log(t.red("\n"+m.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:m.t("wizard.press_enter")}]),!1;const d="claude-code"===i,p=d||"claude-desktop"===i||"agy"===i,u=s(i),_=p||!u?m.t("wizard.model_builtin_default"):u;this.resetScreen(),this.createBox(n.displayName+" · "+m.t("wizard.config_models"));const g=[{name:"✅ "+m.t("wizard.use_default_model",{model:_}),value:{type:"default"}},{name:"🌐 "+m.t("wizard.fetch_models_from_api"),value:{type:"fetch"}},...this.buildPresetChoices(),new e.Separator,{name:"✏️ "+m.t("wizard.input_custom_model"),value:{type:"custom"}},new e.Separator,{name:"<- "+m.t("wizard.nav_return"),value:{type:"back"}}],{choice:w}=await this.promptWithHints([{type:"list",name:"choice",message:m.t("wizard.select_tool_model",{tool:n.displayName}),choices:g}]);if("back"===w.type)return!1;if("default"===w.type)o.setToolModel(i,null);else if("preset"===w.type)o.setToolModel(i,r(w.preset));else if("custom"===w.type){const{model:t}=await e.prompt([{type:"input",name:"model",message:m.t("wizard.input_custom_model"),default:!p&&u?u:void 0}]),a=(t||"").trim();o.setToolModel(i,a?this.singleModelOverride(a):null)}else if("fetch"===w.type){const n=a(m.t("wizard.fetching_models")).start(),r=await f(l);let s;if(n.stop(),r.ok&&r.models.length>0){const{model:t}=await e.prompt([{type:"list",name:"model",message:m.t("wizard.select_fetched_model"),pageSize:20,choices:[...r.models,new e.Separator,{name:"<- "+m.t("wizard.nav_return"),value:"__back__"}]}]);if("__back__"===t)return!1;s=t}else{console.log(t.yellow("\n"+m.t("wizard.fetch_models_failed")));const{model:a}=await e.prompt([{type:"input",name:"model",message:m.t("wizard.input_custom_model"),default:!p&&u?u:void 0}]);s=(a||"").trim()}o.setToolModel(i,s?this.singleModelOverride(s):null)}if("codex"===i){const t=o.getToolSetting(i,y),{enableOneMillionContext:a}=await e.prompt([{type:"confirm",name:"enableOneMillionContext",message:m.t("wizard.codex_enable_1m_context"),default:!1!==t}]);o.setToolSetting(i,y,Boolean(a))}if("claude-desktop"===i){const t=o.getToolSetting(i,h),{hideOfficialLogin:a}=await e.prompt([{type:"confirm",name:"hideOfficialLogin",message:m.t("wizard.desktop_hide_official_login"),default:!1!==t}]);o.setToolSetting(i,h,Boolean(a))}return console.log(t.green("\n✓ "+m.t("wizard.models_saved"))),d&&console.log(t.gray("💡 "+m.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:m.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:m.t("wizard.press_enter")}]);if(!n.force&&!await d([i]))return;const u=a(m.t("wizard.loading_config")).start();try{await l.applyPrivateConfig(i,s,r,n),u.stop(),l.printApplied(i),await p([i]),n.force&&console.log(t.yellow(m.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"+m.t("wizard.run_tool_hint",{command:a.command}))),this.printPathReloadHint([i]));const{nextAction:o}=await e.prompt([{type:"list",name:"nextAction",message:m.t("wizard.what_next"),choices:[{name:m.t("wizard.exit_and_start"),value:"exit"},{name:m.t("wizard.continue_config"),value:"continue"}]}]);"exit"===o&&(this.printGoodbye(),process.exit(0))}catch(a){u.fail(m.t("wizard.config_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:m.t("wizard.press_enter")}])}}async clearPinnedModels(a){const o=c[a]?.displayName||a,{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:m.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"+m.t("config.clear_model_none",{tool:o}))):(console.log(t.green("\n✓ "+m.t("config.clear_model_done",{tool:o}))),e.forEach(e=>console.log(t.gray(` - ${e}`))),console.log(t.gray(m.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:m.t("wizard.press_enter")}])}}async unloadConfig(o){const{confirm:i}=await e.prompt([{type:"confirm",name:"confirm",message:m.t("wizard.confirm_unload_config",{tool:c[o]?.displayName||o}),default:!1}]);if(!i)return;const n=a(m.t("wizard.unloading_config")).start();try{const a=l.holdsOurConfig(o),i=l.unloadPrivateConfig(o);if(!a)return void n.info(m.t("config.remove_nothing",{tool:c[o]?.displayName||o}));n.succeed(m.t("wizard.config_unloaded")),i.forEach(e=>console.log(t.yellow(" ! "+e.text)));const{nextAction:r}=await e.prompt([{type:"list",name:"nextAction",message:m.t("wizard.what_next"),choices:[{name:m.t("wizard.nav_exit"),value:"exit"},{name:m.t("wizard.continue_config"),value:"continue"}]}]);"exit"===r&&(this.printGoodbye(),process.exit(0))}catch(a){n.fail(m.t("wizard.config_unload_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:m.t("wizard.press_enter")}])}}async restoreConfig(o){const i=c[o]?.displayName||o,{confirm:n}=await e.prompt([{type:"confirm",name:"confirm",message:m.t("wizard.confirm_restore_config",{tool:i}),default:!1}]);if(!n)return;const r=a(m.t("wizard.restoring_config")).start();try{const e=l.restorePrivateConfig(o).filter(e=>e.result.restored);0===e.length?r.warn(m.t("wizard.restore_no_backup")):(r.succeed(m.t("wizard.config_restored",{tool:i})),e.forEach(e=>console.log(t.gray(` ${e.file} ← ${e.result.from}`))),console.log(t.yellow(" ! "+m.t("config.reopen_hint",{tool:i}))))}catch(e){r.fail(m.t("wizard.config_restore_failed")),console.log(t.red(e instanceof Error?e.message:String(e)))}await e.prompt([{type:"input",name:"continue",message:m.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(H("── "+m.t("wizard.select_tool")+" ──")),...n,new e.Separator(t.gray("── "+m.t("wizard.settings")+" ──")),{name:"🔑 "+m.t("wizard.menu_change_api_key"),value:{type:"apikey"}},{name:"🔗 "+m.t("wizard.menu_base_url",{url:o.getBaseUrl()}),value:{type:"base"}},{name:"🌐 "+m.t("wizard.menu_config_language"),value:{type:"language"}},new e.Separator,{name:"x "+m.t("wizard.nav_exit"),value:{type:"exit"}}],{action:s}=await this.promptWithHints([{type:"list",name:"action",message:"🛠️ "+m.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();
@@ -0,0 +1 @@
1
+ import o from"chalk";import t from"inquirer";import{getAdapter as r}from"./tools/registry.js";import{SUPPORTED_TOOLS as n}from"./tool-manager.js";import{i18n as e}from"./i18n.js";import{isColorEnabled as l,isDryRun as i,isJsonMode as s,isNonInteractive as a,shouldAutoConfirm as c}from"./runtime-options.js";export function toolWritePlan(o){return o.map(o=>{const t=r(o);return{tool:o,files:t?.backupPaths?.()??(t?[t.configPath]:[])}})}export function printWritePlan(t,r){const i=(l()?o.cyan:o=>o)(r.label),s=l()?o.gray:o=>o;for(const{tool:o,files:r}of t)console.log(`${i} ${e.t("setup.dry_run_tool",{tool:n[o]?.displayName??o})}`),r.forEach(o=>console.log(s(` ${o}`)));for(const o of r.installFirst??[])console.log(`${i} ${e.t("plan.install_first",{tool:n[o]?.displayName??o})}`);r.keyFile&&console.log(`${i} ${e.t("setup.dry_run_key",{file:r.keyFile})}`)}export function asksBeforeWriting(){return Boolean(process.stdin.isTTY&&process.stdout.isTTY)&&!c()&&!a()&&!s()&&!i()}export async function confirmWritePlan(o,r={}){if(!asksBeforeWriting())return!0;if(0===o.length&&!r.keyFile&&!r.installFirst?.length)return!0;console.log("\n"+e.t("plan.title")),printWritePlan(toolWritePlan(o),{label:" •",...r});const{go:n}=await t.prompt([{type:"confirm",name:"go",message:e.t("plan.confirm"),default:!0}]);return n||console.log(e.t("plan.cancelled")),n}