@vibeapi/api-helper 0.0.112 → 0.0.113

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.
@@ -11,3 +11,5 @@ export declare const KEY_INFO_PATH = "/api/platform/vibecode/key";
11
11
  export declare const CLIENT_SECTION = "vibecli";
12
12
  /** Model-row field: lowest CLI version that may see the row. */
13
13
  export declare const MIN_CLIENT_VERSION = "min_vibecli_version";
14
+ /** Request header carrying the install id, so support can match a machine's events and reports. */
15
+ export declare const INSTALL_ID_HEADER = "X-VibeCLI-Install-Id";
@@ -1 +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";
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";
@@ -35,7 +35,9 @@ export declare function clientHeaders(): Record<string, string>;
35
35
  export declare function installClientHeaders(): void;
36
36
  /** Whether sends are still running (the CLI exits without waiting out their timeout). */
37
37
  export declare function telemetryPending(): boolean;
38
- /** API keys anywhere in a text (error messages, logs) become `sk-…abcd`. */
38
+ /** The user's home directory in a path or text becomes `~`, so the account name stays on the machine. */
39
+ export declare function maskHome(text: string): string;
40
+ /** API keys anywhere in a text (error messages, logs) become `sk-…abcd`; the home directory becomes `~`. */
39
41
  export declare function maskSecrets(text: string): string;
40
42
  /** The command this process runs (`setup`, `config`, … or `wizard`), recorded with every event. */
41
43
  export declare function setTelemetryCommand(name: string): void;
