Skip to content
Merged
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
21 changes: 17 additions & 4 deletions src/providers/google-agy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ function formatRemainingAmount(value: string | undefined): string | undefined {
return `${display} left`;
}

export function formatAgyCredentialGroup(credentialName: string, familyLabel: string): string {
const trimmed = credentialName.trim();
if (!familyLabel?.trim()) return trimmed;
const match = trimmed.match(/^(\[[^\]]+\])(.*)$/);
if (match) {
const inside = match[1]?.slice(1, -1) ?? "";
return `[${inside}: ${familyLabel}]${match[2] ?? ""}`;
}
return `[${trimmed}: ${familyLabel}]`;
}

async function isAgyConfigured(): Promise<boolean> {
try {
return await hasAgyQuotaRuntimeAvailable();
Expand Down Expand Up @@ -161,13 +172,15 @@ export const googleAgyProvider: QuotaProvider = {
const entries: QuotaToastEntry[] = [];
const errors: QuotaProviderResult["errors"] = [];
for (const [index, { row, result }] of results.entries()) {
const group = names[index] ?? "Google AGY";
const credentialName = names[index] ?? "Google AGY";
if (!result) continue;
if (!result.success) {
errors.push({ label: group, message: result.error });
errors.push({ label: credentialName, message: result.error });
continue;
}
for (const bucket of [...result.buckets].sort(compareBuckets)) {
const familyLabel = formatAgyFamilyLabel(bucket.family);
const group = formatAgyCredentialGroup(credentialName, familyLabel);
const right = formatRemainingAmount(bucket.remainingAmount);
entries.push({
accounting: {
Expand All @@ -177,7 +190,7 @@ export const googleAgyProvider: QuotaProvider = {
authority: "provider_reported",
sourceId: row.id,
},
name: `${group} ${formatAgyFamilyLabel(bucket.family)} ${bucket.windowLabel}`,
name: `${group} ${bucket.windowLabel}`,
group,
label: `${bucket.windowLabel}:`,
sortPriority: windowRank(bucket.window),
Expand All @@ -188,7 +201,7 @@ export const googleAgyProvider: QuotaProvider = {
}
errors.push(
...(result.errors ?? []).map((error) => ({
label: group,
label: credentialName,
message: error.error,
})),
);
Expand Down
27 changes: 26 additions & 1 deletion tests/providers.google-agy.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from "vitest";
import { googleAgyProvider } from "../src/providers/google-agy.js";
import { formatAgyCredentialGroup, googleAgyProvider } from "../src/providers/google-agy.js";
import {
expectAttemptedWithErrorLabel,
expectAttemptedWithNoErrors,
Expand Down Expand Up @@ -251,4 +251,29 @@ describe("google agy provider", () => {
expect(googleAgyProvider.matchesCurrentModel?.("google-agy-auth/gpt-4")).toBe(true);
expect(googleAgyProvider.matchesCurrentModel?.("google/claude-opus")).toBe(false);
});

describe("formatAgyCredentialGroup", () => {
it("formats credential names with active markers", () => {
expect(
formatAgyCredentialGroup("[Google AGY Antigravity CLI (plugin) 2] (active)", "Gemini"),
).toBe("[Google AGY Antigravity CLI (plugin) 2: Gemini] (active)");
});

it("formats simple bracketed names", () => {
expect(formatAgyCredentialGroup("[Google AGY]", "Claude/GPT")).toBe(
"[Google AGY: Claude/GPT]",
);
});

it("formats names without brackets", () => {
expect(formatAgyCredentialGroup("Google AGY Work", "Gemini")).toBe(
"[Google AGY Work: Gemini]",
);
});

it("trims whitespace and handles empty family label", () => {
expect(formatAgyCredentialGroup(" [Google AGY] ", "Gemini")).toBe("[Google AGY: Gemini]");
expect(formatAgyCredentialGroup("[Google AGY]", "")).toBe("[Google AGY]");
});
});
});
44 changes: 36 additions & 8 deletions tests/providers.google-db-credentials.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,27 @@ describe.each([
accountIndex: 0,
percentRemaining: 70,
},
{
family: "Claude and GPT models",
window: "weekly",
windowLabel: "Weekly",
accountIndex: 0,
percentRemaining: 50,
},
],
},
expectedGroups: [
["[Google AGY Work: Gemini] (active)", "active-id"],
["[Google AGY Work: Claude/GPT] (active)", "active-id"],
["[Google AGY Work 2: Gemini]", "other-id"],
["[Google AGY Work 2: Claude/GPT]", "other-id"],
],
expectedNames: [
"[Google AGY Work: Gemini] (active) Weekly",
"[Google AGY Work: Claude/GPT] (active) Weekly",
"[Google AGY Work 2: Gemini] Weekly",
"[Google AGY Work 2: Claude/GPT] Weekly",
],
},
{
name: "Gemini CLI",
Expand All @@ -79,8 +98,20 @@ describe.each([
success: true,
buckets: [{ displayName: "Gemini 2.5", percentRemaining: 70 }],
},
expectedGroups: [
["[Gemini CLI Work] (active)", "active-id"],
["[Gemini CLI Work 2]", "other-id"],
],
expectedNames: ["[Gemini CLI Work] (active) Gemini 2.5", "[Gemini CLI Work 2] Gemini 2.5"],
},
])("$name DB credentials", ({ integrationId, provider, query, result }) => {
])("$name DB credentials", ({
integrationId,
provider,
query,
result,
expectedGroups,
expectedNames,
}) => {
beforeEach(() => {
vi.clearAllMocks();
mocks.rows.mockResolvedValue([
Expand All @@ -106,12 +137,9 @@ describe.each([
const output = await provider.fetch({ client: {}, config: {} } as never);

expect(query).toHaveBeenCalledTimes(2);
expect(output.entries.map((entry) => [entry.group, entry.accounting.sourceId])).toEqual([
[
`[${provider.id === "google-agy" ? "Google AGY" : "Gemini CLI"} Work] (active)`,
"active-id",
],
[`[${provider.id === "google-agy" ? "Google AGY" : "Gemini CLI"} Work 2]`, "other-id"],
]);
expect(output.entries.map((entry) => [entry.group, entry.accounting.sourceId])).toEqual(
expectedGroups,
);
expect(output.entries.map((entry) => entry.name)).toEqual(expectedNames);
});
});
Loading