This commit is contained in:
2026-04-23 15:53:59 +03:30
parent 36d6b05a7f
commit 72588fe12c
4 changed files with 892 additions and 70 deletions
+9 -9
View File
@@ -17,12 +17,12 @@ class ChatSectionSerializer(serializers.Serializer):
class ConversationSummarySerializer(serializers.Serializer):
id = serializers.UUIDField(source="uuid", read_only=True)
farm_uuid = serializers.UUIDField(source="farm.farm_uuid", read_only=True)
farm_uuid = serializers.UUIDField(source="farm.farm_uuid", read_only=True, allow_null=True)
message_count = serializers.IntegerField(read_only=True)
class ConversationCreateSerializer(serializers.Serializer):
farm_uuid = serializers.UUIDField(required=True)
farm_uuid = serializers.UUIDField(required=False, allow_null=True)
title = serializers.CharField(required=False, allow_blank=True, max_length=255)
farm_context = serializers.JSONField(required=False)
@@ -30,7 +30,7 @@ class ConversationCreateSerializer(serializers.Serializer):
class ChatHistoryMessageSerializer(serializers.Serializer):
message_id = serializers.UUIDField(read_only=True)
conversation_id = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True, allow_null=True)
role = serializers.ChoiceField(choices=Message.ROLE_CHOICES, read_only=True)
content = serializers.CharField(read_only=True, allow_blank=True)
sections = ChatSectionSerializer(many=True, read_only=True)
@@ -40,21 +40,21 @@ class ChatHistoryMessageSerializer(serializers.Serializer):
class ConversationMessagesSerializer(serializers.Serializer):
conversation_id = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True, allow_null=True)
messages = ChatHistoryMessageSerializer(many=True, read_only=True)
class ChatResponseDataSerializer(serializers.Serializer):
message_id = serializers.UUIDField(read_only=True)
conversation_id = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True, allow_null=True)
content = serializers.CharField(read_only=True, allow_blank=True)
sections = ChatSectionSerializer(many=True, read_only=True)
class ConversationDeleteSerializer(serializers.Serializer):
conversation_id = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True, allow_null=True)
class ChatTaskSubmitDataSerializer(serializers.Serializer):
@@ -63,21 +63,21 @@ class ChatTaskSubmitDataSerializer(serializers.Serializer):
status_url = serializers.CharField(required=False, allow_blank=True)
conversation_id = serializers.UUIDField(read_only=True)
message_id = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True, allow_null=True)
class ChatTaskStatusDataSerializer(serializers.Serializer):
task_id = serializers.CharField(required=False, allow_blank=True)
status = serializers.CharField(required=False, allow_blank=True)
conversation_id = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True)
farm_uuid = serializers.UUIDField(read_only=True, allow_null=True)
progress = serializers.JSONField(required=False)
result = serializers.JSONField(required=False)
error = serializers.CharField(required=False, allow_blank=True)
class ChatPostSerializer(serializers.Serializer):
farm_uuid = serializers.UUIDField(required=True)
farm_uuid = serializers.UUIDField(required=False, allow_null=True)
content = serializers.CharField(required=False, allow_blank=True, default="")
images = serializers.ListField(
child=serializers.CharField(),
+171 -25
View File
@@ -5,11 +5,18 @@ from rest_framework.test import APIRequestFactory, force_authenticate
from farm_hub.models import FarmHub, FarmType
from .models import Conversation, Message
from .views import ChatTaskStatusView
from .views import (
ChatDetailView,
ChatListCreateView,
ChatMessagesView,
ChatTaskCreateView,
ChatTaskStatusView,
ContextView,
)
@override_settings(USE_EXTERNAL_API_MOCK=True)
class ChatTaskStatusViewTests(TestCase):
class FarmAiAssistantOptionalFarmUuidTests(TestCase):
def setUp(self):
self.factory = APIRequestFactory()
self.user = get_user_model().objects.create_user(
@@ -24,14 +31,94 @@ class ChatTaskStatusViewTests(TestCase):
farm_type=self.farm_type,
name="Farm 1",
)
self.conversation = Conversation.objects.create(
def test_context_allows_missing_farm_uuid(self):
request = self.factory.get("/api/farm-ai-assistant/context/")
force_authenticate(request, user=self.user)
response = ContextView.as_view()(request)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["status"], "success")
self.assertIsNone(response.data["data"]["farm_uuid"])
def test_chat_task_create_allows_missing_farm_uuid_for_landing_chat(self):
request = self.factory.post(
"/api/farm-ai-assistant/chat/task/",
{"content": "Give me a landing page recommendation"},
format="json",
)
force_authenticate(request, user=self.user)
response = ChatTaskCreateView.as_view()(request)
self.assertEqual(response.status_code, 202)
self.assertEqual(response.data["status"], "success")
self.assertEqual(response.data["data"]["task_id"], "farm-ai-chat-task-123")
self.assertIsNone(response.data["data"]["farm_uuid"])
conversation = Conversation.objects.get(uuid=response.data["data"]["conversation_id"])
self.assertIsNone(conversation.farm)
self.assertEqual(conversation.owner_id, self.user.id)
user_message = conversation.messages.get(role=Message.ROLE_USER)
self.assertIsNone(user_message.farm)
self.assertIsNone(user_message.raw_response["farm_uuid"])
def test_status_success_without_farm_uuid_persists_assistant_message(self):
conversation = Conversation.objects.create(
owner=self.user,
farm=self.farm,
title="Irrigation chat",
farm=None,
title="Landing chat",
farm_context={},
)
self.user_message = Message.objects.create(
conversation=self.conversation,
Message.objects.create(
conversation=conversation,
farm=None,
role=Message.ROLE_USER,
content="What should I plant?",
raw_response={
"task_id": "farm-ai-chat-task-123",
"status": "PENDING",
"status_url": "/api/tasks/farm-ai-chat-task-123/status/",
"farm_uuid": None,
},
)
request = self.factory.get("/api/farm-ai-assistant/chat/task/farm-ai-chat-task-123/status/")
force_authenticate(request, user=self.user)
response = ChatTaskStatusView.as_view()(request, task_id="farm-ai-chat-task-123")
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["status"], "success")
self.assertEqual(response.data["data"]["task_id"], "farm-ai-chat-task-123")
self.assertEqual(response.data["data"]["status"], "SUCCESS")
self.assertEqual(response.data["data"]["conversation_id"], str(conversation.uuid))
self.assertIsNone(response.data["data"]["farm_uuid"])
self.assertEqual(response.data["data"]["result"]["content"], "Here is the recommended plan.")
self.assertEqual(response.data["data"]["result"]["task_id"], "farm-ai-chat-task-123")
assistant_message = (
conversation.messages.filter(role=Message.ROLE_ASSISTANT)
.order_by("-created_at")
.first()
)
self.assertIsNotNone(assistant_message)
self.assertIsNone(assistant_message.farm)
self.assertEqual(assistant_message.content, "Here is the recommended plan.")
self.assertIsNone(assistant_message.raw_response["farm_uuid"])
self.assertEqual(assistant_message.raw_response["task_id"], "farm-ai-chat-task-123")
def test_status_success_with_farm_uuid_still_works_for_farm_chat(self):
conversation = Conversation.objects.create(
owner=self.user,
farm=self.farm,
title="Farm chat",
farm_context={},
)
Message.objects.create(
conversation=conversation,
farm=self.farm,
role=Message.ROLE_USER,
content="What is the best irrigation plan?",
@@ -43,7 +130,6 @@ class ChatTaskStatusViewTests(TestCase):
},
)
def test_status_success_uses_chat_mock_result_and_persists_assistant_message(self):
request = self.factory.get(
f"/api/farm-ai-assistant/chat/task/farm-ai-chat-task-123/status/?farm_uuid={self.farm.farm_uuid}"
)
@@ -52,23 +138,83 @@ class ChatTaskStatusViewTests(TestCase):
response = ChatTaskStatusView.as_view()(request, task_id="farm-ai-chat-task-123")
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["status"], "success")
self.assertEqual(response.data["data"]["task_id"], "farm-ai-chat-task-123")
self.assertEqual(response.data["data"]["status"], "SUCCESS")
self.assertEqual(response.data["data"]["conversation_id"], str(self.conversation.uuid))
self.assertEqual(response.data["data"]["conversation_id"], str(conversation.uuid))
self.assertEqual(response.data["data"]["farm_uuid"], str(self.farm.farm_uuid))
self.assertEqual(response.data["data"]["result"]["content"], "Here is the recommended plan.")
self.assertEqual(len(response.data["data"]["result"]["sections"]), 3)
self.assertEqual(response.data["data"]["result"]["task_id"], "farm-ai-chat-task-123")
assistant_message = (
self.conversation.messages.filter(role=Message.ROLE_ASSISTANT)
.order_by("-created_at")
.first()
def test_chat_list_create_messages_and_delete_work_without_farm_uuid(self):
landing_conversation = Conversation.objects.create(
owner=self.user,
farm=None,
title="Landing chat",
farm_context={"source": "landing"},
)
self.assertIsNotNone(assistant_message)
self.assertEqual(assistant_message.farm_id, self.farm.id)
self.assertEqual(assistant_message.content, "Here is the recommended plan.")
self.assertEqual(assistant_message.raw_response["task_id"], "farm-ai-chat-task-123")
self.assertEqual(assistant_message.raw_response["farm_uuid"], str(self.farm.farm_uuid))
self.assertEqual(len(assistant_message.raw_response["sections"]), 3)
Message.objects.create(
conversation=landing_conversation,
farm=None,
role=Message.ROLE_USER,
content="Hello from landing",
raw_response={"farm_uuid": None},
)
farm_conversation = Conversation.objects.create(
owner=self.user,
farm=self.farm,
title="Farm chat",
farm_context={},
)
Message.objects.create(
conversation=farm_conversation,
farm=self.farm,
role=Message.ROLE_USER,
content="Hello from farm",
raw_response={"farm_uuid": str(self.farm.farm_uuid)},
)
list_request = self.factory.get("/api/farm-ai-assistant/chats/")
force_authenticate(list_request, user=self.user)
list_response = ChatListCreateView.as_view()(list_request)
self.assertEqual(list_response.status_code, 200)
self.assertEqual(len(list_response.data["data"]), 1)
self.assertEqual(list_response.data["data"][0]["id"], str(landing_conversation.uuid))
self.assertIsNone(list_response.data["data"][0]["farm_uuid"])
create_request = self.factory.post(
"/api/farm-ai-assistant/chats/",
{"title": "New landing conversation"},
format="json",
)
force_authenticate(create_request, user=self.user)
create_response = ChatListCreateView.as_view()(create_request)
self.assertEqual(create_response.status_code, 201)
self.assertIsNone(create_response.data["data"]["farm_uuid"])
created_conversation = Conversation.objects.get(uuid=create_response.data["data"]["id"])
self.assertIsNone(created_conversation.farm)
messages_request = self.factory.get(
f"/api/farm-ai-assistant/chats/{landing_conversation.uuid}/messages/"
)
force_authenticate(messages_request, user=self.user)
messages_response = ChatMessagesView.as_view()(
messages_request,
conversation_id=landing_conversation.uuid,
)
self.assertEqual(messages_response.status_code, 200)
self.assertEqual(messages_response.data["data"]["conversation_id"], str(landing_conversation.uuid))
self.assertIsNone(messages_response.data["data"]["farm_uuid"])
self.assertEqual(len(messages_response.data["data"]["messages"]), 1)
self.assertIsNone(messages_response.data["data"]["messages"][0]["farm_uuid"])
delete_request = self.factory.delete(f"/api/farm-ai-assistant/chats/{landing_conversation.uuid}/")
force_authenticate(delete_request, user=self.user)
delete_response = ChatDetailView.as_view()(
delete_request,
conversation_id=landing_conversation.uuid,
)
self.assertEqual(delete_response.status_code, 200)
self.assertEqual(delete_response.data["data"]["conversation_id"], str(landing_conversation.uuid))
self.assertIsNone(delete_response.data["data"]["farm_uuid"])
self.assertFalse(Conversation.objects.filter(uuid=landing_conversation.uuid).exists())
+61 -36
View File
@@ -34,11 +34,21 @@ class FarmAccessMixin:
def _get_farm(request, farm_uuid):
if not farm_uuid:
raise serializers.ValidationError({"farm_uuid": ["This field is required."]})
return FarmAccessMixin._get_optional_farm(request, farm_uuid)
@staticmethod
def _get_optional_farm(request, farm_uuid):
if not farm_uuid:
return None
try:
return FarmHub.objects.get(farm_uuid=farm_uuid, owner=request.user)
except FarmHub.DoesNotExist as exc:
raise Http404("Farm not found") from exc
@staticmethod
def _farm_uuid_or_none(farm):
return str(farm.farm_uuid) if farm else None
class ContextView(FarmAccessMixin, APIView):
permission_classes = [IsAuthenticated]
@@ -46,14 +56,14 @@ class ContextView(FarmAccessMixin, APIView):
@extend_schema(
tags=["Farm AI Assistant"],
parameters=[
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=True, default="11111111-1111-1111-1111-111111111111"),
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=False, default="11111111-1111-1111-1111-111111111111"),
],
responses={200: status_response("FarmAiAssistantContextResponse", data=serializers.JSONField())},
)
def get(self, request):
farm = self._get_farm(request, request.query_params.get("farm_uuid"))
farm = self._get_optional_farm(request, request.query_params.get("farm_uuid"))
data = deepcopy(CONTEXT_RESPONSE_DATA)
data["farm_uuid"] = str(farm.farm_uuid)
data["farm_uuid"] = self._farm_uuid_or_none(farm)
return Response(
{"status": "success", "data": data},
status=status.HTTP_200_OK,
@@ -66,6 +76,8 @@ class ConversationAccessMixin(FarmAccessMixin):
filters = {"uuid": conversation_id, "owner": request.user}
if farm_uuid:
filters["farm__farm_uuid"] = farm_uuid
else:
filters["farm__isnull"] = True
try:
return Conversation.objects.select_related("farm").get(**filters)
except Conversation.DoesNotExist as exc:
@@ -110,17 +122,21 @@ class ConversationAccessMixin(FarmAccessMixin):
def _build_mock_assistant_payload(self, conversation):
payload = deepcopy(CHAT_RESPONSE_DATA)
payload["conversation_id"] = str(conversation.uuid)
payload["farm_uuid"] = str(conversation.farm.farm_uuid)
payload["farm_uuid"] = self._farm_uuid_or_none(conversation.farm)
return payload
def _get_or_create_conversation(self, request, validated):
conversation_id = validated.get("conversation_id")
farm_context = validated.get("farm_context")
title = validated.get("title", "").strip()
farm = self._get_farm(request, validated.get("farm_uuid"))
farm = self._get_optional_farm(request, validated.get("farm_uuid"))
if conversation_id:
conversation = self._get_conversation(request, conversation_id, farm.farm_uuid)
conversation = self._get_conversation(
request,
conversation_id,
farm.farm_uuid if farm else None,
)
updated_fields = []
if farm_context is not None:
conversation.farm_context = farm_context
@@ -143,13 +159,14 @@ class ConversationAccessMixin(FarmAccessMixin):
@staticmethod
def _build_adapter_payload(request, validated, conversation):
payload = {
"farm_uuid": str(conversation.farm.farm_uuid),
"content": validated.get("content", ""),
"query": validated.get("content", ""),
"images": validated.get("images", []),
"conversation_id": str(conversation.uuid),
"user_id": request.user.id,
}
if conversation.farm:
payload["farm_uuid"] = str(conversation.farm.farm_uuid)
if "farm_context" in validated:
payload["farm_context"] = validated.get("farm_context") or {}
if "title" in validated:
@@ -177,7 +194,7 @@ class ConversationAccessMixin(FarmAccessMixin):
return {
"message_id": "",
"conversation_id": str(conversation.uuid),
"farm_uuid": str(conversation.farm.farm_uuid),
"farm_uuid": self._farm_uuid_or_none(conversation.farm),
"content": content,
"sections": sections,
}
@@ -197,7 +214,7 @@ class ConversationAccessMixin(FarmAccessMixin):
"status_url": str(payload_source.get("status_url") or ""),
"conversation_id": str(conversation.uuid),
"message_id": str(message_id),
"farm_uuid": str(conversation.farm.farm_uuid),
"farm_uuid": ConversationAccessMixin._farm_uuid_or_none(conversation.farm),
}
def _extract_task_status_payload(self, adapter_data, task_id, conversation=None, farm_uuid=None):
@@ -214,8 +231,8 @@ class ConversationAccessMixin(FarmAccessMixin):
}
if conversation:
task_status_payload["conversation_id"] = str(conversation.uuid)
task_status_payload["farm_uuid"] = str(conversation.farm.farm_uuid)
elif farm_uuid:
task_status_payload["farm_uuid"] = self._farm_uuid_or_none(conversation.farm)
elif farm_uuid is not None:
task_status_payload["farm_uuid"] = str(farm_uuid)
progress = payload_source.get("progress")
@@ -263,7 +280,7 @@ class ConversationAccessMixin(FarmAccessMixin):
return {
"message_id": str(message.uuid),
"conversation_id": str(message.conversation.uuid),
"farm_uuid": str(message.farm.farm_uuid),
"farm_uuid": ConversationAccessMixin._farm_uuid_or_none(message.farm),
"role": message.role,
"content": message.content,
"sections": ConversationAccessMixin._normalize_sections(sections),
@@ -273,14 +290,18 @@ class ConversationAccessMixin(FarmAccessMixin):
@staticmethod
def _find_user_message_for_task(request, task_id, farm_uuid):
filters = {
"conversation__owner": request.user,
"role": Message.ROLE_USER,
"raw_response__task_id": task_id,
}
if farm_uuid:
filters["farm__farm_uuid"] = farm_uuid
else:
filters["farm__isnull"] = True
return (
Message.objects.select_related("conversation", "farm")
.filter(
conversation__owner=request.user,
farm__farm_uuid=farm_uuid,
role=Message.ROLE_USER,
raw_response__task_id=task_id,
)
.filter(**filters)
.order_by("-created_at")
.first()
)
@@ -329,12 +350,12 @@ class ChatListCreateView(ConversationAccessMixin, APIView):
@extend_schema(
tags=["Farm AI Assistant"],
parameters=[
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=True, default="11111111-1111-1111-1111-111111111111"),
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=False, default="11111111-1111-1111-1111-111111111111"),
],
responses={200: status_response("FarmAiAssistantConversationListResponse", data=ConversationSummarySerializer(many=True))},
)
def get(self, request):
farm = self._get_farm(request, request.query_params.get("farm_uuid"))
farm = self._get_optional_farm(request, request.query_params.get("farm_uuid"))
conversations = (
Conversation.objects.filter(owner=request.user, farm=farm)
.annotate(message_count=Count("messages"))
@@ -353,7 +374,7 @@ class ChatListCreateView(ConversationAccessMixin, APIView):
serializer.is_valid(raise_exception=True)
validated = serializer.validated_data
farm = self._get_farm(request, validated.get("farm_uuid"))
farm = self._get_optional_farm(request, validated.get("farm_uuid"))
conversation = Conversation.objects.create(
owner=request.user,
farm=farm,
@@ -378,13 +399,13 @@ class ChatMessagesView(ConversationAccessMixin, APIView):
tags=["Farm AI Assistant"],
parameters=[
OpenApiParameter(name="conversation_id", type=OpenApiTypes.UUID, location=OpenApiParameter.PATH),
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=True, default="11111111-1111-1111-1111-111111111111"),
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=False, default="11111111-1111-1111-1111-111111111111"),
],
responses={200: status_response("FarmAiAssistantMessageListResponse", data=ConversationMessagesSerializer())},
)
def get(self, request, conversation_id):
farm = self._get_farm(request, request.query_params.get("farm_uuid"))
conversation = self._get_conversation(request, conversation_id, farm.farm_uuid)
farm = self._get_optional_farm(request, request.query_params.get("farm_uuid"))
conversation = self._get_conversation(request, conversation_id, farm.farm_uuid if farm else None)
messages = conversation.messages.select_related("farm").all()
serialized_messages = [self._serialize_chat_message(message) for message in messages]
return Response(
@@ -392,7 +413,7 @@ class ChatMessagesView(ConversationAccessMixin, APIView):
"status": "success",
"data": {
"conversation_id": str(conversation.uuid),
"farm_uuid": str(farm.farm_uuid),
"farm_uuid": self._farm_uuid_or_none(farm),
"messages": serialized_messages,
},
},
@@ -407,15 +428,15 @@ class ChatDetailView(ConversationAccessMixin, APIView):
tags=["Farm AI Assistant"],
parameters=[
OpenApiParameter(name="conversation_id", type=OpenApiTypes.UUID, location=OpenApiParameter.PATH),
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=True, default="11111111-1111-1111-1111-111111111111"),
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=False, default="11111111-1111-1111-1111-111111111111"),
],
responses={200: status_response("FarmAiAssistantConversationDeleteResponse", data=ConversationDeleteSerializer())},
)
def delete(self, request, conversation_id):
farm = self._get_farm(request, request.query_params.get("farm_uuid"))
conversation = self._get_conversation(request, conversation_id, farm.farm_uuid)
farm = self._get_optional_farm(request, request.query_params.get("farm_uuid"))
conversation = self._get_conversation(request, conversation_id, farm.farm_uuid if farm else None)
deleted_conversation_id = str(conversation.uuid)
deleted_farm_uuid = str(conversation.farm.farm_uuid)
deleted_farm_uuid = self._farm_uuid_or_none(conversation.farm)
conversation.delete()
return Response(
{
@@ -450,7 +471,7 @@ class ChatView(ConversationAccessMixin, APIView):
role=Message.ROLE_USER,
content=validated.get("content", ""),
images=validated.get("images", []),
raw_response={"farm_uuid": str(conversation.farm.farm_uuid)},
raw_response={"farm_uuid": self._farm_uuid_or_none(conversation.farm)},
)
adapter_payload = self._build_adapter_payload(request, validated, conversation)
@@ -522,7 +543,7 @@ class ChatTaskCreateView(ConversationAccessMixin, APIView):
role=Message.ROLE_USER,
content=validated.get("content", ""),
images=validated.get("images", []),
raw_response={"farm_uuid": str(conversation.farm.farm_uuid)},
raw_response={"farm_uuid": self._farm_uuid_or_none(conversation.farm)},
)
adapter_payload = self._build_adapter_payload(request, validated, conversation)
@@ -578,18 +599,21 @@ class ChatTaskStatusView(ConversationAccessMixin, APIView):
tags=["Farm AI Assistant"],
parameters=[
OpenApiParameter(name="task_id", type=OpenApiTypes.STR, location=OpenApiParameter.PATH),
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=True, default="11111111-1111-1111-1111-111111111111"),
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=False, default="11111111-1111-1111-1111-111111111111"),
],
responses={200: status_response("FarmAiAssistantChatTaskStatusResponse", data=ChatTaskStatusDataSerializer())},
)
def get(self, request, task_id):
farm = self._get_farm(request, request.query_params.get("farm_uuid"))
farm = self._get_optional_farm(request, request.query_params.get("farm_uuid"))
try:
query = {}
if farm:
query["farm_uuid"] = str(farm.farm_uuid)
adapter_response = external_api_request(
"ai",
f"/tasks/{task_id}/status",
method="GET",
query={"farm_uuid": str(farm.farm_uuid)},
query=query,
)
except ExternalAPIRequestError:
return Response(
@@ -611,13 +635,14 @@ class ChatTaskStatusView(ConversationAccessMixin, APIView):
status=adapter_response.status_code,
)
user_message = self._find_user_message_for_task(request, task_id, farm.farm_uuid)
farm_uuid = farm.farm_uuid if farm else None
user_message = self._find_user_message_for_task(request, task_id, farm_uuid)
conversation = user_message.conversation if user_message else None
task_status_payload = self._extract_task_status_payload(
adapter_response.data,
task_id,
conversation=conversation,
farm_uuid=farm.farm_uuid,
farm_uuid=farm_uuid,
)
result = self._extract_structured_task_result(adapter_response.data)