Use the Logos Chat module API from an app#365
Conversation
danisharora099
left a comment
There was a problem hiding this comment.
Really nice tutorial — clear structure and the API details hold up. I cross-checked every event name, argument order, and the init() signature against chat_module.lidl at v0.1.1, and the dependency_overrides block matches what logos-chat-ui actually ships, so no surprises there.
One thing I think blocks merge: the flake.nix in Step 2 is missing the delivery_module runtime input, so if someone follows this start to finish it won't build. Details in the inline comment. A handful of smaller things too, mostly consistency and "how do I know it worked" stuff.
| ```nix | ||
| inputs = { | ||
| logos-module-builder.url = "github:logos-co/logos-module-builder"; | ||
| chat_module.url = "github:logos-co/logos-chat-module/v0.1.1"; |
There was a problem hiding this comment.
(blocker) This snippet is missing a piece and the build won't resolve delivery_module.
metadata.json lists delivery_module as a dependency, and the module builder pulls each dependency's runtime from a matching flake input — but here the only input is chat_module. The dependency_overrides entry only points the builder at delivery's .lidl contract for codegen; it doesn't supply the runtime build. So nix build has nothing to resolve delivery_module against.
logos-chat-ui handles this by pinning delivery separately and passing it in:
logos-delivery-module.url = "github:logos-co/logos-delivery-module/<rev>";
# then: flakeInputs = { delivery_module = logos-delivery-module; } // inputs;Could we add that to the snippet? One heads-up while you're in there: logos-chat-ui deliberately pins a commit past v0.1.2 to pick up the zerokit/RLN build fix (the v0.1.2 tag trips over a crates.io 403 during the Rust build). Worth a warning so people don't pin the tag and get stuck.
|
|
||
| ## Step 4: Drive the chat lifecycle | ||
|
|
||
| Status-bearing methods return their result **synchronously** as a `LogosResult`: `res.success` tells you whether the call succeeded, `res.getError<QString>()` carries the failure reason, and `res.getValue<QString>()` carries the returned value (for example, the intro bundle). Ongoing activity — incoming messages, new conversations, delivery-state changes — arrives asynchronously through the push events you subscribed to in Step 3. |
There was a problem hiding this comment.
Small thing that'll bite copy-pasters: here we use res.getError<QString>() / res.getValue<QString>(), but the Delivery API doc uses r.getError() / r.getString() for the same LogosResult type. Someone reading both will hit a compile error on one of them. Do you know which form the SDK actually exposes? Would be good to line the two docs up.
| ``` | ||
|
|
||
| - The initiator calls `create_conversation` with the peer's intro bundle and a plain-text opening message. | ||
| - The recipient does not call anything; a `conversation_created` push event (`is_outgoing == false`) arrives automatically, followed by a `message_received` event. |
There was a problem hiding this comment.
The whole point here is two instances talking to each other, but the tutorial stops at "send a message" without showing the reader how to run two instances, swap intro bundles, and see a message land. logos-chat-ui already has this (nix run .#exchange / two-instance-exchange.md). Even a short "run a second instance, paste its bundle, you should see a message_received event" section — or just linking that flow as the verification step — would close the loop.
| nix build | ||
| ``` | ||
|
|
||
| 1. Preview the module using `logos-standalone-app` (for `ui_qml` modules): |
There was a problem hiding this comment.
Step 5 says to preview the module in logos-standalone-app, but since we scaffold the backend template, delete the example UI, and only wire up the C++ chat logic, there's nothing visible to actually preview. Might be worth a line in "What to expect" saying this is the backend pattern and pointing at logos-chat-ui for a full wired UI, so nobody's surprised when nix run doesn't show a chat window.
| title: Build a Logos module that uses the Chat module API | ||
| doc_type: procedure | ||
| product: messaging | ||
| topics: [] |
There was a problem hiding this comment.
authors and topics are both empty here — the Delivery doc fills them in (authors: igor-sirotin, kashepavadan, topics: delivery). Mind adding yourself as author and a topic like chat?
|
|
||
| ```cpp | ||
| // content is plain text — no encoding required. | ||
| const LogosResult res = m_logos->chat_module.create_conversation(peerBundle, "Hello!"); |
There was a problem hiding this comment.
Minor: the contract also has set_conversation_nickname and delete_conversation, and they're what fire the conversation_updated / conversation_deleted events the doc already covers. A one-liner pointing at them would help anyone who wants to rename or delete a conversation.
| |---|---|---| | ||
| | `instance_path` | string | Directory for this instance's persistent state (`identity.db`, `history.json`). Use a distinct directory per instance to run several side by side. | | ||
| | `delivery_preset` | string | Network preset for the delivery node. Use `logos.test` to reach the Logos test network. Must match across all participants. | | ||
| | `tcp_port` | int | Logos Delivery (Waku) TCP port. `0` picks a random port. | |
There was a problem hiding this comment.
(nit, totally optional) the tcp_port note calls it the "Logos Delivery (Waku) TCP port." If the docs generally keep Waku under the hood, might want to drop it; if not, ignore me.
|
Pardon, I'm still working on the last commit that I pushed yesterday |
v0.1.1 reimplements chat_module as a Rust SDK module with the typed chat_module.lidl contract over Logos Core IPC, replacing the v0.1.0 C++ plugin. Align the tutorial with how logos-chat-ui consumes it: - pin chat_module to v0.1.1; declare delivery_module + dependency_overrides - synchronous LogosResult return model instead of async *Result events - new init(instance_path, delivery_preset, tcp_port) signature (no JSON config) - snake_case methods (create_intro_bundle, create_conversation, send_message, shutdown) and typed push events (message_received, conversation_created, ...) - plain-text content (drop hex encoding); persistent identity/history Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
01df00f to
c36c410
Compare
|
Take a look now please @danisharora099 |
weboko
left a comment
There was a problem hiding this comment.
Re-review after the v0.1.2 rewrite — dogfooded on Linux x86_64.
I re-ran this end to end against the pinned upstream sources and a real Nix scaffold. Nice work on the rewrite — the earlier blocker is properly closed:
- ✅
delivery_moduleruntime wiring (previous blocker): Step 2 now pinslogos-delivery-moduletov0.1.3and maps it in viaflakeInputs = { delivery_module = logos-delivery-module; } // inputs;. I diffed this againstlogos-chat-ui'sflake.nix@v0.1.2and it's the same wiring. I scaffolded a fresh module fromtutorial-v3#ui-qml-backend, applied Step 2 verbatim, andnix flake metadatalocks all inputs cleanly (chat_module@v0.1.2,logos-delivery-module@v0.1.3, full builder tree resolve). Thev0.1.3/RLN-403 rationale in the hint matches delivery-module #49. - ✅ Two-instance verification (Step 6) added — closes the "stops at send a message" gap.
- ✅ API surface verified: every method, the
init(instance_path, delivery_preset, tcp_port)signature, and all six events (names + argument order) matchchat_module.lidl@v0.1.2exactly. - ℹ️ On the
getError<QString>()vsgetString()question from last round: this doc's form (res.getError<QString>()/res.getValue<QString>()) is the correct one — it's exactly what the shippingChatBackend.cpp@v0.1.2uses. The divergence is on the Delivery doc side (r.getError()/r.getString()), so nothing to change here — worth aligning that doc in a follow-up instead.
Three inline items left below: one snippet that won't compile as written (worth fixing), plus the two frontmatter/preview nits from last round that are still open. Not blocking beyond the compile-bug fix.
| nix build | ||
| ``` | ||
|
|
||
| 1. Preview the module using `logos-standalone-app` (for `ui_qml` modules): |
There was a problem hiding this comment.
Still open from last round: since Step 1 deletes the example UI and this guide only wires the C++ chat backend, nix run launches the standalone host with no chat window — which surprises readers who expect a visible chat. A one-line heads-up here (or in What to expect) closes that gap:
| 1. Preview the module using `logos-standalone-app` (for `ui_qml` modules): | |
| 1. Preview the host with `logos-standalone-app` (for `ui_qml` modules). Because Step 1 removed the example UI and this guide only wires up the C++ chat backend, `nix run` starts the host but shows no chat window — that's expected. For a fully wired reference UI, see [`logos-chat-ui`](https://github.com/logos-co/logos-chat-ui/tree/v0.1.2): |
weboko
left a comment
There was a problem hiding this comment.
Follow-up: I actually ran nix build (Step 5) end to end, and following the doc literally fails.
I installed Nix, scaffolded from tutorial-v3#ui-qml-backend, ran the Step 1.4 rm, applied Step 2, and ran nix build. It fails at CMake configure:
CMake Error at .../cmake/LogosModule.cmake:602 (file):
file failed to open for reading (No such file or directory):
.../src/ui_example.rep
Root cause: Step 1.4 deletes the four ui_example.* files, but the scaffold's CMakeLists.txt still hardcodes them, and metadata.json still names the module ui_example:
logos_module(
NAME ${MODULE_NAME} # metadata.json "name" = "ui_example"
REP_FILE src/ui_example.rep # <- deleted in Step 1.4
SOURCES
src/ui_example_interface.h # <- deleted
src/ui_example_plugin.h # <- deleted
src/ui_example_plugin.cpp # <- deleted
)So deleting the sources without re-pointing CMakeLists.txt + metadata.json (and supplying your own plugin sources) guarantees a hard build break in Step 5 — the reader never reaches nix build successfully. The suggestion on line 63 makes the missing steps explicit; happy to iterate on the exact wording. (Everything else — Step 1 scaffold, Step 2 flake wiring, input lock — worked; this is the one gap that stops the happy path.)
| git init && git add -A | ||
| ``` | ||
|
|
||
| 1. Remove the template's example sources. The scaffolded template includes `ui_example` files with mismatched class names and IIDs; leaving them causes build errors or plugin-load failures at runtime: |
There was a problem hiding this comment.
This step is where the happy path breaks. Deleting these files while CMakeLists.txt (REP_FILE / SOURCES) and metadata.json (name, main) still reference ui_example makes nix build fail at configure. The step needs to also cover re-pointing those two files and adding your own plugin sources:
| 1. Remove the template's example sources. The scaffolded template includes `ui_example` files with mismatched class names and IIDs; leaving them causes build errors or plugin-load failures at runtime: | |
| 1. Replace the template's example sources with your own. The scaffold's `CMakeLists.txt` (`REP_FILE` / `SOURCES`) and `metadata.json` (`name`, `main`) both reference `ui_example`, so simply deleting these files makes `nix build` (Step 5) fail at CMake configure with `file failed to open for reading: src/ui_example.rep`. Delete the examples, then create your own `src/<name>.rep`, `src/<name>_interface.h`, and `src/<name>_plugin.{h,cpp}` (Step 3 supplies the plugin body) and update `CMakeLists.txt` and `metadata.json` (`name`, `main`) to point at them: |
There was a problem hiding this comment.
@igor-sirotin Is there an easier way to deal with this issue?
There was a problem hiding this comment.
@weboko thanks for the catch!
@kashepavadan I've addressed this in c49e216, please take a look
Co-authored-by: Sasha <118575614+weboko@users.noreply.github.com>
weboko
left a comment
There was a problem hiding this comment.
I re-dogfooded this tutorial end-to-end on a clean Ubuntu 24.04 box after the latest commit: installed Nix + flakes, scaffolded from tutorial-v3#ui-qml-backend, added the Step 2 dependencies (chat_module v0.1.2 + logos-delivery-module v0.1.3), and ran nix build.
Good news: Step 2's delivery wiring now resolves correctly. nix flake lock pulls delivery_module from the logos-delivery-module v0.1.3 input via flakeInputs, and the earlier "can't resolve delivery_module" blocker is gone. The topics/authors, the intro-bundle snippet, and the new Step 6 from the last round all look addressed too.
One blocker remains — Step 1.4 (inline comment below). It's the same spot @weboko flagged and @kashepavadan asked about; I've reproduced the exact failure and verified a minimal fix.
| 1. Remove the template's example sources. The scaffolded template includes `ui_example` files with mismatched class names and IIDs; leaving them causes build errors or plugin-load failures at runtime: | ||
|
|
||
| ```bash | ||
| rm -f src/ui_example.rep src/ui_example_interface.h src/ui_example_plugin.h src/ui_example_plugin.cpp | ||
| ``` |
There was a problem hiding this comment.
(blocker, reproduced) Following this step literally makes nix build fail at the CMake configure step.
tutorial-v3#ui-qml-backend scaffolds a coherent, buildable plugin — src/ui_example.rep + src/ui_example_plugin.* — and both CMakeLists.txt (REP_FILE/SOURCES, line 21) and metadata.json (main) reference it. The rm here deletes those files but leaves the references, so nix build dies at configure:
CMake Error at .../cmake/LogosModule.cmake:602 (file):
file failed to open for reading (No such file or directory):
.../src/ui_example.rep
Call Stack (most recent call first):
.../LogosModule.cmake:577 (_logos_module_add_replica_factory)
CMakeLists.txt:21 (logos_module)
-- Configuring incomplete, errors occurred!
I verified the easiest fix is to keep the scaffolded plugin and wire the chat logic into its existing initLogos() in Step 3. With the files kept + the Step 2 dependencies added:
nix build→ producesui_example_plugin.sonix build .#lgx(Step 5) → produces the.lgx- adding the Step 3/4
LogosModules/chat_modulecalls intoinitLogos()compiles and links cleanly against the generatedlogos_sdk.h([13/16] ui_example_plugin.cpp→[16/16] Linking ui_example_plugin.so, exit 0).
Also, the current rationale ("mismatched class names and IIDs; leaving them causes build errors or plugin-load failures") doesn't hold for tutorial-v3 — the example plugin's class names and IID (org.logos.UiExampleInterface) are internally consistent and build fine. It's the deletion, not the example files, that breaks the build.
Suggested replacement for this step:
| 1. Remove the template's example sources. The scaffolded template includes `ui_example` files with mismatched class names and IIDs; leaving them causes build errors or plugin-load failures at runtime: | |
| ```bash | |
| rm -f src/ui_example.rep src/ui_example_interface.h src/ui_example_plugin.h src/ui_example_plugin.cpp | |
| ``` | |
| 1. **Keep the scaffolded plugin — don't delete it.** In `tutorial-v3#ui-qml-backend` the generated `src/ui_example.rep` and `src/ui_example_plugin.*` are a coherent, buildable plugin that `CMakeLists.txt` (`REP_FILE`/`SOURCES`) and `metadata.json` (`main`) already reference; you'll wire the chat logic into its `initLogos()` in Step 3. Deleting these files without also re-pointing `CMakeLists.txt` and `metadata.json` breaks `nix build` at the CMake configure step (`file failed to open for reading … src/ui_example.rep`). To give the module its own name, **rename** the four `src/ui_example*` files and update the matching `REP_FILE`/`SOURCES` in `CMakeLists.txt` and `main` in `metadata.json` to match — don't remove them outright. |
Step 1.4 told readers to delete the scaffold's ui_example sources, but
CMakeLists.txt and metadata.json still reference them, so `nix build`
(Step 5) failed at CMake configure. Reframe the step to keep and build on
the example instead of deleting it, and keep the module name consistent:
- Step 1.4: keep the generated files; explain what each is and where chat
code goes, with a table for readability.
- Step 2: keep metadata name as `ui_example` (was `my_app`, which would
break the `logos.module("ui_example")` binding in Main.qml).
- Step 3: point initLogos() at the real UiExamplePlugin class and preserve
the scaffold's existing `logosAPI = api;` / `setBackend(this);` lines.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
weboko
left a comment
There was a problem hiding this comment.
Dogfooded end-to-end on Linux (headless) — one build-breaking issue found
I followed this tutorial from scratch on a clean Ubuntu 24.04 box: installed Nix (flakes), scaffolded via nix flake init -t github:logos-co/logos-module-builder/tutorial-v3#ui-qml-backend, applied Step 2 (metadata.json + flake.nix with chat_module v0.1.2 / logos-delivery-module v0.1.3), and wrote the Step 3–4 chat code into ui_example_plugin.{h,cpp}.
What works ✅
nix buildsucceeds —ui_example_plugin.solinks with the chat code (initLogospresent), delivery wrapper auto-generated, lidl tests 17/17.nix build .#lgxsucceeds — produceslogos-ui_example-module.lgx.- The documented API surface (methods, event arg orders,
init(instance_path, delivery_preset, tcp_port)) matcheschat_module.lidlatv0.1.2exactly. - The Step 1.4 "keep the generated files / keep the name
ui_example" fix from the latest commit is correct and builds cleanly.
What breaks ❌ (Step 3.1)
Following Step 3.1 literally does not compile. The snippet places #include "logos_sdk.h" in the .cpp, but instructs adding the member LogosModules* m_logos to the header (src/ui_example_plugin.h). The header then has no visibility of LogosModules, so the build fails:
src/ui_example_plugin.h:36:5: error: 'LogosModules' does not name a type; did you mean 'LogosMode'?
36 | LogosModules* m_logos = nullptr;
src/ui_example_plugin.cpp:19:5: error: 'm_logos' was not declared in this scope
The fix is to put the include in the header (where the member is declared); the .cpp picks it up transitively via #include "ui_example_plugin.h". With the include in the header, nix build passes (that's the variant I built above). Suggested change inline.
Note: Step 6's live two-instance exchange over logos.test requires a GUI (logos-standalone-app) + network peers, so I validated the build/package path (Steps 1–5) rather than the runtime round-trip; nix run is still building the standalone app in this headless env.
| #include "logos_sdk.h" // generated umbrella — exposes LogosModules | ||
|
|
||
| // Add a member to your plugin class (src/ui_example_plugin.h): | ||
| // LogosModules* m_logos = nullptr; |
There was a problem hiding this comment.
Build-breaking as written. The #include belongs in the header, not the .cpp — the LogosModules* m_logos member is declared in src/ui_example_plugin.h, so the type must be visible there. As written the header fails with 'LogosModules' does not name a type. Verified: moving the include into the header makes nix build pass.
| #include "logos_sdk.h" // generated umbrella — exposes LogosModules | |
| // Add a member to your plugin class (src/ui_example_plugin.h): | |
| // LogosModules* m_logos = nullptr; | |
| // Put this include in your plugin **header** (`src/ui_example_plugin.h`), | |
| // next to the `m_logos` member below — `LogosModules` must be a complete | |
| // type where the member is declared. The `.cpp` picks it up transitively | |
| // via its `#include "ui_example_plugin.h"`. Including it only in the `.cpp` | |
| // leaves the header failing with `error: 'LogosModules' does not name a type`. | |
| #include "logos_sdk.h" // generated umbrella — exposes LogosModules | |
| // Add a member to your plugin class (src/ui_example_plugin.h): | |
| // LogosModules* m_logos = nullptr; |
The snippet put `#include "logos_sdk.h"` in the .cpp while declaring the `LogosModules* m_logos` member in the header, so the header saw no declaration of `LogosModules` and failed to compile (`'LogosModules' does not name a type`). Split the snippet into a header block (include + member) and a cpp block (construction), so the type is visible where the member is declared. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fdff1a3 to
d17315b
Compare
weboko
left a comment
There was a problem hiding this comment.
Dogfooded this guide end-to-end on the current revision (head e075c13) — the build path is solid now.
Installed Nix + flakes and ran every step verbatim on a clean machine:
- ✅ Step 1 scaffold (
nix flake init -t …#ui-qml-backend) — generated files match the Step 1.4 table. - ✅ Step 2 deps —
metadata.json+flake.nixexactly as written;delivery_moduleresolves and thelogos-delivery-module/v0.1.3pin builds. The earlier "delivery_modulewon't resolve" blocker no longer reproduces. - ✅ Step 3 — header
#include "logos_sdk.h"+ theLogosModules* m_logosmember + all sixchat.on(...)subscriptions compile. The header/cpp include-split fix holds. - ✅ Step 5 —
nix buildproduces the module;nix build .#lgxproduceslogos-ui_example-module.lgx. - ✅ API accuracy — every method, event name, argument order, and the
Status { convo_count, delivery_state, detail }shape in Steps 3–4 matchchat_modulev0.1.2'srust-lib/chat_module.lidlexactly (verified against the generatedchat_module_api.h).
One doc-level gap remains in Step 6 — it isn't executable with the tutorial's own hardcoded instance_path (inline comment below).
Note: nix run triggers a from-source rebuild of liblogosdelivery; in my sandbox that hit a TLS/proxy snag fetching a transitive cargo git dep — environmental, not a doc issue.
|
|
||
| ## Step 6: Verify a two-instance exchange | ||
|
|
||
| A chat is only proven end to end when a message travels between two running instances. Start two copies of your module — each with its own `instance_path` and `tcp_port` — and confirm a message lands as a `message_received` event. |
There was a problem hiding this comment.
As written, Step 6 can't be run with the tutorial's own code, because instance_path is fixed in initLogos() (see the suggestion on the init() line) — there's no documented way to give two nix run instances distinct directories. Worth either parameterizing instance_path per the suggestion above, or pointing readers at the ready-made two-instance harness in logos-chat-ui (nix run .#exchange).
|
Follow-up on the
So the full path in this guide — scaffold → Step 2 deps → Step 3/4 code → |
…odule-api.md Co-authored-by: Sasha <118575614+weboko@users.noreply.github.com>
From: #311