Skip to content

Commit 5e915f5

Browse files
committed
fix(tool cards): show full write/edit body immediately on settle, not after freeze; bump maya
1 parent 983c4f6 commit 5e915f5

3 files changed

Lines changed: 81 additions & 30 deletions

File tree

maya

Submodule maya updated 1 file

src/runtime/view/thread/turn/agent_timeline/tool_body_preview.cpp

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -192,20 +192,18 @@ maya::ToolBodyPreview::Config tool_body_preview_config(
192192
auto b = body.find(kClose, a);
193193
if (b == std::string::npos) b = body.size();
194194
out.kind = Kind::GitDiff;
195-
// Frozen build keeps the full diff (show_all, painted
196-
// once). In the live tail elide to a tail window so the
197-
// per-frame split_lines stays O(window) for a large edit
198-
// — same discipline as Write's terminal-but-not-frozen
199-
// branch.
200-
if (building_frozen()) {
201-
out.text = body.substr(a, b - a);
202-
out.show_all = true;
203-
} else {
204-
out.text = tail_window(
205-
std::string_view{body}.substr(a, b - a),
206-
kStreamTailLines);
207-
out.show_all = false;
208-
}
195+
// Full diff as soon as the edit is terminal — in the live
196+
// tail too, not only the frozen snapshot. The output is
197+
// FINAL the instant the tool settles, so eliding to a
198+
// tail window here just to expand it one tick later (when
199+
// freeze_range rebuilds with show_all) is the visible
200+
// "diff squeezes, then pops to full size" lag. Per-frame
201+
// split_lines over a stable body for the one-or-two
202+
// frames before the freeze handoff is negligible, and the
203+
// frozen snapshot emits the same full body so the handoff
204+
// is seamless (no height jump).
205+
out.text = body.substr(a, b - a);
206+
out.show_all = true;
209207
out.text_color = text_tertiary;
210208
return out;
211209
}
@@ -225,11 +223,14 @@ maya::ToolBodyPreview::Config tool_body_preview_config(
225223
it != tc.args.end() && it->is_array() && !it->empty())
226224
{
227225
out.kind = Kind::EditDiff;
228-
// show_all only in the frozen snapshot. While streaming
229-
// OR sitting in the live tail (re-rendered every frame)
230-
// keep the elided per-side/per-hunk preview so the cost
231-
// is bounded; the frozen card carries the full diff.
232-
out.show_all = !streaming_now && building_frozen();
226+
// Full diff as soon as the edit is terminal — in the live
227+
// tail too, not only the frozen snapshot. While STREAMING
228+
// keep the elided per-side/per-hunk preview (hunks grow
229+
// line-by-line, would balloon height every frame); once
230+
// settled the hunks are final, so expanding immediately
231+
// avoids the "stub then sudden expand" lag and matches
232+
// what freeze_range will build (seamless handoff).
233+
out.show_all = !streaming_now;
233234
out.is_streaming = streaming_now;
234235
out.hunks.reserve(it->size());
235236
for (const auto& e : *it) {
@@ -246,7 +247,7 @@ maya::ToolBodyPreview::Config tool_body_preview_config(
246247
if (nt.empty()) nt = safe_arg(tc.args, "new_string");
247248
if (!ot.empty() || !nt.empty()) {
248249
out.kind = Kind::EditDiff;
249-
out.show_all = !streaming_now && building_frozen();
250+
out.show_all = !streaming_now;
250251
out.is_streaming = streaming_now;
251252
out.hunks.push_back({std::move(ot), std::move(nt)});
252253
}
@@ -324,15 +325,18 @@ maya::ToolBodyPreview::Config tool_body_preview_config(
324325
out.show_footer_stats = false;
325326
} else if (!building_frozen()) {
326327
// Terminal, but sitting in the LIVE tail (run not settled
327-
// yet, re-rendered every frame). Elide to a window so the
328-
// per-frame split_lines stays bounded; the FROZEN snapshot
329-
// built by freeze_range keeps a generous head+tail (painted
330-
// once, then blitted). Footer is dropped here too because
331-
// its count would reflect the slice; the frozen card
332-
// carries the true `N lines · KB`.
333-
out.show_all = false;
334-
out.text = tail_window(content, kStreamTailLines);
335-
out.show_footer_stats = false;
328+
// yet, re-rendered every frame). The content is FINAL —
329+
// no more deltas arrive — so show it in full immediately
330+
// instead of waiting for the next Tick's
331+
// freeze_settled_subturns to graduate it into the frozen
332+
// prefix. Waiting caused a visible "card stays a stub for
333+
// a beat after the tool finished, then suddenly expands"
334+
// lag. Per-frame split_lines over a stable body for the
335+
// one-or-two frames before the freeze handoff is
336+
// negligible, and the frozen snapshot reuses the same
337+
// show_all body so the freeze instant is seamless (no
338+
// height pop).
339+
out.text = std::move(content);
336340
} else {
337341
out.text = std::move(content);
338342
}

test_stream.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Streaming render test — v4
2+
3+
The write/edit card lag is fixed. The only thing left to verify is the
4+
maya inline-frame bottom-anchor (empty band / jump-up after a tool
5+
finishes when the transcript overflows the viewport).
6+
7+
## The prompt (paste this)
8+
9+
> Write `scratch/big.cpp`: a C++ file with 300 lines, one
10+
> `void fn_0001() {}``void fn_0300() {}` per line, numbered with
11+
> zero-padded 4-digit indices. Then edit that file to renumber every
12+
> function +1000 (fn_0001 → fn_1001, …). Don't explain, just do it.
13+
14+
## Fixed (tool_body_preview.cpp)
15+
16+
- [x] `write` card: stable height while streaming, full body on ✓ DONE.
17+
- [x] `edit` card: full diff on settle, no "squeeze then expand" lag
18+
(fence-extraction path was eliding terminal edits in the live
19+
tail until freeze).
20+
21+
## Still open (maya inline-frame bottom-anchor)
22+
23+
- [ ] No empty band below the status bar (frame ends on the last row).
24+
- [ ] No "jump up" after a tool finishes when content overflows.
25+
26+
## How to repro the open issues
27+
28+
1. Make the terminal short enough that the prompt above overflows the
29+
viewport (or use a long enough file — 300 lines guarantees it).
30+
2. Send the prompt; watch the moment each tool flips to ✓ DONE.
31+
3. Empty-band bug: after settle, the status bar floats with blank rows
32+
between it and the terminal's bottom edge.
33+
4. Jump-up bug: the whole frame snaps upward one beat after the tool
34+
finishes (the freeze handoff re-anchors the canvas).
35+
36+
## Notes / next steps
37+
38+
- These two are a maya concern, not agentty's view layer — the
39+
composer + status bar ride the bottom of a vstack that overflows
40+
into native scrollback, so their screen row is decided by maya's
41+
inline-frame emit (serialize.cpp case-(B)), not by anything
42+
conversation_config does.
43+
- A view-layer bottom-pin pad was tried and reverted: it fought maya's
44+
own anchoring and made the jump worse.
45+
- Fix likely lives in serialize.cpp's viewport-cap / cursor_up math at
46+
the freeze handoff (canvas grows by the now-frozen rows in one frame).
47+

0 commit comments

Comments
 (0)