Component
New LLM provider or task
What problem does this solve?
Right now the only LLM options are OpenAI, Gemini, and Claude (llm/factory.py). All three are solid but none of them are cheap, and resume tailoring is a task where people iterate a lot — scan a posting, generate a resume, not happy with it, regenerate, generate a cover letter, tweak a field answer, repeat for the next job. That adds up in API spend pretty fast if you're job hunting seriously and applying to a lot of places.
DeepSeek's API is dramatically cheaper than GPT/Claude-class models for this kind of text rewriting task, while still being good enough quality-wise for rephrasing bullet points and matching a job description's language. Feels like a natural provider to support for anyone who's cost-sensitive rather than trying to get the absolute best possible phrasing.
Proposed solution
Add DeepSeek as a fourth provider option, following the same shape as the existing three:
- New
server/app/llm/deepseek_provider.py implementing the LlmProvider ABC (test_connection, list_models, generate_json, generate_text). DeepSeek's chat completions API is OpenAI-compatible, so this should be able to reuse most of the request/response handling from openai_provider.py — mainly just a different base URL and model list.
- Register it in
llm/factory.py::get_llm_provider.
- Add
"deepseek" to the ProviderName literal in schemas.py.
- Add the prompt files for all four generation tasks under
server/app/prompts/deepseek/ (job_scan, tailored_resume, cover_letter, field_answer — each needs both a .system.md and .user.md). Missing one of these doesn't fail at startup, it blows up with a FileNotFoundError the first time someone hits that task, so this is easy to half-finish without noticing.
- Extension side: add
"deepseek" to ProviderName in shared/apiClient.ts and to the PROVIDERS list in sidepanel/SettingsView.tsx so it shows up in Settings.
Alternatives considered
Could point people at DeepSeek through an OpenAI-compatible custom base URL instead of a dedicated provider, but that's a bigger change to the settings UI/schema (provider becomes "openai-compatible + arbitrary endpoint" instead of a fixed list) and mixes together providers with meaningfully different auth/quirks. Filing this as its own scoped provider addition for now — a more generic "bring your own OpenAI-compatible endpoint" mode could be a separate follow-up issue if there's appetite for it.
Additional context
If you're picking this up with Claude Code or another AI coding assistant, there's an add-llm-task-or-provider skill in .claude/skills/ that walks through this exact flow and specifically calls out the missing-prompt-file trap mentioned above — worth using it rather than copy-pasting the OpenAI provider by hand and forgetting a file.
Happy to open a PR for this myself if the general direction sounds right — mainly wanted to check that a fourth provider (vs. a more generic custom-endpoint approach) is the preferred direction before investing the time, per the contributing guide's guidance on larger changes.
Component
New LLM provider or task
What problem does this solve?
Right now the only LLM options are OpenAI, Gemini, and Claude (
llm/factory.py). All three are solid but none of them are cheap, and resume tailoring is a task where people iterate a lot — scan a posting, generate a resume, not happy with it, regenerate, generate a cover letter, tweak a field answer, repeat for the next job. That adds up in API spend pretty fast if you're job hunting seriously and applying to a lot of places.DeepSeek's API is dramatically cheaper than GPT/Claude-class models for this kind of text rewriting task, while still being good enough quality-wise for rephrasing bullet points and matching a job description's language. Feels like a natural provider to support for anyone who's cost-sensitive rather than trying to get the absolute best possible phrasing.
Proposed solution
Add DeepSeek as a fourth provider option, following the same shape as the existing three:
server/app/llm/deepseek_provider.pyimplementing theLlmProviderABC (test_connection,list_models,generate_json,generate_text). DeepSeek's chat completions API is OpenAI-compatible, so this should be able to reuse most of the request/response handling fromopenai_provider.py— mainly just a different base URL and model list.llm/factory.py::get_llm_provider."deepseek"to theProviderNameliteral inschemas.py.server/app/prompts/deepseek/(job_scan,tailored_resume,cover_letter,field_answer— each needs both a.system.mdand.user.md). Missing one of these doesn't fail at startup, it blows up with aFileNotFoundErrorthe first time someone hits that task, so this is easy to half-finish without noticing."deepseek"toProviderNameinshared/apiClient.tsand to thePROVIDERSlist insidepanel/SettingsView.tsxso it shows up in Settings.Alternatives considered
Could point people at DeepSeek through an OpenAI-compatible custom base URL instead of a dedicated provider, but that's a bigger change to the settings UI/schema (provider becomes "openai-compatible + arbitrary endpoint" instead of a fixed list) and mixes together providers with meaningfully different auth/quirks. Filing this as its own scoped provider addition for now — a more generic "bring your own OpenAI-compatible endpoint" mode could be a separate follow-up issue if there's appetite for it.
Additional context
If you're picking this up with Claude Code or another AI coding assistant, there's an
add-llm-task-or-providerskill in.claude/skills/that walks through this exact flow and specifically calls out the missing-prompt-file trap mentioned above — worth using it rather than copy-pasting the OpenAI provider by hand and forgetting a file.Happy to open a PR for this myself if the general direction sounds right — mainly wanted to check that a fourth provider (vs. a more generic custom-endpoint approach) is the preferred direction before investing the time, per the contributing guide's guidance on larger changes.