MCPcopy
hub / github.com/codeaashu/claude-code / handleMessageFromStream

Function handleMessageFromStream

src/utils/messages.ts:2930–3095  ·  view source on GitHub ↗
(
  message:
    | Message
    | TombstoneMessage
    | StreamEvent
    | RequestStartEvent
    | ToolUseSummaryMessage,
  onMessage: (message: Message) => void,
  onUpdateLength: (newContent: string) => void,
  onSetStreamMode: (mode: SpinnerMode) => void,
  onStreamingToolUses: (
    f: (streamingToolUse: StreamingToolUse[]) => StreamingToolUse[],
  ) => void,
  onTombstone?: (message: Message) => void,
  onStreamingThinking?: (
    f: (current: StreamingThinking | null) => StreamingThinking | null,
  ) => void,
  onApiMetrics?: (metrics: { ttftMs: number }) => void,
  onStreamingText?: (f: (current: string | null) => string | null) => void,
)

Source from the content-addressed store, hash-verified

2928 * Handles messages from a stream, updating response length for deltas and appending completed messages
2929 */
2930export function handleMessageFromStream(
2931 message:
2932 | Message
2933 | TombstoneMessage
2934 | StreamEvent
2935 | RequestStartEvent
2936 | ToolUseSummaryMessage,
2937 onMessage: (message: Message) => void,
2938 onUpdateLength: (newContent: string) => void,
2939 onSetStreamMode: (mode: SpinnerMode) => void,
2940 onStreamingToolUses: (
2941 f: (streamingToolUse: StreamingToolUse[]) => StreamingToolUse[],
2942 ) => void,
2943 onTombstone?: (message: Message) => void,
2944 onStreamingThinking?: (
2945 f: (current: StreamingThinking | null) => StreamingThinking | null,
2946 ) => void,
2947 onApiMetrics?: (metrics: { ttftMs: number }) => void,
2948 onStreamingText?: (f: (current: string | null) => string | null) => void,
2949): void {
2950 if (
2951 message.type !== 'stream_event' &&
2952 message.type !== 'stream_request_start'
2953 ) {
2954 // Handle tombstone messages - remove the targeted message instead of adding
2955 if (message.type === 'tombstone') {
2956 onTombstone?.(message.message)
2957 return
2958 }
2959 // Tool use summary messages are SDK-only, ignore them in stream handling
2960 if (message.type === 'tool_use_summary') {
2961 return
2962 }
2963 // Capture complete thinking blocks for real-time display in transcript mode
2964 if (message.type === 'assistant') {
2965 const thinkingBlock = message.message.content.find(
2966 block => block.type === 'thinking',
2967 )
2968 if (thinkingBlock && thinkingBlock.type === 'thinking') {
2969 onStreamingThinking?.(() => ({
2970 thinking: thinkingBlock.thinking,
2971 isStreaming: false,
2972 streamingEndedAt: Date.now(),
2973 }))
2974 }
2975 }
2976 // Clear streaming text NOW so the render can switch displayedMessages
2977 // from deferredMessages to messages in the same batch, making the
2978 // transition from streaming text → final message atomic (no gap, no duplication).
2979 onStreamingText?.(() => null)
2980 onMessage(message)
2981 return
2982 }
2983
2984 if (message.type === 'stream_request_start') {
2985 onSetStreamMode('requesting')
2986 return
2987 }

Callers 3

execAgentHookFunction · 0.85
REPLFunction · 0.85
useRemoteSessionFunction · 0.85

Calls 1

featureFunction · 0.85

Tested by

no test coverage detected