@vibeapi/cli 0.0.63 → 0.0.64
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/dist/commands/doctor.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"chalk";import o from"ora";import{spawnSync as s}from"child_process";import{readFileSync as e}from"fs";import{connect as a}from"net";import{join as n}from"path";import{configManager as r}from"../lib/config.js";import{toolManager as c}from"../lib/tool-manager.js";import{i18n as i}from"../lib/i18n.js";import{validateApiKey as l}from"../lib/api-validator.js";import{getAdapter as d}from"../lib/tools/registry.js";import{findInstalls as p,installLabel as u}from"../lib/tools/tool-installs.js";import{detectManagedOverrides as m}from"../lib/tools/claude-managed.js";import{toolHome as g}from"../lib/tools/types.js";const
|
|
1
|
+
import t from"chalk";import o from"ora";import{spawnSync as s}from"child_process";import{readFileSync as e}from"fs";import{connect as a}from"net";import{join as n}from"path";import{configManager as r}from"../lib/config.js";import{toolManager as c}from"../lib/tool-manager.js";import{i18n as i}from"../lib/i18n.js";import{validateApiKey as l}from"../lib/api-validator.js";import{getAdapter as d}from"../lib/tools/registry.js";import{findInstalls as p,installLabel as u}from"../lib/tools/tool-installs.js";import{detectManagedOverrides as m}from"../lib/tools/claude-managed.js";import{codexAuthProblem as _}from"../lib/tools/codex.js";import{toolHome as g}from"../lib/tools/types.js";const f=["HTTPS_PROXY","https_proxy","HTTP_PROXY","http_proxy","ALL_PROXY","all_proxy"];function h(t,o,s=3e3){return new Promise(e=>{const n=a({host:t,port:o}),r=t=>{n.destroy(),e(t)};n.setTimeout(s,()=>r(!1)),n.once("connect",()=>r(!0)),n.once("error",()=>r(!1))})}export async function doctorCommand(a={}){const y=o(i.t("doctor.checking")).start(),w=[],$=Number(process.versions.node.split(".")[0]);w.push({name:"Node.js",status:$>=20?"pass":"fail",message:`v${process.versions.node}`}),y.text=i.t("doctor.check_proxy"),w.push(await async function(){const t=i.t("doctor.proxy"),o=new Map;for(const t of f){const s=process.env[t]?.trim();s&&!o.has(s)&&o.set(s,t)}if(0===o.size)return{name:t,status:"pass",message:i.t("doctor.proxy_none")};const s=[];for(const[t,e]of o){let o;try{o=new URL(t.includes("://")?t:`http://${t}`)}catch{s.push(`${e}=${t}`);continue}const a=Number(o.port)||("https:"===o.protocol?443:o.protocol.startsWith("socks")?1080:80);await h(o.hostname,a)||s.push(`${e}=${t}`)}return 0===s.length?{name:t,status:"pass",message:[...o.keys()].join(", ")}:{name:t,status:"fail",message:i.t("doctor.proxy_dead",{proxies:s.join(", ")})}}()),y.text=i.t("doctor.check_api_key_network");const x=r.getApiKey(),j=i.t("doctor.api_key_network");if(x){const t=await l(x);t.valid?w.push({name:j,status:"pass"}):"invalid_api_key"===t.error?w.push({name:j,status:"fail",message:i.t("doctor.api_key_invalid")}):w.push({name:j,status:"fail",message:`${i.t("doctor.network_error")}: ${t.message??t.error}`})}else w.push({name:j,status:"fail",message:i.t("doctor.api_key_missing")});y.text=i.t("doctor.check_tools");const T=c.getInstalledTools();w.push({name:i.t("doctor.installed_tools"),status:T.length>0?"pass":"warn",message:T.length>0?T.map(t=>d(t)?.displayName??t).join(", "):i.t("doctor.no_tools_installed")}),w.push(...function(){const t=[];for(const o of c.getInstalledTools()){const s=d(o);if(!s?.installSpec)continue;const e=p(s.installSpec);if(0===e.length)continue;const a=[],n=c.outdatedVersion(o);n&&a.push(i.t("doctor.tool_outdated",{min:n.min})),e.length>1&&a.push(i.t("doctor.tool_duplicates",{others:e.slice(1).map(u).join("、")})),t.push({name:s.displayName,status:a.length>0?"warn":"pass",message:[u(e[0]),...a,...a.length>0?[i.t("doctor.run_upgrade",{tool:o})]:[]].join("\n ")})}return t}());const k=function(){if(!c.isToolInstalled("claude-code"))return null;const t=i.t("doctor.claude_config"),o=m();if(o.length>0){const s=o.map(t=>`${t.source}: ${t.keys.join(", ")}`).join("; ");return{name:t,status:"fail",message:i.t("doctor.claude_managed",{detail:s})}}let s={};try{s=JSON.parse(e(n(g(),".claude","settings.json"),"utf-8")).env??{}}catch{}const a=r.getApiKeyForTool("claude-code");return s.ANTHROPIC_AUTH_TOKEN&&s.ANTHROPIC_BASE_URL?s.ANTHROPIC_BASE_URL!==r.getBaseUrl()||a&&s.ANTHROPIC_AUTH_TOKEN!==a?{name:t,status:"warn",message:i.t("doctor.claude_config_changed")}:{name:t,status:"pass"}:{name:t,status:"warn",message:i.t("doctor.claude_not_configured")}}();k&&w.push(k);const b=T.includes("codex")?_():null;T.includes("codex")&&w.push({name:i.t("doctor.codex_auth"),status:b?"fail":"pass",message:b?i.t(`doctor.codex_${b}`):void 0}),"win32"===process.platform&&T.includes("claude-code")&&!process.env.CLAUDE_CODE_GIT_BASH_PATH&&w.push({name:"Git for Windows",status:c.isGitInstalled()?"pass":"warn",message:c.isGitInstalled()?void 0:i.t("tools.claude_code.no_git_bash")}),a.deep&&T.includes("claude-code")&&(y.text=i.t("doctor.check_claude_request"),w.push(function(){const t=i.t("doctor.claude_request"),o=p(d("claude-code").installSpec)[0];if(!o)return{name:t,status:"warn",message:i.t("doctor.claude_request_skipped")};const e={encoding:"utf-8",timeout:12e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]},a=["-p","Reply with the single word OK."],n=/\.cmd$/i.test(o.path)?s(`"${o.path}" ${a.map(t=>`"${t}"`).join(" ")}`,{...e,shell:!0}):s(o.path,a,e),r=`${n.stdout??""}`.trim();if(0===n.status&&r)return{name:t,status:"pass",message:r.slice(0,80)};const c=(`${n.stderr??""}`.trim()||r||n.error?.message||`exit ${n.status}`).slice(0,300);return{name:t,status:"fail",message:i.t("doctor.claude_request_failed",{reason:c})}}())),y.stop(),console.log("\n"+t.bold(i.t("doctor.results_title"))+"\n");const A={pass:t.green("√"),warn:t.yellow("!"),fail:t.red("×")};for(const o of w)console.log(`${A[o.status]} ${o.name}`),o.message&&console.log(t.gray(` ${o.message}`));w.every(t=>"pass"===t.status)&&console.log("\n"+t.green.bold(i.t("doctor.all_good"))),!a.deep&&T.includes("claude-code")&&console.log(t.gray("\n"+i.t("doctor.deep_hint"))),w.some(t=>"fail"===t.status)&&(process.exitCode=1)}
|
|
@@ -8,3 +8,9 @@ export declare const CODEX_ONE_MILLION_CONTEXT_SETTING = "one_million_context";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function setCodexOneMillionContext(enabled: boolean, catalog?: ModelCatalog): void;
|
|
10
10
|
export declare const codexAdapter: ToolAdapter;
|
|
11
|
+
/**
|
|
12
|
+
* Why Codex would send the gateway something other than the saved key, for
|
|
13
|
+
* `vibecli doctor`: a bearer left on our provider (usually cc-switch's
|
|
14
|
+
* `PROXY_MANAGED`), or auth.json in ChatGPT-login mode. Null when neither.
|
|
15
|
+
*/
|
|
16
|
+
export declare function codexAuthProblem(): 'stale_bearer' | 'chatgpt_login' | null;
|
package/dist/lib/tools/codex.js
CHANGED
|
@@ -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
|
|
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}}
|
package/dist/locales/en_US.json
CHANGED
|
@@ -210,7 +210,10 @@
|
|
|
210
210
|
"check_claude_request": "Sending a test request through Claude Code",
|
|
211
211
|
"claude_request_skipped": "claude command not found",
|
|
212
212
|
"claude_request_failed": "Request failed: {{reason}}",
|
|
213
|
-
"deep_hint": "Add --deep to send one real request through Claude Code (uses a little credit) and confirm the whole chain works"
|
|
213
|
+
"deep_hint": "Add --deep to send one real request through Claude Code (uses a little credit) and confirm the whole chain works",
|
|
214
|
+
"codex_auth": "Codex token",
|
|
215
|
+
"codex_stale_bearer": "~/.codex/config.toml has experimental_bearer_token under [model_providers.custom] (usually PROXY_MANAGED left by cc-switch's proxy mode); Codex sends it as the token and gets 401 Invalid token. vibecli setup removes it",
|
|
216
|
+
"codex_chatgpt_login": "Codex is signed in with a ChatGPT account and sends that credential to VibeAPI (401 Invalid token); run vibecli setup to switch back to the key"
|
|
214
217
|
},
|
|
215
218
|
"preset": {
|
|
216
219
|
"claude_mix": "Claude Mix",
|
package/dist/locales/zh_CN.json
CHANGED
|
@@ -210,7 +210,10 @@
|
|
|
210
210
|
"check_claude_request": "用 Claude Code 发一条测试请求",
|
|
211
211
|
"claude_request_skipped": "没找到 claude 命令",
|
|
212
212
|
"claude_request_failed": "请求失败:{{reason}}",
|
|
213
|
-
"deep_hint": "加上 --deep 会用 Claude Code 实际发一条请求(消耗少量额度),确认整条链路能用"
|
|
213
|
+
"deep_hint": "加上 --deep 会用 Claude Code 实际发一条请求(消耗少量额度),确认整条链路能用",
|
|
214
|
+
"codex_auth": "Codex 令牌",
|
|
215
|
+
"codex_stale_bearer": "~/.codex/config.toml 的 [model_providers.custom] 里有 experimental_bearer_token(多半是 cc-switch 等工具代理模式留下的 PROXY_MANAGED),Codex 会把它当令牌发出去,导致 401 Invalid token;运行 vibecli setup 会删掉它",
|
|
216
|
+
"codex_chatgpt_login": "Codex 当前是 ChatGPT 账号登录状态,会把 ChatGPT 的凭据发给 VibeAPI,导致 401 Invalid token;运行 vibecli setup 改回令牌登录"
|
|
214
217
|
},
|
|
215
218
|
"preset": {
|
|
216
219
|
"claude_mix": "Claude 混合",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeapi/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.64",
|
|
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",
|