Skip to main content

active_rpc/
lib.rs

1//! Active RPC — capability-based, promise-pipelined RPC for Active.
2//!
3//! Active RPC moves Active Infinity modules and capabilities between agents.
4//! It is built around five ideas:
5//!
6//! 1. **Capabilities, not ambient authority.** A capability is an unforgeable
7//!    128-bit id minted by a kernel. Holding it is the only permission needed,
8//!    attenuation can only narrow it, and dropping the last handle notifies the
9//!    provider.
10//! 2. **Promises that pipeline.** A pending result can be passed to another
11//!    call, so a chain costs one provider round-trip instead of one per step.
12//! 3. **Lanes and channels.** One agent runs many lanes with independent
13//!    budgets and speaks on many channels at once, including transfers of
14//!    capabilities.
15//! 4. **Domain operations.** `evaluate`, `why`, `impact`, `subgraph` and `patch`
16//!    operate directly on Infinity modules under the capability's budget.
17//! 5. **Transports as adapters.** In-process, shared memory, TCP, QUIC and a
18//!    gRPC/Connect bridge carry the same envelope, so capability semantics do
19//!    not depend on the wire.
20//!
21//! # Example
22//!
23//! ```
24//! use active_rpc::cap::CapAttrs;
25//! use active_rpc::domain::ModuleProvider;
26//! use active_rpc::value::{Arg, Value};
27//! use active_rpc::{Agent, Budget};
28//!
29//! # fn main() -> Result<(), active_rpc::Error> {
30//! // A module capability with a call budget.
31//! let mut provider = ModuleProvider::new();
32//! let object = provider.install(active_rpc::domain::module_from_source(
33//!     "port = 8080\n",
34//!     "demo.active",
35//! )?);
36//! let agent = Agent::new();
37//! let provider_id = agent.register(Box::new(provider));
38//! let cap = agent.mint(provider_id, object, CapAttrs::new(&["stats"]))?;
39//! let lane = agent.create_lane("main", Budget::default())?;
40//!
41//! let promise = agent.call(lane, &cap, "stats", vec![])?;
42//! let stats = promise.value()?;
43//! assert!(matches!(stats, Value::Map(_)));
44//! # Ok(())
45//! # }
46//! ```
47
48#![forbid(unsafe_code)]
49#![deny(missing_docs)]
50#![allow(missing_docs)] // item-level docs live in the specs; see docs/spec/wire.md
51
52pub mod budget;
53pub mod cap;
54pub mod channel;
55pub mod domain;
56pub mod error;
57pub mod kernel;
58pub mod lane;
59pub mod promise;
60pub mod security;
61pub mod tool;
62pub mod transport;
63pub mod value;
64pub mod wire;
65
66pub use budget::{Budget, BudgetMeter};
67pub use cap::{CapAttrs, CapHandle, CapId, CapRecord, ProviderId, ToolPolicy};
68pub use channel::{Channel, ChannelId, Direction, Message};
69pub use error::{Error, Result};
70pub use kernel::{Agent, Event, PromiseHandle, Provider};
71pub use lane::{Lane, LaneId};
72pub use promise::{PromiseId, PromiseState};
73pub use value::{Arg, Call, Response, Value};
74pub use wire::{CapDescriptor, Envelope, Kind, WireLimits};
75
76/// Crate version.
77pub const VERSION: &str = env!("CARGO_PKG_VERSION");
78
79/// Protocol version carried in every envelope.
80pub const PROTOCOL_VERSION: u8 = wire::VERSION;
81
82/// Methods every module capability can be granted.
83pub const MODULE_METHODS: &[&str] = domain::METHODS;