mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-02-09 16:50:13 -05:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 18fb2b530f | |||
| f0d2e42680 | |||
| ff0f994ec6 | |||
| 45df27e749 | |||
| 02863003a9 |
2
.github/workflows/build_cmake.yml
vendored
2
.github/workflows/build_cmake.yml
vendored
@ -47,7 +47,7 @@ jobs:
|
||||
qt_config:
|
||||
- {
|
||||
qt_version: "6.9.2",
|
||||
qt_creator_version: "17.0.1"
|
||||
qt_creator_version: "17.0.2"
|
||||
}
|
||||
- {
|
||||
qt_version: "6.8.3",
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -73,4 +73,5 @@ CMakeLists.txt.user*
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
/build
|
||||
/build
|
||||
/.qodeassist
|
||||
@ -119,6 +119,7 @@ add_qtc_plugin(QodeAssist
|
||||
tools/ListProjectFilesTool.hpp tools/ListProjectFilesTool.cpp
|
||||
tools/ToolsManager.hpp tools/ToolsManager.cpp
|
||||
tools/SearchInProjectTool.hpp tools/SearchInProjectTool.cpp
|
||||
tools/GetIssuesListTool.hpp tools/GetIssuesListTool.cpp
|
||||
providers/ClaudeMessage.hpp providers/ClaudeMessage.cpp
|
||||
providers/OpenAIMessage.hpp providers/OpenAIMessage.cpp
|
||||
providers/OllamaMessage.hpp providers/OllamaMessage.cpp
|
||||
|
||||
@ -28,6 +28,9 @@
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/editormanager/ieditor.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
|
||||
#include <texteditor/textdocument.h>
|
||||
#include <texteditor/texteditor.h>
|
||||
@ -37,6 +40,7 @@
|
||||
#include "Logger.hpp"
|
||||
#include "ProvidersManager.hpp"
|
||||
#include "RequestConfig.hpp"
|
||||
#include <RulesLoader.hpp>
|
||||
|
||||
namespace QodeAssist::Chat {
|
||||
|
||||
@ -81,6 +85,17 @@ void ClientInterface::sendMessage(
|
||||
|
||||
if (chatAssistantSettings.useSystemPrompt()) {
|
||||
QString systemPrompt = chatAssistantSettings.systemPrompt();
|
||||
|
||||
auto project = LLMCore::RulesLoader::getActiveProject();
|
||||
if (project) {
|
||||
QString projectRules
|
||||
= LLMCore::RulesLoader::loadRulesForProject(project, LLMCore::RulesContext::Chat);
|
||||
|
||||
if (!projectRules.isEmpty()) {
|
||||
systemPrompt += "\n\n# Project Rules\n\n" + projectRules;
|
||||
}
|
||||
}
|
||||
|
||||
if (!linkedFiles.isEmpty()) {
|
||||
systemPrompt = getSystemPromptWithLinkedFiles(systemPrompt, linkedFiles);
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "settings/CodeCompletionSettings.hpp"
|
||||
#include "settings/GeneralSettings.hpp"
|
||||
#include <llmcore/RequestConfig.hpp>
|
||||
#include <llmcore/RulesLoader.hpp>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
@ -242,6 +243,18 @@ void LLMClientInterface::handleCompletion(const QJsonObject &request)
|
||||
&& promptTemplate->type() == LLMCore::TemplateType::Chat
|
||||
? m_completeSettings.systemPromptForNonFimModels()
|
||||
: m_completeSettings.systemPrompt());
|
||||
|
||||
auto project = LLMCore::RulesLoader::getActiveProject();
|
||||
if (project) {
|
||||
QString projectRules
|
||||
= LLMCore::RulesLoader::loadRulesForProject(project, LLMCore::RulesContext::Completions);
|
||||
|
||||
if (!projectRules.isEmpty()) {
|
||||
systemPrompt += "\n\n# Project Rules\n\n" + projectRules;
|
||||
LOG_MESSAGE("Loaded project rules for completion");
|
||||
}
|
||||
}
|
||||
|
||||
if (updatedContext.fileContext.has_value())
|
||||
systemPrompt.append(updatedContext.fileContext.value());
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"Id" : "qodeassist",
|
||||
"Name" : "QodeAssist",
|
||||
"Version" : "0.7.0",
|
||||
"Version" : "0.7.1",
|
||||
"CompatVersion" : "${IDE_VERSION}",
|
||||
"Vendor" : "Petr Mironychev",
|
||||
"VendorId" : "petrmironychev",
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <llmcore/PromptTemplateManager.hpp>
|
||||
#include <llmcore/ProvidersManager.hpp>
|
||||
#include <llmcore/RequestConfig.hpp>
|
||||
#include <llmcore/RulesLoader.hpp>
|
||||
#include <logger/Logger.hpp>
|
||||
#include <settings/ChatAssistantSettings.hpp>
|
||||
#include <settings/GeneralSettings.hpp>
|
||||
@ -206,6 +207,18 @@ LLMCore::ContextData QuickRefactorHandler::prepareContext(
|
||||
}
|
||||
|
||||
QString systemPrompt = Settings::codeCompletionSettings().quickRefactorSystemPrompt();
|
||||
|
||||
auto project = LLMCore::RulesLoader::getActiveProject();
|
||||
if (project) {
|
||||
QString projectRules = LLMCore::RulesLoader::loadRulesForProject(
|
||||
project, LLMCore::RulesContext::QuickRefactor);
|
||||
|
||||
if (!projectRules.isEmpty()) {
|
||||
systemPrompt += "\n\n# Project Rules\n\n" + projectRules;
|
||||
LOG_MESSAGE("Loaded project rules for quick refactor");
|
||||
}
|
||||
}
|
||||
|
||||
systemPrompt += "\n\nFile information:";
|
||||
systemPrompt += "\nLanguage: " + documentInfo.mimeType;
|
||||
systemPrompt += "\nFile path: " + documentInfo.filePath;
|
||||
|
||||
40
README.md
40
README.md
@ -3,7 +3,7 @@
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
[](https://discord.gg/BGMkUsXUgf)
|
||||
|
||||
 QodeAssist is an AI-powered coding assistant plugin for Qt Creator. It provides intelligent code completion and suggestions for C++ and QML, leveraging large language models through local providers like Ollama. Enhance your coding productivity with context-aware AI assistance directly in your Qt development environment.
|
||||
@ -55,9 +55,10 @@
|
||||
- LM Studio
|
||||
- Mistral AI
|
||||
- Google AI
|
||||
- OpenAI-compatible providers(eg. llama.cpp, https://openrouter.ai)
|
||||
- OpenAI-compatible providers (eg. llama.cpp, https://openrouter.ai)
|
||||
- Extensive library of model-specific templates
|
||||
- Easy configuration and model selection
|
||||
- Support tools/function calling (enabled by default)
|
||||
|
||||
Join our Discord Community: Have questions or want to discuss QodeAssist? Join our [Discord server](https://discord.gg/BGMkUsXUgf) to connect with other users and get support!
|
||||
|
||||
@ -96,6 +97,11 @@ Join our Discord Community: Have questions or want to discuss QodeAssist? Join o
|
||||
<img width="600" alt="OpenedDocumentsSync" src="https://github.com/user-attachments/assets/08efda2f-dc4d-44c3-927c-e6a975090d2f">
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Example how tools works: (click to expand)</summary>
|
||||
<img width="600" alt="ToolsDemo" src="https://github.com/user-attachments/assets/cf6273ad-d5c8-47fc-81e6-23d929547f6c">
|
||||
</details>
|
||||
|
||||
## Install plugin to QtCreator
|
||||
1. Install Latest Qt Creator
|
||||
2. Download the QodeAssist plugin for your Qt Creator
|
||||
@ -186,6 +192,7 @@ ollama run qwen2.5-coder:32b
|
||||
- The URL is set to http://localhost:11434
|
||||
- Your installed model appears in the model selection
|
||||
- The prompt template is Ollama Auto FIM or Ollama Auto Chat for chat assistance. You can specify template if it is not work correct
|
||||
- Disable using tools if your model doesn't support tooling
|
||||
4. Click Apply if you made any changes
|
||||
|
||||
You're all set! QodeAssist is now ready to use in Qt Creator.
|
||||
@ -201,6 +208,7 @@ You're all set! QodeAssist is now ready to use in Qt Creator.
|
||||
- Set the llama.cpp URL (e.g. http://localhost:8080)
|
||||
- Fill in model name
|
||||
- Choose template for model(e.g. llama.cpp FIM for any model with FIM support)
|
||||
- Disable using tools if your model doesn't support tooling
|
||||
<details>
|
||||
<summary>Example of llama.cpp settings: (click to expand)</summary>
|
||||
<img width="829" alt="llama.cpp Settings" src="https://github.com/user-attachments/assets/8c75602c-60f3-49ed-a7a9-d3c972061ea2" />
|
||||
@ -210,6 +218,34 @@ You're all set! QodeAssist is now ready to use in Qt Creator.
|
||||
|
||||
The plugin comes with default system prompts optimized for chat and instruct models, as these currently provide better results for code assistance. If you prefer using FIM (Fill-in-Middle) models, you can easily customize the system prompt in the settings.
|
||||
|
||||
## Project Rules Configuration
|
||||
|
||||
QodeAssist supports project-specific rules to customize AI behavior for your codebase. Create a `.qodeassist/rules/` directory in your project root.
|
||||
|
||||
### Quick Start
|
||||
```bash
|
||||
mkdir -p .qodeassist/rules/{common,completion,chat,quickrefactor}
|
||||
```
|
||||
```
|
||||
.qodeassist/
|
||||
└── rules/
|
||||
├── common/ # Applied to all contexts
|
||||
├── completion/ # Code completion only
|
||||
├── chat/ # Chat assistant only
|
||||
└── quickrefactor/ # Quick refactor only
|
||||
```
|
||||
All .md files in each directory are automatically loaded and added to the system prompt.
|
||||
|
||||
Example
|
||||
Create .qodeassist/rules/common/general.md:
|
||||
```markdown
|
||||
# Project Guidelines
|
||||
- Use snake_case for private members
|
||||
- Prefix interfaces with 'I'
|
||||
- Always document public APIs
|
||||
- Prefer Qt containers over STL
|
||||
```
|
||||
|
||||
## File Context Feature
|
||||
|
||||
QodeAssist provides two powerful ways to include source code files in your chat conversations: Attachments and Linked Files. Each serves a distinct purpose and helps provide better context for the AI assistant.
|
||||
|
||||
@ -15,9 +15,9 @@ add_library(LLMCore STATIC
|
||||
HttpClient.hpp HttpClient.cpp
|
||||
DataBuffers.hpp
|
||||
SSEBuffer.hpp SSEBuffer.cpp
|
||||
BaseTool.hpp
|
||||
BaseTool.cpp
|
||||
BaseTool.hpp BaseTool.cpp
|
||||
ContentBlocks.hpp
|
||||
RulesLoader.hpp RulesLoader.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(LLMCore
|
||||
|
||||
112
llmcore/RulesLoader.cpp
Normal file
112
llmcore/RulesLoader.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Petr Mironychev
|
||||
*
|
||||
* This file is part of QodeAssist.
|
||||
*
|
||||
* QodeAssist is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QodeAssist is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "RulesLoader.hpp"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
|
||||
namespace QodeAssist::LLMCore {
|
||||
|
||||
QString RulesLoader::loadRules(const QString &projectPath, RulesContext context)
|
||||
{
|
||||
if (projectPath.isEmpty()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString combined;
|
||||
QString basePath = projectPath + "/.qodeassist/rules";
|
||||
|
||||
combined += loadAllMarkdownFiles(basePath + "/common");
|
||||
|
||||
switch (context) {
|
||||
case RulesContext::Completions:
|
||||
combined += loadAllMarkdownFiles(basePath + "/completions");
|
||||
break;
|
||||
case RulesContext::Chat:
|
||||
combined += loadAllMarkdownFiles(basePath + "/chat");
|
||||
break;
|
||||
case RulesContext::QuickRefactor:
|
||||
combined += loadAllMarkdownFiles(basePath + "/quickrefactor");
|
||||
break;
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
QString RulesLoader::loadRulesForProject(ProjectExplorer::Project *project, RulesContext context)
|
||||
{
|
||||
if (!project) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString projectPath = getProjectPath(project);
|
||||
return loadRules(projectPath, context);
|
||||
}
|
||||
|
||||
ProjectExplorer::Project *RulesLoader::getActiveProject()
|
||||
{
|
||||
auto currentEditor = Core::EditorManager::currentEditor();
|
||||
if (currentEditor && currentEditor->document()) {
|
||||
Utils::FilePath filePath = currentEditor->document()->filePath();
|
||||
auto project = ProjectExplorer::ProjectManager::projectForFile(filePath);
|
||||
if (project) {
|
||||
return project;
|
||||
}
|
||||
}
|
||||
|
||||
return ProjectExplorer::ProjectManager::startupProject();
|
||||
}
|
||||
|
||||
QString RulesLoader::loadAllMarkdownFiles(const QString &dirPath)
|
||||
{
|
||||
QString combined;
|
||||
QDir dir(dirPath);
|
||||
|
||||
if (!dir.exists()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList mdFiles = dir.entryList({"*.md"}, QDir::Files, QDir::Name);
|
||||
|
||||
for (const QString &fileName : mdFiles) {
|
||||
QFile file(dir.filePath(fileName));
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
combined += file.readAll();
|
||||
combined += "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
QString RulesLoader::getProjectPath(ProjectExplorer::Project *project)
|
||||
{
|
||||
if (!project) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return project->projectDirectory().toUrlishString();
|
||||
}
|
||||
|
||||
} // namespace QodeAssist::LLMCore
|
||||
44
llmcore/RulesLoader.hpp
Normal file
44
llmcore/RulesLoader.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Petr Mironychev
|
||||
*
|
||||
* This file is part of QodeAssist.
|
||||
*
|
||||
* QodeAssist is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QodeAssist is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class Project;
|
||||
}
|
||||
|
||||
namespace QodeAssist::LLMCore {
|
||||
|
||||
enum class RulesContext { Completions, Chat, QuickRefactor };
|
||||
|
||||
class RulesLoader
|
||||
{
|
||||
public:
|
||||
static QString loadRules(const QString &projectPath, RulesContext context);
|
||||
static QString loadRulesForProject(ProjectExplorer::Project *project, RulesContext context);
|
||||
static ProjectExplorer::Project *getActiveProject();
|
||||
|
||||
private:
|
||||
static QString loadAllMarkdownFiles(const QString &dirPath);
|
||||
static QString getProjectPath(ProjectExplorer::Project *project);
|
||||
};
|
||||
|
||||
} // namespace QodeAssist::LLMCore
|
||||
258
tools/GetIssuesListTool.cpp
Normal file
258
tools/GetIssuesListTool.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Petr Mironychev
|
||||
*
|
||||
* This file is part of QodeAssist.
|
||||
*
|
||||
* QodeAssist is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QodeAssist is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "GetIssuesListTool.hpp"
|
||||
|
||||
#include <logger/Logger.hpp>
|
||||
#include <projectexplorer/taskhub.h>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QMutexLocker>
|
||||
#include <QtConcurrent>
|
||||
|
||||
namespace QodeAssist::Tools {
|
||||
|
||||
IssuesTracker &IssuesTracker::instance()
|
||||
{
|
||||
static IssuesTracker tracker;
|
||||
return tracker;
|
||||
}
|
||||
|
||||
IssuesTracker::IssuesTracker(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
LOG_MESSAGE("IssuesTracker: Initializing tracker");
|
||||
|
||||
auto &hub = ProjectExplorer::taskHub();
|
||||
|
||||
connect(&hub, &ProjectExplorer::TaskHub::taskAdded, this, &IssuesTracker::onTaskAdded);
|
||||
connect(&hub, &ProjectExplorer::TaskHub::taskRemoved, this, &IssuesTracker::onTaskRemoved);
|
||||
connect(&hub, &ProjectExplorer::TaskHub::tasksCleared, this, &IssuesTracker::onTasksCleared);
|
||||
|
||||
LOG_MESSAGE("IssuesTracker: Connected to TaskHub signals");
|
||||
}
|
||||
|
||||
QList<ProjectExplorer::Task> IssuesTracker::getTasks() const
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
LOG_MESSAGE(QString("IssuesTracker: getTasks() called, current count: %1").arg(m_tasks.size()));
|
||||
return m_tasks;
|
||||
}
|
||||
|
||||
void IssuesTracker::onTaskAdded(const ProjectExplorer::Task &task)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
m_tasks.append(task);
|
||||
|
||||
QString typeStr;
|
||||
switch (task.type) {
|
||||
case ProjectExplorer::Task::Error:
|
||||
typeStr = "ERROR";
|
||||
break;
|
||||
case ProjectExplorer::Task::Warning:
|
||||
typeStr = "WARNING";
|
||||
break;
|
||||
default:
|
||||
typeStr = "INFO";
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_MESSAGE(QString("IssuesTracker: Task added [%1] %2 at %3:%4 (total: %5)")
|
||||
.arg(typeStr)
|
||||
.arg(task.description())
|
||||
.arg(task.file.toUrlishString())
|
||||
.arg(task.line)
|
||||
.arg(m_tasks.size()));
|
||||
}
|
||||
|
||||
void IssuesTracker::onTaskRemoved(const ProjectExplorer::Task &task)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
m_tasks.removeOne(task);
|
||||
|
||||
LOG_MESSAGE(QString("IssuesTracker: Task removed: %1 (total: %2)")
|
||||
.arg(task.description())
|
||||
.arg(m_tasks.size()));
|
||||
}
|
||||
|
||||
void IssuesTracker::onTasksCleared(Utils::Id categoryId)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
|
||||
if (categoryId.isValid()) {
|
||||
int beforeCount = m_tasks.size();
|
||||
m_tasks.erase(
|
||||
std::remove_if(
|
||||
m_tasks.begin(),
|
||||
m_tasks.end(),
|
||||
[categoryId](const ProjectExplorer::Task &task) {
|
||||
return task.category == categoryId;
|
||||
}),
|
||||
m_tasks.end());
|
||||
int removedCount = beforeCount - m_tasks.size();
|
||||
|
||||
LOG_MESSAGE(
|
||||
QString("IssuesTracker: Tasks cleared for category %1, removed %2 tasks (total: %3)")
|
||||
.arg(categoryId.toString())
|
||||
.arg(removedCount)
|
||||
.arg(m_tasks.size()));
|
||||
} else {
|
||||
int clearedCount = m_tasks.size();
|
||||
m_tasks.clear();
|
||||
LOG_MESSAGE(QString("IssuesTracker: All tasks cleared, removed %1 tasks").arg(clearedCount));
|
||||
}
|
||||
}
|
||||
|
||||
GetIssuesListTool::GetIssuesListTool(QObject *parent)
|
||||
: BaseTool(parent)
|
||||
{
|
||||
LOG_MESSAGE("GetIssuesListTool: Initializing tool");
|
||||
IssuesTracker::instance();
|
||||
}
|
||||
|
||||
QString GetIssuesListTool::name() const
|
||||
{
|
||||
return "get_issues_list";
|
||||
}
|
||||
|
||||
QString GetIssuesListTool::stringName() const
|
||||
{
|
||||
return "Getting issues list from Qt Creator";
|
||||
}
|
||||
|
||||
QString GetIssuesListTool::description() const
|
||||
{
|
||||
return "Get list of errors, warnings and other issues from Qt Creator's Issues panel. "
|
||||
"Returns information about compilation errors, static analysis warnings, and other "
|
||||
"diagnostic messages.";
|
||||
}
|
||||
|
||||
QJsonObject GetIssuesListTool::getDefinition(LLMCore::ToolSchemaFormat format) const
|
||||
{
|
||||
QJsonObject definition;
|
||||
definition["type"] = "object";
|
||||
|
||||
QJsonObject properties;
|
||||
properties["severity"] = QJsonObject{
|
||||
{"type", "string"},
|
||||
{"description", "Filter by severity: 'error', 'warning', or 'all'"},
|
||||
{"enum", QJsonArray{"error", "warning", "all"}}};
|
||||
|
||||
definition["properties"] = properties;
|
||||
definition["required"] = QJsonArray();
|
||||
|
||||
switch (format) {
|
||||
case LLMCore::ToolSchemaFormat::OpenAI:
|
||||
return customizeForOpenAI(definition);
|
||||
case LLMCore::ToolSchemaFormat::Claude:
|
||||
return customizeForClaude(definition);
|
||||
case LLMCore::ToolSchemaFormat::Ollama:
|
||||
return customizeForOllama(definition);
|
||||
case LLMCore::ToolSchemaFormat::Google:
|
||||
return customizeForGoogle(definition);
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
LLMCore::ToolPermissions GetIssuesListTool::requiredPermissions() const
|
||||
{
|
||||
return LLMCore::ToolPermission::FileSystemRead;
|
||||
}
|
||||
|
||||
QFuture<QString> GetIssuesListTool::executeAsync(const QJsonObject &input)
|
||||
{
|
||||
return QtConcurrent::run([input]() -> QString {
|
||||
LOG_MESSAGE("GetIssuesListTool: Starting execution");
|
||||
|
||||
QString severityFilter = input.value("severity").toString("all");
|
||||
LOG_MESSAGE(QString("GetIssuesListTool: Severity filter: %1").arg(severityFilter));
|
||||
|
||||
const auto tasks = IssuesTracker::instance().getTasks();
|
||||
|
||||
if (tasks.isEmpty()) {
|
||||
LOG_MESSAGE("GetIssuesListTool: No issues found");
|
||||
return "No issues found in Qt Creator Issues panel.";
|
||||
}
|
||||
|
||||
LOG_MESSAGE(QString("GetIssuesListTool: Processing %1 tasks").arg(tasks.size()));
|
||||
|
||||
QStringList results;
|
||||
results.append(QString("Total issues in panel: %1\n").arg(tasks.size()));
|
||||
|
||||
int errorCount = 0;
|
||||
int warningCount = 0;
|
||||
int processedCount = 0;
|
||||
|
||||
for (const ProjectExplorer::Task &task : tasks) {
|
||||
if (severityFilter == "error" && task.type != ProjectExplorer::Task::Error)
|
||||
continue;
|
||||
if (severityFilter == "warning" && task.type != ProjectExplorer::Task::Warning)
|
||||
continue;
|
||||
|
||||
QString typeStr;
|
||||
switch (task.type) {
|
||||
case ProjectExplorer::Task::Error:
|
||||
typeStr = "ERROR";
|
||||
errorCount++;
|
||||
break;
|
||||
case ProjectExplorer::Task::Warning:
|
||||
typeStr = "WARNING";
|
||||
warningCount++;
|
||||
break;
|
||||
default:
|
||||
typeStr = "INFO";
|
||||
break;
|
||||
}
|
||||
|
||||
QString issueText = QString("[%1] %2").arg(typeStr, task.description());
|
||||
|
||||
if (!task.file.isEmpty()) {
|
||||
issueText += QString("\n File: %1").arg(task.file.toUrlishString());
|
||||
if (task.line > 0) {
|
||||
issueText += QString(":%1").arg(task.line);
|
||||
if (task.column > 0) {
|
||||
issueText += QString(":%1").arg(task.column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!task.category.toString().isEmpty()) {
|
||||
issueText += QString("\n Category: %1").arg(task.category.toString());
|
||||
}
|
||||
|
||||
results.append(issueText);
|
||||
processedCount++;
|
||||
}
|
||||
|
||||
QString summary = QString("\nSummary: %1 errors, %2 warnings (processed %3 tasks)")
|
||||
.arg(errorCount)
|
||||
.arg(warningCount)
|
||||
.arg(processedCount);
|
||||
results.prepend(summary);
|
||||
|
||||
LOG_MESSAGE(QString("GetIssuesListTool: Execution completed - %1 errors, %2 warnings")
|
||||
.arg(errorCount)
|
||||
.arg(warningCount));
|
||||
|
||||
return results.join("\n\n");
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace QodeAssist::Tools
|
||||
64
tools/GetIssuesListTool.hpp
Normal file
64
tools/GetIssuesListTool.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Petr Mironychev
|
||||
*
|
||||
* This file is part of QodeAssist.
|
||||
*
|
||||
* QodeAssist is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QodeAssist is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <llmcore/BaseTool.hpp>
|
||||
#include <projectexplorer/task.h>
|
||||
#include <QList>
|
||||
#include <QMutex>
|
||||
|
||||
namespace QodeAssist::Tools {
|
||||
|
||||
class IssuesTracker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static IssuesTracker &instance();
|
||||
|
||||
QList<ProjectExplorer::Task> getTasks() const;
|
||||
|
||||
private:
|
||||
explicit IssuesTracker(QObject *parent = nullptr);
|
||||
~IssuesTracker() override = default;
|
||||
|
||||
void onTaskAdded(const ProjectExplorer::Task &task);
|
||||
void onTaskRemoved(const ProjectExplorer::Task &task);
|
||||
void onTasksCleared(Utils::Id categoryId);
|
||||
|
||||
QList<ProjectExplorer::Task> m_tasks;
|
||||
mutable QMutex m_mutex;
|
||||
};
|
||||
|
||||
class GetIssuesListTool : public LLMCore::BaseTool
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GetIssuesListTool(QObject *parent = nullptr);
|
||||
|
||||
QString name() const override;
|
||||
QString stringName() const override;
|
||||
QString description() const override;
|
||||
QJsonObject getDefinition(LLMCore::ToolSchemaFormat format) const override;
|
||||
LLMCore::ToolPermissions requiredPermissions() const override;
|
||||
|
||||
QFuture<QString> executeAsync(const QJsonObject &input = QJsonObject()) override;
|
||||
};
|
||||
|
||||
} // namespace QodeAssist::Tools
|
||||
@ -24,6 +24,7 @@
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "GetIssuesListTool.hpp"
|
||||
#include "ListProjectFilesTool.hpp"
|
||||
#include "ReadProjectFileByNameTool.hpp"
|
||||
#include "ReadVisibleFilesTool.hpp"
|
||||
@ -43,6 +44,7 @@ void ToolsFactory::registerTools()
|
||||
registerTool(new ReadProjectFileByNameTool(this));
|
||||
registerTool(new ListProjectFilesTool(this));
|
||||
registerTool(new SearchInProjectTool(this));
|
||||
registerTool(new GetIssuesListTool(this));
|
||||
|
||||
LOG_MESSAGE(QString("Registered %1 tools").arg(m_tools.size()));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user