refactor: Combine bool functions with capabilities to flag

This commit is contained in:
Petr Mironychev
2026-03-30 18:23:32 +02:00
parent 545b8ed000
commit 1c12d6d45c
23 changed files with 59 additions and 120 deletions

View File

@ -1298,7 +1298,7 @@ bool ChatRootView::isThinkingSupport() const
auto providerName = Settings::generalSettings().caProvider(); auto providerName = Settings::generalSettings().caProvider();
auto provider = PluginLLMCore::ProvidersManager::instance().getProviderByName(providerName); auto provider = PluginLLMCore::ProvidersManager::instance().getProviderByName(providerName);
return provider && provider->supportThinking(); return provider && provider->capabilities().testFlag(PluginLLMCore::ProviderCapability::Thinking);
} }
QString ChatRootView::generateChatFileName(const QString &shortMessage, const QString &dir) const QString ChatRootView::generateChatFileName(const QString &shortMessage, const QString &dir) const

View File

@ -227,7 +227,8 @@ void ClientInterface::sendMessage(
apiMessage.isRedacted = msg.isRedacted; apiMessage.isRedacted = msg.isRedacted;
apiMessage.signature = msg.signature; apiMessage.signature = msg.signature;
if (provider->supportImage() && !m_chatFilePath.isEmpty() && !msg.images.isEmpty()) { if (provider->capabilities().testFlag(PluginLLMCore::ProviderCapability::Image)
&& !m_chatFilePath.isEmpty() && !msg.images.isEmpty()) {
auto apiImages = loadImagesFromStorage(msg.images); auto apiImages = loadImagesFromStorage(msg.images);
if (!apiImages.isEmpty()) { if (!apiImages.isEmpty()) {
apiMessage.images = apiImages; apiMessage.images = apiImages;
@ -237,7 +238,8 @@ void ClientInterface::sendMessage(
messages.append(apiMessage); messages.append(apiMessage);
} }
if (!imageFiles.isEmpty() && !provider->supportImage()) { if (!imageFiles.isEmpty()
&& !provider->capabilities().testFlag(PluginLLMCore::ProviderCapability::Image)) {
LOG_MESSAGE(QString("Provider %1 doesn't support images, %2 ignored") LOG_MESSAGE(QString("Provider %1 doesn't support images, %2 ignored")
.arg(provider->name(), QString::number(imageFiles.size()))); .arg(provider->name(), QString::number(imageFiles.size())));
} }
@ -330,7 +332,8 @@ void ClientInterface::sendMessage(
provider->sendRequest(requestId, config.url, config.providerRequest); provider->sendRequest(requestId, config.url, config.providerRequest);
if (provider->supportsTools() && provider->toolsManager()) { if (provider->capabilities().testFlag(PluginLLMCore::ProviderCapability::Tools)
&& provider->toolsManager()) {
if (auto *todoTool = qobject_cast<QodeAssist::Tools::TodoTool *>( if (auto *todoTool = qobject_cast<QodeAssist::Tools::TodoTool *>(
provider->toolsManager()->tool("todo_tool"))) { provider->toolsManager()->tool("todo_tool"))) {
todoTool->setCurrentSessionId(m_chatFilePath); todoTool->setCurrentSessionId(m_chatFilePath);
@ -343,7 +346,8 @@ void ClientInterface::clearMessages()
const auto providerName = Settings::generalSettings().caProvider(); const auto providerName = Settings::generalSettings().caProvider();
auto *provider = PluginLLMCore::ProvidersManager::instance().getProviderByName(providerName); auto *provider = PluginLLMCore::ProvidersManager::instance().getProviderByName(providerName);
if (provider && !m_chatFilePath.isEmpty() && provider->supportsTools() if (provider && !m_chatFilePath.isEmpty()
&& provider->capabilities().testFlag(PluginLLMCore::ProviderCapability::Tools)
&& provider->toolsManager()) { && provider->toolsManager()) {
if (auto *todoTool = qobject_cast<QodeAssist::Tools::TodoTool *>( if (auto *todoTool = qobject_cast<QodeAssist::Tools::TodoTool *>(
provider->toolsManager()->tool("todo_tool"))) { provider->toolsManager()->tool("todo_tool"))) {
@ -628,7 +632,9 @@ void ClientInterface::setChatFilePath(const QString &filePath)
const auto providerName = Settings::generalSettings().caProvider(); const auto providerName = Settings::generalSettings().caProvider();
auto *provider = PluginLLMCore::ProvidersManager::instance().getProviderByName(providerName); auto *provider = PluginLLMCore::ProvidersManager::instance().getProviderByName(providerName);
if (provider && provider->supportsTools() && provider->toolsManager()) { if (provider
&& provider->capabilities().testFlag(PluginLLMCore::ProviderCapability::Tools)
&& provider->toolsManager()) {
if (auto *todoTool = qobject_cast<QodeAssist::Tools::TodoTool *>( if (auto *todoTool = qobject_cast<QodeAssist::Tools::TodoTool *>(
provider->toolsManager()->tool("todo_tool"))) { provider->toolsManager()->tool("todo_tool"))) {
todoTool->clearSession(m_chatFilePath); todoTool->clearSession(m_chatFilePath);

View File

@ -19,6 +19,7 @@
#pragma once #pragma once
#include <QFlags>
#include <QFuture> #include <QFuture>
#include <utils/environment.h> #include <utils/environment.h>
#include <QNetworkRequest> #include <QNetworkRequest>
@ -38,6 +39,14 @@ class QJsonObject;
namespace QodeAssist::PluginLLMCore { namespace QodeAssist::PluginLLMCore {
enum class ProviderCapability {
Tools = 0x1,
Thinking = 0x2,
Image = 0x4,
};
Q_DECLARE_FLAGS(ProviderCapabilities, ProviderCapability)
Q_DECLARE_OPERATORS_FOR_FLAGS(ProviderCapabilities)
class Provider : public QObject class Provider : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -68,9 +77,7 @@ public:
virtual void sendRequest(const RequestID &requestId, const QUrl &url, const QJsonObject &payload) virtual void sendRequest(const RequestID &requestId, const QUrl &url, const QJsonObject &payload)
= 0; = 0;
virtual bool supportsTools() const { return false; }; virtual ProviderCapabilities capabilities() const { return {}; }
virtual bool supportThinking() const { return false; };
virtual bool supportImage() const { return false; };
virtual void cancelRequest(const RequestID &requestId) = 0; virtual void cancelRequest(const RequestID &requestId) = 0;

View File

@ -249,19 +249,10 @@ void ClaudeProvider::sendRequest(
.arg(requestId, clientId, url.toString())); .arg(requestId, clientId, url.toString()));
} }
bool ClaudeProvider::supportsTools() const PluginLLMCore::ProviderCapabilities ClaudeProvider::capabilities() const
{ {
return true; return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Thinking
} | PluginLLMCore::ProviderCapability::Image;
bool ClaudeProvider::supportThinking() const
{
return true;
}
bool ClaudeProvider::supportImage() const
{
return true;
} }
void ClaudeProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) void ClaudeProvider::cancelRequest(const PluginLLMCore::RequestID &requestId)

View File

@ -54,9 +54,7 @@ public:
void sendRequest( void sendRequest(
const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override; PluginLLMCore::ProviderCapabilities capabilities() const override;
bool supportThinking() const override;
bool supportImage() const override;
void cancelRequest(const PluginLLMCore::RequestID &requestId) override; void cancelRequest(const PluginLLMCore::RequestID &requestId) override;
::LLMCore::ToolsManager *toolsManager() const override; ::LLMCore::ToolsManager *toolsManager() const override;

View File

@ -265,19 +265,10 @@ void GoogleAIProvider::sendRequest(
.arg(requestId, clientId, url.toString())); .arg(requestId, clientId, url.toString()));
} }
bool GoogleAIProvider::supportsTools() const PluginLLMCore::ProviderCapabilities GoogleAIProvider::capabilities() const
{ {
return true; return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Thinking
} | PluginLLMCore::ProviderCapability::Image;
bool GoogleAIProvider::supportThinking() const
{
return true;
}
bool GoogleAIProvider::supportImage() const
{
return true;
} }
void GoogleAIProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) void GoogleAIProvider::cancelRequest(const PluginLLMCore::RequestID &requestId)

View File

@ -54,9 +54,7 @@ public:
void sendRequest( void sendRequest(
const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override; PluginLLMCore::ProviderCapabilities capabilities() const override;
bool supportThinking() const override;
bool supportImage() const override;
void cancelRequest(const PluginLLMCore::RequestID &requestId) override; void cancelRequest(const PluginLLMCore::RequestID &requestId) override;
::LLMCore::ToolsManager *toolsManager() const override; ::LLMCore::ToolsManager *toolsManager() const override;

View File

@ -177,14 +177,9 @@ void LMStudioProvider::sendRequest(
.arg(requestId, clientId, url.toString())); .arg(requestId, clientId, url.toString()));
} }
bool LMStudioProvider::supportsTools() const PluginLLMCore::ProviderCapabilities LMStudioProvider::capabilities() const
{ {
return true; return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image;
}
bool LMStudioProvider::supportImage() const
{
return true;
} }
void LMStudioProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) void LMStudioProvider::cancelRequest(const PluginLLMCore::RequestID &requestId)

View File

@ -53,8 +53,7 @@ public:
void sendRequest( void sendRequest(
const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override; PluginLLMCore::ProviderCapabilities capabilities() const override;
bool supportImage() const override;
void cancelRequest(const PluginLLMCore::RequestID &requestId) override; void cancelRequest(const PluginLLMCore::RequestID &requestId) override;
::LLMCore::ToolsManager *toolsManager() const override; ::LLMCore::ToolsManager *toolsManager() const override;

View File

@ -237,14 +237,9 @@ void LlamaCppProvider::sendRequest(
.arg(requestId, clientId, url.toString())); .arg(requestId, clientId, url.toString()));
} }
bool LlamaCppProvider::supportsTools() const PluginLLMCore::ProviderCapabilities LlamaCppProvider::capabilities() const
{ {
return true; return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image;
}
bool LlamaCppProvider::supportImage() const
{
return true;
} }
void LlamaCppProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) void LlamaCppProvider::cancelRequest(const PluginLLMCore::RequestID &requestId)

View File

@ -54,8 +54,7 @@ public:
void sendRequest( void sendRequest(
const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override; PluginLLMCore::ProviderCapabilities capabilities() const override;
bool supportImage() const override;
void cancelRequest(const PluginLLMCore::RequestID &requestId) override; void cancelRequest(const PluginLLMCore::RequestID &requestId) override;
::LLMCore::ToolsManager *toolsManager() const override; ::LLMCore::ToolsManager *toolsManager() const override;

View File

@ -189,14 +189,9 @@ void MistralAIProvider::sendRequest(
.arg(requestId, clientId, url.toString())); .arg(requestId, clientId, url.toString()));
} }
bool MistralAIProvider::supportsTools() const PluginLLMCore::ProviderCapabilities MistralAIProvider::capabilities() const
{ {
return true; return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image;
}
bool MistralAIProvider::supportImage() const
{
return true;
} }
void MistralAIProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) void MistralAIProvider::cancelRequest(const PluginLLMCore::RequestID &requestId)

View File

@ -53,8 +53,7 @@ public:
void sendRequest( void sendRequest(
const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override; PluginLLMCore::ProviderCapabilities capabilities() const override;
bool supportImage() const override;
void cancelRequest(const PluginLLMCore::RequestID &requestId) override; void cancelRequest(const PluginLLMCore::RequestID &requestId) override;
::LLMCore::ToolsManager *toolsManager() const override; ::LLMCore::ToolsManager *toolsManager() const override;

View File

@ -272,19 +272,10 @@ void OllamaProvider::sendRequest(
.arg(requestId, clientId, url.toString())); .arg(requestId, clientId, url.toString()));
} }
bool OllamaProvider::supportsTools() const PluginLLMCore::ProviderCapabilities OllamaProvider::capabilities() const
{ {
return true; return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Thinking
} | PluginLLMCore::ProviderCapability::Image;
bool OllamaProvider::supportImage() const
{
return true;
}
bool OllamaProvider::supportThinking() const
{
return true;
} }
void OllamaProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) void OllamaProvider::cancelRequest(const PluginLLMCore::RequestID &requestId)

View File

@ -54,9 +54,7 @@ public:
void sendRequest( void sendRequest(
const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override; PluginLLMCore::ProviderCapabilities capabilities() const override;
bool supportImage() const override;
bool supportThinking() const override;
void cancelRequest(const PluginLLMCore::RequestID &requestId) override; void cancelRequest(const PluginLLMCore::RequestID &requestId) override;
::LLMCore::ToolsManager *toolsManager() const override; ::LLMCore::ToolsManager *toolsManager() const override;

View File

@ -224,14 +224,9 @@ void OpenAICompatProvider::sendRequest(
.arg(requestId, clientId, url.toString())); .arg(requestId, clientId, url.toString()));
} }
bool OpenAICompatProvider::supportsTools() const PluginLLMCore::ProviderCapabilities OpenAICompatProvider::capabilities() const
{ {
return true; return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image;
}
bool OpenAICompatProvider::supportImage() const
{
return true;
} }
void OpenAICompatProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) void OpenAICompatProvider::cancelRequest(const PluginLLMCore::RequestID &requestId)

View File

@ -53,8 +53,7 @@ public:
void sendRequest( void sendRequest(
const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override; PluginLLMCore::ProviderCapabilities capabilities() const override;
bool supportImage() const override;
void cancelRequest(const PluginLLMCore::RequestID &requestId) override; void cancelRequest(const PluginLLMCore::RequestID &requestId) override;
::LLMCore::ToolsManager *toolsManager() const override; ::LLMCore::ToolsManager *toolsManager() const override;

View File

@ -254,14 +254,9 @@ void OpenAIProvider::sendRequest(
.arg(requestId, clientId, url.toString())); .arg(requestId, clientId, url.toString()));
} }
bool OpenAIProvider::supportsTools() const PluginLLMCore::ProviderCapabilities OpenAIProvider::capabilities() const
{ {
return true; return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image;
}
bool OpenAIProvider::supportImage() const
{
return true;
} }
void OpenAIProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) void OpenAIProvider::cancelRequest(const PluginLLMCore::RequestID &requestId)

View File

@ -53,8 +53,7 @@ public:
void sendRequest( void sendRequest(
const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override; PluginLLMCore::ProviderCapabilities capabilities() const override;
bool supportImage() const override;
void cancelRequest(const PluginLLMCore::RequestID &requestId) override; void cancelRequest(const PluginLLMCore::RequestID &requestId) override;
::LLMCore::ToolsManager *toolsManager() const override; ::LLMCore::ToolsManager *toolsManager() const override;

View File

@ -292,19 +292,10 @@ void OpenAIResponsesProvider::sendRequest(
.arg(requestId, clientId, url.toString())); .arg(requestId, clientId, url.toString()));
} }
bool OpenAIResponsesProvider::supportsTools() const PluginLLMCore::ProviderCapabilities OpenAIResponsesProvider::capabilities() const
{ {
return true; return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Thinking
} | PluginLLMCore::ProviderCapability::Image;
bool OpenAIResponsesProvider::supportImage() const
{
return true;
}
bool OpenAIResponsesProvider::supportThinking() const
{
return true;
} }
void OpenAIResponsesProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) void OpenAIResponsesProvider::cancelRequest(const PluginLLMCore::RequestID &requestId)

