import { useState, useEffect, useCallback } from 'react' import { Settings, Bot, Wifi, MessageSquare, Database, Brain, Eye, Terminal, Cpu, Cloud, Radio, BookOpen, Layers, Activity, Thermometer, LayoutDashboard, Save, RotateCcw, RefreshCw, Plus, Trash2, ChevronDown, ChevronRight, AlertTriangle, Check, X, Eye as EyeIcon, EyeOff, ExternalLink, Bell, Send } from 'lucide-react' // Types for config sections interface BotConfig { name: string owner: string respond_to_dms: boolean filter_bbs_protocols: boolean } interface ConnectionConfig { type: string serial_port: string tcp_host: string tcp_port: number } interface ResponseConfig { delay_min: number delay_max: number max_length: number max_messages: number } interface HistoryConfig { database: string max_messages_per_user: number conversation_timeout: number auto_cleanup: boolean cleanup_interval_hours: number max_age_days: number } interface MemoryConfig { enabled: boolean window_size: number summarize_threshold: number } interface ContextConfig { enabled: boolean observe_channels: number[] ignore_nodes: string[] max_age: number max_context_items: number } interface CommandsConfig { enabled: boolean prefix: string disabled_commands: string[] custom_commands: Record } interface LLMConfig { backend: string api_key: string base_url: string model: string timeout: number max_response_tokens: number system_prompt: string use_system_prompt: boolean web_search: boolean google_grounding: boolean } interface WeatherConfig { primary: string fallback: string default_location: string openmeteo: { url: string } wttr: { url: string } } interface MeshMonitorConfig { enabled: boolean url: string inject_into_prompt: boolean refresh_interval: number polite_mode: boolean } interface KnowledgeConfig { enabled: boolean backend: string qdrant_host: string qdrant_port: number qdrant_collection: string tei_host: string tei_port: number sparse_host: string sparse_port: number use_sparse: boolean db_path: string top_k: number } interface MeshSourceConfig { name: string type: string url: string api_token: string refresh_interval: number polite_mode: boolean enabled: boolean host?: string port?: number username?: string password?: string topic_root?: string use_tls?: boolean } interface RegionAnchor { name: string lat: number lon: number local_name: string description: string aliases: string[] cities: string[] } interface AlertRulesConfig { infra_offline: boolean infra_recovery: boolean new_router: boolean battery_trend_declining: boolean battery_warning: boolean battery_critical: boolean battery_emergency: boolean battery_warning_threshold: number battery_critical_threshold: number battery_emergency_threshold: number power_source_change: boolean solar_not_charging: boolean sustained_high_util: boolean high_util_threshold: number high_util_hours: number packet_flood: boolean packet_flood_threshold: number infra_single_gateway: boolean feeder_offline: boolean region_total_blackout: boolean mesh_score_alert: boolean mesh_score_threshold: number region_score_alert: boolean region_score_threshold: number } interface MeshIntelligenceConfig { enabled: boolean regions: RegionAnchor[] locality_radius_miles: number offline_threshold_hours: number packet_threshold: number battery_warning_percent: number critical_nodes: string[] alert_channel: number alert_cooldown_minutes: number alert_rules: AlertRulesConfig } interface NWSConfig { enabled: boolean tick_seconds: number areas: string[] severity_min: string user_agent: string } interface EnvironmentalConfig { enabled: boolean nws_zones: string[] nws: NWSConfig swpc: { enabled: boolean } ducting: { enabled: boolean; tick_seconds: number; latitude: number; longitude: number } fires: { enabled: boolean; tick_seconds: number; state: string } avalanche: { enabled: boolean; tick_seconds: number; center_ids: string[]; season_months: number[] } usgs: { enabled: boolean; tick_seconds: number; sites: string[] } traffic: { enabled: boolean; tick_seconds: number; api_key: string; corridors: { name: string; lat: number; lon: number }[] } roads511: { enabled: boolean; tick_seconds: number; api_key: string; base_url: string; endpoints: string[]; bbox: number[] } firms: { enabled: boolean; tick_seconds: number; map_key: string; source: string; bbox: number[]; day_range: number; confidence_min: string; proximity_km: number } } interface DashboardConfig { enabled: boolean port: number host: string } interface NotificationChannelConfig { id: string type: string enabled: boolean channel_index: number node_ids: string[] smtp_host: string smtp_port: number smtp_user: string smtp_password: string smtp_tls: boolean from_address: string recipients: string[] url: string headers: Record } interface NotificationRuleConfig { name: string categories: string[] min_severity: string channel_ids: string[] override_quiet: boolean } interface NotificationsConfig { enabled: boolean quiet_hours_start: string quiet_hours_end: string dedup_seconds: number channels: NotificationChannelConfig[] rules: NotificationRuleConfig[] } interface AlertCategory { id: string name: string description: string default_severity: string } interface FullConfig { bot: BotConfig connection: ConnectionConfig response: ResponseConfig history: HistoryConfig memory: MemoryConfig context: ContextConfig commands: CommandsConfig llm: LLMConfig weather: WeatherConfig meshmonitor: MeshMonitorConfig knowledge: KnowledgeConfig mesh_sources: MeshSourceConfig[] mesh_intelligence: MeshIntelligenceConfig environmental: EnvironmentalConfig dashboard: DashboardConfig notifications: NotificationsConfig } type SectionKey = keyof FullConfig const SECTIONS: { key: SectionKey; label: string; icon: typeof Settings }[] = [ { key: 'bot', label: 'Bot', icon: Bot }, { key: 'connection', label: 'Connection', icon: Wifi }, { key: 'response', label: 'Response', icon: MessageSquare }, { key: 'history', label: 'History', icon: Database }, { key: 'memory', label: 'Memory', icon: Brain }, { key: 'context', label: 'Context', icon: Eye }, { key: 'commands', label: 'Commands', icon: Terminal }, { key: 'llm', label: 'LLM', icon: Cpu }, { key: 'weather', label: 'Weather', icon: Cloud }, { key: 'meshmonitor', label: 'MeshMonitor', icon: Radio }, { key: 'knowledge', label: 'Knowledge', icon: BookOpen }, { key: 'mesh_sources', label: 'Mesh Sources', icon: Layers }, { key: 'mesh_intelligence', label: 'Intelligence', icon: Activity }, { key: 'environmental', label: 'Environmental', icon: Thermometer }, { key: 'notifications', label: 'Notifications', icon: Bell }, { key: 'dashboard', label: 'Dashboard', icon: LayoutDashboard }, ] // Section descriptions const SECTION_DESCRIPTIONS: Record = { bot: 'Identity and behavior settings for the bot on the mesh network.', connection: 'How MeshAI connects to your Meshtastic radio.', response: 'Controls how quickly and how much the bot responds on the mesh.', history: 'Conversation history storage and cleanup.', memory: 'Short-term conversation memory management. Controls how the bot maintains context within a conversation.', context: 'Passive channel monitoring. The bot listens to mesh channels and uses recent messages as context when responding.', commands: 'Mesh commands available via the configured prefix. Toggle individual commands on or off.', llm: 'AI model configuration. MeshAI uses an LLM to understand questions and generate responses.', weather: 'Weather data for the !weather command. This is separate from NWS environmental alerts.', meshmonitor: 'AIDA MeshMonitor integration. An additional data source for mesh network monitoring.', knowledge: 'Knowledge base for answering questions from stored documents. Connects to Qdrant vector database or local SQLite.', mesh_sources: 'Data sources for mesh network information. MeshAI can pull data from multiple sources simultaneously and merge them into a unified view.', mesh_intelligence: 'Advanced mesh analysis: health scoring, region management, and automated alerting. The intelligence engine monitors your mesh and detects problems automatically.', environmental: 'Live environmental data feeds for situational awareness. Each feed polls a public or authenticated API for real-time conditions affecting your area.', notifications: 'Alert delivery system. Configure where alerts get sent (mesh, email, webhooks) and which conditions trigger them.', dashboard: "Web dashboard settings. You're looking at it right now.", } // Available commands with descriptions const AVAILABLE_COMMANDS = [ { name: 'help', description: 'Show available commands and usage' }, { name: 'health', description: 'Mesh network health overview with status dots' }, { name: 'status', description: 'Quick mesh status summary' }, { name: 'region', description: 'List regions or get detailed region breakdown' }, { name: 'neighbors', description: 'Show top infrastructure neighbors with signal quality' }, { name: 'ping', description: 'Test bot responsiveness' }, { name: 'clear', description: 'Clear your conversation history' }, { name: 'reset', description: 'Reset conversation context' }, { name: 'sub', description: 'Subscribe to scheduled reports or alerts' }, { name: 'unsub', description: 'Remove a subscription' }, { name: 'mysubs', description: 'List your active subscriptions' }, { name: 'alerts', description: 'Active NWS weather alerts for mesh area' }, { name: 'solar', description: 'Space weather and HF propagation conditions' }, { name: 'hf', description: 'HF radio propagation (alias for !solar)' }, { name: 'fire', description: 'Active wildfires near the mesh' }, { name: 'avy', description: 'Avalanche advisories for configured zones' }, { name: 'hotspots', description: 'NASA FIRMS satellite fire detections' }, { name: 'streams', description: 'USGS stream gauge readings' }, { name: 'roads', description: 'Road conditions and closures' }, { name: 'traffic', description: 'Traffic flow on monitored corridors' }, ] // US States for dropdown const US_STATES = [ { value: 'US-AL', label: 'Alabama' }, { value: 'US-AK', label: 'Alaska' }, { value: 'US-AZ', label: 'Arizona' }, { value: 'US-AR', label: 'Arkansas' }, { value: 'US-CA', label: 'California' }, { value: 'US-CO', label: 'Colorado' }, { value: 'US-CT', label: 'Connecticut' }, { value: 'US-DE', label: 'Delaware' }, { value: 'US-FL', label: 'Florida' }, { value: 'US-GA', label: 'Georgia' }, { value: 'US-HI', label: 'Hawaii' }, { value: 'US-ID', label: 'Idaho' }, { value: 'US-IL', label: 'Illinois' }, { value: 'US-IN', label: 'Indiana' }, { value: 'US-IA', label: 'Iowa' }, { value: 'US-KS', label: 'Kansas' }, { value: 'US-KY', label: 'Kentucky' }, { value: 'US-LA', label: 'Louisiana' }, { value: 'US-ME', label: 'Maine' }, { value: 'US-MD', label: 'Maryland' }, { value: 'US-MA', label: 'Massachusetts' }, { value: 'US-MI', label: 'Michigan' }, { value: 'US-MN', label: 'Minnesota' }, { value: 'US-MS', label: 'Mississippi' }, { value: 'US-MO', label: 'Missouri' }, { value: 'US-MT', label: 'Montana' }, { value: 'US-NE', label: 'Nebraska' }, { value: 'US-NV', label: 'Nevada' }, { value: 'US-NH', label: 'New Hampshire' }, { value: 'US-NJ', label: 'New Jersey' }, { value: 'US-NM', label: 'New Mexico' }, { value: 'US-NY', label: 'New York' }, { value: 'US-NC', label: 'North Carolina' }, { value: 'US-ND', label: 'North Dakota' }, { value: 'US-OH', label: 'Ohio' }, { value: 'US-OK', label: 'Oklahoma' }, { value: 'US-OR', label: 'Oregon' }, { value: 'US-PA', label: 'Pennsylvania' }, { value: 'US-RI', label: 'Rhode Island' }, { value: 'US-SC', label: 'South Carolina' }, { value: 'US-SD', label: 'South Dakota' }, { value: 'US-TN', label: 'Tennessee' }, { value: 'US-TX', label: 'Texas' }, { value: 'US-UT', label: 'Utah' }, { value: 'US-VT', label: 'Vermont' }, { value: 'US-VA', label: 'Virginia' }, { value: 'US-WA', label: 'Washington' }, { value: 'US-WV', label: 'West Virginia' }, { value: 'US-WI', label: 'Wisconsin' }, { value: 'US-WY', label: 'Wyoming' }, ] // InfoButton component function InfoButton({ info, link, linkText = 'Learn more' }: { info: string; link?: string; linkText?: string }) { const [open, setOpen] = useState(false) return (
{open && ( <>
setOpen(false)} /> )}
) } // Section description component function SectionDescription({ text }: { text: string }) { return (

