mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 17:18:25 +00:00
refactor!: remove google-antigravity provider support
This commit is contained in:
@@ -42,26 +42,6 @@ describe("sanitizeToolsForGoogle", () => {
|
||||
expectFormatRemoved(sanitized, "additionalProperties");
|
||||
});
|
||||
|
||||
it("strips unsupported schema keywords for google-antigravity", () => {
|
||||
const tool = createTool({
|
||||
type: "object",
|
||||
patternProperties: {
|
||||
"^x-": { type: "string" },
|
||||
},
|
||||
properties: {
|
||||
foo: {
|
||||
type: "string",
|
||||
format: "uuid",
|
||||
},
|
||||
},
|
||||
});
|
||||
const [sanitized] = sanitizeToolsForGoogle({
|
||||
tools: [tool],
|
||||
provider: "google-antigravity",
|
||||
});
|
||||
expectFormatRemoved(sanitized, "patternProperties");
|
||||
});
|
||||
|
||||
it("returns original tools for non-google providers", () => {
|
||||
const tool = createTool({
|
||||
type: "object",
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
import type { TranscriptPolicy } from "../transcript-policy.js";
|
||||
import { resolveTranscriptPolicy } from "../transcript-policy.js";
|
||||
import { log } from "./logger.js";
|
||||
import { dropThinkingBlocks, isAssistantMessageWithContent } from "./thinking.js";
|
||||
import { dropThinkingBlocks } from "./thinking.js";
|
||||
import { describeUnknownError } from "./utils.js";
|
||||
|
||||
const GOOGLE_TURN_ORDERING_CUSTOM_TYPE = "google-turn-ordering-bootstrap";
|
||||
@@ -52,85 +52,8 @@ const GOOGLE_SCHEMA_UNSUPPORTED_KEYWORDS = new Set([
|
||||
"maxProperties",
|
||||
]);
|
||||
|
||||
const ANTIGRAVITY_SIGNATURE_RE = /^[A-Za-z0-9+/]+={0,2}$/;
|
||||
const INTER_SESSION_PREFIX_BASE = "[Inter-session message]";
|
||||
|
||||
function isValidAntigravitySignature(value: unknown): value is string {
|
||||
if (typeof value !== "string") {
|
||||
return false;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) {
|
||||
return false;
|
||||
}
|
||||
if (trimmed.length % 4 !== 0) {
|
||||
return false;
|
||||
}
|
||||
return ANTIGRAVITY_SIGNATURE_RE.test(trimmed);
|
||||
}
|
||||
|
||||
export function sanitizeAntigravityThinkingBlocks(messages: AgentMessage[]): AgentMessage[] {
|
||||
let touched = false;
|
||||
const out: AgentMessage[] = [];
|
||||
for (const msg of messages) {
|
||||
if (!isAssistantMessageWithContent(msg)) {
|
||||
out.push(msg);
|
||||
continue;
|
||||
}
|
||||
const assistant = msg;
|
||||
type AssistantContentBlock = Extract<AgentMessage, { role: "assistant" }>["content"][number];
|
||||
const nextContent: AssistantContentBlock[] = [];
|
||||
let contentChanged = false;
|
||||
for (const block of assistant.content) {
|
||||
if (
|
||||
!block ||
|
||||
typeof block !== "object" ||
|
||||
(block as { type?: unknown }).type !== "thinking"
|
||||
) {
|
||||
nextContent.push(block);
|
||||
continue;
|
||||
}
|
||||
const rec = block as {
|
||||
thinkingSignature?: unknown;
|
||||
signature?: unknown;
|
||||
thought_signature?: unknown;
|
||||
thoughtSignature?: unknown;
|
||||
};
|
||||
const candidate =
|
||||
rec.thinkingSignature ?? rec.signature ?? rec.thought_signature ?? rec.thoughtSignature;
|
||||
if (!isValidAntigravitySignature(candidate)) {
|
||||
// Preserve reasoning content as plain text when signatures are invalid/missing.
|
||||
// Antigravity Claude rejects unsigned thinking blocks, but dropping them loses context.
|
||||
const thinkingText = (block as { thinking?: unknown }).thinking;
|
||||
if (typeof thinkingText === "string" && thinkingText.trim()) {
|
||||
nextContent.push({ type: "text", text: thinkingText } as AssistantContentBlock);
|
||||
}
|
||||
contentChanged = true;
|
||||
continue;
|
||||
}
|
||||
if (rec.thinkingSignature !== candidate) {
|
||||
const nextBlock = {
|
||||
...(block as unknown as Record<string, unknown>),
|
||||
thinkingSignature: candidate,
|
||||
} as AssistantContentBlock;
|
||||
nextContent.push(nextBlock);
|
||||
contentChanged = true;
|
||||
} else {
|
||||
nextContent.push(block);
|
||||
}
|
||||
}
|
||||
if (contentChanged) {
|
||||
touched = true;
|
||||
}
|
||||
if (nextContent.length === 0) {
|
||||
touched = true;
|
||||
continue;
|
||||
}
|
||||
out.push(contentChanged ? { ...assistant, content: nextContent } : msg);
|
||||
}
|
||||
return touched ? out : messages;
|
||||
}
|
||||
|
||||
function buildInterSessionPrefix(message: AgentMessage): string {
|
||||
const provenance = normalizeInputProvenance((message as { provenance?: unknown }).provenance);
|
||||
if (!provenance) {
|
||||
@@ -284,7 +207,7 @@ export function sanitizeToolsForGoogle<
|
||||
// AND Claude models. This field does not support JSON Schema keywords such as
|
||||
// patternProperties, additionalProperties, $ref, etc. We must clean schemas
|
||||
// for every provider that routes through this path.
|
||||
if (params.provider !== "google-gemini-cli" && params.provider !== "google-antigravity") {
|
||||
if (params.provider !== "google-gemini-cli") {
|
||||
return params.tools;
|
||||
}
|
||||
return params.tools.map((tool) => {
|
||||
@@ -301,7 +224,7 @@ export function sanitizeToolsForGoogle<
|
||||
}
|
||||
|
||||
export function logToolSchemasForGoogle(params: { tools: AgentTool[]; provider: string }) {
|
||||
if (params.provider !== "google-antigravity" && params.provider !== "google-gemini-cli") {
|
||||
if (params.provider !== "google-gemini-cli") {
|
||||
return;
|
||||
}
|
||||
const toolNames = params.tools.map((tool, index) => `${index}:${tool.name}`);
|
||||
@@ -481,10 +404,7 @@ export async function sanitizeSessionHistory(params: {
|
||||
const droppedThinking = policy.dropThinkingBlocks
|
||||
? dropThinkingBlocks(sanitizedImages)
|
||||
: sanitizedImages;
|
||||
const sanitizedThinking = policy.sanitizeThinkingSignatures
|
||||
? sanitizeAntigravityThinkingBlocks(droppedThinking)
|
||||
: droppedThinking;
|
||||
const sanitizedToolCalls = sanitizeToolCallInputs(sanitizedThinking, {
|
||||
const sanitizedToolCalls = sanitizeToolCallInputs(droppedThinking, {
|
||||
allowedToolNames: params.allowedToolNames,
|
||||
});
|
||||
const repairedTools = policy.repairToolUseResultPairing
|
||||
|
||||
@@ -232,62 +232,6 @@ describe("resolveModel", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("builds an antigravity forward-compat fallback for claude-opus-4-6-thinking", () => {
|
||||
mockDiscoveredModel({
|
||||
provider: "google-antigravity",
|
||||
modelId: "claude-opus-4-5-thinking",
|
||||
templateModel: buildForwardCompatTemplate({
|
||||
id: "claude-opus-4-5-thinking",
|
||||
name: "Claude Opus 4.5 Thinking",
|
||||
provider: "google-antigravity",
|
||||
api: "google-gemini-cli",
|
||||
baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
|
||||
}),
|
||||
});
|
||||
|
||||
expectResolvedForwardCompatFallback({
|
||||
provider: "google-antigravity",
|
||||
id: "claude-opus-4-6-thinking",
|
||||
expectedModel: {
|
||||
provider: "google-antigravity",
|
||||
id: "claude-opus-4-6-thinking",
|
||||
api: "google-gemini-cli",
|
||||
baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
|
||||
reasoning: true,
|
||||
contextWindow: 200000,
|
||||
maxTokens: 64000,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("builds an antigravity forward-compat fallback for claude-opus-4-6", () => {
|
||||
mockDiscoveredModel({
|
||||
provider: "google-antigravity",
|
||||
modelId: "claude-opus-4-5",
|
||||
templateModel: buildForwardCompatTemplate({
|
||||
id: "claude-opus-4-5",
|
||||
name: "Claude Opus 4.5",
|
||||
provider: "google-antigravity",
|
||||
api: "google-gemini-cli",
|
||||
baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
|
||||
}),
|
||||
});
|
||||
|
||||
expectResolvedForwardCompatFallback({
|
||||
provider: "google-antigravity",
|
||||
id: "claude-opus-4-6",
|
||||
expectedModel: {
|
||||
provider: "google-antigravity",
|
||||
id: "claude-opus-4-6",
|
||||
api: "google-gemini-cli",
|
||||
baseUrl: "https://daily-cloudcode-pa.sandbox.googleapis.com",
|
||||
reasoning: true,
|
||||
contextWindow: 200000,
|
||||
maxTokens: 64000,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("builds a zai forward-compat fallback for glm-5", () => {
|
||||
mockDiscoveredModel({
|
||||
provider: "zai",
|
||||
|
||||
@@ -82,7 +82,6 @@ import { buildEmbeddedExtensionFactories } from "../extensions.js";
|
||||
import { applyExtraParamsToAgent } from "../extra-params.js";
|
||||
import {
|
||||
logToolSchemasForGoogle,
|
||||
sanitizeAntigravityThinkingBlocks,
|
||||
sanitizeSessionHistory,
|
||||
sanitizeToolsForGoogle,
|
||||
} from "../google.js";
|
||||
@@ -1062,10 +1061,7 @@ export async function runEmbeddedAttempt(
|
||||
sessionManager.resetLeaf();
|
||||
}
|
||||
const sessionContext = sessionManager.buildSessionContext();
|
||||
const sanitizedOrphan = transcriptPolicy.sanitizeThinkingSignatures
|
||||
? sanitizeAntigravityThinkingBlocks(sessionContext.messages)
|
||||
: sessionContext.messages;
|
||||
activeSession.agent.replaceMessages(sanitizedOrphan);
|
||||
activeSession.agent.replaceMessages(sessionContext.messages);
|
||||
log.warn(
|
||||
`Removed orphaned user message to prevent consecutive user turns. ` +
|
||||
`runId=${params.runId} sessionId=${params.sessionId}`,
|
||||
|
||||
Reference in New Issue
Block a user