From f36173d932281b769f5a0b50befe07435b05579f Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Thu, 11 Jun 2026 14:51:49 +0200 Subject: [PATCH] refactor: Agent roaster improve --- ChatView/ChatAgentController.cpp | 16 +++++++- ChatView/ChatCompressor.cpp | 4 +- ChatView/ChatRootView.cpp | 13 +++++- LLMClientInterface.cpp | 30 ++++++-------- LLMClientInterface.hpp | 3 ++ QuickRefactorHandler.cpp | 10 ++--- qodeassist.cpp | 1 + sources/Session/SessionManager.cpp | 63 ++++++++++++++++++++++++++++++ sources/Session/SessionManager.hpp | 9 +++++ 9 files changed, 121 insertions(+), 28 deletions(-) diff --git a/ChatView/ChatAgentController.cpp b/ChatView/ChatAgentController.cpp index 39309e7..f40a87b 100644 --- a/ChatView/ChatAgentController.cpp +++ b/ChatView/ChatAgentController.cpp @@ -9,6 +9,7 @@ #include #include +#include namespace QodeAssist::Chat { @@ -52,7 +53,20 @@ void ChatAgentController::setCurrentAgent(const QString &name) void ChatAgentController::reload() { - m_availableAgents = m_agentFactory ? m_agentFactory->configNames() : QStringList{}; + const QStringList all = m_agentFactory ? m_agentFactory->configNames() : QStringList{}; + const QStringList roster = Settings::PipelinesConfig::load().rosters.chatAssistant; + + if (roster.isEmpty()) { + m_availableAgents = all; + } else { + QStringList filtered; + for (const QString &name : roster) { + if (all.contains(name)) + filtered.append(name); + } + m_availableAgents = filtered.isEmpty() ? all : filtered; + } + emit availableAgentsChanged(); ensureValidCurrent(); } diff --git a/ChatView/ChatCompressor.cpp b/ChatView/ChatCompressor.cpp index 624f56a..a6a202f 100644 --- a/ChatView/ChatCompressor.cpp +++ b/ChatView/ChatCompressor.cpp @@ -66,7 +66,7 @@ void ChatCompressor::startCompression( } QString sessionError; - Session *session = m_sessionManager->createSession(m_activeAgent, &sessionError); + Session *session = m_sessionManager->acquire(m_activeAgent, &sessionError); if (!session) { emit compressionFailed( sessionError.isEmpty() ? tr("No chat agent selected") : sessionError); @@ -265,7 +265,7 @@ void ChatCompressor::cleanupState() m_session = nullptr; if (session && m_sessionManager) - m_sessionManager->removeSession(session); + m_sessionManager->release(session); } } // namespace QodeAssist::Chat diff --git a/ChatView/ChatRootView.cpp b/ChatView/ChatRootView.cpp index 716d6df..f759293 100644 --- a/ChatView/ChatRootView.cpp +++ b/ChatView/ChatRootView.cpp @@ -29,9 +29,11 @@ #include "QodeAssistConstants.hpp" #include +#include #include #include #include +#include #include "ChatAgentController.hpp" #include "AgentRole.hpp" @@ -1269,7 +1271,16 @@ void ChatRootView::compressCurrentChat() if (currentChatAgent().isEmpty()) loadAvailableChatAgents(); m_chatCompressor->setSessionManager(sessionManager()); - m_chatCompressor->setActiveAgent(currentChatAgent()); + + QString compressionAgent = currentChatAgent(); + const QStringList roster = Settings::PipelinesConfig::load().rosters.chatCompression; + if (!roster.isEmpty() && agentFactory()) { + const QString picked + = AgentRouter::pickAgent(roster, AgentRouter::Context{}, *agentFactory()); + if (!picked.isEmpty()) + compressionAgent = picked; + } + m_chatCompressor->setActiveAgent(compressionAgent); m_chatCompressor->startCompression(m_recentFilePath, m_history); } diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index b0b0100..b727bce 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "sources/common/ContextData.hpp" @@ -42,11 +43,13 @@ LLMClientInterface::LLMClientInterface( const Settings::GeneralSettings &generalSettings, const Settings::CodeCompletionSettings &completeSettings, AgentFactory &agentFactory, + SessionManager &sessionManager, Context::IDocumentReader &documentReader, IRequestPerformanceLogger &performanceLogger) : m_generalSettings(generalSettings) , m_completeSettings(completeSettings) , m_agentFactory(agentFactory) + , m_sessionManager(sessionManager) , m_documentReader(documentReader) , m_performanceLogger(performanceLogger) , m_contextManager(new Context::ContextManager(this)) @@ -117,7 +120,7 @@ void LLMClientInterface::finishRequest(const QString &requestId) m_performanceLogger.endTimeMeasurement(requestId); if (session) - session->deleteLater(); + m_sessionManager.release(session); } void LLMClientInterface::sendData(const QByteArray &data) @@ -155,10 +158,8 @@ void LLMClientInterface::handleCancelRequest() for (auto it = requests.begin(); it != requests.end(); ++it) { m_performanceLogger.endTimeMeasurement(it.key()); - if (Session *session = it.value().session) { - session->cancel(); - session->deleteLater(); - } + if (Session *session = it.value().session) + m_sessionManager.release(session); } LOG_MESSAGE("All requests cancelled and state cleared"); @@ -251,20 +252,11 @@ void LLMClientInterface::handleCompletion(const QJsonObject &request) return; } - QString agentError; - Agent *agent = m_agentFactory.create(agentName, /*parent=*/nullptr, &agentError); - if (!agent) { - LOG_MESSAGE(agentError); - sendErrorResponse(request, agentError); - return; - } - - auto *session = new Session(agent, this); - if (!session->isValid()) { - const QString error = session->invalidReason(); - delete session; - LOG_MESSAGE(error); - sendErrorResponse(request, error); + QString sessionError; + Session *session = m_sessionManager.acquire(agentName, &sessionError); + if (!session) { + LOG_MESSAGE(sessionError); + sendErrorResponse(request, sessionError); return; } diff --git a/LLMClientInterface.hpp b/LLMClientInterface.hpp index f7783d1..0215597 100644 --- a/LLMClientInterface.hpp +++ b/LLMClientInterface.hpp @@ -24,6 +24,7 @@ namespace QodeAssist { class AgentFactory; class Session; +class SessionManager; namespace Templates { struct ContextData; @@ -38,6 +39,7 @@ public: const Settings::GeneralSettings &generalSettings, const Settings::CodeCompletionSettings &completeSettings, AgentFactory &agentFactory, + SessionManager &sessionManager, Context::IDocumentReader &documentReader, IRequestPerformanceLogger &performanceLogger); ~LLMClientInterface() override; @@ -85,6 +87,7 @@ private: const Settings::CodeCompletionSettings &m_completeSettings; const Settings::GeneralSettings &m_generalSettings; AgentFactory &m_agentFactory; + SessionManager &m_sessionManager; Context::IDocumentReader &m_documentReader; IRequestPerformanceLogger &m_performanceLogger; QElapsedTimer m_completionTimer; diff --git a/QuickRefactorHandler.cpp b/QuickRefactorHandler.cpp index 6962cf1..5b88cd1 100644 --- a/QuickRefactorHandler.cpp +++ b/QuickRefactorHandler.cpp @@ -156,7 +156,7 @@ void QuickRefactorHandler::prepareAndSendRequest( } QString sessionError; - Session *session = m_sessionManager->createSession(agentName, &sessionError); + Session *session = m_sessionManager->acquire(agentName, &sessionError); if (!session) { emitError(sessionError.isEmpty() ? QStringLiteral("No quick refactor agent selected") : sessionError); @@ -172,7 +172,7 @@ void QuickRefactorHandler::prepareAndSendRequest( const bool enableTools = Settings::quickRefactorSettings().useTools(); if (enableTools) { - Tools::registerQodeAssistTools(client->tools()); + m_sessionManager->toolContributors().contribute(client->tools()); client->setMaxToolContinuations(Settings::toolsSettings().maxToolContinuations()); } @@ -385,7 +385,7 @@ void QuickRefactorHandler::cancelRequest() Session *session = it.value().session; m_activeRequests.erase(it); if (session && m_sessionManager) - m_sessionManager->removeSession(session); + m_sessionManager->release(session); } RefactorResult result; @@ -429,7 +429,7 @@ void QuickRefactorHandler::onRefactorFinished(const QString &requestId) emit refactoringCompleted(result); if (session && m_sessionManager) - m_sessionManager->removeSession(session); + m_sessionManager->release(session); } void QuickRefactorHandler::onRefactorFailed( @@ -453,7 +453,7 @@ void QuickRefactorHandler::onRefactorFailed( emit refactoringCompleted(result); if (session && m_sessionManager) - m_sessionManager->removeSession(session); + m_sessionManager->release(session); } } // namespace QodeAssist diff --git a/qodeassist.cpp b/qodeassist.cpp index 72fc26d..2bbf5ed 100644 --- a/qodeassist.cpp +++ b/qodeassist.cpp @@ -347,6 +347,7 @@ public: Settings::generalSettings(), Settings::codeCompletionSettings(), *m_agentFactory, + *m_sessionManager, m_documentReader, m_performanceLogger)); m_qodeAssistClient->setSessionManager(m_sessionManager); diff --git a/sources/Session/SessionManager.cpp b/sources/Session/SessionManager.cpp index dd77222..bbb3f21 100644 --- a/sources/Session/SessionManager.cpp +++ b/sources/Session/SessionManager.cpp @@ -4,9 +4,14 @@ #include "SessionManager.hpp" +#include +#include + #include "Agent.hpp" #include "AgentFactory.hpp" +#include "ConversationHistory.hpp" #include "Session.hpp" +#include "SystemPromptBuilder.hpp" namespace QodeAssist { @@ -54,6 +59,64 @@ Session *SessionManager::createSession( return session; } +Session *SessionManager::acquire(const QString &agentName, QString *errorOut) +{ + auto &bucket = m_pool[agentName]; + while (!bucket.isEmpty()) { + QPointer pooled = bucket.takeLast(); + if (pooled && pooled->isValid()) { + resetSession(pooled); + m_sessions.append(pooled); + return pooled.data(); + } + if (pooled) + pooled->deleteLater(); + } + + return createSession(agentName, /*externalHistory=*/nullptr, errorOut); +} + +void SessionManager::release(Session *session) +{ + if (!session) + return; + + const int idx = m_sessions.indexOf(session); + if (idx < 0) + return; + m_sessions.removeAt(idx); + + if (session->isInFlight()) + session->cancel(); + + session->disconnect(); + resetSession(session); + + const QString agentName + = session->agent() ? session->agent()->config().name : QString(); + QList> &bucket = m_pool[agentName]; + if (agentName.isEmpty() || bucket.size() >= kMaxPooledPerAgent) { + emit sessionRemoved(session); + session->deleteLater(); + } else { + bucket.append(session); + } +} + +void SessionManager::resetSession(Session *session) +{ + if (!session) + return; + if (auto *history = session->history()) + history->clear(); + if (auto *systemPrompt = session->systemPrompt()) + systemPrompt->clear(); + if (auto *client = session->client()) { + if (auto *tools = client->tools()) + tools->removeAllTools(); + } +} + void SessionManager::removeSession(Session *session) { if (!session) diff --git a/sources/Session/SessionManager.hpp b/sources/Session/SessionManager.hpp index 52b35df..d1a3694 100644 --- a/sources/Session/SessionManager.hpp +++ b/sources/Session/SessionManager.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -33,6 +34,9 @@ public: ConversationHistory *externalHistory, QString *errorOut = nullptr); + Session *acquire(const QString &agentName, QString *errorOut = nullptr); + void release(Session *session); + void removeSession(Session *session); QList sessions() const; @@ -47,8 +51,13 @@ signals: void sessionRemoved(Session *session); private: + void resetSession(Session *session); + + static constexpr int kMaxPooledPerAgent = 2; + QPointer m_agentFactory; QList> m_sessions; + QHash>> m_pool; ToolContributorRegistry m_toolContributors; };