import { Box } from 'ink' import * as React from 'react' import type { AssistantMessage, Message, UserMessage } from '../query' import type { ContentBlock, DocumentBlockParam, ImageBlockParam, TextBlockParam, ThinkingBlockParam, ToolResultBlockParam, ToolUseBlockParam, } from '@anthropic-ai/sdk/resources/index.mjs' import { Tool } from '../Tool' import { logError } from '../utils/log' import { UserToolResultMessage } from './messages/UserToolResultMessage/UserToolResultMessage' import { AssistantToolUseMessage } from './messages/AssistantToolUseMessage' import { AssistantTextMessage } from './messages/AssistantTextMessage' import { UserTextMessage } from './messages/UserTextMessage' import { NormalizedMessage } from '../utils/messages' import { AssistantThinkingMessage } from './messages/AssistantThinkingMessage' import { AssistantRedactedThinkingMessage } from './messages/AssistantRedactedThinkingMessage' import { useTerminalSize } from '../hooks/useTerminalSize' type Props = { message: UserMessage | AssistantMessage messages: NormalizedMessage[] // TODO: Find a way to remove this, and leave spacing to the consumer addMargin: boolean tools: Tool[] verbose: boolean debug: boolean erroredToolUseIDs: Set inProgressToolUseIDs: Set unresolvedToolUseIDs: Set shouldAnimate: boolean shouldShowDot: boolean width?: number | string } export function Message({ message, messages, addMargin, tools, verbose, debug, erroredToolUseIDs, inProgressToolUseIDs, unresolvedToolUseIDs, shouldAnimate, shouldShowDot, width, }: Props): React.ReactNode { // Assistant message if (message.type === 'assistant') { return ( {message.message.content.map((_, index) => ( ))} ) } // User message // TODO: normalize upstream const content = typeof message.message.content === 'string' ? [{ type: 'text', text: message.message.content } as TextBlockParam] : message.message.content return ( {content.map((_, index) => ( ))} ) } function UserMessage({ message, messages, addMargin, tools, param, options: { verbose }, }: { message: UserMessage messages: Message[] addMargin: boolean tools: Tool[] param: | TextBlockParam | DocumentBlockParam | ImageBlockParam | ToolUseBlockParam | ToolResultBlockParam options: { verbose: boolean } key?: React.Key }): React.ReactNode { const { columns } = useTerminalSize() switch (param.type) { case 'text': return case 'tool_result': return ( ) } } function AssistantMessage({ param, costUSD, durationMs, addMargin, tools, debug, options: { verbose }, erroredToolUseIDs, inProgressToolUseIDs, unresolvedToolUseIDs, shouldAnimate, shouldShowDot, width, }: { param: | ContentBlock | TextBlockParam | ImageBlockParam | ThinkingBlockParam | ToolUseBlockParam | ToolResultBlockParam costUSD: number durationMs: number addMargin: boolean tools: Tool[] debug: boolean options: { verbose: boolean } erroredToolUseIDs: Set inProgressToolUseIDs: Set unresolvedToolUseIDs: Set shouldAnimate: boolean shouldShowDot: boolean width?: number | string key?: React.Key }): React.ReactNode { switch (param.type) { case 'tool_use': return ( ) case 'text': return ( ) case 'redacted_thinking': return case 'thinking': return default: logError(`Unable to render message type: ${param.type}`) return null } }