From 7a51ed6a21d6532b3beef0b6b7973c4af88c243f Mon Sep 17 00:00:00 2001 From: kaichaosun Date: Mon, 29 Jun 2026 14:03:34 +0800 Subject: [PATCH] feat: add logos default client --- crates/client/src/lib.rs | 2 ++ crates/client/src/logos.rs | 61 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 crates/client/src/logos.rs diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index becf852..d916494 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -4,6 +4,7 @@ mod delegate; mod delivery_in_process; mod errors; mod event; +mod logos; pub use builder::{ChatClientBuilder, Unset}; pub use client::{ChatClient, Transport}; @@ -11,6 +12,7 @@ pub use delegate::DelegateSigner; pub use delivery_in_process::{InProcessDelivery, MessageBus}; pub use errors::ClientError; pub use event::{Event, MessageSender}; +pub use logos::LogosChatClient; // Re-export types callers need to interact with ChatClient. pub use libchat::{ diff --git a/crates/client/src/logos.rs b/crates/client/src/logos.rs new file mode 100644 index 0000000..152fa61 --- /dev/null +++ b/crates/client/src/logos.rs @@ -0,0 +1,61 @@ +//! The opinionated Logos client. +//! +//! [`ChatClientBuilder`] is generic and can only default the zero-config +//! components (random identity, ephemeral registry, in-memory storage) — it has +//! no way to know a registry endpoint or a database path, so its defaults are +//! the test-grade ones. `LogosChatClient` is the layer that *does* commit to a +//! stack: a delegate identity, the HTTP keypackage + account registry, and +//! encrypted on-disk storage. It exists so independently built clients share the +//! same production services instead of each re-deriving them. +//! +//! Only the transport is left to the caller: it carries native dependencies and +//! environment-specific configuration that belong to the binary, not here. + +use crossbeam_channel::Receiver; +use libchat::{ChatStorage, StorageConfig}; + +use crate::ChatClientBuilder; +use crate::client::{ChatClient, Transport}; +use crate::delegate::DelegateSigner; +use crate::errors::ClientError; +use crate::event::Event; +use components::HttpRegistry; + +// The endpoint for account and keypackage registration service. +const REGISTRY_ENDPOINT: &str = "https://devnet.chat-kc.logos.co"; + +/// A [`ChatClient`] wired to the Logos service stack: a [`DelegateSigner`] +/// identity, the HTTP keypackage + account registry ([`HttpRegistry`], which is +/// both the keypackage store and the account → device directory), and encrypted +/// [`ChatStorage`]. Only the transport `T` is supplied by the caller. +pub type LogosChatClient = ChatClient; + +impl LogosChatClient +where + T: Transport + Send + 'static, +{ + /// Open a client on the Logos stack over `transport`, persisting to the + /// encrypted database at `db_path` unlocked with `db_key`. When `registry_url` + /// is `Some`, it overrides the preconfigured registry endpoint (e.g. a local + /// deployment); otherwise the baked-in endpoint is used. + /// + /// `db_path` is a per-client location and `db_key` is a secret, so both are + /// caller-supplied — never baked into the library. + pub fn open( + transport: T, + db_path: impl Into, + db_key: impl Into, + registry_url: Option<&str>, + ) -> Result<(Self, Receiver), ClientError> { + let endpoint = registry_url.unwrap_or(REGISTRY_ENDPOINT); + ChatClientBuilder::new() + .ident(DelegateSigner::random()) + .transport(transport) + .registration(HttpRegistry::new(endpoint)) + .storage_config(StorageConfig::Encrypted { + path: db_path.into(), + key: db_key.into(), + }) + .build() + } +}