1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
6#[serde(rename_all = "snake_case")]
7pub enum InputType {
8 Message,
9 Heartbeat,
10 Cron,
11 Hook,
12 Webhook,
13 AgentMessage,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct InputSource {
19 pub channel: String,
21 pub identifier: String,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(rename_all = "snake_case")]
28pub enum HookEvent {
29 AppStarted,
30 AppStopping,
31 SessionStarted {
32 session_key: String,
33 },
34 SessionCompleted {
35 session_key: String,
36 },
37 SessionError {
38 session_key: String,
39 error: String,
40 },
41 RoutineTriggered {
42 routine_id: String,
43 },
44 RoutineCompleted {
45 routine_id: String,
46 },
47 Custom {
48 name: String,
49 data: serde_json::Value,
50 },
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct KeelInput {
59 pub id: String,
60 pub input_type: InputType,
61 pub source: InputSource,
62 pub payload: serde_json::Value,
63 pub session_key: Option<String>,
64 pub project_id: Option<String>,
65 pub created_at: DateTime<Utc>,
66}
67
68impl KeelInput {
69 pub fn new(
70 input_type: InputType,
71 source: InputSource,
72 payload: serde_json::Value,
73 ) -> Self {
74 Self {
75 id: uuid::Uuid::new_v4().to_string(),
76 input_type,
77 source,
78 payload,
79 session_key: None,
80 project_id: None,
81 created_at: Utc::now(),
82 }
83 }
84
85 pub fn with_session(mut self, key: String) -> Self {
86 self.session_key = Some(key);
87 self
88 }
89
90 pub fn with_project(mut self, id: String) -> Self {
91 self.project_id = Some(id);
92 self
93 }
94
95 pub fn message(channel: &str, identifier: &str, text: &str) -> Self {
97 Self::new(
98 InputType::Message,
99 InputSource {
100 channel: channel.to_string(),
101 identifier: identifier.to_string(),
102 },
103 serde_json::json!({ "text": text }),
104 )
105 }
106
107 pub fn heartbeat(prompt: &str) -> Self {
109 Self::new(
110 InputType::Heartbeat,
111 InputSource {
112 channel: "system".to_string(),
113 identifier: "heartbeat".to_string(),
114 },
115 serde_json::json!({ "prompt": prompt }),
116 )
117 }
118
119 pub fn cron(job_name: &str, prompt: &str) -> Self {
121 Self::new(
122 InputType::Cron,
123 InputSource {
124 channel: "system".to_string(),
125 identifier: job_name.to_string(),
126 },
127 serde_json::json!({ "prompt": prompt }),
128 )
129 }
130
131 pub fn hook(event: HookEvent) -> Self {
133 let payload = serde_json::to_value(&event).unwrap_or_default();
134 Self::new(
135 InputType::Hook,
136 InputSource {
137 channel: "system".to_string(),
138 identifier: "hook".to_string(),
139 },
140 payload,
141 )
142 }
143
144 pub fn webhook(endpoint: &str, payload: serde_json::Value) -> Self {
146 Self::new(
147 InputType::Webhook,
148 InputSource {
149 channel: "webhook".to_string(),
150 identifier: endpoint.to_string(),
151 },
152 payload,
153 )
154 }
155
156 pub fn agent_message(from_agent: &str, to_agent: &str, text: &str) -> Self {
158 Self::new(
159 InputType::AgentMessage,
160 InputSource {
161 channel: "agent".to_string(),
162 identifier: from_agent.to_string(),
163 },
164 serde_json::json!({ "to": to_agent, "text": text }),
165 )
166 }
167}