use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::core::types::Rect;
#[derive(Debug, Clone, Serialize)]
pub struct AgentWidget {
pub sub_id: String,
pub kind: String,
pub rect: Rect,
pub label: Option<String>,
#[serde(default)]
pub meta: Value,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AgentAction {
pub name: String,
#[serde(default)]
pub args: Value,
}
#[derive(Debug, Clone, Serialize)]
pub struct AgentActionReply {
pub ok: bool,
pub message: Option<String>,
pub log_payload: Option<Value>,
}
impl AgentActionReply {
pub fn ok() -> Self {
Self { ok: true, message: None, log_payload: None }
}
pub fn ok_with_log(payload: Value) -> Self {
Self { ok: true, message: None, log_payload: Some(payload) }
}
pub fn err(msg: impl Into<String>) -> Self {
Self { ok: false, message: Some(msg.into()), log_payload: None }
}
}
pub trait BlackboxAgentSurface: Send + 'static {
fn agent_slot_id(&self) -> &str;
fn agent_kind(&self) -> &str { self.agent_slot_id() }
fn list_agent_widgets(&self) -> Vec<AgentWidget> { Vec::new() }
fn agent_state(&self) -> Value { Value::Null }
fn apply_agent_action(&mut self, _action: AgentAction) -> AgentActionReply {
AgentActionReply::err("blackbox does not implement any actions")
}
fn resolve_click_widget(&self, sub_id: &str) -> Option<Rect> {
self.list_agent_widgets()
.into_iter()
.find(|w| w.sub_id == sub_id)
.map(|w| w.rect)
}
}