@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{existsSync as e,readdirSync as r,readFileSync as t}from"fs";import{dirname as n,join as o}from"path";import{fileURLToPath as a}from"url";const i=["id","displayName","productName","cliName","envPrefix","configDirName","providerKey","apiKeyEnv","desktopEntryName","packageName"];export const NEUTRAL_CLI_NAME="codekey";export function normalizeBrand(e){const r=e.cliName??e.shortName??"codekey";return{...e,cliName:r,envPrefix:e.envPrefix??r.toUpperCase().replace(/-/g,"_"),configDirName:e.configDirName??`.${r}`}}export function validateBrand(e,r="brand"){if(!e||"object"!=typeof e)throw new Error(`${r}: not an object`);const t=normalizeBrand(e);for(const e of i)if("string"!=typeof t[e]||!t[e].trim())throw new Error(`${r}: ${e} is required`);if(!/^[a-z][a-z0-9-]*$/.test(t.cliName))throw new Error(`${r}: cliName must be a lowercase command name`);if(!/^[A-Z][A-Z0-9_]*$/.test(t.envPrefix))throw new Error(`${r}: envPrefix must be UPPER_SNAKE`);if(!/^[a-z][a-z0-9-]*$/.test(t.providerKey))throw new Error(`${r}: providerKey must be lowercase`);const n=t.gatewayAddresses;if(!Array.isArray(n)||0===n.length||n.some(e=>!e||"string"!=typeof e.url||!/^https:\/\//.test(e.url)||"string"!=typeof e.label))throw new Error(`${r}: gatewayAddresses must be a non-empty list of { url: https://…, label }`);const o=t.links;if(!o||"string"!=typeof o.tokenPage)throw new Error(`${r}: links.tokenPage is required`);if(!Array.isArray(t.pluginMarketplaces))throw new Error(`${r}: pluginMarketplaces must be a list`);if(!Array.isArray(t.updateRegistries)||0===t.updateRegistries.length)throw new Error(`${r}: updateRegistries must be a non-empty list`);return t}export function loadBrandFile(e){return validateBrand(JSON.parse(t(e,"utf-8")),e)}let s=function(){const i=n(a(import.meta.url)),s=o(i,"..","brand.json");if(e(s))return loadBrandFile(s);const d=o(i,"..","..","brands");for(const n of e(d)?r(d).filter(e=>e.endsWith(".json")).sort():[]){const e=JSON.parse(t(o(d,n),"utf-8"));if(!0===e.default)return validateBrand(e,o(d,n))}throw new Error(`brand.json not found next to ${i}`)}();export function brand(){return s}export function setBrandForTests(e){const r=s;return s=e,()=>{s=r}}export function brandEnv(e){return process.env[brandEnvName(e)]}export function brandEnvName(e){return`${s.envPrefix}_${e}`}function d(e,r){return"zh_CN"===r?e.join("、"):e.length>1?`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`:e.join("")}export function brandTokens(e){const r=new URL(s.gatewayAddresses[0].url),t=s.gatewayAddresses[1]?.url??s.gatewayAddresses[0].url;return{brand:s.displayName,product:s.productName,cli:s.cliName,configDir:s.configDirName,envPrefix:s.envPrefix,siteHost:r.host,altSiteUrl:t,updateSources:d(s.updateRegistries.map(e=>e.label),e)}}export const BRAND_NAME=s.displayName;export const PROVIDER_KEY=s.providerKey;export const API_KEY_ENV=s.apiKeyEnv;export const CLI_NAME=s.cliName;
@@ -0,0 +1 @@
1
+ import{existsSync as e,mkdirSync as t,readFileSync as n,writeFileSync as o,renameSync as i,unlinkSync as r}from"fs";import{join as s,dirname as a}from"path";import{toolHome as c}from"./tools/types.js";import{logger as l}from"../utils/logger.js";import{configManager as d,DEFAULT_MODELS as g}from"./config.js";import{loadSettingsTemplate as f}from"./settings-template.js";import{cleanupAnthropicEnvVars as m}from"./env-cleanup.js";import{getClaudeCodeTierChains as C,getGatewayModelRules as u}from"./model-registry.js";import{autoCompactTokens as O,modelBlurb as h,prettyModelName as p}from"./gateway-models.js";import{baseModelId as _}from"./model-catalog.js";export const MODEL_ENV_VARS=["ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL","ANTHROPIC_MODEL","ANTHROPIC_REASONING_MODEL"];const E={opus:"ANTHROPIC_DEFAULT_OPUS_MODEL",sonnet:"ANTHROPIC_DEFAULT_SONNET_MODEL",haiku:"ANTHROPIC_DEFAULT_HAIKU_MODEL",fable:"ANTHROPIC_DEFAULT_FABLE_MODEL"},A="CLAUDE_CODE_MAX_CONTEXT_TOKENS";function T(){return s(d.getConfigDir(),"claude-code-picker.json")}function P(){try{const e=JSON.parse(n(T(),"utf-8")).ids;return Array.isArray(e)?e.map(String):[]}catch{return[]}}function v(e,t=[]){if(!e||"object"!=typeof e)return!1;const{options:n,replaceBuiltInOptions:o}=e;if(!Array.isArray(n)||o)return!1;const i=u(),r=new Set([...i.models.map(e=>e.id),...i.retired,...P(),...t]);return n.every(e=>e&&"object"==typeof e&&r.has(_(String(e.model))))}export function applyGatewayModels(e,n){if(void 0===n)return e;const i={...e};if(void 0!==i.modelPicker&&!v(i.modelPicker,n.map(e=>e.id)))return i;const r=v(i.modelPicker)?i.modelPicker.options.map(e=>_(e.model)):[],s={...i.env||{}},a={...i.modelSettings||{}};for(const e of r){if(!a[e])continue;const{autoCompactWindow:t,...n}=a[e];Object.keys(n).length>0?a[e]=n:delete a[e]}const c=e=>(e.contextWindow??0)>=1e6,g=n.filter(e=>!c(e)).map(e=>e.contextWindow).filter(e=>"number"==typeof e&&e>0);!function(e){try{t(d.getConfigDir(),{recursive:!0}),o(T(),JSON.stringify({ids:e})+"\n")}catch(e){l.logError("claudeCode.recordWrittenPickerIds",e)}}(n.map(e=>e.id));const f=e=>h(e.description,{millionContext:c(e)});if(0===n.length)delete i.modelPicker,delete s[A];else{i.modelPicker={options:n.map(e=>({model:c(e)?`${e.id}[1m]`:e.id,label:e.name||p(e.id),...f(e)?{description:f(e)}:{}}))},g.length>0?s[A]=String(Math.min(...g)):delete s[A];for(const e of n){if(!e.contextWindow)continue;const t=O(e.contextWindow,e.autoCompactTokens);a[e.id]={...a[e.id],autoCompactWindow:Math.min(Math.max(t,1e5),1e6)}}}return Object.keys(a).length>0?i.modelSettings=a:delete i.modelSettings,Object.keys(s).length>0?i.env=s:delete i.env,i}export function resolveTierFallbacks(e){if(!e||0===e.length)return[];const t=new Set(e.map(_)),n=[];for(const[e,o]of Object.entries(C())){const i=E[e],[r,...s]=o;if(!i||!r||t.has(r))continue;const a=s.find(e=>t.has(e));a&&n.push({tier:e,envVar:i,from:r,to:a})}return n}export class ClaudeCodeManager{static instance;settingsPath;mcpConfigPath;lastTierFallbacks=[];constructor(){this.settingsPath=s(c(),".claude","settings.json"),this.mcpConfigPath=s(c(),".claude.json")}static getInstance(){return ClaudeCodeManager.instance||(ClaudeCodeManager.instance=new ClaudeCodeManager),ClaudeCodeManager.instance}ensureConfigDir(n){const o=a(n);e(o)||t(o,{recursive:!0})}atomicWrite(t,n){const s=`${t}.tmp`;try{o(s,n,"utf-8"),i(s,t)}catch(t){if(e(s))try{r(s)}catch{}throw t}}getSettings(){try{if(e(this.settingsPath)){const e=n(this.settingsPath,"utf-8");return JSON.parse(e)}}catch(e){l.warn("Failed to read Claude Code settings:",e),l.logError("ClaudeCodeManager.getSettings",e)}return{}}saveSettings(e){try{this.ensureConfigDir(this.settingsPath),this.atomicWrite(this.settingsPath,JSON.stringify(e,null,2))}catch(e){throw new Error(`Failed to save Claude Code settings: ${e}`)}}getMCPConfig(){try{if(e(this.mcpConfigPath)){const e=n(this.mcpConfigPath,"utf-8");return JSON.parse(e)}}catch(e){l.warn("Failed to read Claude Code MCP config:",e),l.logError("ClaudeCodeManager.getMCPConfig",e)}return{}}saveMCPConfig(e){try{this.ensureConfigDir(this.mcpConfigPath),this.atomicWrite(this.mcpConfigPath,JSON.stringify(e,null,2))}catch(e){throw new Error(`Failed to save Claude Code MCP config: ${e}`)}}loadPrivateConfig(e,t,n,o){this.ensureOnboardingCompleted(),m();const i=f(),r=i.env||{},{env:s,...a}=i,c=this.getSettings(),{ANTHROPIC_API_KEY:l,...C}=c.env||{},u={...C};for(const e of MODEL_ENV_VARS)delete u[e];const O={},h=e=>{const n=(t[e]||"").trim();return n&&n!==g[e]?n:null},p=h("haiku"),_=h("sonnet"),E=h("opus"),A=new Set([p&&"haiku",_&&"sonnet",E&&"opus"].filter(Boolean));this.lastTierFallbacks=resolveTierFallbacks(n).filter(e=>!A.has(e.tier));for(const e of this.lastTierFallbacks)O[e.envVar]=e.to;p&&(O.ANTHROPIC_DEFAULT_HAIKU_MODEL=p),_&&(O.ANTHROPIC_DEFAULT_SONNET_MODEL=_),E&&(O.ANTHROPIC_DEFAULT_OPUS_MODEL=E,O.ANTHROPIC_MODEL=E);const T={...c};for(const[e,t]of Object.entries(a))e in T||(T[e]=t);T.showThinkingSummaries=!0;const P={...T,env:{...u,...Object.fromEntries(Object.entries(r).filter(([e])=>!(e in u))),ANTHROPIC_AUTH_TOKEN:e,ANTHROPIC_BASE_URL:d.getBaseUrl(),...O}};E?P.model=E:Object.prototype.hasOwnProperty.call(a,"model")?P.model=a.model:delete P.model,this.saveSettings(applyGatewayModels(P,o))}ensureOnboardingCompleted(){try{const e=this.getMCPConfig();e.hasCompletedOnboarding||this.saveMCPConfig({...e,hasCompletedOnboarding:!0})}catch(e){l.warn("Failed to ensure onboarding completed:",e),l.logError("ClaudeCodeManager.ensureOnboardingCompleted",e)}}unloadPrivateConfig(){const e=this.getSettings();if(!e.env){if(void 0!==e.model){const{model:t,...n}=e;this.saveSettings(n)}return}const{ANTHROPIC_AUTH_TOKEN:t,ANTHROPIC_BASE_URL:n,API_TIMEOUT_MS:o,CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:i,CLAUDE_CODE_AUTO_MODE_SERVER:r,...s}=e.env,a={...s};for(const e of MODEL_ENV_VARS)delete a[e];const c={...applyGatewayModels({...e,env:a},[])};c.env=c.env||{},delete c.model,c.env&&0===Object.keys(c.env).length&&delete c.env,this.saveSettings(c)}clearPinnedModels(e){const t=this.getSettings(),n=t.env,o=n?.ANTHROPIC_AUTH_TOKEN?Object.fromEntries(resolveTierFallbacks(e).map(e=>[e.envVar,e.to])):{},i=[];for(const e of MODEL_ENV_VARS)n&&e in n&&n[e]!==o[e]&&i.push(e);void 0!==t.model&&i.push("model");const r=Object.entries(o).some(([e,t])=>n?.[e]!==t);if(0===i.length&&!r)return[];const s={...t};if(delete s.model,n){const e={...n};for(const t of MODEL_ENV_VARS)delete e[t];Object.assign(e,o),0===Object.keys(e).length?delete s.env:s.env=e}return this.saveSettings(s),i}getLastTierFallbacks(){return[...this.lastTierFallbacks]}detectCurrentConfig(){try{const e=this.getSettings();return e.env&&e.env.ANTHROPIC_AUTH_TOKEN?{apiKey:e.env.ANTHROPIC_AUTH_TOKEN}:{apiKey:null}}catch{return{apiKey:null}}}getExperimentalFeature(e){const t=this.getSettings();return t.env?.[e]}setExperimentalFeature(e,t){const n=this.getSettings(),o=n.env||{},i={...n,env:{...o,[e]:t}};this.saveSettings(i)}removeExperimentalFeature(e){const t=this.getSettings();if(!t.env)return;const{[e]:n,...o}=t.env,i={...t,env:o};this.saveSettings(i)}}export const claudeCodeManager=ClaudeCodeManager.getInstance();
@@ -0,0 +1 @@
1
+ import{i18n as e}from"./i18n.js";import{stringWidth as t}from"../utils/string-width.js";import{brand as n,CLI_NAME as r}from"./brand.js";export const DOCS_URL=n().links.commandDocs;const o=new WeakMap;export function attachCommandHelp(e,t){return o.set(e,{when:"",prerequisites:[],alternatives:[],sections:[],examples:[],...t}),e.addHelpText("after",()=>renderHelpExtras(e)),e}export function getCommandHelp(e){return o.get(e)??{when:"",prerequisites:[],alternatives:[],sections:[],examples:[]}}export function commandPath(e){const t=[];for(let n=e;n;n=n.parent)t.unshift(n.name());return t.join(" ")}function i(e){let t=e;for(;t.parent;)t=t.parent;return t}export function visibleSubcommands(e){return e.commands.filter(e=>!e._hidden)}const s=34;function l(e){const n=e.filter(([,e])=>e),r=Math.min(s,Math.max(0,...n.map(([e])=>t(e)))),o=[];for(const[n,i]of e){const e=t(n);i?e>r?o.push(` ${n}`,` ${" ".repeat(r)} ${i}`):o.push(` ${n}${" ".repeat(r-e)} ${i}`):o.push(` ${n}`)}return o}export function learnMoreRows(t){const n=[];if(visibleSubcommands(t).length>0){const r=t.parent?e.t("help.placeholder.subcommand"):e.t("help.placeholder.command");n.push([`${commandPath(t)} ${r} --help`,e.t("help.learn_more.command_help")])}return t.parent&&n.push([`${commandPath(i(t))} --help`,e.t("help.learn_more.all_commands")]),n.push([`${r} help exit-codes`,e.t("help.learn_more.exit_codes")]),n.push([`${r} help environment`,e.t("help.learn_more.environment")]),DOCS_URL&&n.push([e.t("help.learn_more.docs",{url:DOCS_URL}),""]),n}export function renderHelpExtras(t){const n=getCommandHelp(t),r=[];for(const e of n.sections)r.push("",e.title,...l(e.rows));return n.when&&r.push("",e.t("help.title.when"),...n.when.split("\n").map(e=>` ${e}`)),n.prerequisites.length>0&&r.push("",e.t("help.title.prerequisites"),...n.prerequisites.map(e=>` - ${e}`)),n.alternatives.length>0&&r.push("",e.t("help.title.alternatives"),...l(n.alternatives.map(e=>[e.command,e.note]))),n.examples.length>0&&r.push("",e.t("help.title.examples"),...l(n.examples.map(e=>[e.command,e.note]))),r.push("",e.t("help.title.learn_more"),...l(learnMoreRows(t))),r.join("\n")}const p={"Usage:":"help.title.usage","Arguments:":"help.title.arguments","Options:":"help.title.options","Global Options:":"help.title.global_options","Commands:":"help.title.commands"};export function localizeTitle(t){const n=p[t];return n?e.t(n):t}function a(t,n,r){if(void 0===n)return t;const o=r??("string"==typeof n?n:JSON.stringify(n)),i=e.t("help.default_value",{value:o});return t?`${t}(${i})`:i}export function describeOption(e){return e.required||e.optional?a(e.description,e.defaultValue,e.defaultValueDescription):e.description}export function describeArgument(e){return a(e.description,e.defaultValue,e.defaultValueDescription)}export function helpConfiguration(){return{showGlobalOptions:!0,styleTitle:e=>localizeTitle(e),optionDescription:e=>describeOption(e),argumentDescription:e=>describeArgument(e)}}export function firstCommandWord(e){for(let t=0;t<e.length;t+=1){const n=e[t];if("--"===n)return;if("--base"!==n){if(!n.startsWith("-"))return n}else t+=1}}export function isHelpRequest(e){for(const t of e){if("--"===t)break;if("-h"===t||"--help"===t)return!0}return"help"===firstCommandWord(e)}export function renderHelpTopic(t){const n="exit-codes"===t?"exit_codes":"environment"===t?"environment":null;return n?`${e.t(`help_topics.${n}.title`)}\n\n${e.t(`help_topics.${n}.body`)}\n`:null}
@@ -0,0 +1 @@
1
+ import{CLIENT_CONFIG_PATH as e}from"./gateway-protocol.js";import{logger as t}from"../utils/logger.js";import{bundledClientConfig as o,parseClientConfig as n,readCachedClientConfig as r,setClientConfigSiteResolver as i,writeCachedClientConfig as c}from"./client-config.js";import{configManager as f}from"./config.js";import{getBuiltinGatewayAddresses as s,reloadRegistry as l}from"./model-registry.js";import{brandEnv as g,brand as a}from"./brand.js";export const CLIENT_CONFIG_TTL_MS=3e5;function u(e){try{return new URL(e).origin}catch{return e.replace(/\/+$/,"")}}export function clientConfigSite(e=f.getBaseUrl()){const t=u(e);return s().some(e=>u(e.url)===t)?a().id:t}i(()=>clientConfigSite());let d=null;export function lastClientConfigStatus(){return d}function m(e){const t=r();if(t&&t.site===clientConfigSite())return{config:t.config,source:"cache",revision:t.config.revision,fetchedAt:t.fetchedAt,problem:e};const n=o();return n?{config:n,source:"bundled",revision:n.revision,problem:e}:{config:null,source:null,problem:e}}export async function refreshClientConfig(i={}){const{force:s=!1,timeoutMs:u=8e3,fetchFn:h=fetch,now:p=Date.now()}=i;if("1"===g("DISABLE_CLIENT_CONFIG_FETCH"))return d=m(),d;const C=clientConfigSite(),v=r(),w=v&&v.site===C?v:null;if(!s&&w&&p-w.fetchedAt<3e5)return d={config:w.config,source:"cache",revision:w.config.revision,fetchedAt:w.fetchedAt},d;const A=w?.config??(C===a().id?o():null),T=new AbortController,b=setTimeout(()=>T.abort(),u);try{const o={};w?.etag&&(o["If-None-Match"]=w.etag);const r=await h(`${f.getBaseUrl()}${e}`,{method:"GET",headers:o,signal:T.signal});if(304===r.status&&w)return c({...w,fetchedAt:p}),d={config:w.config,source:"cloud",revision:w.config.revision,fetchedAt:p},d;if(!r.ok)return d=m(`HTTP ${r.status}`),d;const i=await r.json(),{config:s,problem:g}=n(i?.data,A);if(!s)return t.warn(`Gateway client config refused: ${g}`),d=m(`refused: ${g}`),d;g&&t.warn(`Gateway client config: ${g}`);const a=r.headers.get("etag")??void 0;return c({site:C,fetchedAt:p,config:s,...a?{etag:a}:{}}),l(),d={config:s,source:"cloud",revision:s.revision,fetchedAt:p,...g?{problem:g}:{}},d}catch(e){return t.logError("refreshClientConfig",e),d=m(e instanceof Error?e.message:String(e)),d}finally{clearTimeout(b)}}
@@ -0,0 +1 @@
1
+ import{createHash as t,randomUUID as e}from"crypto";import{existsSync as n,mkdirSync as o,readFileSync as i,renameSync as r,writeFileSync as s}from"fs";import{homedir as l}from"os";import{dirname as c,join as f}from"path";import{fileURLToPath as a}from"url";import{CLIENT_SECTION as u,MIN_CLIENT_VERSION as d}from"./gateway-protocol.js";import{brand as m,brandEnv as p}from"./brand.js";export const CLIENT_CONFIG_SCHEMA=1;const h=new Set(["haiku","sonnet","opus","reasoning","fable"]),g=/^[A-Za-z0-9._:@/\-[\]]{1,200}$/,_=/^[a-z][a-z0-9-]{0,31}$/,b=/^\d+(\.\d+){0,3}$/,y=t=>!!t&&"object"==typeof t&&!Array.isArray(t),C=t=>"number"==typeof t&&Number.isFinite(t)&&t>0?Math.floor(t):void 0;function $(t){if(!y(t)||"string"!=typeof t.id||!t.id.trim())return null;const e={id:t.id.trim()};if(!0===t.hidden)return{...e,hidden:!0};"string"==typeof t.name&&t.name.trim()&&(e.name=t.name.trim()),"string"==typeof t.description&&t.description.trim()&&(e.description=t.description.trim());const n=C(t.context_window);n&&(e.contextWindow=n);const o=C(t.auto_compact_tokens);if(o&&(e.autoCompactTokens=o),y(t.clients)){const n={};for(const[e,o]of Object.entries(t.clients))_.test(e)&&"boolean"==typeof o&&(n[e]=o);Object.keys(n).length>0&&(e.clients=n)}const i=t[d];return"string"==typeof i&&b.test(i)&&(e.minClientVersion=i),"number"==typeof t.rollout_percent&&t.rollout_percent>=0&&t.rollout_percent<=100&&(e.rolloutPercent=t.rollout_percent),e}function k(t,e,n,o){if(void 0===t)return{};if(!y(t))throw new Error(`${u}.${o} must be an object`);const i={};for(const[r,s]of Object.entries(t)){if(!e.test(r)||"string"!=typeof s||!n(s))throw new Error(`${u}.${o}.${r} is invalid`);i[r]=s}return i}function v(t,e,{nonEmpty:n=!1}={}){if(void 0===t)return[];if(!Array.isArray(t)||t.some(t=>"string"!=typeof t||!g.test(t)))throw new Error(`${u}.${e} must be a list of model ids`);if(n&&0===t.length)throw new Error(`${u}.${e} must not be empty`);return[...t]}function w(t,e,n){if(void 0===t)return{};if(!y(t))throw new Error(`${u}.${e} must be an object`);const o={};for(const[i,r]of Object.entries(t)){if(!h.has(i))throw new Error(`${u}.${e}.${i} is not a tier slot`);o[i]=v(r,`${e}.${i}`,{nonEmpty:n})}return o}const j=t=>(t??[]).filter(t=>!t.hidden).length;export function parseClientConfig(t,e){if(!y(t))return{config:null,problem:"not an object"};if(1!==t.schema)return{config:null,problem:`unsupported schema ${String(t.schema)}`};if(!y(t.models))return{config:null,problem:"models is not an object"};const n={};for(const[e,o]of Object.entries(t.models)){if(!Array.isArray(o))return{config:null,problem:`models.${e} is not a list`};const t=o.map($);if(t.some(t=>null===t))return{config:null,problem:`models.${e} has a row without an id`};n[e]=t}let o,i;try{o=function(t){if(null==t)return;if(!y(t))throw new Error(`${u} must be an object`);const e={};if(void 0!==t.min_version){if("string"!=typeof t.min_version||t.min_version&&!b.test(t.min_version))throw new Error(`${u}.min_version is invalid`);t.min_version&&(e.minVersion=t.min_version)}const n=k(t.default_models,/^(haiku|sonnet|opus|reasoning|fable)$/,t=>g.test(t),"default_models");Object.keys(n).length&&(e.defaultModels=n);const o=w(t.retired_default_models,"retired_default_models",!1);Object.keys(o).length&&(e.retiredDefaultModels=o);const i=k(t.tool_defaults,_,t=>""===t||g.test(t),"tool_defaults");Object.keys(i).length&&(e.toolDefaults=i);const r=w(t.tier_chains,"tier_chains",!0);Object.keys(r).length&&(e.tierChains=r);const s=v(t.retired_models,"retired_models");s.length&&(e.retiredModels=s);const l=k(t.tool_min_versions,_,t=>""===t||b.test(t),"tool_min_versions");Object.keys(l).length&&(e.toolMinVersions=l);const c=v(t.agy_models,"agy_models");c.length&&(e.agyModels=c);const f=v(t.one_million_fallback,"one_million_fallback");return f.length&&(e.oneMillionFallback=f),!0===t.accept_shrink&&(e.acceptShrink=!0),e}(t[u])}catch(t){i=`${u} section dropped: ${t instanceof Error?t.message:String(t)}`}const r=t[u];if(e&&(!y(r)||!0!==r.accept_shrink))for(const[t,o]of Object.entries(e.models)){const e=j(o),i=j(n[t]);if(e>0&&0===i||e>=4&&2*i<e)return{config:null,problem:`models.${t} shrank from ${e} to ${i}`}}return{config:{schema:1,revision:"string"==typeof t.revision?t.revision:"",models:n,...o?{client:o}:{}},problem:i}}export function serializeClientConfig(t){const e=Object.fromEntries(Object.entries(t.models).map(([t,e])=>[t,e.map(t=>({id:t.id,...t.hidden?{hidden:!0}:{},...t.name?{name:t.name}:{},...t.description?{description:t.description}:{},...t.contextWindow?{context_window:t.contextWindow}:{},...t.autoCompactTokens?{auto_compact_tokens:t.autoCompactTokens}:{},...t.clients?{clients:t.clients}:{},...t.minClientVersion?{[d]:t.minClientVersion}:{},...void 0!==t.rolloutPercent?{rollout_percent:t.rolloutPercent}:{}}))])),n=t.client,o=n?{...n.minVersion?{min_version:n.minVersion}:{},...n.defaultModels?{default_models:n.defaultModels}:{},...n.retiredDefaultModels?{retired_default_models:n.retiredDefaultModels}:{},...n.toolDefaults?{tool_defaults:n.toolDefaults}:{},...n.tierChains?{tier_chains:n.tierChains}:{},...n.retiredModels?{retired_models:n.retiredModels}:{},...n.toolMinVersions?{tool_min_versions:n.toolMinVersions}:{},...n.agyModels?{agy_models:n.agyModels}:{},...n.oneMillionFallback?{one_million_fallback:n.oneMillionFallback}:{},...n.acceptShrink?{accept_shrink:!0}:{}}:void 0;return{schema:t.schema,revision:t.revision,models:e,...o?{[u]:o}:{}}}function O(){const t=p("CONFIG_DIR")?.trim();if(t)return t;const e=p("TEST_HOME")?.trim();return f(e||l(),m().configDirName)}export const cachePath=()=>f(O(),"client-config.json");function x(t,e){o(c(t),{recursive:!0});const n=`${t}.${process.pid}.tmp`;s(n,e,"utf-8"),r(n,t)}export function readCachedClientConfig(){try{if(!n(cachePath()))return null;const t=JSON.parse(i(cachePath(),"utf-8"));if("string"!=typeof t.site||"number"!=typeof t.fetchedAt)return null;const{config:e}=parseClientConfig(t.config);return e?{site:t.site,fetchedAt:t.fetchedAt,config:e,..."string"==typeof t.etag?{etag:t.etag}:{}}:null}catch{return null}}export function writeCachedClientConfig(t){x(cachePath(),JSON.stringify({site:t.site,etag:t.etag,fetchedAt:t.fetchedAt,config:serializeClientConfig(t.config)},null,2)+"\n")}let E;export function bundledClientConfig(){if("1"===p("NO_BUNDLED_CLIENT_CONFIG"))return null;if(void 0!==E)return E;E=null;const t=c(a(import.meta.url));for(const e of[f(t,"..","..","client-config.snapshot.json"),f(t,"..","client-config.snapshot.json")])try{if(!n(e))continue;E=parseClientConfig(JSON.parse(i(e,"utf-8"))).config;break}catch{}return E}let M=null;export function setClientConfigSiteResolver(t){M=t}export function currentClientConfig(){const t=readCachedClientConfig();let e=null;try{e=M?M():null}catch{e=null}if(t&&null!==e&&t.site===e)return{config:t.config,source:"cache",fetchedAt:t.fetchedAt};const n=bundledClientConfig();return n?{config:n,source:"bundled"}:null}let V=null,A=null;export function setClientIdentityForTests(t,e){V=t,A=e}export const clientVersion=()=>V??function(){try{const t=c(a(import.meta.url));for(const e of[f(t,"..","..","package.json"),f(t,"..","package.json")])if(n(e))return String(JSON.parse(i(e,"utf-8")).version??"0.0.0")}catch{}return"0.0.0"}();function S(t,e){const n=t.split(".").map(t=>parseInt(t,10)||0),o=e.split(".").map(t=>parseInt(t,10)||0);for(let t=0;t<Math.max(n.length,o.length);t++){const e=(n[t]??0)-(o[t]??0);if(e)return e}return 0}export function installId(){if(A)return A;const t=f(O(),"install-id");try{if(n(t)){const e=i(t,"utf-8").trim();if(e)return e}const o=e();return x(t,o+"\n"),o}catch{return"unknown"}}export function rolloutBucket(e){return t("sha256").update(`${installId()}:${e}`).digest().readUInt32BE(0)%100}export function isEligible(t){return!(t.minClientVersion&&S(clientVersion(),t.minClientVersion)<0||void 0!==t.rolloutPercent&&rolloutBucket(t.id)>=t.rolloutPercent)}export function eligibleLists(t){return Object.fromEntries(Object.entries(t).map(([t,e])=>[t,e.map(t=>t.hidden||isEligible(t)?t:{id:t.id,hidden:!0})]))}export function usableClientSection(t){const e=t?.client;if(e&&!(e.minVersion&&S(clientVersion(),e.minVersion)<0))return e}
@@ -0,0 +1 @@
1
+ import{spawnSync as t}from"child_process";import{closeSync as e,copyFileSync as o,createReadStream as r,createWriteStream as n,existsSync as s,mkdirSync as i,openSync as a,readFileSync as c,readSync as f,readdirSync as l,realpathSync as d,renameSync as u,statSync as p,utimesSync as m,writeFileSync as h}from"fs";import{basename as g,join as b,resolve as y}from"path";import{pipeline as S}from"stream/promises";import*as _ from"@iarna/toml";import{codexHome as v,toolHome as E}from"./tools/types.js";import{CLI_NAME as w}from"./brand.js";export{v as codexHome};export function currentCodexProvider(){try{const t=_.parse(c(b(v(),"config.toml"),"utf-8"));return"string"==typeof t.model_provider&&t.model_provider.trim()?t.model_provider.trim():"openai"}catch{return"openai"}}let x=()=>{if("win32"===process.platform)return`${t("powershell.exe",["-NoProfile","-NonInteractive","-Command","(Get-Process -Name codex -ErrorAction SilentlyContinue).Id"],{encoding:"utf-8",windowsHide:!0}).stdout??""}`.split(/\s+/).filter(Boolean).map(Number);const e=process.getuid?.(),o=`${t("pgrep",["-x","-i",...void 0===e?[]:["-u",String(e)],"codex"],{encoding:"utf-8"}).stdout??""}`.split(/\s+/).filter(Boolean).map(Number);if("linux"!==process.platform)return o;const r=N(v());return o.filter(t=>{let e;try{e=c(`/proc/${t}/environ`,"utf-8")}catch{return!0}const o=new Map(e.split("\0").map(t=>[t.slice(0,t.indexOf("=")),t.slice(t.indexOf("=")+1)])),n=o.get("CODEX_HOME")?.trim()||(o.get("HOME")?b(o.get("HOME"),".codex"):null);return null===n||N(n)===r})};function N(t){try{return d(t)}catch{return t}}export function setCodexProcessCheckForTests(t){x=t}export function runningCodexPids(){try{return x()}catch{return[]}}function O(t){const o=a(t,"r");try{const t=[],e=Buffer.alloc(65536);for(;;){const r=f(o,e,0,e.length,null);if(r<=0)break;const n=e.subarray(0,r).indexOf(10);if(n>=0){t.push(Buffer.from(e.subarray(0,n)));break}t.push(Buffer.from(e.subarray(0,r)))}return Buffer.concat(t).toString("utf-8")}finally{e(o)}}async function $(t,e,o){const{atime:s,mtime:i}=p(t),a=`${t}.${w}-tmp`,c=n(a);c.write(e),await S(r(t,{start:o}),c),u(a,t),m(t,s,i)}export function codexSqliteHome(){const t=v();try{const e=_.parse(c(b(t,"config.toml"),"utf-8")),o="string"==typeof e.sqlite_home?e.sqlite_home.trim():"";if(o)return"~"===o||o.startsWith("~/")?b(E(),o.slice(1)):y(t,o)}catch{}const e=process.env.CODEX_SQLITE_HOME?.trim();return e?y(e):t}function D(){const t=codexSqliteHome();if(!s(t))return null;const e=l(t).map(t=>/^state_(\d+)\.sqlite$/.exec(t)).filter(t=>!!t).sort((t,e)=>Number(e[1])-Number(t[1]));return e.length>0?b(t,e[0][0]):null}const T={threads:"id",local_thread_catalog:"thread_id"};function A(){const t=b(codexSqliteHome(),"sqlite");return s(t)?l(t).filter(t=>/\.(db|sqlite3?)$/.test(t)).map(e=>b(t,e)).sort():[]}function B(t,e,o){const r=function(t,e){return new Set(t.prepare(`PRAGMA table_info(${e})`).all().map(t=>String(t.name)))}(t,e),n=T[e];if(!r.has(n)||!r.has("model_provider"))return null;const s=r.has("host_id")?" AND host_id = 'local'":"";return t.prepare(`SELECT ${n} AS id, model_provider AS "from" FROM ${e} WHERE COALESCE(model_provider, '') NOT IN ('', ?)${s}`).all(o).map(t=>({id:String(t.id),from:String(t.from)}))}async function C(t){try{return new((await import("node:sqlite")).DatabaseSync)(t)}catch(t){return`node:sqlite unavailable (Node ${process.versions.node}; needs 22.13+): ${t instanceof Error?t.message:String(t)}`}}export const NO_STATE_DB="no state DB";export async function moveSessionsToProvider(t,e={}){const r=function(){const t=[],e=o=>{if(s(o))for(const r of l(o,{withFileTypes:!0})){const n=b(o,r.name);r.isDirectory()?e(n):r.isFile()&&r.name.endsWith(".jsonl")&&t.push(n)}};return e(b(v(),"sessions")),e(b(v(),"archived_sessions")),t}(),n=[];for(const e of r){let o,r;try{o=O(e)}catch{continue}try{r=JSON.parse(o)}catch{continue}const s=r.payload?.model_provider;"session_meta"===r.type&&"string"==typeof s&&s!==t&&(r.payload.model_provider=t,n.push({file:e,from:s,line:JSON.stringify(r),length:Buffer.byteLength(o,"utf-8")}))}const a=[D(),...A()].filter(t=>!!t);let c=a.length>0?null:NO_STATE_DB;const f=[];for(const e of a){const o=await C(e);if("string"==typeof o){c=o;break}const r=[];try{for(const n of Object.keys(T)){const s=B(o,n,t);s&&s.length>0&&r.push({db:e,table:n,rows:s})}}catch{}f.push({path:e,db:o,tables:r})}const d=f.flatMap(t=>t.tables),u=new Set(d.flatMap(t=>t.rows.map(t=>t.id))),p={target:t,scanned:r.length,moved:n.map(({file:t,from:e})=>({file:t,from:e})),dbRows:u.size,dbSkipped:c,backupDir:null},m=()=>f.forEach(t=>t.db.close());if(e.dryRun||0===n.length&&0===d.length)return m(),p;const y=b(v(),"backups",`${w}-sessions-${(new Date).toISOString().replace(/[:.]/g,"-")}`);i(y,{recursive:!0}),f.forEach(({path:t,tables:e},r)=>{if(0!==e.length)for(const e of["","-wal","-shm"])s(t+e)&&o(t+e,b(y,`${r}-${g(t)}${e}`))});const S={target:t,moved:p.moved,tables:d};h(b(y,"manifest.json"),JSON.stringify(S,null,2)+"\n");for(const t of n)await $(t.file,t.line,t.length);for(const{db:e,tables:o}of f)for(const{table:r,rows:n}of o){const o=e.prepare(`UPDATE ${r} SET model_provider = ? WHERE ${T[r]} = ? AND model_provider = ?`);for(const{id:e,from:r}of n)o.run(t,e,r)}return m(),p.backupDir=y,p}export async function undoSessionMove(t){const e=JSON.parse(c(b(t,"manifest.json"),"utf-8"));let o=0;for(const{file:t,from:r}of e.moved){if(!s(t))continue;const e=O(t),n=JSON.parse(e);n.payload&&(n.payload.model_provider=r,await $(t,JSON.stringify(n),Buffer.byteLength(e,"utf-8")),o+=1)}const r=e.tables??(e.db&&e.threads?[{db:e.db,table:"threads",rows:e.threads}]:[]),n=new Set;for(const{db:t,table:o,rows:i}of r){if(!s(t)||0===i.length||!T[o])continue;const r=await C(t);if("string"==typeof r)continue;const a=r.prepare(`UPDATE ${o} SET model_provider = ? WHERE ${T[o]} = ? AND model_provider = ?`);for(const{id:t,from:o}of i)Number(a.run(o,t,e.target).changes)>0&&n.add(t);r.close()}return{files:o,dbRows:n.size}}
@@ -0,0 +1 @@
1
+ import{i18n as t}from"./i18n.js";import{buildProgram as e}from"./program.js";import{commandPath as n,describeArgument as o,describeOption as s,getCommandHelp as p,visibleSubcommands as r,DOCS_URL as i}from"./cli-help.js";export const DOC_LOCALES=["zh_CN","en_US"];export function commandDocsPath(t){return`docs/commands.${t}.md`}function a(e,n){return t.t(`help.doc.${e}`,n)}function l(t){return t.replace(/[::]\s*$/,"")}function c(t){return"`"+t.replace(/\|/g,"\\|")+"`"}function m(t){return n(t).replace(/\s+/g,"-").toLowerCase()}function u(t){return`[${c(n(t))}](#${m(t)})`}function h(t,e){return[`| ${t[0]} | ${t[1]} |`,"| --- | --- |",...e.map(([t,e])=>{return`| ${t} | ${n=e,n.replace(/\|/g,"\\|").replace(/\n/g,"<br>")} |`;var n})]}function d(t){return t.createHelp().visibleOptions(t)}function f(t){return t.map(t=>[c(t.flags),s(t)])}function g(t){return t.split("\n").filter(Boolean).flatMap(t=>[t,""])}function $(t){return r(t).flatMap(t=>[t,...$(t)])}function x(e,s){const i=e.createHelp(),$=p(e),x=[`<a id="${m(e)}"></a>`,"",`## ${c(n(e))}`,""];x.push(...g(e.description())),x.push(`**${l(t.t("help.title.usage"))}**`,"","```text",i.commandUsage(e),"```","");const _=i.visibleArguments(e);_.length>0&&(x.push(`**${l(t.t("help.title.arguments"))}**`,""),x.push(...h([a("argument"),a("description")],_.map(t=>[c(i.argumentTerm(t)),o(t)])),"")),x.push(`**${l(t.t("help.title.options"))}**`,""),x.push(...h([a("option"),a("description")],f(d(e))),"");const b=s.options.map(t=>c(t.flags)).join(" ");x.push(a("global_inherited",{options:b,anchor:"global-options"}),"");const C=r(e);C.length>0&&(x.push(`**${l(t.t("help.title.commands"))}**`,""),x.push(...h([a("command"),a("description")],C.map(t=>[u(t),t.summary()||t.description()])),""));for(const t of $.sections)x.push(`**${l(t.title)}**`,""),x.push(...h([a("item"),a("description")],t.rows.map(([t,e])=>[c(t),e])),"");$.when&&x.push(`**${l(t.t("help.title.when"))}**`,"",...g($.when)),$.prerequisites.length>0&&x.push(`**${l(t.t("help.title.prerequisites"))}**`,"",...$.prerequisites.map(t=>`- ${t}`),""),$.alternatives.length>0&&(x.push(`**${l(t.t("help.title.alternatives"))}**`,""),x.push(...h([a("command"),a("use_instead")],$.alternatives.map(t=>[c(t.command),t.note])),"")),$.examples.length>0&&(x.push(`**${l(t.t("help.title.examples"))}**`,""),x.push(...h([a("command"),a("description")],$.examples.map(t=>[c(t.command),t.note])),""));const j=[c(`${n(e)} --help`)];return e.parent&&e.parent!==s&&j.push(u(e.parent)),j.push(`[${a("back_to_index")}](#commands)`),x.push(`**${a("see_also")}**: ${j.join(" · ")}`,""),x}function _(e){const n=[`\x3c!-- ${a("generated_note")} --\x3e`,"",`# ${a("title")}`,"",...g(e.description()),...i?[a("docs_link",{url:i})]:[],"",'<a id="global-options"></a>',"",`## ${l(t.t("help.group.global_options"))}`,"",a("global_note"),"",...h([a("option"),a("description")],f(d(e))),"",'<a id="commands"></a>',"",`## ${l(t.t("help.title.commands"))}`,""],o=new Map;for(const n of r(e)){const e=n.helpGroup()||t.t("help.title.commands");o.set(e,[...o.get(e)??[],n])}for(const[t,e]of o)n.push(`### ${l(t)}`,""),n.push(...h([a("command"),a("description")],e.map(t=>[u(t),t.summary()||t.description()])),"");const s=p(e).examples;s.length>0&&(n.push(`## ${l(t.t("help.title.examples"))}`,""),n.push(...h([a("command"),a("description")],s.map(t=>[c(t.command),t.note])),""));for(const t of $(e))n.push(...x(t,e));return n.join("\n").replace(/\n{3,}/g,"\n\n").trimEnd()+"\n"}export function generateCommandDocs(n){const o=t.getLocale();t.loadFromConfig(n);try{return _(e())}finally{t.loadFromConfig(o)}}
@@ -0,0 +1 @@
1
+ import{i18n as n,detectSystemLang as r}from"./i18n.js";import{configManager as o}from"./config.js";import{runModelRefresh as e}from"./model-refresh.js";import{refreshClientConfig as t}from"./client-config-sync.js";import{normalizeBaseUrl as s}from"./gateway-addresses.js";import i from"chalk";import{setRuntimeOptions as m,detectColorPreferenceFromEnv as a,isColorEnabled as c,isDryRun as l,isJsonMode as d}from"./runtime-options.js";import{cleanupAnthropicEnvVars as u,envCleanupChangedProfile as g,machineEnvVarsLeft as p}from"./env-cleanup.js";import{runStartupUpdate as f}from"./auto-update.js";import{buildProgram as h}from"./program.js";import{firstCommandWord as _,isHelpRequest as y,renderHelpTopic as w}from"./cli-help.js";import{reportCliError as v,usageError as j,CliError as k}from"./errors.js";import{CLI_NAME as C}from"./brand.js";import{dryRunUnsupportedCommand as x}from"./dry-run.js";import{flushTelemetry as A,installClientHeaders as b,setTelemetryCommand as D,track as M}from"./telemetry.js";export{buildProgram}from"./program.js";const E=new Set(["setup","init","auth","enter","config"]);export class Command{program;configuring=!1;constructor(){const e=o.isLangChosen()?o.getLang():r();n.loadFromConfig(e),this.program=h()}cleanupLeakedEnvVars(){const r=u();if(0===r.length||d())return;const o=p(),e=g();if(e||0===o.length){const o=n.t(e?"messages.env_vars_cleared":"messages.env_vars_ignored",{vars:r.join(", ")});console.log(c()?i.yellow(o):o)}if(o.length>0){const r=n.t("messages.env_vars_machine_left",{vars:o.join(", ")});console.log(c()?i.yellow(r):r)}}preflightArgs(n){const r=r=>n.includes(r),e=!r("--no-color")&&a();if(m({nonInteractive:r("--non-interactive"),json:r("--json"),yes:r("--yes")||r("-y"),dryRun:r("--dry-run"),color:e}),e||(i.level=0),this.configuring=!1,y(n))return;let t;for(let r=0;r<n.length;r+=1){const o=n[r];"--base"===o&&n[r+1]?(t=n[r+1],r+=1):o.startsWith("--base=")&&(t=o.slice(7))}const c=_(n),l=void 0===c&&!["--version","-v"].some(r);this.configuring=l||void 0!==c&&E.has(c),t&&o.setBaseUrl(s(t)??t,this.configuring&&!r("--dry-run"))}async execute(n){const r=Date.now();let o=!1;try{if(this.preflightArgs(n),b(),y(n)||["--version","-v"].some(r=>n.includes(r))||(D(_(n)??"wizard"),M("command","start",{detail:{args:n.filter(n=>n.startsWith("-")&&!/key/i.test(n))}}),o=!0),"help"===n[0]&&n[1]){const r=w(n[1]);if(r)return void process.stdout.write(r)}if(this.rejectUnknownCommand(n),!y(n)){if(l()&&this.rejectUnsupportedDryRun(n),this.configuring&&!l()&&this.cleanupLeakedEnvVars(),(await f(n)).handled)return;this.configuring&&await t({timeoutMs:5e3}),await e(n)}if(await this.program.parseAsync(n,{from:"user"}),o){const n=Boolean(process.exitCode)&&0!==process.exitCode;M("command",n?"fail":"ok",{duration_ms:Date.now()-r,...n?{detail:{exit_code:process.exitCode}}:{}})}}catch(e){if("commander.helpDisplayed"===e?.code||"commander.version"===e?.code)return;const t=this.normalizeCommanderError(e,n),s=v(t);if(o){const n=t instanceof k?`${t.type}${t.subtype?"/"+t.subtype:""}`:void 0;M("command",130===s?"cancel":"fail",{duration_ms:Date.now()-r,error:t,detail:{exit_code:s,...n?{type:n}:{}}})}}finally{o&&await A()}}rejectUnsupportedDryRun(r){const o=x(r);if(null!==o)throw j(n.t("runtime.dry_run_unsupported",{command:o,cli:C}),n.t("runtime.dry_run_unsupported_hint",{cli:C}),"dry_run_unsupported")}rejectUnknownCommand(r){const o=_(r);if(!o||"help"===o)return;if(this.program.commands.some(n=>n.name()===o))return;const e=this.suggestCommand(o),t=e?n.t("cli.unknown_hint_suggestion",{command:e}):n.t("cli.unknown_hint");throw j(n.t("cli.error_unknown",{command:o}),t,"unknown_command")}suggestCommand(n){const r=(n,r)=>{const o=Array.from({length:r.length+1},(n,r)=>r);for(let e=1;e<=n.length;e+=1){let t=o[0];o[0]=e;for(let s=1;s<=r.length;s+=1){const i=o[s];o[s]=Math.min(o[s]+1,o[s-1]+1,t+(n[e-1]===r[s-1]?0:1)),t=i}}return o[r.length]};return this.program.commands.map(n=>n.name()).map(o=>({name:o,score:r(n,o)})).filter(({score:r})=>r<=Math.max(2,Math.floor(n.length/2))).sort((n,r)=>n.score-r.score)[0]?.name}normalizeCommanderError(r,o){if(r instanceof k)return r;const e=r?.code,t=r instanceof Error?r.message:String(r);if("commander.unknownOption"===e||"commander.missingArgument"===e||"commander.missingMandatoryOption"===e||"commander.invalidArgument"===e){const r=_(o),s=/'([^']+)'/.exec(t)?.[1]??"",i="commander.unknownOption"===e?"cli.err_unknown_option":"commander.missingArgument"===e?"cli.err_missing_argument":"commander.missingMandatoryOption"===e?"cli.err_missing_option":null,m=i&&s?n.t(i,{name:s}):t.replace(/^error:\s*/,"");return j(m,r?n.t("cli.unknown_option_hint",{command:r}):n.t("cli.unknown_option_hint_root"),e)}return r}getProgram(){return this.program}}
@@ -0,0 +1 @@
1
+ import{existsSync as e,mkdirSync as t,readFileSync as i,writeFileSync as o,renameSync as s,unlinkSync as r,readdirSync as n,rmdirSync as a,statSync as l,chmodSync as c}from"fs";import{join as f,dirname as g}from"path";import{homedir as h}from"os";import{createHash as p}from"crypto";import*as m from"js-yaml";import{logger as u}from"../utils/logger.js";import{getDefaultModels as d,isRetiredDefaultModel as y}from"./model-registry.js";import{readLegacySecretsFile as _}from"./secret-store.js";import{brand as k,brandEnv as b}from"./brand.js";export const DEFAULT_BASE_URL=k().gatewayAddresses[0].url;export const DEFAULT_MODELS=d();export const DEFAULT_PROFILE_NAME="default";const v="plaintext";export class ConfigManager{static instance;configDir;configPath;config;runtimeBaseUrl;constructor(){this.configDir=this.resolveConfigDir(),this.migrateLegacyConfigDir(),this.configPath=f(this.configDir,"config.yaml"),this.config=this.loadConfig()}migrateLegacyConfigDir(){try{const t=f(g(this.configDir),".chelper");if(t===this.configDir||!e(t))return;if(["config.yaml","secrets.enc"].some(t=>e(f(this.configDir,t))))return;if(e(this.configDir)){for(const i of n(t)){const o=f(this.configDir,i);e(o)||s(f(t,i),o)}0===n(t).length&&a(t)}else s(t,this.configDir);u.record(`Migrated config dir: ${t} -> ${this.configDir}`)}catch(e){u.warn("Failed to migrate legacy .chelper config dir:",e)}}resolveConfigDir(){const e=b("CONFIG_DIR");if(e&&e.trim())return e.trim();const t=b("TEST_HOME");return t&&t.trim()?f(t.trim(),k().configDirName):f(h(),k().configDirName)}createDefaultConfig(){return this.syncLegacyFields({lang:"en_US",active_profile:"default",profiles:{[DEFAULT_PROFILE_NAME]:{}},presets:{}})}normalizeModels(e){const t=t=>{const i=e?.[t]?.trim();return i&&!y(t,i)?i:DEFAULT_MODELS[t]},i={haiku:t("haiku"),sonnet:t("sonnet"),opus:t("opus"),reasoning:t("reasoning")};if(e&&"object"==typeof e)for(const[t,o]of Object.entries(e))t in i||"string"==typeof o&&o.trim()&&(i[t]=o.trim());return i}normalizeToolModels(e){if(!e||"object"!=typeof e)return{};const t=Object.entries(e).flatMap(([e,t])=>{if(!e||"string"!=typeof e||!t||"object"!=typeof t)return[];const i={};for(const[e,o]of Object.entries(t))"string"==typeof o&&o.trim()&&(i[e]=o.trim());return Object.keys(i).length>0?[[e,i]]:[]});return Object.fromEntries(t)}normalizeToolSettings(e){if(!e||"object"!=typeof e||Array.isArray(e))return{};const t=Object.entries(e).flatMap(([e,t])=>{if(!e||!t||"object"!=typeof t||Array.isArray(t))return[];const i=Object.fromEntries(Object.entries(t).filter(([,e])=>"string"==typeof e||"boolean"==typeof e||"number"==typeof e&&Number.isFinite(e)));return Object.keys(i).length>0?[[e,i]]:[]});return Object.fromEntries(t)}normalizeStringRecord(e){return!e||"object"!=typeof e||Array.isArray(e)?{}:Object.fromEntries(Object.entries(e).filter(e=>"string"==typeof e[1]&&Boolean(e[1].trim())).map(([e,t])=>[e,t.trim()]))}normalizeProfile(e){if(!e)return{};const t=this.normalizeToolModels(e.tool_models),i=this.normalizeToolSettings(e.tool_settings),o=this.normalizeStringRecord(e.tool_api_keys);return{..."string"==typeof e.api_key&&e.api_key?{api_key:e.api_key}:{},...Object.keys(o).length>0?{tool_api_keys:o}:{},..."string"==typeof e.base_url&&e.base_url?{base_url:e.base_url}:{},...e.models?{models:this.normalizeModels(e.models)}:{},...Object.keys(t).length>0?{tool_models:t}:{},...Object.keys(i).length>0?{tool_settings:i}:{}}}normalizeProfiles(e){if(!e||"object"!=typeof e)return{};const t=Object.entries(e).flatMap(([e,t])=>e&&"string"==typeof e&&t&&"object"==typeof t?[[e,this.normalizeProfile(t)]]:[]);return Object.fromEntries(t)}normalizePresets(e){if(!e||"object"!=typeof e)return{};const t=Object.entries(e).flatMap(([e,t])=>{if(!e||"string"!=typeof e||!t||"object"!=typeof t)return[];const i=t;return i.models?[[e,{models:this.normalizeModels(i.models),updated_at:i.updated_at||new Date(0).toISOString()}]]:[]});return Object.fromEntries(t)}getResolvedActiveProfile(e){const t=e.active_profile||"default";return e.profiles?.[t]||{}}syncLegacyFields(e){const t=this.normalizeProfiles(e.profiles),i=e.active_profile?.trim()||Object.keys(t)[0]||"default",o=t[i]?t:{...t,[i]:{}},s=this.getResolvedActiveProfile({...e,profiles:o,active_profile:i});return{...e,lang:e.lang||"en_US",active_profile:i,profiles:o,presets:this.normalizePresets(e.presets),api_key:s.api_key,base_url:s.base_url,models:s.models?this.normalizeModels(s.models):DEFAULT_MODELS}}sanitizeBackupLabel(e){return(e||"").trim().replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40)}getBackupDir(){return f(this.configDir,"backups")}getLegacySecretsPath(){return f(this.configDir,"secrets.enc")}getSecretsBackupPath(e){return e.replace(/\.yaml$/,".secrets.enc")}static getInstance(){return ConfigManager.instance||(ConfigManager.instance=new ConfigManager),ConfigManager.instance}ensureConfigDir(){e(this.configDir)||t(this.configDir,{recursive:!0})}loadConfig(){try{if(e(this.configPath)){const t=i(this.configPath,"utf-8"),o=m.load(t);let s=this.migrateOldConfig(o||{lang:"en_US"}),n=!1;const a=this.getLegacySecretsPath();if(e(a)&&o?.credential_store!==v)try{s=this.mergeLegacySecrets(s,_(a)),n=!0}catch(e){u.warn("Legacy secrets.enc is unreadable on this host; it was kept for recovery and will not block new credentials."),u.logError("ConfigManager.migrateLegacySecrets",e)}if((this.needsMigration(o)||n)&&(this.backupConfig(),this.atomicWrite(this.configPath,m.dump(this.prepareForPersistence(s))),n))try{r(a)}catch(e){u.logError("ConfigManager.removeLegacySecrets",e)}try{c(this.configPath,384)}catch{}return s}const t=this.getLegacySecretsPath();if(e(t))try{const e=this.mergeLegacySecrets(this.createDefaultConfig(),_(t));this.ensureConfigDir(),this.atomicWrite(this.configPath,m.dump(this.prepareForPersistence(e)));try{r(t)}catch(e){u.logError("ConfigManager.removeLegacySecrets",e)}return e}catch(e){u.warn("Legacy secrets.enc is unreadable on this host; it was kept for recovery and will not block new credentials."),u.logError("ConfigManager.migrateLegacySecretsWithoutConfig",e)}}catch(e){u.warn("Failed to load config, using defaults:",e),u.logError("ConfigManager.loadConfig",e)}return this.createDefaultConfig()}needsMigration(e){return!(!e||"object"!=typeof e)&&("plan"in e||!("profiles"in e)||!("active_profile"in e)||!("presets"in e))}migrateOldConfig(e){if(!e||"object"!=typeof e)return this.createDefaultConfig();const t=e,{plan:i,...o}=t,s=this.normalizeProfiles(o.profiles),r=this.normalizeProfile({api_key:"string"==typeof o.api_key?o.api_key:void 0,base_url:"string"==typeof o.base_url?o.base_url:void 0,models:o.models}),n=Object.keys(s).length>0?s:{[DEFAULT_PROFILE_NAME]:r},a="string"==typeof o.active_profile&&o.active_profile.trim()?o.active_profile.trim():Object.keys(n)[0]||"default";return this.syncLegacyFields({lang:"string"==typeof o.lang&&o.lang?o.lang:"en_US",...!0===o.lang_chosen?{lang_chosen:!0}:{},...o.credential_store===v?{credential_store:v}:{},active_profile:a,profiles:n,presets:this.normalizePresets(o.presets)})}atomicWrite(t,i){const n=`${t}.tmp`;try{o(n,i,{encoding:"utf-8",mode:384}),s(n,t);try{c(t,384)}catch{}}catch(t){if(e(n))try{r(n)}catch{}throw t}}backupConfig(){if(!e(this.configPath))return;const s=this.getBackupDir();e(s)||t(s,{recursive:!0});const r=(new Date).toISOString().replace(/[:.]/g,"-"),n=f(s,`config-${r}.yaml`);try{const e=i(this.configPath,"utf-8");o(n,e,{encoding:"utf-8",mode:384}),this.rotateBackups(s,10,30)}catch(e){u.logError("ConfigManager.backupConfig",e)}}rotateBackups(t,i,o){try{const s=Date.now()-24*o*60*60*1e3,a=n(t).filter(e=>e.startsWith("config-")&&e.endsWith(".yaml")).map(e=>({name:e,path:f(t,e),mtime:l(f(t,e)).mtime})).sort((e,t)=>t.mtime.getTime()-e.mtime.getTime()),c=new Set;a.slice(i).forEach(e=>c.add(e.path)),a.forEach(e=>{e.mtime.getTime()<s&&c.add(e.path)});for(const t of c){let i=!1;try{r(t),i=!0}catch(e){u.logError("ConfigManager.rotateBackups",e)}if(i){const i=this.getSecretsBackupPath(t);if(e(i))try{r(i)}catch(e){u.logError("ConfigManager.rotateBackups.secrets",e)}}}}catch(e){u.logError("ConfigManager.rotateBackups",e)}}saveConfig(e){try{this.ensureConfigDir(),this.backupConfig();const t=this.syncLegacyFields(this.migrateOldConfig(e||this.config)),i=this.prepareForPersistence(t),o=m.dump(i);this.atomicWrite(this.configPath,o),this.config=t}catch(e){throw u.error("Failed to save config:",e),u.logError("ConfigManager.saveConfig",e),e}}prepareForPersistence(e){const t={...e,credential_store:v};return delete t.api_key,delete t.base_url,delete t.models,t}mergeLegacySecrets(e,t){const i={...e.profiles||{}},o=new Set([...Object.keys(t.api_keys||{}),...Object.keys(t.tool_api_keys||{})]);for(const e of o){const o=i[e]||{},s=o.api_key||t.api_keys?.[e],r={...t.tool_api_keys?.[e]||{},...o.tool_api_keys||{}};i[e]={...o,...s?{api_key:s}:{},...Object.keys(r).length>0?{tool_api_keys:r}:{}}}return this.syncLegacyFields({...e,profiles:i})}getConfig(){return this.syncLegacyFields({...this.config})}updateConfig(e){this.saveConfig({...this.config,...e})}isFirstRun(){return!e(this.configPath)}getLang(){return this.config.lang||"en_US"}isLangChosen(){return!0===this.config.lang_chosen}setLang(e){this.updateConfig({lang:e,lang_chosen:!0})}getActiveProfileName(){return this.config.active_profile||"default"}listProfiles(){return Object.keys(this.config.profiles||{}).sort()}getProfile(e=this.getActiveProfileName()){const t=this.config.profiles?.[e]||{};return{...t.api_key?{api_key:t.api_key}:{},...t.tool_api_keys&&Object.keys(t.tool_api_keys).length>0?{tool_api_keys:this.normalizeStringRecord(t.tool_api_keys)}:{},...t.base_url?{base_url:t.base_url}:{},models:t.models?this.normalizeModels(t.models):DEFAULT_MODELS,...t.tool_models&&Object.keys(t.tool_models).length>0?{tool_models:this.normalizeToolModels(t.tool_models)}:{},...t.tool_settings&&Object.keys(t.tool_settings).length>0?{tool_settings:this.normalizeToolSettings(t.tool_settings)}:{}}}createProfile(e,t=this.getActiveProfileName()){const i=this.getProfile(t),o={...this.config.profiles||{},[e]:{...i.api_key?{api_key:i.api_key}:{},...i.base_url?{base_url:i.base_url}:{},models:this.normalizeModels(i.models)}};this.saveConfig({...this.config,profiles:o})}setActiveProfile(e){if(!this.config.profiles?.[e])throw new Error(`Profile not found: ${e}`);this.saveConfig({...this.config,active_profile:e})}updateProfile(e,t){const i=this.config.profiles?.[e]||{},o=t.models?this.normalizeModels({...i.models,...t.models}):i.models?this.normalizeModels(i.models):void 0,s={...i,...void 0!==t.api_key?{api_key:t.api_key}:{},...void 0!==t.base_url?{base_url:t.base_url}:{},...o?{models:o}:{}},r={...this.config.profiles||{},[e]:s};this.saveConfig({...this.config,profiles:r})}deleteProfile(e){const t={...this.config.profiles||{}};if(!t[e])return;const i=Object.keys(t).filter(t=>t!==e);if(0===i.length)throw new Error("At least one profile must remain");delete t[e];const o=this.getActiveProfileName()===e?i[0]:this.getActiveProfileName();this.saveConfig({...this.config,profiles:t,active_profile:o})}getApiKey(){return this.config.profiles?.[this.getActiveProfileName()]?.api_key}setApiKey(e){this.updateProfile(this.getActiveProfileName(),{api_key:e})}revokeApiKey(){const e=this.config.profiles?.[this.getActiveProfileName()]||{},{api_key:t,tool_api_keys:i,...o}=e,s={...this.config.profiles||{},[this.getActiveProfileName()]:o};this.saveConfig({...this.config,profiles:s})}getApiKeyFingerprint(){const e=this.getApiKey();return e?p("sha256").update(e).digest("hex").slice(0,12):""}getApiKeyForTool(e){const t=this.config.profiles?.[this.getActiveProfileName()];return t?.tool_api_keys?.[e]||t?.api_key||void 0}setToolApiKey(e,t){const i=this.getActiveProfileName(),o=this.config.profiles?.[i]||{},s={...this.config.profiles||{},[i]:{...o,tool_api_keys:{...o.tool_api_keys||{},[e]:t}}};this.saveConfig({...this.config,profiles:s})}clearToolApiKey(e){const t=this.getActiveProfileName(),i=this.config.profiles?.[t]||{},{[e]:o,...s}=i.tool_api_keys||{},r={...i};Object.keys(s).length>0?r.tool_api_keys=s:delete r.tool_api_keys,this.saveConfig({...this.config,profiles:{...this.config.profiles||{},[t]:r}})}listToolApiKeys(){return Object.keys(this.config.profiles?.[this.getActiveProfileName()]?.tool_api_keys||{}).sort()}getToolApiKeyFingerprint(e){const t=this.config.profiles?.[this.getActiveProfileName()]?.tool_api_keys?.[e];return t?p("sha256").update(t).digest("hex").slice(0,12):""}getModels(){const e=this.config.profiles?.[this.getActiveProfileName()]?.models;return e?this.normalizeModels(e):DEFAULT_MODELS}setModels(e){this.updateProfile(this.getActiveProfileName(),{models:this.normalizeModels(e)})}updateModels(e){this.setModels(this.normalizeModels({...this.getModels(),...e}))}getModelsForTool(e){const t=this.getModels(),i=this.config.profiles?.[this.getActiveProfileName()]?.tool_models?.[e];return i?this.normalizeModels({...t,...i}):t}setToolModel(e,t){const i=this.getActiveProfileName(),o=this.config.profiles?.[i]||{},s={...o.tool_models||{}};t&&0!==Object.keys(t).length?s[e]=t:delete s[e];const r={...o};Object.keys(s).length>0?r.tool_models=s:delete r.tool_models;const n={...this.config.profiles||{},[i]:r};this.saveConfig({...this.config,profiles:n})}getToolSettings(e){const t=this.config.profiles?.[this.getActiveProfileName()]?.tool_settings?.[e];return t?{...t}:{}}getToolSetting(e,t){return this.config.profiles?.[this.getActiveProfileName()]?.tool_settings?.[e]?.[t]}setToolSetting(e,t,i){if(this.getToolSetting(e,t)===i)return;const o=this.getActiveProfileName(),s=this.config.profiles?.[o]||{},r={...s.tool_settings||{}};r[e]={...r[e]||{},[t]:i};const n={...this.config.profiles||{},[o]:{...s,tool_settings:r}};this.saveConfig({...this.config,profiles:n})}getCustomPresets(){return{...this.config.presets||{}}}saveCustomPreset(e,t){const i={...this.config.presets||{},[e]:{models:this.normalizeModels(t),updated_at:(new Date).toISOString()}};this.saveConfig({...this.config,presets:i})}deleteCustomPreset(e){const t={...this.config.presets||{}};t[e]&&(delete t[e],this.saveConfig({...this.config,presets:t}))}listBackups(){const t=this.getBackupDir();return e(t)?n(t).filter(e=>e.startsWith("config-")&&e.endsWith(".yaml")).map(e=>{const i=f(t,e);return{name:e,path:i,mtimeMs:l(i).mtimeMs}}).sort((e,t)=>t.mtimeMs-e.mtimeMs):[]}createBackup(s){this.ensureConfigDir();const r=this.getBackupDir();e(r)||t(r,{recursive:!0});const n=(new Date).toISOString().replace(/[:.]/g,"-"),a=this.sanitizeBackupLabel(s),l=f(r,a?`config-${n}-${a}.yaml`:`config-${n}.yaml`),c=e(this.configPath)?i(this.configPath,"utf-8"):m.dump(this.prepareForPersistence(this.getConfig()));return o(l,c,{encoding:"utf-8",mode:384}),this.rotateBackups(r,10,30),l}restoreBackup(t){if(!t||"."===t||".."===t||/[/\\]|\.\./.test(t))throw new Error(`Invalid backup name: ${t}`);const o=this.getBackupDir(),s=f(o,t);if(!e(s))throw new Error(`Backup not found: ${t}`);const r=i(s,"utf-8"),n=m.load(r),a=this.getSecretsBackupPath(s);let l=this.migrateOldConfig(n||this.createDefaultConfig());if(n?.credential_store!==v&&e(a))try{l=this.mergeLegacySecrets(l,_(a))}catch(e){throw new Error(`Legacy backup credentials could not be decrypted: ${a}`,{cause:e})}this.saveConfig(l)}getConfigDir(){return this.configDir}getBaseUrl(){return this.runtimeBaseUrl||this.config.profiles?.[this.getActiveProfileName()]?.base_url||DEFAULT_BASE_URL}hasRuntimeBaseUrl(){return Boolean(this.runtimeBaseUrl)}setBaseUrl(e,t=!1){this.runtimeBaseUrl=e,t&&this.updateProfile(this.getActiveProfileName(),{base_url:e})}resetBaseUrl(){this.runtimeBaseUrl=void 0;const e=this.config.profiles?.[this.getActiveProfileName()]||{},{base_url:t,...i}=e,o={...this.config.profiles||{},[this.getActiveProfileName()]:i};this.saveConfig({...this.config,profiles:o})}}export const configManager=ConfigManager.getInstance();
@@ -0,0 +1 @@
1
+ import r from"inquirer";import{isDryRun as n,shouldAutoConfirm as o,isJsonMode as i,emitJson as t,isColorEnabled as e}from"./runtime-options.js";import{i18n as a}from"./i18n.js";import p from"chalk";export async function confirmAction({message:n,defaultValue:i=!1}){if(o())return!0;const{confirmed:t}=await r.prompt([{type:"confirm",name:"confirmed",message:n,default:i}]);return Boolean(t)}export async function applyOrDryRun({description:r,json:o,apply:m,onApplied:s}){if(n()){if(i())return void t({dry_run:!0,description:r,payload:o??null});const n=e()?p.cyan:r=>r;return void process.stdout.write(`${n(a.t("runtime.dry_run_label"))} ${r}\n`)}await m(),s&&s()}
@@ -0,0 +1 @@
1
+ import{firstCommandWord as e}from"./cli-help.js";export function dryRunUnsupportedCommand(s){const n=e(s);if(void 0===n)return"(wizard)";const r=s.filter(e=>!e.startsWith("-")),o=r[r.indexOf(n)+1];switch(n){case"setup":case"config":case"status":case"bench":case"logs":case"completion":case"help":return null;case"doctor":return s.includes("--report")?"doctor --report":null;case"base":return void 0===o?null:`base ${o}`;case"lang":return void 0===o||"show"===o?null:`lang ${o}`;case"codex":return s.includes("--undo")?"codex sessions --undo":null;case"sessions":return"export"===o?"sessions export":"resume"===o&&s.includes("--run")?"sessions resume --run":null;default:return n}}
@@ -0,0 +1 @@
1
+ import{existsSync as e,readFileSync as n,writeFileSync as r}from"fs";import{join as o}from"path";import{logger as t}from"../utils/logger.js";import{toolHome as s}from"./tools/types.js";import{broadcastEnvChange as c,deleteWindowsEnv as i,readWindowsEnv as l}from"./windows-env.js";export const ANTHROPIC_ENV_VARS=["ANTHROPIC_API_KEY","ANTHROPIC_BASE_URL","ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL","ANTHROPIC_MODEL","ANTHROPIC_REASONING_MODEL"];export function getShellRcFilePath(){if("win32"===process.platform)return null;const e=s();switch((process.env.SHELL||"").split("/").pop()||""){case"bash":return o(e,".bashrc");case"zsh":return o(e,".zshrc");case"fish":return o(e,".config","fish","config.fish");default:return o(e,".profile")}}export function cleanupShellRcEnvVars(){if("win32"===process.platform)return!1;try{const o=getShellRcFilePath();if(!o||!e(o))return!1;let s=n(o,"utf-8");const c=s,i=[...ANTHROPIC_ENV_VARS.map(e=>new RegExp(String.raw`^\s*export\s+${e}=.*$`,"gm")),/^\s*#\s*Claude Code environment variables\s*$/gm];for(const e of i)s=s.replace(e,"");if(s!==c)return r(o,s,"utf-8"),t.info(`Cleaned up ANTHROPIC_* environment variables from ${o}`),!0}catch(e){t.warn("Failed to cleanup shell environment variables:",e),t.logError("envCleanup.cleanupShellRcEnvVars",e)}return!1}export function cleanupWindowsEnvVars(f){const a=[];if("win32"!==process.platform||0===f.length)return{machineLeft:a,changed:!1};let p=!1;const u=[];for(const e of f)for(const n of["user","machine"])if(void 0!==l(n,e))try{i(n,e),u.push(`${n}:${e}`)}catch(r){"machine"===n&&a.push(e),t.logError("envCleanup.cleanupWindowsEnvVars",r)}u.length>0&&(p=!0,c(),t.info(`Windows env cleanup: ${u.join(" ")}`));for(const c of function(){const e=s(),n=[];for(const r of[o(e,"Documents"),o(e,"OneDrive","Documents"),o(e,"OneDrive","文档")])for(const e of["PowerShell","WindowsPowerShell"])n.push(o(r,e,"Microsoft.PowerShell_profile.ps1"),o(r,e,"profile.ps1"));return n}())try{if(!e(c))continue;const o=n(c,"utf-8");let s=o;for(const e of f)s=s.replace(new RegExp(String.raw`^[ \t]*\$env:${e}[ \t]*=.*(\r?\n)?`,"gim"),"");s!==o&&(r(c,s,"utf-8"),p=!0,t.info(`Removed ANTHROPIC_* assignments from ${c}`))}catch(e){t.logError("envCleanup.powerShellProfile",e)}return{machineLeft:a,changed:p}}export function cleanupAnthropicEnvVars(){const e=ANTHROPIC_ENV_VARS.filter(e=>!!process.env[e]);if(0===e.length)return[];const n=cleanupShellRcEnvVars(),r=cleanupWindowsEnvVars(e);f=r.machineLeft,a=n||r.changed;for(const n of e)delete process.env[n];return[...e]}let f=[],a=!1;export function envCleanupChangedProfile(){return a}export function machineEnvVarsLeft(){return f}
@@ -0,0 +1 @@
1
+ import r from"chalk";import{i18n as e}from"./i18n.js";import{isColorEnabled as t,isJsonMode as o}from"./runtime-options.js";export const EXIT_CODES={operation:1,usage:2,authentication:3,network:4,internal:5,confirmation:10,cancelled:130};export class CliError extends Error{type;hint;subtype;constructor(r,e,t,o){super(e),this.name="CliError",this.type=r,this.hint=t,this.subtype=o}}export function exitCodeForError(r){return r instanceof CliError?EXIT_CODES[r.type]:EXIT_CODES.internal}export function asCliError(r){if(r instanceof CliError)return r;if("ExitPromptError"===r?.name)return new CliError("cancelled",e.t("errors.cancelled"),e.t("errors.cancel_hint"),"user_cancelled");const t=r instanceof Error?r.message:String(r);return new CliError("internal",t,e.t("errors.hint_logs"),"unexpected_error")}export function reportCliError(e){const n=asCliError(e),i={ok:!1,error:{type:n.type,message:n.message,hint:n.hint,...n.subtype?{subtype:n.subtype}:{}}};if(o())process.stderr.write(JSON.stringify(i)+"\n");else{const e=t()?r.red:r=>r;process.stderr.write(e(n.message)+"\n"+(n.hint?n.hint+"\n":""))}const s=exitCodeForError(n);return process.exitCode=s,s}export function usageError(r,e,t){return new CliError("usage",r,e,t)}export function operationError(r,e,t){return new CliError("operation",r,e,t)}export function authenticationError(r,e,t){return new CliError("authentication",r,e,t)}export function networkError(r,e,t){return new CliError("network",r,e,t)}
@@ -0,0 +1 @@
1
+ import{existsSync as r,mkdirSync as e,readFileSync as t,writeFileSync as o}from"fs";import{join as s}from"path";import{configManager as n}from"./config.js";import{getBuiltinGatewayAddresses as a}from"./model-registry.js";import{logger as i}from"../utils/logger.js";const l=new Set(["SELF_SIGNED_CERT_IN_CHAIN","DEPTH_ZERO_SELF_SIGNED_CERT","UNABLE_TO_VERIFY_LEAF_SIGNATURE","UNABLE_TO_GET_ISSUER_CERT_LOCALLY","CERT_HAS_EXPIRED","CERT_NOT_YET_VALID","ERR_TLS_CERT_ALTNAME_INVALID"]);function u(){return s(n.getConfigDir(),"gateway-addresses.json")}export function normalizeBaseUrl(r){let e,t=r.trim();if(!t)return null;/^[a-z][a-z0-9+.-]*:\/\//i.test(t)||(t=`https://${t}`);try{e=new URL(t)}catch{return null}if("https:"!==e.protocol&&"http:"!==e.protocol)return null;const o=e.pathname.replace(/\/+$/,"").replace(/\/v1$/i,"");return`${e.protocol}//${e.host}${o}`}export function parsePublishedAddresses(r){if(!Array.isArray(r))return[];const e=new Set,t=[];for(const o of r){if(!o||"object"!=typeof o)continue;const{url:r,route:s,description:n}=o,a="string"==typeof r?normalizeBaseUrl(r):null;if(!a?.startsWith("https://")||e.has(a))continue;e.add(a);const i="string"==typeof s?s.trim():"",l="string"==typeof n?n.trim():"";t.push({url:a,label:i&&l?`${i}(${l})`:i||l})}return t}export function rememberPublishedAddresses(r,t){if(!r||"object"!=typeof r)return;if(!a().some(r=>normalizeBaseUrl(r.url)===t))return;const s=r;if(!1===s.api_info_enabled)return;const l=parsePublishedAddresses(s.api_info);if(0!==l.length)try{e(n.getConfigDir(),{recursive:!0}),o(u(),JSON.stringify({addresses:l},null,2)+"\n")}catch(r){i.logError("rememberPublishedAddresses",r)}}export function gatewayAddresses(){const e=function(){const e=u();if(!r(e))return[];try{const r=JSON.parse(t(e,"utf-8"));return(Array.isArray(r.addresses)?r.addresses:[]).flatMap(r=>{const e="string"==typeof r?.url?normalizeBaseUrl(r.url):null;return e?[{url:e,label:"string"==typeof r.label?r.label:""}]:[]})}catch{return[]}}(),o=[];for(const r of a()){const t=normalizeBaseUrl(r.url);if(!t||o.some(r=>r.url===t))continue;const s=e.find(r=>r.url===t)?.label||r.label;o.push({url:t,label:s})}for(const r of e)o.some(e=>e.url===r.url)||o.push(r);return o}function c(r){const e=r?.cause,t="string"==typeof e?.code?e.code:"",o="string"==typeof e?.message?e.message:r instanceof Error?r.message:String(r);return r instanceof Error&&"AbortError"===r.name?{error:"timeout",detail:o}:l.has(t)||/certificate/i.test(o)?{error:"certificate",detail:t||o}:{error:"network",detail:t||o}}export async function probeGatewayAddress(r,e={}){e.apiKey&&!function(r){return r===n.getBaseUrl()||a().some(e=>normalizeBaseUrl(e.url)===r)}(r)&&(e={...e,apiKey:void 0});const t=Math.max(1,e.samples??1),o=[];let s;for(let n=0;n<t;n+=1){const t=await f(r,e);if(!t.ok)return t;o.push(t.ms),s=t.models}return o.sort((r,e)=>r-e),{url:r,ok:!0,ms:o[Math.floor(o.length/2)],...void 0===s?{}:{models:s}}}async function f(r,e){const{apiKey:t,timeoutMs:o=8e3,fetchFn:s=fetch}=e,n=new AbortController,a=setTimeout(()=>n.abort(),o),i=Date.now();try{const e=await s(t?`${r}/v1/models`:`${r}/api/status`,{method:"GET",headers:t?{Authorization:`Bearer ${t}`}:void 0,signal:n.signal});let o;try{o=(await e.json())?.data}catch{o=void 0}const a=Date.now()-i;return!t||401!==e.status&&403!==e.status?t?e.ok&&Array.isArray(o)?{url:r,ok:!0,ms:a,models:o.length}:{url:r,ok:!1,ms:a,error:"not_gateway",detail:`HTTP ${e.status}`}:e.ok&&o&&"object"==typeof o?(rememberPublishedAddresses(o,r),{url:r,ok:!0,ms:a}):{url:r,ok:!1,ms:a,error:"not_gateway",detail:`HTTP ${e.status}`}:{url:r,ok:!1,ms:a,error:"key_rejected",detail:`HTTP ${e.status}`}}catch(e){return{url:r,ok:!1,ms:Date.now()-i,...c(e)}}finally{clearTimeout(a)}}
@@ -0,0 +1 @@
1
+ import{getGatewayModelRules as e}from"./model-registry.js";export function autoCompactTokens(t,i){return i&&i>0?Math.min(i,t):Math.floor(t*e().autoCompactRatio)}export function gatewayModelSpecs(t,i){const o=e().models,n=o.filter(e=>function(e,t){return"codex"===e?!1!==t.codex:"grok"===e?"grok"===modelFamily(t.id):!t.id.startsWith("claude-")&&!1!==t.claudeCode}(t,e));if(!i)return n;const d=new Set(Object.values(i).flat().filter(e=>e.hidden).map(e=>e.id)),r=Object.fromEntries(Object.entries(i).map(([e,t])=>[e,t.filter(e=>!e.hidden)])),s=new Map;for(const e of Object.values(r).flat()){const i=e.clients?.[t];void 0===i||s.has(e.id)||s.set(e.id,i)}for(const[e,t]of s)t||d.add(e);const l=new Map(("claude-code"===t?o:n).map(e=>[e.id,e])),c=(r.gemini??[]).filter(e=>s.get(e.id)??!1!==o.find(t=>t.id===e.id)?.codex),a=("grok"===t?r.grok??[]:"codex"===t?[...r.codex??[],...c,...(r.claude??[]).filter(e=>e.id.startsWith("claude-")&&(s.get(e.id)??l.has(e.id)))]:function(e,t){return[...(e.codex??[]).filter(e=>"gpt"===modelFamily(e.id)),...e.gemini??[],...e.grok??[],...(e.claude??[]).filter(e=>!e.id.startsWith("claude-"))].filter(e=>e.clients?.["claude-code"]??t.get(e.id)?.claudeCode??!0)}(r,l)).filter(e=>!(e=>!1===s.get(e.id))(e));if(0===a.length)return n.filter(e=>!d.has(e.id));const u=new Set,f=[];for(const e of a){if(u.has(e.id))continue;u.add(e.id);const{clients:t,minClientVersion:i,rolloutPercent:o,...n}=e,d={...l.get(e.id),...n};void 0!==t?.codex&&(d.codex=t.codex),void 0!==t?.["claude-code"]&&(d.claudeCode=t["claude-code"]),f.push(d)}return function(e,t,i){const o=[...e];return t.forEach((e,n)=>{if(i.has(e.id)||o.some(t=>t.id===e.id))return;const d=modelFamily(e.id),r=new Set(t.slice(n+1).filter(e=>modelFamily(e.id)===d).map(e=>e.id));let s=o.findIndex(e=>r.has(e.id));if(s<0){s=o.length;for(let e=o.length-1;e>=0;e--)if(modelFamily(o[e].id)===d){s=e+1;break}}o.splice(s,0,e)}),o}(f,n,d)}const t={gpt:"GPT",gemini:"Gemini",glm:"GLM",deepseek:"DeepSeek",minimax:"MiniMax",qwen:"Qwen"};export function modelBlurb(e,t={}){const i=[];for(const o of(e??"").split("|")){const e=o.trim();e&&(/\d\s*万?\s*输出|output\D*\d|\d\D*output/i.test(e)||(/[\d百千]\s*万?\s*上下文|context\D*\d|\d\D*context/i.test(e)?t.millionContext&&!i.includes("百万上下文")&&i.unshift("百万上下文"):i.push(e)))}return t.millionContext&&!i.includes("百万上下文")&&i.unshift("百万上下文"),i.length>0?i.join(" | "):void 0}export function prettyModelName(e){const i=e.replace(/^([a-z]+)(\d)/i,"$1 $2").split(/[-_\s]+/).filter(Boolean),o=[];for(const e of i){const i=o[o.length-1];if(/^\d+$/.test(e)&&i&&/^\d+$/.test(i)&&e.length<=2&&!/^\d{8}$/.test(e)){o[o.length-1]=`${i}.${e}`;continue}const n=e.toLowerCase();o.push(t[n]??(/^[a-z]\d/i.test(e)?e.toUpperCase():e[0].toUpperCase()+e.slice(1)))}return o.join(" ")}export function vendorNames(e){return[...new Set(e.map(e=>prettyModelName(e).split(" ")[0]))]}export function modelFamily(e){const t=e.toLowerCase();return t.startsWith("claude-")?"claude":t.startsWith("gemini")?"gemini":t.startsWith("grok")?"grok":/^(gpt|o\d|codex)/.test(t)?"gpt":"other"}
@@ -0,0 +1 @@
1
+ export const CLIENT_CONFIG_PATH="/api/platform/vibecode/config";export const KEY_INFO_PATH="/api/platform/vibecode/key";export const CLIENT_SECTION="vibecli";export const MIN_CLIENT_VERSION="min_vibecli_version";export const INSTALL_ID_HEADER="X-VibeCLI-Install-Id";
@@ -0,0 +1 @@
1
+ import{readFileSync as t,existsSync as e,readdirSync as s}from"fs";import{join as o,dirname as r}from"path";import{fileURLToPath as a}from"url";import{logger as n}from"../utils/logger.js";import{brandTokens as l}from"./brand.js";class c{static instance;currentLocale="en_US";translations=new Map;fallbackLocale="en_US";localesDir;constructor(){const t=a(import.meta.url),e=r(t);this.localesDir=o(e,"..","locales"),this.loadTranslations(),this.loadSavedLocale()}static getInstance(){return c.instance||(c.instance=new c),c.instance}loadTranslations(){try{if(!e(this.localesDir))return void n.warn(`Locales directory not found at ${this.localesDir}`);const r=s(this.localesDir).filter(t=>t.endsWith(".json"));if(0===r.length)return void n.warn("No locale files found in locales directory");for(const e of r){const s=e.replace(".json",""),r=o(this.localesDir,e);try{const e=t(r,"utf-8"),o=JSON.parse(e);this.translations.set(s,o)}catch(t){n.warn(`Failed to load locale file ${e}:`,t)}}const a=process.env.LANG||process.env.LC_ALL||process.env.LC_MESSAGES;if(a){const t=a.split(".")[0].replace("_","-");if(this.translations.has(t))this.currentLocale=t;else{const e=t.split("-")[0],s=Array.from(this.translations.keys()).find(t=>t.startsWith(e+"_"));s?this.currentLocale=s:"zh"===e?this.currentLocale="zh_CN":"en"===e&&(this.currentLocale="en_US")}}}catch(t){n.warn("Failed to load translations:",t)}}setLocale(t){this.translations.has(t)?(this.currentLocale=t,this.saveLocale()):n.warn(`Locale '${t}' not supported, falling back to '${this.currentLocale}'`)}getLocale(){return this.currentLocale}getAvailableLocales(){return Array.from(this.translations.keys())}translate(t,e){const s=t.split(".");let o=this.translations.get(this.currentLocale);for(const e of s){if(!o||"object"!=typeof o||!(e in o)){o=this.translations.get(this.fallbackLocale);for(const e of s){if(!o||"object"!=typeof o||!(e in o))return t;o=o[e]}break}o=o[e]}if("string"!=typeof o)return t;const r=l(this.currentLocale);return o=o.replace(/\{\{(\w+)\}\}/g,(t,e)=>r[e]??t),e?o.replace(/\{\{(\w+)\}\}/g,(t,s)=>e[s]||t):o}t(t,e){return this.translate(t,e)}saveLocale(){}loadSavedLocale(){}loadFromConfig(t){this.translations.has(t)&&(this.currentLocale=t)}}export function detectSystemLang(){const t=process.env.LC_ALL||process.env.LC_MESSAGES||process.env.LANG||process.env.LANGUAGE||"";let e="";try{e=Intl.DateTimeFormat().resolvedOptions().locale||""}catch{}return`${t} ${e}`.toLowerCase().split(/[\s:;,]+/).some(t=>"zh"===t||t.startsWith("zh-")||t.startsWith("zh_"))?"zh_CN":"en_US"}export{c as I18n};export const i18n=c.getInstance();
@@ -0,0 +1 @@
1
+ import{configManager as n}from"./config.js";import{KEY_INFO_PATH as t}from"./gateway-protocol.js";import{logger as e}from"../utils/logger.js";import{brandEnv as o}from"./brand.js";import{i18n as i}from"./i18n.js";export const BALANCE_TIMEOUT_MS=3e3;function a(n){return"number"==typeof n&&Number.isFinite(n)?n:void 0}export async function fetchKeyBalance(o,i={}){const{timeoutMs:r=BALANCE_TIMEOUT_MS,fetchFn:u=fetch}=i,c=(i.baseUrl??n.getBaseUrl()).replace(/\/+$/,""),l=new AbortController,s=setTimeout(()=>l.abort(),r),m=n=>async function(n,t,e,o){if(o.aborted)return null;const i=await e(n,{method:"GET",headers:{Authorization:`Bearer ${t}`},signal:o});return i.ok?i.json():null}(`${c}${n}`,o,u,l.signal).catch(()=>null);try{const n=function(n){const t=n?.data?.balance,e=a(t?.remaining);if(!t||void 0===e)return null;const o="string"==typeof t.unit&&t.unit?t.unit:"USD",i={remaining:e,unit:o,symbol:"string"==typeof t.symbol?t.symbol:"USD"===o?"$":""},r=a(t.wallet);void 0!==r&&(i.wallet=r);const u=a(t.token_remaining);return void 0!==u&&(i.tokenRemaining=u),!0===t.account_insufficient&&(i.accountInsufficient=!0),i}(await m(t));if(n)return n;const[e,o]=await Promise.all([m("/v1/dashboard/billing/subscription"),m("/v1/dashboard/billing/usage")]);return function(n,t){const e=a(n?.hard_limit_usd),o=a(t?.total_usage);if(void 0===e||void 0===o||e>=1e8)return null;const i=Math.max(0,Math.round(1e4*(e-o/100))/1e4);return{remaining:i,unit:"USD",symbol:"$",tokenRemaining:i}}(e,o)}catch(n){return e.logError("fetchKeyBalance",n),null}finally{clearTimeout(s)}}export function balanceLookupEnabled(){return"1"!==o("SKIP_BALANCE")}export async function fetchKeyBalances(n,t={}){const e=[...new Set(n.filter(Boolean))],o=await Promise.all(e.map(n=>fetchKeyBalance(n,t)));return new Map(e.map((n,t)=>[n,o[t]]))}export function formatAmount(n,t){return"TOKENS"===t.unit?`${Math.round(n)} tokens`:`${t.symbol}${n.toFixed(2)}`}export function limitedByToken(n){return void 0!==n.tokenRemaining}export function balanceText(n){const t=formatAmount(n.remaining,n);return n.remaining<=0?i.t(limitedByToken(n)?"status.balance_token_empty":"status.balance_empty",{amount:t}):n.accountInsufficient?i.t("status.balance_account_low",{amount:t}):limitedByToken(n)?i.t("status.balance_token_limited",{amount:t}):t}export function balanceNeedsAttention(n){return n.remaining<=0||Boolean(n.accountInsufficient)}
@@ -0,0 +1 @@
1
+ import{logger as e}from"../utils/logger.js";import{fetchClientModelConfig as o,fetchKeyGroupInfo as l,fetchModels as t,fetchGatewayStatus as n}from"./api-validator.js";import{getClaudeDesktopRules as r}from"./model-registry.js";export function baseModelId(e){return e.replace(/\[[^\]]*\]$/,"").trim()}export function isClaudeModel(e){return/claude/i.test(baseModelId(e))}export function matchGroups(e,o){const l=new Set(e.map(baseModelId));if(0===l.size)return[];const t=[],n=[];for(const[e,r]of Object.entries(o)){const o=new Set(r.map(e=>baseModelId(e.name)).filter(isClaudeModel));[...l].every(e=>o.has(e))&&(o.size===l.size?t:n).push(e)}return t.length>0?t:n}export function resolveOneMillion(e,o,l){const t=r(),n=[...new Set(e.map(baseModelId))],s=new Set(e.filter(e=>/\[1m\]/i.test(e)).map(baseModelId)),a={};let i,d="fallback",c=[];if(l&&l.claudeDesktopModels.length>0){d="gateway",c=o?l.groups.filter(e=>e in o):l.groups;const e=new Map(l.claudeDesktopModels.map(e=>[baseModelId(e.name),e])),r=new Set(t.oneMillionFallback);i=new Set(n.filter(o=>{const l=e.get(o);return l?.labelOverride&&(a[o]=l.labelOverride),l?!0===l.supports1m:r.has(o)}))}else if(o&&(c=matchGroups(n,o)).length>0){d="gateway",i=new Set(n);for(const e of c){const l=new Map(o[e].map(e=>[baseModelId(e.name),e]));for(const e of n){const o=l.get(e);o?.labelOverride&&!a[e]&&(a[e]=o.labelOverride),!0!==o?.supports1m&&i.delete(e)}}}else{const e=new Set(t.oneMillionFallback);i=new Set(n.filter(o=>e.has(o)))}for(const e of s)i.add(e);for(const e of t.oneMillionExclusions)if(n.some(o=>o.startsWith(e.whenPrefixPresent)))for(const o of e.models)i.delete(o);return{oneMillion:[...i],labels:a,oneMillionSource:d,matchedGroups:c}}export async function resolveModelCatalog(r){try{const[e,s,a,i]=await Promise.all([t(r),n(),o(),l(r)]);if(!e.ok||0===e.models.length)return null;const d=[...new Set(e.models.map(e=>e.trim()).filter(Boolean))],c=d.filter(isClaudeModel);return{models:d,...resolveOneMillion(c,s.ok?s.claudeDesktopGroupModels:null,i),...a?{clientModels:a}:{}}}catch(o){return e.logError("resolveModelCatalog",o),null}}
@@ -0,0 +1 @@
1
+ import{existsSync as e,mkdirSync as o,readFileSync as r,writeFileSync as t}from"fs";import{dirname as n,join as s}from"path";import i from"chalk";import{configManager as l}from"./config.js";import{i18n as f}from"./i18n.js";import{resolveModelCatalog as d}from"./model-catalog.js";import{listAdapters as c}from"./tools/registry.js";import{UserActionNeeded as a}from"./tools/types.js";import{logger as u}from"../utils/logger.js";import{resolveUpdateCachePath as m}from"./auto-update.js";import{isHelpRequest as h}from"./cli-help.js";import{brandEnvName as p}from"./brand.js";export const MODEL_REFRESH_INTERVAL_MS=36e5;const g=new Set(["setup","init","config","auth","enter","completion","update","lang","logs","refresh"]),M=["--json","--dry-run","--help","-h","--version","-v"],y=[];export function shouldSkipModelRefresh(e,o=process.env){if("1"===o[p("DISABLE_MODEL_REFRESH")])return!0;if(M.some(o=>e.includes(o))||h(e))return!0;const r=e.find(e=>!e.startsWith("-"));return void 0!==r&&g.has(r)}let j={checked:0,failed:0};export function lastModelRefreshOutcome(){return{...j}}export async function refreshModelMenus(){const e=new Map,o=[];y.length=0,j={checked:0,failed:0};for(const r of c())if(r.refreshModelMenu&&r.listedModels)try{const t=l.getApiKeyForTool(r.name);if(!t||r.detectCurrentConfig().apiKey!==t)continue;const n=r.listedModels();if(null===n)continue;e.has(t)||e.set(t,await d(t));const s=e.get(t);if(!s)continue;r.refreshModelMenu({apiKey:t,baseUrl:l.getBaseUrl(),models:l.getModelsForTool(r.name),settings:l.getToolSettings(r.name),catalog:s}),j.checked++;const i=r.listedModels()??[],f=i.filter(e=>!n.includes(e)),c=n.filter(e=>!i.includes(e));(f.length>0||c.length>0)&&o.push({tool:r.displayName,added:f,removed:c})}catch(e){j.failed++,u.logError(`modelRefresh(${r.name})`,e),e instanceof a&&y.push(e.message)}return o}export async function runModelRefresh(l,d={}){const c=d.env??process.env,a=d.now??Date.now(),h=function(e){return s(n(m(e)),"model-refresh.json")}(c);if(!d.force){if(shouldSkipModelRefresh(l,c))return[];if(a-function(e){try{const o=JSON.parse(r(e,"utf-8")).refreshed_at;return"number"==typeof o?o:0}catch{return 0}}(h)<36e5)return[]}let p=[];try{p=await refreshModelMenus(),e(n(h))||o(n(h),{recursive:!0}),t(h,JSON.stringify({refreshed_at:a})+"\n")}catch(e){u.logError("runModelRefresh",e)}const g=d.output??(e=>console.log(i.gray(e)));for(const e of y)g(e);for(const e of p){const o=[e.added.length>0?f.t("model_refresh.added",{models:e.added.join(", ")}):"",e.removed.length>0?f.t("model_refresh.removed",{models:e.removed.join(", ")}):""].filter(Boolean);g(f.t("model_refresh.changed",{tool:e.tool,changes:o.join(";")}))}return p}
@@ -0,0 +1 @@
1
+ import{dirname as e,join as o}from"path";import{fileURLToPath as t}from"url";import{existsSync as l,readFileSync as n}from"fs";import{currentClientConfig as r,usableClientSection as s}from"./client-config.js";import{brand as a}from"./brand.js";const i=e(t(import.meta.url)),d=(e=[],o=[])=>[...new Set([...e,...o])];export function overlayClientSection(e,o){if(!o)return e;const t={...e.retiredDefaultModels??{}};for(const[e,l]of Object.entries(o.retiredDefaultModels??{}))t[e]=d(t[e],l);return{...e,defaultModels:{...e.defaultModels,...o.defaultModels??{}},retiredDefaultModels:t,toolDefaults:{...e.toolDefaults??{},...o.toolDefaults??{}},claudeCode:o.tierChains?{...e.claudeCode??{},tierChains:{...e.claudeCode?.tierChains??{},...o.tierChains}}:e.claudeCode,claudeDesktop:o.oneMillionFallback?{...e.claudeDesktop??{},oneMillionFallback:[...o.oneMillionFallback]}:e.claudeDesktop,gatewayModels:o.retiredModels?{...e.gatewayModels??{},retired:d(e.gatewayModels?.retired,o.retiredModels)}:e.gatewayModels,toolMinVersions:{...e.toolMinVersions??{},...o.toolMinVersions??{}},agy:o.agyModels?{...e.agy??{},gatewayModels:[...o.agyModels]}:e.agy}}let u=null;function c(){return u||(u=overlayClientSection(function(){const e=[o(i,"..","..","models.json"),o(i,"..","models.json"),o(i,"models.json")];for(const o of e)if(l(o))return JSON.parse(n(o,"utf-8"));throw new Error(`models.json not found, searched: ${e.join(", ")}`)}(),s(r()?.config))),u}export function getDefaultModels(){return{...c().defaultModels}}export function isRetiredDefaultModel(e,o){return c().retiredDefaultModels?.[e]?.includes(o)??!1}export function getDefaultToolModel(){return c().defaultToolModel?.trim()||"gpt-5.5"}export function getToolDefaultModel(e){const o=c().toolDefaults;return o&&Object.prototype.hasOwnProperty.call(o,e)?(o[e]??"").trim():getDefaultToolModel()}export function getPresets(){return[...c().presets]}export function resolvePreset(e){return e.models?{...e.models}:e.model?{haiku:e.model,sonnet:e.model,opus:e.model,reasoning:e.model}:getDefaultModels()}export function getClaudeCodeTierChains(){const e=c().claudeCode?.tierChains??{};return Object.fromEntries(Object.entries(e).map(([e,o])=>[e,[...o]]))}export function getClaudeDesktopRules(){const e=c().claudeDesktop??{};return{oneMillionFallback:[...e.oneMillionFallback??[]],oneMillionExclusions:(e.oneMillionExclusions??[]).map(e=>({...e,models:[...e.models]}))}}export function getGatewayModelRules(){const e=c().gatewayModels??{};return{autoCompactRatio:e.autoCompactRatio??.8,models:(e.models??[]).map(e=>({...e})),retired:[...e.retired??[]]}}export function getBuiltinGatewayAddresses(){return a().gatewayAddresses.map(e=>({...e}))}export function getCodexRules(){return{standardContextWindow:c().codex?.standardContextWindow??272e3}}export function getAgyRules(){return{gatewayModels:[...c().agy?.gatewayModels??[]]}}export function compareVersions(e,o){const t=e.split(".").map(e=>parseInt(e,10)||0),l=o.split(".").map(e=>parseInt(e,10)||0);for(let e=0;e<Math.max(t.length,l.length);e++){const o=(t[e]??0)-(l[e]??0);if(0!==o)return o}return 0}export function getToolMinVersion(e){return c().toolMinVersions?.[e]?.trim()||null}export function reloadRegistry(){u=null}
@@ -0,0 +1 @@
1
+ import{existsSync as e,readFileSync as o}from"fs";import{join as t}from"path";import{logger as n}from"../utils/logger.js";import{configManager as i,DEFAULT_MODELS as r}from"./config.js";import{atomicWriteFile as a}from"./tools/backup.js";import{toolHome as p}from"./tools/types.js";export class OpenCodeManager{static instance;get configPath(){return t(p(),".config","opencode","opencode.json")}static getInstance(){return OpenCodeManager.instance||(OpenCodeManager.instance=new OpenCodeManager),OpenCodeManager.instance}getConfig(){try{if(e(this.configPath)){const e=o(this.configPath,"utf-8");return JSON.parse(e)}}catch(e){n.warn("Failed to read OpenCode config:",e),n.logError("OpenCodeManager.getConfig",e)}return{}}saveConfig(e){try{a(this.configPath,JSON.stringify(e,null,4))}catch(e){throw new Error(`Failed to save OpenCode config: ${e}`)}}loadPrivateConfig(e,o){const t=this.getConfig(),{provider:n,...a}=t,p={};if(n)for(const[e,o]of Object.entries(n))"private-newapi"!==e&&(p[e]=o);p["private-newapi"]={options:{apiKey:e,baseURL:i.getBaseUrl()}};const s={$schema:"https://opencode.ai/config.json",...a,provider:p,model:`private-newapi/${o.opus||r.opus}`,small_model:`private-newapi/${o.haiku||r.haiku}`};this.saveConfig(s)}unloadPrivateConfig(){const e=this.getConfig();e.provider&&(delete e.provider["private-newapi"],0===Object.keys(e.provider).length&&delete e.provider),e.model?.includes("private-newapi")&&delete e.model,e.small_model?.includes("private-newapi")&&delete e.small_model,this.saveConfig(e)}detectCurrentConfig(){try{const e=this.getConfig();if(!e.provider)return{apiKey:null};let o=null;return e.provider["private-newapi"]&&(o=e.provider["private-newapi"].options?.apiKey||null),{apiKey:o}}catch{return{apiKey:null}}}}export const openCodeManager=OpenCodeManager.getInstance();
@@ -0,0 +1 @@
1
+ import{chmodSync as t,existsSync as n,readFileSync as o,realpathSync as r,unlinkSync as e}from"fs";import{join as s}from"path";import{logger as i}from"../utils/logger.js";import{getShellRcFilePath as c}from"./env-cleanup.js";import{broadcastEnvChange as f,deleteWindowsEnv as u,readWindowsEnv as p,setUserEnv as l}from"./windows-env.js";import{atomicWriteFile as m,backupBeforeWrite as a}from"./tools/backup.js";import{toolHome as $}from"./tools/types.js";import{CLI_NAME as d}from"./brand.js";const h=t=>`# ${d}:${t}`;function v(){const t=$(),o=new Set,r=c();r&&o.add(r);for(const r of[".zshrc",".bashrc"]){const e=s(t,r);n(e)&&o.add(e)}return[...o]}function j(t,n,o){const r=`"${function(t){const n=$();return t.startsWith(n+"/")?`$HOME/${t.slice(n.length+1)}`:t}(n)}"`;return t.endsWith(".fish")?`test -f ${r}; and source ${r} ${h(o)}`:`[ -f ${r} ] && . ${r} ${h(o)}`}function w(t,o){const e=n(t)?r(t):t;a(e),m(e,o)}function E(t,n){return t.split("\n").filter(t=>!t.trimEnd().endsWith(h(n))).join("\n")}function b(t,n){if(/['\r\n]/.test(n))throw new Error(`${t} contains a quote or newline and cannot be written to a shell env file`)}export function writePersistentEnv(r,e,s){for(const[t,n]of Object.entries(s))b(t,n);const i=Object.entries(s).map(([t,n])=>`export ${t}='${n}'`).join("\n");a(e),m(e,`# Written by ${d}. Loaded from your shell profile.\n${i}\n`,384),t(e,384);for(const[t,n]of Object.entries(s))process.env[t]=n;if("win32"===process.platform){for(const[t,n]of Object.entries(s))l(t,n);return f(),{rcFiles:[]}}const c=[];for(const t of v()){const s=n(t)?o(t,"utf-8"):"",i=j(t,e,r);if(s.split("\n").some(t=>t.trimEnd()===i)){c.push(t);continue}const f=E(s,r).replace(/\n*$/,"");w(t,`${f?f+"\n\n":""}${i}\n`),c.push(t)}return{rcFiles:c}}export function removePersistentEnv(t,r,s){const c=readPersistentEnvFile(r);if(n(r)&&(a(r),e(r)),"win32"===process.platform){let t=!1;for(const n of s)if(void 0!==c[n]&&p("user",n)===c[n])try{u("user",n),t=!0}catch(t){i.logError("persistentEnv.remove",t)}return void(t&&f())}for(const r of v()){if(!n(r))continue;const e=o(r,"utf-8"),s=E(e,t);s!==e&&w(r,s)}}export function readPersistentEnvFile(t){const r={};if(!n(t))return r;for(const n of o(t,"utf-8").split("\n")){const t=n.match(/^export ([A-Z_][A-Z0-9_]*)='([^']*)'$/);t&&(r[t[1]]=t[2])}return r}
@@ -0,0 +1 @@
1
+ import o from"chalk";import t from"inquirer";import{i18n as e}from"./i18n.js";import{hasExplicitYes as n,isNonInteractive as i,shouldAutoConfirm as r}from"./runtime-options.js";import{toolManager as s}from"./tool-manager.js";import{getAdapter as l}from"./tools/registry.js";import{upgradeTool as a}from"./tool-upgrade.js";import{logger as p}from"../utils/logger.js";async function f(o){const{ok:e}=await t.prompt([{type:"confirm",name:"ok",message:o,default:!0}]);return e}export async function postApplyPrompts(t){for(const e of t){const t=await(l(e)?.prepareRuntime?.())??[];for(const e of t)console.log("action"===e.kind?o.yellow(" ! "+e.text):o.green(" √ "+e.text))}const c=!i()&&process.stdin.isTTY;for(const n of t){const t=l(n)?.pendingElevation?.();if(!t)continue;if(!(r()||c&&await f(t.prompt)))continue;const i=l(n)?.displayName??n;console.log(o.gray(" "+e.t("setup.elevation_running"))),console.log(t.run()?o.green(" √ "+e.t("setup.elevation_done",{tool:i})):o.yellow(" ! "+e.t("setup.elevation_failed",{tool:i})))}for(const e of t){let t;try{t=await(l(e)?.followUp?.())}catch(o){p.logError(`postApplyPrompts.followUp(${e})`,o);continue}if(!t)continue;const i=n();if("run"in t&&(i||c))if(i||await f(t.prompt))for(const e of await t.run())console.log("action"===e.kind?o.yellow(" ! "+e.text):o.green(" √ "+e.text));else t.decline();else console.log(o.yellow(" ! "+t.hint))}if(!c)return;const m=t.filter(o=>l(o)?.installSpec&&s.outdatedVersion(o));if(m.length>0){const o=m.map(o=>l(o)?.displayName??o).join("、");if(await f(e.t("setup.offer_upgrade",{tools:o})))for(const o of m)await a(o)}for(const n of t){const t=l(n);if(!t?.runningApp?.isRunning())continue;if(!await f(e.t("setup.offer_restart",{tool:t.displayName})))continue;const i=t.runningApp.restart();console.log(i?o.green(" √ "+e.t("setup.restarted",{tool:t.displayName})):o.yellow(" ! "+e.t("setup.restart_failed",{tool:t.displayName})))}}
@@ -0,0 +1 @@
1
+ import{Command as e,Option as o}from"commander";import{readFileSync as s}from"fs";import{join as t,dirname as n}from"path";import{fileURLToPath as a}from"url";import{i18n as i}from"./i18n.js";import{wizard as r}from"./wizard.js";import{SUPPORTED_TOOLS as c}from"./tool-manager.js";import{DEFAULT_BASE_URL as l}from"./config.js";import{attachCommandHelp as p,helpConfiguration as m}from"./cli-help.js";import{langCommand as u,authCommand as d,doctorCommand as f,configCommand as g,statusCommand as x,refreshCommand as h}from"../commands/index.js";import{logsCommand as y}from"../commands/logs.js";import{completionCommand as $}from"../commands/completion.js";import{benchCommand as b}from"../commands/bench.js";import{updateCommand as k}from"../commands/update.js";import{upgradeCommand as _}from"../commands/upgrade.js";import{codexSessionsCommand as w}from"../commands/codex-sessions.js";import{sessionsExportCommand as v,sessionsListCommand as j,sessionsResumeCommand as O,sessionsShowCommand as S}from"../commands/sessions.js";import{setupCommand as A,DEDICATED_KEYS as E}from"../commands/setup.js";import{baseCommand as G}from"../commands/base.js";import{usageError as z}from"./errors.js";import{brand as C,brandEnv as R,CLI_NAME as B}from"./brand.js";const I=(C().gatewayAddresses[1]??C().gatewayAddresses[0]).url,L=(C().gatewayAddresses[2]??C().gatewayAddresses[0]).url;function N(e,o){return i.t(`help.${e}`,o)}function P(e,o){return{command:e,note:N(o)}}function T(e){const o=N(e);return o===`help.${e}`?"":o}function U(e,o=[]){return{when:T(`${e}.when`),prerequisites:T(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>P(e,o))}}function H(e){return e.helpCommand("help [command]",N("help_command"))}export function buildProgram(){const C=new e;C.name(`${B}`).summary(N("root.summary")).description(N("root.description")).configureHelp(m()).allowExcessArguments(!0).optionsGroup(N("group.global_options")).helpOption("-h, --help",N("global.help")).version(function(){try{const e=n(a(import.meta.url));return JSON.parse(s(t(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",N("global.version")).option("--base <url>",N("global.base")).option("--non-interactive",N("global.non_interactive")).option("--json",N("global.json")).option("-y, --yes",N("global.yes")).option("--dry-run",N("global.dry_run")).option("--no-color",N("global.no_color")),C.configureOutput({writeErr:()=>{},outputError:()=>{}}),C.showSuggestionAfterError(),C.exitOverride(e=>{throw e}),C.commandsGroup(N("group.configure"));const T=C.command("setup").summary(N("setup.summary")).description(N("setup.description")).option("--key <key>",N("setup.opt.key"));for(const e of E){const s=new o(`--${e.option} <key>`,N(`setup.opt.${e.option}`));e.hidden&&s.hideHelp(),T.addOption(s)}T.option("--1m",N("setup.opt.one_m")).option("--no-1m",N("setup.opt.no_one_m")).option("--claude-official <on|off>",N("setup.opt.claude_official")).option("--desktop-registry <on|off>",N("setup.opt.desktop_registry")).option("--force",N("setup.opt.force")).option("--install",N("setup.opt.install")).option("--no-install",N("setup.opt.no_install")).option("--all",N("setup.opt.all")).action(async e=>{e.key||E.some(o=>e[o.option])||(e.key=R("SETUP_KEY")?.trim()||void 0,e.fromInstaller=Boolean(e.key));const o=Boolean(e.key||E.some(o=>e[o.option])),s=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,t=i.t("errors.key_placeholder");if(!o&&!s)throw z(i.t("setup.usage"),`${B} setup --key ${t}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw z(i.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),`${B} setup --claude-official on|off`,"invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw z(i.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),`${B} setup --desktop-registry on|off`,"invalid_value");await A({key:e.key,...Object.fromEntries(E.map(o=>[o.option,e[o.option]])),all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,desktopRegistry:e.desktopRegistry,force:e.force,install:e.install,fromInstaller:e.fromInstaller})}),p(T,{...U("setup",[[`${B} init`,"setup.alt.init"],[`${B} config <tool>`,"setup.alt.config"],[`${B} auth <key>`,"setup.alt.auth"]]),sections:[{title:N("setup.autodetect_title"),rows:[["Claude",N("setup.autodetect.claude")],["GPT",N("setup.autodetect.gpt")],["Grok",N("setup.autodetect.grok")],["Gemini",N("setup.autodetect.gemini")]]}],examples:[P(`${B} setup --key sk-xxx`,"setup.ex.key"),P(`${B} setup --install --key sk-xxx`,"setup.ex.install"),P(`${B} setup --claudekey sk-a --codexkey sk-b --agykey sk-g`,"setup.ex.split"),P(`${B} setup --force --key sk-xxx`,"setup.ex.force"),P(`${B} setup --base ${I} --key sk-xxx`,"setup.ex.base")]});const K=C.command("init").summary(N("init.summary")).description(N("init.description")).action(async()=>{await r.runFirstTimeSetup()});p(K,{...U("init",[[`${B} setup --key <key>`,"init.alt.setup"],[`${B}`,"init.alt.menu"]]),examples:[P(`${B} init`,"init.ex.run"),P(`${B} init --base ${I}`,"init.ex.base"),P(`${B}`,"init.ex.menu")]});const M=C.command("auth").summary(N("auth.summary")).description(N("auth.description")).argument("[token]",N("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});H(M);const q=M.command("revoke").description(N("auth.revoke")).action(async()=>{await d(["revoke"])});p(q,{examples:[P(`${B} auth revoke`,"auth.ex.revoke_ask"),P(`${B} auth revoke --yes`,"auth.ex.revoke")]});const D=M.command("reload <tool>").description(N("auth.reload")).action(async e=>{await d(["reload",e])});p(D,{examples:[P(`${B} auth reload claude-code`,"auth.ex.reload"),P(`${B} auth reload claude-code --json`,"auth.ex.reload_json")]}),p(M,{...U("auth",[[`${B} setup --key <key>`,"auth.alt.setup"]]),examples:[P(`${B} auth`,"auth.ex.prompt"),P(`${B} auth sk-xxx --non-interactive`,"auth.ex.save"),P(`${B} auth revoke --yes`,"auth.ex.revoke"),P(`${B} auth reload claude-code`,"auth.ex.reload")]});const F=C.command("config").summary(N("config.summary")).description(N("config.description")).argument("[args...]",N("config.arg.args")).option("-f, --force",N("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await g(o.force?[...e,"--force"]:e)});p(F,{...U("config",[[`${B} setup --force --key <key>`,"config.alt.setup"],[`${B} status`,"config.alt.status"]]),sections:[{title:N("config.subcommands_title"),rows:[["<tool>",N("config.sub.tool")],["<tool> --force",N("config.sub.tool_force")],["<tool> --non-interactive",N("config.sub.tool_non_interactive")],["<tool> remove",N("config.sub.tool_remove")],["<tool> restore",N("config.sub.tool_restore")],["<tool> backups",N("config.sub.tool_backups")],["<tool> clear-model",N("config.sub.tool_clear_model")],["tool-model list",N("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",N("config.sub.tool_model_set")],["tool-model clear <tool>",N("config.sub.tool_model_clear")],["profile list",N("config.sub.profile_list")],["profile create <name>",N("config.sub.profile_create")],["profile use <name>",N("config.sub.profile_use")],["profile delete <name>",N("config.sub.profile_delete")],["preset list",N("config.sub.preset_list")],["preset save <name>",N("config.sub.preset_save")],["preset use <name>",N("config.sub.preset_use")],["preset delete <name>",N("config.sub.preset_delete")],["backup list",N("config.sub.backup_list")],["backup create [label]",N("config.sub.backup_create")],["backup restore <name>",N("config.sub.backup_restore")]]},{title:N("config.tools_title"),rows:Object.values(c).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[P(`${B} config codex`,"config.ex.menu"),P(`${B} config claude-code --force`,"config.ex.force"),P(`${B} config tool-model set codex gpt-6-astra`,"config.ex.tool_model"),P(`${B} config profile create work`,"config.ex.profile"),P(`${B} config codex remove`,"config.ex.remove")]});const J=C.command("base").summary(N("base.summary")).description(N("base.description")).argument("[target]",N("base.arg.target")).action(async e=>{await G(e)});p(J,{...U("base",[[`${B} doctor`,"base.alt.doctor"],[`${B} bench`,"base.alt.bench"]]),sections:[{title:N("base.targets_title"),rows:[[N("base.target.none_term"),N("base.target.none")],[N("base.target.index_term"),N("base.target.index")],[N("base.target.url_term"),N("base.target.url")],["auto",N("base.target.auto")],["default",N("base.target.default",{url:l})]]}],examples:[P(`${B} base`,"base.ex.list"),P(`${B} base auto`,"base.ex.auto"),P(`${B} base 2`,"base.ex.index"),P(`${B} base ${I}`,"base.ex.url"),P(`${B} base default`,"base.ex.default")]}),C.commandsGroup(N("group.diagnose"));const Y=C.command("status").summary(N("status.summary")).description(N("status.description")).action(async()=>{await x()});p(Y,{...U("status",[[`${B} doctor`,"status.alt.doctor"]]),examples:[P(`${B} status`,"status.ex.show"),P(`${B} status --json`,"status.ex.json")]});const Q=C.command("doctor").summary(N("doctor.summary")).description(N("doctor.description")).option("--deep",N("doctor.opt.deep")).option("--report",N("doctor.opt.report")).action(async e=>{await f({deep:e.deep,report:e.report})});p(Q,{...U("doctor",[[`${B} base auto`,"doctor.alt.base"],[`${B} logs tail`,"doctor.alt.logs"]]),examples:[P(`${B} doctor`,"doctor.ex.run"),P(`${B} doctor --deep`,"doctor.ex.deep"),P(`${B} doctor --report`,"doctor.ex.report")]});const V=C.command("bench").summary(N("bench.summary")).description(N("bench.description")).option("--samples <n>",N("bench.opt.samples"),"5").option("--stream",N("bench.opt.stream")).option("--model <model>",N("bench.opt.model")).action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),e.stream&&o.push("--stream"),e.model&&o.push("--model",e.model),await b(o)});p(V,{...U("bench",[[`${B} base`,"bench.alt.base"]]),examples:[P(`${B} bench`,"bench.ex.run"),P(`${B} bench --samples 3`,"bench.ex.samples"),P(`${B} bench --stream`,"bench.ex.stream"),P(`${B} bench --stream --model gpt-6-astra`,"bench.ex.stream_model"),P(`${B} bench --json`,"bench.ex.json")]});const W=C.command("logs").summary(N("logs.summary")).description(N("logs.description")).argument("[action]",N("logs.arg.action")).argument("[file]",N("logs.arg.file")).action(async(e,o)=>{const s=[];e&&s.push(e),o&&s.push(o),await y(s)});p(W,{...U("logs",[[`${B} doctor`,"logs.alt.doctor"]]),sections:[{title:N("logs.actions_title"),rows:[["list",N("logs.action.list")],["tail [file]",N("logs.action.tail")],["path",N("logs.action.path")]]}],examples:[P(`${B} logs`,"logs.ex.list"),P(`${B} logs tail`,"logs.ex.tail"),P(`${B} logs path`,"logs.ex.path")]}),C.commandsGroup(N("group.maintain"));const X=C.command("upgrade").summary(N("upgrade.summary")).description(N("upgrade.description")).argument("[tools...]",N("upgrade.arg.tools")).action(async(e=[])=>{await _(e)});p(X,{...U("upgrade",[[`${B} update`,"upgrade.alt.update"]]),examples:[P(`${B} upgrade`,"upgrade.ex.all"),P(`${B} upgrade claude-code`,"upgrade.ex.one"),P(`${B} upgrade codex agy`,"upgrade.ex.many")]});const Z=C.command("refresh").summary(N("refresh.summary")).description(N("refresh.description")).action(async()=>{await h()});p(Z,{...U("refresh",[[`${B} setup --key ${i.t("errors.key_placeholder")}`,"refresh.alt.setup"]]),examples:[P(`${B} refresh`,"refresh.ex.run"),P(`${B} refresh --base ${L}`,"refresh.ex.base")]});const ee=C.command("update").summary(N("update.summary")).description(N("update.description")).action(async()=>{await k()});p(ee,{...U("update",[[`${B} upgrade`,"update.alt.upgrade"]]),examples:[P(`${B} update`,"update.ex.check"),P(`${B} update --json`,"update.ex.json")]});const oe=C.command("codex").summary(N("codex.summary")).description(N("codex.description"));H(oe);const se=oe.command("sessions").summary(N("codex_sessions.summary")).description(N("codex_sessions.description")).option("--to <provider>",N("codex_sessions.opt.to")).option("--undo <dir>",N("codex_sessions.opt.undo")).action(async e=>{await w(e)});p(oe,{...U("codex"),examples:[P(`${B} codex sessions`,"codex_sessions.ex.move"),P(`${B} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]}),p(se,{...U("codex_sessions",[[`${B} codex sessions --undo <dir>`,"codex_sessions.alt.undo"]]),examples:[P(`${B} codex sessions`,"codex_sessions.ex.move"),P(`${B} codex sessions --to custom`,"codex_sessions.ex.to"),P(`${B} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]});const te=C.command("sessions").summary(N("sessions.summary")).description(N("sessions.description"));H(te);const ne=te.command("list",{isDefault:!0}).description(N("sessions.list")).option("--tool <tool>",N("sessions.opt.tool")).option("--dir <path>",N("sessions.opt.dir")).option("--here",N("sessions.opt.here")).option("-n, --limit <count>",N("sessions.opt.limit")).option("--all",N("sessions.opt.all")).action(async e=>{await j(e)}),ae=te.command("show <id>").description(N("sessions.show")).option("-m, --messages <count>",N("sessions.opt.messages")).action(async(e,o)=>{await S(e,o)}),ie=te.command("resume <id>").description(N("sessions.resume")).option("--run",N("sessions.opt.run")).action(async(e,o)=>{await O(e,o)}),re=te.command("export <ids...>").description(N("sessions.export")).option("-o, --output <dir>",N("sessions.opt.output")).option("--tools",N("sessions.opt.tools")).action(async(e,o)=>{await v(e,o)});p(ne,{examples:[P(`${B} sessions list`,"sessions.ex.list"),P(`${B} sessions list --tool codex`,"sessions.ex.codex"),P(`${B} sessions list --here --all`,"sessions.ex.here"),P(`${B} sessions list --json`,"sessions.ex.json")]}),p(ae,{examples:[P(`${B} sessions show 01a0f5fe`,"sessions.ex.show"),P(`${B} sessions show 01a0f5fe -m 20`,"sessions.ex.show_more")]}),p(ie,{examples:[P(`${B} sessions resume 01a0f5fe`,"sessions.ex.resume_print"),P(`${B} sessions resume 01a0f5fe --run`,"sessions.ex.resume")]}),p(re,{examples:[P(`${B} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export"),P(`${B} sessions export 01a0f5fe -o ./sessions --tools`,"sessions.ex.export_tools")]}),p(te,{...U("sessions",[[`${B} codex sessions`,"sessions.alt.codex_sessions"]]),examples:[P(`${B} sessions`,"sessions.ex.list"),P(`${B} sessions --tool codex --here`,"sessions.ex.here"),P(`${B} sessions show 01a0f5fe`,"sessions.ex.show"),P(`${B} sessions resume 01a0f5fe --run`,"sessions.ex.resume"),P(`${B} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export")]});const ce=C.command("lang").summary(N("lang.summary")).description(N("lang.description"));H(ce);const le=ce.command("show").description(N("lang.show")).action(async()=>{await u(["show"])}),pe=ce.command("set <locale>").description(N("lang.set")).action(async e=>{await u(["set",e])}),me=[P(`${B} lang show`,"lang.ex.show"),P(`${B} lang set en_US`,"lang.ex.set_en"),P(`${B} lang set zh_CN`,"lang.ex.set_zh")];p(ce,{...U("lang",[[`${B} enter lang`,"lang.alt.enter"]]),examples:me}),p(le,{examples:[me[0],P(`${B} lang show --json`,"lang.ex.show_json")]}),p(pe,{examples:me.slice(1)});const ue=C.command("completion").summary(N("completion.summary")).description(N("completion.description")).argument("<shell>",N("completion.arg.shell")).action(async e=>{await $([e])});p(ue,{...U("completion"),examples:[P(`${B} completion bash > ~/.${B}-completion.bash`,"completion.ex.bash"),P(`${B} completion zsh > ~/.${B}-completion.zsh`,"completion.ex.zsh"),P(`${B} completion fish > ~/.config/fish/completions/${B}.fish`,"completion.ex.fish")]});const de=C.command("enter").summary(N("enter.summary")).description(N("enter.description")).argument("[option]",N("enter.arg.option")).action(async e=>{if(e)switch(e){case"lang":case"language":await r.configLanguage();break;case"apikey":case"api-key":await r.configApiKey();break;case"models":await r.configModels();break;default:await g([e])}else await r.run()});p(de,{...U("enter",[[`${B}`,"enter.alt.menu"],[`${B} config <tool>`,"enter.alt.config"]]),sections:[{title:N("enter.options_title"),rows:[[N("enter.option.none_term"),N("enter.option.none")],["lang",N("enter.option.lang")],["apikey",N("enter.option.apikey")],["models",N("enter.option.models")],["<tool>",N("enter.option.tool")]]}],examples:[P(`${B} enter`,"enter.ex.menu"),P(`${B} enter models`,"enter.ex.models"),P(`${B} enter codex`,"enter.ex.tool")]}),H(C),C.action(async()=>{await r.run()}),p(C,{examples:[P(`${B}`,"root.ex.menu"),P(`${B} setup --key sk-xxx`,"root.ex.setup"),P(`${B} doctor`,"root.ex.doctor"),P(`${B} base auto`,"root.ex.base"),P(`${B} config codex`,"root.ex.config")]});const fe=e=>{for(const o of e.commands)o.helpOption("-h, --help",N("global.help")),fe(o)};return fe(C),C}
@@ -0,0 +1 @@
1
+ const n={nonInteractive:!1,json:!1,yes:!1,dryRun:!1,color:!0};let t={...n};export function setRuntimeOptions(n){t={...t,...n}}export function getRuntimeOptions(){return{...t}}export function isJsonMode(){return t.json}export function isNonInteractive(){return t.nonInteractive||t.json}export function isDryRun(){return t.dryRun}export function shouldAutoConfirm(){return t.yes||t.nonInteractive||t.json}export function hasExplicitYes(){return t.yes}export function isColorEnabled(){return t.color}export function resetRuntimeOptions(){t={...n}}export function detectColorPreferenceFromEnv(n=process.env){return(!n.NO_COLOR||"0"===n.NO_COLOR)&&"0"!==n.FORCE_COLOR&&"false"!==n.FORCE_COLOR}export function emitJson(n,t=n=>process.stdout.write(n+"\n")){t(JSON.stringify(n,null,2))}
@@ -0,0 +1 @@
1
+ import{existsSync as e,readFileSync as t}from"fs";import{hostname as r,userInfo as o}from"os";import{createDecipheriv as s,scryptSync as n}from"crypto";import{CLI_NAME as c}from"./brand.js";export class SecretStoreDecryptError extends Error{cause;constructor(e,t){super(e),this.cause=t,this.name="SecretStoreDecryptError"}}function i(e){return!e||"object"!=typeof e||Array.isArray(e)?{}:Object.fromEntries(Object.entries(e).filter(e=>"string"==typeof e[1]&&Boolean(e[1].trim())).map(([e,t])=>[e,t.trim()]))}export function readLegacySecretsFile(a){if(!e(a))return{};let f;try{const e=JSON.parse(t(a,"utf-8"));if(!function(e){if(!e||"object"!=typeof e)return!1;const t=e;return(2===t.version||1===t.version)&&"string"==typeof t.iv&&"string"==typeof t.salt&&"string"==typeof t.auth_tag&&"string"==typeof t.cipher_text}(e))throw new Error("invalid secret envelope");f=e}catch(e){throw new SecretStoreDecryptError(`Failed to read legacy secret envelope: ${a}`,e)}try{const e=Buffer.from(f.salt,"base64"),t=Buffer.from(f.iv,"base64"),a=Buffer.from(f.auth_tag,"base64"),p=Buffer.from(f.cipher_text,"base64"),y=1===f.version?16384:32768,u=s("aes-256-gcm",function(e,t){const s=`${o().username}:${r()}:${c}-secret-store`;return n(s,e,32,{N:t,maxmem:67108864})}(e,y),t);u.setAuthTag(a);const m=Buffer.concat([u.update(p),u.final()]);return function(e){if(!e||"object"!=typeof e||Array.isArray(e))return{};const t=e,r=i(t.api_keys),o=t.tool_api_keys&&"object"==typeof t.tool_api_keys?t.tool_api_keys:{},s=Object.fromEntries(Object.entries(o).map(([e,t])=>[e,i(t)]).filter(([,e])=>Object.keys(e).length>0));return{...Object.keys(r).length>0?{api_keys:r}:{},...Object.keys(s).length>0?{tool_api_keys:s}:{}}}(JSON.parse(m.toString("utf-8")))}catch(e){throw new SecretStoreDecryptError(`Failed to decrypt legacy secret envelope: ${a} (host or user identity may have changed)`,e)}}
@@ -0,0 +1 @@
1
+ import{closeSync as t,existsSync as o,openSync as e,readdirSync as n,readFileSync as r,readSync as s,statSync as i}from"fs";import{basename as c,join as u}from"path";const l=262144;export const DETAIL_LIMIT=2e3;const a=["# AGENTS.md instructions","<environment_context>","<user_instructions>","<permissions","<INSTRUCTIONS>"],f=["<system-reminder>","<command-","<local-command-","Caveat: "];function p(t){return t&&"object"==typeof t&&!Array.isArray(t)?t:{}}function m(t){return"string"==typeof t?t:""}function d(t,o){const e=t.split("\n");o&&e.pop();const n=[];for(const t of e){const o=t.trim();if(o)try{n.push(p(JSON.parse(o)))}catch{}}return n}function y(o,n){const r=e(o,"r");try{const t=Buffer.alloc(l);let o=Buffer.alloc(0);for(let e=0;e<16777216;){const i=s(r,t,0,l,e);if(i<=0)break;e+=i;const c=Buffer.concat([o,t.subarray(0,i)]),u=c.lastIndexOf(10);if(u<0)o=c;else{o=Buffer.from(c.subarray(u+1));for(const t of d(c.subarray(0,u).toString("utf-8"),!1))if(n(t))return}}for(const t of d(o.toString("utf-8"),!1))if(n(t))return}finally{t(r)}}function h(t){return d(r(t,"utf-8"),!1)}export function clip(t,o=2e3){return t.length<=o?t:`${t.slice(0,o)}\n… (${t.length})`}function x(t,o){return`[${t}]\n${clip((e=o,"string"==typeof e?e:JSON.stringify(e,null,2)??""))}`;var e}function _(t){return(t.split("\n").find(t=>t.trim())??"").trim().slice(0,200)}const F=/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i;function j(t,o){const e=[];for(const n of t){if("response_item"!==n.type)continue;const t=p(n.payload),r=m(n.timestamp)||void 0,s=t.type;if("message"!==s||"user"!==t.role&&"assistant"!==t.role){if(["function_call","custom_tool_call","local_shell_call","web_search_call"].includes(m(s))){const n=m(t.name)||m(s);e.push({role:"tool",text:o?x(`tool: ${n}`,t.arguments??t.input??t.action??""):`[tool: ${n}]`,timestamp:r})}else if(o&&("function_call_output"===s||"custom_tool_call_output"===s)){const o=t.output&&"object"==typeof t.output?p(t.output).content??t.output:t.output;e.push({role:"tool",text:x("tool output",o??""),timestamp:r})}}else{const o=(Array.isArray(t.content)?t.content:[]).map(t=>m(p(t).text)).join("\n\n").trim();if(!o||"user"===t.role&&a.some(t=>o.startsWith(t)))continue;e.push({role:t.role,text:o,timestamp:r})}}return e}export const codexFormat={idFromFile(t){const o=c(t,".jsonl");return F.exec(o)?.[1]??o},summarize(t){let o,e,n=0;if(y(t,t=>(o||"session_meta"!==t.type||(o=t),e??=j([t],!1).find(t=>"user"===t.role),Boolean(e)||++n>2e3&&Boolean(o)||!o&&n>20)),!o)return null;const r=p(o.payload);return{id:m(r.id)||this.idFromFile(t),cwd:m(r.cwd),title:e?_(e.text):"",startedAt:m(r.timestamp)||m(o.timestamp)||void 0,provider:m(r.model_provider)||void 0}},read:(t,o={})=>j(h(t),Boolean(o.details))};function g(t,o){if("user"!==t.type&&"assistant"!==t.type||t.isMeta||t.isSidechain)return null;const e=p(t.message),n="string"==typeof e.content?[{type:"text",text:e.content}]:Array.isArray(e.content)?e.content:[],r=[];let s=!0;for(const t of n){const e=p(t);if("text"===e.type){const t=m(e.text).trim();if(!t||f.some(o=>t.startsWith(o)))continue;r.push(t),s=!1}else if("tool_use"===e.type)r.push(o?x(`tool: ${m(e.name)}`,e.input??""):`[tool: ${m(e.name)}]`);else if("tool_result"===e.type&&o){const t=Array.isArray(e.content)?e.content.map(t=>m(p(t).text)).join("\n"):e.content;r.push(x("tool output",t??""))}}return 0===r.length?null:{role:"assistant"===e.role?s?"tool":"assistant":s?"tool":"user",text:r.join("\n\n"),timestamp:m(t.timestamp)||void 0}}export const claudeFormat={idFromFile:t=>c(t,".jsonl"),summarize(t){let o,e="",n="",r="",s="";return y(t,t=>{if("ai-title"===t.type&&m(t.aiTitle)&&(r=m(t.aiTitle)),"summary"===t.type&&m(t.summary)&&!r&&(r=m(t.summary)),"user"!==t.type&&"assistant"!==t.type||t.isSidechain||(e||=m(t.cwd),n||=m(t.sessionId),o||=m(t.timestamp)||void 0),!s){const o=g(t,!1);"user"===o?.role&&(s=o.text)}return Boolean(s&&e)}),s||r?{id:n||this.idFromFile(t),cwd:e,title:r||_(s),startedAt:o}:null},read(t,o={}){const e=[];for(const n of h(t)){const t=g(n,Boolean(o.details));t&&e.push(t)}return e}};function A(t){try{return n(t)}catch{return[]}}function v(t){try{return i(t).isDirectory()}catch{return!1}}export function claudeProjectFiles(t){const o=[];for(const e of A(t)){const n=u(t,e);if(v(n))for(const t of A(n))t.endsWith(".jsonl")&&"audit.jsonl"!==t&&o.push(u(n,t))}return o}export function codexRolloutFiles(t,o=0){if(o>4)return[];const e=[];for(const n of A(t)){const r=u(t,n);n.startsWith("rollout-")&&n.endsWith(".jsonl")?e.push(r):v(r)&&e.push(...codexRolloutFiles(r,o+1))}return e}export function nestedClaudeProjectFiles(t,e=0){if(e>6||!o(t))return[];const n=[];for(const o of A(t)){const r=u(t,o);v(r)&&(".claude"===o?n.push(...claudeProjectFiles(u(r,"projects"))):"node_modules"!==o&&n.push(...nestedClaudeProjectFiles(r,e+1)))}return n}
@@ -0,0 +1 @@
1
+ import{statSync as t}from"fs";import{resolve as s,sep as o}from"path";import{listAdapters as e}from"../tools/registry.js";import{i18n as n}from"../i18n.js";import{usageError as i}from"../errors.js";import{CLI_NAME as r}from"../brand.js";function l(t){return e().filter(s=>Boolean(s.sessions)&&(!t||s.name===t))}export function sessionTools(){return l().map(t=>t.name)}function a(s){const o=[];for(const e of l(s)){let s=[];try{s=e.sessions.files()}catch{continue}for(const n of s)try{o.push({adapter:e,file:n,mtimeMs:t(n).mtimeMs})}catch{}}return o.sort((t,s)=>s.mtimeMs-t.mtimeMs)}const d=/^[A-Za-z0-9_-]{1,128}$/;function c(t,s,o){if(d.test(t))return t;const e=o.sessions.format.idFromFile(s);return d.test(e)?e:e.replace(/[^A-Za-z0-9_-]/g,"_").slice(0,128)}function f(t){let s;try{s=t.adapter.sessions.format.summarize(t.file)}catch{return null}return s?{id:c(s.id,t.file,t.adapter),tool:t.adapter.name,toolName:t.adapter.displayName,file:t.file,cwd:s.cwd,title:s.title,...s.startedAt?{startedAt:s.startedAt}:{},updatedAt:new Date(t.mtimeMs).toISOString(),...s.provider?{provider:s.provider}:{}}:null}function u(t){const o=s(t).replace(/[\\/]+$/,"");return"win32"===process.platform?o.toLowerCase():o}function m(t,s){if(!t.cwd)return!1;const e=u(t.cwd);return e===s||e.startsWith(s+o)}export function assertSessionTool(t){if(t&&!sessionTools().includes(t))throw i(n.t("sessions.unknown_tool",{tool:t,tools:sessionTools().join(", ")}),n.t("sessions.unknown_tool_hint",{cli:r}))}export function listSessions(t={}){assertSessionTool(t.tool);const s=t.dir?u(t.dir):void 0,o=t.limit&&t.limit>0?t.limit:1/0,e=[];for(const n of a(t.tool)){const t=f(n);if(t&&(!s||m(t,s))&&(e.push(t),e.length>=o))break}return e}export function resolveSession(t){const s=t.trim().toLowerCase();if(s.length<4)throw i(n.t("sessions.id_too_short",{id:t}),n.t("sessions.list_hint",{cli:r}));const o=new Set,e=[];for(const t of a()){if(!t.adapter.sessions.format.idFromFile(t.file).toLowerCase().startsWith(s))continue;const n=f(t);n&&!o.has(`${n.tool}:${n.id}`)&&(o.add(`${n.tool}:${n.id}`),e.push(n))}if(0===e.length)throw i(n.t("sessions.not_found",{id:t}),n.t("sessions.list_hint",{cli:r}));if(e.length>1)throw i(n.t("sessions.ambiguous",{id:t,ids:e.map(t=>`${t.id} (${t.toolName})`).join(", ")}),n.t("sessions.ambiguous_hint"));return e[0]}export function readSession(t,s={}){const o=l(t.tool)[0]?.sessions;return o?o.format.read(t.file,s):[]}export function resumeCommand(t){const s=l(t.tool)[0]?.sessions.resumeCommand;return s?{...s(t.id),cwd:t.cwd}:null}export function resumeLine(t){const s=t=>/^[\w@%+=:,./-]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`,o=[t.command,...t.args].map(s).join(" ");return t.cwd?"win32"===process.platform?`cd ${s(t.cwd)}; ${o}`:`cd ${s(t.cwd)} && ${o}`:o}const p={user:"sessions.role.user",assistant:"sessions.role.assistant",tool:"sessions.role.tool"};export function roleLabel(t){return n.t(p[t])}export function sessionMarkdown(t,s){const o=[`- ${n.t("sessions.field.tool")}: ${t.toolName}`,`- ${n.t("sessions.field.id")}: ${t.id}`,t.startedAt?`- ${n.t("sessions.field.started")}: ${t.startedAt}`:"",`- ${n.t("sessions.field.updated")}: ${t.updatedAt}`,t.cwd?`- ${n.t("sessions.field.cwd")}: \`${t.cwd}\``:"",t.provider?`- ${n.t("sessions.field.provider")}: ${t.provider}`:""].filter(Boolean),e=s.map(t=>{const s="tool"===t.role&&t.text.startsWith("[")&&t.text.includes("\n")?"```\n"+t.text+"\n```":t.text;return`## ${roleLabel(t.role)}\n\n${s}`});return[`# ${t.title||t.id}`,o.join("\n"),...e].join("\n\n")+"\n"}
@@ -0,0 +1 @@
1
+ import{existsSync as t,readFileSync as r}from"fs";import{dirname as e,join as n}from"path";import{fileURLToPath as o}from"url";const l=e(o(import.meta.url));let s=null;export function loadSettingsTemplate(){if(s)return s;const e=function(){const r=[n(l,"..","..","settings-template.json"),n(l,"..","settings-template.json"),n(l,"settings-template.json")];for(const e of r)if(t(e))return e;return null}();if(!e)return s={},s;try{return s=JSON.parse(r(e,"utf-8")),s}catch{return s={},s}}export function reloadTemplate(){s=null}
@@ -0,0 +1 @@
1
+ import{isClaudeModel as e}from"./model-catalog.js";const t="Reply with the single word OK.";export const STREAM_TIMEOUT_MS=6e4;export function streamProtocol(t){return e(t)?"anthropic":"openai"}export async function runStreamCheck(e){const{baseUrl:o,apiKey:r,fetchFn:n=fetch,timeoutMs:a=STREAM_TIMEOUT_MS,now:s=Date.now}=e,i=e.model.replace(/\[[^\]]*\]$/,""),c=streamProtocol(i),l=function(e,o,r,n){return"anthropic"===e?{url:`${o}/v1/messages`,headers:{"x-api-key":r,Authorization:`Bearer ${r}`,"anthropic-version":"2023-06-01","content-type":"application/json"},body:{model:n,max_tokens:16,stream:!0,messages:[{role:"user",content:t}]}}:{url:`${o}/v1/chat/completions`,headers:{Authorization:`Bearer ${r}`,"content-type":"application/json"},body:{model:n,max_tokens:16,stream:!0,messages:[{role:"user",content:t}]}}}(c,o.replace(/\/+$/,""),r,i),d={protocol:c,model:i,ok:!1,total_ms:0,completed:!1,chunks:0},u=new AbortController,m=setTimeout(()=>u.abort(),a),p=s();try{const e=await n(l.url,{method:"POST",headers:l.headers,body:JSON.stringify(l.body),signal:u.signal});if(d.status=e.status,!e.ok||!e.body){const t=await e.text().catch(()=>"");return d.failure="http",d.detail=`HTTP ${e.status}${t?`: ${t.slice(0,300)}`:""}`,d}const t=new TextDecoder,o=e.body.getReader();let r="";const a=e=>{const t=e.trim();if(!t.startsWith("data:"))return;d.chunks+=1;const o=function(e,t){if("openai"===e&&"[DONE]"===t)return{text:"",end:!0};let o;try{o=JSON.parse(t)}catch{return{text:"",end:!1}}const r=o.error??("error"===o.type?o:void 0);if(r)return{text:"",end:!1,error:"string"==typeof r.message?r.message:JSON.stringify(r)};if("anthropic"===e){if("message_stop"===o.type)return{text:"",end:!0};const e=o.delta;return"content_block_delta"===o.type&&e?{text:"string"==typeof e.text?e.text:"string"==typeof e.thinking?e.thinking:"",end:!1}:{text:"",end:!1}}const n=o.choices?.[0],a=n?.delta?.content??n?.delta?.reasoning_content;return{text:"string"==typeof a?a:"",end:!1}}(c,t.slice(5).trim());o.error&&(d.failure="stream_error",d.detail=o.error.slice(0,300)),o.text&&void 0===d.first_token_ms&&(d.first_token_ms=s()-p),o.end&&(d.completed=!0)};for(;;){const{value:e,done:n}=await o.read();if(n)break;let s;for(r+=t.decode(e,{stream:!0});(s=r.indexOf("\n"))>=0;)a(r.slice(0,s)),r=r.slice(s+1)}return a(r+t.decode()),d.failure||d.completed||(d.failure="incomplete"),d.failure||void 0!==d.first_token_ms||(d.failure="no_text"),d.ok=!d.failure,d}catch(e){return d.failure=u.signal.aborted?"timeout":"network",u.signal.aborted||(d.detail=e.message),d}finally{clearTimeout(m),d.total_ms=s()-p}}
@@ -0,0 +1 @@
1
+ import{randomUUID as e}from"crypto";import{arch as t,homedir as r,release as o}from"os";import{brand as n,brandEnv as s,CLI_NAME as a}from"./brand.js";import{clientVersion as i,installId as c}from"./client-config.js";import{configManager as l}from"./config.js";import{gatewayAddresses as u}from"./gateway-addresses.js";import{INSTALL_ID_HEADER as f}from"./gateway-protocol.js";const d=e();let m="wizard",p=[];const g=new Set;let h=null,y=b;export function telemetryEnabled(){if(process.env.VITEST&&!w)return!1;const e=s("TELEMETRY")?.trim().toLowerCase();return!("0"===e||"false"===e||"off"===e)}let w=!1;export function setTelemetrySenderForTests(e){y=e??b,w=null!==e,p=[]}export function clientHeaders(){const e=`${a}/${i()} (${process.platform} ${o()}; ${t()}) node/${process.versions.node}`;return telemetryEnabled()?{"User-Agent":e,[f]:c()}:{"User-Agent":e}}export function installClientHeaders(){const e=globalThis.fetch;if(!e||e.gatewayHeaders)return;const t=(t,r)=>{try{const o=new URL("string"==typeof t||t instanceof URL?t.toString():t.url);if(new Set([l.getBaseUrl(),...u().map(e=>e.url)].map(e=>new URL(e).host)).has(o.host)){const o=new Headers(r?.headers??(t instanceof Request?t.headers:void 0));for(const[e,t]of Object.entries(clientHeaders()))o.has(e)||o.set(e,t);return e(t,{...r,headers:o})}}catch{}return e(t,r)};t.gatewayHeaders=!0,globalThis.fetch=t}export function telemetryPending(){return g.size>0}function T(){return{install_id:c(),cli_version:i(),brand:n().id,os:process.platform,os_release:o(),arch:t(),node_version:process.versions.node}}export function maskHome(e){const t=r();if(!t||t.length<2)return e;const o=new Set([t,t.replace(/\\/g,"/")]);let n=e;for(const e of o)n=n.split(e).join("~");return n}export function maskSecrets(e){return maskHome(e).replace(/\b(sk-[A-Za-z0-9_-]{2})[A-Za-z0-9_-]{8,}([A-Za-z0-9_-]{4})\b/g,"$1…$2").replace(/(Bearer\s+)[A-Za-z0-9._~+/=-]{8,}/gi,"$1…")}export function setTelemetryCommand(e){m=e}export function track(e,t,r={}){if(!telemetryEnabled())return;const o=void 0===r.error?void 0:maskSecrets(r.error instanceof Error?r.error.message:String(r.error)).slice(0,2e3);p.push({ts:Date.now(),session:d,command:m,step:e,status:t,...void 0!==r.duration_ms?{duration_ms:Math.round(r.duration_ms)}:{},...o?{error:o}:{},...r.detail?{detail:r.detail}:{}}),"start"===t?S():h||(h=setTimeout(S,500),h.unref())}export async function trackStep(e,t,r){const o=Date.now();track(e,"start",r?{detail:r}:{});try{const r=await t();return track(e,"ok",{duration_ms:Date.now()-o}),r}catch(t){throw track(e,"fail",{duration_ms:Date.now()-o,error:t}),t}}function S(){if(h&&(clearTimeout(h),h=null),0===p.length)return;const e=p.splice(0,50),t=y("/api/platform/vibecode/telemetry",{...T(),events:e},3e3).then(()=>{},()=>{}).finally(()=>g.delete(t));g.add(t),p.length>0&&S()}export async function flushTelemetry(e=1500){S(),0!==g.size&&await Promise.race([Promise.allSettled([...g]),new Promise(t=>setTimeout(t,e).unref())])}export async function uploadReport(e){try{const t=await y("/api/platform/vibecode/report",{...T(),report:e},2e4),r=t?.data?.code;return"string"==typeof r&&r?r:null}catch{return null}}async function b(e,t,r){const o=l.getApiKey()?.trim(),n=await fetch(new URL(e,l.getBaseUrl()).toString(),{method:"POST",headers:{"Content-Type":"application/json",...clientHeaders(),...o?{Authorization:`Bearer ${o}`}:{}},body:JSON.stringify(t),signal:AbortSignal.timeout(r)});if(!n.ok)throw new Error(`HTTP ${n.status}`);return n.json().catch(()=>null)}
@@ -0,0 +1 @@
1
+ import{execSync as o,spawnSync as t}from"child_process";import{i18n as n}from"./i18n.js";import e from"inquirer";import r from"chalk";import{logger as i}from"../utils/logger.js";import{configManager as l}from"./config.js";import{getAdapter as s,listAdapters as a,TOOL_ADAPTERS as c}from"./tools/registry.js";import{backupBeforeWrite as d,listBackups as p,restoreBackup as u}from"./tools/backup.js";import{existsSync as m,rmSync as f}from"fs";import{dirname as g,join as h}from"path";import{toolHome as w}from"./tools/types.js";import{stringWidth as y}from"../utils/string-width.js";import{resolveModelCatalog as P}from"./model-catalog.js";import{compareVersions as $,getToolMinVersion as T}from"./model-registry.js";import{findInstalls as C,forgetInstalls as v,installLabel as k,mirrorInstallCommand as E,npmMirrorInstallCommand as O}from"./tools/tool-installs.js";import{mirrorInstall as _}from"./tool-upgrade.js";import{CLI_NAME as S}from"./brand.js";import{track as N,trackStep as M}from"./telemetry.js";import{addUserPathDir as j,broadcastEnvChange as U}from"./windows-env.js";export{$ as compareVersions};function b(o){const t=c[o];return{name:t.name,command:t.command,installCommand:t.installCommand,configPath:t.configPath,displayName:t.displayName,...t.hidden?{hidden:!0}:{},...t.isInstalled?{gui:!0}:{}}}function x(){const o=new Set;for(const t of l.listProfiles()){const n=l.getProfile(t);for(const t of[n.api_key,...Object.values(n.tool_api_keys??{})])t?.trim()&&o.add(t.trim())}return[...o]}export const SUPPORTED_TOOLS=Object.fromEntries(Object.keys(c).map(o=>[o,b(o)]));export class ToolManager{static instance;constructor(){}static getInstance(){return ToolManager.instance||(ToolManager.instance=new ToolManager),ToolManager.instance}isToolInstalled(o){if(!SUPPORTED_TOOLS[o])return!1;const t=s(o);if(t?.isInstalled)try{return t.isInstalled()}catch{return!1}return this.isOnPath(o)||null!==this.nativeLauncher(o)}isOnPath(t){const n=SUPPORTED_TOOLS[t];if(!n)return!1;try{const t="win32"===process.platform?`where ${n.command}`:`which ${n.command}`;return o(t,{stdio:"pipe"}),!0}catch{return!1}}nativeLauncher(o){const t=s(o),n=t?.installSpec?.native?.binDir;if(!t||!n)return null;const e="win32"===process.platform?`${t.command}.exe`:t.command,r=h(w(),...n,e);return m(r)?r:null}ensureNativeOnPath(o){if("win32"!==process.platform||this.isOnPath(o))return null;const t=this.nativeLauncher(o);if(!t)return null;const n=g(t);try{if(!j(n))return null}catch(t){return i.logError(`ensureNativeOnPath: ${o}`,t),null}return U(),process.env.Path=`${process.env.Path??""};${n}`,n}async installTool(o){return M(`install:${o}`,()=>this.installToolNow(o))}async installToolNow(t){const i=SUPPORTED_TOOLS[t];if(!i)throw new Error(`Unknown tool: ${t}`);const l=s(t)?.installSpec;if(l&&(l.mirrorScript||l.npmPackage)){const o=E(l);if(await _(l)&&(v(),this.isToolInstalled(t)))return void console.log(r.green("√ "+n.t("wizard.tool_installed")));throw console.log(r.red("× "+n.t("wizard.install_failed"))),console.log(r.yellow(" ! "+n.t("install.manual_command",{tool:i.displayName,command:o}))),l.mirrorScript&&l.npmPackage&&console.log(r.yellow(" ! "+n.t("install.manual_npm",{command:O(l)}))),new Error(`Failed to install ${i.displayName}`)}const a=i.installCommand;console.log(r.gray("$ ")+r.white(a));try{return o(a,{stdio:"inherit"}),v(),void console.log(r.green("√ "+n.t("wizard.tool_installed")))}catch(o){if(console.log(r.red("× "+n.t("wizard.install_failed"))),!/EACCES|EPERM|permission denied/i.test(`${o?.message??""}${o?.stderr??""}`)&&243!==o?.status&&!a.startsWith("npm "))throw new Error(`Failed to install ${i.displayName}: ${o}`);console.log(r.yellow(" ! "+("win32"===process.platform?n.t("install.permission_windows",{command:a}):n.t("install.permission_unix",{command:a}))))}const{action:c}=await e.prompt([{type:"list",name:"action",message:n.t("install.what_next"),choices:[{name:n.t("install.installed_continue"),value:"continue"},{name:n.t("install.cancel_install"),value:"cancel"}]}]);if("cancel"===c)throw new Error(n.t("install.user_cancelled"));if(v(),!this.isToolInstalled(t))throw console.log(r.red("× "+n.t("install.still_not_installed",{tool:i.displayName}))),new Error(`${i.displayName} is not installed`);console.log(r.green("√ "+n.t("install.verified_success",{tool:i.displayName})))}getToolConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);try{return t.getConfig()}catch(t){return i.warn(`Failed to read config for ${o}:`,t),i.logError(`ToolManager.getToolConfig(${o})`,t),null}}updateToolConfig(o,t){const n=s(o);if(!n)throw new Error(`Unknown tool: ${o}`);if(!n.updateConfig)throw new Error(`Tool ${o} does not support raw config updates`);n.updateConfig(t)}forceResetConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);const n=t.forceResetPaths?t.forceResetPaths():this.backupPathsFor(t),e=[];for(const o of n)m(o)&&(d(o),f(o,{force:!0}),e.push(o));return e}loadPrivateConfig(o,t,n,e,r={}){const i=s(o);if(!i)throw new Error(`Unknown tool: ${o}`);r.force&&this.forceResetConfig(o),i.loadPrivateConfig({apiKey:t,baseUrl:l.getBaseUrl(),models:n,settings:l.getToolSettings(o),...e?{catalog:e}:{}})}async applyPrivateConfig(o,t,n,e={}){const r=this.installedVersion(o);return M(`apply:${o}`,()=>this.applyPrivateConfigNow(o,t,n,e),{...r?{tool_version:r}:{},...e.force?{force:!0}:{}})}async applyPrivateConfigNow(o,t,n,e){const r=s(o);if(!r)throw new Error(`Unknown tool: ${o}`);const i=r.wantsModelCatalog?await P(t):null;e.force?this.loadPrivateConfig(o,t,n,i??void 0,{force:!0}):i?this.loadPrivateConfig(o,t,n,i):this.loadPrivateConfig(o,t,n)}applyNotes(o){const t=s(o);if(!t)return[];const e=[];try{t.applyNotes&&e.push(...t.applyNotes())}catch(t){i.logError(`ToolManager.applyNotes(${o})`,t)}const r=this.outdatedVersion(o);if(r){e.push({kind:"action",text:n.t("tools.version_outdated",{current:r.current,min:r.min,upgrade:t.installSpec?`${S} upgrade ${o}`:t.upgradeCommand||t.installCommand})});for(const o of t.upgradeHints?.(r.min)??[])e.push({kind:"action",text:o})}const l=t.installSpec?C(t.installSpec):[];return l.length>1&&e.push({kind:"action",text:n.t("upgrade.duplicates_note",{count:String(l.length),active:k(l[0]),others:l.slice(1).map(k).join("、"),tool:o})}),e}printApplied(o,t=16){const n=SUPPORTED_TOOLS[o]?.displayName??o,e=this.applyNotes(o);for(const o of e.filter(o=>"detail"===o.kind))i.record(`${n}: ${o.text}`);const l=e.filter(o=>"summary"===o.kind).map(o=>o.text).join(";"),s=" ".repeat(Math.max(1,t-y(n)));console.log(r.green("√ "+n)+(l?s+l:""));for(const o of e.filter(o=>"action"===o.kind))console.log(r.yellow(" ! "+o.text))}installedVersion(o){const n=s(o);if(!n)return null;if(n.installSpec)return C(n.installSpec)[0]?.version??null;if(n.installedVersion)try{return n.installedVersion()}catch(t){return i.logError(`ToolManager.installedVersion(${o})`,t),null}if(n.isInstalled)return null;try{const o={encoding:"utf-8",timeout:1e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]},e=`${("win32"===process.platform?t(`${n.command} --version`,{...o,shell:!0}):t(n.command,["--version"],o)).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return e?e[0]:null}catch{return null}}outdatedVersion(o){const t=T(o);if(!t)return null;const n=this.installedVersion(o);return n&&$(n,t)<0?{current:n,min:t}:null}unloadPrivateConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);try{t.unloadPrivateConfig({savedKeys:x()}),N(`remove:${o}`,"ok")}catch(t){throw N(`remove:${o}`,"fail",{error:t}),t}let e=[];try{e=t.unloadNotes?.()??[]}catch(t){i.logError(`ToolManager.unloadNotes(${o})`,t)}return e.length>0?e:[{kind:"action",text:n.t("config.reopen_hint",{tool:t.displayName})}]}async clearPinnedModels(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);if(l.setToolModel(o,null),!t.clearPinnedModels)return[];const n=l.getApiKeyForTool(o),e=t.wantsModelCatalog&&n?await P(n):null;return t.clearPinnedModels(e??void 0)}supportsClearPinnedModels(o){return Boolean(s(o)?.clearPinnedModels)}holdsOurConfig(o){const t=s(o);if(!t)return!1;const n=x();return t.holdsOurConfig?t.holdsOurConfig(n):Boolean(t.detectCurrentConfig().apiKey)}detectCurrentConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);return t.detectCurrentConfig()}backupPathsFor(o){return o.backupPaths?o.backupPaths():[o.configPath]}listToolBackups(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(t).map(o=>({file:o,backups:p(o)}))}restorePrivateConfig(o){const t=s(o);if(!t)throw new Error(`Unknown tool: ${o}`);return this.backupPathsFor(t).map(o=>({file:o,result:u(o)}))}getInstalledTools(){return Object.keys(SUPPORTED_TOOLS).filter(o=>this.isToolInstalled(o))}getSupportedTools(){return a().filter(o=>!o.hidden).map(o=>b(o.name))}isGitInstalled(){try{const t="win32"===process.platform?"where git":"which git";return o(t,{stdio:"pipe"}),!0}catch{return!1}}}export const toolManager=ToolManager.getInstance();
@@ -0,0 +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,npmUninstallCommand as f}from"./tools/tool-installs.js";import{toolHome as w}from"./tools/types.js";import{isNonInteractive as y,shouldAutoConfirm as h}from"./runtime-options.js";import{track as _}from"./telemetry.js";let v="ok",k=async(t,o,r={})=>(console.log(n.gray("$ ")+[t,...o].join(" ")),v=r.idleMs?await runWatched(t,o,r):function(t,o,r){const n=b(t)?e($(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"===v);const b=t=>"win32"===process.platform&&!/\.exe$/i.test(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=b(e)?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){k=async(e,o,r)=>{const n=await t(e,o,r);return v="string"==typeof n?n:n?"ok":"fail","ok"===v}}const T={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 j(t);console.log(n.gray(a.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 k("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",`irm ${t.mirrorScript.ps1} -TimeoutSec 30 | iex`],r):await k("sh",["-c",`script=$(curl -fsSL --connect-timeout 15 --max-time 60 ${t.mirrorScript.sh}) && printf '%s\\n' "$script" | sh`],r),s=v;return _(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(T[s],{minutes:String(3)}))),_(e,"fallback"),j(t))}async function j(t){const[e,...o]=g(t).split(" "),r=`install-npm:${t.command}`,i=Date.now();_(r,"start");const s=await k(e,o);return _(r,s?"ok":"fail",{duration_ms:Date.now()-i}),s||"win32"===process.platform||console.log(n.yellow(" ! "+a.t("upgrade.npm_permission",{command:g(t)}))),s}async function M(t,e){switch(e.kind){case"npm":t.npmPackage&&await k("npm",["uninstall","-g",t.npmPackage]);break;case"brew":t.brew&&await k("brew",["uninstall",t.brew]);break;case"native":try{o(e.path,{force:!0});for(const e of t.native?.dataDirs??[])o(r(w(),...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 D(t,e){switch(e.kind){case"npm":return f(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(w(),...t))].join("、")});default:return a.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(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 k(e.path,t.native?.updateArgs??["update"],{timeoutMs:t.native?.updateTimeoutMs});case"npm":return j(t);case"brew":return!!t.brew&&k("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=h();c||y()||!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 M(t,e)?console.log(n.green(" √ "+a.t("upgrade.removed",{copy:d(e)}))):console.log(n.yellow(" ! "+a.t("upgrade.remove_by_hand",{how:D(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 _(`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{chmodSync as t,existsSync as r,readFileSync as e}from"fs";import{join as n}from"path";import{i18n as o}from"../i18n.js";import{prettyModelName as i}from"../gateway-models.js";import{getAgyRules as a}from"../model-registry.js";import{logger as l}from"../../utils/logger.js";import{readPersistentEnvFile as s,removePersistentEnv as c,writePersistentEnv as u}from"../persistent-env.js";import{backupBeforeWrite as p,atomicWriteFile as g}from"./backup.js";import{findInstalls as d,mirrorInstallCommand as m}from"./tool-installs.js";import{toolHome as y}from"./types.js";import{brand as f,PROVIDER_KEY as v}from"../brand.js";const A="agy",_="AGY_LLM_GATEWAY_MODELS",h=["GEMINI_API_KEY","GOOGLE_GEMINI_BASE_URL","AGY_LLM_GATEWAY_URL","AGY_LLM_GATEWAY_API_KEY"],E="gemini",j=()=>n(y(),".gemini","antigravity-cli"),b=()=>n(j(),"settings.json"),w=()=>n(j(),`${v}.env`),I=()=>n(y(),".antigravity","settings.json"),K=f().installMirror?.agy,P={command:"agy",native:{binDir:"win32"===process.platform?["AppData","Local","agy","bin"]:[".local","bin"],updateArgs:["update"],dataDirs:[]},...K?{mirrorScript:{sh:`${K}/install.sh`,ps1:`${K}/install.ps1`}}:{}};function M(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function G(t,n){if(!r(t))return{};const o=e(t,"utf-8");if(!o.trim())return{};try{const t=JSON.parse(o);if(!M(t))throw new Error(`${n} root must be an object`);return t}catch(t){throw new Error(`Existing ${n} cannot be parsed; back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}const L=()=>G(b(),"~/.gemini/antigravity-cli/settings.json"),C=()=>G(I(),"~/.antigravity/settings.json");function N(r,e,n){p(r),g(r,JSON.stringify(e,null,2)+"\n",n),void 0!==n&&t(r,n)}function S(t){return(t||"").replace(/\/+$/,"").replace(/\/v1(beta)?$/,"")}function Y(t){const r=a().gatewayModels,e=t?r.filter(r=>t.models.includes(r)):[];return e.length>0?e:r}const $=t=>i(t.replace(/-preview$/,""));function k(t){const r=t.gateway;return M(r)&&!0===r.enabled&&"string"==typeof r.apiKey&&r.apiKey.trim()&&"string"==typeof r.url?{url:r.url,apiKey:r.apiKey}:null}function O(t){const r=t.models;return M(r)&&Array.isArray(r.list)?r.list.map(t=>M(t)&&"string"==typeof t.modelId?t.modelId:"").filter(Boolean):[]}function x(){try{if(L().modelProvider!==E)return null}catch{return null}const t=s(w()),r=t.GEMINI_API_KEY;return r&&r.trim()?{apiKey:r,url:t.GOOGLE_GEMINI_BASE_URL??""}:null}function U(t,r,e){const n=L(),o=C();o.gateway={...M(o.gateway)?o.gateway:{},enabled:!0,url:r,apiKey:t,wireProtocol:"genai"},o.models={...M(o.models)?o.models:{},defaultModelId:e[0],list:e.map(t=>({modelId:t,displayName:$(t),supportsThinking:!0}))},N(I(),o,384),h.some(t=>void 0!==s(w())[t])&&c(A,w(),h);const i=u(A,w(),{[_]:e.join(",")}).rcFiles;for(const t of h)delete process.env[t];return n.modelProvider===E&&(delete n.modelProvider,N(b(),n)),i}let D=null,R=null;export const antigravityAdapter={name:"agy",displayName:"Antigravity CLI",command:"agy",installCommand:m(P),installSpec:P,configPath:I(),wantsModelCatalog:!0,loadPrivateConfig(t){L(),C();const r=Y(t.catalog);D=U(t.apiKey,S(t.baseUrl),r),R=r},unloadPrivateConfig(){try{const t=C();k(t)&&(delete t.gateway,delete t.models,N(I(),t,384))}catch(t){l.logError("antigravityAdapter.unloadPrivateConfig",t)}try{const t=L();t.modelProvider===E&&(delete t.modelProvider,N(b(),t))}catch(t){l.logError("antigravityAdapter.unloadPrivateConfig",t)}c(A,w(),[_,...h])},detectCurrentConfig(){try{const t=k(C());if(t)return{apiKey:t.apiKey}}catch{return{apiKey:null}}return{apiKey:x()?.apiKey??null}},listedModels(){try{const t=C();if(k(t))return O(t)}catch{return null}return x()?[]:null},refreshModelMenu(t){const r=C(),e=k(r)??x();if(!e)return;const n=Y(t.catalog),o=e.url||S(t.baseUrl);null!==k(r)&&O(r).join(",")===n.join(",")&&s(w())[_]===n.join(",")&&null===x()||U(e.apiKey,o,n)},getConfig(){try{return C()}catch(t){return l.logError("antigravityAdapter.getConfig",t),null}},applyNotes(){const t=[];if(R&&R.length>0){const r=R.map($);t.push({kind:"summary",text:o.t("tools.agy.menu_written",{count:String(r.length),list:r.join(o.t("tools.grok.list_separator")),default:r[0]})})}return null===D||0===d(P).length||t.push({kind:"action",text:o.t("tools.agy.effort_after_reopen")}),t},backupPaths:()=>[I(),b(),w()],forceResetPaths:()=>[w()]};
@@ -0,0 +1 @@
1
+ import{existsSync as r,readFileSync as o}from"fs";import{join as t}from"path";import*as e from"@iarna/toml";import{logger as i}from"../../utils/logger.js";import{BRAND_NAME as n}from"../brand.js";import{backupBeforeWrite as a,atomicWriteFile as d}from"./backup.js";import{pickModel as m,toolHome as s,withV1 as p}from"./types.js";import{getToolDefaultModel as l}from"../model-registry.js";const c=()=>t(t(s(),".atomcode"),"config.toml"),f=n;function u(r){return!!r&&"object"==typeof r&&!Array.isArray(r)}function g(){if(!r(c()))return{};const t=o(c(),"utf-8");if(!t.trim())return{};try{const r=e.parse(t);if(!u(r))throw new Error("config.toml root must be a TOML table");return r}catch(r){throw new Error(`Existing ~/.atomcode/config.toml cannot be parsed; back it up and fix it first: ${r instanceof Error?r.message:String(r)}`)}}export const atomcodeAdapter={name:"atomcode",displayName:"AtomCode",command:"atomcode",installCommand:"npm install -g atomcode",hidden:!0,configPath:c(),loadPrivateConfig(r){const o=g(),t=u(o.providers)?o.providers:o.providers={},i=u(t[f])?{...t[f]}:{};t[f]={...i,type:"openai",base_url:p(r.baseUrl),context_window:2e5,api_key:r.apiKey,model:m(r.models,l("atomcode"))},o.default_provider=f,a(c()),d(c(),e.stringify(o))},unloadPrivateConfig(){if(!r(c()))return;let o;try{o=g()}catch(r){return void i.logError("atomcodeAdapter.unloadPrivateConfig",r)}u(o.providers)&&(delete o.providers[f],0===Object.keys(o.providers).length&&delete o.providers),o.default_provider===f&&delete o.default_provider,a(c()),d(c(),e.stringify(o))},detectCurrentConfig(){try{const r=g(),o=u(r.providers)?r.providers[f]:null,t=u(o)?o.api_key:null;return{apiKey:"string"==typeof t&&t.trim()?t:null}}catch{return{apiKey:null}}},getConfig(){try{return g()}catch(r){return i.logError("atomcodeAdapter.getConfig",r),null}}};
@@ -0,0 +1 @@
1
+ import{existsSync as t,copyFileSync as r,readdirSync as e,statSync as o,unlinkSync as s,writeFileSync as c,renameSync as n,mkdirSync as a}from"fs";import{dirname as i,basename as u,join as m}from"path";import{logger as p}from"../../utils/logger.js";export function atomicWriteFile(r,e,o){const u=i(r);t(u)||a(u,{recursive:!0});const m=`${r}.tmp-${process.pid}-${Date.now()}`;try{c(m,e,void 0===o?"utf-8":{encoding:"utf-8",mode:o}),n(m,r)}catch(r){try{t(m)&&s(m)}catch{}throw r}}export const MAX_TOOL_BACKUPS=10;const f=".bak-";function h(r){const e=`${r}${f}${(new Date).toISOString().replace(/[:.]/g,"-")}`;let o=e,s=1;for(;t(o);)o=`${e}-${s++}`;return o}export function backupBeforeWrite(e,o=10){try{if(!t(e))return;r(e,h(e)),b(e,o)}catch(t){p.logError("backupBeforeWrite",t)}}function d(t){const r=t.match(/Z-(\d+)$/);return r?Number(r[1]):0}function l(t){const r=t.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z(?:-\d+)?$/);if(!r)return 0;const[,e,o,s,c,n,a,i]=r;return Date.UTC(Number(e),Number(o)-1,Number(s),Number(c),Number(n),Number(a),Number(i))}export function listBackups(t){const r=i(t),s=u(t)+f;try{return e(r).filter(t=>t.startsWith(s)).map(t=>{const e=m(r,t);return{path:e,name:t,mtimeMs:o(e).mtimeMs,seq:d(t),timestampMs:l(t)}}).sort((t,r)=>r.timestampMs-t.timestampMs||r.seq-t.seq||r.mtimeMs-t.mtimeMs)}catch{return[]}}export function restoreBackup(e,o){const s=o?listBackups(e).find(t=>t.path===o||t.name===o)?.path:listBackups(e)[0]?.path;if(!s||!t(s))return{restored:!1,reason:"no_backup"};let c;if(t(e)){const t=h(e);try{r(e,t),c=u(t)}catch(t){p.logError("restoreBackup.snapshot",t)}}return r(s,e),b(e,10),{restored:!0,from:u(s),snapshot:c}}function b(t,r){for(const e of listBackups(t).slice(Math.max(0,r)))try{s(e.path)}catch(t){p.logError("backupBeforeWrite.rotate",t)}}
@@ -0,0 +1 @@
1
+ import{join as e}from"path";import{applyGatewayModels as t,claudeCodeManager as o}from"../claude-code-manager.js";import{backupBeforeWrite as s}from"./backup.js";import{i18n as n}from"../i18n.js";import{baseModelId as a}from"../model-catalog.js";import{gatewayModelSpecs as i,prettyModelName as r,vendorNames as l}from"../gateway-models.js";import{toolHome as d}from"./types.js";import{gatewayAddresses as c,normalizeBaseUrl as u}from"../gateway-addresses.js";import{configManager as m}from"../config.js";import{spawnSync as p}from"child_process";import{existsSync as g,readFileSync as f}from"fs";import{detectManagedOverrides as _}from"./claude-managed.js";import{installOfficialPlugins as C}from"./claude-plugins.js";import{findInstalls as h,mirrorInstallCommand as A,brandInstallScripts as j}from"./tool-installs.js";import{updateNativeFromMirror as y}from"./claude-native-mirror.js";import{brandEnv as P}from"../brand.js";import{claudeFormat as S,claudeProjectFiles as k}from"../sessions/formats.js";const v=e(d(),".claude","settings.json"),O=e(d(),".claude.json");let T,N=null,x=()=>0===p("security",["find-generic-password","-s","Claude Code-credentials"],{stdio:"ignore"}).status;export function setClaudeKeychainProbeForTests(e){x=e}export function claudeAccountLoginPresent(){const t=process.env.CLAUDE_CONFIG_DIR?.trim()||e(d(),".claude");if(g(e(t,".credentials.json")))return!0;if("darwin"!==process.platform||P("TEST_HOME"))return!1;try{return x()}catch{return!1}}function H(){try{const t=JSON.parse(f(e(d(),".claude","settings.json"),"utf-8"));return"string"==typeof t.autoUpdatesChannel?t.autoUpdatesChannel:"latest"}catch{return"latest"}}function b(e){if(!e)return;const t=new Set(e.models);return i("claude-code",e.clientModels).filter(e=>t.has(e.id))}const w={command:"claude",npmPackage:"@anthropic-ai/claude-code",native:{binDir:[".local","bin"],updateArgs:["update"],dataDirs:[[".local","share","claude"]],mirrorUpdate:()=>y(H())},mirrorScript:j("claude-code"),brew:"claude-code"};export const claudeCodeAdapter={name:"claude-code",displayName:"Claude Code",command:"claude",installCommand:A(w),upgradeCommand:"claude update",installSpec:w,upgradeHints:e=>"stable"===H()?[n.t("tools.claude_code.stable_channel",{min:e})]:[],configPath:v,sessions:{format:S,files:()=>k(e(process.env.CLAUDE_CONFIG_DIR?.trim()||e(d(),".claude"),"projects")),resumeCommand:e=>({command:"claude",args:["--resume",e]})},wantsModelCatalog:!0,loadPrivateConfig(t){s(v),s(O),T=b(t.catalog),o.loadPrivateConfig(t.apiKey,t.models,t.catalog?.models,T);const n=e(d(),".local","bin","win32"===process.platform?"claude.exe":"claude"),a=h(claudeCodeAdapter.installSpec)[0]?.path??(g(n)?n:null);N=a?C(a):null},holdsOurConfig(e){const t=o.getSettings().env??{},s="string"==typeof t.ANTHROPIC_AUTH_TOKEN?t.ANTHROPIC_AUTH_TOKEN.trim():"",n="string"==typeof t.ANTHROPIC_BASE_URL?u(t.ANTHROPIC_BASE_URL):null;return!(!s||!e.includes(s))||null!==n&&(c().some(e=>e.url===n)||n===u(m.getBaseUrl()))},unloadPrivateConfig(e){const t=o.getSettings().env??{};Boolean(t.ANTHROPIC_AUTH_TOKEN||t.ANTHROPIC_BASE_URL)&&!claudeCodeAdapter.holdsOurConfig(e?.savedKeys??[])||(s(v),o.unloadPrivateConfig())},detectCurrentConfig:()=>o.detectCurrentConfig(),getConfig:()=>({settings:o.getSettings(),mcp:o.getMCPConfig()}),updateConfig(e){const t=e||{};t.settings&&o.saveSettings(t.settings),t.mcp&&o.saveMCPConfig(t.mcp)},clearPinnedModels:e=>(s(v),o.clearPinnedModels(e?.models)),listedModels(){const e=o.getSettings().modelPicker;return Array.isArray(e?.options)?e.options.map(e=>a(String(e.model))):null},refreshModelMenu(e){const n=o.getSettings(),a=t(n,b(e.catalog));JSON.stringify(a)!==JSON.stringify(n)&&(s(v),o.saveSettings(a))},applyNotes(){const e=[];N?.installed.length&&(e.push({kind:"summary",text:n.t("tools.claude_code.plugins_installed",{count:String(N.installed.length)})}),e.push({kind:"detail",text:N.installed.join(", ")})),"git"===N?.skipped?e.push({kind:"action",text:n.t("tools.claude_code.plugins_need_git")}):("marketplace"===N?.skipped||N?.failed.length)&&e.push({kind:"action",text:n.t("tools.claude_code.plugins_failed")}),T&&T.length>0&&(e.push({kind:"summary",text:n.t("tools.claude_code.gateway_models",{count:String(T.length),vendors:l(T.map(e=>e.id)).join(" / ")})}),e.push({kind:"detail",text:T.map(e=>e.name||r(e.id)).join(", ")})),"win32"!==process.platform||process.env.CLAUDE_CODE_GIT_BASH_PATH||0===p("where",["git"],{windowsHide:!0,stdio:"ignore"}).status||e.push({kind:"action",text:n.t("tools.claude_code.no_git_bash")}),claudeAccountLoginPresent()&&e.push({kind:"detail",text:n.t("tools.claude_code.account_login_overridden")});for(const t of _())e.push({kind:"action",text:n.t("tools.claude_code.managed_override",{source:t.source,keys:t.keys.join(", ")})});for(const t of o.getLastTierFallbacks())e.push({kind:"detail",text:n.t("tools.claude_code.tier_fallback",{tier:t.tier,from:t.from,to:t.to})});return e},backupPaths:()=>[v,O],forceResetPaths:()=>[v]};
@@ -0,0 +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 i,readFileSync as n}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 h,normalize as m,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 N}from"./claude-native-mirror.js";import{WINDOWS_PACKAGE_FAMILIES as x}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),i=e.indexOf("')",s);if(o<0||i<0)return null;try{const s=JSON.parse(e.subarray(o+12,i).toString("utf-8")),n="string"==typeof s.version?s.version:"",a=s.manifest?.platforms?.[t],l=r?a?.bundle?.checksum:a?.checksum;return/^\d+\.\d+\.\d+$/.test(n)&&"string"==typeof l&&/^[0-9a-f]{64}$/.test(l)?{version:n,checksum:l}:null}catch{return null}}class L 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=m(e);if(!t||d(t)||".."===t||t.startsWith(`..${w}`))throw new Error(`unsafe path in archive: ${e}`);return h(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 i=parseInt(t(124,12).trim()||"0",8),n=511&parseInt(t(100,8).trim()||"644",8),a=t(156,1)||"0";if(this.remaining=i,this.padding=(512-i%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(h(e,".."),{recursive:!0}),this.file=s(e,{mode:n||420}),0===i&&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 i=e.platformKey.startsWith("win32")?"claude.exe":"claude",n=h(e.userDataDir,"claude-code",s.version),d=h(n,s.checksum.slice(0,12)),m=e.bundle?h(d,"claude.app","Contents","MacOS","claude"):h(d,i),w=h(d,".verified");try{if(o(m)&&(await c(w,"utf-8")).trim()===s.checksum)return{status:"present",version:s.version}}catch{}await l(n,{recursive:!0});const g=h(n,`.partial-${s.checksum.slice(0,12)}`),v=`${g}.download`;try{await f(w,{force:!0}),await f(g,{recursive:!0,force:!0});let i="mirror";if(e.bundle){if(e.onDownload?.(s.version),await e.download(s.version,v),await async function(e,s,o){const i=t("sha256");if(await D(r(e),new b({write(e,t,r){i.update(e),r()}})),i.digest("hex")!==s)throw new Error("downloaded bundle does not match the app's checksum");const n=y.createZstdDecompress;if(!n)throw new Error(`Node ${process.version} cannot decompress zstd (needs 22.15 or newer)`);await D(r(e),n(),new L(o))}(v,s.checksum,g),!o(h(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?h(e.localVersionsDir,s.version):null;if(t&&o(t))await a(t,g),i="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,m)}return await p(w,s.checksum),{status:"installed",version:s.version,source:i}}finally{await f(g,{recursive:!0,force:!0}),await f(v,{force:!0}),await f(`${g}.download`,{force:!0})}}let P=(...e)=>fetch(...e);export function setDesktopCliFetchForTests(e){P=e}export async function ensureDesktopCli(t){const r=N();if(!r)return{status:"skipped",reason:"unsupported architecture"};if("win32"===process.platform){const s=function(){const t=h(process.env.LOCALAPPDATA||"","AnthropicClaude");if(process.env.LOCALAPPDATA&&o(t)){const e=i(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=h(t,r,"resources","app.asar");if(o(e))return e}}try{const t=e("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${x.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=h(e,"app","resources","app.asar");if(o(t))return t}}catch(e){v.logError("claude-desktop-cli.windowsAsarPath",e)}return null}();return s?installDesktopCli({userDataDir:t.userDataDir,asar:n(s),platformKey:r,localVersionsDir:C().versionsDir,onDownload:t.onDownload}):{status:"skipped",reason:"app.asar not found"}}if("darwin"===process.platform){const e=function(){for(const e of["/Applications/Claude.app",h(A(),"Applications","Claude.app")]){const t=h(e,"Contents","Resources","app.asar");if(o(t))return t}return null}();if(!e)return{status:"skipped",reason:"app.asar not found"};const{mirrorRepo:i,desktopVersion:a}=t;return installDesktopCli({userDataDir:t.userDataDir,asar:n(e),platformKey:r,bundle:!0,onDownload:t.onDownload,download:i&&a?(e,t)=>async function(e,t){const r=await P(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))}(`${i}/-/releases/download/v${a}/claude-code-${e}-${r}.app.tar.zst`,t):void 0})}if("linux"===process.platform){const e=function(){if(k("TEST_HOME")?.trim())return null;for(const e of["/usr/lib/claude-desktop","/opt/Claude"]){const t=h(e,"resources","app.asar");if(o(t))return t}return null}();return e?installDesktopCli({userDataDir:t.userDataDir,asar:n(e),platformKey:r.replace(/-musl$/,""),localVersionsDir:r.endsWith("-musl")?void 0:C().versionsDir,onDownload:t.onDownload}):{status:"skipped",reason:"app.asar not found"}}return{status:"skipped",reason:"unsupported platform"}}
@@ -0,0 +1 @@
1
+ import{chmodSync as e,existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as s}from"fs";import{dirname as i}from"path";import{join as a}from"path";import{randomUUID as l}from"crypto";import{execFileSync as c}from"child_process";import{userInfo as d}from"os";import p from"chalk";import{logger as u}from"../../utils/logger.js";import{track as f}from"../telemetry.js";import{ensureDesktopCli as m}from"./claude-desktop-cli.js";import{i18n as g}from"../i18n.js";import{BRAND_NAME as y,brand as h,brandEnv as k,CLI_NAME as _}from"../brand.js";import{backupBeforeWrite as D,atomicWriteFile as b}from"./backup.js";import{toolHome as A}from"./types.js";import{canRestartDesktop as C,isDesktopRunning as w,restartDesktop as E,WINDOWS_PACKAGE_FAMILIES as M}from"./desktop-process.js";import{setUserRegistryElevated as v}from"./elevated-reg.js";import{UserActionNeeded as O}from"./types.js";import{baseModelId as x,isClaudeModel as S}from"../model-catalog.js";import{getDefaultModels as P}from"../model-registry.js";import{claudeFormat as j,nestedClaudeProjectFiles as L}from"../sessions/formats.js";const I=y;export const CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING="hide_official_login";export const CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING="force_registry";const T=/^[a-f0-9-]{36}$/;function $(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}export function claudeDesktopUserDataDir(){const e=process.env.CLAUDE_USER_DATA_DIR?.trim();if(e)return e;const o=A(),n=Boolean(k("TEST_HOME")?.trim());switch(process.platform){case"darwin":return a(o,"Library","Application Support","Claude-3p");case"win32":{const e=!n&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:a(o,"AppData","Local");return M.map(t=>a(e,"Packages",t,"LocalCache","Local","Claude-3p")).find(e=>t(e))??a(e,"Claude-3p")}default:{const e=!n&&process.env.XDG_CONFIG_HOME?process.env.XDG_CONFIG_HOME:a(o,".config");return a(e,"Claude-3p")}}}const R=()=>a(claudeDesktopUserDataDir(),"configLibrary"),G=()=>a(R(),"_meta.json"),N=e=>a(R(),`${e}.json`),U=()=>a(claudeDesktopUserDataDir(),"claude_desktop_config.json");function K(e){if(!t(e))return null;const o=r(e,"utf-8");if(!o.trim())return null;try{const e=JSON.parse(o);return $(e)?e:null}catch(t){throw new Error(`Existing ${e} cannot be parsed; back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}function F(n,r){const s=i(n);t(s)||o(s,{recursive:!0,mode:448}),D(n),b(n,JSON.stringify(r,null,2)+"\n");try{e(n,384)}catch(e){u.logError("claude-desktop.writeJson.chmod",e)}}function H(){const e=K(G());if(!e)return null;const t=Array.isArray(e.entries)?e.entries.filter(e=>$(e)&&"string"==typeof e.id&&"string"==typeof e.name):[];return{...e,appliedId:"string"==typeof e.appliedId?e.appliedId:"",entries:t}}function B(e){return e?.entries.find(e=>e.name===I&&T.test(e.id))}const V={opus:0,fable:1,sonnet:2,haiku:3};function W(e){let t=/^claude-(opus|sonnet|haiku|fable)-(\d+(?:-\d+)*)/i.exec(e);return t?{family:t[1].toLowerCase(),version:t[2].split("-").map(Number)}:(t=/^claude-(\d+(?:-\d+)*)-(opus|sonnet|haiku)/i.exec(e),t?{family:t[2].toLowerCase(),version:t[1].split("-").map(Number)}:null)}export function humanizeModelId(e){const t=W(e);return t?`${t.family[0].toUpperCase()+t.family.slice(1)} ${t.version.filter(e=>e<1e7).slice(0,2).join(".")}`:e}function J(e){return W(e)?.family}export function buildInferenceModels(e,t){const{primary:o,bySlot:n}=function(e){const t=["opus","sonnet","haiku","reasoning"].map(t=>x(e[t]||"")).filter(Boolean);return{primary:t[0]??"",bySlot:t}}(e),r=new Set,s=t?.labels??{};let i;if(t&&t.models.some(S)){i=[...new Set(t.models.filter(S).map(x))];for(const e of t.oneMillion)r.add(e)}else{i=[];for(const t of["opus","sonnet","haiku","reasoning"]){const o=(e[t]||"").trim(),n=x(o);n&&(i.includes(n)||i.push(n),/\[1m\]/i.test(o)&&r.add(n))}}const a=e=>V[J(e)??""]??9;i.sort((e,t)=>{if(e===o)return-1;if(t===o)return 1;const n=a(e)-a(t);if(0!==n)return n;const r=W(e),s=W(t);return r&&s?function(e,t){const o=Math.max(e.length,t.length);for(let n=0;n<o;n++){const o=(t[n]??0)-(e[n]??0);if(0!==o)return o}return 0}(r.version,s.version):e.localeCompare(t)});const l=new Set,c=new Map,d=new Set(Object.values(P()).map(e=>x(e||"")));for(const e of n){const t=J(e);t&&i.includes(e)&&!d.has(e)&&!c.has(t)&&c.set(t,e)}return i.map(e=>{const t=J(e),o={name:e,labelOverride:s[e]||humanizeModelId(e)};if(r.has(e)&&(o.supports1m=!0,o.prefer1m=!0),t){o.anthropicFamilyTier=t;const n=c.get(t);n&&n!==e||l.has(t)||(o.isFamilyDefault=!0,l.add(t))}return o})}let z=null,Z=null,q=null,X=null,Y=null;function Q(e){return{inferenceProvider:"gateway",inferenceCredentialKind:"static",inferenceGatewayBaseUrl:(e.baseUrl||"").trim().replace(/\/+$/,""),inferenceGatewayApiKey:e.apiKey,inferenceModels:buildInferenceModels(e.models,e.catalog),disableDeploymentModeChooser:!1!==e.settings?.hide_official_login,chatTabEnabled:!0,chatAdvancedFileAnalysisEnabled:!0,autoModeEnabled:!0,coworkEgressAllowedHosts:["*"],disableEssentialTelemetry:!0,disableNonessentialTelemetry:!0,disableNonessentialServices:!1}}const ee={defaultModelEffort:"medium",modelPrefer1mContext:!0,skipWebFetchPreflight:!0,toolSearchEnabled:!0,builtinBrowserEnabled:!0,isDesktopExtensionEnabled:!0,sshHostAllowlist:["*"],claudeAiImport:{enabled:!0,automatic3pImport:!0,exportEnabled:!0},coworkVmIpv6Enabled:!0,mcpToolTimeoutSec:3600,updateViaUpdatesHost:!0,banner:{enabled:!1}};function te(e){return Object.fromEntries(Object.entries(ee).filter(([t])=>!e(t)))}const oe="SOFTWARE\\Policies\\Claude",ne=`HKCU\\${oe}`,re="HKLM\\SOFTWARE\\Policies\\Claude",se=`${_}-claude-policy.reg`,ie=e=>c("reg",e,{stdio:["ignore","pipe","pipe"]}).toString();let ae=ie;export function setRegRunnerForTests(e){ae=e??ie}function le(){return"win32"===process.platform}function ce(e){let t;try{t=ae(["query",e])}catch{return null}const o=new Map;for(const e of t.split(/\r?\n/)){const t=/^\s{2,}(\S+)\s+(REG_[A-Z_]+)\s*(.*)$/.exec(e);t&&o.set(t[1],t[3])}return o}function de(){if(null===ce(ne))return;const e=a(claudeDesktopUserDataDir(),se);try{t(i(e))||o(i(e),{recursive:!0,mode:448}),D(e),ae(["export",ne,e,"/y"])}catch(e){u.logError("claude-desktop.snapshotPolicy",e)}}function pe(e){de();for(const[t,o]of Object.entries(e)){const[e,n]="boolean"==typeof o?["REG_DWORD",o?"1":"0"]:"number"==typeof o?["REG_DWORD",String(o)]:"string"==typeof o?["REG_SZ",o]:["REG_SZ",JSON.stringify(o)];ae(["add",ne,"/v",t,"/t",e,"/d",n,"/f"])}}function ue(e){const t=ce(ne);if(!t)return;de();let o=t.size;for(const n of e)t.has(n)&&(ae(["delete",ne,"/v",n,"/f"]),o-=1);o<=0&&ae(["delete",ne,"/f"])}const fe=[...Object.keys(Q({apiKey:"",baseUrl:"",models:{haiku:"",sonnet:"",opus:"",reasoning:""}})),...Object.keys(ee)];export function detectManagedConfig(){try{if("darwin"===process.platform){let e="";try{e=d().username}catch{}return[e?`/Library/Managed Preferences/${e}/com.anthropic.claudefordesktop.plist`:"","/Library/Managed Preferences/com.anthropic.claudefordesktop.plist"].filter(Boolean).find(e=>t(e))??null}if("win32"===process.platform)return ce(re)?re:null;const e="/etc/claude-desktop/managed-settings.json";return t(e)?e:null}catch(e){return u.logError("claude-desktop.detectManagedConfig",e),null}}function me(){const e=A();let o;switch(process.platform){case"darwin":o=["/Applications/Claude.app",a(e,"Applications","Claude.app")];break;case"win32":{const t=process.env.LOCALAPPDATA||a(e,"AppData","Local");o=[a(t,"AnthropicClaude"),a(t,"Programs","Claude"),...M.map(e=>a(t,"Packages",e))];break}default:o=["/usr/lib/claude-desktop","/opt/Claude","/usr/bin/claude-desktop",a(e,".local","bin","claude-desktop")]}return o.push(claudeDesktopUserDataDir(),a(claudeDesktopUserDataDir(),"..","Claude")),o.some(e=>t(e))}const ge=/\d+\.\d+\.\d+/;function ye(e){const t=e=>e.split(".").map(Number);return e.sort((e,o)=>{const[n,r]=[t(e),t(o)];for(let e=0;e<3;e++)if(n[e]!==r[e])return r[e]-n[e];return 0})[0]??null}function he(){if("darwin"===process.platform){for(const e of["/Applications/Claude.app",a(A(),"Applications","Claude.app")]){const o=a(e,"Contents","Info.plist");if(!t(o))continue;const n=/<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/.exec(r(o,"utf-8")),s=n?ge.exec(n[1])?.[0]:void 0;if(s)return s}return null}if("win32"===process.platform){const e=a(process.env.LOCALAPPDATA||a(A(),"AppData","Local"),"AnthropicClaude");if(t(e)){const t=n(e).map(e=>/^app-(\d+\.\d+\.\d+)$/.exec(e)?.[1]).filter(e=>!!e);if(t.length>0)return ye(t)}const o=M.map(e=>`'${e}'`).join(",");return ye(c("powershell.exe",["-NoProfile","-Command",`Get-AppxPackage | Where-Object { @(${o}) -contains $_.PackageFamilyName } | ForEach-Object { $_.Version.ToString() }`],{encoding:"utf-8",timeout:15e3,windowsHide:!0,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).flatMap(e=>ge.exec(e)?.[0]??[]))}if("linux"===process.platform)try{const e=c("dpkg-query",["-W","-f=${Version}","claude-desktop"],{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]});return ge.exec(e)?.[0]??null}catch{return null}return null}const ke="darwin"===process.platform?"open -a Claude":"win32"===process.platform?"Claude":"claude-desktop",_e="darwin"!==process.platform&&"win32"!==process.platform||!h().installMirror?.claudeDesktop?"https://claude.ai/download":h().installMirror.claudeDesktop,De="darwin"===process.platform?`open ${_e}`:"win32"===process.platform?`start ${_e}`:`xdg-open ${_e}`;export const claudeDesktopAdapter={name:"claude-desktop",displayName:"Claude Desktop",command:ke,installCommand:De,configPath:G(),sessions:{format:j,files:()=>L(a(claudeDesktopUserDataDir(),"local-agent-mode-sessions"))},isInstalled:me,installedVersion:he,prepareRuntime:async function(){if(!["win32","darwin","linux"].includes(process.platform)||!me())return[];const e=Date.now();try{const t=await m({userDataDir:claudeDesktopUserDataDir(),onDownload:e=>console.log(p.gray(" "+g.t("tools.claude_desktop.code_cli_downloading",{version:e}))),desktopVersion:"darwin"===process.platform?he():null,mirrorRepo:h().installMirror?.claudeDesktop?.replace(/\/-\/releases\/latest\/?$/,"")??null});return f("desktop-code-cli","skipped"===t.status?"skip":"ok",{duration_ms:Date.now()-e,detail:{...t}}),"installed"!==t.status?[]:[{kind:"summary",text:g.t("tools.claude_desktop.code_cli_installed",{version:t.version})}]}catch(t){return u.logError("claude-desktop.prepareCodeTabCli",t),f("desktop-code-cli","fail",{duration_ms:Date.now()-e,error:t}),[{kind:"action",text:g.t("tools.claude_desktop.code_cli_failed",{reason:t instanceof Error?t.message:String(t)})}]}},runningApp:C()?{isRunning:w,restart:E}:void 0,wantsModelCatalog:!0,loadPrivateConfig(e){const o=H()??{appliedId:"",entries:[]};let n=B(o);n||(n={id:l(),name:I},o.entries.push(n));const r=Q(e);Z=!0===r.disableDeploymentModeChooser,z={models:r.inferenceModels,source:e.catalog?e.catalog.oneMillionSource:"slots",groups:e.catalog?.matchedGroups??[]};const s=K(N(n.id))??{};F(N(n.id),{...te(e=>e in s),...s,...r}),o.appliedId=n.id,F(G(),o);const i=K(U())??{};if("3p"!==i.deploymentMode&&F(U(),{...i,deploymentMode:"3p"}),X=null,Y=null,q=null,le()){const o=ce(ne),n=fe.filter(e=>o?.has(e)),s={...te(e=>o?.has(e)??!1),...r},i=!0===e.settings?.force_registry,l=!i&&function(){const e=!Boolean(k("TEST_HOME")?.trim())&&process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:a(A(),"AppData","Local");return!!t(a(e,"AnthropicClaude"))||M.some(o=>t(a(e,"Packages",o,"LocalCache","Local","Claude-3p")))}();try{l?ue(fe):pe(s),q=l?"removed":"written"}catch(e){u.logError("claude-desktop.policy",e),X=e instanceof Error?e.message.trim():String(e),(n.length>0||i)&&(Y=l?{action:"remove",values:Object.fromEntries(n.map(e=>[e,null])),deleteKey:n.length===o.size}:{action:"write",values:s,deleteKey:!1})}}},pendingElevation(){const e=Y;return e?{prompt:g.t(`tools.claude_desktop.elevate_${e.action}`),run:()=>{if(!v(oe,e.values,e.deleteKey))return!1;const t=ce(ne),o="remove"===e.action?Object.keys(e.values).every(e=>!t?.has(e)):Object.keys(e.values).every(e=>t?.has(e));return o&&(Y=null,X=null),o}}:null},unloadPrivateConfig(){if(le())try{ue(fe)}catch(e){u.logError("claude-desktop.removePolicy",e)}const e=H(),t=B(e);if(!e||!t)return;D(N(t.id)),s(N(t.id),{force:!0});const o=e.entries.filter(e=>e.id!==t.id);0===o.length?(D(G()),s(G(),{force:!0})):F(G(),{...e,entries:o,appliedId:e.appliedId===t.id?o[0].id:e.appliedId})},listedModels(){const e=H(),t=B(e);if(!t||e?.appliedId!==t.id)return null;const o=K(N(t.id))?.inferenceModels;return Array.isArray(o)?o.map(e=>String(e.name)):null},refreshModelMenu(e){const t=H(),o=B(t);if(!o||t?.appliedId!==o.id)return;const n=K(N(o.id));if(!n)return;const r=buildInferenceModels(e.models,e.catalog);if(JSON.stringify(n.inferenceModels)!==JSON.stringify(r)){if(le()&&ce(ne)?.has("inferenceModels"))try{pe({inferenceModels:r})}catch(e){throw u.logError("claude-desktop.refreshModelMenu registry",e),new O(g.t("tools.claude_desktop.refresh_needs_admin"))}F(N(o.id),{...n,inferenceModels:r})}},detectCurrentConfig(){try{if(le()){const e=ce(ne)?.get("inferenceGatewayApiKey");if(e)return{apiKey:e}}const e=B(H());if(!e)return{apiKey:null};const t=K(N(e.id)),o=t?.inferenceGatewayApiKey;return{apiKey:"string"==typeof o&&o?o:null}}catch(e){return u.logError("claude-desktop.detectCurrentConfig",e),{apiKey:null}}},getConfig(){try{const e=H(),t=B(e);return{meta:e,applied:t?K(N(t.id)):null,desktop:K(U()),...le()?{policy:Object.fromEntries(ce(ne)??[])}:{}}}catch(e){return u.logError("claude-desktop.getConfig",e),null}},clearPinnedModels(){let e=!1;le()&&ce(ne)?.has("inferenceModels")&&(de(),ae(["delete",ne,"/v","inferenceModels","/f"]),e=!0);const t=B(H()),o=t?K(N(t.id)):null;if(t&&o&&void 0!==o.inferenceModels){const{inferenceModels:n,...r}=o;F(N(t.id),r),e=!0}return e?["inferenceModels"]:[]},applyNotes(){const e=[];if(z&&z.models.length>0){const{models:t,source:o,groups:n}=z;e.push({kind:"summary",text:g.t("tools.claude_desktop.models_summary",{count:String(t.length),default:t[0].labelOverride??t[0].name})}),e.push({kind:"detail",text:g.t(`tools.claude_desktop.models_written_${o}`,{count:String(t.length),list:t.map(e=>`${e.labelOverride}${e.supports1m?" (1M)":""}`).join(", "),groups:n.join(" / ")})})}null!==Z&&e.push({kind:"detail",text:g.t(Z?"tools.claude_desktop.official_login_hidden":"tools.claude_desktop.official_login_shown")}),C()&&!w()||e.push({kind:"action",text:g.t("tools.claude_desktop.restart_hint")}),Y?(e.push({kind:"action",text:g.t(`tools.claude_desktop.policy_stale_${Y.action}`)}),e.push({kind:"detail",text:X??""})):X?(e.push({kind:"detail",text:g.t("tools.claude_desktop.registry_denied")}),e.push({kind:"detail",text:X})):le()&&q&&e.push({kind:"detail",text:g.t(`tools.claude_desktop.registry_${q}`,{key:ne})});const t=detectManagedConfig();return t&&e.push({kind:"action",text:g.t("tools.claude_desktop.managed_conflict",{path:t})}),e},forceResetPaths(){const e=[G(),U()];try{const t=B(H());t&&e.push(N(t.id))}catch{}return e},backupPaths(){const e=[G(),U()];le()&&e.push(a(claudeDesktopUserDataDir(),se));try{const t=B(H());t&&e.push(N(t.id))}catch{}return e}};