Skip to content
Open
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
68 changes: 68 additions & 0 deletions apps/server/src/provider/Drivers/antigravityUsageReader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,74 @@ describe("readAntigravityUsage", () => {
}).pipe(Effect.provide(NodeServices.layer)),
);

it.effect("prices Antigravity effort variants at their base model", () =>
Effect.gen(function* () {
const path = yield* Path.Path;
const dir = yield* tempDir;
yield* seedDatabase(path.join(dir, "variants.db"), (db) =>
Effect.gen(function* () {
yield* createTables(db);
yield* db.run("INSERT INTO gen_metadata VALUES (?, ?)", [
0,
new Uint8Array(protoBytes(1, protoText(19, "Gemini 3.7 Flash Control"))),
]);
yield* db.run("INSERT INTO steps VALUES (?, ?)", [
0,
new Uint8Array(protoBytes(9, protoNumber(2, 10))),
]);
yield* db.run("INSERT INTO steps VALUES (?, ?)", [
1,
new Uint8Array(protoBytes(9, [...protoNumber(1, 1319), ...protoNumber(2, 11)])),
]);
yield* db.run("INSERT INTO steps VALUES (?, ?)", [
2,
new Uint8Array(protoBytes(9, [...protoNumber(1, 1132), ...protoNumber(2, 12)])),
]);
}),
);
const result = yield* readAntigravityUsage(dir, 0);
assert.deepStrictEqual(result.errors, []);
assert.deepStrictEqual(
records(result).map((record) => [record.model, record.rateModel]),
[
["gemini-3.7-flash-control", "gemini-3.7-flash"],
["gemini-3.8-flash-medium", "gemini-3.8-flash"],
["gemini-3-flash-agent", "gemini-3-flash-preview"],
],
);
}).pipe(Effect.provide(NodeServices.layer)),
);

it.effect("prices a merged Antigravity alias by the model it adopts", () =>
Effect.gen(function* () {
const path = yield* Path.Path;
const dir = yield* tempDir;
yield* seedDatabase(path.join(dir, "adopt.db"), (db) =>
Effect.gen(function* () {
yield* createTables(db);
yield* db.run("INSERT INTO steps VALUES (?, ?)", [
5,
new Uint8Array(protoBytes(9, [...protoNumber(2, 100), ...protoText(11, "response")])),
]);
yield* db.run("INSERT INTO gen_metadata VALUES (?, ?)", [
0,
new Uint8Array(
protoBytes(1, [
...protoText(19, "Gemini 3.8 Flash High"),
...protoBytes(4, [...protoNumber(2, 100), ...protoText(11, "response")]),
]),
),
]);
}),
);
const result = yield* readAntigravityUsage(dir, 0);
assert.deepStrictEqual(
records(result).map((record) => [record.model, record.rateModel]),
[["gemini-3.8-flash-high", "gemini-3.8-flash"]],
);
}).pipe(Effect.provide(NodeServices.layer)),
);

it.effect("merges Antigravity aliases that bridge previously separate step records", () =>
Effect.gen(function* () {
const path = yield* Path.Path;
Expand Down
49 changes: 37 additions & 12 deletions apps/server/src/provider/Drivers/antigravityUsageReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,29 @@ const MODEL_IDS: Record<number, string> = {
1018: "gemini-3-flash-preview",
1084: "gemini-3-flash-preview",
1047: "gemini-3-flash-preview",
342: "gpt-oss-120b-medium",
1020: "gemini-3.5-flash-low",
1072: "gemini-3.6-flash-medium",
1073: "gemini-3.6-flash-low",
1132: "gemini-3-flash-agent",
1133: "gemini-3-flash-agent",
1187: "gemini-3.5-flash-extra-low",
1298: "gemini-3.7-flash-high",
1299: "gemini-3.7-flash-medium",
1301: "gemini-3.7-flash-tiered",
1318: "gemini-3.8-flash-high",
1319: "gemini-3.8-flash-medium",
1320: "gemini-3.8-flash-low",
1322: "gemini-3.8-flash-tiered",
};

/** Prices effort and routing variants such as `gemini-3.8-flash-high` at their base model. */
function antigravityRateModel(model: string): string {
const base = model.replace(/-(?:extra-low|low|medium|high|tiered|control|thinking|agent)$/, "");
// Rate tables only list Gemini 3 Flash under its preview name, as `MODEL_IDS` does.
return base === "gemini-3-flash" ? "gemini-3-flash-preview" : base;
}

function modelName(name: string, id: number): string {
if (name) {
const normalized = name
Expand Down Expand Up @@ -267,16 +288,18 @@ function usageCandidates(
const id = textAt(usage, key);
return id ? [`antigravity:${key}:${id}`] : [];
});
const model =
MODEL_IDS[numberAt(usage, 1)] ||
entry.model ||
(source === "step" ? generationModels.get(idx) : "") ||
modelName("", numberAt(usage, 1)) ||
"antigravity-unknown";
const record: UsageRecord = {
provider: "antigravity",
sessionId,
timestampMs: entry.timestampMs ?? trajectoryTimestamp ?? fallbackTimestamp,
model:
MODEL_IDS[numberAt(usage, 1)] ||
entry.model ||
(source === "step" ? generationModels.get(idx) : "") ||
modelName("", numberAt(usage, 1)) ||
"antigravity-unknown",
model,
rateModel: antigravityRateModel(model),
totals,
reportedCostUsd: null,
speed: "standard",
Expand Down Expand Up @@ -354,14 +377,16 @@ export const readAntigravityUsage = Effect.fn("readAntigravityUsage")(function*
: target;
const x = target.record.totals;
const y = source.record.totals;
const model =
first.record.model === "antigravity-unknown"
? first === target
? source.record.model
: target.record.model
: first.record.model;
target.record = {
...first.record,
model:
first.record.model === "antigravity-unknown"
? first === target
? source.record.model
: target.record.model
: first.record.model,
model,
rateModel: antigravityRateModel(model),
timestampMs: bestTime.record.timestampMs,
totals: {
uncachedInputTokens: Math.max(x.uncachedInputTokens, y.uncachedInputTokens),
Expand Down
Loading