feat(tools): add Monitor for polling background tasks#184
Merged
emal-avala merged 1 commit intomainfrom Apr 23, 2026
Merged
Conversation
Returns status (running/completed/failed/killed), elapsed seconds, and
the tail of stdout+stderr (last ~8 KB) in one call — cheaper than
separate TaskGet + TaskOutput and lets the agent loop on progress
('check the build every 30s until it completes').
UTF-8-safe tail: walks past continuation bytes so a multibyte char
never gets split at the slice boundary. Best-effort on I/O errors —
returns '[output unreadable: ...]' rather than erroring the tool,
since output files can be mid-rotation when the agent polls.
Tail capped at 8 KiB so polling doesn't balloon context.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
Monitortool — one call returns status, elapsed time, and the tail of output for a background task.Why not just TaskGet + TaskOutput? Separate tool calls cost two turns of latency and double the tool-result JSON.
Monitoris the combined read, shaped for the polling loop: agent calls it every N seconds while waiting on a build / deploy / long-running command.Output cap: 8 KiB tail (configurable per-call via
tail_bytes, capped). Prevents multi-MB tails from bloating the context mid-poll.UTF-8 safety: the tail walks past continuation bytes so a multibyte character never gets split at the slice boundary. Prevents the
from_utf8_lossyoutput from showing mojibake when the tail cutoff lands mid-char.Failure mode: on I/O error (file mid-rotation, transient), returns
[output unreadable: \<err\>]instead of erroring — polling should keep working even if a single read fails.Implementation
crates/lib/src/tools/monitor.rs(~200 LOC incl. tests)TaskStatusvariants mapped to human-readable labels (running / completed / failed: <msg> / killed)started_attofinished_at.unwrap_or_else(now)ToolRegistry::with_defaultsbetweenTaskOutputandTodoWriteTest plan
cargo fmt --allcleancargo checkpassescargo clippy --all-targets -- -D warningscleancargo test -p agent-code-lib --lib tools::monitor— 6 tests (ASCII align, UTF-8 continuation walk, ASCII tail, smaller-than-cap, missing file, multibyte no-split)!cargo build --release &→Monitortool call with returned task id shows status=running, then status=completed with tail of build output