#![cfg(all(feature = "comms", any(unix, windows)))]
use serde::{Deserialize, Serialize};
use crate::comms::cursor::Cursor;
use crate::comms::ids::RoomId;
use crate::comms::model::{Room, RoomScope};
use crate::comms::protocol::SeqMeta;
#[derive(Debug, Clone, Deserialize, Serialize, schemars::JsonSchema)]
pub struct AgentRegisterParams {
#[serde(default)]
pub name: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub version: String,
#[serde(default)]
pub skills: Vec<String>,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct AgentRegisterResponse {
pub agent_id: String,
pub registered: bool,
}
#[derive(Debug, Clone, Deserialize, Serialize, schemars::JsonSchema)]
pub struct AgentListParams {
#[serde(default)]
pub room: Option<RoomId>,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct AgentSummary {
pub agent_id: String,
pub name: String,
pub description: String,
pub version: String,
pub skills: Vec<String>,
pub first_seen: i64,
pub last_seen: i64,
}
#[derive(Debug, Serialize)]
pub(super) struct AgentListResponse {
pub total: usize,
pub agents: Vec<AgentSummary>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ScopeInput {
Remote(String),
PathPrefix(std::path::PathBuf),
Session(String),
#[default]
Global,
}
impl From<ScopeInput> for RoomScope {
fn from(value: ScopeInput) -> Self {
match value {
ScopeInput::Remote(r) => RoomScope::Remote(r),
ScopeInput::PathPrefix(p) => RoomScope::PathPrefix(p),
ScopeInput::Session(s) => RoomScope::Session(s),
ScopeInput::Global => RoomScope::Global,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, schemars::JsonSchema)]
pub struct RoomCreateParams {
pub room: RoomId,
#[serde(default)]
pub scope: ScopeInput,
#[serde(default)]
pub title: Option<String>,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct RoomSummary {
pub room_id: String,
pub title: String,
pub created_at: i64,
pub last_activity_micros: i64,
pub stale: bool,
}
pub(super) const STALE_AFTER_HOURS: i64 = 168;
impl RoomSummary {
pub(super) fn from_room(room: &Room, now_micros: i64) -> Self {
let last = room.last_activity;
let window_micros = STALE_AFTER_HOURS * 3_600_000_000;
let stale = last == 0 || (now_micros - last) > window_micros;
Self {
room_id: room.room_id.as_str().to_string(),
title: room.title.clone(),
created_at: room.created_at,
last_activity_micros: last,
stale,
}
}
}
#[derive(Debug, Serialize)]
pub(super) struct RoomCreateResponse {
pub room: RoomSummary,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, schemars::JsonSchema)]
pub struct RoomListParams {}
#[derive(Debug, Serialize)]
pub(super) struct RoomListResponse {
pub total: usize,
pub rooms: Vec<RoomSummary>,
}
#[derive(Debug, Clone, Deserialize, Serialize, schemars::JsonSchema)]
pub struct RoomJoinParams {
pub room: RoomId,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize, schemars::JsonSchema)]
pub struct RoomLeaveParams {
pub room: RoomId,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct RoomMembershipResponse {
pub room: String,
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub joined: bool,
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub left: bool,
}
#[derive(Debug, Clone, Deserialize, Serialize, schemars::JsonSchema)]
pub struct RoomPostParams {
pub room: RoomId,
pub subject: String,
#[serde(default)]
pub body: Option<String>,
#[serde(default)]
pub tags: Option<Vec<String>>,
#[serde(default)]
pub reply_to: Option<String>,
#[serde(default)]
pub scope: Option<Vec<String>>,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct RoomPostResponse {
pub message_id: String,
}
#[derive(Debug, Clone, Deserialize, Serialize, schemars::JsonSchema)]
pub struct RoomHistoryParams {
pub room: RoomId,
#[serde(default)]
pub cursor: Option<String>,
#[serde(default)]
pub limit: Option<u32>,
#[serde(default)]
pub since_hours: Option<u32>,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct MessageFrontMatter {
pub id: String,
pub room: String,
pub from: String,
pub subject: String,
pub ts_micros: i64,
pub age_secs: i64,
pub tags: Vec<String>,
pub scope: Vec<String>,
pub reply_to: Option<String>,
pub seq: u64,
pub body_len: u32,
pub body_sha: String,
}
impl MessageFrontMatter {
pub(super) fn from_seq_meta(sm: &SeqMeta, now_micros: i64) -> Self {
let meta = &sm.meta;
Self {
id: meta.id.clone(),
room: meta.room.as_str().to_string(),
from: meta.from.as_str().to_string(),
subject: meta.subject.clone(),
ts_micros: meta.ts_micros,
age_secs: ((now_micros - meta.ts_micros) / 1_000_000).max(0),
tags: meta.tags.clone(),
scope: meta.scope.clone(),
reply_to: meta.reply_to.clone(),
seq: sm.seq,
body_len: meta.body_len,
body_sha: meta.body_sha.clone(),
}
}
}
#[derive(Debug, Serialize)]
pub(super) struct RoomHistoryResponse {
pub total: usize,
pub messages: Vec<MessageFrontMatter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_cursor: Option<Cursor>,
}
#[derive(Debug, Clone, Deserialize, Serialize, schemars::JsonSchema)]
pub struct MessageGetParams {
pub message_id: String,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct MessageGetResponse {
pub message_id: String,
pub found: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub body: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, schemars::JsonSchema)]
pub struct InboxReadParams {
#[serde(default)]
pub cursor: Option<String>,
#[serde(default)]
pub limit: Option<u32>,
#[serde(default)]
pub mark_read: bool,
#[serde(default)]
pub since_hours: Option<u32>,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct InboxReadResponse {
pub total: usize,
pub unread: u32,
pub messages: Vec<MessageFrontMatter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_cursor: Option<Cursor>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, schemars::JsonSchema)]
pub struct InboxAckParams {
#[serde(default)]
pub message_ids: Vec<String>,
#[serde(default)]
pub room: Option<RoomId>,
#[serde(default)]
pub to_seq: Option<u64>,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct CursorAdvance {
pub room: String,
pub seq: u64,
}
#[derive(Debug, Serialize)]
pub(super) struct InboxAckResponse {
pub acked: usize,
pub cursors_advanced: Vec<CursorAdvance>,
}
#[derive(Debug, Clone, Deserialize, Serialize, schemars::JsonSchema)]
pub struct GetOrCreateRoomForPathParams {
pub path: String,
#[serde(default)]
pub as_agent: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct GetOrCreateRoomForPathResponse {
pub room: String,
pub scope: String,
pub title: String,
pub created: bool,
}
#[derive(Debug, Clone, Deserialize, Serialize, schemars::JsonSchema)]
pub struct DmSendParams {
pub to_agent: String,
#[serde(default)]
pub as_agent: Option<String>,
pub subject: String,
#[serde(default)]
pub body: Option<String>,
#[serde(default)]
pub reply_to: Option<String>,
}
#[derive(Debug, Serialize)]
pub(super) struct DmSendResponse {
pub message_id: String,
pub room: String,
}