@@ -39,6 +39,9 @@ impl From<&[Model]> for Info {
39
39
/// - File content
40
40
#[ derive( Debug , Clone , PartialEq , Eq ) ]
41
41
pub enum Command {
42
+ /// Custom command dispatch that triggers event handling with a format of `/dispatch-event_name value`
43
+ /// The event_name must follow specific formatting rules (alphanumeric, plus hyphens and underscores)
44
+ Dispatch ( String , String ) ,
42
45
/// Start a new conversation while preserving history.
43
46
/// This can be triggered with the '/new' command.
44
47
New ,
@@ -82,6 +85,7 @@ impl Command {
82
85
"/plan" . to_string( ) ,
83
86
"/help" . to_string( ) ,
84
87
"/dump" . to_string( ) ,
88
+ "/dispatch-event_name" . to_string( ) ,
85
89
]
86
90
}
87
91
@@ -98,6 +102,29 @@ impl Command {
98
102
pub fn parse ( input : & str ) -> Self {
99
103
let trimmed = input. trim ( ) ;
100
104
105
+ // Check if this is a dispatch command
106
+ if trimmed. starts_with ( "/dispatch-" ) {
107
+ // Get everything after "/dispatch-" until a space or end of string
108
+ let ( event_name, value) = match trimmed[ 10 ..] . find ( ' ' ) {
109
+ Some ( space_index) => {
110
+ let event_name = & trimmed[ 10 ..10 + space_index] ;
111
+ let value = & trimmed[ 10 + space_index + 1 ..] ;
112
+ ( event_name. to_string ( ) , value. to_string ( ) )
113
+ }
114
+ None => {
115
+ // No space found, so everything after "/dispatch-" is the event name
116
+ // and value is empty
117
+ ( trimmed[ 10 ..] . to_string ( ) , "" . to_string ( ) )
118
+ }
119
+ } ;
120
+
121
+ // Validate event name - only allow alphanumeric, underscores, and hyphens
122
+ if event_name. chars ( ) . all ( |c| c. is_alphanumeric ( ) || c == '_' || c == '-' ) {
123
+ return Command :: Dispatch ( event_name, value) ;
124
+ }
125
+ // If event name is invalid, treat as a regular message
126
+ }
127
+
101
128
match trimmed {
102
129
"/new" => Command :: New ,
103
130
"/info" => Command :: Info ,
@@ -141,3 +168,49 @@ pub trait UserInput {
141
168
/// * `Err` - An error occurred during input processing
142
169
async fn prompt ( & self , input : Option < Self :: PromptInput > ) -> anyhow:: Result < Command > ;
143
170
}
171
+ #[ cfg( test) ]
172
+ mod tests {
173
+ use super :: * ;
174
+
175
+ #[ test]
176
+ fn test_parse_dispatch_command ( ) {
177
+ // Test valid dispatch command with value
178
+ let input = "/dispatch-test_event This is a test value" ;
179
+ match Command :: parse ( input) {
180
+ Command :: Dispatch ( event_name, value) => {
181
+ assert_eq ! ( event_name, "test_event" ) ;
182
+ assert_eq ! ( value, "This is a test value" ) ;
183
+ }
184
+ _ => panic ! ( "Failed to parse valid dispatch command" ) ,
185
+ }
186
+
187
+ // Test valid dispatch command with no value
188
+ let input = "/dispatch-empty_event" ;
189
+ match Command :: parse ( input) {
190
+ Command :: Dispatch ( event_name, value) => {
191
+ assert_eq ! ( event_name, "empty_event" ) ;
192
+ assert_eq ! ( value, "" ) ;
193
+ }
194
+ _ => panic ! ( "Failed to parse valid dispatch command without value" ) ,
195
+ }
196
+
197
+ // Test dispatch command with hyphens and underscores
198
+ let input = "/dispatch-custom-event_name Some value" ;
199
+ match Command :: parse ( input) {
200
+ Command :: Dispatch ( event_name, value) => {
201
+ assert_eq ! ( event_name, "custom-event_name" ) ;
202
+ assert_eq ! ( value, "Some value" ) ;
203
+ }
204
+ _ => panic ! ( "Failed to parse valid dispatch command with hyphens and underscores" ) ,
205
+ }
206
+
207
+ // Test invalid dispatch command (contains invalid characters)
208
+ let input = "/dispatch-invalid!event Value" ;
209
+ match Command :: parse ( input) {
210
+ Command :: Message ( message) => {
211
+ assert_eq ! ( message, input) ;
212
+ }
213
+ _ => panic ! ( "Invalid dispatch command should be treated as a message" ) ,
214
+ }
215
+ }
216
+ }
0 commit comments