#[cfg(feature = "http-api")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "http-api")]
use utoipa::ToSchema;
#[cfg(feature = "http-api")]
use crate::types::{AgentId, AgentState};
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct WorkflowExecutionRequest {
pub workflow_id: String,
pub parameters: serde_json::Value,
pub agent_id: Option<AgentId>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AgentSummary {
pub id: AgentId,
pub name: String,
pub state: AgentState,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AgentStatusResponse {
pub agent_id: AgentId,
pub state: AgentState,
pub last_activity: chrono::DateTime<chrono::Utc>,
pub resource_usage: ResourceUsage,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<std::collections::HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_result: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub recent_events: Option<Vec<AgentEvent>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub execution_mode: Option<String>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ResourceUsage {
pub memory_bytes: u64,
pub cpu_percent: f64,
pub active_tasks: u32,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct HealthResponse {
pub status: String,
pub uptime_seconds: u64,
pub timestamp: chrono::DateTime<chrono::Utc>,
pub version: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct SchedulerHealthResponse {
pub is_running: bool,
pub store_accessible: bool,
pub jobs_total: usize,
pub jobs_active: usize,
pub jobs_paused: usize,
pub jobs_dead_letter: usize,
pub global_active_runs: usize,
pub max_concurrent: usize,
pub runs_total: u64,
pub runs_succeeded: u64,
pub runs_failed: u64,
pub average_execution_time_ms: f64,
pub longest_run_ms: u64,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateAgentRequest {
pub name: String,
pub dsl: Option<String>,
#[schema(value_type = Object)]
pub execution_mode: Option<crate::types::agent::ExecutionMode>,
pub capabilities: Option<Vec<String>>,
pub metadata: Option<std::collections::HashMap<String, String>>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateAgentResponse {
pub id: String,
pub status: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateAgentRequest {
pub name: Option<String>,
pub dsl: Option<String>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateAgentResponse {
pub id: String,
pub status: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct DeleteAgentResponse {
pub id: String,
pub status: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ExecuteAgentRequest {
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ExecuteAgentResponse {
pub execution_id: String,
pub status: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AgentExecutionRecord {
pub execution_id: String,
pub status: String,
pub timestamp: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct GetAgentHistoryResponse {
pub history: Vec<AgentExecutionRecord>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ErrorResponse {
pub error: String,
pub code: String,
pub details: Option<serde_json::Value>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateScheduleRequest {
pub name: String,
#[schema(example = "0 */5 * * * *")]
pub cron_expression: String,
#[serde(default = "default_timezone")]
pub timezone: String,
pub agent_name: String,
#[serde(default)]
pub policy_ids: Vec<String>,
#[serde(default)]
pub one_shot: bool,
}
#[cfg(feature = "http-api")]
fn default_timezone() -> String {
"UTC".to_string()
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateScheduleResponse {
pub job_id: String,
pub next_run: Option<String>,
pub status: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateScheduleRequest {
#[schema(example = "0 */10 * * * *")]
pub cron_expression: Option<String>,
pub timezone: Option<String>,
pub policy_ids: Option<Vec<String>>,
pub one_shot: Option<bool>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ScheduleSummary {
pub job_id: String,
pub name: String,
pub cron_expression: String,
pub timezone: String,
pub status: String,
pub enabled: bool,
pub next_run: Option<String>,
pub run_count: u64,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ScheduleDetail {
pub job_id: String,
pub name: String,
pub cron_expression: String,
pub timezone: String,
pub status: String,
pub enabled: bool,
pub one_shot: bool,
pub next_run: Option<String>,
pub last_run: Option<String>,
pub run_count: u64,
pub failure_count: u64,
pub created_at: String,
pub updated_at: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct NextRunsResponse {
pub job_id: String,
pub next_runs: Vec<String>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ScheduleRunEntry {
pub run_id: String,
pub started_at: String,
pub completed_at: Option<String>,
pub status: String,
pub error: Option<String>,
pub execution_time_ms: Option<u64>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ScheduleHistoryResponse {
pub job_id: String,
pub history: Vec<ScheduleRunEntry>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ScheduleActionResponse {
pub job_id: String,
pub action: String,
pub status: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct DeleteScheduleResponse {
pub job_id: String,
pub deleted: bool,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct RegisterChannelRequest {
pub name: String,
pub platform: String,
pub config: serde_json::Value,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct RegisterChannelResponse {
pub id: String,
pub name: String,
pub platform: String,
pub status: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateChannelRequest {
pub config: Option<serde_json::Value>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ChannelSummary {
pub id: String,
pub name: String,
pub platform: String,
pub status: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ChannelDetail {
pub id: String,
pub name: String,
pub platform: String,
pub status: String,
pub config: serde_json::Value,
pub created_at: String,
pub updated_at: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ChannelActionResponse {
pub id: String,
pub action: String,
pub status: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct DeleteChannelResponse {
pub id: String,
pub deleted: bool,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ChannelHealthResponse {
pub id: String,
pub connected: bool,
pub platform: String,
pub workspace_name: Option<String>,
pub channels_active: usize,
pub last_message_at: Option<String>,
pub uptime_secs: u64,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct IdentityMappingEntry {
pub platform_user_id: String,
pub platform: String,
pub symbiont_user_id: String,
pub email: Option<String>,
pub display_name: String,
pub roles: Vec<String>,
pub verified: bool,
pub created_at: String,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AddIdentityMappingRequest {
pub platform_user_id: String,
pub symbiont_user_id: String,
pub email: Option<String>,
pub display_name: String,
pub roles: Vec<String>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ChannelAuditEntry {
pub timestamp: String,
pub event_type: String,
pub user_id: Option<String>,
pub channel_id: Option<String>,
pub agent: Option<String>,
pub details: serde_json::Value,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ChannelAuditResponse {
pub channel_id: String,
pub entries: Vec<ChannelAuditEntry>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub enum AgentEventType {
RunStarted,
RunCompleted,
RunFailed,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AgentEvent {
pub event_type: AgentEventType,
pub payload: serde_json::Value,
pub timestamp: chrono::DateTime<chrono::Utc>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone)]
pub struct ExternalAgentState {
pub last_heartbeat: Option<chrono::DateTime<chrono::Utc>>,
pub reported_state: crate::types::AgentState,
pub metadata: std::collections::HashMap<String, String>,
pub last_result: Option<String>,
pub events: std::collections::VecDeque<AgentEvent>,
}
#[cfg(feature = "http-api")]
impl Default for ExternalAgentState {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "http-api")]
impl ExternalAgentState {
pub fn new() -> Self {
Self {
last_heartbeat: None,
reported_state: crate::types::AgentState::Created,
metadata: std::collections::HashMap::new(),
last_result: None,
events: std::collections::VecDeque::new(),
}
}
pub fn push_event(&mut self, event: AgentEvent) {
if self.events.len() >= 100 {
self.events.pop_front();
}
self.events.push_back(event);
}
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct HeartbeatRequest {
pub state: crate::types::AgentState,
pub metadata: Option<std::collections::HashMap<String, String>>,
pub last_result: Option<String>,
}
#[cfg(feature = "http-api")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct PushEventRequest {
pub event_type: AgentEventType,
pub payload: serde_json::Value,
}
#[cfg(test)]
mod external_agent_tests {
use super::*;
#[test]
fn test_external_agent_state_new() {
let state = ExternalAgentState::new();
assert!(state.last_heartbeat.is_none());
assert_eq!(state.reported_state, crate::types::AgentState::Created);
assert!(state.events.is_empty());
}
#[test]
fn test_push_event_ring_buffer() {
let mut state = ExternalAgentState::new();
for i in 0..110 {
state.push_event(AgentEvent {
event_type: AgentEventType::RunStarted,
payload: serde_json::json!({ "run": i }),
timestamp: chrono::Utc::now(),
});
}
assert_eq!(state.events.len(), 100);
assert_eq!(state.events.front().unwrap().payload["run"], 10);
}
}