/* Copyright 2026 Marimo. All rights reserved. */
import { useAtom, useAtomValue } from "jotai";
import { RefreshCwIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { useRestartKernel } from "@/components/editor/actions/useRestartKernel";
import {
isConnectedAtom,
startupProgressAtom,
} from "@/core/network/connection";
import { connectionNoticeAtom } from "@/core/network/connection-notice";
import type { DisplayConnectionNotice } from "@/core/network/useConnectionNotice";
import {
preparationAtom,
sandboxActionsAtom,
sandboxAtom,
sandboxSyncAtom,
sandboxSyncOperationAtom,
} from "@/core/packages/sandbox-state";
import { cn } from "@/utils/cn";
import { StartupOutput } from "../../alerts/startup-output";
import { ConnectionDetails } from "../../alerts/connection-details";
import { usePanelSection } from "./panel-context";
import { runtimeDetailsExpandedAtom } from "./runtime-details-state";
function SandboxRecovery({ notice }: { notice: DisplayConnectionNotice }) {
const sandbox = useAtomValue(sandboxAtom);
const actions = useAtomValue(sandboxActionsAtom);
const sync = useAtomValue(sandboxSyncAtom);
if (notice.pending || notice.ready) {
return null;
}
return (
<>
{notice.kind === "sync" && sync.kind === "restart-required" ? (
) : (
)}
{sandbox?.manifest == null && (
A manifest will be available once this new notebook starts.
)}
>
);
}
function SandboxRestart() {
const restartKernel = useRestartKernel();
return (
);
}
function RuntimeNoticeDetails({ notice }: { notice: DisplayConnectionNotice }) {
return (
{notice.sandbox && }
);
}
function SandboxSyncDetails({
notice,
}: {
notice: DisplayConnectionNotice | null;
}) {
const operation = useAtomValue(sandboxSyncOperationAtom);
if (!operation && !notice) {
return null;
}
return (
{notice ? (
) : (
Environment synced
)}
);
}
export function RuntimeDetails() {
const section = usePanelSection();
const sandbox = Boolean(useAtomValue(sandboxAtom)?.backend);
const connected = useAtomValue(isConnectedAtom);
const connectionNotice = useAtomValue(connectionNoticeAtom);
const notice: DisplayConnectionNotice | null = connectionNotice && {
...connectionNotice,
ready: false,
};
const preparation = useAtomValue(preparationAtom);
const progress = useAtomValue(startupProgressAtom);
const [expanded, setExpanded] = useAtom(runtimeDetailsExpandedAtom);
const startup: DisplayConnectionNotice | null =
notice?.kind === "startup"
? notice
: preparation || progress || (connected && !sandbox)
? {
kind: "startup",
sandbox,
title: "Notebook started",
description: "The notebook is ready to run.",
pending: false,
ready: true,
error: null,
}
: null;
return (
setExpanded(true)}
onFocusCapture={() => setExpanded(true)}
>
{notice?.kind === "connection" && (
)}
{startup && }
{sandbox && connected && (
)}
{sandbox && connected && (!notice || notice.pending) && (
)}
{!notice && !startup && !sandbox && (
Not connected to a runtime.
)}
);
}
function SandboxActions() {
const sandbox = useAtomValue(sandboxAtom);
const actions = useAtomValue(sandboxActionsAtom);
const pending = useAtomValue(sandboxSyncAtom).kind === "running";
return (
);
}