import figures from 'figures'; import * as React from 'react'; import { useContext } from 'react'; import { useQueuedMessage } from '../../context/QueuedMessageContext.js'; import { Box, Text } from '@anthropic/ink'; import { formatBriefTimestamp } from '../../utils/formatBriefTimestamp.js'; import { findThinkingTriggerPositions, getRainbowColor, isUltrathinkEnabled } from '../../utils/thinking.js'; import { MessageActionsSelectedContext } from '../messageActions.js'; type Props = { text: string; useBriefLayout?: boolean; timestamp?: string; }; export function HighlightedThinkingText({ text, useBriefLayout, timestamp }: Props): React.ReactNode { // Brief/assistant mode: chat-style "You" label instead of the ❯ highlight. // Parent drops its backgroundColor when this is true, so no grey shows // through. No manual wrap needed — Ink wraps inside the parent Box. const isQueued = useQueuedMessage()?.isQueued ?? false; const isSelected = useContext(MessageActionsSelectedContext); const pointerColor = isSelected ? 'suggestion' : 'subtle'; if (useBriefLayout) { const ts = timestamp ? formatBriefTimestamp(timestamp) : ''; return ( You {ts ? {ts} : null} {text} ); } const triggers = isUltrathinkEnabled() ? findThinkingTriggerPositions(text) : []; if (triggers.length === 0) { return ( {figures.pointer} {text} ); } // Static rainbow (no shimmer — transcript messages don't animate) const parts: React.ReactNode[] = []; let cursor = 0; for (const t of triggers) { if (t.start > cursor) { parts.push( {text.slice(cursor, t.start)} , ); } for (let i = t.start; i < t.end; i++) { parts.push( {text[i]} , ); } cursor = t.end; } if (cursor < text.length) { parts.push( {text.slice(cursor)} , ); } return ( {figures.pointer} {parts} ); }