fix(ai): kept antigravity failover before advisor silence

Gated empty-STOP silence acceptance on the last Cloud Code Assist endpoint so an earlier endpoint returning only empty streams still fails over instead of being recorded as a valid silent review.

Added an Antigravity auto-mode regression covering failover exhaustion before silence.
This commit is contained in:
roboomp
2026-08-11 08:39:08 +00:00
parent c396e38726
commit 0a64b6d965
2 changed files with 34 additions and 1 deletions
@@ -1006,7 +1006,12 @@ export const streamGoogleGeminiCli: StreamFunction<"google-gemini-cli"> = (
}
const streamed = await streamResponse(currentResponse);
const acceptedSilence = options?.acceptEmptyResponse === true && !streamed.strippedPlanningLeak;
// Only accept an empty STOP as valid silence once every fallback
// endpoint is exhausted: an earlier endpoint returning empty
// successful streams must still fail over (Antigravity auto mode)
// rather than be recorded as a real silent review.
const acceptedSilence =
options?.acceptEmptyResponse === true && !streamed.strippedPlanningLeak && isLastEndpoint;
if (output.stopReason !== "stop" || streamed.meaningful || acceptedSilence) {
receivedContent = streamed.meaningful || acceptedSilence;
break;
@@ -364,6 +364,34 @@ describe("Google empty-response retry (Cloud Code Assist path)", () => {
expect(textOf(result)).toBe("Recovered.");
});
it("exhausts Antigravity auto failover before accepting silence", async () => {
const requestedEndpoints: string[] = [];
const fetchMock: FetchImpl = async input => {
const endpoint = endpointFromInput(input);
requestedEndpoints.push(endpoint);
return withResponseUrl(sse(ccaChunk("")), endpoint);
};
const stream = streamGoogleGeminiCli(antigravityModel, context, {
apiKey: JSON.stringify({ token: "token", projectId: "proj-123" }),
antigravityEndpointMode: "auto",
acceptEmptyResponse: true,
fetch: fetchMock,
});
const result = await stream.result();
// Daily still burns its empty-response budget and fails over; only the
// last (sandbox) endpoint records the empty STOP as valid silence.
expect(requestedEndpoints).toEqual([
ANTIGRAVITY_DAILY_ENDPOINT,
ANTIGRAVITY_DAILY_ENDPOINT,
ANTIGRAVITY_DAILY_ENDPOINT,
ANTIGRAVITY_SANDBOX_ENDPOINT,
]);
expect(result.stopReason).toBe("stop");
expect(result.errorMessage).toBeUndefined();
});
for (const { mode, endpoint } of [
{ mode: "production", endpoint: ANTIGRAVITY_DAILY_ENDPOINT },
{ mode: "sandbox", endpoint: ANTIGRAVITY_SANDBOX_ENDPOINT },