Skip to content

Commit 8a2887b

Browse files
committed
fix(web): allow switching away from Ultrathink effort without manual prompt editing
When Ultrathink was active, the effort dropdown was fully disabled, requiring the user to manually remove the "Ultrathink:" prefix from the prompt. Now selecting a different effort level automatically strips the prefix and applies the new effort.
1 parent 9e29c9d commit 8a2887b

File tree

3 files changed

+13
-14
lines changed

3 files changed

+13
-14
lines changed

apps/web/src/components/chat/ClaudeTraitsPicker.browser.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ describe("ClaudeTraitsPicker", () => {
148148
}
149149
});
150150

151-
it("shows prompt-controlled Ultrathink state with disabled effort controls", async () => {
151+
it("shows prompt-controlled Ultrathink state with selectable effort controls", async () => {
152152
const mounted = await mountPicker({
153153
effort: "high",
154154
model: "claude-opus-4-6",
@@ -166,8 +166,7 @@ describe("ClaudeTraitsPicker", () => {
166166
await vi.waitFor(() => {
167167
const text = document.body.textContent ?? "";
168168
expect(text).toContain("Effort");
169-
expect(text).toContain("Remove Ultrathink from the prompt to change effort.");
170-
expect(text).not.toContain("Fallback Effort");
169+
expect(text).not.toContain("Remove Ultrathink from the prompt to change effort.");
171170
});
172171
} finally {
173172
await mounted.cleanup();

apps/web/src/components/chat/ClaudeTraitsPicker.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ export const ClaudeTraitsMenuContent = memo(function ClaudeTraitsMenuContentImpl
107107

108108
const handleEffortChange = useCallback(
109109
(value: ClaudeCodeEffort) => {
110-
if (ultrathinkPromptControlled) return;
111110
if (!value) return;
112111
const nextEffort = options.find((option) => option === value);
113112
if (!nextEffort) return;
@@ -119,6 +118,10 @@ export const ClaudeTraitsMenuContent = memo(function ClaudeTraitsMenuContentImpl
119118
onPromptChange(nextPrompt);
120119
return;
121120
}
121+
if (ultrathinkPromptControlled) {
122+
const stripped = prompt.replace(/\bultrathink\b:?\s*/i, "");
123+
onPromptChange(stripped);
124+
}
122125
setProviderModelOptions(
123126
threadId,
124127
PROVIDER,
@@ -151,14 +154,12 @@ export const ClaudeTraitsMenuContent = memo(function ClaudeTraitsMenuContentImpl
151154
<>
152155
<MenuGroup>
153156
<div className="px-2 pt-1.5 pb-1 font-medium text-muted-foreground text-xs">Effort</div>
154-
{ultrathinkPromptControlled ? (
155-
<div className="px-2 pb-1.5 text-muted-foreground/80 text-xs">
156-
Remove Ultrathink from the prompt to change effort.
157-
</div>
158-
) : null}
159-
<MenuRadioGroup value={effort} onValueChange={handleEffortChange}>
157+
<MenuRadioGroup
158+
value={ultrathinkPromptControlled ? "ultrathink" : effort}
159+
onValueChange={handleEffortChange}
160+
>
160161
{options.map((option) => (
161-
<MenuRadioItem key={option} value={option} disabled={ultrathinkPromptControlled}>
162+
<MenuRadioItem key={option} value={option}>
162163
{CLAUDE_EFFORT_LABELS[option]}
163164
{option === defaultReasoningEffort ? " (default)" : ""}
164165
</MenuRadioItem>

apps/web/src/components/chat/CompactComposerControlsMenu.browser.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ describe("CompactComposerControlsMenu", () => {
159159
}
160160
});
161161

162-
it("shows prompt-controlled Ultrathink messaging with disabled effort controls", async () => {
162+
it("shows prompt-controlled Ultrathink state with selectable effort controls", async () => {
163163
const mounted = await mountMenu({
164164
model: "claude-opus-4-6",
165165
prompt: "Ultrathink:\nInvestigate this",
@@ -176,8 +176,7 @@ describe("CompactComposerControlsMenu", () => {
176176
await vi.waitFor(() => {
177177
const text = document.body.textContent ?? "";
178178
expect(text).toContain("Effort");
179-
expect(text).toContain("Remove Ultrathink from the prompt to change effort.");
180-
expect(text).not.toContain("Fallback Effort");
179+
expect(text).not.toContain("Remove Ultrathink from the prompt to change effort.");
181180
});
182181
} finally {
183182
await mounted.cleanup();

0 commit comments

Comments
 (0)