source dump of claude code
at main 84 lines 2.8 kB view raw
1import { 2 STATUS_TAG, 3 SUMMARY_TAG, 4 TASK_NOTIFICATION_TAG, 5} from '../constants/xml.js' 6import { BACKGROUND_BASH_SUMMARY_PREFIX } from '../tasks/LocalShellTask/LocalShellTask.js' 7import type { 8 NormalizedUserMessage, 9 RenderableMessage, 10} from '../types/message.js' 11import { isFullscreenEnvEnabled } from './fullscreen.js' 12import { extractTag } from './messages.js' 13 14function isCompletedBackgroundBash( 15 msg: RenderableMessage, 16): msg is NormalizedUserMessage { 17 if (msg.type !== 'user') return false 18 const content = msg.message.content[0] 19 if (content?.type !== 'text') return false 20 if (!content.text.includes(`<${TASK_NOTIFICATION_TAG}`)) return false 21 // Only collapse successful completions — failed/killed stay visible individually. 22 if (extractTag(content.text, STATUS_TAG) !== 'completed') return false 23 // The prefix constant distinguishes bash-kind LocalShellTask completions from 24 // agent/workflow/monitor notifications. Monitor-kind completions have their 25 // own summary wording and deliberately don't collapse here. 26 return ( 27 extractTag(content.text, SUMMARY_TAG)?.startsWith( 28 BACKGROUND_BASH_SUMMARY_PREFIX, 29 ) ?? false 30 ) 31} 32 33/** 34 * Collapses consecutive completed-background-bash task-notifications into a 35 * single synthetic "N background commands completed" notification. Failed/killed 36 * tasks and agent/workflow notifications are left alone. Monitor stream 37 * events (enqueueStreamEvent) have no <status> tag and never match. 38 * 39 * Pass-through in verbose mode so ctrl+O shows each completion. 40 */ 41export function collapseBackgroundBashNotifications( 42 messages: RenderableMessage[], 43 verbose: boolean, 44): RenderableMessage[] { 45 if (!isFullscreenEnvEnabled()) return messages 46 if (verbose) return messages 47 48 const result: RenderableMessage[] = [] 49 let i = 0 50 51 while (i < messages.length) { 52 const msg = messages[i]! 53 if (isCompletedBackgroundBash(msg)) { 54 let count = 0 55 while (i < messages.length && isCompletedBackgroundBash(messages[i]!)) { 56 count++ 57 i++ 58 } 59 if (count === 1) { 60 result.push(msg) 61 } else { 62 // Synthesize a task-notification that UserAgentNotificationMessage 63 // already knows how to render — no new renderer needed. 64 result.push({ 65 ...msg, 66 message: { 67 role: 'user', 68 content: [ 69 { 70 type: 'text', 71 text: `<${TASK_NOTIFICATION_TAG}><${STATUS_TAG}>completed</${STATUS_TAG}><${SUMMARY_TAG}>${count} background commands completed</${SUMMARY_TAG}></${TASK_NOTIFICATION_TAG}>`, 72 }, 73 ], 74 }, 75 }) 76 } 77 } else { 78 result.push(msg) 79 i++ 80 } 81 } 82 83 return result 84}