feat(llm): add DeepSeek V4 Pro/Flash as LLM provider

✅ merged · #9 · Edu-Carone-SA/mike ← Edu-Carone-SA/mike · opened 1mo ago by EduardoCarone · merged 1mo ago by EduardoCarone · self · +462-9 across 19 files · ↗ on GitHub

From the PR description

Summary

Adds DeepSeek V4 Pro and V4 Flash as a first-class LLM provider in Mike.

Changes

Backend:

  • New deepseek.ts adapter - Chat Completions API with streaming, tool calls, and thinking/reasoning support
  • models.ts - deepseek-v4-pro (main tier), deepseek-v4-flash (mid/low tier)
  • types.ts - deepseek added to Provider and UserApiKeys
  • index.ts - routing to DeepSeek adapter
  • env.ts - DEEPSEEK_API_KEY in Zod schema + provider key check
  • userApiKeys.ts - deepseek in ApiKeyProvider, PROVIDERS, envApiKey
  • userSettings.ts - DeepSeek considered in resolveTitleModel
  • user.ts route - DeepSeek in title fallback chain

Frontend:

  • ModelToggle.tsx - DeepSeek group with V4 Pro (main) and V4 Flash (settings)
  • modelAvailability.ts - deepseek in ModelProvider, providerLabel, modelGroupToProvider
  • mikeApi.ts - deepseek in ApiKeyProvider
  • api-keys/page.tsx - DeepSeek API key field
  • UserProfileContext.tsx - deepseek in providers list and emptyApiKeys
  • TabularReviewView.tsx - deepseek in provider validation array

Tests:

  • env.test.ts - DEEPSEEK_API_KEY cleanup in provider key test
  • logger.test.ts - DEEPSEEK_API_KEY in sensitive env vars list
  • env-isolation.test.ts - DEEPSEEK in forbidden name tokens

Docs:

  • ENVIRONMENT-VARIABLES.md - DEEPSEEK_API_KEY row
  • .env.example - DEEPSEEK_API_KEY= placeholder

Why a separate adapter?

DeepSeek API is OpenAI-compatible but uses Chat Completions API (/v1/chat/completions), not the Responses API (/v1/responses) that the existing openai.ts adapter uses. These are different endpoints with different request/response formats.

Test results

  • Backend typecheck: pass
  • Frontend typecheck: pass
  • Backend tests: 142 passed
  • Frontend tests: 85 passed
  • Backend lint: pass
  • Frontend lint: pass

Security

  • API key stored in .env (gitignored) and AWS Secrets Manager - never in Git
  • No secrets in diff (verified with grep)
  • Key is optional - app runs without it

Our analysis

Add DeepSeek as an LLM provider — read the full analysis →

Think the analysis missed something the PR description covers?

Capture this PR into my fork

Download a Markdown prompt that tells Claude how to port every commit in this PR into your working tree. Run it via claude -p < capture-pull-9.md from inside the repo you want the changes in.

⬇ Download capture-pull-9.md