chore: restructure llm plugin to be more coherent & fix various bugs in llm ui
C++ / fmt (pull_request) Failing after 6s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 9s
JS/TS / fmt (pull_request) Successful in 10s
JS/TS / lint (pull_request) Successful in 8s
Python / static (pull_request) Successful in 30s
Rust / build (pull_request) Successful in 49s
Python / verify (pull_request) Successful in 1m35s
Rust / fmt (pull_request) Successful in 36s
Rust / clippy (pull_request) Successful in 54s

This commit is contained in:
2026-10-18 12:58:38 +02:00
parent fc81be922f
commit 1fe8a3a959
54 changed files with 3022 additions and 2559 deletions
+23 -46
View File
@@ -1,8 +1,5 @@
#include "shelltool.hpp"
#include "llmclient.hpp"
#include "session.hpp"
#include <QDir>
#include <QJsonArray>
#include <QJsonObject>
@@ -13,24 +10,8 @@
namespace ZShell::llm {
namespace {
QJsonObject makeOutput(const QString& text) {
QJsonObject obj;
obj[QStringLiteral("output")] = text;
return obj;
}
QJsonObject makeError(const QString& message) {
QJsonObject obj;
obj[QStringLiteral("error")] = message;
return obj;
}
} // namespace
ShellTool::ShellTool(LlmClient* client, QObject* parent)
: LlmTool(parent), m_client(client) {}
ShellTool::ShellTool(ToolRegistry* registry, QObject* parent)
: LlmTool(registry, parent) {}
ShellTool::~ShellTool() {
for (auto* job : m_jobs) {
@@ -125,27 +106,29 @@ QStringList ShellTool::sandboxArguments(const QString& workspace) {
return args;
}
bool ShellTool::available(const ToolContext& context) const {
return registry()->sandboxEnabled() && !context.workspace.isEmpty();
}
void ShellTool::execute(
const QString& toolCallId,
const QJsonObject& args,
int outputBudgetChars,
std::function<void(const QJsonObject&)> done) {
Q_UNUSED(toolCallId);
const ToolContext& context, const QJsonObject& args, ToolDone done) {
const QString command = args[QStringLiteral("command")].toString();
if (command.trimmed().isEmpty()) {
done(makeError(QStringLiteral("Missing required argument 'command'")));
done({false, QStringLiteral("Missing required argument 'command'")});
return;
}
LlmClient* client = m_client;
if (!client || !client->sandboxEnabled()) {
done(makeError(QStringLiteral(
"The file sandbox is disabled, so no commands can run")));
if (!registry()->sandboxEnabled()) {
done(
{false,
QStringLiteral(
"The file sandbox is disabled, so no commands can run")});
return;
}
const QString workspace = client->activeWorkspace();
const QString workspace = context.workspace;
if (workspace.isEmpty()) {
done(makeError(
QStringLiteral("No sandbox available: no chat session is active")));
done(
{false,
QStringLiteral("No sandbox available: no chat session is active")});
return;
}
QDir().mkpath(workspace);
@@ -156,7 +139,7 @@ void ShellTool::execute(
MaxTimeoutSeconds);
auto* job = new Job;
job->timeoutSeconds = timeoutSeconds;
job->outputBudgetChars = outputBudgetChars;
job->outputBudgetChars = context.outputBudgetChars;
job->done = std::move(done);
m_jobs.append(job);
@@ -230,9 +213,8 @@ void ShellTool::finishJob(Job* job) {
"Command timed out after %1 seconds and was killed.\n")
.arg(job->timeoutSeconds);
int budget = inlineBudgetChars();
if (job->outputBudgetChars > 0)
budget = qMin(budget, job->outputBudgetChars);
int budget = job->outputBudgetChars > 0 ? job->outputBudgetChars
: registry()->outputBudgetChars(1);
if (output.size() > budget)
output = output.left(budget) + QStringLiteral(
"\n[output truncated: %1 characters "
@@ -242,17 +224,12 @@ void ShellTool::finishJob(Job* job) {
const QString result =
note + QStringLiteral("exit code: %1\n").arg(exitCode) +
(output.isEmpty() ? QStringLiteral("(no output)") : output);
const bool ok = !job->cancelled && !job->timedOut && exitCode == 0;
QJsonObject resultObject;
if (!job->cancelled && !job->timedOut && exitCode == 0)
resultObject = makeOutput(result);
else
resultObject = makeError(result);
std::function<void(const QJsonObject&)> done = std::move(job->done);
ToolDone done = std::move(job->done);
if (process) process->deleteLater();
delete job;
if (done) done(resultObject);
if (done) done({ok, result});
}
} // namespace ZShell::llm