fix(frontend): Sort sidebar agents by last used - #6104
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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
|
mmabrouk
left a comment
There was a problem hiding this comment.
Review summary
Focused on performance. No blocking issue: the stamps driving the new ordering are written once per settled turn, not per streamed token, so the sidebar does not re-render on every frame while chatting. Core logic reads correctly and the traps are well covered by tests. One change requested below, plus two low-severity cleanups.
Requested change
- Avoid re-sorting + re-rendering the whole Agents group on every completed chat turn.
sidebarAgentsListAtomdepends onlocalAgentActivityAtom, which reads the entiresessionMessagesAtommap. That map is rewritten each time a turn settles (bumpSessionActivityAtom), so every turn completion re-sorts all agents (not just the visible five) and returns a new array + new object reference ({...query, data: [...]}), re-rendering the group even when the order is unchanged. Please memoize the emitted list so an unchanged order returns the previous array reference (reference-check the sorted ids), and/or narrowlocalAgentActivityAtom's dependency onsessionMessagesAtom— it subscribes to the full messages map only to feedisSessionHusk'smessages[id]?.lengthlookup, so it invalidates even for sessions that already havelastMessageAtand skip the husk check. Fine at today's scale; this keeps it from becoming a hotspot in a heavy workspace.
Non-blocking cleanups
- Sort key computed inside the comparator.
sortAgentsByLastUsedcallsrank()(which doesDate.parseviaat()for agents lacking usage) inside.sort(), i.e. O(n log n) parses instead of O(n). Precompute rank once per workflow into a map, then sort. Math.max(0, ...used.map(sessionActivity))spread inlocalAgentActivityAtomthrows on a pathologically large per-app session list (arg-count ceiling). Unlikely from real localStorage, but areduceavoids the ceiling.
Confirmed good
- No second network request:
sidebarSessionRowsAtomreuses the existing recent + pinned session query data rather than issuing a new window query. - Local-stamp-wins-when-newer, husk exclusion, non-agent scope exclusion, brand-new-agent fallback, and stable-tie ordering all read correctly and are pinned by the two test files.
Note: stacked on feat/agent-icon-picker (#6062); both touch registry.ts, so #6062 should merge first. This is an advisory review.
The Agents group showed the first five records from the shared workflow list, whose order follows creation, so the visible agents had no relation to the ones in use. Sort by last-used activity before the five-item cut. Recency comes from the session rows the sidebar already fetches (keys shared with the Sessions group, so no extra request), overlaid with the local playground store so a just-started session reorders immediately. Agents with no usage fall back to updated_at ?? created_at, which also puts a freshly created agent on top. Husk tabs (opened, never used) are excluded so visiting an agent does not rank it as used. Closes #6046
9f06d10 to
09d5351
Compare
Context
Opening the Agents group in the sidebar showed five agents in what looked like a random order. The group rendered the first five records from the shared workflow list, whose order follows creation, so the agents on screen had no relation to the ones you actually work with.
Changes
The Agents group now sorts by last used before the five-item cut, so the top of the list is the agents you touched most recently.
"Last used" is the agent's newest session activity. It comes from the session rows the sidebar already fetches for the Sessions group (same query keys, so no extra request), overlaid with this browser's local playground store so a session you just started reorders the list immediately, ahead of the server window's stale time.
An agent with no session history falls back to
updated_at ?? created_at. That is one ranking key, not two tiers, so a freshly created agent carries the newest timestamp in the list and opens at the top.Sorting lives in a new list atom the registry points at, so the order lands before
resolveChildrenslices the visible five, and the full list stays intact for the "Show all" overflow count.Before: first five workflow records, creation order.
After: five most recently used agents, newest first.
Tests / notes
agentsSource.test.tscovers ordering, the created/updated fallback, a brand-new agent ranking on top, ties keeping source order, and the sort-before-limit guarantee.sessions.localActivity.test.tspins the local overlay: a seeded blank tab does not count as usage (opening a playground seeds an empty tab, so "visited" must not read as "used"), a settled turn does, and non-app scopes are skipped.pnpm test:unitgreen on all touched suites,tscandpnpm lint-fixclean.exclude-trigger, and counting trigger sessions would need a separate query key (a second request per sidebar open), so it was left out on purpose.feat/agent-icon-picker([feat] Let each agent carry its own icon and colour #6062), which also editsregistry.ts. Base this PR on that branch; it should merge first.What to QA