diff --git a/packages/ai/streams/assistant-response.ts b/packages/ai/streams/assistant-response.ts
index c4d872483c8f..40e4f83a880a 100644
--- a/packages/ai/streams/assistant-response.ts
+++ b/packages/ai/streams/assistant-response.ts
@@ -92,6 +92,7 @@ export function AssistantResponse(
textEncoder.encode(
formatStreamPart('assistant_message', {
id: value.data.id,
+ createdAt: value.data.created_at ? new Date(value.data.created_at * 1000) : undefined,
role: 'assistant',
content: [{ type: 'text', text: { value: '' } }],
}),
diff --git a/packages/react/src/use-assistant.ts b/packages/react/src/use-assistant.ts
index 7a366f451fe3..b3ead342bda7 100644
--- a/packages/react/src/use-assistant.ts
+++ b/packages/react/src/use-assistant.ts
@@ -186,6 +186,7 @@ export function useAssistant({
{
id: value.id,
role: value.role,
+ createdAt: value.createdAt,
content: value.content[0].text.value,
},
]);
@@ -201,6 +202,7 @@ export function useAssistant({
{
id: lastMessage.id,
role: lastMessage.role,
+ createdAt: lastMessage.createdAt,
content: lastMessage.content + value,
},
];
diff --git a/packages/react/src/use-assistant.ui.test.tsx b/packages/react/src/use-assistant.ui.test.tsx
index 37dd58405b49..80f6164946f1 100644
--- a/packages/react/src/use-assistant.ui.test.tsx
+++ b/packages/react/src/use-assistant.ui.test.tsx
@@ -23,6 +23,7 @@ describe('stream data stream', () => {
{m.role === 'user' ? 'User: ' : 'AI: '}
{m.content}
+ {m.createdAt && ` (Created at: ${m.createdAt})`}
))}
@@ -85,6 +86,91 @@ describe('stream data stream', () => {
);
});
+ it('should show streamed response with createdAt', async () => {
+ const { requestBody } = mockFetchDataStream({
+ url: 'https://example.com/api/assistant',
+ chunks: [
+ formatStreamPart('assistant_control_data', {
+ threadId: 't0',
+ messageId: 'm0',
+ }),
+ formatStreamPart('assistant_message', {
+ id: 'm0',
+ role: 'assistant',
+ createdAt: new Date(1727703377 * 1000),
+ content: [{ type: 'text', text: { value: '' } }],
+ }),
+ // text parts:
+ '0:"Hello"\n',
+ '0:","\n',
+ '0:" world"\n',
+ '0:"."\n',
+ ],
+ });
+
+ await userEvent.click(screen.getByTestId('do-append'));
+
+ await screen.findByTestId('message-0');
+ expect(screen.getByTestId('message-0')).toHaveTextContent('User: hi');
+
+ await screen.findByTestId('message-1');
+ const messageContent = screen.getByTestId('message-1').textContent;
+ console.log(messageContent);
+
+ expect(messageContent).toContain('AI: Hello, world.');
+ expect(messageContent).toContain(`Created at: ${new Date(1727703377 * 1000).toISOString()}`);
+
+ // check that correct information was sent to the server:
+ expect(await requestBody).toStrictEqual(
+ JSON.stringify({
+ threadId: null,
+ message: 'hi',
+ }),
+ );
+ });
+
+ it('should show streamed response without createdAt', async () => {
+ const { requestBody } = mockFetchDataStream({
+ url: 'https://example.com/api/assistant',
+ chunks: [
+ formatStreamPart('assistant_control_data', {
+ threadId: 't0',
+ messageId: 'm0',
+ }),
+ formatStreamPart('assistant_message', {
+ id: 'm0',
+ role: 'assistant',
+ content: [{ type: 'text', text: { value: '' } }],
+ }),
+ // text parts:
+ '0:"Hello"\n',
+ '0:","\n',
+ '0:" world"\n',
+ '0:"."\n',
+ ],
+ });
+
+ await userEvent.click(screen.getByTestId('do-append'));
+
+ await screen.findByTestId('message-0');
+ expect(screen.getByTestId('message-0')).toHaveTextContent('User: hi');
+
+ await screen.findByTestId('message-1');
+ const messageContent = screen.getByTestId('message-1').textContent;
+ console.log(messageContent);
+
+ expect(messageContent).toContain('AI: Hello, world.');
+ expect(messageContent).not.toContain('Created at:');
+
+ // check that correct information was sent to the server:
+ expect(await requestBody).toStrictEqual(
+ JSON.stringify({
+ threadId: null,
+ message: 'hi',
+ }),
+ );
+ });
+
it('should show error response', async () => {
mockFetchError({ statusCode: 500, errorMessage: 'Internal Error' });
diff --git a/packages/ui-utils/src/stream-parts.ts b/packages/ui-utils/src/stream-parts.ts
index 4b5470943ad8..b169c66c7fdb 100644
--- a/packages/ui-utils/src/stream-parts.ts
+++ b/packages/ui-utils/src/stream-parts.ts
@@ -121,7 +121,7 @@ const assistantMessageStreamPart: StreamPart<
return {
type: 'assistant_message',
- value: value as AssistantMessage,
+ value: value as unknown as AssistantMessage,
};
},
};
diff --git a/packages/ui-utils/src/types.ts b/packages/ui-utils/src/types.ts
index df59a5d42e34..53a30dd95a8e 100644
--- a/packages/ui-utils/src/types.ts
+++ b/packages/ui-utils/src/types.ts
@@ -604,6 +604,7 @@ export type JSONValue =
export type AssistantMessage = {
id: string;
role: 'assistant';
+ createdAt?: Date;
content: Array<{
type: 'text';
text: {