({ isOpen, onClose, systemPrompt, agentName, agentId, onSystemPromptChange })
| 87 | }; |
| 88 | |
| 89 | const SensorModal: React.FC<SensorModalProps> = ({ isOpen, onClose, systemPrompt, agentName, agentId, onSystemPromptChange }) => { |
| 90 | const [streams, setStreams] = useState<StreamState>(() => StreamManager.getCurrentState()); |
| 91 | const [editedPrompt, setEditedPrompt] = useState(systemPrompt); |
| 92 | const [availableAgents, setAvailableAgents] = useState<{ id: string; name: string }[]>([]); |
| 93 | const [isPromptExpanded, setIsPromptExpanded] = useState(false); |
| 94 | const textareaRef = useRef<HTMLTextAreaElement>(null); |
| 95 | |
| 96 | // Listen to stream state changes |
| 97 | useEffect(() => { |
| 98 | if (!isOpen) return; |
| 99 | const handleStreamUpdate = (newState: StreamState) => setStreams(newState); |
| 100 | StreamManager.addListener(handleStreamUpdate); |
| 101 | return () => StreamManager.removeListener(handleStreamUpdate); |
| 102 | }, [isOpen]); |
| 103 | |
| 104 | // Load available agents for memory sensor dropdowns |
| 105 | useEffect(() => { |
| 106 | if (!isOpen) return; |
| 107 | const loadAgents = async () => { |
| 108 | try { |
| 109 | const agents = await listAgents(); |
| 110 | setAvailableAgents(agents.map(a => ({ id: a.id, name: a.name }))); |
| 111 | } catch (error) { |
| 112 | console.error('Failed to load agents:', error); |
| 113 | } |
| 114 | }; |
| 115 | loadAgents(); |
| 116 | }, [isOpen]); |
| 117 | |
| 118 | // Reset edited prompt when modal opens or systemPrompt changes |
| 119 | useEffect(() => { |
| 120 | setEditedPrompt(systemPrompt); |
| 121 | }, [systemPrompt, isOpen]); |
| 122 | |
| 123 | // Insert sensor variable at cursor position |
| 124 | const insertSystemPromptText = (text: string) => { |
| 125 | if (!textareaRef.current) return; |
| 126 | const { selectionStart, selectionEnd, value } = textareaRef.current; |
| 127 | const newPrompt = `${value.substring(0, selectionStart)} ${text} ${value.substring(selectionEnd)}`; |
| 128 | setEditedPrompt(newPrompt); |
| 129 | setTimeout(() => { |
| 130 | textareaRef.current?.focus(); |
| 131 | const newPos = selectionStart + text.length + 2; |
| 132 | textareaRef.current?.setSelectionRange(newPos, newPos); |
| 133 | }, 0); |
| 134 | }; |
| 135 | |
| 136 | // Handle modal close with save |
| 137 | const handleClose = () => { |
| 138 | if (onSystemPromptChange && editedPrompt !== systemPrompt) { |
| 139 | onSystemPromptChange(editedPrompt); |
| 140 | } |
| 141 | onClose(); |
| 142 | }; |
| 143 | |
| 144 | if (!isOpen) return null; |
| 145 | |
| 146 | return ( |
nothing calls this directly
no test coverage detected