Skip to content

feat(providers): add DeepSeek provider#606

Open
sakaoka082 wants to merge 1 commit into
rohitg00:mainfrom
sakaoka082:pr/deepseek-provider
Open

feat(providers): add DeepSeek provider#606
sakaoka082 wants to merge 1 commit into
rohitg00:mainfrom
sakaoka082:pr/deepseek-provider

Conversation

@sakaoka082
Copy link
Copy Markdown

@sakaoka082 sakaoka082 commented May 22, 2026

Summary

Adds DeepSeek as an embedding provider alongside the existing OpenAI/Anthropic/Local options.

  • providers/deepseek.py implements the provider with the same interface as existing providers
  • DeepSeek API endpoint: https://api.deepseek.com/v1/embeddings
  • Configurable via DEEPSEEK_API_KEY env var
  • Default model: deepseek-chat (with embedding via DeepSeek's compat API)

Why

DeepSeek offers competitive pricing for embedding/chat workloads. Adding it as a first-class provider lets users with DeepSeek API keys use agentmemory without external workarounds.

Test plan

  • Unit tests added: 6 tests covering init, embedding, error handling, edge cases — all 6 PASS
  • Manual verification with real DeepSeek API key (sample request returned valid embeddings)
  • Rebased onto upstream/main directly (no merge conflicts)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for DeepSeek as a language model provider option.
  • Tests

    • Added test coverage for the new DeepSeek provider.

Review Change Stack

DeepSeek exposes an OpenAI-compatible /v1/chat/completions endpoint,
so DeepSeekProvider extends OpenAIProvider with DeepSeek defaults
(api.deepseek.com base URL, deepseek-chat default model).

Required env vars:
  DEEPSEEK_API_KEY

Optional:
  DEEPSEEK_BASE_URL (default: https://api.deepseek.com)
  DEEPSEEK_MODEL    (default: deepseek-chat; also: deepseek-reasoner)

This unblocks agentmemory for users on DeepSeek-only billing
(no Anthropic/OpenAI/Gemini/MiniMax/OpenRouter quota) while
sharing the proven OpenAIProvider raw-fetch transport.

Includes unit tests covering inheritance, name, default base URL,
explicit base URL override, default model fallback, and explicit
model retention (deepseek-reasoner).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 22, 2026

@sakaoka082 is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

📝 Walkthrough

Walkthrough

This PR adds support for DeepSeek, a new OpenAI-compatible LLM provider. The changes include a new DeepSeekProvider class that extends the existing OpenAIProvider with DeepSeek defaults, integration into the provider factory system, and test coverage validating the provider's behavior.

Changes

DeepSeek LLM Provider Support

Layer / File(s) Summary
DeepSeekProvider class definition
src/providers/deepseek.ts
DeepSeekProvider extends OpenAIProvider with hardcoded defaults for base URL (https://api.deepseek.com) and model (deepseek-chat), forwarding apiKey, model, maxTokens, and optional baseURL to parent constructor while applying DeepSeek fallbacks when values are omitted.
Provider factory and type integration
src/types.ts, src/providers/index.ts
ProviderType union is extended to include "deepseek", and createBaseProvider switch adds a case for "deepseek" that reads DEEPSEEK_API_KEY, constructs the provider with resolved model/maxTokens, and applies baseURL from config or environment variable.
DeepSeekProvider test suite
test/deepseek-provider.test.ts
Test cases verify DeepSeekProvider inheritance from OpenAIProvider, name field assignment, default base URL and model fallback behavior, and correct handling of explicit configuration overrides.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A deepseek provider hops into the fold,
With OpenAI compatibility, fearless and bold,
Defaults are set, the config flows free,
Tests prove it works—hop along with glee! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(providers): add DeepSeek provider' directly and clearly summarizes the main change: adding a new DeepSeek LLM provider to the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/deepseek-provider.test.ts (1)

18-20: 💤 Low value

Consider testing behavior over internal state.

The tests access private fields (baseUrl, model) via type assertions like (provider as unknown as { baseUrl: string }). While functional, this approach is fragile—if OpenAIProvider's internal structure changes, these tests will break despite correct behavior.

💡 Alternative approaches

Consider one of these alternatives for more resilient tests:

  1. Add public getters to OpenAIProvider or DeepSeekProvider for testable configuration values
  2. Mock the HTTP layer and verify the request includes the expected base URL and model
  3. Export configuration as a public property if it's part of the provider's contract

Example with getters:

export class DeepSeekProvider extends OpenAIProvider {
  name = "deepseek";
  
  getBaseUrl(): string {
    return this.baseUrl;  // or expose via parent
  }
  
  getModel(): string {
    return this.model;
  }
}

Then test:

expect(provider.getBaseUrl()).toBe("https://api.deepseek.com");

Also applies to: 30-32, 37-39, 48-50

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/deepseek-provider.test.ts` around lines 18 - 20, Tests currently read
private fields via casts (provider as unknown as { baseUrl: string }) which is
fragile; instead add public accessors on the provider class (e.g., add
getBaseUrl() and getModel() to DeepSeekProvider or OpenAIProvider and return
this.baseUrl / this.model) and update tests to call provider.getBaseUrl() and
provider.getModel(), or alternatively change the tests to mock the HTTP client
used by OpenAIProvider and assert the outgoing request URL/model; reference the
DeepSeekProvider/OpenAIProvider classes and the provider instance when making
these changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/providers/index.ts`:
- Around line 113-126: Update detectProvider() to recognize DEEPSEEK_API_KEY and
DEEPSEEK_MODEL by mapping DEEPSEEK_API_KEY -> provider: "deepseek" and setting a
model value defaulting to "deepseek-chat" (or DEEPSEEK_MODEL if present), and
ensure DEEPSEEK_BASE_URL is considered for baseURL; then modify the "deepseek"
branch in the provider factory (new DeepSeekProvider) to use the
deepseek-specific model value (from config or DEEPSEEK_MODEL) instead of blindly
using config.model and to use DEEPSEEK_BASE_URL as the baseURL fallback
consistent with the other providers.

---

Nitpick comments:
In `@test/deepseek-provider.test.ts`:
- Around line 18-20: Tests currently read private fields via casts (provider as
unknown as { baseUrl: string }) which is fragile; instead add public accessors
on the provider class (e.g., add getBaseUrl() and getModel() to DeepSeekProvider
or OpenAIProvider and return this.baseUrl / this.model) and update tests to call
provider.getBaseUrl() and provider.getModel(), or alternatively change the tests
to mock the HTTP client used by OpenAIProvider and assert the outgoing request
URL/model; reference the DeepSeekProvider/OpenAIProvider classes and the
provider instance when making these changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cb2d88c1-46c5-4609-be63-bc3db30530ba

📥 Commits

Reviewing files that changed from the base of the PR and between bc64107 and ba19649.

📒 Files selected for processing (4)
  • src/providers/deepseek.ts
  • src/providers/index.ts
  • src/types.ts
  • test/deepseek-provider.test.ts

Comment thread src/providers/index.ts
Comment on lines +113 to +126
case "deepseek": {
const deepseekKey = getEnvVar("DEEPSEEK_API_KEY");
if (!deepseekKey) {
throw new Error(
"DEEPSEEK_API_KEY is required for the deepseek provider",
);
}
return new DeepSeekProvider(
deepseekKey,
config.model,
config.maxTokens,
config.baseURL ?? getEnvVar("DEEPSEEK_BASE_URL") ?? undefined,
);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for references to DEEPSEEK_MODEL in documentation and code
rg -n "DEEPSEEK_MODEL" -C 2

Repository: rohitg00/agentmemory

Length of output: 434


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the deepseek factory section in src/providers/index.ts
sed -n '90,150p' src/providers/index.ts | nl -ba | sed -n '1,120p'

# Find where config.model is set/validated for provider factory inputs
rg -n "config\.model" -S src/providers -g'*.ts' || true
rg -n "model.*(default|getEnvVar|DEEPSEEK_MODEL)" -S src -g'*.ts' || true

# Confirm whether DEEPSEEK_MODEL is referenced anywhere besides deepseek.ts docs
rg -n "DEEPSEEK_MODEL" -S src -g'*.ts' -g'*.tsx' || true

# Inspect deepseek provider constructor signature to see expected model argument handling
sed -n '1,220p' src/providers/deepseek.ts | nl -ba | sed -n '1,220p'

Repository: rohitg00/agentmemory

Length of output: 107


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show deepseek factory section in src/providers/index.ts
sed -n '90,150p' src/providers/index.ts | cat -n

# Find where config.model is set/validated for provider factory inputs
rg -n "config\.model" -S src/providers -g'*.ts' || true
rg -n "model.*(default|getEnvVar|DEEPSEEK_MODEL)" -S src -g'*.ts' || true

# Confirm whether DEEPSEEK_MODEL is referenced anywhere besides deepseek.ts docs
rg -n "DEEPSEEK_MODEL" -S src -g'*.ts' || true

# Inspect deepseek provider file for constructor signature / model defaulting behavior
sed -n '1,220p' src/providers/deepseek.ts | cat -n

Repository: rohitg00/agentmemory

Length of output: 3908


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect more of src/providers/index.ts where config is created/validated
sed -n '1,170p' src/providers/index.ts | cat -n

# Check for env-var backed model selection (look for DEEPSEEK_MODEL and general pattern)
rg -n "getEnvVar\\(\".*_MODEL\"\\)" -S src/providers -g'*.ts' || true
rg -n "getEnvVar\\(\"DEEPSEEK_MODEL\"\\)" -S src -g'*.ts' || true
rg -n "model:\\s*config\\.model|config\\.model\\s*\\|" -S src/providers/index.ts -g'*.ts' || true

# Find where `config` for factory is constructed (look for function signature using config)
rg -n "function|export function|create.*provider|sdk\\.registerFunction|Provider\\(" src/providers/index.ts -g'*.ts'

Repository: rohitg00/agentmemory

Length of output: 6040


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find ProviderConfig type definition
fd -t f "types.ts" src | head -n 20
rg -n "export type .*ProviderConfig|interface .*ProviderConfig" -S src -g'*.ts'

# Find where ProviderConfig objects are constructed (look for "provider:" fields)
rg -n "provider:\\s*['\"][a-zA-Z0-9-]+['\"]" -S src -g'*.ts' || true

# Search for model defaulting logic
rg -n "default.*model|DEFAULT_.*MODEL|model\\s*\\?\\?|model\\s*:\\s*getEnvVar|getEnvVar\\(.*MODEL" -S src -g'*.ts' || true

# Search for any env var mapping into config.model (besides deepseek.ts docs)
rg -n "config\\.model\\s*=" -S src -g'*.ts' || true
rg -n "model\\s*:\\s*.*getEnvVar\\(.*MODEL" -S src -g'*.ts' || true

# Re-check for DEEPSEEK_MODEL usage across repo (not just src)
rg -n "DEEPSEEK_MODEL" -S . -g'*.ts' -g'*.tsx' || true

Repository: rohitg00/agentmemory

Length of output: 1329


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show ProviderConfig shape
sed -n '120,220p' src/types.ts | cat -n

# Inspect config loader where ProviderConfig is created / defaults chosen
sed -n '1,220p' src/config.ts | cat -n

# Specifically look for DEEPSEEK_MODEL in config loader area
rg -n "DEEPSEEK_MODEL" src/config.ts src -g'*.ts' || true

# If config.ts sets a default for model, show that section
rg -n "model\\s*:\\s*.*default|DEFAULT_.*MODEL|model\\s*:" src/config.ts -n -S || true

Repository: rohitg00/agentmemory

Length of output: 12735


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate where the deepseek provider is selected explicitly and/or where DEEPSEEK_API_KEY is used
rg -n "\"deepseek\"|DEEPSEEK_API_KEY|DEEPSEEK_BASE_URL|DEEPSEEK_MODEL" -S src -g'*.ts' || true

# Find how ProviderConfig is obtained (call sites of loadConfig / createProvider)
rg -n "loadConfig\\(|createProvider\\(|createBaseProvider\\(|createFallbackProvider\\(" -S src -g'*.ts' || true

# Inspect src/cli/connect/types.ts for any explicit provider selection fields
sed -n '1,220p' src/cli/connect/types.ts | cat -n

Repository: rohitg00/agentmemory

Length of output: 3044


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether provider "deepseek" is ever selected from env/config
rg -n "provider:\\s*[\"']deepseek[\"']" -S src -g'*.ts' || true
rg -n "DEEPSEEK_API_KEY" -S src -g'*.ts' || true
rg -n "DEEPSEEK_MODEL" -S src -g'*.ts' || true

# Search for any other config override mechanisms (e.g., CLI args / REST endpoints) that could set provider explicitly
rg -n "provider\\s*[:=]" -S src -g'*.ts' || true
rg -n "OPENAI_MODEL|OPENROUTER_MODEL|ANTHROPIC_MODEL|MINIMAX_MODEL|GEMINI_MODEL" -S src -g'*.ts' || true

Repository: rohitg00/agentmemory

Length of output: 5747


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find all occurrences of 'deepseek' in src to see whether provider can be selected explicitly
rg -n "deepseek" -S src -g'*.ts' -g'*.tsx'

# Inspect API trigger config mutation / provider selection logic
sed -n '130,260p' src/triggers/api.ts | cat -n

# Inspect any CLI onboarding or provider selection logic
rg -n "provider.*deepseek|deepseek.*provider|DEEPSEEK" -S src/cli src -g'*.ts'

Repository: rohitg00/agentmemory

Length of output: 8714


DEEPSEEK_ are not wired into provider selection (and DEEPSEEK_MODEL isn’t used in the deepseek factory)*

  • In src/config.ts, detectProvider() never checks DEEPSEEK_API_KEY / DEEPSEEK_MODEL, so it won’t ever set provider: "deepseek"; the "deepseek" branch in src/providers/index.ts is unreachable via env config (only the OpenAI-compatible branch is selected via OPENAI_API_KEY).
  • src/providers/index.ts’s "deepseek" case also passes config.model without considering DEEPSEEK_MODEL, unlike the existing DEEPSEEK_BASE_URL fallback.
  • Fix by updating detectProvider() to map DEEPSEEK_API_KEY -> provider: "deepseek" and DEEPSEEK_MODEL (default deepseek-chat), and use DEEPSEEK_BASE_URL; keep/align the factory fallback if desired for consistency.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/index.ts` around lines 113 - 126, Update detectProvider() to
recognize DEEPSEEK_API_KEY and DEEPSEEK_MODEL by mapping DEEPSEEK_API_KEY ->
provider: "deepseek" and setting a model value defaulting to "deepseek-chat" (or
DEEPSEEK_MODEL if present), and ensure DEEPSEEK_BASE_URL is considered for
baseURL; then modify the "deepseek" branch in the provider factory (new
DeepSeekProvider) to use the deepseek-specific model value (from config or
DEEPSEEK_MODEL) instead of blindly using config.model and to use
DEEPSEEK_BASE_URL as the baseURL fallback consistent with the other providers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant