Repository navigation
feat(site/src/pages/AgentsPage/components/ChatConversation): fold each finished turn into one Working block - #31025
Conversation
…h finished turn into one Working block A running or parked turn keeps the split view from #30656, where text between steps closes the open block. Once the turn ends (any turn before the latest user prompt, or the latest turn when the chat is no longer running, interrupting, or requires_action), its text between steps, the text before its first step, and its labeled narration fold back into one block per segment, leaving only the final message and attached files visible. Block and piece keys stay stable, so an expanded block keeps its scroller item and focus through the fold.
…working block key comment
…e parked-turn wiring and drop a duplicate split test
|
@codex review
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: db47d239fc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…he parked-turn story and drop its presence test RequiresActionKeepsTextBetweenSteps passed no liveStatus, so ConversationTimeline threw on liveStatus.phase and the story showed the router error page instead of the parked split view. It now passes buildLiveStatus(), the idle status a requires_action chat derives, so its snapshot shows the text between the two blocks and changes if the requires_action wiring breaks. The Vitest case that guarded the same wiring asserted only toBeVisible and not.toBeInTheDocument, which FE1 leaves to the screenshot, so it is removed.
|
@codex review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 93bd464db9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…s out of folded text and block keys stable across paging chatd appends a step's attach_file files after its last part. When the model wrote text after the attach_file call, splitRowPieces merged that text and the file into one output piece, so once an ended turn folded the text into its block, the file folded with it. Attached files now form output pieces of their own and stay below the block. In an ended turn, labeled narration with no open block opened a block of its own. At the top of a partly loaded turn, that block took its key from the narration and switched to the older work's key once that work loaded, which remounted the block and dropped its expansion and focus. Such narration now waits like text until work joins it, so every block that older history may continue keys on loaded work.
…rration joining loaded work on a partial page The narration paging test checked only the first page, where narration waits, and the fully loaded turn. Neither fails if the open-block clause of the narration fold is dropped. The page that loads the older work but not the prompt now asserts that narration after that work folds into its block.
…ing narration once loaded work joins it Narration at the top of a partly loaded ended turn waits like text until work joins it. When that work had no steps, such as reasoning before the final answer, the block it formed counted no narration and was dropped, so the rows rendered unfolded until the prompt loaded and then folded. Narration that waited now marks its block the way narration that folds directly does, so the partial page matches the loaded turn.
…ten output kinds and the working block key doc outputKindOf accepted a missing item only because Array.prototype.at types the last item as possibly undefined, though no output piece is ever empty, and it classified that missing item as a file. It now takes an item. The non-response kind is "file", since file references fall in it too. The WorkingBlock key doc now says the key is liveKey while the block is live.
…e waiting narration note to its join The pending text comment keeps its two lines, and the reason waiting entries record narration now sits on the loop that uses it. The WorkingBlock key doc says "otherwise" instead of "once complete", since an interrupting or parked turn's block is not live yet may still grow. The new paging test's name says what it compares.
…ting text out of step-less blocks Waiting entries record whether they are narration, and only narration keeps a step-less block. No test failed when every waiting entry counted as narration, which folds a tool-less turn's text before its reasoning. The text case now shares the narration test's fixture and asserts both layouts stay unfolded.
…er history can change a live block's key A live block keys on liveKey, which older history can change once it loads the block's prompt or earlier blocks, so the WorkingBlock key doc limits its stability claim to the key a block has once it stops being live.
|
@codex review
|
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
…the attached-file fixture comment chatd gives attach_file files an assistant message of their own: the step's text and tool calls commit before the tools run, and the files commit with the tool results. The comment said chatd appends the files to the step's last message, which is not true. The fixture keeps its shape, a row that holds both the text and the file.
|
@codex review
|
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
… attached-file fixture comment The test name and the message literal already describe the row, and the chatd message shape the comment named belongs to chatd, not to this frontend test.
|
@codex review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b925402f29
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b925402f29
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…s from a folded earlier block to the merged block When a turn ends, its blocks fold into the block that ran last, so React unmounts the earlier blocks. Focus inside one of them fell to the page body. The timeline now notes the focused control before each commit and, when the commit removes it, focuses the summary button of the block that now holds its rows.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dd392f47ba
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…s on a control whose slice the fold re-keys When one message holds a step, text, and another step, the ended turn folds the row's slices into one, so React remounts them even inside the block that survives, and focus inside either step moved to the block summary. Each slice now marks its row key and piece range. The focus restorer focuses the element at the same place in the slice that kept the first piece of the focused element's slice, counted from the start, or else its last piece, counted from the end, and falls back to the block summary only when neither exists. This replaces the item-level first-piece match, so a control in an earlier block also keeps focus in the expanded block that it folds into.
…place focus loss to the block summary A slice that stays mounted can still drop the focused element, as when streaming reasoning collapses because the next call joins its piece. The element at the same place in that slice is then another control, so the restorer matches a twin only when the focused element's slice itself unmounted, and otherwise falls back to the block summary. Review follow-ups also name the position counted from the end, use `at` for it, and move the whole-row note to the `SlicePosition` doc.
… the focus restorer's class comment
…e the focus restorer's twin by its pieces
|
@codex review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 431cec5789
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…e focus restorer's selector comment
|
@codex review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8fbb2555d3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…s in a live-only block whose step persists as the turn ends
…t why the text-before-second-step fixture shares a row
|
@codex review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 064ef2228a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…story comment that restates its name
…xpanded tool open when its row folds A running or parked row holding a tool, text, then another tool renders a slice in each of two blocks, keyed message:<id> and message:<id>:1. The ended turn's fold merged them into one slice keyed on the first, so the ChatMessageItem holding the second tool remounted inside the surviving block and a tool the reader expanded collapsed. A folded slice now takes the work ordinal of its newest work, the key the open turn gave that work's slice.
…ailing reasoning block open when the turn stops An open turn with a tool block, then text, then a live block of only reasoning shows that reasoning block. When Stop or an error ended the turn, the fold kept the live key of the earlier block with steps, so the reasoning block, the newest block the turn showed, remounted and collapsed. The fold now keeps the newest open-turn block, and falls back to the newest block with steps only once text or a row that never folds closes a block of only reasoning, which an open turn shows inline.
…s on the answer when narration before it folds
…e fold key comments to three lines
… the open-turn block ordinals and shared fold fixtures
… the result fixture by the calls it answers
|
@codex review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8f064bb621
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ol's slice key when a file splits its row from folded text An open row shaped [text, file, tool call] keys the tool's slice on work ordinal 0, the bare row key. The ended turn's fold counted slices per row, so the folded text took ordinal 0, the file kept it apart from the tool, and the tool's slice became message:<id>:1. Its ChatMessageItem remounted and an expanded tool collapsed. A slice in a block now keys on its newest work's ordinal in both modes, as an open turn already did, and a slice of folded text alone keys on text:<first piece>, which no work slice can take. This drops the per-row slice counter.
…s on a control in a middle block when its row folds
…focus twin lookup inside its piece A control in a middle block that the fold remounts may be gone after the fold, such as the output of a command the reader expanded. The twin lookup counted the piece's controls on to the end of the merged slice, so focus landed on a control of the next piece. It now stops at the next piece's marker, and a piece with fewer controls falls back to the block summary. Also moves the piece-start calculation out of BlockList, names the fixtures of the three-step row, and indexes the twin with at().
…re a piece's focusables end The doc on getPieceFocusables repeated its name. It now states the bound at the next piece's marker, which the name does not carry.
|
@codex review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 11685fa85e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| key: sliceKey(rowIndex, workOrdinal), | ||
| })), | ||
| slices: draft.slices.map(({ rowIndex, start, end, workOrdinals }) => { | ||
| const newestWork = workOrdinals.at(-1); |
There was a problem hiding this comment.
Preserve earlier tool expansion when folding the row
When a running row contains tool A, text, then tool B and the user expands tool A, the completed fold keys the merged child from the newest work, tool B. React therefore unmounts tool A's former ChatMessageItem, resetting the local expanded state in ToolCall.Root even though the merged Working block reopens. Fresh evidence beyond the prior tool-B fix is that the earlier slice is now the identity being discarded; preserve expansion by tool identity or otherwise retain state for every merged tool.
AGENTS.md reference: site/AGENTS.md:L11-L11
Useful? React with 👍 / 👎.
…t TimelineRenderBlock and drop a restating comment TimelineRenderBlock is exported now, so it says how a tool group relates to the read_file blocks it replaces. The stepTurnBlockOrdinal comment only restated its name; the openTurnBlockOrdinal comment already says when the newest block with steps takes over.
Stacked on #30656, which splits Working blocks at assistant text. That helps while a turn runs, but finished turns kept the split, so they read as a row of one-step blocks with narration between them.
Finished turns now fold back into one Working block, as on
main: the steps, the text between them, and labeled narration go into the block, and only the final message and attached files stay below it. A turn is finished once the chat status leavesrunning,interrupting, andrequires_action. The running or parked turn keeps the split view, so nothing folds and unfolds while the agent works. Rows that never fold (questions, plans, hook notices, cleared or summarized context) still split a finished turn. The folded block keeps the keys of the running turn's last block, so that block and its tools stay mounted and keep the reader's expansion. Focus on a link or button stays on the same control when the turn folds, including a control in an earlier block that folds into the expanded block. Focus that has no such control after the fold, such as in text that folds or in the output of a command whose block remounts collapsed, moves to the folded block's summary.Finished turn on #30656:
With this PR:
Review notes
mainfolds a one-row[text, narration]ending into its block.span[data-piece]before each piece after its first, so the focus restorer can find a control's twin within its piece after the fold.attach_filefiles a message of their own. The grouping also keeps a file below the block when one row holds text and a file (Codex round 2), though chatd does not write that today.LabeledNarrationFoldsandLeadInBeforeSearchFoldsget theirmainnames back,TextBetweenStepsSplitsBlocksbecomesTextBetweenStepsFolds, andRequiresActionKeepsTextBetweenStepsis new.Delivery record
4ccae5fbb7aagainst fix(site): split Working blocks at assistant text and scroll to their end on expand #30656 (fold, Stop, reload, carry-over, scroll, narration,attach_file, paging,requires_action). Round 2: PASS oneab78dc19e5against4ccae5fbb7a, covering page-top narration and the round 1 checks. Text and a file in one message, and pages that start at a narration-only message or at text before reasoning, never occurred live; unit tests cover them. Round 2 also found that a send can hide new messages until reload when an older page lands after it;maindoes the same.eab78dc19e5have no live UAT:b925402f29a,e165158d8e3,431cec57893,8fbb2555d33,064ef2228a0,11d043c9b82,3f56aa52a37,11685fa85ec, and691fa841266change only comments;cdc623d23aband8f064bb6211address frontend review naming and test findings; and43437ebd091,46a60b4caca,4d6b434e4b6,45a33b14cc5,00e04971fb2,dd392f47ba0,315ba6eef3c,565e8ac9dc3,c360f8a9e1a,e99d7b9c321,c87bc1a4574,5e22991edc6,25090b0bed7,e24d0b8c632, and2168665b101fix Codex rounds 6 to 12 and frontend review findings, covered by unit tests, the timeline stories, and, for the round 6 focus move, a Chromium story probe.main, useparameters.queries. Round 6 found focus lost from an earlier block at the fold and an answer folded behind trailing narration. Round 7 found focus lost from a final answer that the fold re-keyed, and a live-only block that remounted collapsed when its step persisted as the turn ended. Each fix came with a test that failed first. Round 8 found focus lost from a control whose row slice the fold re-keyed; its fix also came with a test that failed first. Round 9 flagged a comment that restated a selector, now removed. Round 10 found focus lost from a control in a live-only block whose step persisted as the turn ended, fixed with a test that failed first, and a fixture comment that restated its initializer, which now says why the fixture exists. Round 11 flagged a story comment that restated its name, now removed, and three edge cases, each fixed with a test that failed first: a row with text between two tools remounted the second tool at the fold, which collapsed it if the reader had expanded it; a trailing block of only reasoning remounted when Stop or an error ended the turn; and focus on an answer link moved to the summary when narration before the answer folded in place. Round 12 found two more, each fixed with a test that failed first: a file between folded text and a tool remounted the tool, and focus in the middle block of a three-block row moved to the summary. Round 13 asked to move thearia-expandedtransition tests to stories, declined because FE1 counts state as a Vitest outcome and a story cannot drive the running-to-ended prop change. It also asked to document the newly exportedTimelineRenderBlockand to drop a comment that restated a field name, both done, and found that a tool expanded in an earlier block collapses when the fold merges that block into the last one. That finding is open: the earlier block unmounts, so keeping the tool open needs disclosure state remembered by ID across tools, read-file groups, subagents, and reasoning, outside the fold logic.frontend-reviewandcoder-frontend-reviewon each round of changes. The last rounds moved the focus restorer to its own module, extended it to folded text, took its per-item mapping out of the timeline render, renamed the fold's open-turn state, and sent focus lost inside a slice that stays mounted to the block summary. Frontend review round 13 found that the middle-block twin lookup could land on a control of the next block when the focused control was gone; fixed in2168665b101with a test that failed first.make pre-commit, biome, tsc, oxlint,lint:compiler, knip, thesrc/pages/AgentsPageunit tests, and the timeline stories pass on2168665b101;11685fa85ecand691fa841266change only comments, andmake pre-commitpasses on each. Its rounds 12 and 13 asked for stories of folded ended states; declined, because a story that starts in the ended state renders the same with or without the fixes, so it cannot catch their regression, and the reviewer accepted that on the last pass.ciworkflow last ran, green, on064ef2228a0. feat(site/src/pages/AgentsPage): keep agent attachments in working blocks and list them under Attachments #30788 then landed onmainand conflicts with fix(site): split Working blocks at assistant text and scroll to their end on expand #30656, so GitHub builds no test merge for this stack and runs onlycontribuntil fix(site): split Working blocks at assistant text and scroll to their end on expand #30656 is restacked onmain.