feat: Integrate CursorProvider into ProviderFactory

- Added CursorProvider to the ProviderFactory for handling cursor-* models.
- Updated getProviderNameForModel method to determine the appropriate provider based on model identifiers.
- Enhanced getAllProviders method to return both ClaudeProvider and CursorProvider.
- Updated documentation to reflect the completion of the Provider Factory integration phase.
This commit is contained in:
Shirone
2025-12-28 00:48:41 +01:00
parent d8dedf8e40
commit 6e9468a56e
4 changed files with 78 additions and 45 deletions

View File

@@ -0,0 +1,23 @@
/**
* Provider exports
*/
// Base provider
export { BaseProvider } from './base-provider.js';
export type {
ProviderConfig,
ExecuteOptions,
ProviderMessage,
InstallationStatus,
ModelDefinition,
} from './types.js';
// Claude provider
export { ClaudeProvider } from './claude-provider.js';
// Cursor provider
export { CursorProvider, CursorErrorCode, CursorError } from './cursor-provider.js';
export { CursorConfigManager } from './cursor-config-manager.js';
// Provider factory
export { ProviderFactory } from './provider-factory.js';

View File

@@ -8,33 +8,56 @@
import { BaseProvider } from './base-provider.js';
import { ClaudeProvider } from './claude-provider.js';
import type { InstallationStatus } from './types.js';
import { CursorProvider } from './cursor-provider.js';
import type { InstallationStatus, ModelDefinition } from './types.js';
import { CURSOR_MODEL_MAP } from '@automaker/types';
export class ProviderFactory {
/**
* Determine which provider to use for a given model
*
* @param model Model identifier
* @returns Provider name ('claude' | 'cursor')
*/
static getProviderNameForModel(model: string): 'claude' | 'cursor' {
const lowerModel = model.toLowerCase();
// Check for explicit cursor prefix
if (lowerModel.startsWith('cursor-')) {
return 'cursor';
}
// Check if it's a known Cursor model ID (without prefix)
const cursorModelId = lowerModel.replace('cursor-', '');
if (cursorModelId in CURSOR_MODEL_MAP) {
return 'cursor';
}
// Check for Claude model patterns
if (
lowerModel.startsWith('claude-') ||
['opus', 'sonnet', 'haiku'].some((n) => lowerModel.includes(n))
) {
return 'claude';
}
// Default to Claude
return 'claude';
}
/**
* Get the appropriate provider for a given model ID
*
* @param modelId Model identifier (e.g., "claude-opus-4-5-20251101", "gpt-5.2", "cursor-fast")
* @param modelId Model identifier (e.g., "claude-opus-4-5-20251101", "cursor-gpt-4o", "cursor-auto")
* @returns Provider instance for the model
*/
static getProviderForModel(modelId: string): BaseProvider {
const lowerModel = modelId.toLowerCase();
const providerName = this.getProviderNameForModel(modelId);
// Claude models (claude-*, opus, sonnet, haiku)
if (lowerModel.startsWith('claude-') || ['haiku', 'sonnet', 'opus'].includes(lowerModel)) {
return new ClaudeProvider();
if (providerName === 'cursor') {
return new CursorProvider();
}
// Future providers:
// if (lowerModel.startsWith("cursor-")) {
// return new CursorProvider();
// }
// if (lowerModel.startsWith("opencode-")) {
// return new OpenCodeProvider();
// }
// Default to Claude for unknown models
console.warn(`[ProviderFactory] Unknown model prefix for "${modelId}", defaulting to Claude`);
return new ClaudeProvider();
}
@@ -42,10 +65,7 @@ export class ProviderFactory {
* Get all available providers
*/
static getAllProviders(): BaseProvider[] {
return [
new ClaudeProvider(),
// Future providers...
];
return [new ClaudeProvider(), new CursorProvider()];
}
/**
@@ -80,11 +100,8 @@ export class ProviderFactory {
case 'anthropic':
return new ClaudeProvider();
// Future providers:
// case "cursor":
// return new CursorProvider();
// case "opencode":
// return new OpenCodeProvider();
case 'cursor':
return new CursorProvider();
default:
return null;
@@ -94,15 +111,8 @@ export class ProviderFactory {
/**
* Get all available models from all providers
*/
static getAllAvailableModels() {
static getAllAvailableModels(): ModelDefinition[] {
const providers = this.getAllProviders();
const allModels = [];
for (const provider of providers) {
const models = provider.getAvailableModels();
allModels.push(...models);
}
return allModels;
return providers.flatMap((p) => p.getAvailableModels());
}
}

View File

@@ -9,7 +9,7 @@
| 0 | [Analysis & Documentation](phases/phase-0-analysis.md) | `completed` | ✅ |
| 1 | [Core Types & Configuration](phases/phase-1-types.md) | `completed` | ✅ |
| 2 | [Cursor Provider Implementation](phases/phase-2-provider.md) | `completed` | ✅ |
| 3 | [Provider Factory Integration](phases/phase-3-factory.md) | `pending` | - |
| 3 | [Provider Factory Integration](phases/phase-3-factory.md) | `completed` | |
| 4 | [Setup Routes & Status Endpoints](phases/phase-4-routes.md) | `pending` | - |
| 5 | [Log Parser Integration](phases/phase-5-log-parser.md) | `pending` | - |
| 6 | [UI Setup Wizard](phases/phase-6-setup-wizard.md) | `pending` | - |

View File

@@ -1,6 +1,6 @@
# Phase 3: Provider Factory Integration
**Status:** `pending`
**Status:** `completed`
**Dependencies:** Phase 2 (Provider)
**Estimated Effort:** Small (routing logic only)
@@ -16,7 +16,7 @@ Integrate CursorProvider into the ProviderFactory so models are automatically ro
### Task 3.1: Update Provider Factory
**Status:** `pending`
**Status:** `completed`
**File:** `apps/server/src/providers/provider-factory.ts`
@@ -132,7 +132,7 @@ export class ProviderFactory {
### Task 3.2: Export CursorProvider
**Status:** `pending`
**Status:** `completed`
**File:** `apps/server/src/providers/index.ts`
@@ -203,13 +203,13 @@ console.log('Total models:', allModels.length);
Before marking this phase complete:
- [ ] ProviderFactory routes `cursor-*` models to CursorProvider
- [ ] ProviderFactory routes Claude models to ClaudeProvider
- [ ] `getAllProviders()` returns both providers
- [ ] `getProviderByName('cursor')` returns CursorProvider
- [ ] `checkAllProviders()` returns status for both providers
- [ ] `getAllAvailableModels()` includes Cursor models
- [ ] Existing Claude routing not broken
- [x] ProviderFactory routes `cursor-*` models to CursorProvider
- [x] ProviderFactory routes Claude models to ClaudeProvider
- [x] `getAllProviders()` returns both providers
- [x] `getProviderByName('cursor')` returns CursorProvider
- [x] `checkAllProviders()` returns status for both providers
- [x] `getAllAvailableModels()` includes Cursor models
- [x] Existing Claude routing not broken
---