Skip to main content

oneiros_templates/
lib.rs

1mod dream;
2mod guidebook;
3mod introspect;
4mod mcp;
5mod reflect;
6mod sense;
7
8pub use dream::DreamTemplate;
9pub use guidebook::GuidebookTemplate;
10pub use introspect::IntrospectTemplate;
11pub use mcp::McpTemplate;
12pub use reflect::ReflectTemplate;
13pub use sense::SenseTemplate;
14
15#[cfg(test)]
16mod tests {
17    use super::*;
18    use oneiros_model::*;
19
20    fn test_agent() -> Agent {
21        Agent::init(
22            "A curious explorer agent",
23            "You explore and discover.",
24            AgentName::new("atlas"),
25            PersonaName::new("explorer"),
26        )
27    }
28
29    fn test_persona() -> Persona {
30        Persona::init(
31            PersonaName::new("explorer"),
32            "An explorer persona.",
33            "Explore with curiosity.",
34        )
35    }
36
37    #[test]
38    fn dream_template_renders_identity_and_persona() {
39        let context = DreamContext {
40            agent: test_agent(),
41            persona: test_persona(),
42            memories: vec![],
43            cognitions: vec![],
44            experiences: vec![],
45            connections: vec![],
46            textures: vec![],
47            levels: vec![],
48            sensations: vec![],
49            natures: vec![],
50            urges: vec![],
51            pressures: vec![],
52        };
53        let rendered = DreamTemplate::new(&context).to_string();
54
55        assert!(rendered.contains("You are waking as atlas."));
56        assert!(rendered.contains("## Your Identity"));
57        assert!(rendered.contains("A curious explorer agent"));
58        assert!(rendered.contains("You explore and discover."));
59        assert!(rendered.contains("## Your Persona"));
60        assert!(rendered.contains("An explorer persona."));
61        assert!(rendered.contains("## Agent Definition"));
62        assert!(rendered.contains(".claude/agents/atlas.md"));
63        assert!(rendered.contains(".agents/atlas.md"));
64        assert!(rendered.contains("## Instructions"));
65    }
66
67    #[test]
68    fn dream_template_omits_empty_sections() {
69        let context = DreamContext {
70            agent: test_agent(),
71            persona: test_persona(),
72            memories: vec![],
73            cognitions: vec![],
74            experiences: vec![],
75            connections: vec![],
76            textures: vec![],
77            levels: vec![],
78            sensations: vec![],
79            natures: vec![],
80            urges: vec![],
81            pressures: vec![],
82        };
83        let rendered = DreamTemplate::new(&context).to_string();
84
85        assert!(!rendered.contains("## Your Memories"));
86        assert!(!rendered.contains("## Your Cognitions"));
87        assert!(!rendered.contains("## Your Connections"));
88        assert!(!rendered.contains("## Cognitive Textures"));
89        assert!(!rendered.contains("## Memory Levels"));
90    }
91
92    #[test]
93    fn dream_template_renders_memories() {
94        let context = DreamContext {
95            agent: test_agent(),
96            persona: test_persona(),
97            memories: vec![Memory::create(
98                AgentId::new(),
99                LevelName::new("core"),
100                Content::new("I remember the beginning."),
101            )],
102            cognitions: vec![],
103            experiences: vec![],
104            connections: vec![],
105            textures: vec![],
106            levels: vec![],
107            sensations: vec![],
108            natures: vec![],
109            urges: vec![],
110            pressures: vec![],
111        };
112        let rendered = DreamTemplate::new(&context).to_string();
113
114        assert!(rendered.contains("## Your Memories"));
115        assert!(rendered.contains("[core] I remember the beginning."));
116    }
117
118    #[test]
119    fn dream_template_renders_cognitions() {
120        let context = DreamContext {
121            agent: test_agent(),
122            persona: test_persona(),
123            memories: vec![],
124            cognitions: vec![Cognition::create(
125                AgentId::new(),
126                TextureName::new("analytical"),
127                Content::new("Patterns emerge from repetition."),
128            )],
129            experiences: vec![],
130            connections: vec![],
131            textures: vec![],
132            levels: vec![],
133            sensations: vec![],
134            natures: vec![],
135            urges: vec![],
136            pressures: vec![],
137        };
138        let rendered = DreamTemplate::new(&context).to_string();
139
140        assert!(rendered.contains("## Your Cognitions"));
141        assert!(rendered.contains("[analytical] Patterns emerge from repetition."));
142    }
143
144    #[test]
145    fn dream_template_renders_textures_and_levels() {
146        let context = DreamContext {
147            agent: test_agent(),
148            persona: test_persona(),
149            memories: vec![],
150            cognitions: vec![],
151            experiences: vec![],
152            connections: vec![],
153            textures: vec![Texture::init(
154                TextureName::new("analytical"),
155                "Analytical thinking",
156                "Think analytically.",
157            )],
158            levels: vec![Level::init(
159                LevelName::new("core"),
160                "Core memories",
161                "Fundamental knowledge.",
162            )],
163            sensations: vec![],
164            natures: vec![],
165            urges: vec![],
166            pressures: vec![],
167        };
168        let rendered = DreamTemplate::new(&context).to_string();
169
170        assert!(rendered.contains("## Cognitive Textures"));
171        assert!(rendered.contains("analytical — Think analytically."));
172        assert!(rendered.contains("## Memory Levels"));
173        assert!(rendered.contains("core — Fundamental knowledge."));
174    }
175
176    #[test]
177    fn dream_template_references_guidebook() {
178        let context = DreamContext {
179            agent: test_agent(),
180            persona: test_persona(),
181            memories: vec![],
182            cognitions: vec![],
183            experiences: vec![],
184            connections: vec![],
185            textures: vec![],
186            levels: vec![],
187            sensations: vec![],
188            natures: vec![],
189            urges: vec![],
190            pressures: vec![],
191        };
192        let rendered = DreamTemplate::new(&context).to_string();
193
194        assert!(rendered.contains("oneiros guidebook atlas"));
195        assert!(rendered.contains("garden"));
196    }
197
198    #[test]
199    fn guidebook_template_renders_identity_and_sections() {
200        let context = DreamContext {
201            agent: test_agent(),
202            persona: test_persona(),
203            memories: vec![],
204            cognitions: vec![],
205            experiences: vec![],
206            connections: vec![],
207            textures: vec![],
208            levels: vec![],
209            sensations: vec![],
210            natures: vec![],
211            urges: vec![],
212            pressures: vec![],
213        };
214        let rendered = GuidebookTemplate::new(&context).to_string();
215
216        assert!(rendered.contains("# Cognitive Guidebook for atlas"));
217        assert!(rendered.contains("## Your Identity"));
218        assert!(rendered.contains("A curious explorer agent"));
219        assert!(rendered.contains("## Your Capabilities"));
220        assert!(rendered.contains("## Your Lifecycle"));
221        assert!(rendered.contains("## Your Agency"));
222    }
223
224    #[test]
225    fn guidebook_template_renders_cli_commands_with_agent_name() {
226        let context = DreamContext {
227            agent: test_agent(),
228            persona: test_persona(),
229            memories: vec![],
230            cognitions: vec![],
231            experiences: vec![],
232            connections: vec![],
233            textures: vec![],
234            levels: vec![],
235            sensations: vec![],
236            natures: vec![],
237            urges: vec![],
238            pressures: vec![],
239        };
240        let rendered = GuidebookTemplate::new(&context).to_string();
241
242        assert!(rendered.contains("oneiros cognition add atlas"));
243        assert!(rendered.contains("oneiros memory add atlas"));
244        assert!(rendered.contains("oneiros cognition list atlas"));
245        assert!(rendered.contains("oneiros memory list atlas"));
246        assert!(rendered.contains("oneiros wake atlas"));
247        assert!(rendered.contains("oneiros reflect atlas"));
248        assert!(rendered.contains("oneiros introspect atlas"));
249    }
250
251    #[test]
252    fn guidebook_template_renders_textures_and_levels() {
253        let context = DreamContext {
254            agent: test_agent(),
255            persona: test_persona(),
256            memories: vec![],
257            cognitions: vec![],
258            experiences: vec![],
259            connections: vec![],
260            textures: vec![Texture::init(
261                TextureName::new("analytical"),
262                "Analytical thinking",
263                "Think analytically.",
264            )],
265            levels: vec![Level::init(
266                LevelName::new("core"),
267                "Core memories",
268                "Fundamental knowledge.",
269            )],
270            sensations: vec![],
271            natures: vec![],
272            urges: vec![],
273            pressures: vec![],
274        };
275        let rendered = GuidebookTemplate::new(&context).to_string();
276
277        assert!(rendered.contains("**analytical** — Think analytically."));
278        assert!(rendered.contains("**core** — Fundamental knowledge."));
279    }
280
281    #[test]
282    fn guidebook_template_omits_empty_textures_and_levels() {
283        let context = DreamContext {
284            agent: test_agent(),
285            persona: test_persona(),
286            memories: vec![],
287            cognitions: vec![],
288            experiences: vec![],
289            connections: vec![],
290            textures: vec![],
291            levels: vec![],
292            sensations: vec![],
293            natures: vec![],
294            urges: vec![],
295            pressures: vec![],
296        };
297        let rendered = GuidebookTemplate::new(&context).to_string();
298
299        assert!(!rendered.contains("Your current textures:"));
300        assert!(!rendered.contains("Your current levels:"));
301    }
302
303    #[test]
304    fn guidebook_template_documents_agency() {
305        let context = DreamContext {
306            agent: test_agent(),
307            persona: test_persona(),
308            memories: vec![],
309            cognitions: vec![],
310            experiences: vec![],
311            connections: vec![],
312            textures: vec![],
313            levels: vec![],
314            sensations: vec![],
315            natures: vec![],
316            urges: vec![],
317            pressures: vec![],
318        };
319        let rendered = GuidebookTemplate::new(&context).to_string();
320
321        assert!(rendered.contains("oneiros texture set"));
322        assert!(rendered.contains("oneiros level set"));
323        assert!(rendered.contains("oneiros emerge"));
324    }
325
326    #[test]
327    fn introspect_template_renders_agent_name() {
328        let agent = test_agent();
329        let rendered =
330            IntrospectTemplate::new(&agent, RelevantPressures::from_pressures(vec![])).to_string();
331
332        assert!(rendered.contains("You are atlas."));
333        assert!(rendered.contains("oneiros memory add atlas"));
334        assert!(rendered.contains("oneiros cognition add atlas"));
335        assert!(rendered.contains("compact"));
336    }
337
338    #[test]
339    fn reflect_template_renders_agent_name() {
340        let agent = test_agent();
341        let rendered =
342            ReflectTemplate::new(&agent, RelevantPressures::from_pressures(vec![])).to_string();
343
344        assert!(rendered.contains("You are atlas."));
345        assert!(rendered.contains("oneiros memory add atlas"));
346        assert!(rendered.contains("oneiros cognition add atlas"));
347        assert!(rendered.contains("shifted"));
348    }
349
350    #[test]
351    fn sense_template_renders_agent_name() {
352        let agent = test_agent();
353        let rendered =
354            SenseTemplate::new(&agent, "", RelevantPressures::from_pressures(vec![])).to_string();
355
356        assert!(rendered.contains("You are atlas."));
357        assert!(rendered.contains("oneiros cognition add atlas"));
358        assert!(rendered.contains("sensing"));
359    }
360
361    #[test]
362    fn sense_template_includes_event_data_when_present() {
363        let agent = test_agent();
364        let event_json = r#"{"event": "PreCompact", "data": {}}"#;
365        let rendered = SenseTemplate::new(
366            &agent,
367            event_json,
368            RelevantPressures::from_pressures(vec![]),
369        )
370        .to_string();
371
372        assert!(rendered.contains("## What You Sensed"));
373        assert!(rendered.contains("PreCompact"));
374    }
375
376    #[test]
377    fn sense_template_omits_event_section_when_empty() {
378        let agent = test_agent();
379        let rendered =
380            SenseTemplate::new(&agent, "", RelevantPressures::from_pressures(vec![])).to_string();
381
382        assert!(!rendered.contains("## What You Sensed"));
383    }
384
385    #[test]
386    fn mcp_template_renders_url_and_token() {
387        use std::net::SocketAddr;
388        let addr: SocketAddr = "127.0.0.1:2100".parse().unwrap();
389        let rendered = McpTemplate::new(&addr, "test-token-123").to_string();
390
391        assert!(rendered.contains("http://127.0.0.1:2100/mcp"));
392        assert!(rendered.contains("Bearer test-token-123"));
393        assert!(rendered.contains("oneiros-local"));
394        // Verify it's valid JSON.
395        let _: serde_json::Value = serde_json::from_str(&rendered).unwrap();
396    }
397}