From be623582706fd015d1851019063f71a183ac94a6 Mon Sep 17 00:00:00 2001
From: cogwheel0 <172976095+cogwheel0@users.noreply.github.com>
Date: Thu, 23 Oct 2025 22:37:06 +0530
Subject: [PATCH] feat(chat): strip reasoning when copying
Remove internal reasoning from copied message text to avoidleaking implementation details or developer-only when a
user content from the chat- In chat_pagecopyMessage, cleaning steps to:
- ... think> and ... tags
- trim leftover whitespace before writing to the clipboard
- In assistant_message_widget._buildSegmentedContent, remove an
unused hasMediaAbove calculation and a conditional spacer that added
extra top padding before reasoning tiles. This simplifies rendering
logic and avoids relying on removed spacing behavior.
---
lib/features/chat/views/chat_page.dart | 28 ++++++++++++++++++-
.../widgets/assistant_message_widget.dart | 9 ------
2 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/lib/features/chat/views/chat_page.dart b/lib/features/chat/views/chat_page.dart
index a157b4f..67c7e16 100644
--- a/lib/features/chat/views/chat_page.dart
+++ b/lib/features/chat/views/chat_page.dart
@@ -969,7 +969,33 @@ class _ChatPageState extends ConsumerState {
}
void _copyMessage(String content) {
- Clipboard.setData(ClipboardData(text: content));
+ // Strip reasoning details from the copied content
+ String cleanedContent = content;
+
+ // Remove blocks
+ cleanedContent = cleanedContent.replaceAll(
+ RegExp(
+ r']*>[\s\S]*?<\/details>',
+ multiLine: true,
+ dotAll: true,
+ ),
+ '',
+ );
+
+ // Remove raw reasoning tags
+ cleanedContent = cleanedContent.replaceAll(
+ RegExp(r'[\s\S]*?<\/think>', multiLine: true, dotAll: true),
+ '',
+ );
+ cleanedContent = cleanedContent.replaceAll(
+ RegExp(r'[\s\S]*?<\/reasoning>', multiLine: true, dotAll: true),
+ '',
+ );
+
+ // Clean up any extra whitespace
+ cleanedContent = cleanedContent.trim();
+
+ Clipboard.setData(ClipboardData(text: cleanedContent));
}
void _regenerateMessage(dynamic message) async {
diff --git a/lib/features/chat/widgets/assistant_message_widget.dart b/lib/features/chat/widgets/assistant_message_widget.dart
index 6bd4ea9..0359fba 100644
--- a/lib/features/chat/widgets/assistant_message_widget.dart
+++ b/lib/features/chat/widgets/assistant_message_widget.dart
@@ -435,10 +435,6 @@ class _AssistantMessageWidgetState extends ConsumerState
Widget _buildSegmentedContent() {
final children = [];
- // Determine if media (attachments or generated images) is rendered above.
- final hasMediaAbove =
- (widget.message.attachmentIds?.isNotEmpty ?? false) ||
- (widget.message.files?.isNotEmpty ?? false);
bool firstToolSpacerAdded = false;
int idx = 0;
for (final seg in _segments) {
@@ -450,11 +446,6 @@ class _AssistantMessageWidgetState extends ConsumerState
}
children.add(_buildToolCallTile(seg.toolCall!));
} else if (seg.isReasoning && seg.reasoning != null) {
- // If a reasoning tile is the very first content and sits at the top,
- // add a small spacer above it for breathing room.
- if (children.isEmpty && !hasMediaAbove) {
- children.add(const SizedBox(height: Spacing.sm));
- }
children.add(_buildReasoningTile(seg.reasoning!, idx));
} else if ((seg.text ?? '').trim().isNotEmpty) {
children.add(_buildEnhancedMarkdownContent(seg.text!));