diff --git a/CMakeLists.txt b/CMakeLists.txt index 7168c53..c703d62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,8 +34,8 @@ add_definitions( -DQODEASSIST_QT_CREATOR_VERSION_PATCH=${QODEASSIST_QT_CREATOR_VERSION_PATCH} ) -add_subdirectory(pluginllmcore) add_subdirectory(sources/external/llmcore) +add_subdirectory(pluginllmcore) add_subdirectory(settings) add_subdirectory(logger) add_subdirectory(UIControls) @@ -62,8 +62,9 @@ add_qtc_plugin(QodeAssist QtCreator::ExtensionSystem QtCreator::Utils QtCreator::CPlusPlus - QodeAssistChatViewplugin LLMCore + PluginLLMCore + QodeAssistChatViewplugin SOURCES .github/workflows/build_cmake.yml .github/workflows/README.md diff --git a/ChatView/ChatCompressor.cpp b/ChatView/ChatCompressor.cpp index c9b0a94..4aa5966 100644 --- a/ChatView/ChatCompressor.cpp +++ b/ChatView/ChatCompressor.cpp @@ -18,6 +18,8 @@ */ #include "ChatCompressor.hpp" + +#include #include "ChatModel.hpp" #include "GeneralSettings.hpp" #include "PromptTemplateManager.hpp" @@ -76,7 +78,6 @@ void ChatCompressor::startCompression(const QString &chatFilePath, ChatModel *ch m_chatModel = chatModel; m_originalChatPath = chatFilePath; m_accumulatedSummary.clear(); - m_currentRequestId = QUuid::createUuid().toString(QUuid::WithoutBraces); emit compressionStarted(); @@ -98,8 +99,8 @@ void ChatCompressor::startCompression(const QString &chatFilePath, ChatModel *ch buildRequestPayload(payload, promptTemplate); + m_currentRequestId = m_provider->sendRequest(requestUrl, payload); LOG_MESSAGE(QString("Starting compression request: %1").arg(m_currentRequestId)); - m_provider->sendRequest(m_currentRequestId, requestUrl, payload); } bool ChatCompressor::isCompressing() const @@ -266,23 +267,25 @@ bool ChatCompressor::createCompressedChatFile( void ChatCompressor::connectProviderSignals() { + auto *c = m_provider->client(); + m_connections.append(connect( - m_provider, - &PluginLLMCore::Provider::partialResponseReceived, + c, + &::LLMCore::BaseClient::chunkReceived, this, &ChatCompressor::onPartialResponseReceived, Qt::UniqueConnection)); m_connections.append(connect( - m_provider, - &PluginLLMCore::Provider::fullResponseReceived, + c, + &::LLMCore::BaseClient::requestCompleted, this, &ChatCompressor::onFullResponseReceived, Qt::UniqueConnection)); m_connections.append(connect( - m_provider, - &PluginLLMCore::Provider::requestFailed, + c, + &::LLMCore::BaseClient::requestFailed, this, &ChatCompressor::onRequestFailed, Qt::UniqueConnection)); diff --git a/ChatView/ClientInterface.cpp b/ChatView/ClientInterface.cpp index ef92fe5..f95b9b0 100644 --- a/ChatView/ClientInterface.cpp +++ b/ChatView/ClientInterface.cpp @@ -19,6 +19,8 @@ #include "ClientInterface.hpp" +#include + #include #include #include @@ -274,63 +276,49 @@ void ClientInterface::sendMessage( useTools, useThinking); - QString requestId = QUuid::createUuid().toString(); + connect( + provider->client(), + &::LLMCore::BaseClient::chunkReceived, + this, + &ClientInterface::handlePartialResponse, + Qt::UniqueConnection); + connect( + provider->client(), + &::LLMCore::BaseClient::requestCompleted, + this, + &ClientInterface::handleFullResponse, + Qt::UniqueConnection); + connect( + provider->client(), + &::LLMCore::BaseClient::requestFailed, + this, + &ClientInterface::handleRequestFailed, + Qt::UniqueConnection); + connect( + provider->client(), + &::LLMCore::BaseClient::toolStarted, + this, + &ClientInterface::handleToolExecutionStarted, + Qt::UniqueConnection); + connect( + provider->client(), + &::LLMCore::BaseClient::toolResultReady, + this, + &ClientInterface::handleToolExecutionCompleted, + Qt::UniqueConnection); + connect( + provider->client(), + &::LLMCore::BaseClient::thinkingBlockReceived, + this, + &ClientInterface::handleThinkingBlockReceived, + Qt::UniqueConnection); + + auto requestId = provider->sendRequest(config.url, config.providerRequest); QJsonObject request{{"id", requestId}}; m_activeRequests[requestId] = {request, provider}; emit requestStarted(requestId); - - connect( - provider, - &PluginLLMCore::Provider::partialResponseReceived, - this, - &ClientInterface::handlePartialResponse, - Qt::UniqueConnection); - connect( - provider, - &PluginLLMCore::Provider::fullResponseReceived, - this, - &ClientInterface::handleFullResponse, - Qt::UniqueConnection); - connect( - provider, - &PluginLLMCore::Provider::requestFailed, - this, - &ClientInterface::handleRequestFailed, - Qt::UniqueConnection); - connect( - provider, - &PluginLLMCore::Provider::toolExecutionStarted, - this, - &ClientInterface::handleToolExecutionStarted, - Qt::UniqueConnection); - connect( - provider, - &PluginLLMCore::Provider::toolExecutionCompleted, - this, - &ClientInterface::handleToolExecutionCompleted, - Qt::UniqueConnection); - connect( - provider, - &PluginLLMCore::Provider::continuationStarted, - this, - &ClientInterface::handleCleanAccumulatedData, - Qt::UniqueConnection); - connect( - provider, - &PluginLLMCore::Provider::thinkingBlockReceived, - this, - &ClientInterface::handleThinkingBlockReceived, - Qt::UniqueConnection); - connect( - provider, - &PluginLLMCore::Provider::redactedThinkingBlockReceived, - this, - &ClientInterface::handleRedactedThinkingBlockReceived, - Qt::UniqueConnection); - - provider->sendRequest(requestId, config.url, config.providerRequest); if (provider->capabilities().testFlag(PluginLLMCore::ProviderCapability::Tools) && provider->toolsManager()) { @@ -368,7 +356,7 @@ void ClientInterface::cancelRequest() } for (auto *provider : providers) { - disconnect(provider, nullptr, this, nullptr); + disconnect(provider->client(), nullptr, this, nullptr); } for (auto it = m_activeRequests.begin(); it != m_activeRequests.end(); ++it) { @@ -380,6 +368,7 @@ void ClientInterface::cancelRequest() m_activeRequests.clear(); m_accumulatedResponses.clear(); + m_awaitingContinuation.clear(); LOG_MESSAGE("All requests cancelled and state cleared"); } @@ -446,6 +435,12 @@ void ClientInterface::handlePartialResponse(const QString &requestId, const QStr if (it == m_activeRequests.end()) return; + if (m_awaitingContinuation.remove(requestId)) { + m_accumulatedResponses[requestId].clear(); + LOG_MESSAGE( + QString("Cleared accumulated responses for continuation request %1").arg(requestId)); + } + m_accumulatedResponses[requestId] += partialText; const RequestContext &ctx = it.value(); @@ -476,12 +471,9 @@ void ClientInterface::handleFullResponse(const QString &requestId, const QString + ": " + finalText); emit messageReceivedCompletely(); - if (it != m_activeRequests.end()) { - m_activeRequests.erase(it); - } - if (m_accumulatedResponses.contains(requestId)) { - m_accumulatedResponses.remove(requestId); - } + m_activeRequests.erase(it); + m_accumulatedResponses.remove(requestId); + m_awaitingContinuation.remove(requestId); } void ClientInterface::handleRequestFailed(const QString &requestId, const QString &error) @@ -493,18 +485,9 @@ void ClientInterface::handleRequestFailed(const QString &requestId, const QStrin LOG_MESSAGE(QString("Chat request %1 failed: %2").arg(requestId, error)); emit errorOccurred(error); - if (it != m_activeRequests.end()) { - m_activeRequests.erase(it); - } - if (m_accumulatedResponses.contains(requestId)) { - m_accumulatedResponses.remove(requestId); - } -} - -void ClientInterface::handleCleanAccumulatedData(const QString &requestId) -{ - m_accumulatedResponses[requestId].clear(); - LOG_MESSAGE(QString("Cleared accumulated responses for continuation request %1").arg(requestId)); + m_activeRequests.erase(it); + m_accumulatedResponses.remove(requestId); + m_awaitingContinuation.remove(requestId); } void ClientInterface::handleThinkingBlockReceived( @@ -515,19 +498,17 @@ void ClientInterface::handleThinkingBlockReceived( return; } - m_chatModel->addThinkingBlock(requestId, thinking, signature); -} - -void ClientInterface::handleRedactedThinkingBlockReceived( - const QString &requestId, const QString &signature) -{ - if (!m_activeRequests.contains(requestId)) { + if (m_awaitingContinuation.remove(requestId)) { + m_accumulatedResponses[requestId].clear(); LOG_MESSAGE( - QString("Ignoring redacted thinking block for non-chat request: %1").arg(requestId)); - return; + QString("Cleared accumulated responses for continuation request %1").arg(requestId)); } - m_chatModel->addRedactedThinkingBlock(requestId, signature); + if (thinking.isEmpty()) { + m_chatModel->addRedactedThinkingBlock(requestId, signature); + } else { + m_chatModel->addThinkingBlock(requestId, thinking, signature); + } } void ClientInterface::handleToolExecutionStarted( @@ -539,6 +520,7 @@ void ClientInterface::handleToolExecutionStarted( } m_chatModel->addToolExecutionStatus(requestId, toolId, toolName); + m_awaitingContinuation.insert(requestId); } void ClientInterface::handleToolExecutionCompleted( diff --git a/ChatView/ClientInterface.hpp b/ChatView/ClientInterface.hpp index 131f6e1..912b2ae 100644 --- a/ChatView/ClientInterface.hpp +++ b/ChatView/ClientInterface.hpp @@ -20,6 +20,7 @@ #pragma once #include +#include #include #include @@ -62,10 +63,8 @@ private slots: void handlePartialResponse(const QString &requestId, const QString &partialText); void handleFullResponse(const QString &requestId, const QString &fullText); void handleRequestFailed(const QString &requestId, const QString &error); - void handleCleanAccumulatedData(const QString &requestId); void handleThinkingBlockReceived( const QString &requestId, const QString &thinking, const QString &signature); - void handleRedactedThinkingBlockReceived(const QString &requestId, const QString &signature); void handleToolExecutionStarted( const QString &requestId, const QString &toolId, const QString &toolName); void handleToolExecutionCompleted( @@ -97,6 +96,7 @@ private: QHash m_activeRequests; QHash m_accumulatedResponses; + QSet m_awaitingContinuation; }; } // namespace QodeAssist::Chat diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index 5914603..f5461e6 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -19,6 +19,7 @@ #include "LLMClientInterface.hpp" +#include #include #include #include @@ -122,8 +123,6 @@ void LLMClientInterface::sendData(const QByteArray &data) } else if (method == "textDocument/didOpen") { handleTextDocumentDidOpen(request); } else if (method == "getCompletionsCycling") { - QString requestId = request["id"].toString(); - m_performanceLogger.startTimeMeasurement(requestId); handleCompletion(request); } else if (method == "$/cancelRequest") { handleCancelRequest(); @@ -144,7 +143,7 @@ void LLMClientInterface::handleCancelRequest() } for (auto *provider : providers) { - disconnect(provider, nullptr, this, nullptr); + disconnect(provider->client(), nullptr, this, nullptr); } for (auto it = m_activeRequests.begin(); it != m_activeRequests.end(); ++it) { @@ -360,25 +359,22 @@ void LLMClientInterface::handleCompletion(const QJsonObject &request) return; } - QString requestId = request["id"].toString(); - m_performanceLogger.startTimeMeasurement(requestId); - - m_activeRequests[requestId] = {request, provider}; - connect( - provider, - &PluginLLMCore::Provider::fullResponseReceived, + provider->client(), + &::LLMCore::BaseClient::requestCompleted, this, &LLMClientInterface::handleFullResponse, Qt::UniqueConnection); connect( - provider, - &PluginLLMCore::Provider::requestFailed, + provider->client(), + &::LLMCore::BaseClient::requestFailed, this, &LLMClientInterface::handleRequestFailed, Qt::UniqueConnection); - provider->sendRequest(requestId, config.url, config.providerRequest); + auto requestId = provider->sendRequest(config.url, config.providerRequest); + m_activeRequests[requestId] = {request, provider}; + m_performanceLogger.startTimeMeasurement(requestId); } PluginLLMCore::ContextData LLMClientInterface::prepareContext( diff --git a/QuickRefactorHandler.cpp b/QuickRefactorHandler.cpp index 67eb7e5..b96124d 100644 --- a/QuickRefactorHandler.cpp +++ b/QuickRefactorHandler.cpp @@ -19,6 +19,7 @@ #include "QuickRefactorHandler.hpp" +#include #include #include #include @@ -173,29 +174,27 @@ void QuickRefactorHandler::prepareAndSendRequest( enableTools, enableThinking); - QString requestId = QUuid::createUuid().toString(); - m_lastRequestId = requestId; - QJsonObject request{{"id", requestId}}; - m_isRefactoringInProgress = true; - m_activeRequests[requestId] = {request, provider}; - connect( - provider, - &PluginLLMCore::Provider::fullResponseReceived, + provider->client(), + &::LLMCore::BaseClient::requestCompleted, this, &QuickRefactorHandler::handleFullResponse, Qt::UniqueConnection); connect( - provider, - &PluginLLMCore::Provider::requestFailed, + provider->client(), + &::LLMCore::BaseClient::requestFailed, this, &QuickRefactorHandler::handleRequestFailed, Qt::UniqueConnection); - provider->sendRequest(requestId, config.url, config.providerRequest); + auto requestId = provider->sendRequest(config.url, config.providerRequest); + m_lastRequestId = requestId; + QJsonObject request{{"id", requestId}}; + + m_activeRequests[requestId] = {request, provider}; } PluginLLMCore::ContextData QuickRefactorHandler::prepareContext( diff --git a/pluginllmcore/CMakeLists.txt b/pluginllmcore/CMakeLists.txt index a2ea5df..a2e2222 100644 --- a/pluginllmcore/CMakeLists.txt +++ b/pluginllmcore/CMakeLists.txt @@ -28,6 +28,7 @@ target_link_libraries(PluginLLMCore QtCreator::Core QtCreator::Utils QtCreator::ExtensionSystem + LLMCore PRIVATE QodeAssistLogger ) diff --git a/pluginllmcore/Provider.cpp b/pluginllmcore/Provider.cpp index e5274f6..fd2e03b 100644 --- a/pluginllmcore/Provider.cpp +++ b/pluginllmcore/Provider.cpp @@ -1,9 +1,61 @@ +/* + * Copyright (C) 2024-2025 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + #include "Provider.hpp" +#include +#include + +#include + namespace QodeAssist::PluginLLMCore { Provider::Provider(QObject *parent) : QObject(parent) {} +RequestID Provider::sendRequest(const QUrl &url, const QJsonObject &payload) +{ + auto *c = client(); + + QUrl baseUrl(url); + baseUrl.setPath(""); + c->setUrl(baseUrl.toString()); + c->setApiKey(apiKey()); + + auto requestId = c->sendMessage(payload); + + LOG_MESSAGE( + QString("%1: Sending request %2 to %3").arg(name(), requestId, url.toString())); + + return requestId; +} + +void Provider::cancelRequest(const RequestID &requestId) +{ + LOG_MESSAGE(QString("%1: Cancelling request %2").arg(name(), requestId)); + client()->cancelRequest(requestId); +} + +::LLMCore::ToolsManager *Provider::toolsManager() const +{ + return client()->tools(); +} + } // namespace QodeAssist::PluginLLMCore diff --git a/pluginllmcore/Provider.hpp b/pluginllmcore/Provider.hpp index 9a63215..f33f84b 100644 --- a/pluginllmcore/Provider.hpp +++ b/pluginllmcore/Provider.hpp @@ -21,10 +21,10 @@ #include #include -#include #include #include #include +#include #include "ContextData.hpp" #include "IToolsManager.hpp" @@ -32,6 +32,7 @@ #include "RequestType.hpp" namespace LLMCore { +class BaseClient; class ToolsManager; } @@ -73,34 +74,13 @@ public: virtual QString apiKey() const = 0; virtual void prepareNetworkRequest(QNetworkRequest &networkRequest) const = 0; virtual ProviderID providerID() const = 0; - - virtual void sendRequest(const RequestID &requestId, const QUrl &url, const QJsonObject &payload) - = 0; - virtual ProviderCapabilities capabilities() const { return {}; } - virtual void cancelRequest(const RequestID &requestId) = 0; - - virtual ::LLMCore::ToolsManager *toolsManager() const { return nullptr; } - -signals: - void partialResponseReceived( - const QodeAssist::PluginLLMCore::RequestID &requestId, const QString &partialText); - void fullResponseReceived( - const QodeAssist::PluginLLMCore::RequestID &requestId, const QString &fullText); - void requestFailed(const QodeAssist::PluginLLMCore::RequestID &requestId, const QString &error); - void toolExecutionStarted( - const QString &requestId, const QString &toolId, const QString &toolName); - void toolExecutionCompleted( - const QString &requestId, - const QString &toolId, - const QString &toolName, - const QString &result); - void continuationStarted(const QodeAssist::PluginLLMCore::RequestID &requestId); - void thinkingBlockReceived( - const QString &requestId, const QString &thinking, const QString &signature); - void redactedThinkingBlockReceived(const QString &requestId, const QString &signature); + virtual ::LLMCore::BaseClient *client() const = 0; + RequestID sendRequest(const QUrl &url, const QJsonObject &payload); + void cancelRequest(const RequestID &requestId); + ::LLMCore::ToolsManager *toolsManager() const; }; } // namespace QodeAssist::PluginLLMCore diff --git a/providers/ClaudeProvider.cpp b/providers/ClaudeProvider.cpp index 127430b..49aecf5 100644 --- a/providers/ClaudeProvider.cpp +++ b/providers/ClaudeProvider.cpp @@ -176,74 +176,6 @@ PluginLLMCore::ProviderID ClaudeProvider::providerID() const return PluginLLMCore::ProviderID::Claude; } -void ClaudeProvider::sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) -{ - QUrl baseUrl(url); - baseUrl.setPath(""); - m_client->setUrl(baseUrl.toString()); - m_client->setApiKey(apiKey()); - - ::LLMCore::RequestCallbacks callbacks; - - callbacks.onChunk = [this, requestId](const ::LLMCore::RequestID &, const QString &chunk) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - emit partialResponseReceived(requestId, chunk); - }; - - callbacks.onCompleted - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &fullText) { - emit fullResponseReceived(requestId, fullText); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onFailed - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &error) { - emit requestFailed(requestId, error); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onThinkingBlock = [this, requestId](const ::LLMCore::RequestID &, - const QString &thinking, - const QString &signature) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - if (thinking.isEmpty()) { - emit redactedThinkingBlockReceived(requestId, signature); - } else { - emit thinkingBlockReceived(requestId, thinking, signature); - } - }; - - callbacks.onToolStarted = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName) { - emit toolExecutionStarted(requestId, toolId, toolName); - m_awaitingContinuation.insert(requestId); - }; - - callbacks.onToolResult = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName, - const QString &result) { - emit toolExecutionCompleted(requestId, toolId, toolName, result); - }; - - auto clientId = m_client->sendMessage(payload, callbacks); - m_providerToClientIds[requestId] = clientId; - m_clientToProviderIds[clientId] = requestId; - - LOG_MESSAGE(QString("ClaudeProvider: Sending request %1 (client: %2) to %3") - .arg(requestId, clientId, url.toString())); -} - PluginLLMCore::ProviderCapabilities ClaudeProvider::capabilities() const { return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Thinking @@ -251,21 +183,9 @@ PluginLLMCore::ProviderCapabilities ClaudeProvider::capabilities() const | PluginLLMCore::ProviderCapability::ModelListing; } -void ClaudeProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) +::LLMCore::BaseClient *ClaudeProvider::client() const { - LOG_MESSAGE(QString("ClaudeProvider: Cancelling request %1").arg(requestId)); - - if (m_providerToClientIds.contains(requestId)) { - auto clientId = m_providerToClientIds.take(requestId); - m_clientToProviderIds.remove(clientId); - m_client->cancelRequest(clientId); - } - m_awaitingContinuation.remove(requestId); -} - -::LLMCore::ToolsManager *ClaudeProvider::toolsManager() const -{ - return m_client->tools(); + return m_client; } } // namespace QodeAssist::Providers diff --git a/providers/ClaudeProvider.hpp b/providers/ClaudeProvider.hpp index 2e78a64..2d0250c 100644 --- a/providers/ClaudeProvider.hpp +++ b/providers/ClaudeProvider.hpp @@ -19,8 +19,6 @@ #pragma once -#include - #include #include @@ -49,20 +47,12 @@ public: QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; PluginLLMCore::ProviderID providerID() const override; - - void sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; - PluginLLMCore::ProviderCapabilities capabilities() const override; - void cancelRequest(const PluginLLMCore::RequestID &requestId) override; - ::LLMCore::ToolsManager *toolsManager() const override; + ::LLMCore::BaseClient *client() const override; private: ::LLMCore::ClaudeClient *m_client; - QHash m_providerToClientIds; - QHash<::LLMCore::RequestID, PluginLLMCore::RequestID> m_clientToProviderIds; - QSet m_awaitingContinuation; }; } // namespace QodeAssist::Providers diff --git a/providers/GoogleAIProvider.cpp b/providers/GoogleAIProvider.cpp index 8acc99d..5cdd6b7 100644 --- a/providers/GoogleAIProvider.cpp +++ b/providers/GoogleAIProvider.cpp @@ -192,74 +192,6 @@ PluginLLMCore::ProviderID GoogleAIProvider::providerID() const return PluginLLMCore::ProviderID::GoogleAI; } -void GoogleAIProvider::sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) -{ - QUrl baseUrl(url); - baseUrl.setPath(""); - m_client->setUrl(baseUrl.toString()); - m_client->setApiKey(apiKey()); - - ::LLMCore::RequestCallbacks callbacks; - - callbacks.onChunk = [this, requestId](const ::LLMCore::RequestID &, const QString &chunk) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - emit partialResponseReceived(requestId, chunk); - }; - - callbacks.onCompleted - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &fullText) { - emit fullResponseReceived(requestId, fullText); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onFailed - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &error) { - emit requestFailed(requestId, error); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onThinkingBlock = [this, requestId](const ::LLMCore::RequestID &, - const QString &thinking, - const QString &signature) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - if (thinking.isEmpty()) { - emit redactedThinkingBlockReceived(requestId, signature); - } else { - emit thinkingBlockReceived(requestId, thinking, signature); - } - }; - - callbacks.onToolStarted = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName) { - emit toolExecutionStarted(requestId, toolId, toolName); - m_awaitingContinuation.insert(requestId); - }; - - callbacks.onToolResult = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName, - const QString &result) { - emit toolExecutionCompleted(requestId, toolId, toolName, result); - }; - - auto clientId = m_client->sendMessage(payload, callbacks); - m_providerToClientIds[requestId] = clientId; - m_clientToProviderIds[clientId] = requestId; - - LOG_MESSAGE(QString("GoogleAIProvider: Sending request %1 (client: %2) to %3") - .arg(requestId, clientId, url.toString())); -} - PluginLLMCore::ProviderCapabilities GoogleAIProvider::capabilities() const { return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Thinking @@ -267,21 +199,9 @@ PluginLLMCore::ProviderCapabilities GoogleAIProvider::capabilities() const | PluginLLMCore::ProviderCapability::ModelListing; } -void GoogleAIProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) +::LLMCore::BaseClient *GoogleAIProvider::client() const { - LOG_MESSAGE(QString("GoogleAIProvider: Cancelling request %1").arg(requestId)); - - if (m_providerToClientIds.contains(requestId)) { - auto clientId = m_providerToClientIds.take(requestId); - m_clientToProviderIds.remove(clientId); - m_client->cancelRequest(clientId); - } - m_awaitingContinuation.remove(requestId); -} - -::LLMCore::ToolsManager *GoogleAIProvider::toolsManager() const -{ - return m_client->tools(); + return m_client; } } // namespace QodeAssist::Providers diff --git a/providers/GoogleAIProvider.hpp b/providers/GoogleAIProvider.hpp index a0037b3..fe99de2 100644 --- a/providers/GoogleAIProvider.hpp +++ b/providers/GoogleAIProvider.hpp @@ -19,8 +19,6 @@ #pragma once -#include - #include #include @@ -49,20 +47,12 @@ public: QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; PluginLLMCore::ProviderID providerID() const override; - - void sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; - PluginLLMCore::ProviderCapabilities capabilities() const override; - void cancelRequest(const PluginLLMCore::RequestID &requestId) override; - ::LLMCore::ToolsManager *toolsManager() const override; + ::LLMCore::BaseClient *client() const override; private: ::LLMCore::GoogleAIClient *m_client; - QHash m_providerToClientIds; - QHash<::LLMCore::RequestID, PluginLLMCore::RequestID> m_clientToProviderIds; - QSet m_awaitingContinuation; }; } // namespace QodeAssist::Providers diff --git a/providers/LMStudioProvider.cpp b/providers/LMStudioProvider.cpp index 744ad0f..bc39a47 100644 --- a/providers/LMStudioProvider.cpp +++ b/providers/LMStudioProvider.cpp @@ -104,92 +104,12 @@ PluginLLMCore::ProviderID LMStudioProvider::providerID() const return PluginLLMCore::ProviderID::LMStudio; } -void LMStudioProvider::sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) -{ - QUrl baseUrl(url); - baseUrl.setPath(""); - m_client->setUrl(baseUrl.toString()); - m_client->setApiKey(apiKey()); - - ::LLMCore::RequestCallbacks callbacks; - - callbacks.onChunk = [this, requestId](const ::LLMCore::RequestID &, const QString &chunk) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - emit partialResponseReceived(requestId, chunk); - }; - - callbacks.onCompleted - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &fullText) { - emit fullResponseReceived(requestId, fullText); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onFailed - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &error) { - emit requestFailed(requestId, error); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onThinkingBlock = [this, requestId](const ::LLMCore::RequestID &, - const QString &thinking, - const QString &signature) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - if (thinking.isEmpty()) { - emit redactedThinkingBlockReceived(requestId, signature); - } else { - emit thinkingBlockReceived(requestId, thinking, signature); - } - }; - - callbacks.onToolStarted = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName) { - emit toolExecutionStarted(requestId, toolId, toolName); - m_awaitingContinuation.insert(requestId); - }; - - callbacks.onToolResult = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName, - const QString &result) { - emit toolExecutionCompleted(requestId, toolId, toolName, result); - }; - - auto clientId = m_client->sendMessage(payload, callbacks); - m_providerToClientIds[requestId] = clientId; - m_clientToProviderIds[clientId] = requestId; - - LOG_MESSAGE(QString("LMStudioProvider: Sending request %1 (client: %2) to %3") - .arg(requestId, clientId, url.toString())); -} - PluginLLMCore::ProviderCapabilities LMStudioProvider::capabilities() const { return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image | PluginLLMCore::ProviderCapability::ModelListing; } -void LMStudioProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) -{ - LOG_MESSAGE(QString("LMStudioProvider: Cancelling request %1").arg(requestId)); - - if (m_providerToClientIds.contains(requestId)) { - auto clientId = m_providerToClientIds.take(requestId); - m_clientToProviderIds.remove(clientId); - m_client->cancelRequest(clientId); - } - m_awaitingContinuation.remove(requestId); -} - void LMStudioProvider::prepareRequest( QJsonObject &request, PluginLLMCore::PromptTemplate *prompt, @@ -235,9 +155,9 @@ void LMStudioProvider::prepareRequest( } } -::LLMCore::ToolsManager *LMStudioProvider::toolsManager() const +::LLMCore::BaseClient *LMStudioProvider::client() const { - return m_client->tools(); + return m_client; } } // namespace QodeAssist::Providers diff --git a/providers/LMStudioProvider.hpp b/providers/LMStudioProvider.hpp index 3bad21f..3145170 100644 --- a/providers/LMStudioProvider.hpp +++ b/providers/LMStudioProvider.hpp @@ -19,8 +19,6 @@ #pragma once -#include - #include #include @@ -48,20 +46,12 @@ public: QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; PluginLLMCore::ProviderID providerID() const override; - - void sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; - PluginLLMCore::ProviderCapabilities capabilities() const override; - void cancelRequest(const PluginLLMCore::RequestID &requestId) override; - ::LLMCore::ToolsManager *toolsManager() const override; + ::LLMCore::BaseClient *client() const override; private: ::LLMCore::OpenAIClient *m_client; - QHash m_providerToClientIds; - QHash<::LLMCore::RequestID, PluginLLMCore::RequestID> m_clientToProviderIds; - QSet m_awaitingContinuation; }; } // namespace QodeAssist::Providers diff --git a/providers/LlamaCppProvider.cpp b/providers/LlamaCppProvider.cpp index b53c7a1..ad3140e 100644 --- a/providers/LlamaCppProvider.cpp +++ b/providers/LlamaCppProvider.cpp @@ -164,94 +164,14 @@ PluginLLMCore::ProviderID LlamaCppProvider::providerID() const return PluginLLMCore::ProviderID::LlamaCpp; } -void LlamaCppProvider::sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) -{ - QUrl baseUrl(url); - baseUrl.setPath(""); - m_client->setUrl(baseUrl.toString()); - m_client->setApiKey(apiKey()); - - ::LLMCore::RequestCallbacks callbacks; - - callbacks.onChunk = [this, requestId](const ::LLMCore::RequestID &, const QString &chunk) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - emit partialResponseReceived(requestId, chunk); - }; - - callbacks.onCompleted - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &fullText) { - emit fullResponseReceived(requestId, fullText); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onFailed - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &error) { - emit requestFailed(requestId, error); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onThinkingBlock = [this, requestId](const ::LLMCore::RequestID &, - const QString &thinking, - const QString &signature) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - if (thinking.isEmpty()) { - emit redactedThinkingBlockReceived(requestId, signature); - } else { - emit thinkingBlockReceived(requestId, thinking, signature); - } - }; - - callbacks.onToolStarted = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName) { - emit toolExecutionStarted(requestId, toolId, toolName); - m_awaitingContinuation.insert(requestId); - }; - - callbacks.onToolResult = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName, - const QString &result) { - emit toolExecutionCompleted(requestId, toolId, toolName, result); - }; - - auto clientId = m_client->sendMessage(payload, callbacks); - m_providerToClientIds[requestId] = clientId; - m_clientToProviderIds[clientId] = requestId; - - LOG_MESSAGE(QString("LlamaCppProvider: Sending request %1 (client: %2) to %3") - .arg(requestId, clientId, url.toString())); -} - PluginLLMCore::ProviderCapabilities LlamaCppProvider::capabilities() const { return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image; } -void LlamaCppProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) +::LLMCore::BaseClient *LlamaCppProvider::client() const { - LOG_MESSAGE(QString("LlamaCppProvider: Cancelling request %1").arg(requestId)); - - if (m_providerToClientIds.contains(requestId)) { - auto clientId = m_providerToClientIds.take(requestId); - m_clientToProviderIds.remove(clientId); - m_client->cancelRequest(clientId); - } - m_awaitingContinuation.remove(requestId); -} - -::LLMCore::ToolsManager *LlamaCppProvider::toolsManager() const -{ - return m_client->tools(); + return m_client; } } // namespace QodeAssist::Providers diff --git a/providers/LlamaCppProvider.hpp b/providers/LlamaCppProvider.hpp index 50dc1e6..8924d24 100644 --- a/providers/LlamaCppProvider.hpp +++ b/providers/LlamaCppProvider.hpp @@ -19,8 +19,6 @@ #pragma once -#include - #include #include @@ -49,20 +47,12 @@ public: QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; PluginLLMCore::ProviderID providerID() const override; - - void sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; - PluginLLMCore::ProviderCapabilities capabilities() const override; - void cancelRequest(const PluginLLMCore::RequestID &requestId) override; - ::LLMCore::ToolsManager *toolsManager() const override; + ::LLMCore::BaseClient *client() const override; private: ::LLMCore::LlamaCppClient *m_client; - QHash m_providerToClientIds; - QHash<::LLMCore::RequestID, PluginLLMCore::RequestID> m_clientToProviderIds; - QSet m_awaitingContinuation; }; } // namespace QodeAssist::Providers diff --git a/providers/MistralAIProvider.cpp b/providers/MistralAIProvider.cpp index b914f1b..6b09374 100644 --- a/providers/MistralAIProvider.cpp +++ b/providers/MistralAIProvider.cpp @@ -116,92 +116,12 @@ PluginLLMCore::ProviderID MistralAIProvider::providerID() const return PluginLLMCore::ProviderID::MistralAI; } -void MistralAIProvider::sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) -{ - QUrl baseUrl(url); - baseUrl.setPath(""); - m_client->setUrl(baseUrl.toString()); - m_client->setApiKey(apiKey()); - - ::LLMCore::RequestCallbacks callbacks; - - callbacks.onChunk = [this, requestId](const ::LLMCore::RequestID &, const QString &chunk) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - emit partialResponseReceived(requestId, chunk); - }; - - callbacks.onCompleted - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &fullText) { - emit fullResponseReceived(requestId, fullText); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onFailed - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &error) { - emit requestFailed(requestId, error); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onThinkingBlock = [this, requestId](const ::LLMCore::RequestID &, - const QString &thinking, - const QString &signature) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - if (thinking.isEmpty()) { - emit redactedThinkingBlockReceived(requestId, signature); - } else { - emit thinkingBlockReceived(requestId, thinking, signature); - } - }; - - callbacks.onToolStarted = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName) { - emit toolExecutionStarted(requestId, toolId, toolName); - m_awaitingContinuation.insert(requestId); - }; - - callbacks.onToolResult = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName, - const QString &result) { - emit toolExecutionCompleted(requestId, toolId, toolName, result); - }; - - auto clientId = m_client->sendMessage(payload, callbacks); - m_providerToClientIds[requestId] = clientId; - m_clientToProviderIds[clientId] = requestId; - - LOG_MESSAGE(QString("MistralAIProvider: Sending request %1 (client: %2) to %3") - .arg(requestId, clientId, url.toString())); -} - PluginLLMCore::ProviderCapabilities MistralAIProvider::capabilities() const { return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image | PluginLLMCore::ProviderCapability::ModelListing; } -void MistralAIProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) -{ - LOG_MESSAGE(QString("MistralAIProvider: Cancelling request %1").arg(requestId)); - - if (m_providerToClientIds.contains(requestId)) { - auto clientId = m_providerToClientIds.take(requestId); - m_clientToProviderIds.remove(clientId); - m_client->cancelRequest(clientId); - } - m_awaitingContinuation.remove(requestId); -} - void MistralAIProvider::prepareRequest( QJsonObject &request, PluginLLMCore::PromptTemplate *prompt, @@ -247,9 +167,9 @@ void MistralAIProvider::prepareRequest( } } -::LLMCore::ToolsManager *MistralAIProvider::toolsManager() const +::LLMCore::BaseClient *MistralAIProvider::client() const { - return m_client->tools(); + return m_client; } } // namespace QodeAssist::Providers diff --git a/providers/MistralAIProvider.hpp b/providers/MistralAIProvider.hpp index 7ed9222..f7ff0b5 100644 --- a/providers/MistralAIProvider.hpp +++ b/providers/MistralAIProvider.hpp @@ -19,8 +19,6 @@ #pragma once -#include - #include #include @@ -48,20 +46,12 @@ public: QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; PluginLLMCore::ProviderID providerID() const override; - - void sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; - PluginLLMCore::ProviderCapabilities capabilities() const override; - void cancelRequest(const PluginLLMCore::RequestID &requestId) override; - ::LLMCore::ToolsManager *toolsManager() const override; + ::LLMCore::BaseClient *client() const override; private: ::LLMCore::OpenAIClient *m_client; - QHash m_providerToClientIds; - QHash<::LLMCore::RequestID, PluginLLMCore::RequestID> m_clientToProviderIds; - QSet m_awaitingContinuation; }; } // namespace QodeAssist::Providers diff --git a/providers/OllamaProvider.cpp b/providers/OllamaProvider.cpp index 22d4580..a6091a0 100644 --- a/providers/OllamaProvider.cpp +++ b/providers/OllamaProvider.cpp @@ -199,74 +199,6 @@ PluginLLMCore::ProviderID OllamaProvider::providerID() const return PluginLLMCore::ProviderID::Ollama; } -void OllamaProvider::sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) -{ - QUrl baseUrl(url); - baseUrl.setPath(""); - m_client->setUrl(baseUrl.toString()); - m_client->setApiKey(apiKey()); - - ::LLMCore::RequestCallbacks callbacks; - - callbacks.onChunk = [this, requestId](const ::LLMCore::RequestID &, const QString &chunk) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - emit partialResponseReceived(requestId, chunk); - }; - - callbacks.onCompleted - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &fullText) { - emit fullResponseReceived(requestId, fullText); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onFailed - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &error) { - emit requestFailed(requestId, error); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onThinkingBlock = [this, requestId](const ::LLMCore::RequestID &, - const QString &thinking, - const QString &signature) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - if (thinking.isEmpty()) { - emit redactedThinkingBlockReceived(requestId, signature); - } else { - emit thinkingBlockReceived(requestId, thinking, signature); - } - }; - - callbacks.onToolStarted = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName) { - emit toolExecutionStarted(requestId, toolId, toolName); - m_awaitingContinuation.insert(requestId); - }; - - callbacks.onToolResult = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName, - const QString &result) { - emit toolExecutionCompleted(requestId, toolId, toolName, result); - }; - - auto clientId = m_client->sendMessage(payload, callbacks); - m_providerToClientIds[requestId] = clientId; - m_clientToProviderIds[clientId] = requestId; - - LOG_MESSAGE(QString("OllamaProvider: Sending request %1 (client: %2) to %3") - .arg(requestId, clientId, url.toString())); -} - PluginLLMCore::ProviderCapabilities OllamaProvider::capabilities() const { return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Thinking @@ -274,21 +206,9 @@ PluginLLMCore::ProviderCapabilities OllamaProvider::capabilities() const | PluginLLMCore::ProviderCapability::ModelListing; } -void OllamaProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) +::LLMCore::BaseClient *OllamaProvider::client() const { - LOG_MESSAGE(QString("OllamaProvider: Cancelling request %1").arg(requestId)); - - if (m_providerToClientIds.contains(requestId)) { - auto clientId = m_providerToClientIds.take(requestId); - m_clientToProviderIds.remove(clientId); - m_client->cancelRequest(clientId); - } - m_awaitingContinuation.remove(requestId); -} - -::LLMCore::ToolsManager *OllamaProvider::toolsManager() const -{ - return m_client->tools(); + return m_client; } } // namespace QodeAssist::Providers diff --git a/providers/OllamaProvider.hpp b/providers/OllamaProvider.hpp index d28164b..63e5db5 100644 --- a/providers/OllamaProvider.hpp +++ b/providers/OllamaProvider.hpp @@ -19,8 +19,6 @@ #pragma once -#include - #include #include @@ -49,20 +47,12 @@ public: QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; PluginLLMCore::ProviderID providerID() const override; - - void sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; - PluginLLMCore::ProviderCapabilities capabilities() const override; - void cancelRequest(const PluginLLMCore::RequestID &requestId) override; - ::LLMCore::ToolsManager *toolsManager() const override; + ::LLMCore::BaseClient *client() const override; private: ::LLMCore::OllamaClient *m_client; - QHash m_providerToClientIds; - QHash<::LLMCore::RequestID, PluginLLMCore::RequestID> m_clientToProviderIds; - QSet m_awaitingContinuation; }; } // namespace QodeAssist::Providers diff --git a/providers/OpenAICompatProvider.cpp b/providers/OpenAICompatProvider.cpp index bb1d2d1..f3b92d5 100644 --- a/providers/OpenAICompatProvider.cpp +++ b/providers/OpenAICompatProvider.cpp @@ -151,94 +151,14 @@ PluginLLMCore::ProviderID OpenAICompatProvider::providerID() const return PluginLLMCore::ProviderID::OpenAICompatible; } -void OpenAICompatProvider::sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) -{ - QUrl baseUrl(url); - baseUrl.setPath(""); - m_client->setUrl(baseUrl.toString()); - m_client->setApiKey(apiKey()); - - ::LLMCore::RequestCallbacks callbacks; - - callbacks.onChunk = [this, requestId](const ::LLMCore::RequestID &, const QString &chunk) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - emit partialResponseReceived(requestId, chunk); - }; - - callbacks.onCompleted - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &fullText) { - emit fullResponseReceived(requestId, fullText); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onFailed - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &error) { - emit requestFailed(requestId, error); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onThinkingBlock = [this, requestId](const ::LLMCore::RequestID &, - const QString &thinking, - const QString &signature) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - if (thinking.isEmpty()) { - emit redactedThinkingBlockReceived(requestId, signature); - } else { - emit thinkingBlockReceived(requestId, thinking, signature); - } - }; - - callbacks.onToolStarted = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName) { - emit toolExecutionStarted(requestId, toolId, toolName); - m_awaitingContinuation.insert(requestId); - }; - - callbacks.onToolResult = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName, - const QString &result) { - emit toolExecutionCompleted(requestId, toolId, toolName, result); - }; - - auto clientId = m_client->sendMessage(payload, callbacks); - m_providerToClientIds[requestId] = clientId; - m_clientToProviderIds[clientId] = requestId; - - LOG_MESSAGE(QString("OpenAICompatProvider: Sending request %1 (client: %2) to %3") - .arg(requestId, clientId, url.toString())); -} - PluginLLMCore::ProviderCapabilities OpenAICompatProvider::capabilities() const { return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image; } -void OpenAICompatProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) +::LLMCore::BaseClient *OpenAICompatProvider::client() const { - LOG_MESSAGE(QString("OpenAICompatProvider: Cancelling request %1").arg(requestId)); - - if (m_providerToClientIds.contains(requestId)) { - auto clientId = m_providerToClientIds.take(requestId); - m_clientToProviderIds.remove(clientId); - m_client->cancelRequest(clientId); - } - m_awaitingContinuation.remove(requestId); -} - -::LLMCore::ToolsManager *OpenAICompatProvider::toolsManager() const -{ - return m_client->tools(); + return m_client; } } // namespace QodeAssist::Providers diff --git a/providers/OpenAICompatProvider.hpp b/providers/OpenAICompatProvider.hpp index f53e635..a106309 100644 --- a/providers/OpenAICompatProvider.hpp +++ b/providers/OpenAICompatProvider.hpp @@ -19,8 +19,6 @@ #pragma once -#include - #include #include @@ -48,20 +46,12 @@ public: QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; PluginLLMCore::ProviderID providerID() const override; - - void sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; - PluginLLMCore::ProviderCapabilities capabilities() const override; - void cancelRequest(const PluginLLMCore::RequestID &requestId) override; - ::LLMCore::ToolsManager *toolsManager() const override; + ::LLMCore::BaseClient *client() const override; private: ::LLMCore::OpenAIClient *m_client; - QHash m_providerToClientIds; - QHash<::LLMCore::RequestID, PluginLLMCore::RequestID> m_clientToProviderIds; - QSet m_awaitingContinuation; }; } // namespace QodeAssist::Providers diff --git a/providers/OpenAIProvider.cpp b/providers/OpenAIProvider.cpp index a21ec2a..45eac6f 100644 --- a/providers/OpenAIProvider.cpp +++ b/providers/OpenAIProvider.cpp @@ -181,95 +181,15 @@ PluginLLMCore::ProviderID OpenAIProvider::providerID() const return PluginLLMCore::ProviderID::OpenAI; } -void OpenAIProvider::sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) -{ - QUrl baseUrl(url); - baseUrl.setPath(""); - m_client->setUrl(baseUrl.toString()); - m_client->setApiKey(apiKey()); - - ::LLMCore::RequestCallbacks callbacks; - - callbacks.onChunk = [this, requestId](const ::LLMCore::RequestID &, const QString &chunk) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - emit partialResponseReceived(requestId, chunk); - }; - - callbacks.onCompleted - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &fullText) { - emit fullResponseReceived(requestId, fullText); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onFailed - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &error) { - emit requestFailed(requestId, error); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onThinkingBlock = [this, requestId](const ::LLMCore::RequestID &, - const QString &thinking, - const QString &signature) { - if (m_awaitingContinuation.remove(requestId)) { - emit continuationStarted(requestId); - } - if (thinking.isEmpty()) { - emit redactedThinkingBlockReceived(requestId, signature); - } else { - emit thinkingBlockReceived(requestId, thinking, signature); - } - }; - - callbacks.onToolStarted = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName) { - emit toolExecutionStarted(requestId, toolId, toolName); - m_awaitingContinuation.insert(requestId); - }; - - callbacks.onToolResult = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName, - const QString &result) { - emit toolExecutionCompleted(requestId, toolId, toolName, result); - }; - - auto clientId = m_client->sendMessage(payload, callbacks); - m_providerToClientIds[requestId] = clientId; - m_clientToProviderIds[clientId] = requestId; - - LOG_MESSAGE(QString("OpenAIProvider: Sending request %1 (client: %2) to %3") - .arg(requestId, clientId, url.toString())); -} - PluginLLMCore::ProviderCapabilities OpenAIProvider::capabilities() const { return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Image | PluginLLMCore::ProviderCapability::ModelListing; } -void OpenAIProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) +::LLMCore::BaseClient *OpenAIProvider::client() const { - LOG_MESSAGE(QString("OpenAIProvider: Cancelling request %1").arg(requestId)); - - if (m_providerToClientIds.contains(requestId)) { - auto clientId = m_providerToClientIds.take(requestId); - m_clientToProviderIds.remove(clientId); - m_client->cancelRequest(clientId); - } - m_awaitingContinuation.remove(requestId); -} - -::LLMCore::ToolsManager *OpenAIProvider::toolsManager() const -{ - return m_client->tools(); + return m_client; } } // namespace QodeAssist::Providers diff --git a/providers/OpenAIProvider.hpp b/providers/OpenAIProvider.hpp index 3e52464..b72ff86 100644 --- a/providers/OpenAIProvider.hpp +++ b/providers/OpenAIProvider.hpp @@ -19,8 +19,6 @@ #pragma once -#include - #include #include @@ -48,20 +46,12 @@ public: QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; PluginLLMCore::ProviderID providerID() const override; - - void sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; - PluginLLMCore::ProviderCapabilities capabilities() const override; - void cancelRequest(const PluginLLMCore::RequestID &requestId) override; - ::LLMCore::ToolsManager *toolsManager() const override; + ::LLMCore::BaseClient *client() const override; private: ::LLMCore::OpenAIClient *m_client; - QHash m_providerToClientIds; - QHash<::LLMCore::RequestID, PluginLLMCore::RequestID> m_clientToProviderIds; - QSet m_awaitingContinuation; }; } // namespace QodeAssist::Providers diff --git a/providers/OpenAIResponsesProvider.cpp b/providers/OpenAIResponsesProvider.cpp index 47ec307..edcf483 100644 --- a/providers/OpenAIResponsesProvider.cpp +++ b/providers/OpenAIResponsesProvider.cpp @@ -222,71 +222,6 @@ PluginLLMCore::ProviderID OpenAIResponsesProvider::providerID() const return PluginLLMCore::ProviderID::OpenAIResponses; } -void OpenAIResponsesProvider::sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) -{ - QUrl baseUrl(url); - baseUrl.setPath(""); - m_client->setUrl(baseUrl.toString()); - m_client->setApiKey(apiKey()); - - ::LLMCore::RequestCallbacks callbacks; - - callbacks.onChunk = [this, requestId](const ::LLMCore::RequestID &, const QString &chunk) { - if (m_awaitingContinuation.remove(requestId)) - emit continuationStarted(requestId); - emit partialResponseReceived(requestId, chunk); - }; - - callbacks.onCompleted - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &fullText) { - emit fullResponseReceived(requestId, fullText); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onFailed - = [this, requestId](const ::LLMCore::RequestID &clientId, const QString &error) { - emit requestFailed(requestId, error); - m_providerToClientIds.remove(requestId); - m_clientToProviderIds.remove(clientId); - m_awaitingContinuation.remove(requestId); - }; - - callbacks.onThinkingBlock = [this, requestId](const ::LLMCore::RequestID &, - const QString &thinking, - const QString &signature) { - if (m_awaitingContinuation.remove(requestId)) - emit continuationStarted(requestId); - if (thinking.isEmpty()) - emit redactedThinkingBlockReceived(requestId, signature); - else - emit thinkingBlockReceived(requestId, thinking, signature); - }; - - callbacks.onToolStarted = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName) { - emit toolExecutionStarted(requestId, toolId, toolName); - m_awaitingContinuation.insert(requestId); - }; - - callbacks.onToolResult = [this, requestId](const ::LLMCore::RequestID &, - const QString &toolId, - const QString &toolName, - const QString &result) { - emit toolExecutionCompleted(requestId, toolId, toolName, result); - }; - - auto clientId = m_client->sendMessage(payload, callbacks); - m_providerToClientIds[requestId] = clientId; - m_clientToProviderIds[clientId] = requestId; - - LOG_MESSAGE(QString("OpenAIResponsesProvider: Sending request %1 (client: %2) to %3") - .arg(requestId, clientId, url.toString())); -} - PluginLLMCore::ProviderCapabilities OpenAIResponsesProvider::capabilities() const { return PluginLLMCore::ProviderCapability::Tools | PluginLLMCore::ProviderCapability::Thinking @@ -294,21 +229,9 @@ PluginLLMCore::ProviderCapabilities OpenAIResponsesProvider::capabilities() cons | PluginLLMCore::ProviderCapability::ModelListing; } -void OpenAIResponsesProvider::cancelRequest(const PluginLLMCore::RequestID &requestId) +::LLMCore::BaseClient *OpenAIResponsesProvider::client() const { - LOG_MESSAGE(QString("OpenAIResponsesProvider: Cancelling request %1").arg(requestId)); - - if (m_providerToClientIds.contains(requestId)) { - auto clientId = m_providerToClientIds.take(requestId); - m_clientToProviderIds.remove(clientId); - m_client->cancelRequest(clientId); - } - m_awaitingContinuation.remove(requestId); -} - -::LLMCore::ToolsManager *OpenAIResponsesProvider::toolsManager() const -{ - return m_client->tools(); + return m_client; } } // namespace QodeAssist::Providers diff --git a/providers/OpenAIResponsesProvider.hpp b/providers/OpenAIResponsesProvider.hpp index e6d0e24..ba363ad 100644 --- a/providers/OpenAIResponsesProvider.hpp +++ b/providers/OpenAIResponsesProvider.hpp @@ -19,8 +19,6 @@ #pragma once -#include - #include #include @@ -48,20 +46,12 @@ public: QString apiKey() const override; void prepareNetworkRequest(QNetworkRequest &networkRequest) const override; PluginLLMCore::ProviderID providerID() const override; - - void sendRequest( - const PluginLLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override; - PluginLLMCore::ProviderCapabilities capabilities() const override; - void cancelRequest(const PluginLLMCore::RequestID &requestId) override; - ::LLMCore::ToolsManager *toolsManager() const override; + ::LLMCore::BaseClient *client() const override; private: ::LLMCore::OpenAIResponsesClient *m_client; - QHash m_providerToClientIds; - QHash<::LLMCore::RequestID, PluginLLMCore::RequestID> m_clientToProviderIds; - QSet m_awaitingContinuation; }; } // namespace QodeAssist::Providers diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4e167b3..581bc88 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,6 +17,8 @@ target_link_libraries(QodeAssistTest PRIVATE GTest::Main QtCreator::LanguageClient Context + PluginLLMCore + LLMCore ) target_compile_definitions(QodeAssistTest PRIVATE CMAKE_CURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")