Include the createdAt
field in AssistantResponse
and useAssistant
#3129
Description
Feature Description
For OpenAI, on the stream event thread.message.created
, the response is a message
object, which includes a created_at
field.
This event is received by the AssistantResponse
's ReadableStream
, but the object it sends down stream only contains id
, role
, and content
. Further, only id
is set from the value received from the event, so if a new role is introduced, or the structure of the content changes, this behavior will break.
At minimum, it makes sense to include the created_at
field, if not all fields, received by the stream event and pass them down stream.
Minimum solution: Add createdAt
Update AssistantResponse
lines 90-101 to
case 'thread.message.created': {
controller.enqueue(
textEncoder.encode(
formatStreamPart('assistant_message', {
id: value.data.id,
createdAt: value.data.created_at, // <--- add field
role: 'assistant',
content: [{ type: 'text', text: { value: '' } }],
}),
),
);
break;
}
Update useAssistant
lines 183-210 to
case 'assistant_message': {
setMessages(messages => [
...messages,
{
id: value.id,
createdAt: value.createdAt, // <--- add field
role: value.role,
content: value.content[0].text.value,
},
]);
break;
}
case 'text': {
// text delta - add to last message:
setMessages(messages => {
const lastMessage = messages[messages.length - 1];
return [
...messages.slice(0, messages.length - 1),
{
id: lastMessage.id,
createdAt: value.createdAt, // <--- add field
role: lastMessage.role,
content: lastMessage.content + value,
},
];
});
break;
}
Use Case
I want to show the created date and time for all messages in the history. This will primarily be helpful if a user returns to a previous thread. Adding this field will make it possible to display the dates without having to separately request them.
Additional context
The only reason I can think of not to include this value is for compatibility with non-OpenAI APIs. I don't know this package well enough to determine if that is an issue or not.
Ideally, this would include all possible values and if there are any incompatibilities with other APIs, they will be accounted for by using union or conditional types.