dashboard: question_added / question_resolved mutation events + client derived state

This commit is contained in:
müde 2026-05-17 13:33:02 +02:00
parent 56d615b51f
commit 1879b2f485
6 changed files with 175 additions and 15 deletions

View file

@ -73,7 +73,8 @@ pub fn handle_ask(
// Agent-targeted questions need to wake the recipient — drop a
// QuestionAsked event into their inbox so the answerer doesn't
// have to poll. Operator-targeted questions show up on the
// dashboard's pending pane via `pending()` instead.
// dashboard's pending pane via `pending()` instead, plus a
// `QuestionAdded` dashboard event so the browser updates live.
if let Some(target_agent) = target {
coord.notify_agent(
target_agent,
@ -85,6 +86,8 @@ pub fn handle_ask(
multi,
},
);
} else {
coord.emit_question_added(id, asker, question, options, multi, deadline_at);
}
if let Some(t) = ttl {
spawn_question_watchdog(coord, id, t);
@ -103,7 +106,7 @@ pub fn handle_answer(
answer: &str,
) -> Result<(), String> {
limits::check_size("answer", answer)?;
let (question, asker, _target) = coord
let (question, asker, target) = coord
.questions
.answer(id, answer, answerer)
.map_err(|e| format!("{e:#}"))?;
@ -117,6 +120,13 @@ pub fn handle_answer(
answerer: answerer.to_owned(),
},
);
// Only operator-targeted questions surface on the dashboard;
// peer-to-peer answers are invisible to it. `cancelled = false`
// because this path is a real answer (operator cancel goes
// through `post_cancel_question` directly).
if target.is_none() {
coord.emit_question_resolved(id, answer, answerer, false);
}
Ok(())
}