+ +
+ +This demo showcases a **realtime voice-based chatbot assistant** built with OpenAI's new Realtime API — now extended with full **MCP tool integration**. +Talk to the assistant naturally, and watch it execute tools in real time. + +### ⚡️ Quick Tool Mentions (`@`) & Presets + +{t("Layout.createYourOwnAgent")}
++ Created {formatTimeAgo(archive.createdAt)} +
++ {archive.description} +
+ )} ++ Add some chat threads to this archive to see them here. +
++ {t("MCP.configureYourMcpServerConnectionSettings")} +
++ {t("MCP.configureYourMcpServerConnectionSettings")} +
+{tool.name}
++ {tool.description} +
++ {showFullDescription + ? description + : `${description.slice(0, 300)}${description.length > 300 ? "..." : ""}`} +
+ {description.length > 300 && ( + + )} ++ {client?.toolInfo?.length ? "No search results" : "No tools available"} +
+ ); + + useEffect(() => { + setCallResult(null); + setIsCallLoading(false); + setJsonError(null); + setJsonInput(""); + setShowInputSchema(false); + setShowFullDescription(false); + }, [selectedToolIndex]); + + useEffect(() => { + setSelectedToolIndex(0); + }, [searchQuery]); + + return ( ++ {t("MCP.noSchemaPropertiesAvailable")} +
+ )} +
+ {isString(callResult.error)
+ ? callResult.error
+ : JSON.stringify(callResult.error, null, 2)}
+
+ + This tool doesn{"'"}t have an input schema defined +
++ Select a tool from the left to test +
+${message}
+This window will close automatically.
++ {t("Common.sharedBy", { userName: agent.userName })} +
+{t("Layout.createYourOwnAgent")}
+{t("Agent.title")}
+ )} + ++ {t("Agent.agentSettingsDescription")} +
++ Step {step} of {steps.length} +
++ {steps[step - 1]} +
+{t("temporaryChat")}
+ + + + ++ {t("VoiceChat.preparing")} +
+ ); + } + if (!isActive) + return ( ++ {t("VoiceChat.startVoiceChat")} +
+ ); + if (!isListening) + return ( ++ {t("VoiceChat.yourMicIsOff")} +
+ ); + if (!isAssistantSpeaking && messages.length === 0) { + return ( ++ {t("VoiceChat.readyWhenYouAreJustStartTalking")} +
+ ); + } + if (isUserSpeaking && useCompactView) { + return+ {t("VoiceChat.readyWhenYouAreJustStartTalking")} +
+ ); + } + }, [ + isAssistantSpeaking, + isUserSpeaking, + isActive, + isLoading, + isListening, + messages.length, + useCompactView, + ]); + + const mcpTools = useMemo+ {t("VoiceChat.pleaseCloseTheVoiceChatAndTryAgain")} +
+{t("VoiceChat.endConversation")}
++ {(part.text || "...") + ?.trim() + .split(" ") + .map((word, wordIndex) => ( + + {word}{" "} + + ))} +
+ ); + } else if (isToolUIPart(part)) { + return ( +{part.type} unknown part
; + }) + )} ++ {textPart.text?.split(" ").map((word, wordIndex) => ( + + {word}{" "} + + ))} +
++ {t("Chat.ChatPreferences.userInstructionsDescription")} +
+ ++ {t("Chat.ChatPreferences.mcpInstructionsDescription")} +
+ ++ {t("MCP.configureYourMcpServerConnectionSettings")} +
++ {t("Chat.ChatPreferences.myExportsDescription")} +
+ ++ {t("Chat.ChatPreferences.noExportsYet")} +
++ {t("Chat.ChatPreferences.exportHint")} +
++ Configure your personal API keys for different providers. These keys are stored securely in your user profile. +
+ +
+
{tool.name}
++ {tool.description} +
++ {t("Chat.Tool.noToolsAvailable")} +
++ Be the first to comment! +
+{t("Layout.createAgent")}
++ {sharedAgents.length > 0 + ? t("Layout.createYourOwnAgentOrSelectShared") + : t("Layout.createYourOwnAgent")} +
++ {sharedAgents.length > 0 + ? t("Layout.availableAgents") + : t("Layout.noAgentsAvailable")} +
++ {sharedAgents.length > 0 + ? t("Layout.browseAgentsToBookmark") + : t("Layout.askAdminToShareAgents")} +
++ {agent.name} +
++ {expanded + ? t("Common.showLess") + : t("Common.showMore")} +
+ {expanded ? ( ++ {t("noConversationsYet")} +
++ {thread.title || "New Chat"} +
+ )} + +
+ {children}
+
+ );
+ },
+ blockquote: ({ children }) => {
+ return (
+ ++{children} +
+
Authorize
+{t("mcpServerCustomization")}
+{t("toolsTest")}
+{t("refresh")}
++ {t("noToolsAvailable")} +
+{tool.name}
++ {tool.description} +
+error
: null} ++ {t("MCP.mcpServerCustomizationDescription")} +
++ {t("MCP.toolCustomizationInstructions")} +
++ {tool.prompt || "None"} +
+{message}
, { + id: "mcp-list-message", + }); + } + }, []); + + return ( + <> + {particle} ++ {t("noMcpServersAvailableDescription")} +
+{nameError}
} ++ {t("overviewDescription")} +
+ +Error rendering Mermaid diagram:
+
+ {state.error}
+
+
+ {chart}
+
+ + {displayText} +
+ {isLongText && ( + + )} ++ High input token usage may occur when many tools are + available. +
++ {filename} +
+{t("Chat.Error")}
++ {t("Chat.thisMessageWasNotSavedPleaseTryTheChatAgain")} +
+++ ); +}; + +export async function Highlight( + code: string, + lang: BundledLanguage | (string & {}), + theme: string, +) { + const parsed: BundledLanguage = ( + bundledLanguages[lang] ? lang : "md" + ) as BundledLanguage; + + if (lang === "json") { + return ( +++ ++ {lang} + ++{children}+
{t(visibilityItem.label)}
++ {t(visibilityItem.description)} +
++ {t("MCP.toolCustomizationInstructions")} +
++ {data?.prompt || t("MCP.noInstructions")} +
+ )} ++ {t("MCP.noSchemaPropertiesAvailable")} +
+ )} ++ {t("MCP.noSchemaPropertiesAvailable")} +
+ )} + + ++ Image generation may take up to 1 minute. +
+
+//
+
+ {result.url} +
++ {t("autoToolModeDescription")} +
++ {t("manualToolModeDescription")} +
++ {t("noneToolModeDescription")} +
++ {t("toolsSetupDescription")} +
+{t("Chat.Tool.noPresetsAvailableYet")}
++ {t("Chat.Tool.clickSaveAsPresetToGetStarted")} +
+{t("Workflow.noTools")}
+ + +{tool.name}
++ {tool.description} +
+{t("Layout.createAgent")}
++ {bookmarkedAgents.length > 0 + ? t("Layout.createYourOwnAgentOrSelectShared") + : t("Layout.createYourOwnAgent")} +
+
+
+ {showLineNumbers && (
+
+ {code?.split("\n").map((_, index) => (
+ {index + 1}
+ ))}
+
+ )}
+ {props.children}
+
+
+ ),
+ },
+ }) as JSX.Element;
+ })
+ .ifOk(setComponent);
+ }, [theme, lang, code]);
+
+ if (!code) return fallback;
+
+ return component ?? fallback;
+}
diff --git a/src/components/ui/accordion.tsx b/src/components/ui/accordion.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..2185c305c32bc6da26ceb600d1a956228e90abf9
--- /dev/null
+++ b/src/components/ui/accordion.tsx
@@ -0,0 +1,66 @@
+"use client";
+
+import * as React from "react";
+import * as AccordionPrimitive from "@radix-ui/react-accordion";
+import { ChevronDownIcon } from "lucide-react";
+
+import { cn } from "lib/utils";
+
+function Accordion({
+ ...props
+}: React.ComponentProps