---
phase: 01-provider-infrastructure
plan: 02
type: execute
---
Create provider abstraction layer defining how providers expose model discovery and generation capabilities.
Purpose: Establish the interface contract that all providers (Gemini, Replicate, fal.ai) will implement, enabling uniform access to different AI services.
Output: Provider abstraction interfaces and types in src/lib/providers/ ready for implementation in Phase 2.
~/.claude/get-shit-done/workflows/execute-phase.md
~/.claude/get-shit-done/templates/summary.md
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
**Prior plan context:**
Plan 01-01 added ProviderType, ProviderConfig, and ProviderSettings types.
**Key files:**
@src/types/index.ts
@src/app/api/generate/route.ts
**Established patterns:**
- Feature libraries in `src/lib/{feature}/` (see quickstart/)
- Types defined with PascalCase interfaces
- Prefer fetch over SDKs per PROJECT.md constraints
**Constraints:**
- No hardcoded schemas - model parameters fetched at runtime
- Fetch over SDKs for bundle size
- Dynamic model discovery for future-proofing
Task 1: Create provider abstraction interfaces
src/lib/providers/types.ts
Create `src/lib/providers/` directory and `types.ts` with provider abstractions:
1. `ProviderModel` interface - represents a model from any provider:
```typescript
interface ProviderModel {
id: string; // Provider-specific model ID (e.g., "stability-ai/sdxl")
name: string; // Display name
description: string | null; // Model description
provider: ProviderType; // Which provider this is from
capabilities: ModelCapability[]; // What it can do
coverImage?: string; // Thumbnail URL
pricing?: { // Optional pricing info
type: "per-run" | "per-second";
amount: number;
currency: string;
};
}
```
2. `ModelCapability` union:
```typescript
type ModelCapability = "text-to-image" | "image-to-image" | "text-to-video" | "image-to-video";
```
3. `GenerationInput` interface - unified input for all providers:
```typescript
interface GenerationInput {
model: ProviderModel;
prompt: string;
images?: string[]; // Base64 data URLs or HTTP URLs
parameters?: Record; // Model-specific params
}
```
4. `GenerationOutput` interface:
```typescript
interface GenerationOutput {
success: boolean;
outputs?: Array<{
type: "image" | "video";
data: string; // Base64 data URL
url?: string; // Original URL if applicable
}>;
error?: string;
}
```
5. `ProviderInterface` - contract all providers implement:
```typescript
interface ProviderInterface {
id: ProviderType;
name: string;
// Model discovery
listModels(): Promise;
getModel(modelId: string): Promise;
searchModels(query: string): Promise;
// Generation
generate(input: GenerationInput): Promise;
// Utilities
isConfigured(): boolean; // Check if API key is set
getApiKey(): string | null;
}
```
Import ProviderType from "@/types".
Export all interfaces and types.
npm run build passes, types can be imported from "@/lib/providers/types"
Provider abstraction interfaces defined in src/lib/providers/types.ts
Task 2: Create provider registry and factory
src/lib/providers/index.ts
Create provider registry that will be populated by specific provider implementations in Phase 2:
1. Create `src/lib/providers/index.ts` with:
2. Export all types from types.ts:
```typescript
export * from "./types";
```
3. Provider registry (empty for now, filled in Phase 2):
```typescript
import { ProviderType } from "@/types";
import { ProviderInterface } from "./types";
// Registry populated by provider implementations
const providerRegistry: Partial> = {};
export function registerProvider(provider: ProviderInterface): void {
providerRegistry[provider.id] = provider;
}
export function getProvider(id: ProviderType): ProviderInterface | undefined {
return providerRegistry[id];
}
export function getConfiguredProviders(): ProviderInterface[] {
return Object.values(providerRegistry).filter(
(p): p is ProviderInterface => p !== undefined && p.isConfigured()
);
}
export function getAllProviders(): ProviderInterface[] {
return Object.values(providerRegistry).filter(
(p): p is ProviderInterface => p !== undefined
);
}
```
4. Add JSDoc comments explaining:
- Registry will be populated when provider modules are imported
- Phase 2 will add Replicate and fal.ai implementations
- Gemini implementation is special-cased in existing generate route for now
This creates the foundation without implementing actual providers yet.
npm run build passes, registry functions can be imported from "@/lib/providers"
Provider registry and factory functions exist in src/lib/providers/index.ts
Before declaring plan complete:
- [ ] `npm run build` succeeds without errors
- [ ] `npm run lint` passes
- [ ] src/lib/providers/types.ts exists with all interfaces
- [ ] src/lib/providers/index.ts exports types and registry functions
- [ ] Types can be imported: `import { ProviderModel, ProviderInterface } from "@/lib/providers"`
- All tasks completed
- All verification checks pass
- No TypeScript errors
- Provider abstraction layer ready for Phase 2 implementations
- Phase 1 complete