Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/oauth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ export async function getValidAccessTokenSnapshot(provider: string): Promise<OAu
}

/** Providers whose upstream-401 replay path may force a snapshot refresh. */
const FORCE_REFRESH_PROVIDERS = new Set(["xai", "github-copilot", "kiro"]);
const FORCE_REFRESH_PROVIDERS = new Set(["xai", "github-copilot", "kiro", "google-antigravity"]);

export async function forceRefreshOAuthAccessSnapshot(
rejected: OAuthAccessSnapshot,
Expand Down
29 changes: 25 additions & 4 deletions src/server/responses/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3327,8 +3327,12 @@ async function handleResponsesInner(

// OAuth providers: swap in a fresh access token (auto-refreshed) as the Bearer key, so the
// existing openai-chat / anthropic adapters authenticate with no change.
const isOAuth401ReplayProvider = (route.providerName === "xai" || route.providerName === "github-copilot" || route.providerName === "kiro")
&& route.provider.authMode === "oauth";
const isOAuth401ReplayProvider = (
route.providerName === "xai"
|| route.providerName === "github-copilot"
|| route.providerName === "kiro"
|| route.providerName === "google-antigravity"
) && route.provider.authMode === "oauth";
let sentOAuthSnapshot: OAuthAccessSnapshot | undefined;
let replayOAuthCredentialSnapshot: Pick<OAuthAccessSnapshot, "accountId" | "generation"> | undefined;
let anthropicPoolAccountId: string | null = null;
Expand Down Expand Up @@ -4369,6 +4373,11 @@ async function handleResponsesInner(
releaseCodexAuthContextProbeLease(authCtx);
return formatErrorResponse(401, "authentication_error", publicOAuthAuthenticationErrorMessage(err));
}
if (route.provider.googleMode === "cloud-code-assist" && !refreshed.projectId) {
upstream.abort();
releaseCodexAuthContextProbeLease(authCtx);
return formatErrorResponse(401, "authentication_error", publicOAuthAuthenticationErrorMessage(new Error("Cloud Code Assist project is required")));
}
sentOAuthSnapshot = refreshed;
replayOAuthCredentialSnapshot = {
accountId: refreshed.accountId,
Expand All @@ -4379,7 +4388,11 @@ async function handleResponsesInner(
}
const refreshedProvider = resolveProviderTransport(
route.providerName,
{ ...route.provider, apiKey: refreshed.accessToken },
{
...route.provider,
apiKey: refreshed.accessToken,
...(refreshed.projectId ? { project: refreshed.projectId } : {}),
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
parsed.options.promptCacheKey,
route.providerName === "github-copilot"
? resolveCopilotApiBaseUrl(refreshed.apiBaseUrl)
Expand Down Expand Up @@ -6120,6 +6133,10 @@ async function handleResponsesInner(
cleanupUpstreamAbort();
return formatErrorResponse(401, "authentication_error", publicOAuthAuthenticationErrorMessage(err));
}
if (route.provider.googleMode === "cloud-code-assist" && !refreshed.projectId) {
cleanupUpstreamAbort();
return formatErrorResponse(401, "authentication_error", publicOAuthAuthenticationErrorMessage(new Error("Cloud Code Assist project is required")));
}
sentOAuthSnapshot = refreshed;
replayOAuthCredentialSnapshot = {
accountId: refreshed.accountId,
Expand All @@ -6130,7 +6147,11 @@ async function handleResponsesInner(
}
const refreshedProvider = resolveProviderTransport(
route.providerName,
{ ...route.provider, apiKey: refreshed.accessToken },
{
...route.provider,
apiKey: refreshed.accessToken,
...(refreshed.projectId ? { project: refreshed.projectId } : {}),
},
parsed.options.promptCacheKey,
route.providerName === "github-copilot"
? resolveCopilotApiBaseUrl(refreshed.apiBaseUrl)
Expand Down
Loading
Loading