Skip to content

[Duplicate Code] Gemini and Vertex adapters repeat Google provider scaffolding #5918

Description

@github-actions

Duplicate Code Opportunity

Summary

  • Pattern: Gemini and Vertex each rebuild the same Google API-key adapter shape: auth scaffold, x-goog-api-key header builder, createAdapterMethods, buildProviderAdapter, enablement, unconfigured response, and health response.
  • Locations: containers/api-proxy/providers/gemini.js lines 28-82 and containers/api-proxy/providers/vertex.js lines 30-74.
  • Impact: Roughly 40-45 lines of provider boilerplate could move behind one Google adapter factory, reducing drift in a credential-isolation path. Score: >20 duplicate lines (+3), security-critical credential path (+3), easy extraction (+1) = 7.

Evidence

containers/api-proxy/providers/gemini.js lines 28-82:

function createGeminiAdapter(env, deps = {}) {
  const { apiKey, rawTarget, basePath, bodyTransform } = createProviderAuthScaffold(env, deps, {
    keyEnvVar: GEMINI_ENV.KEY,
    targetEnvVar: GEMINI_ENV.TARGET,
    basePathEnvVar: GEMINI_ENV.BASE_PATH,
    defaultTarget: 'generativelanguage.googleapis.com',
  });
  const buildAuthHeaders = () => providerKeyHeaders('x-goog-api-key', apiKey);

  const adapterMethods = createAdapterMethods({
    apiKey,
    rawTarget,
    basePath,
    provider: 'gemini',
    port: 10003,
    defaultTarget: 'generativelanguage.googleapis.com',
    validationPath: '/v1beta/models',
    validationHeaders: buildAuthHeaders,
    modelsPath: '/v1beta/models',
    modelsFetchHeaders: buildAuthHeaders,
  });

  return buildProviderAdapter({
    name: 'gemini',
    port: 10003,
    isManagementPort: false,
    adapterMethods,
    getAuthHeaders() {
      return buildAuthHeaders();
    },
    bodyTransform,
    isEnabled() { return !!apiKey; },
    getUnconfiguredResponse() {
      return {
        statusCode: 503,
        body: { error: 'Gemini proxy not configured (no GEMINI_API_KEY). Set GEMINI_API_KEY in the AWF runner environment to enable credential isolation.' },
      };
    },
    getUnconfiguredHealthResponse() {
      return makeUnconfiguredHealthResponse('awf-api-proxy-gemini', 'GEMINI_API_KEY not configured in api-proxy sidecar');
    },
  });
}

containers/api-proxy/providers/vertex.js lines 30-74:

function createVertexAdapter(env, deps = {}) {
  const { apiKey, rawTarget, basePath, bodyTransform } = createProviderAuthScaffold(env, deps, {
    keyEnvVar: VERTEX_ENV.KEY,
    targetEnvVar: VERTEX_ENV.TARGET,
    basePathEnvVar: VERTEX_ENV.BASE_PATH,
    defaultTarget: 'aiplatform.googleapis.com',
  });
  const buildAuthHeaders = () => providerKeyHeaders('x-goog-api-key', apiKey);

  const adapterMethods = createAdapterMethods({
    apiKey,
    rawTarget,
    basePath,
    provider: 'vertex',
    port: 10004,
    defaultTarget: 'aiplatform.googleapis.com',
    validationPath: '/v1/projects',
    validationHeaders: buildAuthHeaders,
    modelsPath: null,
    modelsFetchHeaders: null,
  });

  return buildProviderAdapter({
    name: 'vertex',
    port: 10004,
    isManagementPort: false,
    alwaysBind: true,
    adapterMethods,
    getAuthHeaders() {
      return buildAuthHeaders();
    },
    bodyTransform,
    isEnabled() { return !!apiKey; },
    getUnconfiguredResponse() {
      return {
        statusCode: 503,
        body: { error: 'Vertex AI proxy not configured (no GOOGLE_API_KEY). Set GOOGLE_API_KEY in the AWF runner environment to enable credential isolation.' },
      };
    },
    getUnconfiguredHealthResponse() {
      return makeUnconfiguredHealthResponse('awf-api-proxy-vertex', 'GOOGLE_API_KEY not configured in api-proxy sidecar');
    },
  });
}

Suggested Refactoring

Extract a createGoogleApiKeyAdapter(env, deps, options) helper, either in a new provider utility module or beside the existing adapter helpers. The helper can own the shared createProviderAuthScaffold, providerKeyHeaders('x-goog-api-key', apiKey), createAdapterMethods, getAuthHeaders, isEnabled, and default unconfigured responses, while each provider supplies only name, port, env constants, default target, validation/models paths, and optional request URL transform.

Affected Files

  • containers/api-proxy/providers/gemini.js — lines 28-82
  • containers/api-proxy/providers/vertex.js — lines 30-74

Effort Estimate

Low


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

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 · 141.2 AIC · ⊞ 20.1K ·

  • expires on Aug 4, 2026, 6:56 AM 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