feat(sidebar): group sessions into display-only categories - #458
Open
k0n9-devx wants to merge 3 commits into
Open
feat(sidebar): group sessions into display-only categories#458k0n9-devx wants to merge 3 commits into
k0n9-devx wants to merge 3 commits into
Conversation
added 3 commits
August 10, 2026 08:03
Adds a file-explorer-style folder layer on top of the flat session list. Folders are purely a display concept, stored separately from session files in ~/.pi/agent/session-folders.json — nothing here ever reads or writes a session's .jsonl file. - lib/session-folders.ts: folder CRUD + session assignment store (atomic JSON read/write, same pattern as models-config.json). Deleting a folder never deletes a session: direct child sessions become unfiled, direct child folders are promoted to the deleted folder's parent. - app/api/session-folders/*: REST endpoints for folder CRUD and session-to-folder assignment. - components/SessionTreeItem.tsx: extracted SessionItem/SessionTreeItem (and their helpers) out of SessionSidebar.tsx so both SessionSidebar and the new SessionFolderTree can render sessions with the same rename/delete interactions, plus a new opt-in "move to folder" menu. - components/SessionFolderTree.tsx: renders the folder tree (create, rename, delete, nested subfolders) and groups sessions accordingly; ungrouped sessions fall into "Unfiled". - i18n: en/zh-CN strings for the new folder UI. Tests: lib/session-folders.test.mjs (15 cases covering CRUD, the non-destructive delete/promote semantics, and pruning). Existing SessionSidebar/SessionItem source-inspection tests split across the two files they now live in.
The row's own overflow:hidden (for title ellipsis) plus the scrollable session list clipped the folder dropdown, which opened *inside* that overflow context — so on a session near the visible edge the popup was invisible or cut off. Render it via a portal into document.body with position:fixed computed from the trigger button's live bounding rect, which is unaffected by any ancestor's overflow/scroll. Closes on scroll/resize instead of tracking a stale position. fix(app): suppress hydration warning on <body> Browser extensions (translation tools etc.) inject attributes into <body> before React hydrates, which is a client-only DOM mutation outside our control — suppressHydrationWarning on <html> already covered this pattern; add the same on <body> so it does not surface as a console error for users with such extensions installed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This adds an optional, display-only folder/category layer on top of the
flat session list in the sidebar. Users can create, rename, and delete
categories (up to arbitrary nesting depth) and assign sessions to them
via a dropdown menu on each session row.
Design: pure presentation layer
Categories are stored in
~/.pi/agent/session-folders.json(samedirectory and atomic-write pattern as
models.json). No session.jsonlfile is ever read or written by this feature. TheSessionManager, RPC/agent logic, and the session persistence formatare completely untouched.
Consequence: deleting a category never deletes a session. Direct
child sessions become unfiled; direct child subcategories are promoted
to the deleted category's parent.
When
session-folders.jsonis absent or deleted, the UI behavesexactly as before — all sessions appear flat. The feature is trivially
revertible.
Refactor note
SessionItem/SessionTreeItemwere extracted fromSessionSidebar.tsxinto a sharedcomponents/SessionTreeItem.tsxso both the original sidebar and the new
SessionFolderTreecan rendersessions with the same rename/delete interactions. Extracted code is
unchanged apart from the new optional "move to category" action.
Testing
lib/session-folders.test.mjs: 15 cases covering CRUD,non-destructive delete/promotion, assignment, and pruning.
SessionSidebar.test.mjssource-inspection tests splitbetween the two files where the code now lives.
i18n
Both
enandzh-CNstrings added (category → "分类" in Chinese).