/* Copyright 2026 Marimo. All rights reserved. */ /* oxlint-disable typescript/no-explicit-any */ import { useAtomValue } from "jotai"; import { Spinner } from "@/components/icons/spinner"; import { Button } from "@/components/ui/button"; import { toast } from "@/components/ui/use-toast"; import { NoKernelConnectedError, prettyError } from "@/utils/errors"; import { Logger } from "@/utils/Logger"; import { useConnectToRuntime } from "../runtime/config"; import { store } from "../state/jotai"; import { isConnectingAtom } from "./connection"; import type { EditRequests, RequestKey, RunRequests } from "./types"; export function createErrorToastingRequests( delegate: EditRequests & RunRequests, ): EditRequests & RunRequests { const MESSAGES: Record = { sendComponentValues: "Failed update value", sendModelValue: "Failed to update model value", sendInstantiate: "Failed to instantiate", sendFunctionRequest: "Failed to send function request", sendRestart: "Failed to restart", sendDocumentTransaction: "Failed to sync document transaction", sendRun: "Failed to run", sendRunScratchpad: "Failed to run scratchpad", sendRename: "Failed to rename", sendSave: "Failed to save", sendCopy: "Failed to copy", sendInterrupt: "Failed to interrupt", sendShutdown: "Failed to shutdown", sendFormat: "Failed to format", sendDeleteCell: "Failed to delete cell", sendCodeCompletionRequest: "Failed to complete code", saveUserConfig: "Failed to save user config", saveAppConfig: "Failed to save app config", saveCellConfig: "Failed to save cell config", sendStdin: "Failed to send stdin", readCode: "Failed to read code", readSnippets: "Failed to fetch snippets", previewDatasetColumn: "Failed to fetch data sources", previewSQLTable: "Failed to fetch SQL table", previewSQLTableList: "Failed to fetch SQL table list", previewSQLSchemaList: "Failed to fetch SQL schema list", previewDataSourceConnection: "Failed to preview data source connection", validateSQL: "Failed to validate SQL", openFile: "Failed to open file", getUsageStats: "", // No toast sendListFiles: "Failed to list files", sendSearchFiles: "Failed to search files", sendPdb: "Failed to start debug session", sendCreateFileOrFolder: "Failed to create file or folder", sendDeleteFileOrFolder: "Failed to delete file or folder", sendCopyFileOrFolder: "Failed to duplicate file or folder", sendRenameFileOrFolder: "Failed to rename file or folder", sendUpdateFile: "Failed to update file", sendFileDetails: "Failed to get file details", openTutorial: "Failed to open tutorial", sendInstallMissingPackages: "Failed to install missing packages", getRecentFiles: "Failed to get recent files", getWorkspaceFiles: "Failed to get workspace files", getRunningNotebooks: "Failed to get running notebooks", shutdownSession: "Failed to shutdown session", exportAsHTML: "Failed to export HTML", exportAsIPYNB: "Failed to export ipynb", exportAsMarkdown: "Failed to export Markdown", exportAsPDF: "Failed to export PDF", autoExportAsHTML: "", // No toast autoExportAsMarkdown: "", // No toast autoExportAsIPYNB: "", // No toast updateCellOutputs: "", // No toast addPackage: "Failed to add package", removePackage: "Failed to remove package", getPackageList: "Failed to get package list", getDependencyTree: "Failed to get dependency tree", listSecretKeys: "Failed to fetch secrets", writeSecret: "Failed to write secret", invokeAiTool: "Failed to invoke AI tool", clearCache: "Failed to clear cache", getCacheInfo: "", // No toast listStorageEntries: "Failed to list storage entries", downloadStorage: "Failed to download storage entry", }; const handlers = {} as EditRequests & RunRequests; for (const [key, handler] of Object.entries(delegate)) { const keyString = key as RequestKey; handlers[keyString] = async (...args: any[]) => { try { return await handler(...args); } catch (error) { // Special handling for NoKernelConnectedError error if (error instanceof NoKernelConnectedError) { // If we are connecting to a kernel, don't show the toast const isConnecting = store.get(isConnectingAtom); if (isConnecting) { return; } const toastId = toast({ title: "Kernel Not Connected", description: "You need to connect to a kernel to perform this action.", variant: "default", action: toastId.dismiss()} />, }); Logger.error(`Failed to handle request: ${key}`, error); // Rethrow the error so that the caller can handle it throw error; } const title = MESSAGES[keyString]; const message = prettyError(error); if (title) { toast({ title: title, description: message, variant: "danger", }); } Logger.error(`Failed to handle request: ${key}`, error); // Rethrow the error so that the caller can handle it throw error; } }; } return handlers; } export const ConnectButton: React.FC<{ onConnect: () => void }> = ({ onConnect, }) => { const connectToRuntime = useConnectToRuntime(); const isConnecting = useAtomValue(isConnectingAtom); return ( ); };