mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-01-30 11:56:38 -05:00
feat: Add project-specific rules support
This commit is contained in:
@ -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());
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
28
README.md
28
README.md
@ -218,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
|
||||
Reference in New Issue
Block a user