Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ MODULES_DIR ?= ./modules

.PHONY: all build test clean setup-nix-merged \
build-module build-ui-plugin install install-module \
build-kv-module install-kv-module install-all
build-kv-module install-kv-module \
install-delivery-module install-all

# ── Build ────────────────────────────────────────────────────────────────────

Expand Down Expand Up @@ -124,8 +125,20 @@ install-kv-module: build-kv-module
echo '{"name":"kv_module","version":"0.1.0","type":"core","category":"storage","dependencies":[],"main":{"linux-x86_64":"kv_module_plugin.so","linux-aarch64":"kv_module_plugin.so","darwin-arm64":"kv_module_plugin.so"}}' > ~/.local/share/Logos/LogosAppNix/modules/kv_module/manifest.json
@echo "kv_module installed to ~/.local/share/Logos/LogosAppNix/modules/kv_module/"

## Install everything: scala_ui + scala_module + kv_module
install-all: install install-module install-kv-module
# ── delivery_module (P2P messaging backend) ───────────────────────────────────

LGPM ?= /tmp/package-manager/bin/lgpm
DELIVERY_RELEASE ?= build-20260307-a751c91-69

## Install delivery_module via lgpm
install-delivery-module:
$(LGPM) --release $(DELIVERY_RELEASE) \
--modules-dir ~/.local/share/Logos/LogosAppNix/modules \
install logos-delivery-module
@echo "delivery_module installed to ~/.local/share/Logos/LogosAppNix/modules/delivery_module/"

## Install everything: scala_ui + scala_module + kv_module + delivery_module
install-all: install install-module install-kv-module install-delivery-module
@echo ""
@echo "All installed! Run logos-app:"
@echo " cd ~/logos-workspace && nix run .#logos-app-poc"
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"darwin-arm64": "scala_plugin.so",
"darwin-x86_64": "scala_plugin.so"
},
"dependencies": ["kv_module", "messaging_module", "accounts_module"]
"dependencies": ["kv_module", "delivery_module", "accounts_module"]
}
2 changes: 1 addition & 1 deletion metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
"darwin-arm64": "scala_module_plugin.dylib",
"windows-x86_64": "scala_module_plugin.dll"
},
"dependencies": ["kv_module"],
"dependencies": ["kv_module", "delivery_module"],
"capabilities": []
}
2 changes: 1 addition & 1 deletion module.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ qt_version: "6"

dependencies:
- kv_module
- messaging_module
- delivery_module
- accounts_module

