Skip to main content

feagi_api/v1/
agent_dtos.rs

1// Copyright 2025 Neuraville Inc.
2// Licensed under the Apache License, Version 2.0
3
4//! Agent API DTOs - Exact port from Python schemas
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use utoipa::ToSchema;
9
10/// Agent registration request
11#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
12pub struct AgentRegistrationRequest {
13    /// Type of agent (e.g., "brain_visualizer", "video_agent")
14    pub agent_type: String,
15
16    /// Unique identifier for the agent
17    pub agent_id: String,
18
19    /// Port the agent is listening on for data
20    pub agent_data_port: u16,
21
22    /// Version of the agent software
23    pub agent_version: String,
24
25    /// Version of the controller
26    pub controller_version: String,
27
28    /// Agent capabilities (sensory, motor, visualization, etc.)
29    pub capabilities: HashMap<String, serde_json::Value>,
30
31    /// Optional: Agent IP address (extracted from request if not provided)
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub agent_ip: Option<String>,
34
35    /// Optional: Additional metadata
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub metadata: Option<HashMap<String, serde_json::Value>>,
38
39    /// Optional: Auth token (base64, required by unified registration)
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub auth_token: Option<String>,
42
43    /// Optional: Transport the agent chose to use ("zmq", "websocket", "shm", etc.)
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub chosen_transport: Option<String>,
46}
47
48/// Transport configuration for an agent (from PNS)
49#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
50pub struct TransportConfig {
51    pub transport_type: String,
52    pub enabled: bool,
53    pub ports: HashMap<String, u16>,
54    pub host: String,
55}
56
57/// Agent registration response
58#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
59pub struct AgentRegistrationResponse {
60    pub status: String,
61    pub message: String,
62    pub success: bool,
63
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub transport: Option<HashMap<String, serde_json::Value>>,
66
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub rates: Option<HashMap<String, HashMap<String, f64>>>,
69
70    // FEAGI 2.0: Multi-transport support
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub transports: Option<Vec<TransportConfig>>,
73
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub recommended_transport: Option<String>,
76
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub shm_paths: Option<HashMap<String, String>>,
79
80    /// Cortical area availability status for agent operations
81    pub cortical_areas: serde_json::Value,
82}
83
84/// Heartbeat request
85#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
86pub struct HeartbeatRequest {
87    pub agent_id: String,
88}
89
90/// Heartbeat response
91#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
92pub struct HeartbeatResponse {
93    pub message: String,
94    pub success: bool,
95}
96
97/// Agent list response
98#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
99pub struct AgentListResponse {
100    /// List of agent IDs
101    #[serde(flatten)]
102    pub agent_ids: Vec<String>,
103}
104
105/// Agent properties response
106#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
107pub struct AgentPropertiesResponse {
108    pub agent_name: String,
109    pub agent_type: String,
110    pub agent_ip: String,
111    pub agent_data_port: u16,
112    pub agent_router_address: String,
113    pub agent_version: String,
114    pub controller_version: String,
115    pub capabilities: HashMap<String, serde_json::Value>,
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub chosen_transport: Option<String>,
118}
119
120/// Agent capabilities summary (optionally includes device registrations)
121#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
122pub struct AgentCapabilitiesSummary {
123    pub agent_name: String,
124    pub capabilities: HashMap<String, serde_json::Value>,
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub device_registrations: Option<serde_json::Value>,
127}
128
129/// Query parameters for bulk agent capabilities lookup
130#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
131pub struct AgentCapabilitiesAllQuery {
132    /// Filter by agent type (exact match)
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub agent_type: Option<String>,
135    /// Filter by capability key(s), comma-separated
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub capability: Option<String>,
138    /// Include device registration payloads per agent
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub include_device_registrations: Option<bool>,
141}
142
143/// Agent deregistration request
144#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
145pub struct AgentDeregistrationRequest {
146    pub agent_id: String,
147}
148
149/// Success response
150#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
151pub struct SuccessResponse {
152    pub message: String,
153    #[serde(skip_serializing_if = "Option::is_none")]
154    pub success: Option<bool>,
155}
156
157/// Manual stimulation request
158#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
159pub struct ManualStimulationRequest {
160    /// Map of cortical area IDs to lists of coordinates [[x, y, z], ...]
161    pub stimulation_payload: HashMap<String, Vec<Vec<i32>>>,
162    /// Optional stimulation mode: "candidate" (default) or "force_fire"
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub mode: Option<String>,
165}
166
167/// Manual stimulation response
168#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
169pub struct ManualStimulationResponse {
170    pub success: bool,
171    pub total_coordinates: usize,
172    pub requested_coordinates: usize,
173    pub matched_coordinates: usize,
174    pub unique_neuron_ids: usize,
175    pub mode: String,
176    pub successful_areas: usize,
177    pub failed_areas: Vec<String>,
178    #[serde(skip_serializing_if = "Option::is_none")]
179    pub error: Option<String>,
180}
181
182/// Device registration export response
183///
184/// Contains the complete device registration configuration including
185/// sensor and motor device registrations, encoder/decoder properties,
186/// and feedback configurations.
187#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
188pub struct DeviceRegistrationExportResponse {
189    /// Device registration configuration as JSON
190    /// This matches the format from ConnectorAgent::get_device_registration_json
191    pub device_registrations: serde_json::Value,
192    /// Agent ID this configuration belongs to
193    pub agent_id: String,
194}
195
196/// Device registration import request
197///
198/// Contains the device registration configuration to import.
199/// This will replace all existing device registrations for the agent.
200#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
201pub struct DeviceRegistrationImportRequest {
202    /// Device registration configuration as JSON
203    /// This matches the format expected by ConnectorAgent::set_device_registrations_from_json
204    pub device_registrations: serde_json::Value,
205}
206
207/// Device registration import response
208#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
209pub struct DeviceRegistrationImportResponse {
210    pub success: bool,
211    pub message: String,
212    pub agent_id: String,
213}