Skip to content

feat(ai): add DeepSeek provider with session support and tests#67

Closed
regulusleow wants to merge 12 commits intotickernelz:mainfrom
regulusleow:feat/deepseek-support
Closed

feat(ai): add DeepSeek provider with session support and tests#67
regulusleow wants to merge 12 commits intotickernelz:mainfrom
regulusleow:feat/deepseek-support

Conversation

@regulusleow
Copy link
Copy Markdown

@regulusleow regulusleow commented Mar 18, 2026

Add DeepSeek provider support

Adds DeepSeek (https://api-docs.deepseek.com/) as a supported AI provider for auto-capture and user profile learning.

What's changed

  • New provider DeepSeekProvider — implements BaseAIProvider with full session support (multi-turn conversation history via AISessionManager)
  • OpenAI-compatible API — DeepSeek uses the Chat Completions format, so the implementation follows the same pattern as openai-chat
  • Type registration — "deepseek" added to AIProviderType, memoryProvider config interface, and AIProviderFactory
  • Config template — updated CONFIG_TEMPLATE with DeepSeek provider comment and example (memoryApiUrl is required)
  • Typed response interfaces — replaced the unused ToolCallResponse interface with three focused typed interfaces: DeepSeekToolCall, DeepSeekErrorResponse, and DeepSeekResponse
  • 16 unit tests covering: provider name, session support, URL construction, auth headers, request body fields, temperature handling, error responses, iteration limits, tool call success/failure
  • Integration test script scripts/test-deepseek.ts — run with DEEPSEEK_API_KEY=sk-... bun run scripts/test-deepseek.ts to verify real API connectivity

Configuration

"memoryProvider": "deepseek",
"memoryModel": "deepseek-chat",    // or "deepseek-reasoner"
"memoryApiUrl": "https://api.deepseek.com",
"memoryApiKey": "sk-..."

Testing

  • Unit tests
    bun test tests/deepseek-provider.test.ts
  • Integration test (requires real API key)
    DEEPSEEK_API_KEY=sk-... DEEPSEEK_API_URL=https://api.deepseek.com bun run scripts/test-deepseek.ts

Copilot AI review requested due to automatic review settings March 18, 2026 10:01
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new DeepSeek-backed AI provider to the existing AI provider framework (used for auto-capture and user profile learning), including provider registration, configuration template updates, and a test suite plus an integration script.

Changes:

  • Introduces DeepSeekProvider implementing the same session-based Chat Completions tool-calling flow as the existing OpenAI Chat provider, with DeepSeek defaults.
  • Registers "deepseek" in provider type unions and the AIProviderFactory, and updates CONFIG_TEMPLATE with DeepSeek configuration guidance.
  • Adds unit tests for request construction, auth behavior, temperature handling, and tool-call success/failure; adds an integration script for real API verification.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/services/ai/providers/deepseek.ts New provider implementation (session + tool calling) with DeepSeek defaults.
src/services/ai/session/session-types.ts Adds "deepseek" to AIProviderType.
src/services/ai/ai-provider-factory.ts Registers DeepSeek in factory + supported providers list.
src/config.ts Expands memory provider typing and updates config template with DeepSeek example.
tests/deepseek-provider.test.ts Unit tests for DeepSeek provider behaviors.
scripts/test-deepseek.ts Manual/integration test script for live DeepSeek API.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread src/services/ai/providers/deepseek.ts
Comment thread src/services/ai/providers/deepseek.ts
Comment thread src/config.ts Outdated
Comment thread src/config.ts Outdated
Comment thread scripts/test-deepseek.ts Outdated
Comment thread src/services/ai/providers/deepseek.ts
Comment thread src/services/ai/providers/deepseek.ts
Comment thread src/services/ai/providers/deepseek.ts Outdated
Copy link
Copy Markdown
Owner

@tickernelz tickernelz left a comment

Choose a reason for hiding this comment

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

Thanks for adding DeepSeek support! A few items to address:

1. Code duplication with OpenAIChatCompletionProvider

DeepSeek's chat API is OpenAI-compatible. The 384-line deepseek.ts is nearly identical to openai-chat-completion.ts. Please refactor to either:

  • Extend OpenAIChatCompletionProvider and override only the differences (API URL default, provider name)
  • Or extract a shared base class for OpenAI-compatible providers

This reduces maintenance burden — bug fixes in one place apply to both.

2. Remove or relocate scripts/test-deepseek.ts

This is a manual integration test script that requires a real API key. Either:

  • Remove it from the PR (unit tests are sufficient)
  • Or move it to a scripts/ directory with a README explaining its purpose

3. Add tests for filterIncompleteToolCallSequences

This method has complex branching logic but no direct test coverage. Please add test cases for:

  • Complete tool call sequences (assistant + tool response)
  • Incomplete sequences (assistant with tool calls but missing responses)
  • Mixed sequences

4. Type safety

Several places use any (constructor config, message types). Consider defining proper interfaces for DeepSeek-specific config and message types.

Once these are addressed, this will be ready to merge.

@NaNomicon
Copy link
Copy Markdown
Collaborator

Just for context, did you try using "memoryProvider": "openai-chat" to use deepseek models? What have you tried and what was the result?

@regulusleow
Copy link
Copy Markdown
Author

regulusleow commented Apr 8, 2026

Thanks for adding DeepSeek support! A few items to address:

1. Code duplication with OpenAIChatCompletionProvider

DeepSeek's chat API is OpenAI-compatible. The 384-line deepseek.ts is nearly identical to openai-chat-completion.ts. Please refactor to either:

  • Extend OpenAIChatCompletionProvider and override only the differences (API URL default, provider name)
  • Or extract a shared base class for OpenAI-compatible providers

This reduces maintenance burden — bug fixes in one place apply to both.

2. Remove or relocate scripts/test-deepseek.ts

This is a manual integration test script that requires a real API key. Either:

  • Remove it from the PR (unit tests are sufficient)
  • Or move it to a scripts/ directory with a README explaining its purpose

3. Add tests for filterIncompleteToolCallSequences

This method has complex branching logic but no direct test coverage. Please add test cases for:

  • Complete tool call sequences (assistant + tool response)
  • Incomplete sequences (assistant with tool calls but missing responses)
  • Mixed sequences

4. Type safety

Several places use any (constructor config, message types). Consider defining proper interfaces for DeepSeek-specific config and message types.

Once these are addressed, this will be ready to merge.

@tickernelz Thanks for the review — all four items are addressed now.

  1. I extracted a shared OpenAIChatCompletionBaseProvider for the OpenAI-compatible flow, and DeepSeekProvider is now a thin wrapper that only keeps the provider-specific differences (provider name, session type, log labels, retry prompt). Commits: 259c3af, c0e3cb0.

  2. scripts/test-deepseek.ts has been removed from the PR. Commit: 05c0b75.

  3. I added direct test coverage for filterIncompleteToolCallSequences, covering complete sequences, incomplete trailing sequences, and mixed sequences. Commit: 0d1af83.

  4. I tightened type safety in the shared base with a minimal scope: only openai-chat-completion-base.ts was updated, and the 6 any usages in the main path there have been removed. Commit: bbfd668.

@regulusleow
Copy link
Copy Markdown
Author

Just for context, did you try using "memoryProvider": "openai-chat" to use deepseek models? What have you tried and what was the result?

@NaNomicon Yes, openai-chat with a custom memoryApiUrl does work. That said, a dedicated provider adds a few things:

  • Clearer identity — logs, error messages, and session types are tagged as deepseek rather than the generic openai-chat, making debugging easier
  • Extensibility — DeepSeek has unique features (e.g. reasoning_content field, deepseek-reasoner's special response format) that would need provider-specific handling in the future, without polluting openai-chat
  • User intent — writing "memoryProvider": "deepseek" is more intuitive than openai-chat + manually configuring the DeepSeek URL

machen added 11 commits April 8, 2026 19:04
- Use local variable `iterationTimeout` instead of `this.config.iterationTimeout` in timeout error message
- Use local variable `maxIterations` instead of `this.config.maxIterations` in max iterations error message
- Use `toolSchema.function.name` instead of hardcoded 'save_memories' in retry prompt
Replace the unused ToolCallResponse interface with three focused interfaces:
- DeepSeekToolCall: tool call structure
- DeepSeekErrorResponse: error body shape
- DeepSeekResponse: success response shape

Eliminates 'as any' cast and gives full type coverage to the response path.
@regulusleow regulusleow force-pushed the feat/deepseek-support branch from bbfd668 to 1cfc913 Compare April 8, 2026 11:16
@regulusleow regulusleow requested a review from tickernelz April 8, 2026 11:21
@NaNomicon NaNomicon removed the request for review from tickernelz April 9, 2026 01:23
@NaNomicon
Copy link
Copy Markdown
Collaborator

Thanks again for working through the review feedback here. I went back through the updated commits and comments, and I think the code is in much better shape now. The shared OpenAIChatCompletionBaseProvider extraction in particular feels like a good improvement on its own.

At this point, though, I think the main question is about the direction we want for provider support. My preference is for us to keep the public surface area centered around generic protocols rather than adding more explicit vendor-specific providers. In this case, DeepSeek appears to fit the OpenAI-compatible chat-completions path, and from the discussion it sounds like openai-chat with a custom memoryApiUrl already works.

Because of that, I’m hesitant to add deepseek as a new hardcoded provider type. I worry that if we go this route, we’ll keep growing the matrix of provider enums, factory cases, docs, and tests for each OpenAI-compatible vendor, which will get harder to maintain over time.

I think the better long-term direction is:

  • keep the refactoring that improves the shared OpenAI-compatible path,
  • make the generic/config-driven path easier and clearer to use for providers like DeepSeek,
  • and only introduce a dedicated provider when there is real behavior/protocol divergence that the generic path cannot handle cleanly.

So from a product/API design perspective, I’d prefer not to merge the DeepSeek-specific provider as-is. If you’re open to it, I’d be very happy to support reshaping this toward better support for custom/config-defined providers instead, because I think that would be useful well beyond just DeepSeek.

@regulusleow
Copy link
Copy Markdown
Author

@NaNomicon

At this point, though, I think the main question is about the direction we want for provider support. My preference is for us to keep the public surface area centered around generic protocols rather than adding more explicit vendor-specific providers.

So from a product/API design perspective, I’d prefer not to merge the DeepSeek-specific provider as-is.

At this point, I agree there is not a strong need to split DeepSeek out as a dedicated provider.

It is still fundamentally using the OpenAI-compatible chat completions path, and the existing generic path is sufficient for this use case. So I’m going to reshape this PR accordingly:

  • keep the OpenAIChatCompletionBaseProvider extraction and the related type-safety improvements
  • revert the deepseek-specific surface area, including the provider enum entry, factory registration, and the memoryProvider: "deepseek" config/docs changes in config.ts
  • keep the parts of this work that provide shared value to the generic path
  • add a clearer note in the configuration comments to explain that any service compatible with the OpenAI API can be used via memoryProvider: "openai-chat" together with a custom memoryApiUrl
  • if DeepSeek later turns out to need behavior that cannot be cleanly handled by the generic path, we can revisit introducing a dedicated provider then

Consolidate OpenAI-compatible usage under the generic openai-chat path and update config guidance accordingly. Preserve shared provider behavior coverage by renaming and adapting tests to the OpenAI chat completion provider.
@NaNomicon
Copy link
Copy Markdown
Collaborator

One more thought on the reshaped PR — I don't think we actually need the OpenAIChatCompletionBaseProvider extraction either. With the DeepSeek provider removed, OpenAIChatCompletionProvider would be the only subclass, and all the abstract methods are just returning string labels. That's a premature abstraction for a case we're explicitly choosing not to support right now.

That said, the type-safety improvements from this work are genuinely valuable — the typed interfaces (ToolCallResponse, APIMessage, RequestBody), the type guards (isErrorResponseBody, isToolCallResponse), and removing the any casts. Those are worth keeping.

I see two options and am happy with either:

  1. Reshape this PR further — apply the type-safety improvements directly to openai-chat-completion.ts without the base class extraction, and drop the DeepSeek-specific changes. This keeps the history in one PR.

  2. Close this PR and open a fresh one — a clean PR focused purely on the type-safety improvements to openai-chat-completion.ts, without the base class or DeepSeek provider. This keeps the git history cleaner.

Either way works for us. If a real protocol divergence comes up later that justifies extracting a base class, we can do it then with concrete requirements. Thanks for being flexible on this.

@regulusleow
Copy link
Copy Markdown
Author

@NaNomicon Thanks, this makes sense — I agree option 2 is cleaner.

I will close this PR and open a fresh one focused only on the type-safety improvements in openai-chat-completion.ts (typed interfaces, type guards, and removing any casts), without the base-class extraction and without any DeepSeek-specific surface.

Also, I suggest we keep a clear config note to guide OpenAI-compatible usage, for example:

// Any OpenAI-compatible endpoint can use the "openai-chat" provider pattern below.
// Common examples: DeepSeek, Qwen (via Alibaba Cloud ModelStudio),
// Zhipu GLM (BigModel platform), and Kimi (Moonshot AI platform).

This should make the integration path clearer for users using compatible endpoints via memoryProvider: "openai-chat" + custom memoryApiUrl.

@regulusleow
Copy link
Copy Markdown
Author

I've opened a new focused PR for the follow-up changes: https://github.com/tickernelz/opencode-mem/pull/92\n\nI'll close this PR (#67) to keep scope clean and continue discussion/review on #92.

@regulusleow
Copy link
Copy Markdown
Author

Closing this PR in favor of #92 to keep scope focused. Please continue review there: #92

@regulusleow regulusleow closed this Apr 9, 2026
@regulusleow regulusleow deleted the feat/deepseek-support branch April 10, 2026 08:44
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.

4 participants