Commit Graph
50 Commits
Author SHA1 Message Date
Dario Gabriel LipicarandClaude Opus 5 c0cba910ae refactor(generator): remove --module-dir, and the two dead files it documented
--module-dir walked a directory of BUILT plugins and generated one consumer
wrapper per dependency by dlopen'ing each and reading its QMetaObject. Every
wrapper now comes from a contract instead -- `--general-only` with one
`--dep <name>=<name>.lidl` per dependency -- which builds no dependency plugin
and, unlike introspection, works under cross-compilation.

It is REFUSED rather than ignored, mirroring --provider-header right below it.
Falling through to the dependency LISTING would have exited 0 having generated
nothing: the exact shape that lets a stale caller look green while shipping a
module with no typed API.

No nix build changes as a result -- the flag had no caller left in any of them,
so a store-path diff would be empty either way and would prove nothing. The
only observable difference is what the binary does when handed the flag, so
that is what the new `generator-cli` check asserts, by EXIT CODE:

  OK: control - --metadata alone exits 0 and lists dependencies
  OK: --module-dir exits non-zero (status=2)
  OK: --module-dir fails with the removal diagnostic
  OK: --general-only still emits the umbrella

The control matters: without it a non-zero exit could equally mean the binary
is broken. It runs against an EXISTING modules directory too, because the old
code only errored when that directory was missing.

Also deleted, both genuinely dead:

  * cpp/compile.sh -- compiles logos_api.cpp, module_proxy.cpp, token_manager.cpp
    and six headers, NONE of which exist in this repo any more (they moved to
    logos-protocol / logos-qt-host in the host split). The script cannot run.
  * docs/docs.md -- 789 lines with zero inbound references anywhere in the
    workspace, documenting --module-dir and a cpp/ layout that is gone.

cpp-generator/compile.sh is KEPT: logos-module-builder's LogosModule.cmake:404
still invokes it (`add_custom_target(cpp_generator_build ...)`) on the
LOGOS_CPP_SDK_IS_SOURCE branch, and it builds into exactly the
LOGOS_DEPS_ROOT/build/cpp-generator path that file then reads.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 18:41:20 -03:00
Dario Gabriel LipicarandClaude Opus 5 cefd5aec21 docs: point logos_async_result.h at the one LogosModule.cmake
The comment named "logos-plugin-qt/cmake/LogosModule.cmake and its
module-builder twin". There is no twin any more: logos-plugin-qt's copy is
deleted and the file exists once, in logos-module-builder.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 09:01:46 -03:00
Dario Gabriel LipicarandClaude Opus 5 b9d7641fae feat(sdk): logos_host_services.h — the C++ veneer over the privileged surface
Phase C1. A Qt-free, header-only wrapper over the three trust-root lp_* calls
A3 added, so capability_module can become an ordinary universal module instead
of a hand-written Qt plugin reaching into TokenManager directly.

Deliberately FREE FUNCTIONS, not a LogosModuleContext seam as the plan
sketched. The grant is process-global per IMAGE (host binary and module cdylib
each link their own logos-protocol, so each has its own grant state and its own
TokenManager), so the gate lives in the caller's own image and there is nothing
per-instance to inject; a context seam would imply the privilege is a property
of one impl object, which it is not. It is also markedly cheaper: a seam would
need a new module-impl C ABI export plus lockstep changes in BOTH codegen paths
(the Qt provider glue and the cdylib wrapper).

constantTimeEquals lives here rather than in each caller: the natural spelling
(a == b) leaks the matching-prefix length through timing, and a trust root
comparing tokens with == is the exact bug this file exists to prevent. Ported
from capability_module's own implementation to std::string.

Two things the tests caught that reading had not:

* lp_inform_module_token_to takes SIX arguments (client, auth_token,
  origin_module, module_name, token, timeout_ms), not the three I first wrote.
  The wrapper now mirrors it exactly, with the protocol's own default-timeout
  semantics documented.
* sdk_tests compiles against logos_headers alone, which carries no protocol
  include path. It now resolves logos_protocol.h from LOGOS_PROTOCOL_ROOT,
  accepting either the source layout (cpp/) or a package layout (include/) and
  failing loudly on neither, rather than hard-coding the one in use today.

The suite deliberately does NOT link logos-protocol: the lp_*-calling wrappers
are `inline` and never ODR-used by these tests, so no protocol symbol is
referenced. That is itself the assertion — the veneer must not drag the
protocol library into a header-only consumer. A future test that calls one will
fail to LINK rather than silently pull it in.

Also documents a real gap found while writing it: lp_token_get performs NO
host-service check, so "token_registry" gates ENUMERATION only. The plan claims
that service covers `lp_token_get(any)`; it does not. Flagged at the call site
rather than papered over — if lookup should be gated, the gate belongs in
lp_token_get.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 09:01:46 -03:00
Dario Gabriel LipicarandClaude Opus 5 1017aa56b9 feat(generator): remove --provider-header (interface: "provider")
Every provider now goes through the module-impl C ABI, so the LOGOS_METHOD
dispatch path is gone: parseProviderHeader, generateProviderDispatch,
ParsedMethod and the joinDocLines helper only it used (~300 lines), plus the
test that covered it.

`toQVariantConversion` is NOT removed — it is shared with live emitters — and
its test stays.

