diff --git a/packages/cli/src/ui/components/Composer.test.tsx b/packages/cli/src/ui/components/Composer.test.tsx
index 77c8812812..4c97255529 100644
--- a/packages/cli/src/ui/components/Composer.test.tsx
+++ b/packages/cli/src/ui/components/Composer.test.tsx
@@ -385,7 +385,7 @@ describe('Composer', () => {
const { lastFrame } = await renderComposer(uiState, settings);
const output = lastFrame();
- expect(output).toContain('LoadingIndicator: Thinking about code');
+ expect(output).toContain('LoadingIndicator: Thinking...');
});
it('hides shortcuts hint while loading', async () => {
diff --git a/packages/cli/src/ui/components/Composer.tsx b/packages/cli/src/ui/components/Composer.tsx
index d8cc8d162c..d30f52dddf 100644
--- a/packages/cli/src/ui/components/Composer.tsx
+++ b/packages/cli/src/ui/components/Composer.tsx
@@ -238,7 +238,9 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
? undefined
: uiState.currentLoadingPhrase
}
- thoughtLabel={undefined}
+ thoughtLabel={
+ inlineThinkingMode === 'full' ? 'Thinking...' : undefined
+ }
elapsedTime={uiState.elapsedTime}
/>
)}
@@ -280,7 +282,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
: uiState.currentLoadingPhrase
}
thoughtLabel={
- inlineThinkingMode === 'full' ? 'Thinking ...' : undefined
+ inlineThinkingMode === 'full' ? 'Thinking...' : undefined
}
elapsedTime={uiState.elapsedTime}
/>
@@ -388,7 +390,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
marginTop={
(showApprovalIndicator ||
uiState.shellModeActive) &&
- isNarrow
+ !isNarrow
? 1
: 0
}
diff --git a/packages/cli/src/ui/components/LoadingIndicator.test.tsx b/packages/cli/src/ui/components/LoadingIndicator.test.tsx
index fca56afd38..4c4e3053ef 100644
--- a/packages/cli/src/ui/components/LoadingIndicator.test.tsx
+++ b/packages/cli/src/ui/components/LoadingIndicator.test.tsx
@@ -258,13 +258,32 @@ describe('', () => {
const output = lastFrame();
expect(output).toBeDefined();
if (output) {
- expect(output).toContain('Thinking... ');
+ // Should NOT contain "Thinking... " prefix because the subject already starts with "Thinking"
+ expect(output).not.toContain('Thinking... Thinking');
expect(output).toContain('Thinking about something...');
expect(output).not.toContain('and other stuff.');
}
unmount();
});
+ it('should prepend "Thinking... " if the subject does not start with "Thinking"', async () => {
+ const props = {
+ thought: {
+ subject: 'Planning the response...',
+ description: 'details',
+ },
+ elapsedTime: 5,
+ };
+ const { lastFrame, unmount, waitUntilReady } = renderWithContext(
+ ,
+ StreamingState.Responding,
+ );
+ await waitUntilReady();
+ const output = lastFrame();
+ expect(output).toContain('Thinking... Planning the response...');
+ unmount();
+ });
+
it('should prioritize thought.subject over currentLoadingPhrase', async () => {
const props = {
thought: {
diff --git a/packages/cli/src/ui/components/LoadingIndicator.tsx b/packages/cli/src/ui/components/LoadingIndicator.tsx
index 4cb49d5750..7aea32a249 100644
--- a/packages/cli/src/ui/components/LoadingIndicator.tsx
+++ b/packages/cli/src/ui/components/LoadingIndicator.tsx
@@ -58,7 +58,11 @@ export const LoadingIndicator: React.FC = ({
const hasThoughtIndicator =
currentLoadingPhrase !== INTERACTIVE_SHELL_WAITING_PHRASE &&
Boolean(thought?.subject?.trim());
- const thinkingIndicator = hasThoughtIndicator ? 'Thinking... ' : '';
+ // Avoid "Thinking... Thinking..." duplication if primaryText already starts with "Thinking"
+ const thinkingIndicator =
+ hasThoughtIndicator && !primaryText?.startsWith('Thinking')
+ ? 'Thinking... '
+ : '';
const cancelAndTimerContent =
showCancelAndTimer &&