tirea_contract/runtime/
action.rs

1use crate::runtime::phase::step::StepContext;
2use crate::runtime::phase::Phase;
3
4/// Unified action trait for all phase effects.
5///
6/// Actions are emitted by [`AgentBehavior`](super::behavior::AgentBehavior)
7/// hooks and tool effects, then applied to [`StepContext`] by the runtime
8/// after validation. Extension plugins and tools can define their own actions
9/// by implementing this trait.
10pub trait Action: Send + 'static {
11    /// Human-readable label for diagnostics.
12    fn label(&self) -> &'static str;
13
14    /// Check whether this action is valid in the given phase.
15    ///
16    /// Returns `Ok(())` if allowed, or `Err(reason)` describing the
17    /// violation. The default implementation accepts all phases.
18    fn validate(&self, _phase: Phase) -> Result<(), String> {
19        Ok(())
20    }
21
22    /// Apply this action to the mutable step context.
23    ///
24    /// Consumes `self` (boxed) so that actions can move data into the
25    /// step context without cloning.
26    fn apply(self: Box<Self>, step: &mut StepContext<'_>);
27}
28
29#[cfg(test)]
30mod tests {
31    use super::*;
32
33    struct DummyAction;
34
35    impl Action for DummyAction {
36        fn label(&self) -> &'static str {
37            "dummy"
38        }
39
40        fn validate(&self, phase: Phase) -> Result<(), String> {
41            if phase == Phase::RunStart {
42                Err("not allowed in RunStart".into())
43            } else {
44                Ok(())
45            }
46        }
47
48        fn apply(self: Box<Self>, _step: &mut StepContext<'_>) {
49            // no-op for testing
50        }
51    }
52
53    #[test]
54    fn action_label() {
55        let action = DummyAction;
56        assert_eq!(action.label(), "dummy");
57    }
58
59    #[test]
60    fn action_validate_ok() {
61        let action = DummyAction;
62        assert!(action.validate(Phase::BeforeInference).is_ok());
63    }
64
65    #[test]
66    fn action_validate_err() {
67        let action = DummyAction;
68        assert!(action.validate(Phase::RunStart).is_err());
69    }
70}