feat(oauth): default Antigravity-family connections to model auto-sync (#11887)

Recreated from #11685 (MumuTW) onto the active release/v3.8.51 — both commits cherry-picked
cleanly with author preserved; 5/5 focused tests + file-size + changelog-integrity all green
on this tip. Thanks for the fix!
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-08-28 09:26:26 -03:00
committed by GitHub
parent 0188685a1e
commit 0f88b74dbe
4 changed files with 145 additions and 0 deletions

View File

@@ -0,0 +1 @@
- Default new Antigravity-family connections (agy CLI imports and Antigravity OAuth connects) to model auto-sync, so live model discovery lands in the synced catalog and `/v1/models` picks up freshly released upstream models (e.g. Gemini 3.7 Flash tiers) without code changes. Existing connections keep their current setting; the per-connection dashboard toggle remains the opt-out. (#11685 — thanks @MumuTW)

View File

@@ -247,6 +247,12 @@ function mapAntigravityTokens(
clientProfile,
projectId: extra?.projectId,
tier: extra?.tierId,
// The Antigravity backend ships new models frequently (e.g. Gemini 3.7
// Flash tiers appeared upstream weeks before the pinned catalog knew
// them). Default new connections into the 24h model auto-sync (#488) so
// live discovery lands in the synced catalog and /v1/models stays
// current without code changes. Operator-controlled per connection.
autoSync: true,
},
};
}

View File

@@ -216,6 +216,10 @@ export async function createConnectionFromAgyToken(
testStatus: "active",
isActive: true,
providerSpecificData: {
// Auto-sync default for newly discovered backends — see
// mapAntigravityTokens. Placed BEFORE the existing-data spread so a
// previously persisted operator choice (true or false) wins.
autoSync: true,
...toRecord(existing.providerSpecificData),
clientProfile: "cli",
tokenType: enriched.tokenType,
@@ -249,6 +253,8 @@ export async function createConnectionFromAgyToken(
isActive: true,
testStatus: "active",
providerSpecificData: {
// Default new imports into model auto-sync — see mapAntigravityTokens.
autoSync: true,
clientProfile: "cli",
tokenType: enriched.tokenType,
authMethod: enriched.authMethod,

View File

@@ -0,0 +1,132 @@
/**
* Antigravity-family connections default to model auto-sync on (#488).
*
* The Antigravity backend ships new models faster than the pinned catalog can
* be re-frozen by hand (Gemini 3.7 Flash tiers existed upstream while the
* catalog still stopped at 3.6, leaving /v1/models blind to them). Discovery
* and the 24h model-sync scheduler already exist — the missing piece was the
* opt-in trigger. New agy/antigravity connections now ship with
* providerSpecificData.autoSync = true so live discovery lands in the synced
* catalog automatically; an explicit operator choice must survive re-import.
*/
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
type Row = Record<string, unknown>;
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-agy-autosync-"));
process.env.DATA_DIR = TEST_DATA_DIR;
const { agy } = await import("../../src/lib/oauth/providers/agy.ts");
const { antigravity } = await import("../../src/lib/oauth/providers/antigravity.ts");
const providers = { agy, antigravity };
const { createConnectionFromAgyToken } = await import("../../src/lib/oauth/utils/agyAuthImport.ts");
const providersDb = await import("../../src/lib/db/providers.ts");
const core = await import("../../src/lib/db/core.ts");
const TOKENS = {
access_token: "agy-access-token-fixture",
refresh_token: "agy-refresh-token-fixture",
expires_in: 3600,
scope: "https://www.googleapis.com/auth/cloud-platform",
};
const POST_EXCHANGE = {
projectId: "fixture-project",
tierId: "free_tier",
userInfo: { email: "fixture@example.com" },
};
function asRecord(value: unknown): Row {
return value && typeof value === "object" ? (value as Row) : {};
}
function enrichedAuth(overrides: Partial<Row> = {}): Row {
return {
accessToken: TOKENS.access_token,
refreshToken: TOKENS.refresh_token,
expiresAt: null,
projectId: null,
tier: null,
tokenType: "Bearer",
authMethod: "consumer",
...overrides,
};
}
async function findRowByEmail(email: string): Promise<Row | undefined> {
const rows = (await providersDb.getProviderConnections({ provider: "agy" })) as Row[];
return rows.find((row) => row.email === email);
}
test("agy OAuth mapTokens defaults providerSpecificData.autoSync to true", () => {
const mapped = providers.agy.mapTokens(TOKENS, POST_EXCHANGE) as Row;
assert.equal(asRecord(mapped.providerSpecificData).autoSync, true);
assert.equal(asRecord(mapped.providerSpecificData).clientProfile, "cli");
});
test("antigravity OAuth mapTokens defaults providerSpecificData.autoSync to true", () => {
const mapped = providers.antigravity.mapTokens(TOKENS, POST_EXCHANGE) as Row;
assert.equal(asRecord(mapped.providerSpecificData).autoSync, true);
assert.equal(asRecord(mapped.providerSpecificData).clientProfile, "ide");
});
test("new agy CLI token import persists autoSync: true", async () => {
core.resetDbInstance();
const email = "import-autosync@example.com";
const { connection, created } = await createConnectionFromAgyToken(
enrichedAuth({ email }) as never,
{}
);
assert.equal(created, true);
const row = (await providersDb.getProviderConnections({ provider: "agy" })) as Row[];
const match = row.find((candidate) => candidate.id === (connection as Row).id);
assert.equal(asRecord(match?.providerSpecificData).autoSync, true);
});
test("re-import keeps an explicit autoSync: false choice", async () => {
core.resetDbInstance();
const email = "import-optout@example.com";
const { connection } = await createConnectionFromAgyToken(enrichedAuth({ email }) as never, {});
await providersDb.updateProviderConnection(String((connection as Row).id), {
providerSpecificData: {
...asRecord((connection as Row).providerSpecificData),
autoSync: false,
},
});
const { created } = await createConnectionFromAgyToken(
enrichedAuth({
email,
accessToken: "refreshed-access-token-fixture",
refreshToken: "refreshed-refresh-token-fixture",
}) as never,
{ overwriteExisting: true }
);
assert.equal(created, false);
assert.equal(asRecord((await findRowByEmail(email))?.providerSpecificData).autoSync, false);
});
test("re-import enables autoSync when the existing row never had it", async () => {
core.resetDbInstance();
const email = "import-legacy@example.com";
const { connection } = await createConnectionFromAgyToken(enrichedAuth({ email }) as never, {});
// Simulate a pre-default row: strip autoSync entirely.
await providersDb.updateProviderConnection(String((connection as Row).id), {
providerSpecificData: { clientProfile: "cli" },
});
await createConnectionFromAgyToken(
enrichedAuth({
email,
accessToken: "refreshed-access-token-fixture",
refreshToken: "refreshed-refresh-token-fixture",
}) as never,
{ overwriteExisting: true }
);
assert.equal(asRecord((await findRowByEmail(email))?.providerSpecificData).autoSync, true);
});