import React, { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; interface RecursiveConfigProps { data: any; labels: Record; path?: string; onChange: (path: string, val: any) => void; } const isPrimitive = (v: any) => ['string', 'number', 'boolean'].includes(typeof v) || v === null; const PrimitiveArrayEditor: React.FC<{ value: any[]; path: string; onChange: (next: any[]) => void; }> = ({ value, path, onChange }) => { const [draft, setDraft] = useState(''); const [selected, setSelected] = useState(''); const suggestions = useMemo(() => { // 基础建议项:从当前值推导 + 针对常见配置路径补充 const base = new Set(value.map((v) => String(v))); if (path.includes('tools') || path.includes('tool')) { ['read', 'write', 'edit', 'exec', 'process', 'message', 'nodes', 'memory_search'].forEach((x) => base.add(x)); } if (path.includes('channels')) { ['telegram', 'discord', 'whatsapp', 'slack', 'signal'].forEach((x) => base.add(x)); } return Array.from(base).filter(Boolean); }, [value, path]); const addValue = (v: string) => { const val = v.trim(); if (!val) return; if (value.some((x) => String(x) === val)) return; onChange([...value, val]); }; const removeAt = (idx: number) => { onChange(value.filter((_, i) => i !== idx)); }; return (
{value.length === 0 && (empty)} {value.map((item, idx) => ( {String(item)} ))}
setDraft(e.target.value)} placeholder="输入新值后添加" className="w-full bg-zinc-950 border border-zinc-800 rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-indigo-500" /> {suggestions.map((s) => (
); }; const RecursiveConfig: React.FC = ({ data, labels, path = '', onChange }) => { const { t } = useTranslation(); if (typeof data !== 'object' || data === null) return null; return (
{Object.entries(data).map(([key, value]) => { const currentPath = path ? `${path}.${key}` : key; const label = labels[key] || key.replace(/_/g, ' '); if (Array.isArray(value)) { const allPrimitive = value.every(isPrimitive); return (
{label} {currentPath}
{allPrimitive ? ( onChange(currentPath, next)} /> ) : (