Skip to content

Commit 33cf848

Browse files
authored
feat(ai): pass messages to useChat({ onFinish }) (#8276)
## Background > In onFinish() parametere of useChat() function, I am not able to access the messages history that are returned by the useChat(). Here is a code snippet for the same: > > ``` > const { messages } = useChat({ > onFinish: ({ message }) => { > console.log("Messages are : ", messages); // Messages are : undefined > console.log("Message : ", message); // Message : last message > } > }) > ``` > > How can I get the list of all the messages in the onFinish parameter? —#8251 ## Summary The `messages` array is available anyway, passing it to the `onFinish` has no impact. ## Manual Verification yes 🤞🏼 ## Tasks - [x] Tests have been added / updated (for bug fixes / features) - [x] Documentation has been added / updated (for bug fixes / features) - [x] A _patch_ changeset for relevant packages has been added (for bug fixes / features - run `pnpm changeset` in the project root) - [x] Formatting issues have been fixed (run `pnpm prettier-fix` in the project root) - [x] I have reviewed this pull request (self-review) ## Future Work n/a ## Related Issues fixes #8251
1 parent 5306cdb commit 33cf848

File tree

8 files changed

+179
-3
lines changed

8 files changed

+179
-3
lines changed

.changeset/big-dolphins-heal.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'ai': patch
3+
---
4+
5+
feat(ai): pass messages to `useChat({ onFinish })`

content/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ Allows you to easily create a conversational user interface for your chatbot app
241241
},
242242
{
243243
name: 'onFinish',
244-
type: '(options: {message: UIMessage}) => void',
244+
type: '(options: {message: UIMessage, messages: UIMessage[]}) => void',
245245
isOptional: true,
246246
description:
247247
'Optional callback function that is called when the assistant message has finished streaming completely.',

packages/ai/src/ui/chat.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,17 @@ describe('Chat', () => {
9696

9797
const finishPromise = createResolvablePromise<void>();
9898

99+
let letOnFinishArgs: any = [];
99100
const chat = new TestChat({
100101
id: '123',
101102
generateId: mockId(),
102103
transport: new DefaultChatTransport({
103104
api: 'http://localhost:3000/api/chat',
104105
}),
105-
onFinish: () => finishPromise.resolve(),
106+
onFinish: (...args) => {
107+
letOnFinishArgs = args;
108+
return finishPromise.resolve();
109+
},
106110
});
107111

108112
chat.sendMessage({
@@ -111,6 +115,8 @@ describe('Chat', () => {
111115

112116
await finishPromise.promise;
113117

118+
expect(letOnFinishArgs[0].message).toBe(chat.lastMessage);
119+
expect(letOnFinishArgs[0].messages).toBe(chat.messages);
114120
expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(
115121
`
116122
{

packages/ai/src/ui/chat.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export type ChatOnDataCallback<UI_MESSAGE extends UIMessage> = (
9999

100100
export type ChatOnFinishCallback<UI_MESSAGE extends UIMessage> = (options: {
101101
message: UI_MESSAGE;
102+
messages: UI_MESSAGE[];
102103
}) => void;
103104

104105
export interface ChatInit<UI_MESSAGE extends UIMessage> {
@@ -562,7 +563,10 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
562563
},
563564
});
564565

565-
this.onFinish?.({ message: activeResponse.state.message });
566+
this.onFinish?.({
567+
message: activeResponse.state.message,
568+
messages: this.state.messages,
569+
});
566570

567571
this.setStatus({ status: 'ready' });
568572
} catch (err) {

packages/angular/src/lib/chat.ng.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,22 @@ describe('data protocol stream', () => {
188188
],
189189
role: 'assistant',
190190
},
191+
messages: [
192+
{
193+
id: 'id-1',
194+
role: 'user',
195+
metadata: undefined,
196+
parts: [{ text: 'hi', type: 'text' }],
197+
},
198+
{
199+
id: 'id-2',
200+
role: 'assistant',
201+
metadata: {
202+
example: 'metadata',
203+
},
204+
parts: [{ text: 'Hello, world.', type: 'text', state: 'done' }],
205+
},
206+
],
191207
});
192208
});
193209

@@ -352,6 +368,23 @@ describe('text stream', () => {
352368
{ text: 'Hello, world.', type: 'text', state: 'done' },
353369
],
354370
},
371+
messages: [
372+
{
373+
id: expect.any(String),
374+
role: 'user',
375+
metadata: undefined,
376+
parts: [{ text: 'hi', type: 'text' }],
377+
},
378+
{
379+
id: expect.any(String),
380+
role: 'assistant',
381+
metadata: undefined,
382+
parts: [
383+
{ type: 'step-start' },
384+
{ text: 'Hello, world.', type: 'text', state: 'done' },
385+
],
386+
},
387+
],
355388
});
356389
});
357390
});

packages/react/src/use-chat.ui.test.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,34 @@ describe('data protocol stream', () => {
360360
],
361361
"role": "assistant",
362362
},
363+
"messages": [
364+
{
365+
"id": "id-0",
366+
"metadata": undefined,
367+
"parts": [
368+
{
369+
"text": "hi",
370+
"type": "text",
371+
},
372+
],
373+
"role": "user",
374+
},
375+
{
376+
"id": "id-1",
377+
"metadata": {
378+
"example": "metadata",
379+
},
380+
"parts": [
381+
{
382+
"providerMetadata": undefined,
383+
"state": "done",
384+
"text": "Hello, world.",
385+
"type": "text",
386+
},
387+
],
388+
"role": "assistant",
389+
},
390+
],
363391
},
364392
]
365393
`);
@@ -521,6 +549,35 @@ describe('text stream', () => {
521549
],
522550
"role": "assistant",
523551
},
552+
"messages": [
553+
{
554+
"id": "id-1",
555+
"metadata": undefined,
556+
"parts": [
557+
{
558+
"text": "hi",
559+
"type": "text",
560+
},
561+
],
562+
"role": "user",
563+
},
564+
{
565+
"id": "id-2",
566+
"metadata": undefined,
567+
"parts": [
568+
{
569+
"type": "step-start",
570+
},
571+
{
572+
"providerMetadata": undefined,
573+
"state": "done",
574+
"text": "Hello, world.",
575+
"type": "text",
576+
},
577+
],
578+
"role": "assistant",
579+
},
580+
],
524581
},
525582
]
526583
`);

packages/svelte/src/chat.svelte.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,33 @@ describe('data protocol stream', () => {
191191
],
192192
role: 'assistant',
193193
},
194+
messages: [
195+
{
196+
id: 'id-1',
197+
metadata: undefined,
198+
parts: [
199+
{
200+
text: 'hi',
201+
type: 'text',
202+
},
203+
],
204+
role: 'user',
205+
},
206+
{
207+
id: 'id-2',
208+
metadata: {
209+
example: 'metadata',
210+
},
211+
parts: [
212+
{
213+
text: 'Hello, world.',
214+
type: 'text',
215+
state: 'done',
216+
},
217+
],
218+
role: 'assistant',
219+
},
220+
],
194221
});
195222
});
196223

@@ -355,6 +382,23 @@ describe('text stream', () => {
355382
{ text: 'Hello, world.', type: 'text', state: 'done' },
356383
],
357384
},
385+
messages: [
386+
{
387+
id: expect.any(String),
388+
role: 'user',
389+
metadata: undefined,
390+
parts: [{ text: 'hi', type: 'text' }],
391+
},
392+
{
393+
id: expect.any(String),
394+
role: 'assistant',
395+
metadata: undefined,
396+
parts: [
397+
{ type: 'step-start' },
398+
{ text: 'Hello, world.', type: 'text', state: 'done' },
399+
],
400+
},
401+
],
358402
});
359403
});
360404
});

packages/vue/src/chat.vue.ui.test.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,18 @@ describe('data protocol stream', () => {
255255
role: 'assistant',
256256
parts: [{ text: 'Hello, world.', type: 'text', state: 'done' }],
257257
},
258+
messages: [
259+
{
260+
id: expect.any(String),
261+
role: 'user',
262+
parts: [{ text: 'hi', type: 'text' }],
263+
},
264+
{
265+
id: expect.any(String),
266+
role: 'assistant',
267+
parts: [{ text: 'Hello, world.', type: 'text', state: 'done' }],
268+
},
269+
],
258270
},
259271
]);
260272
});
@@ -307,6 +319,21 @@ describe('text stream', () => {
307319
{ text: 'Hello, world.', type: 'text', state: 'done' },
308320
],
309321
},
322+
messages: [
323+
{
324+
id: expect.any(String),
325+
role: 'user',
326+
parts: [{ text: 'hi', type: 'text' }],
327+
},
328+
{
329+
id: expect.any(String),
330+
role: 'assistant',
331+
parts: [
332+
{ type: 'step-start' },
333+
{ text: 'Hello, world.', type: 'text', state: 'done' },
334+
],
335+
},
336+
],
310337
},
311338
]);
312339
});

0 commit comments

Comments
 (0)