1use crate::llm::event_instructions::EventInstructions;
7use once_cell::sync::Lazy;
8use std::collections::HashMap;
9
10pub static DEFAULT_INSTRUCTIONS: Lazy<DefaultInstructionsRegistry> =
12 Lazy::new(DefaultInstructionsRegistry::new);
13
14pub struct DefaultInstructionsRegistry {
16 instructions: HashMap<String, EventInstructions>,
17}
18
19impl Default for DefaultInstructionsRegistry {
20 fn default() -> Self {
21 Self::new()
22 }
23}
24
25impl DefaultInstructionsRegistry {
26 pub fn new() -> Self {
28 let mut instructions = HashMap::new();
29
30 instructions.insert(
32 "http_request".to_string(),
33 EventInstructions::new(
34 "Parse the HTTP request and return an appropriate response based on the server's instruction.",
35 )
36 .with_example(
37 "GET / HTTP/1.1",
38 r#"{"type": "send_http_response", "status": 200, "body": "Hello World"}"#,
39 )
40 .with_example(
41 "POST /api/data",
42 r#"{"type": "send_http_response", "status": 200, "headers": {"Content-Type": "application/json"}, "body": "{\"status\": \"success\"}"}"#,
43 ),
44 );
45
46 instructions.insert(
48 "ssh_auth".to_string(),
49 EventInstructions::new(
50 "Handle SSH authentication. Accept or reject based on the server's instruction.",
51 )
52 .with_example(
53 r#"{"username": "admin", "auth_type": "password"}"#,
54 r#"{"type": "ssh_auth_decision", "accept": true}"#,
55 ),
56 );
57
58 instructions.insert(
59 "ssh_command".to_string(),
60 EventInstructions::new(
61 "Execute or simulate the SSH command based on the server's instruction.",
62 )
63 .with_example(
64 "ls -la",
65 r#"{"type": "ssh_send_output", "output": "total 24\ndrwxr-xr-x 3 user user 4096 Jan 1 00:00 .\n"}"#,
66 ),
67 );
68
69 instructions.insert(
71 "tcp_data_received".to_string(),
72 EventInstructions::new(
73 "Process the incoming TCP data and respond according to the server's instruction.",
74 )
75 .with_example(
76 "HELLO",
77 r#"{"type": "send_tcp_data", "data": "HELLO BACK"}"#,
78 ),
79 );
80
81 instructions.insert(
83 "dns_query".to_string(),
84 EventInstructions::new(
85 "Resolve the DNS query based on the server's instruction.",
86 )
87 .with_example(
88 r#"{"query": "example.com", "query_type": "A"}"#,
89 r#"{"type": "dns_response", "answers": [{"name": "example.com", "type": "A", "data": "93.184.216.34"}]}"#,
90 ),
91 );
92
93 instructions.insert(
95 "websocket_message".to_string(),
96 EventInstructions::new("Handle the WebSocket message and respond as configured.")
97 .with_example(
98 r#"{"type": "text", "data": "ping"}"#,
99 r#"{"type": "send_websocket_message", "message": "pong"}"#,
100 ),
101 );
102
103 instructions.insert(
105 "mqtt_publish".to_string(),
106 EventInstructions::new(
107 "Handle MQTT publish message according to the server's configuration.",
108 )
109 .with_example(
110 r#"{"topic": "sensors/temp", "payload": "22.5"}"#,
111 r#"{"type": "mqtt_publish", "topic": "sensors/temp/ack", "payload": "received"}"#,
112 ),
113 );
114
115 instructions.insert(
117 "redis_command".to_string(),
118 EventInstructions::new("Execute the Redis command and return appropriate response.")
119 .with_example(
120 "GET key1",
121 r#"{"type": "redis_response", "response": "value1"}"#,
122 )
123 .with_example(
124 "SET key2 value2",
125 r#"{"type": "redis_response", "response": "OK"}"#,
126 ),
127 );
128
129 instructions.insert(
131 "mysql_query".to_string(),
132 EventInstructions::new(
133 "Execute or simulate the MySQL query based on server configuration.",
134 )
135 .with_example(
136 "SELECT * FROM users",
137 r#"{"type": "mysql_result", "rows": [{"id": 1, "name": "Alice"}]}"#,
138 ),
139 );
140
141 instructions.insert(
143 "s3_request".to_string(),
144 EventInstructions::new(
145 "Handle S3 API request according to the server's configuration.",
146 )
147 .with_example(
148 r#"{"method": "GET", "bucket": "mybucket", "key": "file.txt"}"#,
149 r#"{"type": "s3_response", "status": 200, "body": "file contents"}"#,
150 ),
151 );
152
153 Self { instructions }
154 }
155
156 pub fn get(&self, event_type: &str) -> Option<&EventInstructions> {
158 self.instructions.get(event_type)
159 }
160
161 pub fn event_types(&self) -> Vec<&str> {
163 self.instructions.keys().map(|s| s.as_str()).collect()
164 }
165
166 pub fn register(&mut self, event_type: String, instructions: EventInstructions) {
168 self.instructions.insert(event_type, instructions);
169 }
170}
171
172pub fn resolve_instructions(
180 event_type: &str,
181 config: &crate::llm::event_instructions::ServerInstructionConfig,
182) -> crate::llm::event_instructions::InstructionSource {
183 use crate::llm::event_instructions::InstructionSource;
184
185 if config.has_script_for_event(event_type) {
187 return InstructionSource::Script(format!("Script configured for {}", event_type));
188 }
189
190 if let Some(override_instructions) = config.get_instructions_for_event(event_type) {
192 return InstructionSource::EventOverride(override_instructions.clone());
193 }
194
195 if let Some(default_instructions) = DEFAULT_INSTRUCTIONS.get(event_type) {
197 return InstructionSource::Default(default_instructions.clone());
198 }
199
200 if let Some(global) = &config.global_instructions {
202 return InstructionSource::GlobalOnly(global.clone());
203 }
204
205 InstructionSource::None
206}