{text}

) } // Form components function TextInput({ label, value, onChange, type = 'text', placeholder = '', helper = '', info = '', infoLink = '' }: { label: string value: string onChange: (v: string) => void type?: string placeholder?: string helper?: string info?: string infoLink?: string }) { const [showPassword, setShowPassword] = useState(false) const isPassword = type === 'password' return (
onChange(e.target.value)} placeholder={placeholder} className="w-full px-3 py-2 bg-[#0a0e17] border border-[#1e2a3a] rounded text-sm text-slate-200 font-mono focus:outline-none focus:border-accent placeholder-slate-600" /> {isPassword && ( )}
{helper &&

{helper}

}
) } function NumberInput({ label, value, onChange, min, max, step = 1, helper = '', info = '', infoLink = '' }: { label: string value: number onChange: (v: number) => void min?: number max?: number step?: number helper?: string info?: string infoLink?: string }) { return (
onChange(Number(e.target.value))} min={min} max={max} step={step} className="w-full px-3 py-2 bg-[#0a0e17] border border-[#1e2a3a] rounded text-sm text-slate-200 font-mono focus:outline-none focus:border-accent" /> {helper &&

{helper}

}
) } function Toggle({ label, checked, onChange, helper = '', info = '', infoLink = '' }: { label: string checked: boolean onChange: (v: boolean) => void helper?: string info?: string infoLink?: string }) { return (
{label} {info && } {helper &&

{helper}

}
) } function SelectInput({ label, value, onChange, options, helper = '', info = '', infoLink = '' }: { label: string value: string onChange: (v: string) => void options: { value: string; label: string }[] helper?: string info?: string infoLink?: string }) { return (
{helper &&

{helper}

}
) } function TextArea({ label, value, onChange, rows = 4, helper = '', info = '', infoLink = '' }: { label: string value: string onChange: (v: string) => void rows?: number helper?: string info?: string infoLink?: string }) { return (