diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index b74d32f..0186405 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -57,6 +57,17 @@ LLMClientInterface::LLMClientInterface( &LLMCore::RequestHandler::completionReceived, this, &LLMClientInterface::sendCompletionToClient); + + // TODO handle error + // connect( + // &m_requestHandler, + // &LLMCore::RequestHandler::requestFinished, + // this, + // [this](const QString &, bool success, const QString &errorString) { + // if (!success) { + // emit error(errorString); + // } + // }); } Utils::FilePath LLMClientInterface::serverDeviceTemplate() const diff --git a/llmcore/RequestHandler.cpp b/llmcore/RequestHandler.cpp index 29ec568..4135ae0 100644 --- a/llmcore/RequestHandler.cpp +++ b/llmcore/RequestHandler.cpp @@ -22,14 +22,51 @@ #include #include +#include namespace QodeAssist::LLMCore { RequestHandler::RequestHandler(QObject *parent) : RequestHandlerBase(parent) -{} + , m_manager(new QNetworkAccessManager(this)) +{ + connect( + this, + &RequestHandler::doSendRequest, + this, + &RequestHandler::sendLLMRequestInternal, + Qt::QueuedConnection); + + connect( + this, + &RequestHandler::doCancelRequest, + this, + &RequestHandler::cancelRequestInternal, + Qt::QueuedConnection); +} + +RequestHandler::~RequestHandler() +{ + for (auto reply : m_activeRequests) { + reply->abort(); + reply->deleteLater(); + } + m_activeRequests.clear(); + m_accumulatedResponses.clear(); +} void RequestHandler::sendLLMRequest(const LLMConfig &config, const QJsonObject &request) +{ + emit doSendRequest(config, request); +} + +bool RequestHandler::cancelRequest(const QString &id) +{ + emit doCancelRequest(id); + return true; +} + +void RequestHandler::sendLLMRequestInternal(const LLMConfig &config, const QJsonObject &request) { LOG_MESSAGE(QString("Sending request to llm: \nurl: %1\nRequest body:\n%2") .arg( @@ -37,12 +74,13 @@ void RequestHandler::sendLLMRequest(const LLMConfig &config, const QJsonObject & QString::fromUtf8( QJsonDocument(config.providerRequest).toJson(QJsonDocument::Indented)))); - QNetworkAccessManager *manager = new QNetworkAccessManager(); QNetworkRequest networkRequest(config.url); + networkRequest.setTransferTimeout(300000); + config.provider->prepareNetworkRequest(networkRequest); QNetworkReply *reply - = manager->post(networkRequest, QJsonDocument(config.providerRequest).toJson()); + = m_manager->post(networkRequest, QJsonDocument(config.providerRequest).toJson()); if (!reply) { LOG_MESSAGE("Error: Failed to create network reply"); return; @@ -55,24 +93,28 @@ void RequestHandler::sendLLMRequest(const LLMConfig &config, const QJsonObject & handleLLMResponse(reply, request, config); }); - connect(reply, &QNetworkReply::finished, this, [this, reply, requestId, manager]() { - m_activeRequests.remove(requestId); - if (reply->error() != QNetworkReply::NoError) { - QString errorMessage = reply->errorString(); - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + connect( + reply, + &QNetworkReply::finished, + this, + [this, reply, requestId]() { + m_activeRequests.remove(requestId); + if (reply->error() != QNetworkReply::NoError) { + QString errorMessage = reply->errorString(); + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - LOG_MESSAGE( - QString("Error details: %1\nStatus code: %2").arg(errorMessage).arg(statusCode)); + LOG_MESSAGE( + QString("Error details: %1\nStatus code: %2").arg(errorMessage).arg(statusCode)); - emit requestFinished(requestId, false, errorMessage); - } else { - LOG_MESSAGE("Request finished successfully"); - emit requestFinished(requestId, true, QString()); - } + emit requestFinished(requestId, false, errorMessage); + } else { + LOG_MESSAGE("Request finished successfully"); + emit requestFinished(requestId, true, QString()); + } - reply->deleteLater(); - manager->deleteLater(); - }); + reply->deleteLater(); + }, + Qt::QueuedConnection); } void RequestHandler::handleLLMResponse( @@ -102,17 +144,18 @@ void RequestHandler::handleLLMResponse( m_accumulatedResponses.remove(reply); } -bool RequestHandler::cancelRequest(const QString &id) +void RequestHandler::cancelRequestInternal(const QString &id) { + QMutexLocker locker(&m_mutex); if (m_activeRequests.contains(id)) { QNetworkReply *reply = m_activeRequests[id]; reply->abort(); m_activeRequests.remove(id); m_accumulatedResponses.remove(reply); + locker.unlock(); + emit requestCancelled(id); - return true; } - return false; } bool RequestHandler::processSingleLineCompletion( diff --git a/llmcore/RequestHandler.hpp b/llmcore/RequestHandler.hpp index 49fe98c..0cfd7f3 100644 --- a/llmcore/RequestHandler.hpp +++ b/llmcore/RequestHandler.hpp @@ -20,6 +20,7 @@ #pragma once #include +#include #include #include @@ -32,16 +33,32 @@ namespace QodeAssist::LLMCore { class RequestHandler : public RequestHandlerBase { + Q_OBJECT public: explicit RequestHandler(QObject *parent = nullptr); + ~RequestHandler() override; void sendLLMRequest(const LLMConfig &config, const QJsonObject &request) override; bool cancelRequest(const QString &id) override; - void handleLLMResponse(QNetworkReply *reply, const QJsonObject &request, const LLMConfig &config); + +signals: + void doSendRequest(QodeAssist::LLMCore::LLMConfig config, QJsonObject request); + void doCancelRequest(QString id); + +private slots: + void sendLLMRequestInternal( + const QodeAssist::LLMCore::LLMConfig &config, const QJsonObject &request); + void cancelRequestInternal(const QString &id); + void handleLLMResponse( + QNetworkReply *reply, + const QJsonObject &request, + const QodeAssist::LLMCore::LLMConfig &config); private: QMap m_activeRequests; QMap m_accumulatedResponses; + QNetworkAccessManager *m_manager; + QMutex m_mutex; bool processSingleLineCompletion( QNetworkReply *reply, diff --git a/widgets/CompletionProgressHandler.cpp b/widgets/CompletionProgressHandler.cpp index 1fd3046..2536588 100644 --- a/widgets/CompletionProgressHandler.cpp +++ b/widgets/CompletionProgressHandler.cpp @@ -38,7 +38,6 @@ namespace QodeAssist { void CompletionProgressHandler::showProgress(TextEditor::TextEditorWidget *widget) { m_widget = widget; - m_isActive = true; if (m_widget) { const QRect cursorRect = m_widget->cursorRect(m_widget->textCursor()); @@ -54,14 +53,13 @@ void CompletionProgressHandler::showProgress(TextEditor::TextEditorWidget *widge void CompletionProgressHandler::hideProgress() { - m_isActive = false; - Utils::ToolTip::hide(); + Utils::ToolTip::hideImmediately(); } void CompletionProgressHandler::identifyMatch( TextEditor::TextEditorWidget *editorWidget, int pos, ReportPriority report) { - if (!m_isActive || !editorWidget) { + if (!editorWidget) { report(Priority_None); return; } @@ -72,7 +70,7 @@ void CompletionProgressHandler::identifyMatch( void CompletionProgressHandler::operateTooltip( TextEditor::TextEditorWidget *editorWidget, const QPoint &point) { - if (!m_isActive || !editorWidget) + if (!editorWidget) return; auto progressWidget = new ProgressWidget(editorWidget); diff --git a/widgets/CompletionProgressHandler.hpp b/widgets/CompletionProgressHandler.hpp index 2d012e4..6f32e97 100644 --- a/widgets/CompletionProgressHandler.hpp +++ b/widgets/CompletionProgressHandler.hpp @@ -38,7 +38,6 @@ protected: private: QPointer m_widget; QPoint m_iconPosition; - bool m_isActive = false; }; } // namespace QodeAssist