UNPKG

grix-connector

Version:

Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.

2 lines (1 loc) 2.96 kB
import{execFileSync as N}from"node:child_process";import{readJSONFile as A}from"../../core/util/json-file.js";import{log as o}from"../../core/log/index.js";import{homedir as k}from"node:os";import{join as f}from"node:path";const c=[{id:"opus",displayName:"Opus"},{id:"sonnet",displayName:"Sonnet"},{id:"haiku",displayName:"Haiku"},{id:"claude-fable-5",displayName:"Claude Fable 5"},{id:"claude-opus-4-8",displayName:"Claude Opus 4.8"},{id:"claude-opus-4-7",displayName:"Claude Opus 4.7"},{id:"claude-opus-4-6",displayName:"Claude Opus 4.6"},{id:"claude-sonnet-4-6",displayName:"Claude Sonnet 4.6"},{id:"claude-sonnet-4-5",displayName:"Claude Sonnet 4.5"},{id:"claude-haiku-4-5-20251001",displayName:"Claude Haiku 4.5"}],T=3600*1e3,O=300*1e3;let e=null,i=0;function w(){const t=f(k(),".claude");return A(f(t,"settings.json"))?.env??{}}function C(t){return!(!t?.accessToken||t.expiresAt&&Date.now()>t.expiresAt-O)}function _(){if(process.platform==="darwin")try{const t=process.env.USER||process.env.LOGNAME||"";if(!t)return null;const r=N("security",["find-generic-password","-s","Claude Code-credentials","-a",t,"-w"],{encoding:"utf-8",timeout:5e3}).trim(),l=JSON.parse(r)?.claudeAiOauth;return C(l)?l.accessToken:(l?.accessToken&&o.info("model-list","Claude OAuth token expired, skipping keychain"),null)}catch{return null}else try{const t=f(k(),".claude",".credentials.json"),a=A(t)?.claudeAiOauth;return C(a)?a.accessToken:(a?.accessToken&&o.info("model-list","Claude OAuth token expired, skipping credentials file"),null)}catch{return null}}async function P(){if(e&&Date.now()-i<T)return e;const t=w(),r=(t.ANTHROPIC_BASE_URL??"").trim()||"https://api.anthropic.com",a=(t.ANTHROPIC_AUTH_TOKEN??"").trim(),l=(t.ANTHROPIC_API_KEY??"").trim();let d=a||l,h=!!a;if(!d){const n=_();n&&(d=n,h=!0,o.info("model-list","Using Claude CLI OAuth token from Keychain for model list"))}if(!d)return o.info("model-list","No API credentials found, using fallback model list"),e=c,i=Date.now(),e;try{const n=`${r.replace(/\/+$/,"")}/v1/models`,u={"anthropic-version":"2023-06-01"};h?u.Authorization=`Bearer ${d}`:u["x-api-key"]=d;const y=new AbortController,g=setTimeout(()=>y.abort(),1e4),m=await fetch(n,{headers:u,signal:y.signal});if(clearTimeout(g),!m.ok)return o.warn("model-list",`API returned ${m.status}, using fallback model list`),e=c,i=Date.now(),e;const p=(await m.json()).data;return!Array.isArray(p)||p.length===0?(o.warn("model-list","API returned empty model list, using fallback"),e=c,i=Date.now(),e):(e=p.map(s=>({id:s.id,displayName:s.display_name||s.name||s.id})),i=Date.now(),o.info("model-list",`Fetched ${e.length} models from API: ${e.map(s=>s.id).join(", ")}`),e)}catch(n){return o.warn("model-list",`Failed to fetch models: ${n instanceof Error?n.message:n}, using fallback`),e=c,i=Date.now(),e}}function v(){return e??c}function D(){e=null,i=0}export{P as fetchAvailableModels,v as getCachedModels,w as readSettingsEnv,D as resetModelCache};