diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp index 9ae69f7..49fe44d 100644 --- a/LLMClientInterface.cpp +++ b/LLMClientInterface.cpp @@ -230,6 +230,19 @@ void LLMClientInterface::handleCompletion(const QJsonObject &request) if (updatedContext.fileContext.has_value()) systemPrompt.append(updatedContext.fileContext.value()); + if (m_completeSettings.useOpenFilesContext()) { + if (provider->providerID() == LLMCore::ProviderID::LlamaCpp) { + for (const auto openedFilePath : m_contextManager->openedFiles({filePath})) { + if (!updatedContext.filesMetadata) { + updatedContext.filesMetadata = QList(); + } + updatedContext.filesMetadata->append({openedFilePath.first, openedFilePath.second}); + } + } else { + systemPrompt.append(m_contextManager->openedFilesContext({filePath})); + } + } + updatedContext.systemPrompt = systemPrompt; if (promptTemplate->type() == LLMCore::TemplateType::Chat) { @@ -330,6 +343,4 @@ void LLMClientInterface::sendCompletionToClient( emit messageReceived(LanguageServerProtocol::JsonRpcMessage(response)); } -void LLMClientInterface::parseCurrentMessage() {} - } // namespace QodeAssist diff --git a/LLMClientInterface.hpp b/LLMClientInterface.hpp index 9728ba6..cff5c2f 100644 --- a/LLMClientInterface.hpp +++ b/LLMClientInterface.hpp @@ -64,7 +64,6 @@ public: protected: void startImpl() override; - void parseCurrentMessage() override; private: void handleInitialize(const QJsonObject &request); diff --git a/context/ContextManager.cpp b/context/ContextManager.cpp index 1e59cc3..9ddeeb8 100644 --- a/context/ContextManager.cpp +++ b/context/ContextManager.cpp @@ -25,8 +25,10 @@ #include #include "settings/GeneralSettings.hpp" +#include #include #include +#include #include "Logger.hpp" @@ -107,4 +109,48 @@ bool ContextManager::isSpecifyCompletion(const DocumentInfo &documentInfo) const return generalSettings.specifyPreset1() && documentLanguage == preset1Language; } +QList> ContextManager::openedFiles(const QStringList excludeFiles) const +{ + auto documents = Core::DocumentModel::openedDocuments(); + + QList> files; + + for (const auto *document : std::as_const(documents)) { + auto textDocument = qobject_cast(document); + if (!textDocument) + continue; + + auto filePath = textDocument->filePath().toUrlishString(); + if (!excludeFiles.contains(filePath)) { + files.append({filePath, textDocument->plainText()}); + } + } + + return files; +} + +QString ContextManager::openedFilesContext(const QStringList excludeFiles) +{ + QString context = "User files context:\n"; + + auto documents = Core::DocumentModel::openedDocuments(); + + for (const auto *document : documents) { + auto textDocument = qobject_cast(document); + if (!textDocument) + continue; + + auto filePath = textDocument->filePath().toUrlishString(); + if (excludeFiles.contains(filePath)) + continue; + + context += QString("File: %1\n").arg(filePath); + context += textDocument->plainText(); + + context += "\n"; + } + + return context; +} + } // namespace QodeAssist::Context diff --git a/context/ContextManager.hpp b/context/ContextManager.hpp index f09256c..d359606 100644 --- a/context/ContextManager.hpp +++ b/context/ContextManager.hpp @@ -47,6 +47,8 @@ public: ProgrammingLanguage getDocumentLanguage(const DocumentInfo &documentInfo) const override; bool isSpecifyCompletion(const DocumentInfo &documentInfo) const override; + QList> openedFiles(const QStringList excludeFiles = QStringList{}) const; + QString openedFilesContext(const QStringList excludeFiles = QStringList{}); }; } // namespace QodeAssist::Context diff --git a/llmcore/ContextData.hpp b/llmcore/ContextData.hpp index 25295f1..a6810d0 100644 --- a/llmcore/ContextData.hpp +++ b/llmcore/ContextData.hpp @@ -34,6 +34,13 @@ struct Message // clang-format on }; +struct FileMetadata +{ + QString filePath; + QString content; + bool operator==(const FileMetadata &) const = default; +}; + struct ContextData { std::optional systemPrompt; @@ -41,6 +48,7 @@ struct ContextData std::optional suffix; std::optional fileContext; std::optional> history; + std::optional> filesMetadata; bool operator==(const ContextData &) const = default; }; diff --git a/settings/CodeCompletionSettings.cpp b/settings/CodeCompletionSettings.cpp index 1afc9b8..f10871b 100644 --- a/settings/CodeCompletionSettings.cpp +++ b/settings/CodeCompletionSettings.cpp @@ -206,6 +206,10 @@ CodeCompletionSettings::CodeCompletionSettings() showProgressWidget.setLabelText(Tr::tr("Show progress indicator during code completion")); showProgressWidget.setDefaultValue(true); + useOpenFilesContext.setSettingsKey(Constants::CC_USE_OPEN_FILES_CONTEXT); + useOpenFilesContext.setLabelText(Tr::tr("Include context from open files")); + useOpenFilesContext.setDefaultValue(false); + useProjectChangesCache.setSettingsKey(Constants::CC_USE_PROJECT_CHANGES_CACHE); useProjectChangesCache.setDefaultValue(true); useProjectChangesCache.setLabelText(Tr::tr("Max Changes Cache Size:")); @@ -286,7 +290,8 @@ CodeCompletionSettings::CodeCompletionSettings() autoCompletionTypingInterval, startSuggestionTimer, Stretch{1}}, - showProgressWidget}}, + showProgressWidget, + useOpenFilesContext}}, Space{8}, Group{ title(Tr::tr("General Parameters")), @@ -364,6 +369,8 @@ void CodeCompletionSettings::resetSettingsToDefaults() resetAspect(userMessageTemplateForCC); resetAspect(systemPromptForNonFimModels); resetAspect(customLanguages); + resetAspect(showProgressWidget); + resetAspect(useOpenFilesContext); } } diff --git a/settings/CodeCompletionSettings.hpp b/settings/CodeCompletionSettings.hpp index 7aaa1dd..bb693c2 100644 --- a/settings/CodeCompletionSettings.hpp +++ b/settings/CodeCompletionSettings.hpp @@ -45,6 +45,7 @@ public: Utils::StringListAspect customLanguages{this}; Utils::BoolAspect showProgressWidget{this}; + Utils::BoolAspect useOpenFilesContext{this}; // General Parameters Settings Utils::DoubleAspect temperature{this}; diff --git a/settings/SettingsConstants.hpp b/settings/SettingsConstants.hpp index 226c20c..5e71705 100644 --- a/settings/SettingsConstants.hpp +++ b/settings/SettingsConstants.hpp @@ -56,6 +56,7 @@ const char CC_PRESET1_URL_HISTORY[] = "QodeAssist.ccPreset1UrlHistory"; const char ENABLE_QODE_ASSIST[] = "QodeAssist.enableQodeAssist"; const char CC_AUTO_COMPLETION[] = "QodeAssist.ccAutoCompletion"; const char CC_SHOW_PROGRESS_WIDGET[] = "QodeAssist.ccShowProgressWidget"; +const char CC_USE_OPEN_FILES_CONTEXT[] = "QodeAssist.ccUseOpenFilesContext"; const char ENABLE_LOGGING[] = "QodeAssist.enableLogging"; const char ENABLE_CHECK_UPDATE[] = "QodeAssist.enableCheckUpdate"; const char ENABLE_CHAT[] = "QodeAssist.enableChat"; diff --git a/templates/LlamaCppFim.hpp b/templates/LlamaCppFim.hpp index 1bce7a8..202a1c1 100644 --- a/templates/LlamaCppFim.hpp +++ b/templates/LlamaCppFim.hpp @@ -19,6 +19,8 @@ #pragma once +#include + #include "llmcore/PromptTemplate.hpp" namespace QodeAssist::Templates { @@ -34,6 +36,17 @@ public: { request["input_prefix"] = context.prefix.value_or(""); request["input_suffix"] = context.suffix.value_or(""); + + if (context.filesMetadata && !context.filesMetadata->isEmpty()) { + QJsonArray filesArray; + for (const auto &file : *context.filesMetadata) { + QJsonObject fileObj; + fileObj["filename"] = file.filePath; + fileObj["text"] = file.content; + filesArray.append(fileObj); + } + request["input_extra"] = filesArray; + } } QString description() const override