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
3 changes: 3 additions & 0 deletions packages/assistant-ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ can implement that policy using the runtime's continuation API.
For a Vercel AI SDK runtime, the package provides that policy as an optional
convenience helper. Install `ai` and import it from the `/ai-sdk` subpath:

The helper supports AI SDK 6 and 7. AI SDK 7 requires Node.js 22 or later and
an ESM application.

```tsx
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
import { shouldContinueAfterOpenUIPrompt } from "@openuidev/assistant-ui/ai-sdk";
Expand Down
9 changes: 7 additions & 2 deletions packages/react-headless/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@ The Vercel AI SDK integration has one optional peer dependency:

```bash
npm install ai@^6
# or, on Node.js 22+ with ESM
npm install ai@^7
```

Both AI SDK 6 and 7 are supported. AI SDK 7 requires Node.js 22 or later and
is ESM-only.

## Overview

Use `@openuidev/react-headless` when you want OpenUI's chat behavior without OpenUI's visual components:
Expand Down Expand Up @@ -185,7 +190,7 @@ const llm = fetchLLM({ url: "/api/chat", streamAdapter: openAIAdapter() });
| `openAIAdapter()` | Parses OpenAI Chat Completions streaming (`ChatCompletionChunk`) |
| `openAIResponsesAdapter()` | Parses OpenAI Responses API streaming (`ResponseStreamEvent`) |
| `openAIReadableStreamAdapter()` | Parses OpenAI SDK's `Stream.toReadableStream()` NDJSON output |
| `vercelAIAdapter()` | Parses Vercel AI SDK v6 UIMessage streams from `toUIMessageStreamResponse()` |
| `vercelAIAdapter()` | Parses Vercel AI SDK v6 and v7 UIMessage streams |

For a Vercel AI SDK route, use its stream adapter and message format together:

Expand Down Expand Up @@ -236,7 +241,7 @@ const llm = fetchLLM({
| `identityMessageFormat` | Default format when messages are already AG-UI shaped |
| `openAIMessageFormat` | Converts to/from OpenAI `ChatCompletionMessageParam[]` |
| `openAIConversationMessageFormat` | Converts to/from OpenAI Responses API `ResponseInputItem[]` |
| `vercelAIMessageFormat` | Converts to/from Vercel AI SDK v6 `UIMessage[]` |
| `vercelAIMessageFormat` | Converts to/from Vercel AI SDK v6 and v7 `UIMessage[]` |

### Custom format

Expand Down
4 changes: 2 additions & 2 deletions packages/react-headless/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@openuidev/react-headless",
"version": "0.9.7",
"version": "0.9.8",
"description": "Headless React primitives for AI chat — state management, streaming adapters for OpenAI, Vercel AI SDK, and AG-UI, message format converters, and thread management for OpenUI generative UI apps",
"license": "MIT",
"type": "module",
Expand Down Expand Up @@ -39,7 +39,7 @@
"ci": "pnpm run lint:check && pnpm run format:check"
},
"peerDependencies": {
"ai": "^6.0.0",
"ai": "^6.0.0 || ^7.0.0",
"react": "catalog:",
"zustand": "catalog:"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ describe("vercelAIAdapter", () => {

try {
await expect(collect(vercelAIAdapter().parse(makeResponse("")))).rejects.toThrow(
'vercelAIAdapter requires the optional peer dependency "ai" (Vercel AI SDK v6).',
'vercelAIAdapter requires the optional peer dependency "ai" (Vercel AI SDK v6 or v7).',
);
} finally {
vi.doUnmock("ai");
Expand Down
5 changes: 2 additions & 3 deletions packages/react-headless/src/stream/adapters/vercel-ai-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { UIMessage, UIMessageChunk } from "ai";
import { AGUIEvent, EventType, StreamProtocolAdapter } from "../../types";

const MISSING_AI_SDK_MESSAGE =
'vercelAIAdapter requires the optional peer dependency "ai" (Vercel AI SDK v6).';
'vercelAIAdapter requires the optional peer dependency "ai" (Vercel AI SDK v6 or v7).';
const PROVIDER_EXECUTED_TOOLS_UNSUPPORTED_MESSAGE =
"Vercel AI SDK provider-executed tools are not supported because AG-UI messages cannot preserve providerExecuted semantics.";
const TOOL_EXECUTION_DENIED_MESSAGE = "Tool execution was denied";
Expand Down Expand Up @@ -64,8 +64,7 @@ function toolResult(toolCallId: string, content: string, error?: string): AGUIEv
}

/**
* Adapter for Vercel AI SDK v6 UIMessage streams, such as responses returned by
* `toUIMessageStreamResponse()`.
* Adapter for Vercel AI SDK v6 and v7 UIMessage streams.
*
* The AI SDK is loaded only when parsing begins so it can remain an optional
* peer dependency for consumers that use other stream adapters. Its
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ function fromVercelMessages(data: unknown): Message[] {
}

/**
* Converts messages between AG-UI and Vercel AI SDK v6 `UIMessage` format.
* Converts messages between AG-UI and Vercel AI SDK v6 and v7 `UIMessage` format.
*
* AG-UI tool-result messages are folded into the matching assistant tool part,
* because `UIMessage` represents a tool invocation and its result as one part.
Expand Down
Loading