Skip to content

Commit ab7ccef

Browse files
authored
chore (ai): change source ui message parts to source-url (#6387)
## Background Different types of citation sources are expected to be added in the future. To prevent nested switches in the ui code that uses them, they should be flattened into 'source-*' parts in ui messages. ## Summary Flatten url source parts into 'source-url' parts.
1 parent 5dab17d commit ab7ccef

File tree

12 files changed

+53
-73
lines changed

12 files changed

+53
-73
lines changed

‎.changeset/cuddly-eels-perform.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'ai': major
3+
---
4+
5+
chore (ai): change source ui message parts to source-url

‎examples/next-openai/app/api/use-chat-custom-sources/route.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ export async function POST(req: Request) {
1313
execute: writer => {
1414
// write a custom url source to the stream:
1515
writer.write({
16-
type: 'source',
17-
sourceType: 'url',
16+
type: 'source-url',
1817
id: 'source-1',
1918
url: 'https://example.com',
2019
title: 'Example Source',

‎examples/next-openai/app/use-chat-custom-sources/page.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@ export default function Chat() {
2525
<div key={message.id} className="whitespace-pre-wrap">
2626
{message.role === 'user' ? 'User: ' : 'AI: '}
2727
{message.parts
28-
.filter(part => part.type !== 'source')
28+
.filter(part => part.type !== 'source-url')
2929
.map((part, index) => {
3030
if (part.type === 'text') {
3131
return <div key={index}>{part.text}</div>;
3232
}
3333
})}
3434
{message.parts
35-
.filter(part => part.type === 'source')
35+
.filter(part => part.type === 'source-url')
3636
.map(part => (
37-
<span key={`source-${part.source.id}`}>
37+
<span key={`source-${part.sourceId}`}>
3838
[
3939
<a
40-
href={part.source.url}
40+
href={part.url}
4141
target="_blank"
4242
className="text-sm font-bold text-blue-500 hover:underline"
4343
>
44-
{part.source.title ?? new URL(part.source.url).hostname}
44+
{part.title ?? new URL(part.url).hostname}
4545
</a>
4646
]
4747
</span>

‎examples/next-openai/app/use-chat-resume/chat.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,13 @@ export function Chat({
6363

6464
<div>
6565
<div className="text-sm text-zinc-500">{message.id}</div>
66-
{message.parts
67-
.filter(part => part.type !== 'source')
68-
.map((part, partIndex) => {
69-
if (part.type === 'text') {
70-
return (
71-
<div key={`${message.id}-${partIndex}`}>{part.text}</div>
72-
);
73-
}
74-
})}
66+
{message.parts.map((part, partIndex) => {
67+
if (part.type === 'text') {
68+
return (
69+
<div key={`${message.id}-${partIndex}`}>{part.text}</div>
70+
);
71+
}
72+
})}
7573
</div>
7674
</div>
7775
))}

‎examples/next-openai/app/use-chat-sources/page.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@ export default function Chat() {
2525
<div key={message.id} className="whitespace-pre-wrap">
2626
{message.role === 'user' ? 'User: ' : 'AI: '}
2727
{message.parts
28-
.filter(part => part.type !== 'source')
28+
.filter(part => part.type !== 'source-url')
2929
.map((part, index) => {
3030
if (part.type === 'text') {
3131
return <div key={index}>{part.text}</div>;
3232
}
3333
})}
3434
{message.parts
35-
.filter(part => part.type === 'source')
35+
.filter(part => part.type === 'source-url')
3636
.map(part => (
37-
<span key={`source-${part.source.id}`}>
37+
<span key={`source-${part.sourceId}`}>
3838
[
3939
<a
40-
href={part.source.url}
40+
href={part.url}
4141
target="_blank"
4242
className="text-sm font-bold text-blue-500 hover:underline"
4343
>
44-
{part.source.title ?? new URL(part.source.url).hostname}
44+
{part.title ?? new URL(part.url).hostname}
4545
</a>
4646
]
4747
</span>

‎packages/ai/core/generate-text/__snapshots__/stream-text.test.ts.snap

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3505,9 +3505,8 @@ exports[`streamText > result.toUIMessageStream > should send source content when
35053505
"custom": "value",
35063506
},
35073507
},
3508-
"sourceType": "url",
35093508
"title": "Example",
3510-
"type": "source",
3509+
"type": "source-url",
35113510
"url": "https://example.com",
35123511
},
35133512
{
@@ -3521,9 +3520,8 @@ exports[`streamText > result.toUIMessageStream > should send source content when
35213520
"custom": "value2",
35223521
},
35233522
},
3524-
"sourceType": "url",
35253523
"title": "Example 2",
3526-
"type": "source",
3524+
"type": "source-url",
35273525
"url": "https://example.com/2",
35283526
},
35293527
{

‎packages/ai/core/generate-text/stream-text.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,13 +1106,13 @@ describe('streamText', () => {
11061106
"data: {"type":"start-step"}
11071107
11081108
",
1109-
"data: {"type":"source","sourceType":"url","id":"123","url":"https://example.com","title":"Example","providerMetadata":{"provider":{"custom":"value"}}}
1109+
"data: {"type":"source-url","id":"123","url":"https://example.com","title":"Example","providerMetadata":{"provider":{"custom":"value"}}}
11101110
11111111
",
11121112
"data: {"type":"text","text":"Hello!"}
11131113
11141114
",
1115-
"data: {"type":"source","sourceType":"url","id":"456","url":"https://example.com/2","title":"Example 2","providerMetadata":{"provider":{"custom":"value2"}}}
1115+
"data: {"type":"source-url","id":"456","url":"https://example.com/2","title":"Example 2","providerMetadata":{"provider":{"custom":"value2"}}}
11161116
11171117
",
11181118
"data: {"type":"finish-step"}

‎packages/ai/core/generate-text/stream-text.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,8 +1414,7 @@ However, the LLM results are expected to be small enough to not cause issues.
14141414
case 'source': {
14151415
if (sendSources) {
14161416
controller.enqueue({
1417-
type: 'source',
1418-
sourceType: part.sourceType,
1417+
type: 'source-url',
14191418
id: part.id,
14201419
url: part.url,
14211420
title: part.title,

‎packages/ai/src/ui-message-stream/ui-message-stream-parts.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,7 @@ export type UIMessageStreamPart =
124124
providerMetadata?: ProviderMetadata;
125125
}
126126
| {
127-
// TODO evaluate flattening sources similar to data ui parts
128-
type: 'source';
129-
sourceType: 'url';
127+
type: 'source-url';
130128
id: string;
131129
url: string;
132130
title?: string;

‎packages/ai/src/ui/process-ui-message-stream.test.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,8 +2548,7 @@ describe('processUIMessageStream', () => {
25482548
{ type: 'start-step' },
25492549
{ type: 'text', text: 'The weather in London is sunny.' },
25502550
{
2551-
type: 'source',
2552-
sourceType: 'url',
2551+
type: 'source-url',
25532552
id: 'source-id',
25542553
url: 'https://example.com',
25552554
title: 'Example',
@@ -2620,14 +2619,11 @@ describe('processUIMessageStream', () => {
26202619
"type": "text",
26212620
},
26222621
{
2623-
"source": {
2624-
"id": "source-id",
2625-
"providerMetadata": undefined,
2626-
"sourceType": "url",
2627-
"title": "Example",
2628-
"url": "https://example.com",
2629-
},
2630-
"type": "source",
2622+
"providerMetadata": undefined,
2623+
"sourceId": "source-id",
2624+
"title": "Example",
2625+
"type": "source-url",
2626+
"url": "https://example.com",
26312627
},
26322628
],
26332629
"role": "assistant",
@@ -2651,14 +2647,11 @@ describe('processUIMessageStream', () => {
26512647
"type": "text",
26522648
},
26532649
{
2654-
"source": {
2655-
"id": "source-id",
2656-
"providerMetadata": undefined,
2657-
"sourceType": "url",
2658-
"title": "Example",
2659-
"url": "https://example.com",
2660-
},
2661-
"type": "source",
2650+
"providerMetadata": undefined,
2651+
"sourceId": "source-id",
2652+
"title": "Example",
2653+
"type": "source-url",
2654+
"url": "https://example.com",
26622655
},
26632656
],
26642657
"role": "assistant",

0 commit comments

Comments
 (0)