@@ -31,6 +31,7 @@ const CODEX_CONFIG = {
3131
3232// Claude API config
3333const CLAUDE_CONFIG = {
34+ oauthUsageUrl : "https://api.anthropic.com/api/oauth/usage" ,
3435 usageUrl : "https://api.anthropic.com/v1/organizations/{org_id}/usage" ,
3536 settingsUrl : "https://api.anthropic.com/v1/settings" ,
3637} ;
@@ -427,8 +428,79 @@ async function getAntigravitySubscriptionInfo(accessToken) {
427428 */
428429async function getClaudeUsage ( accessToken ) {
429430 try {
430- // Try to get organization/account settings first
431- const settingsResponse = await fetch ( "https://api.anthropic.com/v1/settings" , {
431+ // Primary: Try OAuth usage endpoint (works with Claude Code consumer OAuth tokens)
432+ // Requires anthropic-beta: oauth-2025-04-20 header
433+ const oauthResponse = await fetch ( CLAUDE_CONFIG . oauthUsageUrl , {
434+ method : "GET" ,
435+ headers : {
436+ Authorization : `Bearer ${ accessToken } ` ,
437+ "Content-Type" : "application/json" ,
438+ "anthropic-beta" : "oauth-2025-04-20" ,
439+ "anthropic-version" : "2023-06-01" ,
440+ } ,
441+ } ) ;
442+
443+ if ( oauthResponse . ok ) {
444+ const data = await oauthResponse . json ( ) ;
445+ const quotas : Record < string , any > = { } ;
446+
447+ // Parse five_hour window (session limit)
448+ if ( data . five_hour !== undefined ) {
449+ quotas [ "session (5h)" ] = {
450+ used : data . five_hour . utilization ?? 0 ,
451+ total : 100 ,
452+ resetAt : data . five_hour . resets_at || null ,
453+ remainingPercentage : 100 - ( data . five_hour . utilization ?? 0 ) ,
454+ unlimited : false ,
455+ } ;
456+ }
457+
458+ // Parse seven_day window (weekly limit)
459+ if ( data . seven_day !== undefined ) {
460+ quotas [ "weekly (7d)" ] = {
461+ used : data . seven_day . utilization ?? 0 ,
462+ total : 100 ,
463+ resetAt : data . seven_day . resets_at || null ,
464+ remainingPercentage : 100 - ( data . seven_day . utilization ?? 0 ) ,
465+ unlimited : false ,
466+ } ;
467+ }
468+
469+ // Parse model-specific weekly windows (e.g., seven_day_sonnet, seven_day_opus)
470+ for ( const [ key , value ] of Object . entries ( data ) ) {
471+ if ( key . startsWith ( "seven_day_" ) && key !== "seven_day" && value && typeof value === "object" ) {
472+ const modelName = key . replace ( "seven_day_" , "" ) ;
473+ quotas [ `weekly ${ modelName } (7d)` ] = {
474+ used : ( value as any ) . utilization ?? 0 ,
475+ total : 100 ,
476+ resetAt : ( value as any ) . resets_at || null ,
477+ remainingPercentage : 100 - ( ( value as any ) . utilization ?? 0 ) ,
478+ unlimited : false ,
479+ } ;
480+ }
481+ }
482+
483+ return {
484+ plan : "Claude Code" ,
485+ quotas,
486+ extraUsage : data . extra_usage || null ,
487+ } ;
488+ }
489+
490+ // Fallback: Try legacy settings/org endpoint (for API key users with org admin access)
491+ return await getClaudeUsageLegacy ( accessToken ) ;
492+ } catch ( error ) {
493+ return { message : `Claude connected. Unable to fetch usage: ${ ( error as any ) . message } ` } ;
494+ }
495+ }
496+
497+ /**
498+ * Legacy Claude usage fetcher for API key / org admin users.
499+ * Uses /v1/settings + /v1/organizations/{org_id}/usage endpoints.
500+ */
501+ async function getClaudeUsageLegacy ( accessToken ) {
502+ try {
503+ const settingsResponse = await fetch ( CLAUDE_CONFIG . settingsUrl , {
432504 method : "GET" ,
433505 headers : {
434506 Authorization : `Bearer ${ accessToken } ` ,
@@ -440,7 +512,6 @@ async function getClaudeUsage(accessToken) {
440512 if ( settingsResponse . ok ) {
441513 const settings = await settingsResponse . json ( ) ;
442514
443- // Try usage endpoint if we have org info
444515 if ( settings . organization_id ) {
445516 const usageResponse = await fetch (
446517 `https://api.anthropic.com/v1/organizations/${ settings . organization_id } /usage` ,
@@ -471,10 +542,9 @@ async function getClaudeUsage(accessToken) {
471542 } ;
472543 }
473544
474- // If settings API fails, OAuth token may not have required scope
475545 return { message : "Claude connected. Usage API requires admin permissions." } ;
476546 } catch ( error ) {
477- return { message : `Claude connected. Unable to fetch usage: ${ error . message } ` } ;
547+ return { message : `Claude connected. Unable to fetch usage: ${ ( error as any ) . message } ` } ;
478548 }
479549}
480550
0 commit comments