feat(coding-agent): add named-only filter toggle to /resume picker (#1128)

Adds Ctrl+N toggle to filter sessions by named-only vs all in the /resume picker.

- Add NameFilter type and filtering logic to session-selector-search.ts
- Add toggleSessionNamedFilter app keybinding (default: ctrl+n)
- Show Name: All/Named state in header
- Empty state mentions toggle keybinding as escape hatch
- Export hasSessionName() to avoid duplication

Co-authored-by: warren <warren.winter@gmail.com>
This commit is contained in:
Mario Zechner
2026-02-01 18:30:55 +01:00
parent 507639c760
commit 73839f876e
9 changed files with 203 additions and 23 deletions

View File

@@ -3,6 +3,8 @@ import type { SessionInfo } from "../../../core/session-manager.js";
export type SortMode = "threaded" | "recent" | "relevance";
export type NameFilter = "all" | "named";
export interface ParsedSearchQuery {
mode: "tokens" | "regex";
tokens: { kind: "fuzzy" | "phrase"; value: string }[];
@@ -25,6 +27,15 @@ function getSessionSearchText(session: SessionInfo): string {
return `${session.id} ${session.name ?? ""} ${session.allMessagesText} ${session.cwd}`;
}
export function hasSessionName(session: SessionInfo): boolean {
return Boolean(session.name?.trim());
}
function matchesNameFilter(session: SessionInfo, filter: NameFilter): boolean {
if (filter === "all") return true;
return hasSessionName(session);
}
export function parseSearchQuery(query: string): ParsedSearchQuery {
const trimmed = query.trim();
if (!trimmed) {
@@ -142,9 +153,16 @@ export function matchSession(session: SessionInfo, parsed: ParsedSearchQuery): M
return { matches: true, score: totalScore };
}
export function filterAndSortSessions(sessions: SessionInfo[], query: string, sortMode: SortMode): SessionInfo[] {
export function filterAndSortSessions(
sessions: SessionInfo[],
query: string,
sortMode: SortMode,
nameFilter: NameFilter = "all",
): SessionInfo[] {
const nameFiltered =
nameFilter === "all" ? sessions : sessions.filter((session) => matchesNameFilter(session, nameFilter));
const trimmed = query.trim();
if (!trimmed) return sessions;
if (!trimmed) return nameFiltered;
const parsed = parseSearchQuery(query);
if (parsed.error) return [];
@@ -152,7 +170,7 @@ export function filterAndSortSessions(sessions: SessionInfo[], query: string, so
// Recent mode: filter only, keep incoming order.
if (sortMode === "recent") {
const filtered: SessionInfo[] = [];
for (const s of sessions) {
for (const s of nameFiltered) {
const res = matchSession(s, parsed);
if (res.matches) filtered.push(s);
}
@@ -161,7 +179,7 @@ export function filterAndSortSessions(sessions: SessionInfo[], query: string, so
// Relevance mode: sort by score, tie-break by modified desc.
const scored: { session: SessionInfo; score: number }[] = [];
for (const s of sessions) {
for (const s of nameFiltered) {
const res = matchSession(s, parsed);
if (!res.matches) continue;
scored.push({ session: s, score: res.score });