mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 02:31:22 +00:00
refactor!: remove google-antigravity provider support
This commit is contained in:
@@ -62,7 +62,7 @@ const AUTH_CHOICE_GROUP_DEFS: {
|
||||
value: "google",
|
||||
label: "Google",
|
||||
hint: "Gemini API key + OAuth",
|
||||
choices: ["gemini-api-key", "google-antigravity", "google-gemini-cli"],
|
||||
choices: ["gemini-api-key", "google-gemini-cli"],
|
||||
},
|
||||
{
|
||||
value: "xai",
|
||||
@@ -254,11 +254,6 @@ const BASE_AUTH_CHOICE_OPTIONS: ReadonlyArray<AuthChoiceOption> = [
|
||||
hint: "Uses GitHub device flow",
|
||||
},
|
||||
{ value: "gemini-api-key", label: "Google Gemini API key" },
|
||||
{
|
||||
value: "google-antigravity",
|
||||
label: "Google Antigravity OAuth",
|
||||
hint: "Uses the bundled Antigravity auth plugin",
|
||||
},
|
||||
{
|
||||
value: "google-gemini-cli",
|
||||
label: "Google Gemini CLI OAuth",
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import type { ApplyAuthChoiceParams, ApplyAuthChoiceResult } from "./auth-choice.apply.js";
|
||||
import { applyAuthChoicePluginProvider } from "./auth-choice.apply.plugin-provider.js";
|
||||
|
||||
export async function applyAuthChoiceGoogleAntigravity(
|
||||
params: ApplyAuthChoiceParams,
|
||||
): Promise<ApplyAuthChoiceResult | null> {
|
||||
return await applyAuthChoicePluginProvider(params, {
|
||||
authChoice: "google-antigravity",
|
||||
pluginId: "google-antigravity-auth",
|
||||
providerId: "google-antigravity",
|
||||
methodId: "oauth",
|
||||
label: "Google Antigravity",
|
||||
});
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import { applyAuthChoiceApiProviders } from "./auth-choice.apply.api-providers.j
|
||||
import { applyAuthChoiceBytePlus } from "./auth-choice.apply.byteplus.js";
|
||||
import { applyAuthChoiceCopilotProxy } from "./auth-choice.apply.copilot-proxy.js";
|
||||
import { applyAuthChoiceGitHubCopilot } from "./auth-choice.apply.github-copilot.js";
|
||||
import { applyAuthChoiceGoogleAntigravity } from "./auth-choice.apply.google-antigravity.js";
|
||||
import { applyAuthChoiceGoogleGeminiCli } from "./auth-choice.apply.google-gemini-cli.js";
|
||||
import { applyAuthChoiceMiniMax } from "./auth-choice.apply.minimax.js";
|
||||
import { applyAuthChoiceOAuth } from "./auth-choice.apply.oauth.js";
|
||||
@@ -44,7 +43,6 @@ export async function applyAuthChoice(
|
||||
applyAuthChoiceApiProviders,
|
||||
applyAuthChoiceMiniMax,
|
||||
applyAuthChoiceGitHubCopilot,
|
||||
applyAuthChoiceGoogleAntigravity,
|
||||
applyAuthChoiceGoogleGeminiCli,
|
||||
applyAuthChoiceCopilotProxy,
|
||||
applyAuthChoiceQwenPortal,
|
||||
|
||||
@@ -18,7 +18,6 @@ const PREFERRED_PROVIDER_BY_AUTH_CHOICE: Partial<Record<AuthChoice, string>> = {
|
||||
"moonshot-api-key-cn": "moonshot",
|
||||
"kimi-code-api-key": "kimi-coding",
|
||||
"gemini-api-key": "google",
|
||||
"google-antigravity": "google-antigravity",
|
||||
"google-gemini-cli": "google-gemini-cli",
|
||||
"mistral-api-key": "mistral",
|
||||
"zai-api-key": "zai",
|
||||
|
||||
@@ -13,24 +13,24 @@ function makeProvider(params: { id: string; label?: string; aliases?: string[] }
|
||||
|
||||
describe("resolveRequestedLoginProviderOrThrow", () => {
|
||||
it("returns null when no provider was requested", () => {
|
||||
const providers = [makeProvider({ id: "google-antigravity" })];
|
||||
const providers = [makeProvider({ id: "google-gemini-cli" })];
|
||||
const result = resolveRequestedLoginProviderOrThrow(providers, undefined);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("resolves requested provider by id", () => {
|
||||
const providers = [
|
||||
makeProvider({ id: "google-antigravity" }),
|
||||
makeProvider({ id: "google-gemini-cli" }),
|
||||
makeProvider({ id: "qwen-portal" }),
|
||||
];
|
||||
const result = resolveRequestedLoginProviderOrThrow(providers, "google-antigravity");
|
||||
expect(result?.id).toBe("google-antigravity");
|
||||
const result = resolveRequestedLoginProviderOrThrow(providers, "google-gemini-cli");
|
||||
expect(result?.id).toBe("google-gemini-cli");
|
||||
});
|
||||
|
||||
it("resolves requested provider by alias", () => {
|
||||
const providers = [makeProvider({ id: "google-antigravity", aliases: ["antigravity"] })];
|
||||
const result = resolveRequestedLoginProviderOrThrow(providers, "antigravity");
|
||||
expect(result?.id).toBe("google-antigravity");
|
||||
const providers = [makeProvider({ id: "google-gemini-cli", aliases: ["gemini-cli"] })];
|
||||
const result = resolveRequestedLoginProviderOrThrow(providers, "gemini-cli");
|
||||
expect(result?.id).toBe("google-gemini-cli");
|
||||
});
|
||||
|
||||
it("throws when requested provider is not loaded", () => {
|
||||
|
||||
@@ -200,30 +200,6 @@ describe("models list/status", () => {
|
||||
return JSON.parse(String(runtime.log.mock.calls[0]?.[0]));
|
||||
}
|
||||
|
||||
async function runAvailabilityFallbackCase(params: {
|
||||
setup?: () => void;
|
||||
expectedErrorDetail: string;
|
||||
}) {
|
||||
configureGoogleAntigravityModel("claude-opus-4-6-thinking");
|
||||
enableGoogleAntigravityAuthProfile();
|
||||
const runtime = makeRuntime();
|
||||
|
||||
modelRegistryState.models = [
|
||||
makeGoogleAntigravityTemplate("claude-opus-4-5-thinking", "Claude Opus 4.5 Thinking"),
|
||||
];
|
||||
modelRegistryState.available = [];
|
||||
params.setup?.();
|
||||
await modelsListCommand({ json: true }, runtime);
|
||||
|
||||
expect(runtime.error).toHaveBeenCalledTimes(1);
|
||||
expect(runtime.error.mock.calls[0]?.[0]).toContain("falling back to auth heuristics");
|
||||
expect(runtime.error.mock.calls[0]?.[0]).toContain(params.expectedErrorDetail);
|
||||
const payload = parseJsonLog(runtime);
|
||||
expect(payload.models[0]?.key).toBe("google-antigravity/claude-opus-4-6-thinking");
|
||||
expect(payload.models[0]?.missing).toBe(false);
|
||||
expect(payload.models[0]?.available).toBe(true);
|
||||
}
|
||||
|
||||
async function expectZaiProviderFilter(provider: string) {
|
||||
setDefaultZaiRegistry();
|
||||
const runtime = makeRuntime();
|
||||
@@ -242,66 +218,6 @@ describe("models list/status", () => {
|
||||
modelRegistryState.available = available ? [ZAI_MODEL, OPENAI_MODEL] : [];
|
||||
}
|
||||
|
||||
function setupGoogleAntigravityTemplateCase(params: {
|
||||
configuredModelId: string;
|
||||
templateId: string;
|
||||
templateName: string;
|
||||
available?: boolean;
|
||||
}) {
|
||||
configureGoogleAntigravityModel(params.configuredModelId);
|
||||
const template = makeGoogleAntigravityTemplate(params.templateId, params.templateName);
|
||||
modelRegistryState.models = [template];
|
||||
modelRegistryState.available = params.available ? [template] : [];
|
||||
return template;
|
||||
}
|
||||
|
||||
async function runGoogleAntigravityListCase(params: {
|
||||
configuredModelId: string;
|
||||
templateId: string;
|
||||
templateName: string;
|
||||
available?: boolean;
|
||||
withAuthProfile?: boolean;
|
||||
}) {
|
||||
setupGoogleAntigravityTemplateCase(params);
|
||||
if (params.withAuthProfile) {
|
||||
enableGoogleAntigravityAuthProfile();
|
||||
}
|
||||
const runtime = makeRuntime();
|
||||
await modelsListCommand({ json: true }, runtime);
|
||||
return parseJsonLog(runtime);
|
||||
}
|
||||
|
||||
const GOOGLE_ANTIGRAVITY_OPUS_46_CASES = [
|
||||
{
|
||||
name: "thinking",
|
||||
configuredModelId: "claude-opus-4-6-thinking",
|
||||
templateId: "claude-opus-4-5-thinking",
|
||||
templateName: "Claude Opus 4.5 Thinking",
|
||||
expectedKey: "google-antigravity/claude-opus-4-6-thinking",
|
||||
},
|
||||
{
|
||||
name: "non-thinking",
|
||||
configuredModelId: "claude-opus-4-6",
|
||||
templateId: "claude-opus-4-5",
|
||||
templateName: "Claude Opus 4.5",
|
||||
expectedKey: "google-antigravity/claude-opus-4-6",
|
||||
},
|
||||
] as const;
|
||||
|
||||
function expectAntigravityModel(
|
||||
payload: Record<string, unknown>,
|
||||
params: { key: string; available: boolean; includesTags?: boolean },
|
||||
) {
|
||||
const model = (payload.models as Array<Record<string, unknown>>)[0] ?? {};
|
||||
expect(model.key).toBe(params.key);
|
||||
expect(model.missing).toBe(false);
|
||||
expect(model.available).toBe(params.available);
|
||||
if (params.includesTags) {
|
||||
expect(model.tags).toContain("default");
|
||||
expect(model.tags).toContain("configured");
|
||||
}
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
({ modelsListCommand } = await import("./models/list.list-command.js"));
|
||||
({ loadModelRegistry, toModelRow } = await import("./models/list.registry.js"));
|
||||
@@ -357,177 +273,6 @@ describe("models list/status", () => {
|
||||
expect(payload.models[0]?.available).toBe(false);
|
||||
});
|
||||
|
||||
it.each(GOOGLE_ANTIGRAVITY_OPUS_46_CASES)(
|
||||
"models list resolves antigravity opus 4.6 $name from 4.5 template",
|
||||
async ({ configuredModelId, templateId, templateName, expectedKey }) => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
configuredModelId,
|
||||
templateId,
|
||||
templateName,
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: expectedKey,
|
||||
available: false,
|
||||
includesTags: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it.each(GOOGLE_ANTIGRAVITY_OPUS_46_CASES)(
|
||||
"models list marks synthesized antigravity opus 4.6 $name as available when template is available",
|
||||
async ({ configuredModelId, templateId, templateName, expectedKey }) => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
configuredModelId,
|
||||
templateId,
|
||||
templateName,
|
||||
available: true,
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: expectedKey,
|
||||
available: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: "high",
|
||||
configuredModelId: "gemini-3-1-pro-high",
|
||||
templateId: "gemini-3-pro-high",
|
||||
templateName: "Gemini 3 Pro High",
|
||||
expectedKey: "google-antigravity/gemini-3-1-pro-high",
|
||||
},
|
||||
{
|
||||
name: "low",
|
||||
configuredModelId: "gemini-3-1-pro-low",
|
||||
templateId: "gemini-3-pro-low",
|
||||
templateName: "Gemini 3 Pro Low",
|
||||
expectedKey: "google-antigravity/gemini-3-1-pro-low",
|
||||
},
|
||||
] as const)(
|
||||
"models list resolves antigravity gemini 3.1 $name from gemini 3 template",
|
||||
async ({ configuredModelId, templateId, templateName, expectedKey }) => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
configuredModelId,
|
||||
templateId,
|
||||
templateName,
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: expectedKey,
|
||||
available: false,
|
||||
includesTags: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: "high",
|
||||
configuredModelId: "gemini-3-1-pro-high",
|
||||
templateId: "gemini-3-pro-high",
|
||||
templateName: "Gemini 3 Pro High",
|
||||
expectedKey: "google-antigravity/gemini-3-1-pro-high",
|
||||
},
|
||||
{
|
||||
name: "low",
|
||||
configuredModelId: "gemini-3-1-pro-low",
|
||||
templateId: "gemini-3-pro-low",
|
||||
templateName: "Gemini 3 Pro Low",
|
||||
expectedKey: "google-antigravity/gemini-3-1-pro-low",
|
||||
},
|
||||
] as const)(
|
||||
"models list marks synthesized antigravity gemini 3.1 $name as available when template is available",
|
||||
async ({ configuredModelId, templateId, templateName, expectedKey }) => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
configuredModelId,
|
||||
templateId,
|
||||
templateName,
|
||||
available: true,
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: expectedKey,
|
||||
available: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: "high",
|
||||
configuredModelId: "gemini-3.1-pro-high",
|
||||
templateId: "gemini-3-pro-high",
|
||||
templateName: "Gemini 3 Pro High",
|
||||
expectedKey: "google-antigravity/gemini-3.1-pro-high",
|
||||
},
|
||||
{
|
||||
name: "low",
|
||||
configuredModelId: "gemini-3.1-pro-low",
|
||||
templateId: "gemini-3-pro-low",
|
||||
templateName: "Gemini 3 Pro Low",
|
||||
expectedKey: "google-antigravity/gemini-3.1-pro-low",
|
||||
},
|
||||
] as const)(
|
||||
"models list marks dot-notation antigravity gemini 3.1 $name as available when template is available",
|
||||
async ({ configuredModelId, templateId, templateName, expectedKey }) => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
configuredModelId,
|
||||
templateId,
|
||||
templateName,
|
||||
available: true,
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: expectedKey,
|
||||
available: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it("models list prefers registry availability over provider auth heuristics", async () => {
|
||||
const payload = await runGoogleAntigravityListCase({
|
||||
configuredModelId: "claude-opus-4-6-thinking",
|
||||
templateId: "claude-opus-4-5-thinking",
|
||||
templateName: "Claude Opus 4.5 Thinking",
|
||||
withAuthProfile: true,
|
||||
});
|
||||
expectAntigravityModel(payload, {
|
||||
key: "google-antigravity/claude-opus-4-6-thinking",
|
||||
available: false,
|
||||
});
|
||||
listProfilesForProvider.mockReturnValue([]);
|
||||
});
|
||||
|
||||
it("models list falls back to auth heuristics when registry availability is unavailable", async () => {
|
||||
await runAvailabilityFallbackCase({
|
||||
setup: () => {
|
||||
modelRegistryState.getAvailableError = Object.assign(
|
||||
new Error("availability unsupported: getAvailable failed"),
|
||||
{ code: "MODEL_AVAILABILITY_UNAVAILABLE" },
|
||||
);
|
||||
},
|
||||
expectedErrorDetail: "getAvailable failed",
|
||||
});
|
||||
});
|
||||
|
||||
it("models list falls back to auth heuristics when getAvailable returns invalid shape", async () => {
|
||||
await runAvailabilityFallbackCase({
|
||||
setup: () => {
|
||||
modelRegistryState.available = { bad: true } as unknown as Array<Record<string, unknown>>;
|
||||
},
|
||||
expectedErrorDetail: "non-array value",
|
||||
});
|
||||
});
|
||||
|
||||
it("models list falls back to auth heuristics when getAvailable throws", async () => {
|
||||
await runAvailabilityFallbackCase({
|
||||
setup: () => {
|
||||
modelRegistryState.getAvailableError = new Error(
|
||||
"availability unsupported: getAvailable failed",
|
||||
);
|
||||
},
|
||||
expectedErrorDetail: "availability unsupported: getAvailable failed",
|
||||
});
|
||||
});
|
||||
|
||||
it("models list does not treat availability-unavailable code as discovery fallback", async () => {
|
||||
configureGoogleAntigravityModel("claude-opus-4-6-thinking");
|
||||
modelRegistryState.getAllError = Object.assign(new Error("model discovery failed"), {
|
||||
|
||||
@@ -7,11 +7,6 @@ import {
|
||||
resolveAwsSdkEnvVarName,
|
||||
resolveEnvApiKey,
|
||||
} from "../../agents/model-auth.js";
|
||||
import {
|
||||
ANTIGRAVITY_GEMINI_31_FORWARD_COMPAT_CANDIDATES,
|
||||
ANTIGRAVITY_OPUS_46_FORWARD_COMPAT_CANDIDATES,
|
||||
resolveForwardCompatModel,
|
||||
} from "../../agents/model-forward-compat.js";
|
||||
import { ensureOpenClawModelsJson } from "../../agents/models-config.js";
|
||||
import { ensurePiAuthJsonFromAuthProfiles } from "../../agents/pi-auth-json.js";
|
||||
import type { ModelRegistry } from "../../agents/pi-model-discovery.js";
|
||||
@@ -106,23 +101,13 @@ export async function loadModelRegistry(cfg: OpenClawConfig) {
|
||||
await ensurePiAuthJsonFromAuthProfiles(agentDir);
|
||||
const authStorage = discoverAuthStorage(agentDir);
|
||||
const registry = discoverModels(authStorage, agentDir);
|
||||
const appended = appendAntigravityForwardCompatModels(registry.getAll(), registry);
|
||||
const models = appended.models;
|
||||
const synthesizedForwardCompat = appended.synthesizedForwardCompat;
|
||||
const models = registry.getAll();
|
||||
let availableKeys: Set<string> | undefined;
|
||||
let availabilityErrorMessage: string | undefined;
|
||||
|
||||
try {
|
||||
const availableModels = loadAvailableModels(registry);
|
||||
availableKeys = new Set(availableModels.map((model) => modelKey(model.provider, model.id)));
|
||||
for (const synthesized of synthesizedForwardCompat) {
|
||||
if (hasAvailableTemplate(availableKeys, synthesized.templatePrefixes)) {
|
||||
availableKeys.add(synthesized.key);
|
||||
for (const aliasKey of synthesized.availabilityAliasKeys) {
|
||||
availableKeys.add(aliasKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (!shouldFallbackToAuthHeuristics(err)) {
|
||||
throw err;
|
||||
@@ -138,60 +123,6 @@ export async function loadModelRegistry(cfg: OpenClawConfig) {
|
||||
return { registry, models, availableKeys, availabilityErrorMessage };
|
||||
}
|
||||
|
||||
type SynthesizedForwardCompat = {
|
||||
key: string;
|
||||
templatePrefixes: readonly string[];
|
||||
availabilityAliasKeys: readonly string[];
|
||||
};
|
||||
|
||||
function appendAntigravityForwardCompatModels(
|
||||
models: Model<Api>[],
|
||||
modelRegistry: ModelRegistry,
|
||||
): { models: Model<Api>[]; synthesizedForwardCompat: SynthesizedForwardCompat[] } {
|
||||
const nextModels = [...models];
|
||||
const synthesizedForwardCompat: SynthesizedForwardCompat[] = [];
|
||||
const candidates = [
|
||||
...ANTIGRAVITY_OPUS_46_FORWARD_COMPAT_CANDIDATES,
|
||||
...ANTIGRAVITY_GEMINI_31_FORWARD_COMPAT_CANDIDATES,
|
||||
];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const key = modelKey("google-antigravity", candidate.id);
|
||||
const hasForwardCompat = nextModels.some((model) => modelKey(model.provider, model.id) === key);
|
||||
if (hasForwardCompat) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const fallback = resolveForwardCompatModel("google-antigravity", candidate.id, modelRegistry);
|
||||
if (!fallback) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nextModels.push(fallback);
|
||||
synthesizedForwardCompat.push({
|
||||
key,
|
||||
templatePrefixes: candidate.templatePrefixes,
|
||||
availabilityAliasKeys: candidate.availabilityAliasIds.map((id) =>
|
||||
modelKey("google-antigravity", id),
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
return { models: nextModels, synthesizedForwardCompat };
|
||||
}
|
||||
|
||||
function hasAvailableTemplate(
|
||||
availableKeys: Set<string>,
|
||||
templatePrefixes: readonly string[],
|
||||
): boolean {
|
||||
for (const key of availableKeys) {
|
||||
if (templatePrefixes.some((prefix) => key.startsWith(prefix))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function toModelRow(params: {
|
||||
model?: Model<Api>;
|
||||
key: string;
|
||||
|
||||
@@ -26,7 +26,6 @@ export type AuthChoice =
|
||||
| "codex-cli"
|
||||
| "apiKey"
|
||||
| "gemini-api-key"
|
||||
| "google-antigravity"
|
||||
| "google-gemini-cli"
|
||||
| "zai-api-key"
|
||||
| "zai-coding-global"
|
||||
|
||||
Reference in New Issue
Block a user