refactor: Improve http client (#319)

This commit is contained in:
Petr Mironychev
2026-02-25 15:13:05 +01:00
committed by GitHub
parent 49ae335d7d
commit e2e13f0f38
23 changed files with 394 additions and 450 deletions

View File

@@ -19,11 +19,9 @@
#include "ClaudeProvider.hpp"
#include <QEventLoop>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QUrlQuery>
#include "llmcore/ValidationUtils.hpp"
@@ -142,11 +140,8 @@ void ClaudeProvider::prepareRequest(
}
}
QList<QString> ClaudeProvider::getInstalledModels(const QString &baseUrl)
QFuture<QList<QString>> ClaudeProvider::getInstalledModels(const QString &baseUrl)
{
QList<QString> models;
QNetworkAccessManager manager;
QUrl url(baseUrl + "/v1/models");
QUrlQuery query;
query.addQueryItem("limit", "1000");
@@ -160,32 +155,24 @@ QList<QString> ClaudeProvider::getInstalledModels(const QString &baseUrl)
request.setRawHeader("x-api-key", apiKey().toUtf8());
}
QNetworkReply *reply = manager.get(request);
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() == QNetworkReply::NoError) {
QByteArray responseData = reply->readAll();
QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
QJsonObject jsonObject = jsonResponse.object();
return httpClient()->get(request).then([](const QByteArray &data) {
QList<QString> models;
QJsonObject jsonObject = QJsonDocument::fromJson(data).object();
if (jsonObject.contains("data")) {
QJsonArray modelArray = jsonObject["data"].toArray();
for (const QJsonValue &value : modelArray) {
QJsonObject modelObject = value.toObject();
if (modelObject.contains("id")) {
QString modelId = modelObject["id"].toString();
models.append(modelId);
models.append(modelObject["id"].toString());
}
}
}
} else {
LOG_MESSAGE(QString("Error fetching Claude models: %1").arg(reply->errorString()));
}
reply->deleteLater();
return models;
return models;
}).onFailed([](const std::exception &e) {
LOG_MESSAGE(QString("Error fetching Claude models: %1").arg(e.what()));
return QList<QString>{};
});
}
QList<QString> ClaudeProvider::validateRequest(const QJsonObject &request, LLMCore::TemplateType type)
@@ -240,12 +227,9 @@ void ClaudeProvider::sendRequest(
QNetworkRequest networkRequest(url);
prepareNetworkRequest(networkRequest);
LLMCore::HttpRequest
request{.networkRequest = networkRequest, .requestId = requestId, .payload = payload};
LOG_MESSAGE(QString("ClaudeProvider: Sending request %1 to %2").arg(requestId, url.toString()));
emit httpClient()->sendRequest(request);
httpClient()->postStreaming(requestId, networkRequest, payload);
}
bool ClaudeProvider::supportsTools() const
@@ -289,11 +273,11 @@ void ClaudeProvider::onDataReceived(
}
void ClaudeProvider::onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId, bool success, const QString &error)
const QodeAssist::LLMCore::RequestID &requestId, std::optional<QString> error)
{
if (!success) {
LOG_MESSAGE(QString("ClaudeProvider request %1 failed: %2").arg(requestId, error));
emit requestFailed(requestId, error);
if (error) {
LOG_MESSAGE(QString("ClaudeProvider request %1 failed: %2").arg(requestId, *error));
emit requestFailed(requestId, *error);
cleanupRequest(requestId);
return;
}

View File

@@ -44,7 +44,7 @@ public:
LLMCore::RequestType type,
bool isToolsEnabled,
bool isThinkingEnabled) override;
QList<QString> getInstalledModels(const QString &url) override;
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
QList<QString> validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override;
QString apiKey() const override;
void prepareNetworkRequest(QNetworkRequest &networkRequest) const override;
@@ -65,8 +65,7 @@ public slots:
const QodeAssist::LLMCore::RequestID &requestId, const QByteArray &data) override;
void onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId,
bool success,
const QString &error) override;
std::optional<QString> error) override;
private slots:
void onToolExecutionComplete(

View File

@@ -19,11 +19,9 @@
#include "GoogleAIProvider.hpp"
#include <QEventLoop>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QtCore/qurlquery.h>
#include "llmcore/ValidationUtils.hpp"
@@ -156,29 +154,17 @@ void GoogleAIProvider::prepareRequest(
}
}
QList<QString> GoogleAIProvider::getInstalledModels(const QString &url)
QFuture<QList<QString>> GoogleAIProvider::getInstalledModels(const QString &url)
{
QList<QString> models;
QNetworkAccessManager manager;
QNetworkRequest request(QString("%1/models?key=%2").arg(url, apiKey()));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = manager.get(request);
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() == QNetworkReply::NoError) {
QByteArray responseData = reply->readAll();
QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
QJsonObject jsonObject = jsonResponse.object();
return httpClient()->get(request).then([](const QByteArray &data) {
QList<QString> models;
QJsonObject jsonObject = QJsonDocument::fromJson(data).object();
if (jsonObject.contains("models")) {
QJsonArray modelArray = jsonObject["models"].toArray();
models.clear();
for (const QJsonValue &value : modelArray) {
QJsonObject modelObject = value.toObject();
if (modelObject.contains("name")) {
@@ -190,12 +176,11 @@ QList<QString> GoogleAIProvider::getInstalledModels(const QString &url)
}
}
}
} else {
LOG_MESSAGE(QString("Error fetching Google AI models: %1").arg(reply->errorString()));
}
reply->deleteLater();
return models;
return models;
}).onFailed([](const std::exception &e) {
LOG_MESSAGE(QString("Error fetching Google AI models: %1").arg(e.what()));
return QList<QString>{};
});
}
QList<QString> GoogleAIProvider::validateRequest(
@@ -254,13 +239,10 @@ void GoogleAIProvider::sendRequest(
QNetworkRequest networkRequest(url);
prepareNetworkRequest(networkRequest);
LLMCore::HttpRequest
request{.networkRequest = networkRequest, .requestId = requestId, .payload = payload};
LOG_MESSAGE(
QString("GoogleAIProvider: Sending request %1 to %2").arg(requestId, url.toString()));
emit httpClient()->sendRequest(request);
httpClient()->postStreaming(requestId, networkRequest, payload);
}
bool GoogleAIProvider::supportsTools() const
@@ -327,11 +309,11 @@ void GoogleAIProvider::onDataReceived(
}
void GoogleAIProvider::onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId, bool success, const QString &error)
const QodeAssist::LLMCore::RequestID &requestId, std::optional<QString> error)
{
if (!success) {
LOG_MESSAGE(QString("GoogleAIProvider request %1 failed: %2").arg(requestId, error));
emit requestFailed(requestId, error);
if (error) {
LOG_MESSAGE(QString("GoogleAIProvider request %1 failed: %2").arg(requestId, *error));
emit requestFailed(requestId, *error);
cleanupRequest(requestId);
return;
}

View File

@@ -43,7 +43,7 @@ public:
LLMCore::RequestType type,
bool isToolsEnabled,
bool isThinkingEnabled) override;
QList<QString> getInstalledModels(const QString &url) override;
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
QList<QString> validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override;
QString apiKey() const override;
void prepareNetworkRequest(QNetworkRequest &networkRequest) const override;
@@ -62,8 +62,7 @@ public slots:
const QodeAssist::LLMCore::RequestID &requestId, const QByteArray &data) override;
void onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId,
bool success,
const QString &error) override;
std::optional<QString> error) override;
private slots:
void onToolExecutionComplete(

View File

@@ -27,11 +27,9 @@
#include "settings/GeneralSettings.hpp"
#include "settings/ProviderSettings.hpp"
#include <QEventLoop>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
namespace QodeAssist::Providers {
@@ -71,35 +69,24 @@ bool LMStudioProvider::supportsModelListing() const
return true;
}
QList<QString> LMStudioProvider::getInstalledModels(const QString &url)
QFuture<QList<QString>> LMStudioProvider::getInstalledModels(const QString &url)
{
QList<QString> models;
QNetworkAccessManager manager;
QNetworkRequest request(QString("%1%2").arg(url, "/v1/models"));
QNetworkReply *reply = manager.get(request);
return httpClient()->get(request).then([](const QByteArray &data) {
QList<QString> models;
QJsonObject jsonObject = QJsonDocument::fromJson(data).object();
QJsonArray modelArray = jsonObject["data"].toArray();
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() == QNetworkReply::NoError) {
QByteArray responseData = reply->readAll();
QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
QJsonObject jsonObject = jsonResponse.object();
QJsonArray modelArray = jsonObject["data"].toArray();
for (const QJsonValue &value : modelArray) {
QJsonObject modelObject = value.toObject();
QString modelId = modelObject["id"].toString();
models.append(modelId);
for (const QJsonValue &value : modelArray) {
QJsonObject modelObject = value.toObject();
models.append(modelObject["id"].toString());
}
} else {
LOG_MESSAGE(QString("Error fetching LMStudio models: %1").arg(reply->errorString()));
}
reply->deleteLater();
return models;
return models;
}).onFailed([](const std::exception &e) {
LOG_MESSAGE(QString("Error fetching LMStudio models: %1").arg(e.what()));
return QList<QString>{};
});
}
QList<QString> LMStudioProvider::validateRequest(
@@ -149,13 +136,10 @@ void LMStudioProvider::sendRequest(
QNetworkRequest networkRequest(url);
prepareNetworkRequest(networkRequest);
LLMCore::HttpRequest
request{.networkRequest = networkRequest, .requestId = requestId, .payload = payload};
LOG_MESSAGE(
QString("LMStudioProvider: Sending request %1 to %2").arg(requestId, url.toString()));
emit httpClient()->sendRequest(request);
httpClient()->postStreaming(requestId, networkRequest, payload);
}
bool LMStudioProvider::supportsTools() const
@@ -195,11 +179,11 @@ void LMStudioProvider::onDataReceived(
}
void LMStudioProvider::onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId, bool success, const QString &error)
const QodeAssist::LLMCore::RequestID &requestId, std::optional<QString> error)
{
if (!success) {
LOG_MESSAGE(QString("LMStudioProvider request %1 failed: %2").arg(requestId, error));
emit requestFailed(requestId, error);
if (error) {
LOG_MESSAGE(QString("LMStudioProvider request %1 failed: %2").arg(requestId, *error));
emit requestFailed(requestId, *error);
cleanupRequest(requestId);
return;
}

View File

@@ -43,7 +43,7 @@ public:
LLMCore::RequestType type,
bool isToolsEnabled,
bool isThinkingEnabled) override;
QList<QString> getInstalledModels(const QString &url) override;
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
QList<QString> validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override;
QString apiKey() const override;
void prepareNetworkRequest(QNetworkRequest &networkRequest) const override;
@@ -61,8 +61,7 @@ public slots:
const QodeAssist::LLMCore::RequestID &requestId, const QByteArray &data) override;
void onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId,
bool success,
const QString &error) override;
std::optional<QString> error) override;
private slots:
void onToolExecutionComplete(

View File

@@ -26,11 +26,9 @@
#include "settings/QuickRefactorSettings.hpp"
#include "settings/GeneralSettings.hpp"
#include <QEventLoop>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
namespace QodeAssist::Providers {
@@ -121,9 +119,9 @@ void LlamaCppProvider::prepareRequest(
}
}
QList<QString> LlamaCppProvider::getInstalledModels(const QString &url)
QFuture<QList<QString>> LlamaCppProvider::getInstalledModels(const QString &)
{
return {};
return QtFuture::makeReadyFuture(QList<QString>{});
}
QList<QString> LlamaCppProvider::validateRequest(
@@ -192,13 +190,10 @@ void LlamaCppProvider::sendRequest(
QNetworkRequest networkRequest(url);
prepareNetworkRequest(networkRequest);
LLMCore::HttpRequest
request{.networkRequest = networkRequest, .requestId = requestId, .payload = payload};
LOG_MESSAGE(
QString("LlamaCppProvider: Sending request %1 to %2").arg(requestId, url.toString()));
emit httpClient()->sendRequest(request);
httpClient()->postStreaming(requestId, networkRequest, payload);
}
bool LlamaCppProvider::supportsTools() const
@@ -250,11 +245,11 @@ void LlamaCppProvider::onDataReceived(
}
void LlamaCppProvider::onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId, bool success, const QString &error)
const QodeAssist::LLMCore::RequestID &requestId, std::optional<QString> error)
{
if (!success) {
LOG_MESSAGE(QString("LlamaCppProvider request %1 failed: %2").arg(requestId, error));
emit requestFailed(requestId, error);
if (error) {
LOG_MESSAGE(QString("LlamaCppProvider request %1 failed: %2").arg(requestId, *error));
emit requestFailed(requestId, *error);
cleanupRequest(requestId);
return;
}

View File

@@ -43,7 +43,7 @@ public:
LLMCore::RequestType type,
bool isToolsEnabled,
bool isThinkingEnabled) override;
QList<QString> getInstalledModels(const QString &url) override;
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
QList<QString> validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override;
QString apiKey() const override;
void prepareNetworkRequest(QNetworkRequest &networkRequest) const override;
@@ -61,8 +61,7 @@ public slots:
const QodeAssist::LLMCore::RequestID &requestId, const QByteArray &data) override;
void onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId,
bool success,
const QString &error) override;
std::optional<QString> error) override;
private slots:
void onToolExecutionComplete(

View File

@@ -27,11 +27,9 @@
#include "settings/GeneralSettings.hpp"
#include "settings/ProviderSettings.hpp"
#include <QEventLoop>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
namespace QodeAssist::Providers {
@@ -71,43 +69,32 @@ bool MistralAIProvider::supportsModelListing() const
return true;
}
QList<QString> MistralAIProvider::getInstalledModels(const QString &url)
QFuture<QList<QString>> MistralAIProvider::getInstalledModels(const QString &url)
{
QList<QString> models;
QNetworkAccessManager manager;
QNetworkRequest request(QString("%1/v1/models").arg(url));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
if (!apiKey().isEmpty()) {
request.setRawHeader("Authorization", QString("Bearer %1").arg(apiKey()).toUtf8());
}
QNetworkReply *reply = manager.get(request);
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() == QNetworkReply::NoError) {
QByteArray responseData = reply->readAll();
QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
QJsonObject jsonObject = jsonResponse.object();
return httpClient()->get(request).then([](const QByteArray &data) {
QList<QString> models;
QJsonObject jsonObject = QJsonDocument::fromJson(data).object();
if (jsonObject.contains("data") && jsonObject["object"].toString() == "list") {
QJsonArray modelArray = jsonObject["data"].toArray();
for (const QJsonValue &value : modelArray) {
QJsonObject modelObject = value.toObject();
if (modelObject.contains("id")) {
QString modelId = modelObject["id"].toString();
models.append(modelId);
models.append(modelObject["id"].toString());
}
}
}
} else {
LOG_MESSAGE(QString("Error fetching Mistral AI models: %1").arg(reply->errorString()));
}
reply->deleteLater();
return models;
return models;
}).onFailed([](const std::exception &e) {
LOG_MESSAGE(QString("Error fetching Mistral AI models: %1").arg(e.what()));
return QList<QString>{};
});
}
QList<QString> MistralAIProvider::validateRequest(
@@ -170,13 +157,10 @@ void MistralAIProvider::sendRequest(
QNetworkRequest networkRequest(url);
prepareNetworkRequest(networkRequest);
LLMCore::HttpRequest
request{.networkRequest = networkRequest, .requestId = requestId, .payload = payload};
LOG_MESSAGE(
QString("MistralAIProvider: Sending request %1 to %2").arg(requestId, url.toString()));
emit httpClient()->sendRequest(request);
httpClient()->postStreaming(requestId, networkRequest, payload);
}
bool MistralAIProvider::supportsTools() const
@@ -216,11 +200,11 @@ void MistralAIProvider::onDataReceived(
}
void MistralAIProvider::onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId, bool success, const QString &error)
const QodeAssist::LLMCore::RequestID &requestId, std::optional<QString> error)
{
if (!success) {
LOG_MESSAGE(QString("MistralAIProvider request %1 failed: %2").arg(requestId, error));
emit requestFailed(requestId, error);
if (error) {
LOG_MESSAGE(QString("MistralAIProvider request %1 failed: %2").arg(requestId, *error));
emit requestFailed(requestId, *error);
cleanupRequest(requestId);
return;
}

View File

@@ -43,7 +43,7 @@ public:
LLMCore::RequestType type,
bool isToolsEnabled,
bool isThinkingEnabled) override;
QList<QString> getInstalledModels(const QString &url) override;
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
QList<QString> validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override;
QString apiKey() const override;
void prepareNetworkRequest(QNetworkRequest &networkRequest) const override;
@@ -61,8 +61,7 @@ public slots:
const QodeAssist::LLMCore::RequestID &requestId, const QByteArray &data) override;
void onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId,
bool success,
const QString &error) override;
std::optional<QString> error) override;
private slots:
void onToolExecutionComplete(

View File

@@ -22,8 +22,6 @@
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QtCore/qeventloop.h>
#include "llmcore/ValidationUtils.hpp"
#include "logger/Logger.hpp"
@@ -147,35 +145,25 @@ void OllamaProvider::prepareRequest(
}
}
QList<QString> OllamaProvider::getInstalledModels(const QString &url)
QFuture<QList<QString>> OllamaProvider::getInstalledModels(const QString &url)
{
QList<QString> models;
QNetworkAccessManager manager;
QNetworkRequest request(QString("%1%2").arg(url, "/api/tags"));
prepareNetworkRequest(request);
QNetworkReply *reply = manager.get(request);
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() == QNetworkReply::NoError) {
QByteArray responseData = reply->readAll();
QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
QJsonObject jsonObject = jsonResponse.object();
return httpClient()->get(request).then([](const QByteArray &data) {
QList<QString> models;
QJsonObject jsonObject = QJsonDocument::fromJson(data).object();
QJsonArray modelArray = jsonObject["models"].toArray();
for (const QJsonValue &value : modelArray) {
QJsonObject modelObject = value.toObject();
QString modelName = modelObject["name"].toString();
models.append(modelName);
models.append(modelObject["name"].toString());
}
} else {
LOG_MESSAGE(QString("Error fetching models: %1").arg(reply->errorString()));
}
reply->deleteLater();
return models;
return models;
}).onFailed([](const std::exception &e) {
LOG_MESSAGE(QString("Error fetching models: %1").arg(e.what()));
return QList<QString>{};
});
}
QList<QString> OllamaProvider::validateRequest(const QJsonObject &request, LLMCore::TemplateType type)
@@ -248,12 +236,9 @@ void OllamaProvider::sendRequest(
QNetworkRequest networkRequest(url);
prepareNetworkRequest(networkRequest);
LLMCore::HttpRequest
request{.networkRequest = networkRequest, .requestId = requestId, .payload = payload};
LOG_MESSAGE(QString("OllamaProvider: Sending request %1 to %2").arg(requestId, url.toString()));
emit httpClient()->sendRequest(request);
httpClient()->postStreaming(requestId, networkRequest, payload);
}
bool OllamaProvider::supportsTools() const
@@ -312,11 +297,11 @@ void OllamaProvider::onDataReceived(
}
void OllamaProvider::onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId, bool success, const QString &error)
const QodeAssist::LLMCore::RequestID &requestId, std::optional<QString> error)
{
if (!success) {
LOG_MESSAGE(QString("OllamaProvider request %1 failed: %2").arg(requestId, error));
emit requestFailed(requestId, error);
if (error) {
LOG_MESSAGE(QString("OllamaProvider request %1 failed: %2").arg(requestId, *error));
emit requestFailed(requestId, *error);
cleanupRequest(requestId);
return;
}

View File

@@ -44,7 +44,7 @@ public:
LLMCore::RequestType type,
bool isToolsEnabled,
bool isThinkingEnabled) override;
QList<QString> getInstalledModels(const QString &url) override;
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
QList<QString> validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override;
QString apiKey() const override;
void prepareNetworkRequest(QNetworkRequest &networkRequest) const override;
@@ -63,8 +63,7 @@ public slots:
const QodeAssist::LLMCore::RequestID &requestId, const QByteArray &data) override;
void onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId,
bool success,
const QString &error) override;
std::optional<QString> error) override;
private slots:
void onToolExecutionComplete(

View File

@@ -122,9 +122,9 @@ void OpenAICompatProvider::prepareRequest(
}
}
QList<QString> OpenAICompatProvider::getInstalledModels(const QString &url)
QFuture<QList<QString>> OpenAICompatProvider::getInstalledModels(const QString &)
{
return QStringList();
return QtFuture::makeReadyFuture(QList<QString>{});
}
QList<QString> OpenAICompatProvider::validateRequest(
@@ -178,13 +178,10 @@ void OpenAICompatProvider::sendRequest(
QNetworkRequest networkRequest(url);
prepareNetworkRequest(networkRequest);
LLMCore::HttpRequest
request{.networkRequest = networkRequest, .requestId = requestId, .payload = payload};
LOG_MESSAGE(
QString("OpenAICompatProvider: Sending request %1 to %2").arg(requestId, url.toString()));
emit httpClient()->sendRequest(request);
httpClient()->postStreaming(requestId, networkRequest, payload);
}
bool OpenAICompatProvider::supportsTools() const
@@ -224,11 +221,11 @@ void OpenAICompatProvider::onDataReceived(
}
void OpenAICompatProvider::onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId, bool success, const QString &error)
const QodeAssist::LLMCore::RequestID &requestId, std::optional<QString> error)
{
if (!success) {
LOG_MESSAGE(QString("OpenAICompatProvider request %1 failed: %2").arg(requestId, error));
emit requestFailed(requestId, error);
if (error) {
LOG_MESSAGE(QString("OpenAICompatProvider request %1 failed: %2").arg(requestId, *error));
emit requestFailed(requestId, *error);
cleanupRequest(requestId);
return;
}

View File

@@ -43,7 +43,7 @@ public:
LLMCore::RequestType type,
bool isToolsEnabled,
bool isThinkingEnabled) override;
QList<QString> getInstalledModels(const QString &url) override;
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
QList<QString> validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override;
QString apiKey() const override;
void prepareNetworkRequest(QNetworkRequest &networkRequest) const override;
@@ -61,8 +61,7 @@ public slots:
const QodeAssist::LLMCore::RequestID &requestId, const QByteArray &data) override;
void onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId,
bool success,
const QString &error) override;
std::optional<QString> error) override;
private slots:
void onToolExecutionComplete(

View File

@@ -27,11 +27,9 @@
#include "settings/GeneralSettings.hpp"
#include "settings/ProviderSettings.hpp"
#include <QEventLoop>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
namespace QodeAssist::Providers {
@@ -141,26 +139,17 @@ void OpenAIProvider::prepareRequest(
}
}
QList<QString> OpenAIProvider::getInstalledModels(const QString &url)
QFuture<QList<QString>> OpenAIProvider::getInstalledModels(const QString &url)
{
QList<QString> models;
QNetworkAccessManager manager;
QNetworkRequest request(QString("%1/v1/models").arg(url));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
if (!apiKey().isEmpty()) {
request.setRawHeader("Authorization", QString("Bearer %1").arg(apiKey()).toUtf8());
}
QNetworkReply *reply = manager.get(request);
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() == QNetworkReply::NoError) {
QByteArray responseData = reply->readAll();
QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
QJsonObject jsonObject = jsonResponse.object();
return httpClient()->get(request).then([](const QByteArray &data) {
QList<QString> models;
QJsonObject jsonObject = QJsonDocument::fromJson(data).object();
if (jsonObject.contains("data")) {
QJsonArray modelArray = jsonObject["data"].toArray();
@@ -176,12 +165,11 @@ QList<QString> OpenAIProvider::getInstalledModels(const QString &url)
}
}
}
} else {
LOG_MESSAGE(QString("Error fetching OpenAI models: %1").arg(reply->errorString()));
}
reply->deleteLater();
return models;
return models;
}).onFailed([](const std::exception &e) {
LOG_MESSAGE(QString("Error fetching OpenAI models: %1").arg(e.what()));
return QList<QString>{};
});
}
QList<QString> OpenAIProvider::validateRequest(const QJsonObject &request, LLMCore::TemplateType type)
@@ -235,12 +223,9 @@ void OpenAIProvider::sendRequest(
QNetworkRequest networkRequest(url);
prepareNetworkRequest(networkRequest);
LLMCore::HttpRequest
request{.networkRequest = networkRequest, .requestId = requestId, .payload = payload};
LOG_MESSAGE(QString("OpenAIProvider: Sending request %1 to %2").arg(requestId, url.toString()));
emit httpClient()->sendRequest(request);
httpClient()->postStreaming(requestId, networkRequest, payload);
}
bool OpenAIProvider::supportsTools() const
@@ -280,11 +265,11 @@ void OpenAIProvider::onDataReceived(
}
void OpenAIProvider::onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId, bool success, const QString &error)
const QodeAssist::LLMCore::RequestID &requestId, std::optional<QString> error)
{
if (!success) {
LOG_MESSAGE(QString("OpenAIProvider request %1 failed: %2").arg(requestId, error));
emit requestFailed(requestId, error);
if (error) {
LOG_MESSAGE(QString("OpenAIProvider request %1 failed: %2").arg(requestId, *error));
emit requestFailed(requestId, *error);
cleanupRequest(requestId);
return;
}

View File

@@ -43,7 +43,7 @@ public:
LLMCore::RequestType type,
bool isToolsEnabled,
bool isThinkingEnabled) override;
QList<QString> getInstalledModels(const QString &url) override;
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
QList<QString> validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override;
QString apiKey() const override;
void prepareNetworkRequest(QNetworkRequest &networkRequest) const override;
@@ -61,8 +61,7 @@ public slots:
const QodeAssist::LLMCore::RequestID &requestId, const QByteArray &data) override;
void onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId,
bool success,
const QString &error) override;
std::optional<QString> error) override;
private slots:
void onToolExecutionComplete(

View File

@@ -28,11 +28,9 @@
#include "settings/ProviderSettings.hpp"
#include "settings/QuickRefactorSettings.hpp"
#include <QEventLoop>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
namespace QodeAssist::Providers {
@@ -158,26 +156,17 @@ void OpenAIResponsesProvider::prepareRequest(
request["stream"] = true;
}
QList<QString> OpenAIResponsesProvider::getInstalledModels(const QString &url)
QFuture<QList<QString>> OpenAIResponsesProvider::getInstalledModels(const QString &url)
{
QList<QString> models;
QNetworkAccessManager manager;
QNetworkRequest request(QString("%1/v1/models").arg(url));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
if (!apiKey().isEmpty()) {
request.setRawHeader("Authorization", QString("Bearer %1").arg(apiKey()).toUtf8());
}
QNetworkReply *reply = manager.get(request);
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() == QNetworkReply::NoError) {
const QByteArray responseData = reply->readAll();
const QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
const QJsonObject jsonObject = jsonResponse.object();
return httpClient()->get(request).then([](const QByteArray &data) {
QList<QString> models;
const QJsonObject jsonObject = QJsonDocument::fromJson(data).object();
if (jsonObject.contains("data")) {
const QJsonArray modelArray = jsonObject["data"].toArray();
@@ -200,12 +189,11 @@ QList<QString> OpenAIResponsesProvider::getInstalledModels(const QString &url)
}
}
}
} else {
LOG_MESSAGE(QString("Error fetching OpenAI models: %1").arg(reply->errorString()));
}
reply->deleteLater();
return models;
return models;
}).onFailed([](const std::exception &e) {
LOG_MESSAGE(QString("Error fetching OpenAI models: %1").arg(e.what()));
return QList<QString>{};
});
}
QList<QString> OpenAIResponsesProvider::validateRequest(
@@ -280,10 +268,7 @@ void OpenAIResponsesProvider::sendRequest(
QNetworkRequest networkRequest(url);
prepareNetworkRequest(networkRequest);
LLMCore::HttpRequest
request{.networkRequest = networkRequest, .requestId = requestId, .payload = payload};
emit httpClient()->sendRequest(request);
httpClient()->postStreaming(requestId, networkRequest, payload);
}
bool OpenAIResponsesProvider::supportsTools() const
@@ -344,11 +329,11 @@ void OpenAIResponsesProvider::onDataReceived(
}
void OpenAIResponsesProvider::onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId, bool success, const QString &error)
const QodeAssist::LLMCore::RequestID &requestId, std::optional<QString> error)
{
if (!success) {
LOG_MESSAGE(QString("OpenAIResponses request %1 failed: %2").arg(requestId, error));
emit requestFailed(requestId, error);
if (error) {
LOG_MESSAGE(QString("OpenAIResponses request %1 failed: %2").arg(requestId, *error));
emit requestFailed(requestId, *error);
cleanupRequest(requestId);
return;
}

View File

@@ -43,7 +43,7 @@ public:
LLMCore::RequestType type,
bool isToolsEnabled,
bool isThinkingEnabled) override;
QList<QString> getInstalledModels(const QString &url) override;
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
QList<QString> validateRequest(const QJsonObject &request, LLMCore::TemplateType type) override;
QString apiKey() const override;
void prepareNetworkRequest(QNetworkRequest &networkRequest) const override;
@@ -62,8 +62,7 @@ public slots:
const QodeAssist::LLMCore::RequestID &requestId, const QByteArray &data) override;
void onRequestFinished(
const QodeAssist::LLMCore::RequestID &requestId,
bool success,
const QString &error) override;
std::optional<QString> error) override;
private slots:
void onToolExecutionComplete(