#[cfg(feature = "agent")]
mod expertise_agent_integration_tests {
use llm_toolkit::agent::expertise::{
Expertise, KnowledgeFragment, RenderContext, WeightedFragment,
};
use llm_toolkit::agent::{Agent, ExpertiseAgent, Payload};
use llm_toolkit::context::{ContextProfile, Priority, TaskHealth};
fn get_all_payload_content(payload: &Payload) -> String {
let mut content = String::new();
for msg in payload.to_messages() {
content.push_str(&msg.content);
content.push('\n');
}
content.push_str(&payload.to_text());
content
}
struct PayloadCapturingAgent {
captured_payload: std::sync::Arc<std::sync::Mutex<Option<Payload>>>,
}
impl PayloadCapturingAgent {
fn new() -> Self {
Self {
captured_payload: std::sync::Arc::new(std::sync::Mutex::new(None)),
}
}
fn get_captured_payload(&self) -> Option<Payload> {
self.captured_payload.lock().unwrap().clone()
}
}
#[async_trait::async_trait]
impl Agent for PayloadCapturingAgent {
type Output = String;
type Expertise = &'static str;
fn expertise(&self) -> &&'static str {
&"Payload Capturing Agent"
}
async fn execute(
&self,
intent: Payload,
) -> Result<Self::Output, llm_toolkit::agent::AgentError> {
*self.captured_payload.lock().unwrap() = Some(intent.clone());
Ok("Captured".to_string())
}
fn name(&self) -> String {
"PayloadCapturingAgent".to_string()
}
async fn is_available(&self) -> Result<(), llm_toolkit::agent::AgentError> {
Ok(())
}
}
#[tokio::test]
async fn test_expertise_agent_e2e_context_aware_rendering() {
let expertise = Expertise::new("security-reviewer", "1.0")
.with_description("Security code reviewer with context-aware guidance")
.with_fragment(
WeightedFragment::new(KnowledgeFragment::Text(
"Always verify input validation and authentication.".to_string(),
))
.with_priority(Priority::Critical)
.with_context(ContextProfile::Always),
)
.with_fragment(
WeightedFragment::new(KnowledgeFragment::Text(
"SLOW DOWN. Extra vigilance required for at-risk tasks.".to_string(),
))
.with_priority(Priority::Critical)
.with_context(ContextProfile::Conditional {
task_types: vec![],
user_states: vec![],
task_health: Some(TaskHealth::AtRisk),
}),
)
.with_fragment(
WeightedFragment::new(KnowledgeFragment::Text(
"Focus on SQL injection and XSS vulnerabilities.".to_string(),
))
.with_priority(Priority::High)
.with_context(ContextProfile::Conditional {
task_types: vec!["security-review".to_string()],
user_states: vec![],
task_health: None,
}),
);
let capturing_agent = PayloadCapturingAgent::new();
let agent = ExpertiseAgent::new(capturing_agent, expertise.clone());
let payload = Payload::text("Review this authentication code")
.with_task_type("security-review")
.with_task_health(TaskHealth::AtRisk);
let result = agent.execute(payload.clone()).await.unwrap();
assert_eq!(result, "Captured");
let captured = agent.inner().get_captured_payload().unwrap();
let captured_text = get_all_payload_content(&captured);
assert!(
captured_text.contains("Always verify input validation and authentication"),
"Expected Always fragment to be included"
);
assert!(
captured_text.contains("SLOW DOWN. Extra vigilance required"),
"Expected AtRisk fragment to be included when task_health is AtRisk"
);
assert!(
captured_text.contains("SQL injection and XSS vulnerabilities"),
"Expected security-review fragment to be included when task_type matches"
);
assert!(
captured_text.contains("Review this authentication code"),
"Expected original user question to be preserved"
);
}
#[tokio::test]
async fn test_expertise_agent_e2e_selective_rendering() {
let expertise = Expertise::new("code-reviewer", "1.0")
.with_fragment(
WeightedFragment::new(KnowledgeFragment::Text(
"Base guidance for all reviews.".to_string(),
))
.with_context(ContextProfile::Always),
)
.with_fragment(
WeightedFragment::new(KnowledgeFragment::Text(
"Beginner-friendly explanations.".to_string(),
))
.with_context(ContextProfile::Conditional {
task_types: vec![],
user_states: vec!["beginner".to_string()],
task_health: None,
}),
)
.with_fragment(
WeightedFragment::new(KnowledgeFragment::Text(
"Advanced optimization techniques.".to_string(),
))
.with_context(ContextProfile::Conditional {
task_types: vec![],
user_states: vec!["expert".to_string()],
task_health: None,
}),
);
let capturing_agent = PayloadCapturingAgent::new();
let agent = ExpertiseAgent::new(capturing_agent, expertise.clone());
let payload = Payload::text("Review this code").with_user_state("beginner");
agent.execute(payload).await.unwrap();
let captured = agent.inner().get_captured_payload().unwrap();
let captured_text = get_all_payload_content(&captured);
assert!(
captured_text.contains("Base guidance for all reviews"),
"Expected base guidance"
);
assert!(
captured_text.contains("Beginner-friendly explanations"),
"Expected beginner fragment"
);
assert!(
!captured_text.contains("Advanced optimization techniques"),
"Should NOT include expert fragment"
);
let capturing_agent2 = PayloadCapturingAgent::new();
let agent2 = ExpertiseAgent::new(capturing_agent2, expertise.clone());
let payload2 = Payload::text("Review this code").with_user_state("expert");
agent2.execute(payload2).await.unwrap();
let captured2 = agent2.inner().get_captured_payload().unwrap();
let captured_text2 = get_all_payload_content(&captured2);
assert!(
captured_text2.contains("Base guidance for all reviews"),
"Expected base guidance"
);
assert!(
!captured_text2.contains("Beginner-friendly explanations"),
"Should NOT include beginner fragment"
);
assert!(
captured_text2.contains("Advanced optimization techniques"),
"Expected expert fragment"
);
}
#[tokio::test]
async fn test_expertise_agent_e2e_no_context() {
let expertise = Expertise::new("reviewer", "1.0").with_fragment(
WeightedFragment::new(KnowledgeFragment::Text(
"Special guidance for security reviews.".to_string(),
))
.with_context(ContextProfile::Conditional {
task_types: vec!["security-review".to_string()],
user_states: vec![],
task_health: None,
}),
);
let capturing_agent = PayloadCapturingAgent::new();
let agent = ExpertiseAgent::new(capturing_agent, expertise);
let payload = Payload::text("Review this code");
agent.execute(payload).await.unwrap();
let captured = agent.inner().get_captured_payload().unwrap();
let captured_text = get_all_payload_content(&captured);
assert!(
!captured_text.contains("Special guidance for security reviews"),
"Should NOT include conditional fragment when context doesn't match"
);
assert!(
captured_text.contains("Review this code"),
"Expected original user question to be preserved"
);
}
#[tokio::test]
async fn test_expertise_agent_e2e_multiple_user_states() {
let expertise = Expertise::new("educator", "1.0")
.with_fragment(
WeightedFragment::new(KnowledgeFragment::Text(
"Extra patience for confused learners.".to_string(),
))
.with_context(ContextProfile::Conditional {
task_types: vec![],
user_states: vec!["confused".to_string()],
task_health: None,
}),
)
.with_fragment(
WeightedFragment::new(KnowledgeFragment::Text(
"Simplified explanations for beginners.".to_string(),
))
.with_context(ContextProfile::Conditional {
task_types: vec![],
user_states: vec!["beginner".to_string()],
task_health: None,
}),
);
let capturing_agent = PayloadCapturingAgent::new();
let agent = ExpertiseAgent::new(capturing_agent, expertise);
let payload = Payload::text("Explain this concept")
.with_user_state("beginner")
.with_user_state("confused");
agent.execute(payload).await.unwrap();
let captured = agent.inner().get_captured_payload().unwrap();
let captured_text = get_all_payload_content(&captured);
assert!(
captured_text.contains("Extra patience for confused learners"),
"Expected confused learner fragment"
);
assert!(
captured_text.contains("Simplified explanations for beginners"),
"Expected beginner fragment"
);
}
#[tokio::test]
async fn test_expertise_agent_e2e_render_context_preservation() {
let expertise = Expertise::new("test", "1.0");
let capturing_agent = PayloadCapturingAgent::new();
let agent = ExpertiseAgent::new(capturing_agent, expertise);
let original_context = RenderContext::new()
.with_task_type("review")
.with_task_health(TaskHealth::OnTrack);
let payload = Payload::text("Test").with_render_context(original_context.clone());
agent.execute(payload).await.unwrap();
let captured = agent.inner().get_captured_payload().unwrap();
assert!(captured.render_context().is_some());
let captured_context = captured.render_context().unwrap();
assert_eq!(captured_context.task_type, Some("review".to_string()));
assert_eq!(captured_context.task_health, Some(TaskHealth::OnTrack));
}
}