Duplicate Code Opportunity
Summary
- Pattern:
getUnconfiguredHealthResponse() in three provider adapters returns identically structured objects { statusCode: 503, body: { status: 'not_configured', service: 'awf-api-proxy-{name}', error: '...' } } with no shared builder. This is inconsistent with the existing makeProviderNotConfiguredResponse() helper in proxy-utils.js that already centralises the getUnconfiguredResponse() pattern.
- Locations:
containers/api-proxy/providers/anthropic.js, containers/api-proxy/providers/copilot.js, containers/api-proxy/providers/gemini.js
- Impact: ~28 method-body lines across 3 providers (10 + 10 + 6). Any future change to the health endpoint response shape (e.g., adding a
port field for diagnostics, changing the 503 code, or adding a docs_url) requires touching three files.
Evidence
containers/api-proxy/providers/anthropic.js (lines 237–248)
getUnconfiguredHealthResponse() {
if (oidcRequested) {
return {
statusCode: 503,
body: { status: 'unavailable', service: 'awf-api-proxy-anthropic', error: oidcUnavailableError },
};
}
return {
statusCode: 503,
body: { status: 'not_configured', service: 'awf-api-proxy-anthropic', error: 'ANTHROPIC_API_KEY not configured in api-proxy sidecar' },
};
},
containers/api-proxy/providers/copilot.js (lines 297–308)
getUnconfiguredHealthResponse() {
if (oidcConfigured) {
return {
statusCode: 503,
body: { status: 'not_configured', service: 'awf-api-proxy-copilot', error: `Copilot OIDC token (${authProvider}) not yet available in api-proxy sidecar` },
};
}
return {
statusCode: 503,
body: { status: 'not_configured', service: 'awf-api-proxy-copilot', error: 'COPILOT_GITHUB_TOKEN or COPILOT_PROVIDER_API_KEY not configured in api-proxy sidecar' },
};
},
containers/api-proxy/providers/gemini.js (lines 92–97)
getUnconfiguredHealthResponse() {
return {
statusCode: 503,
body: { status: 'not_configured', service: 'awf-api-proxy-gemini', error: 'GEMINI_API_KEY not configured in api-proxy sidecar' },
};
},
For comparison, proxy-utils.js already has makeProviderNotConfiguredResponse(provider, port, message) that centralises the corresponding getUnconfiguredResponse() pattern — but no equivalent exists for getUnconfiguredHealthResponse.
Suggested Refactoring
Add a makeProviderHealthNotConfiguredResponse helper to containers/api-proxy/proxy-utils.js:
/**
* Build the standard /health response body for an unconfigured provider.
*
* `@param` {string} provider - Provider name (e.g. 'anthropic', 'gemini')
* `@param` {string} status - 'not_configured' | 'unavailable'
* `@param` {string} message - Human-readable error message
* `@returns` {{ statusCode: number, body: object }}
*/
function makeProviderHealthNotConfiguredResponse(provider, status, message) {
return {
statusCode: 503,
body: {
status,
service: `awf-api-proxy-${provider}`,
error: message,
},
};
}
Then each provider's getUnconfiguredHealthResponse becomes:
// anthropic (base case)
return makeProviderHealthNotConfiguredResponse(
'anthropic', 'not_configured',
'ANTHROPIC_API_KEY not configured in api-proxy sidecar'
);
// gemini
return makeProviderHealthNotConfiguredResponse(
'gemini', 'not_configured',
'GEMINI_API_KEY not configured in api-proxy sidecar'
);
The OIDC branch variants in anthropic and copilot would continue to use inline objects or call the helper with 'unavailable' status.
Affected Files
containers/api-proxy/providers/anthropic.js — lines 237–248
containers/api-proxy/providers/copilot.js — lines 297–308
containers/api-proxy/providers/gemini.js — lines 92–97
containers/api-proxy/proxy-utils.js — add new helper and export
Effort Estimate
Low
Detected by Duplicate Code Detector workflow. Run date: 2026-06-09
Generated by Duplicate Code Detector · 440.1 AIC · ⊞ 26.9K · ◷
Duplicate Code Opportunity
Summary
getUnconfiguredHealthResponse()in three provider adapters returns identically structured objects{ statusCode: 503, body: { status: 'not_configured', service: 'awf-api-proxy-{name}', error: '...' } }with no shared builder. This is inconsistent with the existingmakeProviderNotConfiguredResponse()helper inproxy-utils.jsthat already centralises thegetUnconfiguredResponse()pattern.containers/api-proxy/providers/anthropic.js,containers/api-proxy/providers/copilot.js,containers/api-proxy/providers/gemini.jsportfield for diagnostics, changing the 503 code, or adding adocs_url) requires touching three files.Evidence
containers/api-proxy/providers/anthropic.js(lines 237–248)containers/api-proxy/providers/copilot.js(lines 297–308)containers/api-proxy/providers/gemini.js(lines 92–97)For comparison,
proxy-utils.jsalready hasmakeProviderNotConfiguredResponse(provider, port, message)that centralises the correspondinggetUnconfiguredResponse()pattern — but no equivalent exists forgetUnconfiguredHealthResponse.Suggested Refactoring
Add a
makeProviderHealthNotConfiguredResponsehelper tocontainers/api-proxy/proxy-utils.js:Then each provider's
getUnconfiguredHealthResponsebecomes:The OIDC branch variants in anthropic and copilot would continue to use inline objects or call the helper with
'unavailable'status.Affected Files
containers/api-proxy/providers/anthropic.js— lines 237–248containers/api-proxy/providers/copilot.js— lines 297–308containers/api-proxy/providers/gemini.js— lines 92–97containers/api-proxy/proxy-utils.js— add new helper and exportEffort Estimate
Low
Detected by Duplicate Code Detector workflow. Run date: 2026-06-09