Borg Agent 0.13.0
Tools
- The goal, plan, subagent and cross-agent messaging capabilities are their own
tools, and onecapabilitytool reaches everything else by name or by search.
Both are on the default surface, not only on the opt-in one. A promoted name is
refused through the generic tool and points at its own, and an unknown name is
answered with the closest real capabilities rather than a bare error. query_historyis a tool, so which of its retrieval modes answers a question
arrives with the guidance instead of after a wrong guess.search_filesis a tool backed by ripgrep's own engine, so it needs no
external executable and is the thing to reach for rather than grep. A file with
undecodable bytes no longer costs you every match inside it.- Extension capabilities are advertised with descriptions read from the live
catalog, so a newly loaded extension is visible without restarting anything. - Computer use is a tool of its own. It was always a full capability - native
desktop and private-display access, and the approval gate that refuses
consequential controls until you confirm that exact action - but a model had to
already know the name and invent a JSON body for it before it could take a
screenshot. A subagent still gets the private headless display rather than
yours: the spec is surface-aware, so promotion cannot widen a child's reach.
Performance
- A fast reasoning model no longer makes the interface lag. Every frame was
re-rendering the whole expanded block, beginning with a fresh copy of every
byte of reasoning received so far, so a frame cost the length of the block and
a stream cost the square of it. At 800 lines that was 17.22ms a frame and
about seven seconds of CPU for one answer; it is now 0.27ms and 113ms, and a
frame through a real terminal measures 2.02ms with thousands of deltas
coalesced into it. The lines that have finished are reused, and the line still
being written is redone, because that is the only one that can still change. BORG_TUI_FPSandBORG_TUI_STREAMING_FPSare documented. They existed and
were clamped, but appeared nowhere, so the one knob that changes how streamed
text feels could not be found.
Reliability
- A compaction that loses its connection is retried instead of failing your turn.
One empty upstream response on one fold used to abort the whole sequence and
fail the turn, costing you the context it was there to save. Retries are
bounded, and a refusal no repeat can fix -- auth, billing, quota, an
oversized request -- still fails on the first attempt with its real cause. - A provider error now names the field it rejected. Only the code and the
parameter were reported, which say that something is wrong and never what;
a malformed request was undiagnosable from outside. The provider's own
wording comes through with the rejected value stripped.
Reliability
-
A history search on a resumed or forked session can no longer report "no
matches" while having looked at almost none of the history. Those sessions were
scanned oldest-first under a hard budget, so on a long thread only the oldest
events were ever reachable and recent work was invisible however the query was
phrased. The scan now covers the newest window, which is what a resumed thread
is asking about. -
Search results say whether they are complete.
truncatedalready conflated
"your hit list hit the limit" with "the scan never reached the rest of the
history", and the two were indistinguishable to a caller. A result now carries
search_incompleteplus thescanned_from_sequence..scanned_to_sequence
window it covered, so an empty result reads as "not found in what I looked at"
rather than "does not exist", and the rest can be paged withstart_sequence.
Thequery_historydescription says so too. -
An upstream that answers with an empty response is retried instead of ending
the turn. Only a refusal is treated as fatal now; everything else is
retryable, as it was before mid-stream errors were recognised at all. -
A tool call carrying the presentation field its own schema advertises is
accepted. The same idea appears asactionand asdescription, and a call
formed exactly as documented was being refused as malformed - the cause of most
of that tool's flakiness.
Terminal UI
- An action group that live work was holding open now folds when that work
finishes. A group held open by a running process never collapsed, because
being the newest group kept it open on its own. - Pending input reads as an action group rather than a bordered panel: the
same disclosure, the same summary, the same grey, no frame. - A retry no longer re-announces the goal. Every retry re-emits it, and the
card was taken out and pushed back, so resuming dropped it to the bottom of
the transcript and reprinted a goal already on screen.
Terminal UI
- A status line that overflows now ends in a mark. Losing its last column to
truncation used to drop the tail with nothing to show the text had been cut. - The effort and billing segments share one colour instead of being graded per
value, so the same colour no longer means xhigh in one place and a pro/max
subscription in another. - Dragging the scrollbar moves the transcript one line per row. A scrollbar maps
proportionally, so on a long thread one row of drag moved hundreds of lines and
the closer to the middle of the thumb you grabbed, the less each row was
worth. Clicking the track still jumps - that gesture means "go there" - and
only the drag changed. - The composer's text-entry ground is darker and neutral, so the three rows you
type in read as a well rather than another band of transcript. - The splash says what it is. It now reads "BORG" over "agent" over the version
with the channel beside it, and all three lines keep one width and one centre
whatever the version turns out to be - thevprefix yields to the width
rather than the layout bending around it.
Providers
- A tool result carrying an image no longer puts the image inside the tool
result field, which the API reads as text. A valid screenshot came back as
invalid_valueoninput-- "the image data you provided does not
represent a valid image" -- and broke every later turn in the session. - An image attachment is typed by what its bytes are, not by what the file is
called, on every path. - A pay-per-use OpenAI key is no longer sent the request shape a ChatGPT
subscription uses, which the public API rejects outright.
Providers
- Qwen models that take an effort ladder are sent one.
enable_thinkingis a
boolean and is right for Qwen3.5/3.6/3.7, but the Qwen3.8 family takes
reasoning_effortinstead and converts a level into a thinking budget itself- so a laddered model was being offered low/medium/high in the picker and then
havingenable_thinkingput in the body, and the effort had no effect on the
request. The choice is now made per model from the catalog entry that already
exists for it.
- so a laddered model was being offered low/medium/high in the picker and then
Setup
- The Python library's documented usage is corrected:
borgis already in the
namespace, soimport borgis not part of it. HOMEcan be set for the runtime worker as a user setting, defaulting to off.