From 337119844546eb812e7bfa294bb25adc63928659 Mon Sep 17 00:00:00 2001 From: Victor Dibia Date: Thu, 16 Oct 2025 21:51:01 -0700 Subject: [PATCH 1/2] refactor(devui): adopt standard OpenAI lifecycle events for agents and workflows - Replace custom workflow events with OpenAI Responses API standard lifecycle events - Add AgentStartedEvent, AgentCompletedEvent, AgentFailedEvent for clean separation - Implement ExecutorActionItem for workflow executor tracking - Convert informational events to trace events to reduce noise - Update README mapper table with comprehensive event mappings - Maintain full backward compatibility with legacy events --- python/packages/devui/README.md | 19 +- .../devui/agent_framework_devui/_discovery.py | 4 +- .../devui/agent_framework_devui/_executor.py | 27 +- .../devui/agent_framework_devui/_mapper.py | 419 +++++++++++++++++- .../agent_framework_devui/models/__init__.py | 6 + .../models/_openai_custom.py | 68 ++- .../{index-DmL7WSFa.js => index-DpQbOzAN.js} | 228 +++++----- .../devui/agent_framework_devui/ui/index.html | 2 +- .../features/workflow/workflow-view.tsx | 131 ++++-- .../src/components/ui/markdown-renderer.tsx | 6 +- .../devui/frontend/src/services/api.ts | 4 +- .../frontend/src/types/agent-framework.ts | 4 +- .../devui/frontend/src/types/index.ts | 8 + .../devui/frontend/src/types/openai.ts | 88 +++- .../frontend/src/utils/workflow-utils.ts | 54 ++- python/packages/devui/tests/test_mapper.py | 157 ++++++- 16 files changed, 1031 insertions(+), 194 deletions(-) rename python/packages/devui/agent_framework_devui/ui/assets/{index-DmL7WSFa.js => index-DpQbOzAN.js} (58%) diff --git a/python/packages/devui/README.md b/python/packages/devui/README.md index d9a17392b25..a020bfe7ecb 100644 --- a/python/packages/devui/README.md +++ b/python/packages/devui/README.md @@ -159,7 +159,15 @@ Given that DevUI offers an OpenAI Responses API, it internally maps messages and | Agent Framework Content | OpenAI Event/Type | Status | | ------------------------------- | ---------------------------------------- | -------- | -| `TextContent` | `response.output_text.delta` | Standard | +| **Lifecycle Events** | | | +| `AgentStartedEvent` | `response.created` + `response.in_progress` | Standard | +| `AgentCompletedEvent` | `response.completed` | Standard | +| `AgentFailedEvent` | `response.failed` | Standard | +| `WorkflowStartedEvent` | `response.created` + `response.in_progress` | Standard | +| `WorkflowCompletedEvent` | `response.completed` | Standard | +| `WorkflowFailedEvent` | `response.failed` | Standard | +| **Content Types** | | | +| `TextContent` | `response.content_part.added` + `response.output_text.delta` | Standard | | `TextReasoningContent` | `response.reasoning_text.delta` | Standard | | `FunctionCallContent` (initial) | `response.output_item.added` | Standard | | `FunctionCallContent` (args) | `response.function_call_arguments.delta` | Standard | @@ -168,7 +176,14 @@ Given that DevUI offers an OpenAI Responses API, it internally maps messages and | `FunctionApprovalResponseContent`| `response.function_approval.responded` | DevUI | | `ErrorContent` | `error` | Standard | | `UsageContent` | Final `Response.usage` field (not streamed) | Standard | -| `WorkflowEvent` | `response.workflow_event.complete` | DevUI | +| **Workflow Events** | | | +| `ExecutorInvokedEvent` | `response.output_item.added` (ExecutorActionItem) | DevUI | +| `ExecutorCompletedEvent` | `response.output_item.done` (ExecutorActionItem) | DevUI | +| `ExecutorFailedEvent` | `response.output_item.done` (ExecutorActionItem with error) | DevUI | +| `WorkflowEvent` (other) | `response.workflow_event.complete` | DevUI | +| `WorkflowStatusEvent` | `response.trace.complete` | DevUI | +| `WorkflowWarningEvent` | `response.trace.complete` | DevUI | +| **Trace Content** | | | | `DataContent` | `response.trace.complete` | DevUI | | `UriContent` | `response.trace.complete` | DevUI | | `HostedFileContent` | `response.trace.complete` | DevUI | diff --git a/python/packages/devui/agent_framework_devui/_discovery.py b/python/packages/devui/agent_framework_devui/_discovery.py index 175109c7a0a..213af1f0e17 100644 --- a/python/packages/devui/agent_framework_devui/_discovery.py +++ b/python/packages/devui/agent_framework_devui/_discovery.py @@ -127,7 +127,7 @@ async def load_entity(self, entity_id: str) -> Any: # Cache the loaded object self._loaded_objects[entity_id] = entity_obj - logger.info(f"✅ Successfully loaded entity: {entity_id} (type: {enriched_info.type})") + logger.info(f"Successfully loaded entity: {entity_id} (type: {enriched_info.type})") return entity_obj @@ -217,7 +217,7 @@ def invalidate_entity(self, entity_id: str) -> None: if entity_info and "lazy_loaded" in entity_info.metadata: entity_info.metadata["lazy_loaded"] = False - logger.info(f"♻️ Entity invalidated: {entity_id} (will reload on next access)") + logger.info(f"Entity invalidated: {entity_id} (will reload on next access)") def invalidate_all(self) -> None: """Invalidate all cached entities. diff --git a/python/packages/devui/agent_framework_devui/_executor.py b/python/packages/devui/agent_framework_devui/_executor.py index 6c02d91cf0f..16d57c94b59 100644 --- a/python/packages/devui/agent_framework_devui/_executor.py +++ b/python/packages/devui/agent_framework_devui/_executor.py @@ -217,6 +217,11 @@ async def _execute_agent( Agent update events and trace events """ try: + # Emit agent lifecycle start event + from .models._openai_custom import AgentStartedEvent + + yield AgentStartedEvent() + # Convert input to proper ChatMessage or string user_message = self._convert_input_to_chat_message(request.input) @@ -266,8 +271,19 @@ async def _execute_agent( else: raise ValueError("Agent must implement either run() or run_stream() method") + # Emit agent lifecycle completion event + from .models._openai_custom import AgentCompletedEvent + + yield AgentCompletedEvent() + except Exception as e: logger.error(f"Error in agent execution: {e}") + # Emit agent lifecycle failure event + from .models._openai_custom import AgentFailedEvent + + yield AgentFailedEvent(error=e) + + # Still yield the error for backward compatibility yield {"type": "error", "message": f"Agent execution error: {e!s}"} async def _execute_workflow( @@ -284,14 +300,9 @@ async def _execute_workflow( Workflow events and trace events """ try: - # Get input data - prefer structured data from extra_body - input_data: str | list[Any] | dict[str, Any] - if request.extra_body and isinstance(request.extra_body, dict) and request.extra_body.get("input_data"): - input_data = request.extra_body.get("input_data") # type: ignore - logger.debug(f"Using structured input_data from extra_body: {type(input_data)}") - else: - input_data = request.input - logger.debug(f"Using input field as fallback: {type(input_data)}") + # Get input data directly from request.input field + input_data = request.input + logger.debug(f"Using input field: {type(input_data)}") # Parse input based on workflow's expected input type parsed_input = await self._parse_workflow_input(workflow, input_data) diff --git a/python/packages/devui/agent_framework_devui/_mapper.py b/python/packages/devui/agent_framework_devui/_mapper.py index 488b1be10b1..af5501c49a8 100644 --- a/python/packages/devui/agent_framework_devui/_mapper.py +++ b/python/packages/devui/agent_framework_devui/_mapper.py @@ -4,17 +4,32 @@ import json import logging +import time import uuid from collections import OrderedDict from collections.abc import Sequence from datetime import datetime from typing import Any, Union +from uuid import uuid4 + +from openai.types.responses import ( + Response, + ResponseContentPartAddedEvent, + ResponseCreatedEvent, + ResponseError, + ResponseFailedEvent, + ResponseInProgressEvent, +) from .models import ( AgentFrameworkRequest, + CustomResponseOutputItemAddedEvent, + CustomResponseOutputItemDoneEvent, + ExecutorActionItem, InputTokensDetails, OpenAIResponse, OutputTokensDetails, + ResponseCompletedEvent, ResponseErrorEvent, ResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionResultComplete, @@ -102,6 +117,12 @@ async def convert_event(self, raw_event: Any, request: AgentFrameworkRequest) -> ) ] + # Handle Agent lifecycle events first + from .models._openai_custom import AgentCompletedEvent, AgentFailedEvent, AgentStartedEvent + + if isinstance(raw_event, (AgentStartedEvent, AgentCompletedEvent, AgentFailedEvent)): + return await self._convert_agent_lifecycle_event(raw_event, context) + # Import Agent Framework types for proper isinstance checks try: from agent_framework import AgentRunResponse, AgentRunResponseUpdate, WorkflowEvent @@ -245,6 +266,7 @@ def _get_or_create_context(self, request: AgentFrameworkRequest) -> dict[str, An "content_index": 0, "output_index": 0, "request_id": str(request_key), # For usage accumulation + "request": request, # Store the request for model name access # Track active function calls: {call_id: {name, item_id, args_chunks}} "active_function_calls": {}, } @@ -267,7 +289,7 @@ def _next_sequence(self, context: dict[str, Any]) -> int: return int(context["sequence_counter"]) async def _convert_agent_update(self, update: Any, context: dict[str, Any]) -> Sequence[Any]: - """Convert AgentRunResponseUpdate to OpenAI events using comprehensive content mapping. + """Convert agent text updates to proper content part events. Args: update: Agent run response update @@ -283,10 +305,60 @@ async def _convert_agent_update(self, update: Any, context: dict[str, Any]) -> S if not hasattr(update, "contents") or not update.contents: return events + # Check if we're streaming text content + has_text_content = any(content.__class__.__name__ == "TextContent" for content in update.contents) + + # If we have text content and haven't created a message yet, create one + if has_text_content and "current_message_id" not in context: + message_id = f"msg_{uuid4().hex[:8]}" + context["current_message_id"] = message_id + context["output_index"] = context.get("output_index", -1) + 1 + + # Add message output item + events.append( + ResponseOutputItemAddedEvent( + type="response.output_item.added", + output_index=context["output_index"], + sequence_number=self._next_sequence(context), + item=ResponseOutputMessage( + type="message", id=message_id, role="assistant", content=[], status="in_progress" + ), + ) + ) + + # Add content part for text + context["content_index"] = 0 + events.append( + ResponseContentPartAddedEvent( + type="response.content_part.added", + output_index=context["output_index"], + content_index=context["content_index"], + item_id=message_id, + sequence_number=self._next_sequence(context), + part=ResponseOutputText(type="output_text", text="", annotations=[]), + ) + ) + + # Process each content item for content in update.contents: content_type = content.__class__.__name__ - if content_type in self.content_mappers: + # Special handling for TextContent to use proper delta events + if content_type == "TextContent" and "current_message_id" in context: + # Stream text content via proper delta events + events.append( + ResponseTextDeltaEvent( + type="response.output_text.delta", + output_index=context["output_index"], + content_index=context.get("content_index", 0), + item_id=context["current_message_id"], + delta=content.text, + logprobs=[], # We don't have logprobs from Agent Framework + sequence_number=self._next_sequence(context), + ) + ) + elif content_type in self.content_mappers: + # Use existing mappers for other content types mapped_events = await self.content_mappers[content_type](content, context) if mapped_events is not None: # Handle None returns (e.g., UsageContent) if isinstance(mapped_events, list): @@ -297,7 +369,9 @@ async def _convert_agent_update(self, update: Any, context: dict[str, Any]) -> S # Graceful fallback for unknown content types events.append(await self._create_unknown_content_event(content, context)) - context["content_index"] += 1 + # Don't increment content_index for text deltas within the same part + if content_type != "TextContent": + context["content_index"] = context.get("content_index", 0) + 1 except Exception as e: logger.warning(f"Error converting agent update: {e}") @@ -358,8 +432,105 @@ async def _convert_agent_response(self, response: Any, context: dict[str, Any]) return events + async def _convert_agent_lifecycle_event(self, event: Any, context: dict[str, Any]) -> Sequence[Any]: + """Convert agent lifecycle events to OpenAI response events. + + Args: + event: AgentStartedEvent, AgentCompletedEvent, or AgentFailedEvent + context: Conversion context + + Returns: + List of OpenAI response stream events + """ + from .models._openai_custom import AgentCompletedEvent, AgentFailedEvent, AgentStartedEvent + + try: + # Get model name from context (the agent name) + model_name = context.get("request", {}).model if context.get("request") else "agent" + + if isinstance(event, AgentStartedEvent): + execution_id = f"agent_{uuid4().hex[:12]}" + context["execution_id"] = execution_id + + # Create Response object + response_obj = Response( + id=f"resp_{execution_id}", + object="response", + created_at=float(time.time()), + model=model_name, + output=[], + status="in_progress", + parallel_tool_calls=False, + tool_choice="none", + tools=[], + ) + + # Emit both created and in_progress events + return [ + ResponseCreatedEvent( + type="response.created", sequence_number=self._next_sequence(context), response=response_obj + ), + ResponseInProgressEvent( + type="response.in_progress", sequence_number=self._next_sequence(context), response=response_obj + ), + ] + + if isinstance(event, AgentCompletedEvent): + execution_id = context.get("execution_id", f"agent_{uuid4().hex[:12]}") + + response_obj = Response( + id=f"resp_{execution_id}", + object="response", + created_at=float(time.time()), + model=model_name, + output=[], + status="completed", + parallel_tool_calls=False, + tool_choice="none", + tools=[], + ) + + return [ + ResponseCompletedEvent( + type="response.completed", sequence_number=self._next_sequence(context), response=response_obj + ) + ] + + if isinstance(event, AgentFailedEvent): + execution_id = context.get("execution_id", f"agent_{uuid4().hex[:12]}") + + # Create error object + response_error = ResponseError( + message=str(event.error) if event.error else "Unknown error", code="server_error" + ) + + response_obj = Response( + id=f"resp_{execution_id}", + object="response", + created_at=float(time.time()), + model=model_name, + output=[], + status="failed", + error=response_error, + parallel_tool_calls=False, + tool_choice="none", + tools=[], + ) + + return [ + ResponseFailedEvent( + type="response.failed", sequence_number=self._next_sequence(context), response=response_obj + ) + ] + + return [] + + except Exception as e: + logger.warning(f"Error converting agent lifecycle event: {e}") + return [await self._create_error_event(str(e), context)] + async def _convert_workflow_event(self, event: Any, context: dict[str, Any]) -> Sequence[Any]: - """Convert workflow event to structured OpenAI events. + """Convert workflow events to standard OpenAI event objects. Args: event: Workflow event @@ -369,22 +540,247 @@ async def _convert_workflow_event(self, event: Any, context: dict[str, Any]) -> List of OpenAI response stream events """ try: + event_class = event.__class__.__name__ + + # Response-level events - construct proper OpenAI objects + if event_class == "WorkflowStartedEvent": + workflow_id = getattr(event, "workflow_id", str(uuid4())) + context["workflow_id"] = workflow_id + + # Import Response type for proper construction + from openai.types.responses import Response + + # Return proper OpenAI event objects + events: list[Any] = [] + + # Determine the model name - use request model or default to "workflow" + # The request model will be the agent name for agents, workflow name for workflows + model_name = context.get("request", {}).model if context.get("request") else "workflow" + + # Create a full Response object with all required fields + response_obj = Response( + id=f"resp_{workflow_id}", + object="response", + created_at=float(time.time()), + model=model_name, # Use the actual model/agent name + output=[], # Empty output list initially + status="in_progress", + # Required fields with safe defaults + parallel_tool_calls=False, + tool_choice="none", + tools=[], + ) + + # First emit response.created + events.append( + ResponseCreatedEvent( + type="response.created", sequence_number=self._next_sequence(context), response=response_obj + ) + ) + + # Then emit response.in_progress (reuse same response object) + events.append( + ResponseInProgressEvent( + type="response.in_progress", sequence_number=self._next_sequence(context), response=response_obj + ) + ) + + return events + + if event_class in ["WorkflowCompletedEvent", "WorkflowOutputEvent"]: + workflow_id = context.get("workflow_id", str(uuid4())) + + # Import Response type for proper construction + from openai.types.responses import Response + + # Get model name from context + model_name = context.get("request", {}).model if context.get("request") else "workflow" + + # Create a full Response object for completed state + response_obj = Response( + id=f"resp_{workflow_id}", + object="response", + created_at=float(time.time()), + model=model_name, + output=[], # Output should be populated by this point from text streaming + status="completed", + parallel_tool_calls=False, + tool_choice="none", + tools=[], + ) + + return [ + ResponseCompletedEvent( + type="response.completed", sequence_number=self._next_sequence(context), response=response_obj + ) + ] + + if event_class == "WorkflowFailedEvent": + workflow_id = context.get("workflow_id", str(uuid4())) + error_info = getattr(event, "error", None) + + # Import Response and ResponseError types + from openai.types.responses import Response, ResponseError + + # Get model name from context + model_name = context.get("request", {}).model if context.get("request") else "workflow" + + # Create error object + error_message = str(error_info) if error_info else "Unknown error" + + # Create ResponseError object (code must be one of the allowed values) + response_error = ResponseError( + message=error_message, + code="server_error", # Use generic server_error code for workflow failures + ) + + # Create a full Response object for failed state + response_obj = Response( + id=f"resp_{workflow_id}", + object="response", + created_at=float(time.time()), + model=model_name, + output=[], + status="failed", + error=response_error, + parallel_tool_calls=False, + tool_choice="none", + tools=[], + ) + + return [ + ResponseFailedEvent( + type="response.failed", sequence_number=self._next_sequence(context), response=response_obj + ) + ] + + # Executor-level events (output items) + if event_class == "ExecutorInvokedEvent": + executor_id = getattr(event, "executor_id", "unknown") + item_id = f"exec_{executor_id}_{uuid4().hex[:8]}" + context[f"exec_item_{executor_id}"] = item_id + context["output_index"] = context.get("output_index", -1) + 1 + + # Create ExecutorActionItem with proper type + executor_item = ExecutorActionItem( + type="executor_action", + id=item_id, + executor_id=executor_id, + status="in_progress", + metadata=getattr(event, "metadata", {}), + ) + + # Use our custom event type that accepts ExecutorActionItem + return [ + CustomResponseOutputItemAddedEvent( + type="response.output_item.added", + output_index=context["output_index"], + sequence_number=self._next_sequence(context), + item=executor_item, + ) + ] + + if event_class == "ExecutorCompletedEvent": + executor_id = getattr(event, "executor_id", "unknown") + item_id = context.get(f"exec_item_{executor_id}", f"exec_{executor_id}_unknown") + + # Create ExecutorActionItem with completed status + # ExecutorCompletedEvent uses 'data' field, not 'result' + executor_item = ExecutorActionItem( + type="executor_action", + id=item_id, + executor_id=executor_id, + status="completed", + result=getattr(event, "data", None), + ) + + # Use our custom event type + return [ + CustomResponseOutputItemDoneEvent( + type="response.output_item.done", + output_index=context.get("output_index", 0), + sequence_number=self._next_sequence(context), + item=executor_item, + ) + ] + + if event_class == "ExecutorFailedEvent": + executor_id = getattr(event, "executor_id", "unknown") + item_id = context.get(f"exec_item_{executor_id}", f"exec_{executor_id}_unknown") + error_info = getattr(event, "error", None) + + # Create ExecutorActionItem with failed status + executor_item = ExecutorActionItem( + type="executor_action", + id=item_id, + executor_id=executor_id, + status="failed", + error={"message": str(error_info)} if error_info else None, + ) + + # Use our custom event type + return [ + CustomResponseOutputItemDoneEvent( + type="response.output_item.done", + output_index=context.get("output_index", 0), + sequence_number=self._next_sequence(context), + item=executor_item, + ) + ] + + # Handle informational workflow events (status, warnings, errors) + if event_class in ["WorkflowStatusEvent", "WorkflowWarningEvent", "WorkflowErrorEvent", "RequestInfoEvent"]: + # These are informational events that don't map to OpenAI lifecycle events + # Convert them to trace events for debugging visibility + event_data: dict[str, Any] = {} + + # Extract relevant data based on event type + if event_class == "WorkflowStatusEvent": + event_data["state"] = str(getattr(event, "state", "unknown")) + elif event_class == "WorkflowWarningEvent": + event_data["message"] = str(getattr(event, "message", "")) + elif event_class == "WorkflowErrorEvent": + event_data["message"] = str(getattr(event, "message", "")) + event_data["error"] = str(getattr(event, "error", "")) + elif event_class == "RequestInfoEvent": + request_info = getattr(event, "data", {}) + event_data["request_info"] = request_info if isinstance(request_info, dict) else str(request_info) + + # Create a trace event for debugging + trace_event = ResponseTraceEventComplete( + type="response.trace.complete", + data={ + "trace_type": "workflow_info", + "event_type": event_class, + "data": event_data, + "timestamp": datetime.now().isoformat(), + }, + span_id=f"workflow_info_{uuid4().hex[:8]}", + item_id=context["item_id"], + output_index=context.get("output_index", 0), + sequence_number=self._next_sequence(context), + ) + + return [trace_event] + + # For unknown/legacy events, still emit as workflow event for backward compatibility # Get event data and serialize if it's a SerializationMixin - event_data = getattr(event, "data", None) - if event_data is not None and hasattr(event_data, "to_dict"): + raw_event_data = getattr(event, "data", None) + serialized_event_data: dict[str, Any] | str | None = raw_event_data + if raw_event_data is not None and hasattr(raw_event_data, "to_dict"): # SerializationMixin objects - convert to dict for JSON serialization try: - event_data = event_data.to_dict() + serialized_event_data = raw_event_data.to_dict() except Exception as e: logger.debug(f"Failed to serialize event data with to_dict(): {e}") - event_data = str(event_data) + serialized_event_data = str(raw_event_data) - # Create structured workflow event + # Create structured workflow event (keeping for backward compatibility) workflow_event = ResponseWorkflowEventComplete( type="response.workflow_event.complete", data={ "event_type": event.__class__.__name__, - "data": event_data, + "data": serialized_event_data, "executor_id": getattr(event, "executor_id", None), "timestamp": datetime.now().isoformat(), }, @@ -394,6 +790,7 @@ async def _convert_workflow_event(self, event: Any, context: dict[str, Any]) -> sequence_number=self._next_sequence(context), ) + logger.debug(f"Unhandled workflow event type: {event_class}, emitting as legacy workflow event") return [workflow_event] except Exception as e: @@ -723,7 +1120,7 @@ async def _create_unknown_event(self, event_data: Any, context: dict[str, Any]) async def _create_unknown_content_event(self, content: Any, context: dict[str, Any]) -> ResponseStreamEvent: """Create event for unknown content types.""" content_type = content.__class__.__name__ - text = f"⚠️ Unknown content type: {content_type}\n" + text = f"Warning: Unknown content type: {content_type}\n" return self._create_text_delta_event(text, context) async def _create_error_response(self, error_message: str, request: AgentFrameworkRequest) -> OpenAIResponse: diff --git a/python/packages/devui/agent_framework_devui/models/__init__.py b/python/packages/devui/agent_framework_devui/models/__init__.py index 3db699beffb..254bb4e4af8 100644 --- a/python/packages/devui/agent_framework_devui/models/__init__.py +++ b/python/packages/devui/agent_framework_devui/models/__init__.py @@ -30,6 +30,9 @@ from ._discovery_models import DiscoveryResponse, EntityInfo from ._openai_custom import ( AgentFrameworkRequest, + CustomResponseOutputItemAddedEvent, + CustomResponseOutputItemDoneEvent, + ExecutorActionItem, OpenAIError, ResponseFunctionResultComplete, ResponseTraceEvent, @@ -46,8 +49,11 @@ "Conversation", "ConversationDeletedResource", "ConversationItem", + "CustomResponseOutputItemAddedEvent", + "CustomResponseOutputItemDoneEvent", "DiscoveryResponse", "EntityInfo", + "ExecutorActionItem", "InputTokensDetails", "Metadata", "OpenAIError", diff --git a/python/packages/devui/agent_framework_devui/models/_openai_custom.py b/python/packages/devui/agent_framework_devui/models/_openai_custom.py index f07f9c7b9c9..6b7564fac34 100644 --- a/python/packages/devui/agent_framework_devui/models/_openai_custom.py +++ b/python/packages/devui/agent_framework_devui/models/_openai_custom.py @@ -8,6 +8,7 @@ from __future__ import annotations +from dataclasses import dataclass from typing import Any, Literal from pydantic import BaseModel, ConfigDict @@ -15,6 +16,69 @@ # Custom Agent Framework OpenAI event types for structured data +# Agent lifecycle events - simple and clear +class AgentStartedEvent: + """Event emitted when an agent starts execution.""" + + pass + + +class AgentCompletedEvent: + """Event emitted when an agent completes execution successfully.""" + + pass + + +@dataclass +class AgentFailedEvent: + """Event emitted when an agent fails during execution.""" + + error: Exception | None = None + + +class ExecutorActionItem(BaseModel): + """Custom item type for workflow executor actions. + + This is a DevUI-specific extension to represent workflow executors as output items. + Since OpenAI's ResponseOutputItemAddedEvent only accepts specific item types, + and executor actions are not part of the standard, we need this custom type. + """ + + type: Literal["executor_action"] = "executor_action" + id: str + executor_id: str + status: Literal["in_progress", "completed", "failed", "cancelled"] = "in_progress" + metadata: dict[str, Any] | None = None + result: Any | None = None + error: dict[str, Any] | None = None + + +class CustomResponseOutputItemAddedEvent(BaseModel): + """Custom version of ResponseOutputItemAddedEvent that accepts any item type. + + This allows us to emit executor action items while maintaining the same + event structure as OpenAI's standard. + """ + + type: Literal["response.output_item.added"] = "response.output_item.added" + output_index: int + sequence_number: int + item: dict[str, Any] | ExecutorActionItem | Any # Flexible item type + + +class CustomResponseOutputItemDoneEvent(BaseModel): + """Custom version of ResponseOutputItemDoneEvent that accepts any item type. + + This allows us to emit executor action items while maintaining the same + event structure as OpenAI's standard. + """ + + type: Literal["response.output_item.done"] = "response.output_item.done" + output_index: int + sequence_number: int + item: dict[str, Any] | ExecutorActionItem | Any # Flexible item type + + class ResponseWorkflowEventComplete(BaseModel): """Complete workflow event data.""" @@ -64,7 +128,7 @@ class AgentFrameworkExtraBody(BaseModel): """Agent Framework specific routing fields for OpenAI requests.""" entity_id: str - input_data: dict[str, Any] | None = None + # input_data removed - now using standard input field for all data model_config = ConfigDict(extra="allow") @@ -80,7 +144,7 @@ class AgentFrameworkRequest(BaseModel): # All OpenAI fields from ResponseCreateParams model: str # Used as entity_id in DevUI! - input: str | list[Any] # ResponseInputParam + input: str | list[Any] | dict[str, Any] # ResponseInputParam + dict for workflow structured input stream: bool | None = False # OpenAI conversation parameter (standard!) diff --git a/python/packages/devui/agent_framework_devui/ui/assets/index-DmL7WSFa.js b/python/packages/devui/agent_framework_devui/ui/assets/index-DpQbOzAN.js similarity index 58% rename from python/packages/devui/agent_framework_devui/ui/assets/index-DmL7WSFa.js rename to python/packages/devui/agent_framework_devui/ui/assets/index-DpQbOzAN.js index cd628003b6e..db067202bbd 100644 --- a/python/packages/devui/agent_framework_devui/ui/assets/index-DmL7WSFa.js +++ b/python/packages/devui/agent_framework_devui/ui/assets/index-DpQbOzAN.js @@ -1,4 +1,4 @@ -function H_(e,r){for(var o=0;oa[l]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))a(l);new MutationObserver(l=>{for(const u of l)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&a(d)}).observe(document,{childList:!0,subtree:!0});function o(l){const u={};return l.integrity&&(u.integrity=l.integrity),l.referrerPolicy&&(u.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?u.credentials="include":l.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function a(l){if(l.ep)return;l.ep=!0;const u=o(l);fetch(l.href,u)}})();function qh(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Em={exports:{}},wi={};/** +function HE(e,r){for(var o=0;os[l]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))s(l);new MutationObserver(l=>{for(const u of l)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&s(d)}).observe(document,{childList:!0,subtree:!0});function o(l){const u={};return l.integrity&&(u.integrity=l.integrity),l.referrerPolicy&&(u.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?u.credentials="include":l.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function s(l){if(l.ep)return;l.ep=!0;const u=o(l);fetch(l.href,u)}})();function qh(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var _m={exports:{}},wi={};/** * @license React * react-jsx-runtime.production.js * @@ -6,7 +6,7 @@ function H_(e,r){for(var o=0;o>>1,T=E[P];if(0>>1;Pl(ee,z))ael(me,ee)?(E[P]=me,E[ae]=z,P=ae):(E[P]=ee,E[X]=z,P=X);else if(ael(me,z))E[P]=me,E[ae]=z,P=ae;else break e}}return O}function l(E,O){var z=E.sortIndex-O.sortIndex;return z!==0?z:E.id-O.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var u=performance;e.unstable_now=function(){return u.now()}}else{var d=Date,f=d.now();e.unstable_now=function(){return d.now()-f}}var h=[],p=[],g=1,y=null,v=3,b=!1,S=!1,w=!1,j=!1,k=typeof setTimeout=="function"?setTimeout:null,M=typeof clearTimeout=="function"?clearTimeout:null,_=typeof setImmediate<"u"?setImmediate:null;function A(E){for(var O=o(p);O!==null;){if(O.callback===null)a(p);else if(O.startTime<=E)a(p),O.sortIndex=O.expirationTime,r(h,O);else break;O=o(p)}}function D(E){if(w=!1,A(E),!S)if(o(h)!==null)S=!0,L||(L=!0,G());else{var O=o(p);O!==null&&V(D,O.startTime-E)}}var L=!1,H=-1,B=5,q=-1;function Z(){return j?!0:!(e.unstable_now()-qE&&Z());){var P=y.callback;if(typeof P=="function"){y.callback=null,v=y.priorityLevel;var T=P(y.expirationTime<=E);if(E=e.unstable_now(),typeof T=="function"){y.callback=T,A(E),O=!0;break t}y===o(h)&&a(h),A(E)}else a(h);y=o(h)}if(y!==null)O=!0;else{var U=o(p);U!==null&&V(D,U.startTime-E),O=!1}}break e}finally{y=null,v=z,b=!1}O=void 0}}finally{O?G():L=!1}}}var G;if(typeof _=="function")G=function(){_(K)};else if(typeof MessageChannel<"u"){var te=new MessageChannel,I=te.port2;te.port1.onmessage=K,G=function(){I.postMessage(null)}}else G=function(){k(K,0)};function V(E,O){H=k(function(){E(e.unstable_now())},O)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(E){E.callback=null},e.unstable_forceFrameRate=function(E){0>E||125P?(E.sortIndex=z,r(p,E),o(h)===null&&E===o(p)&&(w?(M(H),H=-1):w=!0,V(D,z-P))):(E.sortIndex=T,r(h,E),S||b||(S=!0,L||(L=!0,G()))),E},e.unstable_shouldYield=Z,e.unstable_wrapCallback=function(E){var O=v;return function(){var z=v;v=O;try{return E.apply(this,arguments)}finally{v=z}}}})(km)),km}var _v;function V_(){return _v||(_v=1,Cm.exports=$_()),Cm.exports}var Am={exports:{}},zt={};/** + */var _v;function $E(){return _v||(_v=1,(function(e){function r(_,O){var z=_.length;_.push(O);e:for(;0>>1,T=_[P];if(0>>1;Pl(ee,z))sel(he,ee)?(_[P]=he,_[se]=z,P=se):(_[P]=ee,_[X]=z,P=X);else if(sel(he,z))_[P]=he,_[se]=z,P=se;else break e}}return O}function l(_,O){var z=_.sortIndex-O.sortIndex;return z!==0?z:_.id-O.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var u=performance;e.unstable_now=function(){return u.now()}}else{var d=Date,f=d.now();e.unstable_now=function(){return d.now()-f}}var h=[],p=[],g=1,y=null,v=3,b=!1,S=!1,w=!1,j=!1,k=typeof setTimeout=="function"?setTimeout:null,M=typeof clearTimeout=="function"?clearTimeout:null,E=typeof setImmediate<"u"?setImmediate:null;function A(_){for(var O=o(p);O!==null;){if(O.callback===null)s(p);else if(O.startTime<=_)s(p),O.sortIndex=O.expirationTime,r(h,O);else break;O=o(p)}}function D(_){if(w=!1,A(_),!S)if(o(h)!==null)S=!0,L||(L=!0,G());else{var O=o(p);O!==null&&V(D,O.startTime-_)}}var L=!1,H=-1,B=5,q=-1;function F(){return j?!0:!(e.unstable_now()-q_&&F());){var P=y.callback;if(typeof P=="function"){y.callback=null,v=y.priorityLevel;var T=P(y.expirationTime<=_);if(_=e.unstable_now(),typeof T=="function"){y.callback=T,A(_),O=!0;break t}y===o(h)&&s(h),A(_)}else s(h);y=o(h)}if(y!==null)O=!0;else{var U=o(p);U!==null&&V(D,U.startTime-_),O=!1}}break e}finally{y=null,v=z,b=!1}O=void 0}}finally{O?G():L=!1}}}var G;if(typeof E=="function")G=function(){E(K)};else if(typeof MessageChannel<"u"){var te=new MessageChannel,I=te.port2;te.port1.onmessage=K,G=function(){I.postMessage(null)}}else G=function(){k(K,0)};function V(_,O){H=k(function(){_(e.unstable_now())},O)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(_){_.callback=null},e.unstable_forceFrameRate=function(_){0>_||125<_?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):B=0<_?Math.floor(1e3/_):5},e.unstable_getCurrentPriorityLevel=function(){return v},e.unstable_next=function(_){switch(v){case 1:case 2:case 3:var O=3;break;default:O=v}var z=v;v=O;try{return _()}finally{v=z}},e.unstable_requestPaint=function(){j=!0},e.unstable_runWithPriority=function(_,O){switch(_){case 1:case 2:case 3:case 4:case 5:break;default:_=3}var z=v;v=_;try{return O()}finally{v=z}},e.unstable_scheduleCallback=function(_,O,z){var P=e.unstable_now();switch(typeof z=="object"&&z!==null?(z=z.delay,z=typeof z=="number"&&0P?(_.sortIndex=z,r(p,_),o(h)===null&&_===o(p)&&(w?(M(H),H=-1):w=!0,V(D,z-P))):(_.sortIndex=T,r(h,_),S||b||(S=!0,L||(L=!0,G()))),_},e.unstable_shouldYield=F,e.unstable_wrapCallback=function(_){var O=v;return function(){var z=v;v=O;try{return _.apply(this,arguments)}finally{v=z}}}})(km)),km}var Ev;function VE(){return Ev||(Ev=1,Cm.exports=$E()),Cm.exports}var Am={exports:{}},zt={};/** * @license React * react-dom.production.js * @@ -30,7 +30,7 @@ function H_(e,r){for(var o=0;o"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(r){console.error(r)}}return e(),Am.exports=q_(),Am.exports}/** + */var jv;function qE(){if(jv)return zt;jv=1;var e=Wi();function r(h){var p="https://react.dev/errors/"+h;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(r){console.error(r)}}return e(),Am.exports=qE(),Am.exports}/** * @license React * react-dom-client.production.js * @@ -38,60 +38,60 @@ function H_(e,r){for(var o=0;oT||(t.current=P[T],P[T]=null,T--)}function ee(t,n){T++,P[T]=t.current,t.current=n}var ae=U(null),me=U(null),ue=U(null),Q=U(null);function se(t,n){switch(ee(ue,n),ee(me,t),ee(ae,null),n.nodeType){case 9:case 11:t=(t=n.documentElement)&&(t=t.namespaceURI)?F0(t):0;break;default:if(t=n.tagName,n=n.namespaceURI)n=F0(n),t=Z0(n,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}X(ae),ee(ae,t)}function pe(){X(ae),X(me),X(ue)}function le(t){t.memoizedState!==null&&ee(Q,t);var n=ae.current,s=Z0(n,t.type);n!==s&&(ee(me,t),ee(ae,s))}function de(t){me.current===t&&(X(ae),X(me)),Q.current===t&&(X(Q),gi._currentValue=z)}var he=Object.prototype.hasOwnProperty,xe=e.unstable_scheduleCallback,ge=e.unstable_cancelCallback,Be=e.unstable_shouldYield,at=e.unstable_requestPaint,re=e.unstable_now,ve=e.unstable_getCurrentPriorityLevel,ke=e.unstable_ImmediatePriority,De=e.unstable_UserBlockingPriority,be=e.unstable_NormalPriority,Te=e.unstable_LowPriority,Ye=e.unstable_IdlePriority,it=e.log,Tn=e.unstable_setDisableYieldValue,Fe=null,Ue=null;function Qe(t){if(typeof it=="function"&&Tn(t),Ue&&typeof Ue.setStrictMode=="function")try{Ue.setStrictMode(Fe,t)}catch{}}var ht=Math.clz32?Math.clz32:dd,Ft=Math.log,gs=Math.LN2;function dd(t){return t>>>=0,t===0?32:31-(Ft(t)/gs|0)|0}var na=256,ra=4194304;function Wn(t){var n=t&42;if(n!==0)return n;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t&4194048;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function oa(t,n,s){var c=t.pendingLanes;if(c===0)return 0;var m=0,x=t.suspendedLanes,C=t.pingedLanes;t=t.warmLanes;var R=c&134217727;return R!==0?(c=R&~x,c!==0?m=Wn(c):(C&=R,C!==0?m=Wn(C):s||(s=R&~t,s!==0&&(m=Wn(s))))):(R=c&~x,R!==0?m=Wn(R):C!==0?m=Wn(C):s||(s=c&~t,s!==0&&(m=Wn(s)))),m===0?0:n!==0&&n!==m&&(n&x)===0&&(x=m&-m,s=n&-n,x>=s||x===32&&(s&4194048)!==0)?n:m}function xo(t,n){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&n)===0}function fd(t,n){switch(t){case 1:case 2:case 4:case 8:case 64:return n+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return n+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function dl(){var t=na;return na<<=1,(na&4194048)===0&&(na=256),t}function fl(){var t=ra;return ra<<=1,(ra&62914560)===0&&(ra=4194304),t}function xs(t){for(var n=[],s=0;31>s;s++)n.push(t);return n}function vo(t,n){t.pendingLanes|=n,n!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function md(t,n,s,c,m,x){var C=t.pendingLanes;t.pendingLanes=s,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=s,t.entangledLanes&=s,t.errorRecoveryDisabledLanes&=s,t.shellSuspendCounter=0;var R=t.entanglements,$=t.expirationTimes,J=t.hiddenUpdates;for(s=C&~s;0)":-1T||(t.current=P[T],P[T]=null,T--)}function ee(t,n){T++,P[T]=t.current,t.current=n}var se=U(null),he=U(null),fe=U(null),Q=U(null);function ae(t,n){switch(ee(fe,n),ee(he,t),ee(se,null),n.nodeType){case 9:case 11:t=(t=n.documentElement)&&(t=t.namespaceURI)?F0(t):0;break;default:if(t=n.tagName,n=n.namespaceURI)n=F0(n),t=Z0(n,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}X(se),ee(se,t)}function xe(){X(se),X(he),X(fe)}function le(t){t.memoizedState!==null&&ee(Q,t);var n=se.current,a=Z0(n,t.type);n!==a&&(ee(he,t),ee(se,a))}function ce(t){he.current===t&&(X(se),X(he)),Q.current===t&&(X(Q),gi._currentValue=z)}var ue=Object.prototype.hasOwnProperty,ge=e.unstable_scheduleCallback,pe=e.unstable_cancelCallback,Be=e.unstable_shouldYield,st=e.unstable_requestPaint,re=e.unstable_now,ve=e.unstable_getCurrentPriorityLevel,ke=e.unstable_ImmediatePriority,De=e.unstable_UserBlockingPriority,be=e.unstable_NormalPriority,Te=e.unstable_LowPriority,Ye=e.unstable_IdlePriority,it=e.log,Tn=e.unstable_setDisableYieldValue,Fe=null,Ue=null;function Qe(t){if(typeof it=="function"&&Tn(t),Ue&&typeof Ue.setStrictMode=="function")try{Ue.setStrictMode(Fe,t)}catch{}}var ht=Math.clz32?Math.clz32:dd,Ft=Math.log,ga=Math.LN2;function dd(t){return t>>>=0,t===0?32:31-(Ft(t)/ga|0)|0}var ns=256,rs=4194304;function Wn(t){var n=t&42;if(n!==0)return n;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t&4194048;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function os(t,n,a){var c=t.pendingLanes;if(c===0)return 0;var m=0,x=t.suspendedLanes,C=t.pingedLanes;t=t.warmLanes;var R=c&134217727;return R!==0?(c=R&~x,c!==0?m=Wn(c):(C&=R,C!==0?m=Wn(C):a||(a=R&~t,a!==0&&(m=Wn(a))))):(R=c&~x,R!==0?m=Wn(R):C!==0?m=Wn(C):a||(a=c&~t,a!==0&&(m=Wn(a)))),m===0?0:n!==0&&n!==m&&(n&x)===0&&(x=m&-m,a=n&-n,x>=a||x===32&&(a&4194048)!==0)?n:m}function xo(t,n){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&n)===0}function fd(t,n){switch(t){case 1:case 2:case 4:case 8:case 64:return n+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return n+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function dl(){var t=ns;return ns<<=1,(ns&4194048)===0&&(ns=256),t}function fl(){var t=rs;return rs<<=1,(rs&62914560)===0&&(rs=4194304),t}function xa(t){for(var n=[],a=0;31>a;a++)n.push(t);return n}function vo(t,n){t.pendingLanes|=n,n!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function md(t,n,a,c,m,x){var C=t.pendingLanes;t.pendingLanes=a,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=a,t.entangledLanes&=a,t.errorRecoveryDisabledLanes&=a,t.shellSuspendCounter=0;var R=t.entanglements,$=t.expirationTimes,J=t.hiddenUpdates;for(a=C&~a;0)":-1m||$[c]!==J[m]){var ie=` -`+$[c].replace(" at new "," at ");return t.displayName&&ie.includes("")&&(ie=ie.replace("",t.displayName)),ie}while(1<=c&&0<=m);break}}}finally{_s=!1,Error.prepareStackTrace=s}return(s=t?t.displayName||t.name:"")?tr(s):""}function yd(t){switch(t.tag){case 26:case 27:case 5:return tr(t.type);case 16:return tr("Lazy");case 13:return tr("Suspense");case 19:return tr("SuspenseList");case 0:case 15:return js(t.type,!1);case 11:return js(t.type.render,!1);case 1:return js(t.type,!0);case 31:return tr("Activity");default:return""}}function bl(t){try{var n="";do n+=yd(t),t=t.return;while(t);return n}catch(s){return` -Error generating stack: `+s.message+` -`+s.stack}}function Bt(t){switch(typeof t){case"bigint":case"boolean":case"number":case"string":case"undefined":return t;case"object":return t;default:return""}}function wl(t){var n=t.type;return(t=t.nodeName)&&t.toLowerCase()==="input"&&(n==="checkbox"||n==="radio")}function bd(t){var n=wl(t)?"checked":"value",s=Object.getOwnPropertyDescriptor(t.constructor.prototype,n),c=""+t[n];if(!t.hasOwnProperty(n)&&typeof s<"u"&&typeof s.get=="function"&&typeof s.set=="function"){var m=s.get,x=s.set;return Object.defineProperty(t,n,{configurable:!0,get:function(){return m.call(this)},set:function(C){c=""+C,x.call(this,C)}}),Object.defineProperty(t,n,{enumerable:s.enumerable}),{getValue:function(){return c},setValue:function(C){c=""+C},stopTracking:function(){t._valueTracker=null,delete t[n]}}}}function ia(t){t._valueTracker||(t._valueTracker=bd(t))}function Cs(t){if(!t)return!1;var n=t._valueTracker;if(!n)return!0;var s=n.getValue(),c="";return t&&(c=wl(t)?t.checked?"true":"false":t.value),t=c,t!==s?(n.setValue(t),!0):!1}function la(t){if(t=t||(typeof document<"u"?document:void 0),typeof t>"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var wd=/[\n"\\]/g;function Ut(t){return t.replace(wd,function(n){return"\\"+n.charCodeAt(0).toString(16)+" "})}function bo(t,n,s,c,m,x,C,R){t.name="",C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"?t.type=C:t.removeAttribute("type"),n!=null?C==="number"?(n===0&&t.value===""||t.value!=n)&&(t.value=""+Bt(n)):t.value!==""+Bt(n)&&(t.value=""+Bt(n)):C!=="submit"&&C!=="reset"||t.removeAttribute("value"),n!=null?ks(t,C,Bt(n)):s!=null?ks(t,C,Bt(s)):c!=null&&t.removeAttribute("value"),m==null&&x!=null&&(t.defaultChecked=!!x),m!=null&&(t.checked=m&&typeof m!="function"&&typeof m!="symbol"),R!=null&&typeof R!="function"&&typeof R!="symbol"&&typeof R!="boolean"?t.name=""+Bt(R):t.removeAttribute("name")}function Nl(t,n,s,c,m,x,C,R){if(x!=null&&typeof x!="function"&&typeof x!="symbol"&&typeof x!="boolean"&&(t.type=x),n!=null||s!=null){if(!(x!=="submit"&&x!=="reset"||n!=null))return;s=s!=null?""+Bt(s):"",n=n!=null?""+Bt(n):s,R||n===t.value||(t.value=n),t.defaultValue=n}c=c??m,c=typeof c!="function"&&typeof c!="symbol"&&!!c,t.checked=R?t.checked:!!c,t.defaultChecked=!!c,C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"&&(t.name=C)}function ks(t,n,s){n==="number"&&la(t.ownerDocument)===t||t.defaultValue===""+s||(t.defaultValue=""+s)}function nr(t,n,s,c){if(t=t.options,n){n={};for(var m=0;m"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),jd=!1;if(rr)try{var Ms={};Object.defineProperty(Ms,"passive",{get:function(){jd=!0}}),window.addEventListener("test",Ms,Ms),window.removeEventListener("test",Ms,Ms)}catch{jd=!1}var Or=null,Cd=null,El=null;function Qp(){if(El)return El;var t,n=Cd,s=n.length,c,m="value"in Or?Or.value:Or.textContent,x=m.length;for(t=0;t=Ds),og=" ",ag=!1;function sg(t,n){switch(t){case"keyup":return lE.indexOf(n.keyCode)!==-1;case"keydown":return n.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function ig(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var fa=!1;function uE(t,n){switch(t){case"compositionend":return ig(n);case"keypress":return n.which!==32?null:(ag=!0,og);case"textInput":return t=n.data,t===og&&ag?null:t;default:return null}}function dE(t,n){if(fa)return t==="compositionend"||!Rd&&sg(t,n)?(t=Qp(),El=Cd=Or=null,fa=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(n.ctrlKey||n.altKey||n.metaKey)||n.ctrlKey&&n.altKey){if(n.char&&1=n)return{node:s,offset:n-t};t=c}e:{for(;s;){if(s.nextSibling){s=s.nextSibling;break e}s=s.parentNode}s=void 0}s=pg(s)}}function xg(t,n){return t&&n?t===n?!0:t&&t.nodeType===3?!1:n&&n.nodeType===3?xg(t,n.parentNode):"contains"in t?t.contains(n):t.compareDocumentPosition?!!(t.compareDocumentPosition(n)&16):!1:!1}function vg(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var n=la(t.document);n instanceof t.HTMLIFrameElement;){try{var s=typeof n.contentWindow.location.href=="string"}catch{s=!1}if(s)t=n.contentWindow;else break;n=la(t.document)}return n}function zd(t){var n=t&&t.nodeName&&t.nodeName.toLowerCase();return n&&(n==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||n==="textarea"||t.contentEditable==="true")}var yE=rr&&"documentMode"in document&&11>=document.documentMode,ma=null,Ld=null,Is=null,Id=!1;function yg(t,n,s){var c=s.window===s?s.document:s.nodeType===9?s:s.ownerDocument;Id||ma==null||ma!==la(c)||(c=ma,"selectionStart"in c&&zd(c)?c={start:c.selectionStart,end:c.selectionEnd}:(c=(c.ownerDocument&&c.ownerDocument.defaultView||window).getSelection(),c={anchorNode:c.anchorNode,anchorOffset:c.anchorOffset,focusNode:c.focusNode,focusOffset:c.focusOffset}),Is&&Ls(Is,c)||(Is=c,c=hc(Ld,"onSelect"),0>=C,m-=C,ar=1<<32-ht(n)+m|s<x?x:8;var C=E.T,R={};E.T=R,Sf(t,!1,n,s);try{var $=m(),J=E.S;if(J!==null&&J(R,$),$!==null&&typeof $=="object"&&typeof $.then=="function"){var ie=kE($,c);Qs(t,n,ie,en(t))}else Qs(t,n,c,en(t))}catch(fe){Qs(t,n,{then:function(){},status:"rejected",reason:fe},en())}finally{O.p=x,E.T=C}}function DE(){}function wf(t,n,s,c){if(t.tag!==5)throw Error(a(476));var m=bx(t).queue;yx(t,m,n,z,s===null?DE:function(){return wx(t),s(c)})}function bx(t){var n=t.memoizedState;if(n!==null)return n;n={memoizedState:z,baseState:z,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:cr,lastRenderedState:z},next:null};var s={};return n.next={memoizedState:s,baseState:s,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:cr,lastRenderedState:s},next:null},t.memoizedState=n,t=t.alternate,t!==null&&(t.memoizedState=n),n}function wx(t){var n=bx(t).next.queue;Qs(t,n,{},en())}function Nf(){return Ot(gi)}function Nx(){return yt().memoizedState}function Sx(){return yt().memoizedState}function OE(t){for(var n=t.return;n!==null;){switch(n.tag){case 24:case 3:var s=en();t=Ir(s);var c=Hr(n,t,s);c!==null&&(tn(c,n,s),Gs(c,n,s)),n={cache:Wd()},t.payload=n;return}n=n.return}}function zE(t,n,s){var c=en();s={lane:c,revertLane:0,action:s,hasEagerState:!1,eagerState:null,next:null},Fl(t)?_x(n,s):(s=Pd(t,n,s,c),s!==null&&(tn(s,t,c),jx(s,n,c)))}function Ex(t,n,s){var c=en();Qs(t,n,s,c)}function Qs(t,n,s,c){var m={lane:c,revertLane:0,action:s,hasEagerState:!1,eagerState:null,next:null};if(Fl(t))_x(n,m);else{var x=t.alternate;if(t.lanes===0&&(x===null||x.lanes===0)&&(x=n.lastRenderedReducer,x!==null))try{var C=n.lastRenderedState,R=x(C,s);if(m.hasEagerState=!0,m.eagerState=R,Zt(R,C))return Tl(t,n,m,0),st===null&&Ml(),!1}catch{}finally{}if(s=Pd(t,n,m,c),s!==null)return tn(s,t,c),jx(s,n,c),!0}return!1}function Sf(t,n,s,c){if(c={lane:2,revertLane:tm(),action:c,hasEagerState:!1,eagerState:null,next:null},Fl(t)){if(n)throw Error(a(479))}else n=Pd(t,s,c,2),n!==null&&tn(n,t,2)}function Fl(t){var n=t.alternate;return t===Ie||n!==null&&n===Ie}function _x(t,n){Sa=$l=!0;var s=t.pending;s===null?n.next=n:(n.next=s.next,s.next=n),t.pending=n}function jx(t,n,s){if((s&4194048)!==0){var c=n.lanes;c&=t.pendingLanes,s|=c,n.lanes=s,vs(t,s)}}var Zl={readContext:Ot,use:ql,useCallback:pt,useContext:pt,useEffect:pt,useImperativeHandle:pt,useLayoutEffect:pt,useInsertionEffect:pt,useMemo:pt,useReducer:pt,useRef:pt,useState:pt,useDebugValue:pt,useDeferredValue:pt,useTransition:pt,useSyncExternalStore:pt,useId:pt,useHostTransitionStatus:pt,useFormState:pt,useActionState:pt,useOptimistic:pt,useMemoCache:pt,useCacheRefresh:pt},Cx={readContext:Ot,use:ql,useCallback:function(t,n){return $t().memoizedState=[t,n===void 0?null:n],t},useContext:Ot,useEffect:ux,useImperativeHandle:function(t,n,s){s=s!=null?s.concat([t]):null,Xl(4194308,4,hx.bind(null,n,t),s)},useLayoutEffect:function(t,n){return Xl(4194308,4,t,n)},useInsertionEffect:function(t,n){Xl(4,2,t,n)},useMemo:function(t,n){var s=$t();n=n===void 0?null:n;var c=t();if(Ro){Qe(!0);try{t()}finally{Qe(!1)}}return s.memoizedState=[c,n],c},useReducer:function(t,n,s){var c=$t();if(s!==void 0){var m=s(n);if(Ro){Qe(!0);try{s(n)}finally{Qe(!1)}}}else m=n;return c.memoizedState=c.baseState=m,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:m},c.queue=t,t=t.dispatch=zE.bind(null,Ie,t),[c.memoizedState,t]},useRef:function(t){var n=$t();return t={current:t},n.memoizedState=t},useState:function(t){t=xf(t);var n=t.queue,s=Ex.bind(null,Ie,n);return n.dispatch=s,[t.memoizedState,s]},useDebugValue:yf,useDeferredValue:function(t,n){var s=$t();return bf(s,t,n)},useTransition:function(){var t=xf(!1);return t=yx.bind(null,Ie,t.queue,!0,!1),$t().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,n,s){var c=Ie,m=$t();if(We){if(s===void 0)throw Error(a(407));s=s()}else{if(s=n(),st===null)throw Error(a(349));(Ge&124)!==0||Fg(c,n,s)}m.memoizedState=s;var x={value:s,getSnapshot:n};return m.queue=x,ux(Kg.bind(null,c,x,t),[t]),c.flags|=2048,_a(9,Gl(),Zg.bind(null,c,x,s,n),null),s},useId:function(){var t=$t(),n=st.identifierPrefix;if(We){var s=sr,c=ar;s=(c&~(1<<32-ht(c)-1)).toString(32)+s,n="«"+n+"R"+s,s=Vl++,0Me?(Ct=je,je=null):Ct=je.sibling;var Ze=ne(F,je,W[Me],ce);if(Ze===null){je===null&&(je=Ct);break}t&&je&&Ze.alternate===null&&n(F,je),Y=x(Ze,Y,Me),Pe===null?we=Ze:Pe.sibling=Ze,Pe=Ze,je=Ct}if(Me===W.length)return s(F,je),We&&jo(F,Me),we;if(je===null){for(;MeMe?(Ct=je,je=null):Ct=je.sibling;var to=ne(F,je,Ze.value,ce);if(to===null){je===null&&(je=Ct);break}t&&je&&to.alternate===null&&n(F,je),Y=x(to,Y,Me),Pe===null?we=to:Pe.sibling=to,Pe=to,je=Ct}if(Ze.done)return s(F,je),We&&jo(F,Me),we;if(je===null){for(;!Ze.done;Me++,Ze=W.next())Ze=fe(F,Ze.value,ce),Ze!==null&&(Y=x(Ze,Y,Me),Pe===null?we=Ze:Pe.sibling=Ze,Pe=Ze);return We&&jo(F,Me),we}for(je=c(je);!Ze.done;Me++,Ze=W.next())Ze=oe(je,F,Me,Ze.value,ce),Ze!==null&&(t&&Ze.alternate!==null&&je.delete(Ze.key===null?Me:Ze.key),Y=x(Ze,Y,Me),Pe===null?we=Ze:Pe.sibling=Ze,Pe=Ze);return t&&je.forEach(function(I_){return n(F,I_)}),We&&jo(F,Me),we}function rt(F,Y,W,ce){if(typeof W=="object"&&W!==null&&W.type===S&&W.key===null&&(W=W.props.children),typeof W=="object"&&W!==null){switch(W.$$typeof){case v:e:{for(var we=W.key;Y!==null;){if(Y.key===we){if(we=W.type,we===S){if(Y.tag===7){s(F,Y.sibling),ce=m(Y,W.props.children),ce.return=F,F=ce;break e}}else if(Y.elementType===we||typeof we=="object"&&we!==null&&we.$$typeof===B&&Ax(we)===Y.type){s(F,Y.sibling),ce=m(Y,W.props),ei(ce,W),ce.return=F,F=ce;break e}s(F,Y);break}else n(F,Y);Y=Y.sibling}W.type===S?(ce=Eo(W.props.children,F.mode,ce,W.key),ce.return=F,F=ce):(ce=Dl(W.type,W.key,W.props,null,F.mode,ce),ei(ce,W),ce.return=F,F=ce)}return C(F);case b:e:{for(we=W.key;Y!==null;){if(Y.key===we)if(Y.tag===4&&Y.stateNode.containerInfo===W.containerInfo&&Y.stateNode.implementation===W.implementation){s(F,Y.sibling),ce=m(Y,W.children||[]),ce.return=F,F=ce;break e}else{s(F,Y);break}else n(F,Y);Y=Y.sibling}ce=qd(W,F.mode,ce),ce.return=F,F=ce}return C(F);case B:return we=W._init,W=we(W._payload),rt(F,Y,W,ce)}if(V(W))return Re(F,Y,W,ce);if(G(W)){if(we=G(W),typeof we!="function")throw Error(a(150));return W=we.call(W),Ae(F,Y,W,ce)}if(typeof W.then=="function")return rt(F,Y,Kl(W),ce);if(W.$$typeof===_)return rt(F,Y,Il(F,W),ce);Wl(F,W)}return typeof W=="string"&&W!==""||typeof W=="number"||typeof W=="bigint"?(W=""+W,Y!==null&&Y.tag===6?(s(F,Y.sibling),ce=m(Y,W),ce.return=F,F=ce):(s(F,Y),ce=Vd(W,F.mode,ce),ce.return=F,F=ce),C(F)):s(F,Y)}return function(F,Y,W,ce){try{Js=0;var we=rt(F,Y,W,ce);return ja=null,we}catch(je){if(je===qs||je===Bl)throw je;var Pe=Kt(29,je,null,F.mode);return Pe.lanes=ce,Pe.return=F,Pe}finally{}}}var Ca=Mx(!0),Tx=Mx(!1),mn=U(null),On=null;function Ur(t){var n=t.alternate;ee(Nt,Nt.current&1),ee(mn,t),On===null&&(n===null||Na.current!==null||n.memoizedState!==null)&&(On=t)}function Rx(t){if(t.tag===22){if(ee(Nt,Nt.current),ee(mn,t),On===null){var n=t.alternate;n!==null&&n.memoizedState!==null&&(On=t)}}else Pr()}function Pr(){ee(Nt,Nt.current),ee(mn,mn.current)}function ur(t){X(mn),On===t&&(On=null),X(Nt)}var Nt=U(0);function Ql(t){for(var n=t;n!==null;){if(n.tag===13){var s=n.memoizedState;if(s!==null&&(s=s.dehydrated,s===null||s.data==="$?"||mm(s)))return n}else if(n.tag===19&&n.memoizedProps.revealOrder!==void 0){if((n.flags&128)!==0)return n}else if(n.child!==null){n.child.return=n,n=n.child;continue}if(n===t)break;for(;n.sibling===null;){if(n.return===null||n.return===t)return null;n=n.return}n.sibling.return=n.return,n=n.sibling}return null}function Ef(t,n,s,c){n=t.memoizedState,s=s(c,n),s=s==null?n:g({},n,s),t.memoizedState=s,t.lanes===0&&(t.updateQueue.baseState=s)}var _f={enqueueSetState:function(t,n,s){t=t._reactInternals;var c=en(),m=Ir(c);m.payload=n,s!=null&&(m.callback=s),n=Hr(t,m,c),n!==null&&(tn(n,t,c),Gs(n,t,c))},enqueueReplaceState:function(t,n,s){t=t._reactInternals;var c=en(),m=Ir(c);m.tag=1,m.payload=n,s!=null&&(m.callback=s),n=Hr(t,m,c),n!==null&&(tn(n,t,c),Gs(n,t,c))},enqueueForceUpdate:function(t,n){t=t._reactInternals;var s=en(),c=Ir(s);c.tag=2,n!=null&&(c.callback=n),n=Hr(t,c,s),n!==null&&(tn(n,t,s),Gs(n,t,s))}};function Dx(t,n,s,c,m,x,C){return t=t.stateNode,typeof t.shouldComponentUpdate=="function"?t.shouldComponentUpdate(c,x,C):n.prototype&&n.prototype.isPureReactComponent?!Ls(s,c)||!Ls(m,x):!0}function Ox(t,n,s,c){t=n.state,typeof n.componentWillReceiveProps=="function"&&n.componentWillReceiveProps(s,c),typeof n.UNSAFE_componentWillReceiveProps=="function"&&n.UNSAFE_componentWillReceiveProps(s,c),n.state!==t&&_f.enqueueReplaceState(n,n.state,null)}function Do(t,n){var s=n;if("ref"in n){s={};for(var c in n)c!=="ref"&&(s[c]=n[c])}if(t=t.defaultProps){s===n&&(s=g({},s));for(var m in t)s[m]===void 0&&(s[m]=t[m])}return s}var Jl=typeof reportError=="function"?reportError:function(t){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var n=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof t=="object"&&t!==null&&typeof t.message=="string"?String(t.message):String(t),error:t});if(!window.dispatchEvent(n))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",t);return}console.error(t)};function zx(t){Jl(t)}function Lx(t){console.error(t)}function Ix(t){Jl(t)}function ec(t,n){try{var s=t.onUncaughtError;s(n.value,{componentStack:n.stack})}catch(c){setTimeout(function(){throw c})}}function Hx(t,n,s){try{var c=t.onCaughtError;c(s.value,{componentStack:s.stack,errorBoundary:n.tag===1?n.stateNode:null})}catch(m){setTimeout(function(){throw m})}}function jf(t,n,s){return s=Ir(s),s.tag=3,s.payload={element:null},s.callback=function(){ec(t,n)},s}function Bx(t){return t=Ir(t),t.tag=3,t}function Ux(t,n,s,c){var m=s.type.getDerivedStateFromError;if(typeof m=="function"){var x=c.value;t.payload=function(){return m(x)},t.callback=function(){Hx(n,s,c)}}var C=s.stateNode;C!==null&&typeof C.componentDidCatch=="function"&&(t.callback=function(){Hx(n,s,c),typeof m!="function"&&(Xr===null?Xr=new Set([this]):Xr.add(this));var R=c.stack;this.componentDidCatch(c.value,{componentStack:R!==null?R:""})})}function IE(t,n,s,c,m){if(s.flags|=32768,c!==null&&typeof c=="object"&&typeof c.then=="function"){if(n=s.alternate,n!==null&&Ps(n,s,m,!0),s=mn.current,s!==null){switch(s.tag){case 13:return On===null?Kf():s.alternate===null&&mt===0&&(mt=3),s.flags&=-257,s.flags|=65536,s.lanes=m,c===ef?s.flags|=16384:(n=s.updateQueue,n===null?s.updateQueue=new Set([c]):n.add(c),Qf(t,c,m)),!1;case 22:return s.flags|=65536,c===ef?s.flags|=16384:(n=s.updateQueue,n===null?(n={transitions:null,markerInstances:null,retryQueue:new Set([c])},s.updateQueue=n):(s=n.retryQueue,s===null?n.retryQueue=new Set([c]):s.add(c)),Qf(t,c,m)),!1}throw Error(a(435,s.tag))}return Qf(t,c,m),Kf(),!1}if(We)return n=mn.current,n!==null?((n.flags&65536)===0&&(n.flags|=256),n.flags|=65536,n.lanes=m,c!==Xd&&(t=Error(a(422),{cause:c}),Us(cn(t,s)))):(c!==Xd&&(n=Error(a(423),{cause:c}),Us(cn(n,s))),t=t.current.alternate,t.flags|=65536,m&=-m,t.lanes|=m,c=cn(c,s),m=jf(t.stateNode,c,m),rf(t,m),mt!==4&&(mt=2)),!1;var x=Error(a(520),{cause:c});if(x=cn(x,s),ii===null?ii=[x]:ii.push(x),mt!==4&&(mt=2),n===null)return!0;c=cn(c,s),s=n;do{switch(s.tag){case 3:return s.flags|=65536,t=m&-m,s.lanes|=t,t=jf(s.stateNode,c,t),rf(s,t),!1;case 1:if(n=s.type,x=s.stateNode,(s.flags&128)===0&&(typeof n.getDerivedStateFromError=="function"||x!==null&&typeof x.componentDidCatch=="function"&&(Xr===null||!Xr.has(x))))return s.flags|=65536,m&=-m,s.lanes|=m,m=Bx(m),Ux(m,t,s,c),rf(s,m),!1}s=s.return}while(s!==null);return!1}var Px=Error(a(461)),_t=!1;function kt(t,n,s,c){n.child=t===null?Tx(n,null,s,c):Ca(n,t.child,s,c)}function $x(t,n,s,c,m){s=s.render;var x=n.ref;if("ref"in c){var C={};for(var R in c)R!=="ref"&&(C[R]=c[R])}else C=c;return Mo(n),c=cf(t,n,s,C,x,m),R=uf(),t!==null&&!_t?(df(t,n,m),dr(t,n,m)):(We&&R&&Yd(n),n.flags|=1,kt(t,n,c,m),n.child)}function Vx(t,n,s,c,m){if(t===null){var x=s.type;return typeof x=="function"&&!$d(x)&&x.defaultProps===void 0&&s.compare===null?(n.tag=15,n.type=x,qx(t,n,x,c,m)):(t=Dl(s.type,null,c,n,n.mode,m),t.ref=n.ref,t.return=n,n.child=t)}if(x=t.child,!Of(t,m)){var C=x.memoizedProps;if(s=s.compare,s=s!==null?s:Ls,s(C,c)&&t.ref===n.ref)return dr(t,n,m)}return n.flags|=1,t=or(x,c),t.ref=n.ref,t.return=n,n.child=t}function qx(t,n,s,c,m){if(t!==null){var x=t.memoizedProps;if(Ls(x,c)&&t.ref===n.ref)if(_t=!1,n.pendingProps=c=x,Of(t,m))(t.flags&131072)!==0&&(_t=!0);else return n.lanes=t.lanes,dr(t,n,m)}return Cf(t,n,s,c,m)}function Yx(t,n,s){var c=n.pendingProps,m=c.children,x=t!==null?t.memoizedState:null;if(c.mode==="hidden"){if((n.flags&128)!==0){if(c=x!==null?x.baseLanes|s:s,t!==null){for(m=n.child=t.child,x=0;m!==null;)x=x|m.lanes|m.childLanes,m=m.sibling;n.childLanes=x&~c}else n.childLanes=0,n.child=null;return Gx(t,n,c,s)}if((s&536870912)!==0)n.memoizedState={baseLanes:0,cachePool:null},t!==null&&Hl(n,x!==null?x.cachePool:null),x!==null?qg(n,x):af(),Rx(n);else return n.lanes=n.childLanes=536870912,Gx(t,n,x!==null?x.baseLanes|s:s,s)}else x!==null?(Hl(n,x.cachePool),qg(n,x),Pr(),n.memoizedState=null):(t!==null&&Hl(n,null),af(),Pr());return kt(t,n,m,s),n.child}function Gx(t,n,s,c){var m=Jd();return m=m===null?null:{parent:wt._currentValue,pool:m},n.memoizedState={baseLanes:s,cachePool:m},t!==null&&Hl(n,null),af(),Rx(n),t!==null&&Ps(t,n,c,!0),null}function tc(t,n){var s=n.ref;if(s===null)t!==null&&t.ref!==null&&(n.flags|=4194816);else{if(typeof s!="function"&&typeof s!="object")throw Error(a(284));(t===null||t.ref!==s)&&(n.flags|=4194816)}}function Cf(t,n,s,c,m){return Mo(n),s=cf(t,n,s,c,void 0,m),c=uf(),t!==null&&!_t?(df(t,n,m),dr(t,n,m)):(We&&c&&Yd(n),n.flags|=1,kt(t,n,s,m),n.child)}function Xx(t,n,s,c,m,x){return Mo(n),n.updateQueue=null,s=Gg(n,c,s,m),Yg(t),c=uf(),t!==null&&!_t?(df(t,n,x),dr(t,n,x)):(We&&c&&Yd(n),n.flags|=1,kt(t,n,s,x),n.child)}function Fx(t,n,s,c,m){if(Mo(n),n.stateNode===null){var x=xa,C=s.contextType;typeof C=="object"&&C!==null&&(x=Ot(C)),x=new s(c,x),n.memoizedState=x.state!==null&&x.state!==void 0?x.state:null,x.updater=_f,n.stateNode=x,x._reactInternals=n,x=n.stateNode,x.props=c,x.state=n.memoizedState,x.refs={},tf(n),C=s.contextType,x.context=typeof C=="object"&&C!==null?Ot(C):xa,x.state=n.memoizedState,C=s.getDerivedStateFromProps,typeof C=="function"&&(Ef(n,s,C,c),x.state=n.memoizedState),typeof s.getDerivedStateFromProps=="function"||typeof x.getSnapshotBeforeUpdate=="function"||typeof x.UNSAFE_componentWillMount!="function"&&typeof x.componentWillMount!="function"||(C=x.state,typeof x.componentWillMount=="function"&&x.componentWillMount(),typeof x.UNSAFE_componentWillMount=="function"&&x.UNSAFE_componentWillMount(),C!==x.state&&_f.enqueueReplaceState(x,x.state,null),Fs(n,c,x,m),Xs(),x.state=n.memoizedState),typeof x.componentDidMount=="function"&&(n.flags|=4194308),c=!0}else if(t===null){x=n.stateNode;var R=n.memoizedProps,$=Do(s,R);x.props=$;var J=x.context,ie=s.contextType;C=xa,typeof ie=="object"&&ie!==null&&(C=Ot(ie));var fe=s.getDerivedStateFromProps;ie=typeof fe=="function"||typeof x.getSnapshotBeforeUpdate=="function",R=n.pendingProps!==R,ie||typeof x.UNSAFE_componentWillReceiveProps!="function"&&typeof x.componentWillReceiveProps!="function"||(R||J!==C)&&Ox(n,x,c,C),Lr=!1;var ne=n.memoizedState;x.state=ne,Fs(n,c,x,m),Xs(),J=n.memoizedState,R||ne!==J||Lr?(typeof fe=="function"&&(Ef(n,s,fe,c),J=n.memoizedState),($=Lr||Dx(n,s,$,c,ne,J,C))?(ie||typeof x.UNSAFE_componentWillMount!="function"&&typeof x.componentWillMount!="function"||(typeof x.componentWillMount=="function"&&x.componentWillMount(),typeof x.UNSAFE_componentWillMount=="function"&&x.UNSAFE_componentWillMount()),typeof x.componentDidMount=="function"&&(n.flags|=4194308)):(typeof x.componentDidMount=="function"&&(n.flags|=4194308),n.memoizedProps=c,n.memoizedState=J),x.props=c,x.state=J,x.context=C,c=$):(typeof x.componentDidMount=="function"&&(n.flags|=4194308),c=!1)}else{x=n.stateNode,nf(t,n),C=n.memoizedProps,ie=Do(s,C),x.props=ie,fe=n.pendingProps,ne=x.context,J=s.contextType,$=xa,typeof J=="object"&&J!==null&&($=Ot(J)),R=s.getDerivedStateFromProps,(J=typeof R=="function"||typeof x.getSnapshotBeforeUpdate=="function")||typeof x.UNSAFE_componentWillReceiveProps!="function"&&typeof x.componentWillReceiveProps!="function"||(C!==fe||ne!==$)&&Ox(n,x,c,$),Lr=!1,ne=n.memoizedState,x.state=ne,Fs(n,c,x,m),Xs();var oe=n.memoizedState;C!==fe||ne!==oe||Lr||t!==null&&t.dependencies!==null&&Ll(t.dependencies)?(typeof R=="function"&&(Ef(n,s,R,c),oe=n.memoizedState),(ie=Lr||Dx(n,s,ie,c,ne,oe,$)||t!==null&&t.dependencies!==null&&Ll(t.dependencies))?(J||typeof x.UNSAFE_componentWillUpdate!="function"&&typeof x.componentWillUpdate!="function"||(typeof x.componentWillUpdate=="function"&&x.componentWillUpdate(c,oe,$),typeof x.UNSAFE_componentWillUpdate=="function"&&x.UNSAFE_componentWillUpdate(c,oe,$)),typeof x.componentDidUpdate=="function"&&(n.flags|=4),typeof x.getSnapshotBeforeUpdate=="function"&&(n.flags|=1024)):(typeof x.componentDidUpdate!="function"||C===t.memoizedProps&&ne===t.memoizedState||(n.flags|=4),typeof x.getSnapshotBeforeUpdate!="function"||C===t.memoizedProps&&ne===t.memoizedState||(n.flags|=1024),n.memoizedProps=c,n.memoizedState=oe),x.props=c,x.state=oe,x.context=$,c=ie):(typeof x.componentDidUpdate!="function"||C===t.memoizedProps&&ne===t.memoizedState||(n.flags|=4),typeof x.getSnapshotBeforeUpdate!="function"||C===t.memoizedProps&&ne===t.memoizedState||(n.flags|=1024),c=!1)}return x=c,tc(t,n),c=(n.flags&128)!==0,x||c?(x=n.stateNode,s=c&&typeof s.getDerivedStateFromError!="function"?null:x.render(),n.flags|=1,t!==null&&c?(n.child=Ca(n,t.child,null,m),n.child=Ca(n,null,s,m)):kt(t,n,s,m),n.memoizedState=x.state,t=n.child):t=dr(t,n,m),t}function Zx(t,n,s,c){return Bs(),n.flags|=256,kt(t,n,s,c),n.child}var kf={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function Af(t){return{baseLanes:t,cachePool:Lg()}}function Mf(t,n,s){return t=t!==null?t.childLanes&~s:0,n&&(t|=hn),t}function Kx(t,n,s){var c=n.pendingProps,m=!1,x=(n.flags&128)!==0,C;if((C=x)||(C=t!==null&&t.memoizedState===null?!1:(Nt.current&2)!==0),C&&(m=!0,n.flags&=-129),C=(n.flags&32)!==0,n.flags&=-33,t===null){if(We){if(m?Ur(n):Pr(),We){var R=ft,$;if($=R){e:{for($=R,R=Dn;$.nodeType!==8;){if(!R){R=null;break e}if($=wn($.nextSibling),$===null){R=null;break e}}R=$}R!==null?(n.memoizedState={dehydrated:R,treeContext:_o!==null?{id:ar,overflow:sr}:null,retryLane:536870912,hydrationErrors:null},$=Kt(18,null,null,0),$.stateNode=R,$.return=n,n.child=$,It=n,ft=null,$=!0):$=!1}$||ko(n)}if(R=n.memoizedState,R!==null&&(R=R.dehydrated,R!==null))return mm(R)?n.lanes=32:n.lanes=536870912,null;ur(n)}return R=c.children,c=c.fallback,m?(Pr(),m=n.mode,R=nc({mode:"hidden",children:R},m),c=Eo(c,m,s,null),R.return=n,c.return=n,R.sibling=c,n.child=R,m=n.child,m.memoizedState=Af(s),m.childLanes=Mf(t,C,s),n.memoizedState=kf,c):(Ur(n),Tf(n,R))}if($=t.memoizedState,$!==null&&(R=$.dehydrated,R!==null)){if(x)n.flags&256?(Ur(n),n.flags&=-257,n=Rf(t,n,s)):n.memoizedState!==null?(Pr(),n.child=t.child,n.flags|=128,n=null):(Pr(),m=c.fallback,R=n.mode,c=nc({mode:"visible",children:c.children},R),m=Eo(m,R,s,null),m.flags|=2,c.return=n,m.return=n,c.sibling=m,n.child=c,Ca(n,t.child,null,s),c=n.child,c.memoizedState=Af(s),c.childLanes=Mf(t,C,s),n.memoizedState=kf,n=m);else if(Ur(n),mm(R)){if(C=R.nextSibling&&R.nextSibling.dataset,C)var J=C.dgst;C=J,c=Error(a(419)),c.stack="",c.digest=C,Us({value:c,source:null,stack:null}),n=Rf(t,n,s)}else if(_t||Ps(t,n,s,!1),C=(s&t.childLanes)!==0,_t||C){if(C=st,C!==null&&(c=s&-s,c=(c&42)!==0?1:ys(c),c=(c&(C.suspendedLanes|s))!==0?0:c,c!==0&&c!==$.retryLane))throw $.retryLane=c,ga(t,c),tn(C,t,c),Px;R.data==="$?"||Kf(),n=Rf(t,n,s)}else R.data==="$?"?(n.flags|=192,n.child=t.child,n=null):(t=$.treeContext,ft=wn(R.nextSibling),It=n,We=!0,Co=null,Dn=!1,t!==null&&(dn[fn++]=ar,dn[fn++]=sr,dn[fn++]=_o,ar=t.id,sr=t.overflow,_o=n),n=Tf(n,c.children),n.flags|=4096);return n}return m?(Pr(),m=c.fallback,R=n.mode,$=t.child,J=$.sibling,c=or($,{mode:"hidden",children:c.children}),c.subtreeFlags=$.subtreeFlags&65011712,J!==null?m=or(J,m):(m=Eo(m,R,s,null),m.flags|=2),m.return=n,c.return=n,c.sibling=m,n.child=c,c=m,m=n.child,R=t.child.memoizedState,R===null?R=Af(s):($=R.cachePool,$!==null?(J=wt._currentValue,$=$.parent!==J?{parent:J,pool:J}:$):$=Lg(),R={baseLanes:R.baseLanes|s,cachePool:$}),m.memoizedState=R,m.childLanes=Mf(t,C,s),n.memoizedState=kf,c):(Ur(n),s=t.child,t=s.sibling,s=or(s,{mode:"visible",children:c.children}),s.return=n,s.sibling=null,t!==null&&(C=n.deletions,C===null?(n.deletions=[t],n.flags|=16):C.push(t)),n.child=s,n.memoizedState=null,s)}function Tf(t,n){return n=nc({mode:"visible",children:n},t.mode),n.return=t,t.child=n}function nc(t,n){return t=Kt(22,t,null,n),t.lanes=0,t.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null},t}function Rf(t,n,s){return Ca(n,t.child,null,s),t=Tf(n,n.pendingProps.children),t.flags|=2,n.memoizedState=null,t}function Wx(t,n,s){t.lanes|=n;var c=t.alternate;c!==null&&(c.lanes|=n),Zd(t.return,n,s)}function Df(t,n,s,c,m){var x=t.memoizedState;x===null?t.memoizedState={isBackwards:n,rendering:null,renderingStartTime:0,last:c,tail:s,tailMode:m}:(x.isBackwards=n,x.rendering=null,x.renderingStartTime=0,x.last=c,x.tail=s,x.tailMode=m)}function Qx(t,n,s){var c=n.pendingProps,m=c.revealOrder,x=c.tail;if(kt(t,n,c.children,s),c=Nt.current,(c&2)!==0)c=c&1|2,n.flags|=128;else{if(t!==null&&(t.flags&128)!==0)e:for(t=n.child;t!==null;){if(t.tag===13)t.memoizedState!==null&&Wx(t,s,n);else if(t.tag===19)Wx(t,s,n);else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===n)break e;for(;t.sibling===null;){if(t.return===null||t.return===n)break e;t=t.return}t.sibling.return=t.return,t=t.sibling}c&=1}switch(ee(Nt,c),m){case"forwards":for(s=n.child,m=null;s!==null;)t=s.alternate,t!==null&&Ql(t)===null&&(m=s),s=s.sibling;s=m,s===null?(m=n.child,n.child=null):(m=s.sibling,s.sibling=null),Df(n,!1,m,s,x);break;case"backwards":for(s=null,m=n.child,n.child=null;m!==null;){if(t=m.alternate,t!==null&&Ql(t)===null){n.child=m;break}t=m.sibling,m.sibling=s,s=m,m=t}Df(n,!0,s,null,x);break;case"together":Df(n,!1,null,null,void 0);break;default:n.memoizedState=null}return n.child}function dr(t,n,s){if(t!==null&&(n.dependencies=t.dependencies),Gr|=n.lanes,(s&n.childLanes)===0)if(t!==null){if(Ps(t,n,s,!1),(s&n.childLanes)===0)return null}else return null;if(t!==null&&n.child!==t.child)throw Error(a(153));if(n.child!==null){for(t=n.child,s=or(t,t.pendingProps),n.child=s,s.return=n;t.sibling!==null;)t=t.sibling,s=s.sibling=or(t,t.pendingProps),s.return=n;s.sibling=null}return n.child}function Of(t,n){return(t.lanes&n)!==0?!0:(t=t.dependencies,!!(t!==null&&Ll(t)))}function HE(t,n,s){switch(n.tag){case 3:se(n,n.stateNode.containerInfo),zr(n,wt,t.memoizedState.cache),Bs();break;case 27:case 5:le(n);break;case 4:se(n,n.stateNode.containerInfo);break;case 10:zr(n,n.type,n.memoizedProps.value);break;case 13:var c=n.memoizedState;if(c!==null)return c.dehydrated!==null?(Ur(n),n.flags|=128,null):(s&n.child.childLanes)!==0?Kx(t,n,s):(Ur(n),t=dr(t,n,s),t!==null?t.sibling:null);Ur(n);break;case 19:var m=(t.flags&128)!==0;if(c=(s&n.childLanes)!==0,c||(Ps(t,n,s,!1),c=(s&n.childLanes)!==0),m){if(c)return Qx(t,n,s);n.flags|=128}if(m=n.memoizedState,m!==null&&(m.rendering=null,m.tail=null,m.lastEffect=null),ee(Nt,Nt.current),c)break;return null;case 22:case 23:return n.lanes=0,Yx(t,n,s);case 24:zr(n,wt,t.memoizedState.cache)}return dr(t,n,s)}function Jx(t,n,s){if(t!==null)if(t.memoizedProps!==n.pendingProps)_t=!0;else{if(!Of(t,s)&&(n.flags&128)===0)return _t=!1,HE(t,n,s);_t=(t.flags&131072)!==0}else _t=!1,We&&(n.flags&1048576)!==0&&Ag(n,zl,n.index);switch(n.lanes=0,n.tag){case 16:e:{t=n.pendingProps;var c=n.elementType,m=c._init;if(c=m(c._payload),n.type=c,typeof c=="function")$d(c)?(t=Do(c,t),n.tag=1,n=Fx(null,n,c,t,s)):(n.tag=0,n=Cf(null,n,c,t,s));else{if(c!=null){if(m=c.$$typeof,m===A){n.tag=11,n=$x(null,n,c,t,s);break e}else if(m===H){n.tag=14,n=Vx(null,n,c,t,s);break e}}throw n=I(c)||c,Error(a(306,n,""))}}return n;case 0:return Cf(t,n,n.type,n.pendingProps,s);case 1:return c=n.type,m=Do(c,n.pendingProps),Fx(t,n,c,m,s);case 3:e:{if(se(n,n.stateNode.containerInfo),t===null)throw Error(a(387));c=n.pendingProps;var x=n.memoizedState;m=x.element,nf(t,n),Fs(n,c,null,s);var C=n.memoizedState;if(c=C.cache,zr(n,wt,c),c!==x.cache&&Kd(n,[wt],s,!0),Xs(),c=C.element,x.isDehydrated)if(x={element:c,isDehydrated:!1,cache:C.cache},n.updateQueue.baseState=x,n.memoizedState=x,n.flags&256){n=Zx(t,n,c,s);break e}else if(c!==m){m=cn(Error(a(424)),n),Us(m),n=Zx(t,n,c,s);break e}else{switch(t=n.stateNode.containerInfo,t.nodeType){case 9:t=t.body;break;default:t=t.nodeName==="HTML"?t.ownerDocument.body:t}for(ft=wn(t.firstChild),It=n,We=!0,Co=null,Dn=!0,s=Tx(n,null,c,s),n.child=s;s;)s.flags=s.flags&-3|4096,s=s.sibling}else{if(Bs(),c===m){n=dr(t,n,s);break e}kt(t,n,c,s)}n=n.child}return n;case 26:return tc(t,n),t===null?(s=rv(n.type,null,n.pendingProps,null))?n.memoizedState=s:We||(s=n.type,t=n.pendingProps,c=gc(ue.current).createElement(s),c[Et]=n,c[Dt]=t,Mt(c,s,t),xt(c),n.stateNode=c):n.memoizedState=rv(n.type,t.memoizedProps,n.pendingProps,t.memoizedState),null;case 27:return le(n),t===null&&We&&(c=n.stateNode=ev(n.type,n.pendingProps,ue.current),It=n,Dn=!0,m=ft,Kr(n.type)?(hm=m,ft=wn(c.firstChild)):ft=m),kt(t,n,n.pendingProps.children,s),tc(t,n),t===null&&(n.flags|=4194304),n.child;case 5:return t===null&&We&&((m=c=ft)&&(c=f_(c,n.type,n.pendingProps,Dn),c!==null?(n.stateNode=c,It=n,ft=wn(c.firstChild),Dn=!1,m=!0):m=!1),m||ko(n)),le(n),m=n.type,x=n.pendingProps,C=t!==null?t.memoizedProps:null,c=x.children,um(m,x)?c=null:C!==null&&um(m,C)&&(n.flags|=32),n.memoizedState!==null&&(m=cf(t,n,ME,null,null,s),gi._currentValue=m),tc(t,n),kt(t,n,c,s),n.child;case 6:return t===null&&We&&((t=s=ft)&&(s=m_(s,n.pendingProps,Dn),s!==null?(n.stateNode=s,It=n,ft=null,t=!0):t=!1),t||ko(n)),null;case 13:return Kx(t,n,s);case 4:return se(n,n.stateNode.containerInfo),c=n.pendingProps,t===null?n.child=Ca(n,null,c,s):kt(t,n,c,s),n.child;case 11:return $x(t,n,n.type,n.pendingProps,s);case 7:return kt(t,n,n.pendingProps,s),n.child;case 8:return kt(t,n,n.pendingProps.children,s),n.child;case 12:return kt(t,n,n.pendingProps.children,s),n.child;case 10:return c=n.pendingProps,zr(n,n.type,c.value),kt(t,n,c.children,s),n.child;case 9:return m=n.type._context,c=n.pendingProps.children,Mo(n),m=Ot(m),c=c(m),n.flags|=1,kt(t,n,c,s),n.child;case 14:return Vx(t,n,n.type,n.pendingProps,s);case 15:return qx(t,n,n.type,n.pendingProps,s);case 19:return Qx(t,n,s);case 31:return c=n.pendingProps,s=n.mode,c={mode:c.mode,children:c.children},t===null?(s=nc(c,s),s.ref=n.ref,n.child=s,s.return=n,n=s):(s=or(t.child,c),s.ref=n.ref,n.child=s,s.return=n,n=s),n;case 22:return Yx(t,n,s);case 24:return Mo(n),c=Ot(wt),t===null?(m=Jd(),m===null&&(m=st,x=Wd(),m.pooledCache=x,x.refCount++,x!==null&&(m.pooledCacheLanes|=s),m=x),n.memoizedState={parent:c,cache:m},tf(n),zr(n,wt,m)):((t.lanes&s)!==0&&(nf(t,n),Fs(n,null,null,s),Xs()),m=t.memoizedState,x=n.memoizedState,m.parent!==c?(m={parent:c,cache:c},n.memoizedState=m,n.lanes===0&&(n.memoizedState=n.updateQueue.baseState=m),zr(n,wt,c)):(c=x.cache,zr(n,wt,c),c!==m.cache&&Kd(n,[wt],s,!0))),kt(t,n,n.pendingProps.children,s),n.child;case 29:throw n.pendingProps}throw Error(a(156,n.tag))}function fr(t){t.flags|=4}function e0(t,n){if(n.type!=="stylesheet"||(n.state.loading&4)!==0)t.flags&=-16777217;else if(t.flags|=16777216,!lv(n)){if(n=mn.current,n!==null&&((Ge&4194048)===Ge?On!==null:(Ge&62914560)!==Ge&&(Ge&536870912)===0||n!==On))throw Ys=ef,Ig;t.flags|=8192}}function rc(t,n){n!==null&&(t.flags|=4),t.flags&16384&&(n=t.tag!==22?fl():536870912,t.lanes|=n,Ta|=n)}function ti(t,n){if(!We)switch(t.tailMode){case"hidden":n=t.tail;for(var s=null;n!==null;)n.alternate!==null&&(s=n),n=n.sibling;s===null?t.tail=null:s.sibling=null;break;case"collapsed":s=t.tail;for(var c=null;s!==null;)s.alternate!==null&&(c=s),s=s.sibling;c===null?n||t.tail===null?t.tail=null:t.tail.sibling=null:c.sibling=null}}function ut(t){var n=t.alternate!==null&&t.alternate.child===t.child,s=0,c=0;if(n)for(var m=t.child;m!==null;)s|=m.lanes|m.childLanes,c|=m.subtreeFlags&65011712,c|=m.flags&65011712,m.return=t,m=m.sibling;else for(m=t.child;m!==null;)s|=m.lanes|m.childLanes,c|=m.subtreeFlags,c|=m.flags,m.return=t,m=m.sibling;return t.subtreeFlags|=c,t.childLanes=s,n}function BE(t,n,s){var c=n.pendingProps;switch(Gd(n),n.tag){case 31:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return ut(n),null;case 1:return ut(n),null;case 3:return s=n.stateNode,c=null,t!==null&&(c=t.memoizedState.cache),n.memoizedState.cache!==c&&(n.flags|=2048),lr(wt),pe(),s.pendingContext&&(s.context=s.pendingContext,s.pendingContext=null),(t===null||t.child===null)&&(Hs(n)?fr(n):t===null||t.memoizedState.isDehydrated&&(n.flags&256)===0||(n.flags|=1024,Rg())),ut(n),null;case 26:return s=n.memoizedState,t===null?(fr(n),s!==null?(ut(n),e0(n,s)):(ut(n),n.flags&=-16777217)):s?s!==t.memoizedState?(fr(n),ut(n),e0(n,s)):(ut(n),n.flags&=-16777217):(t.memoizedProps!==c&&fr(n),ut(n),n.flags&=-16777217),null;case 27:de(n),s=ue.current;var m=n.type;if(t!==null&&n.stateNode!=null)t.memoizedProps!==c&&fr(n);else{if(!c){if(n.stateNode===null)throw Error(a(166));return ut(n),null}t=ae.current,Hs(n)?Mg(n):(t=ev(m,c,s),n.stateNode=t,fr(n))}return ut(n),null;case 5:if(de(n),s=n.type,t!==null&&n.stateNode!=null)t.memoizedProps!==c&&fr(n);else{if(!c){if(n.stateNode===null)throw Error(a(166));return ut(n),null}if(t=ae.current,Hs(n))Mg(n);else{switch(m=gc(ue.current),t){case 1:t=m.createElementNS("http://www.w3.org/2000/svg",s);break;case 2:t=m.createElementNS("http://www.w3.org/1998/Math/MathML",s);break;default:switch(s){case"svg":t=m.createElementNS("http://www.w3.org/2000/svg",s);break;case"math":t=m.createElementNS("http://www.w3.org/1998/Math/MathML",s);break;case"script":t=m.createElement("div"),t.innerHTML=" + diff --git a/python/packages/devui/frontend/src/components/features/workflow/workflow-view.tsx b/python/packages/devui/frontend/src/components/features/workflow/workflow-view.tsx index eb457536651..43cf1ac5097 100644 --- a/python/packages/devui/frontend/src/components/features/workflow/workflow-view.tsx +++ b/python/packages/devui/frontend/src/components/features/workflow/workflow-view.tsx @@ -408,46 +408,82 @@ export function WorkflowView({ // This preserves the workflow's final output for display }; - // Extract workflow events from OpenAI events for executor tracking + // Extract workflow and output item events from OpenAI events for executor tracking const workflowEvents = useMemo(() => { return openAIEvents.filter( - (event) => event.type === "response.workflow_event.complete" + (event) => + event.type === "response.output_item.added" || + event.type === "response.output_item.done" || + event.type === "response.created" || + event.type === "response.in_progress" || + event.type === "response.completed" || + event.type === "response.failed" || + // Keep legacy support for older backends + event.type === "response.workflow_event.complete" ); }, [openAIEvents]); // Extract executor history from workflow events (filter out workflow-level events) const executorHistory = useMemo(() => { - return workflowEvents - .filter((event) => { - if ("data" in event && event.data && typeof event.data === "object") { - const data = event.data as Record; - // Filter out workflow-level events (those without executor_id) - // These include: WorkflowStartedEvent, WorkflowOutputEvent, WorkflowStatusEvent, etc. - return data.executor_id != null; + const history: Array<{ + executorId: string; + message: string; + timestamp: string; + status: "running" | "completed" | "error"; + }> = []; + + workflowEvents.forEach((event) => { + // Handle new standard OpenAI events + if ( + event.type === "response.output_item.added" || + event.type === "response.output_item.done" + ) { + const item = (event as any).item; + if (item && item.type === "executor_action" && item.executor_id) { + history.push({ + executorId: item.executor_id, + message: + event.type === "response.output_item.added" + ? "Executor started" + : item.status === "completed" + ? "Executor completed" + : item.status === "failed" + ? "Executor failed" + : "Executor processing", + timestamp: new Date().toISOString(), + status: + item.status === "completed" + ? "completed" + : item.status === "failed" + ? "error" + : "running", + }); } - return false; - }) - .map((event) => { - if ("data" in event && event.data && typeof event.data === "object") { - const data = event.data as Record; - return { + } + // Legacy support for older backends + else if ( + event.type === "response.workflow_event.complete" && + "data" in event && + event.data && + typeof event.data === "object" + ) { + const data = event.data as Record; + if (data.executor_id != null) { + history.push({ executorId: String(data.executor_id), message: String(data.event_type || "Processing"), timestamp: String(data.timestamp || new Date().toISOString()), status: String(data.event_type || "").includes("Completed") - ? ("completed" as const) + ? "completed" : String(data.event_type || "").includes("Error") - ? ("error" as const) - : ("running" as const), - }; + ? "error" + : "running", + }); } - return { - executorId: "unknown", - message: "Processing", - timestamp: new Date().toISOString(), - status: "running" as const, - }; - }); + } + }); + + return history; }, [workflowEvents]); // Track active executors @@ -525,16 +561,51 @@ export function WorkflowView({ ); for await (const openAIEvent of streamGenerator) { - // Only store workflow events in state for performance - // Text deltas are processed directly without state updates - if (openAIEvent.type === "response.workflow_event.complete") { + // Store workflow-related events for tracking + if ( + openAIEvent.type === "response.output_item.added" || + openAIEvent.type === "response.output_item.done" || + openAIEvent.type === "response.created" || + openAIEvent.type === "response.in_progress" || + openAIEvent.type === "response.completed" || + openAIEvent.type === "response.failed" || + openAIEvent.type === "response.workflow_event.complete" // Legacy + ) { setOpenAIEvents((prev) => [...prev, openAIEvent]); } // Pass to debug panel onDebugEvent(openAIEvent); - // Handle workflow events to track current executor + // Handle new standard OpenAI events + if (openAIEvent.type === "response.output_item.added") { + const item = (openAIEvent as any).item; + if (item && item.type === "executor_action" && item.executor_id) { + currentStreamingExecutor.current = item.executor_id; + // Initialize output for this executor if not exists + if (!executorOutputs.current[item.executor_id]) { + executorOutputs.current[item.executor_id] = ""; + } + } + } + + // Handle workflow completion + if (openAIEvent.type === "response.completed") { + // Workflow completed successfully + // Final output is already in workflowResult from text streaming + } + + // Handle workflow failure + if (openAIEvent.type === "response.failed") { + const error = (openAIEvent as any).response?.error; + if (error) { + setWorkflowError( + typeof error === "string" ? error : JSON.stringify(error) + ); + } + } + + // Legacy support for older backends if ( openAIEvent.type === "response.workflow_event.complete" && "data" in openAIEvent && diff --git a/python/packages/devui/frontend/src/components/ui/markdown-renderer.tsx b/python/packages/devui/frontend/src/components/ui/markdown-renderer.tsx index 952dbc1aae0..375f3a010c4 100644 --- a/python/packages/devui/frontend/src/components/ui/markdown-renderer.tsx +++ b/python/packages/devui/frontend/src/components/ui/markdown-renderer.tsx @@ -18,7 +18,7 @@ * - Horizontal rules (---) */ -import React, { useState } from "react"; +import React, { useState, useRef, useEffect } from "react"; interface MarkdownRendererProps { content: string; @@ -35,10 +35,10 @@ interface CodeBlockProps { */ function CodeBlock({ code, language }: CodeBlockProps) { const [copied, setCopied] = useState(false); - const timeoutRef = React.useRef(null); + const timeoutRef = useRef(null); // Cleanup timeout on unmount - React.useEffect(() => { + useEffect(() => { return () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); diff --git a/python/packages/devui/frontend/src/services/api.ts b/python/packages/devui/frontend/src/services/api.ts index c94920222e5..8a685cf5aa1 100644 --- a/python/packages/devui/frontend/src/services/api.ts +++ b/python/packages/devui/frontend/src/services/api.ts @@ -397,9 +397,7 @@ class ApiClient { // Convert to OpenAI format - use model field for entity_id (same as agents) const openAIRequest: AgentFrameworkRequest = { model: workflowId, // Use workflow ID in model field (matches agent pattern) - input: typeof request.input_data === 'string' - ? request.input_data - : JSON.stringify(request.input_data || ""), // Convert input_data to string + input: request.input_data || "", // Send dict directly, no stringification needed stream: true, conversation: request.conversation_id, // Include conversation if present }; diff --git a/python/packages/devui/frontend/src/types/agent-framework.ts b/python/packages/devui/frontend/src/types/agent-framework.ts index 95cd0f261cd..c90c8beb918 100644 --- a/python/packages/devui/frontend/src/types/agent-framework.ts +++ b/python/packages/devui/frontend/src/types/agent-framework.ts @@ -68,13 +68,13 @@ export type ResponseInputParam = ResponseInputItem[]; // Agent Framework extension fields (matches backend AgentFrameworkExtraBody) export interface AgentFrameworkExtraBody { entity_id: string; - input_data?: Record; + // input_data removed - now using standard input field for all data } // Agent Framework Request - OpenAI ResponseCreateParams with extensions export interface AgentFrameworkRequest { model: string; - input: string | ResponseInputParam; // Union type matching OpenAI + input: string | ResponseInputParam | Record; // Union type matching OpenAI + dict for workflows stream?: boolean; // OpenAI conversation parameter (standard!) diff --git a/python/packages/devui/frontend/src/types/index.ts b/python/packages/devui/frontend/src/types/index.ts index 6d1a494cf5b..6435a91654f 100644 --- a/python/packages/devui/frontend/src/types/index.ts +++ b/python/packages/devui/frontend/src/types/index.ts @@ -104,11 +104,19 @@ export type { ResponseWorkflowEventComplete, ResponseTraceEventComplete, ResponseOutputItemAddedEvent, + ResponseOutputItemDoneEvent, + ResponseCreatedEvent, + ResponseInProgressEvent, ResponseCompletedEvent, + ResponseFailedEvent, ResponseFunctionResultComplete, StructuredEvent, + WorkflowItem, + ExecutorActionItem, } from "./openai"; +export { isExecutorAction } from "./openai"; + // Re-export Agent Framework types export type { AgentFrameworkRequest, diff --git a/python/packages/devui/frontend/src/types/openai.ts b/python/packages/devui/frontend/src/types/openai.ts index 9842e37bcc9..91bfb04c917 100644 --- a/python/packages/devui/frontend/src/types/openai.ts +++ b/python/packages/devui/frontend/src/types/openai.ts @@ -21,6 +21,48 @@ export interface ResponseStreamEvent { created_at?: number; } +// Standard OpenAI Response Lifecycle Events +export interface ResponseCreatedEvent { + type: "response.created"; + response: { + id: string; + status: "in_progress"; + created_at: number; + output?: any[]; + }; + sequence_number?: number; +} + +export interface ResponseInProgressEvent { + type: "response.in_progress"; + response: { + id: string; + status: "in_progress"; + }; + sequence_number?: number; +} + +export interface ResponseCompletedEvent { + type: "response.completed"; + response: { + id: string; + status: "completed"; + usage?: any; // Optional usage information + model?: string; // Optional model information + }; + sequence_number?: number; +} + +export interface ResponseFailedEvent { + type: "response.failed"; + response: { + id: string; + status: "failed"; + error?: any; + }; + sequence_number?: number; +} + // Custom Agent Framework OpenAI event types with structured data export interface ResponseWorkflowEventComplete { type: "response.workflow_event.complete"; @@ -83,13 +125,41 @@ export interface ResponseFunctionToolCall { status?: "in_progress" | "completed" | "incomplete"; } -// OpenAI Responses API - Output Item Added Event -// OpenAI standard: Output item added event +// Workflow Item Types - flexible interface for any workflow item +export interface WorkflowItem { + type: string; // "executor_action", "workflow_action", "message", or any future type + id: string; + status?: "in_progress" | "completed" | "failed" | "cancelled"; + [key: string]: any; // Allow any additional fields +} + +// Executor Action Item (DevUI specific) +export interface ExecutorActionItem extends WorkflowItem { + type: "executor_action"; + executor_id: string; + metadata?: Record; + result?: any; + error?: any; +} + +// Type guard for executor actions +export function isExecutorAction(item: WorkflowItem): item is ExecutorActionItem { + return item.type === "executor_action" && "executor_id" in item; +} + +// OpenAI Responses API - Output Item Events export interface ResponseOutputItemAddedEvent { type: "response.output_item.added"; - item: ResponseFunctionToolCall; + item: WorkflowItem | ResponseFunctionToolCall | any; // Flexible to support various item types output_index: number; - sequence_number: number; + sequence_number?: number; +} + +export interface ResponseOutputItemDoneEvent { + type: "response.output_item.done"; + item: WorkflowItem | ResponseFunctionToolCall | any; + output_index: number; + sequence_number?: number; } // Trace event - matching actual backend output @@ -182,11 +252,15 @@ export interface TurnSeparatorEvent { // Union type for all structured events export type StructuredEvent = + | ResponseCreatedEvent + | ResponseInProgressEvent | ResponseCompletedEvent + | ResponseFailedEvent | ResponseWorkflowEventComplete | ResponseTraceEventComplete | ResponseTraceComplete | ResponseOutputItemAddedEvent + | ResponseOutputItemDoneEvent | ResponseFunctionCallComplete | ResponseFunctionCallDelta | ResponseFunctionCallArgumentsDelta @@ -249,12 +323,6 @@ export interface ResponseUsage { }; } -// OpenAI standard: response.completed event -export interface ResponseCompletedEvent { - type: "response.completed"; - response: OpenAIResponse; - sequence_number: number; -} // Request format for Agent Framework // AgentFrameworkRequest moved to agent-framework.ts to avoid conflicts diff --git a/python/packages/devui/frontend/src/utils/workflow-utils.ts b/python/packages/devui/frontend/src/utils/workflow-utils.ts index 0663b6a3769..5e7c01bfb1f 100644 --- a/python/packages/devui/frontend/src/utils/workflow-utils.ts +++ b/python/packages/devui/frontend/src/utils/workflow-utils.ts @@ -307,6 +307,7 @@ export function applyDagreLayout( /** * Process workflow events and extract node updates + * Handles both new standard OpenAI events and legacy workflow events */ export function processWorkflowEvents( events: ExtendedResponseStreamEvent[], @@ -316,7 +317,43 @@ export function processWorkflowEvents( let hasWorkflowStarted = false; events.forEach((event) => { - if ( + // Handle new standard OpenAI events + if (event.type === "response.output_item.added" || event.type === "response.output_item.done") { + const item = (event as any).item; + if (item && item.type === "executor_action" && item.executor_id) { + const executorId = item.executor_id; + + let state: ExecutorState = "pending"; + let error: string | undefined; + + if (event.type === "response.output_item.added") { + state = "running"; + } else if (event.type === "response.output_item.done") { + if (item.status === "completed") { + state = "completed"; + } else if (item.status === "failed") { + state = "failed"; + error = item.error ? (typeof item.error === "string" ? item.error : JSON.stringify(item.error)) : "Execution failed"; + } else if (item.status === "cancelled") { + state = "cancelled"; + } + } + + nodeUpdates[executorId] = { + nodeId: executorId, + state, + data: item.result, + error, + timestamp: new Date().toISOString(), + }; + } + } + // Handle workflow lifecycle events + else if (event.type === "response.created" || event.type === "response.in_progress") { + hasWorkflowStarted = true; + } + // Legacy support for older backends + else if ( event.type === "response.workflow_event.complete" && "data" in event && event.data @@ -417,7 +454,20 @@ export function getCurrentlyExecutingExecutors( // Process events to find the most recent event for each executor events.forEach((event) => { - if ( + // Handle new standard OpenAI events + if (event.type === "response.output_item.added" || event.type === "response.output_item.done") { + const item = (event as any).item; + if (item && item.type === "executor_action" && item.executor_id) { + const executorId = item.executor_id; + + executorTimeline[executorId] = { + lastEvent: event.type === "response.output_item.added" ? "ExecutorInvokedEvent" : "ExecutorCompletedEvent", + timestamp: new Date().toISOString(), + }; + } + } + // Legacy support for older backends + else if ( event.type === "response.workflow_event.complete" && "data" in event && event.data diff --git a/python/packages/devui/tests/test_mapper.py b/python/packages/devui/tests/test_mapper.py index 7eb57a8c997..a41f3a7adcc 100644 --- a/python/packages/devui/tests/test_mapper.py +++ b/python/packages/devui/tests/test_mapper.py @@ -79,15 +79,30 @@ async def test_critical_isinstance_bug_detection(mapper: MessageMapper, test_req async def test_text_content_mapping(mapper: MessageMapper, test_request: AgentFrameworkRequest) -> None: - """Test TextContent mapping.""" + """Test TextContent mapping with proper OpenAI event hierarchy.""" content = create_test_content("text", text="Hello, clean test!") update = create_test_agent_update([content]) events = await mapper.convert_event(update, test_request) - assert len(events) == 1 - assert events[0].type == "response.output_text.delta" - assert events[0].delta == "Hello, clean test!" + # With proper OpenAI hierarchy, we expect 3 events: + # 1. response.output_item.added (message) + # 2. response.content_part.added (text part) + # 3. response.output_text.delta (actual text) + assert len(events) == 3 + + # Check message output item + assert events[0].type == "response.output_item.added" + assert events[0].item.type == "message" + assert events[0].item.role == "assistant" + + # Check content part + assert events[1].type == "response.content_part.added" + assert events[1].part.type == "output_text" + + # Check text delta + assert events[2].type == "response.output_text.delta" + assert events[2].delta == "Hello, clean test!" async def test_function_call_mapping(mapper: MessageMapper, test_request: AgentFrameworkRequest) -> None: @@ -182,6 +197,140 @@ async def test_agent_run_response_mapping(mapper: MessageMapper, test_request: A assert text_events[0].delta == "Complete response from run()" +async def test_agent_lifecycle_events(mapper: MessageMapper, test_request: AgentFrameworkRequest) -> None: + """Test that agent lifecycle events are properly converted to OpenAI format.""" + from agent_framework_devui.models._openai_custom import AgentCompletedEvent, AgentFailedEvent, AgentStartedEvent + + # Test AgentStartedEvent + start_event = AgentStartedEvent() + events = await mapper.convert_event(start_event, test_request) + + assert len(events) == 2 # Should emit response.created and response.in_progress + assert events[0].type == "response.created" + assert events[1].type == "response.in_progress" + assert events[0].response.model == "test_agent" # Should use model from request + assert events[0].response.status == "in_progress" + + # Test AgentCompletedEvent + complete_event = AgentCompletedEvent() + events = await mapper.convert_event(complete_event, test_request) + + assert len(events) == 1 + assert events[0].type == "response.completed" + assert events[0].response.status == "completed" + + # Test AgentFailedEvent + error = Exception("Test error") + failed_event = AgentFailedEvent(error=error) + events = await mapper.convert_event(failed_event, test_request) + + assert len(events) == 1 + assert events[0].type == "response.failed" + assert events[0].response.status == "failed" + assert events[0].response.error.message == "Test error" + assert events[0].response.error.code == "server_error" + + +@pytest.mark.skip(reason="Workflow events need real classes from agent_framework.workflows") +async def test_workflow_lifecycle_events(mapper: MessageMapper, test_request: AgentFrameworkRequest) -> None: + """Test that workflow lifecycle events are properly converted to OpenAI format.""" + + # Create mock workflow events (since we don't have access to the real ones in tests) + class WorkflowStartedEvent: # noqa: B903 + def __init__(self, workflow_id: str): + self.workflow_id = workflow_id + + class WorkflowCompletedEvent: # noqa: B903 + def __init__(self, workflow_id: str): + self.workflow_id = workflow_id + + class WorkflowFailedEvent: # noqa: B903 + def __init__(self, workflow_id: str, error_info: dict | None = None): + self.workflow_id = workflow_id + self.error_info = error_info + + # Test WorkflowStartedEvent + start_event = WorkflowStartedEvent(workflow_id="test_workflow_123") + events = await mapper.convert_event(start_event, test_request) + + assert len(events) == 2 # Should emit response.created and response.in_progress + assert events[0].type == "response.created" + assert events[1].type == "response.in_progress" + assert events[0].response.model == "test_agent" # Should use model from request + assert events[0].response.status == "in_progress" + + # Test WorkflowCompletedEvent + complete_event = WorkflowCompletedEvent(workflow_id="test_workflow_123") + events = await mapper.convert_event(complete_event, test_request) + + assert len(events) == 1 + assert events[0].type == "response.completed" + assert events[0].response.status == "completed" + + # Test WorkflowFailedEvent with error info + failed_event = WorkflowFailedEvent(workflow_id="test_workflow_123", error_info={"message": "Workflow failed"}) + events = await mapper.convert_event(failed_event, test_request) + + assert len(events) == 1 + assert events[0].type == "response.failed" + assert events[0].response.status == "failed" + assert events[0].response.error.message == "{'message': 'Workflow failed'}" + assert events[0].response.error.code == "server_error" + + +@pytest.mark.skip(reason="Executor events need real classes from agent_framework.workflows") +async def test_executor_action_events(mapper: MessageMapper, test_request: AgentFrameworkRequest) -> None: + """Test that workflow executor events are properly converted to custom output item events.""" + + # Create mock executor events (since we don't have access to the real ones in tests) + class ExecutorInvokedEvent: # noqa: B903 + def __init__(self, executor_id: str, executor_type: str = "test"): + self.executor_id = executor_id + self.executor_type = executor_type + + class ExecutorCompletedEvent: # noqa: B903 + def __init__(self, executor_id: str, result: Any = None): + self.executor_id = executor_id + self.result = result + + class ExecutorFailedEvent: # noqa: B903 + def __init__(self, executor_id: str, error: Exception | None = None): + self.executor_id = executor_id + self.error = error + + # Test ExecutorInvokedEvent + invoked_event = ExecutorInvokedEvent(executor_id="exec_123", executor_type="test_executor") + events = await mapper.convert_event(invoked_event, test_request) + + assert len(events) == 1 + assert events[0].type == "response.output_item.added" + assert events[0].item["type"] == "executor_action" + assert events[0].item["executor_id"] == "exec_123" + assert events[0].item["status"] == "in_progress" + + # Test ExecutorCompletedEvent + complete_event = ExecutorCompletedEvent(executor_id="exec_123", result={"data": "success"}) + events = await mapper.convert_event(complete_event, test_request) + + assert len(events) == 1 + assert events[0].type == "response.output_item.done" + assert events[0].item["type"] == "executor_action" + assert events[0].item["executor_id"] == "exec_123" + assert events[0].item["status"] == "completed" + assert events[0].item["result"] == {"data": "success"} + + # Test ExecutorFailedEvent + failed_event = ExecutorFailedEvent(executor_id="exec_123", error=Exception("Executor failed")) + events = await mapper.convert_event(failed_event, test_request) + + assert len(events) == 1 + assert events[0].type == "response.output_item.done" + assert events[0].item["type"] == "executor_action" + assert events[0].item["executor_id"] == "exec_123" + assert events[0].item["status"] == "failed" + assert "Executor failed" in str(events[0].item["error"]["message"]) + + if __name__ == "__main__": # Simple test runner async def run_all_tests() -> None: From fef846c3616ecd0655accfe0c4b3a9a6838c8a8a Mon Sep 17 00:00:00 2001 From: Victor Dibia Date: Mon, 20 Oct 2025 13:19:35 -0700 Subject: [PATCH 2/2] fix(devui): resolve timestamp overwriting and Content serialization errors - Fix tool call timestamps being overwritten on each render (#1483) - Add recursive Content serialization to handle ChatMessage and nested objects (#1548) - Implement proper MCP tool cleanup on server shutdown - Add timestamp field to function_result.complete events - Enhance credential and client resource cleanup Fixes #1483, #1548 Partial improvements for #1476 --- python/packages/devui/README.md | 92 ++++---- .../devui/agent_framework_devui/_mapper.py | 63 +++++- .../devui/agent_framework_devui/_server.py | 44 +++- .../models/_openai_custom.py | 1 + .../{index-DpQbOzAN.js => index-D_Y1oSGu.js} | 198 +++++++++--------- .../devui/agent_framework_devui/ui/index.html | 2 +- python/packages/devui/frontend/src/App.tsx | 4 +- .../src/components/layout/debug-panel.tsx | 37 +++- .../devui/frontend/src/types/openai.ts | 1 + python/packages/devui/tests/test_mapper.py | 86 +++++++- python/packages/devui/tests/test_server.py | 98 +++++++++ 11 files changed, 483 insertions(+), 143 deletions(-) rename python/packages/devui/agent_framework_devui/ui/assets/{index-DpQbOzAN.js => index-D_Y1oSGu.js} (79%) diff --git a/python/packages/devui/README.md b/python/packages/devui/README.md index a020bfe7ecb..30e807e3410 100644 --- a/python/packages/devui/README.md +++ b/python/packages/devui/README.md @@ -49,6 +49,19 @@ devui ./agents --port 8080 When DevUI starts with no discovered entities, it displays a **sample entity gallery** with curated examples from the Agent Framework repository. You can download these samples, review them, and run them locally to get started quickly. +## Using MCP Tools + +**Important:** Don't use `async with` context managers when creating agents with MCP tools for DevUI - connections will close before execution. + +```python +# ✅ Correct - DevUI handles cleanup automatically +mcp_tool = MCPStreamableHTTPTool(url="http://localhost:8011/mcp", chat_client=chat_client) +agent = ChatAgent(tools=mcp_tool) +serve(entities=[agent]) +``` + +MCP tools use lazy initialization and connect automatically on first use. DevUI attempts to clean up connections on shutdown + ## Directory Structure For your agents to be discovered by the DevUI, they must be organized in a directory structure like below. Each agent/workflow must have an `__init__.py` that exports the required variable (`agent` or `workflow`). @@ -157,57 +170,62 @@ Options: Given that DevUI offers an OpenAI Responses API, it internally maps messages and events from Agent Framework to OpenAI Responses API events (in `_mapper.py`). For transparency, this mapping is shown below: -| Agent Framework Content | OpenAI Event/Type | Status | -| ------------------------------- | ---------------------------------------- | -------- | -| **Lifecycle Events** | | | -| `AgentStartedEvent` | `response.created` + `response.in_progress` | Standard | -| `AgentCompletedEvent` | `response.completed` | Standard | -| `AgentFailedEvent` | `response.failed` | Standard | -| `WorkflowStartedEvent` | `response.created` + `response.in_progress` | Standard | -| `WorkflowCompletedEvent` | `response.completed` | Standard | -| `WorkflowFailedEvent` | `response.failed` | Standard | -| **Content Types** | | | -| `TextContent` | `response.content_part.added` + `response.output_text.delta` | Standard | -| `TextReasoningContent` | `response.reasoning_text.delta` | Standard | -| `FunctionCallContent` (initial) | `response.output_item.added` | Standard | -| `FunctionCallContent` (args) | `response.function_call_arguments.delta` | Standard | -| `FunctionResultContent` | `response.function_result.complete` | DevUI | -| `FunctionApprovalRequestContent`| `response.function_approval.requested` | DevUI | -| `FunctionApprovalResponseContent`| `response.function_approval.responded` | DevUI | -| `ErrorContent` | `error` | Standard | -| `UsageContent` | Final `Response.usage` field (not streamed) | Standard | -| **Workflow Events** | | | -| `ExecutorInvokedEvent` | `response.output_item.added` (ExecutorActionItem) | DevUI | -| `ExecutorCompletedEvent` | `response.output_item.done` (ExecutorActionItem) | DevUI | -| `ExecutorFailedEvent` | `response.output_item.done` (ExecutorActionItem with error) | DevUI | -| `WorkflowEvent` (other) | `response.workflow_event.complete` | DevUI | -| `WorkflowStatusEvent` | `response.trace.complete` | DevUI | -| `WorkflowWarningEvent` | `response.trace.complete` | DevUI | -| **Trace Content** | | | -| `DataContent` | `response.trace.complete` | DevUI | -| `UriContent` | `response.trace.complete` | DevUI | -| `HostedFileContent` | `response.trace.complete` | DevUI | -| `HostedVectorStoreContent` | `response.trace.complete` | DevUI | - -- **Standard** = OpenAI Responses API spec -- **DevUI** = Custom extensions for Agent Framework features (workflows, traces, function approvals) +| OpenAI Event/Type | Agent Framework Content | Status | +| ------------------------------------------------------------ | --------------------------------- | -------- | +| | **Lifecycle Events** | | +| `response.created` + `response.in_progress` | `AgentStartedEvent` | OpenAI | +| `response.completed` | `AgentCompletedEvent` | OpenAI | +| `response.failed` | `AgentFailedEvent` | OpenAI | +| `response.created` + `response.in_progress` | `WorkflowStartedEvent` | OpenAI | +| `response.completed` | `WorkflowCompletedEvent` | OpenAI | +| `response.failed` | `WorkflowFailedEvent` | OpenAI | +| | **Content Types** | | +| `response.content_part.added` + `response.output_text.delta` | `TextContent` | OpenAI | +| `response.reasoning_text.delta` | `TextReasoningContent` | OpenAI | +| `response.output_item.added` | `FunctionCallContent` (initial) | OpenAI | +| `response.function_call_arguments.delta` | `FunctionCallContent` (args) | OpenAI | +| `response.function_result.complete` | `FunctionResultContent` | DevUI | +| `response.function_approval.requested` | `FunctionApprovalRequestContent` | DevUI | +| `response.function_approval.responded` | `FunctionApprovalResponseContent` | DevUI | +| `error` | `ErrorContent` | OpenAI | +| Final `Response.usage` field (not streamed) | `UsageContent` | OpenAI | +| | **Workflow Events** | | +| `response.output_item.added` (ExecutorActionItem)* | `ExecutorInvokedEvent` | OpenAI | +| `response.output_item.done` (ExecutorActionItem)* | `ExecutorCompletedEvent` | OpenAI | +| `response.output_item.done` (ExecutorActionItem with error)* | `ExecutorFailedEvent` | OpenAI | +| `response.workflow_event.complete` | `WorkflowEvent` (other) | DevUI | +| `response.trace.complete` | `WorkflowStatusEvent` | DevUI | +| `response.trace.complete` | `WorkflowWarningEvent` | DevUI | +| | **Trace Content** | | +| `response.trace.complete` | `DataContent` | DevUI | +| `response.trace.complete` | `UriContent` | DevUI | +| `response.trace.complete` | `HostedFileContent` | DevUI | +| `response.trace.complete` | `HostedVectorStoreContent` | DevUI | + +\*Uses standard OpenAI event structure but carries DevUI-specific `ExecutorActionItem` payload + +- **OpenAI** = Standard OpenAI Responses API event types +- **DevUI** = Custom event types specific to Agent Framework (e.g., workflows, traces, function approvals) ### OpenAI Responses API Compliance DevUI follows the OpenAI Responses API specification for maximum compatibility: -**Standard OpenAI Types Used:** +**OpenAI Standard Event Types Used:** + - `ResponseOutputItemAddedEvent` - Output item notifications (function calls and results) +- `ResponseOutputItemDoneEvent` - Output item completion notifications - `Response.usage` - Token usage (in final response, not streamed) - All standard text, reasoning, and function call events **Custom DevUI Extensions:** + - `response.function_approval.requested` - Function approval requests (for interactive approval workflows) - `response.function_approval.responded` - Function approval responses (user approval/rejection) - `response.workflow_event.complete` - Agent Framework workflow events - `response.trace.complete` - Execution traces and internal content (DataContent, UriContent, hosted files/stores) -These custom extensions are clearly namespaced and can be safely ignored by standard OpenAI clients. +These custom extensions are clearly namespaced and can be safely ignored by standard OpenAI clients. Note that DevUI also uses standard OpenAI events with custom payloads (e.g., `ExecutorActionItem` within `response.output_item.added`). ### Entity Management @@ -239,12 +257,14 @@ These custom extensions are clearly namespaced and can be safely ignored by stan DevUI is designed as a **sample application for local development** and should not be exposed to untrusted networks or used in production environments. **Security features:** + - Only loads entities from local directories or in-memory registration - No remote code execution capabilities - Binds to localhost (127.0.0.1) by default - All samples must be manually downloaded and reviewed before running **Best practices:** + - Never expose DevUI to the internet - Review all agent/workflow code before running - Only load entities from trusted sources diff --git a/python/packages/devui/agent_framework_devui/_mapper.py b/python/packages/devui/agent_framework_devui/_mapper.py index af5501c49a8..af127e6d3d4 100644 --- a/python/packages/devui/agent_framework_devui/_mapper.py +++ b/python/packages/devui/agent_framework_devui/_mapper.py @@ -56,6 +56,56 @@ ] +def _serialize_content_recursive(value: Any) -> Any: + """Recursively serialize Agent Framework Content objects to JSON-compatible values. + + This handles nested Content objects (like TextContent inside FunctionResultContent.result) + that can't be directly serialized by json.dumps(). + + Args: + value: Value to serialize (can be Content object, dict, list, primitive, etc.) + + Returns: + JSON-serializable version with all Content objects converted to dicts/primitives + """ + # Handle None and basic JSON-serializable types + if value is None or isinstance(value, (str, int, float, bool)): + return value + + # Check if it's a SerializationMixin (includes all Content types) + # Content objects have to_dict() method + if hasattr(value, "to_dict") and callable(getattr(value, "to_dict", None)): + try: + return value.to_dict() + except Exception as e: + # If to_dict() fails, fall through to other methods + logger.debug(f"Failed to serialize with to_dict(): {e}") + + # Handle dictionaries - recursively process values + if isinstance(value, dict): + return {key: _serialize_content_recursive(val) for key, val in value.items()} + + # Handle lists and tuples - recursively process elements + if isinstance(value, (list, tuple)): + serialized = [_serialize_content_recursive(item) for item in value] + # For single-item lists containing text Content, extract just the text + # This handles the MCP case where result = [TextContent(text="Hello")] + # and we want output = "Hello" not output = '[{"type": "text", "text": "Hello"}]' + if len(serialized) == 1 and isinstance(serialized[0], dict) and serialized[0].get("type") == "text": + return serialized[0].get("text", "") + return serialized + + # For other objects with model_dump(), try that + if hasattr(value, "model_dump") and callable(getattr(value, "model_dump", None)): + try: + return value.model_dump() + except Exception as e: + logger.debug(f"Failed to serialize with model_dump(): {e}") + + # Return as-is and let json.dumps handle it (may raise TypeError for non-serializable types) + return value + + class MessageMapper: """Maps Agent Framework messages/responses to OpenAI format.""" @@ -935,8 +985,16 @@ async def _map_function_result_content( result = getattr(content, "result", None) exception = getattr(content, "exception", None) - # Convert result to string - output = result if isinstance(result, str) else json.dumps(result) if result is not None else "" + # Convert result to string, handling nested Content objects from MCP tools + if isinstance(result, str): + output = result + elif result is not None: + # Recursively serialize any nested Content objects (e.g., from MCP tools) + serialized = _serialize_content_recursive(result) + # Convert to JSON string if still not a string + output = serialized if isinstance(serialized, str) else json.dumps(serialized) + else: + output = "" # Determine status based on exception status = "incomplete" if exception else "completed" @@ -953,6 +1011,7 @@ async def _map_function_result_content( item_id=item_id, output_index=context["output_index"], sequence_number=self._next_sequence(context), + timestamp=datetime.now().isoformat(), ) async def _map_error_content(self, content: Any, context: dict[str, Any]) -> ResponseErrorEvent: diff --git a/python/packages/devui/agent_framework_devui/_server.py b/python/packages/devui/agent_framework_devui/_server.py index e6fd871ca24..3e3c5380981 100644 --- a/python/packages/devui/agent_framework_devui/_server.py +++ b/python/packages/devui/agent_framework_devui/_server.py @@ -85,19 +85,25 @@ async def _ensure_executor(self) -> AgentFrameworkExecutor: return self.executor async def _cleanup_entities(self) -> None: - """Cleanup entity resources (close clients, credentials, etc.).""" + """Cleanup entity resources (close clients, MCP tools, credentials, etc.).""" if not self.executor: return logger.info("Cleaning up entity resources...") entities = self.executor.entity_discovery.list_entities() closed_count = 0 + mcp_tools_closed = 0 + credentials_closed = 0 for entity_info in entities: try: entity_obj = self.executor.entity_discovery.get_entity_object(entity_info.id) + + # Close chat clients and their credentials if entity_obj and hasattr(entity_obj, "chat_client"): client = entity_obj.chat_client + + # Close the chat client itself if hasattr(client, "close") and callable(client.close): if inspect.iscoroutinefunction(client.close): await client.close() @@ -105,11 +111,47 @@ async def _cleanup_entities(self) -> None: client.close() closed_count += 1 logger.debug(f"Closed client for entity: {entity_info.id}") + + # Close credentials attached to chat clients (e.g., AzureCliCredential) + credential_attrs = ["credential", "async_credential", "_credential", "_async_credential"] + for attr in credential_attrs: + if hasattr(client, attr): + cred = getattr(client, attr) + if cred and hasattr(cred, "close") and callable(cred.close): + try: + if inspect.iscoroutinefunction(cred.close): + await cred.close() + else: + cred.close() + credentials_closed += 1 + logger.debug(f"Closed credential for entity: {entity_info.id}") + except Exception as e: + logger.warning(f"Error closing credential for {entity_info.id}: {e}") + + # Close MCP tools (framework tracks them in _local_mcp_tools) + if entity_obj and hasattr(entity_obj, "_local_mcp_tools"): + for mcp_tool in entity_obj._local_mcp_tools: + if hasattr(mcp_tool, "close") and callable(mcp_tool.close): + try: + if inspect.iscoroutinefunction(mcp_tool.close): + await mcp_tool.close() + else: + mcp_tool.close() + mcp_tools_closed += 1 + tool_name = getattr(mcp_tool, "name", "unknown") + logger.debug(f"Closed MCP tool '{tool_name}' for entity: {entity_info.id}") + except Exception as e: + logger.warning(f"Error closing MCP tool for {entity_info.id}: {e}") + except Exception as e: logger.warning(f"Error closing entity {entity_info.id}: {e}") if closed_count > 0: logger.info(f"Closed {closed_count} entity client(s)") + if credentials_closed > 0: + logger.info(f"Closed {credentials_closed} credential(s)") + if mcp_tools_closed > 0: + logger.info(f"Closed {mcp_tools_closed} MCP tool(s)") def create_app(self) -> FastAPI: """Create the FastAPI application.""" diff --git a/python/packages/devui/agent_framework_devui/models/_openai_custom.py b/python/packages/devui/agent_framework_devui/models/_openai_custom.py index 6b7564fac34..d4506c7b4cb 100644 --- a/python/packages/devui/agent_framework_devui/models/_openai_custom.py +++ b/python/packages/devui/agent_framework_devui/models/_openai_custom.py @@ -121,6 +121,7 @@ class ResponseFunctionResultComplete(BaseModel): item_id: str output_index: int = 0 sequence_number: int + timestamp: str | None = None # Optional timestamp for UI display # Agent Framework extension fields diff --git a/python/packages/devui/agent_framework_devui/ui/assets/index-DpQbOzAN.js b/python/packages/devui/agent_framework_devui/ui/assets/index-D_Y1oSGu.js similarity index 79% rename from python/packages/devui/agent_framework_devui/ui/assets/index-DpQbOzAN.js rename to python/packages/devui/agent_framework_devui/ui/assets/index-D_Y1oSGu.js index db067202bbd..85924eb9712 100644 --- a/python/packages/devui/agent_framework_devui/ui/assets/index-DpQbOzAN.js +++ b/python/packages/devui/agent_framework_devui/ui/assets/index-D_Y1oSGu.js @@ -1,4 +1,4 @@ -function HE(e,r){for(var o=0;os[l]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))s(l);new MutationObserver(l=>{for(const u of l)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&s(d)}).observe(document,{childList:!0,subtree:!0});function o(l){const u={};return l.integrity&&(u.integrity=l.integrity),l.referrerPolicy&&(u.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?u.credentials="include":l.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function s(l){if(l.ep)return;l.ep=!0;const u=o(l);fetch(l.href,u)}})();function qh(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var _m={exports:{}},wi={};/** +function BE(e,r){for(var o=0;os[l]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))s(l);new MutationObserver(l=>{for(const u of l)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&s(d)}).observe(document,{childList:!0,subtree:!0});function o(l){const u={};return l.integrity&&(u.integrity=l.integrity),l.referrerPolicy&&(u.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?u.credentials="include":l.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function s(l){if(l.ep)return;l.ep=!0;const u=o(l);fetch(l.href,u)}})();function qh(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var _m={exports:{}},wi={};/** * @license React * react-jsx-runtime.production.js * @@ -6,7 +6,7 @@ function HE(e,r){for(var o=0;o>>1,T=_[P];if(0>>1;Pl(ee,z))sel(he,ee)?(_[P]=he,_[se]=z,P=se):(_[P]=ee,_[X]=z,P=X);else if(sel(he,z))_[P]=he,_[se]=z,P=se;else break e}}return O}function l(_,O){var z=_.sortIndex-O.sortIndex;return z!==0?z:_.id-O.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var u=performance;e.unstable_now=function(){return u.now()}}else{var d=Date,f=d.now();e.unstable_now=function(){return d.now()-f}}var h=[],p=[],g=1,y=null,v=3,b=!1,S=!1,w=!1,j=!1,k=typeof setTimeout=="function"?setTimeout:null,M=typeof clearTimeout=="function"?clearTimeout:null,E=typeof setImmediate<"u"?setImmediate:null;function A(_){for(var O=o(p);O!==null;){if(O.callback===null)s(p);else if(O.startTime<=_)s(p),O.sortIndex=O.expirationTime,r(h,O);else break;O=o(p)}}function D(_){if(w=!1,A(_),!S)if(o(h)!==null)S=!0,L||(L=!0,G());else{var O=o(p);O!==null&&V(D,O.startTime-_)}}var L=!1,H=-1,B=5,q=-1;function F(){return j?!0:!(e.unstable_now()-q_&&F());){var P=y.callback;if(typeof P=="function"){y.callback=null,v=y.priorityLevel;var T=P(y.expirationTime<=_);if(_=e.unstable_now(),typeof T=="function"){y.callback=T,A(_),O=!0;break t}y===o(h)&&s(h),A(_)}else s(h);y=o(h)}if(y!==null)O=!0;else{var U=o(p);U!==null&&V(D,U.startTime-_),O=!1}}break e}finally{y=null,v=z,b=!1}O=void 0}}finally{O?G():L=!1}}}var G;if(typeof E=="function")G=function(){E(K)};else if(typeof MessageChannel<"u"){var te=new MessageChannel,I=te.port2;te.port1.onmessage=K,G=function(){I.postMessage(null)}}else G=function(){k(K,0)};function V(_,O){H=k(function(){_(e.unstable_now())},O)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(_){_.callback=null},e.unstable_forceFrameRate=function(_){0>_||125<_?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):B=0<_?Math.floor(1e3/_):5},e.unstable_getCurrentPriorityLevel=function(){return v},e.unstable_next=function(_){switch(v){case 1:case 2:case 3:var O=3;break;default:O=v}var z=v;v=O;try{return _()}finally{v=z}},e.unstable_requestPaint=function(){j=!0},e.unstable_runWithPriority=function(_,O){switch(_){case 1:case 2:case 3:case 4:case 5:break;default:_=3}var z=v;v=_;try{return O()}finally{v=z}},e.unstable_scheduleCallback=function(_,O,z){var P=e.unstable_now();switch(typeof z=="object"&&z!==null?(z=z.delay,z=typeof z=="number"&&0P?(_.sortIndex=z,r(p,_),o(h)===null&&_===o(p)&&(w?(M(H),H=-1):w=!0,V(D,z-P))):(_.sortIndex=T,r(h,_),S||b||(S=!0,L||(L=!0,G()))),_},e.unstable_shouldYield=F,e.unstable_wrapCallback=function(_){var O=v;return function(){var z=v;v=O;try{return _.apply(this,arguments)}finally{v=z}}}})(km)),km}var Ev;function VE(){return Ev||(Ev=1,Cm.exports=$E()),Cm.exports}var Am={exports:{}},zt={};/** + */var _v;function VE(){return _v||(_v=1,(function(e){function r(_,O){var z=_.length;_.push(O);e:for(;0>>1,T=_[P];if(0>>1;Pl(ee,z))sel(he,ee)?(_[P]=he,_[se]=z,P=se):(_[P]=ee,_[X]=z,P=X);else if(sel(he,z))_[P]=he,_[se]=z,P=se;else break e}}return O}function l(_,O){var z=_.sortIndex-O.sortIndex;return z!==0?z:_.id-O.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var u=performance;e.unstable_now=function(){return u.now()}}else{var d=Date,f=d.now();e.unstable_now=function(){return d.now()-f}}var h=[],p=[],g=1,y=null,v=3,b=!1,S=!1,w=!1,j=!1,k=typeof setTimeout=="function"?setTimeout:null,M=typeof clearTimeout=="function"?clearTimeout:null,E=typeof setImmediate<"u"?setImmediate:null;function A(_){for(var O=o(p);O!==null;){if(O.callback===null)s(p);else if(O.startTime<=_)s(p),O.sortIndex=O.expirationTime,r(h,O);else break;O=o(p)}}function D(_){if(w=!1,A(_),!S)if(o(h)!==null)S=!0,L||(L=!0,G());else{var O=o(p);O!==null&&V(D,O.startTime-_)}}var L=!1,H=-1,B=5,q=-1;function F(){return j?!0:!(e.unstable_now()-q_&&F());){var P=y.callback;if(typeof P=="function"){y.callback=null,v=y.priorityLevel;var T=P(y.expirationTime<=_);if(_=e.unstable_now(),typeof T=="function"){y.callback=T,A(_),O=!0;break t}y===o(h)&&s(h),A(_)}else s(h);y=o(h)}if(y!==null)O=!0;else{var U=o(p);U!==null&&V(D,U.startTime-_),O=!1}}break e}finally{y=null,v=z,b=!1}O=void 0}}finally{O?G():L=!1}}}var G;if(typeof E=="function")G=function(){E(K)};else if(typeof MessageChannel<"u"){var te=new MessageChannel,I=te.port2;te.port1.onmessage=K,G=function(){I.postMessage(null)}}else G=function(){k(K,0)};function V(_,O){H=k(function(){_(e.unstable_now())},O)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(_){_.callback=null},e.unstable_forceFrameRate=function(_){0>_||125<_?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):B=0<_?Math.floor(1e3/_):5},e.unstable_getCurrentPriorityLevel=function(){return v},e.unstable_next=function(_){switch(v){case 1:case 2:case 3:var O=3;break;default:O=v}var z=v;v=O;try{return _()}finally{v=z}},e.unstable_requestPaint=function(){j=!0},e.unstable_runWithPriority=function(_,O){switch(_){case 1:case 2:case 3:case 4:case 5:break;default:_=3}var z=v;v=_;try{return O()}finally{v=z}},e.unstable_scheduleCallback=function(_,O,z){var P=e.unstable_now();switch(typeof z=="object"&&z!==null?(z=z.delay,z=typeof z=="number"&&0P?(_.sortIndex=z,r(p,_),o(h)===null&&_===o(p)&&(w?(M(H),H=-1):w=!0,V(D,z-P))):(_.sortIndex=T,r(h,_),S||b||(S=!0,L||(L=!0,G()))),_},e.unstable_shouldYield=F,e.unstable_wrapCallback=function(_){var O=v;return function(){var z=v;v=O;try{return _.apply(this,arguments)}finally{v=z}}}})(km)),km}var Ev;function qE(){return Ev||(Ev=1,Cm.exports=VE()),Cm.exports}var Am={exports:{}},Lt={};/** * @license React * react-dom.production.js * @@ -30,7 +30,7 @@ function HE(e,r){for(var o=0;o"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(r){console.error(r)}}return e(),Am.exports=qE(),Am.exports}/** + */var jv;function YE(){if(jv)return Lt;jv=1;var e=Wi();function r(h){var p="https://react.dev/errors/"+h;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(r){console.error(r)}}return e(),Am.exports=YE(),Am.exports}/** * @license React * react-dom-client.production.js * @@ -38,16 +38,16 @@ function HE(e,r){for(var o=0;oT||(t.current=P[T],P[T]=null,T--)}function ee(t,n){T++,P[T]=t.current,t.current=n}var se=U(null),he=U(null),fe=U(null),Q=U(null);function ae(t,n){switch(ee(fe,n),ee(he,t),ee(se,null),n.nodeType){case 9:case 11:t=(t=n.documentElement)&&(t=t.namespaceURI)?F0(t):0;break;default:if(t=n.tagName,n=n.namespaceURI)n=F0(n),t=Z0(n,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}X(se),ee(se,t)}function xe(){X(se),X(he),X(fe)}function le(t){t.memoizedState!==null&&ee(Q,t);var n=se.current,a=Z0(n,t.type);n!==a&&(ee(he,t),ee(se,a))}function ce(t){he.current===t&&(X(se),X(he)),Q.current===t&&(X(Q),gi._currentValue=z)}var ue=Object.prototype.hasOwnProperty,ge=e.unstable_scheduleCallback,pe=e.unstable_cancelCallback,Be=e.unstable_shouldYield,st=e.unstable_requestPaint,re=e.unstable_now,ve=e.unstable_getCurrentPriorityLevel,ke=e.unstable_ImmediatePriority,De=e.unstable_UserBlockingPriority,be=e.unstable_NormalPriority,Te=e.unstable_LowPriority,Ye=e.unstable_IdlePriority,it=e.log,Tn=e.unstable_setDisableYieldValue,Fe=null,Ue=null;function Qe(t){if(typeof it=="function"&&Tn(t),Ue&&typeof Ue.setStrictMode=="function")try{Ue.setStrictMode(Fe,t)}catch{}}var ht=Math.clz32?Math.clz32:dd,Ft=Math.log,ga=Math.LN2;function dd(t){return t>>>=0,t===0?32:31-(Ft(t)/ga|0)|0}var ns=256,rs=4194304;function Wn(t){var n=t&42;if(n!==0)return n;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t&4194048;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function os(t,n,a){var c=t.pendingLanes;if(c===0)return 0;var m=0,x=t.suspendedLanes,C=t.pingedLanes;t=t.warmLanes;var R=c&134217727;return R!==0?(c=R&~x,c!==0?m=Wn(c):(C&=R,C!==0?m=Wn(C):a||(a=R&~t,a!==0&&(m=Wn(a))))):(R=c&~x,R!==0?m=Wn(R):C!==0?m=Wn(C):a||(a=c&~t,a!==0&&(m=Wn(a)))),m===0?0:n!==0&&n!==m&&(n&x)===0&&(x=m&-m,a=n&-n,x>=a||x===32&&(a&4194048)!==0)?n:m}function xo(t,n){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&n)===0}function fd(t,n){switch(t){case 1:case 2:case 4:case 8:case 64:return n+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return n+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function dl(){var t=ns;return ns<<=1,(ns&4194048)===0&&(ns=256),t}function fl(){var t=rs;return rs<<=1,(rs&62914560)===0&&(rs=4194304),t}function xa(t){for(var n=[],a=0;31>a;a++)n.push(t);return n}function vo(t,n){t.pendingLanes|=n,n!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function md(t,n,a,c,m,x){var C=t.pendingLanes;t.pendingLanes=a,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=a,t.entangledLanes&=a,t.errorRecoveryDisabledLanes&=a,t.shellSuspendCounter=0;var R=t.entanglements,$=t.expirationTimes,J=t.hiddenUpdates;for(a=C&~a;0T||(t.current=P[T],P[T]=null,T--)}function ee(t,n){T++,P[T]=t.current,t.current=n}var se=U(null),he=U(null),fe=U(null),Q=U(null);function ae(t,n){switch(ee(fe,n),ee(he,t),ee(se,null),n.nodeType){case 9:case 11:t=(t=n.documentElement)&&(t=t.namespaceURI)?F0(t):0;break;default:if(t=n.tagName,n=n.namespaceURI)n=F0(n),t=Z0(n,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}X(se),ee(se,t)}function xe(){X(se),X(he),X(fe)}function le(t){t.memoizedState!==null&&ee(Q,t);var n=se.current,a=Z0(n,t.type);n!==a&&(ee(he,t),ee(se,a))}function ce(t){he.current===t&&(X(se),X(he)),Q.current===t&&(X(Q),gi._currentValue=z)}var ue=Object.prototype.hasOwnProperty,ge=e.unstable_scheduleCallback,pe=e.unstable_cancelCallback,Be=e.unstable_shouldYield,st=e.unstable_requestPaint,re=e.unstable_now,ve=e.unstable_getCurrentPriorityLevel,ke=e.unstable_ImmediatePriority,De=e.unstable_UserBlockingPriority,be=e.unstable_NormalPriority,Te=e.unstable_LowPriority,Ye=e.unstable_IdlePriority,it=e.log,Tn=e.unstable_setDisableYieldValue,Fe=null,Ue=null;function Qe(t){if(typeof it=="function"&&Tn(t),Ue&&typeof Ue.setStrictMode=="function")try{Ue.setStrictMode(Fe,t)}catch{}}var ht=Math.clz32?Math.clz32:dd,Ft=Math.log,ga=Math.LN2;function dd(t){return t>>>=0,t===0?32:31-(Ft(t)/ga|0)|0}var ns=256,rs=4194304;function Wn(t){var n=t&42;if(n!==0)return n;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t&4194048;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function os(t,n,a){var c=t.pendingLanes;if(c===0)return 0;var m=0,x=t.suspendedLanes,C=t.pingedLanes;t=t.warmLanes;var R=c&134217727;return R!==0?(c=R&~x,c!==0?m=Wn(c):(C&=R,C!==0?m=Wn(C):a||(a=R&~t,a!==0&&(m=Wn(a))))):(R=c&~x,R!==0?m=Wn(R):C!==0?m=Wn(C):a||(a=c&~t,a!==0&&(m=Wn(a)))),m===0?0:n!==0&&n!==m&&(n&x)===0&&(x=m&-m,a=n&-n,x>=a||x===32&&(a&4194048)!==0)?n:m}function xo(t,n){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&n)===0}function fd(t,n){switch(t){case 1:case 2:case 4:case 8:case 64:return n+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return n+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function dl(){var t=ns;return ns<<=1,(ns&4194048)===0&&(ns=256),t}function fl(){var t=rs;return rs<<=1,(rs&62914560)===0&&(rs=4194304),t}function xa(t){for(var n=[],a=0;31>a;a++)n.push(t);return n}function vo(t,n){t.pendingLanes|=n,n!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function md(t,n,a,c,m,x){var C=t.pendingLanes;t.pendingLanes=a,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=a,t.entangledLanes&=a,t.errorRecoveryDisabledLanes&=a,t.shellSuspendCounter=0;var R=t.entanglements,$=t.expirationTimes,J=t.hiddenUpdates;for(a=C&~a;0)":-1m||$[c]!==J[m]){var ie=` `+$[c].replace(" at new "," at ");return t.displayName&&ie.includes("")&&(ie=ie.replace("",t.displayName)),ie}while(1<=c&&0<=m);break}}}finally{Ea=!1,Error.prepareStackTrace=a}return(a=t?t.displayName||t.name:"")?tr(a):""}function yd(t){switch(t.tag){case 26:case 27:case 5:return tr(t.type);case 16:return tr("Lazy");case 13:return tr("Suspense");case 19:return tr("SuspenseList");case 0:case 15:return ja(t.type,!1);case 11:return ja(t.type.render,!1);case 1:return ja(t.type,!0);case 31:return tr("Activity");default:return""}}function bl(t){try{var n="";do n+=yd(t),t=t.return;while(t);return n}catch(a){return` Error generating stack: `+a.message+` -`+a.stack}}function Bt(t){switch(typeof t){case"bigint":case"boolean":case"number":case"string":case"undefined":return t;case"object":return t;default:return""}}function wl(t){var n=t.type;return(t=t.nodeName)&&t.toLowerCase()==="input"&&(n==="checkbox"||n==="radio")}function bd(t){var n=wl(t)?"checked":"value",a=Object.getOwnPropertyDescriptor(t.constructor.prototype,n),c=""+t[n];if(!t.hasOwnProperty(n)&&typeof a<"u"&&typeof a.get=="function"&&typeof a.set=="function"){var m=a.get,x=a.set;return Object.defineProperty(t,n,{configurable:!0,get:function(){return m.call(this)},set:function(C){c=""+C,x.call(this,C)}}),Object.defineProperty(t,n,{enumerable:a.enumerable}),{getValue:function(){return c},setValue:function(C){c=""+C},stopTracking:function(){t._valueTracker=null,delete t[n]}}}}function is(t){t._valueTracker||(t._valueTracker=bd(t))}function Ca(t){if(!t)return!1;var n=t._valueTracker;if(!n)return!0;var a=n.getValue(),c="";return t&&(c=wl(t)?t.checked?"true":"false":t.value),t=c,t!==a?(n.setValue(t),!0):!1}function ls(t){if(t=t||(typeof document<"u"?document:void 0),typeof t>"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var wd=/[\n"\\]/g;function Ut(t){return t.replace(wd,function(n){return"\\"+n.charCodeAt(0).toString(16)+" "})}function bo(t,n,a,c,m,x,C,R){t.name="",C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"?t.type=C:t.removeAttribute("type"),n!=null?C==="number"?(n===0&&t.value===""||t.value!=n)&&(t.value=""+Bt(n)):t.value!==""+Bt(n)&&(t.value=""+Bt(n)):C!=="submit"&&C!=="reset"||t.removeAttribute("value"),n!=null?ka(t,C,Bt(n)):a!=null?ka(t,C,Bt(a)):c!=null&&t.removeAttribute("value"),m==null&&x!=null&&(t.defaultChecked=!!x),m!=null&&(t.checked=m&&typeof m!="function"&&typeof m!="symbol"),R!=null&&typeof R!="function"&&typeof R!="symbol"&&typeof R!="boolean"?t.name=""+Bt(R):t.removeAttribute("name")}function Nl(t,n,a,c,m,x,C,R){if(x!=null&&typeof x!="function"&&typeof x!="symbol"&&typeof x!="boolean"&&(t.type=x),n!=null||a!=null){if(!(x!=="submit"&&x!=="reset"||n!=null))return;a=a!=null?""+Bt(a):"",n=n!=null?""+Bt(n):a,R||n===t.value||(t.value=n),t.defaultValue=n}c=c??m,c=typeof c!="function"&&typeof c!="symbol"&&!!c,t.checked=R?t.checked:!!c,t.defaultChecked=!!c,C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"&&(t.name=C)}function ka(t,n,a){n==="number"&&ls(t.ownerDocument)===t||t.defaultValue===""+a||(t.defaultValue=""+a)}function nr(t,n,a,c){if(t=t.options,n){n={};for(var m=0;m"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),jd=!1;if(rr)try{var Ma={};Object.defineProperty(Ma,"passive",{get:function(){jd=!0}}),window.addEventListener("test",Ma,Ma),window.removeEventListener("test",Ma,Ma)}catch{jd=!1}var Or=null,Cd=null,_l=null;function Qp(){if(_l)return _l;var t,n=Cd,a=n.length,c,m="value"in Or?Or.value:Or.textContent,x=m.length;for(t=0;t=Da),og=" ",sg=!1;function ag(t,n){switch(t){case"keyup":return l_.indexOf(n.keyCode)!==-1;case"keydown":return n.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function ig(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var fs=!1;function u_(t,n){switch(t){case"compositionend":return ig(n);case"keypress":return n.which!==32?null:(sg=!0,og);case"textInput":return t=n.data,t===og&&sg?null:t;default:return null}}function d_(t,n){if(fs)return t==="compositionend"||!Rd&&ag(t,n)?(t=Qp(),_l=Cd=Or=null,fs=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(n.ctrlKey||n.altKey||n.metaKey)||n.ctrlKey&&n.altKey){if(n.char&&1=n)return{node:a,offset:n-t};t=c}e:{for(;a;){if(a.nextSibling){a=a.nextSibling;break e}a=a.parentNode}a=void 0}a=pg(a)}}function xg(t,n){return t&&n?t===n?!0:t&&t.nodeType===3?!1:n&&n.nodeType===3?xg(t,n.parentNode):"contains"in t?t.contains(n):t.compareDocumentPosition?!!(t.compareDocumentPosition(n)&16):!1:!1}function vg(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var n=ls(t.document);n instanceof t.HTMLIFrameElement;){try{var a=typeof n.contentWindow.location.href=="string"}catch{a=!1}if(a)t=n.contentWindow;else break;n=ls(t.document)}return n}function zd(t){var n=t&&t.nodeName&&t.nodeName.toLowerCase();return n&&(n==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||n==="textarea"||t.contentEditable==="true")}var y_=rr&&"documentMode"in document&&11>=document.documentMode,ms=null,Ld=null,Ia=null,Id=!1;function yg(t,n,a){var c=a.window===a?a.document:a.nodeType===9?a:a.ownerDocument;Id||ms==null||ms!==ls(c)||(c=ms,"selectionStart"in c&&zd(c)?c={start:c.selectionStart,end:c.selectionEnd}:(c=(c.ownerDocument&&c.ownerDocument.defaultView||window).getSelection(),c={anchorNode:c.anchorNode,anchorOffset:c.anchorOffset,focusNode:c.focusNode,focusOffset:c.focusOffset}),Ia&&La(Ia,c)||(Ia=c,c=hc(Ld,"onSelect"),0>=C,m-=C,sr=1<<32-ht(n)+m|a<x?x:8;var C=_.T,R={};_.T=R,Sf(t,!1,n,a);try{var $=m(),J=_.S;if(J!==null&&J(R,$),$!==null&&typeof $=="object"&&typeof $.then=="function"){var ie=k_($,c);Qa(t,n,ie,en(t))}else Qa(t,n,c,en(t))}catch(me){Qa(t,n,{then:function(){},status:"rejected",reason:me},en())}finally{O.p=x,_.T=C}}function D_(){}function wf(t,n,a,c){if(t.tag!==5)throw Error(s(476));var m=bx(t).queue;yx(t,m,n,z,a===null?D_:function(){return wx(t),a(c)})}function bx(t){var n=t.memoizedState;if(n!==null)return n;n={memoizedState:z,baseState:z,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:cr,lastRenderedState:z},next:null};var a={};return n.next={memoizedState:a,baseState:a,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:cr,lastRenderedState:a},next:null},t.memoizedState=n,t=t.alternate,t!==null&&(t.memoizedState=n),n}function wx(t){var n=bx(t).next.queue;Qa(t,n,{},en())}function Nf(){return Ot(gi)}function Nx(){return yt().memoizedState}function Sx(){return yt().memoizedState}function O_(t){for(var n=t.return;n!==null;){switch(n.tag){case 24:case 3:var a=en();t=Ir(a);var c=Hr(n,t,a);c!==null&&(tn(c,n,a),Ga(c,n,a)),n={cache:Wd()},t.payload=n;return}n=n.return}}function z_(t,n,a){var c=en();a={lane:c,revertLane:0,action:a,hasEagerState:!1,eagerState:null,next:null},Fl(t)?Ex(n,a):(a=Pd(t,n,a,c),a!==null&&(tn(a,t,c),jx(a,n,c)))}function _x(t,n,a){var c=en();Qa(t,n,a,c)}function Qa(t,n,a,c){var m={lane:c,revertLane:0,action:a,hasEagerState:!1,eagerState:null,next:null};if(Fl(t))Ex(n,m);else{var x=t.alternate;if(t.lanes===0&&(x===null||x.lanes===0)&&(x=n.lastRenderedReducer,x!==null))try{var C=n.lastRenderedState,R=x(C,a);if(m.hasEagerState=!0,m.eagerState=R,Zt(R,C))return Tl(t,n,m,0),at===null&&Ml(),!1}catch{}finally{}if(a=Pd(t,n,m,c),a!==null)return tn(a,t,c),jx(a,n,c),!0}return!1}function Sf(t,n,a,c){if(c={lane:2,revertLane:tm(),action:c,hasEagerState:!1,eagerState:null,next:null},Fl(t)){if(n)throw Error(s(479))}else n=Pd(t,a,c,2),n!==null&&tn(n,t,2)}function Fl(t){var n=t.alternate;return t===Ie||n!==null&&n===Ie}function Ex(t,n){Ss=$l=!0;var a=t.pending;a===null?n.next=n:(n.next=a.next,a.next=n),t.pending=n}function jx(t,n,a){if((a&4194048)!==0){var c=n.lanes;c&=t.pendingLanes,a|=c,n.lanes=a,va(t,a)}}var Zl={readContext:Ot,use:ql,useCallback:pt,useContext:pt,useEffect:pt,useImperativeHandle:pt,useLayoutEffect:pt,useInsertionEffect:pt,useMemo:pt,useReducer:pt,useRef:pt,useState:pt,useDebugValue:pt,useDeferredValue:pt,useTransition:pt,useSyncExternalStore:pt,useId:pt,useHostTransitionStatus:pt,useFormState:pt,useActionState:pt,useOptimistic:pt,useMemoCache:pt,useCacheRefresh:pt},Cx={readContext:Ot,use:ql,useCallback:function(t,n){return $t().memoizedState=[t,n===void 0?null:n],t},useContext:Ot,useEffect:ux,useImperativeHandle:function(t,n,a){a=a!=null?a.concat([t]):null,Xl(4194308,4,hx.bind(null,n,t),a)},useLayoutEffect:function(t,n){return Xl(4194308,4,t,n)},useInsertionEffect:function(t,n){Xl(4,2,t,n)},useMemo:function(t,n){var a=$t();n=n===void 0?null:n;var c=t();if(Ro){Qe(!0);try{t()}finally{Qe(!1)}}return a.memoizedState=[c,n],c},useReducer:function(t,n,a){var c=$t();if(a!==void 0){var m=a(n);if(Ro){Qe(!0);try{a(n)}finally{Qe(!1)}}}else m=n;return c.memoizedState=c.baseState=m,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:m},c.queue=t,t=t.dispatch=z_.bind(null,Ie,t),[c.memoizedState,t]},useRef:function(t){var n=$t();return t={current:t},n.memoizedState=t},useState:function(t){t=xf(t);var n=t.queue,a=_x.bind(null,Ie,n);return n.dispatch=a,[t.memoizedState,a]},useDebugValue:yf,useDeferredValue:function(t,n){var a=$t();return bf(a,t,n)},useTransition:function(){var t=xf(!1);return t=yx.bind(null,Ie,t.queue,!0,!1),$t().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,n,a){var c=Ie,m=$t();if(We){if(a===void 0)throw Error(s(407));a=a()}else{if(a=n(),at===null)throw Error(s(349));(Ge&124)!==0||Fg(c,n,a)}m.memoizedState=a;var x={value:a,getSnapshot:n};return m.queue=x,ux(Kg.bind(null,c,x,t),[t]),c.flags|=2048,Es(9,Gl(),Zg.bind(null,c,x,a,n),null),a},useId:function(){var t=$t(),n=at.identifierPrefix;if(We){var a=ar,c=sr;a=(c&~(1<<32-ht(c)-1)).toString(32)+a,n="«"+n+"R"+a,a=Vl++,0Me?(Ct=je,je=null):Ct=je.sibling;var Ze=ne(Z,je,W[Me],de);if(Ze===null){je===null&&(je=Ct);break}t&&je&&Ze.alternate===null&&n(Z,je),Y=x(Ze,Y,Me),Pe===null?we=Ze:Pe.sibling=Ze,Pe=Ze,je=Ct}if(Me===W.length)return a(Z,je),We&&jo(Z,Me),we;if(je===null){for(;MeMe?(Ct=je,je=null):Ct=je.sibling;var to=ne(Z,je,Ze.value,de);if(to===null){je===null&&(je=Ct);break}t&&je&&to.alternate===null&&n(Z,je),Y=x(to,Y,Me),Pe===null?we=to:Pe.sibling=to,Pe=to,je=Ct}if(Ze.done)return a(Z,je),We&&jo(Z,Me),we;if(je===null){for(;!Ze.done;Me++,Ze=W.next())Ze=me(Z,Ze.value,de),Ze!==null&&(Y=x(Ze,Y,Me),Pe===null?we=Ze:Pe.sibling=Ze,Pe=Ze);return We&&jo(Z,Me),we}for(je=c(je);!Ze.done;Me++,Ze=W.next())Ze=oe(je,Z,Me,Ze.value,de),Ze!==null&&(t&&Ze.alternate!==null&&je.delete(Ze.key===null?Me:Ze.key),Y=x(Ze,Y,Me),Pe===null?we=Ze:Pe.sibling=Ze,Pe=Ze);return t&&je.forEach(function(IE){return n(Z,IE)}),We&&jo(Z,Me),we}function rt(Z,Y,W,de){if(typeof W=="object"&&W!==null&&W.type===S&&W.key===null&&(W=W.props.children),typeof W=="object"&&W!==null){switch(W.$$typeof){case v:e:{for(var we=W.key;Y!==null;){if(Y.key===we){if(we=W.type,we===S){if(Y.tag===7){a(Z,Y.sibling),de=m(Y,W.props.children),de.return=Z,Z=de;break e}}else if(Y.elementType===we||typeof we=="object"&&we!==null&&we.$$typeof===B&&Ax(we)===Y.type){a(Z,Y.sibling),de=m(Y,W.props),ei(de,W),de.return=Z,Z=de;break e}a(Z,Y);break}else n(Z,Y);Y=Y.sibling}W.type===S?(de=_o(W.props.children,Z.mode,de,W.key),de.return=Z,Z=de):(de=Dl(W.type,W.key,W.props,null,Z.mode,de),ei(de,W),de.return=Z,Z=de)}return C(Z);case b:e:{for(we=W.key;Y!==null;){if(Y.key===we)if(Y.tag===4&&Y.stateNode.containerInfo===W.containerInfo&&Y.stateNode.implementation===W.implementation){a(Z,Y.sibling),de=m(Y,W.children||[]),de.return=Z,Z=de;break e}else{a(Z,Y);break}else n(Z,Y);Y=Y.sibling}de=qd(W,Z.mode,de),de.return=Z,Z=de}return C(Z);case B:return we=W._init,W=we(W._payload),rt(Z,Y,W,de)}if(V(W))return Re(Z,Y,W,de);if(G(W)){if(we=G(W),typeof we!="function")throw Error(s(150));return W=we.call(W),Ae(Z,Y,W,de)}if(typeof W.then=="function")return rt(Z,Y,Kl(W),de);if(W.$$typeof===E)return rt(Z,Y,Il(Z,W),de);Wl(Z,W)}return typeof W=="string"&&W!==""||typeof W=="number"||typeof W=="bigint"?(W=""+W,Y!==null&&Y.tag===6?(a(Z,Y.sibling),de=m(Y,W),de.return=Z,Z=de):(a(Z,Y),de=Vd(W,Z.mode,de),de.return=Z,Z=de),C(Z)):a(Z,Y)}return function(Z,Y,W,de){try{Ja=0;var we=rt(Z,Y,W,de);return js=null,we}catch(je){if(je===qa||je===Bl)throw je;var Pe=Kt(29,je,null,Z.mode);return Pe.lanes=de,Pe.return=Z,Pe}finally{}}}var Cs=Mx(!0),Tx=Mx(!1),mn=U(null),On=null;function Ur(t){var n=t.alternate;ee(Nt,Nt.current&1),ee(mn,t),On===null&&(n===null||Ns.current!==null||n.memoizedState!==null)&&(On=t)}function Rx(t){if(t.tag===22){if(ee(Nt,Nt.current),ee(mn,t),On===null){var n=t.alternate;n!==null&&n.memoizedState!==null&&(On=t)}}else Pr()}function Pr(){ee(Nt,Nt.current),ee(mn,mn.current)}function ur(t){X(mn),On===t&&(On=null),X(Nt)}var Nt=U(0);function Ql(t){for(var n=t;n!==null;){if(n.tag===13){var a=n.memoizedState;if(a!==null&&(a=a.dehydrated,a===null||a.data==="$?"||mm(a)))return n}else if(n.tag===19&&n.memoizedProps.revealOrder!==void 0){if((n.flags&128)!==0)return n}else if(n.child!==null){n.child.return=n,n=n.child;continue}if(n===t)break;for(;n.sibling===null;){if(n.return===null||n.return===t)return null;n=n.return}n.sibling.return=n.return,n=n.sibling}return null}function _f(t,n,a,c){n=t.memoizedState,a=a(c,n),a=a==null?n:g({},n,a),t.memoizedState=a,t.lanes===0&&(t.updateQueue.baseState=a)}var Ef={enqueueSetState:function(t,n,a){t=t._reactInternals;var c=en(),m=Ir(c);m.payload=n,a!=null&&(m.callback=a),n=Hr(t,m,c),n!==null&&(tn(n,t,c),Ga(n,t,c))},enqueueReplaceState:function(t,n,a){t=t._reactInternals;var c=en(),m=Ir(c);m.tag=1,m.payload=n,a!=null&&(m.callback=a),n=Hr(t,m,c),n!==null&&(tn(n,t,c),Ga(n,t,c))},enqueueForceUpdate:function(t,n){t=t._reactInternals;var a=en(),c=Ir(a);c.tag=2,n!=null&&(c.callback=n),n=Hr(t,c,a),n!==null&&(tn(n,t,a),Ga(n,t,a))}};function Dx(t,n,a,c,m,x,C){return t=t.stateNode,typeof t.shouldComponentUpdate=="function"?t.shouldComponentUpdate(c,x,C):n.prototype&&n.prototype.isPureReactComponent?!La(a,c)||!La(m,x):!0}function Ox(t,n,a,c){t=n.state,typeof n.componentWillReceiveProps=="function"&&n.componentWillReceiveProps(a,c),typeof n.UNSAFE_componentWillReceiveProps=="function"&&n.UNSAFE_componentWillReceiveProps(a,c),n.state!==t&&Ef.enqueueReplaceState(n,n.state,null)}function Do(t,n){var a=n;if("ref"in n){a={};for(var c in n)c!=="ref"&&(a[c]=n[c])}if(t=t.defaultProps){a===n&&(a=g({},a));for(var m in t)a[m]===void 0&&(a[m]=t[m])}return a}var Jl=typeof reportError=="function"?reportError:function(t){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var n=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof t=="object"&&t!==null&&typeof t.message=="string"?String(t.message):String(t),error:t});if(!window.dispatchEvent(n))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",t);return}console.error(t)};function zx(t){Jl(t)}function Lx(t){console.error(t)}function Ix(t){Jl(t)}function ec(t,n){try{var a=t.onUncaughtError;a(n.value,{componentStack:n.stack})}catch(c){setTimeout(function(){throw c})}}function Hx(t,n,a){try{var c=t.onCaughtError;c(a.value,{componentStack:a.stack,errorBoundary:n.tag===1?n.stateNode:null})}catch(m){setTimeout(function(){throw m})}}function jf(t,n,a){return a=Ir(a),a.tag=3,a.payload={element:null},a.callback=function(){ec(t,n)},a}function Bx(t){return t=Ir(t),t.tag=3,t}function Ux(t,n,a,c){var m=a.type.getDerivedStateFromError;if(typeof m=="function"){var x=c.value;t.payload=function(){return m(x)},t.callback=function(){Hx(n,a,c)}}var C=a.stateNode;C!==null&&typeof C.componentDidCatch=="function"&&(t.callback=function(){Hx(n,a,c),typeof m!="function"&&(Xr===null?Xr=new Set([this]):Xr.add(this));var R=c.stack;this.componentDidCatch(c.value,{componentStack:R!==null?R:""})})}function I_(t,n,a,c,m){if(a.flags|=32768,c!==null&&typeof c=="object"&&typeof c.then=="function"){if(n=a.alternate,n!==null&&Pa(n,a,m,!0),a=mn.current,a!==null){switch(a.tag){case 13:return On===null?Kf():a.alternate===null&&mt===0&&(mt=3),a.flags&=-257,a.flags|=65536,a.lanes=m,c===ef?a.flags|=16384:(n=a.updateQueue,n===null?a.updateQueue=new Set([c]):n.add(c),Qf(t,c,m)),!1;case 22:return a.flags|=65536,c===ef?a.flags|=16384:(n=a.updateQueue,n===null?(n={transitions:null,markerInstances:null,retryQueue:new Set([c])},a.updateQueue=n):(a=n.retryQueue,a===null?n.retryQueue=new Set([c]):a.add(c)),Qf(t,c,m)),!1}throw Error(s(435,a.tag))}return Qf(t,c,m),Kf(),!1}if(We)return n=mn.current,n!==null?((n.flags&65536)===0&&(n.flags|=256),n.flags|=65536,n.lanes=m,c!==Xd&&(t=Error(s(422),{cause:c}),Ua(cn(t,a)))):(c!==Xd&&(n=Error(s(423),{cause:c}),Ua(cn(n,a))),t=t.current.alternate,t.flags|=65536,m&=-m,t.lanes|=m,c=cn(c,a),m=jf(t.stateNode,c,m),rf(t,m),mt!==4&&(mt=2)),!1;var x=Error(s(520),{cause:c});if(x=cn(x,a),ii===null?ii=[x]:ii.push(x),mt!==4&&(mt=2),n===null)return!0;c=cn(c,a),a=n;do{switch(a.tag){case 3:return a.flags|=65536,t=m&-m,a.lanes|=t,t=jf(a.stateNode,c,t),rf(a,t),!1;case 1:if(n=a.type,x=a.stateNode,(a.flags&128)===0&&(typeof n.getDerivedStateFromError=="function"||x!==null&&typeof x.componentDidCatch=="function"&&(Xr===null||!Xr.has(x))))return a.flags|=65536,m&=-m,a.lanes|=m,m=Bx(m),Ux(m,t,a,c),rf(a,m),!1}a=a.return}while(a!==null);return!1}var Px=Error(s(461)),Et=!1;function kt(t,n,a,c){n.child=t===null?Tx(n,null,a,c):Cs(n,t.child,a,c)}function $x(t,n,a,c,m){a=a.render;var x=n.ref;if("ref"in c){var C={};for(var R in c)R!=="ref"&&(C[R]=c[R])}else C=c;return Mo(n),c=cf(t,n,a,C,x,m),R=uf(),t!==null&&!Et?(df(t,n,m),dr(t,n,m)):(We&&R&&Yd(n),n.flags|=1,kt(t,n,c,m),n.child)}function Vx(t,n,a,c,m){if(t===null){var x=a.type;return typeof x=="function"&&!$d(x)&&x.defaultProps===void 0&&a.compare===null?(n.tag=15,n.type=x,qx(t,n,x,c,m)):(t=Dl(a.type,null,c,n,n.mode,m),t.ref=n.ref,t.return=n,n.child=t)}if(x=t.child,!Of(t,m)){var C=x.memoizedProps;if(a=a.compare,a=a!==null?a:La,a(C,c)&&t.ref===n.ref)return dr(t,n,m)}return n.flags|=1,t=or(x,c),t.ref=n.ref,t.return=n,n.child=t}function qx(t,n,a,c,m){if(t!==null){var x=t.memoizedProps;if(La(x,c)&&t.ref===n.ref)if(Et=!1,n.pendingProps=c=x,Of(t,m))(t.flags&131072)!==0&&(Et=!0);else return n.lanes=t.lanes,dr(t,n,m)}return Cf(t,n,a,c,m)}function Yx(t,n,a){var c=n.pendingProps,m=c.children,x=t!==null?t.memoizedState:null;if(c.mode==="hidden"){if((n.flags&128)!==0){if(c=x!==null?x.baseLanes|a:a,t!==null){for(m=n.child=t.child,x=0;m!==null;)x=x|m.lanes|m.childLanes,m=m.sibling;n.childLanes=x&~c}else n.childLanes=0,n.child=null;return Gx(t,n,c,a)}if((a&536870912)!==0)n.memoizedState={baseLanes:0,cachePool:null},t!==null&&Hl(n,x!==null?x.cachePool:null),x!==null?qg(n,x):sf(),Rx(n);else return n.lanes=n.childLanes=536870912,Gx(t,n,x!==null?x.baseLanes|a:a,a)}else x!==null?(Hl(n,x.cachePool),qg(n,x),Pr(),n.memoizedState=null):(t!==null&&Hl(n,null),sf(),Pr());return kt(t,n,m,a),n.child}function Gx(t,n,a,c){var m=Jd();return m=m===null?null:{parent:wt._currentValue,pool:m},n.memoizedState={baseLanes:a,cachePool:m},t!==null&&Hl(n,null),sf(),Rx(n),t!==null&&Pa(t,n,c,!0),null}function tc(t,n){var a=n.ref;if(a===null)t!==null&&t.ref!==null&&(n.flags|=4194816);else{if(typeof a!="function"&&typeof a!="object")throw Error(s(284));(t===null||t.ref!==a)&&(n.flags|=4194816)}}function Cf(t,n,a,c,m){return Mo(n),a=cf(t,n,a,c,void 0,m),c=uf(),t!==null&&!Et?(df(t,n,m),dr(t,n,m)):(We&&c&&Yd(n),n.flags|=1,kt(t,n,a,m),n.child)}function Xx(t,n,a,c,m,x){return Mo(n),n.updateQueue=null,a=Gg(n,c,a,m),Yg(t),c=uf(),t!==null&&!Et?(df(t,n,x),dr(t,n,x)):(We&&c&&Yd(n),n.flags|=1,kt(t,n,a,x),n.child)}function Fx(t,n,a,c,m){if(Mo(n),n.stateNode===null){var x=xs,C=a.contextType;typeof C=="object"&&C!==null&&(x=Ot(C)),x=new a(c,x),n.memoizedState=x.state!==null&&x.state!==void 0?x.state:null,x.updater=Ef,n.stateNode=x,x._reactInternals=n,x=n.stateNode,x.props=c,x.state=n.memoizedState,x.refs={},tf(n),C=a.contextType,x.context=typeof C=="object"&&C!==null?Ot(C):xs,x.state=n.memoizedState,C=a.getDerivedStateFromProps,typeof C=="function"&&(_f(n,a,C,c),x.state=n.memoizedState),typeof a.getDerivedStateFromProps=="function"||typeof x.getSnapshotBeforeUpdate=="function"||typeof x.UNSAFE_componentWillMount!="function"&&typeof x.componentWillMount!="function"||(C=x.state,typeof x.componentWillMount=="function"&&x.componentWillMount(),typeof x.UNSAFE_componentWillMount=="function"&&x.UNSAFE_componentWillMount(),C!==x.state&&Ef.enqueueReplaceState(x,x.state,null),Fa(n,c,x,m),Xa(),x.state=n.memoizedState),typeof x.componentDidMount=="function"&&(n.flags|=4194308),c=!0}else if(t===null){x=n.stateNode;var R=n.memoizedProps,$=Do(a,R);x.props=$;var J=x.context,ie=a.contextType;C=xs,typeof ie=="object"&&ie!==null&&(C=Ot(ie));var me=a.getDerivedStateFromProps;ie=typeof me=="function"||typeof x.getSnapshotBeforeUpdate=="function",R=n.pendingProps!==R,ie||typeof x.UNSAFE_componentWillReceiveProps!="function"&&typeof x.componentWillReceiveProps!="function"||(R||J!==C)&&Ox(n,x,c,C),Lr=!1;var ne=n.memoizedState;x.state=ne,Fa(n,c,x,m),Xa(),J=n.memoizedState,R||ne!==J||Lr?(typeof me=="function"&&(_f(n,a,me,c),J=n.memoizedState),($=Lr||Dx(n,a,$,c,ne,J,C))?(ie||typeof x.UNSAFE_componentWillMount!="function"&&typeof x.componentWillMount!="function"||(typeof x.componentWillMount=="function"&&x.componentWillMount(),typeof x.UNSAFE_componentWillMount=="function"&&x.UNSAFE_componentWillMount()),typeof x.componentDidMount=="function"&&(n.flags|=4194308)):(typeof x.componentDidMount=="function"&&(n.flags|=4194308),n.memoizedProps=c,n.memoizedState=J),x.props=c,x.state=J,x.context=C,c=$):(typeof x.componentDidMount=="function"&&(n.flags|=4194308),c=!1)}else{x=n.stateNode,nf(t,n),C=n.memoizedProps,ie=Do(a,C),x.props=ie,me=n.pendingProps,ne=x.context,J=a.contextType,$=xs,typeof J=="object"&&J!==null&&($=Ot(J)),R=a.getDerivedStateFromProps,(J=typeof R=="function"||typeof x.getSnapshotBeforeUpdate=="function")||typeof x.UNSAFE_componentWillReceiveProps!="function"&&typeof x.componentWillReceiveProps!="function"||(C!==me||ne!==$)&&Ox(n,x,c,$),Lr=!1,ne=n.memoizedState,x.state=ne,Fa(n,c,x,m),Xa();var oe=n.memoizedState;C!==me||ne!==oe||Lr||t!==null&&t.dependencies!==null&&Ll(t.dependencies)?(typeof R=="function"&&(_f(n,a,R,c),oe=n.memoizedState),(ie=Lr||Dx(n,a,ie,c,ne,oe,$)||t!==null&&t.dependencies!==null&&Ll(t.dependencies))?(J||typeof x.UNSAFE_componentWillUpdate!="function"&&typeof x.componentWillUpdate!="function"||(typeof x.componentWillUpdate=="function"&&x.componentWillUpdate(c,oe,$),typeof x.UNSAFE_componentWillUpdate=="function"&&x.UNSAFE_componentWillUpdate(c,oe,$)),typeof x.componentDidUpdate=="function"&&(n.flags|=4),typeof x.getSnapshotBeforeUpdate=="function"&&(n.flags|=1024)):(typeof x.componentDidUpdate!="function"||C===t.memoizedProps&&ne===t.memoizedState||(n.flags|=4),typeof x.getSnapshotBeforeUpdate!="function"||C===t.memoizedProps&&ne===t.memoizedState||(n.flags|=1024),n.memoizedProps=c,n.memoizedState=oe),x.props=c,x.state=oe,x.context=$,c=ie):(typeof x.componentDidUpdate!="function"||C===t.memoizedProps&&ne===t.memoizedState||(n.flags|=4),typeof x.getSnapshotBeforeUpdate!="function"||C===t.memoizedProps&&ne===t.memoizedState||(n.flags|=1024),c=!1)}return x=c,tc(t,n),c=(n.flags&128)!==0,x||c?(x=n.stateNode,a=c&&typeof a.getDerivedStateFromError!="function"?null:x.render(),n.flags|=1,t!==null&&c?(n.child=Cs(n,t.child,null,m),n.child=Cs(n,null,a,m)):kt(t,n,a,m),n.memoizedState=x.state,t=n.child):t=dr(t,n,m),t}function Zx(t,n,a,c){return Ba(),n.flags|=256,kt(t,n,a,c),n.child}var kf={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function Af(t){return{baseLanes:t,cachePool:Lg()}}function Mf(t,n,a){return t=t!==null?t.childLanes&~a:0,n&&(t|=hn),t}function Kx(t,n,a){var c=n.pendingProps,m=!1,x=(n.flags&128)!==0,C;if((C=x)||(C=t!==null&&t.memoizedState===null?!1:(Nt.current&2)!==0),C&&(m=!0,n.flags&=-129),C=(n.flags&32)!==0,n.flags&=-33,t===null){if(We){if(m?Ur(n):Pr(),We){var R=ft,$;if($=R){e:{for($=R,R=Dn;$.nodeType!==8;){if(!R){R=null;break e}if($=wn($.nextSibling),$===null){R=null;break e}}R=$}R!==null?(n.memoizedState={dehydrated:R,treeContext:Eo!==null?{id:sr,overflow:ar}:null,retryLane:536870912,hydrationErrors:null},$=Kt(18,null,null,0),$.stateNode=R,$.return=n,n.child=$,It=n,ft=null,$=!0):$=!1}$||ko(n)}if(R=n.memoizedState,R!==null&&(R=R.dehydrated,R!==null))return mm(R)?n.lanes=32:n.lanes=536870912,null;ur(n)}return R=c.children,c=c.fallback,m?(Pr(),m=n.mode,R=nc({mode:"hidden",children:R},m),c=_o(c,m,a,null),R.return=n,c.return=n,R.sibling=c,n.child=R,m=n.child,m.memoizedState=Af(a),m.childLanes=Mf(t,C,a),n.memoizedState=kf,c):(Ur(n),Tf(n,R))}if($=t.memoizedState,$!==null&&(R=$.dehydrated,R!==null)){if(x)n.flags&256?(Ur(n),n.flags&=-257,n=Rf(t,n,a)):n.memoizedState!==null?(Pr(),n.child=t.child,n.flags|=128,n=null):(Pr(),m=c.fallback,R=n.mode,c=nc({mode:"visible",children:c.children},R),m=_o(m,R,a,null),m.flags|=2,c.return=n,m.return=n,c.sibling=m,n.child=c,Cs(n,t.child,null,a),c=n.child,c.memoizedState=Af(a),c.childLanes=Mf(t,C,a),n.memoizedState=kf,n=m);else if(Ur(n),mm(R)){if(C=R.nextSibling&&R.nextSibling.dataset,C)var J=C.dgst;C=J,c=Error(s(419)),c.stack="",c.digest=C,Ua({value:c,source:null,stack:null}),n=Rf(t,n,a)}else if(Et||Pa(t,n,a,!1),C=(a&t.childLanes)!==0,Et||C){if(C=at,C!==null&&(c=a&-a,c=(c&42)!==0?1:ya(c),c=(c&(C.suspendedLanes|a))!==0?0:c,c!==0&&c!==$.retryLane))throw $.retryLane=c,gs(t,c),tn(C,t,c),Px;R.data==="$?"||Kf(),n=Rf(t,n,a)}else R.data==="$?"?(n.flags|=192,n.child=t.child,n=null):(t=$.treeContext,ft=wn(R.nextSibling),It=n,We=!0,Co=null,Dn=!1,t!==null&&(dn[fn++]=sr,dn[fn++]=ar,dn[fn++]=Eo,sr=t.id,ar=t.overflow,Eo=n),n=Tf(n,c.children),n.flags|=4096);return n}return m?(Pr(),m=c.fallback,R=n.mode,$=t.child,J=$.sibling,c=or($,{mode:"hidden",children:c.children}),c.subtreeFlags=$.subtreeFlags&65011712,J!==null?m=or(J,m):(m=_o(m,R,a,null),m.flags|=2),m.return=n,c.return=n,c.sibling=m,n.child=c,c=m,m=n.child,R=t.child.memoizedState,R===null?R=Af(a):($=R.cachePool,$!==null?(J=wt._currentValue,$=$.parent!==J?{parent:J,pool:J}:$):$=Lg(),R={baseLanes:R.baseLanes|a,cachePool:$}),m.memoizedState=R,m.childLanes=Mf(t,C,a),n.memoizedState=kf,c):(Ur(n),a=t.child,t=a.sibling,a=or(a,{mode:"visible",children:c.children}),a.return=n,a.sibling=null,t!==null&&(C=n.deletions,C===null?(n.deletions=[t],n.flags|=16):C.push(t)),n.child=a,n.memoizedState=null,a)}function Tf(t,n){return n=nc({mode:"visible",children:n},t.mode),n.return=t,t.child=n}function nc(t,n){return t=Kt(22,t,null,n),t.lanes=0,t.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null},t}function Rf(t,n,a){return Cs(n,t.child,null,a),t=Tf(n,n.pendingProps.children),t.flags|=2,n.memoizedState=null,t}function Wx(t,n,a){t.lanes|=n;var c=t.alternate;c!==null&&(c.lanes|=n),Zd(t.return,n,a)}function Df(t,n,a,c,m){var x=t.memoizedState;x===null?t.memoizedState={isBackwards:n,rendering:null,renderingStartTime:0,last:c,tail:a,tailMode:m}:(x.isBackwards=n,x.rendering=null,x.renderingStartTime=0,x.last=c,x.tail=a,x.tailMode=m)}function Qx(t,n,a){var c=n.pendingProps,m=c.revealOrder,x=c.tail;if(kt(t,n,c.children,a),c=Nt.current,(c&2)!==0)c=c&1|2,n.flags|=128;else{if(t!==null&&(t.flags&128)!==0)e:for(t=n.child;t!==null;){if(t.tag===13)t.memoizedState!==null&&Wx(t,a,n);else if(t.tag===19)Wx(t,a,n);else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===n)break e;for(;t.sibling===null;){if(t.return===null||t.return===n)break e;t=t.return}t.sibling.return=t.return,t=t.sibling}c&=1}switch(ee(Nt,c),m){case"forwards":for(a=n.child,m=null;a!==null;)t=a.alternate,t!==null&&Ql(t)===null&&(m=a),a=a.sibling;a=m,a===null?(m=n.child,n.child=null):(m=a.sibling,a.sibling=null),Df(n,!1,m,a,x);break;case"backwards":for(a=null,m=n.child,n.child=null;m!==null;){if(t=m.alternate,t!==null&&Ql(t)===null){n.child=m;break}t=m.sibling,m.sibling=a,a=m,m=t}Df(n,!0,a,null,x);break;case"together":Df(n,!1,null,null,void 0);break;default:n.memoizedState=null}return n.child}function dr(t,n,a){if(t!==null&&(n.dependencies=t.dependencies),Gr|=n.lanes,(a&n.childLanes)===0)if(t!==null){if(Pa(t,n,a,!1),(a&n.childLanes)===0)return null}else return null;if(t!==null&&n.child!==t.child)throw Error(s(153));if(n.child!==null){for(t=n.child,a=or(t,t.pendingProps),n.child=a,a.return=n;t.sibling!==null;)t=t.sibling,a=a.sibling=or(t,t.pendingProps),a.return=n;a.sibling=null}return n.child}function Of(t,n){return(t.lanes&n)!==0?!0:(t=t.dependencies,!!(t!==null&&Ll(t)))}function H_(t,n,a){switch(n.tag){case 3:ae(n,n.stateNode.containerInfo),zr(n,wt,t.memoizedState.cache),Ba();break;case 27:case 5:le(n);break;case 4:ae(n,n.stateNode.containerInfo);break;case 10:zr(n,n.type,n.memoizedProps.value);break;case 13:var c=n.memoizedState;if(c!==null)return c.dehydrated!==null?(Ur(n),n.flags|=128,null):(a&n.child.childLanes)!==0?Kx(t,n,a):(Ur(n),t=dr(t,n,a),t!==null?t.sibling:null);Ur(n);break;case 19:var m=(t.flags&128)!==0;if(c=(a&n.childLanes)!==0,c||(Pa(t,n,a,!1),c=(a&n.childLanes)!==0),m){if(c)return Qx(t,n,a);n.flags|=128}if(m=n.memoizedState,m!==null&&(m.rendering=null,m.tail=null,m.lastEffect=null),ee(Nt,Nt.current),c)break;return null;case 22:case 23:return n.lanes=0,Yx(t,n,a);case 24:zr(n,wt,t.memoizedState.cache)}return dr(t,n,a)}function Jx(t,n,a){if(t!==null)if(t.memoizedProps!==n.pendingProps)Et=!0;else{if(!Of(t,a)&&(n.flags&128)===0)return Et=!1,H_(t,n,a);Et=(t.flags&131072)!==0}else Et=!1,We&&(n.flags&1048576)!==0&&Ag(n,zl,n.index);switch(n.lanes=0,n.tag){case 16:e:{t=n.pendingProps;var c=n.elementType,m=c._init;if(c=m(c._payload),n.type=c,typeof c=="function")$d(c)?(t=Do(c,t),n.tag=1,n=Fx(null,n,c,t,a)):(n.tag=0,n=Cf(null,n,c,t,a));else{if(c!=null){if(m=c.$$typeof,m===A){n.tag=11,n=$x(null,n,c,t,a);break e}else if(m===H){n.tag=14,n=Vx(null,n,c,t,a);break e}}throw n=I(c)||c,Error(s(306,n,""))}}return n;case 0:return Cf(t,n,n.type,n.pendingProps,a);case 1:return c=n.type,m=Do(c,n.pendingProps),Fx(t,n,c,m,a);case 3:e:{if(ae(n,n.stateNode.containerInfo),t===null)throw Error(s(387));c=n.pendingProps;var x=n.memoizedState;m=x.element,nf(t,n),Fa(n,c,null,a);var C=n.memoizedState;if(c=C.cache,zr(n,wt,c),c!==x.cache&&Kd(n,[wt],a,!0),Xa(),c=C.element,x.isDehydrated)if(x={element:c,isDehydrated:!1,cache:C.cache},n.updateQueue.baseState=x,n.memoizedState=x,n.flags&256){n=Zx(t,n,c,a);break e}else if(c!==m){m=cn(Error(s(424)),n),Ua(m),n=Zx(t,n,c,a);break e}else{switch(t=n.stateNode.containerInfo,t.nodeType){case 9:t=t.body;break;default:t=t.nodeName==="HTML"?t.ownerDocument.body:t}for(ft=wn(t.firstChild),It=n,We=!0,Co=null,Dn=!0,a=Tx(n,null,c,a),n.child=a;a;)a.flags=a.flags&-3|4096,a=a.sibling}else{if(Ba(),c===m){n=dr(t,n,a);break e}kt(t,n,c,a)}n=n.child}return n;case 26:return tc(t,n),t===null?(a=rv(n.type,null,n.pendingProps,null))?n.memoizedState=a:We||(a=n.type,t=n.pendingProps,c=gc(fe.current).createElement(a),c[_t]=n,c[Dt]=t,Mt(c,a,t),xt(c),n.stateNode=c):n.memoizedState=rv(n.type,t.memoizedProps,n.pendingProps,t.memoizedState),null;case 27:return le(n),t===null&&We&&(c=n.stateNode=ev(n.type,n.pendingProps,fe.current),It=n,Dn=!0,m=ft,Kr(n.type)?(hm=m,ft=wn(c.firstChild)):ft=m),kt(t,n,n.pendingProps.children,a),tc(t,n),t===null&&(n.flags|=4194304),n.child;case 5:return t===null&&We&&((m=c=ft)&&(c=fE(c,n.type,n.pendingProps,Dn),c!==null?(n.stateNode=c,It=n,ft=wn(c.firstChild),Dn=!1,m=!0):m=!1),m||ko(n)),le(n),m=n.type,x=n.pendingProps,C=t!==null?t.memoizedProps:null,c=x.children,um(m,x)?c=null:C!==null&&um(m,C)&&(n.flags|=32),n.memoizedState!==null&&(m=cf(t,n,M_,null,null,a),gi._currentValue=m),tc(t,n),kt(t,n,c,a),n.child;case 6:return t===null&&We&&((t=a=ft)&&(a=mE(a,n.pendingProps,Dn),a!==null?(n.stateNode=a,It=n,ft=null,t=!0):t=!1),t||ko(n)),null;case 13:return Kx(t,n,a);case 4:return ae(n,n.stateNode.containerInfo),c=n.pendingProps,t===null?n.child=Cs(n,null,c,a):kt(t,n,c,a),n.child;case 11:return $x(t,n,n.type,n.pendingProps,a);case 7:return kt(t,n,n.pendingProps,a),n.child;case 8:return kt(t,n,n.pendingProps.children,a),n.child;case 12:return kt(t,n,n.pendingProps.children,a),n.child;case 10:return c=n.pendingProps,zr(n,n.type,c.value),kt(t,n,c.children,a),n.child;case 9:return m=n.type._context,c=n.pendingProps.children,Mo(n),m=Ot(m),c=c(m),n.flags|=1,kt(t,n,c,a),n.child;case 14:return Vx(t,n,n.type,n.pendingProps,a);case 15:return qx(t,n,n.type,n.pendingProps,a);case 19:return Qx(t,n,a);case 31:return c=n.pendingProps,a=n.mode,c={mode:c.mode,children:c.children},t===null?(a=nc(c,a),a.ref=n.ref,n.child=a,a.return=n,n=a):(a=or(t.child,c),a.ref=n.ref,n.child=a,a.return=n,n=a),n;case 22:return Yx(t,n,a);case 24:return Mo(n),c=Ot(wt),t===null?(m=Jd(),m===null&&(m=at,x=Wd(),m.pooledCache=x,x.refCount++,x!==null&&(m.pooledCacheLanes|=a),m=x),n.memoizedState={parent:c,cache:m},tf(n),zr(n,wt,m)):((t.lanes&a)!==0&&(nf(t,n),Fa(n,null,null,a),Xa()),m=t.memoizedState,x=n.memoizedState,m.parent!==c?(m={parent:c,cache:c},n.memoizedState=m,n.lanes===0&&(n.memoizedState=n.updateQueue.baseState=m),zr(n,wt,c)):(c=x.cache,zr(n,wt,c),c!==m.cache&&Kd(n,[wt],a,!0))),kt(t,n,n.pendingProps.children,a),n.child;case 29:throw n.pendingProps}throw Error(s(156,n.tag))}function fr(t){t.flags|=4}function e0(t,n){if(n.type!=="stylesheet"||(n.state.loading&4)!==0)t.flags&=-16777217;else if(t.flags|=16777216,!lv(n)){if(n=mn.current,n!==null&&((Ge&4194048)===Ge?On!==null:(Ge&62914560)!==Ge&&(Ge&536870912)===0||n!==On))throw Ya=ef,Ig;t.flags|=8192}}function rc(t,n){n!==null&&(t.flags|=4),t.flags&16384&&(n=t.tag!==22?fl():536870912,t.lanes|=n,Ts|=n)}function ti(t,n){if(!We)switch(t.tailMode){case"hidden":n=t.tail;for(var a=null;n!==null;)n.alternate!==null&&(a=n),n=n.sibling;a===null?t.tail=null:a.sibling=null;break;case"collapsed":a=t.tail;for(var c=null;a!==null;)a.alternate!==null&&(c=a),a=a.sibling;c===null?n||t.tail===null?t.tail=null:t.tail.sibling=null:c.sibling=null}}function ut(t){var n=t.alternate!==null&&t.alternate.child===t.child,a=0,c=0;if(n)for(var m=t.child;m!==null;)a|=m.lanes|m.childLanes,c|=m.subtreeFlags&65011712,c|=m.flags&65011712,m.return=t,m=m.sibling;else for(m=t.child;m!==null;)a|=m.lanes|m.childLanes,c|=m.subtreeFlags,c|=m.flags,m.return=t,m=m.sibling;return t.subtreeFlags|=c,t.childLanes=a,n}function B_(t,n,a){var c=n.pendingProps;switch(Gd(n),n.tag){case 31:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return ut(n),null;case 1:return ut(n),null;case 3:return a=n.stateNode,c=null,t!==null&&(c=t.memoizedState.cache),n.memoizedState.cache!==c&&(n.flags|=2048),lr(wt),xe(),a.pendingContext&&(a.context=a.pendingContext,a.pendingContext=null),(t===null||t.child===null)&&(Ha(n)?fr(n):t===null||t.memoizedState.isDehydrated&&(n.flags&256)===0||(n.flags|=1024,Rg())),ut(n),null;case 26:return a=n.memoizedState,t===null?(fr(n),a!==null?(ut(n),e0(n,a)):(ut(n),n.flags&=-16777217)):a?a!==t.memoizedState?(fr(n),ut(n),e0(n,a)):(ut(n),n.flags&=-16777217):(t.memoizedProps!==c&&fr(n),ut(n),n.flags&=-16777217),null;case 27:ce(n),a=fe.current;var m=n.type;if(t!==null&&n.stateNode!=null)t.memoizedProps!==c&&fr(n);else{if(!c){if(n.stateNode===null)throw Error(s(166));return ut(n),null}t=se.current,Ha(n)?Mg(n):(t=ev(m,c,a),n.stateNode=t,fr(n))}return ut(n),null;case 5:if(ce(n),a=n.type,t!==null&&n.stateNode!=null)t.memoizedProps!==c&&fr(n);else{if(!c){if(n.stateNode===null)throw Error(s(166));return ut(n),null}if(t=se.current,Ha(n))Mg(n);else{switch(m=gc(fe.current),t){case 1:t=m.createElementNS("http://www.w3.org/2000/svg",a);break;case 2:t=m.createElementNS("http://www.w3.org/1998/Math/MathML",a);break;default:switch(a){case"svg":t=m.createElementNS("http://www.w3.org/2000/svg",a);break;case"math":t=m.createElementNS("http://www.w3.org/1998/Math/MathML",a);break;case"script":t=m.createElement("div"),t.innerHTML=" + diff --git a/python/packages/devui/frontend/src/App.tsx b/python/packages/devui/frontend/src/App.tsx index caddc4ffe45..f8473e9c608 100644 --- a/python/packages/devui/frontend/src/App.tsx +++ b/python/packages/devui/frontend/src/App.tsx @@ -241,6 +241,8 @@ export default function App() { // Show error state if loading failed if (entityError) { + const currentBackendUrl = apiClient.getBaseUrl(); + return (
Default:{" "} - http://localhost:8080 + {currentBackendUrl}

