Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: vercel/ai
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ai@2.2.37
Choose a base ref
...
head repository: vercel/ai
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ai@3.0.0
Choose a head ref
  • 5 commits
  • 51 files changed
  • 5 contributors

Commits on Feb 27, 2024

  1. Revert unnecessary change to mistral test. (#1002)

    lgrammel authored Feb 27, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    1a46fc5 View commit details

Commits on Feb 28, 2024

  1. Add tools concept page to docs. (#1005)

    lgrammel authored Feb 28, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    1405b38 View commit details

Commits on Feb 29, 2024

  1. docs: Add docs for ai/rsc (#1007)

    jeremyphilemon authored Feb 29, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    cc28a6f View commit details
  2. feat: RSC (#1008)

    shuding authored Feb 29, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    51054a9 View commit details
  3. Version Packages (#1009)

    Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
    github-actions[bot] and github-actions[bot] authored Feb 29, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    69c8aa1 View commit details
Showing with 2,199 additions and 47 deletions.
  1. +10 −2 docs/pages/docs/api-reference.mdx
  2. +83 −0 docs/pages/docs/api-reference/create-ai.mdx
  3. +90 −0 docs/pages/docs/api-reference/create-streamable-ui.mdx
  4. +72 −0 docs/pages/docs/api-reference/create-streamable-value.mdx
  5. +22 −0 docs/pages/docs/api-reference/get-ai-state.mdx
  6. +92 −0 docs/pages/docs/api-reference/get-mutable-ai-state.mdx
  7. +74 −0 docs/pages/docs/api-reference/use-actions.mdx
  8. +71 −0 docs/pages/docs/api-reference/use-ai-state.mdx
  9. +58 −0 docs/pages/docs/api-reference/use-ui-state.mdx
  10. +2 −0 docs/pages/docs/concepts.mdx
  11. +3 −1 docs/pages/docs/concepts/_meta.json
  12. +300 −0 docs/pages/docs/concepts/ai-rsc.mdx
  13. +22 −0 docs/pages/docs/concepts/tools.mdx
  14. +9 −0 docs/pages/docs/guides/frameworks/nextjs-app.mdx
  15. +3 −3 docs/pages/docs/index.mdx
  16. +1 −1 examples/next-anthropic/package.json
  17. +1 −1 examples/next-aws-bedrock/package.json
  18. +1 −1 examples/next-fireworks/package.json
  19. +1 −1 examples/next-google-generative-ai/package.json
  20. +1 −1 examples/next-huggingface/package.json
  21. +1 −1 examples/next-inkeep/package.json
  22. +1 −1 examples/next-langchain/package.json
  23. +1 −1 examples/next-mistral/package.json
  24. +1 −1 examples/next-openai-pages/package.json
  25. +1 −1 examples/next-openai-rate-limits/package.json
  26. +1 −1 examples/next-openai/package.json
  27. +1 −1 examples/next-perplexity/package.json
  28. +1 −1 examples/next-replicate/package.json
  29. +1 −1 examples/nuxt-langchain/package.json
  30. +1 −1 examples/nuxt-openai/package.json
  31. +1 −1 examples/solidstart-openai/package.json
  32. +1 −1 examples/sveltekit-openai/package.json
  33. +6 −0 packages/core/CHANGELOG.md
  34. +18 −5 packages/core/package.json
  35. +207 −0 packages/core/rsc/ai-state.tsx
  36. +1 −0 packages/core/rsc/constants.ts
  37. +14 −0 packages/core/rsc/package.json
  38. +120 −0 packages/core/rsc/provider.tsx
  39. +7 −0 packages/core/rsc/rsc-client.ts
  40. +7 −0 packages/core/rsc/rsc-server.ts
  41. +10 −0 packages/core/rsc/rsc-shared.ts
  42. +15 −0 packages/core/rsc/rsc-types.ts
  43. +226 −0 packages/core/rsc/shared-client/context.tsx
  44. +59 −0 packages/core/rsc/shared-client/hooks.tsx
  45. +10 −0 packages/core/rsc/shared-client/index.ts
  46. +344 −0 packages/core/rsc/streamable.tsx
  47. +84 −0 packages/core/rsc/types.ts
  48. +72 −0 packages/core/rsc/utils.tsx
  49. +1 −1 packages/core/streams/mistral-stream.test.ts
  50. +18 −0 packages/core/tsup.config.ts
  51. +52 −18 pnpm-lock.yaml
12 changes: 10 additions & 2 deletions docs/pages/docs/api-reference.mdx
Original file line number Diff line number Diff line change
@@ -9,8 +9,16 @@ title: API Reference
- [`useChat`](./api-reference/use-chat)
- [`useCompletion`](./api-reference/use-completion)

## React Server Components

## AI RSC Helpers

- [`createAI`](./api-reference/create-ai)
- [`useUIState`](./api-reference/use-ui-state)
- [`useAIState`](./api-reference/use-ai-state)
- [`useActions`](./api-reference/use-actions)
- [`createStreamableUI`](./api-reference/create-streamable-ui)
- [`createStreamableValue`](./api-reference/create-streamable-value)
- [`getAIState`](./api-reference/get-ai-state)
- [`getMutableAIState`](./api-reference/get-mutable-ai-state)
- [`Tokens`](./api-reference/tokens)

## Streaming Helpers
83 changes: 83 additions & 0 deletions docs/pages/docs/api-reference/create-ai.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: createAI
layout:
toc: false
---

import { Tabs, Tab } from 'nextra-theme-docs';

# createAI

## `createAI`

`createAI` is a function that creates a new `ai/rsc` instance.

## Parameters

### `AIState`

`AIState` is a JSON representation of all the context the LLM needs to read. Usually for a chat app, `AIState` contains the textual conversation history between the user and the assistant. In practice, it can also be used to store other values and meta information such as `createdAt` of each message. `AIState` by default, can be accessed/modified on both Server and Client.

### `UIState`

`UIState` is what the application uses to display the UI. It is a fully client-side state (very similar to `useState`) and can keep data and UI elements returned by the LLM. This state can be anything, but can't be accessed on the server.

## Returns

The method returns an `<AI>` instance, which is a provider component that is used to wrap a part of your component tree and pass the context value down the tree. Any component that needs the context value can access it, no matter how deep it is in the component tree.

## Example

### Server-Side Setup

<Tabs items={['Next.js (App Router)']}>
<Tab>
We use `createAI` to initialize an `ai/rsc` instance on the server.

```tsx filename="app/action.tsx" {5-11}
import 'server-only'

import { createAI } from "ai/rsc";

export const AI = createAI({
actions: {
submitUserMessage,
},
initialUIState: [],
initialAIState: [],
});
```

</Tab>
</Tabs>

### Client-Side Setup

<Tabs items={['Next.js (App Router)']}>
<Tab>
The `ai/rsc` instance is then available to the client through the `<AI/>` context provider.

```tsx filename="app/layout.tsx" {11-13}
import { AI } from "./action";

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>
<AI>
{children}
</AI>
</body>
</html>
);
}

export const runtime = "edge";
```

</Tab>
</Tabs>
90 changes: 90 additions & 0 deletions docs/pages/docs/api-reference/create-streamable-ui.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
title: createStreamableUI
layout:
toc: false
---

import { Tabs, Tab } from 'nextra-theme-docs';

# createStreamableUI

## `createStreamableUI`

Create a piece of changable UI that can be streamed to the client. On the client side, it can be rendered as a normal React node.

## Parameters

Any valid `React.ReactNode` can be passed in such as `string` or `array`. But it will always be a UI node as a result and the client side can only render it, but not deconstructing it. Think of `createStreamableUI('hello')` gives you `<>hello<>`.

## Returns

This creates a special value that can be returned from Actions to the client. It holds a UI node inside and can be updated via the `update` method.

## Methods

### `update`

The `update` method is used to update the UI node. It takes a new UI node and replaces the old one.

### `append`

The `append` method is used to append a new UI node to the end of the old one.

### `done`

The `done` method is used to replace the UI node with a new one and mark it as done. This is useful for when you want to replace the loading UI with the final result.

## Example

<Tabs items={['Next.js (App Router)']}>
<Tab>
UI Streams are created on the server and streamed to the client.

```tsx filename="app/action.tsx" {8-15, 19-26, 30-37, 41}
import { createStreamableUI } from "ai/rsc";

async function confirmPurchase(symbol: string, amount: number) {
"use server";

const price = getStockPrice(symbol);

const uiStream = createStreamableUI(
<div className="inline-flex gap-1">
{spinner}
<p className="mb-2">
Purchasing {amount} ${symbol}...
</p>
</div>
);

await sleep(1000);

uiStream.update(
<div className="inline-flex gap-1">
{spinner}
<p className="mb-2">
Purchasing {amount} ${symbol}... working on it...
</p>
</div>
);

await sleep(1000);

uiStream.done(
<div>
<p className="mb-2">
You have successfully purchased {amount} ${symbol}.
Total cost: ${amount * price}
</p>
</div>
);

return {
id: Date.now(),
display: uiStream.value,
}
}
```

</Tab>
</Tabs>
72 changes: 72 additions & 0 deletions docs/pages/docs/api-reference/create-streamable-value.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
title: createStreamableValue
layout:
toc: false
---

import { Tabs, Tab } from 'nextra-theme-docs';

# createStreamableValue

## `createStreamableValue`

Create a wrapped, changable value that can be streamed to the client.

## Parameters

Any data (i.e. JSON) that RSC supports.

## Returns

This creates a special value that can be returned from Actions to the client. It holds the data inside and can be updated via the `update` method.

## Methods

### `update`

The `update` method is used to update the value of the streamable value.

### `done`

The `done` method is used to replace the old data with a new one and mark it as done. This is useful for when you want to replace the data with the final result.

## Example

<Tabs items={['Next.js (App Router)']}>
<Tab>
Value Streams are created on the server and streamed to the client.

```tsx filename="app/action.tsx" {6-9, 13-16, 20-23, 27}
import { createStreamableValue } from "ai/rsc";

async function getCustomerProfile(id: string) {
"use server";

const valueStream = createStreamableValue({
profile: null,
subscriptions: null,
})

const profile = await getProfile(id);

valueStream.update({
profile,
subscriptions: null,
});

const subscriptions = await getSubscriptions(profile.customerId);

valueStream.done({
profile,
subscriptions,
});

return {
id: Date.now(),
profile: valueStream.value,
}
}
```

</Tab>
</Tabs>
22 changes: 22 additions & 0 deletions docs/pages/docs/api-reference/get-ai-state.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: getAIState
layout:
toc: false
---

import { Tabs, Tab } from 'nextra-theme-docs';

# getAIState

## `getAIState`

`getAIState` is called within a Server Action to get the current [AI state](../concepts/ai-rsc#ai-state). If `key` is provided, it will return the value of the specified key in the AI state if it's an object. If it's not an object, it will throw an error.

The AI state returned is read-only so if you want to make updates to it, you should use [getMutableAIState](./get-mutable-ai-state).

## Example

```tsx
const state = getAIState(); // Get the entire AI state
const field = getAIState('key'); // Get the value of the key
```
92 changes: 92 additions & 0 deletions docs/pages/docs/api-reference/get-mutable-ai-state.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
title: getMutableAIState
layout:
toc: false
---

import { Tabs, Tab } from 'nextra-theme-docs';

# getMutableAIState

## `getMutableAIState`

`getMutableAIState` is called within a Server Action to make updates to the [AI state](../concepts/ai-rsc#aistate).

## Methods

### `get`

The `get` method returns a mutable copy of the AI state.

### `update`

The `update` method updates the AI state with a new value.

### `done`

You must call `.done()` when you're finished updating the AI state.

## Examples

```tsx
const state = getMutableAIState();
state.update({ ...state.get(), key: 'value' });
state.update(currentState => ({ ...currentState, key: 'value' }));
state.done();
```

```tsx
const state = getMutableAIState();
state.done({ ...state.get(), key: 'value' }); // Done with a new state
```

## Usage

<Tabs items={['Next.js (App Router)']}>
<Tab>

```tsx filename="app/action.tsx" {6-7, 19-22, 32}
import { getMutableAIState } from 'ai/rsc';

async function submitUserMessage(content: string) {
'use server'

const aiState = getMutableAIState()
aiState.update([...aiState.get(), { role: 'user', content }])

const reply = createStreamableUI(<BotMessage>{spinner}</BotMessage>)

const completion = runOpenAICompletion(openai, {
model: 'gpt-3.5-turbo',
stream: true,
messages: [
{
role: 'system',
content: 'You are a friendly assistant!',
},
...aiState.get().map((message: any) => ({
role: message.role,
content: message.content,
})),
],
functions: [],
})

completion.onTextContent((content: string, isFinal: boolean) => {
reply.update(<BotMessage>{content}</BotMessage>)

if (isFinal) {
reply.done()
aiState.done([...aiState.get(), { role: 'assistant', content }])
}
})

return {
id: Date.now(),
display: reply.value,
}
}
```

</Tab>
</Tabs>
Loading