converge_domain/
drafting.rs1use converge_core::{Agent, AgentEffect, Context, ContextKey, Fact};
9
10const DRAFT_RESEARCH_PREFIX: &str = "drafting_research:";
11const DRAFT_OUTPUT_PREFIX: &str = "drafting_output:";
12
13pub struct DraftingResearchAgent;
15
16impl Agent for DraftingResearchAgent {
17 fn name(&self) -> &str {
18 "DraftingResearchAgent"
19 }
20
21 fn dependencies(&self) -> &[ContextKey] {
22 &[ContextKey::Seeds]
23 }
24
25 fn accepts(&self, ctx: &Context) -> bool {
26 ctx.has(ContextKey::Seeds)
27 && !ctx
28 .get(ContextKey::Signals)
29 .iter()
30 .any(|fact| fact.id.starts_with(DRAFT_RESEARCH_PREFIX))
31 }
32
33 fn execute(&self, ctx: &Context) -> AgentEffect {
34 let summary = ctx
35 .get(ContextKey::Seeds)
36 .iter()
37 .map(|seed| seed.content.clone())
38 .collect::<Vec<_>>()
39 .join(" | ");
40
41 AgentEffect::with_facts(vec![Fact {
42 key: ContextKey::Signals,
43 id: format!("{DRAFT_RESEARCH_PREFIX}notes"),
44 content: format!("Drafting research notes: {summary}"),
45 }])
46 }
47}
48
49pub struct DraftingComposerAgent;
51
52impl Agent for DraftingComposerAgent {
53 fn name(&self) -> &str {
54 "DraftingComposerAgent"
55 }
56
57 fn dependencies(&self) -> &[ContextKey] {
58 &[ContextKey::Signals]
59 }
60
61 fn accepts(&self, ctx: &Context) -> bool {
62 ctx.get(ContextKey::Signals)
63 .iter()
64 .any(|fact| fact.id.starts_with(DRAFT_RESEARCH_PREFIX))
65 && !ctx
66 .get(ContextKey::Strategies)
67 .iter()
68 .any(|fact| fact.id.starts_with(DRAFT_OUTPUT_PREFIX))
69 }
70
71 fn execute(&self, ctx: &Context) -> AgentEffect {
72 let notes = ctx
73 .get(ContextKey::Signals)
74 .iter()
75 .filter(|fact| fact.id.starts_with(DRAFT_RESEARCH_PREFIX))
76 .map(|fact| fact.content.clone())
77 .collect::<Vec<_>>()
78 .join("\n");
79
80 AgentEffect::with_facts(vec![Fact {
81 key: ContextKey::Strategies,
82 id: format!("{DRAFT_OUTPUT_PREFIX}v0"),
83 content: format!("Draft output (deterministic):\n{notes}"),
84 }])
85 }
86}