import { Component, For, Show, createMemo, createSignal } from "solid-js" import type { Instance } from "../types/instance" import { useOptionalInstanceMetadataContext } from "../lib/contexts/instance-metadata-context" import InstanceServiceStatus from "./instance-service-status" import { useI18n } from "../lib/i18n" import { showConfirmDialog } from "../stores/alerts" import { disposeInstance } from "../stores/instances" import { showToastNotification } from "../lib/notifications" import { getLogger } from "../lib/logger" interface InstanceInfoProps { instance: Instance compact?: boolean showDisposeButton?: boolean } const log = getLogger("actions") const InstanceInfo: Component = (props) => { const { t } = useI18n() const metadataContext = useOptionalInstanceMetadataContext() const isLoadingMetadata = metadataContext?.isLoading ?? (() => false) const instanceAccessor = metadataContext?.instance ?? (() => props.instance) const metadataAccessor = metadataContext?.metadata ?? (() => props.instance.metadata) const [isDisposing, setIsDisposing] = createSignal(false) const currentInstance = () => instanceAccessor() const metadata = () => metadataAccessor() const binaryVersion = () => currentInstance().binaryVersion || metadata()?.version const environmentVariables = () => currentInstance().environmentVariables const environmentEntries = createMemo(() => { const env = environmentVariables() return env ? Object.entries(env) : [] }) const disposeEnabled = createMemo(() => Boolean(currentInstance()?.client) && !isDisposing()) const handleDisposeInstance = async () => { if (!disposeEnabled()) return const confirmed = await showConfirmDialog(t("infoView.dispose.confirm.message"), { title: t("infoView.dispose.confirm.title"), variant: "warning", confirmLabel: t("infoView.dispose.confirm.confirmLabel"), cancelLabel: t("infoView.dispose.confirm.cancelLabel"), }) if (!confirmed) return setIsDisposing(true) try { const ok = await disposeInstance(currentInstance().id) if (ok) { showToastNotification({ message: t("infoView.dispose.toast.success"), variant: "success", duration: 8000, }) } else { showToastNotification({ message: t("infoView.dispose.toast.error"), variant: "error", }) } } catch (error) { log.error("Failed to dispose instance", error) showToastNotification({ message: t("infoView.dispose.toast.error"), variant: "error", }) } finally { setIsDisposing(false) } } return (

{t("instanceInfo.title")}

{t("instanceInfo.labels.folder")}
{currentInstance().folder}
{(project) => ( <>
{t("instanceInfo.labels.project")}
{project().id}
{t("instanceInfo.labels.versionControl")}
{project().vcs}
)}
{t("instanceInfo.labels.opencodeVersion")}
v{binaryVersion()}
{t("instanceInfo.labels.binaryPath")}
{currentInstance().binaryPath}
0}>
{t("instanceInfo.labels.environmentVariables", { count: environmentEntries().length })}
{([key, value]) => (
{key} {value}
)}
{t("instanceInfo.loading")}
{t("instanceInfo.server.title")}
{t("instanceInfo.server.port")} {currentInstance().port}
{t("instanceInfo.server.pid")} {currentInstance().pid}
{t("instanceInfo.server.status")}
{currentInstance().status}
) } export default InstanceInfo