diff --git a/lib/features/chat/widgets/assistant_message_widget.dart b/lib/features/chat/widgets/assistant_message_widget.dart
index 09ca0dc..2144448 100644
--- a/lib/features/chat/widgets/assistant_message_widget.dart
+++ b/lib/features/chat/widgets/assistant_message_widget.dart
@@ -37,12 +37,18 @@ final _inlineDetailsPattern = RegExp(
r']*)>((?:(?! ).)*)',
dotAll: true,
);
+// Patterns for balancing and tags (similar to )
+final _thinkOpenPattern = RegExp(r'');
+final _thinkClosePattern = RegExp(r'');
+final _reasoningOpenPattern = RegExp(r'');
+final _reasoningClosePattern = RegExp(r'');
/// Sanitizes content to handle malformed HTML-like tags that might cause
/// parsing issues, particularly with Pipe Functions (e.g., Gemini).
///
/// This function:
-/// - Ensures all `` tags are properly closed
+/// - Ensures all ``, ``, and `` tags are properly
+/// closed
/// - Converts inline `... ` to multi-line format for proper
/// block-level parsing
/// - Removes orphan closing tags (those without matching opening tags)
@@ -51,38 +57,75 @@ final _inlineDetailsPattern = RegExp(
String sanitizeContentForParsing(String content) {
if (content.isEmpty) return content;
- // Quick check: skip if no details tags present (check for both opening and closing)
- if (!content.contains('')) {
+ String result = content;
+
+ // Check which tag types are present and need balancing
+ final hasDetails =
+ content.contains('');
+ final hasThink = content.contains('') || content.contains('');
+ final hasReasoning =
+ content.contains('') || content.contains('');
+
+ // Quick check: skip if no relevant tags present
+ if (!hasDetails && !hasThink && !hasReasoning) {
return content;
}
- String result = content;
-
// Step 1: Convert inline ... to multi-line format
// This ensures the markdown block parser can properly detect them
- result = result.replaceAllMapped(_inlineDetailsPattern, (match) {
- final attrs = match.group(1) ?? '';
- final inner = match.group(2) ?? '';
- // Only convert if the inner content doesn't already span multiple lines
- if (!inner.contains('\n')) {
- return '\n$inner\n ';
- }
- return match.group(0)!;
- });
+ if (hasDetails) {
+ result = result.replaceAllMapped(_inlineDetailsPattern, (match) {
+ final attrs = match.group(1) ?? '';
+ final inner = match.group(2) ?? '';
+ // Only convert if the inner content doesn't already span multiple lines
+ if (!inner.contains('\n')) {
+ return '\n$inner\n ';
+ }
+ return match.group(0)!;
+ });
+ }
// Step 2: Balance tags by removing orphan closing tags and adding
// missing closing tags using depth tracking
- result = _balanceDetailsTags(result);
+ if (hasDetails) {
+ result = _balanceTags(
+ result,
+ _detailsOpenPattern,
+ _detailsClosePattern,
+ ' ',
+ );
+ }
+ if (hasThink) {
+ result = _balanceTags(
+ result,
+ _thinkOpenPattern,
+ _thinkClosePattern,
+ ' ',
+ );
+ }
+ if (hasReasoning) {
+ result = _balanceTags(
+ result,
+ _reasoningOpenPattern,
+ _reasoningClosePattern,
+ ' ',
+ );
+ }
return result;
}
-/// Balances `` tags by removing orphan closing tags and adding
-/// missing closing tags. Uses depth tracking to properly handle nested tags
-/// and identify orphans anywhere in the content.
-String _balanceDetailsTags(String content) {
- final openMatches = _detailsOpenPattern.allMatches(content).toList();
- final closeMatches = _detailsClosePattern.allMatches(content).toList();
+/// Balances tags by removing orphan closing tags and adding missing closing
+/// tags. Uses depth tracking to properly handle nested tags and identify
+/// orphans anywhere in the content.
+String _balanceTags(
+ String content,
+ RegExp openPattern,
+ RegExp closePattern,
+ String closeTag,
+) {
+ final openMatches = openPattern.allMatches(content).toList();
+ final closeMatches = closePattern.allMatches(content).toList();
if (openMatches.isEmpty && closeMatches.isEmpty) return content;
@@ -121,7 +164,7 @@ String _balanceDetailsTags(String content) {
// Add missing closing tags for unclosed opening tags
if (depth > 0) {
- result += '\n ' * depth;
+ result += '\n$closeTag' * depth;
}
return result;