damocles-daemon/src/types.rs

138 lines
3.5 KiB
Rust

use std::collections::HashMap;
use matrix_sdk::{
authentication::matrix::MatrixSession,
ruma::{OwnedEventId, OwnedRoomId, OwnedUserId},
};
use serde::{Deserialize, Serialize};
/// Serializable shape for one timeline event, used both in matrix_turn JSON
/// (input to the shard) and tool response JSON (get_room_history,
/// fetch_event).
#[derive(Debug, Serialize)]
#[serde(tag = "kind", rename_all = "lowercase")]
pub enum WireEvent {
Message {
event_id: String,
event_id_short: String,
sender: String,
is_self: bool,
ts: i64,
ts_human: String,
body: String,
in_reply_to: Option<String>,
read_by: Vec<String>,
},
Reaction {
sender: String,
is_self: bool,
ts: i64,
ts_human: String,
target_event_id: String,
target_event_id_short: String,
key: String,
},
}
#[derive(Debug, Serialize)]
pub struct RoomInfo {
pub room_id: String,
pub name: String,
}
#[derive(Debug, Serialize)]
pub struct MemberInfo {
pub user_id: String,
pub display_name: String,
}
#[derive(Debug, Serialize)]
pub struct FetchEventResult {
pub event: Option<WireEvent>,
pub context_before: Vec<WireEvent>,
pub earlier_handle: Option<String>,
}
pub const DEFAULT_MODEL: &str = "claude-sonnet-4-6";
pub const DEFAULT_MAX_HISTORY: usize = 20;
pub const DEFAULT_RATE_LIMIT_PER_MIN: u32 = 1;
#[derive(Debug, Deserialize)]
pub struct Config {
pub homeserver: String,
pub username: String,
pub password: String,
pub rate_limit_per_min: Option<u32>,
pub model: Option<String>,
pub max_history: Option<usize>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PersistedSession {
pub homeserver: String,
pub db_path: std::path::PathBuf,
pub user_session: MatrixSession,
#[serde(skip_serializing_if = "Option::is_none")]
pub sync_token: Option<String>,
}
#[derive(Clone, Debug)]
pub enum TimelineItem {
Message {
event_id: OwnedEventId,
sender: OwnedUserId,
body: String,
is_self: bool,
/// Unix seconds. 0 if unknown.
ts: i64,
in_reply_to: Option<OwnedEventId>,
},
Reaction {
sender: OwnedUserId,
target_event_id: OwnedEventId,
key: String,
is_self: bool,
ts: i64,
},
}
impl TimelineItem {
pub fn ts(&self) -> i64 {
match self {
Self::Message { ts, .. } | Self::Reaction { ts, .. } => *ts,
}
}
pub fn event_id(&self) -> Option<&OwnedEventId> {
match self {
Self::Message { event_id, .. } => Some(event_id),
Self::Reaction { .. } => None,
}
}
pub fn sender(&self) -> &OwnedUserId {
match self {
Self::Message { sender, .. } | Self::Reaction { sender, .. } => sender,
}
}
pub fn is_self(&self) -> bool {
match self {
Self::Message { is_self, .. } | Self::Reaction { is_self, .. } => *is_self,
}
}
}
pub struct DaemonState {
pub own_user_id: OwnedUserId,
/// Per-room: the latest event_id that's been "shown" to Claude. Events
/// after this are "new" on the next invocation. Cleared on daemon restart.
pub last_shown: HashMap<OwnedRoomId, OwnedEventId>,
pub pending_rooms: Vec<OwnedRoomId>,
pub rate_budget: u32,
pub rate_limit_per_min: u32,
pub last_rate_reset: std::time::Instant,
pub model: String,
pub max_history: usize,
}