import React, { useState, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { Plus, Trash2, Save } from "lucide-react"; import { toast } from "sonner"; import { useOpenClawTools, useSaveOpenClawTools } from "@/hooks/useOpenClaw"; import { extractErrorMessage } from "@/utils/errorUtils"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import type { OpenClawToolsConfig } from "@/types"; interface ListItem { id: string; value: string; } const PROFILE_OPTIONS = ["default", "strict", "permissive", "custom"]; const ToolsPanel: React.FC = () => { const { t } = useTranslation(); const { data: toolsData, isLoading } = useOpenClawTools(); const saveToolsMutation = useSaveOpenClawTools(); const [config, setConfig] = useState({}); const [allowList, setAllowList] = useState([]); const [denyList, setDenyList] = useState([]); useEffect(() => { if (toolsData) { setConfig(toolsData); setAllowList( (toolsData.allow ?? []).map((v) => ({ id: crypto.randomUUID(), value: v, })), ); setDenyList( (toolsData.deny ?? []).map((v) => ({ id: crypto.randomUUID(), value: v, })), ); } }, [toolsData]); const handleSave = async () => { try { const { profile, allow, deny, ...other } = config; const newConfig: OpenClawToolsConfig = { ...other, profile: config.profile, allow: allowList.map((item) => item.value).filter((s) => s.trim()), deny: denyList.map((item) => item.value).filter((s) => s.trim()), }; await saveToolsMutation.mutateAsync(newConfig); toast.success(t("openclaw.tools.saveSuccess")); } catch (error) { const detail = extractErrorMessage(error); toast.error(t("openclaw.tools.saveFailed"), { description: detail || undefined, }); } }; const updateListItem = ( setList: React.Dispatch>, index: number, value: string, ) => { setList((prev) => prev.map((item, i) => (i === index ? { ...item, value } : item)), ); }; const removeListItem = ( setList: React.Dispatch>, index: number, ) => { setList((prev) => prev.filter((_, i) => i !== index)); }; if (isLoading) { return (
{t("common.loading")}
); } return (

{t("openclaw.tools.description")}

{/* Profile selector */}
{/* Allow list */}
{allowList.map((item, index) => (
updateListItem(setAllowList, index, e.target.value) } placeholder={t("openclaw.tools.patternPlaceholder")} className="font-mono text-xs" />
))}
{/* Deny list */}
{denyList.map((item, index) => (
updateListItem(setDenyList, index, e.target.value) } placeholder={t("openclaw.tools.patternPlaceholder")} className="font-mono text-xs" />
))}
{/* Save button */}
); }; export default ToolsPanel;