nerve-ipc-core 0.1.1

Core IPC layer for the NERVE protocol: authentication, request lifecycle, transport-agnostic dispatch, Unix Domain Socket server, and WebSocket server.
Documentation
//! Core IPC layer for the NERVE protocol.
//!
//! `nerve-ipc-core` provides the runtime infrastructure for local NERVE
//! daemon communication: it accepts NERVE-framed binary messages from a
//! browser extension (via WebSocket) and from local tools (via Unix Domain
//! Socket), authenticates connections, dispatches frames, and manages
//! per-connection request lifecycles.
//!
//! # When to use this crate
//!
//! Use `nerve-ipc-core` when you are building a transport layer for the
//! NERVE protocol — a local daemon, a custom server, or a system-integration
//! test harness.
//!
//! If you only need to encode and decode NERVE frames without running a
//! server, use [`nerve-ipc`](https://crates.io/crates/nerve-ipc) directly.
//! `nerve-ipc-core` does not re-export any `nerve-ipc` types; you will need
//! `nerve-ipc` as a direct dependency to access types such as
//! `nerve_protocol::types::RequestId` or the codec functions.
//!
//! # Quick start
//!
//! The daemon binary starts a WebSocket server (for the browser extension) and
//! a UDS server (for local tools) concurrently:
//!
//! ```no_run
//! use nerve_ipc_core::{Config, auth};
//! use std::thread;
//!
//! fn main() -> std::io::Result<()> {
//!     let config = Config::default();
//!
//!     // Load the per-install secret token, creating it on first run.
//!     let token = auth::load_or_create_token(&config.token_path)?;
//!
//!     // Start the WebSocket server (browser extension transport) in a thread.
//!     let ws_config = config.clone();
//!     let ws_token = token.clone();
//!     thread::spawn(move || {
//!         nerve_ipc_core::ws_server::run_ws(ws_config, ws_token)
//!             .expect("WebSocket server failed");
//!     });
//!
//!     // Start the Unix Domain Socket server (local tool transport).
//!     // This call blocks until the listener is closed.
//!     nerve_ipc_core::server::run(&config.uds_path)
//! }
//! ```
//!
//! # Core concepts
//!
//! ## Transports
//!
//! Two independent transports share the same dispatch logic:
//!
//! - **[`server`]** — Unix Domain Socket server for local tool integrations.
//!   Entry point: [`server::run`].
//! - **[`ws_server`]** — WebSocket server on `127.0.0.1:9001` for the browser
//!   extension. Entry point: [`ws_server::run_ws`]. All connections are
//!   authenticated at the HTTP upgrade step via Origin check and per-install
//!   token.
//!
//! Both transports call the same [`dispatch_frame`] function:
//!
//! ```text
//! Browser Extension ──WebSocket──▶ ws_server  ──┐
//!                                                ├──▶ dispatch_frame() ──▶ RequestTable
//! Local Tool        ──UDS──────▶ server       ──┘
//! ```
//!
//! ## Dispatch
//!
//! [`dispatch_frame`] is transport-agnostic: it reads a decoded NERVE frame,
//! updates the [`RequestTable`], and returns a [`DispatchAction`] telling the
//! transport what to do next — write a reply, forward to the AI daemon, or do
//! nothing. It performs no I/O itself.
//!
//! ## Request lifecycle
//!
//! Each accepted connection owns a [`RequestTable`] that tracks in-flight
//! requests for that connection only. A `SearchQuery` frame causes
//! [`dispatch_frame`] to insert the request and return
//! [`DispatchAction::ForwardToAiDaemon`]. A `Cancel` frame marks it
//! [`RequestState::Cancelled`]. The AI daemon checks
//! [`RequestTable::is_cancelled`] before each result and calls
//! [`RequestTable::remove`] on completion. Request IDs are scoped per
//! connection; the same ID on two different connections refers to two
//! independent requests.
//!
//! # Relationship to nerve-ipc
//!
//! | Crate | Role |
//! |---|---|
//! | [`nerve-ipc`](https://crates.io/crates/nerve-ipc) | Wire format, codec, frame types, protocol constants |
//! | `nerve-ipc-core` *(this crate)* | Authentication, request lifecycle, dispatch, UDS server, WebSocket server |
//!
//! `nerve-ipc-core` does not redefine any protocol types. All frame encoding
//! and decoding is performed by `nerve-ipc`. Types such as
//! `nerve_protocol::types::RequestId` and `nerve_protocol::Frame` come from
//! `nerve-ipc` and appear directly in this crate's public API.

pub use config::Config;
pub use dispatch::{DispatchAction, dispatch_frame};
pub use request_table::{RequestState, RequestTable};

pub mod auth;
pub mod config;
pub mod dispatch;
pub mod request_table;
pub mod server;
pub mod ws_server;