mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-02-12 10:10:44 -05:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e836b86569 | |||
| 288fefebe5 | |||
| 528badbf1e | |||
| b789e42602 | |||
| 4bf955462f | |||
| 5b99e68e53 | |||
| 0f1b277ef7 | |||
| 56995c9edf | |||
| 45aba6b6be | |||
| 1dfb3feb96 | |||
| 2c49d45297 | |||
| 31145f191b | |||
| 9096adde6f |
@ -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
|
||||||
|
|||||||
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
81
README.md
81
README.md
@ -2,7 +2,7 @@
|
|||||||
[](https://github.com/Palm1r/QodeAssist/actions/workflows/build_cmake.yml)
|
[](https://github.com/Palm1r/QodeAssist/actions/workflows/build_cmake.yml)
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
 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 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
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
48
templates/CodeLlamaQMLFim.hpp
Normal file
48
templates/CodeLlamaQMLFim.hpp
Normal 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
|
||||||
@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user