"use client"; import { IconClockHour4 } from "@tabler/icons-react"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import Link from "@/components/routing/app-link"; import { settingsActionClassName } from "@/components/settings/settings-control"; import { useOptionalAppStore } from "@/components/state-provider"; import { formatRelativeTime } from "@/lib/utils"; import type { TaskStatusSummaryLaunchQueue } from "@/lib/types/task-status-summary"; import { buildLaunchQueueViewModel, type LaunchQueueViewModel, } from "@/lib/tasks/launch-queue-view-model"; function reasonLabel( reason: LaunchQueueViewModel["reason"], retrying: boolean, t: (key: string) => string, ): string { switch (reason) { case "session_capacity": return t("task:launchQueueWaitingGlobalCapacity"); case "ownership_unavailable": return t("task:launchQueueOwnershipUnavailable"); case "replay_error": return t(retrying ? "task:launchQueueReplayError" : "task:launchQueueReplayErrorStopped"); } } function retryStatusLabel(view: LaunchQueueViewModel, t: (key: string) => string): string { if (!view.retrying) return t("task:launchQueueRetryStopped"); if (view.reason === "session_capacity") return t("task:launchQueueAutomaticRetry"); return t("task:launchQueueRetryPending"); } function capacityLabel( view: LaunchQueueViewModel, isConnected: boolean, t: (key: string, values?: Record) => string, ): string { if (!view.capacity) { return t( view.retrying ? "task:launchQueueCapacityUnavailable" : "task:launchQueueCapacityUnavailableStopped", ); } let key = "task:launchQueueCapacityStale"; if (view.capacityFreshness === "current") { key = "task:launchQueueCapacity"; } else if (view.capacityFreshness === "stale" && !isConnected) { key = "task:launchQueueCapacityDisconnected"; } return t(key, { inUse: view.capacity.inUse, limit: view.capacity.limit, checkedAt: formatRelativeTime(view.capacity.observedAt), }); } export function LaunchQueueStatus({ queue, isConnected, }: { queue: TaskStatusSummaryLaunchQueue | null | undefined; isConnected?: boolean; }) { const { t } = useTranslation(); const connected = useOptionalAppStore((state) => state.connection.status === "connected", true); const [now, setNow] = useState(() => Date.now()); useEffect(() => { if (!queue) return; const interval = window.setInterval(() => setNow(Date.now()), 1_000); return () => window.clearInterval(interval); }, [queue]); const view = buildLaunchQueueViewModel(queue, { now, isConnected: isConnected ?? connected, }); if (!view) return null; return ; } function LaunchQueueStatusContent({ view, t, isConnected, }: { view: LaunchQueueViewModel; t: (key: string, values?: Record) => string; isConnected: boolean; }) { const destinationLabel = useOptionalAppStore((state) => { if (!view.destinationId) return ""; return ( state.agentProfiles.items.find((profile) => profile.id === view.destinationId)?.label ?? "" ); }, ""); const destination = destinationLabel || t("task:launchQueueUnknownDestination"); const retryLabel = retryStatusLabel(view, t); return (
{t("task:launchQueueIndicator")}
); } export function hasWorkflowParkingMarker( metadata: Record | null | undefined, ): boolean { const marker = metadata?.workflow_parking; if (!marker || typeof marker !== "object" || Array.isArray(marker)) return false; const value = marker as Record; return ( typeof value.stamp === "string" && value.stamp.trim() !== "" && typeof value.parked_at === "string" && value.parked_at.trim() !== "" && typeof value.source_session_id === "string" && value.source_session_id.trim() !== "" ); } export function ParkedSessionNote({ visible }: { visible: boolean }) { const { t } = useTranslation(); if (!visible) return null; return (
{t("task:parkedSessionNote")}
); }