import React, { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { TriangleAlert } from "lucide-react"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import type { OpenClawHealthWarning } from "@/types"; interface OpenClawHealthBannerProps { warnings: OpenClawHealthWarning[]; } function getWarningText( code: string, fallback: string, t: ReturnType["t"], ) { switch (code) { case "invalid_tools_profile": return t("openclaw.health.invalidToolsProfile", { defaultValue: "tools.profile contains an unsupported value. OpenClaw currently expects minimal, coding, messaging, or full.", }); case "legacy_agents_timeout": return t("openclaw.health.legacyTimeout", { defaultValue: "agents.defaults.timeout is deprecated. Save the Agents panel to migrate it to timeoutSeconds.", }); case "stringified_env_vars": return t("openclaw.health.stringifiedEnvVars", { defaultValue: "env.vars should be an object, but the current value looks stringified or malformed.", }); case "stringified_env_shell_env": return t("openclaw.health.stringifiedShellEnv", { defaultValue: "env.shellEnv should be an object, but the current value looks stringified or malformed.", }); case "config_parse_failed": return t("openclaw.health.parseFailed", { defaultValue: "openclaw.json could not be parsed as valid JSON5. Fix the file before editing it here.", }); default: return fallback; } } const OpenClawHealthBanner: React.FC = ({ warnings, }) => { const { t } = useTranslation(); const items = useMemo( () => warnings.map((warning) => ({ ...warning, text: getWarningText(warning.code, warning.message, t), })), [t, warnings], ); if (warnings.length === 0) { return null; } return (
{t("openclaw.health.title", { defaultValue: "OpenClaw config warnings detected", })}
    {items.map((warning) => (
  • {warning.text} {warning.path ? ` (${warning.path})` : ""}
  • ))}
); }; export default OpenClawHealthBanner;