yoagent_state/
behavior.rs1use crate::{BehaviorId, Event, GraphSnapshot, StateError, StateOp};
2use async_trait::async_trait;
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6pub enum EventPattern {
7 Any,
8 Kind(String),
9 KindPrefix(String),
10 StateOpsApplied,
11 PatchStatusChanged,
12}
13
14impl EventPattern {
15 pub fn matches(&self, event: &Event) -> bool {
16 match self {
17 EventPattern::Any => true,
18 EventPattern::Kind(kind) => event.kind == *kind,
19 EventPattern::KindPrefix(prefix) => event.kind.starts_with(prefix),
20 EventPattern::StateOpsApplied => event.kind == crate::STATE_OPS_APPLIED,
21 EventPattern::PatchStatusChanged => event.kind == "patch.status_changed",
22 }
23 }
24}
25
26#[derive(Debug, Clone)]
27pub struct BehaviorContext {
28 pub graph: GraphSnapshot,
29 pub replaying: bool,
30}
31
32#[async_trait]
33pub trait Behavior: Send + Sync {
34 fn id(&self) -> BehaviorId;
35 fn pattern(&self) -> EventPattern;
36 async fn handle(&self, ctx: BehaviorContext, event: &Event)
37 -> Result<Vec<StateOp>, StateError>;
38}
39
40pub struct FnBehavior<F> {
41 id: BehaviorId,
42 pattern: EventPattern,
43 f: F,
44}
45
46impl<F> FnBehavior<F> {
47 pub fn new(id: BehaviorId, pattern: EventPattern, f: F) -> Self {
48 Self { id, pattern, f }
49 }
50}
51
52#[async_trait]
53impl<F, Fut> Behavior for FnBehavior<F>
54where
55 F: Send + Sync + Fn(BehaviorContext, Event) -> Fut,
56 Fut: Send + std::future::Future<Output = Result<Vec<StateOp>, StateError>>,
57{
58 fn id(&self) -> BehaviorId {
59 self.id.clone()
60 }
61
62 fn pattern(&self) -> EventPattern {
63 self.pattern.clone()
64 }
65
66 async fn handle(
67 &self,
68 ctx: BehaviorContext,
69 event: &Event,
70 ) -> Result<Vec<StateOp>, StateError> {
71 (self.f)(ctx, event.clone()).await
72 }
73}