@vibeapi/cli 0.0.67 → 0.0.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -79,7 +79,7 @@ vibecli config claude-code clear-model # 模型选择被钉住时,交还给
79
79
  - **多工具一键配置**:把当前 API Key / 模型注入 Claude Code、Claude Desktop(桌面端第三方推理模式,写应用本地配置库,无需管理员 / 描述文件)、Codex、OpenClaw、Hermes、AtomCode、Grok Build(OpenCode 暂时下架,`vibecli config opencode` 仍可用)。
80
80
  - **按工具选模型**:使用默认 / 实时从 API 拉取 / 内置预设 / 手动输入;每个工具可用不同模型。
81
81
  - Claude Code 用默认模型时不写 `ANTHROPIC_*_MODEL` 环境变量,顶层 `model` 由 `settings-template.json` 提供(当前为 `opus[1m]`);显式选择其它模型时会覆盖该模板值。Codex 默认 `gpt-6-astra`,Grok Build 默认 `grok-4.6`,其余工具默认 `gpt-5.5`。
82
- - Codex(CLI 与桌面版)的模型菜单除自带的 GPT 模型外,还列出网关的 Claude 与国产模型(只列 Key 能用的);Claude Code 的 `/model` 菜单也会在内置档位后列出 Key 能用的国产模型;每个模型按自己的上下文窗口设置,窗口用到 80% 时自动压缩。默认启用 1M 上下文,交互配置 Codex 时可取消(取消后窗口不超过 272K)。需要 Codex 0.122 及以上;Codex、Claude Code 版本过旧时,配置完成会提示升级命令。
82
+ - Codex(CLI 与桌面版)的模型菜单除自带的 GPT 模型外,还列出网关的 Claude、Gemini 与国产模型(只列 Key 能用的);Claude Code 的 `/model` 菜单也会在内置档位后列出 Key 能用的国产模型;每个模型按自己的上下文窗口设置,窗口用到 80% 时自动压缩。默认启用 1M 上下文,交互配置 Codex 时可取消(取消后窗口不超过 272K)。需要 Codex 0.122 及以上;Codex、Claude Code 版本过旧时,配置完成会提示升级命令。
83
83
  - **不动你的其它配置**:只改本工具的 provider 字段,你的 hooks、MCP、插件、权限设置原样保留。
84
84
  - **配置改坏了一键重置**:`vibecli config <tool> --force`(或 `setup … --force`)先快照再整份重写为推荐配置,坏掉的 JSON/TOML 也能救回;不加 `--force` 时只幂等合并、不碰坏文件。
85
85
  - **改前自动备份 + 一键还原**:覆盖配置前先快照(每文件留 10 份),`vibecli config <tool> restore` 随时回退;还原本身也可再撤销。
@@ -12,8 +12,8 @@ export declare function autoCompactTokens(window: number, explicit?: number): nu
12
12
  * The models to add for `tool`. When the gateway publishes its client config
13
13
  * (`/api/platform/vibecode/config`) its lists win — fields it leaves out keep the
14
14
  * built-in values, and Claude models only come from it when `models.json` lists
15
- * them too (so a model removed there, like Haiku for Codex, stays out). Otherwise
16
- * the built-in list from `models.json` → `gatewayModels`.
15
+ * them too (so a model removed there, like Haiku for Codex, stays out); Codex also
16
+ * gets the `gemini` list. Otherwise the built-in list from `models.json` → `gatewayModels`.
17
17
  */
18
18
  export declare function gatewayModelSpecs(tool: GatewayModelTool, clientModels?: Record<string, GatewayClientModel[]>): GatewayModelSpec[];
19
19
  /**
@@ -32,6 +32,6 @@ export declare function modelBlurb(description: string | undefined, options?: {
32
32
  export declare function prettyModelName(id: string): string;
33
33
  /** Vendor names in first-seen order: `glm-5.3`, `glm-5.2`, `kimi-k3` → `GLM`, `Kimi`. */
34
34
  export declare function vendorNames(ids: string[]): string[];
