Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
5 changes: 2 additions & 3 deletions apps/web/src/components/chat/ClaudeTraitsPicker.browser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ describe("ClaudeTraitsPicker", () => {
}
});

it("shows prompt-controlled Ultrathink state with disabled effort controls", async () => {
it("shows prompt-controlled Ultrathink state with selectable effort controls", async () => {
const mounted = await mountPicker({
effort: "high",
model: "claude-opus-4-6",
Expand All @@ -166,8 +166,7 @@ describe("ClaudeTraitsPicker", () => {
await vi.waitFor(() => {
const text = document.body.textContent ?? "";
expect(text).toContain("Effort");
expect(text).toContain("Remove Ultrathink from the prompt to change effort.");
expect(text).not.toContain("Fallback Effort");
expect(text).not.toContain("Remove Ultrathink from the prompt to change effort.");
});
} finally {
await mounted.cleanup();
Expand Down
17 changes: 9 additions & 8 deletions apps/web/src/components/chat/ClaudeTraitsPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ export const ClaudeTraitsMenuContent = memo(function ClaudeTraitsMenuContentImpl

const handleEffortChange = useCallback(
(value: ClaudeCodeEffort) => {
if (ultrathinkPromptControlled) return;
if (!value) return;
const nextEffort = options.find((option) => option === value);
if (!nextEffort) return;
Expand All @@ -119,6 +118,10 @@ export const ClaudeTraitsMenuContent = memo(function ClaudeTraitsMenuContentImpl
onPromptChange(nextPrompt);
return;
}
if (ultrathinkPromptControlled) {
const stripped = prompt.replace(/\bultrathink\b:?\s*/i, "");
onPromptChange(stripped);
}
setProviderModelOptions(
threadId,
PROVIDER,
Expand Down Expand Up @@ -151,14 +154,12 @@ export const ClaudeTraitsMenuContent = memo(function ClaudeTraitsMenuContentImpl
<>
<MenuGroup>
<div className="px-2 pt-1.5 pb-1 font-medium text-muted-foreground text-xs">Effort</div>
{ultrathinkPromptControlled ? (
<div className="px-2 pb-1.5 text-muted-foreground/80 text-xs">
Remove Ultrathink from the prompt to change effort.
</div>
) : null}
<MenuRadioGroup value={effort} onValueChange={handleEffortChange}>
<MenuRadioGroup
value={ultrathinkPromptControlled ? "ultrathink" : effort}
onValueChange={handleEffortChange}
>
{options.map((option) => (
<MenuRadioItem key={option} value={option} disabled={ultrathinkPromptControlled}>
<MenuRadioItem key={option} value={option}>
{CLAUDE_EFFORT_LABELS[option]}
{option === defaultReasoningEffort ? " (default)" : ""}
</MenuRadioItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ describe("CompactComposerControlsMenu", () => {
}
});

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