44 * SPDX-License-Identifier: Apache-2.0
55 */
66
7- import type { MessageRecord } from './chatRecordingService.js' ;
7+ import type { MessageRecord , ToolCallRecord } from './chatRecordingService.js' ;
88import type { BaseLlmClient } from '../core/baseLlmClient.js' ;
99import { partListUnionToString } from '../core/geminiRequest.js' ;
1010import { debugLogger } from '../utils/debugLogger.js' ;
1111import type { Content } from '@google/genai' ;
1212import { getResponseText } from '../utils/partUtils.js' ;
1313import { LlmRole } from '../telemetry/types.js' ;
14+ import { safeJsonStringify } from '../utils/safeJsonStringify.js' ;
1415
1516const DEFAULT_MAX_MESSAGES = 20 ;
1617const DEFAULT_TIMEOUT_MS = 5000 ;
@@ -280,15 +281,15 @@ export class SessionSummaryService {
280281 maxMessages : number ,
281282 maxMessageLength : number ,
282283 ) : string | null {
283- const filteredMessages = messages . filter ( ( msg ) => {
284- if ( msg . type !== 'user' && msg . type !== 'gemini' ) {
285- return false ;
286- }
287- const content = partListUnionToString ( msg . content ) ;
288- return content . trim ( ) . length > 0 ;
289- } ) ;
290-
291- let relevantMessages : MessageRecord [ ] ;
284+ const filteredMessages = messages
285+ . filter ( ( msg ) => msg . type === 'user' || msg . type === 'gemini' )
286+ . map ( ( msg ) => ( {
287+ msg ,
288+ content : this . formatMessageForConversation ( msg ) ,
289+ } ) )
290+ . filter ( ( { content } ) => content . length > 0 ) ;
291+
292+ let relevantMessages : typeof filteredMessages ;
292293 if ( filteredMessages . length <= maxMessages ) {
293294 relevantMessages = filteredMessages ;
294295 } else {
@@ -304,9 +305,8 @@ export class SessionSummaryService {
304305 }
305306
306307 return relevantMessages
307- . map ( ( msg ) => {
308+ . map ( ( { msg, content } ) => {
308309 const role = msg . type === 'user' ? 'User' : 'Assistant' ;
309- const content = partListUnionToString ( msg . content ) ;
310310 const characters = Array . from ( content ) ;
311311 const truncated =
312312 characters . length > maxMessageLength
@@ -316,4 +316,58 @@ export class SessionSummaryService {
316316 } )
317317 . join ( '\n\n' ) ;
318318 }
319+
320+ private formatMessageForConversation ( msg : MessageRecord ) : string {
321+ const sections : string [ ] = [ ] ;
322+ const content = partListUnionToString ( msg . content ) . trim ( ) ;
323+
324+ if ( content ) {
325+ sections . push ( content ) ;
326+ }
327+
328+ if ( msg . type === 'gemini' && msg . toolCalls ?. length ) {
329+ sections . push (
330+ ...msg . toolCalls . map ( ( toolCall ) =>
331+ this . formatToolCallForConversation ( toolCall ) ,
332+ ) ,
333+ ) ;
334+ }
335+
336+ return sections . join ( '\n' ) ;
337+ }
338+
339+ private formatToolCallForConversation ( toolCall : ToolCallRecord ) : string {
340+ const lines = [ `Tool: ${ toolCall . name } ` , `Status: ${ toolCall . status } ` ] ;
341+
342+ if ( Object . keys ( toolCall . args ) . length > 0 ) {
343+ lines . push ( `Args: ${ this . stringifyForConversation ( toolCall . args ) } ` ) ;
344+ }
345+
346+ const result = this . stringifyToolCallResult ( toolCall ) ;
347+ if ( result ) {
348+ lines . push ( `Result: ${ result } ` ) ;
349+ }
350+
351+ return lines . join ( '\n' ) ;
352+ }
353+
354+ private stringifyToolCallResult ( toolCall : ToolCallRecord ) : string {
355+ if ( ! toolCall . result ) {
356+ return '' ;
357+ }
358+
359+ return this . stringifyForConversation ( toolCall . result ) ;
360+ }
361+
362+ private stringifyForConversation ( value : unknown ) : string {
363+ if ( value === undefined || value === null ) {
364+ return '' ;
365+ }
366+
367+ if ( typeof value === 'string' ) {
368+ return value ;
369+ }
370+
371+ return safeJsonStringify ( value ) ;
372+ }
319373}
0 commit comments