//! GrokBoy core: config, streaming chat, tools, ReAct agent, sessions. mod agent; mod browser_client; mod jobs; mod runtime; pub mod team; pub use runtime::{AgentEvent, InputBroker, PlanStep, Runtime, StepStatus}; mod browser; mod config; mod confirm; mod model; mod session; mod tools; pub use agent::{ context_char_budget, max_rounds_budget, max_rounds_total_budget, message_char_len, messages_char_len, round_signature, run_agent, run_agent_with, tool_call_signature, truncate_messages, AgentVerdict, AGENT_SYSTEM, DEFAULT_CONTEXT_CHARS, DEFAULT_MAX_ROUNDS, DEFAULT_MAX_ROUNDS_TOTAL, LOOP_GUARD_REPEAT, }; pub use browser::{ browser_oneshot, browser_self_test, find_helper_script, wait_for_handoff_resume, HandoffWait, INSTALL_HINT as BROWSER_INSTALL_HINT, }; pub use config::Config; pub use confirm::{ confirm_tool_definition, execute_request_user_confirm, wait_for_user_confirm, ConfirmWait, }; pub use model::{chat_completion, stream_chat, ChatMessage, FunctionCall, Role, ToolCall}; pub use session::{load_or_create, load_session, save_session, sessions_dir, Session}; pub use tools::{execute_tool, is_completion_tool, tool_definitions, ToolContext}; /// Serialize tests that mutate process env (CONFIRM_AUTO / HANDOFF_AUTO). #[cfg(test)] pub(crate) mod test_env { use std::sync::OnceLock; use tokio::sync::{Mutex, MutexGuard}; fn mutex() -> &'static Mutex<()> { static M: OnceLock> = OnceLock::new(); M.get_or_init(|| Mutex::new(())) } pub fn lock() -> MutexGuard<'static, ()> { mutex().blocking_lock() } pub async fn lock_async() -> MutexGuard<'static, ()> { mutex().lock().await } }