mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-07-24 12:11:04 -04:00
* refactor: Migrate tests to Qt Creator plugin framework and update llmqore transports * refactor: Move conversation history into IDE-free session library * refactor: Extract turn context assembly behind injected ports * build: Add RunQodeAssistTests target for the plugin test suite * refactor: Route the chat through a Session and ChatBackend seam
108 lines
3.3 KiB
C++
108 lines
3.3 KiB
C++
// Copyright (C) 2026 Petr Mironychev
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
|
|
|
#include "ChatHistoryBridge.hpp"
|
|
|
|
#include "ChatModel.hpp"
|
|
#include "session/Session.hpp"
|
|
|
|
namespace QodeAssist::Chat {
|
|
|
|
namespace {
|
|
|
|
ChatModel::ChatRole toChatRole(Session::RowKind kind)
|
|
{
|
|
switch (kind) {
|
|
case Session::RowKind::System:
|
|
return ChatModel::ChatRole::System;
|
|
case Session::RowKind::User:
|
|
return ChatModel::ChatRole::User;
|
|
case Session::RowKind::Assistant:
|
|
return ChatModel::ChatRole::Assistant;
|
|
case Session::RowKind::Tool:
|
|
return ChatModel::ChatRole::Tool;
|
|
case Session::RowKind::FileEdit:
|
|
return ChatModel::ChatRole::FileEdit;
|
|
case Session::RowKind::Thinking:
|
|
return ChatModel::ChatRole::Thinking;
|
|
}
|
|
return ChatModel::ChatRole::Assistant;
|
|
}
|
|
|
|
ChatModel::Message toChatMessage(const Session::MessageRow &row)
|
|
{
|
|
ChatModel::Message message;
|
|
message.role = toChatRole(row.kind);
|
|
message.content = row.content;
|
|
message.id = row.id;
|
|
message.isRedacted = row.redacted;
|
|
message.signature = row.signature;
|
|
message.toolName = row.toolName;
|
|
message.toolArguments = row.toolArguments;
|
|
message.toolResult = row.toolResult;
|
|
|
|
for (const Session::AttachmentBlock &attachment : row.attachments)
|
|
message.attachments.append(Context::ContentFile{attachment.fileName, attachment.storedPath});
|
|
|
|
for (const Session::ImageBlock &image : row.images)
|
|
message.images.append(
|
|
ChatModel::ImageAttachment{image.fileName, image.storedPath, image.mediaType});
|
|
|
|
message.promptTokens = row.usage.promptTokens;
|
|
message.completionTokens = row.usage.completionTokens;
|
|
message.cachedPromptTokens = row.usage.cachedPromptTokens;
|
|
message.reasoningTokens = row.usage.reasoningTokens;
|
|
|
|
return message;
|
|
}
|
|
|
|
QVector<ChatModel::Message> toChatMessages(const QList<Session::MessageRow> &rows)
|
|
{
|
|
QVector<ChatModel::Message> messages;
|
|
messages.reserve(rows.size());
|
|
for (const Session::MessageRow &row : rows)
|
|
messages.append(toChatMessage(row));
|
|
return messages;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
ChatHistoryBridge::ChatHistoryBridge(Session::Session *session, ChatModel *model, QObject *parent)
|
|
: QObject(parent)
|
|
, m_model(model)
|
|
{
|
|
connect(session, &Session::Session::rowsReset, this, &ChatHistoryBridge::onRowsReset);
|
|
connect(session, &Session::Session::rowsAppended, this, &ChatHistoryBridge::onRowsAppended);
|
|
connect(session, &Session::Session::rowUpdated, this, &ChatHistoryBridge::onRowUpdated);
|
|
connect(session, &Session::Session::rowsRemoved, this, &ChatHistoryBridge::onRowsRemoved);
|
|
|
|
onRowsReset(session->rows());
|
|
}
|
|
|
|
void ChatHistoryBridge::onRowsReset(const QList<Session::MessageRow> &rows)
|
|
{
|
|
if (m_model)
|
|
m_model->resetMessages(toChatMessages(rows));
|
|
}
|
|
|
|
void ChatHistoryBridge::onRowsAppended(const QList<Session::MessageRow> &rows)
|
|
{
|
|
if (m_model)
|
|
m_model->appendMessages(toChatMessages(rows));
|
|
}
|
|
|
|
void ChatHistoryBridge::onRowUpdated(int index, const Session::MessageRow &row)
|
|
{
|
|
if (m_model)
|
|
m_model->updateMessage(index, toChatMessage(row));
|
|
}
|
|
|
|
void ChatHistoryBridge::onRowsRemoved(int first, int count)
|
|
{
|
|
if (m_model)
|
|
m_model->removeMessages(first, count);
|
|
}
|
|
|
|
} // namespace QodeAssist::Chat
|