(
query: string,
options?: { limit?: number; exact?: boolean },
)
| 3063 | * Searches across same-repo worktrees by default. |
| 3064 | */ |
| 3065 | export async function searchSessionsByCustomTitle( |
| 3066 | query: string, |
| 3067 | options?: { limit?: number; exact?: boolean }, |
| 3068 | ): Promise<LogOption[]> { |
| 3069 | const { limit, exact } = options || {} |
| 3070 | // Use worktree-aware loading to search across same-repo sessions |
| 3071 | const worktreePaths = await getWorktreePaths(getOriginalCwd()) |
| 3072 | const allStatLogs = await getStatOnlyLogsForWorktrees(worktreePaths) |
| 3073 | // Enrich all logs to access customTitle metadata |
| 3074 | const { logs } = await enrichLogs(allStatLogs, 0, allStatLogs.length) |
| 3075 | const normalizedQuery = query.toLowerCase().trim() |
| 3076 | |
| 3077 | const matchingLogs = logs.filter(log => { |
| 3078 | const title = log.customTitle?.toLowerCase().trim() |
| 3079 | if (!title) return false |
| 3080 | return exact ? title === normalizedQuery : title.includes(normalizedQuery) |
| 3081 | }) |
| 3082 | |
| 3083 | // Deduplicate by sessionId - multiple logs can have the same sessionId |
| 3084 | // if they're different branches of the same conversation. Keep most recent. |
| 3085 | const sessionIdToLog = new Map<UUID, LogOption>() |
| 3086 | for (const log of matchingLogs) { |
| 3087 | const sessionId = getSessionIdFromLog(log) |
| 3088 | if (sessionId) { |
| 3089 | const existing = sessionIdToLog.get(sessionId) |
| 3090 | if (!existing || log.modified > existing.modified) { |
| 3091 | sessionIdToLog.set(sessionId, log) |
| 3092 | } |
| 3093 | } |
| 3094 | } |
| 3095 | const deduplicated = Array.from(sessionIdToLog.values()) |
| 3096 | |
| 3097 | // Sort by recency |
| 3098 | deduplicated.sort((a, b) => b.modified.getTime() - a.modified.getTime()) |
| 3099 | |
| 3100 | // Apply limit if specified |
| 3101 | if (limit) { |
| 3102 | return deduplicated.slice(0, limit) |
| 3103 | } |
| 3104 | |
| 3105 | return deduplicated |
| 3106 | } |
| 3107 | |
| 3108 | /** |
| 3109 | * Metadata entry types that can appear before a compact boundary but must |
no test coverage detected