#![allow(dead_code)]
use std::sync::Arc;
use async_trait::async_trait;
use parking_lot::RwLock;
use oxios_ouroboros::{
Assessment, Directive, EvaluationResult, ExecutionResult, IntentEngineOps, InterviewResult,
MsgCtx, OuroborosProtocol, Scope, Seed, Verdict,
};
pub struct MockIntentEngine {
pub assess_response: RwLock<Assessment>,
pub crystallize_response: RwLock<Directive>,
pub review_response: RwLock<Verdict>,
}
impl MockIntentEngine {
pub fn new() -> Self {
Self {
assess_response: RwLock::new(Assessment::Task(Scope::Substantial)),
crystallize_response: RwLock::new(Directive::from_message("")),
review_response: RwLock::new(Verdict {
passed: true,
score: 1.0,
notes: vec!["Mock review passed".into()],
gaps: vec![],
}),
}
}
pub fn with_assess(self, assessment: Assessment) -> Self {
*self.assess_response.write() = assessment;
self
}
pub fn with_crystallize(self, directive: Directive) -> Self {
*self.crystallize_response.write() = directive;
self
}
pub fn with_review(self, verdict: Verdict) -> Self {
*self.review_response.write() = verdict;
self
}
pub fn into_arc(self) -> Arc<dyn IntentEngineOps> {
Arc::new(self)
}
}
impl Default for MockIntentEngine {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl IntentEngineOps for MockIntentEngine {
async fn assess(&self, msg: &str, _ctx: &MsgCtx) -> anyhow::Result<Assessment> {
let resp = self.assess_response.read().clone();
Ok(match resp {
Assessment::Clarify { questions } if questions.is_empty() => Assessment::Clarify {
questions: vec![oxios_ouroboros::Question {
id: "q1".into(),
text: format!("Clarify: {msg}"),
kind: oxios_ouroboros::QuestionKind::FreeText,
options: vec![],
}],
},
other => other,
})
}
async fn crystallize(&self, msg: &str, _ctx: &MsgCtx) -> anyhow::Result<Directive> {
let mut resp = self.crystallize_response.read().clone();
if resp.goal.is_empty() {
resp.goal = msg.to_string();
}
if resp.original_request.is_empty() {
resp.original_request = msg.to_string();
}
Ok(resp)
}
async fn review(
&self,
_directive: &Directive,
_result: &ExecutionResult,
) -> anyhow::Result<Verdict> {
Ok(self.review_response.read().clone())
}
}
struct MockOuroborosProtocol;
#[async_trait]
impl OuroborosProtocol for MockOuroborosProtocol {
async fn interview(&self, _user_input: &str) -> anyhow::Result<InterviewResult> {
unimplemented!("handle_unified path does not use interview")
}
async fn generate_seed(&self, _interview: &InterviewResult) -> anyhow::Result<Seed> {
unimplemented!("handle_unified path does not use generate_seed")
}
async fn execute(&self, _seed: &Seed) -> anyhow::Result<ExecutionResult> {
unimplemented!("handle_unified path does not use execute")
}
async fn evaluate(
&self,
_seed: &Seed,
_result: &ExecutionResult,
) -> anyhow::Result<EvaluationResult> {
unimplemented!("handle_unified path does not use evaluate")
}
async fn evolve(
&self,
_seed: &Seed,
_evaluation: &EvaluationResult,
) -> anyhow::Result<Option<Seed>> {
unimplemented!("handle_unified path does not use evolve")
}
fn set_persona_prompt(&self, _prompt: Option<String>) {}
}
pub fn build_test_orchestrator(
supervisor: Arc<dyn oxios_kernel::supervisor::Supervisor>,
state_store: Arc<oxios_kernel::state_store::StateStore>,
event_bus: oxios_kernel::event_bus::EventBus,
) -> (Arc<oxios_kernel::Orchestrator>, Arc<MockIntentEngine>) {
let scheduler = Arc::new(oxios_kernel::scheduler::AgentScheduler::default());
let access_manager = Arc::new(parking_lot::Mutex::new(
oxios_kernel::access_manager::AccessManager::new(),
));
let a2a = Arc::new(oxios_kernel::a2a::A2AProtocol::new(event_bus.clone()));
let lifecycle = oxios_kernel::agent_lifecycle::AgentLifecycleManager::new(
supervisor,
scheduler,
access_manager,
a2a,
event_bus.clone(),
300,
vec![],
true,
"/tmp/oxios-test-workspace".to_string(),
);
let mock = Arc::new(MockIntentEngine::new());
let orchestrator = oxios_kernel::Orchestrator::new(
Arc::new(MockOuroborosProtocol),
event_bus,
state_store,
lifecycle,
);
orchestrator.set_intent_engine(mock.clone() as Arc<dyn IntentEngineOps>);
(Arc::new(orchestrator), mock)
}
pub fn failing_verdict(gaps: Vec<String>) -> Verdict {
Verdict {
passed: false,
score: 0.3,
notes: vec!["Mock review failed".into()],
gaps,
}
}
pub fn passing_verdict() -> Verdict {
Verdict {
passed: true,
score: 1.0,
notes: vec!["Mock review passed".into()],
gaps: vec![],
}
}