--- phase: 02-model-discovery plan: 01 type: execute --- Implement Replicate provider with model discovery from their REST API. Purpose: Enable dynamic fetching of available models from Replicate's API, normalized to our ProviderModel interface. Output: Working Replicate provider that registers in the provider system and an API route for client access. ~/.claude/get-shit-done/workflows/execute-phase.md ~/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/02-model-discovery/DISCOVERY.md # Prior phase context: @.planning/phases/01-provider-infrastructure/01-02-SUMMARY.md # Key files: @src/lib/providers/types.ts @src/lib/providers/index.ts @src/types/index.ts **Tech stack available:** - Provider abstraction interfaces (ProviderInterface, ProviderModel) - Provider registry with registerProvider() - ProviderType includes "replicate" **Established patterns:** - Provider types in src/lib/providers/types.ts - Self-registration via registerProvider() - API routes return { success, error, data } JSON **Constraining decisions:** - No SDKs - use direct fetch calls - API keys from localStorage via provider settings Task 1: Create Replicate provider implementation src/lib/providers/replicate.ts Create Replicate provider implementing ProviderInterface: 1. Import types from @/lib/providers and @/types 2. Implement helper function to get API key from localStorage (client) or return null (server) 3. Implement listModels(): - Fetch GET https://api.replicate.com/v1/models with Bearer auth - Map results to ProviderModel[] (id: `${owner}/${name}`, name, description, provider: "replicate", coverImage: cover_image_url) - Infer capabilities from model name/description (text-to-image default, add image-to-image if "img2img" in name/description) - Return first page only (no pagination traversal) 4. Implement searchModels(query): - Fetch GET https://api.replicate.com/v1/search?query={query} with Bearer auth - Map and return results same as listModels 5. Implement getModel(modelId): - Parse modelId as owner/name - Fetch GET https://api.replicate.com/v1/models/{owner}/{name} - Map single result to ProviderModel 6. Implement generate() as stub returning { success: false, error: "Not implemented" } (Phase 3) 7. Implement isConfigured() checking if API key exists 8. Implement getApiKey() returning key from localStorage or null 9. Call registerProvider(replicateProvider) at module level Note: This runs client-side for isConfigured/getApiKey but API calls will be proxied through API route. TypeScript compiles without errors: npx tsc --noEmit replicate.ts exports working provider, registered in registry when imported Task 2: Create Replicate models API route src/app/api/providers/replicate/models/route.ts Create Next.js API route for fetching Replicate models server-side: 1. Export GET handler 2. Get API key from request header or query param (client passes it) 3. Validate API key exists, return 401 if missing 4. Parse optional `search` query param 5. If search param: - Fetch https://api.replicate.com/v1/search?query={search} 6. Else: - Fetch https://api.replicate.com/v1/models 7. Both calls use Authorization: Bearer {apiKey} 8. Map response to ProviderModel[] using same logic as provider 9. Return { success: true, models: ProviderModel[] } 10. Handle errors: return { success: false, error: message } Pattern to follow from existing generate route: - Use NextRequest, NextResponse - Log request ID for debugging - Handle fetch errors gracefully curl -X GET "http://localhost:3000/api/providers/replicate/models" -H "X-API-Key: test" returns JSON (will error without real key, but route responds) API route returns model list when called with valid API key, 401 without key Before declaring plan complete: - [ ] `npx tsc --noEmit` passes - [ ] `npm run build` succeeds - [ ] Replicate provider file exists and exports provider - [ ] API route file exists at correct path - [ ] Provider registers when module is imported - Replicate provider implements ProviderInterface - Provider self-registers via registerProvider() - API route proxies model fetching with API key from header - Models normalized to ProviderModel interface - No TypeScript errors After completion, create `.planning/phases/02-model-discovery/02-01-SUMMARY.md` following the summary template.