diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 553aa2f51..40856038f 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -4593,6 +4593,7 @@ export default function ChatView({ threadId }: ChatViewProps) { activeProjectCwd={activeProject?.cwd} isGitRepo={isGitRepo} isLocalDraftThread={isLocalDraftThread} + threadBranch={activeThread.branch ?? null} openInCwd={gitCwd} activeProjectScripts={activeProject?.scripts} preferredScriptId={ diff --git a/apps/web/src/components/chat/ChatHeader.tsx b/apps/web/src/components/chat/ChatHeader.tsx index 3fcd2f3af..216211242 100644 --- a/apps/web/src/components/chat/ChatHeader.tsx +++ b/apps/web/src/components/chat/ChatHeader.tsx @@ -4,14 +4,19 @@ import { type ThreadId, type ResolvedKeybindingsConfig, } from "@okcode/contracts"; -import { memo, useEffect } from "react"; +import { useQuery } from "@tanstack/react-query"; +import { GitPullRequestIcon } from "lucide-react"; +import { memo, useCallback, useEffect } from "react"; import type { ProjectScriptDraft } from "~/projectScriptDefaults"; import GitActionsControl from "../GitActionsControl"; import { EditableThreadTitle } from "../EditableThreadTitle"; import { Badge } from "../ui/badge"; import ProjectScriptsControl, { type NewProjectScriptInput } from "../ProjectScriptsControl"; import { SidebarTrigger } from "../ui/sidebar"; +import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { useThreadTitleEditor } from "~/hooks/useThreadTitleEditor"; +import { gitStatusQueryOptions } from "~/lib/gitReactQuery"; +import { ensureNativeApi } from "~/nativeApi"; import { useProjectColor } from "~/projectColors"; import { useTheme } from "~/hooks/useTheme"; import type { ClientMode } from "~/lib/clientMode"; @@ -37,6 +42,7 @@ interface ChatHeaderProps { previewAvailable: boolean; previewOpen: boolean; previewDock: PreviewDock; + threadBranch: string | null; gitCwd: string | null; diffOpen: boolean; clientMode: ClientMode; @@ -60,6 +66,7 @@ export const ChatHeader = memo(function ChatHeader({ activeProjectCwd, isGitRepo, isLocalDraftThread, + threadBranch, openInCwd: _openInCwd, activeProjectScripts, preferredScriptId, @@ -108,6 +115,25 @@ export const ChatHeader = memo(function ChatHeader({ cancelEditing(); }, [activeThreadId, cancelEditing]); + // Derive PR status from git status when the thread has an associated branch + const { data: gitStatus = null } = useQuery({ + ...gitStatusQueryOptions(gitCwd), + // Only need git status for PR info when thread has a branch + enabled: gitCwd !== null && threadBranch !== null, + staleTime: 30_000, + refetchInterval: 60_000, + }); + + const threadPr = + threadBranch !== null && gitStatus?.branch === threadBranch ? (gitStatus?.pr ?? null) : null; + + const openPrLink = useCallback( + (url: string) => { + void ensureNativeApi().shell.openExternal(url); + }, + [], + ); + return (