dashboard: surface peer questions + operator override
questions pane now shows both operator-targeted threads (target IS NULL) and agent-to-agent threads (target = some agent). filter chips above the list: all / @operator / @peer / per-participant. peer rows get a mauve left rule + a 0V3RR1D3 button that POSTs the same /answer-question endpoint (OperatorQuestions::answer already permits the operator as answerer on any target). wire changes: OperatorQuestions gains pending_all + recent_answered_all; QuestionAdded + QuestionResolved events carry target: Option<String>; emit sites drop their target.is_none() guard. answered-history rows show the answerer prefix so override answers are auditable at a glance.
This commit is contained in:
parent
e7ce35c503
commit
a15fafb5de
9 changed files with 187 additions and 71 deletions
|
|
@ -307,9 +307,13 @@ async fn api_state(headers: HeaderMap, State(state): State<AppState>) -> axum::J
|
|||
// operator_inbox used to be served here as a 50-row array; the
|
||||
// dashboard now derives it client-side from the message stream
|
||||
// (terminal backfill + live SSE), so the snapshot stops shipping it.
|
||||
let questions = log_default("questions.pending", state.coord.questions.pending());
|
||||
let question_history =
|
||||
log_default("questions.recent_answered", state.coord.questions.recent_answered(20));
|
||||
// Both operator-targeted and peer threads now surface on the
|
||||
// dashboard. Client filters by target client-side.
|
||||
let questions = log_default("questions.pending_all", state.coord.questions.pending_all());
|
||||
let question_history = log_default(
|
||||
"questions.recent_answered_all",
|
||||
state.coord.questions.recent_answered_all(20),
|
||||
);
|
||||
|
||||
axum::Json(StateSnapshot {
|
||||
seq,
|
||||
|
|
@ -734,14 +738,13 @@ async fn post_answer_question(
|
|||
answerer: hive_sh4re::OPERATOR_RECIPIENT.to_owned(),
|
||||
},
|
||||
);
|
||||
if target.is_none() {
|
||||
state.coord.emit_question_resolved(
|
||||
id,
|
||||
answer,
|
||||
hive_sh4re::OPERATOR_RECIPIENT,
|
||||
false,
|
||||
);
|
||||
}
|
||||
state.coord.emit_question_resolved(
|
||||
id,
|
||||
answer,
|
||||
hive_sh4re::OPERATOR_RECIPIENT,
|
||||
false,
|
||||
target.as_deref(),
|
||||
);
|
||||
(StatusCode::OK, "ok").into_response()
|
||||
}
|
||||
Err(e) => error_response(&format!("answer {id} failed: {e:#}")),
|
||||
|
|
@ -766,14 +769,13 @@ async fn post_cancel_question(
|
|||
{
|
||||
Ok((question, asker, target)) => {
|
||||
tracing::info!(%id, %asker, "operator cancelled question");
|
||||
if target.is_none() {
|
||||
state.coord.emit_question_resolved(
|
||||
id,
|
||||
SENTINEL,
|
||||
hive_sh4re::OPERATOR_RECIPIENT,
|
||||
true,
|
||||
);
|
||||
}
|
||||
state.coord.emit_question_resolved(
|
||||
id,
|
||||
SENTINEL,
|
||||
hive_sh4re::OPERATOR_RECIPIENT,
|
||||
true,
|
||||
target.as_deref(),
|
||||
);
|
||||
state.coord.notify_agent(
|
||||
&asker,
|
||||
&hive_sh4re::HelperEvent::QuestionAnswered {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue