diff --git a/src/adapters/google.ts b/src/adapters/google.ts index ab27089e7d..ffa7f03a55 100644 --- a/src/adapters/google.ts +++ b/src/adapters/google.ts @@ -395,6 +395,7 @@ export function createGoogleAdapter(provider: OcxProviderConfig): ProviderAdapte ? resolveAntigravityEffortWireModel( parsed.modelId, mapReasoningEffort(provider, parsed.modelId, parsed.options.reasoning), + provider.baseUrl, ).wireModelId : resolveDirectGeminiWireModelId(parsed.modelId); const { systemInstruction, contents } = messagesToGeminiFormat(parsed, routedModelId); @@ -450,7 +451,11 @@ export function createGoogleAdapter(provider: OcxProviderConfig): ProviderAdapte if (!project) throw new Error("Antigravity requires a discovered Cloud Code Assist project id (re-run `ocx login google-antigravity`)."); const sessionId = antigravitySessionId(parsed); const mappedEffort = mapReasoningEffort(provider, parsed.modelId, parsed.options.reasoning); - const { wireModelId, thinkingLevel } = resolveAntigravityEffortWireModel(parsed.modelId, mappedEffort); + const { wireModelId, thinkingLevel } = resolveAntigravityEffortWireModel( + parsed.modelId, + mappedEffort, + provider.baseUrl, + ); antigravityModel = wireModelId; antigravitySession = sessionId; // Effort → thinkingConfig for CCA (CLIProxyAPI proven: request.generationConfig.thinkingConfig). diff --git a/src/codex/catalog/provider-fetch.ts b/src/codex/catalog/provider-fetch.ts index c858524eff..2293a45143 100644 --- a/src/codex/catalog/provider-fetch.ts +++ b/src/codex/catalog/provider-fetch.ts @@ -38,7 +38,7 @@ import { type CapturedServiceTierAdapterAuthority, } from "../../providers/service-tier"; import { effectiveGoogleMode, getProviderRegistryEntry, providerMatchesRegistryTransport } from "../../providers/registry"; -import { parseAntigravityAvailableModels } from "../../providers/antigravity-models"; +import { parseAntigravityAvailableModels, registerAntigravityDiscoveredWireModels } from "../../providers/antigravity-models"; import { applyProviderContextCap, providerContextCap } from "../../providers/context-cap"; import { routedSlug, slugEquals, slugsEquivalent } from "../../providers/slug-codec"; import { CODEX_GPT5_IDENTITY_LINE } from "../../adapters/identity"; @@ -1374,6 +1374,10 @@ async function fetchProviderModelsWithAuth( if (!setCached(name, forCache, Date.now(), cacheGeneration)) { return observed(withConfiguredRetention(configured), "degraded"); } + registerAntigravityDiscoveredWireModels(prov.baseUrl, antigravity, { + provider: name, + cacheGeneration, + }); markProviderDiscoveryOk(name, live.length); return observed(withConfiguredRetention(forCache, { warnDrops: true }), "authoritative"); } diff --git a/src/providers/antigravity-models.ts b/src/providers/antigravity-models.ts index 15adece9a1..53c64f37a6 100644 --- a/src/providers/antigravity-models.ts +++ b/src/providers/antigravity-models.ts @@ -1,4 +1,5 @@ import { isValidModelDiscoveryModelId, MODEL_DISCOVERY_MAX_MODELS } from "./model-discovery-limits"; +import { isModelCacheGenerationCurrent } from "../codex/model-cache"; // Google Antigravity (Cloud Code Assist) bundled model list. // @@ -74,8 +75,12 @@ const ANTIGRAVITY_DISCOVERY_EFFORTS = ["low", "medium", "high"] as const; function pickerModelIdForDiscoveredWireId( wireId: string, + info: Record, available: ReadonlyMap>, ): string { + const displayModelId = antigravityDisplayModelId(info.displayName, wireId); + if (displayModelId) return displayModelId; + const explicitPickerId = Object.hasOwn(ANTIGRAVITY_PICKER_MODEL_BY_WIRE_ID, wireId) ? ANTIGRAVITY_PICKER_MODEL_BY_WIRE_ID[wireId] : undefined; @@ -240,6 +245,8 @@ export const ANTIGRAVITY_MODEL_INPUT_MODALITIES: Record = { export interface AntigravityAvailableModel { id: string; + /** CCA model id used by the agent envelope when `id` comes from display metadata. */ + wireModelId: string; contextWindow?: number; inputModalities?: string[]; } @@ -254,6 +261,86 @@ function antigravityPositiveInteger(value: unknown): number | undefined { return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : undefined; } +interface DiscoveredWireModelMapping { + readonly models: ReadonlyMap; + readonly generation?: { provider: string; cacheGeneration: string }; +} + +const discoveredWireModelsByBaseUrl = new Map(); + +function antigravityBaseUrlKey(baseUrl: string | undefined): string | undefined { + if (typeof baseUrl !== "string" || !baseUrl.trim()) return undefined; + const trimmed = baseUrl.trim().replace(/\/+$/, ""); + try { + const url = new URL(trimmed); + url.hash = ""; + url.search = ""; + return url.toString().replace(/\/+$/, "").toLowerCase(); + } catch { + return trimmed.toLowerCase(); + } +} + +/** Remember the wire ids returned by one live CCA discovery for request routing. */ +export function registerAntigravityDiscoveredWireModels( + baseUrl: string | undefined, + models: readonly AntigravityAvailableModel[], + generation?: { provider: string; cacheGeneration: string }, +): void { + const key = antigravityBaseUrlKey(baseUrl); + if (!key) return; + const wireModels = new Map(); + for (const model of models) wireModels.set(model.id, model.wireModelId); + discoveredWireModelsByBaseUrl.set(key, { + models: wireModels, + ...(generation ? { generation } : {}), + }); +} + +function discoveredAntigravityWireModelId( + modelId: string, + baseUrl: string | undefined, +): string | undefined { + const key = antigravityBaseUrlKey(baseUrl); + if (!key) return undefined; + const mapping = discoveredWireModelsByBaseUrl.get(key); + if (!mapping) return undefined; + if (mapping.generation + && !isModelCacheGenerationCurrent(mapping.generation.provider, mapping.generation.cacheGeneration)) { + discoveredWireModelsByBaseUrl.delete(key); + return undefined; + } + return mapping.models.get(modelId); +} + +/** + * Convert the CCA display label used by `agy` into its public model selector. + * + * The wire id is authoritative for requests, while the label is authoritative for the + * user-facing selector when Google has renamed or re-tiered a model. Keep both instead + * of maintaining a provider-specific list of known model names. + */ +function antigravityDisplayModelId(displayName: unknown, wireId: string): string | undefined { + if (typeof displayName !== "string") return undefined; + const label = displayName.trim(); + if (!label || label.length > 512) return undefined; + const slug = (replaceDots: boolean): string => label + .normalize("NFKC") + .toLowerCase() + .replace(replaceDots ? /\./g : /\s+/g, replaceDots ? "-" : " ") + .replace(/[^a-z0-9.-]+/g, "-") + .replace(/-+/g, "-") + .replace(/^-|-$/g, ""); + const preserved = slug(false); + const compact = slug(true); + if (!isValidModelDiscoveryModelId(preserved) && !isValidModelDiscoveryModelId(compact)) return undefined; + if (preserved === wireId || compact === wireId + || preserved === `${wireId}-thinking` || compact === `${wireId}-thinking`) { + return wireId; + } + return isValidModelDiscoveryModelId(preserved) ? preserved : compact; +} + /** * Extract the CCA models that are valid for agent requests. The endpoint also returns tab, * command, commit-message, transcription, and standalone image-generation models; those are not @@ -288,13 +375,6 @@ export function parseAntigravityAvailableModels( } } } - // This model is exposed by Antigravity's agent chat surface even though it is grouped under - // image generation in the discovery response. - if (Array.isArray(body.imageGenerationModelIds) - && body.imageGenerationModelIds.includes("gemini-3.1-flash-image")) { - if (ids.length >= limit) return null; - ids.push("gemini-3.1-flash-image"); - } // Newer CCA responses identify tiered Flash models through this index instead of // adding their synthetic wire ids to agentModelSorts. const tieredModelIds = antigravityRecord(body.tieredModelIds); @@ -305,6 +385,12 @@ export function parseAntigravityAvailableModels( || !Object.hasOwn(models, id) || !antigravityRecord(models[id]) || ids.length >= limit) return null; + const baseId = id.endsWith("-tiered") ? id.slice(0, -"-tiered".length) : id; + if (ids.some(agentId => + agentId === id + || agentId === baseId + || ANTIGRAVITY_DISCOVERY_EFFORTS.some(effort => agentId === `${baseId}-${effort}`) + )) continue; ids.push(id); } } @@ -313,23 +399,18 @@ export function parseAntigravityAvailableModels( for (const wireId of ids) { const info = antigravityRecord(models[wireId]); if (!info || available.has(wireId)) continue; - // Legacy compatibility aliases are deliberately routed to newer wire ids for saved - // selections. They are not safe as independently discovered picker rows. - const alias = Object.hasOwn(ANTIGRAVITY_MODEL_ALIASES, wireId) - ? ANTIGRAVITY_MODEL_ALIASES[wireId] - : undefined; - if (alias && alias !== wireId) continue; available.set(wireId, info); } const out: AntigravityAvailableModel[] = []; const seen = new Set(); for (const [wireId, info] of available) { - const id = pickerModelIdForDiscoveredWireId(wireId, available); + const id = pickerModelIdForDiscoveredWireId(wireId, info, available); if (seen.has(id)) continue; seen.add(id); out.push({ id, + wireModelId: wireId, ...(antigravityPositiveInteger(info.maxTokens) ? { contextWindow: antigravityPositiveInteger(info.maxTokens) } : {}), // Tri-state, deliberately not a ternary: `true` asserts image support, // `false` asserts against it, and ABSENT is unknown. Collapsing absent into @@ -347,7 +428,9 @@ export function parseAntigravityAvailableModels( return out; } -export function resolveAntigravityWireModelId(modelId: string): string { +export function resolveAntigravityWireModelId(modelId: string, baseUrl?: string): string { + const discovered = discoveredAntigravityWireModelId(modelId, baseUrl); + if (discovered) return discovered; return Object.hasOwn(ANTIGRAVITY_MODEL_ALIASES, modelId) ? ANTIGRAVITY_MODEL_ALIASES[modelId] : modelId; @@ -380,7 +463,19 @@ export function retiredAntigravityFlashTier(modelId: string): string | undefined export function resolveAntigravityEffortWireModel( modelId: string, effort?: string, + baseUrl?: string, ): { wireModelId: string; thinkingLevel?: string } { + const discoveredWireModelId = discoveredAntigravityWireModelId(modelId, baseUrl); + if (discoveredWireModelId && (discoveredWireModelId !== modelId || isAntigravitySuffixModelId(modelId))) { + const defaultLevel = ANTIGRAVITY_THINKING_LEVEL_MODELS[modelId]; + return { + wireModelId: discoveredWireModelId, + ...(defaultLevel + ? { thinkingLevel: effort ? resolveAntigravityThinkingLevel(effort) ?? defaultLevel : defaultLevel } + : {}), + }; + } + // Rule 0: retired Flash id — Google has taken the wire id offline, so route to the // current generation and carry the tier the retired id encoded. This runs BEFORE the // suffix check because those ids are aliases, and rule 1 would drop the tier. @@ -394,7 +489,7 @@ export function resolveAntigravityEffortWireModel( // Rule 1: suffix/compat alias — suffix IS the effort. if (isAntigravitySuffixModelId(modelId)) { - return { wireModelId: resolveAntigravityWireModelId(modelId) }; + return { wireModelId: resolveAntigravityWireModelId(modelId, baseUrl) }; } // Rule 1b: single-wire-id Gemini model whose tiers ride on thinkingLevel. Without @@ -424,7 +519,7 @@ export function resolveAntigravityEffortWireModel( } // Rule 5: everything else. - return { wireModelId: resolveAntigravityWireModelId(modelId) }; + return { wireModelId: resolveAntigravityWireModelId(modelId, baseUrl) }; } diff --git a/tests/gemini-37-flash-migration.test.ts b/tests/gemini-37-flash-migration.test.ts index c577c76060..1fed29366d 100644 --- a/tests/gemini-37-flash-migration.test.ts +++ b/tests/gemini-37-flash-migration.test.ts @@ -110,8 +110,8 @@ describe("3.7 reasoning control", () => { }); }); -describe("stale discovery cannot republish a retired model", () => { - test("a CCA payload still listing 3.6 tiers yields no retired picker row", () => { +describe("live discovery follows the CCA agent catalog", () => { + test("a CCA payload still listing 3.6 tiers preserves those live rows", () => { const payload = { models: Object.fromEntries( ["gemini-3.6-flash-low", "gemini-3.6-flash-medium", "gemini-3.6-flash-high", "gemini-3.7-flash"] @@ -124,10 +124,12 @@ describe("stale discovery cannot republish a retired model", () => { }], }; const ids = parseAntigravityAvailableModels(payload)?.map(model => model.id) ?? []; - expect(ids).toContain("gemini-3.7-flash"); - for (const retired of Object.keys(RETIRED_TIERS)) { - expect(ids).not.toContain(retired); - } + expect(ids).toEqual([ + "gemini-3.6-flash-low", + "gemini-3.6-flash-medium", + "gemini-3.6-flash-high", + "gemini-3.7-flash", + ]); }); }); diff --git a/tests/google-antigravity-wire.test.ts b/tests/google-antigravity-wire.test.ts index 5ea15eff2a..cc3b0d458f 100644 --- a/tests/google-antigravity-wire.test.ts +++ b/tests/google-antigravity-wire.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; import { createGoogleAdapter as createGoogleAdapterProduction } from "../src/adapters/google"; import { antigravitySessionId, isLikelyRealThoughtSignature } from "../src/adapters/google-antigravity-wire"; -import { ANTIGRAVITY_MODELS, ANTIGRAVITY_MODEL_EFFORTS, canonicalAntigravityUsageModel, parseAntigravityAvailableModels, resolveAntigravityEffortWireModel, resolveAntigravityWireModelId } from "../src/providers/antigravity-models"; +import { ANTIGRAVITY_MODELS, ANTIGRAVITY_MODEL_EFFORTS, canonicalAntigravityUsageModel, parseAntigravityAvailableModels, registerAntigravityDiscoveredWireModels, resolveAntigravityEffortWireModel, resolveAntigravityWireModelId } from "../src/providers/antigravity-models"; import { MODEL_DISCOVERY_MAX_MODEL_ID_LENGTH, MODEL_DISCOVERY_MAX_MODELS } from "../src/providers/model-discovery"; import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../src/types"; import { withTestTranslatorBudget } from "./helpers/translator-budget"; @@ -168,6 +168,17 @@ describe("antigravity CCA envelope", () => { agentModelSorts: [{ groups: [{ modelIds: [] }] }], tieredModelIds: { flash: ["gemini-3.7-flash-tiered"] }, })?.map(model => model.id)).toEqual(["gemini-3.7-flash"]); + expect(parseAntigravityAvailableModels({ + models: { + "gemini-3.7-flash-image": { maxTokens: 1_048_576 }, + "gemini-3.7-flash-tiered": { maxTokens: 1_048_576 }, + }, + agentModelSorts: [{ groups: [{ modelIds: ["gemini-3.7-flash-image"] }] }], + tieredModelIds: { flash: ["gemini-3.7-flash-tiered"] }, + })?.map(model => model.id)).toEqual([ + "gemini-3.7-flash-image", + "gemini-3.7-flash", + ]); expect(parseAntigravityAvailableModels({ models: { "-tiered": { maxTokens: 1_048_576 } }, agentModelSorts: [{ groups: [{ modelIds: ["-tiered"] }] }], @@ -188,6 +199,94 @@ describe("antigravity CCA envelope", () => { ]); }); + test("uses live CCA display names while retaining their wire ids", async () => { + const payload = { + models: { + "gemini-3.7-flash-high": { displayName: "Gemini 3.7 Flash (High)", maxTokens: 1_048_576 }, + "gemini-3.6-flash-high": { displayName: "Gemini 3.6 Flash (High)", maxTokens: 1_048_576 }, + "gemini-3-flash-agent": { displayName: "Gemini 3.5 Flash (High)", maxTokens: 1_048_576 }, + "gemini-3.5-flash-low": { displayName: "Gemini 3.5 Flash (Medium)", maxTokens: 1_048_576 }, + "gemini-3.5-flash-extra-low": { displayName: "Gemini 3.5 Flash (Low)", maxTokens: 1_048_576 }, + "gemini-pro-agent": { displayName: "Gemini 3.1 Pro (High)", maxTokens: 1_048_576 }, + "gemini-3.1-pro-low": { displayName: "Gemini 3.1 Pro (Low)", maxTokens: 1_048_576 }, + "claude-sonnet-4-6": { displayName: "Claude Sonnet 4.6 (Thinking)", maxTokens: 250_000 }, + }, + agentModelSorts: [{ groups: [{ modelIds: [ + "gemini-3.7-flash-high", + "gemini-3.6-flash-high", + "gemini-3-flash-agent", + "gemini-3.5-flash-low", + "gemini-3.5-flash-extra-low", + "gemini-pro-agent", + "gemini-3.1-pro-low", + "claude-sonnet-4-6", + ] }] }], + }; + const rows = parseAntigravityAvailableModels(payload)!; + expect(rows.map(model => model.id)).toEqual([ + "gemini-3.7-flash-high", + "gemini-3.6-flash-high", + "gemini-3.5-flash-high", + "gemini-3.5-flash-medium", + "gemini-3.5-flash-low", + "gemini-3.1-pro-high", + "gemini-3.1-pro-low", + "claude-sonnet-4-6", + ]); + expect(rows.map(model => [model.id, model.wireModelId])).toEqual([ + ["gemini-3.7-flash-high", "gemini-3.7-flash-high"], + ["gemini-3.6-flash-high", "gemini-3.6-flash-high"], + ["gemini-3.5-flash-high", "gemini-3-flash-agent"], + ["gemini-3.5-flash-medium", "gemini-3.5-flash-low"], + ["gemini-3.5-flash-low", "gemini-3.5-flash-extra-low"], + ["gemini-3.1-pro-high", "gemini-pro-agent"], + ["gemini-3.1-pro-low", "gemini-3.1-pro-low"], + ["claude-sonnet-4-6", "claude-sonnet-4-6"], + ]); + + const baseUrl = "https://cca.example"; + registerAntigravityDiscoveredWireModels(baseUrl, rows); + expect(resolveAntigravityEffortWireModel("gemini-3.5-flash-high", undefined, baseUrl)) + .toEqual({ wireModelId: "gemini-3-flash-agent" }); + expect(resolveAntigravityEffortWireModel("gemini-3.6-flash-high", undefined, baseUrl)) + .toEqual({ wireModelId: "gemini-3.6-flash-high" }); + expect(resolveAntigravityEffortWireModel("claude-sonnet-4-6", "high", baseUrl)) + .toEqual({ wireModelId: "claude-sonnet-4-6", thinkingLevel: "high" }); + + const req = await createGoogleAdapter({ ...effortProvider, baseUrl }).buildRequest( + parsedWithEffort("gemini-3.5-flash-high"), + ); + expect(JSON.parse(req.body).model).toBe("gemini-3-flash-agent"); + }); + + test("preserves thinkingLevel for a display-derived tiered Flash model", async () => { + const payload = { + models: { + "gemini-3.7-flash-tiered": { displayName: "Gemini 3.7 Flash", maxTokens: 1_048_576 }, + }, + agentModelSorts: [{ groups: [{ modelIds: [] }] }], + tieredModelIds: { flash: ["gemini-3.7-flash-tiered"] }, + }; + const rows = parseAntigravityAvailableModels(payload)!; + expect(rows).toEqual([{ + id: "gemini-3.7-flash", + wireModelId: "gemini-3.7-flash-tiered", + contextWindow: 1_048_576, + }]); + + const baseUrl = "https://cca-tiered-discovery.example"; + registerAntigravityDiscoveredWireModels(baseUrl, rows); + expect(resolveAntigravityEffortWireModel("gemini-3.7-flash", "high", baseUrl)) + .toEqual({ wireModelId: "gemini-3.7-flash-tiered", thinkingLevel: "high" }); + + const req = await createGoogleAdapter({ ...effortProvider, baseUrl }).buildRequest( + parsedWithEffort("gemini-3.7-flash", "high"), + ); + const envelope = JSON.parse(req.body); + expect(envelope.model).toBe("gemini-3.7-flash-tiered"); + expect(envelope.request.generationConfig.thinkingConfig).toEqual({ thinkingLevel: "high" }); + }); + test("keeps unknown discovered tier IDs directly routable", async () => { for (const modelId of ["future-flash-tiered", "future-flash-low"]) { const req = await createGoogleAdapter(effortProvider).buildRequest(parsedWithEffort(modelId, "high")); @@ -267,7 +366,7 @@ describe("antigravity CCA envelope", () => { models: { "agent-model": { maxTokens: 1_048_576 } }, agentModelSorts: [{ groups: [{ modelIds: ["agent-model"] }] }], imageGenerationModelIds: ["gemini-3.1-flash-image"], - }, 1)).toBeNull(); + }, 1)?.map(model => model.id)).toEqual(["agent-model"]); }); test("throws when no project id is available", async () => { diff --git a/tests/google-models-listing.test.ts b/tests/google-models-listing.test.ts index 023c3ec07e..01a40230a6 100644 --- a/tests/google-models-listing.test.ts +++ b/tests/google-models-listing.test.ts @@ -4,7 +4,8 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect } from "../src/codex/catalog"; import { buildModelsRequest } from "../src/oauth"; -import { clearModelCache, getStaleCached } from "../src/codex/model-cache"; +import { captureModelCacheGeneration, clearModelCache, getStaleCached } from "../src/codex/model-cache"; +import { registerAntigravityDiscoveredWireModels, resolveAntigravityWireModelId } from "../src/providers/antigravity-models"; import type { OcxConfig, OcxProviderConfig } from "../src/types"; import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; @@ -129,8 +130,6 @@ describe("Antigravity live model discovery", () => { "future-flash-high", "future-flash-low", "future-flash-medium", - "future-flash-tiered", - "gemini-3.1-flash-image", "gemini-3.1-pro-low", "gemini-3.7-flash", ]); @@ -215,6 +214,64 @@ describe("Antigravity live model discovery", () => { } }); + test("does not register wire mappings from a stale CCA discovery", async () => { + const home = mkdtempSync(join(tmpdir(), "ocx-antigravity-stale-discovery-")); + process.env.OPENCODEX_HOME = home; + writeFileSync(join(home, "auth.json"), JSON.stringify({ + "google-antigravity": { + activeAccountId: "active", + accounts: [{ + id: "active", + credential: { + access: "access-token", + refresh: "refresh-token", + expires: Date.now() + 3_600_000, + projectId: "project-id", + }, + }], + }, + })); + let releaseResponse!: () => void; + let markFetchStarted!: () => void; + const responseGate = new Promise(resolve => { releaseResponse = resolve; }); + const fetchStarted = new Promise(resolve => { markFetchStarted = resolve; }); + const baseUrl = "https://cca-stale-discovery.example"; + const priorGeneration = captureModelCacheGeneration("google-antigravity"); + registerAntigravityDiscoveredWireModels(baseUrl, [{ id: "stale-model", wireModelId: "old-wire-model" }], { + provider: "google-antigravity", + cacheGeneration: priorGeneration, + }); + expect(resolveAntigravityWireModelId("stale-model", baseUrl)).toBe("old-wire-model"); + globalThis.fetch = (async () => { + markFetchStarted(); + await responseGate; + return Response.json({ + models: { "stale-wire-model": { displayName: "Stale Model" } }, + agentModelSorts: [{ groups: [{ modelIds: ["stale-wire-model"] }] }], + }); + }) as typeof fetch; + + try { + const pending = gatherRoutedModels(configWith("google-antigravity", { + adapter: "google", + authMode: "oauth", + baseUrl, + project: "configured-project", + liveModels: true, + models: ["configured-only"], + })); + await fetchStarted; + clearModelCache("google-antigravity"); + releaseResponse(); + + expect((await pending).filter(model => model.provider === "google-antigravity").map(model => model.id)) + .toEqual(["configured-only"]); + expect(resolveAntigravityWireModelId("stale-model", baseUrl)).toBe("stale-model"); + } finally { + rmSync(home, { recursive: true, force: true }); + } + }); + test("uses the configured key for a custom CCA provider", async () => { const seen: { headers: Record }[] = []; globalThis.fetch = (async (_input: RequestInfo | URL, init?: RequestInit) => {