Skip to main content

funera_orchestrate/
lib.rs

1//! # funera-orchestrate
2//!
3//! **Easy-to-use orchestration layer for [funera-core].**
4//!
5//! This crate provides a high-level agent API (`Agent`) and a runtime container
6//! (`AgentRuntime`) that together let you integrate funera's LLM agent runtime
7//! into your own projects with minimal boilerplate.
8//!
9//! ## Features
10//!
11//! | Feature | Default | Description |
12//! |---------|---------|-------------|
13//! | `deepseek` | ✅ | DeepSeek provider |
14//! | `openai` | ❌ | OpenAI provider |
15//! | `tool` | ✅ | Tool system (trait, registry, executor) |
16//! | `funera-builtin-tools` | ❌ | Built-in tools (Read, Write, Edit, Shell) |
17//! | `security` | ❌ | Tool policy enforcement |
18//! | `middleware` | ❌ | Event interception pipeline (Inspector + Mutator) |
19//! | `skill` | ❌ | Skill loading and prompt injection |
20//! | `sandbox` | ❌ | Kernel-level subprocess isolation |
21//!
22//! ---
23//!
24//! ## Quick Start
25//!
26//! ```rust,no_run
27//! use funera_orchestrate::{Agent, AgentRuntime, DeepSeekProvider};
28//!
29//! #[tokio::main]
30//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
31//!     let runtime = AgentRuntime::<DeepSeekProvider>::builder()
32//!         .api_key(std::env::var("DEEPSEEK_API_KEY")?)
33//!         .model("deepseek-v4-flash")
34//!         .build()?;
35//!
36//!     let agent = Agent::builder()
37//!         .system_prompt("You are a helpful assistant.")
38//!         .build();
39//!
40//!     let resp = agent.fire("Hello!", &runtime).await?;
41//!     println!("{}", resp.content);
42//!     Ok(())
43//! }
44//! ```
45//!
46//! ## Core Concepts
47//!
48//! | Concept | Type | Description |
49//! |---------|------|-------------|
50//! | **Runtime** | [`AgentRuntime`] | Shared infrastructure + conversation session |
51//! | **Agent** | [`Agent`] | Behavioural config (system prompt, callbacks) |
52//! | **One-shot** | [`Agent::fire`] | Temporary session, discarded after call |
53//! | **Multi-turn** | [`Agent::send`] | Persistent session across calls |
54//! | **Streaming** | [`fire_stream`](Agent::fire_stream) / [`send_stream`](Agent::send_stream) | Token-by-token streaming |
55//!
56//! ## Examples
57//!
58//! ### One-shot query with stream
59//!
60//! ```rust,no_run
61//! # use funera_orchestrate::{Agent, AgentEvent, AgentRuntime, DeepSeekProvider};
62//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
63//! let runtime = AgentRuntime::<DeepSeekProvider>::builder()
64//!     .api_key(std::env::var("DEEPSEEK_API_KEY")?)
65//!     .model("deepseek-v4-flash")
66//!     .build()?;
67//!
68//! let agent = Agent::builder()
69//!     .on_token(|t| print!("{t}"))
70//!     .build();
71//!
72//! let mut rx = agent.fire_stream("Explain Rust's ownership model", &runtime).await?;
73//! while let Some(event) = rx.recv().await {
74//!     if let AgentEvent::Text(t) = event {
75//!         print!("{t}");
76//!     }
77//! }
78//! # Ok(())
79//! # }
80//! ```
81//!
82//! ### Multi-turn conversation with callbacks
83//!
84//! ```rust,no_run
85//! # use funera_orchestrate::{Agent, AgentRuntime, DeepSeekProvider};
86//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
87//! let runtime = AgentRuntime::<DeepSeekProvider>::builder()
88//!     .api_key(std::env::var("DEEPSEEK_API_KEY")?)
89//!     .model("deepseek-v4-flash")
90//!     .build()?;
91//!
92//! let agent = Agent::builder()
93//!     .system_prompt("You are helpful.")
94//!     .on_tool_call(|name, _| eprintln!("[tool] {name}"))
95//!     .on_turn_start(|| eprintln!("--- turn ---"))
96//!     .build();
97//!
98//! let handle = agent.send("Hi, I'm Alice.", runtime).await?;
99//! let (runtime, _resp) = handle.await?;
100//! let handle = agent.send("What's my name?", runtime).await?;
101//! let (_runtime, _resp) = handle.await?;
102//! # Ok(())
103//! # }
104//! ```
105//!
106//! ### Switching models on the same provider
107//!
108//! ```rust,no_run
109//! # use funera_orchestrate::{Agent, AgentRuntime, DeepSeekProvider};
110//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
111//! let fast = AgentRuntime::<DeepSeekProvider>::builder()
112//!     .api_key(std::env::var("DEEPSEEK_API_KEY")?)
113//!     .model("deepseek-v4-flash")
114//!     .build()?;
115//!
116//! let powerful = AgentRuntime::<DeepSeekProvider>::builder()
117//!     .api_key(std::env::var("DEEPSEEK_API_KEY")?)
118//!     .model("deepseek-r1")
119//!     .build()?;
120//!
121//! let agent = Agent::builder().build();
122//!
123//! let (fast, _) = agent.send("Hello", fast).await?.await?;              // fast model
124//! agent.fire("What is Rust?", &powerful).await?;                        // powerful model (temp)
125//! let (_fast, _) = agent.send("Tell me more", fast).await?.await?;       // back to fast
126//! # Ok(())
127//! # }
128//! ```
129//!
130//! ### Security configuration
131//!
132//! Requires the `security` feature (and optionally `funera-builtin-tools`, `sandbox`).
133//!
134//! ```rust,no_run,ignore
135//! # use funera_orchestrate::{AgentRuntime, DeepSeekProvider, ToolPolicy, ShellPolicy};
136//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
137//! let runtime = AgentRuntime::<DeepSeekProvider>::builder()
138//!     .api_key(std::env::var("DEEPSEEK_API_KEY")?)
139//!     .model("deepseek-v4-flash")
140//!     .with_builtin_tools()
141//!     .with_tool_policy(
142//!         ToolPolicy {
143//!             denied_tools: ["shell".into()].into_iter().collect(),
144//!             shell_policy: Some(ShellPolicy::with_allowed(
145//!                 vec!["git".into(), "cargo".into()],
146//!             )),
147//!             ..Default::default()
148//!         },
149//!     )
150//!     .build()?;
151//! # Ok(())
152//! # }
153//! ```
154//!
155//! ## Module Structure
156//!
157//! - [`runtime`] — [`AgentRuntimeBuilder`] and [`AgentRuntime`]
158//! - [`agent`] — [`AgentBuilder`] and [`Agent`]
159//! - [`dispatcher`] — Event bus subscription and callback dispatch
160//! - [`event`] — [`AgentEvent`] enum
161//! - [`response`] — [`ChatResponse`] and [`ToolCallInfo`]
162//! - [`error`] — [`OrchestrateError`]
163
164pub mod agent;
165pub mod dispatcher;
166pub mod error;
167pub mod event;
168pub mod response;
169pub mod runtime;
170pub mod send_handle;
171
172#[cfg(feature = "middleware")]
173pub mod middleware_bundle;
174
175pub use agent::{Agent, AgentBuilder};
176pub use dispatcher::CallbackRegistry;
177pub use error::OrchestrateError;
178pub use event::{AgentEvent, RawAgentEvent};
179#[cfg(feature = "deepseek")]
180pub use funera_core::provider::deepseek::DeepSeekProvider;
181#[cfg(feature = "openai")]
182pub use funera_core::provider::openai::OpenAIProvider;
183pub use response::{ChatResponse, ToolCallInfo};
184pub use runtime::{Acquired, AgentRuntime, AgentRuntimeBuilder, Idle};
185pub use send_handle::{FireStreamHandle, SendHandle, SendStreamHandle};
186
187// Re-export security policy types for convenience.
188#[cfg(feature = "security")]
189pub use funera_core::security::audit::{AuditBus, AuditEvent};
190#[cfg(feature = "security")]
191pub use funera_core::security::policy::{PolicyError, ShellPolicy, ToolPolicy};
192
193// Re-export core event types for direct access
194pub use funera_core::event_bus::env_state_bus::EnvStateEvent;
195pub use funera_core::event_bus::react_bus::{
196    ReactEvent, ToolCallErrorInfo, ToolCallRequest, ToolCallResponse,
197};
198pub use funera_core::event_bus::token_bus::TokenEvent;
199
200/// Middleware 相关的类型和 trait。
201///
202/// 该模块提供了 [`InspectorMiddleware`]、[`MutatorMiddleware`] 等核心 trait,
203/// 以及 [`MiddlewareChain`]、[`MiddlewareBundle`] 等构建管道所需的类型。
204///
205/// ## Feature gate
206///
207/// 需要启用 `middleware` feature:
208///
209/// ```toml
210/// funera-orchestrate = { features = ["middleware"] }
211/// ```
212#[cfg(feature = "middleware")]
213pub mod middleware {
214    pub use crate::middleware_bundle::MiddlewareBundle;
215    pub use funera_core::middleware::*;
216}