Skip to content

Commit 72f80a2

Browse files
feat: Add explicit model provider configuration support
- Extended configuration system to support explicit model provider selection - Added environment variables for specifying providers per mode - Updated config parsing to handle mode-specific and global provider settings - Enhanced PatchClient to dynamically select model providers based on configuration - Updated .env.example and README with new provider configuration options - Implemented flexible provider detection logic with fallback mechanisms
1 parent 279f2c8 commit 72f80a2

File tree

5 files changed

+132
-3
lines changed

5 files changed

+132
-3
lines changed

.env.example

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ OPENROUTER_API_KEY=
3232
OPENAI_API_KEYS=key1,key2,key3
3333
ANTHROPIC_API_KEYS=key1,key2,key3
3434

35+
# Model provider configuration
36+
# Explicitly specify which provider to use (openai, anthropic, openrouter)
37+
# This overrides automatic detection based on model name
38+
PATCH_MODEL_PROVIDER=openai
39+
40+
# Mode-specific model providers (optional)
41+
PATCH_MODEL_PROVIDER_ARCHITECT=anthropic
42+
PATCH_MODEL_PROVIDER_PATCHER=openai
43+
PATCH_MODEL_PROVIDER_HYBRID_SECURITY=anthropic
44+
PATCH_MODEL_PROVIDER_HYBRID_PERFORMANCE=openai
45+
PATCH_MODEL_PROVIDER_HYBRID_TYPESCRIPT=openai
46+
3547
# Label that triggers patchmycode to fix an issue
3648
PATCH_TRIGGER_LABEL=fix:auto
3749
# Additional labels that can trigger fixes (comma-separated)

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,13 @@ Create a `.patchmycode/config.json` file in your repository to customize behavio
8181
},
8282
"modelMap": {
8383
"architect": "claude-3-7-sonnet",
84-
"patcher": "gpt-4o"
84+
"patcher": "gpt-4o",
85+
"hybrid:security": "claude-3-opus-20240229"
86+
},
87+
"providerMap": {
88+
"architect": "anthropic",
89+
"patcher": "openai",
90+
"hybrid:security": "anthropic"
8591
}
8692
}
8793
```
@@ -176,6 +182,14 @@ You can set models globally or per mode:
176182
- `PATCH_MODEL_HYBRID_PERFORMANCE`: Model for performance hybrid mode
177183
- `PATCH_MODEL_HYBRID_TYPESCRIPT`: Model for TypeScript hybrid mode
178184

185+
- **Model provider configuration**:
186+
- `PATCH_MODEL_PROVIDER`: Explicitly specify which provider to use (openai, anthropic, openrouter)
187+
- `PATCH_MODEL_PROVIDER_ARCHITECT`: Provider for architect mode
188+
- `PATCH_MODEL_PROVIDER_PATCHER`: Provider for patcher mode
189+
- `PATCH_MODEL_PROVIDER_HYBRID_SECURITY`: Provider for security hybrid mode
190+
- `PATCH_MODEL_PROVIDER_HYBRID_PERFORMANCE`: Provider for performance hybrid mode
191+
- `PATCH_MODEL_PROVIDER_HYBRID_TYPESCRIPT`: Provider for TypeScript hybrid mode
192+
179193
- **Model-specific arguments**:
180194
- `PATCH_EXTRA_ARGS`: Global extra arguments for Aider
181195
- `PATCH_EXTRA_ARGS_ARCHITECT`: Arguments specific to architect mode

example-aider-config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@
2828
"hybrid": "claude-3-opus",
2929
"default": "gpt-4o"
3030
},
31+
"providerMap": {
32+
"architect": "anthropic",
33+
"patcher": "openai",
34+
"hybrid:security": "anthropic",
35+
"hybrid:performance": "openai",
36+
"hybrid:typescript-migration": "openrouter",
37+
"default": "openai"
38+
},
3139
"systemPrompts": {
3240
"architect": "You are an expert software architect with deep knowledge of design patterns and software engineering principles. Focus on high-level design, refactoring, and code organization. Think about maintainability, extensibility, and adherence to SOLID principles. Prefer clear, modular designs over clever tricks.",
3341
"patcher": "You are an expert code editor with a keen eye for bugs and implementation details. Focus on fixing specific issues with minimal changes. Prioritize correctness, security, and performance in that order. Maintain the existing code style and patterns unless there's a compelling reason to change them.",

src/config.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ export interface PatchBotConfig {
1818
// LLM configuration
1919
model?: string; // Default LLM model to use
2020
extraArgs?: string[]; // Default additional arguments to pass to the LLM
21+
modelProvider?: string; // Default model provider to use (openai, anthropic, openrouter)
2122

2223
// Mode-specific LLM configuration
2324
modeModels?: Record<string, string>; // Mapping of modes to specific models
2425
modeExtraArgs?: Record<string, string[]>; // Mapping of modes to specific extra args
26+
modeProviders?: Record<string, string>; // Mapping of modes to specific providers
2527

2628
// API Keys configuration
2729
openaiKeys?: string[]; // OpenAI API keys for load balancing
@@ -147,6 +149,48 @@ const getModeExtraArgs = (): Record<string, string[]> => {
147149
return modeExtraArgs;
148150
};
149151

152+
// Create a map for mode-specific providers
153+
const getModeProviders = (): Record<string, string> => {
154+
const modeProviders: Record<string, string> = {};
155+
156+
// Check for default provider
157+
const defaultProvider = process.env.PATCH_MODEL_PROVIDER;
158+
if (defaultProvider) {
159+
// This will be the fallback for modes without specific providers
160+
modeProviders['default'] = defaultProvider.toLowerCase();
161+
}
162+
163+
// Check for architect mode provider
164+
const architectProvider = process.env.PATCH_MODEL_PROVIDER_ARCHITECT;
165+
if (architectProvider) {
166+
modeProviders['architect'] = architectProvider.toLowerCase();
167+
}
168+
169+
// Check for patcher mode provider
170+
const patcherProvider = process.env.PATCH_MODEL_PROVIDER_PATCHER;
171+
if (patcherProvider) {
172+
modeProviders['patcher'] = patcherProvider.toLowerCase();
173+
}
174+
175+
// Check for hybrid mode providers
176+
const securityProvider = process.env.PATCH_MODEL_PROVIDER_HYBRID_SECURITY;
177+
if (securityProvider) {
178+
modeProviders['hybrid:security'] = securityProvider.toLowerCase();
179+
}
180+
181+
const performanceProvider = process.env.PATCH_MODEL_PROVIDER_HYBRID_PERFORMANCE;
182+
if (performanceProvider) {
183+
modeProviders['hybrid:performance'] = performanceProvider.toLowerCase();
184+
}
185+
186+
const typescriptProvider = process.env.PATCH_MODEL_PROVIDER_HYBRID_TYPESCRIPT;
187+
if (typescriptProvider) {
188+
modeProviders['hybrid:typescript'] = typescriptProvider.toLowerCase();
189+
}
190+
191+
return modeProviders;
192+
};
193+
150194
// Get multiple API keys
151195
const getApiKeys = (): {
152196
openaiKeys: string[];
@@ -209,10 +253,12 @@ const config: PatchBotConfig = {
209253
// LLM configuration
210254
model: getEnv('PATCH_MODEL', 'gpt-4-turbo'),
211255
extraArgs: getArrayEnv('PATCH_EXTRA_ARGS'),
256+
modelProvider: getEnv('PATCH_MODEL_PROVIDER', ''),
212257

213258
// Mode-specific LLM configuration
214259
modeModels: getModeModels(),
215260
modeExtraArgs: getModeExtraArgs(),
261+
modeProviders: getModeProviders(),
216262

217263
// API Keys configuration
218264
...getApiKeys(),

src/patch.ts

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export interface PatchOptions {
2525
openaiKey?: string;
2626
anthropicKey?: string;
2727
openrouterKey?: string;
28+
modelProvider?: string;
2829
}
2930

3031
// Model provider interface for better abstraction
@@ -238,11 +239,12 @@ export class PatchClient {
238239
excludeFiles: options.excludeFiles || config.excludeFiles,
239240
openaiKey: options.openaiKey,
240241
anthropicKey: options.anthropicKey,
241-
openrouterKey: options.openrouterKey
242+
openrouterKey: options.openrouterKey,
243+
modelProvider: options.modelProvider || config.modelProvider
242244
};
243245

244246
// Create the appropriate model provider
245-
this.modelProvider = createModelProvider(this.options);
247+
this.modelProvider = this.getModelProvider();
246248
}
247249

248250
/**
@@ -319,6 +321,30 @@ export class PatchClient {
319321
* Get the model-specific provider for the current configuration
320322
*/
321323
private getModelProvider(): ModelProvider {
324+
// First check for explicitly configured provider
325+
const provider = this.getProviderForCurrentMode();
326+
327+
if (provider) {
328+
// Use explicitly configured provider
329+
switch (provider) {
330+
case 'anthropic':
331+
return new AnthropicProvider(
332+
this.options.anthropicKey,
333+
config.anthropicKeys
334+
);
335+
case 'openrouter':
336+
return new OpenRouterProvider(
337+
this.options.openrouterKey || config.openrouterKey
338+
);
339+
case 'openai':
340+
return new OpenAIProvider(
341+
this.options.openaiKey,
342+
config.openaiKeys
343+
);
344+
}
345+
}
346+
347+
// If no explicit provider, fall back to model name detection
322348
const modelName = this.getModelForCurrentMode();
323349

324350
if (modelName.includes('claude')) {
@@ -337,6 +363,29 @@ export class PatchClient {
337363
}
338364
}
339365

366+
/**
367+
* Get the provider for the current mode, prioritizing mode-specific settings
368+
*/
369+
private getProviderForCurrentMode(): string | undefined {
370+
// Check if we have mode-specific provider
371+
if (config.modeProviders && this.options.mode && config.modeProviders[this.options.mode]) {
372+
return config.modeProviders[this.options.mode];
373+
}
374+
375+
// Check for default provider in mode providers
376+
if (config.modeProviders && config.modeProviders['default']) {
377+
return config.modeProviders['default'];
378+
}
379+
380+
// Check for global provider
381+
if (this.options.modelProvider) {
382+
return this.options.modelProvider;
383+
}
384+
385+
// Finally check for config default
386+
return config.modelProvider;
387+
}
388+
340389
/**
341390
* Get the correct model for the current mode, prioritizing mode-specific settings
342391
*/

0 commit comments

Comments
 (0)