1//! Capabilities: what a place Whiskers runs can offer, one small trait each. 2//! 3//! An adapter is a type that holds some ports and says which it holds by implementing the `Has…` trait of 4//! each. Nothing obliges it to hold them all: the native binary holds every one, a Worker that serves only the 5//! hubs holds three. What is served is then a question the compiler answers. `whiskers-service` builds a route 6//! only on the capabilities it needs (`Service::check` requires `HasJudge + HasClock`, and an adapter without 7//! them cannot call it), and `whiskers-conformance` selects the laws of a capability only for an adapter that 8//! has it. There is no stand-in port and no "not configured" answer for a capability the adapter does not 9//! have: the route is not there. 10//! 11//! Each trait names the port's type and hands out a reference to it. The ports are not boxed: an adapter is a 12//! build-time choice, and a Worker's futures cannot be `Send`, which a `dyn` with a `Send` bound would demand. 13//! 14//! **One household, one writer.** Every stateful capability of one adapter must behave as if exactly one thing 15//! at a time writes a household's state. How is the adapter's business: natively, locks in one process; on 16//! Cloudflare, one Durable Object per household (single-threaded, so each `merge` is atomic by construction); 17//! under celld, the same object, owned by exactly one node at a time. An adapter whose stateful capabilities 18//! are not serialised together (the hubs on one writer, the allowance on another) is not an adapter: the 19//! conformance suite's concurrency checks exist to catch it. 20//! 21//! [`Backend`] is the name for "every capability", for the adapter that is complete (the native binary). 22 23use crate::allowance::Allowance; 24use crate::embed::Embedder; 25use crate::hub::{ChatHub, HouseholdHub, MemoryHub}; 26use crate::journal::Journal; 27use crate::judge::Judge; 28use crate::pictures::PictureShelf; 29use crate::think::Thinker; 30use crate::time::Clock; 31use crate::voice::Voice; 32 33/// What Whiskers remembers. 34pub trait HasMemory { 35 type Memory: MemoryHub; 36 fn memory(&self) -> &Self::Memory; 37} 38 39/// The grown-ups' choices and the day's time. Besides its own sync route, the routes that apply a policy 40/// (the thinking window, the voice cap, the usage screen) read the household's choices from it. 41pub trait HasHousehold { 42 type Household: HouseholdHub; 43 fn household(&self) -> &Self::Household; 44} 45 46/// The one running session. 47pub trait HasChat { 48 type Chat: ChatHub; 49 fn chat(&self) -> &Self::Chat; 50} 51 52/// The one append-only log of everything said. 53pub trait HasJournal { 54 type Journal: Journal; 55 fn journal(&self) -> &Self::Journal; 56} 57 58/// The pictures that go with memories. 59pub trait HasPictures { 60 type Pictures: PictureShelf; 61 fn pictures(&self) -> &Self::Pictures; 62} 63 64/// What may be spent: the thinking window and the day's voice characters. 65pub trait HasAllowance { 66 type Allowance: Allowance; 67 fn allowance(&self) -> &Self::Allowance; 68} 69 70/// Jev's decisions. 71pub trait HasJudge { 72 type Judge: Judge; 73 fn judge(&self) -> &Self::Judge; 74} 75 76/// Text to vectors. 77pub trait HasEmbedder { 78 type Embedder: Embedder; 79 fn embedder(&self) -> &Self::Embedder; 80} 81 82/// The natural voice. 83pub trait HasVoice { 84 type Voice: Voice; 85 fn voice(&self) -> &Self::Voice; 86} 87 88/// The language model. 89pub trait HasThinker { 90 type Thinker: Thinker; 91 fn thinker(&self) -> &Self::Thinker; 92} 93 94/// The time. 95pub trait HasClock { 96 type Clock: Clock; 97 fn clock(&self) -> &Self::Clock; 98} 99 100/// Every capability. There is nothing to implement: a type is a `Backend` exactly when it implements all the 101/// `Has…` traits, so a capability added to this list is a compile error in every adapter that claims to be 102/// complete, until it has it. 103pub trait Backend: 104 HasMemory 105 + HasHousehold 106 + HasChat 107 + HasJournal 108 + HasPictures 109 + HasAllowance 110 + HasJudge 111 + HasEmbedder 112 + HasVoice 113 + HasThinker 114 + HasClock 115{ 116} 117 118impl<T> Backend for T where 119 T: HasMemory 120 + HasHousehold 121 + HasChat 122 + HasJournal 123 + HasPictures 124 + HasAllowance 125 + HasJudge 126 + HasEmbedder 127 + HasVoice 128 + HasThinker 129 + HasClock 130{ 131}