| ... | @@ -11,7 +11,7 @@ import type { SidebarThreadSortOrder } from "@t3tools/contracts/settings"; | ... | @@ -11,7 +11,7 @@ import type { SidebarThreadSortOrder } from "@t3tools/contracts/settings"; |
| 11 | import * as Arr from "effect/Array"; | 11 | import * as Arr from "effect/Array"; |
| 12 | import * as Result from "effect/Result"; | 12 | import * as Result from "effect/Result"; |
| 13 | import { type ReactNode } from "react"; | 13 | import { type ReactNode } from "react"; |
| 14 | import { sortThreads } from "../lib/threadSort"; | 14 | import { getThreadSortTimestamp, sortThreads } from "../lib/threadSort"; |
| 15 | import { normalizeSearchText } from "../lib/utils"; | 15 | import { normalizeSearchText } from "../lib/utils"; |
| 16 | import { formatRelativeTimeLabel } from "../timestampFormat"; | 16 | import { formatRelativeTimeLabel } from "../timestampFormat"; |
| 17 | import { type Project, type SidebarThreadSummary, type Thread } from "../types"; | 17 | import { type Project, type SidebarThreadSummary, type Thread } from "../types"; |
| ... | @@ -135,6 +135,7 @@ export interface CommandPaletteItem { | ... | @@ -135,6 +135,7 @@ export interface CommandPaletteItem { |
| 135 | readonly description?: ReactNode; | 135 | readonly description?: ReactNode; |
| 136 | readonly threadContentMatch?: CommandPaletteThreadContentMatch; | 136 | readonly threadContentMatch?: CommandPaletteThreadContentMatch; |
| 137 | readonly timestamp?: string; | 137 | readonly timestamp?: string; |
| | 138 | readonly searchRecency?: number; |
| 138 | readonly icon: ReactNode; | 139 | readonly icon: ReactNode; |
| 139 | readonly disabled?: boolean; | 140 | readonly disabled?: boolean; |
| 140 | /** Optional content rendered inline before the title text. */ | 141 | /** Optional content rendered inline before the title text. */ |
| ... | @@ -315,6 +316,7 @@ export function buildThreadActionItems<TThread extends BuildThreadActionItemsThr | ... | @@ -315,6 +316,7 @@ export function buildThreadActionItems<TThread extends BuildThreadActionItemsThr |
| 315 | timestamp: formatRelativeTimeLabel( | 316 | timestamp: formatRelativeTimeLabel( |
| 316 | thread.latestUserMessageAt ?? thread.updatedAt ?? thread.createdAt, | 317 | thread.latestUserMessageAt ?? thread.updatedAt ?? thread.createdAt, |
| 317 | ), | 318 | ), |
| | 319 | searchRecency: getThreadSortTimestamp(thread, "updated_at"), |
| 318 | icon: input.icon, | 320 | icon: input.icon, |
| 319 | }, | 321 | }, |
| 320 | leadingContent ? { titleLeadingContent: leadingContent } : {}, | 322 | leadingContent ? { titleLeadingContent: leadingContent } : {}, |
| ... | @@ -366,6 +368,10 @@ function rankCommandPaletteItemMatch( | ... | @@ -366,6 +368,10 @@ function rankCommandPaletteItemMatch( |
| 366 | for (const [index, field] of terms.entries()) { | 368 | for (const [index, field] of terms.entries()) { |
| 367 | const fieldRank = rankSearchFieldMatch(field, normalizedQuery, queryTokens); | 369 | const fieldRank = rankSearchFieldMatch(field, normalizedQuery, queryTokens); |
| 368 | if (fieldRank !== Number.NEGATIVE_INFINITY) { | 370 | if (fieldRank !== Number.NEGATIVE_INFINITY) { |
| | 371 | if (index === 0 && item.searchRecency !== undefined) { |
| | 372 | // All non-exact thread title matches share a tier so recency breaks the tie. |
| | 373 | return 1_000 + Number(fieldRank === 3); |
| | 374 | } |
| 369 | return 1_000 - index * 100 + fieldRank; | 375 | return 1_000 - index * 100 + fieldRank; |
| 370 | } | 376 | } |
| 371 | } | 377 | } |
| ... | @@ -442,6 +448,7 @@ export function filterCommandPaletteGroups(input: { | ... | @@ -442,6 +448,7 @@ export function filterCommandPaletteGroups(input: { |
| 442 | (left, right) => | 448 | (left, right) => |
| 443 | Number(left.item.secondary ?? false) - Number(right.item.secondary ?? false) || | 449 | Number(left.item.secondary ?? false) - Number(right.item.secondary ?? false) || |
| 444 | right.rank - left.rank || | 450 | right.rank - left.rank || |
| | 451 | (right.item.searchRecency ?? 0) - (left.item.searchRecency ?? 0) || |
| 445 | left.index - right.index, | 452 | left.index - right.index, |
| 446 | ) | 453 | ) |
| 447 | .map((entry) => entry.item); | 454 | .map((entry) => entry.item); |