@@ -24,7 +24,7 @@ import { Session } from "@/session/session"
2424import { MessageID , PartID , SessionID , type SessionID as SessionIDType } from "../../src/session/schema"
2525import { MessageV2 } from "../../src/session/message-v2"
2626import { Database } from "@opencode-ai/core/database/database"
27- import { SessionMessageTable , SessionTable } from "@opencode-ai/core/session/sql"
27+ import { MessageTable , SessionMessageTable , SessionTable } from "@opencode-ai/core/session/sql"
2828import { SessionMessage } from "@opencode-ai/core/session/message"
2929import { ModelV2 } from "@opencode-ai/core/model"
3030import { ProviderV2 } from "@opencode-ai/core/provider"
@@ -182,6 +182,37 @@ const insertCorruptV2Message = (sessionID: SessionIDType, time = 1) =>
182182 . pipe ( Effect . orDie )
183183 } )
184184
185+ const insertLegacyMessageV2Assistant = ( sessionID : SessionIDType , parentID : MessageID ) =>
186+ Effect . sync ( ( ) => {
187+ Database . use ( ( db ) =>
188+ db
189+ . insert ( MessageTable )
190+ . values ( {
191+ id : MessageID . ascending ( ) ,
192+ session_id : sessionID ,
193+ time_created : 1 ,
194+ time_updated : 1 ,
195+ data : {
196+ role : "assistant" ,
197+ time : { created : 1 , completed : 1 } ,
198+ parentID,
199+ modelID : ModelID . make ( "test" ) ,
200+ providerID : ProviderID . make ( "test" ) ,
201+ mode : "build" ,
202+ path : { cwd : "/tmp" , root : "/tmp" } ,
203+ cost : 0 ,
204+ tokens : {
205+ input : 0 ,
206+ output : 0 ,
207+ reasoning : 0 ,
208+ cache : { read : 0 , write : 0 } ,
209+ } ,
210+ } as NonNullable < ( typeof MessageTable . $inferInsert ) [ "data" ] > ,
211+ } )
212+ . run ( ) ,
213+ )
214+ } )
215+
185216const setLegacySummaryDiff = ( sessionID : SessionIDType ) =>
186217 Effect . gen ( function * ( ) {
187218 const { db } = yield * Database . Service
@@ -635,6 +666,30 @@ describe("session HttpApi", () => {
635666 { git : true , config : { formatter : false , lsp : false } } ,
636667 )
637668
669+ it . instance (
670+ "serves legacy assistant messages missing agent" ,
671+ ( ) =>
672+ Effect . gen ( function * ( ) {
673+ const test = yield * TestInstance
674+ const session = yield * createSession ( { title : "legacy assistant" } )
675+ const message = yield * createTextMessage ( session . id , "hello" )
676+ yield * insertLegacyMessageV2Assistant ( session . id , message . info . id )
677+
678+ const response = yield * request ( `${ pathFor ( SessionPaths . messages , { sessionID : session . id } ) } ?limit=80` , {
679+ headers : { "x-opencode-directory" : test . directory } ,
680+ } )
681+
682+ expect ( response . status ) . toBe ( 200 )
683+ expect (
684+ ( yield * json < MessageV2 . WithParts [ ] > ( response ) ) . find ( ( item ) => item . info . role === "assistant" ) ?. info ,
685+ ) . toMatchObject ( {
686+ role : "assistant" ,
687+ agent : "build" ,
688+ } )
689+ } ) ,
690+ { git : true , config : { formatter : false , lsp : false } } ,
691+ )
692+
638693 it . instance (
639694 "serves lifecycle mutation routes" ,
640695 ( ) =>
0 commit comments