35
- export type ModelFamily = 'gpt' | 'claude' | 'grok' | 'other';
36
- /** Coarse family for a summary line; everything that isn't GPT, Claude or Grok counts as other (domestic). */
35
+ export type ModelFamily = 'gpt' | 'claude' | 'gemini' | 'grok' | 'other';
36
+ /** Coarse family for a summary line; everything that isn't GPT, Claude, Gemini or Grok counts as other (domestic). */
37
37
  export declare function modelFamily(id: string): ModelFamily;
@@ -1 +1 @@
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
+ 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 i=t().models,n=i.filter(t=>function(t,e){return"codex"===t?!1!==e.codex:!e.id.startsWith("claude-")&&!1!==e.claudeCode}(e,t));if(!o)return n;const r=new Map(("claude-code"===e?i:n).map(t=>[t.id,t])),s=(o.gemini??[]).filter(t=>!1!==i.find(e=>e.id===t.id)?.codex),d="codex"===e?[...o.codex??[],...s,...(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===d.length)return n;const c=new Set,l=[];for(const t of d)c.has(t.id)||(c.add(t.id),l.push({...r.get(t.id),...t}));return l}const e={gpt:"GPT",gemini:"Gemini",glm:"GLM",deepseek:"DeepSeek",minimax:"MiniMax",qwen:"Qwen"};export function modelBlurb(t,e={}){const o=[];for(const i of(t??"").split("|")){const t=i.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),i=[];for(const t of o){const o=i[i.length-1];if(/^\d+$/.test(t)&&o&&/^\d+$/.test(o)&&t.length<=2&&!/^\d{8}$/.test(t)){i[i.length-1]=`${o}.${t}`;continue}const n=t.toLowerCase();i.push(e[n]??(/^[a-z]\d/i.test(t)?t.toUpperCase():t[0].toUpperCase()+t.slice(1)))}return i.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("gemini")?"gemini":e.startsWith("grok")?"grok":/^(gpt|o\d|codex)/.test(e)?"gpt":"other"}
@@ -1 +1 @@
1
- import{spawnSync as e}from"child_process";import{readFileSync as t}from"fs";import{join as i}from"path";import{logger as o}from"../../utils/logger.js";import{configManager as s}from"../config.js";import{toolHome as n}from"./types.js";export const PLUGIN_SOURCES=[{name:"vibeapi-plugins",add:"https://cnb.cool/sla/claude-plugins-official.git",probe:"https://cnb.cool/sla/claude-plugins-official.git"},{name:"claude-plugins-official",add:"anthropics/claude-plugins-official",probe:"https://github.com/anthropics/claude-plugins-official.git"}];export const OFFICIAL_PLUGINS=["code-review","feature-dev","frontend-design","pr-review-toolkit","commit-commands","security-guidance","code-simplifier","skill-creator","claude-md-management","claude-code-setup"];const l="official_plugins_offered";let r=(t,i)=>{const s=e(t,i,{encoding:"utf-8",timeout:12e4,windowsHide:!0,stdio:["ignore","pipe","pipe"],shell:"win32"===process.platform&&/\.cmd$/i.test(t)});return 0!==s.status&&o.logError(`claude ${i.join(" ")}`,new Error(`${s.stderr??""}${s.stdout??""}`.trim())),0===s.status},a=t=>0===e("git",["ls-remote","--heads",t],{timeout:8e3,windowsHide:!0,stdio:"ignore"}).status;export function setClaudePluginRunnerForTests(e){r=e}export function setPluginSourceProbeForTests(e){a=e}export function installOfficialPlugins(e){if("1"===process.env.VIBECLI_SKIP_CLAUDE_PLUGINS)return{installed:[],failed:[],skipped:"disabled"};const o=s.getToolSetting("claude-code",l),d=new Set("string"==typeof o?o.split(",").filter(Boolean):[]),c=function(){try{const e=JSON.parse(t(i(n(),".claude","plugins","installed_plugins.json"),"utf-8"));return new Set(Object.keys(e.plugins??{}))}catch{return new Set}}(),p=e=>PLUGIN_SOURCES.some(t=>c.has(`${e}@${t.name}`)),u=OFFICIAL_PLUGINS.filter(e=>!d.has(e)&&!p(e));if(0===u.length)return{installed:[],failed:[],skipped:null};const f=PLUGIN_SOURCES.find(e=>a(e.probe));if(!f)return{installed:[],failed:[],skipped:"marketplace"};r(e,["plugin","marketplace","add",f.add]);const g={installed:[],failed:[],skipped:null,source:f.name};for(const t of u)r(e,["plugin","install",`${t}@${f.name}`])?(g.installed.push(t),d.add(t)):g.failed.push(t);for(const e of OFFICIAL_PLUGINS)p(e)&&d.add(e);return s.setToolSetting("claude-code",l,[...d].join(",")),g}
1
+ import{spawnSync as e}from"child_process";import{readFileSync as t}from"fs";import{join as i}from"path";import{logger as o}from"../../utils/logger.js";import{configManager as s}from"../config.js";import{toolHome as n}from"./types.js";export const PLUGIN_SOURCES=[{name:"vibeapi-plugins",add:"https://cnb.cool/sla/claude-plugins-official.git",probe:"https://cnb.cool/sla/claude-plugins-official.git"},{name:"claude-plugins-official",add:"anthropics/claude-plugins-official",probe:"https://github.com/anthropics/claude-plugins-official.git"}];export const OFFICIAL_PLUGINS=["code-review","feature-dev","frontend-design","pr-review-toolkit","commit-commands","security-guidance","code-simplifier","skill-creator","claude-md-management","claude-code-setup"];const l="official_plugins_offered";let r=(t,s)=>{const l=e(t,s,{env:process.env.VIBECLI_TEST_HOME?{...process.env,CLAUDE_CONFIG_DIR:i(n(),".claude")}:process.env,encoding:"utf-8",timeout:12e4,windowsHide:!0,stdio:["ignore","pipe","pipe"],shell:"win32"===process.platform&&/\.cmd$/i.test(t)});return 0!==l.status&&o.logError(`claude ${s.join(" ")}`,new Error(`${l.stderr??""}${l.stdout??""}`.trim())),0===l.status},a=t=>0===e("git",["ls-remote","--heads",t],{timeout:8e3,windowsHide:!0,stdio:"ignore"}).status;export function setClaudePluginRunnerForTests(e){r=e}export function setPluginSourceProbeForTests(e){a=e}export function installOfficialPlugins(e){if("1"===process.env.VIBECLI_SKIP_CLAUDE_PLUGINS)return{installed:[],failed:[],skipped:"disabled"};const o=s.getToolSetting("claude-code",l),c=new Set("string"==typeof o?o.split(",").filter(Boolean):[]),d=function(){try{const e=JSON.parse(t(i(n(),".claude","plugins","installed_plugins.json"),"utf-8"));return new Set(Object.keys(e.plugins??{}).map(e=>e.replace(/@[^@]*$/,"")))}catch{return new Set}}(),p=e=>d.has(e),u=OFFICIAL_PLUGINS.filter(e=>!c.has(e)&&!p(e));if(0===u.length)return{installed:[],failed:[],skipped:null};const f=PLUGIN_SOURCES.find(e=>a(e.probe));if(!f)return{installed:[],failed:[],skipped:"marketplace"};r(e,["plugin","marketplace","add",f.add]);const g={installed:[],failed:[],skipped:null,source:f.name};for(const t of u)r(e,["plugin","install",`${t}@${f.name}`])?(g.installed.push(t),c.add(t)):g.failed.push(t);for(const e of OFFICIAL_PLUGINS)p(e)&&c.add(e);return s.setToolSetting("claude-code",l,[...c].join(",")),g}
@@ -1 +1 @@
1
- import{existsSync as e,readFileSync as t}from"fs";import{join as o}from"path";import*as n from"@iarna/toml";import{logger as r}from"../../utils/logger.js";import{i18n as i}from"../i18n.js";import{backupBeforeWrite as l,atomicWriteFile as a}from"./backup.js";import{pickModel as s,toolHome as d,withV1 as c}from"./types.js";import{getToolDefaultModel as m}from"../model-registry.js";import{buildCodexCatalog as u,codexCatalogPath as p,loadBundledCodexModels as _,loadPreviousCodexModels as g,previousGatewayModelIds as f}from"./codex-catalog.js";import{gatewayModelSpecs as x,modelFamily as y}from"../gateway-models.js";const h=()=>o(d(),".codex"),b=()=>o(h(),"config.toml"),k=()=>o(h(),"auth.json"),w="OPENAI_API_KEY",C="custom",j=1e6,v=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function E(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function M(e,t){return E(e[t])||(e[t]={}),e[t]}function O(){if(!e(b()))return{};const o=t(b(),"utf-8");if(!o.trim())return{};try{const e=n.parse(o);if(!E(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function N(){if(!e(k()))return{};try{const e=JSON.parse(t(k(),"utf-8"));return E(e)?e:{}}catch{return{}}}let S=null;function A(o,n,i){const s=!1!==n.settings?.one_million_context;!function(e){e.model_context_window===j&&delete e.model_context_window,e.model_auto_compact_token_limit===v&&delete e.model_auto_compact_token_limit}(o);const d=_()??g();if(!d)return r.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),S="skipped",o.model_catalog_json===p()&&delete o.model_catalog_json,void(s&&(o.model_context_window=j,o.model_auto_compact_token_limit=v));const c=n.catalog,m=u({bundled:d,specs:x("codex",c?.clientModels),...c?{keyModels:c.models}:{},gatewayAvailable:c?.models??f(),oneMillion:s,selectedModel:i,..."gateway"===c?.oneMillionSource?{claudeOneMillion:c.oneMillion}:{}});S={listed:m.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))};const y=JSON.stringify(m,null,2)+"\n",h=p();e(h)&&t(h,"utf-8")===y||(l(h),a(h,y)),o.model_catalog_json=h}export function setCodexOneMillionContext(e,t){const o=O(),r=n.stringify(o),i="string"==typeof o.model?o.model:m("codex");A(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},i);const s=n.stringify(o);s!==r&&(l(b()),a(b(),s))}export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:"npm install -g @openai/codex",upgradeCommand:"npm install -g @openai/codex@latest",installSpec:{command:"codex",npmPackage:"@openai/codex",brew:"codex"},configPath:b(),wantsModelCatalog:!0,listedModels(){if(O().model_catalog_json!==p())return null;try{return(JSON.parse(t(p(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){O().model_catalog_json===p()&&setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog)},applyNotes(){if("skipped"===S)return[{kind:"action",text:i.t("tools.codex.catalog_skipped")}];if(!S)return[];const e=new Map;for(const t of S.listed)e.set(y(t.id),(e.get(y(t.id))??0)+1);const t=["gpt","claude","other","grok"].filter(t=>e.has(t)).map(t=>`${i.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:i.t("tools.codex.catalog_written",{count:String(S.listed.length),breakdown:t})},{kind:"detail",text:S.listed.map(e=>e.name).join(", ")}]},loadPrivateConfig(e){const t=m("codex"),o=s(e.models,t),r=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,i=c(e.baseUrl),d=O();d.model=r,d.model_provider=C,d.model_reasoning_effort="high",A(d,e,r);const u=M(d,"model_providers"),p=E(u[C])?{...u[C]}:{};delete p.env_key;const{experimental_bearer_token:_,...g}=p;u[C]={...g,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:i};const f=M(d,"profiles"),x=E(f[r])?{...f[r]}:{};f[r]={...x,model_provider:C,model:r},M(M(d,"tui"),"model_availability_nux")[r]=4;const y=M(d,"features");y.goals=!0,y.js_repl=!1,l(b()),a(b(),n.stringify(d)),function(e){const t=e.trim();if(!t)return;const o={...N(),auth_mode:"apikey",[w]:t};l(k()),a(k(),JSON.stringify(o,null,2)+"\n")}(e.apiKey)},unloadPrivateConfig(){if(!e(b()))return;let t;try{t=O()}catch(e){return void r.logError("codexAdapter.unloadPrivateConfig",e)}const o=t.model_providers;E(o)&&(delete o[C],0===Object.keys(o).length&&delete t.model_providers),t.model_provider===C&&delete t.model_provider,t.model_catalog_json===p()&&delete t.model_catalog_json,l(b()),a(b(),n.stringify(t))},detectCurrentConfig(){const e=N()[w];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return O()}catch(e){return r.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[b(),k(),p()]};export function codexAuthProblem(){try{const e=O(),t=e.model_providers?.[C];if(e.model_provider!==C||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=N();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
1
+ import{existsSync as e,readFileSync as t}from"fs";import{join as o}from"path";import*as n from"@iarna/toml";import{logger as r}from"../../utils/logger.js";import{i18n as i}from"../i18n.js";import{backupBeforeWrite as l,atomicWriteFile as a}from"./backup.js";import{pickModel as s,toolHome as d,withV1 as c}from"./types.js";import{getToolDefaultModel as m}from"../model-registry.js";import{buildCodexCatalog as u,codexCatalogPath as p,loadBundledCodexModels as _,loadPreviousCodexModels as g,previousGatewayModelIds as f}from"./codex-catalog.js";import{gatewayModelSpecs as x,modelFamily as y}from"../gateway-models.js";const h=()=>o(d(),".codex"),b=()=>o(h(),"config.toml"),k=()=>o(h(),"auth.json"),w="OPENAI_API_KEY",C="custom",j=1e6,v=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function E(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function M(e,t){return E(e[t])||(e[t]={}),e[t]}function O(){if(!e(b()))return{};const o=t(b(),"utf-8");if(!o.trim())return{};try{const e=n.parse(o);if(!E(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function N(){if(!e(k()))return{};try{const e=JSON.parse(t(k(),"utf-8"));return E(e)?e:{}}catch{return{}}}let S=null;function A(o,n,i){const s=!1!==n.settings?.one_million_context;!function(e){e.model_context_window===j&&delete e.model_context_window,e.model_auto_compact_token_limit===v&&delete e.model_auto_compact_token_limit}(o);const d=_()??g();if(!d)return r.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),S="skipped",o.model_catalog_json===p()&&delete o.model_catalog_json,void(s&&(o.model_context_window=j,o.model_auto_compact_token_limit=v));const c=n.catalog,m=u({bundled:d,specs:x("codex",c?.clientModels),...c?{keyModels:c.models}:{},gatewayAvailable:c?.models??f(),oneMillion:s,selectedModel:i,..."gateway"===c?.oneMillionSource?{claudeOneMillion:c.oneMillion}:{}});S={listed:m.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))};const y=JSON.stringify(m,null,2)+"\n",h=p();e(h)&&t(h,"utf-8")===y||(l(h),a(h,y)),o.model_catalog_json=h}export function setCodexOneMillionContext(e,t){const o=O(),r=n.stringify(o),i="string"==typeof o.model?o.model:m("codex");A(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},i);const s=n.stringify(o);s!==r&&(l(b()),a(b(),s))}export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:"npm install -g @openai/codex",upgradeCommand:"npm install -g @openai/codex@latest",installSpec:{command:"codex",npmPackage:"@openai/codex",brew:"codex"},configPath:b(),wantsModelCatalog:!0,listedModels(){if(O().model_catalog_json!==p())return null;try{return(JSON.parse(t(p(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){O().model_catalog_json===p()&&setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog)},applyNotes(){if("skipped"===S)return[{kind:"action",text:i.t("tools.codex.catalog_skipped")}];if(!S)return[];const e=new Map;for(const t of S.listed)e.set(y(t.id),(e.get(y(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${i.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:i.t("tools.codex.catalog_written",{count:String(S.listed.length),breakdown:t})},{kind:"detail",text:S.listed.map(e=>e.name).join(", ")}]},loadPrivateConfig(e){const t=m("codex"),o=s(e.models,t),r=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,i=c(e.baseUrl),d=O();d.model=r,d.model_provider=C,d.model_reasoning_effort="high",A(d,e,r);const u=M(d,"model_providers"),p=E(u[C])?{...u[C]}:{};delete p.env_key;const{experimental_bearer_token:_,...g}=p;u[C]={...g,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:i};const f=M(d,"profiles"),x=E(f[r])?{...f[r]}:{};f[r]={...x,model_provider:C,model:r},M(M(d,"tui"),"model_availability_nux")[r]=4;const y=M(d,"features");y.goals=!0,y.js_repl=!1,l(b()),a(b(),n.stringify(d)),function(e){const t=e.trim();if(!t)return;const o={...N(),auth_mode:"apikey",[w]:t};l(k()),a(k(),JSON.stringify(o,null,2)+"\n")}(e.apiKey)},unloadPrivateConfig(){if(!e(b()))return;let t;try{t=O()}catch(e){return void r.logError("codexAdapter.unloadPrivateConfig",e)}const o=t.model_providers;E(o)&&(delete o[C],0===Object.keys(o).length&&delete t.model_providers),t.model_provider===C&&delete t.model_provider,t.model_catalog_json===p()&&delete t.model_catalog_json,l(b()),a(b(),n.stringify(t))},detectCurrentConfig(){const e=N()[w];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return O()}catch(e){return r.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[b(),k(),p()]};export function codexAuthProblem(){try{const e=O(),t=e.model_providers?.[C];if(e.model_provider!==C||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=N();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
@@ -402,6 +402,7 @@
402
402
  "model_family": {
403
403
  "gpt": "GPT",
404
404
  "claude": "Claude",
405
+ "gemini": "Gemini",
405
406
  "other": "Chinese",
406
407
  "grok": "Grok"
407
408
  }
@@ -402,6 +402,7 @@
402
402
  "model_family": {
403
403
  "gpt": "GPT",
404
404
  "claude": "Claude",
405
+ "gemini": "Gemini",
405
406
  "other": "国产",
406
407
  "grok": "Grok"
407
408
  }
package/dist/models.json CHANGED
@@ -194,15 +194,13 @@
194
194
  "id": "gemini-3.8-flash",
195
195
  "name": "Gemini 3.8 Flash",
196
196
  "description": "105 万上下文 | 推理与编码",
197
- "contextWindow": 1048576,
198
- "codex": false
197
+ "contextWindow": 1048576
199
198
  },
200
199
  {
201
200
  "id": "gemini-3.1-pro",
202
201
  "name": "Gemini 3.1 Pro",
203
202
  "description": "100 万上下文 | 深度推理 | 长文档",
204
- "contextWindow": 1000000,
205
- "codex": false
203
+ "contextWindow": 1000000
206
204
  },
207
205
  {
208
206
  "id": "gemini-3.7-flash",
package/models.json CHANGED
@@ -194,15 +194,13 @@
194
194
  "id": "gemini-3.8-flash",
195
195
  "name": "Gemini 3.8 Flash",
196
196
  "description": "105 万上下文 | 推理与编码",
197
- "contextWindow": 1048576,
198
- "codex": false
197
+ "contextWindow": 1048576
199
198
  },
200
199
  {
201
200
  "id": "gemini-3.1-pro",
202
201
  "name": "Gemini 3.1 Pro",
203
202
  "description": "100 万上下文 | 深度推理 | 长文档",
204
- "contextWindow": 1000000,
205
- "codex": false
203
+ "contextWindow": 1000000
206
204
  },
207
205
  {
208
206
  "id": "gemini-3.7-flash",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeapi/cli",
3
- "version": "0.0.67",
3
+ "version": "0.0.68",
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",