import { HelpTooltip } from "@/components/HelpTooltip"; import { Checkbox } from "@/components/ui/checkbox"; import { Label } from "@/components/ui/label"; import { Cross2Icon, MagicWandIcon, PaperPlaneIcon, ReloadIcon, } from "@radix-ui/react-icons"; import { useMutation } from "@tanstack/react-query"; import { useCredentialGetter } from "@/hooks/useCredentialGetter"; import { getClient } from "@/api/AxiosClient"; import { CodeEditor } from "@/routes/workflows/components/CodeEditor"; import { helpTooltips } from "@/routes/workflows/editor/helpContent"; import { useMemo, useState } from "react"; import { AutoResizingTextarea } from "../AutoResizingTextarea/AutoResizingTextarea"; import { Button } from "../ui/button"; import { AxiosError } from "axios"; import { toast } from "../ui/use-toast"; import { cn } from "@/util/utils"; type Props = { value: string; onChange: (value: string) => void; suggestionContext: Record; exampleValue: Record; }; function WorkflowDataSchemaInputGroup({ value, onChange, suggestionContext, exampleValue, }: Props) { const credentialGetter = useCredentialGetter(); const [generateWithAIActive, setGenerateWithAIActive] = useState(false); const [generateWithAIPrompt, setGenerateWithAIPrompt] = useState(""); function computeJsonError( jsonText: string, ): { message: string; line?: number; column?: number } | null { try { JSON.parse(jsonText); return null; } catch (e) { const message = e instanceof Error ? e.message : "Invalid JSON"; // Try to extract position and compute line/column for friendlier feedback const match = message.match(/position\s+(\d+)/i); if (!match) { return { message }; } const pos = Number(match[1]); if (Number.isNaN(pos)) { return { message }; } let line = 1; let col = 1; for (let i = 0; i < Math.min(pos, jsonText.length); i++) { if (jsonText[i] === "\n") { line += 1; col = 1; } else { col += 1; } } return { message, line, column: col }; } } const jsonError = useMemo(() => { if (value === "null") return null; return computeJsonError(value); }, [value]); const getDataSchemaSuggestionMutation = useMutation({ mutationFn: async () => { const client = await getClient(credentialGetter); return client.post<{ output: Record }>( "/suggest/data_schema", { input: generateWithAIPrompt, context: suggestionContext, }, ); }, onSuccess: (response) => { onChange(JSON.stringify(response.data.output, null, 2)); }, onError: (error: AxiosError) => { toast({ variant: "destructive", title: "Could not generate the data schema", description: error.message ?? "There was an error generating data schema", }); }, }); return (
{ onChange( checked ? JSON.stringify(exampleValue, null, 2) : "null", ); }} />
{value !== "null" && !generateWithAIActive && ( )}
{value !== "null" && (
{generateWithAIActive ? (
{ setGenerateWithAIActive(false); setGenerateWithAIPrompt(""); }} /> { setGenerateWithAIPrompt(event.target.value); }} placeholder="Describe how you want your output formatted" /> {getDataSchemaSuggestionMutation.isPending ? ( ) : ( { getDataSchemaSuggestionMutation.mutate(); }} /> )}
) : null}
{jsonError && (
{jsonError.line && jsonError.column ? `Invalid JSON (${jsonError.line}:${jsonError.column}) — ${jsonError.message}` : `Invalid JSON — ${jsonError.message}`}
)}
)}
); } export { WorkflowDataSchemaInputGroup };