Compare commits

...

13 Commits

Author SHA1 Message Date
e836b86569 chore: Upgrade plugin to 0.4.12
Some checks failed
Build plugin / ${{ matrix.config.name }} (map[artifact:Linux-x64 cc:gcc cxx:g++ name:Ubuntu Latest GCC os:ubuntu-latest platform:linux_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:Linux-x64(Ubuntu-22.04-experimental) cc:gcc cxx:g++ name:Ubuntu 22.04 GCC os:ubuntu-22.04 platform:linux_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:Windows-x64 cc:cl cxx:cl environment_script:C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat name:Windows Latest MSVC os:windows-latest platform:windows_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:macOS-universal cc:clang cxx:clang++ name:macOS Latest Clang os:macos-latest platform:mac_x64]) (push) Has been cancelled
Build plugin / update_json (push) Has been cancelled
Build plugin / release (push) Has been cancelled
2025-02-01 09:37:21 +01:00
288fefebe5 feat: Add CodeLlama QML FIM 2025-02-01 09:36:14 +01:00
528badbf1e Add commercial support to README.md
Some checks failed
Build plugin / ${{ matrix.config.name }} (map[artifact:Linux-x64 cc:gcc cxx:g++ name:Ubuntu Latest GCC os:ubuntu-latest platform:linux_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:Linux-x64(Ubuntu-22.04-experimental) cc:gcc cxx:g++ name:Ubuntu 22.04 GCC os:ubuntu-22.04 platform:linux_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:Windows-x64 cc:cl cxx:cl environment_script:C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat name:Windows Latest MSVC os:windows-latest platform:windows_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:macOS-universal cc:clang cxx:clang++ name:macOS Latest Clang os:macos-latest platform:mac_x64]) (push) Has been cancelled
Build plugin / update_json (push) Has been cancelled
Build plugin / release (push) Has been cancelled
2025-01-29 15:00:16 +01:00
b789e42602 chore: Upgrade plugin to 0.4.11
Some checks failed
Build plugin / ${{ matrix.config.name }} (map[artifact:Linux-x64 cc:gcc cxx:g++ name:Ubuntu Latest GCC os:ubuntu-latest platform:linux_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:Linux-x64(Ubuntu-22.04-experimental) cc:gcc cxx:g++ name:Ubuntu 22.04 GCC os:ubuntu-22.04 platform:linux_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:Windows-x64 cc:cl cxx:cl environment_script:C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat name:Windows Latest MSVC os:windows-latest platform:windows_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:macOS-universal cc:clang cxx:clang++ name:macOS Latest Clang os:macos-latest platform:mac_x64]) (push) Has been cancelled
Build plugin / update_json (push) Has been cancelled
Build plugin / release (push) Has been cancelled
2025-01-27 00:55:39 +01:00
4bf955462f feat: Update dialog offer open plugin folder 2025-01-27 00:54:49 +01:00
5b99e68e53 doc: Added file context feature description 2025-01-27 00:14:38 +01:00
0f1b277ef7 chore: Upgrade plugin to 0.4.10 2025-01-26 23:11:58 +01:00
56995c9edf fix: Saving name of chat in native language
- Add button to show chat history folder in system viewer
2025-01-26 23:06:51 +01:00
45aba6b6be fix: Sync editors and chat when sync enable 2025-01-26 22:35:43 +01:00
1dfb3feb96 doc: Update info for QtC 15.0.1 changes
Some checks are pending
Build plugin / ${{ matrix.config.name }} (map[artifact:Linux-x64 cc:gcc cxx:g++ name:Ubuntu Latest GCC os:ubuntu-latest platform:linux_x64]) (push) Waiting to run
Build plugin / ${{ matrix.config.name }} (map[artifact:Linux-x64(Ubuntu-22.04-experimental) cc:gcc cxx:g++ name:Ubuntu 22.04 GCC os:ubuntu-22.04 platform:linux_x64]) (push) Waiting to run
Build plugin / ${{ matrix.config.name }} (map[artifact:Windows-x64 cc:cl cxx:cl environment_script:C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat name:Windows Latest MSVC os:windows-latest platform:windows_x64]) (push) Waiting to run
Build plugin / ${{ matrix.config.name }} (map[artifact:macOS-universal cc:clang cxx:clang++ name:macOS Latest Clang os:macos-latest platform:mac_x64]) (push) Waiting to run
Build plugin / update_json (push) Blocked by required conditions
Build plugin / release (push) Blocked by required conditions
2025-01-26 10:08:03 +01:00
2c49d45297 fix: Keep name of chat after saving 2025-01-26 10:03:34 +01:00
31145f191b chore: Upgrade plugin to 0.4.9
Some checks failed
Build plugin / ${{ matrix.config.name }} (map[artifact:Linux-x64 cc:gcc cxx:g++ name:Ubuntu Latest GCC os:ubuntu-latest platform:linux_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:Linux-x64(Ubuntu-22.04-experimental) cc:gcc cxx:g++ name:Ubuntu 22.04 GCC os:ubuntu-22.04 platform:linux_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:Windows-x64 cc:cl cxx:cl environment_script:C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat name:Windows Latest MSVC os:windows-latest platform:windows_x64]) (push) Has been cancelled
Build plugin / ${{ matrix.config.name }} (map[artifact:macOS-universal cc:clang cxx:clang++ name:macOS Latest Clang os:macos-latest platform:mac_x64]) (push) Has been cancelled
Build plugin / update_json (push) Has been cancelled
Build plugin / release (push) Has been cancelled
2025-01-24 18:27:07 +01:00
9096adde6f fix: Remove installing plugin from update dialog 2025-01-24 18:23:11 +01:00
11 changed files with 272 additions and 65 deletions

