/ commands / extra-usage / extra-usage-core.ts
extra-usage-core.ts
  1  import {
  2    checkAdminRequestEligibility,
  3    createAdminRequest,
  4    getMyAdminRequests,
  5  } from '../../services/api/adminRequests.js'
  6  import { invalidateOverageCreditGrantCache } from '../../services/api/overageCreditGrant.js'
  7  import { type ExtraUsage, fetchUtilization } from '../../services/api/usage.js'
  8  import { getSubscriptionType } from '../../utils/auth.js'
  9  import { hasClaudeAiBillingAccess } from '../../utils/billing.js'
 10  import { openBrowser } from '../../utils/browser.js'
 11  import { getGlobalConfig, saveGlobalConfig } from '../../utils/config.js'
 12  import { logError } from '../../utils/log.js'
 13  
 14  type ExtraUsageResult =
 15    | { type: 'message'; value: string }
 16    | { type: 'browser-opened'; url: string; opened: boolean }
 17  
 18  export async function runExtraUsage(): Promise<ExtraUsageResult> {
 19    if (!getGlobalConfig().hasVisitedExtraUsage) {
 20      saveGlobalConfig(prev => ({ ...prev, hasVisitedExtraUsage: true }))
 21    }
 22    // Invalidate only the current org's entry so a follow-up read refetches
 23    // the granted state. Separate from the visited flag since users may run
 24    // /extra-usage more than once while iterating on the claim flow.
 25    invalidateOverageCreditGrantCache()
 26  
 27    const subscriptionType = getSubscriptionType()
 28    const isTeamOrEnterprise =
 29      subscriptionType === 'team' || subscriptionType === 'enterprise'
 30    const hasBillingAccess = hasClaudeAiBillingAccess()
 31  
 32    if (!hasBillingAccess && isTeamOrEnterprise) {
 33      // Mirror apps/claude-ai useHasUnlimitedOverage(): if overage is enabled
 34      // with no monthly cap, there is nothing to request. On fetch error, fall
 35      // through and let the user ask (matching web's "err toward show" behavior).
 36      let extraUsage: ExtraUsage | null | undefined
 37      try {
 38        const utilization = await fetchUtilization()
 39        extraUsage = utilization?.extra_usage
 40      } catch (error) {
 41        logError(error as Error)
 42      }
 43  
 44      if (extraUsage?.is_enabled && extraUsage.monthly_limit === null) {
 45        return {
 46          type: 'message',
 47          value:
 48            'Your organization already has unlimited extra usage. No request needed.',
 49        }
 50      }
 51  
 52      try {
 53        const eligibility = await checkAdminRequestEligibility('limit_increase')
 54        if (eligibility?.is_allowed === false) {
 55          return {
 56            type: 'message',
 57            value: 'Please contact your admin to manage extra usage settings.',
 58          }
 59        }
 60      } catch (error) {
 61        logError(error as Error)
 62        // If eligibility check fails, continue — the create endpoint will enforce if necessary
 63      }
 64  
 65      try {
 66        const pendingOrDismissedRequests = await getMyAdminRequests(
 67          'limit_increase',
 68          ['pending', 'dismissed'],
 69        )
 70        if (pendingOrDismissedRequests && pendingOrDismissedRequests.length > 0) {
 71          return {
 72            type: 'message',
 73            value:
 74              'You have already submitted a request for extra usage to your admin.',
 75          }
 76        }
 77      } catch (error) {
 78        logError(error as Error)
 79        // Fall through to creating a new request below
 80      }
 81  
 82      try {
 83        await createAdminRequest({
 84          request_type: 'limit_increase',
 85          details: null,
 86        })
 87        return {
 88          type: 'message',
 89          value: extraUsage?.is_enabled
 90            ? 'Request sent to your admin to increase extra usage.'
 91            : 'Request sent to your admin to enable extra usage.',
 92        }
 93      } catch (error) {
 94        logError(error as Error)
 95        // Fall through to generic message below
 96      }
 97  
 98      return {
 99        type: 'message',
100        value: 'Please contact your admin to manage extra usage settings.',
101      }
102    }
103  
104    const url = isTeamOrEnterprise
105      ? 'https://claude.ai/admin-settings/usage'
106      : 'https://claude.ai/settings/usage'
107  
108    try {
109      const opened = await openBrowser(url)
110      return { type: 'browser-opened', url, opened }
111    } catch (error) {
112      logError(error as Error)
113      return {
114        type: 'message',
115        value: `Failed to open browser. Please visit ${url} to manage extra usage.`,
116      }
117    }
118  }