Skip to content

feat(sidebar): group sessions into display-only categories - #458

Open
k0n9-devx wants to merge 3 commits into
agegr:mainfrom
k0n9-devx:pr/session-categories
Open

feat(sidebar): group sessions into display-only categories#458
k0n9-devx wants to merge 3 commits into
agegr:mainfrom
k0n9-devx:pr/session-categories

Conversation

@k0n9-devx

Copy link
Copy Markdown
Contributor

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 (same
directory and atomic-write pattern as models.json). No session
.jsonl file is ever read or written by this feature.
The
SessionManager, RPC/agent logic, and the session persistence format
are 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.json is absent or deleted, the UI behaves
exactly as before — all sessions appear flat. The feature is trivially
revertible.

Refactor note

SessionItem / SessionTreeItem were extracted from
SessionSidebar.tsx into a shared components/SessionTreeItem.tsx
so both the original sidebar and the new SessionFolderTree can render
sessions 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.
  • Existing SessionSidebar.test.mjs source-inspection tests split
    between the two files where the code now lives.
  • All 441 existing tests pass.

i18n

Both en and zh-CN strings added (category → "分类" in Chinese).

kun 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant