diff --git a/chatbot/services/response_handlers/base_response_handler.py b/chatbot/services/response_handlers/base_response_handler.py index 77ab74f..850b38d 100644 --- a/chatbot/services/response_handlers/base_response_handler.py +++ b/chatbot/services/response_handlers/base_response_handler.py @@ -524,15 +524,23 @@ def _execute_tool(self, tool_name, arguments, company_bot): text = c.get('text', '') header = f'[{title}]({url})' if url else title parts.append(f'Source: {header}\n{text}') - chunks_text = '\n\n---\n\n'.join(parts) + chunks_text = self._wrap_retrieved_content('\n\n---\n\n'.join(parts), source='repository') else: - chunks_text = 'No relevant results found in the knowledge base.' + chunks_text = self._wrap_retrieved_content( + '(no repository result found — use web search if available, otherwise respond ' + 'from general knowledge if appropriate, per no-hallucination rules)', + source='none', + ) logger.info(f'[tool_loop] search_knowledge_base: {len(retrieved_chunks)} chunks for query: {query}') return chunks_text, retrieved_chunks logger.error(f'[tool_loop] unknown tool: {tool_name}') return f'Tool "{tool_name}" is not available.', [] + def _wrap_retrieved_content(self, text, source): + """Wrap tool-retrieved text in an explicit provenance marker before it enters the transcript.""" + return f'\n{text}\n' + def _call_gateway_non_stream( self, gateway_messages, company_bot, session_id, profile_id, tools, tool_choice, retrieved_chunks=None, append_to_last=False, use_web_search=False, turn_usage=None, diff --git a/chatbot/utils/elevate/profile_utils.py b/chatbot/utils/elevate/profile_utils.py index 60db9f6..55c9976 100644 --- a/chatbot/utils/elevate/profile_utils.py +++ b/chatbot/utils/elevate/profile_utils.py @@ -76,6 +76,7 @@ def fetch_elevate_user(access_token): 'school_name': school_name, 'district': district.get('label'), 'state': state.get('label'), + 'has_accepted_tnc': bool(user_data.get('has_accepted_terms_and_conditions', False)), } except requests.exceptions.HTTPError as e: @@ -107,7 +108,7 @@ def upsert_elevate_profile(user_data): return { "profileid": profile.id, - "has_accepted_tnc": (profile.other_params or {}).get('is_tnc_accepted', False), + "has_accepted_tnc": user_data.get('has_accepted_tnc', False), "route": language, "reroute_url": os.getenv('SSO_REROUTE_URL'), "ums_profile": { @@ -125,7 +126,8 @@ def handle_elevate_profile(access_token): return upsert_elevate_profile(user_data) -def update_elevate_profile(access_token, name=None, role=None, school_name=None, district=None, state=None): +def update_elevate_profile(access_token, name=None, role=None, school_name=None, district=None, state=None, + has_accepted_terms_and_conditions=None): try: url = f"{elevate_base_url}/user/v1/user/update" headers = {'X-auth-token': access_token} @@ -140,6 +142,8 @@ def update_elevate_profile(access_token, name=None, role=None, school_name=None, body['userDistrict'] = district if state: body['profileState'] = state + if has_accepted_terms_and_conditions is not None: + body['has_accepted_terms_and_conditions'] = has_accepted_terms_and_conditions logger.info(f'[update_elevate_profile] sending body={body}') response = requests.patch(url, headers=headers, json=body, timeout=30) diff --git a/chatbot/views/api_views.py b/chatbot/views/api_views.py index 171a306..b9e6e09 100644 --- a/chatbot/views/api_views.py +++ b/chatbot/views/api_views.py @@ -1,4 +1,5 @@ import logging +import os import traceback from django.contrib.auth.hashers import check_password from rest_framework.response import Response @@ -9,6 +10,7 @@ from chatbot.models.company_models import Company, CompanyBot from chatbot.models.profile_models import Profile from chatbot.serializer.profile_serializer import ProfileSerializer +from chatbot.utils.elevate.profile_utils import fetch_elevate_user, update_elevate_profile from django.http import JsonResponse from django.contrib.sessions.backends.db import SessionStore from rest_framework_simplejwt.tokens import RefreshToken @@ -16,6 +18,14 @@ from chatbot.models.company_models import Flow logger = logging.getLogger('django') +ACCESS_TOKEN_COOKIE_KEY = os.getenv('ACCESS_TOKEN_COOKIE_KEY') + + +def _get_access_token(request): + access_token = request.COOKIES.get(ACCESS_TOKEN_COOKIE_KEY) if ACCESS_TOKEN_COOKIE_KEY else None + if not access_token: + access_token = request.headers.get('X-auth-token') + return access_token def generate_session_id(request): @@ -212,9 +222,19 @@ def get_profile_view(request): }, status=404) profile = Profile.objects.get(email=email, company=company) - is_tnc_accepted = bool( - profile.other_params and profile.other_params.get('is_tnc_accepted', False) - ) + access_token = _get_access_token(request) + is_tnc_accepted = False + if access_token: + elevate_user_data = fetch_elevate_user(access_token) + if elevate_user_data.get('error'): + logger.error( + '[get_profile_view] failed to fetch tnc status from Elevate: %s', + elevate_user_data.get('error') + ) + else: + is_tnc_accepted = elevate_user_data.get('has_accepted_tnc', False) + else: + logger.error('[get_profile_view] no access_token available — defaulting is_tnc_accepted to False') is_onboarding_completed = bool( profile.other_params and profile.other_params.get('is_onboarding_completed', False) @@ -272,10 +292,20 @@ def accept_tnc_view(request): 'message': 'No company found' }, status=404) profile = Profile.objects.get(email=email, company=company) - other_params = profile.other_params or {} - other_params['is_tnc_accepted'] = True - profile.other_params = other_params - profile.save(update_fields=['other_params', 'updated_at']) + + access_token = _get_access_token(request) + if not access_token: + return Response({ + 'status': 'error', + 'message': 'access_token is required to accept terms and conditions' + }, status=400) + + result = update_elevate_profile(access_token, has_accepted_terms_and_conditions=True) + if not result: + return Response({ + 'status': 'error', + 'message': 'Failed to update terms and conditions acceptance' + }, status=502) return Response({ 'status': 'ok', diff --git a/shikshalokam/views/profile_views.py b/shikshalokam/views/profile_views.py index 0b40475..addce42 100644 --- a/shikshalokam/views/profile_views.py +++ b/shikshalokam/views/profile_views.py @@ -48,7 +48,7 @@ def read_elevate_profile(request): 'profile_details': { 'profileid': profile_details.get('profileid'), 'company': company_slug, - 'has_accepted_tnc': "ONGOING", + 'has_accepted_tnc': profile_details.get('has_accepted_tnc', False), 'route': profile_details.get('route'), 'reroute_url': profile_details.get('reroute_url'), }