use async_trait::async_trait;
use starweaver_context::AgentContext;
use starweaver_model::{
ModelMessage, ModelRequest, ModelResponse, ModelSettings, ToolCallPart, ToolDefinition,
ToolReturnPart,
};
use starweaver_tools::ToolContext;
use crate::{
agent::AgentInput, executor::AgentCheckpoint, run::AgentRunState, stream::AgentStreamRecord,
};
use super::{CapabilityResult, CapabilitySpec, RetryEventKind};
#[async_trait]
pub trait AgentCapability: Send + Sync {
fn spec(&self) -> CapabilitySpec {
CapabilitySpec::new(std::any::type_name::<Self>())
}
async fn on_run_start(&self, _state: &mut AgentRunState) -> CapabilityResult<()> {
Ok(())
}
async fn on_run_start_with_context(
&self,
state: &mut AgentRunState,
_context: &mut AgentContext,
) -> CapabilityResult<()> {
self.on_run_start(state).await
}
async fn prepare_run_input(
&self,
_state: &mut AgentRunState,
input: AgentInput,
) -> CapabilityResult<AgentInput> {
Ok(input)
}
async fn prepare_run_input_with_context(
&self,
state: &mut AgentRunState,
_context: &mut AgentContext,
input: AgentInput,
) -> CapabilityResult<AgentInput> {
self.prepare_run_input(state, input).await
}
async fn prepare_model_messages(
&self,
_state: &mut AgentRunState,
messages: Vec<ModelMessage>,
) -> CapabilityResult<Vec<ModelMessage>> {
Ok(messages)
}
async fn prepare_model_messages_with_context(
&self,
state: &mut AgentRunState,
_context: &mut AgentContext,
messages: Vec<ModelMessage>,
) -> CapabilityResult<Vec<ModelMessage>> {
self.prepare_model_messages(state, messages).await
}
async fn prepare_provider_messages(
&self,
_state: &mut AgentRunState,
messages: Vec<ModelMessage>,
) -> CapabilityResult<Vec<ModelMessage>> {
Ok(messages)
}
async fn prepare_provider_messages_with_context(
&self,
state: &mut AgentRunState,
_context: &mut AgentContext,
messages: Vec<ModelMessage>,
) -> CapabilityResult<Vec<ModelMessage>> {
self.prepare_provider_messages(state, messages).await
}
async fn prepare_tools(
&self,
_state: &AgentRunState,
tools: Vec<ToolDefinition>,
) -> CapabilityResult<Vec<ToolDefinition>> {
Ok(tools)
}
async fn prepare_tools_with_context(
&self,
state: &AgentRunState,
_context: &AgentContext,
tools: Vec<ToolDefinition>,
) -> CapabilityResult<Vec<ToolDefinition>> {
self.prepare_tools(state, tools).await
}
async fn before_model_request(
&self,
_state: &mut AgentRunState,
_request: &mut ModelRequest,
_settings: &mut Option<ModelSettings>,
) -> CapabilityResult<()> {
Ok(())
}
async fn before_model_request_with_context(
&self,
state: &mut AgentRunState,
context: &mut AgentContext,
request: &mut ModelRequest,
settings: &mut Option<ModelSettings>,
) -> CapabilityResult<()> {
let _ = context;
self.before_model_request(state, request, settings).await
}
async fn after_model_response(
&self,
_state: &mut AgentRunState,
_response: &mut ModelResponse,
) -> CapabilityResult<()> {
Ok(())
}
async fn before_tool_execution(
&self,
_state: &mut AgentRunState,
_tool_context: &mut ToolContext,
_call: &ToolCallPart,
) -> CapabilityResult<()> {
Ok(())
}
async fn before_tool_execution_with_context(
&self,
state: &mut AgentRunState,
_context: &mut AgentContext,
tool_context: &mut ToolContext,
call: &ToolCallPart,
) -> CapabilityResult<()> {
self.before_tool_execution(state, tool_context, call).await
}
async fn after_tool_result(
&self,
_state: &mut AgentRunState,
_call: &ToolCallPart,
_tool_return: &mut ToolReturnPart,
) -> CapabilityResult<()> {
Ok(())
}
async fn after_tool_result_with_context(
&self,
state: &mut AgentRunState,
_context: &mut AgentContext,
call: &ToolCallPart,
tool_return: &mut ToolReturnPart,
) -> CapabilityResult<()> {
self.after_tool_result(state, call, tool_return).await
}
async fn after_model_response_with_context(
&self,
state: &mut AgentRunState,
context: &mut AgentContext,
response: &mut ModelResponse,
) -> CapabilityResult<()> {
let _ = context;
self.after_model_response(state, response).await
}
async fn before_output_validation(
&self,
_state: &mut AgentRunState,
_output: &str,
) -> CapabilityResult<()> {
Ok(())
}
async fn before_output_validation_with_context(
&self,
state: &mut AgentRunState,
_context: &mut AgentContext,
output: &str,
) -> CapabilityResult<()> {
self.before_output_validation(state, output).await
}
async fn validate_output(
&self,
_state: &mut AgentRunState,
_output: &str,
) -> CapabilityResult<()> {
Ok(())
}
async fn validate_output_with_context(
&self,
state: &mut AgentRunState,
context: &mut AgentContext,
output: &str,
) -> CapabilityResult<()> {
let _ = context;
self.validate_output(state, output).await
}
async fn after_output_validation(
&self,
_state: &mut AgentRunState,
_output: &str,
) -> CapabilityResult<()> {
Ok(())
}
async fn after_output_validation_with_context(
&self,
state: &mut AgentRunState,
_context: &mut AgentContext,
output: &str,
) -> CapabilityResult<()> {
self.after_output_validation(state, output).await
}
async fn on_checkpoint(
&self,
_state: &AgentRunState,
_checkpoint: &AgentCheckpoint,
) -> CapabilityResult<()> {
Ok(())
}
async fn on_checkpoint_with_context(
&self,
state: &AgentRunState,
_context: &AgentContext,
checkpoint: &AgentCheckpoint,
) -> CapabilityResult<()> {
self.on_checkpoint(state, checkpoint).await
}
async fn on_retry(
&self,
_state: &mut AgentRunState,
_kind: RetryEventKind,
_retries: usize,
_message: &str,
) -> CapabilityResult<()> {
Ok(())
}
async fn on_stream_event(
&self,
_state: &AgentRunState,
_event: &AgentStreamRecord,
) -> CapabilityResult<()> {
Ok(())
}
async fn on_stream_event_with_context(
&self,
state: &AgentRunState,
_context: &AgentContext,
event: &AgentStreamRecord,
) -> CapabilityResult<()> {
self.on_stream_event(state, event).await
}
async fn on_retry_with_context(
&self,
state: &mut AgentRunState,
_context: &mut AgentContext,
kind: RetryEventKind,
retries: usize,
message: &str,
) -> CapabilityResult<()> {
self.on_retry(state, kind, retries, message).await
}
async fn on_run_complete(&self, _state: &mut AgentRunState) -> CapabilityResult<()> {
Ok(())
}
async fn on_run_complete_with_context(
&self,
state: &mut AgentRunState,
context: &mut AgentContext,
) -> CapabilityResult<()> {
let _ = context;
self.on_run_complete(state).await
}
}