"use client"; import { CalendarClock, ChevronDown, ChevronRight, ListOrdered, Target } from "lucide-react"; import { useState } from "react"; import { describeCron } from "@/lib/automations/describe-cron"; interface DraftTrigger { type: string; params: Record; static_inputs: Record; enabled: boolean; } interface DraftPlanStep { step_id: string; action: string; when?: string | null; } interface AutomationDraft { name: string; description?: string | null; definition: { goal?: string | null; plan: DraftPlanStep[]; }; triggers: DraftTrigger[]; } interface AutomationDraftPreviewProps { draft: AutomationDraft; /** Full unmodified args dict — surfaced as the "raw JSON" escape hatch. */ raw: Record; } /** * Structured preview of a drafted automation rendered inside the chat * approval card. * * Three layers, top to bottom: * 1. Name + description (and goal when present). * 2. Triggers — humanised cron string + timezone + static_inputs hint. * 3. Plan steps — ordered list of ``step_id → action``. * * A "View raw JSON" toggle reveals the full payload for power users who * want to inspect every field; it's collapsed by default so the card * stays scannable for the common case. */ export function AutomationDraftPreview({ draft, raw }: AutomationDraftPreviewProps) { const [showRaw, setShowRaw] = useState(false); return (

{draft.name}

{draft.description &&

{draft.description}

}
{draft.definition.goal && (

{draft.definition.goal}

)}
{draft.triggers.length === 0 ? (

No triggers — automation will need one before it can run.

) : (
    {draft.triggers.map((trigger) => (
  • ))}
)}
    {draft.definition.plan.map((step, idx) => (
  1. {idx + 1}
    {step.step_id} {step.action} {step.when && when {step.when}}
  2. ))}
{showRaw && (
					{JSON.stringify(raw, null, 2)}
				
)}
); } /** * Stable key derived from the trigger's identifying fields. Drafts are * static snapshots so collisions only happen if the LLM emits two literally * identical triggers — harmless in practice. */ function triggerKey(trigger: DraftTrigger): string { const cron = typeof trigger.params.cron === "string" ? trigger.params.cron : ""; const tz = typeof trigger.params.timezone === "string" ? trigger.params.timezone : ""; return `${trigger.type}|${cron}|${tz}`; } function TriggerLine({ trigger }: { trigger: DraftTrigger }) { if (trigger.type === "schedule") { const cron = typeof trigger.params.cron === "string" ? trigger.params.cron : undefined; const tz = typeof trigger.params.timezone === "string" ? trigger.params.timezone : "UTC"; const human = cron ? describeCron(cron) : "Schedule"; const staticKeys = Object.keys(trigger.static_inputs ?? {}); return (
{human} · {tz} {!trigger.enabled && ( Disabled )}
{cron && {cron}} {staticKeys.length > 0 && (

Static inputs: {staticKeys.join(", ")}

)}
); } return {trigger.type}; } function Section({ icon: Icon, label, children, }: { icon: typeof Target; label: string; children: React.ReactNode; }) { return (
{label}
{children}
); }