This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-kde/daemon/session_manager.cpp

342 lines
10 KiB
C++

#include "session_manager.h"
#include "libollie.h"
#include <QDBusInterface>
#include <QDebug>
#include <QMetaObject>
// Global pointer to the singleton — used by C callbacks to route events.
static SessionManager *g_instance = nullptr;
// --- C callback handlers (called from Go goroutines, must be thread-safe) ---
static void onStateChange(const char *session_id, const char *state)
{
if (!g_instance) return;
QString sid = QString::fromUtf8(session_id);
QString st = QString::fromUtf8(state);
QMetaObject::invokeMethod(g_instance, "handleStateChange",
Qt::QueuedConnection,
Q_ARG(QString, sid), Q_ARG(QString, st));
}
static void onChatUpdate(const char *session_id, int64_t offset, const char *text, int len)
{
if (!g_instance) return;
QString sid = QString::fromUtf8(session_id);
QString txt = QString::fromUtf8(text, len);
qlonglong off = static_cast<qlonglong>(offset);
QMetaObject::invokeMethod(g_instance, [sid, off, txt]() {
emit g_instance->ChatUpdated(sid, off, txt);
}, Qt::QueuedConnection);
}
// --- SessionManager implementation ---
SessionManager::SessionManager(QObject *parent)
: QObject(parent)
{
g_instance = this;
ollie_init(nullptr);
installCallbacks();
qDebug() << "SessionManager: initialized ollie core";
}
SessionManager::~SessionManager()
{
ollie_shutdown();
g_instance = nullptr;
qDebug() << "SessionManager: shut down ollie core";
}
void SessionManager::installCallbacks()
{
ollie_on_state_change(onStateChange);
ollie_on_chat_update(onChatUpdate);
}
// --- Session lifecycle ---
QString SessionManager::CreateSession(const QString &cwd, const QString &backend,
const QString &model, const QString &agent)
{
QByteArray cwdUtf8 = cwd.toUtf8();
QByteArray backendUtf8 = backend.toUtf8();
QByteArray modelUtf8 = model.toUtf8();
QByteArray agentUtf8 = agent.toUtf8();
char *outID = nullptr;
int rc = ollie_create_session(
const_cast<char*>(cwdUtf8.constData()),
const_cast<char*>(backendUtf8.constData()),
const_cast<char*>(modelUtf8.constData()),
const_cast<char*>(agentUtf8.constData()),
&outID);
if (rc != 0 || !outID) {
qWarning() << "CreateSession failed, rc=" << rc;
return QString();
}
QString sessionID = QString::fromUtf8(outID);
ollie_free(outID);
emit SessionCreated(sessionID);
return sessionID;
}
QStringList SessionManager::ListSessions()
{
char *buf = nullptr;
ollie_list_sessions(&buf);
QStringList result;
if (buf) {
QString raw = QString::fromUtf8(buf);
ollie_free(buf);
result = raw.split('\n', Qt::SkipEmptyParts);
}
return result;
}
bool SessionManager::KillSession(const QString &session_id)
{
QByteArray idUtf8 = session_id.toUtf8();
int rc = ollie_kill_session(const_cast<char*>(idUtf8.constData()));
if (rc == 0) {
m_sessionStates.remove(session_id);
emit SessionKilled(session_id);
return true;
}
return false;
}
bool SessionManager::RenameSession(const QString &session_id, const QString &new_name)
{
QByteArray idUtf8 = session_id.toUtf8();
QByteArray nameUtf8 = new_name.toUtf8();
int rc = ollie_rename_session(
const_cast<char*>(idUtf8.constData()),
const_cast<char*>(nameUtf8.constData()));
return rc == 0;
}
// --- Interaction ---
bool SessionManager::Submit(const QString &session_id, const QString &prompt)
{
QByteArray idUtf8 = session_id.toUtf8();
QByteArray promptUtf8 = prompt.toUtf8();
int rc = ollie_submit(
const_cast<char*>(idUtf8.constData()),
const_cast<char*>(promptUtf8.constData()));
return rc == 0;
}
bool SessionManager::Interrupt(const QString &session_id)
{
QByteArray idUtf8 = session_id.toUtf8();
int rc = ollie_interrupt(const_cast<char*>(idUtf8.constData()));
return rc == 0;
}
// --- State queries ---
QString SessionManager::GetState(const QString &session_id)
{
QByteArray idUtf8 = session_id.toUtf8();
char *out = nullptr;
int rc = ollie_get_state(const_cast<char*>(idUtf8.constData()), &out);
if (rc != 0 || !out) return QString();
QString state = QString::fromUtf8(out);
ollie_free(out);
return state;
}
QString SessionManager::GetChat(const QString &session_id, qlonglong offset, qlonglong &new_offset)
{
QByteArray idUtf8 = session_id.toUtf8();
char *out = nullptr;
int64_t newOff = 0;
int rc = ollie_get_chat(
const_cast<char*>(idUtf8.constData()),
static_cast<int64_t>(offset), &out, &newOff);
if (rc != 0 || !out) {
new_offset = offset;
return QString();
}
QString text = QString::fromUtf8(out);
ollie_free(out);
new_offset = static_cast<qlonglong>(newOff);
return text;
}
QString SessionManager::GetUsage(const QString &session_id)
{
QByteArray idUtf8 = session_id.toUtf8();
char *out = nullptr;
int rc = ollie_get_usage(const_cast<char*>(idUtf8.constData()), &out);
if (rc != 0 || !out) return QString();
QString usage = QString::fromUtf8(out);
ollie_free(out);
return usage;
}
QString SessionManager::GetCost(const QString &session_id)
{
QByteArray idUtf8 = session_id.toUtf8();
char *out = nullptr;
int rc = ollie_get_cost(const_cast<char*>(idUtf8.constData()), &out);
if (rc != 0 || !out) return QString();
QString cost = QString::fromUtf8(out);
ollie_free(out);
return cost;
}
// --- Config ---
QString SessionManager::GetConfig(const QString &session_id)
{
QByteArray idUtf8 = session_id.toUtf8();
char *out = nullptr;
int rc = ollie_get_config(const_cast<char*>(idUtf8.constData()), &out);
if (rc != 0 || !out) return QString();
QString config = QString::fromUtf8(out);
ollie_free(out);
return config;
}
bool SessionManager::SetConfig(const QString &session_id, const QString &key, const QString &value)
{
QByteArray idUtf8 = session_id.toUtf8();
QByteArray keyUtf8 = key.toUtf8();
QByteArray valueUtf8 = value.toUtf8();
int rc = ollie_set_config(
const_cast<char*>(idUtf8.constData()),
const_cast<char*>(keyUtf8.constData()),
const_cast<char*>(valueUtf8.constData()));
return rc == 0;
}
// --- Context ---
QString SessionManager::GetContext(const QString &session_id)
{
QByteArray idUtf8 = session_id.toUtf8();
char *out = nullptr;
int rc = ollie_get_context(const_cast<char*>(idUtf8.constData()), &out);
if (rc != 0 || !out) return QString();
QString context = QString::fromUtf8(out);
ollie_free(out);
return context;
}
// --- Backends/models/agents ---
QStringList SessionManager::ListBackends()
{
char *out = nullptr;
ollie_list_backends(&out);
if (!out) return {};
QString raw = QString::fromUtf8(out);
ollie_free(out);
return raw.split('\n', Qt::SkipEmptyParts);
}
QStringList SessionManager::ListModels(const QString &session_id)
{
QByteArray idUtf8 = session_id.toUtf8();
char *out = nullptr;
int rc = ollie_list_models(const_cast<char*>(idUtf8.constData()), &out);
if (rc != 0 || !out) return {};
QString raw = QString::fromUtf8(out);
ollie_free(out);
return raw.split('\n', Qt::SkipEmptyParts);
}
QStringList SessionManager::ListAgents()
{
char *out = nullptr;
ollie_list_agents(&out);
if (!out) return {};
QString raw = QString::fromUtf8(out);
ollie_free(out);
return raw.split('\n', Qt::SkipEmptyParts);
}
// --- Peers ---
bool SessionManager::PeerAdd(const QString &session_id, const QString &peer_id)
{
QByteArray idUtf8 = session_id.toUtf8();
QByteArray peerUtf8 = peer_id.toUtf8();
int rc = ollie_peer_add(
const_cast<char*>(idUtf8.constData()),
const_cast<char*>(peerUtf8.constData()));
return rc == 0;
}
bool SessionManager::PeerRemove(const QString &session_id, const QString &peer_id)
{
QByteArray idUtf8 = session_id.toUtf8();
QByteArray peerUtf8 = peer_id.toUtf8();
int rc = ollie_peer_remove(
const_cast<char*>(idUtf8.constData()),
const_cast<char*>(peerUtf8.constData()));
return rc == 0;
}
QStringList SessionManager::PeerList(const QString &session_id)
{
QByteArray idUtf8 = session_id.toUtf8();
char *out = nullptr;
ollie_peer_list(const_cast<char*>(idUtf8.constData()), &out);
if (!out) return {};
QString raw = QString::fromUtf8(out);
ollie_free(out);
return raw.split('\n', Qt::SkipEmptyParts);
}
bool SessionManager::PeerSubmit(const QString &session_id, const QString &peer_id, const QString &prompt)
{
QByteArray idUtf8 = session_id.toUtf8();
QByteArray peerUtf8 = peer_id.toUtf8();
QByteArray promptUtf8 = prompt.toUtf8();
int rc = ollie_peer_submit(
const_cast<char*>(idUtf8.constData()),
const_cast<char*>(peerUtf8.constData()),
const_cast<char*>(promptUtf8.constData()));
return rc == 0;
}
// --- Notifications ---
void SessionManager::handleStateChange(const QString &session_id, const QString &new_state)
{
QString prev = m_sessionStates.value(session_id, "idle");
m_sessionStates[session_id] = new_state;
if (new_state == "idle" && prev != "idle") {
sendNotification("Ollie", "Session " + session_id.left(12) + " finished");
}
emit StateChanged(session_id, new_state);
}
void SessionManager::sendNotification(const QString &title, const QString &body)
{
QDBusInterface notifyIface(
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications",
QDBusConnection::sessionBus());
notifyIface.call("Notify",
"ollie-kde", // app_name
(uint)0, // replaces_id
"system-run", // app_icon
title, // summary
body, // body
QStringList(), // actions
QVariantMap(), // hints
(int)5000); // timeout ms
}