/* Copyright 2026 Marimo. All rights reserved. */ import { useAtomValue, useSetAtom, useStore } from "jotai"; import { ChevronDownIcon, SparklesIcon, WrenchIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Tooltip } from "@/components/ui/tooltip"; import { aiCompletionCellAtom } from "@/core/ai/state"; import { notebookAtom, useCellActions } from "@/core/cells/cells"; import type { CellId } from "@/core/cells/ids"; import { aiEnabledAtom } from "@/core/config/config"; import { getAutoFixes } from "@/core/errors/errors"; import type { MarimoError } from "@/core/kernel/messages"; import { cn } from "@/utils/cn"; import { type FixMode, useFixMode } from "./fix-mode"; export const AutoFixButton = ({ errors, cellId, className, }: { errors: MarimoError[]; cellId: CellId; className?: string; }) => { const store = useStore(); const { createNewCell } = useCellActions(); const aiEnabled = useAtomValue(aiEnabledAtom); const autoFixes = errors.flatMap((error) => getAutoFixes(error, { aiEnabled }), ); const setAiCompletionCell = useSetAtom(aiCompletionCellAtom); if (autoFixes.length === 0) { return null; } // TODO: Add a dropdown menu with the auto-fixes, when we need to support // multiple fixes. const firstFix = autoFixes[0]; const handleFix = (triggerFix: boolean) => { const editorView = store.get(notebookAtom).cellHandles[cellId].current?.editorView; firstFix.onFix({ addCodeBelow: (code: string) => { createNewCell({ cellId: cellId, autoFocus: false, before: false, code: code, }); }, editor: editorView, cellId: cellId, aiFix: { setAiCompletionCell, triggerFix, }, }); // Focus the editor editorView?.focus(); }; return (
{firstFix.fixType === "ai" ? ( handleFix(false)} applyAutofix={() => handleFix(true)} /> ) : ( )}
); }; const PromptIcon = SparklesIcon; const AutofixIcon = WrenchIcon; const PromptTitle = "Suggest a prompt"; const AutofixTitle = "Fix with AI"; export const AIFixButton = ({ tooltip, openPrompt, applyAutofix, }: { tooltip: string; openPrompt: () => void; applyAutofix: () => void; }) => { const { fixMode, setFixMode } = useFixMode(); return (
{ setFixMode(fixMode === "prompt" ? "autofix" : "prompt"); }} >
); }; const AiModeItem = ({ mode }: { mode: FixMode }) => { const icon = mode === "prompt" ? ( ) : ( ); const title = mode === "prompt" ? PromptTitle : AutofixTitle; const description = mode === "prompt" ? "Edit the prompt before applying" : "Apply AI fixes automatically"; return (
{icon}
{title} {description}
); };