@@ -21,6 +21,7 @@ describe('Message Converters', () => {
2121
2222 expect ( result ) . toEqual ( [
2323 {
24+ id : 'msg-1' ,
2425 role : 'user' ,
2526 content : 'Hello' ,
2627 } ,
@@ -41,6 +42,7 @@ describe('Message Converters', () => {
4142
4243 expect ( result ) . toEqual ( [
4344 {
45+ id : 'msg-1' ,
4446 role : 'user' ,
4547 content : 'Hello world!' ,
4648 } ,
@@ -345,6 +347,62 @@ describe('Message Converters', () => {
345347 expect ( result [ 1 ] ?. content ) . toBe ( '{"temp": 72}' )
346348 } )
347349
350+ it ( 'should preserve the UI message id on every generated model message' , ( ) => {
351+ const uiMessage : UIMessage = {
352+ id : 'assistant-1' ,
353+ role : 'assistant' ,
354+ parts : [
355+ { type : 'text' , content : 'Let me check.' } ,
356+ {
357+ type : 'tool-call' ,
358+ id : 'tc-explicit' ,
359+ name : 'getWeather' ,
360+ arguments : '{}' ,
361+ state : 'input-complete' ,
362+ } ,
363+ {
364+ type : 'tool-result' ,
365+ toolCallId : 'tc-explicit' ,
366+ content : '{}' ,
367+ state : 'complete' ,
368+ } ,
369+ { type : 'text' , content : 'I found it.' } ,
370+ {
371+ type : 'tool-call' ,
372+ id : 'tc-output' ,
373+ name : 'getForecast' ,
374+ arguments : '{}' ,
375+ state : 'complete' ,
376+ output : { temperature : 72 } ,
377+ } ,
378+ {
379+ type : 'tool-call' ,
380+ id : 'tc-approval' ,
381+ name : 'deleteForecast' ,
382+ arguments : '{}' ,
383+ state : 'approval-responded' ,
384+ approval : {
385+ id : 'approval-tc-approval' ,
386+ needsApproval : true ,
387+ approved : false ,
388+ } ,
389+ } ,
390+ ] ,
391+ }
392+
393+ const result = uiMessageToModelMessages ( uiMessage )
394+
395+ expect ( result ) . toHaveLength ( 5 )
396+ expect ( result . every ( ( message ) => message . id === uiMessage . id ) ) . toBe ( true )
397+ expect ( result . map ( ( message ) => message . role ) ) . toEqual ( [
398+ 'assistant' ,
399+ 'tool' ,
400+ 'assistant' ,
401+ 'tool' ,
402+ 'tool' ,
403+ ] )
404+ } )
405+
348406 it ( 'should preserve interleaving of text, tool calls, and tool results' , ( ) => {
349407 const uiMessage : UIMessage = {
350408 id : 'msg-1' ,
@@ -1132,7 +1190,7 @@ describe('Message Converters', () => {
11321190
11331191 const result = convertMessagesToModelMessages ( messages )
11341192
1135- expect ( result ) . toEqual ( [ { role : 'user' , content : 'Hello' } ] )
1193+ expect ( result ) . toEqual ( [ { id : 'msg-1' , role : 'user' , content : 'Hello' } ] )
11361194 } )
11371195
11381196 it ( 'should handle mixed UIMessage and ModelMessage array' , ( ) => {
@@ -1148,7 +1206,7 @@ describe('Message Converters', () => {
11481206 const result = convertMessagesToModelMessages ( messages )
11491207
11501208 expect ( result ) . toEqual ( [
1151- { role : 'user' , content : 'Hello' } ,
1209+ { id : 'msg-1' , role : 'user' , content : 'Hello' } ,
11521210 { role : 'assistant' , content : 'Hi there!' } ,
11531211 ] )
11541212 } )
@@ -1361,8 +1419,8 @@ describe('Message Converters', () => {
13611419 describe ( 'Round-trip symmetry: Model -> UI -> Model' , ( ) => {
13621420 it ( 'should round-trip simple text messages' , ( ) => {
13631421 const original : Array < ModelMessage > = [
1364- { role : 'user' , content : 'Hello' } ,
1365- { role : 'assistant' , content : 'Hi there!' } ,
1422+ { id : 'user-1' , role : 'user' , content : 'Hello' } ,
1423+ { id : 'assistant-1' , role : 'assistant' , content : 'Hi there!' } ,
13661424 ]
13671425
13681426 const uiMessages = modelMessagesToUIMessages ( original )
@@ -1374,6 +1432,7 @@ describe('Message Converters', () => {
13741432 it ( 'should round-trip assistant with toolCalls + tool result' , ( ) => {
13751433 const original : Array < ModelMessage > = [
13761434 {
1435+ id : 'assistant-1' ,
13771436 role : 'assistant' ,
13781437 content : 'Let me check.' ,
13791438 toolCalls : [
@@ -1385,6 +1444,7 @@ describe('Message Converters', () => {
13851444 ] ,
13861445 } ,
13871446 {
1447+ id : 'assistant-1' ,
13881448 role : 'tool' ,
13891449 content : '{"temp": 72}' ,
13901450 toolCallId : 'tc-1' ,
@@ -1400,6 +1460,7 @@ describe('Message Converters', () => {
14001460 it ( 'should round-trip multimodal content array' , ( ) => {
14011461 const original : Array < ModelMessage > = [
14021462 {
1463+ id : 'user-1' ,
14031464 role : 'user' ,
14041465 content : [
14051466 { type : 'text' , content : 'What is this?' } ,
@@ -1419,8 +1480,9 @@ describe('Message Converters', () => {
14191480
14201481 it ( 'should round-trip multi-round tool conversation' , ( ) => {
14211482 const original : Array < ModelMessage > = [
1422- { role : 'user' , content : 'Check guitars' } ,
1483+ { id : 'user-1' , role : 'user' , content : 'Check guitars' } ,
14231484 {
1485+ id : 'assistant-1' ,
14241486 role : 'assistant' ,
14251487 content : 'Checking.' ,
14261488 toolCalls : [
@@ -1431,8 +1493,14 @@ describe('Message Converters', () => {
14311493 } ,
14321494 ] ,
14331495 } ,
1434- { role : 'tool' , content : '[{"id":7}]' , toolCallId : 'tc-1' } ,
14351496 {
1497+ id : 'assistant-1' ,
1498+ role : 'tool' ,
1499+ content : '[{"id":7}]' ,
1500+ toolCallId : 'tc-1' ,
1501+ } ,
1502+ {
1503+ id : 'assistant-2' ,
14361504 role : 'assistant' ,
14371505 content : 'Found one!' ,
14381506 toolCalls : [
@@ -1444,11 +1512,16 @@ describe('Message Converters', () => {
14441512 ] ,
14451513 } ,
14461514 {
1515+ id : 'assistant-2' ,
14471516 role : 'tool' ,
14481517 content : '{"recommended":true}' ,
14491518 toolCallId : 'tc-2' ,
14501519 } ,
1451- { role : 'assistant' , content : 'Here is my recommendation.' } ,
1520+ {
1521+ id : 'assistant-3' ,
1522+ role : 'assistant' ,
1523+ content : 'Here is my recommendation.' ,
1524+ } ,
14521525 ]
14531526
14541527 const uiMessages = modelMessagesToUIMessages ( original )
@@ -1460,6 +1533,7 @@ describe('Message Converters', () => {
14601533 it ( 'should round-trip assistant with null content and toolCalls' , ( ) => {
14611534 const original : Array < ModelMessage > = [
14621535 {
1536+ id : 'assistant-1' ,
14631537 role : 'assistant' ,
14641538 content : null ,
14651539 toolCalls : [
@@ -1470,7 +1544,12 @@ describe('Message Converters', () => {
14701544 } ,
14711545 ] ,
14721546 } ,
1473- { role : 'tool' , content : '{"temp":72}' , toolCallId : 'tc-1' } ,
1547+ {
1548+ id : 'assistant-1' ,
1549+ role : 'tool' ,
1550+ content : '{"temp":72}' ,
1551+ toolCallId : 'tc-1' ,
1552+ } ,
14741553 ]
14751554
14761555 const uiMessages = modelMessagesToUIMessages ( original )
0 commit comments