Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/api_v2/api_deployment_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def post(
tag_names = serializer.validated_data.get(ApiExecution.TAGS)
llm_profile_id = serializer.validated_data.get(ApiExecution.LLM_PROFILE_ID)
hitl_queue_name = serializer.validated_data.get(ApiExecution.HITL_QUEUE_NAME)
hitl_packet_id = serializer.validated_data.get(ApiExecution.HITL_PACKET_ID)
custom_data = serializer.validated_data.get(ApiExecution.CUSTOM_DATA)

if presigned_urls:
Expand All @@ -97,6 +98,7 @@ def post(
tag_names=tag_names,
llm_profile_id=llm_profile_id,
hitl_queue_name=hitl_queue_name,
hitl_packet_id=hitl_packet_id,
custom_data=custom_data,
request_headers=dict(request.headers),
)
Expand Down
1 change: 1 addition & 0 deletions backend/api_v2/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ class ApiExecution:
TAGS: str = "tags"
LLM_PROFILE_ID: str = "llm_profile_id"
HITL_QUEUE_NAME: str = "hitl_queue_name"
HITL_PACKET_ID: str = "hitl_packet_id"
PRESIGNED_URLS: str = "presigned_urls"
CUSTOM_DATA: str = "custom_data"
3 changes: 3 additions & 0 deletions backend/api_v2/deployment_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def execute_workflow(
tag_names: list[str] = [],
llm_profile_id: str | None = None,
hitl_queue_name: str | None = None,
hitl_packet_id: str | None = None,
custom_data: dict[str, Any] | None = None,
request_headers=None,
) -> ReturnDict:
Expand All @@ -169,6 +170,7 @@ def execute_workflow(
tag_names (list(str)): list of tag names
llm_profile_id (str, optional): LLM profile ID for overriding tool settings
hitl_queue_name (str, optional): Custom queue name for manual review
hitl_packet_id (str, optional): Packet ID for packet-based review
custom_data (dict[str, Any], optional): JSON data for custom_data variable replacement in prompts

Returns:
Expand Down Expand Up @@ -236,6 +238,7 @@ def execute_workflow(
use_file_history=use_file_history,
llm_profile_id=llm_profile_id,
hitl_queue_name=hitl_queue_name,
hitl_packet_id=hitl_packet_id,
custom_data=custom_data,
)
result.status_api = DeploymentHelper.construct_status_endpoint(
Expand Down
32 changes: 32 additions & 0 deletions backend/api_v2/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Any
from urllib.parse import urlparse

from django.apps import apps
from django.core.validators import RegexValidator
from pipeline_v2.models import Pipeline
from prompt_studio.prompt_profile_manager_v2.models import ProfileManager
Expand Down Expand Up @@ -227,6 +228,7 @@ class ExecutionRequestSerializer(TagParamsSerializer):
presigned_urls = ListField(child=URLField(), required=False)
llm_profile_id = CharField(required=False, allow_null=True, allow_blank=True)
hitl_queue_name = CharField(required=False, allow_null=True, allow_blank=True)
hitl_packet_id = CharField(required=False, allow_null=True, allow_blank=True)
custom_data = JSONField(required=False, allow_null=True)

def validate_hitl_queue_name(self, value: str | None) -> str | None:
Expand All @@ -248,6 +250,36 @@ def validate_hitl_queue_name(self, value: str | None) -> str | None:
)
return value

def validate_hitl_packet_id(self, value: str | None) -> str | None:
"""Validate packet ID format using enterprise validation if available."""
if not value:
return value

# Check if HITL feature is available
if not apps.is_installed("pluggable_apps.manual_review_v2"):
raise ValidationError(
"Packet-based HITL processing requires Unstract Enterprise. "
"This advanced workflow feature is available in our enterprise version. "
"Learn more at https://docs.unstract.com/unstract/unstract_platform/features/workflows/hqr_deployment_workflows/ or "
"contact our sales team at https://unstract.com/contact/"
)

Comment thread
jaags-dev marked this conversation as resolved.
# Validate packet ID format (alphanumeric string, typically 8-character hex)
value = value.strip()
if not value:
raise ValidationError("Packet ID cannot be empty or whitespace only.")

# Basic format validation: alphanumeric, reasonable length
if not re.match(r"^[a-zA-Z0-9_-]+$", value):
raise ValidationError(
"Invalid packet ID format. Packet ID must contain only letters, numbers, hyphens, or underscores."
)

if len(value) > 16: # Reasonable max length
raise ValidationError("Packet ID is too long (maximum 100 characters).")
Comment thread
jaags-dev marked this conversation as resolved.

return value

def validate_custom_data(self, value):
"""Validate custom_data is a valid JSON object."""
if value is None:
Expand Down
Loading