Skip to main content
Version: 0.1.0

Chat

Conversational AI client for building chat interfaces.

Architecture

The ChatClient supports two modes:

  • Direct mode (default): Creates raisin:Conversation and raisin:Message nodes directly, streams responses via SSE. This is the recommended approach for new applications.
  • Flow mode (legacy): Uses FlowClient for flow-backed conversations. Activate by passing flow to createConversation() or setting forceFlowMode: true.

Direct mode conversations are stored as node trees in the user's raisin:access_control workspace. When you send a message, a trigger fires the configured agent, which streams its response back via Server-Sent Events.

ChatClient

Access via the Database instance:

const db = client.database('myapp');
const chatClient = db.chat;

The db.chat getter returns a lazily-created, cached ChatClient pre-configured with the correct base URL, repository, auth manager, and WebSocket-backed FlowsApi.

Options

interface ChatClientOptions {
requestTimeout?: number;
fetch?: typeof fetch;
defaultFlowPath?: string;
/** Force flow mode even for new conversations */
forceFlowMode?: boolean;
}

Methods

chat()

One-shot convenience method. Creates a conversation, sends a message, and returns the full response.

async chat(
agent: string,
message: string,
options?: {
signal?: AbortSignal;
input?: Record<string, unknown>;
}
): Promise<ChatResult>
interface ChatResult {
response: string;
conversationId: string;
}

Example:

const { response } = await chatClient.chat(
'my-assistant',
'Summarize the latest sales report'
);

createConversation()

Start a new multi-turn conversation.

async createConversation(options: {
agent: string;
conversationType?: ConversationType;
flow?: string;
input?: Record<string, unknown>;
signal?: AbortSignal;
}): Promise<Conversation>

In direct mode (default), creates a raisin:Conversation node. In flow mode (when flow is specified), runs the flow and polls until the chat session is ready.

type ConversationType = 'ai_chat' | 'direct_message' | 'flow_chat';

sendMessage()

Send a user message and stream the response as an async iterable.

async *sendMessage(
conversationId: string,
content: string,
options?: { signal?: AbortSignal }
): AsyncIterable<ChatEvent>

The conversationId parameter accepts either:

  • A conversation path (starts with /) for direct mode
  • A flow instance ID for flow mode

Example:

for await (const event of chatClient.sendMessage(id, 'Hello')) {
if (event.type === 'text_chunk') {
process.stdout.write(event.text);
}
}

resumeConversation()

Restore a conversation after a page reload.

async resumeConversation(
conversationPathOrInstanceId: string
): Promise<Conversation | null>

Accepts a conversation path (direct mode) or flow instance ID (flow mode).

getMessages()

Load the full message history for a conversation.

async getMessages(
conversationId: string
): Promise<ChatMessage[]>

stop()

Abort an active streaming response.

stop(conversationId: string): void

Conversation

interface Conversation {
/** Conversation node ID */
id: string;
/** Conversation type */
type: ConversationType;
/** Agent reference path */
agentRef?: string;
/** Participant IDs */
participants?: string[];
/** Participant details */
participantDetails?: Record<string, { display_name: string }>;
/** Number of unread messages */
unreadCount?: number;
/** Last message preview */
lastMessage?: { content: string; sender_id: string; created_at: string };
/** Node path (primary identifier in direct mode) */
conversationPath: string;
/** Workspace */
conversationWorkspace: string;
/** Flow instance ID (only for flow-initiated chats) */
flowInstanceId?: string;
/** Initial events from creation */
initialEvents?: ChatEvent[];
}

Chat Events

Events yielded by sendMessage():

Event TypeKey FieldsDescription
text_chunktextIncremental text from the assistant
assistant_messagemessage: ChatMessageComplete assistant message
waitingsessionId?, turnCount?Conversation is waiting for next input
completedreason?, messages?Conversation turn is complete
failederrorAn error occurred
tool_call_startedtoolCallId, functionName, argumentsAgent is calling a tool
tool_call_completedtoolCallId, result, error?Tool call finished
thought_chunktextReasoning/thinking text
conversation_createdconversationPath, workspaceConversation node was created
message_savedmessagePath, roleMessage was persisted
loglevel, messageLog entry from the flow

ChatMessage

interface ChatMessage {
role: 'user' | 'assistant' | 'system' | 'tool';
content: string;
timestamp: string;
id?: string;
path?: string;
agent?: string;
finishReason?: string;
toolCalls?: ToolCallRecord[];
toolCallId?: string;
children?: MessageChild[];
/** Sender identity ID */
senderId?: string;
/** Sender display name */
senderDisplayName?: string;
/** Message delivery status */
status?: string;
/** Message type discriminator */
messageType?: string;
}

ToolCallRecord

interface ToolCallRecord {
id: string;
name: string;
arguments: unknown;
}

MessageChild

interface MessageChild {
id: string;
path?: string;
type: 'thought' | 'tool_call' | 'tool_result' | 'cost';
content: string;
toolName?: string;
toolInput?: unknown;
status?: string;
}

ConversationClient

The ConversationClient provides inbox-level operations for listing and managing conversations. Access via db.conversations:

const db = client.database('myapp');
const conversations = db.conversations;

listConversations()

List conversations for the current user.

async listConversations(options?: {
type?: ConversationType;
limit?: number;
signal?: AbortSignal;
}): Promise<ConversationListItem[]>
interface ConversationListItem {
id: string;
type: ConversationType;
conversationPath: string;
conversationWorkspace: string;
agentRef?: string;
participants?: string[];
unreadCount?: number;
lastMessage?: { content: string; sender_id: string; created_at: string };
updatedAt?: string;
}

Example:

const aiChats = await conversations.listConversations({ type: 'ai_chat', limit: 20 });

startAIChat()

Create a new AI chat conversation.

async startAIChat(options: {
agent: string;
input?: Record<string, unknown>;
signal?: AbortSignal;
}): Promise<Conversation>

openConversation()

Open an existing conversation by path.

async openConversation(
conversationPath: string,
options?: { signal?: AbortSignal }
): Promise<Conversation | null>

markAsRead()

Mark a conversation as read.

async markAsRead(
conversationPath: string,
options?: { signal?: AbortSignal }
): Promise<void>

ChatStore (Svelte Adapter)

The ChatStore manages chat state for UI frameworks. It handles conversation creation, message sending, streaming, and message history with a subscribe/callback pattern.

Creating a ChatStore

import { ChatStore } from '@raisindb/client';

const db = client.database('myapp');
const store = new ChatStore({
agent: '/agents/support',
database: db,
});

Options

interface ChatStoreOptions {
agent: string;
database?: Database;
flowPath?: string;
clientOptions?: ChatClientOptions;
input?: Record<string, unknown>;
onEvent?: (event: ChatEvent) => void;
}