Skip to content

[Duplicate Code] API proxy provider env-var constants are maintained in parallel JS and TypeScript files #5827

Description

@github-actions

Duplicate Code Opportunity

Summary

Evidence

TypeScript host-side constants:

// src/api-proxy-env-constants.ts:10-41
export const OPENAI_ENV = {
  KEY: 'OPENAI_API_KEY',
  TARGET: 'OPENAI_API_TARGET',
  BASE_PATH: 'OPENAI_API_BASE_PATH',
  AUTH_HEADER: 'AWF_OPENAI_AUTH_HEADER',
} as const;

export const ANTHROPIC_ENV = {
  KEY: 'ANTHROPIC_API_KEY',
  TARGET: 'ANTHROPIC_API_TARGET',
  BASE_PATH: 'ANTHROPIC_API_BASE_PATH',
  AUTH_HEADER: 'AWF_ANTHROPIC_AUTH_HEADER',
} as const;

export const GEMINI_ENV = {
  KEY: 'GEMINI_API_KEY',
  TARGET: 'GEMINI_API_TARGET',
  BASE_PATH: 'GEMINI_API_BASE_PATH',
} as const;

export const COPILOT_ENV = {
  GITHUB_TOKEN: 'COPILOT_GITHUB_TOKEN',
  PROVIDER_API_KEY: 'COPILOT_PROVIDER_API_KEY',
  PROVIDER_TYPE: 'COPILOT_PROVIDER_TYPE',
  PROVIDER_BASE_URL: 'COPILOT_PROVIDER_BASE_URL',
  API_TARGET: 'COPILOT_API_TARGET',
  API_BASE_PATH: 'COPILOT_API_BASE_PATH',
} as const;

CommonJS sidecar constants duplicate the same matrix:

// containers/api-proxy/provider-env-constants.js:12-43
const OPENAI_ENV = /** `@type` {const} */ ({
  KEY: 'OPENAI_API_KEY',
  TARGET: 'OPENAI_API_TARGET',
  BASE_PATH: 'OPENAI_API_BASE_PATH',
  AUTH_HEADER: 'AWF_OPENAI_AUTH_HEADER',
});

const ANTHROPIC_ENV = /** `@type` {const} */ ({
  KEY: 'ANTHROPIC_API_KEY',
  TARGET: 'ANTHROPIC_API_TARGET',
  BASE_PATH: 'ANTHROPIC_API_BASE_PATH',
  AUTH_HEADER: 'AWF_ANTHROPIC_AUTH_HEADER',
});

const GEMINI_ENV = /** `@type` {const} */ ({
  KEY: 'GEMINI_API_KEY',
  TARGET: 'GEMINI_API_TARGET',
  BASE_PATH: 'GEMINI_API_BASE_PATH',
});

const COPILOT_ENV = /** `@type` {const} */ ({
  GITHUB_TOKEN: 'COPILOT_GITHUB_TOKEN',
  PROVIDER_API_KEY: 'COPILOT_PROVIDER_API_KEY',
  PROVIDER_TYPE: 'COPILOT_PROVIDER_TYPE',
  PROVIDER_BASE_URL: 'COPILOT_PROVIDER_BASE_URL',
  API_TARGET: 'COPILOT_API_TARGET',
  API_BASE_PATH: 'COPILOT_API_BASE_PATH',
});

The host-side env builder relies on those names when forwarding credentials and target config into the sidecar:

// src/services/api-proxy-env-config.ts:20-35,72-82
const providers = [
  { target: config.copilotApiTarget, basePath: config.copilotApiBasePath, envTarget: COPILOT_ENV.API_TARGET, envBasePath: COPILOT_ENV.API_BASE_PATH, stripTarget: true },
  { target: config.openaiApiTarget, basePath: config.openaiApiBasePath, envTarget: OPENAI_ENV.TARGET, envBasePath: OPENAI_ENV.BASE_PATH, stripTarget: true },
  { target: config.anthropicApiTarget, basePath: config.anthropicApiBasePath, envTarget: ANTHROPIC_ENV.TARGET, envBasePath: ANTHROPIC_ENV.BASE_PATH, stripTarget: true },
  { target: config.geminiApiTarget, basePath: config.geminiApiBasePath, envTarget: GEMINI_ENV.TARGET, envBasePath: GEMINI_ENV.BASE_PATH, stripTarget: true },
];
...
...(config.openaiApiKey && { [OPENAI_ENV.KEY]: config.openaiApiKey }),
...(config.anthropicApiKey && { [ANTHROPIC_ENV.KEY]: config.anthropicApiKey }),
...(config.copilotGithubToken && { [COPILOT_ENV.GITHUB_TOKEN]: config.copilotGithubToken }),
...(config.geminiApiKey && { [GEMINI_ENV.KEY]: config.geminiApiKey }),
...buildProviderTargetEnv(config),

Suggested Refactoring

Use one generated or shared source of truth for provider env names. Options:

  • Keep a JSON manifest such as shared/api-proxy-env.json and generate both src/api-proxy-env-constants.ts and containers/api-proxy/provider-env-constants.js during build/test.
  • Or move to a .json file consumable by both TypeScript and CommonJS, with typed wrappers on the TS side.
  • Add a test that imports/loads both surfaces and fails if any provider key differs, if generation is not introduced immediately.

Affected Files

  • src/api-proxy-env-constants.ts — lines 1-41
  • containers/api-proxy/provider-env-constants.js — lines 1-43
  • src/services/api-proxy-env-config.ts — lines 5, 20-35, 72-82

Effort Estimate

Medium


Detected by Duplicate Code Detector workflow. Run date: 2026-07-02

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

Generated by Duplicate Code Detector · 160.8 AIC · ⊞ 20.1K ·

  • expires on Aug 1, 2026, 10:01 PM UTC

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions