1pub use converge_pack::Suggestor;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
17pub struct SuggestorId(pub(crate) u32);
18
19impl SuggestorId {
20 #[must_use]
22 pub fn as_u32(self) -> u32 {
23 self.0
24 }
25}
26
27impl std::fmt::Display for SuggestorId {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 write!(f, "Suggestor({})", self.0)
30 }
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36 use crate::context::ContextKey;
37 use crate::effect::AgentEffect;
38
39 struct TestSuggestor {
41 fact_id: String,
42 }
43
44 #[async_trait::async_trait]
45 impl Suggestor for TestSuggestor {
46 fn name(&self) -> &str {
47 "TestSuggestor"
48 }
49
50 fn dependencies(&self) -> &[ContextKey] {
51 &[ContextKey::Seeds]
52 }
53
54 fn accepts(&self, ctx: &dyn crate::Context) -> bool {
55 !ctx.get(ContextKey::Seeds)
56 .iter()
57 .any(|f| f.id().as_str() == self.fact_id)
58 }
59
60 async fn execute(&self, _ctx: &dyn crate::Context) -> AgentEffect {
61 AgentEffect::with_proposal(crate::ProposedFact::new(
62 ContextKey::Seeds,
63 self.fact_id.clone(),
64 crate::TextPayload::new("test content"),
65 self.provenance(),
66 ))
67 }
68 }
69
70 #[test]
71 fn suggestor_accepts_when_fact_missing() {
72 let suggestor = TestSuggestor {
73 fact_id: "test-1".into(),
74 };
75 let ctx = crate::context::ContextState::new();
76 assert!(suggestor.accepts(&ctx));
77 }
78
79 #[test]
80 fn suggestor_rejects_when_fact_present() {
81 let suggestor = TestSuggestor {
82 fact_id: "test-1".into(),
83 };
84 let mut ctx = crate::context::ContextState::new();
85 let fact = crate::context::new_fact(ContextKey::Seeds, "test-1", "already here");
86 let _ = ctx.add_fact(fact);
87 assert!(!suggestor.accepts(&ctx));
88 }
89
90 #[tokio::test]
91 async fn suggestor_produces_effect() {
92 let suggestor = TestSuggestor {
93 fact_id: "test-1".into(),
94 };
95 let ctx = crate::context::ContextState::new();
96 let effect = suggestor.execute(&ctx).await;
97 assert_eq!(effect.proposals().len(), 1);
98 assert_eq!(effect.proposals()[0].id, "test-1");
99 }
100
101 #[test]
102 fn suggestor_id_ordering() {
103 let a = SuggestorId(1);
104 let b = SuggestorId(2);
105 let c = SuggestorId(1);
106 assert!(a < b);
107 assert_eq!(a, c);
108 }
109}