[fix] Session tabs on /m stay put, follow renames and revisions, and close cleanly - #6887
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (115)
📝 SummarySummary by CodeRabbit
WalkthroughChangesChat and navigation experience
Priority: ➖ Normal Estimated code review effort: 5 (Critical) | ~90 minutes Merge Risk: 🔵 Low · up to Navigation failures can affect the next agent selection, while tab loading can briefly duplicate or hide tabs. The mobile source layout also needs to be brought into the required structure before merge. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Railway Preview Environment
Updated at 2026-09-17T06:24:35.856Z |
The transcript no longer floats a "Jump to latest" button; auto-scroll still tracks the bottom, only the pill is gone.
aad395a to
6c8203c
Compare
The scroller wore a fixed top fade, so the first message read dimmed while the transcript sat at its top. `scrollEdgeMask` / `clippedEdges` (shared in @agenta/chat/assets, the Home list's 26/34px lengths) now fade only the edges content is clipped at, read from the same measure the auto-scroll already runs.
The transcript rail was 16px under the tab strip on both the live conversation and the replay; it is 24px now.
The rail derived which chips exist from the sidebar's capped, grouped list, so a session leaving that result for one fetch (a gate opening, a pin, a newer session past the cap) blinked its tab out. Membership is now the open set alone; rows come from a by-id query (`useSessionTabRows`), and the card list only seeds a first visit. Also on the strip: the active chip can be closed (the host routes to the nearest survivor, from the rendered order), the last chip cannot, and every gap carries a hairline — including before the + button — with a wider gap, a stronger line, and a tighter chip radius.
`SessionCardList` gains a `compact` density — the nav rail's one-line row: status glyph, title, pin on hover beside the name, time at the right edge; no subtitle, no gate chip, sentence-case headings, and an `activeRowId` fill for the session on screen. The history popover uses it, wears the rail's Sessions glyph, and the waiting group is now "Waiting for your input".
Chips may shrink to 80px; the rename editor paints edge to edge instead of under the label fade; the strip's scroll fade uses the Home list's lengths (26px in, 34px out).
Running wore the run-status mint, which the pulse dimmed to half and read as washed out — it is the deep semantic green now. "Ready to resume" wore an info-blue that read as a stray tint; it is ink, the filled dot the nav rail paints. The tab chip's dot no longer pulses at all: at 6px the fade registered as a colour, not as motion.
The title reads one `session-stream` query, and the project watch only invalidated `session-list` keys — so when the agent named a session after its first turn, the tab stayed "Agenta" until a reload. A session change now reaches the per-session record too.
Nothing ever removed a pin, so an archived session kept leading every list — a state the menu refuses to create (it will not pin an archived row) but never left. Archive and delete now unpin; unarchive does not re-pin.
The transcript placeholder mirrored a layout the transcript never had — an avatar, bare lines where the user bubble sits — with a local pulse. It is now the real anatomy on the real rail: the 34px bubble at the right, the "Worked for" row, tool steps, prose at the 13/18px pitch, pinned to the bottom, every bar the shared `SkeletonBlock` shimmer. The tab strip's loading chips used the COMPOSITE `Skeleton` (title + paragraph rows) squeezed into 28px; they are three round blocks at real title widths. The history popover's compact list gets a placeholder on its own 28px row geometry.
An unpinned session resolved "the agent's latest revision" through a query keyed under this app's own name, which no commit path ever cleared: the auto-save invalidates `["workflows", "latestRevision"]`, the project watch cleared only the agents list, and the agent's own commits (`data-committed-revision`) had no listener on /m at all. The answer was a snapshot from whenever the page first asked — so a save left the chip old, a new tab or a switch to an unpinned one landed on v1 or whatever was cached, and the agent updating itself changed nothing. - The query now lives under `["workflows", "latestRevision", "mobile", …]`, so every existing invalidation reaches it. - `workflow-changed` (and a reconnect) also clear the latest-revision caches. - The live conversation reads `data-committed-revision` parts and pins, retargets and invalidates on each new one, as the desktop does. - The session row binds by its `workflow` ref explicitly, not the first UUID, so a revision ref listed first cannot pin the turn that ran.
A new session from `+` or the shortcut, and a switch to an existing one, put the caret in the composer once it can take input. Not while the caret is already in another field: a self-commit remounts the screen mid-edit in the config pane.
The composer already knew it had no hardware keyboard — it hid the shortcut hints on that — but `submitOnEnter` stayed at its default, so a phone's Enter sent the message with no way to make a newline. It now follows the same test: Enter sends only where Shift/⌘ can be held; on touch the send button sends and Enter inserts the paragraph.
The composer bound the head of a newest-first roster, so a workspace with two agents opened every visit on the one created last, whichever was in use (#6741). The start is what is remembered, per project, on this device; HomeFocus takes it as preferredAgentId and falls back past an agent no longer listed.
…select text A session opened before its row landed rendered a chip with no context menu, so a right-click on it did nothing and the menu read as broken; repeated clicks on any chip painted its label (#6379). The rail's close verbs move to railTabMenu.tsx so the unlisted chip can offer them without a row view-model, and the chip is select-none, with a rename input keeping its own selection.
…le does The composer's export is markdown with Lexical's escapes in it, so a literal render showed hi\_name for a typed hi_name. Through the same pipeline the assistant uses, minus the typewriter.
It was colorTextLightSolid — white on both fills. colorBgContainer is white on the light theme's ink and ink on the dark theme's yellow, the pairing Home's send already uses.
…own branch markdownIcons lives on the files-pane branch, which this one does not sit on; CI's typecheck had no such name.
…lidator useProjectWatch now calls invalidateAgentCommittedRevisionCache on a workflow change; the desktop suite's mock of @agenta/entities/workflow lacked it.
775cfd9 to
6419f28
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
web/mobile/src/features/chat/AssistantMarkdown.tsx (1)
69-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMove
UserMarkdownto its own file.
AssistantMarkdown.tsxexports bothAssistantMarkdownandUserMarkdown. The mobile rules require one component per.tsxfile, with a matching named export. No colocated-component exception applies. MoveUserMarkdownand its required shared helpers toUserMarkdown.tsx, then update theTurnRow.tsximport.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Advanced
Run ID: c84b489d-9afb-4d38-963c-b96494a01ab2
📒 Files selected for processing (48)
web/mobile/src/components/ContentRail.tsxweb/mobile/src/features/chat/AssistantMarkdown.tsxweb/mobile/src/features/chat/ChatScreen.tsxweb/mobile/src/features/chat/LiveConversation.tsxweb/mobile/src/features/chat/SessionHistoryMenu.tsxweb/mobile/src/features/chat/TurnRow.tsxweb/mobile/src/features/chat/committedRevisionIds.tsweb/mobile/src/features/chat/states/ChatStates.tsxweb/mobile/src/features/chat/useAgentEntity.tsweb/mobile/src/features/chat/useTranscriptAutoScroll.tsweb/mobile/src/features/home/HomeScreen.tsxweb/mobile/src/features/home/lastStartedAgent.tsweb/mobile/src/features/home/useHomeHandoff.tsweb/mobile/src/styles/globals.cssweb/mobile/tests/unit/agentLatestRevisionCache.test.tsweb/mobile/tests/unit/committedRevisionIds.test.tsweb/mobile/tests/unit/lastStartedAgent.test.tsweb/oss/src/components/Layout/ProjectWatch.test.tsxweb/packages/agenta-chat/src/assets/conversationLayout.tsweb/packages/agenta-chat/src/components/ChatComposer.tsxweb/packages/agenta-chat/tests/unit/ChatComposer.touchEnter.test.tsxweb/packages/agenta-chat/tests/unit/assets/scrollEdgeMask.test.tsweb/packages/agenta-entities/src/session/state/invalidate.tsweb/packages/agenta-entities/tests/unit/session-invalidate.test.tsweb/packages/agenta-entity-ui/src/agent/AgentIdentity.tsxweb/packages/agenta-entity-ui/src/agent/chrome.tsweb/packages/agenta-home-ui/src/HomeFocus.tsxweb/packages/agenta-home-ui/src/boundAgent.tsweb/packages/agenta-home-ui/src/index.tsweb/packages/agenta-sessions-ui/src/SessionCardList.tsxweb/packages/agenta-sessions-ui/src/SessionPinButton.tsxweb/packages/agenta-sessions-ui/src/SessionTab.tsxweb/packages/agenta-sessions-ui/src/SessionTabRail.tsxweb/packages/agenta-sessions-ui/src/SessionTabStrip.tsxweb/packages/agenta-sessions-ui/src/railTabMenu.tsxweb/packages/agenta-sessions-ui/src/useSessionActions.tsxweb/packages/agenta-sessions-ui/tests/unit/commitRenameCacheFailure.test.tsxweb/packages/agenta-sessions-ui/tests/unit/sessionRenameMenu.test.tsxweb/packages/agenta-sessions-ui/tests/unit/unlistedTabMenu.test.tsxweb/packages/agenta-sessions/src/row/sessionRowStatus.tsweb/packages/agenta-sessions/src/state/index.tsweb/packages/agenta-sessions/src/state/pins.tsweb/packages/agenta-sessions/src/state/useSessionCardList.tsweb/packages/agenta-sessions/src/state/useSessionTabRows.tsweb/packages/agenta-sessions/src/watch/useProjectWatch.tsweb/packages/agenta-sessions/tests/unit/sessionPins.test.tsweb/packages/agenta-sessions/tests/unit/useProjectWatch.test.tsweb/packages/agenta-sessions/tests/unit/useSessionTabRows.test.ts
Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.
… draws a landed chip twice Review: keepPreviousData held the previous set's pages while a new set loaded, so a tab closed a moment ago could leave useSessionTabRows. And the commit a row landed in drew its chip from both the rows and the unlisted state, one effect late. The rows filter at the hook; the rail derives what it renders synchronously.
…he task Review: a start whose navigation was cancelled restored the draft but had already written the memory.
|
Re the nit on |
Context
A batch of session bugs on
/m, most of them filed against the playground's tab rail and the chat around it. The biggest one: tabs on the rail vanished and came back as you worked, because the rail derived which sessions were open from the sidebar's capped, grouped list instead of from its own open set. Around it sit the smaller reports: the browser title not following the session, an archived session staying pinned, the active tab with no menu and no close, a stale revision after a save or a tab switch, Enter sending on a phone, and Home always opening on the newest agent instead of the one you last used.Stacked on #6868 (
feat/mobile-activity-timeline), which owns the transcript this touches.Changes
Tab rail fetches its open tabs by id (#6842, and the blink). New
useSessionTabRowsin@agenta/sessionsasks the server for exactly the ids in the device's open set. The sidebar list no longer decides what the rail shows, so a session leaving the sidebar's top 12, or moving into its "waiting" group, no longer drops its tab. A session opened before its row lands still gets a chip, and that chip now carries the tab verbs (Close, Close others, Close to the right) instead of no menu at all (#6379). Every chip isselect-none, so repeated clicks stop painting the label.Active tab is a real tab (#6841, #6755). The ✕ shows on the active chip; closing it routes to the nearest surviving neighbour; the last tab cannot be closed.
Cache invalidation that never reached
/m(#6860, #6753, #6754).session-streamquery the title reads is now invalidated onsession-changed, so the browser tab title follows a rename.["workflows", "latestRevision"]prefix thatinvalidateAgentCommittedRevisionCachealready clears, and the chat now readsdata-committed-revisionparts, so a config save, an agent self-commit, or aworkflow-changedwatch event all land in the workspace's version pill.Pins (#6854). Archiving or deleting a session drops its pin (
unpinSessionAtom).Composer (#6377).
submitOnEnterfollowsuseHardwareKeyboard: on a touch-only device Enter inserts a newline and the send button sends. Landing on a session, or switching to one, focuses the composer unless you are already typing somewhere else.Home remembers the agent (#6741). The agent a chat was last started with is stored per project on the device;
HomeFocusbinds it before falling back to the roster head, and skips it if the agent is no longer listed.Visual, all on
/m:+,min-w-20, no label fade while renaming, the scroll fade Home's list uses. Same fade on the transcript, only at clipped edges; the jump-to-latest pill is gone.SkeletonBlock.hi_nameno longer shows ashi\_name(the composer's export escapes it).Tests
useSessionTabRows,unlistedTabMenu,scrollEdgeMask,session-invalidate,sessionPins,agentLatestRevisionCache,useProjectWatch,committedRevisionIds,ChatComposer.touchEnter,lastStartedAgent, plus the palette drill-in and mid-sentence cases. All of@agenta/sessions-ui,@agenta/sessions,@agenta/chatand@agenta/mobilepass./min the browser pane; the revision fix was exercised with a real config save and a tab switch.teach\_me). Display-only fix here, by request.What to QA
/mwith more than 12 sessions, open a few tabs, then let one run until it asks for input. Its tab stays on the rail throughout.+, right-click the new "New session" chip: Close / Close others / Close to the right are there.