Welcome back! In Chapter 2: Data Summarization & Context, we learned how to compress large logs into readable summaries.
Now, we move from the actions the AI takes to the thoughts the AI has.
When you ask an AI a complex question (like "Solve this logic puzzle" or "Refactor this entire database"), there is often a delay.
If the AI simply waits until it has the perfect final answer, the user feels disconnected. We need to show the "work in progress."
Cognitive Visualization is the concept of rendering the AI's internal monologueβits "Chain of Thought" (CoT)βseparately from its final answer.
Think of it like a math student taking a test:
By separating these, we can show the user that the AI is working without cluttering the final result.
User: "If a train leaves Chicago at 60mph..." AI (Internal Thought): "I need to calculate distance relative to time. Let's set up the equation..." AI (Final Output): "The trains will meet at 3:00 PM."
We want to display that internal thought in a distinct, styled block so the user can follow the logic if they want to.
Here is how the system handles the "Thinking" stream versus the "Speaking" stream.
We manage this visualization primarily through the component AssistantThinkingMessage.tsx.
This component receives a param object. This object holds the raw text of what the AI is currently "thinking."
// AssistantThinkingMessage.tsx
export function AssistantThinkingMessage({
param, // The thought object
isTranscriptMode, // Are we looking at history?
verbose // Do we want full details?
}) {
const { thinking } = param;
// If there are no thoughts, render nothing.
if (!thinking) {
return null;
}
// ... continue logic ...
}
Explanation: First, safety checks. If the AI isn't thinking (the thinking string is empty), we draw nothing.
Sometimes, especially in history/transcript mode, we don't want to see pages of old thoughts. We just want a small indicator that thinking happened.
// If we shouldn't show full details...
if (!shouldShowFullThinking) {
return (
<Box marginTop={addMargin ? 1 : 0}>
<Text dimColor italic>
β΄ Thinking <CtrlOToExpand />
</Text>
</Box>
);
}
Explanation: We render a simple line of text: "β΄ Thinking". We also add a helper hint <CtrlOToExpand /> so the user knows they can press a key to see the full brain dump if they really want to.
When the AI is thinking right now, we want to see the thoughts stream in. We wrap this in a container with specific padding to distinguish it from the final answer.
return (
<Box flexDirection="column" gap={1} width="100%">
<Text dimColor italic>
{label}β¦
</Text>
<Box paddingLeft={2}>
<Markdown dimColor>{thinking}</Markdown>
</Box>
</Box>
);
Explanation:
Box with paddingLeft={2}. This indentation visually pushes the text inward, signaling "this is internal/subordinate."<Markdown dimColor> so the text is greyed out (dim), reinforcing that this is not the final answer.
Sometimes, the AI enters a state of deep reasoning (often called "Ultra-thinking"). To make this visually distinct and exciting for the user, we use HighlightedThinkingText.tsx.
This component paints the text with a rainbow gradient to represent "intense" processing.
Instead of rendering plain text, we break the string into characters and color them individually.
// HighlightedThinkingText.tsx
// ... inside the loop ...
for (let i = t.start; i < t.end; i++) {
parts.push(
<Text
key={`rb-${i}`}
color={getRainbowColor(i - t.start)}
>
{text[i]}
</Text>
);
}
Explanation:
getRainbowColor calculates a color based on the position (creating a gradient).<Text> component for that single character into our parts array.
There is a third component: AssistantRedactedThinkingMessage.tsx.
This is used when the system explicitly wants to hide the content of the thought (perhaps for security, or because the mode is set to "minimal").
// AssistantRedactedThinkingMessage.tsx
export function AssistantRedactedThinkingMessage({ addMargin }) {
return (
<Box marginTop={addMargin ? 1 : 0}>
<Text dimColor italic>
β» Thinkingβ¦
</Text>
</Box>
);
}
Explanation: It is purely cosmetic. It ignores the actual text content and simply tells the user "Processing is happening." This relies on the "Switchboard" logic we learned in Chapter 1: User Message Routing to decide when to use this component vs. the full thinking component.
In this chapter, we explored Cognitive Visualization:
Now that we can route messages (Chapter 1), summarize data (Chapter 2), and visualize the AI's thinking (Chapter 3), it is time to look at how the AI actually does things.
Next Chapter: Tool Execution Lifecycle
Generated by Code IQ