MCPcopy
hub / github.com/nowork-studio/NotFair / readCodexUsage

Function readCodexUsage

notfair-cmo/src/server/harness-usage.ts:92–146  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

90}
91
92async function readCodexUsage(): Promise<HarnessUsage> {
93 const authFile = path.join(os.homedir(), ".codex", "auth.json");
94 if (!fs.existsSync(authFile)) {
95 return { kind: "codex", plan: null, email: null, rateLimit: null };
96 }
97 const auth = JSON.parse(fs.readFileSync(authFile, "utf-8")) as {
98 tokens?: { access_token?: string; id_token?: string };
99 };
100 const accessToken = auth.tokens?.access_token;
101 if (!accessToken) {
102 return { kind: "codex", plan: null, email: null, rateLimit: null };
103 }
104
105 // Decode just to pull the email + chatgpt account id (needed as the
106 // ChatGPT-Account-Id header so the backend scopes the response to
107 // the right workspace).
108 const { email, accountId } = decodeIdToken(auth.tokens?.id_token);
109
110 let plan: string | null = null;
111 let rateLimit: CodexUsage["rateLimit"] = null;
112 try {
113 const ctrl = new AbortController();
114 const t = setTimeout(() => ctrl.abort(), 4000);
115 const headers: Record<string, string> = {
116 Authorization: `Bearer ${accessToken}`,
117 Accept: "application/json",
118 };
119 if (accountId) headers["ChatGPT-Account-Id"] = accountId;
120 const res = await fetch("https://chatgpt.com/backend-api/wham/usage", {
121 headers,
122 signal: ctrl.signal,
123 });
124 clearTimeout(t);
125 if (res.ok) {
126 const body = (await res.json()) as {
127 plan_type?: string;
128 rate_limit?: {
129 primary_window?: RateLimitWindow;
130 secondary_window?: RateLimitWindow;
131 };
132 };
133 if (typeof body.plan_type === "string") plan = body.plan_type;
134 const p = body.rate_limit?.primary_window;
135 const s = body.rate_limit?.secondary_window;
136 if (p && s) {
137 rateLimit = { primary: p, secondary: s };
138 }
139 }
140 } catch {
141 // Network error / abort — leave rateLimit null; the footer falls
142 // back to the plan chip only.
143 }
144
145 return { kind: "codex", plan, email, rateLimit };
146}
147
148function decodeIdToken(idToken: string | undefined): {
149 email: string | null;

Callers 1

readHarnessUsageFunction · 0.85

Calls 2

decodeIdTokenFunction · 0.85
fetchFunction · 0.85

Tested by

no test coverage detected