feat(#1290): show per-agent loose-end question count in dashboard
Add a '❓ N' badge to each container row showing the count of pending questions where the agent is the asker (awaiting an answer) or the target (owes a reply). Derived live from questionsState — no backend field needed. Details: - New .badge-loose-ends CSS class (purple, matching Q33R1ES section colour) - Badge tooltip breaks down the count: 'N asked, N to answer' - renderContainersFromState() called on QuestionAdded/QuestionResolved so the badge updates instantly when question state changes - Existing ⏰ reminders badge kept separate (different signal)
This commit is contained in:
parent
bddeb5478e
commit
750f64b7f0
2 changed files with 26 additions and 0 deletions
|
|
@ -78,6 +78,10 @@ code {
|
|||
color: var(--cyan); border-color: var(--cyan);
|
||||
text-shadow: 0 0 6px rgba(137, 220, 235, 0.4);
|
||||
}
|
||||
.badge-loose-ends {
|
||||
color: var(--purple); border-color: var(--purple);
|
||||
text-shadow: 0 0 6px rgba(203, 166, 247, 0.4);
|
||||
}
|
||||
/* Context-window usage badges on dashboard container rows. */
|
||||
.badge-ctx-ok {
|
||||
color: var(--green); border-color: var(--green);
|
||||
|
|
|
|||
|
|
@ -805,6 +805,26 @@ window.marked = marked;
|
|||
},
|
||||
`⏰ ${c.pending_reminders}`));
|
||||
}
|
||||
// Pending questions where this agent is the asker (awaiting an
|
||||
// answer) or the target (owes a reply). Derived live from
|
||||
// questionsState so the badge updates instantly on QuestionAdded /
|
||||
// QuestionResolved without a separate backend field.
|
||||
const agentQCount = questionsState.pending.filter(
|
||||
(q) => q.asker === c.name || q.target === c.name,
|
||||
).length;
|
||||
if (agentQCount > 0) {
|
||||
const askerCount = questionsState.pending.filter((q) => q.asker === c.name).length;
|
||||
const targetCount = questionsState.pending.filter((q) => q.target === c.name).length;
|
||||
const parts = [];
|
||||
if (askerCount > 0) parts.push(`${askerCount} asked`);
|
||||
if (targetCount > 0) parts.push(`${targetCount} to answer`);
|
||||
head.append(el('span',
|
||||
{
|
||||
class: 'badge badge-loose-ends',
|
||||
title: `pending questions: ${parts.join(', ')} — see the Q33R1ES tab`,
|
||||
},
|
||||
`❓ ${agentQCount}`));
|
||||
}
|
||||
if (c.ctx_tokens != null) {
|
||||
const k = Math.round(c.ctx_tokens / 1000);
|
||||
// Thresholds track the model's real context window when the
|
||||
|
|
@ -1459,6 +1479,7 @@ window.marked = marked;
|
|||
question_refs: ev.question_refs || [],
|
||||
});
|
||||
renderQuestions();
|
||||
renderContainersFromState();
|
||||
}
|
||||
function applyQuestionResolved(ev) {
|
||||
const idx = questionsState.pending.findIndex((q) => q.id === ev.id);
|
||||
|
|
@ -1488,6 +1509,7 @@ window.marked = marked;
|
|||
}
|
||||
}
|
||||
renderQuestions();
|
||||
renderContainersFromState();
|
||||
}
|
||||
// Filter selection for the questions section. Persisted so the
|
||||
// operator's preferred view (all / operator-targeted / peer)
|
||||
|
|
|
|||
Loading…
Reference in a new issue