Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assistant-ui/skills/assistant-ui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license: MIT

# assistant-ui

**Always consult [assistant-ui.com/docs](https://assistant-ui.com/docs) for latest API.**
**Always consult [assistant-ui.com/docs](https://assistant-ui.com/llms.txt) for latest API.**

React library for building AI chat interfaces with composable primitives.

Expand Down
27 changes: 24 additions & 3 deletions assistant-ui/skills/assistant-ui/references/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,30 @@ interface ThreadAssistantMessage {
type MessagePart =
| { type: "text"; text: string }
| { type: "image"; image: string }
| { type: "tool-call"; toolCallId: string; toolName: string; args: unknown; result?: unknown }
| { type: "reasoning"; reasoning: string }
| { type: "source"; source: Source };
| {
type: "tool-call";
toolCallId: string;
toolName: string;
args: unknown;
argsText: string;
result?: unknown;
isError?: boolean;
artifact?: unknown;
}
| { type: "reasoning"; text: string }
| {
type: "source";
sourceType: "url";
id: string;
url: string;
title?: string;
}
| {
type: "file";
filename?: string;
data: string;
mimeType: string;
};
```

## Branching Model
Expand Down
31 changes: 31 additions & 0 deletions assistant-ui/skills/assistant-ui/references/packages.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# assistant-ui Packages

## Published Packages

**To check latest version:** Run `npm view <package-name> version` or check the package on npmjs.com.

- All published packages only expose the `latest` dist-tag (no `next/beta/canary`).
- Monorepo-only: `@assistant-ui/x-buildutils` (not on npm).

| Package | Notes |
|---------|-------|
| @assistant-ui/react | Core UI library |
| @assistant-ui/react-ai-sdk | AI SDK v6 integration |
| @assistant-ui/react-langgraph | LangGraph integration |
| @assistant-ui/react-data-stream | Data stream utilities |
| @assistant-ui/react-markdown | Markdown rendering |
| @assistant-ui/react-syntax-highlighter | Code highlighting |
| @assistant-ui/styles | Pre-built CSS (no Tailwind) |
| @assistant-ui/store | State management |
| @assistant-ui/react-devtools | Developer tools |
| @assistant-ui/react-hook-form | React Hook Form integration |
| @assistant-ui/react-a2a | Agent-to-agent protocol |
| @assistant-ui/react-ag-ui | AG-UI protocol |
| @assistant-ui/tap | Testing utilities |
| @assistant-ui/mcp-docs-server | MCP documentation server |
| assistant-stream | Streaming protocol |
| assistant-cloud | Cloud persistence/auth |
| assistant-ui | CLI tool |
| create-assistant-ui | Project scaffolding |
| safe-content-frame | Sandboxed iframe content |
| tw-shimmer | Tailwind shimmer effects |
| chatgpt-app-studio | ChatGPT app builder |

## Core Packages

### @assistant-ui/react
Expand Down
21 changes: 18 additions & 3 deletions assistant-ui/skills/cloud/references/persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,24 @@ interface AUIv0Message {
type MessagePart =
| { type: "text"; text: string }
| { type: "image"; image: string }
| { type: "tool-call"; toolCallId: string; toolName: string; args: unknown; result?: unknown }
| { type: "reasoning"; reasoning: string }
| { type: "source"; source: { url: string; title: string } };
| {
type: "tool-call";
toolCallId: string;
toolName: string;
args: unknown;
argsText: string;
result?: unknown;
isError?: boolean;
artifact?: unknown;
}
| { type: "reasoning"; text: string }
| {
type: "source";
sourceType: "url";
id: string;
url: string;
title?: string;
};
```

## Thread History Adapter
Expand Down
4 changes: 2 additions & 2 deletions assistant-ui/skills/integrations/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export async function POST(req: Request) {
messages,
});

return result.toDataStreamResponse();
return result.toUIMessageStreamResponse();
}
```

Expand Down Expand Up @@ -299,7 +299,7 @@ npm install @ai-sdk/react
```

**Streaming not working**
- Verify `toDataStreamResponse()` is used
- Verify `toUIMessageStreamResponse()` is used
- Check Content-Type header
- Look for CORS errors

Expand Down
29 changes: 17 additions & 12 deletions assistant-ui/skills/integrations/references/ai-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export async function POST(req: Request) {
messages,
});

return result.toDataStreamResponse();
return result.toUIMessageStreamResponse();
}
```

Expand Down Expand Up @@ -95,13 +95,13 @@ const runtime = useChatRuntime({

```ts
import { openai } from "@ai-sdk/openai";
import { streamText, tool } from "ai";
import { streamText, tool, stepCountIs } from "ai";
import { z } from "zod";

