From fa98bc2b44d99bbef49ffdd6a453ae1d3d20362d Mon Sep 17 00:00:00 2001 From: Anthony Hausman Date: Tue, 13 Oct 2026 21:23:40 +0200 Subject: [PATCH 1/4] feat(google-agy): add formatAgyCredentialGroup helper Format credential display names with model family labels for grouped quota entries. Assisted-by: Gemini 3.8 Flash --- src/providers/google-agy.ts | 9 +++++++++ tests/providers.google-agy.test.ts | 22 +++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/providers/google-agy.ts b/src/providers/google-agy.ts index b22f3c07..d6df4d7d 100644 --- a/src/providers/google-agy.ts +++ b/src/providers/google-agy.ts @@ -101,6 +101,15 @@ function formatRemainingAmount(value: string | undefined): string | undefined { return `${display} left`; } +export function formatAgyCredentialGroup(credentialName: string, familyLabel: string): string { + const match = credentialName.match(/^(\[[^\]]+\])(.*)$/); + if (match) { + const inside = match[1]!.slice(1, -1); + return `[${inside}: ${familyLabel}]${match[2]}`; + } + return `[${credentialName}: ${familyLabel}]`; +} + async function isAgyConfigured(): Promise { try { return await hasAgyQuotaRuntimeAvailable(); diff --git a/tests/providers.google-agy.test.ts b/tests/providers.google-agy.test.ts index 96af7999..3a0e1a3e 100644 --- a/tests/providers.google-agy.test.ts +++ b/tests/providers.google-agy.test.ts @@ -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, @@ -251,4 +251,24 @@ 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]", + ); + }); + }); }); From fb64e1b0be64757a7a3691b53a88c680a3124fb6 Mon Sep 17 00:00:00 2001 From: Anthony Hausman Date: Tue, 13 Oct 2026 21:24:43 +0200 Subject: [PATCH 2/4] fix(google-agy): group database credential entries by model family Incorporate model family label into group header for database credential rows. Assisted-by: Gemini 3.8 Flash --- src/providers/google-agy.ts | 10 ++++--- tests/providers.google-db-credentials.test.ts | 29 ++++++++++++++----- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/providers/google-agy.ts b/src/providers/google-agy.ts index d6df4d7d..ec0fb50b 100644 --- a/src/providers/google-agy.ts +++ b/src/providers/google-agy.ts @@ -170,13 +170,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: { @@ -186,7 +188,7 @@ export const googleAgyProvider: QuotaProvider = { authority: "provider_reported", sourceId: row.id, }, - name: `${group} ${formatAgyFamilyLabel(bucket.family)} ${bucket.windowLabel}`, + name: `${credentialName} ${familyLabel} ${bucket.windowLabel}`, group, label: `${bucket.windowLabel}:`, sortPriority: windowRank(bucket.window), @@ -197,7 +199,7 @@ export const googleAgyProvider: QuotaProvider = { } errors.push( ...(result.errors ?? []).map((error) => ({ - label: group, + label: credentialName, message: error.error, })), ); diff --git a/tests/providers.google-db-credentials.test.ts b/tests/providers.google-db-credentials.test.ts index 16eae847..268f6e15 100644 --- a/tests/providers.google-db-credentials.test.ts +++ b/tests/providers.google-db-credentials.test.ts @@ -67,8 +67,21 @@ 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"], + ], }, { name: "Gemini CLI", @@ -79,8 +92,12 @@ describe.each([ success: true, buckets: [{ displayName: "Gemini 2.5", percentRemaining: 70 }], }, + expectedGroups: [ + ["[Gemini CLI Work] (active)", "active-id"], + ["[Gemini CLI Work 2]", "other-id"], + ], }, -])("$name DB credentials", ({ integrationId, provider, query, result }) => { +])("$name DB credentials", ({ integrationId, provider, query, result, expectedGroups }) => { beforeEach(() => { vi.clearAllMocks(); mocks.rows.mockResolvedValue([ @@ -106,12 +123,8 @@ 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, + ); }); }); From 82ccd36f95ca64f3f91ea36da933e46451215af7 Mon Sep 17 00:00:00 2001 From: Anthony Hausman Date: Tue, 13 Oct 2026 21:42:25 +0200 Subject: [PATCH 3/4] fix(google-agy): align entry name with group and harden helper Base entry name on group to preserve model family in TUI compact line. Harden helper with trimming and empty family guard. Assisted-by: Gemini 3.8 Flash --- src/providers/google-agy.ts | 8 +++++--- tests/providers.google-agy.test.ts | 5 +++++ tests/providers.google-db-credentials.test.ts | 13 ++++++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/providers/google-agy.ts b/src/providers/google-agy.ts index ec0fb50b..cac87419 100644 --- a/src/providers/google-agy.ts +++ b/src/providers/google-agy.ts @@ -102,12 +102,14 @@ function formatRemainingAmount(value: string | undefined): string | undefined { } export function formatAgyCredentialGroup(credentialName: string, familyLabel: string): string { - const match = credentialName.match(/^(\[[^\]]+\])(.*)$/); + 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 `[${credentialName}: ${familyLabel}]`; + return `[${trimmed}: ${familyLabel}]`; } async function isAgyConfigured(): Promise { @@ -188,7 +190,7 @@ export const googleAgyProvider: QuotaProvider = { authority: "provider_reported", sourceId: row.id, }, - name: `${credentialName} ${familyLabel} ${bucket.windowLabel}`, + name: `${group} ${bucket.windowLabel}`, group, label: `${bucket.windowLabel}:`, sortPriority: windowRank(bucket.window), diff --git a/tests/providers.google-agy.test.ts b/tests/providers.google-agy.test.ts index 3a0e1a3e..7f5ddc53 100644 --- a/tests/providers.google-agy.test.ts +++ b/tests/providers.google-agy.test.ts @@ -270,5 +270,10 @@ describe("google agy provider", () => { "[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]"); + }); }); }); diff --git a/tests/providers.google-db-credentials.test.ts b/tests/providers.google-db-credentials.test.ts index 268f6e15..d3d1d3de 100644 --- a/tests/providers.google-db-credentials.test.ts +++ b/tests/providers.google-db-credentials.test.ts @@ -82,6 +82,12 @@ describe.each([ ["[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", @@ -96,8 +102,12 @@ describe.each([ ["[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, expectedGroups }) => { +])("$name DB credentials", ({ integrationId, provider, query, result, expectedGroups, expectedNames }) => { beforeEach(() => { vi.clearAllMocks(); mocks.rows.mockResolvedValue([ @@ -126,5 +136,6 @@ describe.each([ expect(output.entries.map((entry) => [entry.group, entry.accounting.sourceId])).toEqual( expectedGroups, ); + expect(output.entries.map((entry) => entry.name)).toEqual(expectedNames); }); }); From f021a9ac7affd21214b4e98148ab3a995f72e784 Mon Sep 17 00:00:00 2001 From: Anthony Hausman Date: Tue, 13 Oct 2026 21:50:51 +0200 Subject: [PATCH 4/4] style(google-agy): format db credentials test and avoid non-null assertion Assisted-by: Gemini 3.8 Flash --- src/providers/google-agy.ts | 4 ++-- tests/providers.google-db-credentials.test.ts | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/providers/google-agy.ts b/src/providers/google-agy.ts index cac87419..c86fcd7f 100644 --- a/src/providers/google-agy.ts +++ b/src/providers/google-agy.ts @@ -106,8 +106,8 @@ export function formatAgyCredentialGroup(credentialName: string, familyLabel: st if (!familyLabel?.trim()) return trimmed; const match = trimmed.match(/^(\[[^\]]+\])(.*)$/); if (match) { - const inside = match[1]!.slice(1, -1); - return `[${inside}: ${familyLabel}]${match[2]}`; + const inside = match[1]?.slice(1, -1) ?? ""; + return `[${inside}: ${familyLabel}]${match[2] ?? ""}`; } return `[${trimmed}: ${familyLabel}]`; } diff --git a/tests/providers.google-db-credentials.test.ts b/tests/providers.google-db-credentials.test.ts index d3d1d3de..698d4cdc 100644 --- a/tests/providers.google-db-credentials.test.ts +++ b/tests/providers.google-db-credentials.test.ts @@ -102,12 +102,16 @@ describe.each([ ["[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", - ], + expectedNames: ["[Gemini CLI Work] (active) Gemini 2.5", "[Gemini CLI Work 2] Gemini 2.5"], }, -])("$name DB credentials", ({ integrationId, provider, query, result, expectedGroups, expectedNames }) => { +])("$name DB credentials", ({ + integrationId, + provider, + query, + result, + expectedGroups, + expectedNames, +}) => { beforeEach(() => { vi.clearAllMocks(); mocks.rows.mockResolvedValue([