Repository: phidatahq/phidata
File: libs/agno/agno/run/agent.py (Python)

Code before:
            _dict = self.to_dict()
        except Exception:
            logger.error("Failed to convert response to json", exc_info=True)
            raise

        if indent is None:
            return json.dumps(_dict, separators=separators)
        else:
            return json.dumps(_dict, indent=indent, separators=separators)

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "RunOutput":
        if "run" in data:
            data = data.pop("run")

        events = data.pop("events", None)
        events = [run_output_event_from_dict(event) for event in events] if events else None

        messages = data.pop("messages", None)
        messages = [Message.from_dict(message) for message in messages] if messages else None

        citations = data.pop("citations", None)
        citations = Citations.model_validate(citations) if citations else None

        tools = data.pop("tools", [])
        tools = [ToolExecution.from_dict(tool) for tool in tools] if tools else None

        images = reconstruct_images(data.pop("images", []))
        videos = reconstruct_videos(data.pop("videos", []))
        audio = reconstruct_audio_list(data.pop("audio", []))
        files = reconstruct_files(data.pop("files", []))
        response_audio = reconstruct_response_audio(data.pop("response_audio", None))

        input_data = data.pop("input", None)
        input_obj = None
        if input_data:
            input_obj = RunInput.from_dict(input_data)

        metrics = data.pop("metrics", None)
        if metrics:
            metrics = Metrics(**metrics)

        additional_input = data.pop("additional_input", None)

        if additional_input is not None:
            additional_input = [Message.from_dict(message) for message in additional_input]

        reasoning_steps = data.pop("reasoning_steps", None)
        if reasoning_steps is not None:
            reasoning_steps = [ReasoningStep.model_validate(step) for step in reasoning_steps]


Review comment (bug):
- Should we encapsulate this logic in run_output_event_from_dict? Worried this is happening in more places, maybe it's better for that func to be ready to handle Team events too
- Is the agent_id check still safe here? We may also want to catch ValueError if not
- The comment is wrong I think

Code after:
            _dict = self.to_dict()
        except Exception:
            logger.error("Failed to convert response to json", exc_info=True)
            raise

        if indent is None:
            return json.dumps(_dict, separators=separators)
        else:
            return json.dumps(_dict, indent=indent, separators=separators)

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "RunOutput":
        if "run" in data:
            data = data.pop("run")

        events = data.pop("events", None)
        final_events = []
        for event in events or []:
            if "agent_id" in event:
                event = run_output_event_from_dict(event)
            else:
                # Use the factory from response.py for agent events
                from agno.run.team import team_run_output_event_from_dict
                event = team_run_output_event_from_dict(event)
            final_events.append(event)
        events = final_events

        messages = data.pop("messages", None)
        messages = [Message.from_dict(message) for message in messages] if messages else None

        citations = data.pop("citations", None)
        citations = Citations.model_validate(citations) if citations else None

        tools = data.pop("tools", [])
        tools = [ToolExecution.from_dict(tool) for tool in tools] if tools else None

        images = reconstruct_images(data.pop("images", []))
        videos = reconstruct_videos(data.pop("videos", []))
        audio = reconstruct_audio_list(data.pop("audio", []))
        files = reconstruct_files(data.pop("files", []))
        response_audio = reconstruct_response_audio(data.pop("response_audio", None))

        input_data = data.pop("input", None)
        input_obj = None
        if input_data:
            input_obj = RunInput.from_dict(input_data)

        metrics = data.pop("metrics", None)
        if metrics:
            metrics = Metrics(**metrics)