@@ -2663,6 +2663,60 @@ describe("dispatchTelegramMessage draft streaming", () => {
26632663 expectDeliveredReply ( 0 , { text : "Branch is up to date" } ) ;
26642664 } ) ;
26652665
2666+ it ( "clears progress drafts before durable verbose tool output" , async ( ) => {
2667+ const { answerDraftStream } = setupDraftStreams ( { answerMessageId : 2001 } ) ;
2668+ dispatchReplyWithBufferedBlockDispatcher . mockImplementation (
2669+ async ( { dispatcherOptions, replyOptions } ) => {
2670+ await replyOptions ?. onToolStart ?.( { name : "exec" , phase : "start" } ) ;
2671+ replyOptions ?. onVerboseProgressVisibility ?.( ( ) => true ) ;
2672+ await dispatcherOptions . deliver ( { text : "Tool output visible to Telegram" } , { kind : "tool" } ) ;
2673+ await dispatcherOptions . deliver ( { text : "Final answer" } , { kind : "final" } ) ;
2674+ return { queuedFinal : true } ;
2675+ } ,
2676+ ) ;
2677+
2678+ await dispatchWithContext ( {
2679+ context : createContext ( ) ,
2680+ streamMode : "progress" ,
2681+ telegramCfg : { streaming : { mode : "progress" , progress : { label : "Shelling" } } } ,
2682+ } ) ;
2683+
2684+ expect ( answerDraftStream . update ) . toHaveBeenCalledWith ( "Shelling\n\n`🛠️ Exec`" ) ;
2685+ expectDeliveredReply ( 0 , { text : "Tool output visible to Telegram" } ) ;
2686+ expectDeliveredReply ( 0 , { text : "Final answer" } , 1 ) ;
2687+ expect ( answerDraftStream . clear . mock . invocationCallOrder [ 0 ] ) . toBeLessThan (
2688+ deliverReplies . mock . invocationCallOrder [ 0 ] ,
2689+ ) ;
2690+ } ) ;
2691+
2692+ it ( "clears progress drafts before visible tool artifacts" , async ( ) => {
2693+ const { answerDraftStream } = setupDraftStreams ( { answerMessageId : 2001 } ) ;
2694+ dispatchReplyWithBufferedBlockDispatcher . mockImplementation (
2695+ async ( { dispatcherOptions, replyOptions } ) => {
2696+ await replyOptions ?. onToolStart ?.( { name : "exec" , phase : "start" } ) ;
2697+ await dispatcherOptions . deliver (
2698+ { mediaUrl : "https://example.com/validation.txt" } ,
2699+ { kind : "tool" } ,
2700+ ) ;
2701+ await dispatcherOptions . deliver ( { text : "Final answer" } , { kind : "final" } ) ;
2702+ return { queuedFinal : true } ;
2703+ } ,
2704+ ) ;
2705+
2706+ await dispatchWithContext ( {
2707+ context : createContext ( ) ,
2708+ streamMode : "progress" ,
2709+ telegramCfg : { streaming : { mode : "progress" , progress : { label : "Shelling" } } } ,
2710+ } ) ;
2711+
2712+ expect ( answerDraftStream . update ) . toHaveBeenCalledWith ( "Shelling\n\n`🛠️ Exec`" ) ;
2713+ expectDeliveredReply ( 0 , { mediaUrl : "https://example.com/validation.txt" } ) ;
2714+ expectDeliveredReply ( 0 , { text : "Final answer" } , 1 ) ;
2715+ expect ( answerDraftStream . clear . mock . invocationCallOrder [ 0 ] ) . toBeLessThan (
2716+ deliverReplies . mock . invocationCallOrder [ 0 ] ,
2717+ ) ;
2718+ } ) ;
2719+
26662720 it ( "does not stream text-only tool results into progress drafts" , async ( ) => {
26672721 const { answerDraftStream } = setupDraftStreams ( { answerMessageId : 2001 } ) ;
26682722 dispatchReplyWithBufferedBlockDispatcher . mockImplementation (
0 commit comments