Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/server/src/provider/Drivers/AntigravityDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export const AntigravityDriver: ProviderDriver<
apiKey: settingsSecretLiteral(settings.apiKey),
gcpProject: settings.gcpProject,
gcpLocation: settings.gcpLocation,
credentialsFile: settings.credentialsFile,
};
const authConfigIssue = antigravityAuthConfigIssue(auth);
const processEnvironment = yield* mergeProviderInstanceEnvironment(environment);
Expand Down
35 changes: 35 additions & 0 deletions apps/server/src/provider/antigravityAuthSupport.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,28 +139,62 @@ describe("Antigravity process environment", () => {
apiKey: "gemini-secret",
gcpProject: "proj",
gcpLocation: "us-central1",
credentialsFile: "/ignored.json",
});
expect(geminiKey.GEMINI_API_KEY).toBe("gemini-secret");
expect(geminiKey.GOOGLE_API_KEY).toBeUndefined();
expect(geminiKey.GOOGLE_CLOUD_PROJECT).toBeUndefined();
expect(geminiKey.GOOGLE_APPLICATION_CREDENTIALS).toBeUndefined();

// An API key belongs to one project, so it wins over a credentials file.
const vertexKey = spawnFor({
authMethod: "agent-platform",
apiKey: "vertex-secret",
gcpProject: "",
gcpLocation: "",
credentialsFile: "/ignored.json",
});
expect(vertexKey.GOOGLE_API_KEY).toBe("vertex-secret");
expect(vertexKey.GEMINI_API_KEY).toBeUndefined();
expect(vertexKey.GOOGLE_APPLICATION_CREDENTIALS).toBeUndefined();

const vertexAdc = spawnFor({
authMethod: "agent-platform",
apiKey: "",
gcpProject: "proj",
gcpLocation: "global",
credentialsFile: "/keys/service-account.json",
});
expect(vertexAdc.GOOGLE_APPLICATION_CREDENTIALS).toBe("/keys/service-account.json");
expect(vertexAdc.GOOGLE_API_KEY).toBeUndefined();

// When credentialsFile is blank, ambient GOOGLE_APPLICATION_CREDENTIALS is ignored.
const vertexBlankAdc =
buildAntigravityAcpSpawnInput({
installation: { executablePath: "/release/acp", harnessPath: "/release/harness" },
profile,
cwd: "/project",
baseEnv: { PATH: "/usr/bin", GOOGLE_APPLICATION_CREDENTIALS: "/env/adc.json" },
auth: {
authMethod: "agent-platform",
apiKey: "",
gcpProject: "proj",
gcpLocation: "global",
credentialsFile: "",
},
}).env ?? {};
expect(vertexBlankAdc.GOOGLE_APPLICATION_CREDENTIALS).toBeUndefined();

const business = spawnFor({
authMethod: "oauth-business",
apiKey: "ignored",
gcpProject: "proj",
gcpLocation: "us-central1",
credentialsFile: "/ignored.json",
});
expect(business.GEMINI_API_KEY).toBeUndefined();
expect(business.GOOGLE_API_KEY).toBeUndefined();
expect(business.GOOGLE_APPLICATION_CREDENTIALS).toBeUndefined();
});

it("isolates TEMP and TMP to the profile directory on Windows", () => {
Expand Down Expand Up @@ -661,6 +695,7 @@ it.layer(NodeServices.layer)("Antigravity profile preparation", (it) => {
apiKey: "vertex-secret",
gcpProject: "proj",
gcpLocation: "us-central1",
credentialsFile: "",
},
});
const settingsPath = path.join(profile.acpDirectory, "settings.json");
Expand Down
6 changes: 5 additions & 1 deletion apps/server/src/provider/antigravityAuthSupport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,15 @@ export interface AntigravityAuthConfig {
readonly apiKey: string;
readonly gcpProject: string;
readonly gcpLocation: string;
readonly credentialsFile: string;
}

const ANTIGRAVITY_PERSONAL_AUTH: AntigravityAuthConfig = {
authMethod: "oauth-personal",
apiKey: "",
gcpProject: "",
gcpLocation: "",
credentialsFile: "",
};

export function antigravityAuthUsesBrowser(authMethod: AntigravityAuthMethod): boolean {
Expand Down Expand Up @@ -210,7 +212,9 @@ function antigravityEnvironment(
? { GEMINI_API_KEY: auth.apiKey }
: auth.authMethod === "agent-platform" && auth.apiKey
? { GOOGLE_API_KEY: auth.apiKey }
: {};
: auth.authMethod === "agent-platform" && auth.credentialsFile
? { GOOGLE_APPLICATION_CREDENTIALS: auth.credentialsFile }
: {};
// Each launch unpacks about 1 GB; use T3-owned temp so the driver can reclaim files after force-kill.
const tempDirectory = runtimeTempDirectory ?? profile.tempDirectory;
return {
Expand Down
14 changes: 8 additions & 6 deletions docs/user/providers-antigravity.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,18 @@ T3 Code's confirmation.

Choose **Sign-in method** in the Antigravity provider settings:

| Method | Credentials |
| -------------------------- | -------------------------------------------------------------------------------------------- |
| Google account | Personal Google sign-in in the browser |
| Gemini Enterprise | Browser sign-in, GCP project, and GCP location |
| Gemini API key | API key; choose Connect without a browser |
| Agent Platform / Vertex AI | API key, or GCP project and location with Application Default Credentials on the environment |
| Method | Credentials |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Google account | Personal Google sign-in in the browser |
| Gemini Enterprise | Browser sign-in, GCP project, and GCP location |
| Gemini API key | API key; choose Connect without a browser |
| Agent Platform / Vertex AI | API key; with no API key, GCP project and location with Application Default Credentials from **Credentials file** or the environment's default |

The environment stores the Antigravity API key outside its settings file, and
clients only see whether one is saved. The agent uses the method and credentials selected for this instance;
ambient `GEMINI_API_KEY` and Google credential variables do not override them.
That includes `GOOGLE_APPLICATION_CREDENTIALS` in the instance's **Environment variables**; set the
path in **Credentials file** instead.
Changing the method stops the instance's sessions. Sign out before replacing an
account.

Expand Down
11 changes: 10 additions & 1 deletion packages/contracts/src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,15 @@ export const AntigravitySettings = makeProviderSettingsSchema(
providerSettingsForm: { placeholder: "us-central1", clearWhenEmpty: "omit" },
}),
),
credentialsFile: TrimmedString.pipe(
Schema.withDecodingDefault(Effect.succeed("")),
Schema.annotateKey({
title: "Credentials file",
description:
"Application Default Credentials or service account JSON. Set the file path here; ambient GOOGLE_APPLICATION_CREDENTIALS environment variables are ignored.",
providerSettingsForm: { placeholder: "Default ADC", clearWhenEmpty: "omit" },
}),
),
binaryPath: TrimmedString.pipe(
Schema.withDecodingDefault(Effect.succeed("")),
Schema.annotateKey({
Expand All @@ -906,7 +915,7 @@ export const AntigravitySettings = makeProviderSettingsSchema(
Schema.annotateKey({ providerSettingsForm: { hidden: true } }),
),
},
{ order: ["authMethod", "apiKey", "gcpProject", "gcpLocation", "binaryPath"] },
{ order: ["authMethod", "apiKey", "credentialsFile", "gcpProject", "gcpLocation", "binaryPath"] },
);
export type AntigravitySettings = typeof AntigravitySettings.Type;

Expand Down
Loading