mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-07-02 02:59:18 -04:00
fix: Remove files and folder watches
This commit is contained in:
@@ -16,11 +16,9 @@
|
|||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
#include <utils/theme/theme.h>
|
#include <utils/theme/theme.h>
|
||||||
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileSystemWatcher>
|
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
@@ -153,26 +151,6 @@ public:
|
|||||||
&AgentListPane::selectByName);
|
&AgentListPane::selectByName);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_reloadDebounce = new QTimer(this);
|
|
||||||
m_reloadDebounce->setSingleShot(true);
|
|
||||||
m_reloadDebounce->setInterval(300);
|
|
||||||
connect(m_reloadDebounce, &QTimer::timeout, this, [this] {
|
|
||||||
constexpr qint64 kSelfWriteIgnoreMs = 1500;
|
|
||||||
if (QDateTime::currentMSecsSinceEpoch() - m_lastSelfWriteMs < kSelfWriteIgnoreMs) {
|
|
||||||
armWatcher();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
reloadFromDisk();
|
|
||||||
});
|
|
||||||
|
|
||||||
m_watcher = new QFileSystemWatcher(this);
|
|
||||||
connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, [this](const QString &) {
|
|
||||||
m_reloadDebounce->start();
|
|
||||||
});
|
|
||||||
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, [this](const QString &) {
|
|
||||||
m_reloadDebounce->start();
|
|
||||||
});
|
|
||||||
|
|
||||||
reloadFromDisk();
|
reloadFromDisk();
|
||||||
|
|
||||||
if (m_navigator) {
|
if (m_navigator) {
|
||||||
@@ -194,21 +172,6 @@ private:
|
|||||||
m_agentFactory->reload();
|
m_agentFactory->reload();
|
||||||
updateUserPathLabel();
|
updateUserPathLabel();
|
||||||
m_listPane->refresh();
|
m_listPane->refresh();
|
||||||
armWatcher();
|
|
||||||
}
|
|
||||||
|
|
||||||
void armWatcher()
|
|
||||||
{
|
|
||||||
if (!m_watcher)
|
|
||||||
return;
|
|
||||||
const QStringList watched = m_watcher->files() + m_watcher->directories();
|
|
||||||
if (!watched.isEmpty())
|
|
||||||
m_watcher->removePaths(watched);
|
|
||||||
const QString dir = QodeAssist::AgentFactory::userAgentsDir();
|
|
||||||
m_watcher->addPath(dir);
|
|
||||||
const QDir userDir(dir);
|
|
||||||
for (const QString &f : userDir.entryList({QStringLiteral("*.toml")}, QDir::Files))
|
|
||||||
m_watcher->addPath(userDir.filePath(f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateUserPathLabel()
|
void updateUserPathLabel()
|
||||||
@@ -246,7 +209,6 @@ private:
|
|||||||
|
|
||||||
void customizeAgent(const AgentConfig &parent)
|
void customizeAgent(const AgentConfig &parent)
|
||||||
{
|
{
|
||||||
m_lastSelfWriteMs = QDateTime::currentMSecsSinceEpoch();
|
|
||||||
const AgentDuplicateResult res = duplicateAgentInUserDir(parent, *m_agentFactory);
|
const AgentDuplicateResult res = duplicateAgentInUserDir(parent, *m_agentFactory);
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
QMessageBox::warning(this, tr("Duplicate"), res.error);
|
QMessageBox::warning(this, tr("Duplicate"), res.error);
|
||||||
@@ -272,7 +234,6 @@ private:
|
|||||||
QMessageBox::No)
|
QMessageBox::No)
|
||||||
!= QMessageBox::Yes)
|
!= QMessageBox::Yes)
|
||||||
return;
|
return;
|
||||||
m_lastSelfWriteMs = QDateTime::currentMSecsSinceEpoch();
|
|
||||||
if (!QFile::remove(sourcePath)) {
|
if (!QFile::remove(sourcePath)) {
|
||||||
QMessageBox::warning(
|
QMessageBox::warning(
|
||||||
this,
|
this,
|
||||||
@@ -296,9 +257,6 @@ private:
|
|||||||
AgentListPane *m_listPane = nullptr;
|
AgentListPane *m_listPane = nullptr;
|
||||||
QScrollArea *m_detailScroll = nullptr;
|
QScrollArea *m_detailScroll = nullptr;
|
||||||
AgentDetailPane *m_detail = nullptr;
|
AgentDetailPane *m_detail = nullptr;
|
||||||
QFileSystemWatcher *m_watcher = nullptr;
|
|
||||||
QTimer *m_reloadDebounce = nullptr;
|
|
||||||
qint64 m_lastSelfWriteMs = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AgentsSettingsPage : public Core::IOptionsPage
|
class AgentsSettingsPage : public Core::IOptionsPage
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
#include "ProjectSettings.hpp"
|
#include "ProjectSettings.hpp"
|
||||||
#include "SettingsConstants.hpp"
|
#include "SettingsConstants.hpp"
|
||||||
@@ -90,6 +91,9 @@ static ProjectSettingsWidget *createProjectPanel(Project *project)
|
|||||||
QObject::connect(
|
QObject::connect(
|
||||||
&settings->projectSkillDirs, &Utils::BaseAspect::changed, skillsList, refreshSkills);
|
&settings->projectSkillDirs, &Utils::BaseAspect::changed, skillsList, refreshSkills);
|
||||||
|
|
||||||
|
auto *reloadSkillsButton = new QPushButton(Tr::tr("Reload"));
|
||||||
|
QObject::connect(reloadSkillsButton, &QPushButton::clicked, skillsList, refreshSkills);
|
||||||
|
|
||||||
Column{
|
Column{
|
||||||
generalWidget,
|
generalWidget,
|
||||||
Space{8},
|
Space{8},
|
||||||
@@ -97,7 +101,7 @@ static ProjectSettingsWidget *createProjectPanel(Project *project)
|
|||||||
title(Tr::tr("Skills")),
|
title(Tr::tr("Skills")),
|
||||||
Column{
|
Column{
|
||||||
settings->projectSkillDirs,
|
settings->projectSkillDirs,
|
||||||
new QLabel(Tr::tr("Discovered project skills:")),
|
Row{new QLabel(Tr::tr("Discovered project skills:")), st, reloadSkillsButton},
|
||||||
skillsList,
|
skillsList,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -86,6 +86,13 @@ public:
|
|||||||
headerRow->setSpacing(8);
|
headerRow->setSpacing(8);
|
||||||
headerRow->addWidget(m_titleLabel, 1);
|
headerRow->addWidget(m_titleLabel, 1);
|
||||||
|
|
||||||
|
auto *reloadButton = new QPushButton(tr("Reload from disk"), this);
|
||||||
|
connect(reloadButton, &QPushButton::clicked, this, [this] {
|
||||||
|
if (m_factory)
|
||||||
|
m_factory->reload();
|
||||||
|
});
|
||||||
|
headerRow->addWidget(reloadButton);
|
||||||
|
|
||||||
auto *headerSep = new QFrame(this);
|
auto *headerSep = new QFrame(this);
|
||||||
headerSep->setFrameShape(QFrame::HLine);
|
headerSep->setFrameShape(QFrame::HLine);
|
||||||
headerSep->setFrameShadow(QFrame::Sunken);
|
headerSep->setFrameShadow(QFrame::Sunken);
|
||||||
|
|||||||
@@ -14,6 +14,14 @@
|
|||||||
<file>openai_chat_responses.toml</file>
|
<file>openai_chat_responses.toml</file>
|
||||||
<file>google_base_chat.toml</file>
|
<file>google_base_chat.toml</file>
|
||||||
<file>google_chat.toml</file>
|
<file>google_chat.toml</file>
|
||||||
|
<file>mistral_base_chat.toml</file>
|
||||||
|
<file>mistral_chat.toml</file>
|
||||||
|
<file>mistral_chat_reasoning.toml</file>
|
||||||
|
<file>mistral_compression.toml</file>
|
||||||
|
<file>mistral_quick_refactor.toml</file>
|
||||||
|
<file>codestral_base_fim.toml</file>
|
||||||
|
<file>codestral_completion_fim.toml</file>
|
||||||
|
<file>mistral_completion_codestral_fim.toml</file>
|
||||||
<file>ollama_base_chat.toml</file>
|
<file>ollama_base_chat.toml</file>
|
||||||
<file>ollama_chat_simple.toml</file>
|
<file>ollama_chat_simple.toml</file>
|
||||||
<file>ollama_chat_thinking.toml</file>
|
<file>ollama_chat_thinking.toml</file>
|
||||||
|
|||||||
@@ -5,12 +5,9 @@
|
|||||||
#include "ProviderInstanceFactory.hpp"
|
#include "ProviderInstanceFactory.hpp"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QFileSystemWatcher>
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
@@ -39,15 +36,6 @@ ProviderInstanceFactory::ProviderInstanceFactory(QObject *parent)
|
|||||||
{
|
{
|
||||||
::initProviderInstancesResource();
|
::initProviderInstancesResource();
|
||||||
|
|
||||||
m_watcher = new QFileSystemWatcher(this);
|
|
||||||
m_reloadDebounce = new QTimer(this);
|
|
||||||
m_reloadDebounce->setSingleShot(true);
|
|
||||||
m_reloadDebounce->setInterval(150);
|
|
||||||
connect(m_reloadDebounce, &QTimer::timeout, this, [this] { reload(); });
|
|
||||||
auto kick = [this](const QString &) { m_reloadDebounce->start(); };
|
|
||||||
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, kick);
|
|
||||||
connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, kick);
|
|
||||||
|
|
||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +53,7 @@ void ProviderInstanceFactory::reload()
|
|||||||
Q_FUNC_INFO, "ProviderInstanceFactory must be used from its owner thread");
|
Q_FUNC_INFO, "ProviderInstanceFactory must be used from its owner thread");
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
|
QDir().mkpath(userInstancesDir());
|
||||||
auto result = ProviderInstanceLoader::load(instanceQrcPrefix(), userInstancesDir());
|
auto result = ProviderInstanceLoader::load(instanceQrcPrefix(), userInstancesDir());
|
||||||
for (const QString &err : result.errors)
|
for (const QString &err : result.errors)
|
||||||
LOG_MESSAGE(QString("[ProviderInstances] error: %1").arg(err));
|
LOG_MESSAGE(QString("[ProviderInstances] error: %1").arg(err));
|
||||||
@@ -83,7 +72,6 @@ void ProviderInstanceFactory::reload()
|
|||||||
m_warnings = std::move(result.warnings);
|
m_warnings = std::move(result.warnings);
|
||||||
|
|
||||||
rebuildIndexes();
|
rebuildIndexes();
|
||||||
rewatchUserDir();
|
|
||||||
emit instancesReloaded();
|
emit instancesReloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,23 +101,6 @@ void ProviderInstanceFactory::rebuildIndexes()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProviderInstanceFactory::rewatchUserDir()
|
|
||||||
{
|
|
||||||
if (!m_watcher)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const QStringList stale = m_watcher->files() + m_watcher->directories();
|
|
||||||
if (!stale.isEmpty())
|
|
||||||
m_watcher->removePaths(stale);
|
|
||||||
|
|
||||||
const QString userDir = userInstancesDir();
|
|
||||||
QDir().mkpath(userDir);
|
|
||||||
m_watcher->addPath(userDir);
|
|
||||||
QDir d(userDir);
|
|
||||||
for (const QFileInfo &fi : d.entryInfoList({"*.toml"}, QDir::Files))
|
|
||||||
m_watcher->addPath(fi.absoluteFilePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
const ProviderInstance *ProviderInstanceFactory::instanceByName(const QString &name) const
|
const ProviderInstance *ProviderInstanceFactory::instanceByName(const QString &name) const
|
||||||
{
|
{
|
||||||
const auto it = m_nameIndex.constFind(name.toCaseFolded());
|
const auto it = m_nameIndex.constFind(name.toCaseFolded());
|
||||||
|
|||||||
@@ -13,9 +13,6 @@
|
|||||||
|
|
||||||
#include "ProviderInstance.hpp"
|
#include "ProviderInstance.hpp"
|
||||||
|
|
||||||
class QFileSystemWatcher;
|
|
||||||
class QTimer;
|
|
||||||
|
|
||||||
namespace QodeAssist::Providers {
|
namespace QodeAssist::Providers {
|
||||||
|
|
||||||
class ProviderInstanceFactory : public QObject
|
class ProviderInstanceFactory : public QObject
|
||||||
@@ -47,7 +44,6 @@ signals:
|
|||||||
void instancesReloaded();
|
void instancesReloaded();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void rewatchUserDir();
|
|
||||||
void rebuildIndexes();
|
void rebuildIndexes();
|
||||||
|
|
||||||
std::vector<ProviderInstance> m_instances;
|
std::vector<ProviderInstance> m_instances;
|
||||||
@@ -55,10 +51,6 @@ private:
|
|||||||
QStringList m_knownClientApisCache;
|
QStringList m_knownClientApisCache;
|
||||||
QStringList m_errors;
|
QStringList m_errors;
|
||||||
QStringList m_warnings;
|
QStringList m_warnings;
|
||||||
|
|
||||||
|
|
||||||
QFileSystemWatcher *m_watcher = nullptr;
|
|
||||||
QTimer *m_reloadDebounce = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QodeAssist::Providers
|
} // namespace QodeAssist::Providers
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ schema_version = 1
|
|||||||
|
|
||||||
name = "Mistral AI"
|
name = "Mistral AI"
|
||||||
client_api = "Mistral AI"
|
client_api = "Mistral AI"
|
||||||
description = "Cloud (Mistral). Mistral chat/instruct models, incl. the Magistral reasoning model. For Mistral's FIM code model, use Codestral."
|
description = "Cloud (Mistral). Mistral chat/instruct models, the Magistral reasoning model, and the Codestral code model — including native FIM via /v1/fim/completions. The dedicated Codestral provider (codestral.mistral.ai) has its own key and endpoint."
|
||||||
|
|
||||||
url = "https://api.mistral.ai"
|
url = "https://api.mistral.ai"
|
||||||
api_key_ref = "qodeassist/providers/Mistral AI"
|
api_key_ref = "qodeassist/providers/Mistral AI"
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "SkillsManager.hpp"
|
#include "SkillsManager.hpp"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileSystemWatcher>
|
|
||||||
|
|
||||||
#include "SkillsLoader.hpp"
|
#include "SkillsLoader.hpp"
|
||||||
|
|
||||||
@@ -13,10 +12,7 @@ namespace QodeAssist::Skills {
|
|||||||
|
|
||||||
SkillsManager::SkillsManager(QObject *parent)
|
SkillsManager::SkillsManager(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_watcher(new QFileSystemWatcher(this))
|
{}
|
||||||
{
|
|
||||||
connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, [this] { reload(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkillsManager::configure(
|
void SkillsManager::configure(
|
||||||
const QString &projectPath,
|
const QString &projectPath,
|
||||||
@@ -61,28 +57,9 @@ void SkillsManager::reload()
|
|||||||
{
|
{
|
||||||
const QStringList roots = resolveRoots(m_projectPath, m_globalRoots, m_projectSubdirs);
|
const QStringList roots = resolveRoots(m_projectPath, m_globalRoots, m_projectSubdirs);
|
||||||
m_skills = SkillsLoader::scan(roots);
|
m_skills = SkillsLoader::scan(roots);
|
||||||
updateWatcher(roots);
|
|
||||||
emit skillsChanged();
|
emit skillsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkillsManager::updateWatcher(const QStringList &roots)
|
|
||||||
{
|
|
||||||
const QStringList watched = m_watcher->directories();
|
|
||||||
if (!watched.isEmpty())
|
|
||||||
m_watcher->removePaths(watched);
|
|
||||||
|
|
||||||
QStringList toWatch;
|
|
||||||
for (const QString &root : roots) {
|
|
||||||
if (QDir(root).exists())
|
|
||||||
toWatch << root;
|
|
||||||
}
|
|
||||||
for (const AgentSkill &skill : m_skills)
|
|
||||||
toWatch << skill.skillDir;
|
|
||||||
|
|
||||||
if (!toWatch.isEmpty())
|
|
||||||
m_watcher->addPaths(toWatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<AgentSkill> SkillsManager::skills() const
|
QVector<AgentSkill> SkillsManager::skills() const
|
||||||
{
|
{
|
||||||
return m_skills;
|
return m_skills;
|
||||||
|
|||||||
@@ -13,8 +13,6 @@
|
|||||||
|
|
||||||
#include "AgentSkill.hpp"
|
#include "AgentSkill.hpp"
|
||||||
|
|
||||||
class QFileSystemWatcher;
|
|
||||||
|
|
||||||
namespace QodeAssist::Skills {
|
namespace QodeAssist::Skills {
|
||||||
|
|
||||||
class SkillsManager : public QObject
|
class SkillsManager : public QObject
|
||||||
@@ -48,13 +46,10 @@ signals:
|
|||||||
void skillsChanged();
|
void skillsChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateWatcher(const QStringList &roots);
|
|
||||||
|
|
||||||
QString m_projectPath;
|
QString m_projectPath;
|
||||||
QStringList m_globalRoots;
|
QStringList m_globalRoots;
|
||||||
QStringList m_projectSubdirs;
|
QStringList m_projectSubdirs;
|
||||||
QVector<AgentSkill> m_skills;
|
QVector<AgentSkill> m_skills;
|
||||||
QFileSystemWatcher *m_watcher = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QodeAssist::Skills
|
} // namespace QodeAssist::Skills
|
||||||
|
|||||||
Reference in New Issue
Block a user