zeph_commands/handlers/
caveman.rs1use std::future::Future;
7use std::pin::Pin;
8
9use crate::context::CommandContext;
10use crate::{CommandError, CommandHandler, CommandOutput, SlashCategory};
11
12pub struct CavemanCommand;
19
20impl CommandHandler<CommandContext<'_>> for CavemanCommand {
21 fn name(&self) -> &'static str {
22 "/caveman"
23 }
24
25 fn description(&self) -> &'static str {
26 "Toggle ultra-compressed (telegraphic) output mode"
27 }
28
29 fn args_hint(&self) -> &'static str {
30 "[on|off|status]"
31 }
32
33 fn category(&self) -> SlashCategory {
34 SlashCategory::Configuration
35 }
36
37 fn requires_auth(&self) -> bool {
38 true
39 }
40
41 fn handle<'a>(
42 &'a self,
43 ctx: &'a mut CommandContext<'_>,
44 args: &'a str,
45 ) -> Pin<Box<dyn Future<Output = Result<CommandOutput, CommandError>> + Send + 'a>> {
46 use tracing::Instrument as _;
47 let span = tracing::info_span!("commands.caveman.handle");
48 Box::pin(
49 async move {
50 let result = ctx.agent.handle_caveman(args).await;
51 Ok(CommandOutput::Message(result))
52 }
53 .instrument(span),
54 )
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61 use crate::handlers::test_helpers::{MockDebug, MockMessages, MockSession, make_ctx};
62 use crate::sink::NullSink;
63 use std::assert_matches;
64
65 #[test]
66 fn caveman_name_and_description() {
67 assert_eq!(CavemanCommand.name(), "/caveman");
68 assert!(!CavemanCommand.description().is_empty());
69 }
70
71 #[tokio::test]
72 async fn caveman_returns_message_with_null_agent() {
73 let mut sink = NullSink;
74 let mut debug = MockDebug;
75 let mut messages = MockMessages;
76 let session = MockSession;
77 let mut agent = crate::NullAgent;
78 let mut ctx = make_ctx(&mut sink, &mut debug, &mut messages, &session, &mut agent);
79 let out = CavemanCommand.handle(&mut ctx, "").await.unwrap();
80 assert_matches!(out, CommandOutput::Message(_));
81 }
82}