Merge pull request #1388 from eyaltoledano/ralph/chore/apply.requested.changes

chore: apply requested coderabbit changes
This commit is contained in:
Ralph Khreish
2025-11-07 22:24:30 +01:00
committed by GitHub
parent 7961ee74b7
commit e108f4310c
16 changed files with 44 additions and 67 deletions

View File

@@ -37,15 +37,12 @@ export class AnthropicAIProvider extends BaseAIProvider {
* @param {string} params.apiKey - Anthropic API key
* @param {string} [params.baseURL] - Optional custom API endpoint
* @returns {Function} Anthropic client function
* @throws {Error} If API key is missing or initialization fails
* @throws {Error} If initialization fails
*/
getClient(params) {
try {
const { apiKey, baseURL } = params;
if (!apiKey) {
throw new Error('Anthropic API key is required.');
}
const fetchImpl = this.createProxyFetch();
return createAnthropic({
apiKey,
@@ -53,7 +50,7 @@ export class AnthropicAIProvider extends BaseAIProvider {
headers: {
'anthropic-beta': 'output-128k-2025-02-19'
},
fetch: this.createProxyFetch()
...(fetchImpl && { fetch: fetchImpl })
});
} catch (error) {
this.handleError('client initialization', error);

View File

@@ -43,16 +43,17 @@ export class AzureProvider extends BaseAIProvider {
* @param {string} params.apiKey - Azure OpenAI API key
* @param {string} params.baseURL - Azure OpenAI endpoint URL (from .taskmasterconfig global.azureBaseURL or models.[role].baseURL)
* @returns {Function} Azure OpenAI client function
* @throws {Error} If required parameters are missing or initialization fails
* @throws {Error} If client initialization fails
*/
getClient(params) {
try {
const { apiKey, baseURL } = params;
const fetchImpl = this.createProxyFetch();
return createAzure({
apiKey,
baseURL,
fetch: this.createProxyFetch()
...(fetchImpl && { fetch: fetchImpl })
});
} catch (error) {
this.handleError('client initialization', error);

View File

@@ -35,10 +35,11 @@ export class BedrockAIProvider extends BaseAIProvider {
getClient(params) {
try {
const credentialProvider = fromNodeProviderChain();
const fetchImpl = this.createProxyFetch();
return createAmazonBedrock({
credentialProvider,
fetch: this.createProxyFetch()
...(fetchImpl && { fetch: fetchImpl })
});
} catch (error) {
this.handleError('client initialization', error);

View File

@@ -91,10 +91,8 @@ export class VertexAIProvider extends BaseAIProvider {
*/
getClient(params) {
try {
// Validate required parameters
this.validateAuth(params);
const { apiKey, projectId, location, credentials, baseURL } = params;
const fetchImpl = this.createProxyFetch();
// Configure auth options - either API key or service account
const authOptions = {};
@@ -110,7 +108,7 @@ export class VertexAIProvider extends BaseAIProvider {
projectId,
location,
...(baseURL && { baseURL }),
fetch: this.createProxyFetch()
...(fetchImpl && { fetch: fetchImpl })
});
} catch (error) {
this.handleError('client initialization', error);

View File

@@ -26,20 +26,17 @@ export class GoogleAIProvider extends BaseAIProvider {
* @param {string} params.apiKey - Google API key
* @param {string} [params.baseURL] - Optional custom API endpoint
* @returns {Function} Google AI client function
* @throws {Error} If API key is missing or initialization fails
* @throws {Error} If initialization fails
*/
getClient(params) {
try {
const { apiKey, baseURL } = params;
if (!apiKey) {
throw new Error('Google API key is required.');
}
const fetchImpl = this.createProxyFetch();
return createGoogleGenerativeAI({
apiKey,
...(baseURL && { baseURL }),
fetch: this.createProxyFetch()
...(fetchImpl && { fetch: fetchImpl })
});
} catch (error) {
this.handleError('client initialization', error);

View File

@@ -34,10 +34,6 @@ export class GroqProvider extends BaseAIProvider {
try {
const { apiKey, baseURL } = params;
if (!apiKey) {
throw new Error('Groq API key is required.');
}
return createGroq({
apiKey,
...(baseURL && { baseURL })

View File

@@ -96,19 +96,13 @@ export class OpenAICompatibleProvider extends BaseAIProvider {
getClient(params) {
try {
const { apiKey } = params;
// Validate API key if required
if (this.requiresApiKey && !apiKey) {
throw new Error(`${this.name} API key is required.`);
}
const fetchImpl = this.createProxyFetch();
const baseURL = this.getBaseURL(params);
const clientConfig = {
// Provider name for SDK (required, used for logging/debugging)
name: this.name.toLowerCase().replace(/[^a-z0-9]/g, '-'),
// Add proxy support
fetch: this.createProxyFetch()
name: this.name.toLowerCase().replace(/[^a-z0-9]/g, '-')
};
// Only include apiKey if provider requires it
@@ -126,6 +120,11 @@ export class OpenAICompatibleProvider extends BaseAIProvider {
clientConfig.supportsStructuredOutputs = this.supportsStructuredOutputs;
}
// Add proxy support if available
if (fetchImpl) {
clientConfig.fetch = fetchImpl;
}
return createOpenAICompatible(clientConfig);
} catch (error) {
this.handleError('client initialization', error);

View File

@@ -26,20 +26,17 @@ export class OpenAIProvider extends BaseAIProvider {
* @param {string} params.apiKey - OpenAI API key
* @param {string} [params.baseURL] - Optional custom API endpoint
* @returns {Function} OpenAI client function
* @throws {Error} If API key is missing or initialization fails
* @throws {Error} If initialization fails
*/
getClient(params) {
try {
const { apiKey, baseURL } = params;
if (!apiKey) {
throw new Error('OpenAI API key is required.');
}
const fetchImpl = this.createProxyFetch();
return createOpenAI({
apiKey,
...(baseURL && { baseURL }),
fetch: this.createProxyFetch()
...(fetchImpl && { fetch: fetchImpl })
});
} catch (error) {
this.handleError('client initialization', error);

View File

@@ -32,10 +32,6 @@ export class OpenRouterAIProvider extends BaseAIProvider {
try {
const { apiKey, baseURL } = params;
if (!apiKey) {
throw new Error('OpenRouter API key is required.');
}
return createOpenRouter({
apiKey,
...(baseURL && { baseURL })

View File

@@ -26,20 +26,17 @@ export class PerplexityAIProvider extends BaseAIProvider {
* @param {string} params.apiKey - Perplexity API key
* @param {string} [params.baseURL] - Optional custom API endpoint
* @returns {Function} Perplexity client function
* @throws {Error} If API key is missing or initialization fails
* @throws {Error} If initialization fails
*/
getClient(params) {
try {
const { apiKey, baseURL } = params;
if (!apiKey) {
throw new Error('Perplexity API key is required.');
}
const fetchImpl = this.createProxyFetch();
return createPerplexity({
apiKey,
baseURL: baseURL || 'https://api.perplexity.ai',
fetch: this.createProxyFetch()
...(fetchImpl && { fetch: fetchImpl })
});
} catch (error) {
this.handleError('client initialization', error);

View File

@@ -32,10 +32,6 @@ export class XAIProvider extends BaseAIProvider {
try {
const { apiKey, baseURL } = params;
if (!apiKey) {
throw new Error('xAI API key is required.');
}
return createXai({
apiKey,
baseURL: baseURL || 'https://api.x.ai/v1'

View File

@@ -175,16 +175,16 @@ describe('OpenAICompatibleProvider', () => {
expect(client).toBeDefined();
});
it('should throw error when API key is required but missing', () => {
it('should create client even when API key is required but missing (validation deferred to SDK)', () => {
const provider = new OpenAICompatibleProvider({
name: 'Test Provider',
apiKeyEnvVar: 'TEST_API_KEY',
requiresApiKey: true
});
expect(() => {
provider.getClient({});
}).toThrow('Test Provider API key is required.');
// getClient() no longer validates API key - validation is deferred to SDK initialization
const client = provider.getClient({});
expect(typeof client).toBe('function');
});
});
});

View File

@@ -85,8 +85,10 @@ describe('OpenAIProvider', () => {
});
describe('getClient', () => {
it('should throw error if API key is missing', () => {
expect(() => provider.getClient({})).toThrow(Error);
it('should create client even without API key (validation deferred to SDK)', () => {
// getClient() no longer validates API key - validation is deferred to SDK initialization
const client = provider.getClient({});
expect(typeof client).toBe('function');
});
it('should create client with apiKey only', () => {

View File

@@ -57,10 +57,10 @@ describe('ZAICodingProvider', () => {
// The provider should use the coding endpoint
});
it('should throw error when API key is missing', () => {
expect(() => {
provider.getClient({});
}).toThrow('Z.ai (Coding Plan) API key is required.');
it('should create client even without API key (validation deferred to SDK)', () => {
// getClient() no longer validates API key - validation is deferred to SDK initialization
const client = provider.getClient({});
expect(typeof client).toBe('function');
});
});

View File

@@ -55,10 +55,10 @@ describe('ZAIProvider', () => {
expect(client).toBeDefined();
});
it('should throw error when API key is missing', () => {
expect(() => {
provider.getClient({});
}).toThrow('Z.ai API key is required.');
it('should create client even without API key (validation deferred to SDK)', () => {
// getClient() no longer validates API key - validation is deferred to SDK initialization
const client = provider.getClient({});
expect(typeof client).toBe('function');
});
});

View File

@@ -70,13 +70,13 @@ const realSupportedModelsPath = path.resolve(
'../../scripts/modules/supported-models.json'
);
let REAL_SUPPORTED_MODELS_CONTENT;
let _REAL_SUPPORTED_MODELS_DATA;
let REAL_SUPPORTED_MODELS_DATA;
try {
REAL_SUPPORTED_MODELS_CONTENT = fs.readFileSync(
realSupportedModelsPath,
'utf-8'
);
_REAL_SUPPORTED_MODELS_DATA = JSON.parse(REAL_SUPPORTED_MODELS_CONTENT);
REAL_SUPPORTED_MODELS_DATA = JSON.parse(REAL_SUPPORTED_MODELS_CONTENT);
} catch (err) {
console.error(
'FATAL TEST SETUP ERROR: Could not read or parse real supported-models.json',