---
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