@@ -199,6 +199,74 @@ describe('runProgrammaticStep', () => {
199199 } )
200200
201201 describe ( 'tool execution' , ( ) => {
202+ it ( 'should not add tool call message for add_message tool' , async ( ) => {
203+ const mockGenerator = ( function * ( ) {
204+ yield {
205+ toolName : 'add_message' ,
206+ args : { role : 'user' , content : 'Hello world' } ,
207+ }
208+ yield { toolName : 'read_files' , args : { paths : [ 'test.txt' ] } }
209+ yield { toolName : 'end_turn' , args : { } }
210+ } ) ( ) as StepGenerator
211+
212+ mockTemplate . handleSteps = ( ) => mockGenerator
213+ mockTemplate . toolNames = [ 'add_message' , 'read_files' , 'end_turn' ]
214+
215+ // Track chunks sent via sendSubagentChunk
216+ const sentChunks : string [ ] = [ ]
217+ const originalSendAction =
218+ require ( '../websockets/websocket-action' ) . sendAction
219+ const sendActionSpy = spyOn (
220+ require ( '../websockets/websocket-action' ) ,
221+ 'sendAction'
222+ ) . mockImplementation ( ( ws : any , action : any ) => {
223+ if ( action . type === 'subagent-response-chunk' ) {
224+ sentChunks . push ( action . chunk )
225+ }
226+ } )
227+
228+ const result = await runProgrammaticStep ( mockAgentState , mockParams )
229+
230+ // Verify add_message tool was executed
231+ expect ( executeToolCallSpy ) . toHaveBeenCalledWith (
232+ expect . objectContaining ( {
233+ toolName : 'add_message' ,
234+ args : { role : 'user' , content : 'Hello world' } ,
235+ } )
236+ )
237+
238+ // Verify read_files tool was executed
239+ expect ( executeToolCallSpy ) . toHaveBeenCalledWith (
240+ expect . objectContaining ( {
241+ toolName : 'read_files' ,
242+ args : { paths : [ 'test.txt' ] } ,
243+ } )
244+ )
245+
246+ // Check that no tool call chunk was sent for add_message
247+ const addMessageToolCallChunk = sentChunks . find (
248+ ( chunk ) =>
249+ chunk . includes ( 'add_message' ) && chunk . includes ( 'Hello world' )
250+ )
251+ expect ( addMessageToolCallChunk ) . toBeUndefined ( )
252+
253+ // Check that tool call chunk WAS sent for read_files (normal behavior)
254+ const readFilesToolCallChunk = sentChunks . find (
255+ ( chunk ) => chunk . includes ( 'read_files' ) && chunk . includes ( 'test.txt' )
256+ )
257+ expect ( readFilesToolCallChunk ) . toBeDefined ( )
258+
259+ // Verify final message history doesn't contain add_message tool call
260+ const addMessageToolCallInHistory = result . agentState . messageHistory . find (
261+ ( msg ) =>
262+ typeof msg . content === 'string' &&
263+ msg . content . includes ( 'add_message' ) &&
264+ msg . content . includes ( 'Hello world' )
265+ )
266+ expect ( addMessageToolCallInHistory ) . toBeUndefined ( )
267+
268+ expect ( result . endTurn ) . toBe ( true )
269+ } )
202270 it ( 'should execute single tool call' , async ( ) => {
203271 const mockGenerator = ( function * ( ) {
204272 yield { toolName : 'read_files' , args : { paths : [ 'test.txt' ] } }
0 commit comments