/* Copyright 2026 Marimo. All rights reserved. */ import type { UIMessage } from "ai"; import React, { Suspense } from "react"; import { z } from "zod"; import { createPlugin } from "@/plugins/core/builder"; import { rpc } from "@/plugins/core/rpc"; import { Arrays } from "@/utils/arrays"; import type { SendMessageRequest } from "./types"; const LazyChatbot = React.lazy(() => import("./chat-ui").then((m) => ({ default: m.Chatbot })), ); // oxlint-disable-next-line typescript/consistent-type-definitions export type PluginFunctions = { get_chat_history: (req: {}) => Promise<{ messages: UIMessage[] }>; delete_chat_history: (req: {}) => Promise; delete_chat_message: (req: { index: number }) => Promise; send_prompt: (req: SendMessageRequest) => Promise; }; const messageSchema = z.array( z.object({ id: z.string(), role: z.enum(["system", "user", "assistant"]), content: z.string().nullable(), parts: z.array(z.any()), metadata: z.any().nullable(), }), ); const configSchema = z.object({ max_tokens: z.number().nullable(), temperature: z.number().nullable(), top_p: z.number().nullable(), top_k: z.number().nullable(), frequency_penalty: z.number().nullable(), presence_penalty: z.number().nullable(), }); export const ChatPlugin = createPlugin<{ messages: UIMessage[] }>( "marimo-chatbot", ) .withData( z.object({ prompts: z.array(z.string()).default(Arrays.EMPTY), showConfigurationControls: z.boolean(), maxHeight: z.number().optional(), config: configSchema, allowAttachments: z.union([z.boolean(), z.string().array()]), disabled: z.boolean().default(false), }), ) .withFunctions({ get_chat_history: rpc.input(z.object({})).output( z.object({ messages: messageSchema, }), ), delete_chat_history: rpc.input(z.object({})).output(z.null()), delete_chat_message: rpc .input(z.object({ index: z.number() })) .output(z.null()), send_prompt: rpc .input( z.object({ messages: messageSchema, config: configSchema, }), ) .output(z.unknown()), }) .renderer((props) => ( props.setValue({ messages })} host={props.host} /> ));