Files
deepseek-harness/packages/client/ui-sidebar
imccyu 7e6f0128b5 fix(gui): keep sidebar controls when collapsed
A closed sidebar previously resolved to a zero-width grid track, clipping
the only toggle and the settings entry with no visible recovery; the closed
preference persisted across reloads, locking the sidebar shut.

- columns.ts maps the closed preference (width 0) to a fixed 60px
  SIDEBAR_COLLAPSED rail through every step of the concession solve;
  closed details still resolve to zero width.
- AppFrame derives data-sidebar-collapsed and the sidebar slot's collapsed
  owner prop from the persisted preference instead of the resolved track
  width, and drops the resize handle while collapsed.
- SidebarRoot reads the owner collapsed prop; the expanded-only body is a
  separate component that unmounts while collapsed (dropping its sessions
  subscription), leaving the expand toggle and Settings in the rail.
- The keyless web smoke gains the ui-sidebar bundle (six real bundles) and
  pins the 60px rail collapse/expand round through the assembled client.
2026-07-23 10:51:57 +08:00
..

@deepseek-ai/dsh-client-ui-sidebar

Sidebar plugin: session multi-level tree (cwd grouping + parentId nesting), search, by-workspace grouping, state dots, three creation entries. The collapsed render keeps the expand control and settings entry in the layout-owned compact rail. Contract: the slot system standard.

src/client/contract/slots.ts is the single-domain contract file: SidebarRootInjected (the registrant's own injected share — plain service callbacks: onOpen/onCreate/onToggleSidebar) and SidebarRootComponentProps = PropsRuntime<'sidebar'> & SidebarRootInjected (owner {collapsed,width} plus the standard useSessions hook, resolved off ui-layout's SlotMap declaration, never re-stated). apply registers SidebarRoot cast-free against that composition; the inject factory closes over the plugin's own ctx.

There is no plugin store: rows derive in the component (useMemo over the useSessions snapshot + local expansion/search state) through the pure deriveRows in tree.ts.

The /client export surface is the plugin body (apply/inject) plus the contract types only — SidebarRoot, the row components, and the tree derivation are internal (the slot registration closes over them; tests import src paths directly).

Model Experience

None, as the sidebar renders the browser session list; nothing here reaches a model request.

KV Cache effect

None; this package neither assembles nor sends a provider request.

Known Limitations and Deferred Work

  • State dots have two live data states (running/none) — the done/error/amber sources arrive with P-II approvals and notifications; the four-color primitive is already wired.
  • Group-by menu ships by-workspace only — Update/Status grouping strategies are drawn without specs and deferred.
  • "New task completed" unread marking is local viewing state — completion-time > last-seen never reaches the host.