### Install FastAPI for Python Backend
Source: https://crayonai.org/docs/quickstart/python-fastapi
Installs the FastAPI framework, a modern, fast (high-performance) web framework for building APIs with Python 3.7+ based on standard Python type hints.
```bash
pip install fastapi
```
--------------------------------
### Serve React App Locally
Source: https://crayonai.org/docs/quickstart/python-fastapi
Commands to start the development server for a React application, enabling local testing and development. Supports npm, pnpm, and yarn.
```bash
npm run dev
```
```bash
pnpm dev
```
```bash
yarn dev
```
--------------------------------
### Create React Project and Install CrayonAI Packages
Source: https://crayonai.org/docs/quickstart/python-fastapi
Provides commands to create a new React application using create-react-app and install the necessary CrayonAI packages (@crayonai/react-ui, @crayonai/react-core) via npm, pnpm, or yarn.
```bash
npx create-react-app my-agent
npm install @crayonai/react-ui @crayonai/react-core
```
```bash
pnpm create react-app my-agent
pnpm install @crayonai/react-ui @crayonai/react-core
```
```bash
yarn create react-app my-agent
yarn add @crayonai/react-ui @crayonai/react-core
```
--------------------------------
### Install CrayonAI Packages with npm, pnpm, or yarn
Source: https://crayonai.org/docs/quickstart/nextjs
This snippet demonstrates how to install the required CrayonAI packages for your NextJS project. It includes installing the UI, core, and stream packages.
```bash
npm install @crayonai/react-ui @crayonai/react-core @crayonai/stream
```
```bash
pnpm add @crayonai/react-ui @crayonai/react-core @crayonai/stream
```
```bash
yarn add @crayonai/react-ui @crayonai/react-core @crayonai/stream
```
--------------------------------
### Run FastAPI Development Server
Source: https://crayonai.org/docs/quickstart/python-fastapi
Starts the FastAPI development server for local testing and development. This command watches for file changes and automatically reloads the server.
```bash
fastapi dev main.py
```
--------------------------------
### Install react-markdown Dependency
Source: https://crayonai.org/docs/guides/rendering-markdown
Installs the 'react-markdown' library, which is essential for rendering Markdown content in your Crayon Chat application. Supports npm, pnpm, and yarn package managers.
```bash
npm install react-markdown
```
```bash
pnpm add react-markdown
```
```bash
yarn add react-markdown
```
--------------------------------
### Serve NextJS App with npm, pnpm, or yarn
Source: https://crayonai.org/docs/quickstart/nextjs
This snippet shows the commands to run the NextJS development server using different package managers. This command starts the application, allowing you to view and test it locally.
```bash
npm run dev
```
```bash
pnpm dev
```
```bash
yarn dev
```
--------------------------------
### Integrate CrayonChat Component with TypeScript
Source: https://crayonai.org/docs/guides/getting-started
This TypeScript code demonstrates how to set up the `CrayonChat` component. It configures the component with a `processMessage` function and defines response templates, including a 'text' template using `TextTemplate`. This integrates the backend logic with the chat UI.
```typescript
```
--------------------------------
### Integrate LLM with FastAPI Route
Source: https://crayonai.org/docs/quickstart/python-fastapi
Demonstrates how to create a FastAPI POST endpoint '/chat' that accepts JSON messages, processes them using the OpenAI API with the gpt-4o model, and streams the response.
```python
from fastapi import FastAPI
from openai import OpenAI
app = FastAPI()
@app.post("/chat")
def chat(request: Request):
messages = await request.json()
client = OpenAI()
stream = client.chat.completions.create(
model="gpt-4o",
messages=messages,
stream=True,
)
return stream
```
--------------------------------
### Create New NextJS Project with npm, pnpm, or yarn
Source: https://crayonai.org/docs/quickstart/nextjs
This snippet shows how to create a new NextJS project using different package managers. It initializes a new NextJS application with the specified name.
```bash
npx create-next-app@latest my-agent
```
```bash
pnpm dlx create-next-app@latest my-agent
```
```bash
yarn create-next-app@latest my-agent
```
--------------------------------
### Add CrayonProvider to React App
Source: https://crayonai.org/docs/quickstart/python-fastapi
Shows how to integrate the CrayonChat component into a React application's App.tsx file, configuring it with the backend chat URL.
```typescript
import { CrayonChat } from "@crayonai/react-ui";
export default function App() {
return ;
}
```
--------------------------------
### Create NextJS Backend Endpoint with TypeScript
Source: https://crayonai.org/docs/guides/getting-started
This TypeScript code defines a NextJS backend endpoint to interact with an OpenAI LLM. It uses a JSON schema to format the response and streams the output. Dependencies include 'next/server', 'openai', and '@crayonai/stream'. It takes messages as input and returns a streamed response.
```typescript
import { NextRequest } from "next/server";
import OpenAI from "openai";
import { fromOpenAICompletion, toOpenAIMessages } from "@crayonai/stream";
import { Message } from "@crayonai/react-core";
const textResponseSchema = {
type: "object",
description: "Use this schema to generate a text response",
properties: {
type: { const: "text" },
text: {
type: "string",
description: "Plaintext message to be displayed to the user",
},
},
required: ["type", "text"],
additionalProperties: false,
};
export async function POST(req: NextRequest) {
const { messages } = (await req.json()) as { messages: Message[] };
const client = new OpenAI();
const llmStream = await client.chat.completions.create({
model: "gpt-4o",
messages: toOpenAIMessages(
messages
) as OpenAI.Chat.ChatCompletionMessageParam[],
stream: true,
response_format: textResponseSchema,
});
const responseStream = fromOpenAICompletion(llmStream);
return new Response(responseStream as unknown as ReadableStream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
},
});
}
```
--------------------------------
### NextJS Backend API with Markdown Template (JavaScript)
Source: https://crayonai.org/docs/guides/rendering-markdown
This JavaScript code provides a similar functionality to the TypeScript example, configuring a NextJS backend API for markdown-formatted LLM responses. It leverages the 'openai' and '@crayonai/stream' libraries. The API processes incoming messages, sends them to the OpenAI API with a specified response format, and returns a stream of events.
```javascript
import OpenAI from "openai";
import { fromOpenAICompletion, toOpenAIMessages } from "@crayonai/stream";
const textResponseSchema = {
type: "object",
description: "Use this schema to generate a markdown response",
properties: {
type: { const: "text" },
text: {
type: "string",
description: "Markdown formatted message to be displayed to the user",
},
},
required: ["type", "text"],
additionalProperties: false,
};
export async function POST(req) {
const { messages } = await req.json();
const client = new OpenAI();
const llmStream = await client.chat.completions.create({
model: "gpt-4o",
messages: toOpenAIMessages(messages),
stream: true,
response_format: textResponseSchema,
});
const responseStream = fromOpenAICompletion(llmStream);
return new Response(responseStream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
},
});
}
```
--------------------------------
### Create Crayon Response Template Component
Source: https://crayonai.org/docs/guides/getting-started
Response templates are React components used to define how different chat response types are rendered in the UI. This example shows a basic template for displaying text content in red.
```typescript
export const TextTemplate: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
return
;
};
```
--------------------------------
### Create NextJS Backend Endpoint with JavaScript
Source: https://crayonai.org/docs/guides/getting-started
This JavaScript code defines a NextJS backend endpoint for LLM interactions, similar to the TypeScript version. It specifies a JSON schema for the response format and handles streaming. It requires 'openai' and '@crayonai/stream' libraries. The input is a list of messages, and the output is a streamed response.
```javascript
import OpenAI from "openai";
import { fromOpenAICompletion, toOpenAIMessages } from "@crayonai/stream";
const textResponseSchema = {
type: "object",
description: "Use this schema to generate a text response",
properties: {
type: { const: "text" },
text: {
type: "string",
description: "Plaintext message to be displayed to the user",
},
},
required: ["type", "text"],
additionalProperties: false,
};
export async function POST(req) {
const { messages } = await req.json();
const client = new OpenAI();
const llmStream = await client.chat.completions.create({
model: "gpt-4o",
messages: toOpenAIMessages(messages),
stream: true,
response_format: textResponseSchema,
});
const responseStream = fromOpenAICompletion(llmStream);
return new Response(responseStream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
},
});
}
```
--------------------------------
### Integrate LLM with NextJS Backend Route (TypeScript/JavaScript)
Source: https://crayonai.org/docs/quickstart/nextjs
This snippet shows how to create a backend API route in NextJS to handle chat messages and stream responses from an LLM using OpenAI. It utilizes CrayonAI's stream utilities for seamless integration.
```typescript
import { NextRequest, NextResponse } from "next/server";
import OpenAI from "openai";
import {
fromOpenAICompletion,
templatesToResponseFormat,
toOpenAIMessages,
} from "@crayonai/stream";
import { Message } from "@crayonai/react-core";
export async function POST(req: NextRequest) {
const { messages } = (await req.json()) as { messages: Message[] };
const client = new OpenAI();
const llmStream = await client.chat.completions.create({
model: "gpt-4o",
messages: toOpenAIMessages(
messages
) as OpenAI.Chat.ChatCompletionMessageParam[],
stream: true,
response_format: templatesToResponseFormat(),
});
const responseStream = fromOpenAICompletion(llmStream);
return new NextResponse(
responseStream as unknown as ReadableStream,
{
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
},
}
);
}
```
```javascript
import { NextResponse } from "next/server";
import OpenAI from "openai";
import {
fromOpenAICompletion,
templatesToResponseFormat,
toOpenAIMessages,
} from "@crayonai/stream";
export async function POST(req) {
const { messages } = await req.json();
const client = new OpenAI();
const llmStream = await client.chat.completions.create({
model: "gpt-4o",
messages: toOpenAIMessages(messages),
stream: true,
response_format: templatesToResponseFormat(),
});
const responseStream = fromOpenAICompletion(llmStream);
return new NextResponse(responseStream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
},
});
}
```
--------------------------------
### Manage Thread Data and Events in JavaScript
Source: https://crayonai.org/docs/guides/customization/connecting-to-backend
This JavaScript example shows how to use the `useThreadManager` hook for managing thread data and events. It covers loading existing threads, processing new user messages (including thread creation and API calls for message handling), and managing streamed responses. Key dependencies include `useThreadListManager`, `fetch`, `crypto.randomUUID`, and `processStreamedMessage`.
```javascript
const threadManager = useThreadManager({
threadId: threadListManager.selectedThreadId,
shouldResetThreadState: threadListManager.shouldResetThreadState,
loadThread: async () => {
// Called to load the data for this specific thread. In this case, you would use your backend API that returns the selected thread's messages
const response = await fetch(
`/api/messages?threadId=${threadListManager.selectedThreadId}`
);
const data = await response.json();
return data.messages;
},
onProcessMessage: async ({ message, threadManager, abortController }) => {
// This is called when the user posts a message. Here, you might want to call your backend API that pushes messages inside the selected thread.
threadManager.appendMessages({
id: crypto.randomUUID(),
role: "user",
type: "prompt",
message: message.message,
});
let threadId = threadListManager.selectedThreadId;
// If this is a new thread that currently has not been created on the backend, create a thread, otherwise push message to an existing thread
if (!threadId) {
const thread = await threadListManager.createThread(message);
threadListManager.selectThread(thread.threadId, false);
threadId = thread.threadId;
}
const response = await fetch("/api/ask", {
method: "POST",
body: JSON.stringify({ threadId, ...message }),
headers: {
"Content-Type": "application/json",
Accept: "text/event-stream",
},
signal: abortController.signal,
});
// This is a utility function provided by crayon to make handling streamed messages more convenient.
await processStreamedMessage({
response,
createMessage: threadManager.appendMessages,
updateMessage: threadManager.updateMessage,
deleteMessage: (messageId) => {
const newMessages = threadManager.messages.filter(
(message) => message.id !== messageId
);
threadManager.setMessages(newMessages);
},
});
return [];
},
responseTemplates: templates,
});
```
--------------------------------
### Update Page Component with Markdown Template
Source: https://crayonai.org/docs/guides/rendering-markdown
Integrates the Markdown template into your Crayon Chat application's page component. This involves adding the 'MarkdownTemplate' to the 'responseTemplates' array, enabling formatted AI responses. Examples provided for TypeScript and JavaScript.
```typescript
import { MarkdownTemplate } from "@/app/templates/markdown";
const YourComponent = () => {
// ... implement processMessage as shown in the 'Getting Started with Crayon' guide
return (
)
}
```
```javascript
import { TextTemplate } from "@/app/templates/text";
const templates = [
{
name: "text",
Component: TextTemplate,
},
];
// Use in your CrayonChat component
;
```
--------------------------------
### Implement Crayon Chat Logic (`processMessage`)
Source: https://crayonai.org/docs/guides/getting-started
The `processMessage` function is central to Crayon's chat implementation. It handles API calls to your backend, processes conversation history, and manages request cancellation via an AbortController. It must return a response adhering to the Streaming Protocol.
```typescript
const processMessage = async ({
threadId,
messages,
abortController,
}: {
threadId: string;
messages: Message[];
abortController: AbortController;
}) => {
const response = await fetch("/api/chat", {
method: "POST",
body: JSON.stringify({ threadId, messages }),
headers: {
"Content-Type": "application/json",
Accept: "text/event-stream",
},
signal: abortController.signal,
});
return response;
};
```
```javascript
const processMessage = async ({
threadId,
messages,
abortController,
}) => {
const response = await fetch("/api/chat", {
method: "POST",
body: JSON.stringify({ threadId, messages }),
headers: {
"Content-Type": "application/json",
Accept: "text/event-stream",
},
signal: abortController.signal,
});
return response;
};
```
--------------------------------
### NextJS Backend API with Markdown Template (TypeScript)
Source: https://crayonai.org/docs/guides/rendering-markdown
This TypeScript code demonstrates how to configure a NextJS backend API to use a JSON schema for LLM responses, specifically for markdown-formatted text. It imports necessary modules from 'next/server', 'openai', and '@crayonai/stream'. The API accepts messages, sends them to the OpenAI API with a defined response format, and streams the result back.
```typescript
import { NextRequest } from "next/server";
import OpenAI from "openai";
import { fromOpenAICompletion, toOpenAIMessages } from "@crayonai/stream";
import { Message } from "@crayonai/react-core";
const textResponseSchema = {
type: "object",
description: "Use this schema to generate a markdown formatted text response",
properties: {
type: { const: "text" },
text: {
type: "string",
description: "Markdown formatted message to be displayed to the user",
},
},
required: ["type", "text"],
additionalProperties: false,
};
export async function POST(req: NextRequest) {
const { messages } = (await req.json()) as { messages: Message[] };
const client = new OpenAI();
const llmStream = await client.chat.completions.create({
model: "gpt-4o",
messages: toOpenAIMessages(
messages
) as OpenAI.Chat.ChatCompletionMessageParam[],
stream: true,
response_format: textResponseSchema,
});
const responseStream = fromOpenAICompletion(llmStream);
return new Response(responseStream as unknown as ReadableStream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
},
});
}
```
--------------------------------
### Apply Custom Theme to Crayon UI (React)
Source: https://crayonai.org/docs/guides/customization/customizing-ui
This example shows how to globally customize the Crayon UI's appearance by providing a custom theme to the `ThemeProvider`. This allows for changes like enabling dark mode and altering background colors for all components within the theme provider.
```jsx
{/* Rest of the crayon components you wish to include in the UI */}
```
--------------------------------
### Create Markdown Template Component
Source: https://crayonai.org/docs/guides/rendering-markdown
Defines a React component for rendering Markdown content. It accepts children as ReactNode and uses 'react-markdown' to parse and display them. Available in both TypeScript and JavaScript.
```typescript
import React from "react";
import Markdown from "react-markdown";
export const MarkdownTemplate: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
return {children as string};
};
```
```javascript
import React from "react";
import Markdown from "react-markdown";
export const MarkdownTemplate = ({ children }) => {
return {children};
};
```
--------------------------------
### Process Streamed Message Example
Source: https://crayonai.org/docs/reference/js/react-core/functions/processStreamedMessage
An example demonstrating how to use the processStreamedMessage function with thread manager methods. It shows the expected arguments for creating, updating, and deleting messages based on a server response.
```javascript
await processStreamedMessage({
response,
createMessage: threadManager.appendMessages,
updateMessage: threadManager.updateMessage,
deleteMessage: threadManager.deleteMessage,
});
```
--------------------------------
### Define Zod Schema for Recipe Response
Source: https://crayonai.org/docs/guides/customization/response-templates
Defines a Zod schema for structuring AI responses to be compatible with the RecipeTemplate component. It specifies the expected types for title, ingredients, and steps, including a custom description for the steps field to guide the LLM's output format.
```typescript
import { z } from "zod";
export const RecipeTemplateSchema = z.object({
title: z.string(),
ingredients: z.array(z.string()),
steps:
z
.array(z.string())
.describe(
"The instructions to cook the recipe. Do not prefix it with numbers or use markdown, just the instructions."
),
});
```
--------------------------------
### Manage Thread Data and Events in TypeScript
Source: https://crayonai.org/docs/guides/customization/connecting-to-backend
This TypeScript example demonstrates using the `useThreadManager` hook to handle data and events within a selected thread. It includes logic for loading thread messages, processing user messages (including creating new threads and calling backend APIs for message processing), and handling streamed responses. Dependencies include `useThreadListManager`, `fetch`, `crypto.randomUUID`, and `processStreamedMessage`.
```typescript
const threadManager = useThreadManager({
threadId: threadListManager.selectedThreadId,
shouldResetThreadState: threadListManager.shouldResetThreadState,
loadThread: async () => {
// Called to load the data for this specific thread. In this case, you would use your backend API that returns the selected thread's messages
const response = await fetch(
`/api/messages?threadId=${threadListManager.selectedThreadId}`
);
const data = await response.json();
return data.messages;
},
onProcessMessage: async ({ message, threadManager, abortController }) => {
// This is called when the user posts a message. Here, you might want to call your backend API that pushes messages inside the selected thread.
threadManager.appendMessages({
id: crypto.randomUUID(),
role: "user",
type: "prompt",
message: message.message as string,
});
let threadId = threadListManager.selectedThreadId;
// If this is a new thread that currently has not been created on the backend, create a thread, otherwise push message to an existing thread
if (!threadId) {
const thread = await threadListManager.createThread(
message as UserMessage
);
threadListManager.selectThread(thread.threadId!, false);
threadId = thread.threadId;
}
const response = await fetch("/api/ask", {
method: "POST",
body: JSON.stringify({ threadId, ...message }),
headers: {
"Content-Type": "application/json",
Accept: "text/event-stream",
},
signal: abortController.signal,
});
// This is a utility function provided by crayon to make handling streamed messages more convenient.
await processStreamedMessage({
response,
createMessage: threadManager.appendMessages,
updateMessage: threadManager.updateMessage,
deleteMessage: (messageId) => {
const newMessages = threadManager.messages.filter(
(message) => message.id !== messageId
);
threadManager.setMessages(newMessages);
},
});
// ... call your backend API to persist the messages here
return [];
},
responseTemplates: templates,
});
```
--------------------------------
### Extract Messages and Templates using useThreadManagerSelector
Source: https://crayonai.org/docs/reference/js/react-core/functions/useThreadManagerSelector
This example demonstrates how to use useThreadManagerSelector to extract 'messages' and 'templates' from the ThreadManager. It utilizes a generic type to specify the structure of the returned object. The accessor function defines which properties to retrieve from the threadManager.
```typescript
interface MessagesAndTemplates {
messages: Message[];
templates: ResponseTemplate[];
}
const { messages, templates } = useThreadManagerSelector(
(threadManager) => ({
messages: threadManager.messages,
templates: Object.values(threadManager.responseTemplates),
}),
);
```
--------------------------------
### Build Custom Crayon AI Sidebar with React and JavaScript
Source: https://crayonai.org/docs/guides/customization/advanced-customization/integrating-custom-components
This JavaScript code snippet demonstrates how to create a custom sidebar for Crayon AI. It leverages `useThreadListState` and `useThreadListActions` hooks for managing conversation data. Similar to the TypeScript version, it includes functionality for starting new chats and deleting existing ones, with styling applied using Tailwind CSS.
```javascript
import { useThreadListActions, useThreadListState } from "@crayonai/react-core";
import { Button } from "@crayonai/react-ui";
import { BrainCircuit, PlusIcon, TrashIcon } from "lucide-react";
export const CustomSidebar = () => {
const { threads, selectedThreadId } = useThreadListState();
const { switchToNewThread, selectThread, deleteThread } =
useThreadListActions();
const newChatHandler = () => {
// Clear thread state and unselect the selected thread so that the user can start a new chat
switchToNewThread();
};
const deleteThreadHandler = (threadId) => {
deleteThread(threadId);
};
return (
{/* Agent logo and name */}
Crayon AI
{/* New chat button */}
}
className="justify-between"
>
New chat
{/* Conversations section */}
{/* Section header */}
);
};
```
--------------------------------
### Add CrayonChat Component to NextJS App (TypeScript/JavaScript)
Source: https://crayonai.org/docs/quickstart/nextjs
This snippet shows how to integrate the CrayonChat component into your NextJS application. It includes setting up a message processing function that fetches responses from a backend API.
```typescript
"use client";
import type { Message } from "@crayonai/react-core";
import { CrayonChat } from "@crayonai/react-ui";
import "@crayonai/react-ui/styles/index.css";
const processMessage = async ({
threadId,
messages,
abortController,
}: {
threadId: string;
messages: Message[];
abortController: AbortController;
}) => {
const response = await fetch("/api/chat", {
method: "POST",
body: JSON.stringify({ threadId, messages }),
headers: {
"Content-Type": "application/json",
Accept: "text/event-stream",
},
signal: abortController.signal,
});
return response;
};
export default function Home() {
return ;
}
```
```javascript
"use client";
import { CrayonChat } from "@crayonai/react-ui";
import "@crayonai/react-ui/styles/index.css";
const processMessage = async ({ threadId, messages, abortController }) => {
const response = await fetch("/api/chat", {
method: "POST",
body: JSON.stringify({ threadId, messages }),
headers: {
"Content-Type": "application/json",
Accept: "text/event-stream",
},
signal: abortController.signal,
});
return response;
};
export default function Home() {
return ;
}
```
--------------------------------
### Create Backend Endpoint for LLM Schema (JavaScript)
Source: https://crayonai.org/docs/guides/customization/response-templates
This JavaScript code defines a POST endpoint for a Next.js application. It handles incoming messages, initializes an OpenAI client, and sets up a response format using CrayonAI utilities based on a recipe schema. The LLM's streamed response is then returned to the client with appropriate headers.
```javascript
import { NextRequest } from "next/server";
import OpenAI from "openai";
import {
fromOpenAICompletion,
toOpenAIMessages,
templatesToResponseFormat,
} from "@crayonai/stream";
import { Message } from "@crayonai/react-core";
import { RecipeTemplateSchema } from "@/types/recipe";
export async function POST(req) {
const { messages } = await req.json();
const client = new OpenAI();
const responseFormat = templatesToResponseFormat({
schema: RecipeTemplateSchema,
name: "recipe",
description: "Use this template to generate a recipe",
});
const llmStream = await client.chat.completions.create({
model: "gpt-4o",
messages: toOpenAIMessages(messages),
stream: true,
response_format: responseFormat,
});
const responseStream = fromOpenAICompletion(llmStream);
return new Response(responseStream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
},
});
}
```
--------------------------------
### POST /api/generate-recipe
Source: https://crayonai.org/docs/guides/customization/response-templates
This endpoint receives a list of messages, configures the OpenAI client with a specific response format (RecipeTemplateSchema), and streams the LLM's response back to the client. It's designed to generate recipes based on the provided schema.
```APIDOC
## POST /api/generate-recipe
### Description
This endpoint creates a backend route that informs the LLM about a specific schema (RecipeTemplateSchema) for generating recipes. It processes incoming messages, interacts with the OpenAI API, and streams the LLM's response.
### Method
POST
### Endpoint
/api/generate-recipe
### Parameters
#### Request Body
- **messages** (array) - Required - An array of message objects representing the conversation history.
### Request Example
```json
{
"messages": [
{"role": "user", "content": "Create a recipe for pasta carbonara."}
]
}
```
### Response
#### Success Response (200)
- **stream** (ReadableStream) - A stream of Server-Sent Events containing the LLM's response.
#### Response Example
(This is a stream, actual content will vary based on LLM response)
```
data: {"role": "assistant", "content": "Sure, here is a recipe for pasta carbonara..."}
```
```
--------------------------------
### Build Custom Composer with Crayon Hooks (TypeScript)
Source: https://crayonai.org/docs/guides/customization/advanced-customization/integrating-custom-components
Demonstrates how to build a custom message composer using Crayon's `useThreadState` and `useThreadActions` hooks in TypeScript. It allows users to input messages, send them, or cancel ongoing processes.
```typescript
import { useThreadActions, useThreadState } from "@crayonai/react-core";
import { Button } from "@crayonai/react-ui";
import { CircleX, SendIcon } from "lucide-react";
import { useState } from "react";
export const CustomComposer = () => {
const [message, setMessage] = useState("");
const { isRunning } = useThreadState();
const { onCancel, processMessage } = useThreadActions();
const handleMessageButton = (e: React.FormEvent) => {
e.preventDefault();
if (isRunning) {
onCancel();
return;
}
if (!message) return;
processMessage({ role: "user", type: "prompt", message });
setMessage("");
};
return (
);
};
```
--------------------------------
### Integrate Custom Components into Crayon Root Component
Source: https://crayonai.org/docs/guides/customization/advanced-customization/integrating-custom-components
Illustrates how to integrate custom-built components, such as `CustomSidebar` and `CustomComposer`, alongside Crayon's default components within the root application component. It shows the necessary provider wrappers.
```jsx
return (
{/* Custom sidebar */}
{/* Custom composer */}
);
```
--------------------------------
### Create Backend Endpoint for LLM Schema (TypeScript)
Source: https://crayonai.org/docs/guides/customization/response-templates
This TypeScript code defines a POST endpoint for a Next.js application. It takes messages as input, configures an OpenAI client with a specific response format based on a recipe schema, and streams the LLM's response back to the client. It utilizes CrayonAI's stream utilities for message conversion and response formatting.
```typescript
import { NextRequest } from "next/server";
import OpenAI from "openai";
import {
fromOpenAICompletion,
toOpenAIMessages,
templatesToResponseFormat,
} from "@crayonai/stream";
import { Message } from "@crayonai/react-core";
import { RecipeTemplateSchema } from "@/types/recipe";
export async function POST(req: NextRequest) {
const { messages } = (await req.json()) as { messages: Message[] };
const client = new OpenAI();
const responseFormat = templatesToResponseFormat({
schema: RecipeTemplateSchema,
name: "recipe",
description: "Use this template to generate a recipe",
});
const llmStream = await client.chat.completions.create({
model: "gpt-4o",
messages: toOpenAIMessages(
messages
) as OpenAI.Chat.ChatCompletionMessageParam[],
stream: true,
response_format: responseFormat,
});
const responseStream = fromOpenAICompletion(llmStream);
return new Response(responseStream as unknown as ReadableStream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
},
});
}
```
--------------------------------
### Replace Sidebar with Custom Component (React)
Source: https://crayonai.org/docs/guides/customization/customizing-ui
This example shows how to replace the default sidebar with a custom component (`CustomSidebar`) while keeping the rest of the Crayon UI structure intact. This highlights the flexibility of composing the UI by swapping out specific components.
```jsx
```
--------------------------------
### ChatProvider Component Usage (React)
Source: https://crayonai.org/docs/reference/js/react-core/functions/ChatProvider
This snippet demonstrates how to use the ChatProvider component in a React application. It shows the required props: threadManager and threadListManager, and how to wrap child components to provide them with chat context.
```jsx
```
--------------------------------
### Extract Boolean Value with useThreadManagerSelector
Source: https://crayonai.org/docs/reference/js/react-core/functions/useThreadManagerSelector
This example shows how to use useThreadManagerSelector to extract a boolean or undefined value, specifically checking if the thread manager is running. The generic type is explicitly set to 'boolean | undefined', and the accessor function returns the 'isRunning' property of the threadManager.
```typescript
const isRunning = useThreadManagerSelector(
(threadManager) => threadManager.isRunning,
);
```
--------------------------------
### Format Response Template SSE Event
Source: https://crayonai.org/docs/concepts/data-format
Demonstrates the SSE format for a 'tpl' event, used to define a UI component to be rendered. It includes the component's name and optional properties.
```text
event: tpl
data: {"name": "", "templateProps": }
```
--------------------------------
### Compose Crayon UI with Individual Components (React)
Source: https://crayonai.org/docs/guides/customization/customizing-ui
This code demonstrates how to replicate the default CrayonChat UI using individual components. It imports necessary providers and UI elements from '@crayonai/react-core' and '@crayonai/react-ui/Shell'. This approach allows for granular customization by replacing or modifying specific components.
```jsx
import {
ChatProvider,
useThreadListManager,
useThreadManager,
} from "@crayonai/react-core";
import {
Container,
SidebarContainer,
SidebarHeader,
SidebarContent,
SidebarSeparator,
ThreadList,
ThreadContainer,
MobileHeader,
ScrollArea,
Messages,
Composer,
NewChatButton,
} from "@crayonai/react-ui/Shell";
import { ThemeProvider } from "@crayonai/react-ui/ThemeProvider";
const YourComponent = () => {
const threadListManager = useThreadListManager({
// /implement as necessary
});
const threadManager = useThreadManager({
// implement as necessary
});
const logoUrl = ""; // URL to the agent logo
return (
);
};
```
--------------------------------
### Integrate Response Templates with CrayonChat
Source: https://crayonai.org/docs/guides/customization/response-templates
This JSX code demonstrates how to pass response templates to the CrayonChat component. It shows the structure for defining templates, including their name and the associated React component for rendering. This allows CrayonChat to handle different types of LLM responses.
```jsx
```
--------------------------------
### Update Backend to Handle Form Response Template (JavaScript)
Source: https://crayonai.org/docs/guides/customization/advanced-customization/message-context
This JavaScript code snippet illustrates how to update your backend to manage form response templates. It leverages `@crayonai/stream` for defining a response schema with `zod` and sends it to an OpenAI LLM for structured data capture. The resulting LLM stream is then transformed into a Crayon stream for the final output.
```javascript
// ... rest of your imports
import {
fromOpenAICompletion,
templatesToResponseFormat,
} from "@crayonai/stream";
import { z } from "zod";
export async function POST(req) {
// ... rest of your code
const responseFormat = templatesToResponseFormat({
schema: z.object({}),
name: "form",
description:
"Use this template to collect the user's name and email address",
});
// pass the response format to the LLM
const llmStream = await client.chat.completions.create({
model: "gpt-4o",
messages: toOpenAIMessages(messages),
stream: true,
response_format: responseFormat,
});
// convert the LLM stream to a Crayon stream
const responseStream = fromOpenAICompletion(llmStream);
return new Response(responseStream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
},
});
}
```
--------------------------------
### Build Custom Composer with Crayon Hooks (JavaScript)
Source: https://crayonai.org/docs/guides/customization/advanced-customization/integrating-custom-components
Provides a JavaScript implementation for a custom message composer using Crayon's `useThreadState` and `useThreadActions` hooks. This component enables message input, sending, and cancellation of operations.
```javascript
import { useThreadActions, useThreadState } from "@crayonai/react-core";
import { Button } from "@crayonai/react-ui";
import { CircleX, SendIcon } from "lucide-react";
import { useState } from "react";
export const CustomComposer = () => {
const [message, setMessage] = useState("");
const { isRunning } = useThreadState();
const { onCancel, processMessage } = useThreadActions();
const handleMessageButton = (e) => {
e.preventDefault();
if (isRunning) {
onCancel();
return;
}
if (!message) return;
processMessage({ role: "user", type: "prompt", message });
setMessage("");
};
return (
);
};
```
--------------------------------
### Create Recipe Card React Component (TypeScript)
Source: https://crayonai.org/docs/guides/customization/response-templates
A React component written in TypeScript for displaying a recipe card. It takes title, ingredients, and steps as props and uses Crayon UI components for rendering. This component is designed to be used with a corresponding Zod schema.
```typescript
import { Card, CardHeader, Tag, TagBlock } from "@crayonai/react-ui";
import { FlaskConical as FlaskConicalIcon } from "lucide-react";
import { StepsItem, Steps } from "@crayonai/react-ui/Steps";
interface RecipeTemplateProps {
title: string; // Name of the recipe
ingredients: string[]; // List of required ingredients
steps: string[]; // Step-by-step cooking instructions
}
export default function RecipeTemplate(props: RecipeTemplateProps) {
return (
{props.title}
))}
);
}
```
--------------------------------
### Create Recipe Card React Component (JavaScript)
Source: https://crayonai.org/docs/guides/customization/response-templates
A React component written in JavaScript for displaying a recipe card. It takes title, ingredients, and steps as props and uses Crayon UI components for rendering. This component is designed to be used with a corresponding Zod schema.
```javascript
import { Card, CardHeader, Tag, TagBlock } from "@crayonai/react-ui";
import { FlaskConical as FlaskConicalIcon } from "lucide-react";
import { StepsItem, Steps } from "@crayonai/react-ui/Steps";
export default function RecipeTemplate(props) {
return (
{props.title}}
icon={}
/>
{props.ingredients.map((ingredient) => (
{ingredient}} />
))}
{props.steps.map((step) => (