From 9b4c8c49a0a369db5cc49cceedf33dbcbea6bf0e Mon Sep 17 00:00:00 2001 From: kaichaosun Date: Thu, 25 Jun 2026 18:28:26 +0800 Subject: [PATCH] chore: rename default to ephemeral --- bin/chat-cli/src/main.rs | 108 ++---------------- .../client/examples/message-exchange/main.rs | 4 +- crates/client/src/builder.rs | 32 +++--- crates/client/src/lib.rs | 2 +- crates/client/src/logos.rs | 9 +- crates/client/tests/saro_and_raya.rs | 6 +- 6 files changed, 37 insertions(+), 124 deletions(-) diff --git a/bin/chat-cli/src/main.rs b/bin/chat-cli/src/main.rs index 27aaee1..b673c52 100644 --- a/bin/chat-cli/src/main.rs +++ b/bin/chat-cli/src/main.rs @@ -9,8 +9,7 @@ use anyhow::{Context, Result}; use clap::{Parser, ValueEnum}; use crossbeam_channel::Receiver; use logos_chat::{ - ChatClient, ChatClientBuilder, ChatStore, Event, HttpRegistry, IdentityProvider, - RegistrationService, StorageConfig, Transport, + ChatClient, ChatStore, Event, IdentityProvider, LogosChatClient, RegistrationService, Transport, }; use app::ChatApp; @@ -59,9 +58,9 @@ struct Cli { #[arg(long)] smoketest: bool, - /// Optional KeyPackage registry base URL. When set, uses the HTTP-backed - /// registry instead of the in-memory `EphemeralRegistry`. - /// Example: `--registry-url http://localhost:8080`. + /// Override the Logos registry endpoint (account + keypackage store). When + /// omitted, the preconfigured endpoint is used. + /// Example: `--registry-url http://127.0.0.1:18080`. #[arg(long)] registry_url: Option, } @@ -108,33 +107,12 @@ fn run(transport: T, cli: &Cli) -> Result<()> { .to_str() .context("db path contains non-UTF-8 characters")? .to_string(); - let storage = StorageConfig::Encrypted { - path: db_str, - key: "chat-cli".to_string(), - }; - match cli.registry_url.as_deref() { - Some(url) => { - let registry = HttpRegistry::new(url); - let (client, events) = ChatClientBuilder::default() - .transport(transport) - .storage_config(storage) - .registration(registry) - .build() - .map_err(|e| anyhow::anyhow!("{e:?}")) - .context("failed to open chat client with HTTP registry")?; - launch_tui(client, events, cli) - } - None => { - let (client, events) = ChatClientBuilder::default() - .transport(transport) - .storage_config(storage) - .build() - .map_err(|e| anyhow::anyhow!("{e:?}")) - .context("failed to open chat client")?; - launch_tui(client, events, cli) - } - } + let (client, events) = + LogosChatClient::open(transport, db_str, "chat-cli", cli.registry_url.as_deref()) + .map_err(|e| anyhow::anyhow!("{e:?}")) + .context("failed to open chat client")?; + launch_tui(client, events, cli) } fn launch_tui( @@ -160,74 +138,6 @@ where result } -#[cfg_attr(not(logos_delivery), allow(dead_code, unused_variables))] -fn run_logos_delivery(cli: Cli) -> Result<()> { - #[cfg(logos_delivery)] - { - use transport::logos_delivery::{Config, Service}; - - eprintln!("Starting logos-delivery node (preset={})...", cli.preset); - eprintln!("This may take a few seconds while connecting to the network."); - - let logos_cfg = Config { - preset: cli.preset.clone(), - tcp_port: cli.port, - ..Default::default() - }; - let delivery = Service::start(logos_cfg).context("failed to start logos-delivery")?; - - eprintln!("Node connected. Initializing chat client..."); - - let data_dir = cli - .db - .as_ref() - .and_then(|p| p.parent()) - .map(|p| p.to_path_buf()) - .unwrap_or_else(|| cli.data.clone()); - - let (client, events) = match cli.db { - Some(ref path) => { - let db_str = path - .to_str() - .context("db path contains non-UTF-8 characters")? - .to_string(); - - logos_chat::ChatClientBuilder::default() - .storage_config(logos_chat::StorageConfig::Encrypted { - path: db_str, - key: "chat-cli".to_string(), - }) - .transport(delivery) - .build() - .map_err(|e| anyhow::anyhow!("{e:?}")) - .context("failed to open persistent client")? - } - None => logos_chat::ChatClientBuilder::default() - .transport(delivery) - .build() - .map_err(|e| anyhow::anyhow!("{e:?}")) - .context("failed to open chat client")?, - }; - - let mut app = ChatApp::new(client, events, &cli.name, &data_dir)?; - - if cli.smoketest { - return Ok(()); - } - - let mut terminal = ui::init().context("failed to initialize terminal")?; - let result = run_app(&mut terminal, &mut app); - ui::restore().context("failed to restore terminal")?; - return result; - } - - #[cfg(not(logos_delivery))] - anyhow::bail!( - "logos-delivery transport is not available in this build.\n\ - Build with LOGOS_DELIVERY_LIB_DIR set to enable it." - ) -} - fn run_app(terminal: &mut ui::Tui, app: &mut ChatApp) -> Result<()> where I: IdentityProvider + Send, diff --git a/crates/client/examples/message-exchange/main.rs b/crates/client/examples/message-exchange/main.rs index 2e87564..08dbcb0 100644 --- a/crates/client/examples/message-exchange/main.rs +++ b/crates/client/examples/message-exchange/main.rs @@ -6,13 +6,13 @@ fn main() { let bus = MessageBus::default(); let reg = EphemeralRegistry::new(); - let (mut saro, saro_events) = ChatClientBuilder::default() + let (mut saro, saro_events) = ChatClientBuilder::ephemeral() .transport(InProcessDelivery::new(bus.clone())) .registration(reg.clone()) .build() .unwrap(); - let (mut raya, raya_events) = ChatClientBuilder::default() + let (mut raya, raya_events) = ChatClientBuilder::ephemeral() .transport(InProcessDelivery::new(bus)) .registration(reg) .build() diff --git a/crates/client/src/builder.rs b/crates/client/src/builder.rs index 654e94c..05df167 100644 --- a/crates/client/src/builder.rs +++ b/crates/client/src/builder.rs @@ -11,8 +11,8 @@ use crate::event::Event; /// Marker for a builder field that has not been configured. A field left `Unset` /// at `build()` is a compile error: `build()` requires every component to have a -/// concrete type. Use [`ChatClientBuilder::default`] to start from filled-in -/// defaults instead. +/// concrete type. Use [`ChatClientBuilder::ephemeral`] to start from filled-in +/// throwaway components instead. pub struct Unset; pub struct ChatClientBuilder { @@ -22,15 +22,15 @@ pub struct ChatClientBuilder { storage: S, } +impl Default for ChatClientBuilder { + fn default() -> Self { + Self::new() + } +} + impl ChatClientBuilder { /// An empty builder: every component is `Unset` and must be supplied before - /// [`build`](ChatClientBuilder::build). For the common case, prefer - /// [`default`](ChatClientBuilder::default), which pre-fills the components. - // - // `Default` is intentionally not implemented: `default()` below is a distinct - // constructor that returns a *different*, pre-filled builder type, which the - // `Default` trait (`fn() -> Self`) cannot express. - #[allow(clippy::new_without_default)] + /// [`build`](ChatClientBuilder::build). pub fn new() -> Self { Self { ident: Unset, @@ -40,12 +40,12 @@ impl ChatClientBuilder { } } - /// A builder pre-filled with the default identity, registration, and storage. - /// Only the transport is left to set; override any default with the matching - /// setter. A complete entry point on its own — there is no need to call - /// [`new`](ChatClientBuilder::new) first. - #[allow(clippy::should_implement_trait)] - pub fn default() -> ChatClientBuilder { + /// A builder pre-filled with throwaway components — a random identity, an + /// ephemeral (in-memory) registry, and in-memory storage. Intended for tests, + /// examples, and local runs that need no persistence or network services; + /// override any slot with the matching setter. A complete entry point on its + /// own — only the transport is left to set before [`build`](ChatClientBuilder::build). + pub fn ephemeral() -> ChatClientBuilder { Self::new() .ident(DelegateSigner::random()) .registration(EphemeralRegistry::new()) @@ -109,7 +109,7 @@ type Built = Result<(ChatClient, Receiver), Clien /// `build()` exists only once every component has a concrete type. Any field /// still `Unset` (always at least the transport, which has no default) fails the /// bounds below, so an incomplete builder is a compile error rather than a -/// runtime one. Start from [`default`](ChatClientBuilder::default) to fill the +/// runtime one. Start from [`ephemeral`](ChatClientBuilder::ephemeral) to fill the /// identity/registration/storage slots, then set the transport. impl ChatClientBuilder where diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index 718f70b..d916494 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -9,10 +9,10 @@ mod logos; pub use builder::{ChatClientBuilder, Unset}; pub use client::{ChatClient, Transport}; pub use delegate::DelegateSigner; -pub use logos::LogosChatClient; 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 index 62f1df3..e50bd02 100644 --- a/crates/client/src/logos.rs +++ b/crates/client/src/logos.rs @@ -35,8 +35,9 @@ 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`. The identity and - /// registry are preconfigured; the registry endpoint is a placeholder for now. + /// 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. @@ -44,11 +45,13 @@ where 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(REGISTRY_ENDPOINT)) + .registration(HttpRegistry::new(endpoint)) .storage_config(StorageConfig::Encrypted { path: db_path.into(), key: db_key.into(), diff --git a/crates/client/tests/saro_and_raya.rs b/crates/client/tests/saro_and_raya.rs index 4ebbba0..36a45a0 100644 --- a/crates/client/tests/saro_and_raya.rs +++ b/crates/client/tests/saro_and_raya.rs @@ -39,7 +39,7 @@ fn create_test_client( logos_chat::ClientError, > { let d = InProcessDelivery::new(message_bus); - ChatClientBuilder::default() + ChatClientBuilder::ephemeral() .transport(d) .registration(reg) .build() @@ -108,7 +108,7 @@ fn direct_v1_standalone_integration() { // Build saro's client with its associated delegate so its outbound messages // carry a credential the receiver can verify against the published bundle. - let (mut saro, _saro_events) = ChatClientBuilder::default() + let (mut saro, _saro_events) = ChatClientBuilder::ephemeral() .ident(saro_delegate) .transport(InProcessDelivery::new(bus.clone())) .registration(reg_service.clone()) @@ -293,7 +293,7 @@ fn malformed_inbound_surfaces_as_error_event() { let delivery = FailingDelivery::new(); let inbound_tx = delivery.inbound_sender(); - let (_client, events) = ChatClientBuilder::default() + let (_client, events) = ChatClientBuilder::ephemeral() .transport(delivery) .build() .expect("client create");