fix google oauth

This commit is contained in:
paisley
2026-03-08 11:03:34 +08:00
parent 807df95e92
commit 38e8449ea2
14 changed files with 1125 additions and 89 deletions

View File

@@ -1,9 +1,12 @@
import type { GatewayManager } from '../../gateway/manager';
import { getProviderAccount } from './provider-store';
import { getProviderSecret } from '../secrets/secret-store';
import type { ProviderConfig } from '../../utils/secure-storage';
import { getAllProviders, getApiKey, getDefaultProvider, getProvider } from '../../utils/secure-storage';
import { getProviderConfig, getProviderDefaultModel } from '../../utils/provider-registry';
import {
removeProviderFromOpenClaw,
saveOAuthTokenToOpenClaw,
saveProviderKeyToOpenClaw,
setOpenClawDefaultModel,
setOpenClawDefaultModelWithOverride,
@@ -12,6 +15,9 @@ import {
} from '../../utils/openclaw-auth';
import { logger } from '../../utils/logger';
const GOOGLE_OAUTH_RUNTIME_PROVIDER = 'google-gemini-cli';
const GOOGLE_OAUTH_DEFAULT_MODEL_REF = `${GOOGLE_OAUTH_RUNTIME_PROVIDER}/gemini-3-pro-preview`;
export function getOpenClawProviderKey(type: string, providerId: string): string {
if (type === 'custom' || type === 'ollama') {
const suffix = providerId.replace(/-/g, '').slice(0, 8);
@@ -23,6 +29,24 @@ export function getOpenClawProviderKey(type: string, providerId: string): string
return type;
}
async function resolveRuntimeProviderKey(config: ProviderConfig): Promise<string> {
const account = await getProviderAccount(config.id);
if (config.type === 'google' && account?.authMode === 'oauth_browser') {
return GOOGLE_OAUTH_RUNTIME_PROVIDER;
}
return getOpenClawProviderKey(config.type, config.id);
}
async function isGoogleBrowserOAuthProvider(config: ProviderConfig): Promise<boolean> {
const account = await getProviderAccount(config.id);
if (config.type !== 'google' || account?.authMode !== 'oauth_browser') {
return false;
}
const secret = await getProviderSecret(config.id);
return secret?.type === 'oauth';
}
export function getProviderModelRef(config: ProviderConfig): string | undefined {
const providerKey = getOpenClawProviderKey(config.type, config.id);
@@ -201,12 +225,13 @@ export async function syncDeletedProviderToRuntime(
provider: ProviderConfig | null,
providerId: string,
gatewayManager?: GatewayManager,
runtimeProviderKey?: string,
): Promise<void> {
if (!provider?.type) {
return;
}
const ock = getOpenClawProviderKey(provider.type, providerId);
const ock = runtimeProviderKey ?? await resolveRuntimeProviderKey({ ...provider, id: providerId });
await removeProviderFromOpenClaw(ock);
scheduleGatewayRestart(
@@ -218,12 +243,13 @@ export async function syncDeletedProviderToRuntime(
export async function syncDeletedProviderApiKeyToRuntime(
provider: ProviderConfig | null,
providerId: string,
runtimeProviderKey?: string,
): Promise<void> {
if (!provider?.type) {
return;
}
const ock = getOpenClawProviderKey(provider.type, providerId);
const ock = runtimeProviderKey ?? await resolveRuntimeProviderKey({ ...provider, id: providerId });
await removeProviderFromOpenClaw(ock);
}
@@ -236,11 +262,12 @@ export async function syncDefaultProviderToRuntime(
return;
}
const ock = getOpenClawProviderKey(provider.type, providerId);
const ock = await resolveRuntimeProviderKey(provider);
const providerKey = await getApiKey(providerId);
const fallbackModels = await getProviderFallbackModelRefs(provider);
const oauthTypes = ['qwen-portal', 'minimax-portal', 'minimax-portal-cn'];
const isOAuthProvider = oauthTypes.includes(provider.type) && !providerKey;
const isGoogleOAuthProvider = await isGoogleBrowserOAuthProvider(provider);
const isOAuthProvider = (oauthTypes.includes(provider.type) && !providerKey) || isGoogleOAuthProvider;
if (!isOAuthProvider) {
const modelOverride = provider.model
@@ -260,6 +287,33 @@ export async function syncDefaultProviderToRuntime(
await saveProviderKeyToOpenClaw(ock, providerKey);
}
} else {
if (isGoogleOAuthProvider) {
const secret = await getProviderSecret(provider.id);
if (secret?.type === 'oauth') {
await saveOAuthTokenToOpenClaw(GOOGLE_OAUTH_RUNTIME_PROVIDER, {
access: secret.accessToken,
refresh: secret.refreshToken,
expires: secret.expiresAt,
email: secret.email,
projectId: secret.subject,
});
}
const modelOverride = provider.model
? (provider.model.startsWith(`${GOOGLE_OAUTH_RUNTIME_PROVIDER}/`)
? provider.model
: `${GOOGLE_OAUTH_RUNTIME_PROVIDER}/${provider.model}`)
: GOOGLE_OAUTH_DEFAULT_MODEL_REF;
await setOpenClawDefaultModel(GOOGLE_OAUTH_RUNTIME_PROVIDER, modelOverride, fallbackModels);
logger.info(`Configured openclaw.json for Google browser OAuth provider "${provider.id}"`);
scheduleGatewayRestart(
gatewayManager,
`Scheduling Gateway restart after provider switch to "${GOOGLE_OAUTH_RUNTIME_PROVIDER}"`,
);
return;
}
const defaultBaseUrl = provider.type === 'minimax-portal'
? 'https://api.minimax.io/anthropic'
: (provider.type === 'minimax-portal-cn' ? 'https://api.minimaxi.com/anthropic' : 'https://portal.qwen.ai/v1');

View File

@@ -55,6 +55,7 @@ export class ProviderService {
async createAccount(account: ProviderAccount, apiKey?: string): Promise<ProviderAccount> {
await ensureProviderStoreMigrated();
await saveProvider(providerAccountToConfig(account));
await saveProviderAccount(account);
if (apiKey !== undefined && apiKey.trim()) {
await storeApiKey(account.id, apiKey.trim());
}
@@ -80,6 +81,7 @@ export class ProviderService {
};
await saveProvider(providerAccountToConfig(nextAccount));
await saveProviderAccount(nextAccount);
if (apiKey !== undefined) {
const trimmedKey = apiKey.trim();
if (trimmedKey) {