/* Copyright 2026 Marimo. All rights reserved. */ import { type DOMNode, Element, Text } from "html-react-parser"; import { useAtomValue } from "jotai"; import { BugPlayIcon, ChevronDown, ChevronRight, CopyIcon, ExternalLinkIcon, MessageCircleIcon, SearchIcon, } from "lucide-react"; import { type JSX, useState } from "react"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Kbd } from "@/components/ui/kbd"; import { Tooltip } from "@/components/ui/tooltip"; import { getCellEditorView } from "@/core/cells/cells"; import type { CellId } from "@/core/cells/ids"; import { SCRATCH_CELL_ID } from "@/core/cells/ids"; import { toggleBreakpoint } from "@/core/codemirror/cells/debugger-state"; import { insertDebuggerAtLine } from "@/core/codemirror/editing/debugging"; import { aiFeaturesEnabledAtom } from "@/core/config/config"; import { getFeatureFlag } from "@/core/config/feature-flag"; import { getRequestClient } from "@/core/network/requests"; import { isStaticNotebook } from "@/core/static/static-state"; import { isWasm } from "@/core/wasm/utils"; import { renderHTML } from "@/plugins/core/RenderHTML"; import { sanitizeHtml } from "@/plugins/core/sanitize-html"; import { copyToClipboard } from "@/utils/copy"; import { containsMangledLocal, splitMangledLocals, } from "@/utils/local-variables"; import { elementContainsMarimoCellFile, extractAllTracebackInfo, getTracebackInfo, } from "@/utils/traceback"; import { useOpenAiAssistant } from "../chrome/wrapper/useOpenAiAssistant"; import { AIFixButton, buildFixInChatPrompt } from "../errors/auto-fix"; import { MangledSegments } from "../errors/mangled-local-chip"; import { CellLinkTraceback } from "../links/cell-link"; import type { OnRefactorWithAI } from "../Output"; interface Props { cellId: CellId | undefined; traceback: string; onRefactorWithAI?: OnRefactorWithAI; } /** * List of errors due to violations of Marimo semantics. */ export const MarimoTracebackOutput = ({ onRefactorWithAI, traceback, cellId, }: Props): JSX.Element => { const htmlTraceback = renderHTML({ html: traceback, additionalReplacements: [ replaceTracebackFilenames, replaceTracebackPrefix, replaceMangledLocal, ], }); const lastTracebackLine = lastLine(traceback); const aiFeaturesEnabled = useAtomValue(aiFeaturesEnabledAtom); const openAiAssistant = useOpenAiAssistant(); // Get last traceback info const tracebackInfo = extractAllTracebackInfo(traceback)?.at(0); // Don't show in wasm, static notebooks, or scratchpad const showDebugger = tracebackInfo && tracebackInfo.kind === "cell" && !isWasm() && !isStaticNotebook() && cellId !== SCRATCH_CELL_ID; const showAIFix = onRefactorWithAI && aiFeaturesEnabled && !isStaticNotebook(); const showSearch = !isStaticNotebook(); const [isOpen, setIsOpen] = useState(true); const handleRefactorWithAI = (triggerImmediately: boolean) => { onRefactorWithAI?.({ prompt: `My code gives the following error:\n\n${lastTracebackLine}`, triggerImmediately, }); }; const openAISidebar = () => { openAiAssistant({ prompt: buildFixInChatPrompt(cellId, lastTracebackLine), }); }; return (