@vibeapi/cli 0.0.58 → 0.0.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import{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 u,getGatewayModelRules as C}from"./model-registry.js";import{autoCompactTokens as O,prettyModelName as h}from"./gateway-models.js";import{baseModelId as p}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 _={opus:"ANTHROPIC_DEFAULT_OPUS_MODEL",sonnet:"ANTHROPIC_DEFAULT_SONNET_MODEL",haiku:"ANTHROPIC_DEFAULT_HAIKU_MODEL",fable:"ANTHROPIC_DEFAULT_FABLE_MODEL"},E="CLAUDE_CODE_MAX_CONTEXT_TOKENS";function A(){return s(d.getConfigDir(),"claude-code-picker.json")}function T(){try{const e=JSON.parse(n(A(),"utf-8")).ids;return Array.isArray(e)?e.map(String):[]}catch{return[]}}function P(e,t=[]){if(!e||"object"!=typeof e)return!1;const{options:n,replaceBuiltInOptions:o}=e;if(!Array.isArray(n)||o)return!1;const i=C(),r=new Set([...i.models.map(e=>e.id),...i.retired,...T(),...t]);return n.every(e=>e&&"object"==typeof e&&r.has(p(String(e.model))))}export function applyGatewayModels(e,n){if(void 0===n)return e;const i={...e};if(void 0!==i.modelPicker&&!P(i.modelPicker,n.map(e=>e.id)))return i;const r=P(i.modelPicker)?i.modelPicker.options.map(e=>p(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);if(function(e){try{t(d.getConfigDir(),{recursive:!0}),o(A(),JSON.stringify({ids:e})+"\n")}catch(e){l.logError("claudeCode.recordWrittenPickerIds",e)}}(n.map(e=>e.id)),0===n.length)delete i.modelPicker,delete s[E];else{i.modelPicker={options:n.map(e=>({model:c(e)?`${e.id}[1m]`:e.id,label:e.name||h(e.id),...e.description?{description:e.description}:{}}))},g.length>0?s[E]=String(Math.min(...g)):delete s[E];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(p)),n=[];for(const[e,o]of Object.entries(u())){const i=_[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,...u}=c.env||{},C={...u};for(const e of MODEL_ENV_VARS)delete C[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:{...C,...Object.fromEntries(Object.entries(r).filter(([e])=>!(e in C))),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();
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();
@@ -16,6 +16,15 @@ export declare function autoCompactTokens(window: number, explicit?: number): nu
16
16
  * the built-in list from `models.json` → `gatewayModels`.
17
17
  */
18
18
  export declare function gatewayModelSpecs(tool: GatewayModelTool, clientModels?: Record<string, GatewayClientModel[]>): GatewayModelSpec[];
19
+ /**
20
+ * Menu subtitle from the gateway's description without its figures: output limits
21
+ * and context sizes don't hold for every relayed model. With `millionContext` (the
22
+ * window vibecli configures is at least 1M) the context part becomes a plain
23
+ * 「百万上下文」; otherwise it is dropped. Undefined when nothing is left.
24
+ */
25
+ export declare function modelBlurb(description: string | undefined, options?: {
26
+ millionContext?: boolean;
27
+ }): string | undefined;
19
28
  /**
20
29
  * Menu label for a model id nobody named: `glm-5.3-flash` → `GLM 5.3 Flash`,
21
30
  * `claude-opus-5-5` → `Claude Opus 5.5`, `qwen3.8-max` → `Qwen 3.8 Max`.
@@ -1 +1 @@
1
- import{getGatewayModelRules as e}from"./model-registry.js";export function autoCompactTokens(t,o){return o&&o>0?Math.min(o,t):Math.floor(t*e().autoCompactRatio)}export function gatewayModelSpecs(t,o){const i=e().models,n=i.filter(e=>function(e,t){return"codex"===e?!1!==t.codex:!t.id.startsWith("claude-")&&!1!==t.claudeCode}(t,e));if(!o)return n;const r=new Map(("claude-code"===t?i:n).map(e=>[e.id,e])),d="codex"===t?[...o.codex??[],...(o.claude??[]).filter(e=>e.id.startsWith("claude-")&&r.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=>t.get(e.id)?.claudeCode??!0)}(o,r);if(0===d.length)return n;const a=new Set,s=[];for(const e of d)a.has(e.id)||(a.add(e.id),s.push({...r.get(e.id),...e}));return s}const t={gpt:"GPT",gemini:"Gemini",glm:"GLM",deepseek:"DeepSeek",minimax:"MiniMax",qwen:"Qwen"};export function prettyModelName(e){const o=e.replace(/^([a-z]+)(\d)/i,"$1 $2").split(/[-_\s]+/).filter(Boolean),i=[];for(const e of o){const o=i[i.length-1];if(/^\d+$/.test(e)&&o&&/^\d+$/.test(o)&&e.length<=2&&!/^\d{8}$/.test(e)){i[i.length-1]=`${o}.${e}`;continue}const n=e.toLowerCase();i.push(t[n]??(/^[a-z]\d/i.test(e)?e.toUpperCase():e[0].toUpperCase()+e.slice(1)))}return i.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("grok")?"grok":/^(gpt|o\d|codex)/.test(t)?"gpt":"other"}
1
+ import{getGatewayModelRules as t}from"./model-registry.js";export function autoCompactTokens(e,o){return o&&o>0?Math.min(o,e):Math.floor(e*t().autoCompactRatio)}export function gatewayModelSpecs(e,o){const n=t().models,i=n.filter(t=>function(t,e){return"codex"===t?!1!==e.codex:!e.id.startsWith("claude-")&&!1!==e.claudeCode}(e,t));if(!o)return i;const r=new Map(("claude-code"===e?n:i).map(t=>[t.id,t])),s="codex"===e?[...o.codex??[],...(o.claude??[]).filter(t=>t.id.startsWith("claude-")&&r.has(t.id))]:function(t,e){return[...(t.codex??[]).filter(t=>"gpt"===modelFamily(t.id)),...t.gemini??[],...t.grok??[],...(t.claude??[]).filter(t=>!t.id.startsWith("claude-"))].filter(t=>e.get(t.id)?.claudeCode??!0)}(o,r);if(0===s.length)return i;const d=new Set,c=[];for(const t of s)d.has(t.id)||(d.add(t.id),c.push({...r.get(t.id),...t}));return c}const e={gpt:"GPT",gemini:"Gemini",glm:"GLM",deepseek:"DeepSeek",minimax:"MiniMax",qwen:"Qwen"};export function modelBlurb(t,e={}){const o=[];for(const n of(t??"").split("|")){const t=n.trim();t&&(/\d\s*万?\s*输出|output\D*\d|\d\D*output/i.test(t)||(/[\d百千]\s*万?\s*上下文|context\D*\d|\d\D*context/i.test(t)?e.millionContext&&!o.includes("百万上下文")&&o.unshift("百万上下文"):o.push(t)))}return e.millionContext&&!o.includes("百万上下文")&&o.unshift("百万上下文"),o.length>0?o.join(" | "):void 0}export function prettyModelName(t){const o=t.replace(/^([a-z]+)(\d)/i,"$1 $2").split(/[-_\s]+/).filter(Boolean),n=[];for(const t of o){const o=n[n.length-1];if(/^\d+$/.test(t)&&o&&/^\d+$/.test(o)&&t.length<=2&&!/^\d{8}$/.test(t)){n[n.length-1]=`${o}.${t}`;continue}const i=t.toLowerCase();n.push(e[i]??(/^[a-z]\d/i.test(t)?t.toUpperCase():t[0].toUpperCase()+t.slice(1)))}return n.join(" ")}export function vendorNames(t){return[...new Set(t.map(t=>prettyModelName(t).split(" ")[0]))]}export function modelFamily(t){const e=t.toLowerCase();return e.startsWith("claude-")?"claude":e.startsWith("grok")?"grok":/^(gpt|o\d|codex)/.test(e)?"gpt":"other"}
@@ -1 +1 @@
1
- import{spawnSync as t}from"child_process";import{existsSync as e,readFileSync as o}from"fs";import{dirname as n,join as i}from"path";import{fileURLToPath as s}from"url";import{logger as r}from"../../utils/logger.js";import{getCodexRules as l}from"../model-registry.js";import{autoCompactTokens as u,prettyModelName as a}from"../gateway-models.js";import{toolHome as d}from"./types.js";const c=n(s(import.meta.url));export const CODEX_CATALOG_FILE="vibeapi-model-catalog.json";export const codexCatalogPath=()=>i(d(),".codex",CODEX_CATALOG_FILE);function p(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function _(t){try{const e=JSON.parse(t),o=p(e)&&Array.isArray(e.models)?e.models.filter(p):[];return o.length>0?o:null}catch{return null}}export function loadBundledCodexModels(){for(const o of function(){const t=process.env.VIBECLI_CODEX_BIN;if(void 0!==t)return t.trim()?[t.trim()]:[];const e=["codex"];if("darwin"===process.platform)for(const t of["/Applications",i(d(),"Applications")])e.push(i(t,"ChatGPT.app/Contents/Resources/codex-cli/bin/codex")),e.push(i(t,"Codex.app/Contents/Resources/codex"));return e}()){if("codex"!==o&&!e(o))continue;const n={encoding:"utf-8",timeout:2e4,maxBuffer:67108864,windowsHide:!0,stdio:["ignore","pipe","pipe"]},i="win32"===process.platform&&"codex"===o?t("codex debug models --bundled",{...n,shell:!0}):t(o,["debug","models","--bundled"],n);if(0===i.status&&i.stdout){const t=_(i.stdout);if(t)return t}(i.error||0!==i.status)&&r.logError("loadBundledCodexModels",i.error??new Error(`${o} exited ${i.status}`))}return null}export function loadPreviousCodexModels(){const t=m()?.filter(t=>!f(t));return t&&t.length>0?t:null}export function previousGatewayModelIds(){return(m()??[]).filter(f).map(t=>String(t.slug))}function m(){return e(codexCatalogPath())?_(o(codexCatalogPath(),"utf-8")):null}function f(t){return"number"==typeof t.priority&&t.priority>=1e3}let x=null;function w(){if(null!==x)return x;const t=[i(c,"..","..","..","codex-base-instructions.md"),i(c,"..","..","codex-base-instructions.md"),i(c,"codex-base-instructions.md")],n=t.find(t=>e(t));if(!n)throw new Error(`codex-base-instructions.md not found, searched: ${t.join(", ")}`);return x=o(n,"utf-8"),x}function g(t){return"number"==typeof t&&Number.isFinite(t)&&t>0?t:void 0}function h(t,e,o,n){const i=o?t:Math.min(t,e);return{window:i,compact:u(i,n)}}function y(t,e,o,n){const{standardContextWindow:i}=l();let s=g(t.contextWindow)??i;n&&t.id.startsWith("claude-")&&(s=n.has(t.id)?Math.max(s,1e6):Math.min(s,2e5));const{window:r,compact:u}=h(s,i,o,g(t.autoCompactTokens));return{slug:t.id,display_name:t.name||a(t.id),description:t.description??null,supported_reasoning_levels:[],shell_type:"unified_exec",visibility:"list",supported_in_api:!0,priority:e,additional_speed_tiers:[],service_tiers:[],availability_nux:null,upgrade:null,model_messages:{instructions_template:w()},base_instructions:w(),supports_reasoning_summaries:!0,supports_parallel_tool_calls:!1,prefer_websockets:!1,include_skills_usage_instructions:!1,include_plugin_usage_instructions:!1,include_apps_usage_instructions:!1,default_reasoning_summary:"auto",support_verbosity:!1,default_verbosity:null,apply_patch_tool_type:null,web_search_tool_type:"text",truncation_policy:{mode:"bytes",limit:1e4},supports_image_detail_original:!1,context_window:r,max_context_window:r,auto_compact_token_limit:u,effective_context_window_percent:95,experimental_supported_tools:[],input_modalities:["text","image"],supports_search_tool:!1,supports_experimental_context:!1,use_responses_lite:!1,supports_reasoning_effort_updates:!1,node_repl_auto_review_required:!1,node_repl_disabled:!1}}function b(t,e,o){if("list"!==t.visibility)return t;const n=g(t.context_window);if(!n)return t;const i=g(t.max_context_window)??n,s=o?Math.min(g(e?.contextWindow)??i,i):n,{window:r,compact:l}=h(s,n,!0,g(e?.autoCompactTokens));return{...t,context_window:r,auto_compact_token_limit:l}}export function buildCodexCatalog(t){const{bundled:e,specs:o,oneMillion:n,selectedModel:i}=t,s=t.claudeOneMillion?new Set(t.claudeOneMillion):void 0,r=t.keyModels?new Set(t.keyModels):null,l=new Set(t.gatewayAvailable),u=t=>!r||r.has(t)||t===i,a=t=>l.has(t)||t===i,d=new Map(o.map(t=>[t.id,t])),c=[],p=new Set;for(const t of e){const e="string"==typeof t.slug?t.slug:"";e&&!p.has(e)&&("list"!==t.visibility||u(e))&&(p.add(e),c.push(b(t,d.get(e),n)))}const _=[...o];i&&!d.has(i)&&_.push({id:i});for(const t of _)!p.has(t.id)&&a(t.id)&&(p.add(t.id),c.push(y(t,1e3+c.length,n,s)));return{models:c}}
1
+ import{spawnSync as t}from"child_process";import{existsSync as e,readFileSync as o}from"fs";import{dirname as n,join as i}from"path";import{fileURLToPath as s}from"url";import{logger as r}from"../../utils/logger.js";import{getCodexRules as l,compareVersions as u}from"../model-registry.js";import{autoCompactTokens as a,modelBlurb as d,prettyModelName as c}from"../gateway-models.js";import{toolHome as p}from"./types.js";const _=n(s(import.meta.url));export const CODEX_CATALOG_FILE="vibeapi-model-catalog.json";export const codexCatalogPath=()=>i(p(),".codex",CODEX_CATALOG_FILE);function m(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function f(t){try{const e=JSON.parse(t),o=m(e)&&Array.isArray(e.models)?e.models.filter(m):[];return o.length>0?o:null}catch{return null}}export function loadBundledCodexModels(){for(const o of function(){const t=process.env.VIBECLI_CODEX_BIN;if(void 0!==t)return t.trim()?[t.trim()]:[];const e=["codex"];if("darwin"===process.platform)for(const t of["/Applications",i(p(),"Applications")])e.push(i(t,"ChatGPT.app/Contents/Resources/codex-cli/bin/codex")),e.push(i(t,"Codex.app/Contents/Resources/codex"));return e}()){if("codex"!==o&&!e(o))continue;const n={encoding:"utf-8",timeout:2e4,maxBuffer:67108864,windowsHide:!0,stdio:["ignore","pipe","pipe"]},i="win32"===process.platform&&"codex"===o?t("codex debug models --bundled",{...n,shell:!0}):t(o,["debug","models","--bundled"],n);if(0===i.status&&i.stdout){const t=f(i.stdout);if(t)return t}(i.error||0!==i.status)&&r.logError("loadBundledCodexModels",i.error??new Error(`${o} exited ${i.status}`))}return null}export function loadPreviousCodexModels(){const t=x()?.filter(t=>!w(t));return t&&t.length>0?t:null}export function previousGatewayModelIds(){return(x()??[]).filter(w).map(t=>String(t.slug))}function x(){return e(codexCatalogPath())?f(o(codexCatalogPath(),"utf-8")):null}function w(t){return"number"==typeof t.priority&&t.priority>=1e3}let g=null;function h(){if(null!==g)return g;const t=[i(_,"..","..","..","codex-base-instructions.md"),i(_,"..","..","codex-base-instructions.md"),i(_,"codex-base-instructions.md")],n=t.find(t=>e(t));if(!n)throw new Error(`codex-base-instructions.md not found, searched: ${t.join(", ")}`);return g=o(n,"utf-8"),g}function y(t){return"number"==typeof t&&Number.isFinite(t)&&t>0?t:void 0}function b(t,e,o,n){const i=o?t:Math.min(t,e);return{window:i,compact:a(i,n)}}function C(t,e,o,n){const{standardContextWindow:i}=l();let s=y(t.contextWindow)??i;n&&t.id.startsWith("claude-")&&(s=n.has(t.id)?Math.max(s,1e6):Math.min(s,2e5));const{window:r,compact:u}=b(s,i,o,y(t.autoCompactTokens));return{slug:t.id,display_name:t.name||c(t.id),description:d(t.description,{millionContext:r>=1e6})??null,supported_reasoning_levels:[],shell_type:"unified_exec",visibility:"list",supported_in_api:!0,priority:e,additional_speed_tiers:[],service_tiers:[],availability_nux:null,upgrade:null,model_messages:{instructions_template:h()},base_instructions:h(),supports_reasoning_summaries:!0,supports_parallel_tool_calls:!1,prefer_websockets:!1,include_skills_usage_instructions:!1,include_plugin_usage_instructions:!1,include_apps_usage_instructions:!1,default_reasoning_summary:"auto",support_verbosity:!1,default_verbosity:null,apply_patch_tool_type:null,web_search_tool_type:"text",truncation_policy:{mode:"bytes",limit:1e4},supports_image_detail_original:!1,context_window:r,max_context_window:r,auto_compact_token_limit:u,effective_context_window_percent:95,experimental_supported_tools:[],input_modalities:["text","image"],supports_search_tool:!1,supports_experimental_context:!1,use_responses_lite:!1,supports_reasoning_effort_updates:!1,node_repl_auto_review_required:!1,node_repl_disabled:!1}}function v(t,e,o){if("list"!==t.visibility)return t;const n=y(t.context_window);if(!n)return t;const i=y(t.max_context_window)??n,s=o?Math.min(y(e?.contextWindow)??i,i):n,{window:r,compact:l}=b(s,n,!0,y(e?.autoCompactTokens));return{...t,context_window:r,auto_compact_token_limit:l}}export function buildCodexCatalog(t){const{bundled:e,specs:o,oneMillion:n,selectedModel:i}=t,s=t.claudeOneMillion?new Set(t.claudeOneMillion):void 0,r=t.keyModels?new Set(t.keyModels):null,l=new Set(t.gatewayAvailable),a=t=>!r||r.has(t)||t===i,d=t=>l.has(t)||t===i,c=new Map(o.map(t=>[t.id,t])),p=[],_=new Set;for(const t of e){const e="string"==typeof t.slug?t.slug:"";e&&!_.has(e)&&("list"!==t.visibility||a(e))&&(_.add(e),p.push(v(t,c.get(e),n)))}const m=[...o];i&&!c.has(i)&&m.push({id:i});const f=function(t){const e=new Map;for(const o of t){const t=/^claude-([a-z]+)-(.+)$/.exec(o);if(!t)continue;const n=t[2].split("-").filter(t=>/^\d{1,2}$/.test(t)).join("."),i=e.get(t[1]);(!i||u(n,i.version)>0)&&e.set(t[1],{id:o,version:n})}return new Set([...e.values()].map(t=>t.id))}(m.map(t=>t.id).filter(d));for(const t of m)!_.has(t.id)&&d(t.id)&&(t.id.startsWith("claude-")&&!f.has(t.id)&&t.id!==i||(_.add(t.id),p.push(C(t,1e3+p.length,n,s))));return{models:p}}
package/dist/models.json CHANGED
@@ -159,26 +159,36 @@
159
159
  "contextWindow": 1050000,
160
160
  "codex": false
161
161
  },
162
+ {
163
+ "id": "gpt-6-luna",
164
+ "name": "GPT-6 Luna",
165
+ "contextWindow": 1050000,
166
+ "claudeCode": false,
167
+ "codex": false
168
+ },
162
169
  {
163
170
  "id": "gpt-5.6-sol",
164
171
  "name": "GPT-5.6 Sol",
165
172
  "description": "105 万上下文 | 前沿档",
166
173
  "contextWindow": 1050000,
167
- "codex": false
174
+ "codex": false,
175
+ "claudeCode": false
168
176
  },
169
177
  {
170
178
  "id": "gpt-5.6-terra",
171
179
  "name": "GPT-5.6 Terra",
172
180
  "description": "105 万上下文 | 均衡生产档",
173
181
  "contextWindow": 1050000,
174
- "codex": false
182
+ "codex": false,
183
+ "claudeCode": false
175
184
  },
176
185
  {
177
186
  "id": "gpt-5.6-luna",
178
187
  "name": "GPT-5.6 Luna",
179
188
  "description": "105 万上下文 | 大批量低成本档",
180
189
  "contextWindow": 1050000,
181
- "codex": false
190
+ "codex": false,
191
+ "claudeCode": false
182
192
  },
183
193
  {
184
194
  "id": "gemini-3.8-flash",
@@ -199,7 +209,8 @@
199
209
  "name": "Gemini 3.7 Flash",
200
210
  "description": "100 万上下文 | Agent | 软件工程",
201
211
  "contextWindow": 1000000,
202
- "codex": false
212
+ "codex": false,
213
+ "claudeCode": false
203
214
  },
204
215
  {
205
216
  "id": "deepseek-v4-pro",
@@ -260,7 +271,8 @@
260
271
  "name": "Grok 4.6",
261
272
  "description": "50 万上下文 | 编码",
262
273
  "contextWindow": 500000,
263
- "codex": false
274
+ "codex": false,
275
+ "claudeCode": false
264
276
  }
265
277
  ]
266
278
  },
package/models.json CHANGED
@@ -159,26 +159,36 @@
159
159
  "contextWindow": 1050000,
160
160
  "codex": false
161
161
  },
162
+ {
163
+ "id": "gpt-6-luna",
164
+ "name": "GPT-6 Luna",
165
+ "contextWindow": 1050000,
166
+ "claudeCode": false,
167
+ "codex": false
168
+ },
162
169
  {
163
170
  "id": "gpt-5.6-sol",
164
171
  "name": "GPT-5.6 Sol",
165
172
  "description": "105 万上下文 | 前沿档",
166
173
  "contextWindow": 1050000,
167
- "codex": false
174
+ "codex": false,
175
+ "claudeCode": false
168
176
  },
169
177
  {
170
178
  "id": "gpt-5.6-terra",
171
179
  "name": "GPT-5.6 Terra",
172
180
  "description": "105 万上下文 | 均衡生产档",
173
181
  "contextWindow": 1050000,
174
- "codex": false
182
+ "codex": false,
183
+ "claudeCode": false
175
184
  },
176
185
  {
177
186
  "id": "gpt-5.6-luna",
178
187
  "name": "GPT-5.6 Luna",
179
188
  "description": "105 万上下文 | 大批量低成本档",
180
189
  "contextWindow": 1050000,
181
- "codex": false
190
+ "codex": false,
191
+ "claudeCode": false
182
192
  },
183
193
  {
184
194
  "id": "gemini-3.8-flash",
@@ -199,7 +209,8 @@
199
209
  "name": "Gemini 3.7 Flash",
200
210
  "description": "100 万上下文 | Agent | 软件工程",
201
211
  "contextWindow": 1000000,
202
- "codex": false
212
+ "codex": false,
213
+ "claudeCode": false
203
214
  },
204
215
  {
205
216
  "id": "deepseek-v4-pro",
@@ -260,7 +271,8 @@
260
271
  "name": "Grok 4.6",
261
272
  "description": "50 万上下文 | 编码",
262
273
  "contextWindow": 500000,
263
- "codex": false
274
+ "codex": false,
275
+ "claudeCode": false
264
276
  }
265
277
  ]
266
278
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeapi/cli",
3
- "version": "0.0.58",
3
+ "version": "0.0.60",
4
4
  "description": "CLI tool for managing AI coding assistants (Claude Code, Codex, OpenClaw, Hermes, AtomCode, Grok Build) with one unified config",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",