fix(cliproxy): refresh non-default gemini quota tokens

This commit is contained in:
Tam Nhu Tran committed 2026-04-08 23:55:55 -04:00
1 parent 04878f0864
commit b6fb443f57
11 files changed
+207 -71

No files matched your search

+19 -8
View File
@@ -5,7 +5,11 @@
*/
import { describe, it, expect } from 'bun:test';
import { sanitizeEmail, isTokenExpired } from '../../../src/cliproxy/auth-utils';
import {
getTokenExpiryTimestamp,
isTokenExpired,
sanitizeEmail,
} from '../../../src/cliproxy/auth-utils';
describe('Auth Utilities', () => {
describe('sanitizeEmail', () => {
@@ -75,14 +79,21 @@ describe('Auth Utilities', () => {
expect(isTokenExpired(futureISO)).toBe(false);
});
it('should handle Unix timestamp strings', () => {
// JavaScript Date can parse numeric strings as timestamps
it('should handle Unix timestamp strings deterministically', () => {
const pastTimestamp = String(Date.now() - 86400000); // Yesterday
// Note: Date parsing of pure numbers as strings is inconsistent
// This test documents the actual behavior
const result = isTokenExpired(pastTimestamp);
// The behavior depends on how Date parses the string
expect(typeof result).toBe('boolean');
expect(isTokenExpired(pastTimestamp)).toBe(true);
});
it('should handle Unix timestamps provided as numbers', () => {
const futureTimestamp = Date.now() + 86400000;
expect(isTokenExpired(futureTimestamp)).toBe(false);
});
it('should expose normalized expiry timestamps for string and numeric inputs', () => {
const futureTimestamp = Date.now() + 60000;
expect(getTokenExpiryTimestamp(futureTimestamp)).toBe(futureTimestamp);
expect(getTokenExpiryTimestamp(String(futureTimestamp))).toBe(futureTimestamp);
expect(getTokenExpiryTimestamp('not-a-date')).toBeNull();
});
});
});
@@ -27,10 +27,10 @@ describe('Gemini CLI Quota Fetcher', () => {
let refreshGeminiToken: typeof import('../../../src/cliproxy/auth/gemini-token-refresh').refreshGeminiToken;
let getProviderAuthDir: typeof import('../../../src/cliproxy/config-generator').getProviderAuthDir;
function writeGeminiToken(token: Record<string, unknown>): string {
function writeGeminiToken(token: Record<string, unknown>, filename = 'gemini-test.json'): string {
const authDir = getProviderAuthDir('gemini');
fs.mkdirSync(authDir, { recursive: true });
const tokenPath = path.join(authDir, 'gemini-test.json');
const tokenPath = path.join(authDir, filename);
fs.writeFileSync(tokenPath, JSON.stringify(token, null, 2));
return tokenPath;
}
@@ -649,6 +649,74 @@ describe('Gemini CLI Quota Fetcher', () => {
expect(result.error).toBe('Gemini quota service unavailable (HTTP 502)');
expect(result.errorDetail).toBe('[HTML error response omitted]');
});
it('refreshes the requested Gemini account instead of the default account', async () => {
writeGeminiToken(
{
type: 'gemini',
email: 'default@example.com',
project_id: 'default-project',
token: {
access_token: 'default-access-token',
refresh_token: 'default-refresh-token',
expiry: Date.now() + 60 * 60 * 1000,
client_id: 'default-client-id',
client_secret: 'default-client-secret',
token_uri: GOOGLE_TOKEN_URL,
},
},
'gemini-default.json'
);
writeGeminiToken(
{
type: 'gemini',
email: 'target@example.com',
project_id: 'target-project',
token: {
access_token: 'target-stale-token',
refresh_token: 'target-refresh-token',
expiry: Date.now() - 1000,
client_id: 'target-client-id',
client_secret: 'target-client-secret',
token_uri: GOOGLE_TOKEN_URL,
},
},
'gemini-target.json'
);
mockFetch([
{
url: GOOGLE_TOKEN_URL,
method: 'POST',
response: { access_token: 'target-fresh-token', expires_in: 1800 },
},
{
url: GEMINI_QUOTA_URL,
method: 'POST',
status: 200,
response: {
buckets: [{ model_id: 'gemini-3-flash-preview', remaining_fraction: 0.88 }],
},
},
{
url: GEMINI_CODE_ASSIST_URL,
method: 'POST',
status: 503,
response: { error: { message: 'supplementary unavailable' } },
},
]);
const result = await fetchGeminiCliQuota('target@example.com');
expect(result.success).toBe(true);
const [refreshRequest, quotaRequest] = getCapturedFetchRequests();
expect(refreshRequest.url).toBe(GOOGLE_TOKEN_URL);
expect(refreshRequest.body).toContain('refresh_token=target-refresh-token');
expect(refreshRequest.body).not.toContain('default-refresh-token');
expect(quotaRequest.headers.Authorization).toBe('Bearer target-fresh-token');
});
});
describe('direct Gemini error helper coverage', () => {