UNPKG

@assistant-ui/react

Version:

Typescript/React library for AI Chat

129 lines 5.11 kB
"use client"; import { jsx, jsxs } from "react/jsx-runtime"; import { memo, useMemo } from "react"; import { TextContentPartProvider, useContentPart, useContentPartRuntime, useToolUIs } from "../../context"; import { useMessage, useMessageRuntime } from "../../context/react/MessageContext"; import { ContentPartRuntimeProvider } from "../../context/providers/ContentPartRuntimeProvider"; import { ContentPartPrimitiveText } from "../contentPart/ContentPartText"; import { ContentPartPrimitiveImage } from "../contentPart/ContentPartImage"; import { ContentPartPrimitiveInProgress } from "../contentPart/ContentPartInProgress"; const ToolUIDisplay = ({ Fallback, ...props }) => { const Render = useToolUIs((s) => s.getToolUI(props.toolName)) ?? Fallback; if (!Render) return null; return /* @__PURE__ */ jsx(Render, { ...props }); }; const defaultComponents = { Text: () => /* @__PURE__ */ jsxs("p", { style: { whiteSpace: "pre-line" }, children: [ /* @__PURE__ */ jsx(ContentPartPrimitiveText, {}), /* @__PURE__ */ jsx(ContentPartPrimitiveInProgress, { children: /* @__PURE__ */ jsx("span", { style: { fontFamily: "revert" }, children: " \u25CF" }) }) ] }), Reasoning: () => null, Source: () => null, Image: () => /* @__PURE__ */ jsx(ContentPartPrimitiveImage, {}), File: () => null, Unstable_Audio: () => null }; const MessageContentPartComponent = ({ components: { Text = defaultComponents.Text, Reasoning = defaultComponents.Reasoning, Image = defaultComponents.Image, Source = defaultComponents.Source, File = defaultComponents.File, Unstable_Audio: Audio = defaultComponents.Unstable_Audio, tools = {} } = {} }) => { const contentPartRuntime = useContentPartRuntime(); const part = useContentPart(); const type = part.type; if (type === "tool-call") { const addResult = (result) => contentPartRuntime.addToolResult(result); if ("Override" in tools) return /* @__PURE__ */ jsx(tools.Override, { ...part, addResult }); const Tool = tools.by_name?.[part.toolName] ?? tools.Fallback; return /* @__PURE__ */ jsx(ToolUIDisplay, { ...part, Fallback: Tool, addResult }); } if (part.status.type === "requires-action") throw new Error("Encountered unexpected requires-action status"); switch (type) { case "text": return /* @__PURE__ */ jsx(Text, { ...part }); case "reasoning": return /* @__PURE__ */ jsx(Reasoning, { ...part }); case "source": return /* @__PURE__ */ jsx(Source, { ...part }); case "image": return /* @__PURE__ */ jsx(Image, { ...part }); case "file": return /* @__PURE__ */ jsx(File, { ...part }); case "audio": return /* @__PURE__ */ jsx(Audio, { ...part }); default: const unhandledType = type; throw new Error(`Unknown content part type: ${unhandledType}`); } }; const MessageContentPartImpl = ({ partIndex, components }) => { const messageRuntime = useMessageRuntime(); const runtime = useMemo( () => messageRuntime.getContentPartByIndex(partIndex), [messageRuntime, partIndex] ); return /* @__PURE__ */ jsx(ContentPartRuntimeProvider, { runtime, children: /* @__PURE__ */ jsx(MessageContentPartComponent, { components }) }); }; const MessageContentPart = memo( MessageContentPartImpl, (prev, next) => prev.partIndex === next.partIndex && prev.components?.Text === next.components?.Text && prev.components?.Reasoning === next.components?.Reasoning && prev.components?.Source === next.components?.Source && prev.components?.Image === next.components?.Image && prev.components?.File === next.components?.File && prev.components?.Unstable_Audio === next.components?.Unstable_Audio && prev.components?.tools === next.components?.tools ); const COMPLETE_STATUS = Object.freeze({ type: "complete" }); const EmptyContentFallback = ({ status, component: Component }) => { return /* @__PURE__ */ jsx(TextContentPartProvider, { text: "", isRunning: status.type === "running", children: /* @__PURE__ */ jsx(Component, { type: "text", text: "", status }) }); }; const EmptyContentImpl = ({ components }) => { const status = useMessage((s) => s.status) ?? COMPLETE_STATUS; if (components?.Empty) return /* @__PURE__ */ jsx(components.Empty, { status }); return /* @__PURE__ */ jsx( EmptyContentFallback, { status, component: components?.Text ?? defaultComponents.Text } ); }; const EmptyContent = memo( EmptyContentImpl, (prev, next) => prev.components?.Empty === next.components?.Empty && prev.components?.Text === next.components?.Text ); const MessagePrimitiveContent = ({ components }) => { const contentLength = useMessage((s) => s.content.length); if (contentLength === 0) { return /* @__PURE__ */ jsx(EmptyContent, { components }); } return Array.from({ length: contentLength }, (_, index) => /* @__PURE__ */ jsx(MessageContentPart, { partIndex: index, components }, index)); }; MessagePrimitiveContent.displayName = "MessagePrimitive.Content"; export { MessagePrimitiveContent }; //# sourceMappingURL=MessageContent.js.map