From bf6a8ec5a76719c1979c877c822d6433f8a1e22f Mon Sep 17 00:00:00 2001 From: T3 Code PR Stack <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 16:04:29 +0200 Subject: [PATCH] fix(web): restore remote Open in VS Code header button Stack conflict recovery kept resolveRemoteVscodeOpenTarget for tests but dropped the chat-header control that opens Remote SSH worktrees via vscode://. Wire the button back for non-primary project environments. --- apps/web/src/components/chat/ChatHeader.tsx | 44 ++++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/apps/web/src/components/chat/ChatHeader.tsx b/apps/web/src/components/chat/ChatHeader.tsx index 254cd18244e..e3f2d7c584d 100644 --- a/apps/web/src/components/chat/ChatHeader.tsx +++ b/apps/web/src/components/chat/ChatHeader.tsx @@ -8,7 +8,7 @@ import { import { scopeThreadRef } from "@t3tools/client-runtime/environment"; import type { ConnectionCatalogEntry } from "@t3tools/client-runtime/connection"; import * as Option from "effect/Option"; -import { memo } from "react"; +import { memo, useCallback, useMemo } from "react"; import GitActionsControl from "../GitActionsControl"; import { type DraftId } from "~/composerDraftStore"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; @@ -17,10 +17,13 @@ import ProjectScriptsControl, { type ProjectScriptActionResult, } from "../ProjectScriptsControl"; import { OpenInPicker } from "./OpenInPicker"; -import { usePrimaryEnvironmentId } from "../../state/environments"; +import { useEnvironment, usePrimaryEnvironmentId } from "../../state/environments"; import { useT3ProjectFileScripts } from "~/hooks/useT3ProjectFileScripts"; import { ProjectFavicon } from "../ProjectFavicon"; import { cn } from "~/lib/utils"; +import { Button } from "../ui/button"; +import { VisualStudioCode } from "../Icons"; +import { readLocalApi } from "~/localApi"; interface ChatHeaderProps { activeThreadEnvironmentId: EnvironmentId; @@ -121,6 +124,7 @@ export const ChatHeader = memo(function ChatHeader({ onDeleteProjectScript, }: ChatHeaderProps) { const primaryEnvironmentId = usePrimaryEnvironmentId(); + const activeEnvironment = useEnvironment(activeThreadEnvironmentId); const fileScripts = useT3ProjectFileScripts( activeThreadEnvironmentId, activeProjectScripts ? activeProjectCwd : null, @@ -130,6 +134,20 @@ export const ChatHeader = memo(function ChatHeader({ activeThreadEnvironmentId, primaryEnvironmentId, }); + const remoteVscodeTarget = useMemo( + () => + activeProjectName && !showOpenInPicker + ? resolveRemoteVscodeOpenTarget({ + entry: activeEnvironment?.entry ?? null, + cwd: openInCwd, + }) + : null, + [activeEnvironment?.entry, activeProjectName, openInCwd, showOpenInPicker], + ); + const openRemoteVscode = useCallback(() => { + if (!remoteVscodeTarget) return; + void readLocalApi()?.shell.openExternal(remoteVscodeTarget.uri); + }, [remoteVscodeTarget]); return (
@@ -204,6 +222,28 @@ export const ChatHeader = memo(function ChatHeader({ openInCwd={openInCwd} /> )} + {remoteVscodeTarget && ( + + + + )} {activeProjectName && (