import figures from 'figures'
import * as React from 'react'
import { useContext } from 'react'
import { useQueuedMessage } from '../../context/QueuedMessageContext.js'
import { Box, Text } from '../../ink.js'
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}
)
}