@@ -251,20 +251,25 @@ function completedTool(
251251 callID : string ,
252252 output = "done" ,
253253 attachments : Extract < ToolPart [ "state" ] , { status : "completed" } > [ "attachments" ] = [ ] ,
254+ options : {
255+ readonly tool ?: string
256+ readonly input ?: Record < string , unknown >
257+ readonly metadata ?: Record < string , unknown >
258+ } = { } ,
254259) {
255260 return {
256261 id : `part_${ callID } ` ,
257262 sessionID,
258263 messageID : `msg_${ callID } ` ,
259264 type : "tool" ,
260265 callID,
261- tool : "bash" ,
266+ tool : options . tool ?? "bash" ,
262267 state : {
263268 status : "completed" ,
264- input : { cmd : "printf done" } ,
269+ input : options . input ?? { cmd : "printf done" } ,
265270 output,
266271 title : "bash" ,
267- metadata : { exit : 0 } ,
272+ metadata : options . metadata ?? { exit : 0 } ,
268273 time : { start : Date . now ( ) - 1 , end : Date . now ( ) } ,
269274 ...( attachments . length ? { attachments } : { } ) ,
270275 } ,
@@ -605,6 +610,55 @@ describe("acp event routing", () => {
605610 } )
606611 } )
607612
613+ it ( "emits clean read display content and preserves rawOutput" , async ( ) => {
614+ const harness = createHarness ( )
615+ await Effect . runPromise ( harness . session . create ( { id : "ses_read" , cwd : "/workspace" } ) )
616+ const output = [
617+ "<path>/workspace/file.ts</path>" ,
618+ "<type>file</type>" ,
619+ "<content>" ,
620+ "1: import { value } from './value'" ,
621+ "2: export { value }" ,
622+ "" ,
623+ "(End of file - total 2 lines)" ,
624+ "</content>" ,
625+ ] . join ( "\n" )
626+ const metadata = {
627+ display : {
628+ type : "file" ,
629+ path : "/workspace/file.ts" ,
630+ text : "import { value } from './value'\nexport { value }" ,
631+ lineStart : 1 ,
632+ lineEnd : 2 ,
633+ totalLines : 2 ,
634+ truncated : false ,
635+ } ,
636+ }
637+
638+ await harness . subscription . handle (
639+ toolUpdated (
640+ completedTool ( "ses_read" , "call_read" , output , [ ] , {
641+ tool : "read" ,
642+ input : { filePath : "/workspace/file.ts" } ,
643+ metadata,
644+ } ) ,
645+ ) ,
646+ )
647+
648+ expect ( harness . updates . at ( - 1 ) ?. update ) . toMatchObject ( {
649+ sessionUpdate : "tool_call_update" ,
650+ toolCallId : "call_read" ,
651+ status : "completed" ,
652+ content : [
653+ {
654+ type : "content" ,
655+ content : { type : "text" , text : "import { value } from './value'\nexport { value }" } ,
656+ } ,
657+ ] ,
658+ rawOutput : { output, metadata } ,
659+ } )
660+ } )
661+
608662 it ( "emits error tool output" , async ( ) => {
609663 const harness = createHarness ( )
610664 await Effect . runPromise ( harness . session . create ( { id : "ses_error" , cwd : "/workspace" } ) )
0 commit comments