Skip to content

chore: extract rsc to separate package #5542

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 8, 2025
Merged
Show file tree
Hide file tree
Changes from 5 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
6 changes: 3 additions & 3 deletions content/cookbook/20-rsc/20-stream-text.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ Text generation can sometimes take a long time to complete, especially when you'

## Client

Let's create a simple React component that will call the `generate` function when a button is clicked. The `generate` function will call the `streamText` function, which will then generate text based on the input prompt. To consume the stream of text in the client, we will use the `readStreamableValue` function from the `ai/rsc` module.
Let's create a simple React component that will call the `generate` function when a button is clicked. The `generate` function will call the `streamText` function, which will then generate text based on the input prompt. To consume the stream of text in the client, we will use the `readStreamableValue` function from the `@ai-sdk/rsc` module.

```tsx filename="app/page.tsx"
'use client';

import { useState } from 'react';
import { generate } from './actions';
import { readStreamableValue } from 'ai/rsc';
import { readStreamableValue } from '@ai-sdk/rsc';

// Allow streaming responses up to 30 seconds
export const maxDuration = 30;
Expand Down Expand Up @@ -66,7 +66,7 @@ Using DevTools, we can see the text generation being streamed to the client in r

import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { createStreamableValue } from 'ai/rsc';
import { createStreamableValue } from '@ai-sdk/rsc';

export async function generate(input: string) {
const stream = createStreamableValue('');
Expand Down
4 changes: 2 additions & 2 deletions content/cookbook/20-rsc/21-stream-text-with-chat-prompt.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Let's create a simple conversation between a user and a model, and place a butto

import { useState } from 'react';
import { Message, continueConversation } from './actions';
import { readStreamableValue } from 'ai/rsc';
import { readStreamableValue } from '@ai-sdk/rsc';

// Allow streaming responses up to 30 seconds
export const maxDuration = 30;
Expand Down Expand Up @@ -95,7 +95,7 @@ Now, let's implement the `continueConversation` function that will insert the us

import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { createStreamableValue } from 'ai/rsc';
import { createStreamableValue } from '@ai-sdk/rsc';

export interface Message {
role: 'user' | 'assistant';
Expand Down
4 changes: 2 additions & 2 deletions content/cookbook/20-rsc/40-stream-object.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Let's create a simple React component that will call the `getNotifications` func

import { useState } from 'react';
import { generate } from './actions';
import { readStreamableValue } from 'ai/rsc';
import { readStreamableValue } from '@ai-sdk/rsc';

// Allow streaming responses up to 30 seconds
export const maxDuration = 30;
Expand Down Expand Up @@ -92,7 +92,7 @@ Now let's implement the `getNotifications` function. We'll use the `generateObje

import { streamObject } from 'ai';
import { openai } from '@ai-sdk/openai';
import { createStreamableValue } from 'ai/rsc';
import { createStreamableValue } from '@ai-sdk/rsc';
import { z } from 'zod';

