use kernel::{Address, ApprovalId, EventKind, EventRecord, RunId};
#[derive(Debug, Default)]
pub(crate) struct Room {
pub(crate) run: Option<RunId>,
pub(crate) waiting: Vec<ApprovalId>,
}
impl Room {
pub(crate) fn clear(&mut self) {
self.run = None;
self.waiting.clear();
}
pub(crate) fn read(&mut self, record: &EventRecord, room: &Address) -> Vec<String> {
if record.addr() != Some(room) {
return Vec::new();
}
let data = record.data().as_map();
let text = |key: &str| data.get(key).and_then(serde_json::Value::as_str);
let kind = record.kind();
if kind == EventKind::RunStarted {
self.run = Some(record.run());
Vec::new()
} else if kind == EventKind::RunFrozen {
if self.run == Some(record.run()) {
self.run = None;
}
Vec::new()
} else if kind == EventKind::ModelReturned {
replied(data.get("message"))
} else if kind == EventKind::ToolCalled {
vec![format!(
" {:<8} {}",
text("name").unwrap_or("tool"),
text("subject").unwrap_or("")
)]
} else if kind == EventKind::ApprovalRequested {
self.requested(data)
} else if kind == EventKind::ApprovalResolved {
if let Some(id) = text("id") {
self.waiting.retain(|waiting| waiting.as_str() != id);
}
Vec::new()
} else {
Vec::new()
}
}
}
impl Room {
fn requested(&mut self, data: &serde_json::Map<String, serde_json::Value>) -> Vec<String> {
match serde_json::from_value::<kernel::ApprovalItem>(serde_json::Value::Object(
data.clone(),
)) {
Ok(item) => {
let line = format!(" ? {} y approve n deny", item.action_desc);
self.waiting.push(item.id);
vec![line]
}
Err(err) => vec![format!(
" ? a request is waiting that this terminal cannot read ({err}); answer it in the WebUI"
)],
}
}
}
fn replied(message: Option<&serde_json::Value>) -> Vec<String> {
let blocks = message
.and_then(|message| message.get("content"))
.and_then(serde_json::Value::as_array);
blocks
.into_iter()
.flatten()
.filter(|block| block.get("type").and_then(serde_json::Value::as_str) == Some("text"))
.filter_map(|block| block.get("text").and_then(serde_json::Value::as_str))
.flat_map(str::lines)
.map(|line| format!(" {line}"))
.collect()
}