@@ -401,6 +401,45 @@ def get_text_parts(parts: Sequence[Part]) -> list[str]:
401401 return [part .text for part in parts if part .HasField ('text' )]
402402
403403
404+ def get_data_parts (parts : Sequence [Part ]) -> list [Any ]:
405+ """Extracts structured data from all data Parts.
406+
407+ Each returned element is the Python object obtained from the
408+ ``google.protobuf.Value`` stored in the Part.
409+
410+ Args:
411+ parts: A sequence of ``Part`` objects.
412+
413+ Returns:
414+ A list of deserialized data values from any data Parts found.
415+ """
416+ return [part .data for part in parts if part .HasField ('data' )]
417+
418+
419+ def get_raw_parts (parts : Sequence [Part ]) -> list [bytes ]:
420+ """Extracts raw bytes content from all raw Parts.
421+
422+ Args:
423+ parts: A sequence of ``Part`` objects.
424+
425+ Returns:
426+ A list of ``bytes`` from any raw Parts found.
427+ """
428+ return [part .raw for part in parts if part .HasField ('raw' )]
429+
430+
431+ def get_url_parts (parts : Sequence [Part ]) -> list [str ]:
432+ """Extracts URL strings from all URL Parts.
433+
434+ Args:
435+ parts: A sequence of ``Part`` objects.
436+
437+ Returns:
438+ A list of URL strings from any URL Parts found.
439+ """
440+ return [part .url for part in parts if part .HasField ('url' )]
441+
442+
404443# --- Event & Stream Helpers ---
405444
406445
@@ -447,6 +486,129 @@ def new_text_artifact_update_event( # noqa: PLR0913
447486 )
448487
449488
489+ def new_data_artifact_update_event ( # noqa: PLR0913
490+ task_id : str ,
491+ context_id : str ,
492+ name : str ,
493+ data : Any ,
494+ media_type : str | None = None ,
495+ append : bool = False ,
496+ last_chunk : bool = False ,
497+ artifact_id : str | None = None ,
498+ ) -> TaskArtifactUpdateEvent :
499+ """Creates a TaskArtifactUpdateEvent with a single data artifact.
500+
501+ Args:
502+ task_id: The task ID.
503+ context_id: The context ID.
504+ name: The name of the artifact.
505+ data: JSON-serializable data to embed (dict, list, str, etc.).
506+ media_type: Optional MIME type of the part content.
507+ append: Whether to append to the existing artifact.
508+ last_chunk: Whether this is the last chunk.
509+ artifact_id: Optional artifact ID (auto-generated if not provided).
510+
511+ Returns:
512+ A TaskArtifactUpdateEvent with a single data artifact.
513+ """
514+ return TaskArtifactUpdateEvent (
515+ task_id = task_id ,
516+ context_id = context_id ,
517+ artifact = new_data_artifact (
518+ name = name ,
519+ data = data ,
520+ media_type = media_type ,
521+ artifact_id = artifact_id ,
522+ ),
523+ append = append ,
524+ last_chunk = last_chunk ,
525+ )
526+
527+
528+ def new_raw_artifact_update_event ( # noqa: PLR0913
529+ task_id : str ,
530+ context_id : str ,
531+ name : str ,
532+ raw : bytes ,
533+ media_type : str | None = None ,
534+ filename : str | None = None ,
535+ append : bool = False ,
536+ last_chunk : bool = False ,
537+ artifact_id : str | None = None ,
538+ ) -> TaskArtifactUpdateEvent :
539+ """Creates a TaskArtifactUpdateEvent with a single raw bytes artifact.
540+
541+ Args:
542+ task_id: The task ID.
543+ context_id: The context ID.
544+ name: The name of the artifact.
545+ raw: The raw bytes content.
546+ media_type: Optional MIME type (e.g. 'image/png').
547+ filename: Optional filename.
548+ append: Whether to append to the existing artifact.
549+ last_chunk: Whether this is the last chunk.
550+ artifact_id: Optional artifact ID (auto-generated if not provided).
551+
552+ Returns:
553+ A TaskArtifactUpdateEvent with a single raw artifact.
554+ """
555+ return TaskArtifactUpdateEvent (
556+ task_id = task_id ,
557+ context_id = context_id ,
558+ artifact = new_raw_artifact (
559+ name = name ,
560+ raw = raw ,
561+ media_type = media_type ,
562+ filename = filename ,
563+ artifact_id = artifact_id ,
564+ ),
565+ append = append ,
566+ last_chunk = last_chunk ,
567+ )
568+
569+
570+ def new_url_artifact_update_event ( # noqa: PLR0913
571+ task_id : str ,
572+ context_id : str ,
573+ name : str ,
574+ url : str ,
575+ media_type : str | None = None ,
576+ filename : str | None = None ,
577+ append : bool = False ,
578+ last_chunk : bool = False ,
579+ artifact_id : str | None = None ,
580+ ) -> TaskArtifactUpdateEvent :
581+ """Creates a TaskArtifactUpdateEvent with a single URL artifact.
582+
583+ Args:
584+ task_id: The task ID.
585+ context_id: The context ID.
586+ name: The name of the artifact.
587+ url: The URL pointing to the file content.
588+ media_type: Optional MIME type (e.g. 'image/png').
589+ filename: Optional filename.
590+ append: Whether to append to the existing artifact.
591+ last_chunk: Whether this is the last chunk.
592+ artifact_id: Optional artifact ID (auto-generated if not provided).
593+
594+ Returns:
595+ A TaskArtifactUpdateEvent with a single URL artifact.
596+ """
597+ return TaskArtifactUpdateEvent (
598+ task_id = task_id ,
599+ context_id = context_id ,
600+ artifact = new_url_artifact (
601+ name = name ,
602+ url = url ,
603+ media_type = media_type ,
604+ filename = filename ,
605+ artifact_id = artifact_id ,
606+ ),
607+ append = append ,
608+ last_chunk = last_chunk ,
609+ )
610+
611+
450612def get_stream_response_text (
451613 response : StreamResponse , delimiter : str = '\n '
452614) -> str :
0 commit comments