rateLimitMocking.ts
services/rateLimitMocking.ts
145
Lines
4420
Bytes
5
Exports
2
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with integrations. It contains 145 lines, 2 detected imports, and 5 detected exports.
Important relationships
Detected exports
processRateLimitHeadersshouldProcessRateLimitscheckMockRateLimitErrorisMockRateLimitErrorshouldProcessMockLimits
Keywords
headersratechecklimitmockapierrorshouldprocessmocklimitsthrowmockheadersglobalthis
Detected imports
@anthropic-ai/sdk./mockRateLimits.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
/**
* Facade for rate limit header processing
* This isolates mock logic from production code
*/
import { APIError } from '@anthropic-ai/sdk'
import {
applyMockHeaders,
checkMockFastModeRateLimit,
getMockHeaderless429Message,
getMockHeaders,
isMockFastModeRateLimitScenario,
shouldProcessMockLimits,
} from './mockRateLimits.js'
/**
* Process headers, applying mocks if /mock-limits command is active
*/
export function processRateLimitHeaders(
headers: globalThis.Headers,
): globalThis.Headers {
// Only apply mocks for Ant employees using /mock-limits command
if (shouldProcessMockLimits()) {
return applyMockHeaders(headers)
}
return headers
}
/**
* Check if we should process rate limits (either real subscriber or /mock-limits command)
*/
export function shouldProcessRateLimits(isSubscriber: boolean): boolean {
return isSubscriber || shouldProcessMockLimits()
}
/**
* Check if mock rate limits should throw a 429 error
* Returns the error to throw, or null if no error should be thrown
* @param currentModel The model being used for the current request
* @param isFastModeActive Whether fast mode is currently active (for fast-mode-only mocks)
*/
export function checkMockRateLimitError(
currentModel: string,
isFastModeActive?: boolean,
): APIError | null {
if (!shouldProcessMockLimits()) {
return null
}
const headerlessMessage = getMockHeaderless429Message()
if (headerlessMessage) {
return new APIError(
429,
{ error: { type: 'rate_limit_error', message: headerlessMessage } },
headerlessMessage,
// eslint-disable-next-line eslint-plugin-n/no-unsupported-features/node-builtins
new globalThis.Headers(),
)
}
const mockHeaders = getMockHeaders()
if (!mockHeaders) {
return null
}
// Check if we should throw a 429 error
// Only throw if:
// 1. Status is rejected AND
// 2. Either no overage headers OR overage is also rejected
// 3. For Opus-specific limits, only throw if actually using an Opus model
const status = mockHeaders['anthropic-ratelimit-unified-status']
const overageStatus =
mockHeaders['anthropic-ratelimit-unified-overage-status']
const rateLimitType =
mockHeaders['anthropic-ratelimit-unified-representative-claim']
// Check if this is an Opus-specific rate limit
const isOpusLimit = rateLimitType === 'seven_day_opus'
// Check if current model is an Opus model (handles all variants including aliases)
const isUsingOpus = currentModel.includes('opus')
// For Opus limits, only throw 429 if actually using Opus
// This simulates the real API behavior where fallback to Sonnet succeeds
if (isOpusLimit && !isUsingOpus) {
return null
}
// Check for mock fast mode rate limits (handles expiry, countdown, etc.)
if (isMockFastModeRateLimitScenario()) {
const fastModeHeaders = checkMockFastModeRateLimit(isFastModeActive)
if (fastModeHeaders === null) {
return null
}
// Create a mock 429 error with the fast mode headers
const error = new APIError(
429,
{ error: { type: 'rate_limit_error', message: 'Rate limit exceeded' } },
'Rate limit exceeded',
// eslint-disable-next-line eslint-plugin-n/no-unsupported-features/node-builtins
new globalThis.Headers(
Object.entries(fastModeHeaders).filter(([_, v]) => v !== undefined) as [
string,
string,
][],
),
)
return error
}
const shouldThrow429 =
status === 'rejected' && (!overageStatus || overageStatus === 'rejected')
if (shouldThrow429) {
// Create a mock 429 error with the appropriate headers
const error = new APIError(
429,
{ error: { type: 'rate_limit_error', message: 'Rate limit exceeded' } },
'Rate limit exceeded',
// eslint-disable-next-line eslint-plugin-n/no-unsupported-features/node-builtins
new globalThis.Headers(
Object.entries(mockHeaders).filter(([_, v]) => v !== undefined) as [
string,
string,
][],
),
)
return error
}
return null
}
/**
* Check if this is a mock 429 error that shouldn't be retried
*/
export function isMockRateLimitError(error: APIError): boolean {
return shouldProcessMockLimits() && error.status === 429
}
/**
* Check if /mock-limits command is currently active (for UI purposes)
*/
export { shouldProcessMockLimits }