// Copyright (C) 2024-2026 Petr Mironychev // SPDX-License-Identifier: GPL-3.0-or-later #include "Agent.hpp" #include #include "JsonPromptTemplate.hpp" #include "PromptTemplate.hpp" #include "Provider.hpp" namespace QodeAssist { using Providers::Provider; using Templates::JsonPromptTemplate; using Templates::PromptTemplate; QString AgentConfig::validate(const AgentConfig &config) { if (config.name.isEmpty()) return QStringLiteral("Agent config has no name"); if (config.schemaVersion > AgentConfig::kSupportedSchemaVersion) { return QStringLiteral( "Agent config '%1' declares schema_version %2 but this plugin " "supports at most %3 — update QodeAssist to use this profile") .arg(config.name) .arg(config.schemaVersion) .arg(AgentConfig::kSupportedSchemaVersion); } if (config.providerInstance.isEmpty()) return QStringLiteral("Agent config '%1' has no provider_instance").arg(config.name); if (config.model.isEmpty()) return QStringLiteral("Agent config '%1' has no model").arg(config.name); if (config.endpoint.isEmpty()) return QStringLiteral("Agent config '%1' has no endpoint").arg(config.name); if (config.messageFormat.isEmpty()) { return QStringLiteral("Agent config '%1' has no [template].message_format") .arg(config.name); } return {}; } Agent::Agent(AgentConfig config, Providers::Provider *providerOwned, QObject *parent) : QObject(parent) , m_config(std::move(config)) , m_provider(providerOwned) { m_invalidReason = AgentConfig::validate(m_config); if (!m_invalidReason.isEmpty()) return; if (!m_provider) { m_invalidReason = QStringLiteral("Agent '%1' was constructed without a provider").arg(m_config.name); return; } m_provider->setParent(this); QString tmplErr; m_promptTemplate = JsonPromptTemplate::fromConfig(m_config, &tmplErr); if (!m_promptTemplate) { m_invalidReason = tmplErr.isEmpty() ? QStringLiteral("Failed to build prompt template for agent '%1'") .arg(m_config.name) : tmplErr; } } Agent::~Agent() = default; PromptTemplate *Agent::promptTemplate() noexcept { return m_promptTemplate.get(); } const PromptTemplate *Agent::promptTemplate() const noexcept { return m_promptTemplate.get(); } QFuture> Agent::installedModels() { Q_ASSERT_X(thread() == QThread::currentThread(), Q_FUNC_INFO, "Agent::installedModels called from non-owning thread; " "the underlying BaseClient is not thread-safe and must be " "accessed from the Agent's owner thread"); if (!m_provider) { return QtFuture::makeReadyValueFuture(QList{}); } return m_provider->getInstalledModels(m_provider->url()); } } // namespace QodeAssist