Skip to content

Latest commit

 

History

History
530 lines (437 loc) · 14.5 KB

File metadata and controls

530 lines (437 loc) · 14.5 KB
title Plugin Chatbot

import { InteractiveDemo } from '@/app/components/InteractiveDemo'; import { PluginLoader } from '@/app/components/PluginLoader';

Chat interface component with message history, typing indicators, and customizable avatars.

v5.4+ — the chat surface is now composed from vendored Vercel AI Elements (MIT). The public chatbot schema and ChatbotEnhanced / FloatingChatbot props are unchanged. A new optional suggestions: string[] field renders chip prompts in the empty state.

For advanced compositions, the underlying elements are re-exported:

import { AIElements } from '@object-ui/plugin-chatbot';
// AIElements.Conversation, AIElements.Message, AIElements.PromptInput, ...

Installation

npm install @object-ui/plugin-chatbot

<PluginLoader plugins={['chatbot']}>

Interactive Examples

Basic Chatbot

Chatbot with Timestamps

Customer Support Chat

Usage

Basic Usage

// Import once in your app entry point
import '@object-ui/plugin-chatbot'

// Use in schemas
const schema = {
  type: 'chatbot',
  messages: [
    {
      id: '1',
      role: 'assistant',
      content: 'Hello! How can I help you?'
    }
  ],
  placeholder: 'Type your message...',
  autoResponse: true
}

Features

  • Message History: Display chat messages with user and assistant roles
  • System Messages: Show system notifications in the chat
  • Timestamps: Optional timestamp display for each message
  • Custom Avatars: Configurable avatar images and fallback text
  • Auto-scroll: Automatically scroll to newest messages
  • Typing Indicator: Built-in typing indicator component
  • Auto-response: Demo mode with automatic responses
  • Responsive Floating Panel: Console assistants keep the panel inside safe browser gutters and hide the FAB while the chat is open
  • Conversation States: Empty streaming messages render as an assistant responding indicator, the submit control becomes Stop while streaming, and backend errors collapse into a retryable notice with optional details
  • Lightweight: Pure React components with minimal dependencies

Schema API

{
  type: 'chatbot',
  messages?: ChatMessage[],
  placeholder?: string,
  showTimestamp?: boolean,
  disabled?: boolean,
  userAvatarUrl?: string,
  userAvatarFallback?: string,
  assistantAvatarUrl?: string,
  assistantAvatarFallback?: string,
  maxHeight?: string,
  autoResponse?: boolean,
  autoResponseText?: string,
  autoResponseDelay?: number,
  onSend?: (content: string, messages: ObjectChatMessage[]) => void,
  className?: string,
  // AI / service-ai integration fields
  api?: string,
  conversationId?: string,
  systemPrompt?: string,
  model?: string,
  streamingEnabled?: boolean,
  headers?: Record<string, string>,
  requestBody?: Record<string, unknown>,
  maxToolRoundtrips?: number, // deprecated - inert, see below
  onError?: (error: Error) => void,
}

ChatMessage

{
  id: string,
  role: 'user' | 'assistant' | 'system' | 'tool',
  content: string,
  timestamp?: string | Date,
  metadata?: any,
  streaming?: boolean,
  toolInvocations?: ChatToolInvocation[],
}

Properties