const tools = {
search: tool({
description: "Search the web for information",
parameters: z.object({
inputSchema: z.object({
query: z.string().describe("Search query"),
limit: z.number().optional().default(5),
}),
Expand All @@ -119,10 +119,10 @@ export async function POST(req: Request) {
model: openai("gpt-4o"),
messages,
tools,
maxSteps: 5, // Allow multi-step tool use
stopWhen: stepCountIs(5), // Allow multi-step tool use
});

return result.toDataStreamResponse();
return result.toUIMessageStreamResponse();
}
```

Expand Down Expand Up @@ -251,19 +251,24 @@ streamText({

```ts
import { z } from "zod";
import { generateObject } from "ai";
import { generateText, Output } from "ai";
import { openai } from "@ai-sdk/openai";

const result = await generateObject({
const { output } = await generateText({
model: openai("gpt-4o"),
schema: z.object({
name: z.string(),
age: z.number(),
hobbies: z.array(z.string()),
output: Output.object({
schema: z.object({
name: z.string(),
age: z.number(),
hobbies: z.array(z.string()),
}),
}),
prompt: "Generate a user profile",
});
Comment thread
JustAnOkapi marked this conversation as resolved.
```

AI SDK v6 uses `generateText` + `Output.object` for structured output; `generateObject` is the older pattern.

## Error Handling

```tsx
Expand Down Expand Up @@ -329,6 +334,6 @@ export async function POST(req: Request) {
: openai(model);

const result = streamText({ model: provider, messages });
return result.toDataStreamResponse();
return result.toUIMessageStreamResponse();
}
```
98 changes: 64 additions & 34 deletions assistant-ui/skills/integrations/references/custom-backend.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ Connect assistant-ui to any backend.

## Using useLocalRuntime

For backends that return streaming responses.
For backends that return streaming responses. Emit `ChatModelRunResult` chunks (append-only `content` parts).

### Basic Setup

Plain-text streaming only. For AI SDK Data Stream responses, use `toUIMessageStreamResponse()` + `useChatRuntime` or decode with `DataStreamDecoder` and convert to content parts.

```tsx
import { useLocalRuntime, AssistantRuntimeProvider, Thread } from "@assistant-ui/react";

Expand All @@ -24,17 +26,27 @@ function Chat() {

const reader = response.body?.getReader();
const decoder = new TextDecoder();
let buffer = "";

while (reader) {
const { done, value } = await reader.read();
if (done) break;

while (reader) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const parts = buffer.split("\n");
buffer = parts.pop() ?? "";

const text = decoder.decode(value);
yield { type: "text-delta", textDelta: text };
for (const textChunk of parts.filter(Boolean)) {
yield { content: [{ type: "text", text: textChunk }] };
}
Comment thread
JustAnOkapi marked this conversation as resolved.
},
}

if (buffer) {
yield { content: [{ type: "text", text: buffer }] };
}
},
});
},
});

return (
<AssistantRuntimeProvider runtime={runtime}>
Expand All @@ -46,6 +58,8 @@ function Chat() {

### With SSE Parsing

Simple SSE `data:` lines only (not AI SDK Data Stream prefixes like `0:`/`b:`/`c:`).

```tsx
const runtime = useLocalRuntime({
model: {
Expand Down Expand Up @@ -73,7 +87,14 @@ const runtime = useLocalRuntime({
if (line === "data: [DONE]") return;

const data = JSON.parse(line.slice(6));
yield { type: "text-delta", textDelta: data.content };
yield { content: [{ type: "text", text: data.content }] };
}
}

if (buffer.startsWith("data: ")) {
const data = JSON.parse(buffer.slice(6));
if (data?.content) {
yield { content: [{ type: "text", text: data.content }] };
}
}
},
Expand All @@ -93,32 +114,41 @@ const runtime = useLocalRuntime({
signal: abortSignal,
});

const toolCalls = new Map<
string,
{ toolCallId: string; toolName: string; args: unknown; argsText: string }
>();

for await (const event of parseResponse(response)) {
switch (event.type) {
case "text":
yield { type: "text-delta", textDelta: event.content };
break;

case "tool_use":
yield {
type: "tool-call-begin",
toolCallId: event.id,
toolName: event.name,
};
yield {
type: "tool-call-done",
toolCallId: event.id,
args: event.input,
};
break;

case "tool_result":
yield {
type: "tool-result",
toolCallId: event.tool_use_id,
result: event.content,
};
break;
if (event.type === "text") {
yield { content: [{ type: "text", text: event.content }] };
}

if (event.type === "tool_use") {
const toolCall = {
toolCallId: event.id,
toolName: event.name,
args: event.input ?? {},
argsText: JSON.stringify(event.input ?? {}),
};
toolCalls.set(event.id, toolCall);
yield { content: [{ type: "tool-call", ...toolCall }] };
}

if (event.type === "tool_result") {
const toolCall = toolCalls.get(event.tool_use_id);
yield {
content: [
{
type: "tool-call",
toolCallId: event.tool_use_id,
toolName: toolCall?.toolName ?? "tool",
args: toolCall?.args ?? {},
argsText: toolCall?.argsText ?? "{}",
result: event.content,
},
],
};
Comment thread
JustAnOkapi marked this conversation as resolved.
}
}
},
Expand Down
28 changes: 20 additions & 8 deletions assistant-ui/skills/integrations/references/langgraph.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,24 +196,36 @@ async function* parseStream(response: Response) {
switch (data.event) {
case "on_chat_model_stream":
yield {
type: "text-delta",
textDelta: data.data.chunk.content,
content: [{ type: "text", text: data.data.chunk.content }],
};
break;

case "on_tool_start":
yield {
type: "tool-call-begin",
toolCallId: data.run_id,
toolName: data.name,
content: [
{
type: "tool-call",
toolCallId: data.run_id,
toolName: data.name,
args: data.input ?? {},
argsText: JSON.stringify(data.input ?? {}),
},
],
};
break;

case "on_tool_end":
yield {
type: "tool-result",
toolCallId: data.run_id,
result: data.data.output,
content: [
{
type: "tool-call",
toolCallId: data.run_id,
toolName: data.name,
args: data.input ?? {},
argsText: JSON.stringify(data.input ?? {}),
result: data.data.output,
},
],
};
break;
}
Expand Down
Loading