4.7 KiB
| phase | plan | type |
|---|---|---|
| 02-model-discovery | 1 | execute |
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.
<execution_context> ~/.claude/get-shit-done/workflows/execute-phase.md ~/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/02-model-discovery/DISCOVERY.mdPrior 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
- Import types from @/lib/providers and @/types
- Implement helper function to get API key from localStorage (client) or return null (server)
- 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)
- Implement searchModels(query):
- Fetch GET https://api.replicate.com/v1/search?query={query} with Bearer auth
- Map and return results same as listModels
- Implement getModel(modelId):
- Parse modelId as owner/name
- Fetch GET https://api.replicate.com/v1/models/{owner}/{name}
- Map single result to ProviderModel
- Implement generate() as stub returning { success: false, error: "Not implemented" } (Phase 3)
- Implement isConfigured() checking if API key exists
- Implement getApiKey() returning key from localStorage or null
- 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:- Export GET handler
- Get API key from request header or query param (client passes it)
- Validate API key exists, return 401 if missing
- Parse optional
searchquery param - If search param:
- Else:
- Both calls use Authorization: Bearer {apiKey}
- Map response to ProviderModel[] using same logic as provider
- Return { success: true, models: ProviderModel[] }
- 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
<success_criteria>
- 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 </success_criteria>