cap get_loose_ends todo output + add ack_todos_until bulk-clear (#2944)
This commit is contained in:
parent
58a9f218f2
commit
eb570c003d
7 changed files with 167 additions and 9 deletions
|
|
@ -136,6 +136,21 @@ fn msg_id_tag(id: i64) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
/// Hard cap on how many individual `Todo` lines `render_loose_ends` will
|
||||
/// emit. Approvals/questions/reminders stay naturally bounded (they're
|
||||
/// triaged interactively and don't self-multiply), but todos are pushed by
|
||||
/// unattended producers (matrix/bash/forge) — an agent that goes a long
|
||||
/// stretch without calling `get_loose_ends`, or whose producers outpace its
|
||||
/// triage, can accumulate hundreds of them. Rendering all of them
|
||||
/// unconditionally risks producing a tool result too large for the MCP
|
||||
/// transport to return at all, which is worse than a bug: it's a deadlock
|
||||
/// (the agent can't even see what's pending to start clearing it). Capping
|
||||
/// here guarantees `get_loose_ends` always returns successfully; the
|
||||
/// truncation summary tells the agent how to bulk-clear the rest via
|
||||
/// `ack_todos_until` (see that tool's doc for why it's the intended escape
|
||||
/// hatch, not a per-id triage loop).
|
||||
const MAX_RENDERED_TODOS: usize = 40;
|
||||
|
||||
/// Inner renderer for a `Vec<LooseEnd>` already extracted from the socket
|
||||
/// reply. Called by the `get_loose_ends` handler, which injects the
|
||||
/// `UnreadMatrix` entry before formatting.
|
||||
|
|
@ -145,7 +160,17 @@ pub(super) fn render_loose_ends(loose_ends: &[hive_sh4re::LooseEnd]) -> String {
|
|||
return "(no loose ends)".to_owned();
|
||||
}
|
||||
let mut out = format!("{} loose end(s):\n", loose_ends.len());
|
||||
let mut shown_todos = 0usize;
|
||||
let mut hidden_todos = 0usize;
|
||||
let mut hidden_min_id: Option<i64> = None;
|
||||
for t in loose_ends {
|
||||
if let hive_sh4re::LooseEnd::Todo { id, .. } = t
|
||||
&& shown_todos >= MAX_RENDERED_TODOS
|
||||
{
|
||||
hidden_todos += 1;
|
||||
hidden_min_id = Some(hidden_min_id.map_or(*id, |m| m.min(*id)));
|
||||
continue;
|
||||
}
|
||||
match t {
|
||||
hive_sh4re::LooseEnd::Approval {
|
||||
id,
|
||||
|
|
@ -233,9 +258,19 @@ pub(super) fn render_loose_ends(loose_ends: &[hive_sh4re::LooseEnd]) -> String {
|
|||
"- todo #{id} [{subsystem}{key}, {age_seconds}s old]: {summary}{src} \
|
||||
(cancel_loose_end kind:\"todo\" id:{id} to clear)"
|
||||
);
|
||||
shown_todos += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if hidden_todos > 0 {
|
||||
let min_id = hidden_min_id.unwrap_or(0);
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"- {hidden_todos} more todo(s) not shown (oldest not shown: #{min_id}) — \
|
||||
call ack_todos_until(up_to: {min_id}) to bulk-clear the old backlog, or \
|
||||
cancel_loose_end kind:\"todo\" id:<N> to clear individually"
|
||||
);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
|
|
@ -350,6 +385,13 @@ pub(super) async fn mark_local_todo_done(id: i64) -> Option<hive_agent_sock::Res
|
|||
dial_agent_socket(&hive_agent_sock::Request::MarkTodoDone { id }).await
|
||||
}
|
||||
|
||||
/// Bulk-ack every un-acked local todo with `id <= up_to`, via the harness's
|
||||
/// in-agent socket — the todo-store analogue of `mark_local_todo_done`, for
|
||||
/// the `ack_todos_until` tool.
|
||||
pub(super) async fn mark_local_todos_done_until(up_to: i64) -> Option<hive_agent_sock::Response> {
|
||||
dial_agent_socket(&hive_agent_sock::Request::MarkTodosDoneUntil { up_to }).await
|
||||
}
|
||||
|
||||
/// Format a `Vec<MatrixRoomUnread>` into a per-room summary string.
|
||||
/// Single room / single message collapses to one line; multi-room
|
||||
/// expands to a bulleted list. Returns an empty string for empty input.
|
||||
|
|
|
|||
Loading…
Reference in a new issue