showTimestamp through onSend below are declared on ChatbotSchema (@object-ui/types) — previously they existed only in an anonymous type local to the renderer, referenceable, validatable and documentable by nothing outside that one file (objectui#6169).

Property Type Default Description
messages array [] Initial chat messages
placeholder string 'Type your message...' Input field placeholder text
showTimestamp boolean false Display timestamps for messages
disabled boolean false Disable chat input
userAvatarUrl string - URL for user avatar image
userAvatarFallback string 'You' Fallback text for user avatar
assistantAvatarUrl string - URL for assistant avatar image
assistantAvatarFallback string 'AI' Fallback text for assistant avatar
maxHeight string '500px' Maximum chat container height
autoResponse boolean false Enable auto-response (demo mode, ignored when api is set)
autoResponseText string - Text for auto-response
autoResponseDelay number 1000 Delay before auto-response (ms)
onSend function - Callback when message is sent
className string '' Additional Tailwind CSS classes
api string - Backend SSE endpoint (e.g., /api/v1/ai/chat). Enables AI streaming mode
conversationId string - Multi-turn conversation identifier
systemPrompt string - System prompt to configure assistant behavior
model string - AI model identifier (e.g., gpt-4o)
streamingEnabled boolean true Enable SSE streaming for AI responses
headers object - Additional headers for API requests
requestBody object - Additional body parameters sent with each API request. Authored on the node as requestBody; the renderer forwards it to the chat runtime under its own body option. Writing body on the node instead sets the base schema's children container and never reaches the API
maxToolRoundtrips number - Deprecated - has no effect. Nothing reads this value, so it never capped anything. Cap tool-calling loops on the agent instead (planning.maxIterations). Still accepted so existing documents keep parsing; slated for removal in a future major
surface 'card' | 'plain' 'card' Controls whether the chat renders as a bordered panel or a frameless full-page workspace
processVisibility 'hidden' | 'summary' | 'debug' 'summary' Controls how much agent reasoning and tool detail is shown
onError function - Error callback for streaming/API errors

Operating Modes

The chatbot supports two modes, automatically selected based on the api field:

Local/Demo Mode (default)

When api is not set, the chatbot operates in local mode with optional auto-response:

const schema = {
  type: 'chatbot',
  messages: [...],
  autoResponse: true,
  autoResponseText: 'Thanks!',
  autoResponseDelay: 1000,
};

AI Streaming Mode (service-ai)

When api is set, the chatbot uses @ai-sdk/react for real SSE streaming:

const schema = {
  type: 'chatbot',
  api: '/api/v1/ai/chat',
  model: 'gpt-4o',
  systemPrompt: 'You are a helpful assistant.',
  streamingEnabled: true,
  messages: [],
};

Message Roles

User Messages

Messages from the user appear on the right side with primary styling:

{
  id: '1',
  role: 'user',
  content: 'Hello!',
  timestamp: '10:30 AM'
}

Assistant Messages

Messages from the assistant appear on the left side:

{
  id: '2',
  role: 'assistant',
  content: 'Hi! How can I help?',
  timestamp: '10:30 AM'
}

System Messages

System messages appear centered with muted styling:

{
  id: '3',
  role: 'system',
  content: 'Chat session started'
}

Tool Messages (AI Mode)

Tool messages represent results from tool invocations during AI streaming. They are generated automatically by the vercel/ai SDK when the backend performs tool calls (e.g., fetching weather, querying a database). The SDK may emit role: 'tool' messages as well as populate the assistant message's toolInvocations array.

By default, ChatbotEnhanced renders tool invocations as a compact agent activity summary. Repeated calls are grouped, raw tool names are hidden, and reasoning text is not shown. Use processVisibility="debug" for developer/admin views that need the full reasoning panel, raw tool names, parameters, and results. Use processVisibility="hidden" to suppress non-interactive activity entirely; approval and draft-review actions remain visible.

Use surface="plain" for full-page chat workspaces where the surrounding app already provides navigation chrome. The default surface="card" remains a better fit for embedded dashboards, side panels, and floating chat windows.

Console chat surfaces also keep a sanitized browser-side display cache for the current conversation. When a conversation can be reopened but the server returns no message rows, the UI restores user/assistant text and grouped tool names plus states. Reasoning, tool parameters, and raw tool results are not stored in this cache.

{
  id: '4',
  role: 'assistant',
  content: 'The weather in SF is 68°F.',
  toolInvocations: [
    {
      toolCallId: 'tc-1',
      toolName: 'getWeather',
      args: { city: 'San Francisco' },
      result: { temp: 68, condition: 'Sunny' },
      state: 'result',
    }
  ]
}

Examples

Simple AI Chat

const aiChat = {
  type: 'chatbot',
  messages: [
    {
      id: 'welcome',
      role: 'assistant',
      content: 'Hello! I\'m your AI assistant. Ask me anything!'
    }
  ],
  placeholder: 'Ask me a question...',
  assistantAvatarFallback: 'AI',
  userAvatarFallback: 'You',
  autoResponse: true,
  autoResponseText: 'That\'s a great question! Let me think about that...',
  maxHeight: '600px'
}

Support Ticket Chat

const supportChat = {
  type: 'chatbot',
  messages: [
    {
      id: 'sys-1',
      role: 'system',
      content: 'Ticket #12345 - Account Access Issue'
    },
    {
      id: '1',
      role: 'assistant',
      content: 'Hi! I\'m here to help with your account access issue.',
      avatarFallback: 'SP',
      timestamp: '2:15 PM'
    }
  ],
  placeholder: 'Describe your issue...',
  showTimestamp: true,
  userAvatarFallback: 'JD',
  assistantAvatarFallback: 'SP',
  className: 'w-full max-w-3xl mx-auto'
}

Sales Bot

const salesBot = {
  type: 'chatbot',
  messages: [
    {
      id: '1',
      role: 'assistant',
      content: 'Welcome! I\'m here to help you find the perfect product. What are you looking for today?',
      avatarFallback: 'SB'
    }
  ],
  placeholder: 'Tell us what you need...',
  assistantAvatarFallback: 'SB',
  userAvatarFallback: 'You',
  autoResponse: true,
  autoResponseText: 'Great choice! Let me show you some options...',
  autoResponseDelay: 1200,
  maxHeight: '500px',
  className: 'border-2 border-primary rounded-xl'
}

Multi-agent Chat

const multiAgentChat = {
  type: 'chatbot',
  messages: [
    {
      id: '1',
      role: 'assistant',
      content: 'Hello! Sarah from Sales here.',
      avatarFallback: 'SA'
    },
    {
      id: '2',
      role: 'user',
      content: 'I need help with pricing',
      avatarFallback: 'CU'
    },
    {
      id: '3',
      role: 'system',
      content: 'Transferring to Finance team...'
    },
    {
      id: '4',
      role: 'assistant',
      content: 'Hi! Mike from Finance. I can help with that.',
      avatarFallback: 'MI'
    }
  ],
  showTimestamp: true,
  userAvatarFallback: 'CU'
}

Custom Avatars

Avatar Images

const schema = {
  type: 'chatbot',
  userAvatarUrl: 'https://example.com/user-avatar.jpg',
  assistantAvatarUrl: 'https://example.com/bot-avatar.jpg',
  messages: [...]
}

Avatar Fallbacks

When images aren't available, fallback text is displayed:

const schema = {
  type: 'chatbot',
  userAvatarFallback: 'JD',  // User initials
  assistantAvatarFallback: 'AI',  // Bot identifier
  messages: [...]
}

Per-message Avatars

Override avatars for individual messages:

{
  id: '1',
  role: 'assistant',
  content: 'Message content',
  avatar: 'https://example.com/special-avatar.jpg',
  avatarFallback: 'SP'
}

Event Handling

onSend Callback

Handle message sending in your application:

const schema = {
  type: 'chatbot',
  messages: [...],
  onSend: (content, allMessages) => {
    console.log('User sent:', content);
    console.log('All messages:', allMessages);
    
    // Send to your backend
    fetch('/api/chat', {
      method: 'POST',
      body: JSON.stringify({ message: content })
    });
  }
}

Customization

Container Styling

const schema = {
  type: 'chatbot',
  className: 'w-full max-w-2xl mx-auto border-2 rounded-xl shadow-lg',
  maxHeight: '600px',
  messages: [...]
}

Responsive Heights

const schema = {
  type: 'chatbot',
  maxHeight: '400px', // or use Tailwind: 'h-96'
  className: 'sm:max-h-[500px] lg:max-h-[600px]',
  messages: [...]
}

TypeScript Support

import type { ChatbotSchema, ChatMessage, ChatToolInvocation } from '@object-ui/types'
import { useObjectChat } from '@object-ui/plugin-chatbot'

// Basic messages
const messages: ChatMessage[] = [
  {
    id: '1',
    role: 'assistant',
    content: 'Hello!'
  }
]

// Local/demo mode
const demoSchema: ChatbotSchema = {
  type: 'chatbot',
  messages,
  placeholder: 'Type here...',
  showTimestamp: true
}

// AI streaming mode (service-ai)
const aiSchema: ChatbotSchema = {
  type: 'chatbot',
  messages: [],
  api: '/api/v1/ai/chat',
  model: 'gpt-4o',
  systemPrompt: 'You are a helpful assistant.',
  streamingEnabled: true,
  conversationId: 'conv-123',
}

What comes back out: ObjectChatMessage

You AUTHOR with @object-ui/types' ChatMessage. What useObjectChat HANDS BACK — from messages and from onSend(content, messages) — is ObjectChatMessage, exported from @object-ui/plugin-chatbot:

import type { ObjectChatMessage } from '@object-ui/plugin-chatbot'

It is the authoring shape plus the render-only keys API mode really carries (buildProgress, blueprintProgress, charts, and pendingActionId / draftReview / proposedPlan / proposedChanges / builderHandoff on each tool invocation — the approval card, the "Review N changes" affordance, the plan card, the build panel, the inline charts), with timestamp narrowed to string because both modes absorb an authored Date before emitting.

It is a subtype of the authoring ChatMessage, so an onSend callback that already declares ChatMessage[] keeps type-checking; naming ObjectChatMessage is what lets it read those keys. Rebuilding a message field-by-field from the authoring type drops every one of them — silently, and with the compiler's agreement (objectui#4424).

Related Documentation