The flag is REFUSED rather than dropped. Without that, `--provider-header x.h`
falls through to the plugin-path branch, which reads the flag itself as a
plugin path and reports "Plugin file does not exist: --provider-header" — a
missing-file error for what is really a retired mode. It now exits 2 with a
message pointing at interface: "universal".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 09:01:45 -03:00
Dario LipicarandClaude Opus 5 f3369faca4 feat(generator): async callers can see the error, sync callers can set a deadline (#132)
The two consumer surfaces had complementary holes:

  sync :  T    foo(params…, logos::CallError* err = nullptr)   error yes, timeout NO
  async:  void fooAsync(params…, cb, Timeout = Timeout())      timeout yes, error NO

so an async caller could not tell a failed remote call from a provider that
legitimately returned 0 / "" / false — the exact ambiguity the sync path's
CallError* was added to resolve — and a sync caller could not say how long it
was willing to wait, even though the transport overload the generator already
calls takes both.

Both fixes are additive:

  T    foo(params…, logos::CallError* err = nullptr, Timeout timeout = Timeout());
  void fooAsync(params…, std::function<void(T)> cb, Timeout timeout = Timeout());   // unchanged
  void fooAsyncResult(params…, std::function<void(logos::AsyncResult<T>)> cb,
                      Timeout timeout = Timeout());                                  // new

logos::AsyncResult<T> (new, Qt-free, cpp/logos_async_result.h) is {value, error}
plus ok(); AsyncResult<void> carries only the error so every fooAsyncResult has
the same callback shape. The name is distinct rather than an overload because
std::function<void(AsyncResult<T>)> next to std::function<void(T)> is ambiguous
for a generic lambda.

Applied to both emitters that produce this surface — legacy/generator_lib.cpp
(the module-builder path) and experimental/lidl_gen_client.cpp (`--lidl
--module-only`, from a published contract) — since a consumer can reach either
for the same contract.

The Qt-free (ApiStyle::Lp) surface gets the sync timeout (spelled `int
timeout_ms`; `Timeout` lives behind a Qt header) but NOT fooAsyncResult:
logos-protocol's lp_invoke_async hard-codes `cb(1, …)`, so an AsyncResult there
would report ok() on a failed call. Measured, not assumed. See the note in
makeHeaderLp.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 10:19:08 -03:00
Dario LipicarandClaude Opus 5 9a6d7b8228 fix(generator): one Qt type mapper, and it knows about void; LpClient takes a timeout (#119)
Two near-duplicate LIDL->Qt type mappers existed — legacy/main.cpp's
lidlTypeExprToQtTypeName and experimental/lidl_emit_common.cpp's lidlTypeToQt —
and they disagreed. The legacy one had no `void` case, so a `-> void` method
arriving as Primitive("void") from the impl-header parser fell through to
QVariant. (The .lidl parser spells it Named("void"), which survived only by
accident, through mapReturnType's `base == "void"` early-out.)

That was not a Qt-consumer bug: the std/lp tables are DERIVED from this name, so
the same method generated `LogosMap doVoid(...)` on the Qt-free surface too.
Measured, from `void doVoid();` in a .h interface:

    QVariant  doVoid(...)   --api-style qt   before
    void      doVoid(...)   --api-style qt   after
    LogosMap  doVoid(...)   --api-style lp   before
    void      doVoid(...)   --api-style lp   after

lidlTypeExprToQtTypeName is now a delegation, so there is one table to disagree
with. This changes the generated signature for any module consuming a `-> void`
method through a .h interface; the two in-tree call sites discard the value and
are unaffected.

logos::LpClient::invoke/invokeAsync gain a timeout_ms parameter, defaulted to
the C ABI's "use the default" (0) so no existing caller changes. The Qt-typed
consumer surface takes a Timeout on every async overload and had nowhere to put
it — a wrapper delegating to the lp path silently dropped it.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 10:21:18 -03:00
Dario LipicarandClaude Opus 5 461cfed52d refactor: the LIDL codec exists once (#117)
* refactor: the LIDL codec exists once

The cdylib generator emitted its own copy of the codec — ~186 lines of
C++-emitting-C++ mirroring logos-protocol's logos_codec.h by hand. Every codec
fix had to be written twice or it silently only half-applied, which happened
twice in a row recently (routing scalars through the codec + signedness; then
accepting 3.0 while still rejecting 3.7).

It was worse than duplication. The two copies had DRIFTED — the emitted integer
decode gated on is_number() where the canonical one checked is_number_integer()
|| is_number_unsigned() — and logos_json.h's byte helpers were the same mangled
symbols with weak linkage and DIFFERENT bodies as logos_codec.h's, both reaching
one program (module TUs compiled one; liblogos_protocol.a carries TUs that
included the other). Which body won was down to link order.

logos_json.h goes back to its documented charter — "LogosMap/LogosList aliases
for impl classes", per its own CMakeLists — and loses 77 lines. jsonToBytes moves
beside its sibling jsonToStringVec in logos_lp_client.h, rebuilt on the canonical
isTaggedBytes/b64UrlDecode; it keeps its own narrow spelling because every lp
decoder is documented to yield the default-constructed value on a mismatch,
which neither bytesFromJson (throws) nor bytesFromJsonLenient (accepts more) does.

Emptying it rather than making it include logos_codec.h is deliberate: some
thirty alias-only include sites across the module repos get ZERO new includes,
and logos-cpp-sdkConfig's "only dependency is nlohmann_json" stays true.

With the clash gone the generic half is deletable. emitGeneratedCodec becomes
emitRecordCodecs: one logos::detail::Codec<::Rec, void> per declared record, and
nothing else. That residue is irreducible — a LIDL `type` is a per-contract
struct whose fields exist only in that module's header, and C++17 has no field
reflection. Nesting composes for free: Codec<std::vector<Blob>> and deeper come
from the shared half once Codec<::Blob> exists.

One asymmetry dies with it. The scalar bstr decode and the [bstr] element decode
were different functions with different strictness, so echoBytes("hi") succeeded
while echoBytesList(["hi"]) threw — inside one module, for the same type. They
are one function now.

Build wiring: ONE line, in this repo's own test CMake, using a variable
nix/tests.nix already supplies. Nothing in logos-module-builder, logos-qt-sdk, or
any module repo.

verified: cpp-sdk + protocol suites green; test_fullapi_cpp, test_fullapi_ext_cpp
and test_basic_module_cpp build; test-modules 176/176. Conformance delta is
exactly one cell, baselined first in logos-test-modules#31.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore: bump logos-protocol to the path-threaded bstr decoder

logos-protocol 4359557 (#33). Required by this branch, not incidental: deleting
the emitted codec swaps its path-carrying bstr decode for the canonical one, and
without #33 the canonical one reported "at value" instead of "[0].payload" —
losing the diagnostic exactly where a malformed bstr is hardest to find.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 16:01:14 -03:00
Dario LipicarandClaude Opus 4.8 c7444bc29a Follow-ups to #100: lp-consumer bstr decode, Qt-free cdylib event types, binary-event coverage (#102)
* cdylib events: Qt-free types, and drop the unused bytes encoder

Three follow-ups to the bstr event fix, all in the cdylib events sidecar --
a Qt-FREE translation unit:

- An `any`/map event parameter was emitted as a bare QVariant/QVariantMap,
  which does not compile there. Spell those as their nlohmann aliases
  (LogosMap / LogosList) and pull in <logos_json.h> when they appear.
- std::vector<std::vector<uint8_t>> fell through the impl-header parser's
  unknown-type fallback to `any`, so the cdylib gate admitted it and the
  generator then emitted QVariant. Parse it as `[bstr]` so the gate rejects it
  with a message naming the offending parameter.
- The bytes encoder was emitted into every module's sidecar, leaving an unused
  static function (-Wunused-function) wherever no event carries binary data.
  Emit it only when a bstr event parameter exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* lp consumer: decode bstr into std::vector<uint8_t>

The Qt-free (`lp`) consumer wrappers -- what every universal C++ module gets for
its dependencies -- had no QByteArray in their type tables, so a `bstr` event
parameter, method argument, or return degraded to QVariant and then to LogosMap.
A consumer subscribing to a binary event was handed the raw tagged JSON object
{"_bytes": "<base64url>"} instead of the bytes, with no generated decode.

Teach the tables about QByteArray (-> std::vector<uint8_t>) and marshal it
through the canonical tagged form in both directions: logos::bytesToJson on the
way out, logos::jsonToBytes on the way in. Those live in logos_json.h -- Qt-free
and protocol-free, so the generated wrappers and module code can share them.
The Qt apiStyle already did this via QByteArray::toBase64/fromBase64.

Without this, a subscriber written the obvious way --

    onBinaryReady([](const std::string&, const std::vector<uint8_t>& payload) {...})

-- compiles (nlohmann::json has an implicit conversion operator) and then throws
at runtime on every event, so the callback body silently never runs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* tests: cover binary event payloads by value, not just by source text

The regression test for #99 asserts on generated source text, so it stays green
against an encoder that emits the wrong bytes. Add the value-level half:

- tests/sdk/test_logos_json_bytes.cpp exercises the canonical tagged-bytes codec
  against the RFC 4648 vectors, the URL-safe alphabet, every len%3 tail group,
  embedded NULs and high bytes, a 109,447-byte payload (the size from #99), and
  the lenient/padded decode paths.
- tests/experimental/test_lidl_gen_cdylib.cpp additionally pins the Qt-free
  spelling of JSON event payloads, the rejection of [bstr], and the omission of
  the bytes encoder from modules whose events carry no binary data.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* doctests: prove a binary event payload survives the round trip

Neither doc-test covered bytes-in-an-event -- the gap #99 fell through. The
generator round-trip carried `bstr` only as a method argument and return, and
the composition doc-test, which is the one that actually runs two modules under
logoscore and subscribes to an event, carried only a string. So a generator that
dropped every bstr event argument kept both of them green.

- cpp-sdk-module-composition: greeter_module gains a `blobReady(label, payload)`
  event and an `emitBlob(size)` method; orchestrator_module subscribes and
  reports the length AND a checksum of what it received. Length alone would not
  catch a corrupted payload -- a wrong alphabet round-trips to the same size.
- cpp-sdk-generator-roundtrip: sensor_module gains a `capture(id, frame: bstr)`
  event, and a new step shows the generated event body encoding it through
  lidlBytesToJson rather than pushing it raw.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* logos_json.h: include <cstddef> for size_t

The tagged-bytes codec uses size_t but relied on it arriving transitively
through the other includes. Include <cstddef> directly so the header is
self-contained. (Copilot review, PR #102.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 18:50:40 -03:00
Dario LipicarandClaude Opus 4.8 676154070c codegen: Qt-free outbound — ApiStyle::Lp typed wrappers over the lp_* C ABI (#88)
* ci: drop doctest chain pins — the qt-split chain is fully merged

logoscore-cli and module-builder masters now contain the chain; the
temporary --release-for pins (added so stacked-branch CI could resolve
compatible cross-repo revs) default back to latest releases.

* codegen: Qt-free outbound — ApiStyle::Lp typed wrappers over the lp_* C ABI

Adds a third generator flavor (ApiStyle::Lp, --api-style lp) whose typed
dependency wrappers + LogosModules umbrella call the logos-protocol C ABI
directly via a new header-only logos::LpClient, instead of LogosAPIClient.
This lets a module make outbound typed calls and event subscriptions with NO
Qt in its translation units — Qt stays confined to the QRO transport (inside
logos-protocol) and the generated plugin glue.

- cpp/logos_lp_client.h: header-only logos::LpClient (lazy lp_client_create
  on a baked origin; invoke / invokeAsync / subscribe; std<->nlohmann JSON;
  CallError out-param) + RAII logos::LpSubscription (unsubscribes on drop) +
  json<->std helpers. The C++ analog of rust-sdk PluginProxy.
- generator: makeHeaderLp/makeSourceLp emit the Lp wrappers; the Lp umbrella
  drops the LogosAPI ctor and bakes this module name as the lp_client origin
  (LogosModules() default-constructible). Qt/Std emission is byte-unchanged
  (dispatch added at the top of makeHeader/makeSource).

Verified: generator builds; generated wrappers + umbrella compile to .o with
ONLY cpp-sdk + logos-protocol headers + nlohmann (no Qt); cpp-sdk tests pass.

* cdylib: wire the Qt-free typed dependency surface (modules()) into the impl

When a cdylib module declares dependencies, the generated exports now include
the Lp umbrella (logos_sdk.h) and construct LogosModules() + maybeSetLogosModules
on the impl just before onContextReady — so the author can call
modules().<dep>... and subscribe to dep events from a Qt-free cdylib. Guarded
on module.depends so dependency-less cdylib modules are byte-unchanged.

The umbrella + dep wrappers themselves are produced by the --general-only
--api-style lp generation; feeding the dep .lidl files into that during the
module build is the remaining build-system wiring (module-builder + plugin-qt
dep resolution).

* cdylib: wire modules() unconditionally (deps come from metadata, not the .lidl)

The umbrella wiring was guarded on the .lidl module.depends, but a cdylib
module declares its dependencies in metadata.json#dependencies — the .lidl
contract.depends is typically empty — so modules() was left null and a typed
outbound call segfaulted. Always include the generated logos_sdk.h umbrella
and maybeSetLogosModules(impl, new LogosModules()) before onContextReady; the
overload is a no-op for context-less impls and the umbrella codegen emits an
(empty) logos_sdk.h for every cdylib, so this is safe in all cases.

* fix(headers): ship logos_lp_client.h in the include/cpp source-export root

A cdylib module's generated dep wrapper includes "logos_lp_client.h" and,
transitively, "logos_result.h". The wrapper is compiled with the cpp-sdk
source-export include root (include/cpp), so logos_lp_client.h must sit
beside logos_result.h there — a quoted include resolves siblings relative
to the including file's directory. Previously logos_lp_client.h shipped
only at the top-level include/ (the CMake-export layout via cpp/
CMakeLists.txt), so it pulled in include/logos_result.h while the impl's
logos_module_context.h pulled include/cpp/logos_result.h. Those are two
distinct realpaths under the symlinkJoin, so #pragma once could not dedup
them and StdLogosResult was redefined. Install every std header into both
roots so a single TU only ever sees one logos_result.h.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(cdylib): route logos_module_accept_token into the protocol TokenManager

The generated module-impl export stored accepted tokens in a process-local
std::map (g_tokens) that nothing ever read, so a cdylib module's OUTBOUND
lp_client (modules().<dep>...) never saw the capability_module bootstrap
token the host delivers at load. The automatic requestModule flow then ran
unauthenticated: capability_module rejected requestModule, no per-target
token was issued, and the cross-module call was rejected (returning a
default-constructed result, e.g. 0).

Forward the token into lp_token_save, which writes the same
TokenManager::instance() singleton the cdylib's lp_client reads. The
capability/token handshake now completes and typed Qt-free outbound calls
return real results. Drop the dead g_tokens map + mutex.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(lidl): exclude LogosModuleContext hooks from header-derived contracts

--header-to-lidl parses an impl class's public methods. An impl commonly
overrides onContextReady() (and could redeclare a context accessor) in its
own public section, so the derived LIDL would include onContextReady /
modules / modulePath / instanceId / instancePersistencePath. Those are
framework plumbing, not API methods — and feeding them to the cdylib
backend breaks cdylib-eligibility (e.g. the inherited accessors' Qt-free
return-type check), which is exactly what header-first universal modules
now hit. Skip the reserved LogosModuleContext names in the parser so both
the Qt --from-header path and the cdylib --header-to-lidl path emit clean,
API-only contracts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(cdylib): support the full std type set in header-derived contracts

Routing core universal modules through the cdylib backend surfaced gaps
between the cdylib subset and what the std apiStyle handled — a universal
module that built under std must also build as a header-first cdylib.

- lidl parser: restore the return-shape flags (resultReturn / jsonReturn)
  from the parsed return TypeExpr, so a header -> .lidl -> cdylib round-trip
  (the universal path, needed to feed the Qt glue) preserves the semantics
  the impl-header parser sets from C++ types (StdLogosResult -> result;
  LogosMap/LogosList -> json). Without this the cdylib codegen/eligibility
  mis-handled result / map / list returns.
- cdylib eligibility + dispatch: `void` is not a lidlBuiltinType, so the
  parser yields it as a Named "void" (header path uses empty name) — treat
  both as void in the eligibility check and the dispatch (was relying on
  lidlTypeToQt=="void", which didn't match Named "void" -> generated an
  `auto result = <void call>`).
- typeSupported: accept `any` (both directions), `void`/`result` (returns),
  arrays-of-any, and Map ({k:v}/LogosMap) — the Qt-free-via-nlohmann set.

Verified: a probe with void / LogosMap / LogosList / StdLogosResult /
const returns is cdylib-eligible and dispatches correctly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(lidl): carry method/event descriptions across the .lidl round-trip

Header-first universal modules go header -> .lidl -> cdylib backend. The
impl-header parser captures /// and /** */ doc comments into method/event
descriptions, but the .lidl serializer emitted only the signature, so the
descriptions were dropped — introspection (lm methods / --json, getMethods)
then showed no docs (regressing the wrap-external-lib + tutorial doctests).

Serialize each method/event's description as a trailing `description "..."`
clause (escaped for the string literal; the lexer already decodes \\ \" \n
\t) and parse it back in parseMethodDef/parseEventDef. Module description
now escaped too. Verified: /// docs survive header -> .lidl -> getMethods.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(lp): bound-interface wrappers are handles over umbrella-owned state

The Lp interface (bind_<iface>) wrapper owned its LpClient + RAII
subscriptions BY VALUE, so the idiomatic transient handle —
  modules().bind_calculator(p).fibonacciAsync(...)
  modules().bind_calculator(p).onVersionReady(...)
— tore the client/subscription down when the temporary died, cancelling
the async callback and the event subscription. (Sync calls completed before
the temporary's destruction, so they worked; the Qt/std flavor works because
its handle is thin over a LogosAPI-owned persistent client.)

Make the Lp Bound wrapper a THIN, copyable handle over `State { LpClient
client; vector<LpSubscription> subs; }` that the LogosModules umbrella OWNS
per provider (std::map<provider, unique_ptr<State>>) for the module's
lifetime. bind_<iface>(p) creates/looks up the State and returns a handle to
it, so a transient handle's async/event registrations outlive it. Concrete
(Static) dep wrappers are unchanged — they're already persistent umbrella
members, so by-value ownership is fine there.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(cdylib): lenient bytes-param decode (string / array / tagged)

A universal module's bstr (std::vector<uint8_t>) PARAM arrived empty when
the caller sent a plain string rather than the tagged {"_bytes": base64url}
form — lidlBytesFromJson only accepted the tagged object, so
byteArraySize("12345") and byteArraySize(b"\x01..") both saw 0 bytes (the
return direction already worked). The std path was lenient (a QString or
QByteArray arg both became bytes). Accept all three forms: a plain JSON
string (raw UTF-8 bytes), an array of byte values, and the tagged
{"_bytes"} form (base64url). Return direction unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(cdylib): a number arg to a bytes param decodes as its decimal text

byteArraySize("12345") arrives as a JSON number (the logoscore CLI's type
auto-detection turns the string "12345" into int 12345), and the Qt path
gives QVariant(int)->QByteArray "12345" (5 bytes). The cdylib bstr decode
returned 0 for a number. Treat a JSON number as its decimal text bytes
(j.dump()), matching the Qt behaviour, so a bare-number arg to a bytes
param round-trips identically. Verified: byteArraySize 12345 -> 5.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 00:47:09 -03:00
Dario LipicarandClaude Opus 4.8 f0fe8cbfeb Make the base SDK Qt-free: Qt developer layer moves to logos-qt-sdk (#83)
* Extract the protocol layer into logos-protocol; consume it as a flake input

The transport/token/IPC layer (transports incl. QRO + plain TCP/TLS,
consumer core LogosAPIClient/LogosAPIConsumer with the capability
auto-requestModule flow, ModuleProxy, token manager, QVariant<->JSON
conversion, the abstract LogosProviderObject interface) now lives in the
logos-protocol repo behind the versioned lp_* C ABI.

This SDK keeps the typed C++ developer layer (LogosAPI, provider base
classes + Qt provider glue, module context, code generator) and still
compiles the protocol sources INTO liblogos_sdk.a from the flake input,
so the installed artifact (archive symbols, include/ + include/cpp
layouts, cmake config) stays byte-compatible: existing consumers need
no changes. Public headers are unchanged; logos_provider_object.h keeps
its name and now re-exports the abstract interface from
logos_provider_interface.h.

Transport/protocol component tests moved to logos-protocol with the
code; the remaining sdk/generator/experimental suites are unchanged
(432/432 green against the local protocol checkout).

* lock: add logos-protocol input

* Make the base SDK Qt-free: move the Qt developer layer to logos-qt-sdk

LogosAPI, LogosAPIProvider, LogosProviderBase/LOGOS_PROVIDER macros, the
QObject provider glue (QtProviderObject) and the legacy PluginInterface
(core/interface.h) move to the new logos-qt-sdk repo. The protocol
sources are no longer compiled into a monolithic archive — consumers
link logos-qt-sdk (which layers on logos-protocol) instead.

What remains here is header-only std C++: logos_module_context.h,
logos_result.h (StdLogosResult), logos_json.h — exported as the CMake
INTERFACE target logos-cpp-sdk::logos_headers — plus the code generator
(a build-time tool; its introspection mode now includes
logos_provider_interface.h from logos-protocol, where
LogosProviderPlugin moved).

Mechanically verified Qt-free: the logos-cpp-lib / logos-cpp-include
closures contain only nlohmann_json. Tests: 245/245 (module-context std
suite + generator + experimental).

* fix: accept the installed source-export layout in the protocol-root check

The fail-fast only tested <root>/cpp/logos_protocol.h, but the LP_SRC
selection right below (and the error message itself) support the
installed export layout <root>/include/cpp as well. Pointing
LOGOS_PROTOCOL_ROOT at an installed export tripped the FATAL_ERROR
before that fallback could apply.

Caught by Copilot review on #82.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* lock: pin logos-protocol to the qt-free-split branch head

The Qt-free SDK (and the cdylib backend stacked on it) reference
LogosProviderPlugin from protocol's logos_provider_interface.h, which
lands on feat/qt-free-split — the P1-branch pin no longer compiles
standalone. Temporary — drop when the chain PRs merge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* doctest: pin the logoscore runtime via its {release} placeholder

The spec built logoscore-cli at bare master with only the cpp-sdk inputs
overridden — master's stack cannot compile against the qt-free SDK, so
the suite failed on the chain branches. With the placeholder, CI's
--release-for pins expand it to the workspace's logoscore commit (and
local runs without a pin still fall back to master, unchanged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* doctest: override the nested module builders to {release} too

capability_module (via logoscore's lock) and the cloned accounts module
resolve module-builder from their own locks — pre-split revs whose
LogosModule.cmake still detects the SDK by logos_api.h, which the
qt-free SDK no longer ships ('logos-cpp-sdk not found'). Overriding the
builder itself to the workspace-pinned chain rev (keeping the nested
cpp-sdk override) builds both modules with the split-aware builder.
Verified end-to-end locally with the exact doctest command.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* doctest: apply the {release} + nested-builder overrides to all three specs

The runtime spec got the treatment in 210eea1; the composition and
worker-thread specs have the same logoscore/module build commands and
failed identically (pre-split builders from the modules' own locks).
All executed run: blocks now pin logoscore-cli{release} and override
the nested module builders to logos-module-builder{release}; the
displayed code_block: variants stay in their generic master form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* codegen: typed wrappers throw on call failure; dispatch catches escapes

Generated sync client wrappers call the new err-out invokeRemoteMethod
overload and throw logos::LogosCallError when the call fails (e.g. the
bound module is missing) — previously the empty QVariant silently
degraded to the return type's default and a caller could not tell
failure from a legitimate 0 / "". Both generators (legacy + LIDL),
both API styles. Async paths unchanged.

Generated provider dispatch (universal qt glue + LOGOS_PROVIDER) wraps
the method body in a catch-all that logs and returns an invalid QVariant
— an escaped exception becomes an ordinary METHOD_FAILED instead of
unwinding through Qt event dispatch and killing the module process.

* codegen: CallError out-param instead of throwing wrappers

Per review, the generated sync wrappers expose the error channel as an
optional trailing parameter — add(a, b, &err) — rather than throwing:
explicit, stateless, works on temporaries, and existing call sites
compile unchanged (they keep default-on-failure, now with a qWarning so
failures are visible in the module log). The dispatch catch-all from the
previous commit stays: it contains author exceptions, it doesn't
introduce any.

* glue: fire onContextReady AFTER modules()/event wiring

The generated onInit set the context (which fires the impl's
onContextReady hook) before constructing the LogosModules aggregate and
wiring typed event emission — so an impl doing its documented one-time
setup there (typed dependency calls, event subscriptions) dereferenced
a null aggregate and crashed the module process (signal 11). Found by
the first module to subscribe to a dependency's typed event from
onContextReady. Context now goes last.

* ci: run workflows on stacked PRs + workflow_dispatch

Both workflows filtered pull_request to master-based PRs, so stacked PRs
(feat/qt-free-sdk -> feat/extract-logos-protocol, feat/cdylib-authoring
-> feat/qt-free-sdk) ran NO checks at all. Drop the base-branch filter
for pull_request and add workflow_dispatch for manual runs. Same fix as
logos-module-builder 232b8a2.

* lock: protocol at the typed-requestModule port (3de5398)

* ci: chain pins for the doc-tests (drop at merge)

In repo CI only cpp-sdk's {release} is the commit under test —
logoscore-cli and module-builder expanded to master, which doesn't link
against the chain SDK the specs override in ('Build the CLI with the SDK
override' failed on every run since the stacked-PR triggers were
enabled). Pin both to the extraction-chain heads; the workspace pipeline
is unaffected (it pins every repo itself).

* generator: distribute the LIDL frontend for external generators

First step of moving ALL Qt glue emission out of this repo into
logos-qt-sdk's logos-qt-generator (cpp-sdk's generator keeps only the
Qt-free outputs: std typed wrappers, logos_sdk umbrella, cdylib
impl-exports, LIDL derivation).

- Shared emit helpers (lidlToPascalCase, lidlTypeToQt, lidlTypeToStd,
  lidlIsStdConvertible) move to a new lidl_emit_common.{h,cpp} unit, used
  by both generators.
- The frontend set (AST, lexer, parser, serializer, validator,
  impl-header parser, emit-common) is installed under
  share/lidl-frontend/ — the qt generator compiles these sources in
  directly, so the two tools share one frontend without a binary ABI.

* lock: protocol#3 merged — pin advances to protocol master

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 19:56:19 -03:00
Dario LipicarandClaude Opus 4.8 38bc77e127 Consume logos-protocol: the transport/token/IPC layer moves behind the lp_* C ABI (#82)
* Extract the protocol layer into logos-protocol; consume it as a flake input

The transport/token/IPC layer (transports incl. QRO + plain TCP/TLS,
consumer core LogosAPIClient/LogosAPIConsumer with the capability
auto-requestModule flow, ModuleProxy, token manager, QVariant<->JSON
conversion, the abstract LogosProviderObject interface) now lives in the
logos-protocol repo behind the versioned lp_* C ABI.

This SDK keeps the typed C++ developer layer (LogosAPI, provider base
classes + Qt provider glue, module context, code generator) and still
compiles the protocol sources INTO liblogos_sdk.a from the flake input,
so the installed artifact (archive symbols, include/ + include/cpp
layouts, cmake config) stays byte-compatible: existing consumers need
no changes. Public headers are unchanged; logos_provider_object.h keeps
its name and now re-exports the abstract interface from
logos_provider_interface.h.

Transport/protocol component tests moved to logos-protocol with the
code; the remaining sdk/generator/experimental suites are unchanged
(432/432 green against the local protocol checkout).

* lock: add logos-protocol input

* fix: accept the installed source-export layout in the protocol-root check

The fail-fast only tested <root>/cpp/logos_protocol.h, but the LP_SRC
selection right below (and the error message itself) support the
installed export layout <root>/include/cpp as well. Pointing
LOGOS_PROTOCOL_ROOT at an installed export tripped the FATAL_ERROR
before that fallback could apply.

Caught by Copilot review on #82.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* lock: protocol at the typed-requestModule P1 port (1e4bc72)

* lock: protocol at master (protocol#2 merged)

The extraction is on protocol master now (29afbac); the temporary branch
pin is dropped.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 19:21:00 -03:00
Iuri Matias f5a127dd11 use updated capability module (#85)
* use refactored capability module

use refactored capability module

remove unneded comments

* use cpp types
2026-06-11 15:44:37 -04:00
Dario LipicarandClaude Opus 4.8 40e7631402 Marshal inter-module calls to the owner thread (#79)
* Marshal inter-module calls to the owner thread

Logos inter-module calls go over Qt Remote Objects, whose replicas only
work on the thread that created them (the module's main/event-loop thread).
A module that makes calls from a worker thread — e.g. an embedded HTTP
server serving /metrics — would otherwise hang on replica acquisition.

Make LogosAPIClient transparently marshal to its owner thread when called
off-thread (guarded so same-thread calls run directly with no overhead):
- LogosAPI::getClient creates the client/consumer/replicas on the owner thread
- LogosAPIClient::invokeRemoteMethod / requestObject / onEvent run there too

New header logos_thread_marshal.h (runOnOwnerThread). No new data members —
ABI-safe for statically-linked plugins.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Add regression test for worker-thread inter-module calls

A provider records the thread its method runs on; a consumer calls it from
a worker thread via LogosAPIClient::invokeRemoteMethod. The call must execute
on the owner (main/event-loop) thread, not the worker thread.

Fails without the marshaling change (the call runs on the worker thread —
0x..d80d0 vs owner 0x..c53e0, "executed on the worker thread instead of the
owner thread"); passes with it (511/511).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Address review: async marshaling, helper constraints, test ownership

- invokeRemoteMethodAsync now also marshals to the owner thread (non-blocking
  QueuedConnection) — the async path acquires a replica too, so calling it from
  a worker thread previously re-introduced the off-thread bug.
- runOnOwnerThread: document the return-type constraints (void or
  default-constructible, non-reference) and static_assert against references.
- test: declare the provider before its LogosAPI so the ModuleProxy (which
  holds a raw pointer to it) is torn down first — removes the leak and the
  inaccurate comment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* doctest: call a module from a worker thread (HTTP server)

Adds cpp-sdk-worker-thread-http.test.yaml: builds a sensor_module callee and
an http_module caller that embeds a libmicrohttpd server, runs them in
logoscore, starts the server, and curls it. The HTTP handler calls
sensor_module.readTemperature() from the server's worker thread — which only
works because the SDK marshals the cross-module call onto the module's owner
thread. The module stays pure C++.

Wired into doctests/run.sh and the doctests CI workflow. Validated locally
(23/23 steps pass): `curl` returns `temperature 42`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 16:47:24 -03:00
Iuri MatiasandCopilot Autofix powered by AI d142262436 Fix: F-007: add function to redact logged tokens (#80)
* add function to redact logged tokens

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-08 15:22:27 -04:00
Iuri MatiasandCopilot Autofix powered by AI 448aa9002c fix: F-002: only allow core and capability module to call informTokenModule (#78)
* only allow core and capability module to call informTokenModule

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-08 14:27:07 -04:00
Iuri Matias 825b80aeee re-add token auth (#73) 2026-06-05 18:12:29 -04:00
Dario LipicarandClaude Opus 4.8 7b62ac2017 Per-event documentation + getPluginEvents introspection (#71)
* Add per-event documentation + getPluginEvents introspection

Mirror the per-method documentation pipeline for events. Events
(declared in a universal module's logos_events: section) now carry a
description parsed from their /// doc comments, and are introspectable
at runtime via a new getPluginEvents framework call.

- lidl_ast: EventDecl gains a description field.
- impl_header_parser: capture the event's doc comment (previously
  discarded) and an optional metadata.json events[].description.
- lidl_gen_provider: generated universal provider emits
  getEvents() override, mirroring getMethods() (name/signature/
  parameters/description; no returnType/isInvokable — events are void).
- logos_provider_object: default-empty virtual getEvents() so the
  legacy provider path and QtProviderObject inherit empty.
- module_proxy / qt_provider_object: intercept getPluginEvents next to
  the getPluginMethods special-case.
- docs: spec + README event-documentation notes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Add unit tests for event documentation + getEvents generation

Address review feedback (#71): cover the event-introspection paths that
previously only had method-side tests.

- impl_header_parser test: assert metadata.json events[].description is
  parsed; new documented_events fixture asserts `///` doc-comment
  capture on a logos_events: block (multi-line joined with \n,
  adjacent-only, plain // ignored).
- lidl_gen_provider test: assert the generated dispatch contains
  getEvents() emitting each event's name/signature/parameters and an
  escaped description, and that events carry no returnType/isInvokable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Fold event introspection into getMethods() to keep the provider ABI stable

The previous approach added a getEvents() virtual to LogosProviderObject,
which inserted a new vtable slot and shifted every later slot — an ABI
break that would misdispatch virtual calls whenever an old and new
host/module were mixed across the in-process plugin boundary.

Instead, report events INSIDE the existing getMethods() call: it now
returns the module's whole interface, with each entry tagged
type "method" or "event" (events omit returnType/isInvokable). The
provider vtable is therefore byte-for-byte unchanged, so old/new hosts
and modules stay binary-compatible — a new host reading an old module
sees no event entries (zero events), and an old host reading a new
module just ignores the "type" field (cosmetic). An entry with no
"type" is treated as a method.

- logos_provider_object.h: remove the getEvents() virtual; document that
  getMethods() carries both, and why.
- generator (lidl_gen_provider): emit events as type "event" entries
  inside getMethods(); tag methods type "method"; no getEvents() output.
- module_proxy / qt_provider_object: getPluginMethods()/getPluginEvents()
  are now type-filtered views of getMethods(), plus a new
  getPluginInterface() returning the whole list. (These are name-
  dispatched Q_INVOKABLEs, not vtable surface — adding them is safe.)
- tests: generator asserts events fold into getMethods() tagged "event";
  ModuleProxy asserts the three filtered views; parser tests unchanged.
- docs: spec/project/docs/README updated, incl. an ABI rationale note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 17:06:12 -03:00
Igor SirotinandClaude Opus 4.7 d77c3dd616 fix: marshal provider events onto the source thread (#68)
* fix: marshal provider events onto the source thread

ModuleProxy's event listener emitted eventResponse directly on whatever thread
the module fired the event from (its worker/FFI thread). QtRemoteObjects then
serialized and sent the event from that foreign thread, racing the source
socket against a method reply being sent from the source thread, which silently
dropped the reply.

This is why a method that emits an event mid-call never returns to the caller
(e.g. delivery_module start(), which emits connectionStateChanged as the node
connects) while a method that emits nothing (createNode) returns fine.

Marshal the emission onto the ModuleProxy's own thread via a queued invocation
so events and method replies are serialized on the single thread
QtRemoteObjects expects to own the source.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: generalize the threading comment

* fix: use AutoConnection so same-thread emits stay synchronous

QueuedConnection deferred every emission, breaking same-thread callers that
emit-then-assert and crashing when a queued lambda outlived the object.
AutoConnection invokes synchronously when already on the source thread and only
queues cross-thread emissions (the actual fix); passing 'this' as context
cancels a queued call if the object is destroyed first.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 09:35:25 -04:00
Iuri Matias 4e20614cda add universal qt-free provider interface (#67)
add universal qt-free provider interface

address review
2026-05-22 17:44:07 -04:00
Iuri Matias c87f3437e3 add overloads supporting nlohmann::json as intermediate steps to remove qt (#66) 2026-05-22 16:08:24 -04:00
Iuri Matias 3eea564de1 overload with method that don't use QString (#65) 2026-05-21 15:37:50 -04:00
Iuri Matias e29ba9b185 overload with method that don't use QString (#64)
overload with method that don't use QString

overload with method that don't use QString

overload with method that don't use QString

overload with method that don't use QString
2026-05-21 14:04:25 -04:00
Dario Lipicar 8bdbd13848 Extend universal modules with module context (#61)
* extend universal modules with module context

* implement module calls and events for universal modules

* pr comments
2026-05-19 12:49:15 -03:00
Dario Lipicar 25c88f4d48 support non-local remote transports (#57)
* support non-local remote transports

* fix LogosResult

* allow getting client over specific transport

* fix ssl

* investiage ssl error

* pr comments

* allow transport set configuration on any module

* pr comments

* add docs

* pr comments

* propagate only non-qt dependencies

* restore ABI compatibility
2026-05-07 12:27:14 -03:00
Dario Lipicar ecd369d48b properly handle subscribers to all events (#56) 2026-04-22 15:31:20 -03:00
Iuri Matias f7c855b110 add logos result type (#55) 2026-04-21 09:38:37 -04:00
Iuri Matias 04b75c84b8 add setProperty without using qt type (#52) 2026-04-16 13:15:18 -04:00
Iuri Matias 1a0cb031db add overloards using cpp types to replace qt ones later (#51) 2026-04-16 12:41:17 -04:00
Iuri Matias 1468180b25 add support for new types (#50) 2026-04-13 13:29:26 -04:00
Dario Lipicar 2a21637e02 fix async call crash (#49)
* fix async call crash

* add regression test
2026-04-10 10:39:14 -04:00
Dario Lipicar 8b1cfadf09 make async method calls truly async (#48)
* make async method calls truly async

* PR comments
2026-04-09 11:37:51 -03:00
Khushboo-dev-cppandDario Lipicar 38006e7240 add support for QVariantList and QVariantMap (#31) (#32)
Co-authored-by: Dario Lipicar <lipigl@gmail.com>
2026-03-31 14:02:35 +02:00
Dario Lipicar 01221559b7 add support for QVariantList and QVariantMap (#31) 2026-03-26 10:12:18 -03:00
Iuri MatiasandLogos Workspace 02baa918a8 remove proxy api (moved to logos-module-client) (#30)
Co-authored-by: Logos Workspace <logos@workspace.local>
2026-03-25 15:00:21 -04:00
Iuri MatiasandLogos Workspace 21f8fb43d3 abstract/move some of proxy api logic to cpp-sdk (#28)
Co-authored-by: Logos Workspace <logos@workspace.local>
2026-03-25 08:46:45 -04:00
Iuri MatiasandLogos Workspace 4197ee1830 Finish Abstraction & Refactor (Ongoing) - part 1 (#25)
* refactor: abstract connection/transport; and clearly separate qt remote obj and qt local into separate implementations

* abstract qt remote registry

* add mock implementation; these serves to further test the abstraction but also useful for testing modules later

* use LogosObject instead of QObject

* abstract provider side

* updates to use new api

* re-add async api back

---------

Co-authored-by: Logos Workspace <logos@workspace.local>
2026-03-23 11:45:25 -04:00
Khushboo-dev-cpp 128180971c feat: add auto support for async calls (#21) 2026-03-19 15:57:08 -04:00
Eric a4bd66cd6e add Logos instance id to registry url (#20)
Allows multiple Logos core instances to run on the same machine by giving appending a unique instance identifier to each registry url.
2026-03-16 10:43:39 -04:00
Vedran 5c49a0d6a4 fix: redact sensitive data from debug logs (#18)
Remove logging of method arguments. It may contain private keys,
DB passwords, auth tokens, and token values. Log only method
names and argument counts for debugging.

- https://github.com/status-im/infra-logos/issues/1
2026-02-25 09:15:39 -05:00
Arnaud 4fdf157120 feat: LogosResult (#14)
* Add LogosResult

* Add documentation for complex types

* Add get type util function

* Add more shorthand functions

* Add bool support

* Provide more shorthand functions

* Throw exception on bad access

* Fix typo in doc
2026-02-25 09:13:43 -05:00
Iuri Matias 63bcab1b42 remove unused files 2026-02-03 10:36:07 -05:00
Iuri Matias f649e0365c Merge pull request #10 from logos-co/feat/add-qstringlist-as-argument
feat: add QStringList, QByteArray and QUrl arguments
2026-02-03 08:59:28 -05:00
Arnaud b7a556483a Add QUrl argument 2026-02-03 10:57:53 +04:00
Arnaud d4e6255a28 Add QByteArray arg 2026-02-03 07:46:11 +04:00
Arnaud c61215a250 Add QStringList argument 2026-02-02 10:01:58 +04:00
Iuri Matias a8b2d5b083 fixes issue with two int parameters at the end by making timeout a special type 2025-12-11 13:40:41 -05:00
Iuri Matias 3c82d99f20 fix return of getPluginMethods 2025-12-02 13:21:51 -05:00
Iuri Matias c754c83f27 add support for a 'local' mode that does not use separate processes. required for some platforms such as mobile.
support local mode

some refactor

some refactor
2025-12-02 13:21:23 -05:00
Iuri Matias bb5498edef feat: add nix flake
feat: add nix flake

test
2025-10-02 16:42:25 -04:00
Iuri Matias 65aa4a1b24 feat: move logos-cpp-sdk to its own repo 2025-09-30 14:56:47 -04:00