@@ -1 +1 @@
1
- import{randomUUID as e}from"crypto";import{arch as t,release as r}from"os";import{brand as n,brandEnv as o,CLI_NAME as s}from"./brand.js";import{clientVersion as a,installId as i}from"./client-config.js";import{configManager as c}from"./config.js";import{gatewayAddresses as l}from"./gateway-addresses.js";const u=e();let d="wizard",f=[];const m=new Set;let p=null,h=b;export function telemetryEnabled(){if(process.env.VITEST&&!g)return!1;const e=o("TELEMETRY")?.trim().toLowerCase();return!("0"===e||"false"===e||"off"===e)}let g=!1;export function setTelemetrySenderForTests(e){h=e??b,g=null!==e,f=[]}export function clientHeaders(){const e=`${s}/${a()} (${process.platform} ${r()}; ${t()}) node/${process.versions.node}`;return telemetryEnabled()?{"User-Agent":e,"X-VibeCLI-Install-Id":i()}:{"User-Agent":e}}export function installClientHeaders(){const e=globalThis.fetch;if(!e||e.vibecliHeaders)return;const t=(t,r)=>{try{const n=new URL("string"==typeof t||t instanceof URL?t.toString():t.url);if(new Set([c.getBaseUrl(),...l().map(e=>e.url)].map(e=>new URL(e).host)).has(n.host)){const n=new Headers(r?.headers??(t instanceof Request?t.headers:void 0));for(const[e,t]of Object.entries(clientHeaders()))n.has(e)||n.set(e,t);return e(t,{...r,headers:n})}}catch{}return e(t,r)};t.vibecliHeaders=!0,globalThis.fetch=t}export function telemetryPending(){return m.size>0}function y(){return{install_id:i(),cli_version:a(),brand:n().id,os:process.platform,os_release:r(),arch:t(),node_version:process.versions.node}}export function maskSecrets(e){return 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){d=e}export function track(e,t,r={}){if(!telemetryEnabled())return;const n=void 0===r.error?void 0:maskSecrets(r.error instanceof Error?r.error.message:String(r.error)).slice(0,2e3);f.push({ts:Date.now(),session:u,command:d,step:e,status:t,...void 0!==r.duration_ms?{duration_ms:Math.round(r.duration_ms)}:{},...n?{error:n}:{},...r.detail?{detail:r.detail}:{}}),"start"===t?w():p||(p=setTimeout(w,500),p.unref())}export async function trackStep(e,t,r){const n=Date.now();track(e,"start",r?{detail:r}:{});try{const r=await t();return track(e,"ok",{duration_ms:Date.now()-n}),r}catch(t){throw track(e,"fail",{duration_ms:Date.now()-n,error:t}),t}}function w(){if(p&&(clearTimeout(p),p=null),0===f.length)return;const e=f.splice(0,50),t=h("/api/platform/vibecode/telemetry",{...y(),events:e},3e3).then(()=>{},()=>{}).finally(()=>m.delete(t));m.add(t),f.length>0&&w()}export async function flushTelemetry(e=1500){w(),0!==m.size&&await Promise.race([Promise.allSettled([...m]),new Promise(t=>setTimeout(t,e).unref())])}export async function uploadReport(e){try{const t=await h("/api/platform/vibecode/report",{...y(),report:e},2e4),r=t?.data?.code;return"string"==typeof r&&r?r:null}catch{return null}}async function b(e,t,r){const n=c.getApiKey()?.trim(),o=await fetch(new URL(e,c.getBaseUrl()).toString(),{method:"POST",headers:{"Content-Type":"application/json",...clientHeaders(),...n?{Authorization:`Bearer ${n}`}:{}},body:JSON.stringify(t),signal:AbortSignal.timeout(r)});if(!o.ok)throw new Error(`HTTP ${o.status}`);return o.json().catch(()=>null)}
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)}
@@ -1 +1 @@
1
- import{spawnSync as t}from"child_process";import{existsSync as o,mkdtempSync as e,readFileSync as n,realpathSync as s,rmSync as r,statSync as i,writeFileSync as c}from"fs";import{tmpdir as l}from"os";import{delimiter as a,dirname as u,isAbsolute as d,join as p}from"path";import*as f from"@iarna/toml";import{fileURLToPath as m}from"url";import{logger as _}from"../../utils/logger.js";import{getCodexRules as x,compareVersions as g}from"../model-registry.js";import{autoCompactTokens as w,modelBlurb as h,prettyModelName as y}from"../gateway-models.js";import{toolHome as b}from"./types.js";import{brandEnv as v,PROVIDER_KEY as C}from"../brand.js";const M=u(m(import.meta.url));export const CODEX_CATALOG_FILE=`${C}-model-catalog.json`;export const codexCatalogPath=()=>p(b(),".codex",CODEX_CATALOG_FILE);function A(){const t=v("CODEX_BIN");if(void 0!==t)return t.trim()?[t.trim()]:[];const o=["codex"];if("win32"===process.platform){const t=process.env.LOCALAPPDATA||p(b(),"AppData","Local");o.push(p(t,"Programs","OpenAI","Codex","bin","codex.exe"))}else o.push(p(b(),".local","bin","codex"));if("darwin"===process.platform)for(const t of["/Applications",p(b(),"Applications")])o.push(p(t,"ChatGPT.app/Contents/Resources/codex-cli/bin/codex")),o.push(p(t,"Codex.app/Contents/Resources/codex"));return o}function j(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function O(t){try{const o=JSON.parse(t),e=j(o)&&Array.isArray(o.models)?o.models.filter(j):[];return e.length>0?e:null}catch{return null}}function E(o,e,n){const s={encoding:"utf-8",timeout:2e4,maxBuffer:67108864,windowsHide:!0,stdio:["ignore","pipe","pipe"],...n?{env:n}:{}};return"win32"!==process.platform||"codex"!==o&&!/\.cmd$/i.test(o)?t(o,e,s):t(["codex"===o?"codex":`"${o}"`,...e].join(" "),{...s,shell:!0})}function $(t){const o=E(t,["debug","models","--bundled"]);if(0===o.status&&o.stdout){const t=O(o.stdout);if(t)return t}return(o.error||0!==o.status)&&_.logError("loadBundledCodexModels",o.error??new Error(`${t} exited ${o.status}`)),null}export function loadBundledCodexModels(t){if(t)return $(t);for(const t of A()){if("codex"!==t&&!o(t))continue;const e=$(t);if(e)return e}return null}function k(t){try{return i(t).isFile()}catch{return!1}}export function installedCodexBinaries(){const t=[],o=A();if(o.includes("codex")){const o="win32"===process.platform?["codex.exe","codex.cmd"]:["codex"];for(const e of(process.env.PATH??"").split(a))if(e&&d(e))for(const n of o)t.push(p(e,n))}t.push(...o.filter(t=>"codex"!==t));const e=new Set,n=[];for(const o of t){if(!k(o))continue;let t=o;try{t=s(o)}catch{}const r="win32"===process.platform?t.toLowerCase():t;e.has(r)||(e.add(r),n.push(o))}return n}export function codexBinaryVersion(t){const o=`${E(t,["--version"]).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return o?o[0]:null}export function catalogRejections(t,o=installedCodexBinaries()){if(0===o.length)return[];const n=e(p(l(),"vibecli-codex-")),s=[];try{c(p(n,"config.toml"),f.stringify({model_catalog_json:t}));for(const t of o){const o=E(t,["debug","models"],{...process.env,CODEX_HOME:n});if(0===o.status)continue;const e=`${o.stderr??""}\n${o.stdout??""}`,r=e.split(/\r?\n/).find(t=>t.includes("model_catalog_json"));r?s.push({bin:t,version:codexBinaryVersion(t),error:r.trim()}):_.logError("catalogRejections",o.error??new Error(`${t} exited ${o.status}: ${e.trim().slice(0,500)}`))}}finally{r(n,{recursive:!0,force:!0})}return s}export function loadPreviousCodexModels(){const t=P()?.filter(t=>!B(t));return t&&t.length>0?t:null}export function previousGatewayModelIds(){return(P()??[]).filter(B).map(t=>String(t.slug))}function P(){return o(codexCatalogPath())?O(n(codexCatalogPath(),"utf-8")):null}function B(t){return"number"==typeof t.priority&&t.priority>=1e3}let L=null;function S(){if(null!==L)return L;const t=[p(M,"..","..","..","codex-base-instructions.md"),p(M,"..","..","codex-base-instructions.md"),p(M,"codex-base-instructions.md")],e=t.find(t=>o(t));if(!e)throw new Error(`codex-base-instructions.md not found, searched: ${t.join(", ")}`);return L=n(e,"utf-8"),L}function T(t){return"number"==typeof t&&Number.isFinite(t)&&t>0?t:void 0}function D(t,o,e,n){const s=e?t:Math.min(t,o);return{window:s,compact:w(s,n)}}function F(t,o,e,n){const{standardContextWindow:s}=x();let r=T(t.contextWindow)??s;n&&t.id.startsWith("claude-")&&(r=n.has(t.id)?Math.max(r,1e6):Math.min(r,2e5));const{window:i,compact:c}=D(r,s,e,T(t.autoCompactTokens));return{slug:t.id,display_name:t.name||y(t.id),description:h(t.description,{millionContext:i>=1e6})??null,supported_reasoning_levels:[],shell_type:"unified_exec",visibility:"list",supported_in_api:!0,priority:o,additional_speed_tiers:[],service_tiers:[],availability_nux:null,upgrade:null,model_messages:{instructions_template:S()},base_instructions:S(),supports_reasoning_summaries:!0,supports_parallel_tool_calls:!1,prefer_websockets:!1,include_skills_usage_instructions:!1,include_plugin_usage_instructions:!1,include_apps_usage_instructions:!1,default_reasoning_summary:"auto",support_verbosity:!1,default_verbosity:null,apply_patch_tool_type:null,web_search_tool_type:"text",truncation_policy:{mode:"bytes",limit:1e4},supports_image_detail_original:!1,context_window:i,max_context_window:i,auto_compact_token_limit:c,effective_context_window_percent:95,experimental_supported_tools:[],input_modalities:["text","image"],supports_search_tool:!1,supports_experimental_context:!1,use_responses_lite:!1,supports_reasoning_effort_updates:!1,node_repl_auto_review_required:!1,node_repl_disabled:!1}}const I={supports_parallel_tool_calls:!0,supports_reasoning_summaries:!0};export function fillFromOlderEntries(t,o){const e=new Map(o.map(t=>[t.slug,t])),n=new Map;for(const t of o)for(const[o,e]of Object.entries(t))n.has(o)||n.set(o,e);return t.map(t=>{const o=e.get(t.slug),s={...t};for(const[t,e]of n)t in s||(s[t]=o&&t in o?o[t]:e);return s})}function W(t,o,e){if("list"!==(t=function(t){const o=Object.keys(I).filter(o=>!(o in t));return 0===o.length?t:{...t,...Object.fromEntries(o.map(t=>[t,I[t]]))}}(t)).visibility)return t;const n=T(t.context_window);if(!n)return t;const s=T(t.max_context_window)??n,r=e?Math.min(T(o?.contextWindow)??s,s):n,{window:i,compact:c}=D(r,n,!0,T(o?.autoCompactTokens));return{...t,context_window:i,auto_compact_token_limit:c}}export function buildCodexCatalog(t){const{bundled:o,specs:e,oneMillion:n,selectedModel:s}=t,r=t.claudeOneMillion?new Set(t.claudeOneMillion):void 0,i=t.keyModels?new Set(t.keyModels):null,c=new Set(t.gatewayAvailable),l=t=>!i||i.has(t)||t===s,a=t=>c.has(t)||t===s,u=new Map(e.map(t=>[t.id,t])),d=[],p=new Set;for(const t of o){const o="string"==typeof t.slug?t.slug:"";o&&!p.has(o)&&("list"!==t.visibility||l(o))&&(p.add(o),d.push(W(t,u.get(o),n)))}const f=[...e];s&&!u.has(s)&&f.push({id:s});const m=function(t){const o=new Map;for(const e of t){const t=/^claude-([a-z]+)-(.+)$/.exec(e);if(!t)continue;const n=t[2].split("-").filter(t=>/^\d{1,2}$/.test(t)).join("."),s=o.get(t[1]);(!s||g(n,s.version)>0)&&o.set(t[1],{id:e,version:n})}return new Set([...o.values()].map(t=>t.id))}(f.map(t=>t.id).filter(a));for(const t of f)!p.has(t.id)&&a(t.id)&&(t.id.startsWith("claude-")&&!m.has(t.id)&&t.id!==s||(p.add(t.id),d.push(F(t,1e3+d.length,n,r))));return{models:d}}
1
+ import{spawnSync as t}from"child_process";import{existsSync as o,mkdtempSync as e,readFileSync as n,realpathSync as s,rmSync as r,statSync as i,writeFileSync as c}from"fs";import{tmpdir as l}from"os";import{delimiter as a,dirname as u,isAbsolute as d,join as p}from"path";import*as f from"@iarna/toml";import{fileURLToPath as m}from"url";import{logger as _}from"../../utils/logger.js";import{getCodexRules as x,compareVersions as g}from"../model-registry.js";import{autoCompactTokens as w,modelBlurb as h,prettyModelName as y}from"../gateway-models.js";import{toolHome as b}from"./types.js";import{brandEnv as C,CLI_NAME as v,PROVIDER_KEY as M}from"../brand.js";const A=u(m(import.meta.url));export const CODEX_CATALOG_FILE=`${M}-model-catalog.json`;export const codexCatalogPath=()=>p(b(),".codex",CODEX_CATALOG_FILE);function j(){const t=C("CODEX_BIN");if(void 0!==t)return t.trim()?[t.trim()]:[];const o=["codex"];if("win32"===process.platform){const t=process.env.LOCALAPPDATA||p(b(),"AppData","Local");o.push(p(t,"Programs","OpenAI","Codex","bin","codex.exe"))}else o.push(p(b(),".local","bin","codex"));if("darwin"===process.platform)for(const t of["/Applications",p(b(),"Applications")])o.push(p(t,"ChatGPT.app/Contents/Resources/codex-cli/bin/codex")),o.push(p(t,"Codex.app/Contents/Resources/codex"));return o}function O(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function $(t){try{const o=JSON.parse(t),e=O(o)&&Array.isArray(o.models)?o.models.filter(O):[];return e.length>0?e:null}catch{return null}}function E(o,e,n){const s={encoding:"utf-8",timeout:2e4,maxBuffer:67108864,windowsHide:!0,stdio:["ignore","pipe","pipe"],...n?{env:n}:{}};return"win32"!==process.platform||"codex"!==o&&!/\.cmd$/i.test(o)?t(o,e,s):t(["codex"===o?"codex":`"${o}"`,...e].join(" "),{...s,shell:!0})}function k(t){const o=E(t,["debug","models","--bundled"]);if(0===o.status&&o.stdout){const t=$(o.stdout);if(t)return t}return(o.error||0!==o.status)&&_.logError("loadBundledCodexModels",o.error??new Error(`${t} exited ${o.status}`)),null}export function loadBundledCodexModels(t){if(t)return k(t);for(const t of j()){if("codex"!==t&&!o(t))continue;const e=k(t);if(e)return e}return null}function P(t){try{return i(t).isFile()}catch{return!1}}export function installedCodexBinaries(){const t=[],o=j();if(o.includes("codex")){const o="win32"===process.platform?["codex.exe","codex.cmd"]:["codex"];for(const e of(process.env.PATH??"").split(a))if(e&&d(e))for(const n of o)t.push(p(e,n))}t.push(...o.filter(t=>"codex"!==t));const e=new Set,n=[];for(const o of t){if(!P(o))continue;let t=o;try{t=s(o)}catch{}const r="win32"===process.platform?t.toLowerCase():t;e.has(r)||(e.add(r),n.push(o))}return n}export function codexBinaryVersion(t){const o=`${E(t,["--version"]).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return o?o[0]:null}export function catalogRejections(t,o=installedCodexBinaries()){if(0===o.length)return[];const n=e(p(l(),`${v}-codex-`)),s=[];try{c(p(n,"config.toml"),f.stringify({model_catalog_json:t}));for(const t of o){const o=E(t,["debug","models"],{...process.env,CODEX_HOME:n});if(0===o.status)continue;const e=`${o.stderr??""}\n${o.stdout??""}`,r=e.split(/\r?\n/).find(t=>t.includes("model_catalog_json"));r?s.push({bin:t,version:codexBinaryVersion(t),error:r.trim()}):_.logError("catalogRejections",o.error??new Error(`${t} exited ${o.status}: ${e.trim().slice(0,500)}`))}}finally{r(n,{recursive:!0,force:!0})}return s}export function loadPreviousCodexModels(){const t=B()?.filter(t=>!L(t));return t&&t.length>0?t:null}export function previousGatewayModelIds(){return(B()??[]).filter(L).map(t=>String(t.slug))}function B(){return o(codexCatalogPath())?$(n(codexCatalogPath(),"utf-8")):null}function L(t){return"number"==typeof t.priority&&t.priority>=1e3}let S=null;function T(){if(null!==S)return S;const t=[p(A,"..","..","..","codex-base-instructions.md"),p(A,"..","..","codex-base-instructions.md"),p(A,"codex-base-instructions.md")],e=t.find(t=>o(t));if(!e)throw new Error(`codex-base-instructions.md not found, searched: ${t.join(", ")}`);return S=n(e,"utf-8"),S}function D(t){return"number"==typeof t&&Number.isFinite(t)&&t>0?t:void 0}function F(t,o,e,n){const s=e?t:Math.min(t,o);return{window:s,compact:w(s,n)}}function I(t,o,e,n){const{standardContextWindow:s}=x();let r=D(t.contextWindow)??s;n&&t.id.startsWith("claude-")&&(r=n.has(t.id)?Math.max(r,1e6):Math.min(r,2e5));const{window:i,compact:c}=F(r,s,e,D(t.autoCompactTokens));return{slug:t.id,display_name:t.name||y(t.id),description:h(t.description,{millionContext:i>=1e6})??null,supported_reasoning_levels:[],shell_type:"unified_exec",visibility:"list",supported_in_api:!0,priority:o,additional_speed_tiers:[],service_tiers:[],availability_nux:null,upgrade:null,model_messages:{instructions_template:T()},base_instructions:T(),supports_reasoning_summaries:!0,supports_parallel_tool_calls:!1,prefer_websockets:!1,include_skills_usage_instructions:!1,include_plugin_usage_instructions:!1,include_apps_usage_instructions:!1,default_reasoning_summary:"auto",support_verbosity:!1,default_verbosity:null,apply_patch_tool_type:null,web_search_tool_type:"text",truncation_policy:{mode:"bytes",limit:1e4},supports_image_detail_original:!1,context_window:i,max_context_window:i,auto_compact_token_limit:c,effective_context_window_percent:95,experimental_supported_tools:[],input_modalities:["text","image"],supports_search_tool:!1,supports_experimental_context:!1,use_responses_lite:!1,supports_reasoning_effort_updates:!1,node_repl_auto_review_required:!1,node_repl_disabled:!1}}const W={supports_parallel_tool_calls:!0,supports_reasoning_summaries:!0};export function fillFromOlderEntries(t,o){const e=new Map(o.map(t=>[t.slug,t])),n=new Map;for(const t of o)for(const[o,e]of Object.entries(t))n.has(o)||n.set(o,e);return t.map(t=>{const o=e.get(t.slug),s={...t};for(const[t,e]of n)t in s||(s[t]=o&&t in o?o[t]:e);return s})}function G(t,o,e){if("list"!==(t=function(t){const o=Object.keys(W).filter(o=>!(o in t));return 0===o.length?t:{...t,...Object.fromEntries(o.map(t=>[t,W[t]]))}}(t)).visibility)return t;const n=D(t.context_window);if(!n)return t;const s=D(t.max_context_window)??n,r=e?Math.min(D(o?.contextWindow)??s,s):n,{window:i,compact:c}=F(r,n,!0,D(o?.autoCompactTokens));return{...t,context_window:i,auto_compact_token_limit:c}}export function buildCodexCatalog(t){const{bundled:o,specs:e,oneMillion:n,selectedModel:s}=t,r=t.claudeOneMillion?new Set(t.claudeOneMillion):void 0,i=t.keyModels?new Set(t.keyModels):null,c=new Set(t.gatewayAvailable),l=t=>!i||i.has(t)||t===s,a=t=>c.has(t)||t===s,u=new Map(e.map(t=>[t.id,t])),d=[],p=new Set;for(const t of o){const o="string"==typeof t.slug?t.slug:"";o&&!p.has(o)&&("list"!==t.visibility||l(o))&&(p.add(o),d.push(G(t,u.get(o),n)))}const f=[...e];s&&!u.has(s)&&f.push({id:s});const m=function(t){const o=new Map;for(const e of t){const t=/^claude-([a-z]+)-(.+)$/.exec(e);if(!t)continue;const n=t[2].split("-").filter(t=>/^\d{1,2}$/.test(t)).join("."),s=o.get(t[1]);(!s||g(n,s.version)>0)&&o.set(t[1],{id:e,version:n})}return new Set([...o.values()].map(t=>t.id))}(f.map(t=>t.id).filter(a));for(const t of f)!p.has(t.id)&&a(t.id)&&(t.id.startsWith("claude-")&&!m.has(t.id)&&t.id!==s||(p.add(t.id),d.push(I(t,1e3+d.length,n,r))));return{models:d}}
@@ -1 +1 @@
1
- import{createHash as e}from"crypto";import{existsSync as t,mkdirSync as o,readFileSync as n,rmSync as r,statSync as i,writeFileSync as l}from"fs";import{join as a}from"path";import*as s from"@iarna/toml";import{logger as c}from"../../utils/logger.js";import{i18n as d}from"../i18n.js";import{backupBeforeWrite as u,atomicWriteFile as m}from"./backup.js";import{pickModel as f,toolHome as p,withV1 as g}from"./types.js";import{getToolDefaultModel as _}from"../model-registry.js";import{configManager as x}from"../config.js";import{track as y}from"../telemetry.js";import{buildCodexCatalog as h,catalogRejections as k,codexCatalogPath as b,fillFromOlderEntries as j,installedCodexBinaries as v,loadBundledCodexModels as w,loadPreviousCodexModels as O,previousGatewayModelIds as C}from"./codex-catalog.js";import{gatewayModelSpecs as M,modelFamily as E}from"../gateway-models.js";import{mirrorInstallCommand as N,brandInstallScripts as S}from"./tool-installs.js";const A=()=>a(p(),".codex"),P=()=>a(A(),"config.toml"),T=()=>a(A(),"auth.json"),D="OPENAI_API_KEY",I="custom",$=1e6,J=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function L(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function K(e,t){return L(e[t])||(e[t]={}),e[t]}function X(){if(!t(P()))return{};const e=n(P(),"utf-8");if(!e.trim())return{};try{const t=s.parse(e);if(!L(t))throw new Error("config.toml root must be a TOML table");return t}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function B(){if(!t(T()))return{};try{const e=JSON.parse(n(T(),"utf-8"));return L(e)?e:{}}catch{return{}}}let q=null;function G(e){const t=e.profiles;if(L(t)){for(const[e,o]of Object.entries(t))L(o)&&2===Object.keys(o).length&&o.model_provider===I&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let z=null;const R=()=>a(x.getConfigDir(),"codex-catalog-check.json");function U(e){const o=b();t(o)&&n(o,"utf-8")===e||(u(o),m(o,e))}function Y(t,r){if(0===r.length)return[];const a=function(t,o){const n=e("sha256").update(t);for(const e of o)try{const t=i(e);n.update(`\0${e}\0${t.size}\0${t.mtimeMs}`)}catch{n.update(`\0${e}`)}return n.digest("hex")}(t,r);if(function(e){try{return JSON.parse(n(R(),"utf-8")).signature===e}catch{return!1}}(a))return[];const s=k(b(),r);return 0===s.length&&function(e){try{o(x.getConfigDir(),{recursive:!0}),l(R(),JSON.stringify({signature:e})+"\n")}catch(e){c.logError("codexAdapter.rememberAccepted",e)}}(a),s}function F(e,t,o){const n=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===$&&delete e.model_context_window,e.model_auto_compact_token_limit===J&&delete e.model_auto_compact_token_limit}(e);const i=()=>{e.model_catalog_json===b()&&delete e.model_catalog_json,n&&(e.model_context_window=$,e.model_auto_compact_token_limit=J)},l=w()??O();if(!l)return c.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),z="skipped",void i();const a=t.catalog,s=e=>h({bundled:e,specs:M("codex",a?.clientModels),...a?{keyModels:a.models}:{},gatewayAvailable:a?.models??C(),oneMillion:n,selectedModel:o,..."gateway"===a?.oneMillionSource?{claudeOneMillion:a.oneMillion}:{}}),d=e=>JSON.stringify(e,null,2)+"\n";let u=s(l);U(d(u));const m=v(),f=Y(d(u),m);if(f.length>0){const e=Date.now();let t=!1;for(const e of f){const o=w(e.bin);if(o){for(const e of[{models:j(u.models,o)},{models:j(s(o).models,o)}])if(U(d(e)),0===Y(d(e),m).length){u=e,t=!0;break}if(t)break}}if(y("codex-catalog",t?"fallback":"fail",{duration_ms:Date.now()-e,error:f[0].error,detail:{rejected_by:f.map(e=>({version:e.version,path:e.bin}))}}),!t)return z={rejectedBy:f[0]},r(b(),{force:!0}),void i()}z={listed:u.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))},e.model_catalog_json=b()}export function codexCatalogRejection(){let e;try{e=X()}catch{return null}return e.model_catalog_json===b()&&t(b())?k(b())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=X(),n=s.stringify(o),r="string"==typeof o.model?o.model:_("codex");F(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=s.stringify(o);i!==n&&(u(P()),m(P(),i))}const H={command:"codex",npmPackage:"@openai/codex",native:{binDir:"win32"===process.platform?["AppData","Local","Programs","OpenAI","Codex","bin"]:[".local","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".codex","packages","standalone"]]},mirrorScript:S("codex"),brew:"codex"};export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:N(H),installSpec:H,configPath:P(),wantsModelCatalog:!0,listedModels(){if(X().model_catalog_json!==b())return null;try{return(JSON.parse(n(b(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){X().model_catalog_json===b()&&setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog)},applyNotes(){if("skipped"===z)return[{kind:"action",text:d.t("tools.codex.catalog_skipped")}];if(!z)return[];if("rejectedBy"in z){const{bin:e,version:t}=z.rejectedBy;return[{kind:"action",text:d.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of z.listed)e.set(E(t.id),(e.get(E(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${d.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:d.t("tools.codex.catalog_written",{count:String(z.listed.length),breakdown:t})},{kind:"detail",text:z.listed.map(e=>e.name).join(", ")}]},loadPrivateConfig(e){const t=_("codex"),o=f(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,r=g(e.baseUrl),i=X();i.model=n,i.model_provider=I,i.model_reasoning_effort="high",F(i,e,n);const l=K(i,"model_providers"),a=L(l[I])?{...l[I]}:{};delete a.env_key;const{experimental_bearer_token:c,...d}=a;l[I]={...d,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:r},G(i),K(K(i,"tui"),"model_availability_nux")[n]=4;const p=K(i,"features");p.goals=!0,p.js_repl=!1,u(P()),m(P(),s.stringify(i)),function(e){const t=e.trim();if(!t)return;const o={...B(),auth_mode:"apikey",[D]:t};u(T()),m(T(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},unloadPrivateConfig(e){if(q=function(e){const t=B(),o="string"==typeof t[D]?t[D].trim():"";if(!o)return L(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[D]:n,auth_mode:i,...l}=t;return u(T()),L(l.tokens)?(m(T(),JSON.stringify({...l,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(r(T(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(P()))return;let o;try{o=X()}catch(e){return void c.logError("codexAdapter.unloadPrivateConfig",e)}const n=o.model_providers;L(n)&&(delete n[I],0===Object.keys(n).length&&delete o.model_providers),o.model_provider===I&&delete o.model_provider,o.model_catalog_json===b()&&delete o.model_catalog_json,G(o),u(P()),m(P(),s.stringify(o))},unloadNotes(){switch(q){case"chatgpt":return[{kind:"action",text:d.t("tools.codex.unload_chatgpt_restored")}];case"other_key":return[{kind:"action",text:d.t("tools.codex.unload_other_key")}];default:return[{kind:"action",text:d.t("tools.codex.unload_sign_in")}]}},detectCurrentConfig(){const e=B()[D];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return X()}catch(e){return c.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[P(),T(),b()]};export function codexAuthProblem(){try{const e=X(),t=e.model_providers?.[I];if(e.model_provider!==I||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=B();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
1
+ import{createHash as e}from"crypto";import{existsSync as t,mkdirSync as o,readFileSync as n,rmSync as r,statSync as i,writeFileSync as l}from"fs";import{join as a}from"path";import*as s from"@iarna/toml";import{logger as c}from"../../utils/logger.js";import{i18n as d}from"../i18n.js";import{backupBeforeWrite as u,atomicWriteFile as m}from"./backup.js";import{pickModel as f,toolHome as p,withV1 as g}from"./types.js";import{getToolDefaultModel as _}from"../model-registry.js";import{configManager as x}from"../config.js";import{maskHome as y,track as h}from"../telemetry.js";import{buildCodexCatalog as k,catalogRejections as b,codexCatalogPath as j,fillFromOlderEntries as v,installedCodexBinaries as w,loadBundledCodexModels as O,loadPreviousCodexModels as C,previousGatewayModelIds as M}from"./codex-catalog.js";import{gatewayModelSpecs as E,modelFamily as N}from"../gateway-models.js";import{mirrorInstallCommand as S,brandInstallScripts as A}from"./tool-installs.js";const P=()=>a(p(),".codex"),T=()=>a(P(),"config.toml"),D=()=>a(P(),"auth.json"),I="OPENAI_API_KEY",$="custom",J=1e6,L=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function K(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function X(e,t){return K(e[t])||(e[t]={}),e[t]}function B(){if(!t(T()))return{};const e=n(T(),"utf-8");if(!e.trim())return{};try{const t=s.parse(e);if(!K(t))throw new Error("config.toml root must be a TOML table");return t}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function q(){if(!t(D()))return{};try{const e=JSON.parse(n(D(),"utf-8"));return K(e)?e:{}}catch{return{}}}let G=null;function z(e){const t=e.profiles;if(K(t)){for(const[e,o]of Object.entries(t))K(o)&&2===Object.keys(o).length&&o.model_provider===$&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let R=null;const U=()=>a(x.getConfigDir(),"codex-catalog-check.json");function Y(e){const o=j();t(o)&&n(o,"utf-8")===e||(u(o),m(o,e))}function F(t,r){if(0===r.length)return[];const a=function(t,o){const n=e("sha256").update(t);for(const e of o)try{const t=i(e);n.update(`\0${e}\0${t.size}\0${t.mtimeMs}`)}catch{n.update(`\0${e}`)}return n.digest("hex")}(t,r);if(function(e){try{return JSON.parse(n(U(),"utf-8")).signature===e}catch{return!1}}(a))return[];const s=b(j(),r);return 0===s.length&&function(e){try{o(x.getConfigDir(),{recursive:!0}),l(U(),JSON.stringify({signature:e})+"\n")}catch(e){c.logError("codexAdapter.rememberAccepted",e)}}(a),s}function H(e,t,o){const n=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===J&&delete e.model_context_window,e.model_auto_compact_token_limit===L&&delete e.model_auto_compact_token_limit}(e);const i=()=>{e.model_catalog_json===j()&&delete e.model_catalog_json,n&&(e.model_context_window=J,e.model_auto_compact_token_limit=L)},l=O()??C();if(!l)return c.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),R="skipped",void i();const a=t.catalog,s=e=>k({bundled:e,specs:E("codex",a?.clientModels),...a?{keyModels:a.models}:{},gatewayAvailable:a?.models??M(),oneMillion:n,selectedModel:o,..."gateway"===a?.oneMillionSource?{claudeOneMillion:a.oneMillion}:{}}),d=e=>JSON.stringify(e,null,2)+"\n";let u=s(l);Y(d(u));const m=w(),f=F(d(u),m);if(f.length>0){const e=Date.now();let t=!1;for(const e of f){const o=O(e.bin);if(o){for(const e of[{models:v(u.models,o)},{models:v(s(o).models,o)}])if(Y(d(e)),0===F(d(e),m).length){u=e,t=!0;break}if(t)break}}if(h("codex-catalog",t?"fallback":"fail",{duration_ms:Date.now()-e,error:f[0].error,detail:{rejected_by:f.map(e=>({version:e.version,path:y(e.bin)}))}}),!t)return R={rejectedBy:f[0]},r(j(),{force:!0}),void i()}R={listed:u.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))},e.model_catalog_json=j()}export function codexCatalogRejection(){let e;try{e=B()}catch{return null}return e.model_catalog_json===j()&&t(j())?b(j())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=B(),n=s.stringify(o),r="string"==typeof o.model?o.model:_("codex");H(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=s.stringify(o);i!==n&&(u(T()),m(T(),i))}const Q={command:"codex",npmPackage:"@openai/codex",native:{binDir:"win32"===process.platform?["AppData","Local","Programs","OpenAI","Codex","bin"]:[".local","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".codex","packages","standalone"]]},mirrorScript:A("codex"),brew:"codex"};export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:S(Q),installSpec:Q,configPath:T(),wantsModelCatalog:!0,listedModels(){if(B().model_catalog_json!==j())return null;try{return(JSON.parse(n(j(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){B().model_catalog_json===j()&&setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog)},applyNotes(){if("skipped"===R)return[{kind:"action",text:d.t("tools.codex.catalog_skipped")}];if(!R)return[];if("rejectedBy"in R){const{bin:e,version:t}=R.rejectedBy;return[{kind:"action",text:d.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of R.listed)e.set(N(t.id),(e.get(N(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${d.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:d.t("tools.codex.catalog_written",{count:String(R.listed.length),breakdown:t})},{kind:"detail",text:R.listed.map(e=>e.name).join(", ")}]},loadPrivateConfig(e){const t=_("codex"),o=f(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,r=g(e.baseUrl),i=B();i.model=n,i.model_provider=$,i.model_reasoning_effort="high",H(i,e,n);const l=X(i,"model_providers"),a=K(l[$])?{...l[$]}:{};delete a.env_key;const{experimental_bearer_token:c,...d}=a;l[$]={...d,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:r},z(i),X(X(i,"tui"),"model_availability_nux")[n]=4;const p=X(i,"features");p.goals=!0,p.js_repl=!1,u(T()),m(T(),s.stringify(i)),function(e){const t=e.trim();if(!t)return;const o={...q(),auth_mode:"apikey",[I]:t};u(D()),m(D(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},unloadPrivateConfig(e){if(G=function(e){const t=q(),o="string"==typeof t[I]?t[I].trim():"";if(!o)return K(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[I]:n,auth_mode:i,...l}=t;return u(D()),K(l.tokens)?(m(D(),JSON.stringify({...l,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(r(D(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(T()))return;let o;try{o=B()}catch(e){return void c.logError("codexAdapter.unloadPrivateConfig",e)}const n=o.model_providers;K(n)&&(delete n[$],0===Object.keys(n).length&&delete o.model_providers),o.model_provider===$&&delete o.model_provider,o.model_catalog_json===j()&&delete o.model_catalog_json,z(o),u(T()),m(T(),s.stringify(o))},unloadNotes(){switch(G){case"chatgpt":return[{kind:"action",text:d.t("tools.codex.unload_chatgpt_restored")}];case"other_key":return[{kind:"action",text:d.t("tools.codex.unload_other_key")}];default:return[{kind:"action",text:d.t("tools.codex.unload_sign_in")}]}},detectCurrentConfig(){const e=q()[I];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return B()}catch(e){return c.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[T(),D(),j()]};export function codexAuthProblem(){try{const e=B(),t=e.model_providers?.[$];if(e.model_provider!==$||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=q();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeapi/api-helper",
3
- "version": "0.0.112",
3
+ "version": "0.0.113",
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",