Skip to content

[Duplicate Code] API proxy environment variable matrix is duplicated between wrapper config and provider adapters #5198

Description

@github-actions

Duplicate Code Opportunity

Summary

  • Pattern: API proxy credential/target/base-path environment variable names are declared in multiple places: TypeScript wrapper config assembly and JavaScript provider adapters. The same matrix (*_API_KEY, *_API_TARGET, *_API_BASE_PATH, auth-header overrides, BYOK fields) is repeated as string literals.
  • Locations: src/commands/build-config.ts lines 170-201; containers/api-proxy/providers/openai.js lines 32-37, 40-49; containers/api-proxy/providers/anthropic.js lines 45-52; containers/api-proxy/providers/gemini.js lines 27-32; containers/api-proxy/providers/copilot.js lines 53-59.
  • Impact: The wrapper decides which host credentials/config values enter the isolated API proxy, while provider adapters decide how those same values are consumed. Duplicating the env matrix increases the chance that a new provider setting is forwarded but not read, read but not forwarded, or documented inconsistently.

Evidence

The wrapper copies API proxy env/config values into WrapperConfig using repeated string literals:

openaiApiKey: process.env.OPENAI_API_KEY,
anthropicApiKey: process.env.ANTHROPIC_API_KEY,
copilotGithubToken: process.env.COPILOT_GITHUB_TOKEN,
copilotProviderApiKey: process.env.COPILOT_PROVIDER_API_KEY,
copilotProviderType:
  (options.copilotProviderType as string | undefined) || process.env.COPILOT_PROVIDER_TYPE,
copilotProviderBaseUrl:
  (options.copilotProviderBaseUrl as string | undefined) || process.env.COPILOT_PROVIDER_BASE_URL,
geminiApiKey: process.env.GEMINI_API_KEY,
// ...
openaiApiTarget:
  (options.openaiApiTarget as string | undefined) || process.env.OPENAI_API_TARGET,
openaiApiBasePath:
  (options.openaiApiBasePath as string | undefined) || process.env.OPENAI_API_BASE_PATH,
anthropicApiTarget:
  (options.anthropicApiTarget as string | undefined) || process.env.ANTHROPIC_API_TARGET,
anthropicApiBasePath:
  (options.anthropicApiBasePath as string | undefined) || process.env.ANTHROPIC_API_BASE_PATH,
openaiApiAuthHeader:
  (options.openaiApiAuthHeader as string | undefined) || process.env.AWF_OPENAI_AUTH_HEADER,
anthropicApiAuthHeader:
  (options.anthropicApiAuthHeader as string | undefined) || process.env.AWF_ANTHROPIC_AUTH_HEADER,
geminiApiTarget:
  (options.geminiApiTarget as string | undefined) || process.env.GEMINI_API_TARGET,
geminiApiBasePath:
  (options.geminiApiBasePath as string | undefined) || process.env.GEMINI_API_BASE_PATH,

Provider adapters repeat the same env names when consuming the values:

const { apiKey: openaiApiKey, rawTarget: openaiTarget, basePath: openaiBasePath } = createBaseAdapterConfig(env, {
  keyEnvVar: 'OPENAI_API_KEY',
  targetEnvVar: 'OPENAI_API_TARGET',
  basePathEnvVar: 'OPENAI_API_BASE_PATH',
  defaultTarget: 'api.openai.com',
});
const customAuthHeader = (() => {
  const header = validateAuthHeaderEnv('AWF_OPENAI_AUTH_HEADER', env.AWF_OPENAI_AUTH_HEADER);
  // ...
})();
const { apiKey, rawTarget, basePath } = createBaseAdapterConfig(env, {
  keyEnvVar: 'ANTHROPIC_API_KEY',
  targetEnvVar: 'ANTHROPIC_API_TARGET',
  basePathEnvVar: 'ANTHROPIC_API_BASE_PATH',
  defaultTarget: 'api.anthropic.com',
});
const authHeaderName = validateAuthHeaderEnv('AWF_ANTHROPIC_AUTH_HEADER', env.AWF_ANTHROPIC_AUTH_HEADER, 'x-api-key');
const { apiKey, rawTarget, basePath } = createBaseAdapterConfig(env, {
  keyEnvVar: 'GEMINI_API_KEY',
  targetEnvVar: 'GEMINI_API_TARGET',
  basePathEnvVar: 'GEMINI_API_BASE_PATH',
  defaultTarget: 'generativelanguage.googleapis.com',
});

Suggested Refactoring

Introduce a single provider environment matrix, for example src/api-proxy-provider-env.ts (and generated/JSON-exported data for the container JS side), describing each provider's:

  • key env var
  • target env var
  • base path env var
  • auth-header override env var, where supported
  • default upstream target
  • wrapper option field names

Use it in build-config.ts to assemble wrapper config and in containers/api-proxy/providers/* to call createBaseAdapterConfig(). If sharing TS directly with container JS is not practical, generate a small checked-in JSON/CommonJS constants file during build so both sides consume the same source of truth.

Affected Files

  • src/commands/build-config.ts — lines 170-201
  • containers/api-proxy/providers/openai.js — lines 32-37, 40-49
  • containers/api-proxy/providers/anthropic.js — lines 45-52
  • containers/api-proxy/providers/gemini.js — lines 27-32
  • containers/api-proxy/providers/copilot.js — lines 53-59

Effort Estimate

Medium


Detected by Duplicate Code Detector workflow. Run date: 2026-06-17

Generated by Duplicate Code Detector ·

  • expires on Jul 17, 2026, 10:20 PM UTC

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions