diff --git a/benchmarks/terminal_bench/prepare_leaderboard_submission.py b/benchmarks/terminal_bench/prepare_leaderboard_submission.py index 4b94e293b8..e379b25e5a 100755 --- a/benchmarks/terminal_bench/prepare_leaderboard_submission.py +++ b/benchmarks/terminal_bench/prepare_leaderboard_submission.py @@ -216,6 +216,11 @@ def get_model_from_config(config_path: Path) -> str | None: return None +def _child_dirs(path: Path) -> list[Path]: + """List the immediate subdirectories of a directory, skipping plain files.""" + return [child for child in path.iterdir() if child.is_dir()] + + def _is_job_folder(path: Path) -> bool: """Check if a directory looks like a job folder (contains trial dirs with config.json).""" if not path.is_dir(): @@ -249,20 +254,14 @@ def find_job_folders(artifacts_dir: Path) -> list[Path]: # Check for direct jobs/ folder direct_jobs = artifacts_dir / "jobs" if direct_jobs.exists(): - for item in direct_jobs.iterdir(): - if item.is_dir(): - job_folders.append(item) + job_folders.extend(_child_dirs(direct_jobs)) return job_folders # Check for per-artifact structure - for artifact_dir in artifacts_dir.iterdir(): - if not artifact_dir.is_dir(): - continue + for artifact_dir in _child_dirs(artifacts_dir): jobs_dir = artifact_dir / "jobs" if jobs_dir.exists(): - for item in jobs_dir.iterdir(): - if item.is_dir(): - job_folders.append(item) + job_folders.extend(_child_dirs(jobs_dir)) return job_folders diff --git a/src/browser/App.tsx b/src/browser/App.tsx index 8b1903912b..cc5920100e 100644 --- a/src/browser/App.tsx +++ b/src/browser/App.tsx @@ -45,6 +45,7 @@ import { LEFT_SIDEBAR_DEFAULT_WIDTH_PX, LEFT_SIDEBAR_MAX_WIDTH_PX, LEFT_SIDEBAR_MIN_WIDTH_PX, + MOBILE_TOUCH_MEDIA_QUERY, } from "@/constants/layout"; import { buildCoreSources, type BuildSourcesParams } from "./utils/commands/sources"; @@ -231,8 +232,7 @@ function AppInner() { // because the sidebar width is controlled by CSS and shouldn't rewrite the user's desktop // width preference. const isMobileTouch = - typeof window !== "undefined" && - window.matchMedia("(max-width: 768px) and (pointer: coarse)").matches; + typeof window !== "undefined" && window.matchMedia(MOBILE_TOUCH_MEDIA_QUERY).matches; if (isMobileTouch) { return Number.POSITIVE_INFINITY; } diff --git a/src/browser/components/ChatPane/ChatPane.tsx b/src/browser/components/ChatPane/ChatPane.tsx index c585d2c2a1..16203c67a4 100644 --- a/src/browser/components/ChatPane/ChatPane.tsx +++ b/src/browser/components/ChatPane/ChatPane.tsx @@ -41,6 +41,7 @@ import { mergeConsecutiveStreamErrors, computeBashOutputGroupInfos, shouldBypassDeferredMessages, + isBashMonitorWakeMessage, } from "@/browser/utils/messages/messageUtils"; import { computeTaskReportLinking } from "@/browser/utils/messages/taskReportLinking"; import { BashCollapsedSummaryModeProvider } from "@/browser/features/Tools/BashCollapsedSummaryModeContext"; @@ -104,6 +105,7 @@ import { useBackgroundBashError, } from "@/browser/contexts/BackgroundBashContext"; import { hasWorkspaceRepository } from "@/browser/utils/workspaceCapabilities"; +import { isPrimaryMouseButton } from "@/browser/utils/events"; import { buildEditingStateFromDisplayed, canEditDisplayedUserMessage, @@ -728,7 +730,7 @@ const ChatPaneContent: React.FC = (props) => { ); const handleComposerDockMouseDown = (event: React.MouseEvent) => { - if (event.defaultPrevented || event.button !== 0) { + if (event.defaultPrevented || !isPrimaryMouseButton(event)) { return; } const control = resolveComposerControlFocusTarget(event.target, composerDockRef.current); @@ -779,7 +781,7 @@ const ChatPaneContent: React.FC = (props) => { const userHistoryIds: string[] = []; for (const message of deferredMessages) { // Monitor wake events should not interrupt navigation between human prompts. - if (message.type === "user" && message.bashMonitorWake == null) { + if (message.type === "user" && !isBashMonitorWakeMessage(message)) { userHistoryIds.push(message.historyId); } } diff --git a/src/browser/components/ChatPane/WorkspaceFooterBar.tsx b/src/browser/components/ChatPane/WorkspaceFooterBar.tsx index 1a4a69ebd3..47ee0a75c4 100644 --- a/src/browser/components/ChatPane/WorkspaceFooterBar.tsx +++ b/src/browser/components/ChatPane/WorkspaceFooterBar.tsx @@ -143,6 +143,11 @@ function WorkspaceBranchControls(props: { ); } +// Shared by the footer's interactive pills (repository link, "Last prompt") so they keep reading as +// one affordance family: restyling one silently drifting from the other is the failure mode here. +const FOOTER_PILL_CLASS = + "text-muted hover:bg-hover hover:text-foreground focus-visible:ring-accent flex h-5 shrink-0 items-center gap-1 rounded-md px-1.5 transition-colors focus-visible:ring-1"; + function FooterRepositoryLabel(props: { workspaceId: string; projectLabel: string }) { const workspacePR = useWorkspacePR(props.workspaceId); @@ -161,7 +166,7 @@ function FooterRepositoryLabel(props: { workspaceId: string; projectLabel: strin target="_blank" rel="noopener noreferrer" data-testid="workspace-footer-repository" - className="text-muted hover:bg-hover hover:text-foreground focus-visible:ring-accent flex h-5 shrink-0 items-center gap-1 rounded-md px-1.5 transition-colors focus-visible:ring-1" + className={FOOTER_PILL_CLASS} >