From 961eb95e9a882b2fd87d29d85161e361cb74ee97 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 13 Apr 2026 19:43:52 +0100 Subject: [PATCH] perf(secrets): lazy-load provider env var exports --- src/secrets/provider-env-vars.dynamic.test.ts | 27 ++++++++++ src/secrets/provider-env-vars.ts | 50 ++++++++++++++++--- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/secrets/provider-env-vars.dynamic.test.ts b/src/secrets/provider-env-vars.dynamic.test.ts index 79247ad0324..cf10f9d5e69 100644 --- a/src/secrets/provider-env-vars.dynamic.test.ts +++ b/src/secrets/provider-env-vars.dynamic.test.ts @@ -51,6 +51,33 @@ describe("provider env vars dynamic manifest metadata", () => { expect(mod.listKnownSecretEnvVarNames()).toContain("FIREWORKS_ALT_API_KEY"); }); + it("keeps lazy manifest-backed exports cold until accessed and resolves them once", async () => { + loadPluginManifestRegistry.mockReturnValue({ + plugins: [ + { + id: "external-fireworks", + origin: "global", + providerAuthEnvVars: { + fireworks: ["FIREWORKS_ALT_API_KEY"], + }, + }, + ], + diagnostics: [], + }); + + const mod = await import("./provider-env-vars.js"); + + expect(loadPluginManifestRegistry).not.toHaveBeenCalled(); + expect(mod.PROVIDER_ENV_VARS.fireworks).toEqual(["FIREWORKS_ALT_API_KEY"]); + expect(mod.PROVIDER_AUTH_ENV_VAR_CANDIDATES.fireworks).toEqual(["FIREWORKS_ALT_API_KEY"]); + const initialLoads = loadPluginManifestRegistry.mock.calls.length; + expect(initialLoads).toBeGreaterThan(0); + + void mod.PROVIDER_ENV_VARS.fireworks; + void mod.PROVIDER_AUTH_ENV_VAR_CANDIDATES.fireworks; + expect(loadPluginManifestRegistry).toHaveBeenCalledTimes(initialLoads); + }); + it("keeps workspace plugin env vars in default lookups", async () => { loadPluginManifestRegistry.mockReturnValue({ plugins: [ diff --git a/src/secrets/provider-env-vars.ts b/src/secrets/provider-env-vars.ts index 900677b9e31..f2c929339ca 100644 --- a/src/secrets/provider-env-vars.ts +++ b/src/secrets/provider-env-vars.ts @@ -163,6 +163,46 @@ export function resolveProviderEnvVars( }; } +function createLazyReadonlyRecord( + resolve: () => Record, +): Record { + let cached: Record | undefined; + const getResolved = (): Record => { + cached ??= resolve(); + return cached; + }; + + return new Proxy({} as Record, { + get(_target, prop) { + if (typeof prop !== "string") { + return undefined; + } + return getResolved()[prop]; + }, + has(_target, prop) { + return typeof prop === "string" && Object.hasOwn(getResolved(), prop); + }, + ownKeys() { + return Reflect.ownKeys(getResolved()); + }, + getOwnPropertyDescriptor(_target, prop) { + if (typeof prop !== "string") { + return undefined; + } + const value = getResolved()[prop]; + if (value === undefined) { + return undefined; + } + return { + configurable: true, + enumerable: true, + value, + writable: false, + }; + }, + }); +} + /** * Provider auth env candidates used by generic auth resolution. * @@ -170,9 +210,9 @@ export function resolveProviderEnvVars( * `resolveEnvApiKey()`. Bundled providers source this from plugin manifest * metadata so auth probes do not need to load plugin runtime. */ -export const PROVIDER_AUTH_ENV_VAR_CANDIDATES: Record = { - ...resolveProviderAuthEnvVarCandidates(), -}; +export const PROVIDER_AUTH_ENV_VAR_CANDIDATES = createLazyReadonlyRecord(() => + resolveProviderAuthEnvVarCandidates(), +); /** * Provider env vars used for setup/default secret refs and broad secret @@ -183,9 +223,7 @@ export const PROVIDER_AUTH_ENV_VAR_CANDIDATES: Record * is only for true core/non-plugin providers and a few setup-specific ordering * overrides where generic onboarding wants a different preferred env var. */ -export const PROVIDER_ENV_VARS: Record = { - ...resolveProviderEnvVars(), -}; +export const PROVIDER_ENV_VARS = createLazyReadonlyRecord(() => resolveProviderEnvVars()); export function getProviderEnvVars( providerId: string,