diff --git a/python/packages/devui/frontend/src/components/layout/debug-panel.tsx b/python/packages/devui/frontend/src/components/layout/debug-panel.tsx index 64866ae7284..b96fb185e61 100644 --- a/python/packages/devui/frontend/src/components/layout/debug-panel.tsx +++ b/python/packages/devui/frontend/src/components/layout/debug-panel.tsx @@ -116,6 +116,39 @@ function getFunctionResultFromEvent(event: ExtendedResponseStreamEvent): { return null; } +// Helper to get a stable timestamp for an event +// Uses event's own timestamp fields if available +function getEventTimestamp(event: ExtendedResponseStreamEvent): string { + // Priority 1: Check for top-level timestamp (DevUI custom events like function_result.complete) + if ('timestamp' in event && typeof event.timestamp === 'string') { + return new Date(event.timestamp).toLocaleTimeString(); + } + + // Priority 2: Check for nested data.timestamp (workflow/trace events) + if ('data' in event && event.data && typeof event.data === 'object' && 'timestamp' in event.data) { + const dataTimestamp = (event.data as any).timestamp; + if (typeof dataTimestamp === 'string') { + return new Date(dataTimestamp).toLocaleTimeString(); + } + } + + // Priority 3: Check for created_at in response object (lifecycle events) + if ('response' in event && event.response && typeof event.response === 'object' && 'created_at' in event.response) { + const createdAt = (event.response as any).created_at; + if (typeof createdAt === 'number') { + return new Date(createdAt * 1000).toLocaleTimeString(); + } + } + + // Fallback: use sequence number as label (better than showing same time for all) + if ('sequence_number' in event && typeof event.sequence_number === 'number') { + return `#${event.sequence_number}`; + } + + // Last resort: hide timestamp by returning empty string + return ''; +} + // Helper function to accumulate OpenAI events into meaningful units function processEventsForDisplay( events: ExtendedResponseStreamEvent[] @@ -551,7 +584,7 @@ function EventItem({ event }: EventItemProps) { const [isExpanded, setIsExpanded] = useState(false); const Icon = getEventIcon(event.type); const colorClass = getEventColor(event.type); - const timestamp = new Date().toLocaleTimeString(); + const timestamp = getEventTimestamp(event); const summary = getEventSummary(event); // Determine if this event has expandable content @@ -1487,7 +1520,7 @@ function ToolsTab({ events }: { events: ExtendedResponseStreamEvent[] }) { } function ToolEventItem({ event }: { event: ExtendedResponseStreamEvent }) { - const timestamp = new Date().toLocaleTimeString(); + const timestamp = getEventTimestamp(event); // Check if this is a function call or result event const isFunctionCall = event.type === "response.function_call.complete"; diff --git a/python/packages/devui/frontend/src/types/openai.ts b/python/packages/devui/frontend/src/types/openai.ts index 91bfb04c917..e4df1a1bf84 100644 --- a/python/packages/devui/frontend/src/types/openai.ts +++ b/python/packages/devui/frontend/src/types/openai.ts @@ -241,6 +241,7 @@ export interface ResponseFunctionResultComplete { item_id: string; output_index: number; sequence_number: number; + timestamp?: string; // Optional ISO timestamp for UI display } // DevUI Extension: Turn Separator (UI-only event for grouping) diff --git a/python/packages/devui/tests/test_mapper.py b/python/packages/devui/tests/test_mapper.py index a41f3a7adcc..dfa8ac9d6de 100644 --- a/python/packages/devui/tests/test_mapper.py +++ b/python/packages/devui/tests/test_mapper.py @@ -13,7 +13,14 @@ sys.path.insert(0, str(Path(__file__).parent.parent.parent / "main")) # Import Agent Framework types (assuming they are always available) -from agent_framework._types import AgentRunResponseUpdate, ErrorContent, FunctionCallContent, Role, TextContent +from agent_framework._types import ( + AgentRunResponseUpdate, + ErrorContent, + FunctionCallContent, + FunctionResultContent, + Role, + TextContent, +) from agent_framework_devui._mapper import MessageMapper from agent_framework_devui.models._openai_custom import AgentFrameworkRequest @@ -123,6 +130,83 @@ async def test_function_call_mapping(mapper: MessageMapper, test_request: AgentF assert "TestCity" in full_json +async def test_function_result_content_with_string_result( + mapper: MessageMapper, test_request: AgentFrameworkRequest +) -> None: + """Test FunctionResultContent with plain string result (regular tools).""" + content = FunctionResultContent( + call_id="test_call_123", + result="Hello, World!", # Plain string like regular Python function tools + ) + update = create_test_agent_update([content]) + + events = await mapper.convert_event(update, test_request) + + # Should produce response.function_result.complete event + assert len(events) >= 1 + result_events = [e for e in events if e.type == "response.function_result.complete"] + assert len(result_events) == 1 + assert result_events[0].output == "Hello, World!" + assert result_events[0].call_id == "test_call_123" + assert result_events[0].status == "completed" + + +async def test_function_result_content_with_nested_content_objects( + mapper: MessageMapper, test_request: AgentFrameworkRequest +) -> None: + """Test FunctionResultContent with nested Content objects (MCP tools case). + + This tests the issue from GitHub #1476 where MCP tools return FunctionResultContent + with nested TextContent objects that fail to serialize properly. + """ + # This is what MCP tools return - result contains nested Content objects + content = FunctionResultContent( + call_id="mcp_call_456", + result=[TextContent(text="Hello from MCP!")], # List containing TextContent object + ) + update = create_test_agent_update([content]) + + events = await mapper.convert_event(update, test_request) + + # Should successfully serialize the nested Content object + assert len(events) >= 1 + result_events = [e for e in events if e.type == "response.function_result.complete"] + assert len(result_events) == 1 + + # The output should contain the text from the nested TextContent + # Should not have TypeError or empty output + assert result_events[0].output != "" + assert "Hello from MCP!" in result_events[0].output + assert result_events[0].call_id == "mcp_call_456" + + +async def test_function_result_content_with_multiple_nested_content_objects( + mapper: MessageMapper, test_request: AgentFrameworkRequest +) -> None: + """Test FunctionResultContent with multiple nested Content objects.""" + # MCP tools can return multiple Content objects + content = FunctionResultContent( + call_id="mcp_call_789", + result=[ + TextContent(text="First result"), + TextContent(text="Second result"), + ], + ) + update = create_test_agent_update([content]) + + events = await mapper.convert_event(update, test_request) + + assert len(events) >= 1 + result_events = [e for e in events if e.type == "response.function_result.complete"] + assert len(result_events) == 1 + + # Should serialize all nested Content objects + output = result_events[0].output + assert output != "" + assert "First result" in output + assert "Second result" in output + + async def test_error_content_mapping(mapper: MessageMapper, test_request: AgentFrameworkRequest) -> None: """Test ErrorContent mapping.""" content = create_test_content("error", message="Test error", code="test_code") diff --git a/python/packages/devui/tests/test_server.py b/python/packages/devui/tests/test_server.py index ab5c387effe..bf03a612bd1 100644 --- a/python/packages/devui/tests/test_server.py +++ b/python/packages/devui/tests/test_server.py @@ -143,6 +143,104 @@ def test_select_primary_input_type_prefers_string_and_dict(): assert fallback is int +@pytest.mark.asyncio +async def test_credential_cleanup() -> None: + """Test that async credentials are properly closed during server cleanup.""" + from unittest.mock import AsyncMock, Mock + + from agent_framework import ChatAgent + + # Create mock credential with async close + mock_credential = AsyncMock() + mock_credential.close = AsyncMock() + + # Create mock chat client with credential + mock_client = Mock() + mock_client.async_credential = mock_credential + mock_client.model_id = "test-model" + + # Create agent with mock client + agent = ChatAgent(name="TestAgent", chat_client=mock_client, instructions="Test agent") + + # Create DevUI server with agent + server = DevServer() + server._pending_entities = [agent] + await server._ensure_executor() + + # Run cleanup + await server._cleanup_entities() + + # Verify credential.close() was called + assert mock_credential.close.called, "Async credential close should have been called" + assert mock_credential.close.call_count == 1 + + +@pytest.mark.asyncio +async def test_credential_cleanup_error_handling() -> None: + """Test that credential cleanup errors are handled gracefully.""" + from unittest.mock import AsyncMock, Mock + + from agent_framework import ChatAgent + + # Create mock credential that raises error on close + mock_credential = AsyncMock() + mock_credential.close = AsyncMock(side_effect=Exception("Close failed")) + + # Create mock chat client with credential + mock_client = Mock() + mock_client.async_credential = mock_credential + mock_client.model_id = "test-model" + + # Create agent with mock client + agent = ChatAgent(name="TestAgent", chat_client=mock_client, instructions="Test agent") + + # Create DevUI server with agent + server = DevServer() + server._pending_entities = [agent] + await server._ensure_executor() + + # Run cleanup - should not raise despite credential error + await server._cleanup_entities() + + # Verify close was attempted + assert mock_credential.close.called + + +@pytest.mark.asyncio +async def test_multiple_credential_attributes() -> None: + """Test that we check all common credential attribute names.""" + from unittest.mock import AsyncMock, Mock + + from agent_framework import ChatAgent + + # Create mock credentials + mock_cred1 = Mock() + mock_cred1.close = Mock() + mock_cred2 = AsyncMock() + mock_cred2.close = AsyncMock() + + # Create mock chat client with multiple credential attributes + mock_client = Mock() + mock_client.credential = mock_cred1 + mock_client.async_credential = mock_cred2 + mock_client.model_id = "test-model" + + # Create agent with mock client + agent = ChatAgent(name="TestAgent", chat_client=mock_client, instructions="Test agent") + + # Create DevUI server with agent + server = DevServer() + server._pending_entities = [agent] + await server._ensure_executor() + + # Run cleanup + await server._cleanup_entities() + + # Verify both credentials were closed + assert mock_cred1.close.called, "Sync credential should be closed" + assert mock_cred2.close.called, "Async credential should be closed" + + if __name__ == "__main__": # Simple test runner async def run_tests():