(
query: string,
options?: { limit?: number; exact?: boolean },
)
| 3155 | * Searches across same-repo worktrees by default. |
| 3156 | */ |
| 3157 | export async function searchSessionsByCustomTitle( |
| 3158 | query: string, |
| 3159 | options?: { limit?: number; exact?: boolean }, |
| 3160 | ): Promise<LogOption[]> { |
| 3161 | const { limit, exact } = options || {} |
| 3162 | // Use worktree-aware loading to search across same-repo sessions |
| 3163 | const worktreePaths = await getWorktreePaths(getOriginalCwd()) |
| 3164 | const allStatLogs = await getStatOnlyLogsForWorktrees(worktreePaths) |
| 3165 | // Enrich all logs to access customTitle metadata |
| 3166 | const { logs } = await enrichLogs(allStatLogs, 0, allStatLogs.length) |
| 3167 | const normalizedQuery = query.toLowerCase().trim() |
| 3168 | |
| 3169 | const matchingLogs = logs.filter(log => { |
| 3170 | const title = log.customTitle?.toLowerCase().trim() |
| 3171 | if (!title) return false |
| 3172 | return exact ? title === normalizedQuery : title.includes(normalizedQuery) |
| 3173 | }) |
| 3174 | |
| 3175 | // Deduplicate by sessionId - multiple logs can have the same sessionId |
| 3176 | // if they're different branches of the same conversation. Keep most recent. |
| 3177 | const sessionIdToLog = new Map<UUID, LogOption>() |
| 3178 | for (const log of matchingLogs) { |
| 3179 | const sessionId = getSessionIdFromLog(log) |
| 3180 | if (sessionId) { |
| 3181 | const existing = sessionIdToLog.get(sessionId) |
| 3182 | if (!existing || log.modified > existing.modified) { |
| 3183 | sessionIdToLog.set(sessionId, log) |
| 3184 | } |
| 3185 | } |
| 3186 | } |
| 3187 | const deduplicated = Array.from(sessionIdToLog.values()) |
| 3188 | |
| 3189 | // Sort by recency |
| 3190 | deduplicated.sort((a, b) => b.modified.getTime() - a.modified.getTime()) |
| 3191 | |
| 3192 | // Apply limit if specified |
| 3193 | if (limit) { |
| 3194 | return deduplicated.slice(0, limit) |
| 3195 | } |
| 3196 | |
| 3197 | return deduplicated |
| 3198 | } |
| 3199 | |
| 3200 | /** |
| 3201 | * Metadata entry types that can appear before a compact boundary but must |
no test coverage detected