fix(usage-api): change User-Agent to avoid Anthropic 429 rate limiting (#168)

* fix(usage-api): change User-Agent to avoid Anthropic 429 rate limiting

Anthropic applies stricter rate limits to non-official User-Agent
strings. The current 'claude-hud/1.0' consistently receives 429
responses while 'claude-code/2.1' succeeds for the same token.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test(usage-api): cover user-agent constant

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jarrod Watts <jarrod@cubelabs.xyz>
This commit is contained in:
xiangboit
2026-03-06 07:55:11 +08:00
committed by GitHub
parent 5467f29e50
commit ceb112777c
2 changed files with 7 additions and 1 deletions

View File

@@ -48,6 +48,7 @@ const CACHE_FAILURE_TTL_MS = 15_000; // 15 seconds for failed requests
const KEYCHAIN_TIMEOUT_MS = 3000;
const KEYCHAIN_BACKOFF_MS = 60_000; // Backoff on keychain failures to avoid re-prompting
const USAGE_API_TIMEOUT_MS_DEFAULT = 15_000;
export const USAGE_API_USER_AGENT = 'claude-code/2.1';
interface CacheFile {
data: UsageData;
@@ -662,7 +663,7 @@ function fetchUsageApi(accessToken: string): Promise<UsageApiResult> {
headers: {
'Authorization': `Bearer ${accessToken}`,
'anthropic-beta': 'oauth-2025-04-20',
'User-Agent': 'claude-hud/1.0',
'User-Agent': USAGE_API_USER_AGENT,
},
timeout: timeoutMs,
agent: proxyUrl ? createProxyTunnelAgent(proxyUrl) : undefined,

View File

@@ -9,6 +9,7 @@ import {
getUsageApiTimeoutMs,
isNoProxy,
getProxyUrl,
USAGE_API_USER_AGENT,
} from '../dist/usage-api.js';
import { mkdtemp, rm, mkdir, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
@@ -505,6 +506,10 @@ describe('getUsage', () => {
});
});
test('usage API user agent matches the working Claude Code identifier', () => {
assert.equal(USAGE_API_USER_AGENT, 'claude-code/2.1');
});
describe('getKeychainServiceName', () => {
test('uses legacy default service name for default config directory', () => {
const homeDir = '/tmp/claude-hud-home-default';