fix: improve oauth error and model discovery fallbacks

This commit is contained in:
ciat-777
2026-03-17 23:13:01 +08:00
parent 2f2c93477d
commit f565d1b54d
6 changed files with 394 additions and 49 deletions
@@ -11,6 +11,8 @@ export const ANTIGRAVITY_LOOPBACK_CALLBACK_PORT = 51121;
export const ANTIGRAVITY_LOOPBACK_CALLBACK_PATH = '/oauth-callback';
export const ANTIGRAVITY_LOOPBACK_REDIRECT_URI = `http://localhost:${ANTIGRAVITY_LOOPBACK_CALLBACK_PORT}${ANTIGRAVITY_LOOPBACK_CALLBACK_PATH}`;
export const ANTIGRAVITY_UPSTREAM_BASE_URL = 'https://cloudcode-pa.googleapis.com';
export const ANTIGRAVITY_DAILY_UPSTREAM_BASE_URL = 'https://daily-cloudcode-pa.googleapis.com';
export const ANTIGRAVITY_SANDBOX_DAILY_UPSTREAM_BASE_URL = 'https://daily-cloudcode-pa.sandbox.googleapis.com';
export const ANTIGRAVITY_GOOGLE_API_CLIENT = 'google-cloud-sdk vscode_cloudshelleditor/0.1';
export const ANTIGRAVITY_USER_AGENT = 'google-api-nodejs-client/9.15.1';
export const ANTIGRAVITY_CLIENT_METADATA = '{"ideType":"IDE_UNSPECIFIED","platform":"PLATFORM_UNSPECIFIED","pluginType":"GEMINI"}';
@@ -156,16 +156,16 @@ async function resolveGeminiProjectId(accessToken: string, requestedProjectId?:
}
const projects = await fetchGcpProjects(accessToken);
if (projects.length === 1 && projects[0]) {
await ensureGeminiProjectEnabled(accessToken, projects[0]);
return projects[0];
}
if (projects.length <= 0) {
throw new Error('no Google Cloud projects available for this account');
}
throw new Error('gemini cli: project selection required');
const firstProject = projects[0];
if (!firstProject) {
throw new Error('no Google Cloud projects available for this account');
}
await ensureGeminiProjectEnabled(accessToken, firstProject);
return firstProject;
}
export const geminiCliOauthProvider: OAuthProviderDefinition = {
+42 -32
View File
@@ -356,40 +356,50 @@ export async function handleOauthCallback(input: {
throw new Error('missing oauth code');
}
const exchange = await definition.exchangeAuthorizationCode({
code,
state: input.state,
redirectUri: session.redirectUri,
codeVerifier: session.codeVerifier,
projectId: session.projectId,
});
const { account, site, created } = await upsertOauthAccount({
definition,
exchange,
rebindAccountId: session.rebindAccountId,
});
if (!account) {
markOauthSessionError(input.state, 'failed to persist oauth account');
throw new Error('failed to persist oauth account');
}
const refreshResult = await refreshModelsForAccount(account.id);
if (refreshResult.status !== 'success') {
if (created) {
await db.delete(schema.accounts).where(eq(schema.accounts.id, account.id)).run();
try {
const exchange = await definition.exchangeAuthorizationCode({
code,
state: input.state,
redirectUri: session.redirectUri,
codeVerifier: session.codeVerifier,
projectId: session.projectId,
});
const { account, site, created } = await upsertOauthAccount({
definition,
exchange,
rebindAccountId: session.rebindAccountId,
});
if (!account) {
markOauthSessionError(input.state, 'failed to persist oauth account');
throw new Error('failed to persist oauth account');
}
await rebuildTokenRoutesFromAvailability();
const errorMessage = refreshResult.errorMessage || `${input.provider} model discovery failed`;
markOauthSessionError(input.state, errorMessage);
throw new Error(errorMessage);
}
await rebuildTokenRoutesFromAvailability();
markOauthSessionSuccess(input.state, {
accountId: account.id,
siteId: site.id,
});
return { accountId: account.id, siteId: site.id };
const refreshResult = await refreshModelsForAccount(account.id);
if (refreshResult.status !== 'success') {
if (created) {
await db.delete(schema.accounts).where(eq(schema.accounts.id, account.id)).run();
}
await rebuildTokenRoutesFromAvailability();
const errorMessage = refreshResult.errorMessage || `${input.provider} model discovery failed`;
markOauthSessionError(input.state, errorMessage);
throw new Error(errorMessage);
}
await rebuildTokenRoutesFromAvailability();
markOauthSessionSuccess(input.state, {
accountId: account.id,
siteId: site.id,
});
return { accountId: account.id, siteId: site.id };
} catch (error) {
const message = (
error instanceof Error
? (error.message || error.name)
: String(error || 'OAuth failed')
).trim() || 'OAuth failed';
markOauthSessionError(input.state, message);
throw error;
}
}
export async function submitOauthManualCallback(input: {