(props: StepContainerProps)
| 19 | } |
| 20 | |
| 21 | export default function StepContainer(props: StepContainerProps) { |
| 22 | const dispatch = useDispatch(); |
| 23 | const [isTruncated, setIsTruncated] = useState(false); |
| 24 | const isStreaming = useAppSelector((state) => state.session.isStreaming); |
| 25 | const uiConfig = useAppSelector(selectUIConfig); |
| 26 | |
| 27 | // Calculate dimming and indicator state based on latest summary index |
| 28 | const latestSummaryIndex = props.latestSummaryIndex ?? -1; |
| 29 | const isBeforeLatestSummary = |
| 30 | latestSummaryIndex !== -1 && props.index <= latestSummaryIndex; |
| 31 | const isLatestSummary = |
| 32 | latestSummaryIndex !== -1 && props.index === latestSummaryIndex; |
| 33 | |
| 34 | const historyItemAfterThis = useAppSelector( |
| 35 | (state) => state.session.history[props.index + 1], |
| 36 | ); |
| 37 | const showResponseActions = |
| 38 | (props.isLast || historyItemAfterThis?.message.role === "user") && |
| 39 | !(props.isLast && (isStreaming || props.item.toolCallStates)); |
| 40 | |
| 41 | useEffect(() => { |
| 42 | if (!isStreaming) { |
| 43 | const content = renderChatMessage(props.item.message).trim(); |
| 44 | const endingPunctuation = [".", "?", "!", "```", ":"]; |
| 45 | |
| 46 | // If not ending in punctuation or emoji, we assume the response got truncated |
| 47 | if ( |
| 48 | content.trim() !== "" && |
| 49 | !( |
| 50 | endingPunctuation.some((p) => content.endsWith(p)) || |
| 51 | /\p{Emoji}/u.test(content.slice(-2)) |
| 52 | ) |
| 53 | ) { |
| 54 | setIsTruncated(true); |
| 55 | } else { |
| 56 | setIsTruncated(false); |
| 57 | } |
| 58 | } |
| 59 | }, [props.item.message.content, isStreaming]); |
| 60 | |
| 61 | function onDelete() { |
| 62 | dispatch(deleteMessage(props.index)); |
| 63 | } |
| 64 | |
| 65 | function onContinueGeneration() { |
| 66 | window.postMessage( |
| 67 | { |
| 68 | messageType: "userInput", |
| 69 | data: { |
| 70 | input: "Continue your response exactly where you left off:", |
| 71 | }, |
| 72 | }, |
| 73 | "*", |
| 74 | ); |
| 75 | } |
| 76 | |
| 77 | return ( |
| 78 | <div> |
nothing calls this directly
no test coverage detected