use super::interaction_response::InteractionResponsePlugin;
use super::INTERACTION_PLUGIN_ID;
use async_trait::async_trait;
use tirea_contract::plugin::phase::{
AfterInferenceContext, AfterToolExecuteContext, BeforeInferenceContext,
BeforeToolExecuteContext, RunEndContext, RunStartContext, StepEndContext, StepStartContext,
};
use tirea_contract::plugin::AgentPlugin;
use tirea_contract::InteractionResponse;
pub struct InteractionPlugin {
static_response: InteractionResponsePlugin,
}
impl InteractionPlugin {
pub fn new(approved_ids: Vec<String>, denied_ids: Vec<String>) -> Self {
Self {
static_response: InteractionResponsePlugin::new(approved_ids, denied_ids),
}
}
pub fn with_responses(approved_ids: Vec<String>, denied_ids: Vec<String>) -> Self {
Self::new(approved_ids, denied_ids)
}
pub fn from_interaction_responses(responses: Vec<InteractionResponse>) -> Self {
Self {
static_response: InteractionResponsePlugin::from_responses(responses),
}
}
pub fn is_active(&self) -> bool {
self.static_response.has_responses()
}
pub fn has_responses(&self) -> bool {
self.static_response.has_responses()
}
pub fn is_approved(&self, interaction_id: &str) -> bool {
self.static_response.is_approved(interaction_id)
}
pub fn is_denied(&self, interaction_id: &str) -> bool {
self.static_response.is_denied(interaction_id)
}
fn response_plugin(&self) -> InteractionResponsePlugin {
InteractionResponsePlugin::from_responses(self.static_response.responses())
}
}
impl Default for InteractionPlugin {
fn default() -> Self {
Self::new(Vec::new(), Vec::new())
}
}
#[async_trait]
impl AgentPlugin for InteractionPlugin {
fn id(&self) -> &str {
INTERACTION_PLUGIN_ID
}
async fn run_start(&self, ctx: &mut RunStartContext<'_, '_>) {
let response = self.response_plugin();
response.run_start(ctx).await;
}
async fn step_start(&self, ctx: &mut StepStartContext<'_, '_>) {
let response = self.response_plugin();
response.step_start(ctx).await;
}
async fn before_inference(&self, ctx: &mut BeforeInferenceContext<'_, '_>) {
let response = self.response_plugin();
response.before_inference(ctx).await;
}
async fn after_inference(&self, ctx: &mut AfterInferenceContext<'_, '_>) {
let response = self.response_plugin();
response.after_inference(ctx).await;
}
async fn before_tool_execute(&self, ctx: &mut BeforeToolExecuteContext<'_, '_>) {
let response = self.response_plugin();
response.before_tool_execute(ctx).await;
}
async fn after_tool_execute(&self, ctx: &mut AfterToolExecuteContext<'_, '_>) {
let response = self.response_plugin();
response.after_tool_execute(ctx).await;
}
async fn step_end(&self, ctx: &mut StepEndContext<'_, '_>) {
let response = self.response_plugin();
response.step_end(ctx).await;
}
async fn run_end(&self, ctx: &mut RunEndContext<'_, '_>) {
let response = self.response_plugin();
response.run_end(ctx).await;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn plugin_inactive_without_responses() {
let plugin = InteractionPlugin::new(Vec::new(), Vec::new());
assert!(!plugin.is_active());
}
#[test]
fn plugin_active_with_responses() {
let plugin = InteractionPlugin::new(vec!["call_1".to_string()], Vec::new());
assert!(plugin.is_active());
assert!(plugin.has_responses());
}
}