View File

@ -53,9 +53,7 @@ public:
void sendRequest( void sendRequest(
const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override; PluginLLMCore::ProviderCapabilities capabilities() const override;
bool supportImage() const override;
bool supportThinking() const override;
void cancelRequest(const PluginLLMCore::RequestID &requestId) override; void cancelRequest(const PluginLLMCore::RequestID &requestId) override;
::LLMCore::ToolsManager *toolsManager() const override; ::LLMCore::ToolsManager *toolsManager() const override;

View File

@ -369,7 +369,7 @@ TEST_F(DocumentContextReaderTest, testPrepareContext)
EXPECT_EQ( EXPECT_EQ(
reader.prepareContext(2, 3, *createSettingsForWholeFile()), reader.prepareContext(2, 3, *createSettingsForWholeFile()),
(ContextData{ (QodeAssist::PluginLLMCore::ContextData{
.prefix = "Line 0\nLine 1\nLin", .prefix = "Line 0\nLine 1\nLin",
.suffix = "e 2\nLine 3\nLine 4", .suffix = "e 2\nLine 3\nLine 4",
.fileContext = "\n Language: (MIME: text/python) filepath: /path/to/file()\n\n" .fileContext = "\n Language: (MIME: text/python) filepath: /path/to/file()\n\n"
@ -377,7 +377,7 @@ TEST_F(DocumentContextReaderTest, testPrepareContext)
EXPECT_EQ( EXPECT_EQ(
reader.prepareContext(2, 3, *createSettingsForLines(1, 1)), reader.prepareContext(2, 3, *createSettingsForLines(1, 1)),
(ContextData{ (QodeAssist::PluginLLMCore::ContextData{
.prefix = "Line 1\nLin", .prefix = "Line 1\nLin",
.suffix = "e 2\nLine 3", .suffix = "e 2\nLine 3",
.fileContext = "\n Language: (MIME: text/python) filepath: /path/to/file()\n\n" .fileContext = "\n Language: (MIME: text/python) filepath: /path/to/file()\n\n"
@ -385,7 +385,7 @@ TEST_F(DocumentContextReaderTest, testPrepareContext)
EXPECT_EQ( EXPECT_EQ(
reader.prepareContext(2, 3, *createSettingsForLines(2, 2)), reader.prepareContext(2, 3, *createSettingsForLines(2, 2)),
(ContextData{ (QodeAssist::PluginLLMCore::ContextData{
.prefix = "Line 0\nLine 1\nLin", .prefix = "Line 0\nLine 1\nLin",
.suffix = "e 2\nLine 3\nLine 4", .suffix = "e 2\nLine 3\nLine 4",
.fileContext = "\n Language: (MIME: text/python) filepath: /path/to/file()\n\n" .fileContext = "\n Language: (MIME: text/python) filepath: /path/to/file()\n\n"

View File

@ -18,7 +18,7 @@
*/ */
#include <iostream> #include <iostream>
#include <llmcore/ContextData.hpp> #include <pluginllmcore/ContextData.hpp>
#include <QString> #include <QString>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -61,14 +61,14 @@ std::ostream &operator<<(std::ostream &out, const std::optional<T> &value)
namespace QodeAssist::LLMCore { namespace QodeAssist::LLMCore {
inline std::ostream &operator<<(std::ostream &out, const Message &value) inline std::ostream &operator<<(std::ostream &out, const PluginLLMCore::Message &value)
{ {
out << "Message{" out << "Message{"
<< "role=" << value.role << "content=" << value.content << "}"; << "role=" << value.role << "content=" << value.content << "}";
return out; return out;
} }
inline std::ostream &operator<<(std::ostream &out, const ContextData &value) inline std::ostream &operator<<(std::ostream &out, const PluginLLMCore::ContextData &value)
{ {
out << "ContextData{" out << "ContextData{"
<< "\n systemPrompt=" << value.systemPrompt << "\n prefix=" << value.prefix << "\n systemPrompt=" << value.systemPrompt << "\n prefix=" << value.prefix