"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { Play, Loader2, Info } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Form } from "@/components/ui/form"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { buildVariableSchemaFromList } from "@/lib/validation/variable-schema"; import type { ClientScript } from "@/lib/config/serialize"; import { FieldRenderer } from "./field-renderer"; function emptyValueFor(variable: ClientScript["variables"][number]): unknown { if (variable.type === "boolean") return false; if (variable.type === "multiselect") return []; return ""; } /** `initialValues` comes from a previous run's (already-redacted) variables when re-running - * secret fields are deliberately excluded there (their stored value is just "***", not the real * one), so those always fall through to the normal empty/default state and have to be re-entered. */ function defaultValuesFor( script: ClientScript, initialValues?: Record, ): Record { const values: Record = {}; for (const variable of script.variables) { const fromPreviousRun = initialValues && !variable.secret ? initialValues[variable.name] : undefined; values[variable.name] = fromPreviousRun ?? variable.default ?? emptyValueFor(variable); } return values; } export function DynamicForm({ script, initialValues, }: { script: ClientScript; initialValues?: Record; }) { const router = useRouter(); const [submitError, setSubmitError] = useState(null); const schema = buildVariableSchemaFromList(script.variables); const hasSecretVariable = script.variables.some((v) => v.secret); const form = useForm({ resolver: zodResolver(schema), defaultValues: defaultValuesFor(script, initialValues), }); async function onSubmit(values: Record) { setSubmitError(null); const response = await fetch(`/api/scripts/${script.id}/runs`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ variables: values }), }); if (!response.ok) { const data = await response.json().catch(() => ({})); setSubmitError(data.error ?? "Failed to start run"); return; } const data = await response.json(); toast.success(`${script.name} started`); router.push(`/runs/${data.runId}`); } return (
{submitError && ( {submitError} )} {initialValues && ( Pre-filled from a previous run. {hasSecretVariable && " Secret fields aren't carried over and need to be entered again."} )} {script.variables.length === 0 && (

This script takes no parameters.

)} {script.variables.map((variable) => ( ))} ); }