No LaTeX/markdown anywhere students read (seed, import, DB migration 0021, tutor history, frontend guard); quiz of an island is fixed per user again

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 12:15:28 +03:30
parent dd10ff83f4
commit e662914efc
11 changed files with 855 additions and 670 deletions

View File

@@ -0,0 +1,25 @@
from django.core.cache import cache
from django.test import TestCase
from accounts.authentication import issue_access_token
from accounts.models import User
from ai_tutor.models import Conversation, Message
class HistoryNeverShowsLatexTests(TestCase):
def test_old_latex_message_is_cleaned_on_read(self):
cache.clear()
user = User.objects.create(phone='09120000042')
conv = Conversation.objects.create(user_id=user.id)
Message.objects.create(conversation=conv, role='user', text='حل کن $x^{2}=4$')
Message.objects.create(conversation=conv, role='assistant', text=r'جواب: \( \frac{1}{2} \vec{a} \) و **مهم** x^2')
auth = {'HTTP_AUTHORIZATION': f'Bearer {issue_access_token(user.id)}'}
r = self.client.get(f'/api/ai/conversations/{conv.id}/messages', **auth)
self.assertEqual(r.status_code, 200, r.content)
texts = [m['text'] for m in r.json()['messages']]
for t in texts:
self.assertNotIn('\\', t)
self.assertNotIn('**', t)
self.assertNotIn('^', t)
self.assertNotIn('$', t)
self.assertIn('x²', texts[0])

View File

@@ -17,6 +17,8 @@ from rest_framework.views import APIView
from accounts.models import User as AccountUser
from config.db import release_db_connection
from content.plain_math import convert as plain_convert
from rag.services.mathtext import to_plain
from . import concurrency, provider_status
from .models import AskIdempotency, Conversation, Message, MessageFeedback
from .serializers import (
@@ -823,7 +825,7 @@ class AskAIView(APIView):
data = {
'conversationId': str(conversation.id),
'messageId': str(existing.assistant_message.id),
'answer': existing.assistant_message.text,
'answer': to_plain(existing.assistant_message.text),
'suggestedFollowUps': existing.suggested_follow_ups,
'remainingQuota': state['remainingQuota'],
'credits': state['credits'],
@@ -852,7 +854,9 @@ class ConversationMessagesView(APIView):
'conversationId': str(conversation.id),
'lessonId': str(conversation.lesson_id) if conversation.lesson_id else None,
'messages': [
{'messageId': str(m.id), 'role': m.role, 'text': m.text, 'diagram': m.diagram}
{'messageId': str(m.id), 'role': m.role,
# تورِ ایمنی: پیامِ قدیمی با LaTeX/markdown هم هرگز خام نمایش داده نمی‌شود.
'text': to_plain(m.text) if m.role == 'assistant' else plain_convert(m.text), 'diagram': m.diagram}
for m in messages
],
}