Skip to main content

oxi_agent/agent_loop/
config.rs

1//! Agent loop configuration types
2
3/// Configuration for an [`crate::AgentLoop`] instance.
4#[derive(Clone)]
5pub struct AgentLoopConfig {
6    /// Model identifier in `provider/model` format.
7    pub model_id: String,
8    /// Optional system prompt prepended to every request.
9    pub system_prompt: Option<String>,
10    /// Sampling temperature (0.0 – 2.0).
11    pub temperature: f32,
12    /// Maximum tokens the model may generate per request.
13    pub max_tokens: u32,
14    /// Whether tool calls run in parallel or sequentially.
15    pub tool_execution: ToolExecutionMode,
16    /// Compaction strategy for managing context window usage.
17    pub compaction_strategy: oxi_ai::CompactionStrategy,
18    /// Approximate context window size in tokens.
19    pub context_window: usize,
20    /// Optional instruction injected into the compaction prompt.
21    pub compaction_instruction: Option<String>,
22    /// Optional session identifier for logging and tracing.
23    pub session_id: Option<String>,
24    /// Optional transport override (e.g. "sse", "stdio").
25    pub transport: Option<String>,
26    /// Whether to trigger compaction before the first turn.
27    pub compact_on_start: bool,
28    /// Optional cap on retry back-off delay (milliseconds).
29    pub max_retry_delay_ms: Option<u64>,
30    /// Enable automatic retry on retryable assistant errors.
31    pub auto_retry_enabled: bool,
32    /// Maximum number of auto-retry attempts.
33    pub auto_retry_max_attempts: usize,
34    /// Base delay in milliseconds for auto-retry exponential back-off.
35    pub auto_retry_base_delay_ms: u64,
36    /// API key override for the provider.
37    ///
38    /// When set, this is injected into [`oxi_ai::StreamOptions`] so the
39    /// provider uses it instead of an environment variable.
40    pub api_key: Option<String>,
41    /// Working directory for file tools. Defaults to current directory if None.
42    pub workspace_dir: Option<std::path::PathBuf>,
43    /// Per-provider options for fine-grained control.
44    ///
45    /// Passed through to [`oxi_ai::StreamOptions::provider_options`] so the
46    /// provider can read provider-specific settings.
47    pub provider_options: Option<oxi_ai::ProviderOptions>,
48
49    /// Async hook invoked after context compaction completes.
50    ///
51    /// Unlike the `Compaction` event in the `Fn` callback, this hook is
52    /// async and its future is awaited within the agent loop. Errors are
53    /// logged at WARN level but don't fail the loop.
54    ///
55    /// Use this for side effects that require async I/O (e.g., persisting
56    /// compaction summaries to a memory store) without resorting to
57    /// `tokio::spawn` fire-and-forget.
58    pub on_compaction: Option<CompactionHook>,
59    /// Snapshot store for hashline edit mode.
60    pub snapshot_store: Option<Arc<dyn oxi_hashline::SnapshotStore>>,
61    /// Memory backend for memory tools.
62    pub memory: Option<Arc<dyn crate::tools::MemoryBackend>>,
63    /// URL resolver for internal protocol schemes.
64    pub url_resolver: Option<Arc<dyn crate::tools::UrlResolver>>,
65    /// Todo state provider for the `todo` tool.
66    pub todo: Option<Arc<dyn crate::tools::TodoStateProvider>>,
67    /// Agent pool for Hub display.
68    pub agent_pool: Option<Arc<dyn crate::tools::AgentPoolProvider>>,
69    /// LSP provider for the `lsp` tool.
70    pub lsp: Option<Arc<dyn crate::tools::LspProvider>>,
71    /// TTSR engine for stream rule checking.
72    pub ttsr_engine: Option<Arc<crate::agent_loop::ttsr::TtsrEngine>>,
73}
74
75impl Default for AgentLoopConfig {
76    fn default() -> Self {
77        Self {
78            model_id: String::new(),
79            system_prompt: None,
80            temperature: 0.7,
81            max_tokens: 4096,
82            tool_execution: ToolExecutionMode::Parallel,
83            compaction_strategy: oxi_ai::CompactionStrategy::default(),
84            context_window: 128_000,
85            compaction_instruction: None,
86            session_id: None,
87            transport: None,
88            compact_on_start: false,
89            max_retry_delay_ms: None,
90            auto_retry_enabled: false,
91            auto_retry_max_attempts: 3,
92            auto_retry_base_delay_ms: 2000,
93            api_key: None,
94            workspace_dir: None,
95            provider_options: None,
96            on_compaction: None,
97            snapshot_store: None,
98            memory: None,
99            url_resolver: None,
100            todo: None,
101            agent_pool: None,
102            lsp: None,
103            ttsr_engine: None,
104        }
105    }
106}
107
108// Re-export ToolExecutionMode from crate::config to avoid duplicate definitions.
109pub use crate::config::ToolExecutionMode;
110
111use crate::AgentToolResult;
112use crate::compaction::CompactedContext;
113use anyhow::{Error, Result};
114use serde_json::Value;
115use std::future::Future;
116use std::pin::Pin;
117use std::sync::Arc;
118
119/// Async hook invoked after context compaction completes.
120///
121/// Receives the [`CompactedContext`] and returns a `Result<()>` future.
122/// The future is awaited within the agent loop, so async operations
123/// (memory storage, logging, etc.) are safe here.
124///
125/// # Example
126///
127/// ```ignore
128/// let config = AgentLoopConfig {
129///     on_compaction: Some(Arc::new(|ctx: CompactedContext| {
130///         let summary = ctx.summary.clone();
131///         Box::pin(async move {
132///             memory_store.save(summary).await
133///         })
134///     })),
135///     ..Default::default()
136/// };
137/// ```
138pub type CompactionHook =
139    Arc<dyn Fn(CompactedContext) -> Pin<Box<dyn Future<Output = Result<()>> + Send>> + Send + Sync>;
140
141/// Hook invoked before each tool call; may return an override result.
142pub type BeforeToolCallHook = Arc<
143    dyn Fn(
144            &str,
145            &Value,
146        ) -> Pin<Box<dyn Future<Output = Result<Option<AgentToolResult>, Error>> + Send>>
147        + Send
148        + Sync,
149>;
150
151/// Hook invoked after each tool call; may return a modified result.
152pub type AfterToolCallHook = Arc<
153    dyn Fn(
154            &str,
155            &AgentToolResult,
156        ) -> Pin<Box<dyn Future<Output = Result<Option<AgentToolResult>, Error>> + Send>>
157        + Send
158        + Sync,
159>;
160
161// MAX_RETRIES and BACKOFF_BASE_SECS are now defined in crate::stream_retry
162// and re-exported from crate::agent_loop::retry.
163pub use crate::stream_retry::{BACKOFF_BASE_SECS, MAX_RETRIES};