forked from qt-creator/qt-creator
ProjectExplorer: Create AI task handlers dynamically
Change-Id: I7495bf7f4001031e84fc29eb852ddc9160d9bd94 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -244,7 +244,7 @@ CustomLanguageModels::CustomLanguageModels()
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
QStringList availableLanguageModels()
|
const QStringList availableLanguageModels()
|
||||||
{
|
{
|
||||||
return Utils::transform(
|
return Utils::transform(
|
||||||
customLanguageModels().models.items(), [](const std::shared_ptr<BaseAspect> &aspect) {
|
customLanguageModels().models.items(), [](const std::shared_ptr<BaseAspect> &aspect) {
|
||||||
@@ -261,6 +261,11 @@ CommandLine commandLineForLanguageModel(const QString &model)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BaseAspect &customLanguageModelsContext()
|
||||||
|
{
|
||||||
|
return customLanguageModels();
|
||||||
|
}
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
void setupCustomLanguageModels()
|
void setupCustomLanguageModels()
|
||||||
|
@@ -6,10 +6,13 @@
|
|||||||
|
|
||||||
#include <utils/commandline.h>
|
#include <utils/commandline.h>
|
||||||
|
|
||||||
|
namespace Utils { class BaseAspect; }
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
CORE_EXPORT QStringList availableLanguageModels();
|
CORE_EXPORT const QStringList availableLanguageModels();
|
||||||
CORE_EXPORT Utils::CommandLine commandLineForLanguageModel(const QString &model);
|
CORE_EXPORT Utils::CommandLine commandLineForLanguageModel(const QString &model);
|
||||||
|
CORE_EXPORT Utils::BaseAspect &customLanguageModelsContext();
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
@@ -18,18 +18,22 @@
|
|||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
#include <coreplugin/vcsmanager.h>
|
#include <coreplugin/vcsmanager.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/aspects.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/stringutils.h>
|
#include <utils/stringutils.h>
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
namespace {
|
namespace {
|
||||||
static QObject *g_actionParent = nullptr;
|
static QPointer<QObject> g_actionParent;
|
||||||
static Core::Context g_cmdContext;
|
static Core::Context g_cmdContext;
|
||||||
static Internal::RegisterHandlerAction g_onCreateAction;
|
static Internal::RegisterHandlerAction g_onCreateAction;
|
||||||
static Internal::GetHandlerTasks g_getTasks;
|
static Internal::GetHandlerTasks g_getTasks;
|
||||||
@@ -248,11 +252,13 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: There should be one handler per LLM
|
|
||||||
class ExplainWithAiHandler : public ITaskHandler
|
class ExplainWithAiHandler : public ITaskHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ExplainWithAiHandler() : ITaskHandler(createAction()) {}
|
ExplainWithAiHandler(const QString &model)
|
||||||
|
: ITaskHandler(createAction(model))
|
||||||
|
, m_model(model)
|
||||||
|
{}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool canHandle(const Task &task) const override
|
bool canHandle(const Task &task) const override
|
||||||
@@ -263,8 +269,8 @@ private:
|
|||||||
|
|
||||||
void handle(const Task &task) override
|
void handle(const Task &task) override
|
||||||
{
|
{
|
||||||
const QStringList llms = availableLanguageModels();
|
const CommandLine cmdLine = commandLineForLanguageModel(m_model);
|
||||||
QTC_ASSERT(!llms.isEmpty(), return);
|
QTC_ASSERT(!cmdLine.isEmpty(), return);
|
||||||
|
|
||||||
QString prompt;
|
QString prompt;
|
||||||
if (task.origin.isEmpty())
|
if (task.origin.isEmpty())
|
||||||
@@ -288,7 +294,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto process = new Process;
|
const auto process = new Process;
|
||||||
process->setCommand(commandLineForLanguageModel(llms.first()));
|
process->setCommand(cmdLine);
|
||||||
process->setProcessMode(ProcessMode::Writer);
|
process->setProcessMode(ProcessMode::Writer);
|
||||||
process->setTextChannelMode(Channel::Output, TextChannelMode::MultiLine);
|
process->setTextChannelMode(Channel::Output, TextChannelMode::MultiLine);
|
||||||
process->setTextChannelMode(Channel::Error, TextChannelMode::MultiLine);
|
process->setTextChannelMode(Channel::Error, TextChannelMode::MultiLine);
|
||||||
@@ -305,16 +311,40 @@ private:
|
|||||||
process->closeWriteChannel();
|
process->closeWriteChannel();
|
||||||
});
|
});
|
||||||
QTimer::singleShot(60000, process, [process] { process->kill(); });
|
QTimer::singleShot(60000, process, [process] { process->kill(); });
|
||||||
MessageManager::writeDisrupting(Tr::tr("Querying LLM..."));
|
MessageManager::writeDisrupting(Tr::tr("Querying %1...").arg(m_model));
|
||||||
process->start();
|
process->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction *createAction() const
|
QAction *createAction(const QString &model) const
|
||||||
{
|
{
|
||||||
const auto action = new QAction(Tr::tr("Get help from AI"));
|
const auto action = new QAction(Tr::tr("Get help from %1").arg(model));
|
||||||
action->setToolTip(Tr::tr("Ask an AI to help with this issue."));
|
action->setToolTip(Tr::tr("Ask the %1 LLM to help with this issue.").arg(model));
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString m_model;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AiHandlersManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AiHandlersManager()
|
||||||
|
{
|
||||||
|
QObject::connect(&customLanguageModelsContext(), &BaseAspect::changed,
|
||||||
|
g_actionParent, [this] { reset(); });
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
m_aiTaskHandlers.clear();
|
||||||
|
for (const QString &model : availableLanguageModels())
|
||||||
|
m_aiTaskHandlers.emplace_back(std::make_unique<ExplainWithAiHandler>(model));
|
||||||
|
updateTaskHandlerActionsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<ExplainWithAiHandler>> m_aiTaskHandlers;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -336,7 +366,7 @@ void setupTaskHandlers(
|
|||||||
static const RemoveTaskHandler removeTaskHandler;
|
static const RemoveTaskHandler removeTaskHandler;
|
||||||
static const ShowInEditorTaskHandler showInEditorTaskHandler;
|
static const ShowInEditorTaskHandler showInEditorTaskHandler;
|
||||||
static const VcsAnnotateTaskHandler vcsAnnotateTaskHandler;
|
static const VcsAnnotateTaskHandler vcsAnnotateTaskHandler;
|
||||||
static const ExplainWithAiHandler explainWithAiHandler;
|
static const AiHandlersManager aiHandlersManager;
|
||||||
|
|
||||||
registerQueuedTaskHandlers();
|
registerQueuedTaskHandlers();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user