diff --git a/src/commands/effort/effort.tsx b/src/commands/effort/effort.tsx index 89d2c7fd2..8f1c8064f 100644 --- a/src/commands/effort/effort.tsx +++ b/src/commands/effort/effort.tsx @@ -1,11 +1,11 @@ -import * as React from 'react' -import { useMainLoopModel } from '../../hooks/useMainLoopModel.js' +import * as React from 'react'; +import { useMainLoopModel } from '../../hooks/useMainLoopModel.js'; import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent, -} from '../../services/analytics/index.js' -import { useAppState, useSetAppState } from '../../state/AppState.js' -import type { LocalJSXCommandOnDone } from '../../types/command.js' +} from '../../services/analytics/index.js'; +import { useAppState, useSetAppState } from '../../state/AppState.js'; +import type { LocalJSXCommandOnDone } from '../../types/command.js'; import { type EffortValue, getDisplayedEffortLevel, @@ -13,171 +13,157 @@ import { getEffortValueDescription, isEffortLevel, toPersistableEffort, -} from '../../utils/effort.js' -import { updateSettingsForSource } from '../../utils/settings/settings.js' +} from '../../utils/effort.js'; +import { updateSettingsForSource } from '../../utils/settings/settings.js'; -const COMMON_HELP_ARGS = ['help', '-h', '--help'] +const COMMON_HELP_ARGS = ['help', '-h', '--help']; type EffortCommandResult = { - message: string - effortUpdate?: { value: EffortValue | undefined } -} + message: string; + effortUpdate?: { value: EffortValue | undefined }; +}; function setEffortValue(effortValue: EffortValue): EffortCommandResult { - const persistable = toPersistableEffort(effortValue) + const persistable = toPersistableEffort(effortValue); if (persistable !== undefined) { const result = updateSettingsForSource('userSettings', { effortLevel: persistable, - }) + }); if (result.error) { return { message: `Failed to set effort level: ${result.error.message}`, - } + }; } } logEvent('tengu_effort_command', { - effort: - effortValue as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, - }) + effort: effortValue as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }); // Env var wins at resolveAppliedEffort time. Only flag it when it actually // conflicts — if env matches what the user just asked for, the outcome is // the same, so "Set effort to X" is true and the note is noise. - const envOverride = getEffortEnvOverride() + const envOverride = getEffortEnvOverride(); if (envOverride !== undefined && envOverride !== effortValue) { - const envRaw = process.env.CLAUDE_CODE_EFFORT_LEVEL + const envRaw = process.env.CLAUDE_CODE_EFFORT_LEVEL; if (persistable === undefined) { return { message: `Not applied: CLAUDE_CODE_EFFORT_LEVEL=${envRaw} overrides effort this session, and ${effortValue} is session-only (nothing saved)`, effortUpdate: { value: effortValue }, - } + }; } return { message: `CLAUDE_CODE_EFFORT_LEVEL=${envRaw} overrides this session — clear it and ${effortValue} takes over`, effortUpdate: { value: effortValue }, - } + }; } - const description = getEffortValueDescription(effortValue) - const suffix = persistable !== undefined ? '' : ' (this session only)' + const description = getEffortValueDescription(effortValue); + const suffix = persistable !== undefined ? '' : ' (this session only)'; return { message: `Set effort level to ${effortValue}${suffix}: ${description}`, effortUpdate: { value: effortValue }, - } + }; } -export function showCurrentEffort( - appStateEffort: EffortValue | undefined, - model: string, -): EffortCommandResult { - const envOverride = getEffortEnvOverride() - const effectiveValue = - envOverride === null ? undefined : (envOverride ?? appStateEffort) +export function showCurrentEffort(appStateEffort: EffortValue | undefined, model: string): EffortCommandResult { + const envOverride = getEffortEnvOverride(); + const effectiveValue = envOverride === null ? undefined : (envOverride ?? appStateEffort); if (effectiveValue === undefined) { - const level = getDisplayedEffortLevel(model, appStateEffort) - return { message: `Effort level: auto (currently ${level})` } + const level = getDisplayedEffortLevel(model, appStateEffort); + return { message: `Effort level: auto (currently ${level})` }; } - const description = getEffortValueDescription(effectiveValue) + const description = getEffortValueDescription(effectiveValue); return { message: `Current effort level: ${effectiveValue} (${description})`, - } + }; } function unsetEffortLevel(): EffortCommandResult { const result = updateSettingsForSource('userSettings', { effortLevel: undefined, - }) + }); if (result.error) { return { message: `Failed to set effort level: ${result.error.message}`, - } + }; } logEvent('tengu_effort_command', { - effort: - 'auto' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, - }) + effort: 'auto' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, + }); // env=auto/unset (null) matches what /effort auto asks for, so only warn // when env is pinning a specific level that will keep overriding. - const envOverride = getEffortEnvOverride() + const envOverride = getEffortEnvOverride(); if (envOverride !== undefined && envOverride !== null) { - const envRaw = process.env.CLAUDE_CODE_EFFORT_LEVEL + const envRaw = process.env.CLAUDE_CODE_EFFORT_LEVEL; return { message: `Cleared effort from settings, but CLAUDE_CODE_EFFORT_LEVEL=${envRaw} still controls this session`, effortUpdate: { value: undefined }, - } + }; } return { message: 'Effort level set to auto', effortUpdate: { value: undefined }, - } + }; } export function executeEffort(args: string): EffortCommandResult { - const normalized = args.toLowerCase() + const normalized = args.toLowerCase(); if (normalized === 'auto' || normalized === 'unset') { - return unsetEffortLevel() + return unsetEffortLevel(); } if (!isEffortLevel(normalized)) { return { message: `Invalid argument: ${args}. Valid options are: low, medium, high, max, auto`, - } + }; } - return setEffortValue(normalized) + return setEffortValue(normalized); } -function ShowCurrentEffort({ - onDone, -}: { - onDone: (result: string) => void -}): React.ReactNode { - const effortValue = useAppState(s => s.effortValue) - const model = useMainLoopModel() - const { message } = showCurrentEffort(effortValue, model) - onDone(message) - return null +function ShowCurrentEffort({ onDone }: { onDone: (result: string) => void }): React.ReactNode { + const effortValue = useAppState(s => s.effortValue); + const model = useMainLoopModel(); + const { message } = showCurrentEffort(effortValue, model); + onDone(message); + return null; } function ApplyEffortAndClose({ result, onDone, }: { - result: EffortCommandResult - onDone: (result: string) => void + result: EffortCommandResult; + onDone: (result: string) => void; }): React.ReactNode { - const setAppState = useSetAppState() - const { effortUpdate, message } = result + const setAppState = useSetAppState(); + const { effortUpdate, message } = result; React.useEffect(() => { if (effortUpdate) { setAppState(prev => ({ ...prev, effortValue: effortUpdate.value, - })) + })); } - onDone(message) - }, [setAppState, effortUpdate, message, onDone]) - return null + onDone(message); + }, [setAppState, effortUpdate, message, onDone]); + return null; } -export async function call( - onDone: LocalJSXCommandOnDone, - _context: unknown, - args?: string, -): Promise { - args = args?.trim() || '' +export async function call(onDone: LocalJSXCommandOnDone, _context: unknown, args?: string): Promise { + args = args?.trim() || ''; if (COMMON_HELP_ARGS.includes(args)) { onDone( - 'Usage: /effort [low|medium|high|max|xhigh|auto]\\n\\nEffort levels:\\n- low: Quick, straightforward implementation\\n- medium: Balanced approach with standard testing\\n- high: Comprehensive implementation with extensive testing\\n- xhigh: Extended reasoning beyond high\\n- max: Maximum capability with deepest reasoning\\n- auto: Use the default effort level for your model', - ) - return + 'Usage: /effort [low|medium|high|xhigh|max|auto]\n\nEffort levels:\n- low: Quick, straightforward implementation\n- medium: Balanced approach with standard testing\n- high: Comprehensive implementation with extensive testing\n- xhigh: Extended reasoning beyond high\n- max: Maximum capability with deepest reasoning\n- auto: Use the default effort level for your model', + ); + return; } if (!args || args === 'current' || args === 'status') { - return + return ; } - const result = executeEffort(args) - return + const result = executeEffort(args); + return ; } diff --git a/src/utils/__tests__/effort.test.ts b/src/utils/__tests__/effort.test.ts index 4424321c6..eb7c0a500 100644 --- a/src/utils/__tests__/effort.test.ts +++ b/src/utils/__tests__/effort.test.ts @@ -224,6 +224,22 @@ describe('getEffortLevelDescription', () => { const desc = getEffortLevelDescription('max') expect(desc).toContain('Maximum') }) + + test('max description does not contain model names', () => { + const desc = getEffortLevelDescription('max') + expect(desc).not.toContain('Opus') + expect(desc).not.toContain('DeepSeek') + }) + + test("returns description for 'xhigh'", () => { + const desc = getEffortLevelDescription('xhigh') + expect(desc).toContain('Extended reasoning') + }) + + test('xhigh description does not contain model names', () => { + const desc = getEffortLevelDescription('xhigh') + expect(desc).not.toContain('Opus') + }) }) // ─── resolvePickerEffortPersistence ──────────────────────────────────── diff --git a/src/utils/effort.ts b/src/utils/effort.ts index bbc16917e..90c597156 100644 --- a/src/utils/effort.ts +++ b/src/utils/effort.ts @@ -262,9 +262,9 @@ export function getEffortLevelDescription(level: EffortLevel): string { case 'high': return 'Comprehensive implementation with extensive testing and documentation' case 'xhigh': - return 'Extended reasoning beyond high, short of max (Opus 4.7 only)' + return 'Extended reasoning beyond high, short of max' case 'max': - return 'Maximum capability with deepest reasoning (Opus 4.6/4.7/DeepSeek V4 Pro)' + return 'Maximum capability with deepest reasoning' } }