fix(cliproxy): refresh upstream model and quota surfaces (#1158)

* fix(cliproxy): refresh upstream model and quota surfaces

* test(cliproxy): cover codex legacy model fallback
This commit is contained in:
Kai (Tam Nhu) Tran authored and GitHub committed 2026-05-01 02:19:31 -04:00
1 parent 66865127d7
commit 50b0ffba75
7 files changed
+220 -97

No files matched your search

+2 -2
View File
@@ -19,13 +19,13 @@ export const BACKEND_CONFIG = {
repo: 'router-for-me/CLIProxyAPI',
binaryPrefix: 'CLIProxyAPI',
executable: 'cli-proxy-api',
fallbackVersion: '6.8.2',
fallbackVersion: '6.9.45',
},
plus: {
repo: 'kaitranntt/CLIProxyAPIPlus',
binaryPrefix: 'CLIProxyAPIPlus',
executable: 'cli-proxy-api-plus',
fallbackVersion: '6.9.36-0',
fallbackVersion: '6.9.45-0',
},
} as const;
@@ -208,4 +208,111 @@ describe('Antigravity quota failure metadata', () => {
fs.rmSync(tempHome, { recursive: true, force: true });
}
});
it('tries the daily loadCodeAssist host before falling back to prod', async () => {
const moduleId = Date.now() + Math.random();
const { fetchAccountQuota } = await import(`../quota-fetcher?agy-daily-host=${moduleId}`);
const { getProviderAuthDir } = await import(
`../../config/config-generator?agy-config=${moduleId}`
);
const fs = await import('node:fs');
const os = await import('node:os');
const path = await import('node:path');
const tempHome = fs.mkdtempSync(path.join(os.tmpdir(), 'ccs-agy-daily-host-'));
const originalCcsHome = process.env.CCS_HOME;
process.env.CCS_HOME = tempHome;
try {
const authDir = getProviderAuthDir('agy');
fs.mkdirSync(authDir, { recursive: true });
fs.writeFileSync(
path.join(authDir, 'antigravity-user@example.com.json'),
JSON.stringify({
type: 'antigravity',
email: 'user@example.com',
access_token: 'token',
})
);
const originalFetch = globalThis.fetch;
const urls: string[] = [];
globalThis.fetch = (async (input, init) => {
const url = String(input);
urls.push(url);
if (url === 'https://daily-cloudcode-pa.googleapis.com/v1internal:loadCodeAssist') {
const bodyText = typeof init?.body === 'string' ? init.body : '';
expect(init?.headers).toMatchObject({
'X-Goog-Api-Client': 'gl-node/22.21.1',
});
expect(bodyText).toBe(
JSON.stringify({
metadata: {
ide_name: 'antigravity',
ide_type: 'ANTIGRAVITY',
ide_version: '1.21.9',
},
})
);
return new Response('daily unavailable', { status: 503 });
}
if (url === 'https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist') {
return new Response(
JSON.stringify({
cloudaicompanionProject: { id: 'project-x' },
paidTier: { id: 'g1-pro-tier' },
}),
{
status: 200,
headers: { 'Content-Type': 'application/json' },
}
);
}
if (url === 'https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels') {
return new Response(
JSON.stringify({
models: {
'gemini-3-pro-high': {
quotaInfo: {
remainingFraction: 0.75,
resetTime: '2026-05-01T10:00:00Z',
},
},
},
}),
{
status: 200,
headers: { 'Content-Type': 'application/json' },
}
);
}
return new Response('unexpected url', { status: 500 });
}) as typeof fetch;
try {
const result = await fetchAccountQuota('agy', 'user@example.com');
expect(result.success).toBe(true);
expect(result.tier).toBe('pro');
expect(result.projectId).toBe('project-x');
expect(urls).toEqual([
'https://daily-cloudcode-pa.googleapis.com/v1internal:loadCodeAssist',
'https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist',
'https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels',
]);
} finally {
globalThis.fetch = originalFetch;
}
} finally {
if (originalCcsHome === undefined) {
delete process.env.CCS_HOME;
} else {
process.env.CCS_HOME = originalCcsHome;
}
fs.rmSync(tempHome, { recursive: true, force: true });
}
});
});
+48 -11
View File
@@ -82,17 +82,20 @@ export interface QuotaResult {
}
/** Google Cloud Code API endpoints */
const ANTIGRAVITY_DAILY_API_BASE = 'https://daily-cloudcode-pa.googleapis.com';
const ANTIGRAVITY_API_BASE = 'https://cloudcode-pa.googleapis.com';
const ANTIGRAVITY_API_VERSION = 'v1internal';
const ANTIGRAVITY_LOADCODEASSIST_BASE_URLS = [
ANTIGRAVITY_DAILY_API_BASE,
ANTIGRAVITY_API_BASE,
] as const;
const MANAGEMENT_API_TIMEOUT_MS = 5000;
/** Headers for loadCodeAssist (matches CLIProxyAPI antigravity.go) */
/** Headers for loadCodeAssist (matches current CLIProxyAPIPlus control-plane requests) */
const LOADCODEASSIST_HEADERS = {
'Content-Type': 'application/json',
'User-Agent': 'google-api-nodejs-client/9.15.1',
'X-Goog-Api-Client': 'google-cloud-sdk vscode_cloudshelleditor/0.1',
'Client-Metadata':
'{"ideType":"IDE_UNSPECIFIED","platform":"PLATFORM_UNSPECIFIED","pluginType":"GEMINI"}',
'User-Agent': 'antigravity/1.21.9 darwin/arm64 google-api-nodejs-client/10.3.0',
'X-Goog-Api-Client': 'gl-node/22.21.1',
};
/** Headers for fetchAvailableModels (matches CLIProxyAPI antigravity_executor.go) */
@@ -543,6 +546,40 @@ async function performAntigravityRequest(
}
}
async function performAntigravityRequestWithBaseUrlFallback(
accountId: string,
accessToken: string,
baseUrls: readonly string[],
apiPath: string,
headers: Record<string, string>,
body: string
): Promise<ManagedResponse> {
let lastResponse: ManagedResponse | null = null;
for (const baseUrl of baseUrls) {
const response = await performAntigravityRequest(
accountId,
accessToken,
`${baseUrl}/${apiPath}`,
headers,
body
);
if (response.status >= 200 && response.status < 300) {
return response;
}
lastResponse = response;
}
return (
lastResponse ?? {
status: 503,
bodyText: 'No Antigravity API endpoint available',
json: null,
viaManagement: false,
}
);
}
/**
* Read auth data from auth file (access token, project_id, expiry status)
*/
@@ -616,18 +653,18 @@ function readAuthData(provider: CLIProxyProvider, accountId: string): AuthData |
* Uses paidTier.id for accurate tier detection (g1-ultra-tier, g1-pro-tier)
*/
async function getProjectId(accountId: string, accessToken: string): Promise<ProjectLookupResult> {
const url = `${ANTIGRAVITY_API_BASE}/${ANTIGRAVITY_API_VERSION}:loadCodeAssist`;
const body = JSON.stringify({
metadata: {
ideType: 'IDE_UNSPECIFIED',
platform: 'PLATFORM_UNSPECIFIED',
pluginType: 'GEMINI',
ide_name: 'antigravity',
ide_type: 'ANTIGRAVITY',
ide_version: '1.21.9',
},
});
const response = await performAntigravityRequest(
const response = await performAntigravityRequestWithBaseUrlFallback(
accountId,
accessToken,
url,
ANTIGRAVITY_LOADCODEASSIST_BASE_URLS,
`${ANTIGRAVITY_API_VERSION}:loadCodeAssist`,
LOADCODEASSIST_HEADERS,
body
);