Skip to content

Commit 7a7b3bd

Browse files
committed
make streamUI() from @ai-sdk/rsc accept zod v4
1 parent dfb5749 commit 7a7b3bd

File tree

3 files changed

+25
-24
lines changed

3 files changed

+25
-24
lines changed

.changeset/eight-months-sip.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ All these methods now accept both a zod v4 and zod v3 schemas for validation:
1010
- `generateObject()`
1111
- `streamObject()`
1212
- `generateText()`
13+
- `experimental_useObject()` from `@ai-sdk/react`
14+
- `streamUI()` from `@ai-sdk/rsc`

packages/provider-utils/src/parse-json.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import {
44
TypeValidationError,
55
} from '@ai-sdk/provider';
66
import { secureJsonParse } from './secure-json-parse';
7-
import { ZodSchema } from 'zod';
7+
import * as z3 from 'zod/v3';
8+
import * as z4 from 'zod/v4/core';
89
import { safeValidateTypes, validateTypes } from './validate-types';
910
import { Validator } from './validator';
11+
import { InferSchema } from './schema';
1012

1113
/**
1214
* Parses a JSON string into an unknown object.
@@ -26,17 +28,17 @@ export async function parseJSON(options: {
2628
* @param {Validator<T>} schema - The schema to use for parsing the JSON.
2729
* @returns {Promise<T>} - The parsed object.
2830
*/
29-
export async function parseJSON<T>(options: {
31+
export async function parseJSON<SCHEMA extends z4.$ZodType | z3.Schema | Validator, VALUE = InferSchema<SCHEMA>>(options: {
3032
text: string;
31-
schema: ZodSchema<T> | Validator<T>;
32-
}): Promise<T>;
33-
export async function parseJSON<T>({
33+
schema: SCHEMA;
34+
}): Promise<VALUE>;
35+
export async function parseJSON<SCHEMA extends z4.$ZodType | z3.Schema | Validator, VALUE = InferSchema<SCHEMA>>({
3436
text,
3537
schema,
3638
}: {
3739
text: string;
38-
schema?: ZodSchema<T> | Validator<T>;
39-
}): Promise<T> {
40+
schema?: SCHEMA;
41+
}): Promise<VALUE> {
4042
try {
4143
const value = secureJsonParse(text);
4244

@@ -83,22 +85,22 @@ export async function safeParseJSON(options: {
8385
* @param {Validator<T>} schema - The schema to use for parsing the JSON.
8486
* @returns An object with either a `success` flag and the parsed and typed data, or a `success` flag and an error object.
8587
*/
86-
export async function safeParseJSON<T>(options: {
88+
export async function safeParseJSON<SCHEMA extends z4.$ZodType | z3.Schema | Validator, VALUE = InferSchema<SCHEMA>>(options: {
8789
text: string;
88-
schema: ZodSchema<T> | Validator<T>;
89-
}): Promise<ParseResult<T>>;
90-
export async function safeParseJSON<T>({
90+
schema: SCHEMA;
91+
}): Promise<ParseResult<VALUE>>;
92+
export async function safeParseJSON<SCHEMA extends z4.$ZodType | z3.Schema | Validator, VALUE = InferSchema<SCHEMA>>({
9193
text,
9294
schema,
9395
}: {
9496
text: string;
95-
schema?: ZodSchema<T> | Validator<T>;
96-
}): Promise<ParseResult<T>> {
97+
schema?: SCHEMA;
98+
}): Promise<ParseResult<VALUE>> {
9799
try {
98100
const value = secureJsonParse(text);
99101

100102
if (schema == null) {
101-
return { success: true, value: value as T, rawValue: value };
103+
return { success: true, value: value as VALUE, rawValue: value };
102104
}
103105

104106
return await safeValidateTypes({ value, schema });

packages/rsc/src/stream-ui/stream-ui.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { LanguageModelV2, LanguageModelV2CallWarning } from '@ai-sdk/provider';
2-
import { safeParseJSON } from '@ai-sdk/provider-utils';
2+
import { InferSchema, safeParseJSON } from '@ai-sdk/provider-utils';
33
import { ReactNode } from 'react';
4-
import { z } from 'zod';
4+
import * as z3 from 'zod/v3';
5+
import * as z4 from 'zod/v4/core';
56
import {
67
CallWarning,
78
FinishReason,
@@ -35,16 +36,12 @@ type Renderer<T extends Array<any>> = (
3536
| Generator<Streamable, Streamable, void>
3637
| AsyncGenerator<Streamable, Streamable, void>;
3738

38-
type RenderTool<PARAMETERS extends z.Schema | Schema = any> = {
39+
type RenderTool<PARAMETERS_SCHEMA extends z4.$ZodType | z3.Schema | Schema = any> = {
3940
description?: string;
40-
parameters: PARAMETERS;
41+
parameters: PARAMETERS_SCHEMA;
4142
generate?: Renderer<
4243
[
43-
PARAMETERS extends z.Schema
44-
? z.infer<PARAMETERS>
45-
: PARAMETERS extends Schema<infer T>
46-
? T
47-
: never,
44+
InferSchema<PARAMETERS_SCHEMA>,
4845
{
4946
toolName: string;
5047
toolCallId: string;
@@ -86,7 +83,7 @@ const defaultTextRenderer: RenderText = ({ content }: { content: string }) =>
8683
* `streamUI` is a helper function to create a streamable UI from LLMs.
8784
*/
8885
export async function streamUI<
89-
TOOLS extends { [name: string]: z.Schema | Schema } = {},
86+
TOOLS extends { [name: string]: z4.$ZodType | z3.Schema | Schema } = {},
9087
>({
9188
model,
9289
tools,

0 commit comments

Comments
 (0)