mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-06-14 02:09:22 -04:00
refactor: Move to agent-session architecture
This commit is contained in:
@@ -5,5 +5,6 @@ add_subdirectory(common)
|
||||
add_subdirectory(providers)
|
||||
add_subdirectory(templates)
|
||||
add_subdirectory(agents)
|
||||
add_subdirectory(Session)
|
||||
add_subdirectory(providersConfig)
|
||||
add_subdirectory(settings)
|
||||
|
||||
@@ -106,6 +106,19 @@ bool Session::isInFlight() const noexcept
|
||||
return !m_inFlight.isEmpty();
|
||||
}
|
||||
|
||||
LLMQore::BaseClient *Session::client() const noexcept
|
||||
{
|
||||
auto *provider = m_agent ? m_agent->provider() : nullptr;
|
||||
return provider ? provider->client() : nullptr;
|
||||
}
|
||||
|
||||
bool Session::supportsImages() const noexcept
|
||||
{
|
||||
auto *provider = m_agent ? m_agent->provider() : nullptr;
|
||||
return provider
|
||||
&& provider->capabilities().testFlag(Providers::ProviderCapability::Image);
|
||||
}
|
||||
|
||||
void Session::setContentLoader(ContentLoader loader)
|
||||
{
|
||||
m_contentLoader = std::move(loader);
|
||||
@@ -186,6 +199,13 @@ LLMQore::RequestID Session::sendCompletion(Templates::ContextData ctx)
|
||||
auto *tmpl = m_agent->promptTemplate();
|
||||
const auto &cfg = m_agent->config();
|
||||
|
||||
const QString rolePrompt = m_systemPrompt ? m_systemPrompt->compose() : QString();
|
||||
if (!rolePrompt.isEmpty()) {
|
||||
ctx.systemPrompt = (ctx.systemPrompt && !ctx.systemPrompt->isEmpty())
|
||||
? rolePrompt + QStringLiteral("\n\n") + *ctx.systemPrompt
|
||||
: rolePrompt;
|
||||
}
|
||||
|
||||
QJsonObject payload{{QStringLiteral("model"), cfg.model}};
|
||||
if (!provider->prepareRequest(payload, tmpl, ctx, /*tools=*/false, /*thinking=*/false))
|
||||
return {};
|
||||
|
||||
@@ -55,6 +55,9 @@ public:
|
||||
ConversationHistory *history() const noexcept { return m_history; }
|
||||
SystemPromptBuilder *systemPrompt() const noexcept { return m_systemPrompt; }
|
||||
|
||||
LLMQore::BaseClient *client() const noexcept;
|
||||
bool supportsImages() const noexcept;
|
||||
|
||||
void setContextBindings(Templates::ContextRenderer::Bindings bindings);
|
||||
|
||||
QString renderAgentContext() const;
|
||||
|
||||
@@ -2,6 +2,7 @@ add_library(Providers STATIC
|
||||
ProviderID.hpp
|
||||
Provider.hpp Provider.cpp
|
||||
ProviderFactory.hpp ProviderFactory.cpp
|
||||
GenericProvider.hpp GenericProvider.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(Providers
|
||||
|
||||
113
sources/providers/GenericProvider.cpp
Normal file
113
sources/providers/GenericProvider.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright (C) 2024-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "GenericProvider.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <LLMQore/BaseClient.hpp>
|
||||
#include <LLMQore/ClaudeClient.hpp>
|
||||
#include <LLMQore/GoogleAIClient.hpp>
|
||||
#include <LLMQore/LlamaCppClient.hpp>
|
||||
#include <LLMQore/MistralClient.hpp>
|
||||
#include <LLMQore/OllamaClient.hpp>
|
||||
#include <LLMQore/OpenAIClient.hpp>
|
||||
#include <LLMQore/OpenAIResponsesClient.hpp>
|
||||
|
||||
#include "ProviderFactory.hpp"
|
||||
|
||||
namespace QodeAssist::Providers {
|
||||
|
||||
GenericProvider::GenericProvider(
|
||||
QString name,
|
||||
ProviderID id,
|
||||
ProviderCapabilities capabilities,
|
||||
const ClientFactory &clientFactory,
|
||||
QObject *parent)
|
||||
: Provider(parent)
|
||||
, m_name(std::move(name))
|
||||
, m_id(id)
|
||||
, m_capabilities(capabilities)
|
||||
, m_client(clientFactory(this))
|
||||
{}
|
||||
|
||||
QString GenericProvider::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
ProviderID GenericProvider::providerID() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ProviderCapabilities GenericProvider::capabilities() const
|
||||
{
|
||||
return m_capabilities;
|
||||
}
|
||||
|
||||
::LLMQore::BaseClient *GenericProvider::client() const
|
||||
{
|
||||
return m_client;
|
||||
}
|
||||
|
||||
QFuture<QList<QString>> GenericProvider::getInstalledModels(const QString &url)
|
||||
{
|
||||
m_client->setUrl(url);
|
||||
m_client->setApiKey(apiKey());
|
||||
return m_client->listModels();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using Cap = ProviderCapability;
|
||||
|
||||
template<typename ClientT>
|
||||
GenericProvider::ClientFactory makeFactory()
|
||||
{
|
||||
return [](QObject *parent) -> ::LLMQore::BaseClient * {
|
||||
return new ClientT(QString(), QString(), QString(), parent);
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void registerBuiltinProviders()
|
||||
{
|
||||
const auto reg = [](const QString &api,
|
||||
ProviderID id,
|
||||
ProviderCapabilities caps,
|
||||
GenericProvider::ClientFactory factory) {
|
||||
ProviderFactory::registerType(api, [=](QObject *parent) -> Provider * {
|
||||
return new GenericProvider(api, id, caps, factory, parent);
|
||||
});
|
||||
};
|
||||
|
||||
const ProviderCapabilities full
|
||||
= Cap::Tools | Cap::Thinking | Cap::Image | Cap::ModelListing;
|
||||
|
||||
reg("Claude", ProviderID::Claude, full, makeFactory<::LLMQore::ClaudeClient>());
|
||||
reg("Google AI", ProviderID::GoogleAI, full, makeFactory<::LLMQore::GoogleAIClient>());
|
||||
reg("llama.cpp", ProviderID::LlamaCpp, full, makeFactory<::LLMQore::LlamaCppClient>());
|
||||
reg("LM Studio (Chat Completions)", ProviderID::LMStudio, full,
|
||||
makeFactory<::LLMQore::OpenAIClient>());
|
||||
reg("LM Studio (Responses API)", ProviderID::OpenAIResponses, full,
|
||||
makeFactory<::LLMQore::OpenAIResponsesClient>());
|
||||
reg("Mistral AI", ProviderID::MistralAI, full, makeFactory<::LLMQore::MistralClient>());
|
||||
reg("Codestral", ProviderID::MistralAI, Cap::Tools | Cap::Image,
|
||||
makeFactory<::LLMQore::MistralClient>());
|
||||
reg("Ollama (Native)", ProviderID::Ollama, full, makeFactory<::LLMQore::OllamaClient>());
|
||||
reg("Ollama (OpenAI-compatible)", ProviderID::OpenAICompatible, full,
|
||||
makeFactory<::LLMQore::OpenAIClient>());
|
||||
reg("OpenAI (Chat Completions)", ProviderID::OpenAI, full,
|
||||
makeFactory<::LLMQore::OpenAIClient>());
|
||||
reg("OpenAI (Responses API)", ProviderID::OpenAIResponses, full,
|
||||
makeFactory<::LLMQore::OpenAIResponsesClient>());
|
||||
reg("OpenAI Compatible", ProviderID::OpenAICompatible,
|
||||
Cap::Tools | Cap::Image | Cap::Thinking, makeFactory<::LLMQore::OpenAIClient>());
|
||||
reg("OpenRouter", ProviderID::OpenRouter,
|
||||
Cap::Tools | Cap::Image | Cap::Thinking | Cap::ModelListing,
|
||||
makeFactory<::LLMQore::OpenAIClient>());
|
||||
}
|
||||
|
||||
} // namespace QodeAssist::Providers
|
||||
50
sources/providers/GenericProvider.hpp
Normal file
50
sources/providers/GenericProvider.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2024-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "Provider.hpp"
|
||||
|
||||
namespace LLMQore {
|
||||
class BaseClient;
|
||||
}
|
||||
|
||||
namespace QodeAssist::Providers {
|
||||
|
||||
// A configuration-driven provider: it owns an LLMQore client and exposes a
|
||||
// fixed identity/capability set. Concrete behaviour (request shape) comes from
|
||||
// the agent's prompt template via Provider::prepareRequest, so a single class
|
||||
// covers every client_api by varying the client factory + metadata.
|
||||
class GenericProvider : public Provider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using ClientFactory = std::function<::LLMQore::BaseClient *(QObject *)>;
|
||||
|
||||
GenericProvider(
|
||||
QString name,
|
||||
ProviderID id,
|
||||
ProviderCapabilities capabilities,
|
||||
const ClientFactory &clientFactory,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
QString name() const override;
|
||||
QFuture<QList<QString>> getInstalledModels(const QString &url) override;
|
||||
ProviderID providerID() const override;
|
||||
ProviderCapabilities capabilities() const override;
|
||||
::LLMQore::BaseClient *client() const override;
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
ProviderID m_id;
|
||||
ProviderCapabilities m_capabilities;
|
||||
::LLMQore::BaseClient *m_client;
|
||||
};
|
||||
|
||||
// Registers every built-in client_api into ProviderFactory. Must be called once
|
||||
// at plugin startup before any agent/session is created.
|
||||
void registerBuiltinProviders();
|
||||
|
||||
} // namespace QodeAssist::Providers
|
||||
@@ -1,274 +0,0 @@
|
||||
// Copyright (C) 2024-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
||||
|
||||
#include "AgentPipelinesPage.hpp"
|
||||
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QColor>
|
||||
#include <QFont>
|
||||
#include <QFrame>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <QPointer>
|
||||
#include <QPushButton>
|
||||
#include <QScrollArea>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "../../Version.hpp"
|
||||
#include "AgentRosterWidget.hpp"
|
||||
#include "AgentsSettingsPage.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "PipelinesConfig.hpp"
|
||||
#include "SettingsConstants.hpp"
|
||||
#include "SettingsTr.hpp"
|
||||
|
||||
#include <AgentFactory.hpp>
|
||||
|
||||
namespace QodeAssist::Settings {
|
||||
|
||||
AgentPipelinesPageNavigator::AgentPipelinesPageNavigator(QObject *parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kSaveDebounceMs = 300;
|
||||
|
||||
struct SlotMeta
|
||||
{
|
||||
const char *title;
|
||||
const char *hint;
|
||||
};
|
||||
|
||||
const SlotMeta kSlotMeta[] = {
|
||||
{TrConstants::CODE_COMPLETION, TrConstants::SLOT_HINT_CODE_COMPLETION},
|
||||
{TrConstants::CHAT_ASSISTANT, TrConstants::SLOT_HINT_CHAT_ASSISTANT},
|
||||
{TrConstants::CHAT_COMPRESSION, TrConstants::SLOT_HINT_CHAT_COMPRESSION},
|
||||
{TrConstants::QUICK_REFACTOR, TrConstants::SLOT_HINT_QUICK_REFACTOR},
|
||||
};
|
||||
|
||||
class AgentPipelinesPageWidget : public Core::IOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY_MOVE(AgentPipelinesPageWidget)
|
||||
public:
|
||||
AgentPipelinesPageWidget(
|
||||
const QPointer<AgentFactory> &agentFactory,
|
||||
const QPointer<AgentPipelinesPageNavigator> &navigator,
|
||||
const QPointer<AgentsPageNavigator> &agentsNavigator)
|
||||
: m_agentFactory(agentFactory)
|
||||
, m_navigator(navigator)
|
||||
, m_agentsNavigator(agentsNavigator)
|
||||
{
|
||||
m_titleLabel = new QLabel(Tr::tr(TrConstants::AGENT_PIPELINES), this);
|
||||
QFont tf = m_titleLabel->font();
|
||||
tf.setBold(true);
|
||||
tf.setPixelSize(13);
|
||||
m_titleLabel->setFont(tf);
|
||||
|
||||
m_resetBtn = new QPushButton(Tr::tr(TrConstants::RESET_TO_DEFAULTS), this);
|
||||
|
||||
auto *headerRow = new QHBoxLayout;
|
||||
headerRow->setContentsMargins(0, 0, 0, 0);
|
||||
headerRow->setSpacing(8);
|
||||
headerRow->addWidget(m_titleLabel);
|
||||
headerRow->addStretch(1);
|
||||
headerRow->addWidget(m_resetBtn);
|
||||
|
||||
auto *headerSep = new QFrame(this);
|
||||
headerSep->setFrameShape(QFrame::HLine);
|
||||
headerSep->setFrameShadow(QFrame::Sunken);
|
||||
|
||||
m_rosters[0] = new AgentRosterWidget(this);
|
||||
m_rosters[1] = new AgentRosterWidget(this);
|
||||
m_rosters[2] = new AgentRosterWidget(this);
|
||||
m_rosters[3] = new AgentRosterWidget(this);
|
||||
|
||||
for (int i = 0; i < kRosterCount; ++i)
|
||||
m_rosters[i]->setSlot(Tr::tr(kSlotMeta[i].title), Tr::tr(kSlotMeta[i].hint), {});
|
||||
|
||||
auto *content = new QWidget(this);
|
||||
auto *contentLay = new QVBoxLayout(content);
|
||||
contentLay->setContentsMargins(0, 0, 0, 0);
|
||||
contentLay->setSpacing(12);
|
||||
for (int i = 0; i < kRosterCount; ++i)
|
||||
contentLay->addWidget(m_rosters[i]);
|
||||
contentLay->addStretch(1);
|
||||
|
||||
auto *scroll = new QScrollArea(this);
|
||||
scroll->setWidgetResizable(true);
|
||||
scroll->setFrameShape(QFrame::NoFrame);
|
||||
scroll->setWidget(content);
|
||||
|
||||
auto *root = new QVBoxLayout(this);
|
||||
root->setContentsMargins(8, 8, 8, 8);
|
||||
root->setSpacing(6);
|
||||
root->addLayout(headerRow);
|
||||
root->addWidget(headerSep);
|
||||
root->addWidget(scroll, 1);
|
||||
|
||||
m_saveDebounce = new QTimer(this);
|
||||
m_saveDebounce->setSingleShot(true);
|
||||
m_saveDebounce->setInterval(kSaveDebounceMs);
|
||||
connect(m_saveDebounce, &QTimer::timeout, this, [this]() { persistRosters(); });
|
||||
|
||||
loadFromSettings();
|
||||
|
||||
connect(m_resetBtn, &QPushButton::clicked, this, &AgentPipelinesPageWidget::onReset);
|
||||
|
||||
for (int i = 0; i < kRosterCount; ++i) {
|
||||
connect(m_rosters[i], &AgentRosterWidget::editAgentRequested, this,
|
||||
&AgentPipelinesPageWidget::onEditAgent);
|
||||
connect(m_rosters[i], &AgentRosterWidget::rosterChanged, this,
|
||||
[this](const QStringList &) { m_saveDebounce->start(); });
|
||||
}
|
||||
}
|
||||
|
||||
~AgentPipelinesPageWidget() override
|
||||
{
|
||||
if (m_saveDebounce && m_saveDebounce->isActive()) {
|
||||
m_saveDebounce->stop();
|
||||
persistRosters();
|
||||
}
|
||||
}
|
||||
|
||||
void apply() final
|
||||
{
|
||||
if (m_saveDebounce && m_saveDebounce->isActive())
|
||||
m_saveDebounce->stop();
|
||||
persistRosters();
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int kRosterCount = 4;
|
||||
|
||||
void persistRosters()
|
||||
{
|
||||
PipelineRosters rosters;
|
||||
rosters.codeCompletion = m_rosters[0]->roster();
|
||||
rosters.chatAssistant = m_rosters[1]->roster();
|
||||
rosters.chatCompression = m_rosters[2]->roster();
|
||||
rosters.quickRefactor = m_rosters[3]->roster();
|
||||
QString err;
|
||||
if (!PipelinesConfig::save(rosters, &err)) {
|
||||
LOG_MESSAGE(QStringLiteral("[Pipelines] save failed (%1): %2")
|
||||
.arg(PipelinesConfig::filePath(), err));
|
||||
if (!m_saveErrorShown) {
|
||||
m_saveErrorShown = true;
|
||||
QMessageBox::warning(
|
||||
Core::ICore::dialogParent(),
|
||||
Tr::tr(TrConstants::AGENT_PIPELINES),
|
||||
tr("Failed to save pipelines.toml:\n%1\n\n"
|
||||
"Further save failures will only be logged.")
|
||||
.arg(err));
|
||||
}
|
||||
} else {
|
||||
m_saveErrorShown = false;
|
||||
}
|
||||
}
|
||||
|
||||
void onReset()
|
||||
{
|
||||
const auto reply = QMessageBox::question(
|
||||
Core::ICore::dialogParent(),
|
||||
Tr::tr(TrConstants::RESET_SETTINGS),
|
||||
Tr::tr(TrConstants::CONFIRMATION),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
|
||||
if (reply != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
QString err;
|
||||
if (!PipelinesConfig::save(PipelineRosters::defaults(), &err))
|
||||
LOG_MESSAGE(QStringLiteral("[Pipelines] failed to reset rosters: %1").arg(err));
|
||||
|
||||
m_saveErrorShown = false;
|
||||
loadFromSettings();
|
||||
}
|
||||
|
||||
void onEditAgent(const QString &name)
|
||||
{
|
||||
if (m_agentsNavigator)
|
||||
m_agentsNavigator->requestSelectAgent(name);
|
||||
if (m_navigator)
|
||||
emit m_navigator->editAgentRequested(name);
|
||||
|
||||
#if QODEASSIST_QT_CREATOR_VERSION >= QT_VERSION_CHECK(18, 0, 83)
|
||||
Core::ICore::showSettings(Constants::QODE_ASSIST_AGENTS_SETTINGS_PAGE_ID);
|
||||
#else
|
||||
Core::ICore::showOptionsDialog(Constants::QODE_ASSIST_AGENTS_SETTINGS_PAGE_ID);
|
||||
#endif
|
||||
}
|
||||
|
||||
void loadFromSettings()
|
||||
{
|
||||
const PipelinesLoadResult lr = PipelinesConfig::load();
|
||||
if (lr.status == PipelinesLoadStatus::ParseError
|
||||
|| lr.status == PipelinesLoadStatus::SchemaError) {
|
||||
QMessageBox::warning(
|
||||
Core::ICore::dialogParent(),
|
||||
Tr::tr(TrConstants::AGENT_PIPELINES),
|
||||
tr("pipelines.toml has issues — using defaults for affected entries:\n%1\n\n"
|
||||
"Click OK to continue. Changes you make here will overwrite the file.")
|
||||
.arg(lr.message));
|
||||
}
|
||||
|
||||
AgentFactory *factory = m_agentFactory.data();
|
||||
m_rosters[0]->setRoster(lr.rosters.codeCompletion, factory);
|
||||
m_rosters[1]->setRoster(lr.rosters.chatAssistant, factory);
|
||||
m_rosters[2]->setRoster(lr.rosters.chatCompression, factory);
|
||||
m_rosters[3]->setRoster(lr.rosters.quickRefactor, factory);
|
||||
}
|
||||
|
||||
QPointer<AgentFactory> m_agentFactory;
|
||||
QPointer<AgentPipelinesPageNavigator> m_navigator;
|
||||
QPointer<AgentsPageNavigator> m_agentsNavigator;
|
||||
|
||||
QLabel *m_titleLabel = nullptr;
|
||||
QPushButton *m_resetBtn = nullptr;
|
||||
|
||||
AgentRosterWidget *m_rosters[kRosterCount] = {};
|
||||
|
||||
QTimer *m_saveDebounce = nullptr;
|
||||
bool m_saveErrorShown = false;
|
||||
};
|
||||
|
||||
class AgentPipelinesOptionsPage final : public Core::IOptionsPage
|
||||
{
|
||||
public:
|
||||
AgentPipelinesOptionsPage(
|
||||
AgentFactory *agentFactory,
|
||||
AgentPipelinesPageNavigator *navigator,
|
||||
AgentsPageNavigator *agentsNavigator)
|
||||
{
|
||||
setId(Constants::QODE_ASSIST_AGENT_PIPELINES_PAGE_ID);
|
||||
setDisplayName(Tr::tr(TrConstants::AGENT_PIPELINES));
|
||||
setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY);
|
||||
const QPointer<AgentFactory> factoryPtr(agentFactory);
|
||||
const QPointer<AgentPipelinesPageNavigator> navPtr(navigator);
|
||||
const QPointer<AgentsPageNavigator> agentsNavPtr(agentsNavigator);
|
||||
setWidgetCreator([factoryPtr, navPtr, agentsNavPtr] {
|
||||
return new AgentPipelinesPageWidget(factoryPtr, navPtr, agentsNavPtr);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<Core::IOptionsPage> createAgentPipelinesSettingsPage(
|
||||
AgentFactory *agentFactory,
|
||||
AgentPipelinesPageNavigator *navigator,
|
||||
AgentsPageNavigator *agentsNavigator)
|
||||
{
|
||||
return std::make_unique<AgentPipelinesOptionsPage>(
|
||||
agentFactory, navigator, agentsNavigator);
|
||||
}
|
||||
|
||||
} // namespace QodeAssist::Settings
|
||||
|
||||
#include "AgentPipelinesPage.moc"
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright (C) 2024-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
namespace Core {
|
||||
class IOptionsPage;
|
||||
}
|
||||
|
||||
namespace QodeAssist {
|
||||
class AgentFactory;
|
||||
}
|
||||
|
||||
namespace QodeAssist::Settings {
|
||||
|
||||
class AgentsPageNavigator;
|
||||
|
||||
class AgentPipelinesPageNavigator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY_MOVE(AgentPipelinesPageNavigator)
|
||||
public:
|
||||
explicit AgentPipelinesPageNavigator(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void editAgentRequested(const QString &agentName);
|
||||
};
|
||||
|
||||
std::unique_ptr<Core::IOptionsPage> createAgentPipelinesSettingsPage(
|
||||
AgentFactory *agentFactory,
|
||||
AgentPipelinesPageNavigator *navigator,
|
||||
AgentsPageNavigator *agentsNavigator);
|
||||
|
||||
} // namespace QodeAssist::Settings
|
||||
@@ -1,5 +1,4 @@
|
||||
add_library(QodeAssistAgentPipelines OBJECT
|
||||
AgentPipelinesPage.hpp AgentPipelinesPage.cpp
|
||||
add_library(QodeAssistAgentPipelines STATIC
|
||||
PipelinesConfig.hpp PipelinesConfig.cpp
|
||||
AgentRosterWidget.hpp AgentRosterWidget.cpp
|
||||
AgentSlotWidget.hpp AgentSlotWidget.cpp
|
||||
|
||||
Reference in New Issue
Block a user