import type { ClaudeAuth, ClaudeOrg, ClaudeUsageResponse } from "@/types/claude"; const BASE_URL = "https://claude.ai/api"; const BROWSER_UA = "Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36"; function buildHeaders(auth: ClaudeAuth): Record { const cookies = [`sessionKey=${auth.sessionKey}`]; if (auth.lastActiveOrg) cookies.push(`lastActiveOrg=${auth.lastActiveOrg}`); return { Cookie: cookies.join("; "), Accept: "application/json, text/plain, */*", "Accept-Language": "en-US,en;q=0.9", "User-Agent": BROWSER_UA, Referer: "https://claude.ai/", Origin: "https://claude.ai", "anthropic-client-platform": "web_claude_to_cc_migration", }; } function isClaudeWindow(value: unknown): boolean { if (!value || typeof value !== "object") return false; const window = value as Record; return ( typeof window.utilization === "number" && Number.isFinite(window.utilization) && (window.resets_at === undefined || window.resets_at === null || typeof window.resets_at === "string") ); } export function parseClaudeOrgsResponse(data: unknown): ClaudeOrg[] { if ( !Array.isArray(data) || data.some( (org) => !org || typeof org !== "object" || typeof (org as Record).uuid !== "string" || typeof (org as Record).name !== "string" ) ) { throw new Error("INVALID_CLAUDE_ORGS_RESPONSE"); } return data.map((org) => { const value = org as Record; return { uuid: value.uuid as string, name: value.name as string }; }); } export function parseClaudeUsageResponse(data: unknown): ClaudeUsageResponse { if (!data || typeof data !== "object") { throw new Error("INVALID_CLAUDE_RESPONSE"); } const value = data as Record; if ( !isClaudeWindow(value.five_hour) || !isClaudeWindow(value.seven_day) || (value.seven_day_sonnet !== undefined && value.seven_day_sonnet !== null && !isClaudeWindow(value.seven_day_sonnet)) || (value.seven_day_opus !== undefined && value.seven_day_opus !== null && !isClaudeWindow(value.seven_day_opus)) ) { throw new Error("INVALID_CLAUDE_RESPONSE"); } const toWindow = (window: unknown) => { const item = window as Record; return { utilization: item.utilization as number, ...(typeof item.resets_at === "string" ? { resets_at: item.resets_at } : {}), }; }; return { five_hour: toWindow(value.five_hour), seven_day: toWindow(value.seven_day), ...(value.seven_day_sonnet ? { seven_day_sonnet: toWindow(value.seven_day_sonnet) } : {}), ...(value.seven_day_opus ? { seven_day_opus: toWindow(value.seven_day_opus) } : {}), }; } export async function fetchClaudeOrgs(auth: ClaudeAuth): Promise { const response = await fetch(`${BASE_URL}/organizations`, { headers: buildHeaders(auth), credentials: "omit", }); if (!response.ok) { await response.text().catch(() => null); if (response.status === 401 || response.status === 403) throw new Error("TOKEN_EXPIRED"); throw new Error(`HTTP_ERROR_${response.status}`); } const data: unknown = await response.json(); return parseClaudeOrgsResponse(data); } export async function fetchClaudeUsage( auth: ClaudeAuth, orgUuid: string ): Promise { const response = await fetch(`${BASE_URL}/organizations/${orgUuid}/usage`, { headers: buildHeaders(auth), credentials: "omit", }); if (!response.ok) { await response.text().catch(() => null); if (response.status === 401 || response.status === 403) throw new Error("TOKEN_EXPIRED"); throw new Error(`HTTP_ERROR_${response.status}`); } const data: unknown = await response.json(); return parseClaudeUsageResponse(data); }