diff --git a/desktop/src/features/chats/lib/chatWorkAutomation.ts b/desktop/src/features/chats/lib/chatWorkAutomation.ts index 4470275d6..11b00fad1 100644 --- a/desktop/src/features/chats/lib/chatWorkAutomation.ts +++ b/desktop/src/features/chats/lib/chatWorkAutomation.ts @@ -162,6 +162,12 @@ export function readChatPinnedPr(chatId: string): string | null { } } +/** + * Explicit "no PR" pin: suppresses branch discovery for the chat (the user + * said the discovered PR was wrong) while posted links still override. + */ +export const CHAT_PR_UNPINNED = ""; + export function writeChatPinnedPr(chatId: string, href: string) { if (typeof window === "undefined") { return; diff --git a/desktop/src/features/chats/ui/ChatWorkPanel.tsx b/desktop/src/features/chats/ui/ChatWorkPanel.tsx index 4d14b03e5..4904d3555 100644 --- a/desktop/src/features/chats/ui/ChatWorkPanel.tsx +++ b/desktop/src/features/chats/ui/ChatWorkPanel.tsx @@ -11,6 +11,7 @@ import { } from "lucide-react"; import { + CHAT_PR_UNPINNED, readChatPinnedPr, updateChatWorkAutomation, useChatWorkAutomation, @@ -88,17 +89,32 @@ export function ChatWorkPanel({ // Pin resolution order: a link posted in THIS chat wins, then the chat's // previously pinned PR, then branch discovery — discovery alone is // ambiguous when agents reuse a worktree across chats in one project. - const pinnedHref = React.useMemo(() => readChatPinnedPr(chatId), [chatId]); + const [pinnedHref, setPinnedHref] = React.useState(() => + readChatPinnedPr(chatId), + ); + React.useEffect(() => { + setPinnedHref(readChatPinnedPr(chatId)); + }, [chatId]); + // The empty-string sentinel means "user unlinked — no PR for this chat": + // discovery stays off, posted links still win. + const isUnpinned = pinnedHref === CHAT_PR_UNPINNED; const discoveredPrQuery = useGithubPrForBranchQuery( - monitorActive && !prHref && !pinnedHref ? projectPath : null, + monitorActive && !prHref && pinnedHref === null ? projectPath : null, branch, ); - const effectiveHref = prHref ?? pinnedHref ?? discoveredPrQuery.data ?? null; + const effectiveHref = + prHref ?? + (isUnpinned ? null : (pinnedHref ?? discoveredPrQuery.data ?? null)); React.useEffect(() => { if (effectiveHref && effectiveHref !== readChatPinnedPr(chatId)) { writeChatPinnedPr(chatId, effectiveHref); + setPinnedHref(effectiveHref); } }, [chatId, effectiveHref]); + const handleUnlinkPr = React.useCallback(() => { + writeChatPinnedPr(chatId, CHAT_PR_UNPINNED); + setPinnedHref(CHAT_PR_UNPINNED); + }, [chatId]); const preview = effectiveHref ? parseSupportedLinkPreview(effectiveHref) : null; @@ -259,6 +275,16 @@ export function ChatWorkPanel({ key={preview.href} > + {!prHref ? ( + + ) : null}