mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-27 17:58:07 +00:00
Merge pull request #72514 from NousResearch/bb/desktop-pinned-session-order
fix(desktop): keep pinned sidebar rows in user order
This commit is contained in:
commit
9f0e62c5c4
3 changed files with 61 additions and 5 deletions
|
|
@ -205,7 +205,15 @@ export function SidebarSessionsSection({
|
|||
// The flat recents/pinned list is the only place sessions reorder by hand;
|
||||
// grouped/tree views always sort by creation date and never drag.
|
||||
const sessionsDraggable = sortable && !!onReorderSessions
|
||||
const displayEntries = useMemo(() => flattenSessionsWithBranches(sessions), [sessions])
|
||||
// Pinned and manual-drag lists pass sessions already in the caller's order.
|
||||
// Default recents stay dateGrouped and still re-sort roots by group recency
|
||||
// so partition buckets stay truthful — but NEVER for pins, where a turn
|
||||
// finishing was floating background tasks over the user's fixed ranking.
|
||||
const preserveInputOrder = pinned || (sessionsDraggable && !dateGrouped)
|
||||
const displayEntries = useMemo(
|
||||
() => flattenSessionsWithBranches(sessions, { preserveOrder: preserveInputOrder }),
|
||||
[sessions, preserveInputOrder]
|
||||
)
|
||||
|
||||
const renderRow = (session: SessionInfo, draggable: boolean, branchStem?: string) => {
|
||||
const rowProps = {
|
||||
|
|
|
|||
|
|
@ -50,4 +50,34 @@ describe('flattenSessionsWithBranches', () => {
|
|||
|
||||
expect(flattenSessionsWithBranches([branch])).toEqual([{ session: branch }])
|
||||
})
|
||||
|
||||
it('re-sorts roots by group recency by default (pinned-style jumps without preserveOrder)', () => {
|
||||
// Stale important chat first in the caller's array; a recently-active
|
||||
// background task second. Default path must lift the fresher root — that
|
||||
// is what was scrambling the Pinned section before preserveOrder.
|
||||
const important = session('important', { last_active: 10 })
|
||||
const background = session('background', { last_active: 99 })
|
||||
|
||||
expect(flattenSessionsWithBranches([important, background]).map(e => e.session.id)).toEqual([
|
||||
'background',
|
||||
'important'
|
||||
])
|
||||
})
|
||||
|
||||
it("preserveOrder keeps the caller's root order even when activity is newer lower down", () => {
|
||||
const important = session('important', { last_active: 10 })
|
||||
const background = session('background', { last_active: 99 })
|
||||
const branch = session('branch', { last_active: 50, parent_session_id: 'important' })
|
||||
|
||||
expect(
|
||||
flattenSessionsWithBranches([important, background, branch], { preserveOrder: true }).map(e => ({
|
||||
id: e.session.id,
|
||||
stem: e.branchStem
|
||||
}))
|
||||
).toEqual([
|
||||
{ id: 'important', stem: undefined },
|
||||
{ id: 'branch', stem: '└─ ' },
|
||||
{ id: 'background', stem: undefined }
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,10 +5,23 @@ export interface SidebarSessionEntry {
|
|||
session: SessionInfo
|
||||
}
|
||||
|
||||
export interface FlattenSessionsOptions {
|
||||
/**
|
||||
* Keep the input root order instead of re-sorting by group recency.
|
||||
* Use for hand-ordered surfaces (pinned ids, manual recents drag) so a
|
||||
* turn completing can't float a row. Branch children still nest under
|
||||
* their parent; sibling branches stay ordered by their own recency.
|
||||
*/
|
||||
preserveOrder?: boolean
|
||||
}
|
||||
|
||||
const recency = (session: SessionInfo): number => session.last_active || session.started_at || 0
|
||||
|
||||
/** Flat list with branch/fork sessions nested visually under their parent. */
|
||||
export function flattenSessionsWithBranches(sessions: readonly SessionInfo[]): SidebarSessionEntry[] {
|
||||
export function flattenSessionsWithBranches(
|
||||
sessions: readonly SessionInfo[],
|
||||
options: FlattenSessionsOptions = {}
|
||||
): SidebarSessionEntry[] {
|
||||
if (sessions.length < 2) {
|
||||
return sessions.map(session => ({ session }))
|
||||
}
|
||||
|
|
@ -53,6 +66,7 @@ export function flattenSessionsWithBranches(sessions: readonly SessionInfo[]): S
|
|||
// A group sorts by its freshest member, so activity on any branch lifts the
|
||||
// whole parent→branches cluster together instead of stranding the parent at
|
||||
// its own stale timestamp. Memoized — each subtree is folded at most once.
|
||||
// Skipped when preserveOrder is set: the caller already chose positions.
|
||||
const groupRecencyMemo = new Map<string, number>()
|
||||
|
||||
const groupRecency = (session: SessionInfo): number => {
|
||||
|
|
@ -92,11 +106,15 @@ export function flattenSessionsWithBranches(sessions: readonly SessionInfo[]): S
|
|||
children?.forEach((child, index) => emit(child, index === children.length - 1 ? '└─ ' : '├─ '))
|
||||
}
|
||||
|
||||
sessions
|
||||
const roots = sessions
|
||||
.filter(session => !nestedIds.has(session.id))
|
||||
.map((session, index) => ({ index, session }))
|
||||
.sort((a, b) => groupRecency(b.session) - groupRecency(a.session) || a.index - b.index)
|
||||
.forEach(({ session }) => emit(session))
|
||||
|
||||
if (!options.preserveOrder) {
|
||||
roots.sort((a, b) => groupRecency(b.session) - groupRecency(a.session) || a.index - b.index)
|
||||
}
|
||||
|
||||
roots.forEach(({ session }) => emit(session))
|
||||
|
||||
for (const session of sessions) {
|
||||
if (!seen.has(session.id)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue