use std::num::NonZeroUsize;
use crate::{KitError, ModelSelector, ToolSelection};
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct CustomLoopLimits {
max_model_turns: NonZeroUsize,
max_tool_actions: usize,
max_parallel_tool_actions: NonZeroUsize,
}
impl CustomLoopLimits {
pub fn new(
max_model_turns: usize,
max_tool_actions: usize,
max_parallel_tool_actions: usize,
) -> Result<Self, KitError> {
let max_model_turns = NonZeroUsize::new(max_model_turns)
.ok_or_else(|| KitError::invalid_config("Custom model-turn limit must be positive"))?;
let max_parallel_tool_actions =
NonZeroUsize::new(max_parallel_tool_actions).ok_or_else(|| {
KitError::invalid_config("Custom parallel-tool limit must be positive")
})?;
if max_tool_actions > 65_536 {
return Err(KitError::invalid_config(
"Custom aggregate tool-action limit exceeds the portable bound",
));
}
Ok(Self {
max_model_turns,
max_tool_actions,
max_parallel_tool_actions,
})
}
#[must_use]
pub fn max_model_turns(self) -> usize {
self.max_model_turns.get()
}
#[must_use]
pub fn max_tool_actions(self) -> usize {
self.max_tool_actions
}
#[must_use]
pub fn max_parallel_tool_actions(self) -> usize {
self.max_parallel_tool_actions.get()
}
pub(crate) fn validate(self) -> Result<(), KitError> {
if self.max_tool_actions > 65_536 {
return Err(KitError::invalid_state(
"stored Custom tool-action limit exceeds the portable bound",
));
}
Ok(())
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum CustomToolApproval {
Allow,
Deny,
Interaction,
}
#[derive(Clone, Debug)]
pub struct CustomAgentConfig {
default_model: ModelSelector,
default_tool_selection: ToolSelection,
loop_limits: CustomLoopLimits,
tool_approval: CustomToolApproval,
}
impl CustomAgentConfig {
pub fn new(
default_model: ModelSelector,
default_tool_selection: ToolSelection,
loop_limits: CustomLoopLimits,
tool_approval: CustomToolApproval,
) -> Result<Self, KitError> {
default_tool_selection.validate()?;
Ok(Self {
default_model,
default_tool_selection,
loop_limits,
tool_approval,
})
}
#[must_use]
pub fn default_model(&self) -> &ModelSelector {
&self.default_model
}
#[must_use]
pub fn default_tool_selection(&self) -> &ToolSelection {
&self.default_tool_selection
}
#[must_use]
pub fn loop_limits(&self) -> CustomLoopLimits {
self.loop_limits
}
#[must_use]
pub fn tool_approval(&self) -> CustomToolApproval {
self.tool_approval
}
pub(crate) fn validate(&self) -> Result<(), KitError> {
self.default_tool_selection.validate()?;
self.loop_limits.validate()
}
}