export async function generate(input: string) {
Expand Down
6 changes: 3 additions & 3 deletions content/cookbook/20-rsc/60-save-messages-to-database.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default function RootLayout({

import { useState } from 'react';
import { ClientMessage } from './actions';
import { useActions, useUIState } from 'ai/rsc';
import { useActions, useUIState } from '@ai-sdk/rsc';
import { generateId } from 'ai';

// Allow streaming responses up to 30 seconds
Expand Down Expand Up @@ -100,7 +100,7 @@ We will use the callback function to listen to state changes and save the conver
```tsx filename='app/actions.tsx'
'use server';

import { getAIState, getMutableAIState, streamUI } from 'ai/rsc';
import { getAIState, getMutableAIState, streamUI } from '@ai-sdk/rsc';
import { openai } from '@ai-sdk/openai';
import { ReactNode } from 'react';
import { z } from 'zod';
Expand Down Expand Up @@ -176,7 +176,7 @@ export async function continueConversation(
```

```ts filename='app/ai.ts'
import { createAI } from 'ai/rsc';
import { createAI } from '@ai-sdk/rsc';
import { ServerMessage, ClientMessage, continueConversation } from './actions';

export const AI = createAI<ServerMessage[], ClientMessage[]>({
Expand Down
6 changes: 3 additions & 3 deletions content/cookbook/20-rsc/61-restore-messages-from-database.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function RootLayout({

import { useState, useEffect } from 'react';
import { ClientMessage } from './actions';
import { useActions, useUIState } from 'ai/rsc';
import { useActions, useUIState } from '@ai-sdk/rsc';
import { generateId } from 'ai';

export default function Home() {
Expand Down Expand Up @@ -97,7 +97,7 @@ export default function Home() {
The server-side implementation handles the restoration of messages and their transformation into the appropriate format for display.

```tsx filename='app/ai.ts'
import { createAI } from 'ai/rsc';
import { createAI } from '@ai-sdk/rsc';
import { ServerMessage, ClientMessage, continueConversation } from './actions';
import { Stock } from '@ai-studio/components/stock';
import { generateId } from 'ai';
Expand Down Expand Up @@ -126,7 +126,7 @@ export const AI = createAI<ServerMessage[], ClientMessage[]>({
```tsx filename='app/actions.tsx'
'use server';

import { getAIState } from 'ai/rsc';
import { getAIState } from '@ai-sdk/rsc';

export interface ServerMessage {
role: 'user' | 'assistant' | 'function';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ When we define multiple functions in [`tools`](/docs/reference/ai-sdk-core/gener

import { useState } from 'react';
import { ClientMessage } from './actions';
import { useActions, useUIState } from 'ai/rsc';
import { useActions, useUIState } from '@ai-sdk/rsc';
import { generateId } from 'ai';

// Allow streaming responses up to 30 seconds
Expand Down Expand Up @@ -112,7 +112,7 @@ export async function Flight({ flightNumber }) {
```tsx filename='app/actions.tsx'
'use server';

import { getMutableAIState, streamUI } from 'ai/rsc';
import { getMutableAIState, streamUI } from '@ai-sdk/rsc';
import { openai } from '@ai-sdk/openai';
import { ReactNode } from 'react';
import { z } from 'zod';
Expand Down Expand Up @@ -206,7 +206,7 @@ export async function continueConversation(
```

```typescript filename='app/ai.ts'
import { createAI } from 'ai/rsc';
import { createAI } from '@ai-sdk/rsc';
import { ServerMessage, ClientMessage, continueConversation } from './actions';

export const AI = createAI<ServerMessage[], ClientMessage[]>({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ In our previous example we've been streaming react components from the server to

import { useState } from 'react';
import { ClientMessage } from './actions';
import { useActions, useUIState } from 'ai/rsc';
import { useActions, useUIState } from '@ai-sdk/rsc';
import { generateId } from 'ai';

// Allow streaming responses up to 30 seconds
Expand Down Expand Up @@ -72,7 +72,7 @@ export default function Home() {
```tsx filename='app/actions.tsx'
'use server';

import { getMutableAIState, streamUI } from 'ai/rsc';
import { getMutableAIState, streamUI } from '@ai-sdk/rsc';
import { openai } from '@ai-sdk/openai';
import { ReactNode } from 'react';
import { z } from 'zod';
Expand Down Expand Up @@ -137,7 +137,7 @@ export async function continueConversation(
```

```typescript filename='app/ai.ts'
import { createAI } from 'ai/rsc';
import { createAI } from '@ai-sdk/rsc';
import { ServerMessage, ClientMessage, continueConversation } from './actions';

export const AI = createAI<ServerMessage[], ClientMessage[]>({
Expand Down
6 changes: 3 additions & 3 deletions content/cookbook/20-rsc/92-stream-ui-record-token-usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ It is called when the stream is finished.

import { useState } from 'react';
import { ClientMessage } from './actions';
import { useActions, useUIState } from 'ai/rsc';
import { useActions, useUIState } from '@ai-sdk/rsc';
import { generateId } from 'ai';

// Allow streaming responses up to 30 seconds
Expand Down Expand Up @@ -76,7 +76,7 @@ export default function Home() {
```tsx filename='app/actions.tsx' highlight={"57-63"}
'use server';

import { createAI, getMutableAIState, streamUI } from 'ai/rsc';
import { createAI, getMutableAIState, streamUI } from '@ai-sdk/rsc';
import { openai } from '@ai-sdk/openai';
import { ReactNode } from 'react';
import { z } from 'zod';
Expand Down Expand Up @@ -148,7 +148,7 @@ export async function continueConversation(
```

```typescript filename='app/ai.ts'
import { createAI } from 'ai/rsc';
import { createAI } from '@ai-sdk/rsc';
import { ServerMessage, ClientMessage, continueConversation } from './actions';

export const AI = createAI<ServerMessage[], ClientMessage[]>({
Expand Down
2 changes: 1 addition & 1 deletion content/docs/02-guides/21-llama-3_1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ First, create a Server Action.
```tsx filename="app/actions.tsx"
'use server';

import { streamUI } from 'ai/rsc';
import { streamUI } from '@ai-sdk/rsc';
import { deepinfra } from '@ai-sdk/deepinfra';
import { z } from 'zod';

Expand Down
4 changes: 2 additions & 2 deletions content/docs/05-ai-sdk-rsc/01-overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ description: An overview of AI SDK RSC.
</Note>

<Note>
The `ai/rsc` package is compatible with frameworks that support React Server
Components.
The `@ai-sdk/rsc` package is compatible with frameworks that support React
Server Components.
</Note>

[React Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components) (RSC) allow you to write UI that can be rendered on the server and streamed to the client. RSCs enable [ Server Actions ](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#with-client-components), a new way to call server-side code directly from the client just like any other function with end-to-end type-safety. This combination opens the door to a new way of building AI applications, allowing the large language model (LLM) to generate and stream UI directly from the server to the client.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Create a Server Action at `app/actions.tsx` and add the following code:
```tsx filename="app/actions.tsx"
'use server';

import { streamUI } from 'ai/rsc';
import { streamUI } from '@ai-sdk/rsc';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';

Expand Down
18 changes: 9 additions & 9 deletions content/docs/05-ai-sdk-rsc/03-generative-ui-state.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ AI SDK RSC simplifies managing AI and UI state across your application by provid

Notably, this means you do not have to pass the message history to the server explicitly for each request. You also can access and update your application state in any child component of the context provider. As you begin building [multistep generative interfaces](/docs/ai-sdk-rsc/multistep-interfaces), this will be particularly helpful.

To use `ai/rsc` to manage AI and UI State in your application, you can create a React context using [`createAI`](/docs/reference/ai-sdk-rsc/create-ai):
To use `@ai-sdk/rsc` to manage AI and UI State in your application, you can create a React context using [`createAI`](/docs/reference/ai-sdk-rsc/create-ai):

```tsx filename='app/actions.tsx'
// Define the AI state and UI state types
Expand All @@ -78,7 +78,7 @@ export const sendMessage = async (input: string): Promise<ClientMessage> => {
```

```tsx filename='app/ai.ts'
import { createAI } from 'ai/rsc';
import { createAI } from '@ai-sdk/rsc';
import { ClientMessage, ServerMessage, sendMessage } from './actions';

export type AIState = ServerMessage[];
Expand Down Expand Up @@ -124,7 +124,7 @@ The UI state can be accessed in Client Components using the [`useUIState`](/docs
```tsx filename='app/page.tsx'
'use client';

import { useUIState } from 'ai/rsc';
import { useUIState } from '@ai-sdk/rsc';

export default function Page() {
const [messages, setMessages] = useUIState();
Expand All @@ -146,7 +146,7 @@ The AI state can be accessed in Client Components using the [`useAIState`](/docs
```tsx filename='app/page.tsx'
'use client';

import { useAIState } from 'ai/rsc';
import { useAIState } from '@ai-sdk/rsc';

export default function Page() {
const [messages, setMessages] = useAIState();
Expand All @@ -166,7 +166,7 @@ export default function Page() {
The AI State can be accessed within any Server Action provided to the `createAI` context using the [`getAIState`](/docs/reference/ai-sdk-rsc/get-ai-state) function. It returns the current AI state as a read-only value:

```tsx filename='app/actions.ts'
import { getAIState } from 'ai/rsc';
import { getAIState } from '@ai-sdk/rsc';

export async function sendMessage(message: string) {
'use server';
Expand All @@ -192,7 +192,7 @@ export async function sendMessage(message: string) {
The AI State can also be updated from within your Server Action with the [`getMutableAIState`](/docs/reference/ai-sdk-rsc/get-mutable-ai-state) function. This function is similar to `getAIState`, but it returns the state with methods to read and update it:

```tsx filename='app/actions.ts'
import { getMutableAIState } from 'ai/rsc';
import { getMutableAIState } from '@ai-sdk/rsc';

export async function sendMessage(message: string) {
'use server';
Expand Down Expand Up @@ -226,7 +226,7 @@ To call the `sendMessage` action from the client, you can use the [`useActions`]
```tsx filename='app/page.tsx'
'use client';

import { useActions, useUIState } from 'ai/rsc';
import { useActions, useUIState } from '@ai-sdk/rsc';
import { AI } from './ai';

export default function Page() {
Expand Down Expand Up @@ -272,8 +272,8 @@ When the user submits a message, the `sendMessage` action is called with the mes
Action otherwise the streamed component will not show in the UI.
</Note>

To learn more, check out this [example](/examples/next-app/state-management/ai-ui-states) on managing AI and UI state using `ai/rsc`.
To learn more, check out this [example](/examples/next-app/state-management/ai-ui-states) on managing AI and UI state using `@ai-sdk/rsc`.

---

Next, you will learn how you can save and restore state with `ai/rsc`.
Next, you will learn how you can save and restore state with `@ai-sdk/rsc`.
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,4 @@ To learn more, check out this [example](/examples/next-app/state-management/save

---

Next, you will learn how you can use `ai/rsc` functions like `useActions` and `useUIState` to create interactive, multistep interfaces.
Next, you will learn how you can use `@ai-sdk/rsc` functions like `useActions` and `useUIState` to create interactive, multistep interfaces.
10 changes: 5 additions & 5 deletions content/docs/05-ai-sdk-rsc/04-multistep-interfaces.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ To build this kind of application you will leverage two concepts, **tool composi

## Overview

In order to build a multistep interface with `ai/rsc`, you will need a few things:
In order to build a multistep interface with `@ai-sdk/rsc`, you will need a few things:

- A Server Action that calls and returns the result from the `streamUI` function
- Tool(s) (sub-tasks necessary to complete your overall task)
Expand All @@ -49,7 +49,7 @@ The turn-by-turn implementation is the simplest form of multistep interfaces. In
In the following example, you specify two tools (`searchFlights` and `lookupFlight`) that the model can use to search for flights and lookup details for a specific flight.

```tsx filename="app/actions.tsx"
import { streamUI } from 'ai/rsc';
import { streamUI } from '@ai-sdk/rsc';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';

Expand Down Expand Up @@ -137,7 +137,7 @@ export async function submitUserMessage(input: string) {
Next, create an AI context that will hold the UI State and AI State.

```ts filename='app/ai.ts'
import { createAI } from 'ai/rsc';
import { createAI } from '@ai-sdk/rsc';
import { submitUserMessage } from './actions';

export const AI = createAI<any[], React.ReactNode[]>({
Expand Down Expand Up @@ -175,7 +175,7 @@ To call your Server Action, update your root page with the following:

import { useState } from 'react';
import { AI } from './ai';
import { useActions, useUIState } from 'ai/rsc';
import { useActions, useUIState } from '@ai-sdk/rsc';

export default function Page() {
const [input, setInput] = useState<string>('');
Expand Down Expand Up @@ -224,7 +224,7 @@ To add user interaction, you will have to convert the component into a client co
```tsx filename="components/flights.tsx"
'use client';

import { useActions, useUIState } from 'ai/rsc';
import { useActions, useUIState } from '@ai-sdk/rsc';
import { ReactNode } from 'react';

interface FlightsProps {
Expand Down
10 changes: 5 additions & 5 deletions content/docs/05-ai-sdk-rsc/05-streaming-values.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ This is useful when you want to stream:

## Creating a Streamable Value

You can import `createStreamableValue` from `ai/rsc` and use it to create a streamable value.
You can import `createStreamableValue` from `@ai-sdk/rsc` and use it to create a streamable value.

```tsx file='app/actions.ts'
'use server';

import { createStreamableValue } from 'ai/rsc';
import { createStreamableValue } from '@ai-sdk/rsc';

export const runThread = async () => {
const streamableStatus = createStreamableValue('thread.init');
Expand All @@ -70,7 +70,7 @@ export const runThread = async () => {
You can read streamable values on the client using `readStreamableValue`. It returns an async iterator that yields the value of the streamable as it is updated:

```tsx file='app/page.tsx'
import { readStreamableValue } from 'ai/rsc';
import { readStreamableValue } from '@ai-sdk/rsc';
import { runThread } from '@/actions';

export default function Page() {
Expand Down Expand Up @@ -103,7 +103,7 @@ Let's look at how you can use the `createStreamableUI` function with a Server Ac
```tsx filename='app/actions.tsx'
'use server';

import { createStreamableUI } from 'ai/rsc';
import { createStreamableUI } from '@ai-sdk/rsc';

export async function getWeather() {
const weatherUI = createStreamableUI();
Expand All @@ -128,7 +128,7 @@ On the client side, you can call the `getWeather` Server Action and render the r
'use client';

import { useState } from 'react';
import { readStreamableValue } from 'ai/rsc';
import { readStreamableValue } from '@ai-sdk/rsc';
import { getWeather } from '@/actions';

export default function Page() {
Expand Down
Loading
Loading