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}