import { CheckCircle2, Circle, TrashIcon } from "lucide-react"; import { Button } from "@/src/components/ui/button"; import { CodeMirrorEditor } from "@/src/components/editor"; import { useState, useCallback } from "react"; import { type ChatMessage } from "@langfuse/shared"; import { usePlaygroundContext } from "../context"; import { type PlaceholderMessageFillIn } from "../types"; import { useNamingConflicts } from "../hooks/useNamingConflicts"; export const MessagePlaceholderComponent: React.FC<{ messagePlaceholder: PlaceholderMessageFillIn; }> = ({ messagePlaceholder }) => { const { updateMessagePlaceholderValue, deleteMessagePlaceholder, promptVariables, messagePlaceholders, } = usePlaygroundContext(); const { name, value, isUsed } = messagePlaceholder; const [error, setError] = useState(null); const { isPlaceholderConflicting } = useNamingConflicts( promptVariables, messagePlaceholders, ); const hasConflict = isPlaceholderConflicting(name); const handleInputChange = useCallback( (jsonString: string) => { try { const parsed = jsonString.trim() === "" ? [] : JSON.parse(jsonString); // Basic validation: must be an array of objects if (!Array.isArray(parsed)) { setError("Input must be an array of objects"); return; } // Check that all items are objects const allObjects = parsed.every( (item) => typeof item === "object" && item !== null && !Array.isArray(item), ); if (!allObjects) { setError("All items must be objects"); return; } // Allow arbitrary objects - no strict role/content validation updateMessagePlaceholderValue(name, parsed as ChatMessage[]); setError(null); } catch { setError("Invalid JSON format"); } }, [name, updateMessagePlaceholderValue], ); const UsedIcon = isUsed ? CheckCircle2 : Circle; const iconColor = isUsed ? "green" : "grey"; return (

{name ? name : "Unnamed placeholder"}

{hasConflict && (

Placeholder name conflicts with variable. Names must be unique.

)} {error &&

{error}

}
); };