1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct AgentRegister {
6 pub agent_id: String,
7 pub role: AgentRole,
8 pub capabilities: Vec<String>,
9}
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct AgentStatus {
13 pub agent_id: String,
14 pub status: RunnerStatus,
15 pub metrics: HashMap<String, serde_json::Value>,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct AgentSkillReport {
20 pub agent_id: String,
21 pub skill_id: String,
22 pub result: SkillResult,
23 pub score: Option<f64>,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct AgentHealth {
28 pub agent_id: String,
29 pub health_checks: Vec<HealthCheck>,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct KingCommand {
34 pub command: String,
35 pub target_agent: String,
36 pub params: HashMap<String, serde_json::Value>,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct KingConfigUpdate {
41 pub config_type: String,
42 pub new_config_hash: String,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct PipelineNext {
47 pub stage: PipelineStage,
48 pub artifact_id: String,
49 pub metadata: HashMap<String, serde_json::Value>,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
53#[serde(rename_all = "snake_case")]
54pub enum AgentRole {
55 SkillManage,
56 Learning,
57 PreLoad,
58 Building,
59 Evaluation,
60 User(String),
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
64#[serde(rename_all = "snake_case")]
65pub enum RunnerStatus {
66 Starting,
67 Ready,
68 Busy,
69 Error,
70 Shutting,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
74#[serde(rename_all = "snake_case")]
75pub enum SkillResult {
76 Success,
77 Failure(String),
78 Partial(String),
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct HealthCheck {
83 pub name: String,
84 pub endpoint: String,
85 pub healthy: bool,
86 pub latency_ms: Option<u64>,
87 pub error: Option<String>,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
91#[serde(rename_all = "snake_case")]
92pub enum PipelineStage {
93 Learning,
94 Building,
95 PreLoad,
96 Evaluation,
97 SkillManage,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
101#[serde(rename_all = "snake_case")]
102pub enum PipelineRunStatus {
103 Running,
104 Completed,
105 Failed,
106 TimedOut,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct PipelineStageResult {
112 pub run_id: String,
113 pub stage: PipelineStage,
114 pub agent_id: String,
115 pub status: PipelineRunStatus,
116 pub artifact_id: String,
117 pub output: serde_json::Value,
118 pub error: Option<String>,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
122#[serde(rename_all = "snake_case")]
123pub enum TaskStatus {
124 Pending,
125 InProgress,
126 Completed,
127 Failed,
128 Cancelled,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct TaskCreate {
135 pub task_type: String,
136 #[serde(default)]
137 pub agent_id: Option<String>,
138 #[serde(default = "default_empty_object")]
139 pub payload: serde_json::Value,
140 #[serde(default)]
141 pub parent_id: Option<String>,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct TaskUpdate {
146 pub task_id: String,
147 #[serde(default)]
148 pub status: Option<TaskStatus>,
149 #[serde(default)]
150 pub agent_id: Option<String>,
151 #[serde(default)]
152 pub payload: Option<serde_json::Value>,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct TaskGet {
157 pub task_id: String,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct TaskList {
162 #[serde(default = "default_task_limit")]
163 pub limit: u32,
164 #[serde(default)]
165 pub status: Option<TaskStatus>,
166 #[serde(default)]
167 pub agent_id: Option<String>,
168 #[serde(default)]
169 pub parent_id: Option<String>,
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct TaskDelete {
174 pub task_id: String,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct TaskRecord {
179 pub id: String,
180 pub task_type: String,
181 pub status: String,
182 pub agent_id: String,
183 pub payload: serde_json::Value,
184 #[serde(default)]
185 pub parent_id: String,
186 pub created_at: String,
187 pub updated_at: String,
188}
189
190fn default_task_limit() -> u32 {
191 50
192}
193
194fn default_memory_limit() -> u32 {
195 20
196}
197
198fn default_empty_object() -> serde_json::Value {
199 serde_json::Value::Object(serde_json::Map::new())
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
205#[serde(rename_all = "snake_case")]
206pub enum MemoryScope {
207 System,
208 Agent,
209 Pipeline,
210 Skill,
211}
212
213#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
214#[serde(rename_all = "snake_case")]
215pub enum MemoryCategory {
216 Case,
217 Pattern,
218 Fact,
219 Preference,
220 Resource,
221 Event,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct MemoryTierEntry {
227 pub tier: String,
228 pub content: String,
229}
230
231#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct MemoryStore {
234 pub scope: MemoryScope,
235 pub category: MemoryCategory,
236 #[serde(default)]
237 pub key: String,
238 #[serde(default = "default_empty_object")]
239 pub metadata: serde_json::Value,
240 #[serde(default)]
241 pub tags: Vec<String>,
242 #[serde(default)]
243 pub agent_id: String,
244 #[serde(default)]
245 pub run_id: String,
246 #[serde(default)]
247 pub skill_id: String,
248 #[serde(default)]
249 pub relevance_score: f64,
250 #[serde(default)]
251 pub tiers: Vec<MemoryTierEntry>,
252 #[serde(default)]
253 pub task_id: Option<String>,
254}
255
256#[derive(Debug, Clone, Serialize, Deserialize)]
258pub struct MemoryQuery {
259 pub query: String,
260 #[serde(default)]
261 pub scope: Option<MemoryScope>,
262 #[serde(default)]
263 pub category: Option<MemoryCategory>,
264 #[serde(default)]
265 pub agent_id: Option<String>,
266 #[serde(default)]
267 pub tier: Option<String>,
268 #[serde(default)]
269 pub task_id: Option<String>,
270 #[serde(default = "default_memory_limit")]
271 pub limit: u32,
272}
273
274#[derive(Debug, Clone, Serialize, Deserialize)]
276pub struct MemoryTierRecord {
277 pub id: String,
278 pub memory_id: String,
279 pub tier: String,
280 pub content: String,
281 pub created_at: String,
282 pub updated_at: String,
283}
284
285#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct MemoryRecord {
288 pub id: String,
289 pub scope: String,
290 pub category: String,
291 pub key: String,
292 #[serde(default)]
293 pub tiers: Vec<MemoryTierRecord>,
294 #[serde(default = "default_empty_object")]
295 pub metadata: serde_json::Value,
296 #[serde(default)]
297 pub tags: Vec<String>,
298 #[serde(default)]
299 pub agent_id: String,
300 #[serde(default)]
301 pub run_id: String,
302 #[serde(default)]
303 pub skill_id: String,
304 #[serde(default)]
305 pub relevance_score: f64,
306 #[serde(default)]
307 pub access_count: i64,
308 pub created_at: String,
309 pub updated_at: String,
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize)]
314pub struct MemoryResult {
315 pub memories: Vec<MemoryRecord>,
316 pub count: u32,
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct MemoryChanged {
322 pub action: String,
323 #[serde(default)]
324 pub memory: Option<MemoryRecord>,
325 #[serde(default)]
326 pub memory_id: Option<String>,
327}
328
329#[derive(Debug, Clone, Serialize, Deserialize)]
333pub struct TaskInvite {
334 pub task_id: String,
335 pub task_type: String,
336 #[serde(default)]
337 pub payload: serde_json::Value,
338}
339
340#[derive(Debug, Clone, Serialize, Deserialize)]
342pub struct TaskOutput {
343 pub task_id: String,
344 pub request_id: String,
345 pub source: String,
347 pub delta: String,
348 pub chunk_index: u32,
349 #[serde(default)]
350 pub is_final: bool,
351}
352
353#[derive(Debug, Clone, Serialize, Deserialize)]
355pub struct TaskEvaluate {
356 pub task_id: String,
357 pub task_type: String,
358 #[serde(default)]
360 pub output_summary: String,
361 #[serde(default)]
362 pub exit_code: Option<i32>,
363 #[serde(default)]
364 pub latency_ms: Option<u64>,
365 #[serde(default)]
366 pub metadata: serde_json::Value,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize)]
371pub struct TaskSummary {
372 pub task_id: String,
373 pub agent_id: String,
374 pub summary: String,
375 #[serde(default)]
376 pub score: Option<f64>,
377 #[serde(default)]
378 pub tags: Vec<String>,
379 #[serde(default)]
380 pub evaluation: serde_json::Value,
381}
382
383pub mod events {
384 pub const AGENT_REGISTER: &str = "agent:register";
385 pub const AGENT_STATUS: &str = "agent:status";
386 pub const AGENT_SKILL_REPORT: &str = "agent:skill_report";
387 pub const AGENT_HEALTH: &str = "agent:health";
388 pub const KING_COMMAND: &str = "king:command";
389 pub const KING_CONFIG_UPDATE: &str = "king:config_update";
390 pub const PIPELINE_NEXT: &str = "pipeline:next";
391
392 pub const TASK_CREATE: &str = "task:create";
394 pub const TASK_UPDATE: &str = "task:update";
395 pub const TASK_GET: &str = "task:get";
396 pub const TASK_LIST: &str = "task:list";
397 pub const TASK_DELETE: &str = "task:delete";
398 pub const TASK_CHANGED: &str = "task:changed";
399
400 pub const PIPELINE_STAGE_RESULT: &str = "pipeline:stage_result";
402
403 pub const DEBUG_PROMPT: &str = "debug:prompt";
405 pub const DEBUG_RESPONSE: &str = "debug:response";
406 pub const DEBUG_STREAM: &str = "debug:stream";
407
408 pub const MEMORY_STORE: &str = "memory:store";
410 pub const MEMORY_QUERY: &str = "memory:query";
411 pub const MEMORY_UPDATE: &str = "memory:update";
412 pub const MEMORY_DELETE: &str = "memory:delete";
413 pub const MEMORY_CHANGED: &str = "memory:changed";
414
415 pub const TASK_INVITE: &str = "task:invite";
417 pub const TASK_JOIN: &str = "task:join";
418 pub const TASK_OUTPUT: &str = "task:output";
419 pub const TASK_EVALUATE: &str = "task:evaluate";
420 pub const TASK_SUMMARY: &str = "task:summary";
421 pub const TASK_LOG: &str = "task:log";
422
423 pub const KING_SYSTEM_INFO: &str = "king:system_info";
425
426 pub const ROOM_KERNEL: &str = "kernel";
428 pub const ROOM_ROLE_PREFIX: &str = "role:";
429 pub const ROOM_TASK_PREFIX: &str = "task:";
430}
431
432#[cfg(test)]
433mod tests {
434 use super::*;
435
436 #[test]
437 fn serialize_agent_register() {
438 let msg = AgentRegister {
439 agent_id: "learning-001".into(),
440 role: AgentRole::Learning,
441 capabilities: vec!["discover".into(), "evaluate".into()],
442 };
443 let json = serde_json::to_string(&msg).unwrap();
444 let deserialized: AgentRegister = serde_json::from_str(&json).unwrap();
445 assert_eq!(deserialized.agent_id, "learning-001");
446 assert_eq!(deserialized.role, AgentRole::Learning);
447 }
448
449 #[test]
450 fn serialize_pipeline_next() {
451 let msg = PipelineNext {
452 stage: PipelineStage::Building,
453 artifact_id: "skill-xyz".into(),
454 metadata: HashMap::new(),
455 };
456 let json = serde_json::to_string(&msg).unwrap();
457 let deserialized: PipelineNext = serde_json::from_str(&json).unwrap();
458 assert_eq!(deserialized.stage, PipelineStage::Building);
459 }
460
461 #[test]
462 fn serialize_task_status() {
463 let status = TaskStatus::InProgress;
464 let json = serde_json::to_string(&status).unwrap();
465 assert_eq!(json, r#""in_progress""#);
466 let de: TaskStatus = serde_json::from_str(&json).unwrap();
467 assert_eq!(de, TaskStatus::InProgress);
468 }
469
470 #[test]
471 fn serialize_task_create() {
472 let msg = TaskCreate {
473 task_type: "build".into(),
474 agent_id: Some("building-001".into()),
475 payload: serde_json::json!({"skill_id": "web-search"}),
476 parent_id: None,
477 };
478 let json = serde_json::to_string(&msg).unwrap();
479 let de: TaskCreate = serde_json::from_str(&json).unwrap();
480 assert_eq!(de.task_type, "build");
481 assert_eq!(de.agent_id.unwrap(), "building-001");
482 }
483
484 #[test]
485 fn deserialize_task_list_defaults() {
486 let msg: TaskList = serde_json::from_str("{}").unwrap();
487 assert_eq!(msg.limit, 50);
488 assert!(msg.status.is_none());
489 assert!(msg.agent_id.is_none());
490 }
491
492 #[test]
493 fn serialize_pipeline_run_status() {
494 let status = PipelineRunStatus::Running;
495 let json = serde_json::to_string(&status).unwrap();
496 assert_eq!(json, r#""running""#);
497 let de: PipelineRunStatus = serde_json::from_str(&json).unwrap();
498 assert_eq!(de, PipelineRunStatus::Running);
499
500 let timed_out = PipelineRunStatus::TimedOut;
501 let json = serde_json::to_string(&timed_out).unwrap();
502 assert_eq!(json, r#""timed_out""#);
503 }
504
505 #[test]
506 fn serialize_pipeline_stage_result() {
507 let result = PipelineStageResult {
508 run_id: "run-001".into(),
509 stage: PipelineStage::Learning,
510 agent_id: "learning-001".into(),
511 status: PipelineRunStatus::Completed,
512 artifact_id: "artifact-xyz".into(),
513 output: serde_json::json!({"candidates": 3}),
514 error: None,
515 };
516 let json = serde_json::to_string(&result).unwrap();
517 let de: PipelineStageResult = serde_json::from_str(&json).unwrap();
518 assert_eq!(de.run_id, "run-001");
519 assert_eq!(de.stage, PipelineStage::Learning);
520 assert_eq!(de.status, PipelineRunStatus::Completed);
521 assert!(de.error.is_none());
522 }
523
524 #[test]
525 fn serialize_pipeline_stage_result_with_error() {
526 let result = PipelineStageResult {
527 run_id: "run-002".into(),
528 stage: PipelineStage::Building,
529 agent_id: "building-001".into(),
530 status: PipelineRunStatus::Failed,
531 artifact_id: "".into(),
532 output: serde_json::Value::Null,
533 error: Some("build failed: missing dependency".into()),
534 };
535 let json = serde_json::to_string(&result).unwrap();
536 let de: PipelineStageResult = serde_json::from_str(&json).unwrap();
537 assert_eq!(de.status, PipelineRunStatus::Failed);
538 assert_eq!(de.error.unwrap(), "build failed: missing dependency");
539 }
540
541 #[test]
542 fn serialize_task_update_partial() {
543 let msg = TaskUpdate {
544 task_id: "abc-123".into(),
545 status: Some(TaskStatus::Completed),
546 agent_id: None,
547 payload: None,
548 };
549 let json = serde_json::to_string(&msg).unwrap();
550 let de: TaskUpdate = serde_json::from_str(&json).unwrap();
551 assert_eq!(de.task_id, "abc-123");
552 assert_eq!(de.status, Some(TaskStatus::Completed));
553 assert!(de.agent_id.is_none());
554 }
555
556 #[test]
557 fn deserialize_task_create_with_parent_id() {
558 let msg: TaskCreate =
559 serde_json::from_str(r#"{"task_type": "subtask", "parent_id": "abc-123"}"#).unwrap();
560 assert_eq!(msg.parent_id, Some("abc-123".to_string()));
561 }
562
563 #[test]
564 fn deserialize_task_create_without_parent_id() {
565 let msg: TaskCreate = serde_json::from_str(r#"{"task_type": "test"}"#).unwrap();
566 assert!(msg.parent_id.is_none());
567 }
568
569 #[test]
570 fn deserialize_task_list_with_parent_id() {
571 let msg: TaskList = serde_json::from_str(r#"{"parent_id": "parent-001"}"#).unwrap();
572 assert_eq!(msg.parent_id, Some("parent-001".to_string()));
573 assert_eq!(msg.limit, 50);
574 }
575
576 #[test]
577 fn serialize_memory_scope() {
578 let scope = MemoryScope::Agent;
579 let json = serde_json::to_string(&scope).unwrap();
580 assert_eq!(json, r#""agent""#);
581 let de: MemoryScope = serde_json::from_str(&json).unwrap();
582 assert_eq!(de, MemoryScope::Agent);
583 }
584
585 #[test]
586 fn serialize_memory_category() {
587 let cat = MemoryCategory::Pattern;
588 let json = serde_json::to_string(&cat).unwrap();
589 assert_eq!(json, r#""pattern""#);
590 let de: MemoryCategory = serde_json::from_str(&json).unwrap();
591 assert_eq!(de, MemoryCategory::Pattern);
592 }
593
594 #[test]
595 fn serialize_memory_store() {
596 let msg = MemoryStore {
597 scope: MemoryScope::Agent,
598 category: MemoryCategory::Pattern,
599 key: "memory://agent/learning/api_pattern".into(),
600 metadata: serde_json::json!({"source": "pipeline"}),
601 tags: vec!["discovery".into(), "api".into()],
602 agent_id: "learning-001".into(),
603 run_id: "".into(),
604 skill_id: "".into(),
605 relevance_score: 0.85,
606 tiers: vec![
607 MemoryTierEntry {
608 tier: "l0".into(),
609 content: "API discovery pattern".into(),
610 },
611 MemoryTierEntry {
612 tier: "l2".into(),
613 content: "Full detailed content...".into(),
614 },
615 ],
616 task_id: None,
617 };
618 let json = serde_json::to_string(&msg).unwrap();
619 let de: MemoryStore = serde_json::from_str(&json).unwrap();
620 assert_eq!(de.scope, MemoryScope::Agent);
621 assert_eq!(de.category, MemoryCategory::Pattern);
622 assert_eq!(de.tiers.len(), 2);
623 }
624
625 #[test]
626 fn deserialize_memory_query_defaults() {
627 let msg: MemoryQuery = serde_json::from_str(r#"{"query": "api discovery"}"#).unwrap();
628 assert_eq!(msg.limit, 20);
629 assert!(msg.scope.is_none());
630 assert!(msg.task_id.is_none());
631 }
632
633 #[test]
634 fn serialize_memory_changed() {
635 let msg = MemoryChanged {
636 action: "created".into(),
637 memory: None,
638 memory_id: Some("mem-001".into()),
639 };
640 let json = serde_json::to_string(&msg).unwrap();
641 let de: MemoryChanged = serde_json::from_str(&json).unwrap();
642 assert_eq!(de.action, "created");
643 assert_eq!(de.memory_id.unwrap(), "mem-001");
644 }
645}