This guide will help you get started with the Aikit library.
npm install aikit
# or
yarn add aikit
# or
pnpm add aikitThe fastest way to get started is to use the ready-made ChatContainer component:
import React, { useState } from 'react';
import { ChatContainer } from 'aikit';
import type { ChatType, MessageType } from 'aikit';
function App() {
const [messages, setMessages] = useState<MessageType[]>([]);
const [chats, setChats] = useState<ChatType[]>([]);
const [activeChat, setActiveChat] = useState<ChatType | null>(null);
const handleSendMessage = async (content: string) => {
// Your message sending logic
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ message: content })
});
const data = await response.json();
// Update state
setMessages(prev => [...prev, data]);
};
return (
<ChatContainer
chats={chats}
activeChat={activeChat}
messages={messages}
onSendMessage={handleSendMessage}
onSelectChat={setActiveChat}
onCreateChat={() => {/* Create chat */}}
onDeleteChat={(chat) => {/* Delete chat */}}
/>
);
}For more flexible customization, use components separately:
import {
Header,
MessageList,
PromptBox,
} from 'aikit';
function CustomChat() {
return (
<div className="custom-chat">
<Header
title="AI Assistant"
onNewChat={() => {/* ... */}}
/>
<MessageList
messages={messages}
showTimestamp
/>
<PromptBox
onSend={handleSend}
placeholder="Enter message..."
/>
</div>
);
}import { usePromptBox } from 'aikit';
function MyCustomPromptBox() {
const {
value,
setValue,
handleSubmit,
canSubmit
} = usePromptBox({
onSend: async (data) => {
// Your logic
}
});
return (
<div className="my-prompt">
<textarea
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<button
onClick={handleSubmit}
disabled={!canSubmit}
>
Send
</button>
</div>
);
}The library supports three built-in message types:
- Simple — regular text message
- Thinking — AI thinking process
- Tool — tool execution
import type {SimpleMessageType} from 'aikit';
const message: SimpleMessageType = {
type: 'simple',
id: 'msg-1',
author: 'assistant',
timestamp: new Date().toISOString(),
state: 'success',
data: {
formattedText: 'Hello! How can I help?',
},
};You can create your own message types:
import type { BaseMessage, MessageTypeRegistry } from 'aikit';
// 1. Define data
interface ImageMessageData {
imageUrl: string;
caption?: string;
}
// 2. Create message type
type ImageMessage = BaseMessage<ImageMessageData> & {
type: 'image';
};
// 3. Create display component
const ImageMessageView = ({ message }: { message: ImageMessage }) => {
return (
<div>
<img src={message.data.imageUrl} />
{message.data.caption && <p>{message.data.caption}</p>}
</div>
);
};
// 4. Register type
const customTypes: MessageTypeRegistry = {
image: {
component: ImageMessageView,
validator: (msg) => msg.type === 'image'
}
};
// 5. Use in ChatContainer
<ChatContainer
messages={messages}
messageTypeRegistry={customTypes}
/><ChatContainer
theme="dark" // 'light' | 'dark' | 'auto'
// ...
/>.g-root {
--g-aikit-color-bg-primary: #ffffff;
/* ... */
}
[data-theme='dark'] {
--g-aikit-bg-primary: #1a1a1a;
/* ... */
}The library supports streaming responses:
const handleSendMessage = async (content: string) => {
// Create temporary message in streaming state
const tempMessage: SimpleMessageType = {
type: 'simple',
id: 'temp-' + Date.now(),
author: 'assistant',
timestamp: new Date().toISOString(),
state: 'streaming',
data: {formattedText: ''},
};
setMessages((prev) => [...prev, tempMessage]);
// Streaming from server
const response = await fetch('/api/chat/stream', {
method: 'POST',
body: JSON.stringify({message: content}),
});
const reader = response.body.getReader();
let accumulated = '';
while (true) {
const {done, value} = await reader.read();
if (done) break;
accumulated += new TextDecoder().decode(value);
// Update message as data arrives
setMessages((prev) =>
prev.map((msg) =>
msg.id === tempMessage.id ? {...msg, data: {formattedText: accumulated}} : msg,
),
);
}
// Change state to success
setMessages((prev) =>
prev.map((msg) => (msg.id === tempMessage.id ? {...msg, state: 'success' as const} : msg)),
);
};const service = new OpenAIService({...})
const stream = await service.createResponseStream({
input: 'Hello world',
});
stream.start() // start stream to get chunks
stream.onEventChunk(console.log) // a typed chunk object
stream.onBufferChunk(console.log) // if we need pass chunks to another service (for example via http)
stream.abort() // abort streamconst summarizing = await service.summarizeConversationTitle({
conversation: '<convId>',
byLastItems: 5, // summarizes based on the last 5 messages
// byFirstItems: 5, summarizes based on the first 5 messages
});
console.log('summarizing :>> ', summarizing); // header of conversationIf neither the byLastItems nor the byFirstItems parameter is provided, summarization will, by default, be performed on the first 5 items.
- Study the full architecture
- Review the project structure