@vibeapi/api-helper 0.0.121 → 0.0.122

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,3 +1,4 @@
1
+ import { codexHome } from './tools/types.js';
1
2
  /**
2
3
  * Codex lists only the threads whose `model_provider` matches the provider it is
3
4
  * using now (`threads.model_provider IN (…)` in its state DB, source:
@@ -21,7 +22,7 @@ export interface SessionMoveResult {
21
22
  dbSkipped: string | null;
22
23
  backupDir: string | null;
23
24
  }
24
- export declare function codexHome(): string;
25
+ export { codexHome };
25
26
  /** The provider Codex uses now: `model_provider` in config.toml, else the built-in `openai`. */
26
27
  export declare function currentCodexProvider(): string;
27
28
  /** Tests replace the process probe. */
@@ -1 +1 @@
1
- import{spawnSync as e}from"child_process";import{closeSync as o,copyFileSync as t,createReadStream as r,createWriteStream as n,existsSync as s,mkdirSync as i,openSync as a,readFileSync as c,readSync as f,readdirSync as l,renameSync as d,statSync as m,utimesSync as p,writeFileSync as u}from"fs";import{join as h}from"path";import{pipeline as y}from"stream/promises";import*as g from"@iarna/toml";import{toolHome as b}from"./tools/types.js";import{CLI_NAME as v}from"./brand.js";export function codexHome(){return process.env.CODEX_HOME?.trim()||h(b(),".codex")}export function currentCodexProvider(){try{const e=g.parse(c(h(codexHome(),"config.toml"),"utf-8"));return"string"==typeof e.model_provider&&e.model_provider.trim()?e.model_provider.trim():"openai"}catch{return"openai"}}let x=()=>"win32"===process.platform?`${e("powershell.exe",["-NoProfile","-NonInteractive","-Command","(Get-Process -Name codex -ErrorAction SilentlyContinue).Id"],{encoding:"utf-8",windowsHide:!0}).stdout??""}`.split(/\s+/).filter(Boolean).map(Number):`${e("pgrep",["-x","-i","codex"],{encoding:"utf-8"}).stdout??""}`.split(/\s+/).filter(Boolean).map(Number);export function setCodexProcessCheckForTests(e){x=e}export function runningCodexPids(){try{return x()}catch{return[]}}function S(e){const t=a(e,"r");try{const e=[],o=Buffer.alloc(65536);for(;;){const r=f(t,o,0,o.length,null);if(r<=0)break;const n=o.subarray(0,r).indexOf(10);if(n>=0){e.push(Buffer.from(o.subarray(0,n)));break}e.push(Buffer.from(o.subarray(0,r)))}return Buffer.concat(e).toString("utf-8")}finally{o(t)}}async function w(e,o,t){const{atime:s,mtime:i}=m(e),a=`${e}.${v}-tmp`,c=n(a);c.write(o),await y(r(e,{start:t}),c),d(a,e),p(e,s,i)}async function E(e){try{return new((await import("node:sqlite")).DatabaseSync)(e)}catch(e){return`node:sqlite unavailable (Node ${process.versions.node}; needs 22.13+): ${e instanceof Error?e.message:String(e)}`}}export async function moveSessionsToProvider(e,o={}){const r=function(){const e=[],o=t=>{if(s(t))for(const r of l(t,{withFileTypes:!0})){const n=h(t,r.name);r.isDirectory()?o(n):r.isFile()&&r.name.endsWith(".jsonl")&&e.push(n)}};return o(h(codexHome(),"sessions")),o(h(codexHome(),"archived_sessions")),e}(),n=[];for(const o of r){let t,r;try{t=S(o)}catch{continue}try{r=JSON.parse(t)}catch{continue}const s=r.payload?.model_provider;"session_meta"===r.type&&"string"==typeof s&&s!==e&&(r.payload.model_provider=e,n.push({file:o,from:s,line:JSON.stringify(r),length:Buffer.byteLength(t,"utf-8")}))}const a=function(){const e=codexHome();if(!s(e))return null;const o=l(e).map(e=>/^state_(\d+)\.sqlite$/.exec(e)).filter(e=>!!e).sort((e,o)=>Number(o[1])-Number(e[1]));return o.length>0?h(e,o[0][0]):null}();let c=a?null:"no state DB",f=[],d=null;if(a){const o=await E(a);"string"==typeof o?c=o:(d=o,f=d.prepare('SELECT id, model_provider AS "from" FROM threads WHERE model_provider <> ?').all(e).map(e=>({id:String(e.id),from:String(e.from)})))}const m={target:e,scanned:r.length,moved:n.map(({file:e,from:o})=>({file:e,from:o})),dbRows:f.length,dbSkipped:c,backupDir:null};if(o.dryRun||0===n.length&&0===f.length)return d?.close(),m;const p=h(codexHome(),"backups",`${v}-sessions-${(new Date).toISOString().replace(/[:.]/g,"-")}`);if(i(p,{recursive:!0}),a)for(const e of["","-wal","-shm"])s(a+e)&&t(a+e,h(p,`state.sqlite${e}`));const y={target:e,moved:m.moved,threads:f,db:a};u(h(p,"manifest.json"),JSON.stringify(y,null,2)+"\n");for(const e of n)await w(e.file,e.line,e.length);return d&&(d.prepare("UPDATE threads SET model_provider = ? WHERE model_provider <> ?").run(e,e),d.close()),m.backupDir=p,m}export async function undoSessionMove(e){const o=JSON.parse(c(h(e,"manifest.json"),"utf-8"));let t=0;for(const{file:e,from:r}of o.moved){if(!s(e))continue;const o=S(e),n=JSON.parse(o);n.payload&&(n.payload.model_provider=r,await w(e,JSON.stringify(n),Buffer.byteLength(o,"utf-8")),t+=1)}let r=0;if(o.db&&s(o.db)&&o.threads.length>0){const e=await E(o.db);if("string"!=typeof e){const t=e.prepare("UPDATE threads SET model_provider = ? WHERE id = ?");for(const{id:e,from:n}of o.threads)r+=Number(t.run(n,e).changes);e.close()}}return{files:t,dbRows:r}}
1
+ import{spawnSync as e}from"child_process";import{closeSync as t,copyFileSync as r,createReadStream as o,createWriteStream as n,existsSync as s,mkdirSync as i,openSync as a,readFileSync as f,readSync as l,readdirSync as c,renameSync as d,statSync as p,utimesSync as m,writeFileSync as u}from"fs";import{join as h}from"path";import{pipeline as y}from"stream/promises";import*as g from"@iarna/toml";import{codexHome as b}from"./tools/types.js";import{CLI_NAME as v}from"./brand.js";export{b as codexHome};export function currentCodexProvider(){try{const e=g.parse(f(h(b(),"config.toml"),"utf-8"));return"string"==typeof e.model_provider&&e.model_provider.trim()?e.model_provider.trim():"openai"}catch{return"openai"}}let S=()=>"win32"===process.platform?`${e("powershell.exe",["-NoProfile","-NonInteractive","-Command","(Get-Process -Name codex -ErrorAction SilentlyContinue).Id"],{encoding:"utf-8",windowsHide:!0}).stdout??""}`.split(/\s+/).filter(Boolean).map(Number):`${e("pgrep",["-x","-i","codex"],{encoding:"utf-8"}).stdout??""}`.split(/\s+/).filter(Boolean).map(Number);export function setCodexProcessCheckForTests(e){S=e}export function runningCodexPids(){try{return S()}catch{return[]}}function w(e){const r=a(e,"r");try{const e=[],t=Buffer.alloc(65536);for(;;){const o=l(r,t,0,t.length,null);if(o<=0)break;const n=t.subarray(0,o).indexOf(10);if(n>=0){e.push(Buffer.from(t.subarray(0,n)));break}e.push(Buffer.from(t.subarray(0,o)))}return Buffer.concat(e).toString("utf-8")}finally{t(r)}}async function x(e,t,r){const{atime:s,mtime:i}=p(e),a=`${e}.${v}-tmp`,f=n(a);f.write(t),await y(o(e,{start:r}),f),d(a,e),m(e,s,i)}async function N(e){try{return new((await import("node:sqlite")).DatabaseSync)(e)}catch(e){return`node:sqlite unavailable (Node ${process.versions.node}; needs 22.13+): ${e instanceof Error?e.message:String(e)}`}}export async function moveSessionsToProvider(e,t={}){const o=function(){const e=[],t=r=>{if(s(r))for(const o of c(r,{withFileTypes:!0})){const n=h(r,o.name);o.isDirectory()?t(n):o.isFile()&&o.name.endsWith(".jsonl")&&e.push(n)}};return t(h(b(),"sessions")),t(h(b(),"archived_sessions")),e}(),n=[];for(const t of o){let r,o;try{r=w(t)}catch{continue}try{o=JSON.parse(r)}catch{continue}const s=o.payload?.model_provider;"session_meta"===o.type&&"string"==typeof s&&s!==e&&(o.payload.model_provider=e,n.push({file:t,from:s,line:JSON.stringify(o),length:Buffer.byteLength(r,"utf-8")}))}const a=function(){const e=b();if(!s(e))return null;const t=c(e).map(e=>/^state_(\d+)\.sqlite$/.exec(e)).filter(e=>!!e).sort((e,t)=>Number(t[1])-Number(e[1]));return t.length>0?h(e,t[0][0]):null}();let f=a?null:"no state DB",l=[],d=null;if(a){const t=await N(a);"string"==typeof t?f=t:(d=t,l=d.prepare('SELECT id, model_provider AS "from" FROM threads WHERE model_provider <> ?').all(e).map(e=>({id:String(e.id),from:String(e.from)})))}const p={target:e,scanned:o.length,moved:n.map(({file:e,from:t})=>({file:e,from:t})),dbRows:l.length,dbSkipped:f,backupDir:null};if(t.dryRun||0===n.length&&0===l.length)return d?.close(),p;const m=h(b(),"backups",`${v}-sessions-${(new Date).toISOString().replace(/[:.]/g,"-")}`);if(i(m,{recursive:!0}),a)for(const e of["","-wal","-shm"])s(a+e)&&r(a+e,h(m,`state.sqlite${e}`));const y={target:e,moved:p.moved,threads:l,db:a};u(h(m,"manifest.json"),JSON.stringify(y,null,2)+"\n");for(const e of n)await x(e.file,e.line,e.length);return d&&(d.prepare("UPDATE threads SET model_provider = ? WHERE model_provider <> ?").run(e,e),d.close()),p.backupDir=m,p}export async function undoSessionMove(e){const t=JSON.parse(f(h(e,"manifest.json"),"utf-8"));let r=0;for(const{file:e,from:o}of t.moved){if(!s(e))continue;const t=w(e),n=JSON.parse(t);n.payload&&(n.payload.model_provider=o,await x(e,JSON.stringify(n),Buffer.byteLength(t,"utf-8")),r+=1)}let o=0;if(t.db&&s(t.db)&&t.threads.length>0){const e=await N(t.db);if("string"!=typeof e){const r=e.prepare("UPDATE threads SET model_provider = ? WHERE id = ?");for(const{id:e,from:n}of t.threads)o+=Number(r.run(n,e).changes);e.close()}}return{files:r,dbRows:o}}
@@ -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 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
+ 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{codexHome as b,toolHome as C}from"./types.js";import{brandEnv as v,CLI_NAME as M,PROVIDER_KEY as A}from"../brand.js";const j=u(m(import.meta.url));export const CODEX_CATALOG_FILE=`${A}-model-catalog.json`;export const codexCatalogPath=()=>p(b(),CODEX_CATALOG_FILE);function O(){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(C(),"AppData","Local");o.push(p(t,"Programs","OpenAI","Codex","bin","codex.exe"))}else o.push(p(C(),".local","bin","codex"));if("darwin"===process.platform)for(const t of["/Applications",p(C(),"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 $(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function E(t){try{const o=JSON.parse(t),e=$(o)&&Array.isArray(o.models)?o.models.filter($):[];return e.length>0?e:null}catch{return null}}function k(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 P(t){const o=k(t,["debug","models","--bundled"]);if(0===o.status&&o.stdout){const t=E(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 P(t);for(const t of O()){if("codex"!==t&&!o(t))continue;const e=P(t);if(e)return e}return null}function B(t){try{return i(t).isFile()}catch{return!1}}export function installedCodexBinaries(){const t=[],o=O();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(!B(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=`${k(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(),`${M}-codex-`)),s=[];try{c(p(n,"config.toml"),f.stringify({model_catalog_json:t}));for(const t of o){const o=k(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=L()?.filter(t=>!S(t));return t&&t.length>0?t:null}export function previousGatewayModelIds(){return(L()??[]).filter(S).map(t=>String(t.slug))}function L(){return o(codexCatalogPath())?E(n(codexCatalogPath(),"utf-8")):null}function S(t){return"number"==typeof t.priority&&t.priority>=1e3}let T=null;function D(){if(null!==T)return T;const t=[p(j,"..","..","..","codex-base-instructions.md"),p(j,"..","..","codex-base-instructions.md"),p(j,"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 T=n(e,"utf-8"),T}function F(t){return"number"==typeof t&&Number.isFinite(t)&&t>0?t:void 0}function I(t,o,e,n){const s=e?t:Math.min(t,o);return{window:s,compact:w(s,n)}}function W(t,o,e,n){const{standardContextWindow:s}=x();let r=F(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}=I(r,s,e,F(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:D()},base_instructions:D(),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 G={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 R(t,o,e){if("list"!==(t=function(t){const o=Object.keys(G).filter(o=>!(o in t));return 0===o.length?t:{...t,...Object.fromEntries(o.map(t=>[t,G[t]]))}}(t)).visibility)return t;const n=F(t.context_window);if(!n)return t;const s=F(t.max_context_window)??n,r=e?Math.min(F(o?.contextWindow)??s,s):n,{window:i,compact:c}=I(r,n,!0,F(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(R(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(W(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{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{findInstalls as S,mirrorInstallCommand as A,brandInstallScripts as P}from"./tool-installs.js";const T=()=>a(p(),".codex"),D=()=>a(T(),"config.toml"),I=()=>a(T(),"auth.json"),$="OPENAI_API_KEY",J="custom",L=1e6,K=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function X(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function B(e,t){return X(e[t])||(e[t]={}),e[t]}function q(){if(!t(D()))return{};const e=n(D(),"utf-8");if(!e.trim())return{};try{const t=s.parse(e);if(!X(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 G(){if(!t(I()))return{};try{const e=JSON.parse(n(I(),"utf-8"));return X(e)?e:{}}catch{return{}}}let z=null;function R(e){const t=e.profiles;if(X(t)){for(const[e,o]of Object.entries(t))X(o)&&2===Object.keys(o).length&&o.model_provider===J&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let U=null;const Y=()=>a(x.getConfigDir(),"codex-catalog-check.json");function F(e){const o=j();t(o)&&n(o,"utf-8")===e||(u(o),m(o,e))}function H(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(Y(),"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(Y(),JSON.stringify({signature:e})+"\n")}catch(e){c.logError("codexAdapter.rememberAccepted",e)}}(a),s}function Q(e,t,o){const n=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===L&&delete e.model_context_window,e.model_auto_compact_token_limit===K&&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=L,e.model_auto_compact_token_limit=K)},l=O()??C();if(!l)return c.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),U="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);F(d(u));const m=w(),f=H(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(F(d(e)),0===H(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 U={rejectedBy:f[0]},r(j(),{force:!0}),void i()}U={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=q()}catch{return null}return e.model_catalog_json===j()&&t(j())?b(j())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=q(),n=s.stringify(o),r="string"==typeof o.model?o.model:_("codex");Q(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=s.stringify(o);i!==n&&(u(D()),m(D(),i))}const V={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:P("codex"),brew:"codex"};export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:A(V),installSpec:V,configPath:D(),wantsModelCatalog:!0,listedModels(){if(q().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){q().model_catalog_json===j()&&setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog)},applyNotes(){if("skipped"===U)return 0===S(V).length?[]:[{kind:"action",text:d.t("tools.codex.catalog_skipped")}];if(!U)return[];if("rejectedBy"in U){const{bin:e,version:t}=U.rejectedBy;return[{kind:"action",text:d.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of U.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(U.listed.length),breakdown:t})},{kind:"detail",text:U.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=q();i.model=n,i.model_provider=J,i.model_reasoning_effort="high",Q(i,e,n);const l=B(i,"model_providers"),a=X(l[J])?{...l[J]}:{};delete a.env_key;const{experimental_bearer_token:c,...d}=a;l[J]={...d,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:r},R(i),B(B(i,"tui"),"model_availability_nux")[n]=4;const p=B(i,"features");p.goals=!0,p.js_repl=!1,u(D()),m(D(),s.stringify(i)),function(e){const t=e.trim();if(!t)return;const o={...G(),auth_mode:"apikey",[$]:t};u(I()),m(I(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},unloadPrivateConfig(e){if(z=function(e){const t=G(),o="string"==typeof t[$]?t[$].trim():"";if(!o)return X(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[$]:n,auth_mode:i,...l}=t;return u(I()),X(l.tokens)?(m(I(),JSON.stringify({...l,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(r(I(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(D()))return;let o;try{o=q()}catch(e){return void c.logError("codexAdapter.unloadPrivateConfig",e)}const n=o.model_providers;X(n)&&(delete n[J],0===Object.keys(n).length&&delete o.model_providers),o.model_provider===J&&delete o.model_provider,o.model_catalog_json===j()&&delete o.model_catalog_json,R(o),u(D()),m(D(),s.stringify(o))},unloadNotes(){switch(z){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=G()[$];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return q()}catch(e){return c.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[D(),I(),j()]};export function codexAuthProblem(){try{const e=q(),t=e.model_providers?.[J];if(e.model_provider!==J||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=G();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 s}from"path";import*as a 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{codexHome as f,pickModel 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 b,catalogRejections as k,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{findInstalls as S,mirrorInstallCommand as A,brandInstallScripts as P}from"./tool-installs.js";const T=()=>f(),D=()=>s(T(),"config.toml"),I=["browser_use","browser_use_external","computer_use"];function $(e){const t=G(e,"features");let o=!1;for(const e of I)!1!==t[e]&&(t[e]=!1,o=!0);return o}const J=()=>s(T(),"auth.json"),L="OPENAI_API_KEY",K="custom",X=1e6,B=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function q(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function G(e,t){return q(e[t])||(e[t]={}),e[t]}function z(){if(!t(D()))return{};const e=n(D(),"utf-8");if(!e.trim())return{};try{const t=a.parse(e);if(!q(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 R(){if(!t(J()))return{};try{const e=JSON.parse(n(J(),"utf-8"));return q(e)?e:{}}catch{return{}}}let U=null;function Y(e){const t=e.profiles;if(q(t)){for(const[e,o]of Object.entries(t))q(o)&&2===Object.keys(o).length&&o.model_provider===K&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let F=null;const H=()=>s(x.getConfigDir(),"codex-catalog-check.json");function Q(e){const o=j();t(o)&&n(o,"utf-8")===e||(u(o),m(o,e))}function V(t,r){if(0===r.length)return[];const s=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(H(),"utf-8")).signature===e}catch{return!1}}(s))return[];const a=k(j(),r);return 0===a.length&&function(e){try{o(x.getConfigDir(),{recursive:!0}),l(H(),JSON.stringify({signature:e})+"\n")}catch(e){c.logError("codexAdapter.rememberAccepted",e)}}(s),a}function W(e,t,o){const n=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===X&&delete e.model_context_window,e.model_auto_compact_token_limit===B&&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=X,e.model_auto_compact_token_limit=B)},l=O()??C();if(!l)return c.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),F="skipped",void i();const s=t.catalog,a=e=>b({bundled:e,specs:E("codex",s?.clientModels),...s?{keyModels:s.models}:{},gatewayAvailable:s?.models??M(),oneMillion:n,selectedModel:o,..."gateway"===s?.oneMillionSource?{claudeOneMillion:s.oneMillion}:{}}),d=e=>JSON.stringify(e,null,2)+"\n";let u=a(l);Q(d(u));const m=w(),f=V(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(a(o).models,o)}])if(Q(d(e)),0===V(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 F={rejectedBy:f[0]},r(j(),{force:!0}),void i()}F={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=z()}catch{return null}return e.model_catalog_json===j()&&t(j())?k(j())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=z(),n=a.stringify(o),r="string"==typeof o.model?o.model:_("codex");W(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=a.stringify(o);i!==n&&(u(D()),m(D(),i))}const Z={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:P("codex"),brew:"codex"};export const codexAdapter={name:"codex",displayName:"Codex",command:"codex",installCommand:A(Z),installSpec:Z,configPath:D(),wantsModelCatalog:!0,listedModels(){if(z().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){if(z().model_catalog_json!==j())return;setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog);const t=z();$(t)&&(u(D()),m(D(),a.stringify(t)))},applyNotes(){if("skipped"===F)return 0===S(Z).length?[]:[{kind:"action",text:d.t("tools.codex.catalog_skipped")}];if(!F)return[];if("rejectedBy"in F){const{bin:e,version:t}=F.rejectedBy;return[{kind:"action",text:d.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of F.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(F.listed.length),breakdown:t})},{kind:"detail",text:F.listed.map(e=>e.name).join(", ")}]},loadPrivateConfig(e){const t=_("codex"),o=p(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,r=g(e.baseUrl),i=z();i.model=n,i.model_provider=K,i.model_reasoning_effort="high",W(i,e,n);const l=G(i,"model_providers"),s=q(l[K])?{...l[K]}:{};delete s.env_key;const{experimental_bearer_token:c,...d}=s;l[K]={...d,name:"custom",wire_api:"responses",requires_openai_auth:!0,base_url:r},Y(i),G(G(i,"tui"),"model_availability_nux")[n]=4;const f=G(i,"features");f.goals=!0,f.js_repl=!1,$(i),u(D()),m(D(),a.stringify(i)),function(e){const t=e.trim();if(!t)return;const o={...R(),auth_mode:"apikey",[L]:t};u(J()),m(J(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},unloadPrivateConfig(e){if(U=function(e){const t=R(),o="string"==typeof t[L]?t[L].trim():"";if(!o)return q(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[L]:n,auth_mode:i,...l}=t;return u(J()),q(l.tokens)?(m(J(),JSON.stringify({...l,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(r(J(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(D()))return;let o;try{o=z()}catch(e){return void c.logError("codexAdapter.unloadPrivateConfig",e)}const n=o.model_providers;q(n)&&(delete n[K],0===Object.keys(n).length&&delete o.model_providers),o.model_provider===K&&delete o.model_provider,o.model_catalog_json===j()&&delete o.model_catalog_json;const i=o.features;if(q(i))for(const e of I)!1===i[e]&&delete i[e];Y(o),u(D()),m(D(),a.stringify(o))},unloadNotes(){switch(U){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=R()[L];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return z()}catch(e){return c.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[D(),J(),j()]};export function codexAuthProblem(){try{const e=z(),t=e.model_providers?.[K];if(e.model_provider!==K||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=R();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
@@ -7,6 +7,12 @@ import type { ToolInstallSpec } from './tool-installs.js';
7
7
  * etc. into a temp dir instead of the real home directory.
8
8
  */
9
9
  export declare function toolHome(): string;
10
+ /**
11
+ * Codex's own directory: `CODEX_HOME` when set (Codex and the ChatGPT desktop app both
12
+ * honor it, so a desktop app started with its own CODEX_HOME is configured there), else
13
+ * `~/.codex`.
14
+ */
15
+ export declare function codexHome(): string;
10
16
  /**
11
17
  * Everything a tool adapter needs to write a working private-provider config.
12
18
  * Built by ToolManager from the active profile (api key + base url + the models
@@ -1 +1 @@
1
- import{homedir as r}from"os";import{getDefaultModels as o}from"../model-registry.js";import{brandEnv as t}from"../brand.js";export function toolHome(){const o=t("TEST_HOME");return o&&o.trim()?o.trim():r()}export function primaryModel(r){return r.opus||r.sonnet||r.reasoning||r.haiku}export function pickModel(r,t){const e=primaryModel(r);return e&&e!==o().opus?e:t}export function withV1(r){const o=(r||"").replace(/\/+$/,"");return/\/v\d+$/.test(o)?o:`${o}/v1`}export class UserActionNeeded extends Error{constructor(r){super(r),this.name="UserActionNeeded"}}
1
+ import{homedir as o}from"os";import{join as r}from"path";import{getDefaultModels as e}from"../model-registry.js";import{brandEnv as t}from"../brand.js";export function toolHome(){const r=t("TEST_HOME");return r&&r.trim()?r.trim():o()}export function codexHome(){return process.env.CODEX_HOME?.trim()||r(toolHome(),".codex")}export function primaryModel(o){return o.opus||o.sonnet||o.reasoning||o.haiku}export function pickModel(o,r){const t=primaryModel(o);return t&&t!==e().opus?t:r}export function withV1(o){const r=(o||"").replace(/\/+$/,"");return/\/v\d+$/.test(r)?r:`${r}/v1`}export class UserActionNeeded extends Error{constructor(o){super(o),this.name="UserActionNeeded"}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeapi/api-helper",
3
- "version": "0.0.121",
3
+ "version": "0.0.122",
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",