--- 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 After completion, create `.planning/phases/01-provider-infrastructure/01-02-SUMMARY.md` Include in summary: - Phase 1 complete, ready for Phase 2: Model Discovery