qml_files:
Expand Down
10 changes: 5 additions & 5 deletions src/calendar_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ void LogosCalendar::initLogos(LogosAPI *logosAPIInstance) {

// Skip optional module lookups in e2e/CI mode (they timeout ~20s each)
if (qgetenv("SCALA_E2E_MINIMAL").isEmpty()) {
// Get messaging module client for sync
m_messagingClient = m_logosAPI->getClient("messaging_module");
if (!m_messagingClient) {
qWarning() << "LogosCalendar: failed to get messaging_module client"
// Get delivery module client for P2P sync
m_deliveryClient = m_logosAPI->getClient("delivery_module");
if (!m_deliveryClient) {
qWarning() << "LogosCalendar: failed to get delivery_module client"
<< "(sync will use stub)";
} else {
m_sync->setMessagingClient(m_messagingClient);
m_sync->setDeliveryClient(m_deliveryClient);
}

// Get identity from accounts module (optional — may not be loaded)
Expand Down
2 changes: 1 addition & 1 deletion src/calendar_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,6 @@ class LogosCalendar final : public QObject, public ILogosCalendar {
#ifdef LOGOS_CORE_AVAILABLE
LogosAPI *m_logosAPI = nullptr;
LogosAPIClient *m_kvClient = nullptr;
LogosAPIClient *m_messagingClient = nullptr;
LogosAPIClient *m_deliveryClient = nullptr;
#endif
};
88 changes: 72 additions & 16 deletions src/calendar_sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,64 @@ bool CalendarSync::isSyncing(const QString &calendarId) const {
}

#ifdef LOGOS_CORE_AVAILABLE
void CalendarSync::setMessagingClient(LogosAPIClient *client) {
m_messagingClient = client;
void CalendarSync::setDeliveryClient(LogosAPIClient *client) {
m_deliveryClient = client;

if (m_deliveryClient) {
ensureDeliveryNode();

// Listen for messageReceived events from delivery_module
QObject *replica = m_deliveryClient->requestObject("delivery_module");
if (replica) {
m_deliveryClient->onEvent(
replica, this, QStringLiteral("messageReceived"),
[this](const QString &eventName, const QVariantList &args) {
Q_UNUSED(eventName)
if (args.size() >= 4) {
onDeliveryMessageReceived(
args.at(0).toString(), // hash
args.at(1).toString(), // topic
args.at(2).toString(), // payload_base64
args.at(3).toLongLong() // timestamp
);
}
});
qInfo() << "CalendarSync: registered messageReceived event handler";
} else {
qWarning() << "CalendarSync: failed to get delivery_module replica for events";
}
}
}

void CalendarSync::ensureDeliveryNode() {
if (m_deliveryNodeStarted || !m_deliveryClient)
return;

// Create and start the delivery node with logos.dev preset
m_deliveryClient->invokeRemoteMethod(
"delivery_module", "createNode",
QStringLiteral("{\"logLevel\":\"INFO\",\"mode\":\"Core\",\"preset\":\"logos.dev\"}"));
m_deliveryClient->invokeRemoteMethod("delivery_module", "start");
m_deliveryNodeStarted = true;

qInfo() << "CalendarSync: delivery node created and started (logos.dev)";
}

void CalendarSync::onDeliveryMessageReceived(const QString &hash, const QString &topic,
const QString &payloadBase64, qint64 timestamp) {
Q_UNUSED(hash)
Q_UNUSED(timestamp)

// Find which calendar this topic belongs to
for (auto it = m_activeTopics.constBegin(); it != m_activeTopics.constEnd(); ++it) {
if (topicForCalendar(it.key()) == topic) {
QByteArray payload = QByteArray::fromBase64(payloadBase64.toUtf8());
SyncMessage msg = SyncMessage::fromBytes(payload);
emit messageReceived(it.key(), msg);
return;
}
}
qDebug() << "CalendarSync: received message for unknown topic" << topic;
}
#endif

Expand All @@ -104,16 +160,17 @@ void CalendarSync::startSync(const QString &calendarId, const QString &encryptio
m_activeTopics.insert(calendarId, encryptionKey);

#ifdef LOGOS_CORE_AVAILABLE
if (m_messagingClient) {
// Subscribe to the topic via the messaging module
m_messagingClient->invokeRemoteMethod(
"messaging_module", "subscribe", topic, encryptionKey);
if (m_deliveryClient) {
ensureDeliveryNode();
// Subscribe to the content topic via delivery_module
m_deliveryClient->invokeRemoteMethod(
"delivery_module", "subscribe", topic);

qInfo() << "CalendarSync: subscribed to topic" << topic;
emit syncStarted(calendarId);
return;
}
qWarning() << "CalendarSync: no messaging client, falling back to stub";
qWarning() << "CalendarSync: no delivery client, falling back to stub";
#endif

// Stub: emit syncStarted immediately for testing without Logos Core
Expand All @@ -132,10 +189,9 @@ void CalendarSync::stopSync(const QString &calendarId) {
m_activeTopics.remove(calendarId);

#ifdef LOGOS_CORE_AVAILABLE
if (m_messagingClient) {
m_messagingClient->invokeRemoteMethod(
"messaging_module", "unsubscribe", topic);

if (m_deliveryClient) {
// delivery_module does not have an explicit unsubscribe;
// topic is simply no longer tracked locally
qInfo() << "CalendarSync: unsubscribed from topic" << topic;
emit syncStopped(calendarId);
return;
Expand All @@ -157,12 +213,12 @@ void CalendarSync::sendMessage(const QString &calendarId, const SyncMessage &msg
const QByteArray data = msg.toBytes();

#ifdef LOGOS_CORE_AVAILABLE
if (m_messagingClient) {
const QString &encryptionKey = m_activeTopics.value(calendarId);
m_messagingClient->invokeRemoteMethod(
"messaging_module", "publish", topic, data, encryptionKey);
if (m_deliveryClient) {
ensureDeliveryNode();
m_deliveryClient->invokeRemoteMethod(
"delivery_module", "send", topic, data);

qDebug() << "CalendarSync: published" << SyncMessage::typeToString(msg.type)
qDebug() << "CalendarSync: sent" << SyncMessage::typeToString(msg.type)
<< "to" << topic << "(" << data.size() << "bytes)";
return;
}
Expand Down
9 changes: 7 additions & 2 deletions src/calendar_sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class CalendarSync : public QObject {
static QString topicForCalendar(const QString &calendarId);

#ifdef LOGOS_CORE_AVAILABLE
void setMessagingClient(LogosAPIClient *client);
void setDeliveryClient(LogosAPIClient *client);
#endif

signals:
Expand All @@ -85,6 +85,11 @@ class CalendarSync : public QObject {
QMap<QString, QString> m_activeTopics;

#ifdef LOGOS_CORE_AVAILABLE
LogosAPIClient *m_messagingClient = nullptr;
LogosAPIClient *m_deliveryClient = nullptr;
bool m_deliveryNodeStarted = false;

void ensureDeliveryNode();
void onDeliveryMessageReceived(const QString &hash, const QString &topic,
const QString &payloadBase64, qint64 timestamp);
#endif
};
Loading