mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-06-30 18:19:11 -04:00
feat: Add possibility to overwrite agent config tools enabling
This commit is contained in:
@@ -9,12 +9,15 @@
|
||||
#include "SettingsTheme.hpp"
|
||||
#include "SettingsUiBuilders.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <utils/theme/theme.h>
|
||||
|
||||
#include <AgentFactory.hpp>
|
||||
#include <ProviderInstance.hpp>
|
||||
#include <ProviderInstanceFactory.hpp>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QColor>
|
||||
#include <QComboBox>
|
||||
#include <QEvent>
|
||||
@@ -29,6 +32,7 @@
|
||||
#include <QPlainTextEdit>
|
||||
#include <QPushButton>
|
||||
#include <QScopedValueRollback>
|
||||
#include <QSignalBlocker>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
@@ -247,6 +251,43 @@ AgentDetailPane::AgentDetailPane(QWidget *parent)
|
||||
m_effectiveUrl->setAutoFillBackground(true);
|
||||
connection->bodyLayout()->addWidget(m_effectiveUrl);
|
||||
|
||||
auto *capabilities = new SectionBox(tr("Capabilities"), this);
|
||||
m_thinkingValue = new QLabel(this);
|
||||
|
||||
m_toolsCheck = new QCheckBox(tr("Allow tool calls"), this);
|
||||
m_toolsCheck->setEnabled(false);
|
||||
connect(m_toolsCheck, &QCheckBox::clicked, this, [this](bool on) { onToggleTools(on); });
|
||||
|
||||
m_toolsResetBtn = new QPushButton(tr("Reset"), this);
|
||||
m_toolsResetBtn->setToolTip(tr("Remove the tools override and restore the agent's default"));
|
||||
m_toolsResetBtn->setVisible(false);
|
||||
connect(m_toolsResetBtn, &QPushButton::clicked, this, [this] { onResetTools(); });
|
||||
|
||||
auto *toolsHolder = new QWidget(this);
|
||||
auto *toolsRow = new QHBoxLayout(toolsHolder);
|
||||
toolsRow->setContentsMargins(0, 0, 0, 0);
|
||||
toolsRow->setSpacing(6);
|
||||
toolsRow->addWidget(m_toolsCheck);
|
||||
toolsRow->addStretch(1);
|
||||
toolsRow->addWidget(m_toolsResetBtn);
|
||||
|
||||
auto *capGrid = new QGridLayout;
|
||||
capGrid->setContentsMargins(0, 0, 0, 0);
|
||||
capGrid->setHorizontalSpacing(8);
|
||||
capGrid->setVerticalSpacing(4);
|
||||
FormBuilder(capGrid)
|
||||
.row(
|
||||
tr("Thinking:"),
|
||||
m_thinkingValue,
|
||||
tr("Whether this agent requests extended thinking. Defined by the "
|
||||
"agent template."))
|
||||
.row(
|
||||
tr("Tools:"),
|
||||
toolsHolder,
|
||||
tr("Whether the agent may call tools. Toggle to save a per-agent "
|
||||
"override in settings; Reset restores the agent's default."));
|
||||
capabilities->bodyLayout()->addLayout(capGrid);
|
||||
|
||||
auto *match = new SectionBox(tr("Match"), this);
|
||||
auto *matchHint = makeHintLabel(
|
||||
tr("When a feature slot has multiple bound agents, the first whose "
|
||||
@@ -286,6 +327,7 @@ AgentDetailPane::AgentDetailPane(QWidget *parent)
|
||||
root->addWidget(m_description);
|
||||
root->addWidget(identity);
|
||||
root->addWidget(connection);
|
||||
root->addWidget(capabilities);
|
||||
root->addWidget(match);
|
||||
root->addWidget(m_rawToggle, 0, Qt::AlignLeft);
|
||||
root->addWidget(m_rawToml);
|
||||
@@ -414,6 +456,38 @@ void AgentDetailPane::onResetProvider()
|
||||
setAgent(*cfg);
|
||||
}
|
||||
|
||||
void AgentDetailPane::onToggleTools(bool enabled)
|
||||
{
|
||||
if (!m_agentFactory || !m_current)
|
||||
return;
|
||||
|
||||
const QString name = m_current->name;
|
||||
QString err;
|
||||
if (!m_agentFactory->setAgentToolsOverride(name, enabled, &err)) {
|
||||
QMessageBox::warning(this, tr("Set tools"), err);
|
||||
return;
|
||||
}
|
||||
if (const AgentConfig *cfg = m_agentFactory->configByName(name))
|
||||
setAgent(*cfg);
|
||||
}
|
||||
|
||||
void AgentDetailPane::onResetTools()
|
||||
{
|
||||
if (!m_agentFactory || !m_current)
|
||||
return;
|
||||
if (!m_agentFactory->agentToolsOverride(m_current->name).has_value())
|
||||
return;
|
||||
|
||||
const QString name = m_current->name;
|
||||
QString err;
|
||||
if (!m_agentFactory->setAgentToolsOverride(name, std::nullopt, &err)) {
|
||||
QMessageBox::warning(this, tr("Reset tools"), err);
|
||||
return;
|
||||
}
|
||||
if (const AgentConfig *cfg = m_agentFactory->configByName(name))
|
||||
setAgent(*cfg);
|
||||
}
|
||||
|
||||
void AgentDetailPane::setAgent(const AgentConfig &cfg)
|
||||
{
|
||||
m_currentStorage = cfg;
|
||||
@@ -481,6 +555,19 @@ void AgentDetailPane::setAgent(const AgentConfig &cfg)
|
||||
hasModelOverride ? tr("Overridden in settings. Reset to use the agent's default model.")
|
||||
: QString());
|
||||
|
||||
m_thinkingValue->setText(cfg.enableThinking ? tr("Enabled") : tr("Disabled"));
|
||||
{
|
||||
QSignalBlocker block(m_toolsCheck);
|
||||
m_toolsCheck->setChecked(cfg.enableTools);
|
||||
}
|
||||
m_toolsCheck->setEnabled(m_agentFactory != nullptr);
|
||||
const bool hasToolsOverride = m_agentFactory
|
||||
&& m_agentFactory->agentToolsOverride(cfg.name).has_value();
|
||||
m_toolsResetBtn->setVisible(hasToolsOverride);
|
||||
m_toolsCheck->setToolTip(
|
||||
hasToolsOverride ? tr("Overridden in settings. Reset to use the agent's default.")
|
||||
: QString());
|
||||
|
||||
const QString eff = resolvedUrl + cfg.endpoint;
|
||||
m_effectiveUrl->setText(
|
||||
eff.isEmpty() ? tr("# effective request line\n(unknown — provider instance not found)")
|
||||
@@ -542,6 +629,13 @@ void AgentDetailPane::clear()
|
||||
m_modelChangeBtn->setEnabled(false);
|
||||
m_modelResetBtn->setVisible(false);
|
||||
m_effectiveUrl->clear();
|
||||
m_thinkingValue->clear();
|
||||
{
|
||||
QSignalBlocker block(m_toolsCheck);
|
||||
m_toolsCheck->setChecked(false);
|
||||
}
|
||||
m_toolsCheck->setEnabled(false);
|
||||
m_toolsResetBtn->setVisible(false);
|
||||
m_filePatternsValue->clear();
|
||||
m_rawToml->clear();
|
||||
m_openBtn->setEnabled(false);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <AgentConfig.hpp>
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
@@ -56,6 +57,8 @@ private:
|
||||
void onResetModel();
|
||||
void onChangeProvider(int index);
|
||||
void onResetProvider();
|
||||
void onToggleTools(bool enabled);
|
||||
void onResetTools();
|
||||
|
||||
bool m_inApplyPalette = false;
|
||||
bool m_providerComboPopulated = false;
|
||||
@@ -88,6 +91,10 @@ private:
|
||||
QPushButton *m_modelResetBtn = nullptr;
|
||||
QLabel *m_effectiveUrl = nullptr;
|
||||
|
||||
QLabel *m_thinkingValue = nullptr;
|
||||
QCheckBox *m_toolsCheck = nullptr;
|
||||
QPushButton *m_toolsResetBtn = nullptr;
|
||||
|
||||
QLineEdit *m_filePatternsValue = nullptr;
|
||||
|
||||
QToolButton *m_rawToggle = nullptr;
|
||||
|
||||
@@ -243,6 +243,7 @@ private:
|
||||
}
|
||||
m_agentFactory->clearAgentModelOverride(name);
|
||||
m_agentFactory->clearAgentProviderOverride(name);
|
||||
m_agentFactory->clearAgentToolsOverride(name);
|
||||
reloadFromDisk();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <QPalette>
|
||||
#include <QScopedValueRollback>
|
||||
#include <QScrollArea>
|
||||
#include <QScrollBar>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
@@ -164,6 +165,7 @@ void TagFilterStrip::rebuild()
|
||||
return a.first.localeAwareCompare(b.first) < 0;
|
||||
});
|
||||
|
||||
constexpr int kMaxColumns = 3;
|
||||
auto *gridHost = new QWidget(this);
|
||||
auto *grid = new QGridLayout(gridHost);
|
||||
grid->setContentsMargins(0, 0, 0, 0);
|
||||
@@ -176,12 +178,11 @@ void TagFilterStrip::rebuild()
|
||||
connect(chip, &TagChip::clicked, this, &TagFilterStrip::toggleTag);
|
||||
grid->addWidget(chip, gridRow, col, Qt::AlignLeft);
|
||||
m_chipByTag.insert(tag, chip);
|
||||
if (++col >= 4) {
|
||||
if (++col >= kMaxColumns) {
|
||||
col = 0;
|
||||
++gridRow;
|
||||
}
|
||||
}
|
||||
grid->setColumnStretch(4, 1);
|
||||
|
||||
constexpr int kMaxVisibleRows = 4;
|
||||
constexpr int kRowSpacing = 5;
|
||||
@@ -194,10 +195,12 @@ void TagFilterStrip::rebuild()
|
||||
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
scroll->setWidget(gridHost);
|
||||
scroll->setMaximumHeight(
|
||||
kMaxVisibleRows * chipHeight + (kMaxVisibleRows - 1) * kRowSpacing + 4);
|
||||
m_layout->addWidget(scroll);
|
||||
kMaxVisibleRows * chipHeight + (kMaxVisibleRows - 1) * kRowSpacing + chipHeight / 2 + 4);
|
||||
const int scrollBarWidth = scroll->verticalScrollBar()->sizeHint().width();
|
||||
scroll->setFixedWidth(gridHost->sizeHint().width() + scrollBarWidth + 2);
|
||||
m_layout->addWidget(scroll, 0, Qt::AlignLeft);
|
||||
} else {
|
||||
m_layout->addWidget(gridHost);
|
||||
m_layout->addWidget(gridHost, 0, Qt::AlignLeft);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,37 @@ void writeProviderOverride(const QString &name, const QString &providerInstance)
|
||||
s->setValue(providerOverrideKey(name), providerInstance);
|
||||
s->sync();
|
||||
}
|
||||
|
||||
constexpr auto kToolsOverrideGroup = "QodeAssist/AgentToolsOverrides";
|
||||
|
||||
Utils::Key toolsOverrideKey(const QString &name)
|
||||
{
|
||||
return Utils::Key(
|
||||
QStringLiteral("%1/%2").arg(QLatin1StringView(kToolsOverrideGroup), name).toUtf8());
|
||||
}
|
||||
|
||||
std::optional<bool> readToolsOverride(const QString &name)
|
||||
{
|
||||
auto *s = Core::ICore::settings();
|
||||
if (!s)
|
||||
return std::nullopt;
|
||||
const Utils::Key key = toolsOverrideKey(name);
|
||||
if (!s->contains(key))
|
||||
return std::nullopt;
|
||||
return s->value(key).toBool();
|
||||
}
|
||||
|
||||
void writeToolsOverride(const QString &name, std::optional<bool> enabled)
|
||||
{
|
||||
auto *s = Core::ICore::settings();
|
||||
if (!s)
|
||||
return;
|
||||
if (!enabled.has_value())
|
||||
s->remove(toolsOverrideKey(name));
|
||||
else
|
||||
s->setValue(toolsOverrideKey(name), *enabled);
|
||||
s->sync();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace QodeAssist {
|
||||
@@ -146,6 +177,11 @@ void AgentFactory::reload()
|
||||
const QString overrideProvider = readProviderOverride(cfg.name);
|
||||
if (!overrideProvider.isEmpty())
|
||||
cfg.providerInstance = overrideProvider;
|
||||
|
||||
m_baseToolsByName.insert(cfg.name, cfg.enableTools);
|
||||
const std::optional<bool> overrideTools = readToolsOverride(cfg.name);
|
||||
if (overrideTools.has_value())
|
||||
cfg.enableTools = *overrideTools;
|
||||
}
|
||||
emit agentsChanged();
|
||||
}
|
||||
@@ -289,6 +325,7 @@ void AgentFactory::clear()
|
||||
m_indexByName.clear();
|
||||
m_baseModelByName.clear();
|
||||
m_baseProviderByName.clear();
|
||||
m_baseToolsByName.clear();
|
||||
}
|
||||
|
||||
Providers::ProviderInstanceFactory *AgentFactory::instanceFactory() const noexcept
|
||||
@@ -361,4 +398,37 @@ void AgentFactory::clearAgentProviderOverride(const QString &name)
|
||||
writeProviderOverride(name, QString());
|
||||
}
|
||||
|
||||
bool AgentFactory::setAgentToolsOverride(
|
||||
const QString &name, std::optional<bool> enabled, QString *error)
|
||||
{
|
||||
Q_ASSERT(thread() == QThread::currentThread());
|
||||
|
||||
const auto it = m_indexByName.constFind(name);
|
||||
if (it == m_indexByName.constEnd()) {
|
||||
if (error)
|
||||
*error = QStringLiteral("Agent '%1' is not registered").arg(name);
|
||||
return false;
|
||||
}
|
||||
AgentConfig &cfg = m_configs[it.value()];
|
||||
const bool effective = enabled.has_value() ? *enabled
|
||||
: m_baseToolsByName.value(name, cfg.enableTools);
|
||||
if (cfg.enableTools == effective && readToolsOverride(name) == enabled)
|
||||
return true;
|
||||
|
||||
writeToolsOverride(name, enabled);
|
||||
cfg.enableTools = effective;
|
||||
emit agentToolsChanged(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<bool> AgentFactory::agentToolsOverride(const QString &name) const
|
||||
{
|
||||
return readToolsOverride(name);
|
||||
}
|
||||
|
||||
void AgentFactory::clearAgentToolsOverride(const QString &name)
|
||||
{
|
||||
writeToolsOverride(name, std::nullopt);
|
||||
}
|
||||
|
||||
} // namespace QodeAssist
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <QHash>
|
||||
@@ -60,18 +61,25 @@ public:
|
||||
[[nodiscard]] QString agentProviderOverride(const QString &name) const;
|
||||
void clearAgentProviderOverride(const QString &name);
|
||||
|
||||
bool setAgentToolsOverride(
|
||||
const QString &name, std::optional<bool> enabled, QString *error = nullptr);
|
||||
[[nodiscard]] std::optional<bool> agentToolsOverride(const QString &name) const;
|
||||
void clearAgentToolsOverride(const QString &name);
|
||||
|
||||
[[nodiscard]] Providers::ProviderInstanceFactory *instanceFactory() const noexcept;
|
||||
|
||||
signals:
|
||||
void agentsChanged();
|
||||
void agentModelChanged(const QString &name);
|
||||
void agentProviderChanged(const QString &name);
|
||||
void agentToolsChanged(const QString &name);
|
||||
|
||||
private:
|
||||
std::vector<AgentConfig> m_configs;
|
||||
QHash<QString, qsizetype> m_indexByName;
|
||||
QHash<QString, QString> m_baseModelByName;
|
||||
QHash<QString, QString> m_baseProviderByName;
|
||||
QHash<QString, bool> m_baseToolsByName;
|
||||
QPointer<Providers::ProviderInstanceFactory> m_instanceFactory;
|
||||
QPointer<Providers::ProviderSecretsStore> m_secrets;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user