"use client"; import { useCallback, useState } from "react"; import { IconBox, IconLoader2, IconTrash } from "@tabler/icons-react"; import { HoverCard, HoverCardContent, HoverCardTrigger } from "@kandev/ui/hover-card"; import { Button } from "@kandev/ui/button"; import { getExecutorStatusIcon } from "@/lib/executor-icons"; import { TaskResetEnvConfirmDialog } from "./task-reset-env-confirm-dialog"; import type { StatusTone } from "./executor-environment-status"; import { usePrepareSummary } from "@/hooks/domains/session/use-prepare-summary"; import { useTaskEnvironment } from "@/hooks/domains/session/use-task-environment"; import { isPreparingPhase } from "@/lib/prepare/summarize"; import { PrepareStatusSection } from "./executor-prepare-status"; import { EnvironmentInfo } from "./executor-environment-info"; type ExecutorSettingsButtonProps = { taskId?: string | null; sessionId?: string | null; disabled?: boolean; }; export function ExecutorSettingsButton({ taskId, sessionId, disabled, }: ExecutorSettingsButtonProps) { const [open, setOpen] = useState(false); const [resetDialogOpen, setResetDialogOpen] = useState(false); const prepare = usePrepareSummary(sessionId ?? null); const isPreparing = isPreparingPhase(prepare.phase); // Promote the foreground polling cadence while preparing so the icon flips // to "ready" without the user hovering over the trigger. const { env, container, ssh, loading, isResetting, reset, status } = useTaskEnvironment( taskId, open || isPreparing, ); const handleReset = useCallback( async (opts: { pushBranch: boolean }) => { const ok = await reset(opts); if (ok) { setResetDialogOpen(false); setOpen(false); } }, [reset], ); if (!taskId) return null; const executorType = env?.executor_type ?? null; const ariaLabel = computeAriaLabel(isPreparing, status); return ( <> {/* Real
); } function computeAriaLabel( preparing: boolean, status: { label: string; tone: StatusTone } | null, ): string { if (preparing) return "Executor settings, preparing environment"; if (status) return `Executor settings, environment ${status.label}`; return "Executor settings"; } function ExecutorButtonIcon({ executorType, preparing, }: { executorType: string | null; preparing: boolean; }) { if (preparing) { return ( ); } if (!executorType) { return ; } const { Icon, testId } = getExecutorStatusIcon(executorType, false); return ; } const DOT_CLASSES: Record = { running: "bg-green-500", stopped: "bg-zinc-500", warn: "bg-amber-500", error: "bg-red-500", neutral: "bg-muted-foreground", }; function ExecutorStatusDot({ status, loading, }: { status: { label: string; tone: StatusTone } | null; loading: boolean; }) { const tone = status?.tone ?? "neutral"; const label = status?.label ?? "not created"; return (