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.

6 lines (5 loc) 6.85 kB
import{execFile as C}from"node:child_process";import{existsSync as U,readdirSync as q,readFileSync as R}from"node:fs";import*as F from"node:https";import{homedir as A}from"node:os";import{join as y}from"node:path";import{promisify as M}from"node:util";import{log as w}from"../../core/log/index.js";const g=M(C),T="agy-quota",G=300*1e3,O=5e3;let x=null,I=0,d=null;function he(){return(!x||Date.now()-I>=G)&&P(),x??{}}async function de(){await P()}async function P(){return d||(d=(async()=>{try{x=await Q(),I=Date.now()}catch(t){w.info(T,`fetch failed: ${t instanceof Error?t.message:t}`)}finally{d=null}})(),d)}async function Q(){const t=await $();if(t)try{const n=await j(t.port,t.csrfToken);if(n){w.info(T,`language server: plan=${n.plan}, reset_at=${n.quota_reset_at}`);const i=L();return{...n,quota_exhausted:i.exhausted}}}catch(n){w.info(T,`language server query failed: ${n instanceof Error?n.message:n}`)}const e=L(),s={};return e.exhausted&&(s.quota_exhausted=!0),e.resetAt&&(s.quota_reset_at=e.resetAt),s}async function $(){if(process.platform==="win32")return null;try{const t=await B();if(!t)return null;const e=await Y(t);if(!e)return null;const s=e.match(/--csrf_token\s+([0-9a-f-]+)/i);if(!s)return null;const n=s[1],i=await H(t);return i?{pid:t,port:i,csrfToken:n}:null}catch{return null}}async function B(){try{const{stdout:t}=await g("pgrep",["-f","language_server.*--csrf_token"],{timeout:3e3}),e=parseInt(t.trim().split(` `)[0],10);return isNaN(e)?null:e}catch{return null}}async function Y(t){try{const{stdout:e}=await g("ps",["-p",String(t),"-o","args="],{timeout:3e3});return e.trim()||null}catch{return null}}async function H(t){return process.platform==="darwin"?b(t):await W(t)??b(t)}async function b(t){try{const{stdout:e}=await g("lsof",["-p",String(t),"-a","-i","TCP","-s","TCP:LISTEN"],{timeout:3e3}),s=[];for(const n of e.split(` `)){const i=n.match(/:(\d+)\s+\(LISTEN\)/);i&&s.push(parseInt(i[1],10))}return s[0]??null}catch{return null}}async function W(t){try{const{stdout:e}=await g("ss",["-tlnp"],{timeout:3e3});for(const s of e.split(` `)){if(!s.includes(`pid=${t}`))continue;const n=s.match(/[*\d.]+:(\d+)\s/);if(n)return parseInt(n[1],10)}return null}catch{return null}}async function j(t,e){const s=V(new Uint8Array(0));return new Promise(n=>{const i=setTimeout(()=>{r.destroy(),n(null)},O),r=F.request({hostname:"localhost",port:t,path:"/exa.language_server_pb.LanguageServerService/GetUserStatus",method:"POST",headers:{"Content-Type":"application/grpc-web+proto",Accept:"application/grpc-web+proto","x-codeium-csrf-token":e,"Content-Length":s.length},rejectUnauthorized:!1},o=>{const c=[];o.on("data",l=>c.push(l)),o.on("end",()=>{if(clearTimeout(i),o.statusCode!==200){n(null);return}const l=new Uint8Array(Buffer.concat(c));n(X(l))}),o.on("error",()=>{clearTimeout(i),n(null)})});r.on("error",()=>{clearTimeout(i),n(null)}),r.write(Buffer.from(s)),r.end()})}function V(t){const e=new Uint8Array(5+t.length);return e[0]=0,new DataView(e.buffer).setUint32(1,t.length,!1),e.set(t,5),e}function X(t){try{if(t.length<6)return null;const e=t[1]<<24|t[2]<<16|t[3]<<8|t[4];if(e<=0||5+e>t.length)return null;const s=t.slice(5,5+e),[n,i,r]=p(s,0);if(n!==1||i!==2)return null;const[o,c]=f(s,r),l=s.slice(c,c+o);return z(l)}catch{return null}}function z(t){const e={};let s=0;for(;s<t.length;){const[n,i,r]=p(t,s);if(s=r,s>=t.length&&i!==0)break;if(i===0){const[,o]=f(t,s);s=o}else if(i===2){const[o,c]=f(t,s),l=t.slice(c,c+o);if(s=c+o,n===36){const u=J(l);u[3]&&(e.plan=u[3])}else if(n===33){if(!e.quota_reset_at){const a=K(l);a&&(e.quota_reset_at=a)}const u=te(l);u!==void 0&&(e.available_credits=u)}}else if(i===1)s+=8;else if(i===5)s+=4;else break}return e}function J(t){const e={};let s=0;for(;s<t.length;){const[n,i,r]=p(t,s);if(s=r,i===2){const[o,c]=f(t,s),l=t.slice(c,c+o);s=c+o;try{e[n]=new TextDecoder().decode(l)}catch{}}else if(i===0){const[,o]=f(t,s);s=o}else if(i===1)s+=8;else if(i===5)s+=4;else break}return e}function K(t){let e=0;for(;e<t.length;){const[s,n,i]=p(t,e);if(e=i,n===2){const[r,o]=f(t,e),c=t.slice(o,o+r);if(e=o+r,s===1){const l=Z(c);if(l)return l}}else if(n===0){const[,r]=f(t,e);e=r}else if(n===1)e+=8;else if(n===5)e+=4;else break}}function Z(t){let e=0;for(;e<t.length;){const[s,n,i]=p(t,e);if(e=i,n===2){const[r,o]=f(t,e),c=t.slice(o,o+r);if(e=o+r,s===15)return ee(c)}else if(n===0){const[,r]=f(t,e);e=r}else if(n===1)e+=8;else if(n===5)e+=4;else break}}function ee(t){let e=0;for(;e<t.length;){const[s,n,i]=p(t,e);if(e=i,n===2){const[r,o]=f(t,e),c=t.slice(o,o+r);if(e=o+r,s===2){const[l,u,a]=p(c,0);if(l===1&&u===0){const[h]=f(c,a);if(h>1e9)return h}}}else if(n===0){const[,r]=f(t,e);e=r}else if(n===5)e+=4;else if(n===1)e+=8;else break}}function te(t){let e=0;for(;e<t.length;){const[s,n,i]=p(t,e);if(e=i,n===2){const[r,o]=f(t,e),c=t.slice(o,o+r);if(e=o+r,s===3){const l=ne(c);if(l!==void 0)return l}}else if(n===0){const[,r]=f(t,e);e=r}else if(n===1)e+=8;else if(n===5)e+=4;else break}}function ne(t){let e=0;for(;e<t.length;){const[s,n,i]=p(t,e);if(e=i,n===2){const[r,o]=f(t,e),c=t.slice(o,o+r);if(e=o+r,s===1){const{creditType:l,creditAmount:u}=se(c);if(l===1&&u!==void 0)return u}}else if(n===0){const[,r]=f(t,e);e=r}else if(n===1)e+=8;else if(n===5)e+=4;else break}}function se(t){let e,s,n=0;for(;n<t.length;){const[i,r,o]=p(t,n);if(n=o,r===0){const[c,l]=f(t,n);n=l,i===1?e=c:i===2&&(s=c)}else if(r===2){const[c,l]=f(t,n);n=l+c}else if(r===1)n+=8;else if(r===5)n+=4;else break}return{creditType:e,creditAmount:s}}function f(t,e){let s=0,n=0;for(;e<t.length;){const i=t[e++];if(s|=(i&127)<<n,n+=7,!(i&128))break}return[s,e]}function p(t,e){const[s,n]=f(t,e);return[s>>3,s&7,n]}const _=process.platform==="win32"?y(process.env.APPDATA??A(),".gemini","antigravity-cli","log"):y(A(),".gemini","antigravity-cli","log"),re=/RESOURCE_EXHAUSTED.*?Resets in (?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?/,ie=/^[EWID](\d{2})(\d{2})\s+(\d{2}):(\d{2}):(\d{2})/;function L(){try{if(!U(_))return{exhausted:!1};const t=q(_).filter(e=>e.endsWith(".log")).sort().reverse().slice(0,3);for(const e of t){const s=oe(y(_,e));if(s.exhausted)return s}}catch{}return{exhausted:!1}}function oe(t){try{const s=R(t,"utf-8").split(` `);for(let n=s.length-1;n>=0;n--){const i=s[n];if(!i.includes("RESOURCE_EXHAUSTED"))continue;const r=i.match(re);if(!r)continue;const o=parseInt(r[1]??"0",10),c=parseInt(r[2]??"0",10),l=parseInt(r[3]??"0",10),u=o*3600+c*60+l,a=i.match(ie);let h;if(a&&u>0){const E=parseInt(a[1],10),D=parseInt(a[2],10),k=parseInt(a[3],10),v=parseInt(a[4],10),N=parseInt(a[5],10),S=new Date,m=new Date(S.getFullYear(),E-1,D,k,v,N);m.getTime()>S.getTime()+6e4&&m.setFullYear(m.getFullYear()-1),h=Math.floor(m.getTime()/1e3)+u}return h!==void 0&&h<=Math.floor(Date.now()/1e3)?{exhausted:!1}:{exhausted:!0,resetAt:h}}}catch{}return{exhausted:!1}}export{he as getCachedAgyQuotaInfo,de as primeAgyQuotaInfo};