From f07610df5c890fd3e7a10d108b8922328887c45e Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Wed, 11 Sep 2024 01:24:22 +0200 Subject: [PATCH 1/6] Upgrade version to 0.1.2 --- QodeAssist.json.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QodeAssist.json.in b/QodeAssist.json.in index 8e11076..d4cf82c 100644 --- a/QodeAssist.json.in +++ b/QodeAssist.json.in @@ -1,6 +1,6 @@ { "Name" : "QodeAssist", - "Version" : "0.1.1", + "Version" : "0.1.2", "CompatVersion" : "${IDE_VERSION_COMPAT}", "Vendor" : "Petr Mironychev", "Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd", From cd1a9e16e0d6b5db28f28ab7527b8ccf83d9bf20 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Wed, 11 Sep 2024 01:25:00 +0200 Subject: [PATCH 2/6] Add basic cache manager --- CMakeLists.txt | 1 + LLMClientInterface.cpp | 16 +++++--- QodeAssistClient.cpp | 4 ++ core/ChangesManager.cpp | 86 +++++++++++++++++++++++++++++++++++++++++ core/ChangesManager.h | 62 +++++++++++++++++++++++++++++ 5 files changed, 163 insertions(+), 6 deletions(-) create mode 100644 core/ChangesManager.cpp create mode 100644 core/ChangesManager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e98f4f..f1e9092 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,4 +54,5 @@ add_qtc_plugin(QodeAssist settings/CustomPromptSettings.hpp settings/CustomPromptSettings.cpp settings/PresetPromptsSettings.hpp settings/PresetPromptsSettings.cpp settings/SettingsUtils.hpp + core/ChangesManager.h core/ChangesManager.cpp ) diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index a473ac1..3facf56 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -29,6 +29,7 @@ #include "LLMProvidersManager.hpp" #include "PromptTemplateManager.hpp" #include "QodeAssistUtils.hpp" +#include "core/ChangesManager.h" #include "settings/ContextSettings.hpp" #include "settings/GeneralSettings.hpp" @@ -277,14 +278,17 @@ ContextData LLMClientInterface::prepareContext(const QJsonObject &request, DocumentContextReader reader(widget->textDocument()); + QString recentChanges = ChangesManager::instance().getRecentChangesContext(); + QString contextBefore = сontextBefore(widget, lineNumber, cursorPosition); QString contextAfter = сontextAfter(widget, lineNumber, cursorPosition); - QString instructions = QString("%1%2").arg(Settings::contextSettings().useSpecificInstructions() - ? reader.getSpecificInstructions() - : QString(), - Settings::contextSettings().useFilePathInContext() - ? reader.getLanguageAndFileInfo() - : QString()); + QString instructions = QString("%1%2%3").arg(Settings::contextSettings().useSpecificInstructions() + ? reader.getSpecificInstructions() + : QString(), + Settings::contextSettings().useFilePathInContext() + ? reader.getLanguageAndFileInfo() + : QString(), + recentChanges); return {QString("%1%2").arg(contextBefore, accumulatedCompletion), contextAfter, instructions}; } diff --git a/QodeAssistClient.cpp b/QodeAssistClient.cpp index d8593ec..1f3bf53 100644 --- a/QodeAssistClient.cpp +++ b/QodeAssistClient.cpp @@ -31,6 +31,7 @@ #include "LLMClientInterface.hpp" #include "LLMSuggestion.hpp" +#include "core/ChangesManager.h" #include "settings/GeneralSettings.hpp" using namespace LanguageServerProtocol; @@ -83,6 +84,9 @@ void QodeAssistClient::openDocument(TextEditor::TextDocument *document) auto textEditor = BaseTextEditor::currentTextEditor(); if (!textEditor || textEditor->document() != document) return; + + ChangesManager::instance().addChange(document, position, charsRemoved, charsAdded); + TextEditorWidget *widget = textEditor->editorWidget(); if (widget->isReadOnly() || widget->multiTextCursor().hasMultipleCursors()) return; diff --git a/core/ChangesManager.cpp b/core/ChangesManager.cpp new file mode 100644 index 0000000..fcee753 --- /dev/null +++ b/core/ChangesManager.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2024 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 . + */ + +#include "ChangesManager.h" +#include "QodeAssistUtils.hpp" + +namespace QodeAssist { + +ChangesManager &ChangesManager::instance() +{ + static ChangesManager instance; + return instance; +} + +ChangesManager::ChangesManager() + : QObject(nullptr) +{ +} + +ChangesManager::~ChangesManager() +{ +} + +void ChangesManager::addChange(TextEditor::TextDocument *document, + int position, + int charsRemoved, + int charsAdded) +{ + auto &documentQueue = m_documentChanges[document]; + + QTextBlock block = document->document()->findBlock(position); + int lineNumber = block.blockNumber(); + QString lineContent = block.text(); + QString fileName = document->filePath().fileName(); + + ChangeInfo change{fileName, lineNumber, lineContent}; + + auto it = std::find_if(documentQueue.begin(), + documentQueue.end(), + [lineNumber](const ChangeInfo &c) { return c.lineNumber == lineNumber; }); + + if (it != documentQueue.end()) { + it->lineContent = lineContent; + } else { + documentQueue.enqueue(change); + + if (documentQueue.size() > MAX_CACHED_CHANGES) { + documentQueue.dequeue(); + } + } + + logMessage(QString("ChangesManager: Updated %1 line %2: '%3'") + .arg(fileName) + .arg(lineNumber) + .arg(lineContent)); + logMessage(QString("ChangesManager: Document queue size %1").arg(documentQueue.size())); +} + +QString ChangesManager::getRecentChangesContext() const +{ + QString context; + for (const auto &documentChanges : m_documentChanges) { + for (const auto &change : documentChanges) { + context += change.lineContent + "\n"; + } + } + return context; +} + +} // namespace QodeAssist diff --git a/core/ChangesManager.h b/core/ChangesManager.h new file mode 100644 index 0000000..4bd759b --- /dev/null +++ b/core/ChangesManager.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 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 . + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace QodeAssist { + +class ChangesManager : public QObject +{ + Q_OBJECT + +public: + struct ChangeInfo + { + QString fileName; + int lineNumber; + QString lineContent; + }; + + static ChangesManager &instance(); + + void addChange(TextEditor::TextDocument *document, + int position, + int charsRemoved, + int charsAdded); + QString getRecentChangesContext() const; + +private: + ChangesManager(); + ~ChangesManager(); + ChangesManager(const ChangesManager &) = delete; + ChangesManager &operator=(const ChangesManager &) = delete; + + void cleanupOldChanges(); + static const int MAX_CACHED_CHANGES = 50; + + QHash> m_documentChanges; +}; + +} // namespace QodeAssist From 2fb876ff00fefcb9de50bfa68e12ad3cc4ca94dc Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Wed, 11 Sep 2024 01:37:57 +0200 Subject: [PATCH 3/6] Exclude current file cache from request --- LLMClientInterface.cpp | 2 +- core/ChangesManager.cpp | 10 ++++++---- core/ChangesManager.h | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index 3facf56..cb78ddb 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -278,7 +278,7 @@ ContextData LLMClientInterface::prepareContext(const QJsonObject &request, DocumentContextReader reader(widget->textDocument()); - QString recentChanges = ChangesManager::instance().getRecentChangesContext(); + QString recentChanges = ChangesManager::instance().getRecentChangesContext(textDocument); QString contextBefore = сontextBefore(widget, lineNumber, cursorPosition); QString contextAfter = сontextAfter(widget, lineNumber, cursorPosition); diff --git a/core/ChangesManager.cpp b/core/ChangesManager.cpp index fcee753..032dee7 100644 --- a/core/ChangesManager.cpp +++ b/core/ChangesManager.cpp @@ -72,12 +72,14 @@ void ChangesManager::addChange(TextEditor::TextDocument *document, logMessage(QString("ChangesManager: Document queue size %1").arg(documentQueue.size())); } -QString ChangesManager::getRecentChangesContext() const +QString ChangesManager::getRecentChangesContext(const TextEditor::TextDocument *currentDocument) const { QString context; - for (const auto &documentChanges : m_documentChanges) { - for (const auto &change : documentChanges) { - context += change.lineContent + "\n"; + for (auto it = m_documentChanges.constBegin(); it != m_documentChanges.constEnd(); ++it) { + if (it.key() != currentDocument) { + for (const auto &change : it.value()) { + context += change.lineContent + "\n"; + } } } return context; diff --git a/core/ChangesManager.h b/core/ChangesManager.h index 4bd759b..7132347 100644 --- a/core/ChangesManager.h +++ b/core/ChangesManager.h @@ -45,7 +45,7 @@ public: int position, int charsRemoved, int charsAdded); - QString getRecentChangesContext() const; + QString getRecentChangesContext(const TextEditor::TextDocument *currentDocument) const; private: ChangesManager(); From 8e052ff45c74305c52b5041a9db8e7272d10cea0 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Wed, 11 Sep 2024 01:59:25 +0200 Subject: [PATCH 4/6] Add settings for cache of changes --- LLMClientInterface.cpp | 16 +++++++++------- QodeAssistClient.cpp | 7 ++++++- QodeAssistConstants.hpp | 2 ++ core/ChangesManager.cpp | 3 ++- core/ChangesManager.h | 1 - settings/ContextSettings.cpp | 11 +++++++++++ settings/ContextSettings.hpp | 2 ++ 7 files changed, 32 insertions(+), 10 deletions(-) diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index cb78ddb..029a70c 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -282,13 +282,15 @@ ContextData LLMClientInterface::prepareContext(const QJsonObject &request, QString contextBefore = сontextBefore(widget, lineNumber, cursorPosition); QString contextAfter = сontextAfter(widget, lineNumber, cursorPosition); - QString instructions = QString("%1%2%3").arg(Settings::contextSettings().useSpecificInstructions() - ? reader.getSpecificInstructions() - : QString(), - Settings::contextSettings().useFilePathInContext() - ? reader.getLanguageAndFileInfo() - : QString(), - recentChanges); + QString instructions + = QString("%1%2%3").arg(Settings::contextSettings().useSpecificInstructions() + ? reader.getSpecificInstructions() + : QString(), + Settings::contextSettings().useFilePathInContext() + ? reader.getLanguageAndFileInfo() + : QString(), + Settings::contextSettings().useProjectChangesCache() ? recentChanges + : QString()); return {QString("%1%2").arg(contextBefore, accumulatedCompletion), contextAfter, instructions}; } diff --git a/QodeAssistClient.cpp b/QodeAssistClient.cpp index 1f3bf53..f85056f 100644 --- a/QodeAssistClient.cpp +++ b/QodeAssistClient.cpp @@ -32,6 +32,7 @@ #include "LLMClientInterface.hpp" #include "LLMSuggestion.hpp" #include "core/ChangesManager.h" +#include "settings/ContextSettings.hpp" #include "settings/GeneralSettings.hpp" using namespace LanguageServerProtocol; @@ -85,7 +86,11 @@ void QodeAssistClient::openDocument(TextEditor::TextDocument *document) if (!textEditor || textEditor->document() != document) return; - ChangesManager::instance().addChange(document, position, charsRemoved, charsAdded); + if (Settings::contextSettings().useProjectChangesCache()) + ChangesManager::instance().addChange(document, + position, + charsRemoved, + charsAdded); TextEditorWidget *widget = textEditor->editorWidget(); if (widget->isReadOnly() || widget->multiTextCursor().hasMultipleCursors()) diff --git a/QodeAssistConstants.hpp b/QodeAssistConstants.hpp index 774bdca..8f51de7 100644 --- a/QodeAssistConstants.hpp +++ b/QodeAssistConstants.hpp @@ -59,6 +59,8 @@ const char API_KEY[] = "QodeAssist.apiKey"; const char USE_SPECIFIC_INSTRUCTIONS[] = "QodeAssist.useSpecificInstructions"; const char USE_FILE_PATH_IN_CONTEXT[] = "QodeAssist.useFilePathInContext"; const char CUSTOM_JSON_TEMPLATE[] = "QodeAssist.customJsonTemplate"; +const char USE_PROJECT_CHANGES_CACHE[] = "QodeAssist.useProjectChangesCache"; +const char MAX_CHANGES_CACHE_SIZE[] = "QodeAssist.maxChangesCacheSize"; const char QODE_ASSIST_GENERAL_OPTIONS_ID[] = "QodeAssist.GeneralOptions"; const char QODE_ASSIST_GENERAL_SETTINGS_PAGE_ID[] = "QodeAssist.1GeneralSettingsPageId"; diff --git a/core/ChangesManager.cpp b/core/ChangesManager.cpp index 032dee7..216465e 100644 --- a/core/ChangesManager.cpp +++ b/core/ChangesManager.cpp @@ -19,6 +19,7 @@ #include "ChangesManager.h" #include "QodeAssistUtils.hpp" +#include "settings/ContextSettings.hpp" namespace QodeAssist { @@ -60,7 +61,7 @@ void ChangesManager::addChange(TextEditor::TextDocument *document, } else { documentQueue.enqueue(change); - if (documentQueue.size() > MAX_CACHED_CHANGES) { + if (documentQueue.size() > Settings::contextSettings().maxChangesCacheSize()) { documentQueue.dequeue(); } } diff --git a/core/ChangesManager.h b/core/ChangesManager.h index 7132347..d9c4c91 100644 --- a/core/ChangesManager.h +++ b/core/ChangesManager.h @@ -54,7 +54,6 @@ private: ChangesManager &operator=(const ChangesManager &) = delete; void cleanupOldChanges(); - static const int MAX_CACHED_CHANGES = 50; QHash> m_documentChanges; }; diff --git a/settings/ContextSettings.cpp b/settings/ContextSettings.cpp index d0574df..5ff5d46 100644 --- a/settings/ContextSettings.cpp +++ b/settings/ContextSettings.cpp @@ -74,6 +74,15 @@ ContextSettings::ContextSettings() resetToDefaults.m_buttonText = Tr::tr("Reset Page to Defaults"); + useProjectChangesCache.setSettingsKey(Constants::USE_PROJECT_CHANGES_CACHE); + useProjectChangesCache.setDefaultValue(true); + useProjectChangesCache.setLabelText(Tr::tr("Use Project Changes Cache")); + + maxChangesCacheSize.setSettingsKey(Constants::MAX_CHANGES_CACHE_SIZE); + maxChangesCacheSize.setLabelText(Tr::tr("Max Changes Cache Size")); + maxChangesCacheSize.setRange(2, 1000); + maxChangesCacheSize.setDefaultValue(20); + readSettings(); readStringsAfterCursor.setEnabled(!readFullFile()); @@ -90,6 +99,8 @@ ContextSettings::ContextSettings() useFilePathInContext, useSpecificInstructions, specificInstractions, + useProjectChangesCache, + Row{maxChangesCacheSize, Stretch{1}}, Stretch{1}}; }); } diff --git a/settings/ContextSettings.hpp b/settings/ContextSettings.hpp index 4a6f539..dbe491b 100644 --- a/settings/ContextSettings.hpp +++ b/settings/ContextSettings.hpp @@ -37,6 +37,8 @@ public: Utils::StringAspect specificInstractions{this}; Utils::BoolAspect useSpecificInstructions{this}; Utils::BoolAspect useFilePathInContext{this}; + Utils::BoolAspect useProjectChangesCache{this}; + Utils::IntegerAspect maxChangesCacheSize{this}; ButtonAspect resetToDefaults{this}; From 793b855819d41baf67b5cb24f8c64cc07339c0ff Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Wed, 11 Sep 2024 01:59:45 +0200 Subject: [PATCH 5/6] Change default value for start ai suggestion --- settings/GeneralSettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp index 5f86830..7933965 100644 --- a/settings/GeneralSettings.cpp +++ b/settings/GeneralSettings.cpp @@ -72,7 +72,7 @@ GeneralSettings::GeneralSettings() Tr::tr("The number of characters that need to be typed within the typing interval " "before an AI suggestion request is sent.")); autoCompletionCharThreshold.setRange(0, 10); - autoCompletionCharThreshold.setDefaultValue(1); + autoCompletionCharThreshold.setDefaultValue(0); autoCompletionTypingInterval.setSettingsKey(Constants::AUTO_COMPLETION_TYPING_INTERVAL); autoCompletionTypingInterval.setLabelText(Tr::tr("character(s) within(ms)")); From 0ae12e0fc67bd772b5b8b424092b9fde62943285 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Wed, 11 Sep 2024 02:01:00 +0200 Subject: [PATCH 6/6] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a0168c4..58bfac2 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ If you've successfully used a model that's not listed here, please let us know b - [x] Basic plugin with code autocomplete functionality - [x] Improve and automate settings - [ ] Add chat functionality -- [ ] Sharing diff with model +- [x] Sharing diff with model - [ ] Sharing project source with model - [ ] Support for more providers and models