mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-05-30 02:49:12 -04:00
feat: Add DeepSeek provider
This commit is contained in:
@@ -118,6 +118,7 @@ add_qtc_plugin(QodeAssist
|
||||
providers/OpenAIResponsesProvider.hpp providers/OpenAIResponsesProvider.cpp
|
||||
providers/QwenProvider.hpp providers/QwenProvider.cpp
|
||||
providers/QwenResponsesProvider.hpp providers/QwenResponsesProvider.cpp
|
||||
providers/DeepSeekProvider.hpp providers/DeepSeekProvider.cpp
|
||||
QodeAssist.qrc
|
||||
LSPCompletion.hpp
|
||||
LLMSuggestion.hpp LLMSuggestion.cpp
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||
[](https://discord.gg/BGMkUsXUgf)
|
||||
|
||||
 **QodeAssist** brings a full AI coding workflow to Qt Creator for C++ and QML — smart code completion, multi-panel chat, inline quick refactoring, and project-aware tool calling. It works with local runtimes (Ollama, llama.cpp, LM Studio) and cloud providers (Claude, OpenAI, Google AI, Mistral, Qwen), can run as an **MCP server** so other clients reuse its project context, and can also act as an **MCP client** to consume tools from external MCP servers (authenticated MCP servers are not supported yet).
|
||||
 **QodeAssist** brings a full AI coding workflow to Qt Creator for C++ and QML — smart code completion, multi-panel chat, inline quick refactoring, and project-aware tool calling. It works with local runtimes (Ollama, llama.cpp, LM Studio) and cloud providers (Claude, OpenAI, Google AI, Mistral, Qwen, DeepSeek), can run as an **MCP server** so other clients reuse its project context, and can also act as an **MCP client** to consume tools from external MCP servers (authenticated MCP servers are not supported yet).
|
||||
|
||||
⚠️ **Important Notice About Paid Providers**
|
||||
> When using paid providers like Claude, OpenRouter or OpenAI-compatible services:
|
||||
@@ -39,7 +39,8 @@ QodeAssist enhances Qt Creator with AI-powered coding assistance:
|
||||
- **MCP Server** — expose QodeAssist's project-aware tools to external MCP clients (Claude Code, VS Code, Claude Desktop via bridge)
|
||||
- **MCP Client Hub** — connect QodeAssist to external MCP servers and use their tools in Chat and Quick Refactor (authenticated MCP servers are not supported yet)
|
||||
- **File Context** — attach, link, or auto-sync open editor files for richer prompts
|
||||
- **Many Providers** — Ollama, llama.cpp, LM Studio (Chat + Responses), Claude, OpenAI (Chat + Responses), Google AI, Mistral, Codestral, OpenRouter, Qwen (OpenAI + Responses), any OpenAI-compatible endpoint
|
||||
- **Many Providers** — Ollama, llama.cpp, LM Studio (Chat + Responses), Claude, OpenAI (Chat + Responses), Google AI, Mistral, Codestral, OpenRouter, Qwen (OpenAI + Responses), DeepSeek, any OpenAI-compatible endpoint
|
||||
- **Reasoning / Thinking** — streamed chain-of-thought is shown for reasoning models across Claude, Google, OpenAI Responses, and any OpenAI-compatible endpoint that returns `reasoning_content` (DeepSeek, Qwen QwQ/Qwen3-Thinking, LM Studio, OpenRouter, …)
|
||||
- **Customizable** — per-project rules (`.qodeassist/rules/`), agent roles, reusable refactor templates, full prompt-template control
|
||||
|
||||
**Join our [Discord Community](https://discord.gg/BGMkUsXUgf)** to get support and connect with other users!
|
||||
@@ -170,6 +171,7 @@ The Quick Setup feature provides one-click configuration for popular cloud AI mo
|
||||
- **Mistral AI** (Codestral 2501)
|
||||
- **Google AI** (Gemini 2.5 Flash)
|
||||
- **Qwen** (Qwen3.6 Plus, Qwen3.7 Max)
|
||||
- **DeepSeek** (DeepSeek V4 Flash, DeepSeek V4 Pro)
|
||||
3. **Configure API Key** - Click "Configure API Key" button and enter your API key in Provider Settings
|
||||
|
||||
All settings (provider, model, template, URL) are configured automatically. Just add your API key and you're ready to go!
|
||||
@@ -191,6 +193,7 @@ For advanced users or local models, choose your preferred provider and follow th
|
||||
- **[Mistral AI](docs/mistral-configuration.md)** / **Codestral**
|
||||
- **[Google AI](docs/google-ai-configuration.md)** — Gemini
|
||||
- **Qwen (Alibaba)** — DashScope OpenAI-compatible Chat and Responses endpoints
|
||||
- **DeepSeek** — `deepseek-chat` and `deepseek-reasoner` (reasoning shown as thinking)
|
||||
- **OpenAI-compatible** — OpenRouter and any custom endpoint
|
||||
|
||||
### Recommended Models for Best Experience
|
||||
@@ -255,7 +258,7 @@ Configure in: `Tools → Options → QodeAssist → Code Completion → General
|
||||
- **[Chat Summarization](docs/chat-summarization.md)** - Compress long conversations into AI-generated summaries
|
||||
- **[File Context](docs/file-context.md)** - Attach or link files for better context
|
||||
- Automatic syncing with open editor files (optional)
|
||||
- Extended thinking mode (Claude, other providers in plan) - Enable deeper reasoning for complex tasks
|
||||
- Extended thinking / reasoning mode - shows streamed chain-of-thought for reasoning models (Claude, Google, OpenAI Responses, and OpenAI-compatible endpoints returning `reasoning_content` such as DeepSeek, Qwen, LM Studio, OpenRouter)
|
||||
|
||||
### Quick Refactoring
|
||||
- Inline code refactoring directly in the editor with AI assistance
|
||||
|
||||
@@ -15,6 +15,7 @@ enum class ProviderID {
|
||||
OpenRouter,
|
||||
GoogleAI,
|
||||
LlamaCpp,
|
||||
Qwen
|
||||
Qwen,
|
||||
DeepSeek
|
||||
};
|
||||
}
|
||||
|
||||
110
providers/DeepSeekProvider.cpp
Normal file
110
providers/DeepSeekProvider.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright (C) 2024-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "DeepSeekProvider.hpp"
|
||||
|
||||
#include <LLMQore/ToolsManager.hpp>
|
||||
#include "logger/Logger.hpp"
|
||||
#include "settings/ChatAssistantSettings.hpp"
|
||||
#include "settings/CodeCompletionSettings.hpp"
|
||||
#include "settings/GeneralSettings.hpp"
|
||||
#include "settings/ProviderSettings.hpp"
|
||||
#include "settings/QuickRefactorSettings.hpp"
|
||||
#include "tools/ToolsRegistration.hpp"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace QodeAssist::Providers {
|
||||
|
||||
DeepSeekProvider::DeepSeekProvider(QObject *parent)
|
||||
: PluginLLMCore::Provider(parent)
|
||||
, m_client(new ::LLMQore::OpenAIClient(QString(), QString(), QString(), this))
|
||||
{
|
||||
Tools::registerQodeAssistTools(m_client->tools());
|
||||
}
|
||||
|
||||
QString DeepSeekProvider::name() const
|
||||
{
|
||||
return "DeepSeek";
|
||||
}
|
||||
|
||||
QString DeepSeekProvider::apiKey() const
|
||||
{
|
||||
return Settings::providerSettings().deepSeekApiKey();
|
||||
}
|
||||
|
||||
QString DeepSeekProvider::url() const
|
||||
{
|
||||
return "https://api.deepseek.com";
|
||||
}
|
||||
|
||||
QFuture<QList<QString>> DeepSeekProvider::getInstalledModels(const QString &url)
|
||||
{
|
||||
m_client->setUrl(url);
|
||||
m_client->setApiKey(apiKey());
|
||||
return m_client->listModels();
|
||||
}
|
||||
|
||||
PluginLLMCore::ProviderID DeepSeekProvider::providerID() const
|
||||
{
|
||||
return PluginLLMCore::ProviderID::DeepSeek;
|
||||
}
|
||||
|
||||
PluginLLMCore::ProviderCapabilities DeepSeekProvider::capabilities() const
|
||||
{
|
||||
return PluginLLMCore::ProviderCapability::Tools
|
||||
| PluginLLMCore::ProviderCapability::Thinking
|
||||
| PluginLLMCore::ProviderCapability::ModelListing;
|
||||
}
|
||||
|
||||
void DeepSeekProvider::prepareRequest(
|
||||
QJsonObject &request,
|
||||
PluginLLMCore::PromptTemplate *prompt,
|
||||
PluginLLMCore::ContextData context,
|
||||
PluginLLMCore::RequestType type,
|
||||
bool isToolsEnabled,
|
||||
bool isThinkingEnabled)
|
||||
{
|
||||
if (!prompt->isSupportProvider(providerID())) {
|
||||
LOG_MESSAGE(QString("Template %1 doesn't support %2 provider").arg(name(), prompt->name()));
|
||||
}
|
||||
|
||||
prompt->prepareRequest(request, context);
|
||||
|
||||
auto applyModelParams = [&request](const auto &settings) {
|
||||
request["max_tokens"] = settings.maxTokens();
|
||||
request["temperature"] = settings.temperature();
|
||||
|
||||
if (settings.useTopP())
|
||||
request["top_p"] = settings.topP();
|
||||
if (settings.useFrequencyPenalty())
|
||||
request["frequency_penalty"] = settings.frequencyPenalty();
|
||||
if (settings.usePresencePenalty())
|
||||
request["presence_penalty"] = settings.presencePenalty();
|
||||
};
|
||||
|
||||
if (type == PluginLLMCore::RequestType::CodeCompletion) {
|
||||
applyModelParams(Settings::codeCompletionSettings());
|
||||
} else if (type == PluginLLMCore::RequestType::QuickRefactoring) {
|
||||
applyModelParams(Settings::quickRefactorSettings());
|
||||
} else {
|
||||
applyModelParams(Settings::chatAssistantSettings());
|
||||
}
|
||||
|
||||
if (isToolsEnabled) {
|
||||
auto toolsDefinitions = m_client->tools()->getToolsDefinitions();
|
||||
if (!toolsDefinitions.isEmpty()) {
|
||||
request["tools"] = toolsDefinitions;
|
||||
LOG_MESSAGE(QString("Added %1 tools to DeepSeek request").arg(toolsDefinitions.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::LLMQore::BaseClient *DeepSeekProvider::client() const
|
||||
{
|
||||
return m_client;
|
||||
}
|
||||
|
||||
} // namespace QodeAssist::Providers
|
||||
37
providers/DeepSeekProvider.hpp
Normal file
37
providers/DeepSeekProvider.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2024-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LLMQore/OpenAIClient.hpp>
|
||||
#include <pluginllmcore/Provider.hpp>
|
||||
|
||||
namespace QodeAssist::Providers {
|
||||
|
||||
class DeepSeekProvider : public PluginLLMCore::Provider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeepSeekProvider(QObject *parent = nullptr);
|
||||
|
||||
QString name() const override;
|
||||
QString url() const override;
|
||||
void prepareRequest(
|
||||
QJsonObject &request,
|
||||
PluginLLMCore::PromptTemplate *prompt,
|
||||
PluginLLMCore::ContextData context,
|
||||
PluginLLMCore::RequestType type,
|
||||
bool isToolsEnabled,
|
||||
bool isThinkingEnabled) override;
|
||||
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
|
||||
PluginLLMCore::ProviderID providerID() const override;
|
||||
PluginLLMCore::ProviderCapabilities capabilities() const override;
|
||||
|
||||
::LLMQore::BaseClient *client() const override;
|
||||
QString apiKey() const override;
|
||||
|
||||
private:
|
||||
::LLMQore::OpenAIClient *m_client;
|
||||
};
|
||||
|
||||
} // namespace QodeAssist::Providers
|
||||
@@ -57,7 +57,8 @@ PluginLLMCore::ProviderID LMStudioProvider::providerID() const
|
||||
PluginLLMCore::ProviderCapabilities LMStudioProvider::capabilities() const
|
||||
{
|
||||
return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image
|
||||
| PluginLLMCore::ProviderCapability::ModelListing;
|
||||
| PluginLLMCore::ProviderCapability::ModelListing
|
||||
| PluginLLMCore::ProviderCapability::Thinking;
|
||||
}
|
||||
|
||||
void LMStudioProvider::prepareRequest(
|
||||
|
||||
@@ -55,7 +55,8 @@ PluginLLMCore::ProviderID MistralAIProvider::providerID() const
|
||||
PluginLLMCore::ProviderCapabilities MistralAIProvider::capabilities() const
|
||||
{
|
||||
return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image
|
||||
| PluginLLMCore::ProviderCapability::ModelListing;
|
||||
| PluginLLMCore::ProviderCapability::ModelListing
|
||||
| PluginLLMCore::ProviderCapability::Thinking;
|
||||
}
|
||||
|
||||
void MistralAIProvider::prepareRequest(
|
||||
|
||||
@@ -113,7 +113,8 @@ PluginLLMCore::ProviderID OllamaCompatProvider::providerID() const
|
||||
PluginLLMCore::ProviderCapabilities OllamaCompatProvider::capabilities() const
|
||||
{
|
||||
return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image
|
||||
| PluginLLMCore::ProviderCapability::ModelListing;
|
||||
| PluginLLMCore::ProviderCapability::ModelListing
|
||||
| PluginLLMCore::ProviderCapability::Thinking;
|
||||
}
|
||||
|
||||
::LLMQore::BaseClient *OllamaCompatProvider::client() const
|
||||
|
||||
@@ -98,7 +98,8 @@ PluginLLMCore::ProviderID OpenAICompatProvider::providerID() const
|
||||
|
||||
PluginLLMCore::ProviderCapabilities OpenAICompatProvider::capabilities() const
|
||||
{
|
||||
return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image;
|
||||
return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image
|
||||
| PluginLLMCore::ProviderCapability::Thinking;
|
||||
}
|
||||
|
||||
::LLMQore::BaseClient *OpenAICompatProvider::client() const
|
||||
|
||||
@@ -129,7 +129,8 @@ PluginLLMCore::ProviderID OpenAIProvider::providerID() const
|
||||
PluginLLMCore::ProviderCapabilities OpenAIProvider::capabilities() const
|
||||
{
|
||||
return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image
|
||||
| PluginLLMCore::ProviderCapability::ModelListing;
|
||||
| PluginLLMCore::ProviderCapability::ModelListing
|
||||
| PluginLLMCore::ProviderCapability::Thinking;
|
||||
}
|
||||
|
||||
::LLMQore::BaseClient *OpenAIProvider::client() const
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "pluginllmcore/ProvidersManager.hpp"
|
||||
#include "providers/ClaudeProvider.hpp"
|
||||
#include "providers/DeepSeekProvider.hpp"
|
||||
#include "providers/CodestralProvider.hpp"
|
||||
#include "providers/GoogleAIProvider.hpp"
|
||||
#include "providers/LMStudioProvider.hpp"
|
||||
@@ -40,6 +41,7 @@ inline void registerProviders()
|
||||
providerManager.registerProvider<CodestralProvider>();
|
||||
providerManager.registerProvider<QwenProvider>();
|
||||
providerManager.registerProvider<QwenResponsesProvider>();
|
||||
providerManager.registerProvider<DeepSeekProvider>();
|
||||
}
|
||||
|
||||
} // namespace QodeAssist::Providers
|
||||
|
||||
@@ -121,6 +121,28 @@ QVector<AIConfiguration> ConfigurationManager::getPredefinedConfigurations(
|
||||
qwenMax.type = type;
|
||||
qwenMax.isPredefined = true;
|
||||
|
||||
AIConfiguration deepSeekFlash;
|
||||
deepSeekFlash.id = "preset_deepseek_flash";
|
||||
deepSeekFlash.name = "DeepSeek V4 Flash";
|
||||
deepSeekFlash.provider = "DeepSeek";
|
||||
deepSeekFlash.model = "deepseek-v4-flash";
|
||||
deepSeekFlash.url = "https://api.deepseek.com";
|
||||
deepSeekFlash.customEndpoint = "";
|
||||
deepSeekFlash.templateName = "OpenAI Compatible";
|
||||
deepSeekFlash.type = type;
|
||||
deepSeekFlash.isPredefined = true;
|
||||
|
||||
AIConfiguration deepSeekPro;
|
||||
deepSeekPro.id = "preset_deepseek_pro";
|
||||
deepSeekPro.name = "DeepSeek V4 Pro";
|
||||
deepSeekPro.provider = "DeepSeek";
|
||||
deepSeekPro.model = "deepseek-v4-pro";
|
||||
deepSeekPro.url = "https://api.deepseek.com";
|
||||
deepSeekPro.customEndpoint = "";
|
||||
deepSeekPro.templateName = "OpenAI Compatible";
|
||||
deepSeekPro.type = type;
|
||||
deepSeekPro.isPredefined = true;
|
||||
|
||||
AIConfiguration gpt;
|
||||
gpt.id = "preset_gpt";
|
||||
gpt.name = "gpt-5.5";
|
||||
@@ -141,6 +163,8 @@ QVector<AIConfiguration> ConfigurationManager::getPredefinedConfigurations(
|
||||
presets.append(geminiFlash);
|
||||
presets.append(qwenPlus);
|
||||
presets.append(qwenMax);
|
||||
presets.append(deepSeekFlash);
|
||||
presets.append(deepSeekPro);
|
||||
|
||||
return presets;
|
||||
}
|
||||
|
||||
@@ -132,6 +132,15 @@ ProviderSettings::ProviderSettings()
|
||||
qwenApiKey.setDefaultValue("");
|
||||
qwenApiKey.setAutoApply(true);
|
||||
|
||||
// DeepSeek Settings
|
||||
deepSeekApiKey.setSettingsKey(Constants::DEEPSEEK_API_KEY);
|
||||
deepSeekApiKey.setLabelText(Tr::tr("DeepSeek API Key:"));
|
||||
deepSeekApiKey.setDisplayStyle(Utils::StringAspect::LineEditDisplay);
|
||||
deepSeekApiKey.setPlaceHolderText(Tr::tr("Enter your API key here"));
|
||||
deepSeekApiKey.setHistoryCompleter(Constants::DEEPSEEK_API_KEY_HISTORY);
|
||||
deepSeekApiKey.setDefaultValue("");
|
||||
deepSeekApiKey.setAutoApply(true);
|
||||
|
||||
resetToDefaults.m_buttonText = Tr::tr("Reset Page to Defaults");
|
||||
|
||||
readSettings();
|
||||
@@ -163,6 +172,8 @@ ProviderSettings::ProviderSettings()
|
||||
Group{title(Tr::tr("llama.cpp Settings")), Column{llamaCppApiKey}},
|
||||
Space{8},
|
||||
Group{title(Tr::tr("Qwen (Alibaba) Settings")), Column{qwenApiKey}},
|
||||
Space{8},
|
||||
Group{title(Tr::tr("DeepSeek Settings")), Column{deepSeekApiKey}},
|
||||
Stretch{1}};
|
||||
});
|
||||
}
|
||||
@@ -201,6 +212,9 @@ void ProviderSettings::setupConnections()
|
||||
llamaCppApiKey.writeSettings();
|
||||
});
|
||||
connect(&qwenApiKey, &ButtonAspect::changed, this, [this]() { qwenApiKey.writeSettings(); });
|
||||
connect(&deepSeekApiKey, &ButtonAspect::changed, this, [this]() {
|
||||
deepSeekApiKey.writeSettings();
|
||||
});
|
||||
}
|
||||
|
||||
void ProviderSettings::resetSettingsToDefaults()
|
||||
@@ -224,6 +238,7 @@ void ProviderSettings::resetSettingsToDefaults()
|
||||
resetAspect(ollamaBasicAuthApiKey);
|
||||
resetAspect(llamaCppApiKey);
|
||||
resetAspect(qwenApiKey);
|
||||
resetAspect(deepSeekApiKey);
|
||||
writeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ public:
|
||||
Utils::StringAspect ollamaBasicAuthApiKey{this};
|
||||
Utils::StringAspect llamaCppApiKey{this};
|
||||
Utils::StringAspect qwenApiKey{this};
|
||||
Utils::StringAspect deepSeekApiKey{this};
|
||||
|
||||
private:
|
||||
void setupConnections();
|
||||
|
||||
@@ -165,6 +165,8 @@ const char LLAMA_CPP_API_KEY[] = "QodeAssist.llamaCppApiKey";
|
||||
const char LLAMA_CPP_API_KEY_HISTORY[] = "QodeAssist.llamaCppApiKeyHistory";
|
||||
const char QWEN_API_KEY[] = "QodeAssist.qwenApiKey";
|
||||
const char QWEN_API_KEY_HISTORY[] = "QodeAssist.qwenApiKeyHistory";
|
||||
const char DEEPSEEK_API_KEY[] = "QodeAssist.deepSeekApiKey";
|
||||
const char DEEPSEEK_API_KEY_HISTORY[] = "QodeAssist.deepSeekApiKeyHistory";
|
||||
|
||||
const char CLAUDE_ENABLE_PROMPT_CACHING[] = "QodeAssist.claudeEnablePromptCaching";
|
||||
const char CLAUDE_USE_EXTENDED_CACHE_TTL[] = "QodeAssist.claudeUseExtendedCacheTTL";
|
||||
|
||||
2
sources/external/llmqore
vendored
2
sources/external/llmqore
vendored
Submodule sources/external/llmqore updated: 95a7b3ac51...68ecec3dc9
@@ -82,6 +82,7 @@ public:
|
||||
case PluginLLMCore::ProviderID::LMStudio:
|
||||
case PluginLLMCore::ProviderID::LlamaCpp:
|
||||
case PluginLLMCore::ProviderID::Qwen:
|
||||
case PluginLLMCore::ProviderID::DeepSeek:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user