View File

@ -55,6 +55,7 @@ add_qtc_plugin(QodeAssist
templates/Llama2.hpp templates/Llama2.hpp
templates/Claude.hpp templates/Claude.hpp
templates/OpenAI.hpp templates/OpenAI.hpp
templates/CodeLlamaQMLFim.hpp
providers/Providers.hpp providers/Providers.hpp
providers/OllamaProvider.hpp providers/OllamaProvider.cpp providers/OllamaProvider.hpp providers/OllamaProvider.cpp
providers/LMStudioProvider.hpp providers/LMStudioProvider.cpp providers/LMStudioProvider.hpp providers/LMStudioProvider.cpp

View File

@ -20,6 +20,7 @@
#include "ChatRootView.hpp" #include "ChatRootView.hpp"
#include <QClipboard> #include <QClipboard>
#include <QDesktopServices>
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
@ -72,7 +73,7 @@ ChatRootView::ChatRootView(QQuickItem *parent)
this, this,
&ChatRootView::updateInputTokensCount); &ChatRootView::updateInputTokensCount);
connect(m_chatModel, &ChatModel::modelReseted, [this]() { setRecentFilePath(QString{}); }); connect(m_chatModel, &ChatModel::modelReseted, this, [this]() { setRecentFilePath(QString{}); });
connect(this, &ChatRootView::attachmentFilesChanged, &ChatRootView::updateInputTokensCount); connect(this, &ChatRootView::attachmentFilesChanged, &ChatRootView::updateInputTokensCount);
connect(this, &ChatRootView::linkedFilesChanged, &ChatRootView::updateInputTokensCount); connect(this, &ChatRootView::linkedFilesChanged, &ChatRootView::updateInputTokensCount);
connect(&Settings::chatAssistantSettings().useSystemPrompt, &Utils::BaseAspect::changed, connect(&Settings::chatAssistantSettings().useSystemPrompt, &Utils::BaseAspect::changed,
@ -82,9 +83,20 @@ ChatRootView::ChatRootView(QQuickItem *parent)
auto editors = Core::EditorManager::instance(); auto editors = Core::EditorManager::instance();
connect(editors, &Core::EditorManager::editorOpened, this, &ChatRootView::onEditorOpened); connect(editors, &Core::EditorManager::editorCreated, this, &ChatRootView::onEditorCreated);
connect(editors, &Core::EditorManager::editorAboutToClose, this, &ChatRootView::onEditorAboutToClose); connect(
connect(editors, &Core::EditorManager::editorsClosed, this, &ChatRootView::onEditorsClosed); editors,
&Core::EditorManager::editorAboutToClose,
this,
&ChatRootView::onEditorAboutToClose);
connect(editors, &Core::EditorManager::currentEditorAboutToChange, this, [this]() {
if (m_isSyncOpenFiles) {
for (auto editor : std::as_const(m_currentEditors)) {
onAppendLinkFileFromEditor(editor);
}
}
});
updateInputTokensCount(); updateInputTokensCount();
} }
@ -173,6 +185,8 @@ void ChatRootView::saveHistory(const QString &filePath)
auto result = ChatSerializer::saveToFile(m_chatModel, filePath); auto result = ChatSerializer::saveToFile(m_chatModel, filePath);
if (!result.success) { if (!result.success) {
LOG_MESSAGE(QString("Failed to save chat history: %1").arg(result.errorMessage)); LOG_MESSAGE(QString("Failed to save chat history: %1").arg(result.errorMessage));
} else {
setRecentFilePath(filePath);
} }
} }
@ -243,17 +257,50 @@ QString ChatRootView::getSuggestedFileName() const
{ {
QStringList parts; QStringList parts;
static const QRegularExpression saitizeSymbols = QRegularExpression("[\\/:*?\"<>|\\s]");
static const QRegularExpression underSymbols = QRegularExpression("_+");
if (m_chatModel->rowCount() > 0) { if (m_chatModel->rowCount() > 0) {
QString firstMessage QString firstMessage
= m_chatModel->data(m_chatModel->index(0), ChatModel::Content).toString(); = m_chatModel->data(m_chatModel->index(0), ChatModel::Content).toString();
QString shortMessage = firstMessage.split('\n').first().simplified().left(30); QString shortMessage = firstMessage.split('\n').first().simplified().left(30);
shortMessage.replace(QRegularExpression("[^a-zA-Z0-9_-]"), "_");
parts << shortMessage; QString sanitizedMessage = shortMessage;
sanitizedMessage.replace(saitizeSymbols, "_");
sanitizedMessage.replace(underSymbols, "_");
sanitizedMessage = sanitizedMessage.trimmed();
if (!sanitizedMessage.isEmpty()) {
if (sanitizedMessage.startsWith('_')) {
sanitizedMessage.remove(0, 1);
}
if (sanitizedMessage.endsWith('_')) {
sanitizedMessage.chop(1);
}
QString targetDir = getChatsHistoryDir();
QString fullPath = QDir(targetDir).filePath(sanitizedMessage);
QFileInfo fileInfo(fullPath);
if (!fileInfo.exists() && QFileInfo(fileInfo.path()).isWritable()) {
parts << sanitizedMessage;
}
}
} }
parts << QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm"); parts << QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm");
return parts.join("_"); QString fileName = parts.join("_");
QString fullPath = QDir(getChatsHistoryDir()).filePath(fileName);
QFileInfo finalCheck(fullPath);
if (fileName.isEmpty() || finalCheck.exists() || !QFileInfo(finalCheck.path()).isWritable()) {
fileName = QString("chat_%1").arg(
QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm"));
}
return fileName;
} }
void ChatRootView::autosave() void ChatRootView::autosave()
@ -306,7 +353,7 @@ void ChatRootView::showAttachFilesDialog()
QStringList newFilePaths = dialog.selectedFiles(); QStringList newFilePaths = dialog.selectedFiles();
if (!newFilePaths.isEmpty()) { if (!newFilePaths.isEmpty()) {
bool filesAdded = false; bool filesAdded = false;
for (const QString &filePath : newFilePaths) { for (const QString &filePath : std::as_const(newFilePaths)) {
if (!m_attachmentFiles.contains(filePath)) { if (!m_attachmentFiles.contains(filePath)) {
m_attachmentFiles.append(filePath); m_attachmentFiles.append(filePath);
filesAdded = true; filesAdded = true;
@ -340,7 +387,7 @@ void ChatRootView::showLinkFilesDialog()
QStringList newFilePaths = dialog.selectedFiles(); QStringList newFilePaths = dialog.selectedFiles();
if (!newFilePaths.isEmpty()) { if (!newFilePaths.isEmpty()) {
bool filesAdded = false; bool filesAdded = false;
for (const QString &filePath : newFilePaths) { for (const QString &filePath : std::as_const(newFilePaths)) {
if (!m_linkedFiles.contains(filePath)) { if (!m_linkedFiles.contains(filePath)) {
m_linkedFiles.append(filePath); m_linkedFiles.append(filePath);
filesAdded = true; filesAdded = true;
@ -373,6 +420,31 @@ void ChatRootView::setIsSyncOpenFiles(bool state)
m_isSyncOpenFiles = state; m_isSyncOpenFiles = state;
emit isSyncOpenFilesChanged(); emit isSyncOpenFilesChanged();
} }
if (m_isSyncOpenFiles) {
for (auto editor : std::as_const(m_currentEditors)) {
onAppendLinkFileFromEditor(editor);
}
}
}
void ChatRootView::openChatHistoryFolder()
{
QString path;
if (auto project = ProjectExplorer::ProjectManager::startupProject()) {
Settings::ProjectSettings projectSettings(project);
path = projectSettings.chatHistoryPath().toString();
} else {
path = QString("%1/qodeassist/chat_history").arg(Core::ICore::userResourcePath().toString());
}
QDir dir(path);
if (!dir.exists()) {
dir.mkpath(".");
}
QUrl url = QUrl::fromLocalFile(dir.absolutePath());
QDesktopServices::openUrl(url);
} }
void ChatRootView::updateInputTokensCount() void ChatRootView::updateInputTokensCount()
@ -414,7 +486,20 @@ bool ChatRootView::isSyncOpenFiles() const
return m_isSyncOpenFiles; return m_isSyncOpenFiles;
} }
void ChatRootView::onEditorOpened(Core::IEditor *editor) void ChatRootView::onEditorAboutToClose(Core::IEditor *editor)
{
if (auto document = editor->document(); document && isSyncOpenFiles()) {
QString filePath = document->filePath().toString();
m_linkedFiles.removeOne(filePath);
emit linkedFilesChanged();
}
if (editor) {
m_currentEditors.removeOne(editor);
}
}
void ChatRootView::onAppendLinkFileFromEditor(Core::IEditor *editor)
{ {
if (auto document = editor->document(); document && isSyncOpenFiles()) { if (auto document = editor->document(); document && isSyncOpenFiles()) {
QString filePath = document->filePath().toString(); QString filePath = document->filePath().toString();
@ -425,25 +510,10 @@ void ChatRootView::onEditorOpened(Core::IEditor *editor)
} }
} }
void ChatRootView::onEditorAboutToClose(Core::IEditor *editor) void ChatRootView::onEditorCreated(Core::IEditor *editor, const Utils::FilePath &filePath)
{ {
if (auto document = editor->document(); document && isSyncOpenFiles()) { if (editor && editor->document()) {
QString filePath = document->filePath().toString(); m_currentEditors.append(editor);
m_linkedFiles.removeOne(filePath);
emit linkedFilesChanged();
}
}
void ChatRootView::onEditorsClosed(QList<Core::IEditor *> editors)
{
if (isSyncOpenFiles()) {
for (Core::IEditor *editor : editors) {
if (auto document = editor->document()) {
QString filePath = document->filePath().toString();
m_linkedFiles.removeOne(filePath);
}
}
emit linkedFilesChanged();
} }
} }

View File

@ -64,15 +64,16 @@ public:
Q_INVOKABLE void removeFileFromLinkList(int index); Q_INVOKABLE void removeFileFromLinkList(int index);
Q_INVOKABLE void calculateMessageTokensCount(const QString &message); Q_INVOKABLE void calculateMessageTokensCount(const QString &message);
Q_INVOKABLE void setIsSyncOpenFiles(bool state); Q_INVOKABLE void setIsSyncOpenFiles(bool state);
Q_INVOKABLE void openChatHistoryFolder();
Q_INVOKABLE void updateInputTokensCount(); Q_INVOKABLE void updateInputTokensCount();
int inputTokensCount() const; int inputTokensCount() const;
bool isSyncOpenFiles() const; bool isSyncOpenFiles() const;
void onEditorOpened(Core::IEditor *editor);
void onEditorAboutToClose(Core::IEditor *editor); void onEditorAboutToClose(Core::IEditor *editor);
void onEditorsClosed(QList<Core::IEditor *> editors); void onAppendLinkFileFromEditor(Core::IEditor *editor);
void onEditorCreated(Core::IEditor *editor, const Utils::FilePath &filePath);
QString chatFileName() const; QString chatFileName() const;
void setRecentFilePath(const QString &filePath); void setRecentFilePath(const QString &filePath);
@ -106,6 +107,7 @@ private:
int m_messageTokensCount{0}; int m_messageTokensCount{0};
int m_inputTokensCount{0}; int m_inputTokensCount{0};
bool m_isSyncOpenFiles; bool m_isSyncOpenFiles;
QList<Core::IEditor *> m_currentEditors;
}; };
} // namespace QodeAssist::Chat } // namespace QodeAssist::Chat

View File

@ -75,6 +75,7 @@ ChatRootView {
recentPath { recentPath {
text: qsTr("Latest chat file name: %1").arg(root.chatFileName.length > 0 ? root.chatFileName : "Unsaved") text: qsTr("Latest chat file name: %1").arg(root.chatFileName.length > 0 ? root.chatFileName : "Unsaved")
} }
openChatHistory.onClicked: root.openChatHistoryFolder()
} }
ListView { ListView {

View File

@ -29,6 +29,7 @@ Rectangle {
property alias clearButton: clearButtonId property alias clearButton: clearButtonId
property alias tokensBadge: tokensBadgeId property alias tokensBadge: tokensBadgeId
property alias recentPath: recentPathId property alias recentPath: recentPathId
property alias openChatHistory: openChatHistoryId
color: palette.window.hslLightness > 0.5 ? color: palette.window.hslLightness > 0.5 ?
Qt.darker(palette.window, 1.1) : Qt.darker(palette.window, 1.1) :
@ -66,11 +67,16 @@ Rectangle {
Text { Text {
id: recentPathId id: recentPathId
Layout.fillWidth: true
elide: Text.ElideMiddle elide: Text.ElideMiddle
color: palette.text color: palette.text
} }
QoAButton {
id: openChatHistoryId
text: qsTr("Show in system")
}
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
} }

View File

@ -1,7 +1,7 @@
{ {
"Id" : "qodeassist", "Id" : "qodeassist",
"Name" : "QodeAssist", "Name" : "QodeAssist",
"Version" : "0.4.8", "Version" : "0.4.12",
"Vendor" : "Petr Mironychev", "Vendor" : "Petr Mironychev",
"VendorId" : "petrmironychev", "VendorId" : "petrmironychev",
"Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd", "Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd",

View File

@ -2,7 +2,7 @@
[![Build plugin](https://github.com/Palm1r/QodeAssist/actions/workflows/build_cmake.yml/badge.svg?branch=main)](https://github.com/Palm1r/QodeAssist/actions/workflows/build_cmake.yml) [![Build plugin](https://github.com/Palm1r/QodeAssist/actions/workflows/build_cmake.yml/badge.svg?branch=main)](https://github.com/Palm1r/QodeAssist/actions/workflows/build_cmake.yml)
![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/Palm1r/QodeAssist/total?color=41%2C173%2C71) ![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/Palm1r/QodeAssist/total?color=41%2C173%2C71)
![GitHub Tag](https://img.shields.io/github/v/tag/Palm1r/QodeAssist) ![GitHub Tag](https://img.shields.io/github/v/tag/Palm1r/QodeAssist)
![Static Badge](https://img.shields.io/badge/QtCreator-15.0.0-brightgreen) ![Static Badge](https://img.shields.io/badge/QtCreator-15.0.1-brightgreen)
![Static Badge](https://img.shields.io/badge/donations:0-brightgreen) ![Static Badge](https://img.shields.io/badge/donations:0-brightgreen)
![qodeassist-icon](https://github.com/user-attachments/assets/dc336712-83cb-440d-8761-8d0a31de898d) 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. ![qodeassist-icon](https://github.com/user-attachments/assets/dc336712-83cb-440d-8761-8d0a31de898d) 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.
@ -13,6 +13,15 @@
> - The QodeAssist developer bears no responsibility for any charges incurred > - The QodeAssist developer bears no responsibility for any charges incurred
> - Please carefully review the provider's pricing and your account settings before use > - Please carefully review the provider's pricing and your account settings before use
⚠️ **Commercial Support and Custom Development**
> The QodeAssist developer offers commercial services for:
> - Adapting the plugin for specific Qt Creator versions
> - Custom development for particular operating systems
> - Integration with specific language models
> - Implementing custom features and modifications
>
> For commercial inquiries, please contact: qodeassist.dev@pm.me
## Table of Contents ## Table of Contents
1. [Overview](#overview) 1. [Overview](#overview)
2. [Install plugin to QtCreator](#install-plugin-to-qtcreator) 2. [Install plugin to QtCreator](#install-plugin-to-qtcreator)
@ -20,19 +29,25 @@
4. [Configure for OpenAI](#configure-for-openai) 4. [Configure for OpenAI](#configure-for-openai)
5. [Configure for using Ollama](#configure-for-using-ollama) 5. [Configure for using Ollama](#configure-for-using-ollama)
6. [System Prompt Configuration](#system-prompt-configuration) 6. [System Prompt Configuration](#system-prompt-configuration)
7. [Template-Model Compatibility](#template-model-compatibility) 7. [File Context Features](#file-context-features)
8. [QtCreator Version Compatibility](#qtcreator-version-compatibility) 8. [Template-Model Compatibility](#template-model-compatibility)
9. [Development Progress](#development-progress) 9. [QtCreator Version Compatibility](#qtcreator-version-compatibility)
10. [Hotkeys](#hotkeys) 10. [Development Progress](#development-progress)
11. [Troubleshooting](#troubleshooting) 11. [Hotkeys](#hotkeys)
12. [Support the Development](#support-the-development-of-qodeassist) 12. [Troubleshooting](#troubleshooting)
13. [How to Build](#how-to-build) 13. [Support the Development](#support-the-development-of-qodeassist)
14. [How to Build](#how-to-build)
## Overview ## Overview
- AI-powered code completion - AI-powered code completion
- Chat functionality: - Chat functionality:
- Side and Bottom panels - Side and Bottom panels
- Chat history autosave and restore
- Token usage monitoring and management
- Attach files for one-time code analysis
- Link files for persistent context with auto update in conversations
- Automatic syncing with open editor files (optional)
- Support for multiple LLM providers: - Support for multiple LLM providers:
- Ollama - Ollama
- OpenAI - OpenAI
@ -63,9 +78,15 @@
<img width="326" alt="QodeAssistBottomPanel" src="https://github.com/user-attachments/assets/4cc64c23-a294-4df8-9153-39ad6fdab34b"> <img width="326" alt="QodeAssistBottomPanel" src="https://github.com/user-attachments/assets/4cc64c23-a294-4df8-9153-39ad6fdab34b">
</details> </details>
<details>
<summary>Automatic syncing with open editor files: (click to expand)</summary>
<img width="600" alt="OpenedDocumentsSync" src="https://github.com/user-attachments/assets/08efda2f-dc4d-44c3-927c-e6a975090d2f">
</details>
## Install plugin to QtCreator ## Install plugin to QtCreator
1. Install Latest Qt Creator 1. Install Latest Qt Creator
2. Download the QodeAssist plugin for your Qt Creator 2. Download the QodeAssist plugin for your Qt Creator
- Remove old version plugin if already was installed
3. Launch Qt Creator and install the plugin: 3. Launch Qt Creator and install the plugin:
- Go to: - Go to:
- MacOS: Qt Creator -> About Plugins... - MacOS: Qt Creator -> About Plugins...
@ -136,25 +157,59 @@ 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. 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.
## File Context Features
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.
### Attached Files
Attachments are designed for one-time code analysis and specific queries:
- Files are included only in the current message
- Content is discarded after the message is processed
- Ideal for:
- Getting specific feedback on code changes
- Code review requests
- Analyzing isolated code segments
- Quick implementation questions
- Files can be attached using the paperclip icon in the chat interface
- Multiple files can be attached to a single message
### Linked Files
Linked files provide persistent context throughout the conversation:
- Files remain accessible for the entire chat session
- Content is included in every message exchange
- Files are automatically refreshed - always using latest content from disk
- Perfect for:
- Long-term refactoring discussions
- Complex architectural changes
- Multi-file implementations
- Maintaining context across related questions
- Can be managed using the link icon in the chat interface
- Supports automatic syncing with open editor files (can be enabled in settings)
- Files can be added/removed at any time during the conversation
## Template-Model Compatibility ## Template-Model Compatibility
| Template | Compatible Models | Purpose | | Template | Compatible Models | Purpose |
|----------|------------------|----------| |----------|------------------|----------|
| CodeLlama FIM | `codellama:code` | Code completion | | CodeLlama FIM | `codellama:code` | Code completion |
| DeepSeekCoder FIM | `deepseek-coder-v2`, `deepseek-v2.5` | Code completion | | DeepSeekCoder FIM | `deepseek-coder-v2`, `deepseek-v2.5` | Code completion |
| Ollama Auto FIM | `Any Ollama base model` | Code completion | | Ollama Auto FIM | `Any Ollama base/fim models` | Code completion |
| Qwen FIM | `Qwen 2.5 models` | Code completion | | Qwen FIM | `Qwen 2.5 models(exclude instruct)` | Code completion |
| StarCoder2 FIM | `starcoder2 base model` | Code completion | | StarCoder2 FIM | `starcoder2 base model` | Code completion |
| Alpaca | `starcoder2:instruct` | Chat assistance | | Alpaca | `starcoder2:instruct` | Chat assistance |
| Basic Chat| `Messages without tokens` | Chat assistance | | Basic Chat| `Messages without tokens` | Chat assistance |
| ChatML | `Qwen 2.5 models` | Chat assistance | | ChatML | `Qwen 2.5 models(exclude base models)` | Chat assistance |
| Llama2 | `llama2 model family`, `codellama:instruct` | Chat assistance | | Llama2 | `llama2 model family`, `codellama:instruct` | Chat assistance |
| Llama3 | `llama3 model family` | Chat assistance | | Llama3 | `llama3 model family` | Chat assistance |
| Ollama Auto Chat | `Any Ollama chat model` | Chat assistance | | Ollama Auto Chat | `Any Ollama chat/instruct models` | Chat assistance |
## QtCreator Version Compatibility ## QtCreator Version Compatibility
- QtCreator 15.0.0 - 0.4.x - QtCreator 15.0.1 - 0.4.8 - 0.4.x
- QtCreator 15.0.0 - 0.4.0 - 0.4.7
- QtCreator 14.0.2 - 0.2.3 - 0.3.x - QtCreator 14.0.2 - 0.2.3 - 0.3.x
- QtCreator 14.0.1 - 0.2.2 plugin version and below - QtCreator 14.0.1 - 0.2.2 plugin version and below

View File

@ -160,12 +160,18 @@ void PluginUpdater::handleDownloadFinished()
} }
QString downloadPath = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) QString downloadPath = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)
+ QDir::separator() + "qodeassisttemp"; + QDir::separator() + "QodeAssist_v" + m_lastUpdateInfo.version;
QDir().mkpath(downloadPath); QDir().mkpath(downloadPath);
QString filePath = downloadPath + "/" + m_lastUpdateInfo.fileName; QString filePath = downloadPath + QDir::separator() + m_lastUpdateInfo.fileName;
QFile file(filePath);
if (QFile::exists(filePath)) {
emit downloadError(tr("Update file already exists: %1").arg(filePath));
reply->deleteLater();
return;
}
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly)) { if (!file.open(QIODevice::WriteOnly)) {
emit downloadError(tr("Could not save the update file")); emit downloadError(tr("Could not save the update file"));
reply->deleteLater(); reply->deleteLater();
@ -175,17 +181,7 @@ void PluginUpdater::handleDownloadFinished()
file.write(reply->readAll()); file.write(reply->readAll());
file.close(); file.close();
if (!Core::executePluginInstallWizard(Utils::FilePath::fromString(filePath))) {
emit downloadError(tr("Failed to install the update"));
} else {
emit downloadFinished(filePath); emit downloadFinished(filePath);
}
auto tempDir = QDir(downloadPath);
if (tempDir.exists()) {
tempDir.removeRecursively();
}
reply->deleteLater(); reply->deleteLater();
} }

View File

@ -19,6 +19,11 @@
#include "UpdateDialog.hpp" #include "UpdateDialog.hpp"
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <QDesktopServices>
namespace QodeAssist { namespace QodeAssist {
UpdateDialog::UpdateDialog(QWidget *parent) UpdateDialog::UpdateDialog(QWidget *parent)
@ -81,7 +86,7 @@ UpdateDialog::UpdateDialog(QWidget *parent)
m_layout->addWidget(m_progress); m_layout->addWidget(m_progress);
auto *buttonLayout = new QHBoxLayout; auto *buttonLayout = new QHBoxLayout;
m_downloadButton = new QPushButton(tr("Download and Install"), this); m_downloadButton = new QPushButton(tr("Download"), this);
m_downloadButton->setEnabled(false); m_downloadButton->setEnabled(false);
buttonLayout->addWidget(m_downloadButton); buttonLayout->addWidget(m_downloadButton);
@ -166,11 +171,32 @@ void UpdateDialog::updateProgress(qint64 received, qint64 total)
void UpdateDialog::handleDownloadFinished(const QString &path) void UpdateDialog::handleDownloadFinished(const QString &path)
{ {
m_progress->setVisible(false); m_progress->setVisible(false);
QMessageBox::information(
this, QMessageBox msgBox(this);
tr("Update Successful"), msgBox.setWindowTitle(tr("Update Downloaded"));
tr("Update has been downloaded and installed. " msgBox.setText(tr("The update has been downloaded successfully.\n"
"Please restart Qt Creator to apply changes.")); "Would you like to close Qt Creator now and open the plugin folder?"));
msgBox.setInformativeText(tr("To complete the update:\n\n"
"1. Close Qt Creator completely\n"
"2. Navigate to the plugin folder\n"
"3. Remove the old version of QodeAssist plugin\n"
"4. Install plugin as usual via About plugin menu"));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
msgBox.setIcon(QMessageBox::Information);
if (msgBox.exec() == QMessageBox::Yes) {
const auto pluginSpecs = ExtensionSystem::PluginManager::plugins();
for (const ExtensionSystem::PluginSpec *spec : pluginSpecs) {
if (spec->name() == QLatin1String("QodeAssist")) {
const auto pluginPath = spec->filePath().path();
QFileInfo fileInfo(pluginPath);
QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absolutePath()));
Core::ICore::exit();
break;
}
}
}
accept(); accept();
} }

View File

@ -0,0 +1,48 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "llmcore/PromptTemplate.hpp"
namespace QodeAssist::Templates {
class CodeLlamaQMLFim : public LLMCore::PromptTemplate
{
public:
LLMCore::TemplateType type() const override { return LLMCore::TemplateType::Fim; }
QString name() const override { return "CodeLlama QML FIM"; }
QString promptTemplate() const override { return "<SUF>%1<PRE>%2<MID>"; }
QStringList stopWords() const override
{
return QStringList() << "<SUF>" << "<PRE>" << "</PRE>" << "</SUF>" << "< EOT >" << "\\end"
<< "<MID>" << "</MID>" << "##";
}
void prepareRequest(QJsonObject &request, const LLMCore::ContextData &context) const override
{
QString formattedPrompt = promptTemplate().arg(context.suffix, context.prefix);
request["prompt"] = formattedPrompt;
}
QString description() const override
{
return "The message will contain the following tokens: <SUF>%1<PRE>%2<MID>";
}
};
} // namespace QodeAssist::Templates

View File

@ -25,6 +25,7 @@
#include "templates/ChatML.hpp" #include "templates/ChatML.hpp"
#include "templates/Claude.hpp" #include "templates/Claude.hpp"
#include "templates/CodeLlamaFim.hpp" #include "templates/CodeLlamaFim.hpp"
#include "templates/CodeLlamaQMLFim.hpp"
#include "templates/CustomFimTemplate.hpp" #include "templates/CustomFimTemplate.hpp"
#include "templates/DeepSeekCoderFim.hpp" #include "templates/DeepSeekCoderFim.hpp"
#include "templates/Llama2.hpp" #include "templates/Llama2.hpp"
@ -53,6 +54,7 @@ inline void registerTemplates()
templateManager.registerTemplate<Llama2>(); templateManager.registerTemplate<Llama2>();
templateManager.registerTemplate<Claude>(); templateManager.registerTemplate<Claude>();
templateManager.registerTemplate<OpenAI>(); templateManager.registerTemplate<OpenAI>();
templateManager.registerTemplate<CodeLlamaQMLFim>();
} }
} // namespace QodeAssist::Templates } // namespace QodeAssist::Templates