ai 2.2.37 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,6 +4,7 @@ The Vercel AI SDK is **a library for building AI-powered streaming text and chat
4
4
 
5
5
  ## Features
6
6
 
7
+ - React Server Components API for streaming Generative UI
7
8
  - [SWR](https://swr.vercel.app)-powered React, Svelte, Vue and Solid helpers for streaming text responses and building chat and completion UIs
8
9
  - First-class support for [LangChain](https://js.langchain.com/docs) and [OpenAI](https://openai.com), [Anthropic](https://www.anthropic.com), [Cohere](https://cohere.com), [Hugging Face](https://huggingface.co), [Fireworks](https://app.fireworks.ai) and [Replicate](https://replicate.com)
9
10
  - Node.js, Serverless, and [Edge Runtime](https://edge-runtime.vercel.app/) support
@@ -15,66 +16,6 @@ The Vercel AI SDK is **a library for building AI-powered streaming text and chat
15
16
  pnpm install ai
16
17
  ```
17
18
 
18
- View the full documentation and examples on [sdk.vercel.ai/docs](https://sdk.vercel.ai/docs)
19
-
20
- ## Example: An AI Chatbot with Next.js and OpenAI
21
-
22
- With the Vercel AI SDK, you can build a ChatGPT-like app in just a few lines of code:
23
-
24
- ```tsx
25
- // ./app/api/chat/route.js
26
- import OpenAI from 'openai';
27
- import { OpenAIStream, StreamingTextResponse } from 'ai';
28
-
29
- const openai = new OpenAI({
30
- apiKey: process.env.OPENAI_API_KEY,
31
- });
32
-
33
- export const runtime = 'edge';
34
-
35
- export async function POST(req) {
36
- const { messages } = await req.json();
37
- const response = await openai.chat.completions.create({
38
- model: 'gpt-4',
39
- stream: true,
40
- messages,
41
- });
42
- const stream = OpenAIStream(response);
43
- return new StreamingTextResponse(stream);
44
- }
45
- ```
46
-
47
- ```tsx
48
- // ./app/page.js
49
- 'use client';
50
-
51
- import { useChat } from 'ai/react';
52
-
53
- export default function Chat() {
54
- const { messages, input, handleInputChange, handleSubmit } = useChat();
55
-
56
- return (
57
- <div>
58
- {messages.map(m => (
59
- <div key={m.id}>
60
- {m.role}: {m.content}
61
- </div>
62
- ))}
63
-
64
- <form onSubmit={handleSubmit}>
65
- <input
66
- value={input}
67
- placeholder="Say something..."
68
- onChange={handleInputChange}
69
- />
70
- </form>
71
- </div>
72
- );
73
- }
74
- ```
75
-
76
- ---
77
-
78
19
  View the full documentation and examples on [sdk.vercel.ai/docs](https://sdk.vercel.ai/docs).
79
20
 
80
21
  ## Authors
package/dist/index.d.ts CHANGED
@@ -602,6 +602,8 @@ interface AIStreamCallbacksAndOptions {
602
602
  onFinal?: (completion: string) => Promise<void> | void;
603
603
  /** `onToken`: Called for each tokenized message. */
604
604
  onToken?: (token: string) => Promise<void> | void;
605
+ /** `onText`: Called for each text chunk. */
606
+ onText?: (text: string) => Promise<void> | void;
605
607
  /**
606
608
  * A flag for enabling the experimental_StreamData class and the new protocol.
607
609
  * @see https://github.com/vercel-labs/ai/pull/425
@@ -626,14 +628,20 @@ interface AIStreamParserOptions {
626
628
  * @returns {string | void} The parsed data or void.
627
629
  */
628
630
  interface AIStreamParser {
629
- (data: string, options: AIStreamParserOptions): string | void;
631
+ (data: string, options: AIStreamParserOptions): string | void | {
632
+ isText: false;
633
+ content: string;
634
+ };
630
635
  }
631
636
  /**
632
637
  * Creates a TransformStream that parses events from an EventSource stream using a custom parser.
633
638
  * @param {AIStreamParser} customParser - Function to handle event data.
634
639
  * @returns {TransformStream<Uint8Array, string>} TransformStream parsing events.
635
640
  */
636
- declare function createEventStreamTransformer(customParser?: AIStreamParser): TransformStream<Uint8Array, string>;
641
+ declare function createEventStreamTransformer(customParser?: AIStreamParser): TransformStream<Uint8Array, string | {
642
+ isText: false;
643
+ content: string;
644
+ }>;
637
645
  /**
638
646
  * Creates a transform stream that encodes input messages and invokes optional callback functions.
639
647
  * The transform stream uses the provided callbacks to execute custom logic at different stages of the stream's lifecycle.
@@ -656,7 +664,10 @@ declare function createEventStreamTransformer(customParser?: AIStreamParser): Tr
656
664
  * };
657
665
  * const transformer = createCallbacksTransformer(callbacks);
658
666
  */
659
- declare function createCallbacksTransformer(cb: AIStreamCallbacksAndOptions | OpenAIStreamCallbacks | undefined): TransformStream<string, Uint8Array>;
667
+ declare function createCallbacksTransformer(cb: AIStreamCallbacksAndOptions | OpenAIStreamCallbacks | undefined): TransformStream<string | {
668
+ isText: false;
669
+ content: string;
670
+ }, Uint8Array>;
660
671
  /**
661
672
  * Returns a stateful function that, when invoked, trims leading whitespace
662
673
  * from the input text. The trimming only occurs on the first invocation, ensuring that
package/dist/index.js CHANGED
@@ -296,10 +296,14 @@ function createCallbacksTransformer(cb) {
296
296
  await callbacks.onStart();
297
297
  },
298
298
  async transform(message, controller) {
299
- controller.enqueue(textEncoder.encode(message));
300
- aggregatedResponse += message;
299
+ const content = typeof message === "string" ? message : message.content;
300
+ controller.enqueue(textEncoder.encode(content));
301
+ aggregatedResponse += content;
301
302
  if (callbacks.onToken)
302
- await callbacks.onToken(message);
303
+ await callbacks.onToken(content);
304
+ if (callbacks.onText && typeof message === "string") {
305
+ await callbacks.onText(message);
306
+ }
303
307
  },
304
308
  async flush() {
305
309
  const isOpenAICallbacks = isOfTypeOpenAIStreamCallbacks(callbacks);
@@ -899,25 +903,46 @@ function chunkToText() {
899
903
  const delta = (_a = json.choices[0]) == null ? void 0 : _a.delta;
900
904
  if ((_b = delta.function_call) == null ? void 0 : _b.name) {
901
905
  isFunctionStreamingIn = true;
902
- return `{"function_call": {"name": "${delta.function_call.name}", "arguments": "`;
906
+ return {
907
+ isText: false,
908
+ content: `{"function_call": {"name": "${delta.function_call.name}", "arguments": "`
909
+ };
903
910
  } else if ((_e = (_d = (_c = delta.tool_calls) == null ? void 0 : _c[0]) == null ? void 0 : _d.function) == null ? void 0 : _e.name) {
904
911
  isFunctionStreamingIn = true;
905
912
  const toolCall = delta.tool_calls[0];
906
913
  if (toolCall.index === 0) {
907
- return `{"tool_calls":[ {"id": "${toolCall.id}", "type": "function", "function": {"name": "${(_f = toolCall.function) == null ? void 0 : _f.name}", "arguments": "`;
914
+ return {
915
+ isText: false,
916
+ content: `{"tool_calls":[ {"id": "${toolCall.id}", "type": "function", "function": {"name": "${(_f = toolCall.function) == null ? void 0 : _f.name}", "arguments": "`
917
+ };
908
918
  } else {
909
- return `"}}, {"id": "${toolCall.id}", "type": "function", "function": {"name": "${(_g = toolCall.function) == null ? void 0 : _g.name}", "arguments": "`;
919
+ return {
920
+ isText: false,
921
+ content: `"}}, {"id": "${toolCall.id}", "type": "function", "function": {"name": "${(_g = toolCall.function) == null ? void 0 : _g.name}", "arguments": "`
922
+ };
910
923
  }
911
924
  } else if ((_h = delta.function_call) == null ? void 0 : _h.arguments) {
912
- return cleanupArguments((_i = delta.function_call) == null ? void 0 : _i.arguments);
925
+ return {
926
+ isText: false,
927
+ content: cleanupArguments((_i = delta.function_call) == null ? void 0 : _i.arguments)
928
+ };
913
929
  } else if ((_l = (_k = (_j = delta.tool_calls) == null ? void 0 : _j[0]) == null ? void 0 : _k.function) == null ? void 0 : _l.arguments) {
914
- return cleanupArguments((_o = (_n = (_m = delta.tool_calls) == null ? void 0 : _m[0]) == null ? void 0 : _n.function) == null ? void 0 : _o.arguments);
930
+ return {
931
+ isText: false,
932
+ content: cleanupArguments((_o = (_n = (_m = delta.tool_calls) == null ? void 0 : _m[0]) == null ? void 0 : _n.function) == null ? void 0 : _o.arguments)
933
+ };
915
934
  } else if (isFunctionStreamingIn && (((_p = json.choices[0]) == null ? void 0 : _p.finish_reason) === "function_call" || ((_q = json.choices[0]) == null ? void 0 : _q.finish_reason) === "stop")) {
916
935
  isFunctionStreamingIn = false;
917
- return '"}}';
936
+ return {
937
+ isText: false,
938
+ content: '"}}'
939
+ };
918
940
  } else if (isFunctionStreamingIn && ((_r = json.choices[0]) == null ? void 0 : _r.finish_reason) === "tool_calls") {
919
941
  isFunctionStreamingIn = false;
920
- return '"}}]}';
942
+ return {
943
+ isText: false,
944
+ content: '"}}]}'
945
+ };
921
946
  }
922
947
  }
923
948
  const text = trimStartOfStream(