diff --git a/lib/features/chat/providers/chat_providers.dart b/lib/features/chat/providers/chat_providers.dart index 7719b2738..67cd94850 100644 --- a/lib/features/chat/providers/chat_providers.dart +++ b/lib/features/chat/providers/chat_providers.dart @@ -1025,6 +1025,19 @@ class WebSearchEnabledNotifier extends Notifier { void set(bool value) => state = value; } +// Extended Thinking enabled state for high reasoning effort +final extendedThinkingEnabledProvider = + NotifierProvider( + ExtendedThinkingEnabledNotifier.new, + ); + +class ExtendedThinkingEnabledNotifier extends Notifier { + @override + bool build() => false; + + void set(bool value) => state = value; +} + class ImageGenerationEnabledNotifier extends Notifier { @override bool build() => false; @@ -1417,6 +1430,7 @@ Future regenerateMessage( ref.read(webSearchEnabledProvider) && ref.read(webSearchAvailableProvider); final imageGenerationEnabled = ref.read(imageGenerationEnabledProvider); + final extendedThinkingEnabled = ref.read(extendedThinkingEnabledProvider); // Model metadata for completion notifications final supportedParams = @@ -1581,6 +1595,7 @@ Future regenerateMessage( 'follow_up_generation': true, if (webSearchEnabled) 'web_search': true, if (imageGenerationEnabled) 'image_generation': true, + if (extendedThinkingEnabled) 'reasoning_effort': 'high', }; final bool isBackgroundToolsFlowPre = @@ -2011,6 +2026,7 @@ Future _sendMessageInternal( ref.read(webSearchEnabledProvider) && ref.read(webSearchAvailableProvider); final imageGenerationEnabled = ref.read(imageGenerationEnabledProvider); + final extendedThinkingEnabled = ref.read(extendedThinkingEnabledProvider); // Prepare tools list - pass tool IDs directly final List? toolIdsForApi = (toolIds != null && toolIds.isNotEmpty) @@ -2226,6 +2242,7 @@ Future _sendMessageInternal( if (webSearchEnabled) 'web_search': true, // enable bg web search if (imageGenerationEnabled) 'image_generation': true, // enable bg image flow + if (extendedThinkingEnabled) 'reasoning_effort': 'high', }; // Determine if we need background task flow (tools/tool servers or web search) diff --git a/lib/features/chat/widgets/modern_chat_input.dart b/lib/features/chat/widgets/modern_chat_input.dart index 8b5f9b6a2..2d28aa6c3 100644 --- a/lib/features/chat/widgets/modern_chat_input.dart +++ b/lib/features/chat/widgets/modern_chat_input.dart @@ -952,6 +952,7 @@ class _ModernChatInputState extends ConsumerState final webSearchEnabled = ref.watch(webSearchEnabledProvider); final imageGenEnabled = ref.watch(imageGenerationEnabledProvider); final imageGenAvailable = ref.watch(imageGenerationAvailableProvider); + final extendedThinkingEnabled = ref.watch(extendedThinkingEnabledProvider); final selectedQuickPills = ref.watch( appSettingsProvider.select((s) => s.quickPills), ); @@ -1170,6 +1171,7 @@ class _ModernChatInputState extends ConsumerState tooltip: AppLocalizations.of(context)!.more, webSearchActive: webSearchEnabled, imageGenerationActive: imageGenEnabled, + extendedThinkingActive: extendedThinkingEnabled, toolsActive: selectedToolIds.isNotEmpty, filtersActive: selectedFilterIds.isNotEmpty, ), @@ -1283,6 +1285,7 @@ class _ModernChatInputState extends ConsumerState tooltip: AppLocalizations.of(context)!.more, webSearchActive: webSearchEnabled, imageGenerationActive: imageGenEnabled, + extendedThinkingActive: extendedThinkingEnabled, toolsActive: selectedToolIds.isNotEmpty, filtersActive: selectedFilterIds.isNotEmpty, ), @@ -1567,6 +1570,7 @@ class _ModernChatInputState extends ConsumerState required String tooltip, required bool webSearchActive, required bool imageGenerationActive, + required bool extendedThinkingActive, required bool toolsActive, required bool filtersActive, }) { @@ -1580,6 +1584,9 @@ class _ModernChatInputState extends ConsumerState } else if (imageGenerationActive) { icon = Platform.isIOS ? CupertinoIcons.photo : Icons.image; activeColor = context.conduitTheme.buttonPrimary; + } else if (extendedThinkingActive) { + icon = Icons.psychology; + activeColor = context.conduitTheme.buttonPrimary; } else if (toolsActive) { icon = Platform.isIOS ? CupertinoIcons.wrench : Icons.build; activeColor = context.conduitTheme.buttonPrimary; @@ -2146,6 +2153,19 @@ class _ModernChatInputState extends ConsumerState ); } + final extendedThinkingEnabled = modalRef.watch(extendedThinkingEnabledProvider); + featureTiles.add( + _buildFeatureToggleTile( + icon: Icons.psychology, + title: l10n.extendedThinking, + subtitle: l10n.extendedThinkingDescription, + value: extendedThinkingEnabled, + onChanged: (next) { + modalRef.read(extendedThinkingEnabledProvider.notifier).set(next); + }, + ), + ); + final imageGenAvailable = modalRef.watch( imageGenerationAvailableProvider, ); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 30001ddba..b4dce715b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -980,6 +980,14 @@ "@imageGenerationDescription": { "description": "Explains creating images via model prompts." }, + "extendedThinking": "Extended Thinking", + "@extendedThinking": { + "description": "Feature toggle for high reasoning effort mode." + }, + "extendedThinkingDescription": "Boosts reasoning effort for more thoughtful responses.", + "@extendedThinkingDescription": { + "description": "Explains that extended thinking mode provides more detailed reasoning." + }, "copy": "Copy", "@copy": { "description": "Action to copy text to clipboard."