mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 16:14:31 +00:00
fix(cliproxy): surface quota metadata in CLI
This commit is contained in:
1 parent
4d49d13931
commit
19f6b3c4e6
4 files changed
+227
-6
No files matched your search
@@ -22,6 +22,7 @@ describe('Gemini CLI Quota Fetcher', () => {
|
||||
let buildGeminiCliBuckets: typeof import('../../../src/cliproxy/quota-fetcher-gemini-cli').buildGeminiCliBuckets;
|
||||
let fetchGeminiCliQuota: typeof import('../../../src/cliproxy/quota-fetcher-gemini-cli').fetchGeminiCliQuota;
|
||||
let resolveGeminiCliProjectId: typeof import('../../../src/cliproxy/quota-fetcher-gemini-cli').resolveGeminiCliProjectId;
|
||||
let geminiTestExports: typeof import('../../../src/cliproxy/quota-fetcher-gemini-cli').__testExports;
|
||||
let refreshGeminiToken: typeof import('../../../src/cliproxy/auth/gemini-token-refresh').refreshGeminiToken;
|
||||
let getProviderAuthDir: typeof import('../../../src/cliproxy/config-generator').getProviderAuthDir;
|
||||
|
||||
@@ -69,7 +70,12 @@ describe('Gemini CLI Quota Fetcher', () => {
|
||||
const configGenerator = await import(
|
||||
`../../../src/cliproxy/config-generator?gemini-config-generator=${moduleVersion}`
|
||||
);
|
||||
({ buildGeminiCliBuckets, fetchGeminiCliQuota, resolveGeminiCliProjectId } = await import(
|
||||
({
|
||||
buildGeminiCliBuckets,
|
||||
fetchGeminiCliQuota,
|
||||
resolveGeminiCliProjectId,
|
||||
__testExports: geminiTestExports,
|
||||
} = await import(
|
||||
`../../../src/cliproxy/quota-fetcher-gemini-cli?gemini-quota-fetcher=${moduleVersion}`
|
||||
));
|
||||
({ refreshGeminiToken } = await import(
|
||||
@@ -452,6 +458,62 @@ describe('Gemini CLI Quota Fetcher', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('direct Gemini error helper coverage', () => {
|
||||
it('sanitizes HTML and truncates oversized token-bearing error details', () => {
|
||||
const longTokenBody = JSON.stringify({
|
||||
access_token: 'super-secret-token',
|
||||
detail: `Bearer top-secret ${'x'.repeat(400)}`,
|
||||
});
|
||||
|
||||
const sanitized = geminiTestExports.sanitizeGeminiCliErrorDetail(longTokenBody);
|
||||
|
||||
expect(sanitized).toContain('[redacted]');
|
||||
expect(sanitized).toContain('Bearer [redacted]');
|
||||
expect(sanitized?.endsWith('...[truncated]')).toBe(true);
|
||||
expect(sanitized?.length).toBeLessThanOrEqual(320);
|
||||
expect(geminiTestExports.sanitizeGeminiCliErrorDetail('<html>bad gateway</html>')).toBe(
|
||||
'[HTML error response omitted]'
|
||||
);
|
||||
});
|
||||
|
||||
it('extracts nested messages and parses structured JSON error bodies', () => {
|
||||
expect(
|
||||
geminiTestExports.extractGeminiCliNestedMessage([
|
||||
{ reason: 'ACCOUNT_VERIFICATION_REQUIRED' },
|
||||
])
|
||||
).toBe('ACCOUNT_VERIFICATION_REQUIRED');
|
||||
|
||||
const parsed = geminiTestExports.parseGeminiCliErrorBody(
|
||||
JSON.stringify({
|
||||
error: {
|
||||
message: 'Verification required',
|
||||
status: 'PERMISSION_DENIED',
|
||||
details: [{ reason: 'ACCOUNT_VERIFICATION_REQUIRED' }],
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
expect(parsed.message).toBe('Verification required');
|
||||
expect(parsed.errorCode).toBe('PERMISSION_DENIED');
|
||||
expect(parsed.errorDetail).toContain('ACCOUNT_VERIFICATION_REQUIRED');
|
||||
});
|
||||
|
||||
it('builds verification and project-specific forbidden action hints', () => {
|
||||
expect(
|
||||
geminiTestExports.buildGeminiCliForbiddenActionHint({
|
||||
message: 'Please verify this account',
|
||||
errorDetail: 'ACCOUNT_VERIFICATION_REQUIRED',
|
||||
})
|
||||
).toContain('verification');
|
||||
|
||||
expect(
|
||||
geminiTestExports.buildGeminiCliForbiddenActionHint({
|
||||
message: 'Project no longer has access',
|
||||
})
|
||||
).toContain('project');
|
||||
});
|
||||
});
|
||||
|
||||
describe('refreshGeminiToken', () => {
|
||||
it('uses OAuth client metadata stored in the token file', async () => {
|
||||
writeGeminiToken({
|
||||
|
||||
Reference in new issue
Block a user