Skip to main content

gemini_adk_fluent_rs/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![warn(unreachable_pub)]
3#![forbid(unsafe_code)]
4#![warn(missing_docs)]
5//! # gemini-adk-fluent-rs
6//!
7//! Fluent developer experience layer for the Gemini Live agent stack.
8//! This is the highest-level crate in the workspace, providing a builder API,
9//! operator algebra, and composition modules that sit on top of
10//! [`gemini_adk_rs`] (agent runtime) and [`gemini_genai_rs`] (wire protocol).
11//!
12//! ## Module Organization
13//!
14//! | Module | Purpose |
15//! |--------|---------|
16//! | [`builder`] | Copy-on-write immutable `AgentBuilder` for declarative agent configuration |
17//! | [`compose`] | The eight-namespace operator algebra — `S` state, `C` context, `T` tools, `P` prompts, `M` middleware, `A` artifacts, `E` evaluation, `G` guards |
18//! | [`live`] | `Live` session builder — callback-driven full-duplex event handling |
19//! | [`live_builders`] | Phase and watcher sub-builders for `Live` |
20//! | [`operators`] | `>> | * /` combinators for composing agents |
21//! | [`patterns`] | Pre-built composition patterns for common use cases |
22//! | [`voice`] | Microphone/speaker plumbing; `talk()` needs the `voice-io` feature |
23//! | [`testing`] | Contract checks, data-flow inference, mock harnesses |
24//!
25//! ## Quick Start
26//!
27//! Text generation is on by default (feature `gemini-llm`); set
28//! `GEMINI_API_KEY` and ask a question:
29//!
30//! ```no_run
31//! use gemini_adk_fluent_rs::prelude::*;
32//! use std::sync::Arc;
33//!
34//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
35//! let llm = Arc::new(GeminiLlm::new(GeminiLlmParams::default()));
36//! let agent = AgentBuilder::new("assistant")
37//!     .instruction("You are a concise assistant.")
38//!     .build(llm)?;
39//! let state = State::new();
40//! state.set("input", "Say hello in one sentence.")?;
41//! println!("{}", agent.run(&state).await?);
42//!
43//! // Voice: microphone in, speakers out, barge-in handled — `.talk()` exists
44//! // only with the `voice-io` feature (Linux: libasound2-dev).
45//! let handle = Live::builder()
46//!     .instruction("You are a helpful concierge.")
47//!     .greeting("Greet the caller.")
48//!     .connect_from_env()
49//!     .await?;
50//! # let _ = handle;
51//! # Ok(())
52//! # }
53//! ```
54//!
55//! ## Relationship to Other Crates
56//!
57//! - **`gemini-genai-rs`** (L0): wire protocol, transport, types — re-exported as [`gemini_genai_rs`]
58//! - **`gemini-adk-rs`** (L1): agent runtime, tools, sessions — re-exported as [`gemini_adk_rs`]
59//! - **`gemini-adk-fluent-rs`** (L2): this crate — the builder API and composition algebra
60
61pub mod a2a;
62pub mod builder;
63pub mod compose;
64pub mod conversation;
65pub mod flow_macros;
66pub mod handoff;
67pub mod live;
68pub mod live_builders;
69pub mod motifs;
70pub mod operators;
71pub mod patterns;
72pub mod policy;
73pub mod primitives;
74pub mod simulation;
75pub mod spec;
76pub mod tasks;
77pub mod telephony;
78pub mod testing;
79pub mod voice;
80
81pub use gemini_adk_rs;
82pub use gemini_genai_rs;
83
84// ---------------------------------------------------------------------------
85// Curated submodule homes (the prelude is a kernel, not an everything-glob).
86//
87// The kernel `prelude` (below) re-exports only the ~30 types a typical app
88// touches. Everything else lives in these focused, discoverable modules so
89// `use gemini_adk_fluent_rs::prelude::*` stays small and the rest is one
90// `use gemini_adk_fluent_rs::{live, text, tools, …}` away. Import from the
91// highest-level crate you need.
92// ---------------------------------------------------------------------------
93
94/// Text-agent runtime and combinators (carved out of the kernel `prelude`).
95///
96/// `LlmTextAgent`, the sequential/parallel/loop/fallback/route/race/timeout/map
97/// combinators, and the `TextAgent` trait.
98pub mod text {
99    pub use gemini_adk_rs::text::*;
100}
101
102/// Tool definitions, dispatch, toolsets, the confirmation flow, and frames.
103pub mod tools {
104    pub use gemini_adk_rs::confirmation::*;
105    pub use gemini_adk_rs::extract::{Recognizer, RecordExtractor};
106    pub use gemini_adk_rs::frame::{
107        ConfirmPolicy, FrameSpec, SlotRecognizer, SlotSpec, SlotValidator,
108    };
109    pub use gemini_adk_rs::tool::*;
110    pub use gemini_adk_rs::toolset::*;
111}
112
113/// Code mode: a tool through which the model runs a short Python program
114/// whose functions are the session's own tools, each call governed like a
115/// direct call. See [`Live::code_mode`](crate::live::Live::code_mode).
116pub mod code_mode {
117    pub use gemini_adk_rs::code_mode::*;
118}
119
120/// LLM abstraction: params, requests/responses, and the registry.
121pub mod llm {
122    pub use gemini_adk_rs::llm::*;
123}
124
125/// Concurrent typed state: `State`, `PrefixedState`, `StateKey`, prefix scopes.
126pub mod state {
127    pub use gemini_adk_rs::state::*;
128}
129
130/// Governed-conversation flow primitives: `Flow`, `Step`, `Guard`, `FlowMonitor`.
131pub mod flow {
132    pub use gemini_adk_rs::flow::*;
133}
134
135/// Agent builders, the L1 [`Agent`](gemini_adk_rs::agent::Agent) trait, and
136/// the operator/pattern combinators.
137pub mod agents {
138    pub use crate::builder::*;
139    pub use crate::operators::*;
140    pub use crate::patterns::*;
141    #[doc(inline)]
142    pub use gemini_adk_rs::agent::Agent;
143    pub use gemini_adk_rs::agent_session::*;
144    pub use gemini_adk_rs::orchestration::{self, AgentMode, Resolver, call_agent, provenance};
145}
146
147/// L0 wire-protocol types for raw WebSocket access.
148pub mod wire {
149    pub use gemini_genai_rs::prelude::*;
150}
151
152/// Clone multiple bindings for use in `move` closures, reducing Arc/clone boilerplate.
153///
154/// # Example
155///
156/// ```
157/// use gemini_adk_fluent_rs::let_clone;
158/// use std::sync::Arc;
159///
160/// let state = Arc::new(42);
161/// let writer = Arc::new("hello");
162///
163/// let_clone!(state, writer);
164/// let task = move || format!("{state} {writer}");
165/// assert_eq!(task(), "42 hello");
166/// ```
167#[macro_export]
168macro_rules! let_clone {
169    ($($name:ident),+ $(,)?) => {
170        $(let $name = $name.clone();)+
171    };
172}
173
174/// The kernel prelude — the names a typical application touches.
175///
176/// Deliberately a kernel, not an everything-glob. Anything not here lives in
177/// a focused submodule and is one import away:
178///
179/// | Need | Import |
180/// |------|--------|
181/// | Full Live control plane (persistence, repair, steering, transcripts, contracts) | `use gemini_adk_fluent_rs::live::*;` |
182/// | Text-agent runtime details | `use gemini_adk_fluent_rs::text::*;` |
183/// | Toolsets, confirmation, frames | `use gemini_adk_fluent_rs::tools::*;` |
184/// | State prefixes / `SlotEvidence` | `use gemini_adk_fluent_rs::state::*;` |
185/// | Full flow vocabulary (`CompiledFlow`, `StepAction`, `Violation`, …) | `use gemini_adk_fluent_rs::flow::*;` |
186/// | `Agent` trait + operator/pattern internals | `use gemini_adk_fluent_rs::agents::*;` |
187/// | Conversation compiler internals (`ResolverRegistry`, `StageSpec`, `OverlaySpec`, …) | `use gemini_adk_fluent_rs::conversation::*;` (`Conversation`, `ConversationSpec`, `CompiledConversation` are in the prelude) |
188/// | Serializable scenarios (`Scenario`, `SimStep`) | `use gemini_adk_fluent_rs::simulation::*;` (`Sim` is in the prelude) |
189/// | A2A, motifs, policy, testing, orchestration, credentials, run_config | the same-named module, e.g. `use gemini_adk_fluent_rs::policy::*;` |
190/// | Raw L0 wire types | `use gemini_adk_fluent_rs::wire::*;` |
191pub mod prelude {
192    // ── Voice I/O: `.talk()` on a connected handle (feature `voice-io`) ──
193    #[cfg(feature = "voice-io")]
194    pub use crate::voice::Talk;
195
196    // ── Builders, composition algebra, operators, patterns (headline DX) ──
197    pub use crate::builder::*;
198    pub use crate::compose::{A, C, Ctx, E, G, M, P, S, T};
199    pub use crate::live::Live;
200    // Dynamic instructions (ADK instruction-provider pattern) + tool media.
201    pub use crate::operators::*;
202    pub use crate::patterns::*;
203    pub use gemini_adk_rs::instruction::InstructionProvider;
204    #[cfg(feature = "templates")]
205    pub use gemini_adk_rs::instruction::TemplateInstruction;
206    pub use gemini_adk_rs::tool::media as tool_media;
207    // Build-time validation DX (contract checking, data-flow inference, harness).
208    pub use crate::testing::{
209        AgentHarness, ContractViolation, DataFlowEdge, LiveViolation, check_contracts, check_live,
210        diagnose, infer_data_flow,
211    };
212
213    // The L1 `Agent` trait (`name()` + `run_live()`); the L2 builder is
214    // `AgentBuilder`, so the two names never collide.
215    #[doc(inline)]
216    pub use gemini_adk_rs::agent::Agent;
217
218    // ── Errors ──
219    pub use gemini_adk_rs::error::{AgentError, AgentResult, ConfigError, ToolError};
220
221    // ── Governed flow (core vocabulary; full set in `crate::flow`) ──
222    pub use gemini_adk_rs::flow::{Enforcement, Flow, FlowMonitor, Guard, Verdict};
223
224    // ── Conversations and the model-free simulator ──
225    // The authoring model above `Flow` and the deterministic driver that runs
226    // it without a model. They are the flagship of the crate, so they live on
227    // the same import line as `Live`; the compiler internals stay in
228    // `crate::conversation` and the serializable `Scenario` in
229    // `crate::simulation`.
230    pub use crate::conversation::{
231        CompiledConversation, Conversation, ConversationSpec, RepairPolicy, VoiceTiming,
232    };
233    pub use crate::simulation::Sim;
234
235    // ── State (prefix scopes + `SlotEvidence` in `crate::state`) ──
236    pub use gemini_adk_rs::state::{State, StateKey};
237
238    // ── LLM (core; request/response/registry in `crate::text`) ──
239    pub use gemini_adk_rs::llm::{BaseLlm, GeminiLlm, GeminiLlmParams, LlmError};
240
241    // ── Tools ──
242    pub use gemini_adk_rs::tool::{
243        SimpleTool, ToolContext, ToolDispatcher, ToolFunction, ToolPolicy, TypedTool,
244    };
245    // The `#[tool]` attribute macro — turns an `async fn` into a registrable tool.
246    pub use gemini_adk_rs::tool;
247    // Brings in both the `Extract` struct and the `#[derive(Extract)]` macro.
248    pub use gemini_adk_rs::Extract;
249    // The `#[derive(Frame)]` macro.
250    pub use gemini_adk_rs::Frame;
251
252    // ── Callback contexts (used in `M::` hooks) ──
253    // `ToolContext` in the prelude is what a tool receives
254    // (`gemini_adk_rs::tool::ToolContext`); the `InvocationContext` wrapper of
255    // the same name stays at `gemini_adk_rs::context::ToolContext`.
256    pub use gemini_adk_rs::context::CallbackContext;
257
258    // ── Common Live session types (full control plane in `crate::live`) ──
259    pub use gemini_adk_rs::live::{
260        ContextDelivery, EventCallbacks, ExtractionTrigger, FsPersistence, LiveHandle,
261        LlmExtractor, MemoryPersistence, PersistenceError, RepairConfig, SessionPersistence,
262        SoftTurnDetector, SteeringMode, TranscriptBuffer, TranscriptTurn, TurnExtractor,
263    };
264
265    // ── Text-agent combinators (runtime details in `crate::text`) ──
266    pub use gemini_adk_rs::text::{
267        Chat, DispatchTextAgent, FallbackTextAgent, FnTextAgent, JoinTextAgent, LlmTextAgent,
268        LoopTextAgent, MapOverTextAgent, ParallelTextAgent, RaceTextAgent, RouteRule,
269        RouteTextAgent, RunEvent, RunRequest, RunResult, SequentialTextAgent, TapTextAgent,
270        TaskRegistry, TextAgent, TimeoutTextAgent,
271    };
272
273    // ── L0 wire types an application names (the rest: `crate::wire`) ──
274    pub use gemini_genai_rs::prelude::{
275        ActivityHandling, ApiEndpoint, AudioFormat, AudioTranscriptionConfig,
276        AutomaticActivityDetection, AvatarConfig, Blob, Content, FinishReason, FunctionCall,
277        FunctionCallingBehavior, FunctionDeclaration, FunctionResponse, FunctionResponseScheduling,
278        GenerationConfig, HarmBlockThreshold, HarmCategory, Modality, ModelId, Part, Role,
279        SafetySetting, Sensitivity, ServerMessage, SessionConfig, SessionEvent, SpeechConfig,
280        ThinkingConfig, Tool, TurnCoverage, UsageMetadata, Voice,
281    };
282
283    // `while let Some(event) = agent.stream(..).next().await` needs this trait.
284    pub use futures_util::StreamExt;
285}