From 742c1ef71124814d25bc8380c6700907b9fd5696 Mon Sep 17 00:00:00 2001 From: Matthias Trip Date: Sun, 2 Aug 2026 09:36:37 +0200 Subject: [PATCH] fix(web): honor autoOpenPreview when running a project action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "Open preview automatically when this action runs" toggle has had no effect since #2978: that rewrite moved runProjectScript onto the atom command API and dropped the block that opened the preview panel after the command was written to the terminal. #3842 later restored persistence of previewUrl/autoOpenPreview, so the setting saves and reloads correctly — it simply is not read at run time by anything. Restore the auto-open through the existing openUrlInPreview helper, which already does what the deleted code did by hand (open the session, apply the snapshot, remember the URL, reveal the tab in the right panel). A failed terminal write now returns instead of falling through, so a script that never started cannot open a preview. Preview failures stay silent for the caller: they are surfaced by the panel itself, and the script is already running, so they are not the script's failure. Fixes #5221 Co-Authored-By: Claude Opus 5 (1M context) --- apps/web/src/components/ChatView.tsx | 32 ++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 2b9eda1a787..269c2e121ae 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -134,6 +134,7 @@ import { closePreviewSession } from "./preview/closePreviewSession"; import { ThreadPreviewMiniPlayer } from "./preview/ThreadPreviewMiniPlayer"; import { subscribePreviewAction } from "./preview/previewActionBus"; import { getConfiguredPreviewUrls } from "./preview/previewEmptyStateLogic"; +import { openUrlInPreview } from "~/browser/openFileInPreview"; import { selectThreadPreviewMiniPlayer, usePreviewMiniPlayerStore, @@ -2880,12 +2881,30 @@ function ChatViewContent(props: ChatViewProps) { data: `${script.command}\r`, }, }); - if (writeResult._tag === "Failure" && !isAtomCommandInterrupted(writeResult)) { - const error = squashAtomCommandFailure(writeResult); - setThreadError( - activeThreadId, - error instanceof Error ? error.message : `Failed to run script "${script.name}".`, - ); + if (writeResult._tag === "Failure") { + if (!isAtomCommandInterrupted(writeResult)) { + const error = squashAtomCommandFailure(writeResult); + setThreadError( + activeThreadId, + error instanceof Error ? error.message : `Failed to run script "${script.name}".`, + ); + } + return; + } + + if ( + script.autoOpenPreview && + script.previewUrl && + isPreviewSupportedInRuntime() && + activeThreadRef + ) { + // Preview failures surface in the panel itself, and the script is + // already running — never report one as a failure of the script. + await openUrlInPreview({ + threadRef: activeThreadRef, + url: script.previewUrl, + openPreview, + }); } }, [ @@ -2894,6 +2913,7 @@ function ChatViewContent(props: ChatViewProps) { activeThreadId, activeThreadRef, gitCwd, + openPreview, setTerminalOpen, setThreadError, storeNewTerminal,