1use uuid::Uuid;
4
5use crate::engine::{MemoryContext, TurnOutcome};
6use ainl_graph_extractor::ExtractionReport;
7
8#[cfg(feature = "async")]
9use crate::engine::{PatchDispatchContext, TurnInput};
10
11pub trait TurnHooks: Send + Sync {
13 fn on_artifact_loaded(&self, _agent_id: &str, _node_count: usize) {}
14 fn on_persona_compiled(&self, _contribution: Option<&str>) {}
15 fn on_memory_context_ready(&self, _ctx: &MemoryContext) {}
16 fn on_episode_recorded(&self, _episode_id: Uuid) {}
17 fn on_patch_dispatched(&self, _label: &str, _fitness: f32) {}
18 fn on_extraction_complete(&self, _report: &ExtractionReport) {}
19 fn on_emit(&self, _target: &str, _payload: &serde_json::Value) {}
20 fn on_turn_complete(&self, _outcome: &TurnOutcome) {}
21 fn on_vitals_classified(&self, _gate: &str, _phase: &str, _trust: f32) {}
26}
27
28pub struct NoOpHooks;
30
31impl TurnHooks for NoOpHooks {}
32
33#[cfg(feature = "async")]
39#[async_trait::async_trait]
40pub trait TurnHooksAsync: Send + Sync {
41 async fn on_turn_start(&self, _input: &TurnInput) {}
42
43 async fn on_patch_dispatched(
44 &self,
45 _ctx: &PatchDispatchContext<'_>,
46 ) -> Result<serde_json::Value, String> {
47 Ok(serde_json::Value::Null)
48 }
49
50 async fn on_plan_step_execute(
52 &self,
53 _step_id: &str,
54 _tool: &str,
55 _args: &serde_json::Value,
56 ) -> Result<serde_json::Value, ainl_agent_snapshot::PlanStepError> {
57 Err(ainl_agent_snapshot::PlanStepError::ToolNotFound(
58 "on_plan_step_execute not implemented".into(),
59 ))
60 }
61
62 async fn on_turn_complete(&self, _outcome: &TurnOutcome) {}
63}
64
65#[cfg(feature = "async")]
67pub struct NoOpAsyncHooks;
68
69#[cfg(feature = "async")]
70#[async_trait::async_trait]
71impl TurnHooksAsync for NoOpAsyncHooks {}