Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 0 additions & 138 deletions gui/src/components/StepContainer/Reasoning.tsx

This file was deleted.

11 changes: 9 additions & 2 deletions gui/src/components/StepContainer/StepContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { useDispatch } from "react-redux";
import { useAppSelector } from "../../redux/hooks";
import { selectUIConfig } from "../../redux/slices/configSlice";
import { deleteMessage } from "../../redux/slices/sessionSlice";
import ThinkingBlockPeek from "../mainInput/belowMainInput/ThinkingBlockPeek";
import StyledMarkdownPreview from "../StyledMarkdownPreview";
import ConversationSummary from "./ConversationSummary";
import Reasoning from "./Reasoning";
import ResponseActions from "./ResponseActions";
import ThinkingIndicator from "./ThinkingIndicator";

Expand Down Expand Up @@ -85,7 +85,14 @@ export default function StepContainer(props: StepContainerProps) {
</pre>
) : (
<>
<Reasoning {...props} />
{props.item.reasoning?.text && (
<ThinkingBlockPeek
content={props.item.reasoning.text}
index={props.index}
prevItem={props.index > 0 ? props.item : null}
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing the current item as prevItem breaks ThinkingBlockPeek’s duplicate-suppression logic, so assistant steps will render an extra thinking block whenever a standalone thinking message precedes them.

Prompt for AI agents
Address the following comment on gui/src/components/StepContainer/StepContainer.tsx at line 92:

<comment>Passing the current item as prevItem breaks ThinkingBlockPeek’s duplicate-suppression logic, so assistant steps will render an extra thinking block whenever a standalone thinking message precedes them.</comment>

<file context>
@@ -85,7 +85,14 @@ export default function StepContainer(props: StepContainerProps) {
+              &lt;ThinkingBlockPeek
+                content={props.item.reasoning.text}
+                index={props.index}
+                prevItem={props.index &gt; 0 ? props.item : null}
+                inProgress={!props.item.reasoning?.endAt}
+              /&gt;
</file context>
Fix with Cubic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will never be true because redactedThinking in props is always passed as undefined

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback! I've saved this as a new learning to improve future reviews.

inProgress={!props.item.reasoning?.endAt}
/>
)}

<StyledMarkdownPreview
isRenderingInStepContainer
Expand Down
89 changes: 35 additions & 54 deletions gui/src/components/mainInput/belowMainInput/ThinkingBlockPeek.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,8 @@ import { ChatHistoryItem } from "core";
import { useEffect, useState } from "react";
import styled from "styled-components";

import { vscBackground } from "../..";
import { AnimatedEllipsis } from "../../AnimatedEllipsis";
import StyledMarkdownPreview from "../../StyledMarkdownPreview";
import { ButtonContent, SpoilerButton } from "../../ui/SpoilerButton";

const ThinkingTextContainer = styled.span`
display: inline-block;
min-width: fit-content;

padding-right: 1em; /* Reserve space for the ellipsis animation */
`;

const MarkdownWrapper = styled.div`
& > div > *:first-child {
Expand All @@ -39,7 +30,6 @@ function ThinkingBlockPeek({
index,
prevItem,
inProgress,
signature,
tokens,
}: ThinkingBlockPeekProps) {
const [open, setOpen] = useState(false);
Expand All @@ -66,58 +56,49 @@ function ThinkingBlockPeek({

return duplicateRedactedThinkingBlock ? null : (
<div className="thread-message">
<div className="" style={{ backgroundColor: vscBackground }}>
<div
className="flex items-center justify-start pl-2 text-xs text-gray-300"
data-testid="thinking-block-peek"
>
<SpoilerButton onClick={() => setOpen(!open)}>
<ButtonContent>
{inProgress ? (
<span>
{redactedThinking ? "Redacted Thinking" : "Thinking"}
<AnimatedEllipsis />
</span>
) : redactedThinking ? (
"Redacted Thinking"
) : (
"Thought" +
(elapsedTime ? ` for ${elapsedTime}` : "") +
(tokens ? ` (${tokens} tokens)` : "")
)}
{open ? (
<ChevronUpIcon className="h-3 w-3" />
) : (
<ChevronDownIcon className="h-3 w-3" />
)}
</ButtonContent>
</SpoilerButton>
<div className="mt-1 flex flex-col px-4">
<div className="flex min-w-0 flex-row items-center justify-between gap-2">
<div
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing the toggle with a plain div drops button semantics and keyboard support, so keyboard users can’t open the thinking block. Please keep this control as a button (or add appropriate semantics and key handling).

Prompt for AI agents
Address the following comment on gui/src/components/mainInput/belowMainInput/ThinkingBlockPeek.tsx at line 61:

<comment>Replacing the toggle with a plain div drops button semantics and keyboard support, so keyboard users can’t open the thinking block. Please keep this control as a button (or add appropriate semantics and key handling).</comment>

<file context>
@@ -66,58 +56,49 @@ function ThinkingBlockPeek({
-          &lt;/SpoilerButton&gt;
+      &lt;div className=&quot;mt-1 flex flex-col px-4&quot;&gt;
+        &lt;div className=&quot;flex min-w-0 flex-row items-center justify-between gap-2&quot;&gt;
+          &lt;div
+            className=&quot;text-description flex min-w-0 cursor-pointer flex-row items-center gap-1.5 text-xs transition-colors duration-200 ease-in-out hover:brightness-125&quot;
+            data-testid=&quot;thinking-block-peek&quot;
</file context>

✅ Addressed in 302ffb8

className="text-description flex min-w-0 cursor-pointer flex-row items-center gap-1.5 text-xs transition-colors duration-200 ease-in-out hover:brightness-125"
data-testid="thinking-block-peek"
onClick={() => setOpen(!open)}
>
{inProgress ? (
<span>
{redactedThinking ? "Redacted Thinking" : "Thinking"}
<AnimatedEllipsis />
</span>
) : redactedThinking ? (
"Redacted Thinking"
) : (
"Thought" +
(elapsedTime ? ` for ${elapsedTime}` : "") +
(tokens ? ` (${tokens} tokens)` : "")
)}
{open ? (
<ChevronUpIcon className="h-3 w-3" />
) : (
<ChevronDownIcon className="h-3 w-3" />
)}
</div>
</div>
<div
className={`ml-2 mt-2 overflow-y-auto transition-none duration-300 ease-in-out ${
open ? "mb-2 mt-5 opacity-100" : "max-h-0 border-0 opacity-0"
className={`mt-2 overflow-y-auto transition-all duration-300 ease-in-out ${
open ? "max-h-[50vh] opacity-100" : "max-h-0 opacity-0"
}`}
style={{
borderLeft:
open && !redactedThinking
? "2px solid var(--vscode-input-border, #606060)"
: "none",
}}
>
{redactedThinking ? (
<div className="text-description-muted pl-4 text-xs">
<div className="text-description pl-5 text-xs italic">
Thinking content redacted due to safety reasons.
</div>
) : (
<>
<MarkdownWrapper className="-mt-1 px-0 pl-1">
<StyledMarkdownPreview
isRenderingInStepContainer
source={content}
itemIndex={index}
/>
</MarkdownWrapper>
</>
<MarkdownWrapper>
<StyledMarkdownPreview
isRenderingInStepContainer
source={content}
itemIndex={index}
/>
</MarkdownWrapper>
)}
</div>
</div>
Expand Down
Loading