mirror of
				https://github.com/Palm1r/QodeAssist.git
				synced 2025-10-31 08:14:36 -04:00 
			
		
		
		
	feat: Add tool for reading issues tab
This commit is contained in:
		| @ -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 | ||||
|  | ||||
							
								
								
									
										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