gemini_adk_fluent_rs/
primitives.rs

1//! # The L2 contract — authoring
2//!
3//! This module is the *engineered surface* of the authoring layer: the closed
4//! set of primitives L2 exposes to applications, curated and named. L0 moves
5//! frames; L1 gives them meaning and enforces it; this layer makes a whole
6//! application sayable — in one fluent expression, or in one JSON document.
7//!
8//! **L2 promises:** two equivalent ways to state a session. In code: the
9//! [`Live`] builder and the [`AgentBuilder`] combinators, composed through
10//! eight one-letter algebras — [`S`]tate `>>`, [`C`]ontext `+`, [`T`]ools `|`,
11//! [`P`]rompt `+`, [`M`]iddleware `|`, [`A`]rtifacts `+`, [`E`]valuation `|`,
12//! [`G`]uards `|`. As data: [`SessionSpec`], the same session as one
13//! serializable document, with load-time validation and offline tests. What
14//! serializes, runs; what can fail, fails before connect
15//! ([`check_contracts`], [`SessionSpec::validate`]).
16//!
17//! **L2 never:** invents runtime semantics. Every builder method lowers to an
18//! L1 primitive; every spec field lowers to a builder method. This layer adds
19//! *phrasing*, not *behavior* — which is why the JSON document and the fluent
20//! chain stay equivalent.
21//!
22//! The primitives, by concern:
23//!
24//! | Concern | Primitives |
25//! |---|---|
26//! | Voice session | [`Live`] (·builder → connect → [`LiveHandle`](gemini_adk_rs::live::LiveHandle)) |
27//! | Text agents | [`AgentBuilder`], [`Pipeline`] `>>`, [`FanOut`] `\|`, `*` loops, [`until`], `/` fallback |
28//! | The algebra | [`S`], [`C`], [`T`], [`P`], [`M`], [`A`], [`E`], [`G`] |
29//! | Session as data | [`SessionSpec`], [`SpecResources`], [`SpecTest`] (`SessionSpec::run_tests`) |
30//! | Proof before connect | [`check_contracts`], [`ContractViolation`] |
31//! | Telephony | [`TwilioCall`] (·attach — a phone call on the same pump as a microphone) |
32//! | Ergonomics | [`let_clone!`](crate::let_clone) |
33//!
34//! Five lines to a governed voice application (add the `voice-io` feature for
35//! `voice::Talk::talk`):
36//!
37//! ```ignore
38//! // `ignore`: `.talk()` exists only with the `voice-io` feature.
39//! let session = Live::builder()
40//!     .instruction("You are a helpful concierge.")
41//!     .greeting("Greet the caller.")
42//!     .govern(flow)
43//!     .connect_from_env().await?;
44//! session.talk().await?;      // microphone in, speakers out, barge-in handled
45//! ```
46
47pub use crate::builder::AgentBuilder;
48pub use crate::live::Live;
49
50pub use crate::operators::{FanOut, Pipeline, until};
51
52pub use crate::compose::artifacts::A;
53pub use crate::compose::context::C;
54pub use crate::compose::eval::E;
55pub use crate::compose::guards::G;
56pub use crate::compose::middleware::M;
57pub use crate::compose::prompt::P;
58pub use crate::compose::state::S;
59pub use crate::compose::tools::T;
60
61pub use crate::spec::{SessionSpec, SpecResources, SpecTest};
62
63pub use crate::telephony::TwilioCall;
64pub use crate::testing::{ContractViolation, check_contracts};
65
66#[cfg(test)]
67mod contract {
68    //! The drift guard: every primitive the module docs name must exist and
69    //! be reachable from this path.
70    #[test]
71    fn every_named_primitive_is_reachable() {
72        use super::*;
73        fn is_type<T: ?Sized>() {}
74        is_type::<Live>();
75        is_type::<TwilioCall>();
76        is_type::<AgentBuilder>();
77        is_type::<Pipeline>();
78        is_type::<FanOut>();
79        is_type::<S>();
80        is_type::<C>();
81        is_type::<T>();
82        is_type::<P>();
83        is_type::<M>();
84        is_type::<A>();
85        is_type::<E>();
86        is_type::<G>();
87        is_type::<SessionSpec>();
88        is_type::<SpecResources>();
89        is_type::<SpecTest>();
90        is_type::<ContractViolation>();
91        let _ = until(|_| true);
92        let _ = check_contracts;
93    }
94}